
ralph-gpu
★ 58by vercel · part of vercel-labs/ralph-gpu
Minimal WebGPU shader library for creative coding and real-time graphics. Provides fullscreen passes, particles, compute shaders, render targets, and ping-pong…
Minimal WebGPU shader library for creative coding and real-time graphics. Provides fullscreen passes, particles, compute shaders, render targets, and ping-pong…
Inspect the full instructions your agent will receiveExpandCollapse
This is the exact playbook injected into your agent when the skill activates — shown here so you can audit it before installing. You don't need to read it to use the skill.
by vercel
Minimal WebGPU shader library for creative coding and real-time graphics. Provides fullscreen passes, particles, compute shaders, render targets, and ping-pong…
npx skills add https://github.com/vercel-labs/ralph-gpu --skill ralph-gpu
Download ZIPGitHub58
ralph-gpu
A minimal WebGPU shader library for creative coding and real-time graphics.
When to Use
Use this skill when:
-
Building WebGPU shader effects, creative coding projects, or real-time graphics
-
Working with fullscreen shader passes, particle systems, or compute shaders
-
Need guidance on ralph-gpu API, render targets, or WGSL shader patterns
-
Implementing GPU-accelerated simulations or visual effects
Core Concepts
Concept Description
gpu Module entry point for initialization
ctx GPU context — manages state and rendering
pass Fullscreen shader (fragment only, uses internal quad)
material Shader with custom vertex code (particles, geometry)
target Render target (offscreen texture)
pingPong Pair of render targets for iterative effects
compute Compute shader for GPU-parallel computation
storage Storage buffer for large data (particles, simulations)
sampler Custom texture sampler with explicit filtering/wrapping
texture Load images, canvases, video, or raw data as GPU textures
Auto-Injected Globals
Every shader automatically has access to these uniforms:
struct Globals {
resolution: vec2f, // Current render target size in pixels
time: f32, // Seconds since init
deltaTime: f32, // Seconds since last frame
frame: u32, // Frame count since init
aspect: f32, // resolution.x / resolution.y
}
@group(0) @binding(0) var globals: Globals;
API Overview
Context Creation
const ctx = await gpu.init(canvas, {
autoResize?: boolean, // Auto-handle canvas sizing (default: false)
dpr?: number, // Device pixel ratio
debug?: boolean, // Enable debug mode
events?: { // Event tracking
enabled: boolean,
types?: string[],
historySize?: number
}
});
Fullscreen Passes
// Simple mode (auto-generated bindings)
const pass = ctx.pass(wgslCode, {
uTexture: someTarget,
color: [1, 0, 0],
intensity: 0.5
});
pass.set("intensity", 0.8); // Update uniforms
// Manual mode (explicit bindings)
const pass = ctx.pass(wgslCode, {
uniforms: {
myValue: { value: 1.0 }
}
});
pass.uniforms.myValue.value = 2.0;
Render Targets
const target = ctx.target(512, 512, {
format?: "rgba8unorm" | "rgba16float" | "r16float" | "rg16float",
filter?: "linear" | "nearest",
wrap?: "clamp" | "repeat" | "mirror",
usage?: "render" | "storage" | "both"
});
ctx.setTarget(target); // Render to target
ctx.setTarget(null); // Render to screen
Ping-Pong Buffers
const simulation = ctx.pingPong(128, 128, {
format: "rgba16float"
});
// In render loop:
uniforms.inputTex.value = simulation.read;
ctx.setTarget(simulation.write);
processPass.draw();
simulation.swap();
Particles (Instanced Quads)
const particles = ctx.particles(1000, {
shader: wgslCode, // Full vertex + fragment shader
bufferSize: 1000 * 16, // Buffer size in bytes
blend: "additive"
});
particles.write(particleData); // Float32Array
particles.draw();
Compute Shaders
const compute = ctx.compute(\`
@compute @workgroup_size(64)
fn main(@builtin(global_invocation_id) id: vec3 ) {
// GPU computation
}
\`);
compute.storage("buffer", storageBuffer);
compute.dispatch(Math.ceil(count / 64));
Storage Buffers
const buffer = ctx.storage(byteSize);
buffer.write(new Float32Array([...]));
// Bind to shader
pass.storage("dataBuffer", buffer);
Texture Loading
// From URL (async)
const tex = await ctx.texture("image.png");
// From canvas / video / ImageBitmap (sync)
const tex = ctx.texture(canvas);
// From raw pixel data (sync)
const tex = ctx.texture(new Uint8Array(data), { width: 256, height: 256 });
// Options
const tex = await ctx.texture("photo.jpg", {
filter: "linear", // "linear" | "nearest"
wrap: "repeat", // "clamp" | "repeat" | "mirror"
format: "rgba8unorm", // GPU texture format
flipY: true, // Flip vertically on load
});
// Bind to shader (manual mode)
const pass = ctx.pass(shader, {
uniforms: {
uTex: { value: tex }, // .texture and .sampler auto-bound
}
});
// Update from live source (canvas, video)
tex.update(videoElement);
// Clean up
tex.dispose();
Important Notes
WGSL Alignment: array<vec3f> has 16-byte stride, not 12. Always pad to 16 bytes:
// Correct: [x, y, z, 0.0] per element
const buffer = ctx.storage(count * 16);
Particle Rendering: Use instanced quads, not point-list (WebGPU points are always 1px)
Texture References: Target references stay valid after resize — no need to update uniforms
Screen Readback: Cannot read pixels from screen, only from render targets
Examples
Full working examples extracted from the docs app:
-
Simple Gradient — The simplest possible shader — map UV coordinates to colors. This creates a gradient from black (bottom-left) to cyan (top-right).
-
Animated Wave — A glowing sine wave with custom uniforms. The wave animates over time using globals.time.
-
Time-Based Color Cycling — A hypnotic pattern that cycles through colors over time. Combines time, distance, and angle for a mesmerizing effect.
-
Raymarching Sphere — A basic 3D sphere rendered using raymarching. This demonstrates how to create 3D shapes and lighting entirely within a fragment shader.
-
Perlin-style Noise — Layered fractional Brownian motion (fBm) noise. This technique is fundamental for generating procedural textures, terrain, and natural-looking patterns.
-
Metaballs — Organic-looking "blobs" that merge together based on an implicit surface. This effect uses a distance-based field and a threshold to create smooth blending.
-
Mandelbrot Set — The classic complex number fractal. This shader computes the set by iterating z = z² + c and mapping the escape time to vibrant colors.
-
Alien Planet — A procedurally generated alien world with atmospheric scattering and an orbiting moon. Uses raymarching with fBm noise for terrain detail.
-
Fluid Simulation — Real-time Navier-Stokes fluid simulation using ping-pong buffers, vorticity confinement, and pressure projection.
-
Triangle Particles — GPU-driven particle system with SDF-based physics. 30,000 particles spawn on triangle edges and flow along a signed distance field with chromatic aberration postprocessing.
Resources
npm install ralph-gpu
# For TypeScript support:
npm install -D @webgpu/typesRun this in your project — your agent picks the skill up automatically.
Installation
npm install ralph-gpu
# For TypeScript support:
npm install -D @webgpu/types
Quick Start
import { gpu } from "ralph-gpu";
// Check support
if (!gpu.isSupported()) {
console.error("WebGPU not supported");
return;
}
// Initialize
const ctx = await gpu.init(canvas, { autoResize: true });
// Create fullscreen shader pass
const pass = ctx.pass(\`
@fragment
fn main(@builtin(position) pos: vec4f) -> @location(0) vec4f {
let uv = pos.xy / globals.resolution;
return vec4f(uv, sin(globals.time) * 0.5 + 0.5, 1.0);
}
\`);
// Render loop
function frame() {
pass.draw();
requestAnimationFrame(frame);
}
frame();
No common issues documented yet. If you hit a problem, the repository's GitHub Issues page is the best place to look.