THE WIZARD'S
LIBRARY
A screenshot record of a Blender-built Gothic hall and its Three.js adaptation: a candlelit aisle, timber galleries, a globe, a spiral stair, and cold light beyond the great window.
View screenshots screenshots and development notes · interactive demo retired
Keep the authored room.
Change the rendering contract.
The browser version is not a panoramic render wrapped around a camera. The owner-supplied Blender scene was exported as 27 material-batched meshes with 27 materials, while book colors remain stable through vertex color. Baked base color, AO, roughness, metallic, and tangent-normal channels carry the procedural surface work into the realtime asset.
Five Blender views—hero, gallery, stair, entrance, and desk—became regression anchors for camera position, focal intent, and exposure. They keep the same spatial reading while the browser adds its own walk camera, collision bounds, local light management, WebAudio, and deterministic comparison hooks.
Warm knowledge within.
Cold daylight beyond.
The room is organized around one long Gothic axis: reading tables and scattered papers at ground level, book walls and pointed stone bays at the sides, timber galleries above, then chandeliers, blue-gold banners, a globe, and a spiral stair breaking the repetition. Candlelight holds the wood and brass in warm pools while the great window stays deliberately pale and cool.
Three.js r170 renders the scene through AgX and OutputPass. A PMREM interior reflection environment, fog, a bright exterior portal, eight resident structural lights, and a nearest-neighbour candle pool reinterpret the authored lighting without pretending to reproduce Cycles. The archived build used a 2048 static sun shadow and 12 local lights; the diagnostic high profile restores the 4096 shadow, 24-light pool, restrained Bloom, and DPR 2 framing used by the earlier comparison path. The realtime build has no multi-bounce GI, volumetric shafts, or the desk camera's f/2.4 depth of field.

Pixels were expensive.
They were not the whole story.
The earlier hardware A/B proved that DPR 2 was expensive, but an M2 Max report showed that v34 had not gone far enough. A static comparison with Spaceship exposed the rest of the frame path: this library carries 1.93 million triangles, 3.16 million vertex slots, room-spanning double-sided material batches, and far more realtime point lights. Version 35 therefore starts at a 0.85 internal ratio with no scene MSAA, 12 nearest local lights, a 2048 static shadow, no Bloom, and standard depth so dense shelving can use early-Z again; it adapts through 0.7 and 0.6, caps active work at 60 FPS, and stops full rendering behind the menu, after Esc, and in hidden tabs. Version 36 keeps that cheaper backing buffer but separates it from layout: the canvas always fills the iframe, while a container observer resizes the renderer, composer, and camera whenever the embedded frame grows. Balanced, high, logarithmic-depth, and original-texture query fallbacks remain available for diagnosis.
- Process-tree PSS: 2150.4 → 669.6 MiB at DPR 2
- Process-tree RSS: 2428.7 → 939.8 MiB at DPR 2
- Ready: 10567 → 9597 ms for original → 1K/512 KTX2 at DPR 2
- Historical KTX2 frame-rate A/B: 60.18 FPS at DPR 1 / 4× MSAA; 33.59 FPS at DPR 2
- v35 live profile: 0.85 → 0.7 → 0.6 / 0× MSAA / 12 local lights / 2048 static shadow / no Bloom
- Idle menu, Esc release, hidden tabs, and BFCache no longer run the full scene loop
- WebGL context loss now stops RAF before Three can continue on an invalid precision result
- v36 viewport: full-size canvas CSS + container ResizeObserver; adaptive DPR changes only the backing buffer
- DPR 2 shadows: 33.59 FPS static; 30.19 FPS continuously updated
- Frozen static/continuous comparison frame: AE=0 and RMSE=0, with zero recorded runtime errors
The FPS figures above are the prior hardware baseline that isolated DPR; they do not claim a fresh browser measurement for v36 or an M2 Max result. AE=0 / RMSE=0 compares the frozen static-shadow and continuously updated shadow screenshots at the same DPR 2 camera. It does not compare Three.js against Blender or Cycles, and it is not a claim of pixel equivalence. Version 36 passed source, mock, lint, and build checks under the current no-browser boundary; its visual and live-frame verification remains pending.