61 lines
3.8 KiB
Markdown
61 lines
3.8 KiB
Markdown
# Draw distance mod (`fog`, VISUAL)
|
||
|
||
Code: `src/main/java/com/eliasmueller/llamamod/mods/fog/FogMod.java`, test
|
||
`src/test/.../mods/fog/FogModTest` (needs `-Dllamamod.cd=<cd dir>`). Data-only (MAP chunks), no
|
||
exe patch.
|
||
|
||
## Options
|
||
|
||
| Key | Type | Default | Effect |
|
||
|---|---|---|---|
|
||
| `distance` | INT % 100–600 | 250 | fog start/end (= far clip) × distance/100 |
|
||
| `fog` | CHOICE `scaled` / `off` | scaled | `off`: fog band shrunk to 1/16 tile, i.e. no fade, hard edge at the draw distance |
|
||
|
||
## Engine facts (groove.exe)
|
||
|
||
* Environment zone (MAP block 4, 90 bytes on disk, 0x5c in memory; loader FUN_0042ac50). Fog
|
||
values are 20.12 fixed point, 4096 = 1 tile:
|
||
| memory | file offset | meaning |
|
||
|---|---|---|
|
||
| +0x34 | 0x34 | fog mode (3 = vertex fog/darkening; 2 = other mode; read by FUN_00438180) |
|
||
| +0x3c / +0x40 | 0x3a / 0x3e | fog start / end for detail "Minimum" |
|
||
| +0x44 / +0x48 | 0x42 / 0x46 | fog start / end for detail "Maximum" (loader: if +0x44 ≤ +0x3c, both are set to 1.5 × the low pair) |
|
||
| +0x4c, +0x50 | 0x4a, 0x4e | colours (ambient → FUN_0041bcf0, backdrop/fog → FUN_00439110) |
|
||
| +0x58 | 0x56 | music id |
|
||
The u16 at +0x38 takes 2 bytes on disk, so all later file offsets are memory − 2.
|
||
* Per frame (FUN_0041a480; zone switch FUN_0041e1c0): `t` = detail setting (0x5848cc: 1.0
|
||
Maximum, 0.5 Medium, 0.0 Minimum). Fixed `end = lo_end + (hi_end − lo_end)·t` → 0x58658c /
|
||
0x586590; float `far = end·(t + (1−t)·0.5)/4096` → 0x57f90c = 0x57f8fc; fog start likewise →
|
||
0x57f8f8; 0x57f904 = 1/(far − start) (fog factor), 0x57f914 = 0.9999999/(far − near) (depth).
|
||
`FUN_00424bb0(near, far)` sets the clip range for the rasteriser.
|
||
* Everything that limits view distance derives from these zone values:
|
||
* fog: vertex colours are scaled by `(far − d)·0x57f904` when `d > start` (0x421a14 …, 0x557b20 …),
|
||
* far clip plane 0x57f90c,
|
||
* tile renderer FUN_0042bf40 walks the grid cells within camera ± (far + const),
|
||
* strat visibility/activity radius `0x586590 + 0x800` (FUN_00428700, FUN_004361xx; strat opcode
|
||
0xf2 also returns it). So objects (and enemies) wake up from further away as well.
|
||
* Not changed: the region mask `0x58642c` (32 region bits from MAP block 6/7, set by triggers;
|
||
hides other rooms/areas) – it is a level-design visibility mechanism, not a distance limit.
|
||
* Original fog end at Maximum detail, per level: 7–16 tiles (village t1l1m001 8.2–12.8, jungle
|
||
t1l2m001 8.6–10.5, jungle night chase t1l2m003 6.9, city t1l6m001 14, roller coaster up to 23).
|
||
At Minimum the float far is only half of the low pair (2.5–4 tiles). Zones with mode 0 carry
|
||
placeholder values (2.0/3.5/3.0/5.25) and are scaled as well.
|
||
|
||
## Verified in game (apptest, Wine 6, llvmpipe, 2026-11-06)
|
||
|
||
* Jungle t1l2m001 at 50 % / original / 400 %: at 50 % the spider-web gate at the end of the first
|
||
path disappears in the dark fog, at 400 % it is a bit clearer than in the original
|
||
(`img/mods/fog-jungle-50-100-400.jpg`). This proves the four zone values drive fog + clip.
|
||
* Village t1l1m001 (400 %, 300 %, 50 %) and city t1l6m001 (400 %, `img/mods/fog-city-400.jpg`):
|
||
levels load and run, no crash, no slowdown noticeable in the harness; the start views are
|
||
enclosed (village backdrop mountains are a sky texture, the city streets are short), so the
|
||
difference there is small.
|
||
* Not tested: 600 % in large open levels (roller coaster, 23 tiles × 6) – expect more tiles and
|
||
strats per frame; and the `off` mode in game (unit test only).
|
||
|
||
## Known limits
|
||
* Many areas are enclosed or use region masks, so the gain is mostly visible on long paths and
|
||
open views (jungle, river, roller coaster). The village backdrop is a texture, not geometry.
|
||
* Objects/enemies activate from further away (strat radius = fog end); with large values enemies
|
||
may start moving before they are in view.
|