Uniforms are the primary mechanism for passing dynamic values from your JavaScript/TypeScript runtime code into WGSL shaders. This page covers declaration, type inference, memory layout, and runtime updates.
Examples below use the same runtime uniform APIs across Svelte, React, and Vue.
Declaring uniforms
Uniforms are declared in the uniforms field of defineMaterial:
Each uniform becomes a field on the motiongpuUniforms struct. The library generates the binding struct and uniform buffer automatically.
Input forms
Motion GPU accepts two styles of uniform declaration:
Shorthand (value only)
The type is inferred from the value shape:
Explicit (type + value)
For clarity or for mat4x4f, use the explicit form:
The mat4x4f type must use explicit form — it cannot be inferred from an array length of 16.
Naming rules
All uniform identifiers must be WGSL-safe: [A-Za-z_][A-Za-z0-9_]*.
Invalid names throw at material definition time. Common conventions:
uTime,uMouse,uColor— prefix withufor user uniformsmotiongpuFrame.*— built-in frame uniforms (do not declare these indefineMaterial)
WGSL alignment and packing
Uniforms are packed into a single Float32Array buffer following WGSL std140-like alignment rules:
Packing behavior
- Uniform entries are sorted alphabetically by name.
- Each entry is placed at the next offset that satisfies its alignment requirement.
- The total buffer size is rounded up to 16 bytes (minimum 16 bytes).
Example layout for { uA: f32, uB: vec3f, uC: vec2f } (sorted: uA, uB, uC):
You generally don’t need to think about this — it’s handled automatically. The material signature is based on uniform names and types (order does not matter because layout is sorted).
Runtime updates with setUniform
Inside a useFrame callback, use state.setUniform(name, value) to update a uniform’s value for the current frame:
<script lang="ts">
import { useFrame } from '@motion-core/motion-gpu/svelte';
useFrame((state) => {
state.setUniform('uTime', state.time);
state.setUniform('uMouse', [mouseX, mouseY]);
});
</script>Important rules
- Name must exist in the material’s
uniformsmap. Setting an unknown name throws. - Value shape must match the declared type. Passing
[1, 2]to anf32uniform throws. - Updates are merged — material defaults are used for any uniform not set during the frame.
- Dirty tracking — only changed ranges are written to the GPU buffer, minimizing upload overhead.
Built-in frame uniforms
The renderer provides a built-in motiongpuFrame uniform buffer. You do not declare it in defineMaterial: