Replace ITintableRenderable with IModifyableRenderable.

This commit is contained in:
Paul Chote
2020-12-11 22:19:30 +00:00
committed by abcdefg30
parent 67754e8693
commit 8edd9de278
16 changed files with 117 additions and 56 deletions

View File

@@ -54,12 +54,13 @@ namespace OpenRA.Graphics
public IRenderable[] Render(WPos pos, WVec offset, int zOffset, PaletteReference palette, float scale)
{
var imageRenderable = new SpriteRenderable(Image, pos, offset, CurrentSequence.ZOffset + zOffset, palette, scale, IsDecoration, CurrentSequence.IgnoreWorldTint);
var tintModifiers = CurrentSequence.IgnoreWorldTint ? TintModifiers.IgnoreWorldTint : TintModifiers.None;
var imageRenderable = new SpriteRenderable(Image, pos, offset, CurrentSequence.ZOffset + zOffset, palette, scale, IsDecoration, tintModifiers);
if (CurrentSequence.ShadowStart >= 0)
{
var shadow = CurrentSequence.GetShadow(CurrentFrame, facingFunc());
var shadowRenderable = new SpriteRenderable(shadow, pos, offset, CurrentSequence.ShadowZOffset + zOffset, palette, scale, true, CurrentSequence.IgnoreWorldTint);
var shadowRenderable = new SpriteRenderable(shadow, pos, offset, CurrentSequence.ShadowZOffset + zOffset, palette, scale, true, tintModifiers);
return new IRenderable[] { shadowRenderable, imageRenderable };
}

View File

@@ -9,6 +9,7 @@
*/
#endregion
using System;
using OpenRA.Primitives;
namespace OpenRA.Graphics
@@ -32,9 +33,22 @@ namespace OpenRA.Graphics
IPalettedRenderable WithPalette(PaletteReference newPalette);
}
public interface ITintableRenderable
[Flags]
public enum TintModifiers
{
IRenderable WithTint(in float3 newTint);
None = 0,
IgnoreWorldTint = 1,
ReplaceColor = 2
}
public interface IModifyableRenderable : IRenderable
{
float Alpha { get; }
float3 Tint { get; }
TintModifiers TintModifiers { get; }
IModifyableRenderable WithAlpha(float newAlpha);
IModifyableRenderable WithTint(in float3 newTint, TintModifiers newTintModifiers);
}
public interface IFinalizedRenderable

View File

@@ -14,7 +14,7 @@ using OpenRA.Primitives;
namespace OpenRA.Graphics
{
public struct SpriteRenderable : IPalettedRenderable, ITintableRenderable, IFinalizedRenderable
public struct SpriteRenderable : IPalettedRenderable, IModifyableRenderable, IFinalizedRenderable
{
public static readonly IEnumerable<IRenderable> None = new IRenderable[0];
@@ -25,16 +25,17 @@ namespace OpenRA.Graphics
readonly PaletteReference palette;
readonly float scale;
readonly float3 tint;
readonly TintModifiers tintModifiers;
readonly float alpha;
readonly bool isDecoration;
readonly bool ignoreWorldTint;
public SpriteRenderable(Sprite sprite, WPos pos, WVec offset, int zOffset, PaletteReference palette, float scale, bool isDecoration)
: this(sprite, pos, offset, zOffset, palette, scale, float3.Ones, isDecoration, false) { }
: this(sprite, pos, offset, zOffset, palette, scale, 1f, float3.Ones, TintModifiers.None, isDecoration) { }
public SpriteRenderable(Sprite sprite, WPos pos, WVec offset, int zOffset, PaletteReference palette, float scale, bool isDecoration, bool ignoreWorldTint)
: this(sprite, pos, offset, zOffset, palette, scale, float3.Ones, isDecoration, ignoreWorldTint) { }
public SpriteRenderable(Sprite sprite, WPos pos, WVec offset, int zOffset, PaletteReference palette, float scale, bool isDecoration, TintModifiers tintModifiers)
: this(sprite, pos, offset, zOffset, palette, scale, 1f, float3.Ones, tintModifiers, isDecoration) { }
public SpriteRenderable(Sprite sprite, WPos pos, WVec offset, int zOffset, PaletteReference palette, float scale, float3 tint, bool isDecoration, bool ignoreWorldTint)
public SpriteRenderable(Sprite sprite, WPos pos, WVec offset, int zOffset, PaletteReference palette, float scale, float alpha, float3 tint, TintModifiers tintModifiers, bool isDecoration)
{
this.sprite = sprite;
this.pos = pos;
@@ -44,7 +45,8 @@ namespace OpenRA.Graphics
this.scale = scale;
this.tint = tint;
this.isDecoration = isDecoration;
this.ignoreWorldTint = ignoreWorldTint;
this.tintModifiers = tintModifiers;
this.alpha = alpha;
}
public WPos Pos { get { return pos + offset; } }
@@ -53,12 +55,24 @@ namespace OpenRA.Graphics
public int ZOffset { get { return zOffset; } }
public bool IsDecoration { get { return isDecoration; } }
public IPalettedRenderable WithPalette(PaletteReference newPalette) { return new SpriteRenderable(sprite, pos, offset, zOffset, newPalette, scale, tint, isDecoration, ignoreWorldTint); }
public IRenderable WithZOffset(int newOffset) { return new SpriteRenderable(sprite, pos, offset, newOffset, palette, scale, tint, isDecoration, ignoreWorldTint); }
public IRenderable OffsetBy(WVec vec) { return new SpriteRenderable(sprite, pos + vec, offset, zOffset, palette, scale, tint, isDecoration, ignoreWorldTint); }
public IRenderable AsDecoration() { return new SpriteRenderable(sprite, pos, offset, zOffset, palette, scale, tint, true, ignoreWorldTint); }
public float Alpha { get { return alpha; } }
public float3 Tint { get { return tint; } }
public TintModifiers TintModifiers { get { return tintModifiers; } }
public IRenderable WithTint(in float3 newTint) { return new SpriteRenderable(sprite, pos, offset, zOffset, palette, scale, newTint, isDecoration, ignoreWorldTint); }
public IPalettedRenderable WithPalette(PaletteReference newPalette) { return new SpriteRenderable(sprite, pos, offset, zOffset, newPalette, scale, alpha, tint, tintModifiers, isDecoration); }
public IRenderable WithZOffset(int newOffset) { return new SpriteRenderable(sprite, pos, offset, newOffset, palette, scale, alpha, tint, tintModifiers, isDecoration); }
public IRenderable OffsetBy(WVec vec) { return new SpriteRenderable(sprite, pos + vec, offset, zOffset, palette, scale, alpha, tint, tintModifiers, isDecoration); }
public IRenderable AsDecoration() { return new SpriteRenderable(sprite, pos, offset, zOffset, palette, scale, alpha, tint, tintModifiers, true); }
public IModifyableRenderable WithAlpha(float newAlpha)
{
return new SpriteRenderable(sprite, pos, offset, zOffset, palette, scale, newAlpha, tint, tintModifiers, isDecoration);
}
public IModifyableRenderable WithTint(in float3 newTint, TintModifiers newTintModifiers)
{
return new SpriteRenderable(sprite, pos, offset, zOffset, palette, scale, alpha, newTint, newTintModifiers, isDecoration);
}
float3 ScreenPosition(WorldRenderer wr)
{
@@ -72,16 +86,16 @@ namespace OpenRA.Graphics
public void Render(WorldRenderer wr)
{
var wsr = Game.Renderer.WorldSpriteRenderer;
if (ignoreWorldTint)
wsr.DrawSprite(sprite, ScreenPosition(wr), palette, scale * sprite.Size);
else
{
var t = tint;
if (wr.TerrainLighting != null)
t *= wr.TerrainLighting.TintAt(pos);
var t = alpha * tint;
if (wr.TerrainLighting != null && (tintModifiers & TintModifiers.IgnoreWorldTint) == 0)
t *= wr.TerrainLighting.TintAt(pos);
wsr.DrawSprite(sprite, ScreenPosition(wr), palette, scale * sprite.Size, t, 1f);
}
// Shader interprets negative alpha as a flag to use the tint colour directly instead of multiplying the sprite colour
var a = alpha;
if ((tintModifiers & TintModifiers.ReplaceColor) != 0)
a *= -1;
wsr.DrawSprite(sprite, ScreenPosition(wr), palette, scale * sprite.Size, t, a);
}
public void RenderDebugGeometry(WorldRenderer wr)

View File

@@ -148,7 +148,8 @@ namespace OpenRA.Mods.Cnc.Graphics
.MinBy(t => Math.Abs(float2.Dot(z + new float2(t[0], t[1]), q) + c));
var pos = wr.ProjectedPosition((z + new float2(step[2], step[3])).ToInt2());
rs.Add(new SpriteRenderable(s.GetSprite(step[4]), pos, WVec.Zero, 0, pal, 1f, true, s.IgnoreWorldTint).PrepareRender(wr));
var tintModifiers = s.IgnoreWorldTint ? TintModifiers.IgnoreWorldTint : TintModifiers.None;
rs.Add(new SpriteRenderable(s.GetSprite(step[4]), pos, WVec.Zero, 0, pal, 1f, true, tintModifiers).PrepareRender(wr));
z += new float2(step[0], step[1]);
if (rs.Count >= 1000)

View File

@@ -287,7 +287,7 @@ namespace OpenRA.Mods.Cnc.Traits
|| !movement.CanEnterCell(c, null, BlockedByActor.Immovable) || (mobile != null && !mobile.CanStayInCell(c)))
tile = tileBlocked;
yield return new SpriteRenderable(tile, world.Map.CenterOfCell(c), WVec.Zero, -511, pal, 1f, true, true);
yield return new SpriteRenderable(tile, world.Map.CenterOfCell(c), WVec.Zero, -511, pal, 1f, true, TintModifiers.IgnoreWorldTint);
}
}

View File

@@ -203,7 +203,7 @@ namespace OpenRA.Mods.Cnc.Traits
var tiles = power.CellsMatching(xy, footprint, dimensions);
var palette = wr.Palette(((ChronoshiftPowerInfo)power.Info).TargetOverlayPalette);
foreach (var t in tiles)
yield return new SpriteRenderable(tile, wr.World.Map.CenterOfCell(t), WVec.Zero, -511, palette, 1f, true, true);
yield return new SpriteRenderable(tile, wr.World.Map.CenterOfCell(t), WVec.Zero, -511, palette, 1f, true, TintModifiers.IgnoreWorldTint);
}
protected override string GetCursor(World world, CPos cell, int2 worldPixel, MouseInput mi)
@@ -288,7 +288,7 @@ namespace OpenRA.Mods.Cnc.Traits
foreach (var t in power.CellsMatching(sourceLocation, footprint, dimensions))
{
var tile = manager.Self.Owner.Shroud.IsExplored(t + delta) ? validTile : invalidTile;
yield return new SpriteRenderable(tile, wr.World.Map.CenterOfCell(t + delta), WVec.Zero, -511, palette, 1f, true, true);
yield return new SpriteRenderable(tile, wr.World.Map.CenterOfCell(t + delta), WVec.Zero, -511, palette, 1f, true, TintModifiers.IgnoreWorldTint);
}
// Unit previews
@@ -300,7 +300,7 @@ namespace OpenRA.Mods.Cnc.Traits
var canEnter = manager.Self.Owner.Shroud.IsExplored(targetCell) &&
unit.Trait<Chronoshiftable>().CanChronoshiftTo(unit, targetCell);
var tile = canEnter ? validTile : invalidTile;
yield return new SpriteRenderable(tile, wr.World.Map.CenterOfCell(targetCell), WVec.Zero, -511, palette, 1f, true, true);
yield return new SpriteRenderable(tile, wr.World.Map.CenterOfCell(targetCell), WVec.Zero, -511, palette, 1f, true, TintModifiers.IgnoreWorldTint);
}
var offset = world.Map.CenterOfCell(xy) - world.Map.CenterOfCell(sourceLocation);
@@ -330,7 +330,7 @@ namespace OpenRA.Mods.Cnc.Traits
// Source tiles
foreach (var t in power.CellsMatching(sourceLocation, footprint, dimensions))
yield return new SpriteRenderable(sourceTile, wr.World.Map.CenterOfCell(t), WVec.Zero, -511, palette, 1f, true, true);
yield return new SpriteRenderable(sourceTile, wr.World.Map.CenterOfCell(t), WVec.Zero, -511, palette, 1f, true, TintModifiers.IgnoreWorldTint);
}
bool IsValidTarget(CPos xy)

View File

@@ -17,7 +17,7 @@ using OpenRA.Primitives;
namespace OpenRA.Mods.Common.Graphics
{
public struct ModelRenderable : IPalettedRenderable, ITintableRenderable
public struct ModelRenderable : IPalettedRenderable, IModifyableRenderable
{
readonly IEnumerable<ModelAnimation> models;
readonly WPos pos;
@@ -30,7 +30,9 @@ namespace OpenRA.Mods.Common.Graphics
readonly PaletteReference normalsPalette;
readonly PaletteReference shadowPalette;
readonly float scale;
readonly float alpha;
readonly float3 tint;
readonly TintModifiers tintModifiers;
public ModelRenderable(
IEnumerable<ModelAnimation> models, WPos pos, int zOffset, in WRot camera, float scale,
@@ -38,14 +40,14 @@ namespace OpenRA.Mods.Common.Graphics
PaletteReference color, PaletteReference normals, PaletteReference shadow)
: this(models, pos, zOffset, camera, scale,
lightSource, lightAmbientColor, lightDiffuseColor,
color, normals, shadow,
float3.Ones) { }
color, normals, shadow, 1f,
float3.Ones, TintModifiers.None) { }
public ModelRenderable(
IEnumerable<ModelAnimation> models, WPos pos, int zOffset, in WRot camera, float scale,
in WRot lightSource, float[] lightAmbientColor, float[] lightDiffuseColor,
PaletteReference color, PaletteReference normals, PaletteReference shadow,
in float3 tint)
float alpha, in float3 tint, TintModifiers tintModifiers)
{
this.models = models;
this.pos = pos;
@@ -58,7 +60,9 @@ namespace OpenRA.Mods.Common.Graphics
palette = color;
normalsPalette = normals;
shadowPalette = shadow;
this.alpha = alpha;
this.tint = tint;
this.tintModifiers = tintModifiers;
}
public WPos Pos { get { return pos; } }
@@ -66,12 +70,16 @@ namespace OpenRA.Mods.Common.Graphics
public int ZOffset { get { return zOffset; } }
public bool IsDecoration { get { return false; } }
public float Alpha { get { return alpha; } }
public float3 Tint { get { return tint; } }
public TintModifiers TintModifiers { get { return tintModifiers; } }
public IPalettedRenderable WithPalette(PaletteReference newPalette)
{
return new ModelRenderable(
models, pos, zOffset, camera, scale,
lightSource, lightAmbientColor, lightDiffuseColor,
newPalette, normalsPalette, shadowPalette, tint);
newPalette, normalsPalette, shadowPalette, alpha, tint, tintModifiers);
}
public IRenderable WithZOffset(int newOffset)
@@ -79,7 +87,7 @@ namespace OpenRA.Mods.Common.Graphics
return new ModelRenderable(
models, pos, newOffset, camera, scale,
lightSource, lightAmbientColor, lightDiffuseColor,
palette, normalsPalette, shadowPalette, tint);
palette, normalsPalette, shadowPalette, alpha, tint, tintModifiers);
}
public IRenderable OffsetBy(WVec vec)
@@ -87,17 +95,25 @@ namespace OpenRA.Mods.Common.Graphics
return new ModelRenderable(
models, pos + vec, zOffset, camera, scale,
lightSource, lightAmbientColor, lightDiffuseColor,
palette, normalsPalette, shadowPalette, tint);
palette, normalsPalette, shadowPalette, alpha, tint, tintModifiers);
}
public IRenderable AsDecoration() { return this; }
public IRenderable WithTint(in float3 newTint)
public IModifyableRenderable WithAlpha(float newAlpha)
{
return new ModelRenderable(
models, pos, zOffset, camera, scale,
lightSource, lightAmbientColor, lightDiffuseColor,
palette, normalsPalette, shadowPalette, newTint);
palette, normalsPalette, shadowPalette, newAlpha, tint, tintModifiers);
}
public IModifyableRenderable WithTint(in float3 newTint, TintModifiers newTintModifiers)
{
return new ModelRenderable(
models, pos, zOffset, camera, scale,
lightSource, lightAmbientColor, lightDiffuseColor,
palette, normalsPalette, shadowPalette, alpha, newTint, newTintModifiers);
}
// This will need generalizing once we support TS/RA2 terrain
@@ -145,11 +161,16 @@ namespace OpenRA.Mods.Common.Graphics
var wrsr = Game.Renderer.WorldRgbaSpriteRenderer;
var t = model.tint;
if (wr.TerrainLighting != null)
if (wr.TerrainLighting != null && (model.tintModifiers & TintModifiers.IgnoreWorldTint) == 0)
t *= wr.TerrainLighting.TintAt(model.pos);
wrsr.DrawSprite(renderProxy.ShadowSprite, sa, sb, sc, sd, t, 1f);
wrsr.DrawSprite(renderProxy.Sprite, pxOrigin - 0.5f * renderProxy.Sprite.Size, renderProxy.Sprite.Size, t, 1f);
// Shader interprets negative alpha as a flag to use the tint colour directly instead of multiplying the sprite colour
var a = model.alpha;
if ((model.tintModifiers & TintModifiers.ReplaceColor) != 0)
a *= -1;
wrsr.DrawSprite(renderProxy.ShadowSprite, sa, sb, sc, sd, t, a);
wrsr.DrawSprite(renderProxy.Sprite, pxOrigin - 0.5f * renderProxy.Sprite.Size, renderProxy.Sprite.Size, t, a);
}
public void RenderDebugGeometry(WorldRenderer wr)

View File

@@ -199,7 +199,7 @@ namespace OpenRA.Mods.Common.Traits
return footprint.Select(c => (IRenderable)(new SpriteRenderable(
wr.Theater.TileSprite(new TerrainTile(template, c.Value)),
wr.World.Map.CenterOfCell(c.Key), WVec.Zero, -offset, palette, 1f, true, false))).ToArray();
wr.World.Map.CenterOfCell(c.Key), WVec.Zero, -offset, palette, 1f, true))).ToArray();
}
bool initialized;

View File

@@ -93,7 +93,7 @@ namespace OpenRA.Mods.Common.Traits
var pal = HasFlag(c.Value, PlaceBuildingCellType.LineBuild) ? linePalette : cellPalette;
var pos = wr.World.Map.CenterOfCell(c.Key);
var offset = new WVec(0, 0, topLeftPos.Z - pos.Z);
yield return new SpriteRenderable(tile, pos, offset, -511, pal, 1f, true, true);
yield return new SpriteRenderable(tile, pos, offset, -511, pal, 1f, true, TintModifiers.IgnoreWorldTint);
}
}

View File

@@ -90,7 +90,7 @@ namespace OpenRA.Mods.Common.Traits
if (!a.IsCanceling)
foreach (var n in a.TargetLineNodes(self))
if (n.Tile != null && n.Target.Type != TargetType.Invalid)
yield return new SpriteRenderable(n.Tile, n.Target.CenterPosition, WVec.Zero, -511, pal, 1f, true, true);
yield return new SpriteRenderable(n.Tile, n.Target.CenterPosition, WVec.Zero, -511, pal, 1f, true, TintModifiers.IgnoreWorldTint);
}
bool IRenderAboveShroud.SpatiallyPartitionable { get { return false; } }

View File

@@ -176,7 +176,8 @@ namespace OpenRA.Mods.Common.Traits.Render
var dat = self.World.Map.DistanceAboveTerrain(self.CenterPosition);
var pos = self.CenterPosition - new WVec(0, 0, dat.Length);
var palette = wr.Palette(info.ShadowPalette);
return new IRenderable[] { new SpriteRenderable(shadow.Image, pos, info.ShadowOffset, info.ShadowZOffset, palette, 1, true, shadow.CurrentSequence.IgnoreWorldTint) };
var tintModifiers = shadow.CurrentSequence.IgnoreWorldTint ? TintModifiers.IgnoreWorldTint : TintModifiers.None;
return new IRenderable[] { new SpriteRenderable(shadow.Image, pos, info.ShadowOffset, info.ShadowZOffset, palette, 1, true, tintModifiers) };
}
IEnumerable<Rectangle> IRender.ScreenBounds(Actor self, WorldRenderer wr)

View File

@@ -161,7 +161,7 @@ namespace OpenRA.Mods.Common.Traits
var pal = wr.Palette(TileSet.TerrainPaletteInternalName);
foreach (var t in power.CellsMatching(xy, footprint, dimensions))
yield return new SpriteRenderable(tile, wr.World.Map.CenterOfCell(t), WVec.Zero, -511, pal, 1f, true, true);
yield return new SpriteRenderable(tile, wr.World.Map.CenterOfCell(t), WVec.Zero, -511, pal, 1f, true, TintModifiers.IgnoreWorldTint);
}
protected override string GetCursor(World world, CPos cell, int2 worldPixel, MouseInput mi)

View File

@@ -85,7 +85,7 @@ namespace OpenRA.Mods.Common.Traits
var offset = world.Map.Offset(new CVec(x, y), tileInfo.Height);
var palette = wr.Palette(TerrainTemplate.Palette ?? TileSet.TerrainPaletteInternalName);
terrainOrResourcePreview.Add(new SpriteRenderable(sprite, pos, offset, 0, palette, 1, false, false));
terrainOrResourcePreview.Add(new SpriteRenderable(sprite, pos, offset, 0, palette, 1, false));
}
}
}
@@ -96,7 +96,8 @@ namespace OpenRA.Mods.Common.Traits
var sprite = sequence.GetSprite(Resource.MaxDensity - 1);
var palette = wr.Palette(Resource.Palette);
terrainOrResourcePreview.Add(new SpriteRenderable(sprite, pos, WVec.Zero, 0, palette, 1, false, sequence.IgnoreWorldTint));
var tintModifiers = sequence.IgnoreWorldTint ? TintModifiers.IgnoreWorldTint : TintModifiers.None;
terrainOrResourcePreview.Add(new SpriteRenderable(sprite, pos, WVec.Zero, 0, palette, 1, false, tintModifiers));
}
}
}

View File

@@ -89,12 +89,12 @@ namespace OpenRA.Mods.Common.Traits
if (CopyRegion != null)
foreach (var c in CopyRegion)
yield return new SpriteRenderable(copySprite, wr.World.Map.CenterOfCell(c),
WVec.Zero, -511, palette, 1f, true, true);
WVec.Zero, -511, palette, 1f, true, TintModifiers.IgnoreWorldTint);
if (PasteRegion != null)
foreach (var c in PasteRegion)
yield return new SpriteRenderable(pasteSprite, wr.World.Map.CenterOfCell(c),
WVec.Zero, -511, palette, 1f, true, true);
WVec.Zero, -511, palette, 1f, true, TintModifiers.IgnoreWorldTint);
}
bool IRenderAboveShroud.SpatiallyPartitionable { get { return false; } }

View File

@@ -89,7 +89,7 @@ namespace OpenRA.Mods.D2k.Traits
var pal = HasFlag(c.Value, PlaceBuildingCellType.LineBuild) ? linePalette : cellPalette;
var pos = wr.World.Map.CenterOfCell(c.Key);
var offset = new WVec(0, 0, topLeftPos.Z - pos.Z);
yield return new SpriteRenderable(tile, pos, offset, -511, pal, 1f, true, true);
yield return new SpriteRenderable(tile, pos, offset, -511, pal, 1f, true, TintModifiers.IgnoreWorldTint);
}
}
}

View File

@@ -228,9 +228,17 @@ void main()
#endif
}
else
#if __VERSION__ == 120
gl_FragColor = c * vTint;
{
// A negative tint alpha indicates that the tint should replace the colour instead of multiplying it
if (vTint.a < 0.0)
c = vec4(vTint.rgb, -vTint.a);
else
c *= vTint;
#if __VERSION__ == 120
gl_FragColor = c;
#else
fragColor = c * vTint;
fragColor = c;
#endif
}
}