Skip to content

fix(platformer): visible waterfall and own gradient sky; core reports PMREM-size and ignored-opacity traps - #491

Merged
jonit-dev merged 11 commits into
developfrom
fix/platformer-sky-waterfall
Oct 12, 2026
Merged

jonit-dev merged 11 commits into
developfrom
fix/platformer-sky-waterfall

Conversation

@jonit-dev

Copy link
Copy Markdown
Contributor

TL;DR: The platformer (fox game) gets visible waterfalls and its own stylized gradient sky in place of the leaked Poly Haven photo. Its lighting stays the same as before. Core now reports the two silent three.js traps behind these bugs, so CI fails if they come back.

Why

The owner reported two platformer bugs: the waterfall did not render correctly, and a default photo skybox had leaked into the kit.

Symptom Root cause Layer
Waterfall is a thin sliver under foam blobs flat() in render/materials.ts passed opacity without transparent: true. three then draws the sheet opaque. With depthWrite: false, it drew first (front-to-back sort) and the cliff behind painted over it. Gem shine and the fox blob shadow had the same bug. game
Photo skybox in a toon kit PRD-470 (#376) put the shared Poly Haven sky.jpg in every kit. The original sandbox fox game used a blue gradient dome. Only platformer changes here. The other kits keep the photo, as PRD-470 decided. game
(found on the way) Shaded faces near-black with a procedural sky three r185 WebGPU PMREMGenerator sizes its cube from equirect.width / 4. An 8 px gradient gave a 2 px cube, below LOD_MIN 4, so the environment was empty. engine guard
(found on the way) 404 /assets.manifest.json in an asset-free game The web build wrote no manifest when a project has no assets/, but the core loader always fetches it. engine
flowchart LR
  G[gradientColor rows] --> BG[skyTexture 256x128 8-bit sRGB<br/>scene.background]
  G --> ENV[skyEnvironment 256x128 half-float<br/>scene.environment]
  M[measured photo fill<br/>upper 0.355,0.423,0.627<br/>lower 0.680,0.670,0.633] --> ENV
Loading

What changed

  • platformer render/materials.ts: flat() sets transparent when opacity < 1.
  • platformer render/sky.ts + new render/skyEnvironment.ts: the background is a stylized gradient. The environment is a separate texture whose hemisphere means match the photo's measured fill. This keeps the lighting the kit was tuned under: gold coins stay gold and rock stays warm. sky.jpg no longer ships with the kit (a scaffold test asserts this).
  • assets compile.ts: an asset-free project gets { version: 1, entries: {} }. core assets.ts: an empty manifest falls back like a missing one, so public/ files still load verbatim.
  • core new profiling/render-trap-audit.ts, run once per scene entry: TN_ENVIRONMENT_TOO_SMALL (equirect environment narrower than 64 px) and TN_OPACITY_IGNORED (visible material with opacity < 1 and no transparent/alphaHash). Both go to console.error, so every scenario with noConsoleErrors fails. Golden-path runs those on CI. CI drops pixel scenarios on software adapters, which is why no gate saw these bugs.

Evidence

  • Visual judge (fresh read-only subagent, real GPU: Intel gen-9 WebGPU, headed, 2 runs per arm, 3 poses): IMPROVEMENT on 6/6 frames, overall IMPROVEMENT, no lighting regression. A first attempt was judged IMPROVEMENT but flagged olive coins and blue-grey rock. That was fixed by the measured environment, then judged again by a new judge.
  • Guardrail red-green on the CI-run move.playtest.json (TN_PLAYTEST_ALLOW_SOFTWARE=1, as CI): flat() without transparent reports TN_OPACITY_IGNORED; an 8 px environment reports TN_ENVIRONMENT_TOO_SMALL; the fixed build reports neither. Locally, all three runs also exit 1 on SwiftShader createBuffer device loss, a known local-lane problem. CI's golden-path is the authoritative green.
  • Unit: render-trap-audit.spec.ts 16 pass (red first); core asset/manifest specs 67 pass; looks.spec.ts + scaffold.spec.ts 87 pass; empty-manifest compile spec red 4 → green 4; empty-manifest loader spec red → green.
  • Scaffolded platformer: build:web 0 errors, typecheck 0 errors, 0 console/network errors on real GPU.
  • Known pre-existing reds, same on base e6ed27869: template-assets-compile-2 shooter cases, the build.spec.ts audio-worker 60 s timeout, and the recast-bundle 15 s timeout.

Screenshots (BEFORE top, AFTER bottom, real GPU)

spawn run 1
mid run 1
spawn run 2
mid run 2

Rejected first attempt (gradient used as light: olive coins, cool rock):
rejected attempt
coins attempt 1 vs final

Far poses and the BEFORE waterfall zoom are on the platformer-sky-waterfall-screenshots branch.

Not done / limits

  • The audit runs at scene entry only. Content streamed in after entry is not audited (the foliage warning has a second, ready-time pass; this audit does not).
  • Not run: native desktop/Android lanes for the platformer, and the full pnpm test. CI covers these.
  • Other kits keep the photo sky. Whether racing (part toon) should also lose it is an open owner question.

@jonit-dev
jonit-dev enabled auto-merge October 11, 2026 21:34
@jonit-dev jonit-dev added prd:100% prd:100% — ready PRD complete, ready to merge and removed prd:100% labels Oct 11, 2026
Guard the render-trap audit against creating or mutating appearance while allowing
its read-only diagnostics. Expect empty manifests in receipt cleanup and the shared
template compiler check, matching the asset-free compiler contract.

Verification: 38 core/asset contract tests and the platformer compile case pass.
@jonit-dev
jonit-dev added this pull request to the merge queue Oct 12, 2026
Merged via the queue into develop with commit 35139bd Oct 12, 2026
107 of 120 checks passed
@jonit-dev

Copy link
Copy Markdown
Contributor Author

Screenshots: BEFORE (top) vs AFTER (bottom), real GPU (Intel gen-9, WebGPU, headed)

Two independent runs per arm, three poses. A fresh read-only visual judge rated IMPROVEMENT on 6 of 6 frames, with no lighting regression. All images are on the platformer-sky-waterfall-screenshots branch.

Run 1

spawn run 1
mid run 1
far run 1

Run 2

spawn run 2
mid run 2
far run 2

BEFORE waterfall, zoomed

before waterfall zoom

Rejected first attempt (gradient used as the light: olive coins, cool rock) vs final

rejected attempt spawn
rejected attempt coins
coins attempt 1 vs final

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

prd:100% — ready PRD complete, ready to merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant