Log inGet started

renderer

The renderer namespace — the engine's Luau API reference for renderer.

The renderer namespace — 40 functions.

globals/renderer/destroy

globals/renderer/destroy(handle: any) -> boolean

Free the GPU resource behind a MeshHandle / TextureHandle (the GPU-destroy verb). Routes by the handle's category. The on-disk asset, if any, is untouched. A CPU handle's :unload() frees the CPU copy separately.

globals/renderer/feature/create

globals/renderer/feature.create(ref: any, guid: string?) -> any

Instantiate a render feature so the engine calls its render(ctx) hook every frame. ref is an AssetRef<renderFeature> whose init.luau returns { setup?, render, teardown? }. Returns a live RenderFeatureHandle (its guid is the stable id, same as mesh/texture handles); tear it down with renderer:destroy(handle). Pass guid to assign a specific id.

globals/renderer/feature/destroy

globals/renderer/feature.destroy(handleOrGuid: any) -> boolean

Tear down a live render feature by its RenderFeatureHandle OR its guid string — the by-id path for when the handle was lost (e.g. across execute calls). Same effect as renderer.destroy(handle). Returns true if a feature was live under that id.

globals/renderer/feature/list

globals/renderer/feature.list() -> { { guid: string, identity: string } }

List every render feature currently live (running its render(ctx) each frame). Each entry is { guid, identity } — the guid is the same id a RenderFeatureHandle carries, so you can tear a feature down by guid even after losing its handle (e.g. across separate execute calls).

globals/renderer/getRaytrace

globals/renderer/getRaytrace() -> boolean

Whether ray tracing is currently enabled.

globals/renderer/mainCameraView

globals/renderer/mainCameraView() -> { number }?

The main camera's inverse view-projection (column-major, 16 numbers) followed by its world position (3 numbers) — {m0..m15, px,py,pz} — for reconstructing world positions from the depth buffer in a ray-tracing pass. Nil before the first render.

globals/renderer/material/create

globals/renderer/material.create(content: MaterialContent, key: string) -> MaterialHandle

Register (or update) a material's GPU resource under key and return its MaterialHandle. content = { shader, properties, textures, aliases?, render? }. The referenced textures must already be GPU-resident (the material assetType materialises each slot via texRef:handle() before calling this) — this only files the shader+property+texture-slot record the renderer binds. Mirrors renderer.mesh.create / renderer.texture.create; idempotent upsert by key. render sets pipeline render-state (cull / depthWrite / blend) — e.g. { cull = "front", depthWrite = false } for an inverted-hull outline program.

globals/renderer/material/describe

globals/renderer/material.describe(key: string) -> any

The recoverable definition ({ shader, properties, textures, name }) this module registered under key via renderer.material.create, or nil for keys registered elsewhere (e.g. material assets resolved by the assetType).

globals/renderer/material/destroy

globals/renderer/material.destroy(key: string) -> boolean

Drop a runtime material registered via renderer.material.create: clears its recoverable definition, unregisters its runtime-resource stamp so it is no longer swept into the material freeze/save flow, and frees the GPU record. Use for transient materials (e.g. a preview swatch) that must not outlive their use. The on-disk asset, if any, is untouched.

globals/renderer/material/setProperty

globals/renderer/material.setProperty(key: string, name: string, value: any) -> ()

Push one changed uniform property to a registered material's GPU record (frame-fast incremental update; no re-register). Keyed by the material's registry key.

globals/renderer/material/setTexture

globals/renderer/material.setTexture(key: string, slot: string, ref: string) -> ()

Push one changed texture slot to a registered material's GPU record. The texture must already be GPU-resident (materialise it with texRef:handle() first). Keyed by the material's registry key.

globals/renderer/mesh/buildClusters

globals/renderer/mesh.buildClusters(guid: string) -> string?

Build a cluster-LOD DAG (Nanite-style virtualized geometry) for the static CPU mesh held under guid and return its serialized data.clusters bytes. The native offline bake; returns nil when the mesh is degenerate or the platform has no builder (the cross-platform runtime consumes pre-baked clusters). Pair with renderer.mesh.uploadClusters.

globals/renderer/mesh/clusterComponents

globals/renderer/mesh.clusterComponents(clusterBytes: string) -> (ClusterComponents?, string?)

Split a cluster blob (from renderer.mesh.buildClusters) into its GPU-ready component byte pools — the cluster vertex pool, the u32 index pool, and the per-cluster record array — plus their counts. A pure decode (no GPU work): upload the pools to compute buffers (compute.createBuffer + compute.writeBufferBytes) to drive a cluster draw from Luau.

globals/renderer/mesh/create

globals/renderer/mesh.create(src: any, guid: string?) -> MeshHandle

Create (or fetch) a GPU mesh resource and return its MeshHandle. src: a MeshCpuHandle from meshRef:load() (CPU→GPU upload under the asset's guid, idempotent — returns the resident handle if already uploaded); raw geometry {positions, indices, normals?, uvs?, colors?} (a new runtime mesh); GPU compute buffers {vertexBuffer, indexBuffer, vertexCount, indexCount, aabbMin?, aabbMax?}; or a MeshHandle (returned as-is). NEVER takes an AssetRef — load the CPU first.

globals/renderer/mesh/decode

globals/renderer/mesh.decode(zmsh: string) -> (MeshGeometry?, string?)

Decode engine-native ZMSH bytes back into geometry { positions, indices, normals?, uvs?, colors? }. Inverse of renderer.mesh.encode.

globals/renderer/mesh/encode

globals/renderer/mesh.encode(geom: MeshGeometry) -> string?

Encode raw geometry into engine-native ZMSH bytes (the on-disk mesh payload). The CPU codec behind the mesh assetType's onCreate.

globals/renderer/mesh/encodeCpu

globals/renderer/mesh.encodeCpu(guid: string) -> string

Encode the CPU mesh resident under guid into ZMSH bytes. Reads the ONE guid-keyed CPU store — meshRef:load() populates it for assets, and renderer.mesh.readback(guid) populates it for a runtime mesh. Errors loudly when no CPU mesh is resident under the guid.

globals/renderer/mesh/getVertices

globals/renderer/mesh.getVertices(guid: string) -> { any }

Read the vertices of the CPU mesh resident under guid — one entry per vertex, { pos = {x,y,z}, normal = {x,y,z}, uv = {u,v} }. Reads the resident CPU store directly (no re-decode). Errors when no CPU mesh is resident under the guid — load it (meshRef:load()) or retain it (keepCpu) first.

globals/renderer/mesh/isCpuResident

globals/renderer/mesh.isCpuResident(guid: string) -> boolean

True if a CPU mesh is resident under guid in the guid-keyed CPU store.

globals/renderer/mesh/isResident

globals/renderer/mesh.isResident(guid: string) -> boolean

True if a GPU mesh is resident under guid.

globals/renderer/mesh/loadCpu

globals/renderer/mesh.loadCpu(ref: any) -> MeshCpuHandle

Load a .mesh asset's geometry into the ONE guid-keyed CPU store (the Disk→CPU step) and return a CPU handle. The handle holds NO geometry — only the guid plus counts and the per-handle read/encode/unload ops (which read the Rust-side store). Called by meshRef:load(). DEFAULT lifecycle: upload to the GPU then handle:unload(); the store is populated only by this call.

globals/renderer/mesh/readback

globals/renderer/mesh.readback(guid: string) -> MeshCpuHandle

Read a runtime GPU mesh's geometry back to CPU and return a MeshCpuHandle for it — the GPU→CPU half of the runtime-mesh freeze path. A mesh made with renderer.mesh.create keeps no CPU copy, so persisting it (:encode()asset.create("mesh", …)) reads it back here first. Yields until the readback completes (a frame or two). After it returns the geometry is resident in the guid-keyed CPU store: :getTriangles, :getVertices, :getBounds, :encode, :unload all work. Errors if no GPU mesh is resident in the vertex pool under guid.

globals/renderer/mesh/setVertices

globals/renderer/mesh.setVertices(guid: string, positions: { number })

Replace the resident CPU mesh's vertex positions (flat { x,y,z, ... }) under guid, IN PLACE — indices, normals/uvs, and skinning are preserved, the AABB recomputes, and the GPU re-fetches the new geometry so it shows on screen. The mesh must be CPU-resident (load it, or retain it with keepCpu). Errors with the reason otherwise, or when the vertex count doesn't match.

globals/renderer/mesh/unloadCpu

globals/renderer/mesh.unloadCpu(guid: string)

Drop the CPU mesh resident under guid from the guid-keyed CPU store. The explicit release for a runtime geometry mesh's recoverable definition.

globals/renderer/mesh/update

globals/renderer/mesh.update(handle: MeshHandle, src: any) -> MeshHandle

Overwrite the GPU resource behind handle IN PLACE, under the same guid, from new geometry or compute buffers. Never writes a .mesh file — the play-mode mutate path. A Model bound to handle.guid reflects the change with no re-bind. Returns the same handle with refreshed bounds.

globals/renderer/mesh/uploadClusters

globals/renderer/mesh.uploadClusters(guid: string, clusters: string) -> boolean

Attach a cluster-LOD DAG (bytes from renderer.mesh.buildClusters) to the GPU mesh keyed by guid, enabling the continuous-cut cluster draw path for that mesh.

globals/renderer/raytraceCapability

globals/renderer/raytraceCapability() -> string

The active ray-tracing backend: "hardware" (GPU ray query) or "compute" (software traversal — the path on devices without hardware ray query, e.g. the web). The same ray-tracing features work on both.

globals/renderer/setRaytrace

globals/renderer/setRaytrace(enabled: boolean) -> ()

Enable or disable GPU ray tracing. While enabled the engine builds the scene acceleration structure each frame so ray-tracing render features can trace against it; disabling stops the build (so it costs nothing until a ray-traced effect is active). Required before any ray-traced shadows / AO / reflections render.

globals/renderer/texture/capture

globals/renderer/texture.capture(handle: TextureHandle) -> string

Request a CPU readback of the GPU texture behind handle (e.g. a camera's rendered output). Returns a result key to pass to a TextureCpuHandle's :encode() once the readback completes.

globals/renderer/texture/cpuCreate

globals/renderer/texture.cpuCreate(width: number, height: number, fill: any?) -> TextureCpuHandle

Allocate a blank CPU image (RGBA8) filled with a solid colour and return a TextureCpuHandle. Compose into it with canvas:blit(src, x, y, w, h), then canvas:encodeJpeg() / :encodePng() for the bytes; :unload() drops it.

globals/renderer/texture/create

globals/renderer/texture.create(src: any, guid: string?) -> TextureHandle

Create (or fetch) a GPU texture resource and return its TextureHandle. src: a TextureCpuHandle from texRef:load() (CPU→GPU under the asset's guid, idempotent); raw pixels {rgba, width, height, srgb?} (a flat widthheight4 byte buffer, 0-255, row-major, top-to-bottom, RGBA); a TextureHandle (returned as-is); or render-target dimensions {width, height, name?} with no pixel source — an empty GPU texture a render pass writes into (camera output, UI surface) and that samples like any other texture. NEVER takes an AssetRef — load the CPU first.

globals/renderer/texture/decode

globals/renderer/texture.decode(ztex: string) -> (any, any, any)

Decode an engine-native ZTEX payload to RGBA8 pixels.

globals/renderer/texture/destroy

globals/renderer/texture.destroy(handle: TextureHandle)

Release the GPU texture behind handle. For an empty render-into texture (camera output, UI surface) this also frees its render scratch; for an uploaded runtime texture it drops the GPU resource (and any CPU shadow).

globals/renderer/texture/encode

globals/renderer/texture.encode(rgba: any, width: number, height: number, opts: any) -> (string?, string?)

Encode raw RGBA8 pixels into an engine-native ZTEX payload (the on-disk texture content). The CPU codec behind the texture assetType's onCreate.

globals/renderer/texture/encodeFromImage

globals/renderer/texture.encodeFromImage(bytes: string, opts: any) -> (string?, string?)

Encode source image bytes (png/jpg/webp/…) into an engine-native ZTEX payload. Used by the texture importer / assetType onChange.

globals/renderer/texture/info

globals/renderer/texture.info(ztex: string) -> (any, any)

Read the header of an engine-native ZTEX payload without copying the pixels. Returns its format, dimensions, mip count, and filter ("nearest" or "linear" — the sampler baked into the blob from the asset's settings.filter).

globals/renderer/texture/isResident

globals/renderer/texture.isResident(guid: string) -> boolean

True if a GPU texture is resident under guid.

globals/renderer/texture/loadCpu

globals/renderer/texture.loadCpu(ref: any, encodeOpts: any?) -> TextureCpuHandle

Load a .texture asset's pixels into the ONE guid-keyed CPU store (the Disk→CPU step) and return a CPU handle for per-pixel access (no GPU readback). The handle holds NO pixels — only the guid plus dims and the read/write/encode/unload ops (which read the Rust store). Called by texRef:load(). DEFAULT: upload to the GPU then handle:unload().

globals/renderer/texture/readback

globals/renderer/texture.readback(guid: string) -> TextureCpuHandle

Read a runtime GPU texture's pixels back to CPU and return a TextureCpuHandle for them — the GPU→CPU half of the runtime-texture freeze path. A texture made with renderer.texture.create keeps no CPU copy, so persisting it (:encode()asset.create("texture", …)) reads it back here first. Yields until the readback completes (a frame or two). After it returns the pixels are resident in the guid-keyed CPU store: :readPixel, :writePixel, :getInfo, :encode, :unload all work. Errors if no GPU texture is resident under guid.

globals/renderer/texture/update

globals/renderer/texture.update(handle: TextureHandle, src: any) -> TextureHandle

Overwrite the GPU texture behind handle IN PLACE, under the same guid, from new raw pixels. Never writes a .texture file — the play-mode mutate path. Returns the same handle (refreshed dims).

  • api
  • reference