docs(research): retail Environment Detail Textures = overlay blend, decomp-verified
One checkbox drives building + EnvCell detail; base texture always drawn; detail is a region-authored ImgTex with its own tiling, modulate-blended over (single-pass multitexture or two-pass fallback). Port sketch included. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
9bd3a98363
commit
bf934d98c3
1 changed files with 59 additions and 0 deletions
59
docs/research/2026-07-10-detail-texturing.md
Normal file
59
docs/research/2026-07-10-detail-texturing.md
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
# Retail "Environment Detail Textures" — mechanism (decomp-verified 2026-07-10)
|
||||
|
||||
**Question:** does the option apply a texture OVER the original, or a new texture altogether?
|
||||
**Answer: OVERLAY — the base texture is always drawn unchanged; detail is an extra blended layer.**
|
||||
All references are `docs/research/named-retail/acclient_2013_pseudo_c.txt` `line:address` or `acclient.h:line`.
|
||||
|
||||
## Chain
|
||||
|
||||
- Checkbox: `RenderPrefs.EnvironmentDetailTextures` (acclient.h:41674-41678) →
|
||||
`Render::UpdateFromPreferences` (344244:0054d850) → `SmartBox::SetDetailTexturing`
|
||||
(90961:00451df0) → `LScape::SetDetailTexturing` (268389:00506b40).
|
||||
- **One checkbox drives TWO categories:** building (cat 1) AND EnvCell/dungeon (cat 2).
|
||||
Landscape detail is force-zeroed at the options layer in this Sept-2013 build
|
||||
(344384:0054d9c8) — vestigial but fully wired at draw time. Object/creature detail is
|
||||
never enabled; `DrawPartCell` (429201:005a07a6) explicitly nulls `curr_detail_surface`.
|
||||
- Asset: per-terrain-type `detail_tex_gid` + `detail_tex_tiling` authored in the **region dat**
|
||||
(acclient.h:52986-52987; read via `TexMerge::GetDetailTex` 264927:005039e0). Ordinary ImgTex
|
||||
(QDID type 0xb). `LScape::GenerateDetailSurface` (267853:00506230) wraps it in a custom
|
||||
CSurface (`makeCustomSurface(SH_CUSTOMDB)` + `UseTextureMap`, `type |= 0x20000` =
|
||||
`SurfaceType::DETAIL`) and publishes to `Render::environment/building_detail_surface`
|
||||
(setters 342321-342349:0054b7c0+) with its tiling factor.
|
||||
|
||||
## Draw + blend (base ALWAYS stays)
|
||||
|
||||
Per frame `RenderDeviceD3D::DrawEnvCell` (427885:0059f170) / `DrawBuilding` (427938:0059f2a0)
|
||||
stash the category surface into `Render::curr_detail_surface` with blend
|
||||
**src=9 D3DBLEND_DESTCOLOR / dst=6 INVSRCALPHA** (427897-427900 / 427950-427953); landscape path
|
||||
(`DrawBlock` 430027:005a17c0, full-LOD `side_cell_count==8` only) uses **5/6 SRCALPHA/INVSRCALPHA**.
|
||||
Detail UVs = baseUV × tiling, written as a second texcoord set (`landPolyDraw` 702299:006b6525,
|
||||
FVF 0x242/0x252; `D3DPolyRender::SetDetailTiling` 424834:0059c150 caches in
|
||||
`MeshBuffer.detailTilingFactorSet` acclient.h:31954).
|
||||
|
||||
Two hardware paths, both compositing over the base:
|
||||
|
||||
1. **Single-pass multitexture** (when `bCanDoSinglePassDetailing`, caps 428180:0059f6cf):
|
||||
`D3DPolyRender::SetSurface` (425083:0059c4d0) — stage 0 = BASE tex MODULATE diffuse +
|
||||
ALPHAOP PREMODULATE; stage 1 = DETAIL tex `TEXOP_BLENDCURRENTALPHA` on texcoord set 1
|
||||
(425109-425115:0059c51c-0059c574); `ACRender::SetDetailSurfaceInternal(1)` (702183:006b6280)
|
||||
binds detail in stage 1, WRAP+LINEAR.
|
||||
2. **Two-pass fallback:** draw base normally, then rebind detail into stage 0 with
|
||||
`SetBlendFunction(src,dst,ADD)` + AlphaBlendEnable + DEPTHTEST_LESSEQUAL
|
||||
(702199-702204:006b62db) and **redraw the same geometry** with detail-tiled UVs
|
||||
(landPolyDraw 2nd pass 702352:006b6664; `RenderMeshSubset` 2nd pass 425604:0059cdb3).
|
||||
|
||||
Blend math: buildings/EnvCells → `final = base × (detail.rgb + (1 − detail.a))` — modulate-style
|
||||
tint fading to identity where detail alpha→0. Landscape → classic alpha-lerp. Detail suppressed on
|
||||
clip-mapped (color-keyed) base surfaces (`BASE1_CLIPMAP`=4 gate, 702215:006b6333).
|
||||
|
||||
## Open ends
|
||||
|
||||
- A 10→50-unit distance fade exists (`get_alpha_for_z`) but its `noFadeDetail` global inits to 1
|
||||
(fade DISABLED, alpha forced 0xff) at 1105973:00820e38 with no writer found — as-shipped the
|
||||
detail likely renders full-strength at all distances. A cdb poke on live retail would settle it.
|
||||
|
||||
## Port sketch for acdream (when we add the option)
|
||||
|
||||
Draw the base exactly as today; add detail layer = detailTex sampled at (baseUV × detail_tex_tiling);
|
||||
combine per category — buildings/EnvCells: `base × (detail.rgb + (1−detail.a))`; terrain:
|
||||
`lerp(base, detail, detail.a)` (vestigial in 2013). One option gates buildings + EnvCells together.
|
||||
Loading…
Add table
Add a link
Reference in a new issue