Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Shader Graph

A material can go beyond the fixed PBR set through a shader graph: a closed, loop-free node graph compiled host-side into WGSL. A script or asset can never supply raw shader text. Every graph is built from a fixed set of node kinds (Add, Lerp, Fresnel, TextureSample, and others), and each node references only earlier nodes in the same network, so a cycle cannot be constructed and cost is bounded before the graph runs: at most 128 nodes and 4 texture samples per network.

Structure

A graph has two independent networks. The surface network computes the fragment-stage look, either Lit (feeding a standard PBR pass) or Unlit (written straight to the output, for beams, holograms, and other emissive looks a lighting pass cannot produce). The optional displacement network computes a vertex-stage position or normal offset, for effects like curved beams or billboarding.

Public Inputs

A graph exposes up to 16 public inputs — values a prim can override per-instance without recompiling the graph. Two prims can share one compiled graph and still look different, and because the compiled material:graph_data bytes are identical between them, they dedupe in the blob store regardless of how many prims use them.

Authoring

A graph is written as an .hss (Hyper-Space Shader) file and referenced from a prim’s material_graph attribute in .hsda:

// glow.hss — an unlit rim glow, tinted by public input 0
(
    public_inputs: [Color((0.1, 0.6, 1.0, 1.0))],
    surface: (
        nodes: [
            Fresnel(power: Const(Float(2.0))),
            Lerp(a: Const(Color((0.0, 0.0, 0.0, 1.0))), b: Input(0), t: Node(0)),
        ],
        output: Unlit((color: Node(1))),
    ),
)
// asset.hsda — this prim overrides input 0 to red
(attributes: (name: "red_glow", material_graph: (
    path: "./glow.hss",
    overrides: {0: Color((1.0, 0.0, 0.0, 1.0))},
)))