import type { Mat4 } from "../math/Mat4" import type { Camera } from "../scene/Camera" import type { RenderConfig } from "./RenderConfig" import type { RenderInstance, RenderScene } from "./RenderScene" export type RenderWorkerInit = { colorSAB: SharedArrayBuffer depthSAB: SharedArrayBuffer width: number height: number scene: RenderScene band: [number, number] config: RenderConfig skyStep: number ctrlSAB: SharedArrayBuffer cameraSAB: SharedArrayBuffer viewProjectionSAB: SharedArrayBuffer visibleChunkSAB: SharedArrayBuffer instanceIdSAB: SharedArrayBuffer instanceTransformSAB: SharedArrayBuffer timesSAB: SharedArrayBuffer workerIndex: number } export type RenderFrameCamera = { camera: Camera time: number } /** Shared frame-buffer layout used by browser driver and render workers. */ export namespace RenderProtocol { export const FRAME = 0 export const DONE = 1 export const VISIBLE_CHUNKS = 2 export const VISIBLE_INSTANCES = 3 export const CONTROL_LENGTH = 4 export const CAMERA_X = 0 export const CAMERA_Y = 1 export const CAMERA_Z = 2 export const CAMERA_YAW = 3 export const CAMERA_PITCH = 4 export const CAMERA_FOV = 5 export const CAMERA_TIME = 6 export const CAMERA_LENGTH = 7 export const VIEW_PROJECTION_LENGTH = 16 export const TRANSFORM_FLOATS = 5 export function writeCamera( output: Float64Array, camera: Camera, time: number, ): void { output[CAMERA_X] = camera.position.x output[CAMERA_Y] = camera.position.y output[CAMERA_Z] = camera.position.z output[CAMERA_YAW] = camera.yaw output[CAMERA_PITCH] = camera.pitch output[CAMERA_FOV] = camera.fov output[CAMERA_TIME] = time } export function readCamera(input: Float64Array): RenderFrameCamera { return { camera: { position: { x: input[CAMERA_X], y: input[CAMERA_Y], z: input[CAMERA_Z], }, yaw: input[CAMERA_YAW], pitch: input[CAMERA_PITCH], fov: input[CAMERA_FOV], }, time: input[CAMERA_TIME], } } export function writeViewProjection( output: Float32Array, viewProjection: Mat4, ): void { output.set(viewProjection) } export function writeInstances( ids: Int32Array, transforms: Float32Array, instances: RenderInstance[], ): number { const count = Math.min(instances.length, ids.length) for (let i = 0; i < count; i++) { const instance = instances[i] const offset = i * TRANSFORM_FLOATS ids[i] = instance.prototype transforms[offset] = instance.x transforms[offset + 1] = instance.y transforms[offset + 2] = instance.z transforms[offset + 3] = instance.heading transforms[offset + 4] = instance.scale } return count } export function readInstances( ids: Int32Array, transforms: Float32Array, count: number, output: RenderInstance[], ): void { output.length = 0 for (let i = 0; i < count; i++) { const offset = i * TRANSFORM_FLOATS output.push({ prototype: ids[i], x: transforms[offset], y: transforms[offset + 1], z: transforms[offset + 2], heading: transforms[offset + 3], scale: transforms[offset + 4], }) } } }