Skip to content

Commit

Permalink
Implement batched rendering for objects
Browse files Browse the repository at this point in the history
  • Loading branch information
Rampastring committed Sep 25, 2024
1 parent 587a118 commit 9f9d506
Show file tree
Hide file tree
Showing 27 changed files with 836 additions and 385 deletions.
3 changes: 2 additions & 1 deletion src/TSMapEditor/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ public static class Constants
public const string NoneValue2 = "None";

public const float RemapBrightenFactor = 1.25f;
public const float DepthRenderStep = 1 / 32f;
public const float DownwardsDepthRenderSpace = 0.3f;
public static readonly float DepthRenderStep = 0.5f / MaxMapHeightLevel;

public const bool DrawShadows = true;

Expand Down
6 changes: 6 additions & 0 deletions src/TSMapEditor/Content/Content.mgcb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@
/processorParam:DebugMode=Debug
/build:Shaders/ColorDraw.fx

#begin Shaders/CombineWithDepth.fx
/importer:EffectImporter
/processor:EffectProcessor
/processorParam:DebugMode=Debug
/build:Shaders/CombineWithDepth.fx

#begin Shaders/DepthApply.fx
/importer:EffectImporter
/processor:EffectProcessor
Expand Down
92 changes: 92 additions & 0 deletions src/TSMapEditor/Content/Shaders/CombineWithDepth.fx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#pragma enable_d3d11_debug_symbols

#if OPENGL
#define SV_POSITION POSITION
#define VS_SHADERMODEL vs_3_0
#define PS_SHADERMODEL ps_3_0
#else
#define VS_SHADERMODEL vs_4_0
#define PS_SHADERMODEL ps_4_0
#endif

// Shader for combining the terrain and object render layers,
// taking depth of each into account in separate textures.

sampler2D SpriteTextureSampler : register(s0)
{
Texture = (SpriteTexture); // this is set by spritebatch
MipFilter = Point;
MinFilter = Point;
MagFilter = Point;
};

Texture2D TerrainDepthTexture;
sampler2D TerrainDepthTextureSampler
{
Texture = <TerrainDepthTexture>;
AddressU = clamp;
AddressV = clamp;
MipFilter = Point;
MinFilter = Point;
MagFilter = Point;
};

// We use SpriteTextureSampler in place of this, because it has to be supplied anyway
// Texture2D ObjectsTexture;
// sampler2D ObjectsTextureSampler
// {
// Texture = <ObjectsTexture>;
// AddressU = clamp;
// AddressV = clamp;
// MipFilter = Point;
// MinFilter = Point;
// MagFilter = Point;
// };

Texture2D ObjectsDepthTexture;
sampler2D ObjectsDepthTextureSampler
{
Texture = <ObjectsDepthTexture>;
AddressU = clamp;
AddressV = clamp;
MipFilter = Point;
MinFilter = Point;
MagFilter = Point;
};

struct VertexShaderOutput
{
float4 Position : SV_POSITION;
float4 Color : COLOR0;
float2 TextureCoordinates : TEXCOORD0;
};

float4 MainPS(VertexShaderOutput input) : COLOR
{
// We need to read from the main texture first,
// otherwise the output will be black!
float4 objectsTex = tex2D(SpriteTextureSampler, input.TextureCoordinates);
float terrainDepth = tex2D(TerrainDepthTextureSampler, input.TextureCoordinates).x;
float objectsDepth = tex2D(ObjectsDepthTextureSampler, input.TextureCoordinates).x;

if (objectsTex.a == 0)
{
discard;
}

if (objectsDepth < terrainDepth)
{
discard;
}

return objectsTex;
}

technique SpriteDrawing
{
pass P0
{
AlphaBlendEnable = TRUE;
PixelShader = compile PS_SHADERMODEL MainPS();
}
};
9 changes: 5 additions & 4 deletions src/TSMapEditor/Content/Shaders/PalettedColorDraw.fx
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ struct VertexShaderOutput

struct PixelShaderOutput
{
float4 color : SV_Target;
float depth : SV_Depth;
float4 color : SV_Target0;
float depthTarget : SV_Target1;
float depthEmbedded : SV_Depth;
};

PixelShaderOutput MainPS(VertexShaderOutput input)
Expand All @@ -65,7 +66,8 @@ PixelShaderOutput MainPS(VertexShaderOutput input)
// This is because when doing batched rendering, shader parameters cannot be changed
// within one batch, meaning we cannot introduce a shader parameter for depth
// without sacrificing performance. And we need a unique depth value for each sprite.
output.depth = input.Color.a;
output.depthTarget = input.Color.a;
output.depthEmbedded = input.Color.a;

if (IsShadow)
{
Expand Down Expand Up @@ -115,7 +117,6 @@ technique SpriteDrawing
{
pass P0
{
AlphaBlendEnable = TRUE;
PixelShader = compile PS_SHADERMODEL MainPS();
}
};
2 changes: 1 addition & 1 deletion src/TSMapEditor/Initialization/MapLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1149,7 +1149,7 @@ public static void ReadHouses(IMap map, IniFile mapIni)

if (houseType == null)
{
houseType = map.StandardHouseTypes[0];
houseType = map.GetHouseTypes()[0];
AddMapLoadError($"Nonexistent Country= or no Country= specified for House {houseName}. This makes it default to the first standard Country ({houseType.ININame}).");
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/TSMapEditor/Models/Animation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public Animation(AnimType animType, Point2D position) : this(animType)

public override RTTIType WhatAmI() => RTTIType.Anim;

public override GameObjectType GetObjectType() => AnimType;

public AnimType AnimType { get; private set; }
public House Owner { get; set; }
public byte Facing { get; set; }
Expand Down
16 changes: 9 additions & 7 deletions src/TSMapEditor/Models/BridgeType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public enum BridgeKind

public enum BridgeDirection
{
None,
EastWest,
NorthSouth
}
Expand All @@ -35,17 +36,17 @@ public BridgeConfig(IniSection iniSection, BridgeDirection direction, BridgeType
if (bridgeStart == null)
throw new BridgeLoadException($"Low bridge {bridgeType.Name} has no start overlay!");

Start = rules.FindOverlayType(bridgeStart)?.Index ??
Start = rules.FindOverlayType(bridgeStart) ??
throw new BridgeLoadException($"Low bridge {bridgeType.Name} has an invalid start overlay {bridgeStart}!");

string bridgeEnd = iniSection.GetStringValue($"BridgeEnd.{suffix}", null);
if (bridgeEnd == null)
throw new BridgeLoadException($"Low bridge {bridgeType.Name} has no end overlay!");

End = rules.FindOverlayType(bridgeEnd)?.Index ??
End = rules.FindOverlayType(bridgeEnd) ??
throw new BridgeLoadException($"Low bridge {bridgeType.Name} has an invalid end overlay {bridgeEnd}!");

Pieces = iniSection.GetListValue($"BridgePieces.{suffix}", ',', (overlayName) => rules.FindOverlayType(overlayName)?.Index ??
Pieces = iniSection.GetListValue($"BridgePieces.{suffix}", ',', (overlayName) => rules.FindOverlayType(overlayName) ??
throw new BridgeLoadException($"Low bridge {bridgeType.Name} has an invalid bridge piece {overlayName}!"));

if (Pieces.Count == 0)
Expand All @@ -57,16 +58,17 @@ public BridgeConfig(IniSection iniSection, BridgeDirection direction, BridgeType
if (piece == null)
throw new BridgeLoadException($"High bridge {bridgeType.Name} has no bridge piece!");

int bridgePiece = rules.FindOverlayType(piece)?.Index ??
OverlayType bridgePiece = rules.FindOverlayType(piece) ??
throw new BridgeLoadException($"High bridge {bridgeType.Name} has an invalid bridge piece {piece}!");

Pieces.Add(bridgePiece);
Pieces.ForEach(p => p.HighBridgeDirection = direction);
}
}

public int Start;
public int End;
public List<int> Pieces = new List<int>();
public OverlayType Start;
public OverlayType End;
public List<OverlayType> Pieces = new List<OverlayType>();
}

public class BridgeType
Expand Down
2 changes: 2 additions & 0 deletions src/TSMapEditor/Models/GameObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public abstract class GameObject : AbstractObject, IMovable

public ulong LastRefreshIndex;

public abstract GameObjectType GetObjectType();

public virtual int GetYDrawOffset()
{
return 0;
Expand Down
2 changes: 2 additions & 0 deletions src/TSMapEditor/Models/Overlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
{
public class Overlay : GameObject
{
public override GameObjectType GetObjectType() => OverlayType;

public override RTTIType WhatAmI() => RTTIType.Overlay;

public OverlayType OverlayType { get; set; }
Expand Down
3 changes: 3 additions & 0 deletions src/TSMapEditor/Models/OverlayType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,8 @@ public OverlayType(string iniName) : base(iniName)
public bool IsVeins { get; set; }
public bool IsVeinholeMonster { get; set; }
public TiberiumType TiberiumType { get; set; }

[INI(false)]
public BridgeDirection HighBridgeDirection { get; set; }
}
}
2 changes: 2 additions & 0 deletions src/TSMapEditor/Models/Smudge.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ public class Smudge : GameObject
{
public override RTTIType WhatAmI() => RTTIType.Smudge;

public override GameObjectType GetObjectType() => SmudgeType;

public SmudgeType SmudgeType { get; set; }

public override int GetYDrawOffset()
Expand Down
2 changes: 2 additions & 0 deletions src/TSMapEditor/Models/Techno.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ public Techno(T objectType)
ObjectType = objectType;
}

public override GameObjectType GetObjectType() => ObjectType;

public override double GetWeaponRange() => ObjectType.GetWeaponRange();

public override double GetGuardRange()
Expand Down
2 changes: 2 additions & 0 deletions src/TSMapEditor/Models/TerrainObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public TerrainObject(TerrainType terrainType, Point2D position) : this(terrainTy
Position = position;
}

public override GameObjectType GetObjectType() => TerrainType;

public override RTTIType WhatAmI() => RTTIType.Terrain;

public TerrainType TerrainType { get; private set; }
Expand Down
36 changes: 18 additions & 18 deletions src/TSMapEditor/Mutations/Classes/PlaceBridgeMutation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,32 +95,32 @@ public override void Perform()
MutationTarget.InvalidateMap();
}

private void PlaceLowBridge(int bridgeStartOverlayIndex, int bridgeEndOverlayIndex, List<int> bridgePieces, int beginCoord, int endCoord, Action<int, int> piecePlacementFunction)
private void PlaceLowBridge(OverlayType bridgeStartOverlayType, OverlayType bridgeEndOverlayType, List<OverlayType> bridgePieces, int beginCoord, int endCoord, Action<OverlayType, int> piecePlacementFunction)
{
piecePlacementFunction(bridgeStartOverlayIndex, beginCoord);
piecePlacementFunction(bridgeStartOverlayType, beginCoord);

for (int c = beginCoord + 1; c < endCoord; c++)
{
int overlayIndex = bridgePieces[MutationTarget.Randomizer.GetRandomNumber(0, bridgePieces.Count - 1)];
piecePlacementFunction(overlayIndex, c);
OverlayType overlayType = bridgePieces[MutationTarget.Randomizer.GetRandomNumber(0, bridgePieces.Count - 1)];
piecePlacementFunction(overlayType, c);
}

piecePlacementFunction(bridgeEndOverlayIndex, endCoord);
piecePlacementFunction(bridgeEndOverlayType, endCoord);
}

private void PlaceEastWestDirectionLowBridgePiece(int overlayIndex, int x)
private void PlaceEastWestDirectionLowBridgePiece(OverlayType overlayType, int x)
{
PlaceLowBridgePiece(overlayIndex, x,
PlaceLowBridgePiece(overlayType, x,
(fixedCoord, variableCoord) => new Point2D(fixedCoord, startPoint.Y + variableCoord));
}

private void PlaceNorthSouthDirectionLowBridgePiece(int overlayIndex, int y)
private void PlaceNorthSouthDirectionLowBridgePiece(OverlayType overlayType, int y)
{
PlaceLowBridgePiece(overlayIndex, y,
PlaceLowBridgePiece(overlayType, y,
(fixedCoord, variableCoord) => new Point2D(startPoint.X + variableCoord, fixedCoord));
}

private void PlaceLowBridgePiece(int overlayIndex, int fixedCoordinate, Func<int, int, Point2D> coordGenerator)
private void PlaceLowBridgePiece(OverlayType overlayType, int fixedCoordinate, Func<int, int, Point2D> coordGenerator)
{
for (int variableCoordinateOffset = -1; variableCoordinateOffset <= 1; variableCoordinateOffset++)
{
Expand All @@ -137,13 +137,13 @@ private void PlaceLowBridgePiece(int overlayIndex, int fixedCoordinate, Func<int

mapCell.Overlay = new Overlay()
{
OverlayType = MutationTarget.Map.Rules.OverlayTypes[overlayIndex],
OverlayType = overlayType,
FrameIndex = variableCoordinateOffset + 1,
Position = cellCoords
};
}
}
private void PlaceHighBridge(int bridgePiece, int beginCoord, int endCoord, Action<int, int, int> piecePlacementFunction)
private void PlaceHighBridge(OverlayType bridgePiece, int beginCoord, int endCoord, Action<OverlayType, int, int> piecePlacementFunction)
{
var startCell = MutationTarget.Map.GetTile(startPoint);
if (startCell == null)
Expand All @@ -155,25 +155,25 @@ private void PlaceHighBridge(int bridgePiece, int beginCoord, int endCoord, Acti
}
}

private void PlaceEastWestDirectionHighBridgePiece(int overlayIndex, int x, int startingHeight)
private void PlaceEastWestDirectionHighBridgePiece(OverlayType overlayType, int x, int startingHeight)
{
const int xStartFrame = 0;
const int xEndFrame = 3;
int frameIndex = MutationTarget.Randomizer.GetRandomNumber(xStartFrame, xEndFrame);

PlaceHighBridgePiece(overlayIndex, frameIndex, new Point2D(x, startPoint.Y), startingHeight);
PlaceHighBridgePiece(overlayType, frameIndex, new Point2D(x, startPoint.Y), startingHeight);
}

private void PlaceNorthSouthDirectionHighBridgePiece(int overlayIndex, int y, int startingHeight)
private void PlaceNorthSouthDirectionHighBridgePiece(OverlayType overlayType, int y, int startingHeight)
{
const int yStartFrame = 9;
const int yEndFrame = 12;
int frameIndex = MutationTarget.Randomizer.GetRandomNumber(yStartFrame, yEndFrame);

PlaceHighBridgePiece(overlayIndex, frameIndex, new Point2D(startPoint.X, y), startingHeight);
PlaceHighBridgePiece(overlayType, frameIndex, new Point2D(startPoint.X, y), startingHeight);
}

private void PlaceHighBridgePiece(int overlayIndex, int frameIndex, Point2D cellCoords, int startingHeight)
private void PlaceHighBridgePiece(OverlayType overlayType, int frameIndex, Point2D cellCoords, int startingHeight)
{
var mapCell = MutationTarget.Map.GetTile(cellCoords);

Expand All @@ -190,7 +190,7 @@ private void PlaceHighBridgePiece(int overlayIndex, int frameIndex, Point2D cell

mapCell.Overlay = new Overlay()
{
OverlayType = MutationTarget.Map.Rules.OverlayTypes[overlayIndex],
OverlayType = overlayType,
FrameIndex = frameIndex,
Position = cellCoords
};
Expand Down
Loading

0 comments on commit 9f9d506

Please sign in to comment.