refactor: move world concepts into engine

This commit is contained in:
Toad 2026-08-24 15:17:53 +02:00
parent eeedcb8e48
commit 2d15c7ab8d
52 changed files with 3298 additions and 1558 deletions

View file

@ -1,35 +1,12 @@
import type { Framebuffer } from "../engine/render/Framebuffer"
import type { RenderConfig } from "../engine/render/RenderConfig"
import { MOB_KINDS } from "../game/actors/Mob"
import { renderBand, MOB_FLOATS, type MobDraw, type Scene } from "../game/renderScene"
/** One-time setup: shared framebuffer + control/param buffers, the (cloned)
* scene, this worker's row band, and its index into the per-worker times array. */
type Init = {
colorSAB: SharedArrayBuffer
depthSAB: SharedArrayBuffer
width: number
height: number
scene: Scene
band: [number, number]
config: RenderConfig
skyStep: number
ctrlSAB: SharedArrayBuffer
camSAB: SharedArrayBuffer
vpSAB: SharedArrayBuffer
visSAB: SharedArrayBuffer
mobSAB: SharedArrayBuffer
timesSAB: SharedArrayBuffer
index: number
}
const FRAME = 0
const DONE = 1
const VIS = 2
const MOBVIS = 3
import { RenderProtocol, type RenderWorkerInit } from "../engine/render/RenderProtocol"
import { RenderScene, type RenderInstance } from "../engine/render/RenderScene"
const ctx = globalThis as unknown as {
addEventListener: (type: "message", handler: (e: { data: Init }) => void) => void
addEventListener: (
type: "message",
handler: (e: { data: RenderWorkerInit }) => void,
) => void
}
ctx.addEventListener("message", (e) => {
@ -41,31 +18,46 @@ ctx.addEventListener("message", (e) => {
depth: new Float32Array(m.depthSAB),
}
const ctrl = new Int32Array(m.ctrlSAB)
const cam = new Float64Array(m.camSAB)
const vp = new Float32Array(m.vpSAB)
const vis = new Int32Array(m.visSAB)
const mob = new Float32Array(m.mobSAB)
const cameraData = new Float64Array(m.cameraSAB)
const viewProjection = new Float32Array(m.viewProjectionSAB)
const visibleChunks = new Int32Array(m.visibleChunkSAB)
const instanceIds = new Int32Array(m.instanceIdSAB)
const instanceTransforms = new Float32Array(m.instanceTransformSAB)
const times = new Float64Array(m.timesSAB)
const { scene, band, config, skyStep, index } = m
const { scene, band, config, skyStep, workerIndex } = m
const instances: RenderInstance[] = []
// Lock-free frame loop: block until main bumps the frame counter, render this
// band, record the band time, and signal done. No messages per frame.
let last = 0
for (;;) {
Atomics.wait(ctrl, FRAME, last)
last = Atomics.load(ctrl, FRAME)
Atomics.wait(ctrl, RenderProtocol.FRAME, last)
last = Atomics.load(ctrl, RenderProtocol.FRAME)
const t0 = performance.now()
const camera = { position: { x: cam[0], y: cam[1], z: cam[2] }, yaw: cam[3], pitch: cam[4], fov: cam[5] }
const count = Atomics.load(ctrl, VIS)
const visible = [...vis.subarray(0, count)]
const mobCount = Atomics.load(ctrl, MOBVIS)
const mobDraws: MobDraw[] = []
for (let i = 0; i < mobCount; i++) {
const o = i * MOB_FLOATS
mobDraws.push({ kind: MOB_KINDS[mob[o]] ?? "frog", x: mob[o + 1], y: mob[o + 2], z: mob[o + 3], heading: mob[o + 4], scale: mob[o + 5] })
}
renderBand(fb, scene, camera, vp, visible, mobDraws, config, skyStep, cam[6], band[0], band[1])
times[index] = performance.now() - t0
Atomics.add(ctrl, DONE, 1)
const frameCamera = RenderProtocol.readCamera(cameraData)
const count = Atomics.load(ctrl, RenderProtocol.VISIBLE_CHUNKS)
const visible = [...visibleChunks.subarray(0, count)]
const instanceCount = Atomics.load(ctrl, RenderProtocol.VISIBLE_INSTANCES)
RenderProtocol.readInstances(
instanceIds,
instanceTransforms,
instanceCount,
instances,
)
RenderScene.renderBand(
fb,
scene,
frameCamera.camera,
viewProjection,
visible,
instances,
config,
skyStep,
frameCamera.time,
band[0],
band[1],
)
times[workerIndex] = performance.now() - t0
Atomics.add(ctrl, RenderProtocol.DONE, 1)
}
})