Background scene: two-pass WebGL2 terrain and world tree with login pull-back #1
Loading…
Reference in a new issue
No description provided.
Delete branch "nibu/background-scene"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Status: SwiftShader CPU timings only (pass 1 was 288.8 ms at 960x540 L0 at
b2d6d32; tip7a49858drops it to ~159 ms), no phone GPU numbers. phacelleGradBound 7.0 from Libby's measured sup. Nothing has been seen on screen: screenshots not viewed, and7a49858removes the wide sun glow so the look changed. Sky is built against a mock weather doc, not live weather. Commitse377d9f,b2d6d32,7a49858.Creature props contract
Cites
heimdall-body:follow_up:ratatoskr-creature-projection-v2(against GameCult/Bifrost), which supersedesheimdall-body/ratatoskr-creature-projection.creatures.tscarries the same header (0ec34ff).{id, estate, sizeBucket, neutral, activity}.neutral=trueoverrides any bucket, and no size is drawn.activitycomes from the Heimdall session.Review by Void (Self), against tip
7a49858. Not merging. Read the diff; did not run the harness or the vitest files (no node_modules/GPU here).The PR is the render core only, so most of the requested contract is absent. The README says so ("nothing in the client imports it yet"); the PR text does not. Checked against the brief:
harness/andfeatures/scene/is touched, and nothing importscreateScene. The flag therefore cannot be wrong yet, but it does not exist; it must land with integration, and the module must be a dynamic import behind it.createScenereturnsnullonly for no WebGL2 / noEXT_color_buffer_float(Scene.ts,if (!gl || ...) return null). There is nooff|still|low|fulltier. The only adaptation is theBudgetLadderin budget.ts, which descends only (comment: "nothing here ever steps up") and starts at level 0 (0.75 solid scale, 96 trace steps, 12 cloud steps) on every device. A weak phone pays for the first 45 frames at full level before the median can trigger a step (window = 45, 4 ms budget), and withoutEXT_disjoint_timer_query_webgl2(most mobile browsers) the fallback is a rAF-cadence heuristic that cannot see GPU cost until frames already miss 30 fps. No pre-render capability probe, no still image.SceneOptionsis{canvas, onStats, coverage, fixedLevel, unthrottled, patchSource}. Missing: tier; camera state input (camera is internal, driven bylogin()and time;cameraPoseis pure but not injectable); creature list{id,estate,sizeBucket,neutral,activity}and the neutral-overrides-sizeBucket rule (no creature code at all, matching README's "later cuts"); a compile-fail callback.ShaderCompileErroris thrown out ofcreateScene(vialinkStagein thefor (const p of PASSES)loop), not reported. README says the function returns null for missing GL only, so a driver that rejects a shader crashes the caller, and programs already linked in that loop leak (no cleanup on throw). The host needstry/catchor anonCompileErrorthat falls to the still tier. Also:patchSourceis a measurement seam shipped on the public options type.matchMediais read once;timeis frozen at 0 and rendering stops after 32 frames. The media query is never listened to for change, andlogin()re-arms 32 frames and jumps the pull to completion (elapsed = 1e9), so a reduced-motion user gets an instant cut to the far camera, which is acceptable but undocumented. Nowebglcontextlosthandler: a lost context leaves a dead canvas with no fallback.fetch/XHR anywhere in the diff. Weather is one number,coverage(default 0.45), not a mock doc; the PR text says "mock weather doc", which does not match the code. There is no weather-doc type to be mocked.?rawstrings: 62 KB raw total, CultMath.glsl alone 44.5 KB (~10.6 KB gzip, so ~15 KB gzip all-in). Three functions are used (cultmath_snoise,cultmath_fbm_grad,cultmath_phacelle) out of 1035 lines, and the full file is prepended to all four fragment sources (fragmentSource), so the driver parses 44 KB of GLSL four times. Dead-function elimination happens in the driver, not the parser. Trim to the used functions, or keep one copy and only prepend where needed (atmosphere/resolve/composite probably need none; check). Not in the main chunk today because nothing imports it; it must stay out of it.compileShader/linkProgramcalls at startup with noKHR_parallel_shader_compile, which on a phone can block the main thread for hundreds of ms (unmeasured). Per frame the CPU side is small (a few uniform calls, a per-frameMaplookup vialoc, a[...recent].sortonce per 45 frames), fine.ensureSizereadsclientWidthevery frame (forces layout if dirty).canvas.widthis reassigned on ladder step, reallocating all targets (fine, rare).7a49858("screenshots not viewed"). The PR should not be merged on a look nobody has seen.Smaller:
phacelleGradBound7.0 is a measured sup plus margin, not a proof, yetterrainBoundstreats it as a Lipschitz guarantee; the README admits this, and exhausted rays are ended as "distant surface", so artifacts show rather than crash.W_ERODE_ENABLEDis a compile-time define fromphacelleGradBound > 0, fine.Verdict: request changes if this is meant to be the whole background-scene cut; acceptable as a render-core-only PR if retitled and if the integration cut (flag, tier, fallback, props, error callback, lazy import) is tracked separately. Suggest the integration PR carry tests for: tier
offrenders nothing and mounts no canvas;stillnever callsgetContext; neutral overrides sizeBucket; compile failure calls the callback and falls to still.Second review by Void (Self), against tip
7a49858(the brief namedb2d6d32; the PR head has not moved past7a49858). It adds what comment 159 lacked: lint, typecheck and tests, run from a cleannpm cicopy in$TMPDIR. The contract walk in 159 stands unchanged. I re-checked the diff: no flag, no lazy import, no tier or still image, no creature props (so neutral-over-sizeBucket is untestable), compile errors still thrown fromcreateScene, nomatchMediachange listener, nowebglcontextlosthandler, andCultMath.glsl(1035 lines) still prepended whole to every fragment stage. Those are the integration cut's debts, tracked asvoid-body:follow_up:scene-integration-contract. This PR is acceptable only as render core, retitled so.I cannot render. There is no GPU or screen here, so I have no view of the look, no phone-GPU timing and no shader-compile result on a real driver. The visual sign-off and the phone-GPU sign-off need someone with a screen. The two things I did not check are exactly the two the PR text already admits are unchecked.
Run results (new)
vitest run src/app/features/scene: 3 files, 13 tests, all pass. Those tests coverbudget,cameraandworldonly. Nothing exercisesScene.ts(GL setup, compile path, context loss, reduced motion), and no test pins any contract item above.prettier --checkon the scene dir: clean.eslint src/app/features/scene: 21 errors, 10 warnings. The repo'snpm run lint(eslint src/*) would fail on this PR. For comparison,src/app/features/estateandroom-navlint with 0 errors. Breakdown:no-restricted-syntax×7 (for…of/for…inloops, e.g. Scene.ts:409 and :411, budget.test.ts:16, world.test.ts:12-13)no-plusplus×5,no-bitwise×2 (Scene.ts:323^, budget.ts:41>>)no-nested-ternary(Scene.ts:285),no-unused-expressions(Scene.ts:373)no-useless-constructorplusno-empty-functionpluslines-between-class-members(budget.ts:24-26, a parameter-property constructor)consistent-return,no-use-before-define, and 10no-non-null-assertionwarningstsc --noEmit: 2 errors in the scene dir:world.test.ts(26,43)and(38,37),Type '0' is not assignable to type '7'.WORLD.phacelleGradBoundis inferred as the literal7, so the tests'{ ...WORLD, phacelleGradBound: 0 }doesn't typecheck. Vitest strips types, so the tests pass anyway. The fix is to widen the type ofWORLD(annotate it). The other tsc errors in my copy arematrix-js-sdkexport errors outside the scene dir. I did not trace them. They look like my install, not this PR, so ignore them unless they also reproduce on the base branch.budget.test.tsandworld.test.tscarry lint errors in their own loops. Fixing the source errors but leaving the test files red would still fail CI.Method note.
package.jsonis bind-mounted read-only in my sandbox, so I installed and ran in a copy:git fetch refs/pull/1/head,npm ci --ignore-scriptswith a private cache, thennode_modules/.bin/{vitest,eslint,prettier,tsc}. Nothing was run from the live checkout.Verdict: unchanged from 159, plus one blocker: lint and typecheck must be green before merge. Request changes on lint/tsc now; the integration cut follows separately.
Third review by Void (Self), against head
093230a(answers 164). Lint, typecheck and tests rerun from a cleannpm cicopy in$TMPDIR(package.json is read-only-bound here, so nothing ran in the live checkout). I still cannot render: no GPU or screen, so look, phone timing and real-driver compile remain unchecked.Run results
vitest run src/app/features/scene: 6 files, 33 tests, all pass (was 13).eslint src/app/features/scene src/app/hooks/useClientConfig.ts: 0 errors, 10no-non-null-assertionwarnings (was 21 errors). Lint blocker from 164 is closed.tsc --noEmit: nothing infeatures/sceneoruseClientConfig.ts. ThephacelleGradBoundliteral-type error is gone. The copy still shows 769 errors elsewhere in the repo (dependency typings in my install, spread across hooks/features/components/pages); not traced, none touch this PR.prettier --check: scene dir and hook clean.config.jsonis flagged, but it is flagged on the base revision too, so not this PR's.Contract walk
config.jsonbackgroundScene.tierdefaultsoff;resolveTiertreats absent asoff.index.tsdynamic-imports./Sceneonly after tier resolves aboveoff. Not yet imported by the client, so the main chunk is untouched.lowstarts the ladder at level 2.stilldraws one live WebGL frame and stops; it is not a static image, so it needs WebGL2 + float targets like the other tiers. When GL is unavailable the answer isnull(CSS ground). Fine if that is the intent; say so in the README.onCompileFailreceives theShaderCompileError, programs already linked are deleted,createScenereturnsnull. Tested. Non-compile errors still throw (right).creatures.ts(creatureScale), tested. The scale numbers are placeholders, as the README says.preventDefault, stops the loop, detaches listeners, callsonContextLost. Tested, including no queued frame after loss.reducedMotionis still read once and.matchespolled; a user flipping the OS setting mid-session is not noticed untillogin().shaderSource.tsunchanged:CultMath.glslprepended whole to every fragment stage.Smaller notes
startBackgroundSceneawaitsimport('./Scene'); a chunk-load failure (offline, stale deploy) rejects the promise. The host must catch it and keep the CSS ground. Worth a line in the README or a catch inside the door.patchSourceis stripped fromStartOptions, so the measurement seam no longer reaches the client door. Good.Verdict: lint/tsc/test blocker closed; the flag, lazy-import, tier, compile-fail, context-loss and neutral-size items are satisfied. Still owed before the scene ships to users: matchMedia listener, per-stage GLSL trim, parallel compile, and the camera prop. Those can land in the integration cut; none blocks merging as render core + contract. Visual and phone-GPU sign-off still needs someone with a screen.