# Motion GPU Motion GPU is a lightweight WebGPU runtime for writing Shadertoy-style fullscreen shaders in pure WGSL. It provides a framework-agnostic core with a Svelte 5 adapter for building fullscreen shader pipelines, offering a minimal runtime loop, scheduler, and render graph specifically designed for fragment-driven GPU programs. Unlike general-purpose 3D engines, Motion GPU focuses on running fullscreen fragment shaders and multi-pass GPU pipelines with a significantly smaller bundle size (3.5-5x smaller than Three.js). The library follows a simple three-step workflow: define an immutable material with `defineMaterial()`, render it with ``, and drive runtime updates with hooks like `useFrame()`, `useMotionGPU()`, and `useTexture()`. It supports runtime uniform and texture updates without pipeline rebuilds, a frame scheduler with task ordering and profiling, and a render graph with built-in post-process passes (ShaderPass, BlitPass, CopyPass). Motion GPU is ideal for generative art, procedural textures, GPU simulations, shader editors, and interactive visual experiments. ## Installation ```bash npm i @motion-core/motion-gpu ``` ## defineMaterial Creates an immutable material object with validated shader, uniform, and texture contracts. The material is frozen and safe to share and cache. ```typescript import { defineMaterial } from '@motion-core/motion-gpu/svelte'; const material = defineMaterial({ fragment: ` fn frag(uv: vec2f) -> vec4f { let t = sin(motiongpuUniforms.uTime * 3.0); let color = mix(motiongpuUniforms.uColorA, motiongpuUniforms.uColorB, t * 0.5 + 0.5); return vec4f(color, 1.0); } `, uniforms: { uTime: 0, // f32 (inferred) uColorA: [1.0, 0.2, 0.3], // vec3f (inferred) uColorB: { type: 'vec3f', value: [0.2, 0.5, 1.0] } // vec3f (explicit) }, textures: { uAlbedo: { colorSpace: 'srgb', filter: 'linear', generateMipmaps: true } }, defines: { PI: 3.14159265359, RAY_BOUNCE_MAX: { type: 'i32', value: 10 } } }); ``` ## FragCanvas Component The main Svelte component for rendering materials. Handles WebGPU initialization, canvas sizing, scheduling, and render passes. ```svelte console.error(report)} class="shader-canvas" > ``` ## useFrame Hook Registers a callback that runs every frame, providing access to timing data and methods to update uniforms and textures. ```svelte ``` ## useMotionGPU Hook Returns the MotionGPU context for accessing runtime state and controlling rendering from within FragCanvas children. ```svelte

Canvas: {$gpu.size.width}x{$gpu.size.height} @ {$gpu.dpr}x

``` ## useTexture Hook Loads textures from URLs with reactive loading/error state and automatic cleanup. ```svelte {#if $loaded.loading}

Loading textures...

{:else if $loaded.error}

Error: {$loaded.error.message}

{:else}

Loaded {$loaded.textures?.length ?? 0} textures

{/if} ``` ## ShaderPass Programmable post-process pass with custom WGSL fragment shader. The fragment must declare `fn shade(inputColor: vec4f, uv: vec2f) -> vec4f`. ```typescript import { ShaderPass } from '@motion-core/motion-gpu/svelte'; // Vignette effect const vignettePass = new ShaderPass({ fragment: ` fn shade(inputColor: vec4f, uv: vec2f) -> vec4f { let dist = distance(uv, vec2f(0.5, 0.5)); let v = smoothstep(0.9, 0.35, dist); return vec4f(inputColor.rgb * v, inputColor.a); } `, enabled: true, needsSwap: true, // Swap source/target after render input: 'source', // Read from source buffer output: 'target', // Write to target buffer filter: 'linear' }); // Gamma correction to canvas (final pass) const gammaPass = new ShaderPass({ needsSwap: false, input: 'source', output: 'canvas', fragment: ` fn shade(inputColor: vec4f, uv: vec2f) -> vec4f { return vec4f(pow(inputColor.rgb, vec3f(1.0 / 2.2)), inputColor.a); } ` }); // Hot-swap shader at runtime vignettePass.setFragment(` fn shade(inputColor: vec4f, uv: vec2f) -> vec4f { return inputColor; // Passthrough } `); ``` ## BlitPass Fullscreen texture blit pass that copies input to output using configurable filter mode. ```typescript import { BlitPass } from '@motion-core/motion-gpu/svelte'; const blitPass = new BlitPass({ enabled: true, needsSwap: true, input: 'source', output: 'target', filter: 'nearest', // 'linear' or 'nearest' clear: false, clearColor: [0, 0, 0, 1], preserve: true }); ``` ## CopyPass Optimized texture copy with GPU-side `copyTextureToTexture` when possible, falling back to blit when direct copy conditions aren't met. ```typescript import { CopyPass } from '@motion-core/motion-gpu/svelte'; const copyPass = new CopyPass({ enabled: true, needsSwap: true, input: 'source', output: 'target', filter: 'linear' }); // Direct GPU copy when: same size/format, different textures, neither is canvas ``` ## Uniform Types Supported uniform types with shorthand and explicit declaration forms. ```typescript import { defineMaterial } from '@motion-core/motion-gpu/svelte'; const material = defineMaterial({ fragment: ` fn frag(uv: vec2f) -> vec4f { let t = motiongpuUniforms.uTime; let pos = motiongpuUniforms.uPosition; let color = motiongpuUniforms.uColor; let tint = motiongpuUniforms.uTint; let matrix = motiongpuUniforms.uModelMatrix; return vec4f(color * t, 1.0); } `, uniforms: { // Shorthand (type inferred from value shape) uTime: 0, // f32 uPosition: [0.5, 0.5], // vec2f uColor: [1.0, 0.5, 0.0], // vec3f uTint: [1.0, 1.0, 1.0, 0.8], // vec4f // Explicit (required for mat4x4f) uBrightness: { type: 'f32', value: 1.0 }, uModelMatrix: { type: 'mat4x4f', value: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ] } } }); // Built-in frame uniforms (auto-provided, don't declare): // motiongpuFrame.time - f32 timestamp in seconds // motiongpuFrame.delta - f32 frame delta in seconds // motiongpuFrame.resolution - vec2f canvas size in pixels ``` ## Texture Configuration Configure texture sampling, upload behavior, and update strategies. ```typescript import { defineMaterial } from '@motion-core/motion-gpu/svelte'; const material = defineMaterial({ fragment: ` fn frag(uv: vec2f) -> vec4f { let color = textureSample(uAlbedo, uAlbedoSampler, uv); let video = textureSample(uVideo, uVideoSampler, uv); return mix(color, video, 0.5); } `, textures: { uAlbedo: { colorSpace: 'srgb', // 'srgb' or 'linear' flipY: true, // Flip vertically on upload generateMipmaps: true, // Generate mip chain premultipliedAlpha: false, // Alpha premultiplication update: 'once', // 'once' | 'onInvalidate' | 'perFrame' anisotropy: 4, // Anisotropic filtering (1-16) filter: 'linear', // 'linear' or 'nearest' addressModeU: 'repeat', // 'clamp-to-edge' | 'repeat' | 'mirror-repeat' addressModeV: 'repeat' }, uVideo: { update: 'perFrame' // Re-upload every frame for video } } }); ``` ## Video Texture Example Bind video elements as textures with automatic per-frame updates. ```svelte