Pack vertex attributes and palette into a single integer bitfield.

This commit is contained in:
Paul Chote
2023-10-23 19:07:55 +01:00
committed by Gustas
parent 143cd8f856
commit 3bb42522b8
6 changed files with 143 additions and 181 deletions

View File

@@ -45,10 +45,10 @@ namespace OpenRA.Graphics
var eb = endColor.B / 255.0f; var eb = endColor.B / 255.0f;
var ea = endColor.A / 255.0f; var ea = endColor.A / 255.0f;
vertices[0] = new Vertex(start - corner + Offset, sr, sg, sb, sa, 0, 0); vertices[0] = new Vertex(start - corner + Offset, sr, sg, sb, sa, 0);
vertices[1] = new Vertex(start + corner + Offset, sr, sg, sb, sa, 0, 0); vertices[1] = new Vertex(start + corner + Offset, sr, sg, sb, sa, 0);
vertices[2] = new Vertex(end + corner + Offset, er, eg, eb, ea, 0, 0); vertices[2] = new Vertex(end + corner + Offset, er, eg, eb, ea, 0);
vertices[3] = new Vertex(end - corner + Offset, er, eg, eb, ea, 0, 0); vertices[3] = new Vertex(end - corner + Offset, er, eg, eb, ea, 0);
parent.DrawRGBAQuad(vertices, blendMode); parent.DrawRGBAQuad(vertices, blendMode);
} }
@@ -64,10 +64,10 @@ namespace OpenRA.Graphics
var b = color.B / 255.0f; var b = color.B / 255.0f;
var a = color.A / 255.0f; var a = color.A / 255.0f;
vertices[0] = new Vertex(start - corner + Offset, r, g, b, a, 0, 0); vertices[0] = new Vertex(start - corner + Offset, r, g, b, a, 0);
vertices[1] = new Vertex(start + corner + Offset, r, g, b, a, 0, 0); vertices[1] = new Vertex(start + corner + Offset, r, g, b, a, 0);
vertices[2] = new Vertex(end + corner + Offset, r, g, b, a, 0, 0); vertices[2] = new Vertex(end + corner + Offset, r, g, b, a, 0);
vertices[3] = new Vertex(end - corner + Offset, r, g, b, a, 0, 0); vertices[3] = new Vertex(end - corner + Offset, r, g, b, a, 0);
parent.DrawRGBAQuad(vertices, blendMode); parent.DrawRGBAQuad(vertices, blendMode);
} }
@@ -153,10 +153,10 @@ namespace OpenRA.Graphics
var cd = closed || i < limit - 1 ? IntersectionOf(end - corner, dir, end - nextCorner, nextDir) : end - corner; var cd = closed || i < limit - 1 ? IntersectionOf(end - corner, dir, end - nextCorner, nextDir) : end - corner;
// Fill segment // Fill segment
vertices[0] = new Vertex(ca + Offset, r, g, b, a, 0, 0); vertices[0] = new Vertex(ca + Offset, r, g, b, a, 0);
vertices[1] = new Vertex(cb + Offset, r, g, b, a, 0, 0); vertices[1] = new Vertex(cb + Offset, r, g, b, a, 0);
vertices[2] = new Vertex(cc + Offset, r, g, b, a, 0, 0); vertices[2] = new Vertex(cc + Offset, r, g, b, a, 0);
vertices[3] = new Vertex(cd + Offset, r, g, b, a, 0, 0); vertices[3] = new Vertex(cd + Offset, r, g, b, a, 0);
parent.DrawRGBAQuad(vertices, blendMode); parent.DrawRGBAQuad(vertices, blendMode);
// Advance line segment // Advance line segment
@@ -209,10 +209,10 @@ namespace OpenRA.Graphics
var cb = color.B / 255.0f; var cb = color.B / 255.0f;
var ca = color.A / 255.0f; var ca = color.A / 255.0f;
vertices[0] = new Vertex(a + Offset, cr, cg, cb, ca, 0, 0); vertices[0] = new Vertex(a + Offset, cr, cg, cb, ca, 0);
vertices[1] = new Vertex(b + Offset, cr, cg, cb, ca, 0, 0); vertices[1] = new Vertex(b + Offset, cr, cg, cb, ca, 0);
vertices[2] = new Vertex(c + Offset, cr, cg, cb, ca, 0, 0); vertices[2] = new Vertex(c + Offset, cr, cg, cb, ca, 0);
vertices[3] = new Vertex(d + Offset, cr, cg, cb, ca, 0, 0); vertices[3] = new Vertex(d + Offset, cr, cg, cb, ca, 0);
parent.DrawRGBAQuad(vertices, blendMode); parent.DrawRGBAQuad(vertices, blendMode);
} }
@@ -234,7 +234,7 @@ namespace OpenRA.Graphics
var cb = color.B / 255.0f; var cb = color.B / 255.0f;
var ca = color.A / 255.0f; var ca = color.A / 255.0f;
return new Vertex(xyz, cr, cg, cb, ca, 0, 0); return new Vertex(xyz, cr, cg, cb, ca, 0);
} }
public void FillEllipse(in float3 tl, in float3 br, Color color, BlendMode blendMode = BlendMode.Alpha) public void FillEllipse(in float3 tl, in float3 br, Color color, BlendMode blendMode = BlendMode.Alpha)

View File

@@ -76,7 +76,8 @@ namespace OpenRA.Graphics
{ {
var v = vertices[i]; var v = vertices[i];
var p = palettes[i / 4]?.TextureIndex ?? 0; var p = palettes[i / 4]?.TextureIndex ?? 0;
vertices[i] = new Vertex(v.X, v.Y, v.Z, v.S, v.T, v.U, v.V, p, v.C, v.R, v.G, v.B, v.A); var c = (uint)((p & 0xFFFF) << 16) | (v.C & 0xFFFF);
vertices[i] = new Vertex(v.X, v.Y, v.Z, v.S, v.T, v.U, v.V, c, v.R, v.G, v.B, v.A);
} }
for (var row = 0; row < map.MapSize.Y; row++) for (var row = 0; row < map.MapSize.Y; row++)
@@ -113,7 +114,7 @@ namespace OpenRA.Graphics
for (var i = 0; i < 4; i++) for (var i = 0; i < 4; i++)
{ {
var v = vertices[offset + i]; var v = vertices[offset + i];
vertices[offset + i] = new Vertex(v.X, v.Y, v.Z, v.S, v.T, v.U, v.V, v.P, v.C, v.A * float3.Ones, v.A); vertices[offset + i] = new Vertex(v.X, v.Y, v.Z, v.S, v.T, v.U, v.V, v.C, v.A * float3.Ones, v.A);
} }
return; return;
@@ -138,7 +139,7 @@ namespace OpenRA.Graphics
for (var i = 0; i < 4; i++) for (var i = 0; i < 4; i++)
{ {
var v = vertices[offset + i]; var v = vertices[offset + i];
vertices[offset + i] = new Vertex(v.X, v.Y, v.Z, v.S, v.T, v.U, v.V, v.P, v.C, v.A * weights[i], v.A); vertices[offset + i] = new Vertex(v.X, v.Y, v.Z, v.S, v.T, v.U, v.V, v.C, v.A * weights[i], v.A);
} }
dirtyRows.Add(uv.V); dirtyRows.Add(uv.V);

View File

@@ -94,11 +94,13 @@ namespace OpenRA.Graphics
attribC |= samplers.Y << 9; attribC |= samplers.Y << 9;
} }
var fAttribC = (float)attribC; attribC |= (paletteTextureIndex & 0xFFFF) << 16;
vertices[nv] = new Vertex(a, r.Left, r.Top, sl, st, paletteTextureIndex, fAttribC, tint, alpha);
vertices[nv + 1] = new Vertex(b, r.Right, r.Top, sr, st, paletteTextureIndex, fAttribC, tint, alpha); var uAttribC = (uint)attribC;
vertices[nv + 2] = new Vertex(c, r.Right, r.Bottom, sr, sb, paletteTextureIndex, fAttribC, tint, alpha); vertices[nv] = new Vertex(a, r.Left, r.Top, sl, st, uAttribC, tint, alpha);
vertices[nv + 3] = new Vertex(d, r.Left, r.Bottom, sl, sb, paletteTextureIndex, fAttribC, tint, alpha); vertices[nv + 1] = new Vertex(b, r.Right, r.Top, sr, st, uAttribC, tint, alpha);
vertices[nv + 2] = new Vertex(c, r.Right, r.Bottom, sr, sb, uAttribC, tint, alpha);
vertices[nv + 3] = new Vertex(d, r.Left, r.Bottom, sl, sb, uAttribC, tint, alpha);
} }
public static void FastCopyIntoChannel(Sprite dest, byte[] src, SpriteFrameType srcType) public static void FastCopyIntoChannel(Sprite dest, byte[] src, SpriteFrameType srcType)

View File

@@ -23,26 +23,26 @@ namespace OpenRA.Graphics
public readonly float S, T, U, V; public readonly float S, T, U, V;
// Palette and channel flags // Palette and channel flags
public readonly float P, C; public readonly uint C;
// Color tint // Color tint
public readonly float R, G, B, A; public readonly float R, G, B, A;
public Vertex(in float3 xyz, float s, float t, float u, float v, float p, float c) public Vertex(in float3 xyz, float s, float t, float u, float v, uint c)
: this(xyz.X, xyz.Y, xyz.Z, s, t, u, v, p, c, float3.Ones, 1f) { } : this(xyz.X, xyz.Y, xyz.Z, s, t, u, v, c, float3.Ones, 1f) { }
public Vertex(in float3 xyz, float s, float t, float u, float v, float p, float c, in float3 tint, float a) public Vertex(in float3 xyz, float s, float t, float u, float v, uint c, in float3 tint, float a)
: this(xyz.X, xyz.Y, xyz.Z, s, t, u, v, p, c, tint.X, tint.Y, tint.Z, a) { } : this(xyz.X, xyz.Y, xyz.Z, s, t, u, v, c, tint.X, tint.Y, tint.Z, a) { }
public Vertex(float x, float y, float z, float s, float t, float u, float v, float p, float c, in float3 tint, float a) public Vertex(float x, float y, float z, float s, float t, float u, float v, uint c, in float3 tint, float a)
: this(x, y, z, s, t, u, v, p, c, tint.X, tint.Y, tint.Z, a) { } : this(x, y, z, s, t, u, v, c, tint.X, tint.Y, tint.Z, a) { }
public Vertex(float x, float y, float z, float s, float t, float u, float v, float p, float c, float r, float g, float b, float a) public Vertex(float x, float y, float z, float s, float t, float u, float v, uint c, float r, float g, float b, float a)
{ {
X = x; Y = y; Z = z; X = x; Y = y; Z = z;
S = s; T = t; S = s; T = t;
U = u; V = v; U = u; V = v;
P = p; C = c; C = c;
R = r; G = g; B = b; A = a; R = r; G = g; B = b; A = a;
} }
} }
@@ -57,8 +57,8 @@ namespace OpenRA.Graphics
{ {
new ShaderVertexAttribute("aVertexPosition", ShaderVertexAttributeType.Float, 3, 0), new ShaderVertexAttribute("aVertexPosition", ShaderVertexAttributeType.Float, 3, 0),
new ShaderVertexAttribute("aVertexTexCoord", ShaderVertexAttributeType.Float, 4, 12), new ShaderVertexAttribute("aVertexTexCoord", ShaderVertexAttributeType.Float, 4, 12),
new ShaderVertexAttribute("aVertexTexMetadata", ShaderVertexAttributeType.Float, 2, 28), new ShaderVertexAttribute("aVertexAttributes", ShaderVertexAttributeType.UInt, 1, 28),
new ShaderVertexAttribute("aVertexTint", ShaderVertexAttributeType.Float, 4, 36) new ShaderVertexAttribute("aVertexTint", ShaderVertexAttributeType.Float, 4, 32)
}; };
} }
} }

View File

@@ -19,17 +19,13 @@ uniform vec2 DepthPreviewParams;
uniform float DepthTextureScale; uniform float DepthTextureScale;
uniform float AntialiasPixelsPerTexel; uniform float AntialiasPixelsPerTexel;
in vec4 vColor;
in vec4 vTexCoord; in vec4 vTexCoord;
in float vTexPalette; flat in float vTexPalette;
in vec4 vChannelMask; flat in vec4 vChannelMask;
in vec4 vDepthMask; flat in uint vChannelSampler;
in vec2 vTexSampler; flat in uint vChannelType;
flat in vec4 vDepthMask;
in vec4 vColorFraction; flat in uint vDepthSampler;
in vec4 vRGBAFraction;
in vec4 vPalettedFraction;
in vec4 vTint; in vec4 vTint;
out vec4 fragColor; out vec4 fragColor;
@@ -77,47 +73,53 @@ vec4 linear2srgb(vec4 c)
return c.a * vec4(linear2srgb(c.r / c.a), linear2srgb(c.g / c.a), linear2srgb(c.b / c.a), 1.0f); return c.a * vec4(linear2srgb(c.r / c.a), linear2srgb(c.g / c.a), linear2srgb(c.b / c.a), 1.0f);
} }
ivec2 Size(float samplerIndex) ivec2 Size(uint samplerIndex)
{ {
if (samplerIndex < 0.5) switch (samplerIndex)
return textureSize(Texture0, 0); {
else if (samplerIndex < 1.5) case 7u:
return textureSize(Texture1, 0); return textureSize(Texture7, 0);
else if (samplerIndex < 2.5) case 6u:
return textureSize(Texture2, 0); return textureSize(Texture6, 0);
else if (samplerIndex < 3.5) case 5u:
return textureSize(Texture3, 0); return textureSize(Texture5, 0);
else if (samplerIndex < 4.5) case 4u:
return textureSize(Texture4, 0); return textureSize(Texture4, 0);
else if (samplerIndex < 5.5) case 3u:
return textureSize(Texture5, 0); return textureSize(Texture3, 0);
else if (samplerIndex < 6.5) case 2u:
return textureSize(Texture6, 0); return textureSize(Texture2, 0);
case 1u:
return textureSize(Texture7, 0); return textureSize(Texture1, 0);
default:
return textureSize(Texture0, 0);
}
} }
vec4 Sample(float samplerIndex, vec2 pos) vec4 Sample(uint samplerIndex, vec2 pos)
{ {
if (samplerIndex < 0.5) switch (samplerIndex)
return texture(Texture0, pos); {
else if (samplerIndex < 1.5) case 7u:
return texture(Texture1, pos); return texture(Texture7, pos);
else if (samplerIndex < 2.5) case 6u:
return texture(Texture2, pos); return texture(Texture6, pos);
else if (samplerIndex < 3.5) case 5u:
return texture(Texture3, pos); return texture(Texture5, pos);
else if (samplerIndex < 4.5) case 4u:
return texture(Texture4, pos); return texture(Texture4, pos);
else if (samplerIndex < 5.5) case 3u:
return texture(Texture5, pos); return texture(Texture3, pos);
else if (samplerIndex < 6.5) case 2u:
return texture(Texture6, pos); return texture(Texture2, pos);
case 1u:
return texture(Texture7, pos); return texture(Texture1, pos);
default:
return texture(Texture0, pos);
}
} }
vec4 SamplePalettedBilinear(float samplerIndex, vec2 coords, vec2 textureSize) vec4 SamplePalettedBilinear(uint samplerIndex, vec2 coords, vec2 textureSize)
{ {
vec2 texPos = (coords * textureSize) - vec2(0.5); vec2 texPos = (coords * textureSize) - vec2(0.5);
vec2 interp = fract(texPos); vec2 interp = fract(texPos);
@@ -152,11 +154,13 @@ vec4 ColorShift(vec4 c, float p)
void main() void main()
{ {
vec2 coords = vTexCoord.st; vec2 coords = vTexCoord.st;
bool isPaletted = (vChannelType & 0x01u) != 0u;
bool isColor = vChannelType == 0u;
vec4 c; vec4 c;
if (AntialiasPixelsPerTexel > 0.0) if (AntialiasPixelsPerTexel > 0.0)
{ {
vec2 textureSize = vec2(Size(vTexSampler.s)); vec2 textureSize = vec2(Size(vChannelSampler));
vec2 offset = fract(coords.st * textureSize); vec2 offset = fract(coords.st * textureSize);
// Offset the sampling point to simulate bilinear intepolation in window coordinates instead of texture coordinates // Offset the sampling point to simulate bilinear intepolation in window coordinates instead of texture coordinates
@@ -167,28 +171,33 @@ void main()
vec2 interp = clamp(offset * ik * AntialiasPixelsPerTexel, 0.0, .5) + clamp((offset - 1.0) * ik * AntialiasPixelsPerTexel + .5, 0.0, .5); vec2 interp = clamp(offset * ik * AntialiasPixelsPerTexel, 0.0, .5) + clamp((offset - 1.0) * ik * AntialiasPixelsPerTexel + .5, 0.0, .5);
coords = (floor(coords.st * textureSize) + interp) / textureSize; coords = (floor(coords.st * textureSize) + interp) / textureSize;
if (vPalettedFraction.x > 0.0) if (isPaletted)
c = SamplePalettedBilinear(vTexSampler.s, coords, textureSize); c = SamplePalettedBilinear(vChannelSampler, coords, textureSize);
} }
if (!(AntialiasPixelsPerTexel > 0.0 && vPalettedFraction.x > 0.0)) if (!(AntialiasPixelsPerTexel > 0.0 && isPaletted))
{ {
vec4 x = Sample(vTexSampler.s, coords); vec4 x = Sample(vChannelSampler, coords);
vec2 p = vec2(dot(x, vChannelMask), vTexPalette); vec2 p = vec2(dot(x, vChannelMask), vTexPalette);
c = vPalettedFraction * texture(Palette, p) + vRGBAFraction * x + vColorFraction * vTexCoord; if (isPaletted)
c = texture(Palette, p);
else if (isColor)
c = vTexCoord;
else
c = x;
} }
// Discard any transparent fragments (both color and depth) // Discard any transparent fragments (both color and depth)
if (c.a == 0.0) if (c.a == 0.0)
discard; discard;
if (vRGBAFraction.r > 0.0 && vTexPalette > 0.0) if (!isPaletted && vTexPalette > 0.0)
c = ColorShift(c, vTexPalette); c = ColorShift(c, vTexPalette);
float depth = gl_FragCoord.z; float depth = gl_FragCoord.z;
if (length(vDepthMask) > 0.0) if (length(vDepthMask) > 0.0)
{ {
vec4 y = Sample(vTexSampler.t, vTexCoord.pq); vec4 y = Sample(vDepthSampler, vTexCoord.pq);
depth = depth + DepthTextureScale * dot(y, vDepthMask); depth = depth + DepthTextureScale * dot(y, vDepthMask);
} }

View File

@@ -6,109 +6,59 @@ uniform float PaletteRows;
in vec3 aVertexPosition; in vec3 aVertexPosition;
in vec4 aVertexTexCoord; in vec4 aVertexTexCoord;
in vec2 aVertexTexMetadata; in uint aVertexAttributes;
in vec4 aVertexTint; in vec4 aVertexTint;
out vec4 vTexCoord; out vec4 vTexCoord;
out float vTexPalette; flat out float vTexPalette;
out vec4 vChannelMask; flat out vec4 vChannelMask;
out vec4 vDepthMask; flat out uint vChannelSampler;
out vec2 vTexSampler; flat out uint vChannelType;
flat out vec4 vDepthMask;
out vec4 vColorFraction; flat out uint vDepthSampler;
out vec4 vRGBAFraction;
out vec4 vPalettedFraction;
out vec4 vTint; out vec4 vTint;
vec4 UnpackChannelAttributes(float x) vec4 SelectChannelMask(uint x)
{ {
// The channel attributes float encodes a set of attributes switch (x)
// stored as flags in the mantissa of the unnormalized float value. {
// Bits 9-11 define the sampler index (0-7) that the secondary texture is bound to case 7u:
// Bits 6-8 define the sampler index (0-7) that the primary texture is bound to return vec4(0.0, 0.0, 0.0, 1.0);
// Bits 3-5 define the behaviour of the secondary texture channel: case 5u:
// 000: Channel is not used return vec4(0.0, 0.0, 1.0, 0.0);
// 001, 011, 101, 111: Sample depth sprite from channel R,G,B,A case 3u:
// Bits 0-2 define the behaviour of the primary texture channel: return vec4(0, 1.0, 0.0, 0.0);
// 000: Channel is not used (aVertexTexCoord instead defines a color value) case 2u:
// 010: Sample RGBA sprite from all four channels return vec4(1.0, 1.0, 1.0, 1.0);
// 001, 011, 101, 111: Sample paletted sprite from channel R,G,B,A case 1u:
return vec4(1.0, 0.0, 0.0, 0.0);
float secondarySampler = 0.0; default:
if (x >= 2048.0) { x -= 2048.0; secondarySampler += 4.0; } return vec4(0.0, 0.0, 0.0, 0.0);
if (x >= 1024.0) { x -= 1024.0; secondarySampler += 2.0; } }
if (x >= 512.0) { x -= 512.0; secondarySampler += 1.0; }
float primarySampler = 0.0;
if (x >= 256.0) { x -= 256.0; primarySampler += 4.0; }
if (x >= 128.0) { x -= 128.0; primarySampler += 2.0; }
if (x >= 64.0) { x -= 64.0; primarySampler += 1.0; }
float secondaryChannel = 0.0;
if (x >= 32.0) { x -= 32.0; secondaryChannel += 4.0; }
if (x >= 16.0) { x -= 16.0; secondaryChannel += 2.0; }
if (x >= 8.0) { x -= 8.0; secondaryChannel += 1.0; }
float primaryChannel = 0.0;
if (x >= 4.0) { x -= 4.0; primaryChannel += 4.0; }
if (x >= 2.0) { x -= 2.0; primaryChannel += 2.0; }
if (x >= 1.0) { x -= 1.0; primaryChannel += 1.0; }
return vec4(primaryChannel, secondaryChannel, primarySampler, secondarySampler);
}
vec4 SelectChannelMask(float x)
{
if (x >= 7.0)
return vec4(0,0,0,1);
if (x >= 5.0)
return vec4(0,0,1,0);
if (x >= 3.0)
return vec4(0,1,0,0);
if (x >= 2.0)
return vec4(1,1,1,1);
if (x >= 1.0)
return vec4(1,0,0,0);
return vec4(0, 0, 0, 0);
}
vec4 SelectColorFraction(float x)
{
if (x > 0.0)
return vec4(0, 0, 0, 0);
return vec4(1, 1, 1, 1);
}
vec4 SelectRGBAFraction(float x)
{
if (x == 2.0)
return vec4(1, 1, 1, 1);
return vec4(0, 0, 0, 0);
}
vec4 SelectPalettedFraction(float x)
{
if (x == 0.0 || x == 2.0)
return vec4(0, 0, 0, 0);
return vec4(1, 1, 1, 1);
} }
void main() void main()
{ {
gl_Position = vec4((aVertexPosition - Scroll) * p1 + p2, 1); gl_Position = vec4((aVertexPosition - Scroll) * p1 + p2, 1);
vTexCoord = aVertexTexCoord; vTexCoord = aVertexTexCoord;
vTexPalette = aVertexTexMetadata.s / PaletteRows;
vec4 attrib = UnpackChannelAttributes(aVertexTexMetadata.t); // aVertexAttributes is a packed bitfield, where:
vChannelMask = SelectChannelMask(attrib.s); // Bits 0-2 define the behaviour of the primary texture channel:
vColorFraction = SelectColorFraction(attrib.s); // 000: Channel is not used (aVertexTexCoord instead defines a color value)
vRGBAFraction = SelectRGBAFraction(attrib.s); // 010: Sample RGBA sprite from all four channels
vPalettedFraction = SelectPalettedFraction(attrib.s); // 001, 011, 101, 111: Sample paletted sprite from channel R,G,B,A
vDepthMask = SelectChannelMask(attrib.t); // Bits 3-5 define the behaviour of the secondary texture channel:
vTexSampler = attrib.pq; // 000: Channel is not used
// 001, 011, 101, 111: Sample depth sprite from channel R,G,B,A
// Bits 6-8 define the sampler index (0-7) that the primary texture is bound to
// Bits 9-11 define the sampler index (0-7) that the secondary texture is bound to
// Bits 16-31 define the palette row for paletted sprites
vChannelType = aVertexAttributes & 0x07u;
vChannelMask = SelectChannelMask(vChannelType);
vDepthMask = SelectChannelMask((aVertexAttributes >> 3) & 0x07u);
vChannelSampler = (aVertexAttributes >> 6) & 0x07u;
vDepthSampler = (aVertexAttributes >> 9) & 0x07u;
vTexPalette = (aVertexAttributes >> 16) / PaletteRows;
vTint = aVertexTint; vTint = aVertexTint;
} }