Merge pull request #11098 from pchote/vertex-secondary-texcoords

Replace SheetType.DualIndexed with secondary texture coordinates on Vertex.
This commit is contained in:
Matthias Mailänder
2016-04-17 10:22:57 +02:00
16 changed files with 132 additions and 87 deletions

View File

@@ -69,12 +69,12 @@ namespace OpenRA.Graphics
var eb = endColor.B / 255.0f;
var ea = endColor.A / 255.0f;
vertices[nv++] = new Vertex(start - corner + Offset, sr, sg, sb, sa);
vertices[nv++] = new Vertex(start + corner + Offset, sr, sg, sb, sa);
vertices[nv++] = new Vertex(end + corner + Offset, er, eg, eb, ea);
vertices[nv++] = new Vertex(end + corner + Offset, er, eg, eb, ea);
vertices[nv++] = new Vertex(end - corner + Offset, er, eg, eb, ea);
vertices[nv++] = new Vertex(start - corner + Offset, sr, sg, sb, sa);
vertices[nv++] = new Vertex(start - corner + Offset, sr, sg, sb, sa, 0, 0);
vertices[nv++] = new Vertex(start + corner + Offset, sr, sg, sb, sa, 0, 0);
vertices[nv++] = new Vertex(end + corner + Offset, er, eg, eb, ea, 0, 0);
vertices[nv++] = new Vertex(end + corner + Offset, er, eg, eb, ea, 0, 0);
vertices[nv++] = new Vertex(end - corner + Offset, er, eg, eb, ea, 0, 0);
vertices[nv++] = new Vertex(start - corner + Offset, sr, sg, sb, sa, 0, 0);
}
public void DrawLine(float2 start, float2 end, float width, Color color)
@@ -93,12 +93,12 @@ namespace OpenRA.Graphics
var b = color.B / 255.0f;
var a = color.A / 255.0f;
vertices[nv++] = new Vertex(start - corner + Offset, r, g, b, a);
vertices[nv++] = new Vertex(start + corner + Offset, r, g, b, a);
vertices[nv++] = new Vertex(end + corner + Offset, r, g, b, a);
vertices[nv++] = new Vertex(end + corner + Offset, r, g, b, a);
vertices[nv++] = new Vertex(end - corner + Offset, r, g, b, a);
vertices[nv++] = new Vertex(start - corner + Offset, r, g, b, a);
vertices[nv++] = new Vertex(start - corner + Offset, r, g, b, a, 0, 0);
vertices[nv++] = new Vertex(start + corner + Offset, r, g, b, a, 0, 0);
vertices[nv++] = new Vertex(end + corner + Offset, r, g, b, a, 0, 0);
vertices[nv++] = new Vertex(end + corner + Offset, r, g, b, a, 0, 0);
vertices[nv++] = new Vertex(end - corner + Offset, r, g, b, a, 0, 0);
vertices[nv++] = new Vertex(start - corner + Offset, r, g, b, a, 0, 0);
}
/// <summary>
@@ -186,12 +186,12 @@ namespace OpenRA.Graphics
if (nv + 6 > renderer.TempBufferSize)
Flush();
vertices[nv++] = new Vertex(ca + Offset, r, g, b, a);
vertices[nv++] = new Vertex(cb + Offset, r, g, b, a);
vertices[nv++] = new Vertex(cc + Offset, r, g, b, a);
vertices[nv++] = new Vertex(cc + Offset, r, g, b, a);
vertices[nv++] = new Vertex(cd + Offset, r, g, b, a);
vertices[nv++] = new Vertex(ca + Offset, r, g, b, a);
vertices[nv++] = new Vertex(ca + Offset, r, g, b, a, 0, 0);
vertices[nv++] = new Vertex(cb + Offset, r, g, b, a, 0, 0);
vertices[nv++] = new Vertex(cc + Offset, r, g, b, a, 0, 0);
vertices[nv++] = new Vertex(cc + Offset, r, g, b, a, 0, 0);
vertices[nv++] = new Vertex(cd + Offset, r, g, b, a, 0, 0);
vertices[nv++] = new Vertex(ca + Offset, r, g, b, a, 0, 0);
// Advance line segment
end = next;
@@ -243,12 +243,12 @@ namespace OpenRA.Graphics
var cb = color.B / 255.0f;
var ca = color.A / 255.0f;
vertices[nv++] = new Vertex(a + Offset, cr, cg, cb, ca);
vertices[nv++] = new Vertex(b + Offset, cr, cg, cb, ca);
vertices[nv++] = new Vertex(c + Offset, cr, cg, cb, ca);
vertices[nv++] = new Vertex(c + Offset, cr, cg, cb, ca);
vertices[nv++] = new Vertex(d + Offset, cr, cg, cb, ca);
vertices[nv++] = new Vertex(a + Offset, cr, cg, cb, ca);
vertices[nv++] = new Vertex(a + Offset, cr, cg, cb, ca, 0, 0);
vertices[nv++] = new Vertex(b + Offset, cr, cg, cb, ca, 0, 0);
vertices[nv++] = new Vertex(c + Offset, cr, cg, cb, ca, 0, 0);
vertices[nv++] = new Vertex(c + Offset, cr, cg, cb, ca, 0, 0);
vertices[nv++] = new Vertex(d + Offset, cr, cg, cb, ca, 0, 0);
vertices[nv++] = new Vertex(a + Offset, cr, cg, cb, ca, 0, 0);
}
public void FillEllipse(RectangleF r, Color color, int vertices = 32)

View File

@@ -25,8 +25,7 @@ namespace OpenRA.Graphics
public enum SheetType
{
Indexed = 1,
DualIndexed = 2,
BGRA = 4,
BGRA = 2,
}
public sealed class SheetBuilder : IDisposable

View File

@@ -48,6 +48,24 @@ namespace OpenRA.Graphics
}
}
public class SpriteWithSecondaryData : Sprite
{
public readonly Rectangle SecondaryBounds;
public readonly TextureChannel SecondaryChannel;
public readonly float SecondaryTop, SecondaryLeft, SecondaryBottom, SecondaryRight;
public SpriteWithSecondaryData(Sprite s, Rectangle secondaryBounds, TextureChannel secondaryChannel)
: base(s.Sheet, s.Bounds, s.ZRamp, s.Offset, s.Channel, s.BlendMode)
{
SecondaryBounds = secondaryBounds;
SecondaryChannel = secondaryChannel;
SecondaryLeft = (float)Math.Min(secondaryBounds.Left, secondaryBounds.Right) / s.Sheet.Size.Width;
SecondaryTop = (float)Math.Min(secondaryBounds.Top, secondaryBounds.Bottom) / s.Sheet.Size.Height;
SecondaryRight = (float)Math.Max(secondaryBounds.Left, secondaryBounds.Right) / s.Sheet.Size.Width;
SecondaryBottom = (float)Math.Max(secondaryBounds.Top, secondaryBounds.Bottom) / s.Sheet.Size.Height;
}
}
public enum TextureChannel : byte
{
Red = 0,

View File

@@ -59,7 +59,7 @@ namespace OpenRA.Graphics
for (var i = 0; i < vertices.Length; i++)
{
var v = vertices[i];
vertices[i] = new Vertex(v.X, v.Y, v.Z, v.U, v.V, palette.TextureIndex, v.C);
vertices[i] = new Vertex(v.X, v.Y, v.Z, v.S, v.T, v.U, v.V, palette.TextureIndex, v.C);
}
for (var row = 0; row < map.MapSize.Y; row++)

View File

@@ -43,7 +43,6 @@ namespace OpenRA.Graphics
{
this.tileset = tileset;
var allocated = false;
var type = tileset.EnableDepth ? SheetType.DualIndexed : SheetType.Indexed;
Func<Sheet> allocate = () =>
{
@@ -51,10 +50,10 @@ namespace OpenRA.Graphics
throw new SheetOverflowException("Terrain sheet overflow. Try increasing the tileset SheetSize parameter.");
allocated = true;
return new Sheet(type, new Size(tileset.SheetSize, tileset.SheetSize));
return new Sheet(SheetType.Indexed, new Size(tileset.SheetSize, tileset.SheetSize));
};
sheetBuilder = new SheetBuilder(type, allocate);
sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate);
random = new MersenneTwister();
var frameCache = new FrameCache(Game.ModData.DefaultFileSystem, Game.ModData.SpriteLoaders);
@@ -71,10 +70,17 @@ namespace OpenRA.Graphics
{
var f = allFrames[j];
var s = sheetBuilder.Allocate(f.Size, f.Offset);
Util.FastCopyIntoChannel(s, 0, f.Data);
Util.FastCopyIntoChannel(s, f.Data);
if (tileset.EnableDepth)
Util.FastCopyIntoChannel(s, 1, allFrames[j + frameCount].Data);
{
var ss = sheetBuilder.Allocate(f.Size, f.Offset);
Util.FastCopyIntoChannel(ss, allFrames[j + frameCount].Data);
// s and ss are guaranteed to use the same sheet
// because of the custom terrain sheet allocation
s = new SpriteWithSecondaryData(s, ss.Bounds, ss.Channel);
}
return s;
}).ToArray());

View File

@@ -31,25 +31,36 @@ namespace OpenRA.Graphics
public static void FastCreateQuad(Vertex[] vertices, float3 a, float3 b, float3 c, float3 d, Sprite r, float paletteTextureIndex, int nv)
{
float sl = 0;
float st = 0;
float sr = 0;
float sb = 0;
var attribC = ChannelSelect[(int)r.Channel];
if (r.Sheet.Type == SheetType.DualIndexed)
attribC *= -1;
vertices[nv] = new Vertex(a, r.Left, r.Top, paletteTextureIndex, attribC);
vertices[nv + 1] = new Vertex(b, r.Right, r.Top, paletteTextureIndex, attribC);
vertices[nv + 2] = new Vertex(c, r.Right, r.Bottom, paletteTextureIndex, attribC);
vertices[nv + 3] = new Vertex(c, r.Right, r.Bottom, paletteTextureIndex, attribC);
vertices[nv + 4] = new Vertex(d, r.Left, r.Bottom, paletteTextureIndex, attribC);
vertices[nv + 5] = new Vertex(a, r.Left, r.Top, paletteTextureIndex, attribC);
var ss = r as SpriteWithSecondaryData;
if (ss != null)
{
sl = ss.SecondaryLeft;
st = ss.SecondaryTop;
sr = ss.SecondaryRight;
sb = ss.SecondaryBottom;
attribC = -(attribC + ChannelSelect[(int)ss.Channel] / 10);
}
public static void FastCopyIntoChannel(Sprite dest, byte[] src) { FastCopyIntoChannel(dest, 0, src); }
public static void FastCopyIntoChannel(Sprite dest, int channelOffset, byte[] src)
vertices[nv] = new Vertex(a, r.Left, r.Top, sl, st, paletteTextureIndex, attribC);
vertices[nv + 1] = new Vertex(b, r.Right, r.Top, sr, st, paletteTextureIndex, attribC);
vertices[nv + 2] = new Vertex(c, r.Right, r.Bottom, sr, sb, paletteTextureIndex, attribC);
vertices[nv + 3] = new Vertex(c, r.Right, r.Bottom, sr, sb, paletteTextureIndex, attribC);
vertices[nv + 4] = new Vertex(d, r.Left, r.Bottom, sl, sb, paletteTextureIndex, attribC);
vertices[nv + 5] = new Vertex(a, r.Left, r.Top, sl, st, paletteTextureIndex, attribC);
}
public static void FastCopyIntoChannel(Sprite dest, byte[] src)
{
var data = dest.Sheet.GetData();
var srcStride = dest.Bounds.Width;
var destStride = dest.Sheet.Size.Width * 4;
var destOffset = destStride * dest.Bounds.Top + dest.Bounds.Left * 4 + ChannelMasks[(int)dest.Channel + channelOffset];
var destOffset = destStride * dest.Bounds.Top + dest.Bounds.Left * 4 + ChannelMasks[(int)dest.Channel];
var destSkip = destStride - 4 * srcStride;
var height = dest.Bounds.Height;

View File

@@ -16,14 +16,15 @@ namespace OpenRA.Graphics
[StructLayout(LayoutKind.Sequential)]
public struct Vertex
{
public readonly float X, Y, Z, U, V, P, C;
public readonly float X, Y, Z, S, T, U, V, P, C;
public Vertex(float3 xyz, float u, float v, float p, float c)
: this(xyz.X, xyz.Y, xyz.Z, u, v, p, c) { }
public Vertex(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) { }
public Vertex(float x, float y, float z, float u, float v, float p, float c)
public Vertex(float x, float y, float z, float s, float t, float u, float v, float p, float c)
{
X = x; Y = y; Z = z;
S = s; T = t;
U = u; V = v;
P = p; C = c;
}

View File

@@ -54,10 +54,10 @@ namespace OpenRA.Graphics
if (allocated)
throw new SheetOverflowException("");
allocated = true;
return SheetBuilder.AllocateSheet(SheetType.DualIndexed, Game.Settings.Graphics.SheetSize);
return SheetBuilder.AllocateSheet(SheetType.Indexed, Game.Settings.Graphics.SheetSize);
};
return new SheetBuilder(SheetType.DualIndexed, allocate);
return new SheetBuilder(SheetType.Indexed, allocate);
}
public VoxelLoader(IReadOnlyFileSystem fileSystem)
@@ -78,6 +78,7 @@ namespace OpenRA.Graphics
var c = 0;
for (var v = 0; v < sv; v++)
{
for (var u = 0; u < su; u++)
{
var voxel = first(u, v) ?? second(u, v);
@@ -85,22 +86,28 @@ namespace OpenRA.Graphics
normals[c] = voxel == null ? (byte)0 : voxel.Normal;
c++;
}
}
var s = sheetBuilder.Allocate(new Size(su, sv));
Util.FastCopyIntoChannel(s, 0, colors);
Util.FastCopyIntoChannel(s, 1, normals);
var size = new Size(su, sv);
var s = sheetBuilder.Allocate(size);
var t = sheetBuilder.Allocate(size);
Util.FastCopyIntoChannel(s, colors);
Util.FastCopyIntoChannel(t, normals);
// s and t are guaranteed to use the same sheet because
// of the custom voxel sheet allocation implementation
s.Sheet.CommitBufferedData();
var channelP = ChannelSelect[(int)s.Channel];
var channelC = ChannelSelect[(int)s.Channel + 1];
var channelC = ChannelSelect[(int)t.Channel];
return new Vertex[6]
{
new Vertex(coord(0, 0), s.Left, s.Top, channelP, channelC),
new Vertex(coord(su, 0), s.Right, s.Top, channelP, channelC),
new Vertex(coord(su, sv), s.Right, s.Bottom, channelP, channelC),
new Vertex(coord(su, sv), s.Right, s.Bottom, channelP, channelC),
new Vertex(coord(0, sv), s.Left, s.Bottom, channelP, channelC),
new Vertex(coord(0, 0), s.Left, s.Top, channelP, channelC)
new Vertex(coord(0, 0), s.Left, s.Top, t.Left, t.Top, channelP, channelC),
new Vertex(coord(su, 0), s.Right, s.Top, t.Right, t.Top, channelP, channelC),
new Vertex(coord(su, sv), s.Right, s.Bottom, t.Right, t.Bottom, channelP, channelC),
new Vertex(coord(su, sv), s.Right, s.Bottom, t.Right, t.Bottom, channelP, channelC),
new Vertex(coord(0, sv), s.Left, s.Bottom, t.Left, t.Bottom, channelP, channelC),
new Vertex(coord(0, 0), s.Left, s.Top, t.Left, t.Top, channelP, channelC)
};
}

View File

@@ -332,7 +332,7 @@ namespace OpenRA.Graphics
var size = new Size(renderer.SheetSize, renderer.SheetSize);
var framebuffer = renderer.Device.CreateFrameBuffer(size);
var sheet = new Sheet(SheetType.DualIndexed, framebuffer.Texture);
var sheet = new Sheet(SheetType.BGRA, framebuffer.Texture);
mappedBuffers.Add(sheet, framebuffer);
return sheet;

View File

@@ -81,6 +81,8 @@ namespace OpenRA.Platforms.Default
OpenGL.CheckGLError();
OpenGL.glEnableVertexAttribArray(Shader.TexCoordAttributeIndex);
OpenGL.CheckGLError();
OpenGL.glEnableVertexAttribArray(Shader.TexMetadataAttributeIndex);
OpenGL.CheckGLError();
SDL.SDL_SetModState(SDL.SDL_Keymod.KMOD_NONE);
input = new Sdl2Input();

View File

@@ -20,6 +20,7 @@ namespace OpenRA.Platforms.Default
{
public const int VertexPosAttributeIndex = 0;
public const int TexCoordAttributeIndex = 1;
public const int TexMetadataAttributeIndex = 2;
readonly Dictionary<string, int> samplers = new Dictionary<string, int>();
readonly Dictionary<int, ITexture> textures = new Dictionary<int, ITexture>();
@@ -73,7 +74,8 @@ namespace OpenRA.Platforms.Default
OpenGL.CheckGLError();
OpenGL.glBindAttribLocation(program, TexCoordAttributeIndex, "aVertexTexCoord");
OpenGL.CheckGLError();
OpenGL.glBindAttribLocation(program, TexMetadataAttributeIndex, "aVertexTexMetadata");
OpenGL.CheckGLError();
OpenGL.glAttachShader(program, vertexShader);
OpenGL.CheckGLError();
OpenGL.glAttachShader(program, fragmentShader);

View File

@@ -87,6 +87,8 @@ namespace OpenRA.Platforms.Default
OpenGL.CheckGLError();
OpenGL.glVertexAttribPointer(Shader.TexCoordAttributeIndex, 4, OpenGL.GL_FLOAT, false, VertexSize, new IntPtr(12));
OpenGL.CheckGLError();
OpenGL.glVertexAttribPointer(Shader.TexMetadataAttributeIndex, 2, OpenGL.GL_FLOAT, false, VertexSize, new IntPtr(28));
OpenGL.CheckGLError();
}
~VertexBuffer()

View File

@@ -4,13 +4,14 @@ uniform bool EnableDepthPreview;
uniform float DepthTextureScale;
varying vec4 vTexCoord;
varying vec2 vTexMetadata;
varying vec4 vChannelMask;
varying vec4 vDepthMask;
void main()
{
vec4 x = texture2D(DiffuseTexture, vTexCoord.st);
vec2 p = vec2(dot(x, vChannelMask), vTexCoord.p);
vec2 p = vec2(dot(x, vChannelMask), vTexMetadata.s);
vec4 c = texture2D(Palette, p);
// Discard any transparent fragments (both color and depth)
@@ -20,8 +21,8 @@ void main()
float depth = gl_FragCoord.z;
if (length(vDepthMask) > 0.0)
{
// Preview vertex aware depth
depth = depth + DepthTextureScale * dot(x, vDepthMask);
vec4 y = texture2D(DiffuseTexture, vTexCoord.pq);
depth = depth + DepthTextureScale * dot(y, vDepthMask);
}
// Convert to window coords

View File

@@ -3,41 +3,35 @@ uniform vec3 r1, r2;
attribute vec4 aVertexPosition;
attribute vec4 aVertexTexCoord;
attribute vec2 aVertexTexMetadata;
varying vec4 vTexCoord;
varying vec2 vTexMetadata;
varying vec4 vChannelMask;
varying vec4 vDepthMask;
vec4 DecodeChannelMask(float x)
{
float y = abs(x);
if (y > 0.7)
if (x > 0.7)
return vec4(0,0,0,1);
if (y > 0.5)
if (x > 0.5)
return vec4(0,0,1,0);
if (y > 0.3)
if (x > 0.3)
return vec4(0,1,0,0);
else
return vec4(1,0,0,0);
}
vec4 DecodeDepthChannelMask(float x)
{
if (x > 0.0)
return vec4(0,0,0,0);
if (x < -0.7)
return vec4(1,0,0,0);
if (x < -0.5)
return vec4(0,0,0,1);
if (x < -0.3)
return vec4(0,0,1,0);
else
return vec4(0,1,0,0);
}
void main()
{
gl_Position = vec4((aVertexPosition.xyz - Scroll.xyz) * r1 + r2, 1);
vTexCoord = aVertexTexCoord;
vChannelMask = DecodeChannelMask(aVertexTexCoord.w);
vDepthMask = DecodeDepthChannelMask(aVertexTexCoord.w);
vTexMetadata = aVertexTexMetadata;
vChannelMask = DecodeChannelMask(abs(aVertexTexMetadata.t));
if (aVertexTexMetadata.t < 0.0)
{
float x = -aVertexTexMetadata.t * 10.0;
vDepthMask = DecodeChannelMask(x - floor(x));
}
else
vDepthMask = vec4(0,0,0,0);
}

View File

@@ -15,7 +15,8 @@ void main()
if (color.a < 0.01)
discard;
vec4 normal = (2.0 * texture2D(Palette, vec2(dot(x, vNormalsMask), PaletteRows.y)) - 1.0);
vec4 y = texture2D(DiffuseTexture, vTexCoord.pq);
vec4 normal = (2.0 * texture2D(Palette, vec2(dot(y, vNormalsMask), PaletteRows.y)) - 1.0);
vec3 intensity = AmbientLight + DiffuseLight * max(dot(normal, LightDirection), 0.0);
gl_FragColor = vec4(intensity * color.rgb, color.a);
}

View File

@@ -3,6 +3,7 @@ uniform mat4 TransformMatrix;
attribute vec4 aVertexPosition;
attribute vec4 aVertexTexCoord;
attribute vec2 aVertexTexMetadata;
varying vec4 vTexCoord;
varying vec4 vChannelMask;
varying vec4 vNormalsMask;
@@ -19,6 +20,6 @@ void main()
{
gl_Position = View*TransformMatrix*aVertexPosition;
vTexCoord = aVertexTexCoord;
vChannelMask = DecodeMask(aVertexTexCoord.z);
vNormalsMask = DecodeMask(aVertexTexCoord.w);
vChannelMask = DecodeMask(aVertexTexMetadata.s);
vNormalsMask = DecodeMask(aVertexTexMetadata.t);
}