Phone Chrome without EXT_color_buffer_float returned null with one message. Rendering to
RGBA16F only needs EXT_color_buffer_half_float, and every other target is already a half, so
only the prepass start (RGBA32F) needed a fallback. In half mode the prepass writes
t*(1-2^-10) - 2^-15, which stays below t after the half rounds to nearest, so pass 1 still
starts at or before the true distance. W_FAR stays exact. onUnavailable names no-webgl2 vs
neither float extension; Scene.startFormat and options.halfStart (force, for tests and the
harness). The standalone page shows the reason, renderer, vendor, UA and extension list.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Soul pass on 87c9ca60: the R8 steps read used the default PACK_ALIGNMENT of 4, so
at widths not divisible by 4 the buffer was too small (readPixels fails) and padding
would be summed. Portrait runs read 0 steps/pixel. The prepass step now divides by
1.0006 so pass 1's tolerance, which grows with t, stays clear at the end of the step.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
trace: steps per pixel and pass ms at three fixed camera poses, PREPASS=0,1 arms.
diff: one frozen frame with and without the prepass, against a 512-step render.
bundle.cjs demo: full-window page with a prepass switch and the readout.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Pass 0 marches one ray per 8x8 tile of pass 1, each step shrunk by the widest
any ray of the tile strays from it, and stores the distance no ray of the tile
can have hit before (W_FAR when the whole tile climbs out above the highest
geometry). Pass 1 starts from it. The distance bound moves to sdf.glsl so both
passes step by the same function.
onTraceStats adds a step-count render target to pass 1 and reads it back every
8th frame through a pixel-pack buffer and fence, outside the timed span. Unset,
neither the output nor the target exists. prepass:false is the baseline.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The client's own SHARED_POSES/MIND_POSES lists and the committed webp art are gone.
catalogue.json (cast-art poses/catalogue.json, synced by npm run sync:poses) is the
only list of Minds, labels and art paths. RoomViewPoseStatus draws "Ratatoskr:
<Mind> is <pose>, since HH:MM" from the loaded timeline; it is never sent to a room.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
NeutralFrame drops size alongside kind and energy; the reader ignores a size a producer sends on a neutral frame, and a live frame without a valid size is malformed. The human kind subset (Idle/Working/Speaking) stays PROVISIONAL, still proposed.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
world.ts already carries Libby's 7.0 (CultLib PR #1 990521b3); the comment now
states the 6.63 sup was measured, not proved.
creatures.ts follows creature-projection-v2: a neutral creature publishes no
sizeBucket, and one that arrives is ignored. creatureScale returns null (draw
nothing) for neutral, absent or unknown buckets; it never defaults to medium.
NEUTRAL_SCALE is removed.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A neutral frame yields no kind and no energy: nothing drawn, nothing sounded, never an
Idle. For a non-neutral human, a kind outside {Idle, Working, Speaking} or omitted becomes
Idle and Peak reads as High. Minds and personas keep all seven kinds. The subset is
provisional until Bifrost's steward cuts the list.
Cites heimdall-body:follow_up:ratatoskr-creature-projection-v2.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- matchMedia 'change' listener freezes/thaws a running scene; removed on dispose and context loss
- startBackgroundScene catches a failed scene chunk import: onCompileFail, null, no throw
- shaderSource compiles each stage with only the CultMath declarations it reaches
(cultmathTrim.ts); Phacelle stays a separate file, terrain only
- README: 'still' is a live rendered frame
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Reads the grammar frame (AquaSynth docs/soundscape-grammar.md @ aeae510) into a
per-mind table, plans voices (neutral overrides all, Muted, cap, master mute,
weak-device off) and the drawn set. No activity source exists yet
(ratatoskr❓activity-feed-source) and no audio assets, so nothing sounds.
Cites heimdall-body:follow_up:ratatoskr-creature-projection-v2.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Header names heimdall-body/ratatoskr-creature-projection, the shape,
invariants and consent rule, and marks the bucket scales as placeholders.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Fixes the 21 eslint errors and 2 tsc errors Void's review found in
features/scene (WORLD.phacelleGradBound is typed number, not the literal 7).
Adds the contract the host needs: client config backgroundScene.tier as flag and
ceiling (off by default, lowered by saveData / memory / cores), lazy
startBackgroundScene, still and low tiers, onCompileFail (createScene frees
linked programs and returns null), webglcontextlost handling, and creatureScale
where neutral overrides sizeBucket. Scene.ts gets its first tests, on a fake GL.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Reads org.gamecult.pose from event content for senders that are known
Minds; unknown or missing labels fall back to neutral. Portrait sits
beside the bubble on wide screens and stacks above it on phones.
84 downscaled webp portraits (7 Minds x 12 poses, ~415 KB).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Sky rays were ~90% of pass 1 (noSkyMarch variant: 292 -> 26 ms, SwiftShader 960x540 L0).
terrainDistance now returns early where the plateau mask is 0 (height exactly 0), skipping
fbm and Phacelle there: pass 1 292 -> 159 ms, same step values. skyColor keeps one sun term
(the wide glow is gone; screenshots differ by that and by TAA/time, not compared pixelwise).
Harness: noSkyMarch variant, ONLY=<names> selects variants.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Libby measured sup |grad| 6.63 at |side| = 1.5, n = 0 (CultLib PR #1 head
990521b3); 7.0 adds margin. The shader passes roughness 0 as a literal, so no
1/(1-n) factor is needed; the comment records it. Pass 1 under SwiftShader:
terrain 288.8 ms vs 287.5 at 960x540 level 0, 75.3 vs 75.7 at level 3 (noise).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
RoomTombstone, RoomIntro and the lobby RoomItem/SpaceItem joined with mx.joinRoom
beside the pre-join filing; they now call joinEstateRoomOrThrow, which delegates
to the one path. /join hands each refusal to the user instead of discarding it.
Tests pin the via pass-through and the 400/429/499 refusal bounds.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Pass 1 sphere-traces CultMath noise terrain (fbm plus Phacelle erosion) and the
world tree with a conservative Lipschitz step, writing colour and depth. Pass 2
marches fog and clouds only up to that depth at low resolution with TAA. The
camera pulls back from the tree on login. Vendors CultLib's generated GLSL
(658c09e). The Phacelle gradient bound is an empirical probe, not a proof.
Headless harness compiles, renders and times it; nothing run on a GPU.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The room card's Join (deep links, permalinks, history) and /join joined
through mx.joinRoom and never filed the DM. They now go through
activateEstateRoom. A gateway 5xx, or a status with no errcode, has an unknown
outcome like a dropped connection: the entry stays and the tap is retryable.
The harness gains Soul's s6 deeplink and gw504 drives.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>