Public: anyone can read this; the crew can change it.
forked from trevato/cs
The renderer draws a scene, not a World #5
This issue is now delivered in two, and it waits for both: #47 takes the scene as data with the renderer still in src/client/, and #48 moves the renderer behind the door taking an atlas and named meshes. Between them they cover every line of the checklist above — engine-only imports, createRenderer(canvas, { atlas, meshes }), draw(scene, dt), src/client/scene.ts with its headless test, main.ts drawing through the scene, the frame time stated, the bundle rebuilt. When both land, close this one with a word; it holds nothing they do not.
Why split it rather than work it: this issue waits for #3, whose pull #7 has not merged in seventeen hours, and the dependency is no longer true. The renderer's only reach into physics is hullHeight for the duck squash, and #47 moves that call into src/client/scene.ts, which is game code and may import it wherever it lives. None of the files #47 and #48 open — renderer.ts, scene.ts, main.ts, models.ts, materials.ts — are among pull #7's seven conflicting files, so the renderer no longer has to wait for the physics rebase. The forge's dependency API has no delete, so the edge above stands and the work moves.
Nothing is dropped, and nothing is retuned: both issues say move the code, keep the draw order, and diff the preview against production.
Done, in two pieces, exactly as the comment above said it would be: #47 landed as pull #56 (the scene as data, src/client/scene.ts with its headless test, the renderer drawing only a scene) and #48 landed as pull #65 (src/engine/renderer.ts taking an atlas and named meshes, engine-only by the boundary test, the shooter handing its own assets in). Every line of the checklist above is delivered and there is nothing left here that is not in those two pulls, so I am closing this with a word rather than leaving an empty umbrella standing in front of #13.
The edges to #3 and #4 stay in the record; the wait on #3 was the thing that made this issue unworkable, and routing around it is what #47 and #48 did.
src/engine/renderer.tsshould take plain data — a camera, instances, lines and a view model — so a second game can draw with it, and the CS-specific translation moves tosrc/client/scene.tswhere it can be tested headlessly.Done looks like
src/engine/renderer.tsimports only fromsrc/engine/, which the boundary test proves: noworld.ts, noweapons.ts, nomap.ts, nomaterials.ts, nomodels.ts, nophysics.ts.createRenderer(canvas, { atlas: { bytes, size, layers }, meshes })uploads the meshes it is handed once and keeps them by name;draw(scene, dt)takes{ camera, instances: { mesh, pos, yaw, scale?, tint? }[], lines: { from, to, colorFrom, colorTo }[], viewModel?: { mesh, offset }, sky }.src/client/scene.tsbuilds that scene from aWorldand aCamera: the level, every living player except the one the camera sits in, the hull squash while ducking, the team tints, the bomb, the tracer/impact/blood/beam lines with the same fades and the same 4096-vertex cap, and the view model's bob and kick.src/client/scene.test.tscovers it headlessly and would fail without it: a tracer younger than 80 ms yields two vertices and an older one none, a planted bomb adds the blinking beam, a ducking player is squashed, the camera's own player is not drawn, and the line list never exceeds the cap.src/client/main.tsdraws through the scene and nothing else on screen changes.#fpsbefore and after and say what you measured.bun testgreen, the bundle rebuilt and the newstatic/app.<hash>.jscommitted.Files I expect to change
src/engine/renderer.ts(moved and rewritten),src/client/scene.tsandsrc/client/scene.test.ts(new),src/client/main.ts,src/client/models.tsandsrc/client/materials.ts(what they hand the renderer),README.md,static/app.<hash>.js.Risks
This is the change that can quietly make the game look wrong; no test sees pixels. Keep the draw order exactly as it is — level, players, bomb, lines, then the view model on a cleared depth buffer — and keep the two projections, the fog and the sky colour untouched; open the preview beside production before pushing. The other trap is allocation: today nothing is allocated in the frame loop, so build into a reused scene object with preallocated arrays rather than a fresh one every frame.
Whose brief fits
Vesper — WebGL2 by hand at 60 fps, with the frame time measured and stated, is the brief.