# Webgpu R3f Tsl

> Comprehensive guide for developing WebGPU-enabled React Three Fiber applications using TSL (Three.js Shading Language). Covers Canvas/WebGPURenderer setup, TSL syntax and node materials in JSX, compute shaders driven from useFrame, post-processing effects, and WGSL integration. Use this skill when working with React Three Fiber and three/webgpu, TSL shaders, node materials, or GPU compute in R3F.

- Skill: `williammelin/webgpu-r3f-tsl` (Agent Skill, multi-file: 17 files)
- Install (CLI): `npx skillmds@latest add williammelin/webgpu-r3f-tsl`
- Raw SKILL.md: https://api.skillmd.com/api/skills/williammelin/webgpu-r3f-tsl/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: williammelin (https://skillmd.com/u/williammelin)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/williammelin/webgpu-r3f-tsl

---


# WebGPU React Three Fiber with TSL

TSL (Three.js Shading Language) is a node-based shader abstraction that lets you write GPU shaders in JavaScript instead of GLSL/WGSL strings. React Three Fiber renders Three.js declaratively — TSL works unchanged inside it, but the renderer, render loop and resize handling move into `<Canvas>`.

## Quick Start

```tsx
import * as THREE from 'three/webgpu';
import { Canvas, extend, type ThreeToJSXElements } from '@react-three/fiber';
import { color, time, oscSine } from 'three/tsl';

declare module '@react-three/fiber' {
  interface ThreeElements extends ThreeToJSXElements<typeof THREE> {}
}

extend(THREE as any);

<Canvas
  gl={async (props) => {
    const renderer = new THREE.WebGPURenderer(props as any);
    await renderer.init();
    return renderer;
  }}
>
  <mesh>
    <boxGeometry />
    <meshStandardNodeMaterial colorNode={color(0xff0000).mul(oscSine(time))} />
  </mesh>
</Canvas>
```

## Skill Contents

### Documentation
- `docs/r3f-integration.md` - Canvas setup, memoization rules, render loop, SSR **(read this first)**
- `docs/core-concepts.md` - Types, operators, uniforms, control flow
- `docs/materials.md` - Node materials and all properties
- `docs/compute-shaders.md` - GPU compute with instanced arrays
- `docs/post-processing.md` - Built-in and custom effects
- `docs/wgsl-integration.md` - Custom WGSL functions
- `docs/device-loss.md` - Handling GPU device loss and recovery
- `docs/limits-and-features.md` - WebGPU device limits and optional features

### Examples
- `examples/basic-setup.tsx` - Minimal WebGPU Canvas
- `examples/custom-material.tsx` - Custom shader material with runtime controls
- `examples/particle-system.tsx` - GPU compute particles
- `examples/post-processing.tsx` - Effect pipeline
- `examples/earth-shader.tsx` - Complete Earth with atmosphere

### Templates
- `templates/r3f-project.tsx` - Starter project template
- `templates/compute-shader.tsx` - Compute shader template

### Reference
- `REFERENCE.md` - Quick reference cheatsheet

## Key Concepts

### Import Pattern
```tsx
// Always use the WebGPU entry point
import * as THREE from 'three/webgpu';
import { /* TSL functions */ } from 'three/tsl';
import { Canvas, useFrame, useThree, extend } from '@react-three/fiber';
```

`extend(THREE)` with the **`three/webgpu`** namespace is required — without it, `<meshStandardNodeMaterial />` and the other node materials don't exist as JSX elements.

### Node Materials
Replace standard material properties with TSL nodes, either as JSX props or on a memoized instance:
```tsx
<meshStandardNodeMaterial colorNode={colorNode} roughnessNode={float(0.5)} />

// or
material.colorNode = texture(map);        // instead of material.map
material.roughnessNode = float(0.5);      // instead of material.roughness
material.positionNode = displaced;        // vertex displacement
```

### ⚠️ Memoize every node graph
A TSL node built inline in JSX is rebuilt on every React render, and assigning a new node recompiles the shader. Build node graphs in `useMemo(() => ..., [])` and animate through `uniform()` values, never by re-deriving nodes:

```tsx
const { colorNode, strength } = useMemo(() => {
  const strength = uniform(1.0);
  return { colorNode: color(0xff0000).mul(strength), strength };
}, []);

useFrame(({ clock }) => { strength.value = Math.sin(clock.elapsedTime); });
```

This is the single most important R3F-specific rule. See `docs/r3f-integration.md`.

### Method Chaining
TSL uses method chaining for operations:
```tsx
// Instead of: sin(time * 2.0 + offset) * 0.5 + 0.5
time.mul(2.0).add(offset).sin().mul(0.5).add(0.5)
```

### Custom Functions
Use `Fn()` for reusable shader logic (define at module scope — it's static):
```tsx
const fresnel = Fn(([power = 2.0]) => {
  const nDotV = normalWorld.dot(viewDir).saturate();
  return float(1.0).sub(nDotV).pow(power);
});
```

### Render Loop
`renderer.setAnimationLoop()` and manual resize handling are gone — R3F owns both:
```tsx
useFrame((state, delta) => { /* per-frame updates */ });
```
Give `useFrame` a priority above 0 only when you are rendering yourself (post-processing).

## When to Use This Skill

- Setting up React Three Fiber with the WebGPU renderer
- Creating custom shader materials with TSL inside React components
- Writing GPU compute shaders dispatched from R3F
- Building post-processing pipelines in R3F
- Migrating from GLSL to TSL, or from vanilla Three.js WebGPU to R3F
- Implementing visual effects (particles, water, terrain, etc.)

## Resources

- [React Three Fiber Docs](https://r3f.docs.pmnd.rs/)
- [Three.js TSL Wiki](https://github.com/mrdoob/three.js/wiki/Three.js-Shading-Language)
- [WebGPU Examples](https://github.com/mrdoob/three.js/tree/master/examples) (files prefixed with `webgpu_`)

