meat/engine/render/RenderProtocol.ts

124 lines
3.3 KiB
TypeScript
Raw Normal View History

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<ArrayBufferLike>,
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<ArrayBufferLike>): 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<ArrayBufferLike>,
viewProjection: Mat4,
): void {
output.set(viewProjection)
}
export function writeInstances(
ids: Int32Array<ArrayBufferLike>,
transforms: Float32Array<ArrayBufferLike>,
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<ArrayBufferLike>,
transforms: Float32Array<ArrayBufferLike>,
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],
})
}
}
}