From c25d618684376ab40378377dab6a879112970107 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 25 Jun 2026 20:26:19 +0200 Subject: [PATCH] =?UTF-8?q?docs(issues):=20#155=20=E2=80=94=20terrain=20te?= =?UTF-8?q?xtures=20stretched/blurry=20=3D=20missing=20landscape=20detail-?= =?UTF-8?q?texture=20overlay?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Verified root cause (oracle-first) of the user's "stretched + less-detailed" outdoor terrain: acdream tiles the base ground texture once per 24m landcell (terrain_modern.frag TILE=1.0) and never applies retail's landscape DETAIL texture overlay (dat TerrainTex.DetailTextureId / DetailTexTiling). Decomp-cited mechanism (landPolyDraw detail UV = curr_detail_tiling*baseUV pc:702299; 10->50 depth fade pc:702263; TEXOP_MODULATE pc:425099; single landscape scalar via TexMerge::GetDetailTiling pc:263852). Filtering + 512^2 resolution ruled out. Fix attempt (parallel detail texture array + MODULATE2X + distance fade) built and ran but rendered the ground black (detail array sampled ~0); reverted. Handles verified NOT swapped -- the bug is detail-texture DATA (gray fill / DetailTextureId decode). Filed with full debugging steps for a fresh pass. Also recorded the DO-NOT-RETRY: the first investigation agent FABRICATED a base `TexTiling` dat field that does not exist (only DetailTexTiling). Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/ISSUES.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/docs/ISSUES.md b/docs/ISSUES.md index abc99525..25b9c959 100644 --- a/docs/ISSUES.md +++ b/docs/ISSUES.md @@ -46,6 +46,45 @@ Copy this block when adding a new issue: --- +## #155 — Outdoor terrain textures look stretched + blurry vs retail (missing landscape DETAIL-texture overlay) + +**Status:** OPEN — **root cause VERIFIED (oracle-first); fix attempt implemented + REVERTED** (rendered the ground black). Ready for a focused fresh implementation pass. +**Severity:** MEDIUM (visible — outdoor ground reads soft/stretched everywhere vs retail's crisp ground; user side-by-side screenshots) +**Filed:** 2026-06-25 +**Component:** render — terrain texturing (WB-derived modern path: `TerrainAtlas` / `TerrainModernRenderer` / `terrain_modern.frag`) + +**Description (user-observed, 2026-06-25):** Outdoor terrain textures look stretched and less detailed than retail — a cobblestone road's stones look too big/blurry, grass is softer. Side-by-side: retail crisp, acdream smeared. + +**Root cause (VERIFIED — decomp + dat, not guessed):** acdream renders one base texture tiled **once per 24 m landcell** (`terrain_modern.frag:49` `const float TILE = 1.0;`, `vBaseUV` 0→1 per cell) and **ignores the dat's detail-texture fields entirely**. Retail overlays a high-frequency **landscape detail texture** on the base ground; that overlay is what keeps retail's ground crisp up close. Filtering is NOT the problem (the ground array already has mipmaps + `LinearMipmapLinear` + 16× anisotropy, `TerrainAtlas.cs:187-193`); resolution is NOT the problem (terrain is 512² in both Portal and HighRes). + +**Verified retail mechanism (decomp `docs/research/named-retail/acclient_2013_pseudo_c.txt`):** +- Dat fields on `DatReaderWriter.Types.TerrainTex` (confirmed via reflection on Chorizite.DatReaderWriter 2.1.7): `DetailTextureId` (`QualifiedDataId`, `.DataId`) + `DetailTexTiling` (`uint`). acdream currently reads neither (only `TextureId`). +- `ACRender::landPolyDraw` 0x006b6525 (lines 702299-702300): **detail UV = `curr_detail_tiling × baseUV`** (the detail texture tiles `detail_tiling×` relative to the base). +- `landPolyDraw` 0x006b6450-0x006b649c (lines 702263-702287): **distance fade** — detail alpha is FULL at camera depth `< 10`, lerps to 0 by depth `50`, gone beyond. (Detail only sharpens up close.) +- 0x0059cab4 / lines 425099-425112: blend = **`TEXOP_MODULATE`** (modern equivalent: MODULATE2X `base*detail*2`, neutral at gray 0.5). +- `TexMerge::GetDetailTiling` 0x00503a10 (line 263852); `LScape::GenerateDetailSurfaces`/`SetDetailTexturing` 0x00506b40 (line 268389). Gated by the `EnvironmentDetailTextures` graphics preference (`Render::m_RenderPrefs.EnvironmentDetailTextures`). +- **FAITHFULNESS NOTE:** retail uses a **single landscape detail-tiling SCALAR** — `GetDetailTiling(region, 0)` reads `TerrainDesc[0].DetailTexTiling` (category 0 = landscape; default **2.0** @0x0081eca8), stored in global `Render::curr_detail_tiling` and applied to ALL terrain UVs. It is **NOT per-terrain-type**. Prefer the single scalar. + +**⚠ DO-NOT-RETRY:** the first investigation agent **FABRICATED a base `TexTiling` field** — it does **NOT** exist on `TerrainTex` (only `DetailTexTiling`). Do not re-introduce a "read `TexTiling`, multiply the base UV" fix; the base tiling is not a per-type dat field. (Verify the actual base landcell UV scale in the decomp before touching `TILE`.) + +**Fix attempt (implemented + REVERTED, this session):** built a parallel detail `GL_TEXTURE_2D_ARRAY` (per type from `DetailTextureId`) + `uDetailTiling[]` + the shader block `rgb *= mix(vec3(1.0), detail*2.0, fade)` with the 10→50 depth fade. It **compiled, linked, ran with no GL error** — but the ground rendered **black/dark up close**: the detail array sampled near-zero, so MODULATE2X collapsed `rgb` to 0. **The bindless handles were verified NOT swapped** (renderer correctly binds `(terrain, alpha, detail)`). The bug is in the detail-texture **DATA**: the no-detail gray fill (`NoDetailGray=128`) didn't land as neutral, OR `DetailTextureId` decodes dark/black, OR AC's detail textures are not 0.5-centered (so MODULATE2X darkens). Reverted via `git checkout` — terrain back to the working (blurry) state. + +**NEXT (debugging steps for the fresh pass):** +1. **Dump the detail array content** — are the layers ~0.5 gray or ~0 black? (Throwaway: decode each `DetailTextureId` + print mean brightness.) This tells you gray-fill vs decode vs texture-content. +2. If the textures decode dark, AC detail textures may not be gray-centered → use plain MODULATE or re-center, not MODULATE2X. Confirm the actual blend visually. +3. Confirm `DetailTextureId` → `SurfaceTexture` → `RenderSurface` resolves (do the detail textures even exist for these terrain types? many may be 0 → must fall to the gray no-op). +4. Use retail's **single landscape scalar** (`TerrainDesc[0].DetailTexTiling`, default 2.0), not per-type (faithfulness note above). +5. Gate behind an `EnvironmentDetailTextures` equivalent. +6. **Secondary (separate, unconfirmed):** is the base `TILE=1.0` (once per cell) correct vs retail? Verify the landcell base UV scale in the decomp during the fix — it may also contribute to "stretched." + +**Files (the reverted attempt, for reference):** `TerrainAtlas.cs` (detail array build + gray fill + `DetailTiling`), `terrain_modern.frag` (uDetail sampler + MODULATE2X + fade), `TerrainModernRenderer.cs` (bind detail handle + upload `uDetailTiling[]`). + +**Milestone note:** freeze-override render-polish (off the M1.5 critical path); resume when prioritized. Detail-overlay is a real retail feature acdream lacks — register an AP row when it ships (or note it as a known divergence until then). + +**Acceptance:** outdoor ground (cobblestone road + grass) reads crisp up close matching retail, detail fades cleanly past ~50 m, no overall color/brightness shift (modulate neutral); user side-by-side vs retail. + +--- + ## #151 — Far-town (Arwic) collision broken at login: terrain barely grounds + city/perimeter walls never block **Status:** 🟡 city/perimeter walls **FIXED + user-verified** (`9743537`, 2026-06-24); terrain-grounding sub-question OPEN but re-scoped LOW (likely not a real defect).