sky(phase-8): retail-faithful night sky + README refresh

Iteration on the sky rendering pipeline to restore stars/moon visibility
at night and fix washed-out grey daytime clouds. Key fixes:

* sky.frag: disable fog-mix on sky meshes. Retail's keyframe FogEnd
  (0..400m at midnight, up to 2400m during day) is calibrated for
  terrain; sky meshes are authored at radii 1050-14271m which sits
  past FogEnd universally, causing every sky pixel to saturate to
  fogColor (dark navy). Stars, moon, dome texture all got
  obliterated. The horizon-glow trade-off is noted in the shader
  comment; research item to find retail's sky-specific fog range
  later.

* SkyRenderer + sky.frag: promote rep.Luminosity into uEmissive so the
  vertex lighting saturates properly for bright keyframes. Retail's
  FUN_0059da60 non-luminous path writes rep.Luminosity into
  material.Emissive via the cache +0x3c slot; we were instead using
  it as a post-fragment multiply which could only dim, never brighten.
  Net effect: daytime clouds now render saturated white, dome dims
  correctly at night (rep.Luminosity=0.11 → Emissive=0.11), stars
  and moon unchanged.

* terrain.vert: MIN_FACTOR 0.08 -> 0.0 per retail FUN_00532440 decompile
  (DAT_00796344 ambient-floor = 0.0). Back-lit terrain now falls to
  pure ambient rather than getting an 8% sun floor.

New research / tooling (no runtime impact):

* docs/research/2026-04-24-lambert-brightness-split.md — retail's
  ambient-brightness formula pinned from PE .rdata read + live
  RetailTimeProbe capture: effAmbBright = AmbBright + |sunDir| * 0.2
  where scale constant 0x0079a1e8 = 0.2f exactly.

* docs/research/2026-04-23-lightning-real.md — research note on the
  dat-baked PhysicsScript-driven lightning path (Rainy DayGroup has
  explicit PES-triggered flash SkyObjects with 5ms time windows).

* Corrections stapled to sky-decompile-hunt-{B,C}.md: DAT_00842778 is
  DirColor, DAT_0084277c is AmbColor (the hunt docs had the swap
  backwards).

* tools/RetailTimeProbe/Program.cs: extended with pid=NNNN selector,
  sky global probe (DirColor/AmbColor/AmbBright/sunDir/cache.amb),
  and the 0x0079a1e8 scale-factor readout.

* tools/SkyObjectInspect/: throwaway dat-inspector built by the Opus
  deep-dive agent. Identified GfxObj 0x010015EF as the stars layer
  (A8R8G8B8 128x128 texture, 4% bright-pixel ratio).

* src/AcDream.App/Rendering/TextureCache.cs: per-texture alpha
  histogram dump under ACDREAM_DUMP_SKY=1 for diagnosing "are the
  clouds decoded with proper alpha" type questions.

README: rewrite to reflect current state (playable pre-alpha rendering
Dereth with animated characters, day-night cycle, weather, etc.)
instead of the stale "Phase 0 dat inventory only" description.

All 742 tests green.
This commit is contained in:
Erik 2026-04-24 20:34:36 +02:00
parent 889b235886
commit 1d54880213
12 changed files with 1217 additions and 43 deletions

View file

@ -9,6 +9,31 @@ All citations use `{chunk_file}:{line}` relative to the decompile tree.
---
## ⚠ 2026-04-24 correction
Sections §1, §2, §5 of this doc label `DAT_00842778` as "AmbColor" and
`DAT_0084277c` as "DirColor/Fog". **That labeling is backwards.** The
correct mapping — cross-verified against the DatReaderWriter schema
(`SkyTimeOfDay.Unpack` field order) and the `FUN_00501600` output map:
- `DAT_00842778` = **DirColor** (directional/sun color ARGB)
- `DAT_0084277c` = **AmbColor** (ambient color ARGB)
- `DAT_00842780` = **AmbBright** (ambient brightness scalar, *not* fog start)
The `FUN_00532440` per-vertex Lambert at `chunk_00530000.c:2118-2124`
reads `DAT_00842778` as the N·L-modulated color (→ directional) and
`DAT_0084277c × DAT_00842780` as the flat / brightness-scaled color
(→ ambient × ambBright). The pre-multiply at line 2107 takes
`DAT_00842780 * DAT_0084277c` which is the textbook "ambient scalar ×
ambient color" retail ambient term.
See `docs/research/2026-04-24-lambert-brightness-split.md` for the full
re-analysis and `SkyTimeOfDay.generated.cs` for the field offsets (+0x10
DirColor, +0x18 AmbColor). All entries below should be read with this
swap in mind; the decompile math quotes themselves are correct.
---
## 1. Global Inventory — the sky state block
All globals live in a contiguous block at **`0x00842778..0x008427c0`** with a second cluster at **`0x00842950..0x00842960`**. Every field is read by landblock/draw code and written only by the per-frame updater `FUN_005062e0` via the interp delegate `FUN_00501600`. Initial values are set in `FUN_00505dd0` (the sky-system constructor).