Skip to main content
Every HLSL module of @native/gpu and every scene material can include it. Nothing is read from disk: includes only resolve to built-in headers. The prelude also defines LOCATION(n) for vertex inputs and GPU_D3D11 or GPU_D3D12, whichever the overlay runs on.

Camera

Bind device.frame.camera to a GPU_CAMERA and read it like a struct:
The camera includes the game’s TAA jitter, so your draws line up with the engine’s. Don’t declare the matrices row_major: mul(M, v) is already the right product.

Spaces and depth

frame.sceneDepth, worldDepth and solidDepth hold post-projection depth, 0 near and 1 far, cleared to 1. It’s the same value SV_Position.z has in your own draws.

Draw parameters

D3D starts SV_VertexID and SV_InstanceID at 0 for every draw. WebGPU’s numbering includes the draw’s first vertex (or base vertex) and first instance. To get it in HLSL:
register(b0, space4) is reserved for this. WGSL doesn’t need it.

Poses

Every player skinned this frame, from the opaque hook on. pass.drawPose binds them as vertex buffers; bound as read-only storage, you read them yourself.
Pose positions end up in scene space: project with camera.sceneViewProj, or convert with GpuSceneToGame.

Models

What device.importModel loads: 80 bytes per vertex, bind pose, game space.
GpuLoadModelVertex(buffer, index) reads one from a storage buffer. As a vertex buffer, use the model’s vertexLayout.

Map

frame.worldVertices is float3 positions in scene space, frame.worldIndices is a uint32 triangle list. They are vertex and index buffers; copy them into a buffer of your own to read them in a compute shader.

Smokes

Game space. A voxel is a box of GPU_SMOKE_VOXEL_HALF (60, 60, 30) around its center, and they overlap a lot: treat them as “smoke is somewhere around here”, not as the cloud’s exact shape. GpuLoadSmokeVoxel(smokeVoxels, index) and GpuLoadSmoke(smokeTable, cloud) read them. In WGSL: