Getting Started
Get up and running with ralph-gpu in minutes.
Installation
Install ralph-gpu using your preferred package manager:
npm install ralph-gpu
# or
pnpm add ralph-gpuFor better TypeScript support, also install WebGPU types:
# Optional but recommended for TypeScript
npm install -D @webgpu/typesBrowser Support
WebGPU is a modern API and requires a compatible browser:
✅ Supported
- Chrome 113+ (desktop)
- Chrome 121+ (Android)
- Edge 113+
- Safari 17+ (macOS Sonoma, iOS 17)
⚠️ Limited
- Firefox Nightly (behind flag)
- Older browser versions
Warning
gpu.isSupported() before initializing to handle unsupported browsers gracefully.Basic Setup
Here's how to properly initialize ralph-gpu with error handling:
import { gpu, WebGPUNotSupportedError } from "ralph-gpu";
// Always check support first
if (!gpu.isSupported()) {
console.log('WebGPU not supported');
// Show fallback UI
return;
}
try {
const ctx = await gpu.init(canvas, {
dpr: Math.min(window.devicePixelRatio, 2), // Limit pixel ratio
debug: true // Enable debug logs
});
} catch (e) {
if (e instanceof WebGPUNotSupportedError) {
// Browser doesn't support WebGPU
}
}Your First Shader
Let's create a simple animated gradient shader. This demonstrates the basics of creating a pass and running an animation loop:
import { gpu } from "ralph-gpu";
const canvas = document.querySelector('canvas')!;
const ctx = await gpu.init(canvas);
// Create a simple gradient shader
const gradient = 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);
}
`);
// Animation loop
function frame() {
gradient.draw();
requestAnimationFrame(frame);
}
frame();What's happening here?
- Line 7: We create a
pass— a fullscreen fragment shader. - Line 10:
globals.resolutiongives us the canvas size. - Line 11:
globals.timeis automatically updated each frame. - Line 17:
draw()renders the shader to the screen.
React Integration
Here's a complete React component with proper initialization, cleanup, and resize handling:
import { useEffect, useRef } from "react";
import { gpu, GPUContext, Pass } from "ralph-gpu";
function ShaderCanvas() {
const canvasRef = useRef<HTMLCanvasElement>(null);
useEffect(() => {
let ctx: GPUContext | null = null;
let pass: Pass;
let animationId: number;
let disposed = false;
async function init() {
if (!canvasRef.current || !gpu.isSupported()) return;
// Recommended: autoResize handles sizing and DPR automatically
ctx = await gpu.init(canvasRef.current, {
autoResize: true,
});
if (disposed) {
ctx.dispose();
return;
}
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);
}
`);
function frame() {
if (disposed) return;
pass.draw();
animationId = requestAnimationFrame(frame);
}
frame();
}
init();
return () => {
disposed = true;
cancelAnimationFrame(animationId);
ctx?.dispose();
};
}, []);
return <canvas ref={canvasRef} style={{ width: "100%", height: "100%" }} />;
}
export default ShaderCanvas;Note
- • Use a
disposedflag to prevent rendering after unmount - • Clean up with
ctx.dispose()in the effect cleanup - • Use
autoResize: trueto handle canvas sizing and DPR automatically
Common Setup Issues
❓ Canvas is blank
Make sure you're calling draw() in a loop with requestAnimationFrame. Also check that the canvas has explicit dimensions.
❓ WebGPU not supported error
Check your browser version. Chrome 113+ and Safari 17+ are required. On Firefox, WebGPU must be enabled in about:config.
❓ Shader compilation errors
WGSL is strictly typed. Make sure all variables have explicit types and function return types are specified. Enable debug: true for detailed errors.
❓ Low frame rate / poor performance
Limit the device pixel ratio with dpr: Math.min(window.devicePixelRatio, 2) to avoid rendering at 4x resolution on high-DPI displays.