f81d5218d498a4f8480f9fe54e8c0812cd9bb78f
3 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
3c4649d078 |
fix: make the app boot on an insecure origin, and re-aim the capture harness
Three things, all found by trying to re-shoot the product imagery and failing.
**`crypto.randomUUID` is secure-context only.** `main.ts` called it at module top
level for its three wire identities, so on any origin that is not HTTPS and not
`localhost` the call threw before the scene was built and the app stopped at
"Starting up" with one TypeError and no other symptom. Every way a developer
normally opens this app is a secure context — `vite dev` and `vite preview` serve
localhost, the deployed site is HTTPS — which is why this survived since
|
||
|
|
0cc2126e85 |
The capture harness uses the graphics card that was there all along
`launch()` asks for `--use-angle=vulkan` and gets the Radeon RX 6700 XT. On the real film loop at 1440x900 that is 7.56 s a frame to 0.47, and about twelve cores pegged down to less than one. A 180-frame film goes from twenty-two minutes to ninety seconds; the three shipped reels go from over an hour to four minutes. The SwiftShader flag was inherited from the share-card script and its comment said "a box with no display and no GPU". Half of that was never true. The card has been in this machine the whole time, with the amdgpu driver and a working RADV ICD, and Chrome reaches it with **no display server at all** — no DISPLAY, no XDG_RUNTIME_DIR, nothing but read access to /dev/dri/renderD128, which group `render` already grants. So the portability the flag was protecting is intact: this still runs over ssh and under cron. Naming the backend is the whole trick, and most of the plausible spellings are traps. `--use-angle=gl`, `--use-gl=egl`, `--use-gl=desktop`, `--enable-features=Vulkan` and passing no GL flags at all were each measured on this box, and all five land on SwiftShader while reporting success. Only `--use-angle=vulkan` and `--use-angle=gl-egl` reach the card. So `launch()` verifies instead of assuming. `--use-angle=vulkan` is a demand, not a preference: with the driver hidden it yields no WebGL context at all rather than falling back, the boot curtain never lifts, and the caller sits in `waitForFunction` until a three-minute timeout before failing with something that looks nothing like "there is no GPU here". Reading `UNMASKED_RENDERER_WEBGL` once per run costs about half a second and turns that into a printed line and a slow, correct render. Both branches are tested; the sabotaged one was verified with `VK_LOADER_DRIVERS_DISABLE`. The pictures are the same pictures: mean absolute difference of half a level out of 255, confined to MSAA edges and to cloud shadow that already drifts between any two runs of the same renderer. Also corrects every comment across the four scripts that asserted three frames a second or twenty-two minutes a reel. Those were true when written and are not now, and the `reducedMotion` rationale in two of them was resting on the number: the real reason a chapter flight cannot be waited out is that it is ~40 frames however fast they are drawn, which was twenty seconds under software GL and is a shorter race on the GPU — still a race. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
d71e844703 |
The engine gets photographed, and the camera stops moving while the shutter is open
`shots.mjs` renders the product imagery for lumbridgecorp.com/simulate: seven frames of the running `dist/`, at chapters and times chosen rather than defaulted, written as WebP into the sibling site checkout together with a generated manifest that carries each picture's caption and alt text. The pages there had described a renderer in prose for their whole life without ever showing one, which is a strange way to sell a renderer. The captions live next to the camera poses in this repo, not on the site, so re-aiming a camera cannot leave a caption behind describing the old view. The manifest emits a `ShotId` union, so a page asking for a picture that has been renamed fails the site's typecheck instead of rendering a hole. Along the way: the share cards were never reproducible. `scenekit.ts` eases a chapter change over about two seconds of scene time, `stage.ts` clamps `dt` to 50 ms a frame, and SwiftShader here draws about three frames a second — so the flight takes twenty seconds of wall clock and `capture.mjs` waited four. Every run caught the camera at a different point over the bay, and none of them at the chapter the key press asked for. Both scripts now open the page with reduced motion, which is the app's own answer to "somebody clicked a name in a list": `flyTo` sets the pose outright. `og-tera.png` is regenerated and is Hayes Valley for the first time. The bytes still differ run to run, because aircraft are crossing and cloud shadow is drifting; the framing no longer does. `harness.mjs` is the static server, the SwiftShader flags, the two-hostnames- one-dist trick and the clock shim, extracted because there are two consumers now and two copies would have drifted apart while both claimed to photograph the same app. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |