Log inGet started

Shader module (asset type)

A .shaderModule is a block of WGSL that other shaders include rather than copy — a lighting model, a set of colour-space helpers, one package's shared prelude. It declares no entry point and is never…

Folder shape

<name>.shaderModule/
  module.wgsl        # the WGSL — helpers, structs, constants (required)
  README.md          # what THIS module provides (required)

Each file carries a committed .meta sidecar pinning its stable guid, and the folder carries one of its own.

Including one

A shader names a module by identity, and the identity is what records the dependency — so a shader that is packed, pulled or published carries the modules it includes with it:

#include "~.colour"                         // a module in the same package
#include "@builtin::shaderModules.pbr_shading"      // one from the builtin library

A missing module is a hard error at compile: a shader that names an interface which no longer exists fails loudly rather than compiling against a stale copy. Each module is expanded at most once per shader, so two shaders that both include the same module — or a module that includes another — produce one copy, not a duplicate-definition error.

Writing one

Write only what other shaders need in scope: functions, structs, constants. A module may reference a binding its includers declare, which is how a package's prelude can read that package's uniform block.

const LUMA: vec3<f32> = vec3<f32>(0.2126, 0.7152, 0.0722);

fn srgb_to_linear(c: vec3<f32>) -> vec3<f32> {
    let lo = c / 12.92;
    let hi = pow(max(c + vec3<f32>(0.055), vec3<f32>(0.0)) / 1.055, vec3<f32>(2.4));
    return select(hi, lo, c <= vec3<f32>(0.04045));
}

Answering to another name

A module declares extra names it answers to with @alias lines in the header of module.wgsl:

// @alias: colour_helpers
// @alias: @mypack::shaderModules.colour

Each becomes an alias on the asset, so the name resolves everywhere an identity does — asset.resolve, an #include, and the publish gate alike. That is what lets a module be renamed without breaking the shaders already written against its old name: content persists the source it was authored with, so a name that stops resolving is a world that stops publishing.

Only the header is read — the scan stops at the first line that is not a comment, so a directive cannot hide in the module body. A name another asset already holds is refused and reported, since an alias extends the identity namespace rather than taking a name out of another asset's hands.

Registration & hot reload

Writing module.wgsl registers the module under every name the asset answers to — its guid, its identity, and any alias — so a shader includes it by whichever name it holds. Saving re-registers it and the shaders that include it recompile, with no world reload.

Discovery

  • asset.list("shaderModule") — every registered module.
  • moduleRef:getSource() — the module's WGSL.
  • .shader — render-domain shaders (surface, sky, post-process, screen).
  • .computeShader — compute programs.
  • asset-type
  • reference