Shader Modules
luma.gl provides a shader module system through @luma.gl/shadertools that
lets you build modular shaders. The system is built around a shader
"assembler", and addresses the lack of a module/import system in GLSL and WGSL.
The shader assembler allows you to import chunks of reusable shader code from
separately defined shader fragments into your shader program source code, which
lets you organize shader code into reusable modules.
- Enables you to import and "inject" prepackaged modules of shader code into your shaders.
- Allows you to package up reusable GLSL and/or WGSL code as shader modules.
- Adds GPU detection and a measure of portability your shaders.
Usage
To add/inject existing modules into your shaders, just add the modules parameter to your assembleShaders call:
import {shaderModule} from 'library-of-shader-modules';
const {vs, fs, getUniforms, moduleMap} = assembleShaders(device, {
fs: '...',
vs: '...',
modules: [shaderModule],
...
})
To create a new shader module, you need to create a descriptor object.
const MY_SHADER_MODULE = {
name: 'my-shader-module',
vs: ....
fs: null,
inject: {},
dependencies: [],
deprecations: [],
getUniforms
};
This object can be used as shader module directly:
assembleShaders(device, {..., modules: [MY_SHADER_MODULE]});
Structure of a Shader Module
The simplest shader modules just contain one or more reusable generic global
GLSL or WGSL functions that can be included either in fragment or vertex
shaders, or both. The shader assembler simply adds the functions to the top of
the assembled shader. The fp64 module is an example of this type of module.
More complex shader modules contain specific vertex and/or fragment shader "chunks". In this case the shader module defines vertex shader inputs and outputs requiring more sophisticated shader generation to wire up the inputs and outputs between shader stages.
Shader Module Descriptors
To define a new shader module, you create a descriptor object that brings together all the necessary pieces:
import type {ShaderModule} from '@luma.gl/shadertools';
export const myShaderModule = {
name: 'my-shader-module',
vs: '...',
fs: '...',
inject: {},
dependencies: [],
deprecations: [],
getUniforms
} as const satisfies ShaderModule;
For details see the ShaderModule type reference page.
For the uniform descriptor syntax used by uniformTypes, including structs,
fixed-size arrays, and TypeScript inference, see
Core Shader Types.
Several functions are also available to initialize and use shader modules.
For the current WGSL-specific assembly and binding-relocation rules used by
shadertools, see
WGSL Support.