@motion-core/motion-gpu
v0.2.0
Published
Framework-agnostic WebGPU runtime for fullscreen WGSL shaders with explicit Svelte adapter entrypoints.
Maintainers
Readme
Motion GPU
A tiny WebGPU runtime for writing Shadertoy-style fullscreen shaders in pure WGSL.
@motion-core/motion-gpu ships a framework-agnostic core plus a Svelte 5 adapter for building fullscreen shader pipelines using WebGPU and WGSL.
It provides a minimal runtime loop, 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.
When to Use Motion GPU
Motion GPU is designed for applications where the entire scene is driven by fullscreen shaders.
Typical use cases include:
- Shadertoy-style GPU experiments
- Generative art
- Procedural textures
- Multi-pass post-processing pipelines
- GPU simulations
- Shader editors and live-coding tools
- Interactive visual experiments
If your application is primarily a fullscreen fragment shader pipeline, using a full 3D engine can add unnecessary complexity and bundle size.
Why Not Use Three.js?
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 (3.5-5x smaller) | | 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.
Core Workflow
Motion GPU follows a simple three-step flow:
- Define an immutable material with
defineMaterial(...). - Render it with
<FragCanvas />. - Drive runtime updates with
useFrame(...),useMotionGPU(), anduseTexture(...).
What This Package Includes
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:
ShaderPassBlitPassCopyPass
Named 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
Entrypoints
Svelte adapter
@motion-core/motion-gpu/svelte exposes the runtime API for Svelte:
FragCanvasdefineMaterialuseMotionGPUuseFrameuseTextureShaderPassBlitPassCopyPass
Also exports runtime/core types:
- uniforms
- textures
- render passes
- scheduler
- loader types
@motion-core/motion-gpu/svelte/advanced re-exports everything above, plus:
useMotionGPUUserContextsetMotionGPUUserContextapplySchedulerPresetcaptureSchedulerDebugSnapshot
Framework-agnostic core
@motion-core/motion-gpu (and explicit alias @motion-core/motion-gpu/core) exposes adapter-building primitives:
defineMaterialresolveMaterialcreateCurrentWritablecreateFrameRegistrycreateMotionGPURuntimeLooploadTexturesFromUrlstoMotionGPUErrorReportShaderPassBlitPassCopyPass
@motion-core/motion-gpu/advanced (and explicit alias @motion-core/motion-gpu/core/advanced) re-exports core plus:
applySchedulerPresetcaptureSchedulerDebugSnapshot
Requirements
- Svelte 5 is required only for the Svelte adapter entrypoints (
/svelte,/svelte/advanced) - A browser/runtime with WebGPU support
- Secure context (
https://orlocalhost)
Installation
npm i @motion-core/motion-gpuQuick Start
1. Create a material and render it
<!-- App.svelte -->
<script lang="ts">
import { FragCanvas, defineMaterial } from '@motion-core/motion-gpu/svelte';
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>2. Add animated uniforms via useFrame
<!-- App.svelte -->
<script lang="ts">
import { FragCanvas, defineMaterial } from '@motion-core/motion-gpu/svelte';
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/svelte';
useFrame((state) => {
state.setUniform('uTime', state.time);
});
</script>Core Runtime Model
Material Phase (compile-time contract)
defineMaterial(...) validates and freezes:
- WGSL fragment source
- Uniform declarations
- Texture declarations
- Compile-time
defines - Shader
includes
A deterministic material signature is generated from resolved shader/layout metadata.
Frame Phase (runtime updates)
Inside useFrame(...) callbacks you update per-frame values:
state.setUniform(name, value)state.setTexture(name, value)state.invalidate(token?)state.advance()
Renderer Phase
FragCanvas resolves material state, schedules tasks, and decides whether to render based on:
renderMode(always,on-demand,manual)- invalidation / advance state
autoRender
Hard Contracts and Validation Rules
These are enforced by runtime validation.
- Material entrypoint must be:
fn frag(uv: vec2f) -> vec4fShaderPassfragment entrypoint must be:
fn shade(inputColor: vec4f, uv: vec2f) -> vec4fuseFrame()anduseMotionGPU()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: trueis valid only forinput: 'source'andoutput: 'target'.Render passes cannot read from
input: 'canvas'.maxDeltaand profiling window must be finite and greater than0.
Pipeline Rebuild Rules
Rebuilds renderer
- Material signature changes (shader/layout/bindings)
outputColorSpacechanges
Does not rebuild renderer
- Runtime uniform value changes
- Runtime texture source changes
- Clear color changes
- Canvas resize (resources are resized/reallocated as needed)
Development
Run from packages/motion-gpu:
bun run build
bun run check
bun run test
bun run test:e2e
bun run lint
bun run formatPerformance
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:baselineLicense
This project is licensed under the MIT License.
See the LICENSE file for details.
