docs(overhaul): contract issue 469 lighting ownership
This commit is contained in:
parent
2f1e625fea
commit
8098875240
3 changed files with 174 additions and 10 deletions
|
|
@ -2687,3 +2687,168 @@ frame. High retains the separately registered #469 lighting-direction shift;
|
|||
that known blocker is neither waived nor attributed to #470. #470 changes no
|
||||
retail-visible policy and requires no divergence-register row. Next is #469,
|
||||
then S5-c5, closeout, and G4. Nothing has merged to `main`.
|
||||
|
||||
## 31. S5-#469 contract — keep retail world lighting stable across the opt-in shadow gate
|
||||
|
||||
### 31.1 Lead-recovered retail and binary boundary
|
||||
|
||||
Issue #469 is not an ambiguous art-direction choice. Retail owns exactly one
|
||||
outdoor directional-light channel, authored by `SkyTimeOfDay`; the atmospheric
|
||||
pack's visible sun/moon choice is an acdream-only shadow-projection input and
|
||||
must not replace that lighting channel.
|
||||
|
||||
The lead re-read the named retail decomp and its verbatim type header before
|
||||
writing this contract:
|
||||
|
||||
- `SkyTimeOfDay` contains `dir_bright`, `dir_heading`, `dir_pitch`, and
|
||||
`dir_color` (`acclient.h` lines 53124–53137).
|
||||
- `SkyDesc::GetLighting @0x00500A80` interpolates those fields between the two
|
||||
surrounding authored time-of-day records, constructs one directional vector,
|
||||
and returns one directional colour.
|
||||
- `LScape::set_landscape_lighting @0x005054D0` copies that vector and colour to
|
||||
`LScape::sunlight` and then `Render::world_lights.sunlight`; it has no shadow-
|
||||
gate or celestial-mesh selection input.
|
||||
- `PrimD3DRender::UpdateLightsInternal @0x0059AED0`, specifically
|
||||
`0x0059B4ED–0x0059B5CE`, derives the D3D sunlight colour and direction from
|
||||
that same `Render::world_lights.sunlight`. It does not replace the direction
|
||||
when any drawing feature is enabled or disabled.
|
||||
|
||||
The paired executable was independently verified again with
|
||||
`tools/pdb-extract/check_exe_pdb.py`: `C:\Users\erikn\Downloads\acclient.exe`
|
||||
is PE32 v11.4186, whole-file SHA-256
|
||||
`006FFEADC5D679C871497112A5BD1F87714D0E273E2166BAE5052DDE369297B1`, CodeView
|
||||
GUID `{9E847E2F-777C-4BD9-886C-22256BB87F32}`, age 1, and matches
|
||||
`C:\Users\erikn\source\repos\acdream\refs\acclient.pdb`. Exact function-range
|
||||
SHA-256 anchors are:
|
||||
|
||||
| Function | File range | Bytes | SHA-256 |
|
||||
|---|---:|---:|---|
|
||||
| `SkyDesc::GetLighting` | `0x00100A80..0x00100CDF` | 608 | `9D82E8EDDBD66C52DBD3F08D07D661482DB545C4F513E81AB4F16E4EDF410188` |
|
||||
| `LScape::set_landscape_lighting` | `0x001054D0..0x0010565F` | 400 | `DF3FD816845AE0F6E2423442A325CE43A44A8204E1B857D7674BBB8F4640D0CB` |
|
||||
| `PrimD3DRender::UpdateLightsInternal` | `0x0019AED0..0x0019B5DF` | 1,808 | `E18FD7AD9A8EB819AB9602D25DE5D1BB99FADD1D439B35140E443EB1E0437F84` |
|
||||
|
||||
This agrees with the pre-existing static source study
|
||||
`docs/research/2026-08-22-dereth-celestial-shadow-sources.md`: celestial meshes
|
||||
supply only the opt-in shadow **direction**; colour and energy remain retail's
|
||||
single authored channel; existing retail scene lighting remains driven by
|
||||
`SkyStateProvider`.
|
||||
|
||||
The current atmospheric receiver shaders violate that declared boundary.
|
||||
When shadow flag bit 0 is clear they use the plain pipeline's authored
|
||||
`-uLights[].dirAndRange.xyz`; when it is set they abruptly use normalized
|
||||
`uShadowLightDirectionAndSource.xyz`. Shadow strength is blended later, so this
|
||||
binary vertex-light switch produces the whole-world relight captured in both
|
||||
the exact parent and S5-c2 candidate A/Bs. It is not absent shadow work and it
|
||||
is not caused by S5-c2.
|
||||
|
||||
### 31.2 Bounded production repair and IA-24 correction
|
||||
|
||||
Restore one stable lighting owner in both atmospheric vertex receivers:
|
||||
|
||||
1. `mesh_atmospheric.vert` computes every outdoor directional-light `Ldir`
|
||||
with the exact plain-mesh expression `-uLights[i].dirAndRange.xyz` in every
|
||||
shadow-gate state. Preserve its unnormalized value and its per-light loop.
|
||||
2. `terrain_atmospheric.vert` computes `surfaceToLight` with the exact plain-
|
||||
terrain expression `-uLights[0].dirAndRange.xyz` in every shadow-gate state.
|
||||
Preserve `MIN_FACTOR`, authored colour/energy, and the split directional
|
||||
varying used by the fragment receiver.
|
||||
3. Delete the obsolete `shadowGatedOff` branches and replace their comments
|
||||
with the retail ownership above.
|
||||
4. Keep `uShadowLightDirectionAndSource` unchanged for cascade projection,
|
||||
receiver depth/bias/PCF, and atmospheric volumetrics. The optional shadows
|
||||
may therefore be geometrically directed at the selected visible celestial
|
||||
source while the receiver's base lighting remains the authored retail
|
||||
direction. That separation is deliberate and was already the original
|
||||
IA-24 research boundary.
|
||||
5. Recompile the committed shader set and update only the generated atmospheric
|
||||
vertex SPIR-V and manifest/hash entries required by those source changes.
|
||||
6. Amend IA-24 in the **same implementation commit**: remove its statement that
|
||||
receiver lighting switches to the celestial direction while shadows render;
|
||||
state instead that authored `uLights` remains the sole base-light direction
|
||||
in every gate state, while the selected celestial source drives only the
|
||||
opt-in shadow/volumetric projection. Explicitly record the possible visual
|
||||
light/shadow-angle separation as the cost of preserving retail lighting and
|
||||
eliminating the binary relight. This is the required deviation-register
|
||||
update; add no second row.
|
||||
|
||||
Do not change `SceneLighting`, `SkyStateProvider`, the celestial-source
|
||||
resolver or its sun/moon priority, shadow strength/fades, cascade matrices,
|
||||
shadow caster selection, receiver binding/descriptor ABI, fragment shadow
|
||||
lookup, PCF/bias, volumetric policy, render-pack selection, plain shaders,
|
||||
materials, fog, tone mapping, colour/energy, terrain `MIN_FACTOR`, indoor
|
||||
lighting, point/spot lights, visibility, geometry, package recipe, or any
|
||||
unrelated renderer. Do not normalize the authored direction, blend the two
|
||||
directions, invent another runtime state owner, hide the switch behind a
|
||||
threshold, or add per-frame work/allocation. If any wider production change is
|
||||
needed, stop and return the exact dependency before expanding scope.
|
||||
|
||||
Allowed production scope is the two atmospheric vertex shader sources, their
|
||||
regenerated SPIR-V/manifest pins, and the IA-24 row. Tests may add only the
|
||||
smallest structural and real-shader proof below. The implementer changes no
|
||||
packet, plan, issue, package, gate artifact, architecture text outside IA-24,
|
||||
or campaign memory.
|
||||
|
||||
### 31.3 Discriminating proof, mutations, and return
|
||||
|
||||
Permanent proof must establish both halves of the boundary rather than merely
|
||||
matching a copied CPU formula:
|
||||
|
||||
1. compile and inspect the committed production atmospheric vertex SPIR-V and
|
||||
prove mesh and terrain take their diffuse-light direction only from the
|
||||
corresponding authored `uLights` member, with the exact unnormalized plain-
|
||||
shader expressions and no shadow-flag/celestial-direction selection;
|
||||
2. exercise the committed production atmospheric receiver shaders in a real
|
||||
offscreen Vulkan pixel witness for both mesh and terrain. Holding authored
|
||||
light/material/geometry constant while toggling only shadow flag and
|
||||
celestial direction must leave the unshadowed base directional-light result
|
||||
invariant; choose inputs for which the pre-fix branch gives a different
|
||||
pixel. The witness is explicitly `Lane=Vulkan`, uses the existing dedicated
|
||||
lavapipe/local lane, and fails rather than skips when that lane lacks Vulkan;
|
||||
3. prove the committed fragment receiver and volumetric shaders still consume
|
||||
`uShadowLightDirectionAndSource` for opt-in shadow projection/bias/visibility,
|
||||
so the repair cannot silently disable or redirect shadows;
|
||||
4. prove active and inactive receiver states still select/bind the same
|
||||
atmospheric/plain pipelines and descriptors as before;
|
||||
5. pin that neither plain shader source/SPIR-V nor any pipeline-selection or
|
||||
renderer source changed from the contract parent; and
|
||||
6. read the live IA-24 row and fail if it again claims celestial direction owns
|
||||
base receiver lighting or omits the explicit light/shadow separation.
|
||||
|
||||
Apply and independently restore at least these mutations, recording the first
|
||||
discriminating failure for each in the implementation commit body:
|
||||
|
||||
1. restore the shadow-flag/celestial-direction branch in
|
||||
`mesh_atmospheric.vert`;
|
||||
2. restore it in `terrain_atmospheric.vert`;
|
||||
3. normalize either authored vertex-light direction;
|
||||
4. redirect a fragment shadow/volumetric use from the celestial source to the
|
||||
authored light, or remove its celestial-source read; and
|
||||
5. restore IA-24's old assertion that pack-active base lighting follows the
|
||||
celestial source.
|
||||
|
||||
Return one clean implementation commit atop this contract; exact changed-file
|
||||
and line counts; all mutation first failures; both `git diff --check` forms;
|
||||
exact shader compiler command and generated hashes; the dedicated physical
|
||||
`Lane=Vulkan` result; focused atmospheric shader/receiver/manifest/source-
|
||||
resolver tests; Release solution build with zero warnings/errors; official
|
||||
hermetic lane; and canonical-inclusive InstalledDat with every accepted
|
||||
nonpassing identity named. Recipe 10 and prepared content are unchanged, so no
|
||||
bake is required. No graphical client launch.
|
||||
|
||||
Review is sequential. Retail/deviation pass 1/10 first verifies the three
|
||||
named-retail functions and paired bytes, the stable authored-light rule, IA-24
|
||||
truth, pack-off preservation, and that the pixel/structural tests actually fail
|
||||
on both old branches. Only after PASS does production/gate-honesty pass 2/10
|
||||
inspect the complete source-to-SPIR-V-to-pipeline path, run the real Vulkan
|
||||
witness, reproduce at least mutations 1–4, and rule on portable/dedicated-lane
|
||||
ownership and full gate sufficiency. A failed pass receives one bounded fix
|
||||
contract. The owner-authorized ceiling is ten review passes. Nothing lands or
|
||||
launches graphically before both lenses pass.
|
||||
|
||||
After landing, the lead repeats the exact fixed-pose retail/off -> High ->
|
||||
retail/off plus dusk transition used to file #469, with Release green, a clean
|
||||
tree, UDP/client preflight, one background command, and graceful self-owned
|
||||
shutdown. PASS requires no whole-world base-light jump as shadow work gates,
|
||||
while pack-active shadow direction/visibility still changes and the final
|
||||
retail frame restores. Record exact PNG paths; the result remains provisional
|
||||
until owner inspection.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue