Merge pull request #8176 from pchote/fix-palette-alpha
Load textures using premultiplied alpha.
This commit is contained in:
@@ -41,8 +41,6 @@ namespace OpenRA
|
||||
Additive,
|
||||
Subtractive,
|
||||
Multiply,
|
||||
SoftAdditive,
|
||||
Translucency,
|
||||
Multiplicative,
|
||||
DoubleMultiplicative
|
||||
}
|
||||
@@ -70,7 +68,7 @@ namespace OpenRA
|
||||
void EnableDepthBuffer();
|
||||
void DisableDepthBuffer();
|
||||
|
||||
void SetBlendMode(BlendMode mode, float alpha = 1f);
|
||||
void SetBlendMode(BlendMode mode);
|
||||
|
||||
void GrabWindowMouseFocus();
|
||||
void ReleaseWindowMouseFocus();
|
||||
|
||||
@@ -49,15 +49,9 @@ namespace OpenRA.Graphics
|
||||
using (var bitmap = (Bitmap)Image.FromStream(stream))
|
||||
{
|
||||
Size = bitmap.Size;
|
||||
data = new byte[4 * Size.Width * Size.Height];
|
||||
|
||||
var dataStride = 4 * Size.Width;
|
||||
data = new byte[dataStride * Size.Height];
|
||||
|
||||
var bd = bitmap.LockBits(bitmap.Bounds(),
|
||||
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
|
||||
for (var y = 0; y < Size.Height; y++)
|
||||
Marshal.Copy(IntPtr.Add(bd.Scan0, y * bd.Stride), data, y * dataStride, dataStride);
|
||||
bitmap.UnlockBits(bd);
|
||||
Util.FastCopyIntoSprite(new Sprite(this, bitmap.Bounds(), TextureChannel.Red), bitmap);
|
||||
}
|
||||
|
||||
ReleaseBuffer();
|
||||
|
||||
@@ -17,7 +17,6 @@ namespace OpenRA.Graphics
|
||||
public readonly Rectangle Bounds;
|
||||
public readonly Sheet Sheet;
|
||||
public readonly BlendMode BlendMode;
|
||||
public readonly float Alpha;
|
||||
public readonly TextureChannel Channel;
|
||||
public readonly float2 Size;
|
||||
public readonly float2 Offset;
|
||||
@@ -27,7 +26,7 @@ namespace OpenRA.Graphics
|
||||
public Sprite(Sheet sheet, Rectangle bounds, TextureChannel channel)
|
||||
: this(sheet, bounds, float2.Zero, channel) { }
|
||||
|
||||
public Sprite(Sheet sheet, Rectangle bounds, float2 offset, TextureChannel channel, BlendMode blendMode = BlendMode.Alpha, float alpha = 1f)
|
||||
public Sprite(Sheet sheet, Rectangle bounds, float2 offset, TextureChannel channel, BlendMode blendMode = BlendMode.Alpha)
|
||||
{
|
||||
Sheet = sheet;
|
||||
Bounds = bounds;
|
||||
@@ -35,7 +34,6 @@ namespace OpenRA.Graphics
|
||||
Channel = channel;
|
||||
Size = new float2(bounds.Size);
|
||||
BlendMode = blendMode;
|
||||
Alpha = alpha;
|
||||
|
||||
FractionalOffset = offset / Size;
|
||||
|
||||
|
||||
@@ -114,6 +114,7 @@ namespace OpenRA.Graphics
|
||||
|
||||
// A new bitmap is generated each time this property is accessed, so we do need to dispose it.
|
||||
using (var bitmap = face.Glyph.Bitmap)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
var p = (byte*)bitmap.Buffer;
|
||||
@@ -123,18 +124,23 @@ namespace OpenRA.Graphics
|
||||
for (var j = 0; j < s.Size.Y; j++)
|
||||
{
|
||||
for (var i = 0; i < s.Size.X; i++)
|
||||
{
|
||||
if (p[i] != 0)
|
||||
{
|
||||
var q = destStride * (j + s.Bounds.Top) + 4 * (i + s.Bounds.Left);
|
||||
dest[q] = c.Second.B;
|
||||
dest[q + 1] = c.Second.G;
|
||||
dest[q + 2] = c.Second.R;
|
||||
dest[q + 3] = p[i];
|
||||
var pmc = Util.PremultiplyAlpha(Color.FromArgb(p[i], c.Second));
|
||||
|
||||
dest[q] = pmc.B;
|
||||
dest[q + 1] = pmc.G;
|
||||
dest[q + 2] = pmc.R;
|
||||
dest[q + 3] = pmc.A;
|
||||
}
|
||||
}
|
||||
|
||||
p += bitmap.Pitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s.Sheet.CommitBufferedData();
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ namespace OpenRA.Graphics
|
||||
readonly Vertex[] vertices;
|
||||
Sheet currentSheet;
|
||||
BlendMode currentBlend = BlendMode.Alpha;
|
||||
float currentAlpha = 1f;
|
||||
int nv = 0;
|
||||
|
||||
public SpriteRenderer(Renderer renderer, IShader shader)
|
||||
@@ -37,14 +36,14 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
shader.SetTexture("DiffuseTexture", currentSheet.GetTexture());
|
||||
|
||||
renderer.Device.SetBlendMode(currentBlend, currentAlpha);
|
||||
renderer.Device.SetBlendMode(currentBlend);
|
||||
shader.Render(() =>
|
||||
{
|
||||
var vb = renderer.GetTempVertexBuffer();
|
||||
vb.SetData(vertices, nv);
|
||||
renderer.DrawBatch(vb, 0, nv, PrimitiveType.QuadList);
|
||||
});
|
||||
renderer.Device.SetBlendMode(BlendMode.None, currentAlpha);
|
||||
renderer.Device.SetBlendMode(BlendMode.None);
|
||||
|
||||
nv = 0;
|
||||
currentSheet = null;
|
||||
@@ -55,10 +54,9 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
renderer.CurrentBatchRenderer = this;
|
||||
|
||||
if (s.Alpha != currentAlpha || s.BlendMode != currentBlend || s.Sheet != currentSheet || nv + 4 > renderer.TempBufferSize)
|
||||
if (s.BlendMode != currentBlend || s.Sheet != currentSheet || nv + 4 > renderer.TempBufferSize)
|
||||
Flush();
|
||||
|
||||
currentAlpha = s.Alpha;
|
||||
currentBlend = s.BlendMode;
|
||||
currentSheet = s.Sheet;
|
||||
}
|
||||
|
||||
@@ -73,18 +73,37 @@ namespace OpenRA.Graphics
|
||||
|
||||
try
|
||||
{
|
||||
var data = dest.Sheet.GetData();
|
||||
var dataStride = dest.Sheet.Size.Width * 4;
|
||||
var x = dest.Bounds.Left * 4;
|
||||
var width = dest.Bounds.Width * 4;
|
||||
var y = dest.Bounds.Top;
|
||||
var destData = dest.Sheet.GetData();
|
||||
var destStride = dest.Sheet.Size.Width;
|
||||
var width = dest.Bounds.Width;
|
||||
var height = dest.Bounds.Height;
|
||||
|
||||
var bd = src.LockBits(src.Bounds(),
|
||||
ImageLockMode.ReadWrite, src.PixelFormat);
|
||||
for (var row = 0; row < height; row++)
|
||||
Marshal.Copy(IntPtr.Add(bd.Scan0, row * bd.Stride), data, (y + row) * dataStride + x, width);
|
||||
src.UnlockBits(bd);
|
||||
var srcData = src.LockBits(src.Bounds(),
|
||||
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
|
||||
unsafe
|
||||
{
|
||||
var c = (int*)srcData.Scan0;
|
||||
|
||||
// Cast the data to an int array so we can copy the src data directly
|
||||
fixed (byte* bd = &destData[0])
|
||||
{
|
||||
var data = (int*)bd;
|
||||
var x = dest.Bounds.Left;
|
||||
var y = dest.Bounds.Top;
|
||||
|
||||
for (var j = 0; j < height; j++)
|
||||
{
|
||||
for (var i = 0; i < width; i++)
|
||||
{
|
||||
var cc = Color.FromArgb(*(c + (j * srcData.Stride >> 2) + i));
|
||||
data[(y + j) * destStride + x + i] = PremultiplyAlpha(cc).ToArgb();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
src.UnlockBits(srcData);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -93,6 +112,12 @@ namespace OpenRA.Graphics
|
||||
}
|
||||
}
|
||||
|
||||
public static Color PremultiplyAlpha(Color c)
|
||||
{
|
||||
var a = c.A / 255f;
|
||||
return Color.FromArgb(c.A, (byte)(c.R * a + 0.5f), (byte)(c.G * a + 0.5f), (byte)(c.B * a + 0.5f));
|
||||
}
|
||||
|
||||
public static float[] IdentityMatrix()
|
||||
{
|
||||
return Exts.MakeArray(16, j => (j % 5 == 0) ? 1.0f : 0);
|
||||
|
||||
Reference in New Issue
Block a user