Merge pull request #7291 from RoosterDragon/dynamic-palette-sizing

Implement dynamic hardware palette sizing.
This commit is contained in:
Paul Chote
2015-01-13 17:41:15 +13:00
7 changed files with 42 additions and 32 deletions

View File

@@ -16,14 +16,13 @@ namespace OpenRA.Graphics
{
public sealed class HardwarePalette : IDisposable
{
public const int MaxPalettes = 256;
public ITexture Texture { get; private set; }
public int Height { get; private set; }
readonly Dictionary<string, ImmutablePalette> palettes = new Dictionary<string, ImmutablePalette>();
readonly Dictionary<string, MutablePalette> modifiablePalettes = new Dictionary<string, MutablePalette>();
readonly IReadOnlyDictionary<string, MutablePalette> readOnlyModifiablePalettes;
readonly Dictionary<string, int> indices = new Dictionary<string, int>();
readonly uint[,] buffer = new uint[MaxPalettes, Palette.Size];
byte[] buffer = new byte[0];
public HardwarePalette()
{
@@ -52,14 +51,19 @@ namespace OpenRA.Graphics
public void AddPalette(string name, ImmutablePalette p, bool allowModifiers)
{
if (palettes.Count >= MaxPalettes)
throw new InvalidOperationException("Limit of {0} palettes reached. Cannot add {1}.".F(MaxPalettes, name));
if (palettes.ContainsKey(name))
throw new InvalidOperationException("Palette {0} has already been defined".F(name));
int index = palettes.Count;
indices.Add(name, index);
palettes.Add(name, p);
if (palettes.Count > Height)
{
Height = Exts.NextPowerOf2(palettes.Count);
Array.Resize(ref buffer, Height * Palette.Size * 4);
}
if (allowModifiers)
modifiablePalettes.Add(name, new MutablePalette(p));
else
@@ -74,13 +78,13 @@ namespace OpenRA.Graphics
CopyPaletteToBuffer(indices[name], palettes[name] = new ImmutablePalette(p));
else
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
Texture.SetData(buffer);
CopyBufferToTexture();
}
public void Initialize()
{
CopyModifiablePalettesToBuffer();
Texture.SetData(buffer);
CopyBufferToTexture();
}
void CopyPaletteToBuffer(int index, IPalette p)
@@ -94,6 +98,11 @@ namespace OpenRA.Graphics
CopyPaletteToBuffer(indices[kvp.Key], kvp.Value);
}
void CopyBufferToTexture()
{
Texture.SetData(buffer, Palette.Size, Height);
}
public void ApplyModifiers(IEnumerable<IPaletteModifier> paletteMods)
{
foreach (var mod in paletteMods)
@@ -101,7 +110,7 @@ namespace OpenRA.Graphics
// Update our texture with the changes.
CopyModifiablePalettesToBuffer();
Texture.SetData(buffer);
CopyBufferToTexture();
// Reset modified palettes back to their original colors, ready for next time.
foreach (var kvp in modifiablePalettes)

View File

@@ -57,7 +57,7 @@ namespace OpenRA.Graphics
PaletteReference CreatePaletteReference(string name)
{
var pal = palette.GetPalette(name);
return new PaletteReference(name, palette.GetPaletteIndex(name), pal);
return new PaletteReference(name, palette.GetPaletteIndex(name), pal, palette);
}
string cursorName;

View File

@@ -51,15 +51,15 @@ namespace OpenRA.Graphics
public void DrawSprite(Sprite s, float2 location, PaletteReference pal)
{
DrawSprite(s, location, pal.Index, s.Size);
DrawSprite(s, location, pal.TextureIndex, s.Size);
}
public void DrawSprite(Sprite s, float2 location, PaletteReference pal, float2 size)
{
DrawSprite(s, location, pal.Index, size);
DrawSprite(s, location, pal.TextureIndex, size);
}
void DrawSprite(Sprite s, float2 location, int paletteIndex, float2 size)
void DrawSprite(Sprite s, float2 location, float paletteTextureIndex, float2 size)
{
renderer.CurrentBatchRenderer = this;
@@ -74,7 +74,7 @@ namespace OpenRA.Graphics
currentBlend = s.BlendMode;
currentSheet = s.Sheet;
Util.FastCreateQuad(vertices, location + s.FractionalOffset * size, s, paletteIndex, nv, size);
Util.FastCreateQuad(vertices, location + s.FractionalOffset * size, s, paletteTextureIndex, nv, size);
nv += 4;
}

View File

@@ -24,7 +24,7 @@ namespace OpenRA.Graphics
this.world = world;
this.map = world.Map;
var terrainPalette = wr.Palette("terrain").Index;
var terrainPalette = wr.Palette("terrain").TextureIndex;
var vertices = new Vertex[4 * map.Bounds.Height * map.Bounds.Width];
var nv = 0;

View File

@@ -21,23 +21,22 @@ namespace OpenRA.Graphics
static readonly int[] ChannelMasks = { 2, 1, 0, 3 };
static readonly float[] ChannelSelect = { 0.75f, 0.25f, -0.25f, -0.75f };
public static void FastCreateQuad(Vertex[] vertices, float2 o, Sprite r, int palette, int nv, float2 size)
public static void FastCreateQuad(Vertex[] vertices, float2 o, Sprite r, float paletteTextureIndex, int nv, float2 size)
{
var b = new float2(o.X + size.X, o.Y);
var c = new float2(o.X + size.X, o.Y + size.Y);
var d = new float2(o.X, o.Y + size.Y);
FastCreateQuad(vertices, o, b, c, d, r, palette, nv);
FastCreateQuad(vertices, o, b, c, d, r, paletteTextureIndex, nv);
}
public static void FastCreateQuad(Vertex[] vertices, float2 a, float2 b, float2 c, float2 d, Sprite r, int palette, int nv)
public static void FastCreateQuad(Vertex[] vertices, float2 a, float2 b, float2 c, float2 d, Sprite r, float paletteTextureIndex, int nv)
{
var attribP = palette / (float)HardwarePalette.MaxPalettes;
var attribC = ChannelSelect[(int)r.Channel];
vertices[nv] = new Vertex(a, r.Left, r.Top, attribP, attribC);
vertices[nv + 1] = new Vertex(b, r.Right, r.Top, attribP, attribC);
vertices[nv + 2] = new Vertex(c, r.Right, r.Bottom, attribP, attribC);
vertices[nv + 3] = new Vertex(d, r.Left, r.Bottom, attribP, attribC);
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(d, r.Left, r.Bottom, paletteTextureIndex, attribC);
}
public static void FastCopyIntoChannel(Sprite dest, byte[] src) { FastCopyIntoChannel(dest, 0, src); }

View File

@@ -203,11 +203,11 @@ namespace OpenRA.Graphics
var lightDirection = ExtractRotationVector(Util.MatrixMultiply(Util.MatrixInverse(t), lightTransform));
Render(rd, Util.MatrixMultiply(transform, t), lightDirection,
lightAmbientColor, lightDiffuseColor, color.Index, normals.Index);
lightAmbientColor, lightDiffuseColor, color.TextureMidIndex, normals.TextureMidIndex);
// Disable shadow normals by forcing zero diffuse and identity ambient light
Render(rd, Util.MatrixMultiply(shadow, t), lightDirection,
ShadowAmbient, ShadowDiffuse, shadowPalette.Index, normals.Index);
ShadowAmbient, ShadowDiffuse, shadowPalette.TextureMidIndex, normals.TextureMidIndex);
}
}
}));
@@ -254,12 +254,10 @@ namespace OpenRA.Graphics
VoxelRenderData renderData,
float[] t, float[] lightDirection,
float[] ambientLight, float[] diffuseLight,
int colorPalette, int normalsPalette)
float colorPaletteTextureMidIndex, float normalsPaletteTextureMidIndex)
{
shader.SetTexture("DiffuseTexture", renderData.Sheet.GetTexture());
shader.SetVec("PaletteRows",
(colorPalette + 0.5f) / HardwarePalette.MaxPalettes,
(normalsPalette + 0.5f) / HardwarePalette.MaxPalettes);
shader.SetVec("PaletteRows", colorPaletteTextureMidIndex, normalsPaletteTextureMidIndex);
shader.SetMatrix("TransformMatrix", t);
shader.SetVec("LightDirection", lightDirection, 4);
shader.SetVec("AmbientLight", ambientLight, 3);

View File

@@ -19,13 +19,17 @@ namespace OpenRA.Graphics
public class PaletteReference
{
public readonly string Name;
public readonly int Index;
public IPalette Palette { get; internal set; }
public PaletteReference(string name, int index, IPalette palette)
readonly float index;
readonly HardwarePalette hardwarePalette;
public float TextureIndex { get { return index / hardwarePalette.Height; } }
public float TextureMidIndex { get { return (index + 0.5f) / hardwarePalette.Height; } }
public PaletteReference(string name, int index, IPalette palette, HardwarePalette hardwarePalette)
{
Name = name;
Index = index;
Palette = palette;
this.index = index;
this.hardwarePalette = hardwarePalette;
}
}
@@ -62,7 +66,7 @@ namespace OpenRA.Graphics
PaletteReference CreatePaletteReference(string name)
{
var pal = palette.GetPalette(name);
return new PaletteReference(name, palette.GetPaletteIndex(name), pal);
return new PaletteReference(name, palette.GetPaletteIndex(name), pal, palette);
}
public PaletteReference Palette(string name) { return palettes.GetOrAdd(name, CreatePaletteReference); }