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 ea = endColor.A / 255.0f;
vertices[0] = new Vertex(start - corner + Offset, sr, sg, sb, sa, 0, 0);
vertices[1] = new Vertex(start + corner + Offset, sr, sg, sb, sa, 0, 0);
vertices[2] = new Vertex(end + corner + Offset, er, eg, eb, ea, 0, 0);
vertices[3] = new Vertex(end - corner + Offset, er, eg, eb, ea, 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);
vertices[2] = new Vertex(end + corner + Offset, er, eg, eb, ea, 0);
vertices[3] = new Vertex(end - corner + Offset, er, eg, eb, ea, 0);
parent.DrawRGBAQuad(vertices, blendMode);
}
@@ -64,10 +64,10 @@ namespace OpenRA.Graphics
var b = color.B / 255.0f;
var a = color.A / 255.0f;
vertices[0] = new Vertex(start - corner + Offset, r, g, b, a, 0, 0);
vertices[1] = new Vertex(start + corner + Offset, r, g, b, a, 0, 0);
vertices[2] = new Vertex(end + corner + Offset, r, g, b, a, 0, 0);
vertices[3] = new Vertex(end - 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);
vertices[2] = new Vertex(end + corner + Offset, r, g, b, a, 0);
vertices[3] = new Vertex(end - corner + Offset, r, g, b, a, 0);
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;
// Fill segment
vertices[0] = new Vertex(ca + Offset, r, g, b, a, 0, 0);
vertices[1] = new Vertex(cb + Offset, r, g, b, a, 0, 0);
vertices[2] = new Vertex(cc + Offset, r, g, b, a, 0, 0);
vertices[3] = new Vertex(cd + 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);
vertices[2] = new Vertex(cc + Offset, r, g, b, a, 0);
vertices[3] = new Vertex(cd + Offset, r, g, b, a, 0);
parent.DrawRGBAQuad(vertices, blendMode);
// Advance line segment
@@ -209,10 +209,10 @@ namespace OpenRA.Graphics
var cb = color.B / 255.0f;
var ca = color.A / 255.0f;
vertices[0] = new Vertex(a + Offset, cr, cg, cb, ca, 0, 0);
vertices[1] = new Vertex(b + Offset, cr, cg, cb, ca, 0, 0);
vertices[2] = new Vertex(c + Offset, cr, cg, cb, ca, 0, 0);
vertices[3] = new Vertex(d + 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);
vertices[2] = new Vertex(c + Offset, cr, cg, cb, ca, 0);
vertices[3] = new Vertex(d + Offset, cr, cg, cb, ca, 0);
parent.DrawRGBAQuad(vertices, blendMode);
}
@@ -234,7 +234,7 @@ namespace OpenRA.Graphics
var cb = color.B / 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)

View File

@@ -76,7 +76,8 @@ namespace OpenRA.Graphics
{
var v = vertices[i];
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++)
@@ -113,7 +114,7 @@ namespace OpenRA.Graphics
for (var i = 0; i < 4; 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;
@@ -138,7 +139,7 @@ namespace OpenRA.Graphics
for (var i = 0; i < 4; 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);

View File

@@ -94,11 +94,13 @@ namespace OpenRA.Graphics
attribC |= samplers.Y << 9;
}
var fAttribC = (float)attribC;
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);
vertices[nv + 2] = new Vertex(c, r.Right, r.Bottom, sr, sb, paletteTextureIndex, fAttribC, tint, alpha);
vertices[nv + 3] = new Vertex(d, r.Left, r.Bottom, sl, sb, paletteTextureIndex, fAttribC, tint, alpha);
attribC |= (paletteTextureIndex & 0xFFFF) << 16;
var uAttribC = (uint)attribC;
vertices[nv] = new Vertex(a, r.Left, r.Top, sl, st, uAttribC, 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)

View File

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

View File

@@ -19,17 +19,13 @@ uniform vec2 DepthPreviewParams;
uniform float DepthTextureScale;
uniform float AntialiasPixelsPerTexel;
in vec4 vColor;
in vec4 vTexCoord;
in float vTexPalette;
in vec4 vChannelMask;
in vec4 vDepthMask;
in vec2 vTexSampler;
in vec4 vColorFraction;
in vec4 vRGBAFraction;
in vec4 vPalettedFraction;
flat in float vTexPalette;
flat in vec4 vChannelMask;
flat in uint vChannelSampler;
flat in uint vChannelType;
flat in vec4 vDepthMask;
flat in uint vDepthSampler;
in vec4 vTint;
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);
}
ivec2 Size(float samplerIndex)
ivec2 Size(uint samplerIndex)
{
if (samplerIndex < 0.5)
return textureSize(Texture0, 0);
else if (samplerIndex < 1.5)
return textureSize(Texture1, 0);
else if (samplerIndex < 2.5)
return textureSize(Texture2, 0);
else if (samplerIndex < 3.5)
return textureSize(Texture3, 0);
else if (samplerIndex < 4.5)
return textureSize(Texture4, 0);
else if (samplerIndex < 5.5)
return textureSize(Texture5, 0);
else if (samplerIndex < 6.5)
return textureSize(Texture6, 0);
switch (samplerIndex)
{
case 7u:
return textureSize(Texture7, 0);
case 6u:
return textureSize(Texture6, 0);
case 5u:
return textureSize(Texture5, 0);
case 4u:
return textureSize(Texture4, 0);
case 3u:
return textureSize(Texture3, 0);
case 2u:
return textureSize(Texture2, 0);
case 1u:
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)
return texture(Texture0, pos);
else if (samplerIndex < 1.5)
return texture(Texture1, pos);
else if (samplerIndex < 2.5)
return texture(Texture2, pos);
else if (samplerIndex < 3.5)
return texture(Texture3, pos);
else if (samplerIndex < 4.5)
return texture(Texture4, pos);
else if (samplerIndex < 5.5)
return texture(Texture5, pos);
else if (samplerIndex < 6.5)
return texture(Texture6, pos);
switch (samplerIndex)
{
case 7u:
return texture(Texture7, pos);
case 6u:
return texture(Texture6, pos);
case 5u:
return texture(Texture5, pos);
case 4u:
return texture(Texture4, pos);
case 3u:
return texture(Texture3, pos);
case 2u:
return texture(Texture2, pos);
case 1u:
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 interp = fract(texPos);
@@ -152,11 +154,13 @@ vec4 ColorShift(vec4 c, float p)
void main()
{
vec2 coords = vTexCoord.st;
bool isPaletted = (vChannelType & 0x01u) != 0u;
bool isColor = vChannelType == 0u;
vec4 c;
if (AntialiasPixelsPerTexel > 0.0)
{
vec2 textureSize = vec2(Size(vTexSampler.s));
vec2 textureSize = vec2(Size(vChannelSampler));
vec2 offset = fract(coords.st * textureSize);
// 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);
coords = (floor(coords.st * textureSize) + interp) / textureSize;
if (vPalettedFraction.x > 0.0)
c = SamplePalettedBilinear(vTexSampler.s, coords, textureSize);
if (isPaletted)
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);
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)
if (c.a == 0.0)
discard;
if (vRGBAFraction.r > 0.0 && vTexPalette > 0.0)
if (!isPaletted && vTexPalette > 0.0)
c = ColorShift(c, vTexPalette);
float depth = gl_FragCoord.z;
if (length(vDepthMask) > 0.0)
{
vec4 y = Sample(vTexSampler.t, vTexCoord.pq);
vec4 y = Sample(vDepthSampler, vTexCoord.pq);
depth = depth + DepthTextureScale * dot(y, vDepthMask);
}

View File

@@ -6,109 +6,59 @@ uniform float PaletteRows;
in vec3 aVertexPosition;
in vec4 aVertexTexCoord;
in vec2 aVertexTexMetadata;
in uint aVertexAttributes;
in vec4 aVertexTint;
out vec4 vTexCoord;
out float vTexPalette;
out vec4 vChannelMask;
out vec4 vDepthMask;
out vec2 vTexSampler;
out vec4 vColorFraction;
out vec4 vRGBAFraction;
out vec4 vPalettedFraction;
flat out float vTexPalette;
flat out vec4 vChannelMask;
flat out uint vChannelSampler;
flat out uint vChannelType;
flat out vec4 vDepthMask;
flat out uint vDepthSampler;
out vec4 vTint;
vec4 UnpackChannelAttributes(float x)
vec4 SelectChannelMask(uint x)
{
// The channel attributes float encodes a set of attributes
// 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
// Bits 6-8 define the sampler index (0-7) that the primary texture is bound to
// Bits 3-5 define the behaviour of the secondary texture channel:
// 000: Channel is not used
// 001, 011, 101, 111: Sample depth sprite from channel R,G,B,A
// Bits 0-2 define the behaviour of the primary texture channel:
// 000: Channel is not used (aVertexTexCoord instead defines a color value)
// 010: Sample RGBA sprite from all four channels
// 001, 011, 101, 111: Sample paletted sprite from channel R,G,B,A
float secondarySampler = 0.0;
if (x >= 2048.0) { x -= 2048.0; secondarySampler += 4.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);
switch (x)
{
case 7u:
return vec4(0.0, 0.0, 0.0, 1.0);
case 5u:
return vec4(0.0, 0.0, 1.0, 0.0);
case 3u:
return vec4(0, 1.0, 0.0, 0.0);
case 2u:
return vec4(1.0, 1.0, 1.0, 1.0);
case 1u:
return vec4(1.0, 0.0, 0.0, 0.0);
default:
return vec4(0.0, 0.0, 0.0, 0.0);
}
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()
{
gl_Position = vec4((aVertexPosition - Scroll) * p1 + p2, 1);
vTexCoord = aVertexTexCoord;
vTexPalette = aVertexTexMetadata.s / PaletteRows;
vec4 attrib = UnpackChannelAttributes(aVertexTexMetadata.t);
vChannelMask = SelectChannelMask(attrib.s);
vColorFraction = SelectColorFraction(attrib.s);
vRGBAFraction = SelectRGBAFraction(attrib.s);
vPalettedFraction = SelectPalettedFraction(attrib.s);
vDepthMask = SelectChannelMask(attrib.t);
vTexSampler = attrib.pq;
// aVertexAttributes is a packed bitfield, where:
// Bits 0-2 define the behaviour of the primary texture channel:
// 000: Channel is not used (aVertexTexCoord instead defines a color value)
// 010: Sample RGBA sprite from all four channels
// 001, 011, 101, 111: Sample paletted sprite from channel R,G,B,A
// Bits 3-5 define the behaviour of the secondary texture channel:
// 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;
}