fix(lighting): match retail indoor ambient (0.20 neutral, not 0.10/0.09/0.08 warm)
Indoor cells rendered "almost black" because the hardcoded ambient at GameWindow.cs:8342-8345 was an early-2026 guess (0.10, 0.09, 0.08 — half retail brightness, warm-tinted) rather than the retail value. The named retail decomp (acclient.pdb, Sept 2013 EoR build) shows CellManager::ChangePosition @ 0x004559B0 calls SmartBox::SetWorldAmbientLight(0.2f, 0xFFFFFFFF) whenever the player's CObjCell::seen_outside flag is 0 — a flat 0.20 white floor, not a dungeon-tone warm color. Investigation also confirmed: - EnvCell.dat does NOT carry inline lights — CEnvCell::UnPack reads numVisibleCells where Binary Ninja's heuristic decomp inferred "num_lights". Retail's CObjCell.light_list is populated at runtime via add_light() calls from neighbouring cell light registrations + per-cell static-object Setup.Lights, NOT from the dat byte stream. - Setup.Lights from indoor static objects (entity.SourceGfxObjOrSetupId prefix 0x02xxxxxx) DO flow through LightInfoLoader.Load (line 5765) and reach LightManager via LightingHookSink. The wire is intact; the per-frame Tick + UBO upload chain (line 6865-6867) is intact. - Retail's particle system does NOT emit lights from particles themselves. The light comes from the owning Setup's LightInfo records. Pre-existing failures in DispatcherToMovementIntegrationTests, BSPStepUpTests, and MotionInterpreterTests are on the branch already and unrelated to this change (verified by stashing + retesting). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
67e64c79cf
commit
a54cd7bef6
2 changed files with 11 additions and 4 deletions
|
|
@ -46,7 +46,7 @@ public partial class LightInfo : IDatObjType {
|
|||
|
||||
- **Practical consequence.** For indoor cells, retail sets directional sun to zero (the cell is windowless) and relies on the baked vertex colours for the ambient "floor". Any `LightInfo` inside the cell is additive.
|
||||
- **No cell has a separate ambient RGB field.** The only global ambient is `SkyTimeOfDay.AmbColor` / `AmbBright`, which is only applied outdoors.
|
||||
- **acdream action.** We need a `CellAmbientState` that holds the current `AmbColor * AmbBright` (outdoors, driven by sky dat) or a fixed dark RGB like `(0.10, 0.09, 0.08)` (indoors, approximating the dungeon "deep" tone) — then add active lights on top. See §12 for the C# class.
|
||||
- **acdream action.** We need a `CellAmbientState` that holds the current `AmbColor * AmbBright` (outdoors, driven by sky dat) or **a flat `(0.20, 0.20, 0.20)` neutral** (indoors) — then add active lights on top. The indoor constant is taken **directly from retail**: `CellManager::ChangePosition` (0x004559B0) calls `SmartBox::SetWorldAmbientLight(0.2f, 0xFFFFFFFF)` whenever `CObjCell::seen_outside == 0`. The early-2026 guess at `(0.10, 0.09, 0.08)` was eyeballed; the retail value is both brighter and neutral. See §12 for the C# class.
|
||||
|
||||
## 4. Torch lights and `WeenieType.LightSource`
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue