From f48c74aa8b20cc07a7dc3b8895970c66428f7495 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 25 May 2026 21:24:28 +0200 Subject: [PATCH] =?UTF-8?q?fix(render):=20#100=20=E2=80=94=20render=20terr?= =?UTF-8?q?ain=201=20cm=20below=20physical=20Z=20(retail=20zFightTerrainAd?= =?UTF-8?q?just)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Subtract 0.01 from every terrain vertex Z in the modern terrain vertex shader, matching retail's per-draw nudge applied inside ACRender::landPolysDraw(arg2=2). Coplanar building floors now always win the depth test against the rendered terrain, so the visual "ground at the building floor" reads as the building's floor, not as Z-fighting. Constant 0.01f bit-equals retail's float literal 0.00999999978 when rounded to single precision. Render-only — physics reads the un-nudged heightmap via TerrainSurface.SampleZ / SampleZFromHeightmap. The same render-vs- physics split is already established for EnvCell render lift (+0.02m at GameWindow.cs around the cell-mesh draw). Retail anchors: docs/research/named-retail/acclient_2013_pseudo_c.txt:1120769 docs/research/named-retail/acclient_2013_pseudo_c.txt:702254 Cross-ref: docs/research/2026-05-25-issue-100-terrain-cutout-handoff.md docs/superpowers/plans/2026-05-25-issue-100-terrain-cutout.md Followed by Task 2 (delete the hiddenTerrainCells / BuildingTerrainCells plumbing). Visible result of this commit alone: building floors stop Z-fighting, but the 24m x 24m transparent rectangles persist until the plumbing is removed. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/AcDream.App/Rendering/Shaders/terrain_modern.vert | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/AcDream.App/Rendering/Shaders/terrain_modern.vert b/src/AcDream.App/Rendering/Shaders/terrain_modern.vert index 473cba5..9427a55 100644 --- a/src/AcDream.App/Rendering/Shaders/terrain_modern.vert +++ b/src/AcDream.App/Rendering/Shaders/terrain_modern.vert @@ -136,5 +136,12 @@ void main() { vRoad0 = unpackOverlayLayer(aPacked2.x, aPacked2.y, rotRd0, baseUV); vRoad1 = unpackOverlayLayer(aPacked2.z, aPacked2.w, rotRd1, baseUV); - gl_Position = uProjection * uView * vec4(aPos, 1.0); + // Retail zFightTerrainAdjust (acclient_2013_pseudo_c.txt:1120769 = 0.00999999978, + // applied per terrain vertex inside ACRender::landPolysDraw at line 702254, + // address 006b6402). Render terrain 1 cm below its physical Z so coplanar + // building floors win the depth test. Physics path is unaffected — it reads + // the un-nudged heightmap via TerrainSurface.SampleZ. + // Closes issue #100; supersedes the hiddenTerrainCells cell-collapse hack. + vec3 terrainPos = vec3(aPos.xy, aPos.z - 0.01); + gl_Position = uProjection * uView * vec4(terrainPos, 1.0); }