API Reference
Complete documentation of all ralph-gpu methods and properties.
modulegpu
The main entry point for initializing WebGPU.
import { gpu, WebGPUNotSupportedError, DeviceCreationError, ShaderCompileError } from "ralph-gpu";
// Check if WebGPU is supported in this browser
gpu.isSupported() // → boolean
// Initialize the GPU context
gpu.init(canvas, options?) // → Promise<GPUContext>Init Options
interface InitOptions {
autoResize?: boolean; // Auto-resize from CSS size (default: false)
dpr?: number; // Device pixel ratio (default: min(devicePixelRatio, 2))
debug?: boolean; // Enable debug logging (default: false)
}
// Recommended: autoResize handles canvas sizing and DPR automatically
const ctx = await gpu.init(canvas, {
autoResize: true,
});
// Manual control:
// If autoResize is false, library uses canvas.width/height directly
// as pixel dimensions. No extra DPR multiplication is applied.
canvas.width = 1280;
canvas.height = 720;
const ctx = await gpu.init(canvas, {
autoResize: false,
});classGPUContext
The main context object returned by gpu.init(). Creates and manages all GPU resources.
Factory Methods
// Create a fullscreen pass
ctx.pass(fragmentWGSL, options?) // → Pass
// Create custom geometry material
ctx.material(wgsl, options?) // → Material
// Create compute shader
ctx.compute(wgsl, options?) // → ComputeShader
// Create render target
ctx.target(width, height, options?) // → RenderTarget
// Create ping-pong buffers
ctx.pingPong(width, height, options?) // → PingPongTarget
// Create multi-render target (MRT)
ctx.mrt(outputs, width, height) // → MultiRenderTarget
// Create storage buffer
ctx.storage(byteSize) // → StorageBuffer
// Create particle system (instanced quads)
ctx.particles(count, options) // → Particles
// Create custom texture sampler
ctx.createSampler(descriptor?) // → SamplerState Management
// Render target management
ctx.setTarget(target) // Set render target (pass null for screen)
ctx.setTarget(null) // Render to screen
// Viewport and scissor
ctx.setViewport(x?, y?, w?, h?) // Set viewport rectangle
ctx.setScissor(x?, y?, w?, h?) // Set scissor rectangle
// Clearing
ctx.autoClear = true // Auto-clear before each draw (default: true)
ctx.clearColor = [r, g, b, a] // Set clear color (default: [0, 0, 0, 1])
ctx.clear(target?, color?) // Manual clear (color as [r, g, b, a])
// Resize
ctx.resize(width, height) // Resize context and internal buffersProperties
ctx.width: number // Canvas width in pixels
ctx.height: number // Canvas height in pixels
ctx.dpr: number // Device pixel ratio (get/set)
ctx.time: number // Elapsed time in seconds
ctx.timeScale: number // Time multiplier (default: 1)
ctx.paused: boolean // Pause time updates
ctx.autoClear: boolean // Auto-clear before draw (default: true)
ctx.clearColor: [number, number, number, number] // Clear color RGBA (default: [0, 0, 0, 1])Time Control
// Pause/resume time
ctx.paused = true; // Freeze globals.time
ctx.paused = false; // Resume time
// Time scale
ctx.timeScale = 0.5; // Slow motion (half speed)
ctx.timeScale = 2.0; // Fast forward (double speed)
// Reset time
ctx.time = 0; // Jump to time 0Cleanup
ctx.dispose()Releases all GPU resources created by this context. Call this when unmounting a component or destroying the canvas.
classPass
A fullscreen shader pass. Renders a fragment shader to the entire render target using an internal quad.
Creation Options
// 1. Simple Mode (Recommended)
// Bindings are auto-generated. Uniforms available via 'uniforms' struct.
const pass = ctx.pass(shaderCode, {
color: [1, 0.5, 0.2],
intensity: 0.5,
uTexture: someTarget,
});
// Update values
pass.set("intensity", 0.8);
// 2. Manual Mode (explicit bindings)
// Requires manual @group(1) declarations in WGSL.
const pass = ctx.pass(shaderCode, {
uniforms: {
color: { value: [1, 0.5, 0.2] },
intensity: { value: 0.5 },
},
blend: "additive",
});
// Update values
pass.uniforms.intensity.value = 0.8;Methods & Properties
// Draw the pass to current target
pass.draw()
// Access uniforms
pass.uniforms.amplitude.value = 0.8
// Set uniform (alternative syntax)
pass.set("amplitude", 0.8)
// Bind a storage buffer
pass.storage("particles", particleBuffer)
// Clean up resources
pass.dispose()classMaterial
A shader with custom vertex code. Use for particles, instanced geometry, or any non-fullscreen rendering.
Creation Options
interface MaterialOptions {
uniforms?: Record<string, { value: any }>;
blend?: BlendMode;
vertexCount?: number; // Vertices per instance (default: 6)
instances?: number; // Number of instances (default: 1)
topology?: "triangle-list" | "line-list" | "point-list";
}
const particles = ctx.material(shaderCode, {
vertexCount: 6, // Quad has 6 vertices (2 triangles)
instances: 10000, // 10k particles
blend: "additive",
});Note: Material has the same methods as Pass (draw(), storage(), dispose(), etc.)
classComputeShader
A compute shader for GPU-parallel computation. Supports storage buffers, texture sampling, and storage texture writes.
// Create compute shader
const sim = ctx.compute(`
@compute @workgroup_size(64)
fn main(@builtin(global_invocation_id) id: vec3u) {
// GPU-parallel computation
}
`);
// Dispatch compute work
sim.dispatch(workgroupsX, workgroupsY?, workgroupsZ?)
// Bind storage buffer
sim.storage("data", buffer)
// Access uniforms (if any)
sim.uniforms
// Cleanup
sim.dispose()totalItems / workgroupSize. If your shader has @workgroup_size(64) and you have 1000 particles, dispatch Math.ceil(1000/64) = 16 workgroups.classRenderTarget
An offscreen texture that can be rendered to and sampled from.
Creation Options
interface TargetOptions {
format?: "rgba8unorm" | "rgba16float" | "r16float" | "rg16float" | "r32float";
filter?: "linear" | "nearest";
wrap?: "clamp" | "repeat" | "mirror";
usage?: "render" | "storage" | "both"; // NEW: Control texture usage
}
const buffer = ctx.target(512, 512, {
format: "rgba16float", // HDR
filter: "linear", // Smooth sampling
wrap: "clamp", // Clamp to edge
});
// Storage texture for compute shader writes
const storageTarget = ctx.target(512, 512, {
format: "rgba16float",
usage: "storage", // Enable textureStore() in compute shaders
});Properties & Methods
target.texture // TextureReference - stable reference (use in uniforms)
target.gpuTexture // GPUTexture - direct access (becomes invalid after resize)
target.sampler // GPUSampler
target.view // GPUTextureView (auto-updated on resize)
target.width // Width in pixels
target.height // Height in pixels
target.format // Texture format string
target.usage // Usage mode: "render" | "storage" | "both"
// Methods
target.resize(width, height) // Resize (texture refs remain valid!)
target.readPixels(x?, y?, w?, h?) // → Promise<Uint8Array | Float32Array>
target.dispose() // Cleanup resources
// Note: Use .texture for uniforms (stable reference)
// Only use .gpuTexture when you need direct GPU texture accessFormats
rgba8unorm— Standard 8-bit colorrgba16float— HDR, negative valuesr16float— Single channel floatrg16float— Two channel floatr32float— High precision single channel
Usage Modes
render— Render to & sample (default)storage— Compute shader writesboth— All operations
Read Pixels
Returns Uint8Array for 8-bit formats, Float32Array for float formats. This is a GPU→CPU transfer and may be slow.
classPingPongTarget
A pair of render targets for iterative effects. Read from one, write to the other, then swap.
const velocity = ctx.pingPong(128, 128, { format: "rg16float" });
// Access buffers
velocity.read // Current state (RenderTarget)
velocity.write // Next state (RenderTarget)
// Swap after writing
velocity.swap()
// Resize both buffers
velocity.resize(width, height)
// Cleanup
velocity.dispose()Usage Pattern
- Read from
pingPong.read.texturein your shader - Set target to
pingPong.write - Draw your pass
- Call
pingPong.swap() - Repeat next frame
classMultiRenderTarget
Multiple render targets (MRT) for deferred rendering, G-buffers, or any technique requiring simultaneous output to multiple textures.
// Create multiple render targets
const gbuffer = ctx.mrt({
albedo: { format: "rgba8unorm" },
normal: { format: "rgba16float" },
depth: { format: "r32float" },
}, 1024, 1024);
// Get individual targets
gbuffer.get("albedo") // → RenderTarget | undefined
gbuffer.get("normal") // → RenderTarget | undefined
// Or access via property (proxied)
gbuffer.albedo // → RenderTarget | undefined
// Get all views/formats
gbuffer.getViews() // → GPUTextureView[]
gbuffer.getFormats() // → string[]
gbuffer.getFirstTarget() // → RenderTarget | undefined
// Dimensions
gbuffer.width // 1024
gbuffer.height // 1024
// Resize all targets
gbuffer.resize(2048, 2048)
// Cleanup
gbuffer.dispose()Common Use Cases
- • Deferred rendering — Store albedo, normals, depth in separate buffers
- • G-buffer — Multiple material properties for post-processing
- • Multi-output effects — Generate multiple textures in one pass
mrt.get("name") for type-safe access, or mrt.name for convenience (proxied property access).classStorageBuffer
A GPU buffer for large data sets. Used with compute shaders and materials for particles, simulations, etc.
// Create buffer (size in bytes)
const buffer = ctx.storage(4 * 4 * 1000); // 1000 vec4s
// Write data
const data = new Float32Array(4 * 1000);
buffer.write(data)
// Access GPUBuffer directly
buffer.gpuBuffer
// Cleanup
buffer.dispose()Size calculation: Multiply the number of items by bytes per item. A vec4f is 16 bytes (4 floats × 4 bytes). For 1000 particles with position and velocity (2 × vec2f), that's 1000 × 16 = 16000 bytes.
classParticles
A helper for instanced quad rendering with full shader control. User provides vertex and fragment shaders — no built-in colors, shapes, or assumptions about data layout.
// Create particle system - instanced quads with full shader control
const particles = ctx.particles(1000, {
shader: `
struct Particle { pos: vec2f, size: f32, hue: f32 }
@group(1) @binding(0) var<storage, read> particles: array<Particle>;
struct VertexOutput {
@builtin(position) position: vec4f,
@location(0) uv: vec2f,
@location(1) hue: f32,
}
@vertex
fn vs_main(
@builtin(instance_index) iid: u32,
@builtin(vertex_index) vid: u32
) -> VertexOutput {
let p = particles[iid];
// Built-in helpers: quadOffset(), quadUV()
let quadPos = quadOffset(vid) * p.size;
var out: VertexOutput;
out.position = vec4f(p.pos + quadPos, 0.0, 1.0);
out.uv = quadUV(vid);
out.hue = p.hue;
return out;
}
@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4f {
// Circle SDF
let d = length(in.uv - 0.5);
if (d > 0.5) { discard; }
return vec4f(1.0, in.hue, 0.5, 1.0);
}
`,
bufferSize: 1000 * 16, // 16 bytes per particle
blend: "alpha",
});
// Write particle data
const data = new Float32Array(1000 * 4);
// Fill data: [x, y, size, hue] per particle
particles.write(data);
// Draw all particles
particles.draw();
// Access underlying resources
particles.storageBuffer // → StorageBuffer
particles.underlyingMaterial // → MaterialBuilt-in WGSL Helpers
- •
quadOffset(vid: u32) → vec2f— Quad corner position (-0.5 to 0.5) - •
quadUV(vid: u32) → vec2f— UV coordinates (0 to 1)
What You Control
- • Particle struct layout — Any data you need (position, size, color, age, etc.)
- • Vertex shader — Position, size, rotation, billboarding, etc.
- • Fragment shader — Shape via SDF, color, effects (squares, circles, triangles)
point-list topology renders points as exactly 1 pixel with no size control. The Particles helper uses instanced quads (2 triangles per particle) to support variable sizes.classSampler
A texture sampler with explicit control over filtering and wrapping modes. Samplers can be reused across multiple textures and shaders for consistency and performance.
// Create custom samplers for explicit texture filtering control
const linearClamp = ctx.createSampler({
magFilter: "linear",
minFilter: "linear",
addressModeU: "clamp-to-edge",
addressModeV: "clamp-to-edge",
});
const nearestRepeat = ctx.createSampler({
magFilter: "nearest",
minFilter: "nearest",
addressModeU: "repeat",
addressModeV: "repeat",
});
// Reuse across multiple textures and shaders
const uniforms = {
texture1: { value: tex1.texture },
sampler1: { value: linearClamp },
texture2: { value: tex2.texture },
sampler2: { value: nearestRepeat },
};Sampler Options
interface SamplerDescriptor {
magFilter?: "linear" | "nearest"; // Default: "linear"
minFilter?: "linear" | "nearest"; // Default: "linear"
mipmapFilter?: "linear" | "nearest"; // Default: "linear"
addressModeU?: "clamp-to-edge" | "repeat" | "mirror-repeat"; // Default: "clamp-to-edge"
addressModeV?: "clamp-to-edge" | "repeat" | "mirror-repeat"; // Default: "clamp-to-edge"
addressModeW?: "clamp-to-edge" | "repeat" | "mirror-repeat"; // Default: "clamp-to-edge"
lodMinClamp?: number; // Default: 0
lodMaxClamp?: number; // Default: 32
compare?: "never" | "less" | "equal" | "less-equal" | "greater" | "not-equal" | "greater-equal" | "always";
maxAnisotropy?: number; // Default: 1
}Properties & Methods
sampler.gpuSampler // GPUSampler - use in uniforms
sampler.descriptor // SamplerDescriptor (readonly)
// Cleanup
sampler.dispose() // No-op currently (kept for API consistency)Common Patterns
- • Linear Clamp — Blur, postprocessing, smooth sampling at edges
- • Nearest Repeat — Pixel art, tiling textures, retro effects
- • Mirror Repeat — Seamless tiling without visible seams
Blend Modes
Control how colors are combined when rendering.
Presets & Custom
// Preset blend modes
ctx.pass(shader, { blend: "alpha" }) // Standard transparency
ctx.pass(shader, { blend: "additive" }) // Add colors (glow, fire)
ctx.pass(shader, { blend: "multiply" }) // Multiply (darken)
ctx.pass(shader, { blend: "screen" }) // Screen (lighten)
// Custom blend configuration
ctx.pass(shader, {
blend: {
color: {
src: "src-alpha",
dst: "one",
operation: "add"
},
alpha: {
src: "one",
dst: "one-minus-src-alpha",
operation: "add"
}
}
});Blend Factors & Operations
// Blend factors
"zero" // 0
"one" // 1
"src" // Source color/alpha
"one-minus-src" // 1 - source
"src-alpha" // Source alpha
"one-minus-src-alpha" // 1 - source alpha
"dst" // Destination color/alpha
"one-minus-dst" // 1 - destination
"dst-alpha" // Destination alpha
"one-minus-dst-alpha" // 1 - destination alpha
// Blend operations
"add" // src + dst
"subtract" // src - dst
"reverse-subtract" // dst - src
"min" // min(src, dst)
"max" // max(src, dst)alpha
Standard transparency
additive
Glow, fire, bright effects
multiply
Darken, shadows
screen
Lighten, highlights
Auto-Injected Globals
Every shader automatically has access to the globals uniform — no declaration needed.
struct Globals {
resolution: vec2f, // Current render target size in pixels
time: f32, // Seconds since init (affected by timeScale)
deltaTime: f32, // Seconds since last frame
frame: u32, // Frame count since init
aspect: f32, // resolution.x / resolution.y
}
// Automatically available in all shaders
@group(0) @binding(0) var<uniform> globals: Globals;resolution
Width and height of current render target in pixels.
time
Seconds since init. Affected by timeScale and paused.
deltaTime
Seconds since last frame. Use for frame-rate independent animation.
frame
Integer frame count. Useful for alternating effects or debugging.
aspect
Resolution width divided by height. Use to correct for non-square pixels.
Uniform Types
JavaScript values are automatically converted to WGSL types.
// Scalar → f32
{ value: 0.5 }
// Vec2 → vec2f
{ value: [0.5, 0.5] }
// Vec3 → vec3f
{ value: [1.0, 0.5, 0.2] }
// Vec4 → vec4f
{ value: [1.0, 0.5, 0.2, 1.0] }
// Texture → texture_2d<f32> + sampler
{ value: renderTarget.texture }.value, the change is automatically uploaded to the GPU before the next draw call. No manual update needed.Texture Bindings
ralph-gpu supports flexible ways to pass textures and samplers to shaders.
Binding Patterns
// Pattern 1: RenderTarget (convenience - auto-extracts texture + sampler)
const uniforms1 = {
myTexture: { value: renderTarget }, // Easiest
};
// Pattern 2: Separate texture + custom sampler (explicit control)
const customSampler = ctx.createSampler({ magFilter: "nearest" });
const uniforms2 = {
myTexture: { value: renderTarget.texture },
mySampler: { value: customSampler },
};
// Pattern 3: Texture without sampler (for textureLoad in WGSL)
const uniforms3 = {
dataTexture: { value: renderTarget.texture }, // No sampler needed
};
// In WGSL:
@group(1) @binding(0) var myTexture: texture_2d<f32>;
@group(1) @binding(1) var mySampler: sampler; // Auto-matched by naming conventionSampler Naming Convention
The system automatically matches samplers to textures:
- •
myTexture→ looks formyTextureSampler - •
inputTex→ looks forinputSamplerorinputTexSampler - •
someTexture→ looks forsomeSamplerorsomeTextureSampler
Compute Shaders with Textures
Compute shaders can now sample from textures for advanced GPU-accelerated effects.
// Compute shader with texture sampling
const compute = ctx.compute(`
@group(1) @binding(0) var inputTex: texture_2d<f32>;
@group(1) @binding(1) var inputSampler: sampler;
@group(1) @binding(2) var<storage, read_write> output: array<f32>;
@compute @workgroup_size(64)
fn main(@builtin(global_invocation_id) id: vec3<u32>) {
let uv = vec2f(f32(id.x) / 512.0, f32(id.y) / 512.0);
let color = textureSampleLevel(inputTex, inputSampler, uv, 0.0);
output[id.x] = color.r;
}
`, {
uniforms: {
inputTex: { value: renderTarget },
},
});
compute.storage("output", dataBuffer);
compute.dispatch(512);Storage Textures (Write Operations)
Use storage textures to write directly to textures from compute shaders.
// Storage texture for compute shader writes
const outputTarget = ctx.target(512, 512, {
format: "rgba16float",
usage: "storage", // Enable textureStore()
});
const compute = ctx.compute(`
@group(1) @binding(0) var input: texture_2d<f32>;
@group(1) @binding(1) var inputSampler: sampler;
@group(1) @binding(2) var output: texture_storage_2d<rgba16float, write>;
@compute @workgroup_size(8, 8)
fn main(@builtin(global_invocation_id) id: vec3<u32>) {
let uv = vec2f(id.xy) / 512.0;
let color = textureSampleLevel(input, inputSampler, uv, 0.0);
textureStore(output, id.xy, color * 2.0); // Write to storage texture
}
`, {
uniforms: {
input: { value: inputTarget },
output: { value: outputTarget },
},
});
compute.dispatch(512 / 8, 512 / 8);Usage Modes
- •
"render"(default) — For rendering and sampling - •
"storage"— For compute shader write operations - •
"both"— For both rendering and storage operations
textureStore() directly with pixel coordinates.Error Types
ralph-gpu exports typed errors for better error handling.
import {
WebGPUNotSupportedError,
DeviceCreationError,
ShaderCompileError,
} from "ralph-gpu";
try {
const ctx = await gpu.init(canvas);
} catch (e) {
if (e instanceof WebGPUNotSupportedError) {
// Browser doesn't support WebGPU
// navigator.gpu is undefined
} else if (e instanceof DeviceCreationError) {
// GPU device couldn't be created
// May happen with unsupported hardware
} else if (e instanceof ShaderCompileError) {
// WGSL syntax error
console.error(`Line ${e.line}, Col ${e.column}: ${e.message}`);
}
}WebGPUNotSupportedError
Thrown when navigator.gpu is undefined. The browser doesn't support WebGPU. Show a fallback UI.
DeviceCreationError
Thrown when the GPU device couldn't be created. May happen with unsupported hardware or driver issues.
ShaderCompileError
Thrown when WGSL code has syntax errors. Includes line, column, and message properties for debugging.