Public: anyone can read this; the crew can change it.
forked from trevato/cs · proposes · 4 behind
The renderer moves behind the door: src/engine/renderer.ts takes an atlas and named meshes #65
Check · Review · Land · Live done — Landed and live in production.
Pushed. Both commits are on the branch and `bun test` is green (415 pass).
shipped production is serving it deploy ae07c2d
Sign in to join this conversation.
new above
offline
Pushed. Both commits are on the branch and
bun testis green (415 pass).---
The WebGL2 moves to
src/engine/renderer.tsunchanged — same two programs, same uniforms, same culling, same near/far planes, same draw order — and takes what it used to reach for as data:createRenderer(canvas, { atlas: { bytes, size, layers }, meshes, sky, devicePixelRatio })uploads the array texture and every named mesh once at construction and keeps them by name, so a frame does no upload at all.Scene,CameraandInstancemove behind the door with it;src/client/scene.tsis now the engine's frame plus the two things this game remembers between frames,src/client/main.tshands inmaterialTextures()/TEX_SIZE/LAYERSand all eight meshes frommodels.ts, andsrc/client/renderer.tsis gone rather than left as a re-export. The diff worth reading isgit show 8cc8a81 -- src/engine/renderer.tsagainst the deleted file: outside the types and the asset plumbing, nothing in the GL sequence moved.src/engine/renderer.test.tsdrives the module with a stub context that only writes down what it was asked for — the same trickoverlay.test.tsplays withPaint— and checks one texture and one buffer set per mesh handed in, nobufferData/texImage3Din a frame, one vertex-array bind for two instances of one mesh and two for two meshes, the clamped device pixel ratio, lines drawn in pairs, the view model's own depth clear, andnullwhen the surface gives nowebgl2.main.test.tsgains a test ongameMeshes(), because the renderer resolving nothing means a name that table misses is an exception on the frame a player first holds that gun.Three places where the move is not literal, all deliberate: the device pixel ratio arrives as a function instead of the engine reading
window(sameMath.min(dpr, 2)clamp, so the same pixels);skyis optional on both the assets and theScene, so a game whose horizon never changes says it once — the shooter still writes it every frame and also passes it at construction, so nothing about its colour changed; and a mesh name nobody handed in throws on the first frame that asks for it rather than at construction, since only a scene knows which names it will use — construction is where the atlas is checked (size * size * 4 * layers, refused before a context is even requested, with both numbers in the message).What I could not do here: there is no browser or GPU in this sandbox, so the
#fpsreading before and after and the 360px/1920px comparison against production are a reviewer's checks on the preview, not claims I am making — please do them. What I can measure: the golden digest and the range's pin are untouched and green, the eight meshes cost about 2 ms to build at start-up (the atlas beside them is ~120 ms, exactly as before), and the app bundle is 70,558 raw / 32,850 gzipped against a 75,400 / 34,900 ceiling, whilestatic/range.*.jsis unchanged at 12,548 bytes — the range imports the door and none of the WebGL2 behind it, which is the tree-shaking doing its job.GUIDE.mdgains the renderer's paragraph and two quoted lines, and the README's engine list gains the module.🤖 Generated with Claude Code
Closes #48