Draw tfrag per-vertex colour, unlit, and record why the frame is dark

The tfrag RGBA array now modulates the texture. It is indexed by
*position*, not by vertex-info: several vertex-info entries can share a
position, and the array is sized vert_count, which is a position count.

Colour follows the same rule as the vertex itself. Morphing blends the
position only -- the game keeps the high-detail colour -- while collapse
replaces the vertex outright, colour included. Getting that the other way
round would tint distant terrain.

The material is unlit, and that is a decision rather than a shortcut.
Level 0's colours really are dark (patch 0 runs (25,26,26) to
(108,144,141)) and the game's lighting is what brightens them, so what is
on screen is the true albedo.

Worth recording: the obvious move -- add a directional light, or crank
ambient brightness -- does nothing at all. With no normals the PBR path
is degenerate, so the brightness change has no effect, and a host light
would have hidden the gap rather than shown it. The colour data was
always reaching the mesh; what is missing is lighting, not a material
flag.

Written up in plan/level-assets.md, including what LightTfrags actually
needs: the light bank from the level's gameplay extent, the 256-entry
normal table at BOOT_NORMAL_TABLE_VADDR (0x165500) which every level
overlay carries, and the already-parsed azimuth/elevation light records.
This commit is contained in:
2026-10-10 03:02:52 +02:00
parent 192dcde247
commit 17c7e8ccc9
4 changed files with 79 additions and 7 deletions
+10 -2
View File
@@ -31,8 +31,16 @@ early, while they are still cheap to retire.
passed: the vertex count matched, the triangle count matched, only the
*place* was wrong. Fixed by taking the STROW immediately preceding the
first position unpack rather than the last one.
- [ ] Next: the per-vertex light records, which is why the first frame is flat
and dark. Then the GS register set and the guard-band clip test.
- [x] **Per-vertex colour.** The tfrag's RGBA array now modulates the texture,
drawn unlit so the frame shows real albedo rather than a faked lighting
model. Verified against the stored values (level 0 patch 0 runs
`(25,26,26)` to `(108,144,141)`), which are genuinely dark.
- [ ] **tfrag lighting.** Needs the level light bank from `gameplay`, the
256-entry normal table from the overlay ELF at `0x165500`, and the
already-parsed azimuth/elevation light records. The pass itself is
`base + A*max(dA, dA*wA) + B*max(dB, dB*wB)` and has to run in the PS2
float model. Detail in `plan/level-assets.md`.
- [ ] Then the GS register set and the guard-band clip test.
The disc being the exact build the reference projects pin is the single
biggest favourable fact so far: no disc conversion, no regional timing work,