Merge pull request #7291 from RoosterDragon/dynamic-palette-sizing
Implement dynamic hardware palette sizing.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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); }
|
||||
|
||||
Reference in New Issue
Block a user