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 sealed class HardwarePalette : IDisposable
|
||||||
{
|
{
|
||||||
public const int MaxPalettes = 256;
|
|
||||||
|
|
||||||
public ITexture Texture { get; private set; }
|
public ITexture Texture { get; private set; }
|
||||||
|
public int Height { get; private set; }
|
||||||
readonly Dictionary<string, ImmutablePalette> palettes = new Dictionary<string, ImmutablePalette>();
|
readonly Dictionary<string, ImmutablePalette> palettes = new Dictionary<string, ImmutablePalette>();
|
||||||
readonly Dictionary<string, MutablePalette> modifiablePalettes = new Dictionary<string, MutablePalette>();
|
readonly Dictionary<string, MutablePalette> modifiablePalettes = new Dictionary<string, MutablePalette>();
|
||||||
readonly IReadOnlyDictionary<string, MutablePalette> readOnlyModifiablePalettes;
|
readonly IReadOnlyDictionary<string, MutablePalette> readOnlyModifiablePalettes;
|
||||||
readonly Dictionary<string, int> indices = new Dictionary<string, int>();
|
readonly Dictionary<string, int> indices = new Dictionary<string, int>();
|
||||||
readonly uint[,] buffer = new uint[MaxPalettes, Palette.Size];
|
byte[] buffer = new byte[0];
|
||||||
|
|
||||||
public HardwarePalette()
|
public HardwarePalette()
|
||||||
{
|
{
|
||||||
@@ -52,14 +51,19 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
public void AddPalette(string name, ImmutablePalette p, bool allowModifiers)
|
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))
|
if (palettes.ContainsKey(name))
|
||||||
throw new InvalidOperationException("Palette {0} has already been defined".F(name));
|
throw new InvalidOperationException("Palette {0} has already been defined".F(name));
|
||||||
|
|
||||||
int index = palettes.Count;
|
int index = palettes.Count;
|
||||||
indices.Add(name, index);
|
indices.Add(name, index);
|
||||||
palettes.Add(name, p);
|
palettes.Add(name, p);
|
||||||
|
|
||||||
|
if (palettes.Count > Height)
|
||||||
|
{
|
||||||
|
Height = Exts.NextPowerOf2(palettes.Count);
|
||||||
|
Array.Resize(ref buffer, Height * Palette.Size * 4);
|
||||||
|
}
|
||||||
|
|
||||||
if (allowModifiers)
|
if (allowModifiers)
|
||||||
modifiablePalettes.Add(name, new MutablePalette(p));
|
modifiablePalettes.Add(name, new MutablePalette(p));
|
||||||
else
|
else
|
||||||
@@ -74,13 +78,13 @@ namespace OpenRA.Graphics
|
|||||||
CopyPaletteToBuffer(indices[name], palettes[name] = new ImmutablePalette(p));
|
CopyPaletteToBuffer(indices[name], palettes[name] = new ImmutablePalette(p));
|
||||||
else
|
else
|
||||||
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
|
throw new InvalidOperationException("Palette `{0}` does not exist".F(name));
|
||||||
Texture.SetData(buffer);
|
CopyBufferToTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
CopyModifiablePalettesToBuffer();
|
CopyModifiablePalettesToBuffer();
|
||||||
Texture.SetData(buffer);
|
CopyBufferToTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CopyPaletteToBuffer(int index, IPalette p)
|
void CopyPaletteToBuffer(int index, IPalette p)
|
||||||
@@ -94,6 +98,11 @@ namespace OpenRA.Graphics
|
|||||||
CopyPaletteToBuffer(indices[kvp.Key], kvp.Value);
|
CopyPaletteToBuffer(indices[kvp.Key], kvp.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CopyBufferToTexture()
|
||||||
|
{
|
||||||
|
Texture.SetData(buffer, Palette.Size, Height);
|
||||||
|
}
|
||||||
|
|
||||||
public void ApplyModifiers(IEnumerable<IPaletteModifier> paletteMods)
|
public void ApplyModifiers(IEnumerable<IPaletteModifier> paletteMods)
|
||||||
{
|
{
|
||||||
foreach (var mod in paletteMods)
|
foreach (var mod in paletteMods)
|
||||||
@@ -101,7 +110,7 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
// Update our texture with the changes.
|
// Update our texture with the changes.
|
||||||
CopyModifiablePalettesToBuffer();
|
CopyModifiablePalettesToBuffer();
|
||||||
Texture.SetData(buffer);
|
CopyBufferToTexture();
|
||||||
|
|
||||||
// Reset modified palettes back to their original colors, ready for next time.
|
// Reset modified palettes back to their original colors, ready for next time.
|
||||||
foreach (var kvp in modifiablePalettes)
|
foreach (var kvp in modifiablePalettes)
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ namespace OpenRA.Graphics
|
|||||||
PaletteReference CreatePaletteReference(string name)
|
PaletteReference CreatePaletteReference(string name)
|
||||||
{
|
{
|
||||||
var pal = palette.GetPalette(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;
|
string cursorName;
|
||||||
|
|||||||
@@ -51,15 +51,15 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
public void DrawSprite(Sprite s, float2 location, PaletteReference pal)
|
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)
|
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;
|
renderer.CurrentBatchRenderer = this;
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
currentBlend = s.BlendMode;
|
currentBlend = s.BlendMode;
|
||||||
currentSheet = s.Sheet;
|
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;
|
nv += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace OpenRA.Graphics
|
|||||||
this.world = world;
|
this.world = world;
|
||||||
this.map = world.Map;
|
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 vertices = new Vertex[4 * map.Bounds.Height * map.Bounds.Width];
|
||||||
var nv = 0;
|
var nv = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -21,23 +21,22 @@ namespace OpenRA.Graphics
|
|||||||
static readonly int[] ChannelMasks = { 2, 1, 0, 3 };
|
static readonly int[] ChannelMasks = { 2, 1, 0, 3 };
|
||||||
static readonly float[] ChannelSelect = { 0.75f, 0.25f, -0.25f, -0.75f };
|
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 b = new float2(o.X + size.X, o.Y);
|
||||||
var c = new float2(o.X + size.X, o.Y + size.Y);
|
var c = new float2(o.X + size.X, o.Y + size.Y);
|
||||||
var d = new float2(o.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];
|
var attribC = ChannelSelect[(int)r.Channel];
|
||||||
|
|
||||||
vertices[nv] = new Vertex(a, r.Left, r.Top, attribP, attribC);
|
vertices[nv] = new Vertex(a, r.Left, r.Top, paletteTextureIndex, attribC);
|
||||||
vertices[nv + 1] = new Vertex(b, r.Right, r.Top, attribP, attribC);
|
vertices[nv + 1] = new Vertex(b, r.Right, r.Top, paletteTextureIndex, attribC);
|
||||||
vertices[nv + 2] = new Vertex(c, r.Right, r.Bottom, attribP, attribC);
|
vertices[nv + 2] = new Vertex(c, r.Right, r.Bottom, paletteTextureIndex, attribC);
|
||||||
vertices[nv + 3] = new Vertex(d, r.Left, r.Bottom, attribP, 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); }
|
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));
|
var lightDirection = ExtractRotationVector(Util.MatrixMultiply(Util.MatrixInverse(t), lightTransform));
|
||||||
|
|
||||||
Render(rd, Util.MatrixMultiply(transform, t), lightDirection,
|
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
|
// Disable shadow normals by forcing zero diffuse and identity ambient light
|
||||||
Render(rd, Util.MatrixMultiply(shadow, t), lightDirection,
|
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,
|
VoxelRenderData renderData,
|
||||||
float[] t, float[] lightDirection,
|
float[] t, float[] lightDirection,
|
||||||
float[] ambientLight, float[] diffuseLight,
|
float[] ambientLight, float[] diffuseLight,
|
||||||
int colorPalette, int normalsPalette)
|
float colorPaletteTextureMidIndex, float normalsPaletteTextureMidIndex)
|
||||||
{
|
{
|
||||||
shader.SetTexture("DiffuseTexture", renderData.Sheet.GetTexture());
|
shader.SetTexture("DiffuseTexture", renderData.Sheet.GetTexture());
|
||||||
shader.SetVec("PaletteRows",
|
shader.SetVec("PaletteRows", colorPaletteTextureMidIndex, normalsPaletteTextureMidIndex);
|
||||||
(colorPalette + 0.5f) / HardwarePalette.MaxPalettes,
|
|
||||||
(normalsPalette + 0.5f) / HardwarePalette.MaxPalettes);
|
|
||||||
shader.SetMatrix("TransformMatrix", t);
|
shader.SetMatrix("TransformMatrix", t);
|
||||||
shader.SetVec("LightDirection", lightDirection, 4);
|
shader.SetVec("LightDirection", lightDirection, 4);
|
||||||
shader.SetVec("AmbientLight", ambientLight, 3);
|
shader.SetVec("AmbientLight", ambientLight, 3);
|
||||||
|
|||||||
@@ -19,13 +19,17 @@ namespace OpenRA.Graphics
|
|||||||
public class PaletteReference
|
public class PaletteReference
|
||||||
{
|
{
|
||||||
public readonly string Name;
|
public readonly string Name;
|
||||||
public readonly int Index;
|
|
||||||
public IPalette Palette { get; internal set; }
|
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;
|
Name = name;
|
||||||
Index = index;
|
|
||||||
Palette = palette;
|
Palette = palette;
|
||||||
|
this.index = index;
|
||||||
|
this.hardwarePalette = hardwarePalette;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +66,7 @@ namespace OpenRA.Graphics
|
|||||||
PaletteReference CreatePaletteReference(string name)
|
PaletteReference CreatePaletteReference(string name)
|
||||||
{
|
{
|
||||||
var pal = palette.GetPalette(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); }
|
public PaletteReference Palette(string name) { return palettes.GetOrAdd(name, CreatePaletteReference); }
|
||||||
|
|||||||
Reference in New Issue
Block a user