Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,15 @@ public GeometryRenderer(IConfig config, ArchiveCollection archiveCollection, Leg
m_fakeSideScrollData = new();
m_fakeSide = new(0, default, m_fakeWall, m_fakeWall, m_fakeWall, m_sliceSector)
{
NoCache = true,
ScrollData = m_fakeSideScrollData
};
m_emptyTraverseSide = new(0, default, m_fakeWall, m_fakeWall, m_fakeWall, m_emptyTraverseSector);

m_fogWall.TextureHandle = TextureManager.BlackTextureIndex;
m_fogSide = new(0, default, m_fogWall, m_fogWall, m_fogWall, null!)
{
NoCache = true,
RenderDataStyle = RenderDataStyle.FogBarrier
};
m_fogSide.Flags.WrapMidTex = true;
Expand Down Expand Up @@ -744,7 +746,7 @@ public void RenderOneSided(Side side, bool isFront, out DynamicVertex[]? vertice
WallVertices wall = default;
texture = m_glTextureManager?.GetTexture(side.Middle.TextureHandle) ?? TestTexture;
var brightmapTexture = m_glTextureManager?.GetBrightmapTexture(side.Middle.TextureHandle);
var data = m_vertexLookup[side.Id];
var data = GetCachedSide(m_vertexLookup, side);

renderSector ??= side.Sector.GetRenderSector(m_transferHeightsView);
lightLevelSector ??= renderSector;
Expand Down Expand Up @@ -778,7 +780,7 @@ public void RenderOneSided(Side side, bool isFront, out DynamicVertex[]? vertice
else
SetWallVertices(data, wall, GetLightLevelAdd(side), lightIndex, colorMapIndex, GetWallLightLevel(side, side.Middle), side.Line.Id, WallLocation.Middle, addAlpha: addAlpha, alpha: side.Alpha);

m_vertexLookup[side.Id] = data;
SetCachedSide(m_vertexLookup, side, data);
}

if (m_buffer)
Expand All @@ -792,6 +794,19 @@ public void RenderOneSided(Side side, bool isFront, out DynamicVertex[]? vertice
vertices = data;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static DynamicVertex[]? GetCachedSide(DynamicVertex[]?[] lookup, Side side)
{
return side.NoCache ? null : lookup[side.Id];
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SetCachedSide(DynamicVertex[]?[] lookup, Side side, DynamicVertex[] data)
{
if (!side.NoCache)
lookup[side.Id] = data;
}

private static GeometryType GetGeometryType(RenderDataStyle style, GeometryType baseType)
{
if (style != RenderDataStyle.Normal)
Expand Down Expand Up @@ -1113,7 +1128,7 @@ public void RenderTwoSidedLower(Side facingSide, Side otherSide, Sector facingSe
}
else
{
DynamicVertex[]? data = m_vertexLowerLookup[facingSide.Id];
var data = GetCachedSide(m_vertexLowerLookup, facingSide);

if (facingSide.OffsetChanged || m_sectorChangedLine || data == null)
{
Expand All @@ -1129,7 +1144,7 @@ public void RenderTwoSidedLower(Side facingSide, Side otherSide, Sector facingSe
else
SetWallVertices(data, wall, GetLightLevelAdd(facingSide), lightIndex, colorMapIndex, GetWallLightLevel(facingSide, facingSide.Lower), facingSide.Line.Id, WallLocation.Lower);

m_vertexLowerLookup[facingSide.Id] = data;
SetCachedSide(m_vertexLookup, facingSide, data);
}

if (m_buffer)
Expand Down Expand Up @@ -1236,7 +1251,7 @@ public void RenderTwoSidedUpper(Side facingSide, Side otherSide, Sector facingSe
return;
}

DynamicVertex[]? data = m_vertexUpperLookup[facingSide.Id];
var data = GetCachedSide(m_vertexUpperLookup, facingSide);

if (facingSide.OffsetChanged || m_sectorChangedLine || data == null)
{
Expand All @@ -1248,7 +1263,7 @@ public void RenderTwoSidedUpper(Side facingSide, Side otherSide, Sector facingSe
else
SetWallVertices(data, wall, GetLightLevelAdd(facingSide), lightIndex, colorMapIndex, GetWallLightLevel(facingSide, facingSide.Upper), facingSide.Line.Id, WallLocation.Upper);

m_vertexUpperLookup[facingSide.Id] = data;
SetCachedSide(m_vertexUpperLookup, facingSide, data);
}

if (m_buffer)
Expand Down Expand Up @@ -1392,14 +1407,11 @@ public void RenderTwoSidedMiddle(Side facingSide, Side otherSide, Sector facingS
GLLegacyTexture? brightmapTexture = m_glTextureManager.GetBrightmapTexture(middleWall.TextureHandle, repeatY: facingSide.Flags.WrapMidTex);

var line = facingSide.Line;
float alpha = m_config.Render.TextureTransparency ? Math.Clamp(line.Alpha, 0, 1) : 1.0f;
DynamicVertex[]? data = m_vertexLookup[facingSide.Id];
var alpha = m_config.Render.TextureTransparency ? Math.Clamp(line.Alpha, 0, 1) : 1.0f;
var data = GetCachedSide(m_vertexLookup, facingSide);
var geometryType = alpha < 1 ? GeometryType.Translucent : GeometryType.TwoSidedMiddleWall;
if (facingSide == m_fogSide)
{
data = null;
geometryType = GeometryType.FogBarrier;
}

if (facingSide.OffsetChanged || m_sectorChangedLine || data == null)
{
Expand Down Expand Up @@ -1437,8 +1449,7 @@ public void RenderTwoSidedMiddle(Side facingSide, Side otherSide, Sector facingS
else
SetWallVertices(data, wall, GetLightLevelAdd(facingSide), lightIndex, colorMapIndex, GetWallLightLevel(facingSide, facingSide.Middle), line.Id, WallLocation.None, alpha, addAlpha: 0);

if (facingSide != m_fogSide)
m_vertexLookup[facingSide.Id] = data;
SetCachedSide(m_vertexLookup, facingSide, data);
line.RenderSegStart = saveStart;
line.RenderSegEnd = saveEnd;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public static class VertexFunction
@"
int colorMapAndLightLevel = floatBitsToInt(colorMapIndex);
vertexLightLevelFrag = float(colorMapAndLightLevel & 0xFF);
colorMapIndexFrag = float((colorMapAndLightLevel >> 10) & 0xFFFF);
colorMapIndexFrag = float((colorMapAndLightLevel >> 10) & 0x3FFFFF);
uvFlags = float((colorMapAndLightLevel >> 8) & 0x3);";

public static string LightLevelAddAndMapIdSet =>
Expand Down
4 changes: 2 additions & 2 deletions Core/Render/OpenGL/Renderers/Legacy/World/VertexOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public static unsafe float World(int topLeft, float alpha, int addAlpha, int upp
// UvFlags only required for walls
public static unsafe float ColorMapIndex(int colorMapIndex, int vertexLightLevel, UvFlags uvFlags = UvFlags.Normal)
{
// colorMapIndex 16 bits, uvFlags 2 bits, vertexLightLevel 8 bits (6 bits free)
int packed = ((colorMapIndex & 0xFFFF) << 10) | (((int)uvFlags & 0x3) << 8) | ((vertexLightLevel) & 0xFF);
// colorMapIndex 22 bits, uvFlags 2 bits, vertexLightLevel 8 bits
int packed = ((colorMapIndex & 0x3FFFFF) << 10) | (((int)uvFlags & 0x3) << 8) | (vertexLightLevel & 0xFF);
return *(float*)&packed;
}

Expand Down
7 changes: 6 additions & 1 deletion Core/World/Geometry/Sectors/Sector3D.cs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ public static void SetHeights3D(Sector sector)
var overlapLight = false;
if (i > 0 && lastPlane3D.Sector3D != null && lastPlane3D.ControlPlane.Z == plane3D.Plane.Z)
{
if (lastPlane3D.Face == plane3D.Face)
if (lastPlane3D.Face == plane3D.Face && !sector3D.ShouldRenderInsideWalls)
{
// Flag previous plane not to render since this one takes precedence
var keepPlane = (SectorPlanes)(lastPlane3D.Face + 1);
Expand Down Expand Up @@ -656,7 +656,12 @@ private bool ShouldClipSector3D(Sector3D other, bool clipSolid = false, bool cli
return false;

if (RenderDataStyle != RenderDataStyle.Normal && other.RenderDataStyle != RenderDataStyle.Normal)
{
if ((Alpha == 0 && other.Alpha != 0) || (Alpha != 0 && other.Alpha == 0))
return false;

return true;
}

if (ClipStyle != other.ClipStyle && (IsLightTransfer || other.IsLightTransfer))
return false;
Expand Down
1 change: 1 addition & 0 deletions Core/World/Geometry/Sides/Side.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public sealed class Side

public bool IsFront;
public bool FogCleared;
public bool NoCache;
public Side? PartnerSide;

public SideScrollData? ScrollData;
Expand Down
Binary file modified Tests/Resources/sector3d-map.zip
Binary file not shown.
20 changes: 20 additions & 0 deletions Tests/Unit/GameAction/3DSector/Sector3D_Map.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,26 @@ public void OverlappingAlphaWalls()
wallHeights = left3D.WallHeights;
left3D.CalculateWallHeights(GameActions.GetLine(World, 307).Front, out newWallHeights).Should().BeFalse();
}

[Fact(DisplayName = "Overlapping alpha walls render when other is zero")]
public void OverlappingAlphaWallsZeroAlpha()
{
var innerSector = GameActions.GetSector(World, 225);
var outerSector = GameActions.GetSector(World, 224);
var inner3D = innerSector.Sectors3D[0];
var outer3D = outerSector.Sectors3D[0];
inner3D.RenderDataStyle.Should().Be(RenderDataStyle.Translucent);
outer3D.RenderDataStyle.Should().Be(RenderDataStyle.Translucent);
inner3D.Alpha.Should().BeApproximately(0.5f, 1);
outer3D.Alpha.Should().Be(0f);

inner3D.CalculateWallHeights(GameActions.GetLine(World, 837).Front, out var newWallHeights).Should().BeTrue();
newWallHeights.TopZ.Should().Be(32);
newWallHeights.BottomZ.Should().Be(0);

outer3D.Alpha = 1f;
inner3D.CalculateWallHeights(GameActions.GetLine(World, 837).Front, out _).Should().BeFalse();
}

[Fact(DisplayName = "Partially overlapping non-solid walls")]
public void PartiallyOverlappingNonSolidWalls()
Expand Down
16 changes: 14 additions & 2 deletions Tests/Unit/GameAction/3DSector/Sector3D_PlaneSort.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Helion.Resources.IWad;
using Helion.World.Geometry.Sectors;
using Helion.World.Impl.SinglePlayer;
using System.Linq;
using Xunit;

namespace Helion.Tests.Unit.GameAction._3DSector;
Expand Down Expand Up @@ -115,7 +116,7 @@ public void ComplexSort()
*/

[Fact(DisplayName = "3D sector light transfer pool with floating solid sector")]
private void LightTransferLavaPool()
public void LightTransferLavaPool()
{
var lavaSector = GameActions.GetSector(World, 167);
AssertPlanes3D(lavaSector,
Expand Down Expand Up @@ -153,7 +154,7 @@ private void LightTransferLavaPool()
}

[Fact(DisplayName = "3D sector light water pool with floating solid sector")]
private void LightTransferWaterPool()
public void LightTransferWaterPool()
{
var waterSector = GameActions.GetSector(World, 173);
AssertPlanes3D(waterSector,
Expand Down Expand Up @@ -190,6 +191,17 @@ public void WaterSector()
);
}

[Fact(DisplayName = "3D sector with overlapping planes should render inside walls")]
public void OverlapRenderInside()
{
var sector = GameActions.GetSector(World, 229);
sector.Sectors3D.Length.Should().Be(2);
sector.Sectors3D[1].ShouldRenderInsideWalls.Should().BeTrue();

foreach (var plane in sector.SectorPlanes3D)
plane.NoRenderWall.Should().BeFalse();
}

private static void AssertPlanes3D(Sector sector, params PlaneData[] planes)
{
for (int i = 0; i < planes.Length; i++)
Expand Down
Loading