diff --git a/OpenRA.Game/Graphics/Minimap.cs b/OpenRA.Game/Graphics/Minimap.cs
index c7aba5fa3b..3db0bd3117 100644
--- a/OpenRA.Game/Graphics/Minimap.cs
+++ b/OpenRA.Game/Graphics/Minimap.cs
@@ -180,12 +180,14 @@ namespace OpenRA.Graphics
{
var colors = (int*)bitmapData.Scan0;
var stride = bitmapData.Stride / 4;
+ var shroudObscured = world.ShroudObscuresTest(map.Cells);
+ var fogObscured = world.FogObscuresTest(map.Cells);
foreach (var cell in map.Cells)
{
var uv = Map.CellToMap(map.TileShape, cell) - offset;
- if (world.ShroudObscures(cell))
+ if (shroudObscured(cell))
colors[uv.Y * stride + uv.X] = shroud;
- else if (world.FogObscures(cell))
+ else if (fogObscured(cell))
colors[uv.Y * stride + uv.X] = fog;
}
}
diff --git a/OpenRA.Game/Map/CellRegion.cs b/OpenRA.Game/Map/CellRegion.cs
index 66501c4fc1..ef7fc6debd 100644
--- a/OpenRA.Game/Map/CellRegion.cs
+++ b/OpenRA.Game/Map/CellRegion.cs
@@ -8,8 +8,10 @@
*/
#endregion
+using System;
using System.Collections;
using System.Collections.Generic;
+using System.Linq;
namespace OpenRA
{
@@ -47,29 +49,69 @@ namespace OpenRA
return new CellRegion(region.shape, tl, br);
}
+ /// Returns the minimal region that covers at least the specified cells.
+ public static CellRegion BoundingRegion(TileShape shape, IEnumerable cells)
+ {
+ if (cells == null || !cells.Any())
+ throw new ArgumentException("cells must not be null or empty.", "cells");
+
+ var minX = int.MaxValue;
+ var minY = int.MaxValue;
+ var maxX = int.MinValue;
+ var maxY = int.MinValue;
+ foreach (var cell in cells)
+ {
+ if (minX > cell.X)
+ minX = cell.X;
+ if (maxX < cell.X)
+ maxX = cell.X;
+ if (minY > cell.Y)
+ minY = cell.Y;
+ if (maxY < cell.Y)
+ maxY = cell.Y;
+ }
+
+ return new CellRegion(shape, new CPos(minX, minY), new CPos(maxX, maxY));
+ }
+
+ public bool Contains(CellRegion region)
+ {
+ return
+ TopLeft.X <= region.TopLeft.X && TopLeft.Y <= region.TopLeft.Y &&
+ BottomRight.X >= region.BottomRight.X && BottomRight.Y >= region.BottomRight.Y;
+ }
+
public bool Contains(CPos cell)
{
var uv = Map.CellToMap(shape, cell);
return uv.X >= mapTopLeft.X && uv.X <= mapBottomRight.X && uv.Y >= mapTopLeft.Y && uv.Y <= mapBottomRight.Y;
}
- public IEnumerator GetEnumerator()
+ public CellRegionEnumerator GetEnumerator()
{
return new CellRegionEnumerator(this);
}
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
- class CellRegionEnumerator : IEnumerator
+ public class CellRegionEnumerator : IEnumerator
{
readonly CellRegion r;
// Current position, in map coordinates
int u, v;
+ // Current position, in cell coordinates
+ CPos current;
+
public CellRegionEnumerator(CellRegion region)
{
r = region;
@@ -91,6 +133,7 @@ namespace OpenRA
return false;
}
+ current = Map.MapToCell(r.shape, new CPos(u, v));
return true;
}
@@ -101,7 +144,7 @@ namespace OpenRA
v = r.mapTopLeft.Y;
}
- public CPos Current { get { return Map.MapToCell(r.shape, new CPos(u, v)); } }
+ public CPos Current { get { return current; } }
object IEnumerator.Current { get { return Current; } }
public void Dispose() { }
}
diff --git a/OpenRA.Game/Traits/Player/FrozenActorLayer.cs b/OpenRA.Game/Traits/Player/FrozenActorLayer.cs
index d59558eaf5..05d299e0f7 100755
--- a/OpenRA.Game/Traits/Player/FrozenActorLayer.cs
+++ b/OpenRA.Game/Traits/Player/FrozenActorLayer.cs
@@ -23,6 +23,7 @@ namespace OpenRA.Traits
public class FrozenActor
{
public readonly CPos[] Footprint;
+ public readonly CellRegion FootprintRegion;
public readonly WPos CenterPosition;
public readonly Rectangle Bounds;
readonly Actor actor;
@@ -38,10 +39,12 @@ namespace OpenRA.Traits
public bool Visible;
- public FrozenActor(Actor self, IEnumerable footprint)
+ public FrozenActor(Actor self, CPos[] footprint, CellRegion footprintRegion)
{
actor = self;
- Footprint = footprint.ToArray();
+ Footprint = footprint;
+ FootprintRegion = footprintRegion;
+
CenterPosition = self.CenterPosition;
Bounds = self.Bounds.Value;
}
@@ -54,16 +57,7 @@ namespace OpenRA.Traits
int flashTicks;
public void Tick(World world, Shroud shroud)
{
- Visible = true;
- foreach (var pos in Footprint)
- {
- if (shroud.IsVisible(pos))
- {
- Visible = false;
- break;
- }
- }
-
+ Visible = !Footprint.Any(shroud.IsVisibleTest(FootprintRegion));
if (flashTicks > 0)
flashTicks--;
}
diff --git a/OpenRA.Game/Traits/World/Shroud.cs b/OpenRA.Game/Traits/World/Shroud.cs
index c273db386b..ccff0506c8 100644
--- a/OpenRA.Game/Traits/World/Shroud.cs
+++ b/OpenRA.Game/Traits/World/Shroud.cs
@@ -26,8 +26,8 @@ namespace OpenRA.Traits
readonly Actor self;
readonly Map map;
- readonly CellLayer visibleCount;
- readonly CellLayer generatedShroudCount;
+ readonly CellLayer visibleCount;
+ readonly CellLayer generatedShroudCount;
readonly CellLayer explored;
readonly Lazy fogVisibilities;
@@ -39,13 +39,19 @@ namespace OpenRA.Traits
public int Hash { get; private set; }
+ static readonly Func TruthPredicate = cell => true;
+ readonly Func fastExploredTest;
+ readonly Func slowExploredTest;
+ readonly Func fastVisibleTest;
+ readonly Func slowVisibleTest;
+
public Shroud(Actor self)
{
this.self = self;
map = self.World.Map;
- visibleCount = new CellLayer(map);
- generatedShroudCount = new CellLayer(map);
+ visibleCount = new CellLayer(map);
+ generatedShroudCount = new CellLayer(map);
explored = new CellLayer(map);
self.World.ActorAdded += AddVisibility;
@@ -55,6 +61,11 @@ namespace OpenRA.Traits
self.World.ActorRemoved += RemoveShroudGeneration;
fogVisibilities = Exts.Lazy(() => self.TraitsImplementing().ToArray());
+
+ fastExploredTest = IsExploredCore;
+ slowExploredTest = IsExplored;
+ fastVisibleTest = IsVisibleCore;
+ slowVisibleTest = IsVisible;
}
void Invalidate()
@@ -223,10 +234,32 @@ namespace OpenRA.Traits
if (!map.Contains(cell))
return false;
- if (Disabled || !self.World.LobbyInfo.GlobalSettings.Shroud)
+ if (!ShroudEnabled)
return true;
- return explored[cell] && (generatedShroudCount[cell] == 0 || visibleCount[cell] > 0);
+ return IsExploredCore(cell);
+ }
+
+ bool ShroudEnabled { get { return !Disabled && self.World.LobbyInfo.GlobalSettings.Shroud; } }
+
+ bool IsExploredCore(CPos cell)
+ {
+ var uv = Map.CellToMap(map.TileShape, cell);
+ return explored[uv.X, uv.Y] && (generatedShroudCount[uv.X, uv.Y] == 0 || visibleCount[uv.X, uv.Y] > 0);
+ }
+
+ public Func IsExploredTest(CellRegion region)
+ {
+ // If the region to test extends outside the map we must use the slow test that checks the map boundary every time.
+ if (!map.Cells.Contains(region))
+ return slowExploredTest;
+
+ // If shroud isn't enabled, then we can see everything.
+ if (!ShroudEnabled)
+ return TruthPredicate;
+
+ // If shroud is enabled, we can use the fast test that just does the core check.
+ return fastExploredTest;
}
public bool IsExplored(Actor a)
@@ -239,12 +272,33 @@ namespace OpenRA.Traits
if (!map.Contains(cell))
return false;
- if (Disabled || !self.World.LobbyInfo.GlobalSettings.Fog)
+ if (!FogEnabled)
return true;
+ return IsVisibleCore(cell);
+ }
+
+ bool FogEnabled { get { return !Disabled && self.World.LobbyInfo.GlobalSettings.Fog; } }
+
+ bool IsVisibleCore(CPos cell)
+ {
return visibleCount[cell] > 0;
}
+ public Func IsVisibleTest(CellRegion region)
+ {
+ // If the region to test extends outside the map we must use the slow test that checks the map boundary every time.
+ if (!map.Cells.Contains(region))
+ return slowVisibleTest;
+
+ // If fog isn't enabled, then we can see everything.
+ if (!FogEnabled)
+ return TruthPredicate;
+
+ // If fog is enabled, we can use the fast test that just does the core check.
+ return fastVisibleTest;
+ }
+
// Actors are hidden under shroud, but not under fog by default
public bool IsVisible(Actor a)
{
diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs
index 3661df521f..1bf06a9fd4 100644
--- a/OpenRA.Game/World.cs
+++ b/OpenRA.Game/World.cs
@@ -24,6 +24,7 @@ namespace OpenRA
{
public class World
{
+ static readonly Func FalsePredicate = cell => false;
internal readonly TraitDictionary traitDict = new TraitDictionary();
readonly HashSet actors = new HashSet();
readonly List effects = new List();
@@ -53,6 +54,24 @@ namespace OpenRA
public bool FogObscures(CPos p) { return RenderPlayer != null && !RenderPlayer.Shroud.IsVisible(p); }
public bool ShroudObscures(Actor a) { return RenderPlayer != null && !RenderPlayer.Shroud.IsExplored(a); }
public bool ShroudObscures(CPos p) { return RenderPlayer != null && !RenderPlayer.Shroud.IsExplored(p); }
+
+ public Func FogObscuresTest(CellRegion region)
+ {
+ var rp = RenderPlayer;
+ if (rp == null)
+ return FalsePredicate;
+ var predicate = rp.Shroud.IsVisibleTest(region);
+ return cell => !predicate(cell);
+ }
+
+ public Func ShroudObscuresTest(CellRegion region)
+ {
+ var rp = RenderPlayer;
+ if (rp == null)
+ return FalsePredicate;
+ var predicate = rp.Shroud.IsExploredTest(region);
+ return cell => !predicate(cell);
+ }
public bool IsReplay
{
diff --git a/OpenRA.Mods.RA/Modifiers/FrozenUnderFog.cs b/OpenRA.Mods.RA/Modifiers/FrozenUnderFog.cs
index dfb85070e3..3687ae6976 100644
--- a/OpenRA.Mods.RA/Modifiers/FrozenUnderFog.cs
+++ b/OpenRA.Mods.RA/Modifiers/FrozenUnderFog.cs
@@ -30,6 +30,7 @@ namespace OpenRA.Mods.RA
readonly bool startsRevealed;
readonly CPos[] footprint;
+ readonly CellRegion footprintRegion;
readonly Lazy tooltip;
readonly Lazy health;
@@ -44,6 +45,7 @@ namespace OpenRA.Mods.RA
// Spawned actors (e.g. building husks) shouldn't be revealed
startsRevealed = info.StartsRevealed && !init.Contains();
footprint = FootprintUtils.Tiles(init.self).ToArray();
+ footprintRegion = CellRegion.BoundingRegion(init.world.Map.TileShape, footprint);
tooltip = Exts.Lazy(() => init.self.TraitsImplementing().FirstOrDefault());
tooltip = Exts.Lazy(() => init.self.TraitsImplementing().FirstOrDefault());
health = Exts.Lazy(() => init.self.TraitOrDefault());
@@ -65,15 +67,7 @@ namespace OpenRA.Mods.RA
VisibilityHash = 0;
foreach (var p in self.World.Players)
{
- var isVisible = false;
- foreach (var pos in footprint)
- {
- if (p.Shroud.IsVisible(pos))
- {
- isVisible = true;
- break;
- }
- }
+ var isVisible = footprint.Any(p.Shroud.IsVisibleTest(footprintRegion));
visible[p] = isVisible;
if (isVisible)
VisibilityHash += p.ClientIndex;
@@ -84,7 +78,7 @@ namespace OpenRA.Mods.RA
foreach (var p in self.World.Players)
{
visible[p] |= startsRevealed;
- p.PlayerActor.Trait().Add(frozen[p] = new FrozenActor(self, footprint));
+ p.PlayerActor.Trait().Add(frozen[p] = new FrozenActor(self, footprint, footprintRegion));
}
initialized = true;
diff --git a/OpenRA.Mods.RA/ShroudRenderer.cs b/OpenRA.Mods.RA/ShroudRenderer.cs
index 51ac394387..3a726b1c1b 100644
--- a/OpenRA.Mods.RA/ShroudRenderer.cs
+++ b/OpenRA.Mods.RA/ShroudRenderer.cs
@@ -65,33 +65,37 @@ namespace OpenRA.Mods.RA
All = Top | Right | Bottom | Left
}
- class ShroudTile
+ struct ShroudTile
{
- public readonly CPos Position;
public readonly float2 ScreenPosition;
- public readonly int Variant;
+ public readonly byte Variant;
public Sprite Fog;
public Sprite Shroud;
- public ShroudTile(CPos position, float2 screenPosition, int variant)
+ public ShroudTile(float2 screenPosition, byte variant)
{
- Position = position;
ScreenPosition = screenPosition;
Variant = variant;
+
+ Fog = null;
+ Shroud = null;
}
}
readonly ShroudRendererInfo info;
readonly Sprite[] shroudSprites, fogSprites;
- readonly int[] spriteMap;
+ readonly byte[] spriteMap;
readonly CellLayer tiles;
- readonly int variantStride;
+ readonly byte variantStride;
readonly Map map;
readonly Edges notVisibleEdges;
+ bool clearedForNullShroud;
+ int lastShroudHash;
+ CellRegion updatedRegion;
+
PaletteReference fogPalette, shroudPalette;
- int shroudHash;
public ShroudRenderer(World world, ShroudRendererInfo info)
{
@@ -101,17 +105,20 @@ namespace OpenRA.Mods.RA
if ((info.OverrideFullFog == null) ^ (info.OverrideFullShroud == null))
throw new ArgumentException("ShroudRenderer cannot define overrides for only one of shroud or fog!", "info");
+ if (info.ShroudVariants.Length > byte.MaxValue)
+ throw new ArgumentException("ShroudRenderer cannot define this many shroud and fog variants.", "info");
+
+ if (info.Index.Length >= byte.MaxValue)
+ throw new ArgumentException("ShroudRenderer cannot define this many indexes for shroud directions.", "info");
+
this.info = info;
map = world.Map;
tiles = new CellLayer(map);
- // Force update on first render
- shroudHash = -1;
-
// Load sprite variants
var variantCount = info.ShroudVariants.Length;
- variantStride = info.Index.Length + (info.OverrideFullShroud != null ? 1 : 0);
+ variantStride = (byte)(info.Index.Length + (info.OverrideFullShroud != null ? 1 : 0));
shroudSprites = new Sprite[variantCount * variantStride];
fogSprites = new Sprite[variantCount * variantStride];
@@ -134,33 +141,33 @@ namespace OpenRA.Mods.RA
}
// Mapping of shrouded directions -> sprite index
- spriteMap = new int[info.UseExtendedIndex ? 256 : 16];
+ spriteMap = new byte[(byte)(info.UseExtendedIndex ? Edges.All : Edges.AllCorners) + 1];
for (var i = 0; i < info.Index.Length; i++)
- spriteMap[info.Index[i]] = i;
+ spriteMap[info.Index[i]] = (byte)i;
if (info.OverrideFullShroud != null)
- spriteMap[info.OverrideShroudIndex] = variantStride - 1;
+ spriteMap[info.OverrideShroudIndex] = (byte)(variantStride - 1);
notVisibleEdges = info.UseExtendedIndex ? Edges.AllSides : Edges.AllCorners;
}
- Edges GetEdges(int x, int y, Func isVisible)
+ Edges GetEdges(CPos p, Func isVisible)
{
- if (!isVisible(x, y))
+ if (!isVisible(p))
return notVisibleEdges;
// If a side is shrouded then we also count the corners
var u = Edges.None;
- if (!isVisible(x, y - 1)) u |= Edges.Top;
- if (!isVisible(x + 1, y)) u |= Edges.Right;
- if (!isVisible(x, y + 1)) u |= Edges.Bottom;
- if (!isVisible(x - 1, y)) u |= Edges.Left;
+ if (!isVisible(p + new CVec(0, -1))) u |= Edges.Top;
+ if (!isVisible(p + new CVec(1, 0))) u |= Edges.Right;
+ if (!isVisible(p + new CVec(0, 1))) u |= Edges.Bottom;
+ if (!isVisible(p + new CVec(-1, 0))) u |= Edges.Left;
var ucorner = u & Edges.AllCorners;
- if (!isVisible(x - 1, y - 1)) u |= Edges.TopLeft;
- if (!isVisible(x + 1, y - 1)) u |= Edges.TopRight;
- if (!isVisible(x + 1, y + 1)) u |= Edges.BottomRight;
- if (!isVisible(x - 1, y + 1)) u |= Edges.BottomLeft;
+ if (!isVisible(p + new CVec(-1, -1))) u |= Edges.TopLeft;
+ if (!isVisible(p + new CVec(1, -1))) u |= Edges.TopRight;
+ if (!isVisible(p + new CVec(1, 1))) u |= Edges.BottomRight;
+ if (!isVisible(p + new CVec(-1, 1))) u |= Edges.BottomLeft;
// RA provides a set of frames for tiles with shrouded
// corners but unshrouded edges. We want to detect this
@@ -171,19 +178,19 @@ namespace OpenRA.Mods.RA
return info.UseExtendedIndex ? u ^ ucorner : u & Edges.AllCorners;
}
- Edges GetObserverEdges(int x, int y)
+ Edges GetObserverEdges(CPos p)
{
var u = Edges.None;
- if (!map.Contains(new CPos(x, y - 1))) u |= Edges.Top;
- if (!map.Contains(new CPos(x + 1, y))) u |= Edges.Right;
- if (!map.Contains(new CPos(x, y + 1))) u |= Edges.Bottom;
- if (!map.Contains(new CPos(x - 1, y))) u |= Edges.Left;
+ if (!map.Contains(p + new CVec(0, -1))) u |= Edges.Top;
+ if (!map.Contains(p + new CVec(1, 0))) u |= Edges.Right;
+ if (!map.Contains(p + new CVec(0, 1))) u |= Edges.Bottom;
+ if (!map.Contains(p + new CVec(-1, 0))) u |= Edges.Left;
var ucorner = u & Edges.AllCorners;
- if (!map.Contains(new CPos(x - 1, y - 1))) u |= Edges.TopLeft;
- if (!map.Contains(new CPos(x + 1, y - 1))) u |= Edges.TopRight;
- if (!map.Contains(new CPos(x + 1, y + 1))) u |= Edges.BottomRight;
- if (!map.Contains(new CPos(x - 1, y + 1))) u |= Edges.BottomLeft;
+ if (!map.Contains(p + new CVec(-1, -1))) u |= Edges.TopLeft;
+ if (!map.Contains(p + new CVec(1, -1))) u |= Edges.TopRight;
+ if (!map.Contains(p + new CVec(1, 1))) u |= Edges.BottomRight;
+ if (!map.Contains(p + new CVec(-1, 1))) u |= Edges.BottomLeft;
return info.UseExtendedIndex ? u ^ ucorner : u & Edges.AllCorners;
}
@@ -195,64 +202,84 @@ namespace OpenRA.Mods.RA
foreach (var cell in CellRegion.Expand(w.Map.Cells, 1))
{
var screen = wr.ScreenPosition(w.Map.CenterOfCell(cell));
- var variant = Game.CosmeticRandom.Next(info.ShroudVariants.Length);
- tiles[cell] = new ShroudTile(cell, screen, variant);
+ var variant = (byte)Game.CosmeticRandom.Next(info.ShroudVariants.Length);
+ tiles[cell] = new ShroudTile(screen, variant);
// Set the cells outside the border so they don't need to be touched again
if (!map.Contains(cell))
- tiles[cell].Shroud = GetTile(notVisibleEdges, variant);
+ {
+ var shroudTile = tiles[cell];
+ shroudTile.Shroud = GetTile(shroudSprites, notVisibleEdges, variant);
+ tiles[cell] = shroudTile;
+ }
}
fogPalette = wr.Palette(info.FogPalette);
shroudPalette = wr.Palette(info.ShroudPalette);
}
- Sprite GetTile(Edges edges, int variant)
+ Sprite GetTile(Sprite[] sprites, Edges edges, int variant)
{
if (edges == Edges.None)
return null;
- return shroudSprites[variant * variantStride + spriteMap[(byte)edges]];
+ return sprites[variant * variantStride + spriteMap[(byte)edges]];
}
- void Update(Shroud shroud)
+ void Update(Shroud shroud, CellRegion region)
{
- var hash = shroud != null ? shroud.Hash : 0;
- if (shroudHash == hash)
- return;
-
- shroudHash = hash;
- if (shroud == null)
+ if (shroud != null)
{
- // Players with no shroud see the whole map so we only need to set the edges
- foreach (var cell in map.Cells)
- {
- var t = tiles[cell];
- var shrouded = GetObserverEdges(cell.X, cell.Y);
+ // If the current shroud hasn't changed and we have already updated the specified area, we don't need to do anything.
+ if (lastShroudHash == shroud.Hash && !clearedForNullShroud && updatedRegion.Contains(region))
+ return;
- t.Shroud = shrouded != 0 ? shroudSprites[t.Variant * variantStride + spriteMap[(byte)shrouded]] : null;
- t.Fog = shrouded != 0 ? fogSprites[t.Variant * variantStride + spriteMap[(byte)shrouded]] : null;
- }
+ lastShroudHash = shroud.Hash;
+ clearedForNullShroud = false;
+ updatedRegion = region;
+ UpdateShroud(shroud);
}
- else
+ else if (!clearedForNullShroud)
{
- foreach (var cell in map.Cells)
- {
- Func visibleUnderShroud = (x, y) => shroud.IsExplored(new CPos(x, y));
- Func visibleUnderFog = (x, y) => shroud.IsVisible(new CPos(x, y));
- var t = tiles[cell];
- var shrouded = GetEdges(cell.X, cell.Y, visibleUnderShroud);
- var fogged = GetEdges(cell.X, cell.Y, visibleUnderFog);
+ // We need to clear any applied shroud.
+ clearedForNullShroud = true;
+ updatedRegion = new CellRegion(map.TileShape, new CPos(0, 0), new CPos(-1, -1));
+ UpdateNullShroud();
+ }
+ }
- t.Shroud = shrouded != 0 ? shroudSprites[t.Variant * variantStride + spriteMap[(byte)shrouded]] : null;
- t.Fog = fogged != 0 ? fogSprites[t.Variant * variantStride + spriteMap[(byte)fogged]] : null;
- }
+ void UpdateShroud(Shroud shroud)
+ {
+ var visibleUnderShroud = shroud.IsExploredTest(updatedRegion);
+ var visibleUnderFog = shroud.IsVisibleTest(updatedRegion);
+ foreach (var cell in updatedRegion)
+ {
+ var shrouded = GetEdges(cell, visibleUnderShroud);
+ var fogged = GetEdges(cell, visibleUnderFog);
+ var shroudTile = tiles[cell];
+ var variant = shroudTile.Variant;
+ shroudTile.Shroud = GetTile(shroudSprites, shrouded, variant);
+ shroudTile.Fog = GetTile(fogSprites, fogged, variant);
+ tiles[cell] = shroudTile;
+ }
+ }
+
+ void UpdateNullShroud()
+ {
+ foreach (var cell in map.Cells)
+ {
+ var edges = GetObserverEdges(cell);
+ var shroudTile = tiles[cell];
+ var variant = shroudTile.Variant;
+ shroudTile.Shroud = GetTile(shroudSprites, edges, variant);
+ shroudTile.Fog = GetTile(fogSprites, edges, variant);
+ tiles[cell] = shroudTile;
}
}
public void RenderShroud(WorldRenderer wr, Shroud shroud)
{
- Update(shroud);
+ Update(shroud, wr.Viewport.VisibleCells);
foreach (var cell in CellRegion.Expand(wr.Viewport.VisibleCells, 1))
{
diff --git a/OpenRA.Mods.RA/World/ResourceLayer.cs b/OpenRA.Mods.RA/World/ResourceLayer.cs
index 02eac34b10..b7bf86fbe5 100644
--- a/OpenRA.Mods.RA/World/ResourceLayer.cs
+++ b/OpenRA.Mods.RA/World/ResourceLayer.cs
@@ -34,9 +34,10 @@ namespace OpenRA.Mods.RA
public void Render(WorldRenderer wr)
{
+ var shroudObscured = world.ShroudObscuresTest(wr.Viewport.VisibleCells);
foreach (var cell in wr.Viewport.VisibleCells)
{
- if (world.ShroudObscures(cell))
+ if (shroudObscured(cell))
continue;
var c = render[cell];