ShaderModule
ShaderModule is the reusable shader feature descriptor used by
@luma.gl/shaders. A module may contribute WGSL and/or GLSL source,
shader-facing uniform descriptors, resource bindings, dependencies, and defines.
ShaderModules are used by ShaderAssembler
and engine classes such as Model and
Computation. The assembler
resolves dependencies, prepends module source, and returns
assembled source plus a combined uniform getter.
For the composition model, see Shader Assembly.
Usageโ
Attach modules through an engine class:
import {Model} from '@luma.gl/engine';
const model = new Model(device, {
source: wgslSource,
vs: glslVertexSource,
fs: glslFragmentSource,
modules: [color]
});
Or pass modules directly to ShaderAssembler.
To define a new shader module, create a descriptor that brings together the source, uniforms, and dependencies that belong to one reusable shader feature:
import type {ShaderModule} from '@luma.gl/shaders';
type MyShaderModuleProps = {
intensity: number;
};
export const myShaderModule = {
name: 'my-shader-module',
source: '...',
vs: '...',
fs: '...',
uniformTypes: {
intensity: 'f32'
},
dependencies: [],
getUniforms: props => ({intensity: props.intensity})
} as const satisfies ShaderModule<MyShaderModuleProps>;
Use source for WGSL, vs and fs for GLSL stage source, or all three when
the module supports both backends. uniformTypes declares shader-facing
layouts; getUniforms maps application props to the uniforms and bindings
consumed by the shader; dependencies brings in other modules first.
Fieldsโ
props, uniforms, bindingsโ
props?,uniforms?,bindings?- Type-inference fields. They are not currently used as runtime values.
nameโ
name(string) - The name of the shader module.
sourceโ
source?(string) - WGSL code contributed by the module.
vsโ
vs?(string) - GLSL vertex shader code contributed by the module.
fsโ
fs?(string) - GLSL fragment shader code contributed by the module.
uniformTypes (Object) - Uniform shader typesโ
The uniformTypes map describes the shader-facing uniform layout for the
module. Primitive uniform leaves use string shader types such as 'f32',
'vec3<f32>', and 'mat4x4<f32>'.
From v9.3
luma.gl also supports composite uniform descriptors:
- structs use object literals
- fixed-size arrays use
[elementType, length]
See Core Shader Types for the
descriptor syntax, TypeScript inference, array handling, and how nested values
flow through ShaderInputs and uniform-buffer packing.
propTypes (Object) - Uniform JS prop typesโ
defaultUniforms (Object) - Default uniform valuesโ
getUniforms (function) - Function that maps props to uniforms and bindingsโ
When getUniforms is not provided, shaders validates props using
propTypes and returns the matching values.
bindingLayout (Array) - Logical bind-group assignment for bindingsโ
Each entry has name and group. For current bind-group guidance, see
Bind Groups and Bindings.
firstBindingSlot (Number) - Preferred WGSL auto-binding start slotโ
This affects module-owned WGSL @binding(auto) relocation.
defines (Object) - Constant defines to be injected into shaderโ
implements (string, optional)โ
Declares an exclusive named shader interface, for example
{name: 'project32', implements: 'projection'} or
{name: 'project64', implements: 'projection'}. The interface name describes a
shared shader contract; it does not verify function signatures or uniform layouts.
Only one distinct module may implement a given interface in an assembly. The
assembler checks the complete dependency graph, including default modules and
transitive dependencies, and rejects conflicting providers in either input order.
Repeated references to the same module object are allowed and deduplicated.
Modules without implements keep their existing behavior.
Choose a provider explicitly by including only that implementation. There is no
last-module-wins precedence or automatic dependency substitution: dependencies
still requires concrete module objects. If a required dependency implements the
same interface as another selected module, assembly fails rather than dropping
the dependency or leaving its dependent incomplete. Remove a conflicting default
module before adding an alternative provider.
This proof of concept supports one interface name per module. Interface-based requirements and provider substitution are future design work.
dependencies (Array) - Shader modules that this module depends onโ
Dependencies are resolved before the module source is assembled.
deprecations (Array) - Deprecated APIs detected during assemblyโ
If deprecations is supplied, assembleShaders will scan shader source code for the deprecated constructs and issue a console warning if found. Each API is described in the following format:
type:uniform <type>orfunctionold: name of the deprecated uniform/functionnew: name of the new uniform/functiondeprecated: whether the old API is still supported.
instance (Object) - Runtime initialization stateโ
Generated by initializeShaderModule() or shader assembly. Application module
descriptors should normally leave this unset.
Statically defining Uniformsโ
If the uniforms of this module can be directly pulled from user props, they may
be declaratively defined by a defaultUniforms object:
{
name: 'my-shader-module',
defaultUniforms: {center: [0.5, 0.5], strength: 0.9},
uniformTypes: {center: 'vec2<f32>', strength: 'f32'}
}
At runtime, this map will be used to generate the uniforms needed by the shaders. If either strength or center is present in the user's module props, then the user's value will be used; otherwise, the default value in the original definition will be used.
Dynamically defining Uniformsโ
The shader module may want to perform more complex logic when mapping the
user's module props to uniforms. This can be achieved using getUniforms():
{
name: 'my-shader-module',
uniformTypes: {center: 'vec2<f32>', strength: 'f32'},
getUniforms: ({intensity}) => {
return {
strength: Math.sqrt(intensity),
center: intensity > 0 ? [0.5, 0.5] : [0, 0]
};
}
}
Adding Injectionsโ
Use a named ShaderPlugin for target or
anchor injections. A plugin can attach this module through its module field and
select GLSL or WGSL source for each injection.
Functionsโ
initializeShaderModule()โ
initializeShaderModule(module: ShaderModule): void
Initializes one module's dependencies, parsed deprecations, prop validators, and default uniforms. Assembly calls this as needed.
initializeShaderModules()โ
initializeShaderModules(modules: ShaderModule[]): void
Initializes each module in an array.
getShaderModuleUniforms()โ
getShaderModuleUniforms(
module: ShaderModule,
props?: Record<string, unknown>,
oldUniforms?: Record<string, ShaderModuleUniformValue>
): Record<string, Binding | ShaderModuleUniformValue>
Returns the uniforms and bindings produced for one module update. When the
module has getUniforms and props are supplied, shaders calls
getUniforms(props, oldUniforms || defaultUniforms). Otherwise it validates
and returns matching props through propTypes.
getShaderModuleDependencies()โ
getShaderModuleDependencies(modules: ShaderModule[]): ShaderModule[]
Returns modules and transitive dependencies sorted so dependencies are assembled before modules that use them.
checkShaderModuleDeprecations()โ
checkShaderModuleDeprecations(
shaderModule: ShaderModule,
shaderSource: string,
log: any
): void
Checks shader source against the module's deprecation definitions and logs matching warnings or removals.
sourceLanguage and source-language modulesโ
When sourceLanguage names an application-registered transpiler, source
contains reusable code in that language. The assembler combines it with modules'
dependencies and the application translation unit before compilation. Set the
same sourceLanguage on the application shader. Native shader code and injections
continue to use the target GLSL/WGSL language. See
application-owned transpilers.