A tiny WebGPU runtime for writing Shadertoy-style fullscreen shaders in pure WGSL.
@motion-core/motion-gpu is a Svelte 5 package for building fullscreen shader pipelines using WebGPU and WGSL.
It provides a minimal runtime, scheduler, and render graph designed specifically for fragment-driven GPU programs.
Unlike general-purpose 3D engines, Motion GPU focuses on a very narrow problem: running fullscreen fragment shaders and multi-pass GPU pipelines.
Motion GPU is designed for applications where the entire scene is driven by fullscreen shaders.
Typical use cases include:
If your application is primarily a fullscreen fragment shader pipeline, using a full 3D engine can add unnecessary complexity and bundle size.
Three.js is a powerful general-purpose 3D engine. Motion GPU focuses on a much narrower problem: running fullscreen WGSL shader pipelines.
| Feature | Three.js | Motion GPU |
|---|---|---|
| Scope | Full 3D engine | Fullscreen shader runtime |
| Shader language | TSL / generated WGSL | Native WGSL |
| Bundle size | large | tiny |
| Rendering model | Scene graph | GPU pipeline |
| Shader pipeline | materials | explicit passes |
| Multi-pass | possible but indirect | first-class |
| Shader debugging | generated shaders | direct WGSL |
Motion GPU is not a replacement for Three.js.
Instead, it is designed for cases where a full 3D engine would be unnecessary overhead.
Motion GPU follows a simple three-step flow:
defineMaterial(...).<FragCanvas />.useFrame(...), useMotionGPU(), and useTexture(...).Fullscreen WebGPU renderer for WGSL fragment shaders
Strict material contract and validation (fn frag(uv: vec2f) -> vec4f)
Runtime uniform and texture updates without rebuilding the pipeline
Frame scheduler with task ordering, stages, invalidation modes, diagnostics and profiling
Render graph with built-in post-process passes:
ShaderPassBlitPassCopyPassNamed render targets for multi-pass pipelines
Structured error normalization with built-in overlay UI and custom renderer support
Advanced runtime API for namespaced shared user context and scheduler presets
@motion-core/motion-gpu)Primary runtime API:
FragCanvasdefineMaterialuseMotionGPUuseFrameuseTextureShaderPassBlitPassCopyPassAlso exports runtime/core types:
@motion-core/motion-gpu/advanced)Re-exports everything from root, plus:
useMotionGPUUserContextsetMotionGPUUserContextapplySchedulerPresetcaptureSchedulerDebugSnapshotpeerDependency: svelte ^5)https:// or localhost)npm i @motion-core/motion-gpu
<!-- App.svelte -->
<script lang="ts">
import { FragCanvas, defineMaterial } from '@motion-core/motion-gpu';
const material = defineMaterial({
fragment: `
fn frag(uv: vec2f) -> vec4f {
return vec4f(uv.x, uv.y, 0.25, 1.0);
}
`
});
</script>
<div style="width: 100vw; height: 100vh;">
<FragCanvas {material} />
</div>
useFrame<!-- App.svelte -->
<script lang="ts">
import { FragCanvas, defineMaterial } from '@motion-core/motion-gpu';
import Runtime from './Runtime.svelte';
const material = defineMaterial({
fragment: `
fn frag(uv: vec2f) -> vec4f {
let wave = 0.5 + 0.5 * sin(motiongpuUniforms.uTime + uv.x * 8.0);
return vec4f(vec3f(wave), 1.0);
}
`,
uniforms: {
uTime: 0
}
});
</script>
<FragCanvas {material}>
<Runtime />
</FragCanvas>
<!-- Runtime.svelte -->
<script lang="ts">
import { useFrame } from '@motion-core/motion-gpu';
useFrame((state) => {
state.setUniform('uTime', state.time);
});
</script>
defineMaterial(...) validates and freezes:
definesincludesA deterministic material signature is generated from resolved shader/layout metadata.
Inside useFrame(...) callbacks you update per-frame values:
state.setUniform(name, value)state.setTexture(name, value)state.invalidate(token?)state.advance()FragCanvas resolves material state, schedules tasks, and decides whether to render based on:
renderMode (always, on-demand, manual)autoRenderThese are enforced by runtime validation.
fn frag(uv: vec2f) -> vec4f
ShaderPass fragment entrypoint must be:fn shade(inputColor: vec4f, uv: vec2f) -> vec4f
useFrame() and useMotionGPU() must be called inside <FragCanvas> subtree.
You can only set uniforms/textures that were declared in defineMaterial(...).
Uniform/texture/include/define names must match WGSL-safe identifiers:
[A-Za-z_][A-Za-z0-9_]*
needsSwap: true is valid only for input: 'source' and output: 'target'.
Render passes cannot read from input: 'canvas'.
maxDelta and profiling window must be finite and greater than 0.
outputColorSpace changesRun from packages/motion-gpu:
bun run build
bun run check
bun run test
bun run test:e2e
bun run lint
bun run format
bun run perf:core
bun run perf:core:check
bun run perf:core:baseline
bun run perf:runtime
bun run perf:runtime:check
bun run perf:runtime:baseline
This project is licensed under the MIT License.
See the LICENSE file for details.