Composable TSL (Three.js Shading Language) nodes and utilities for Three.js WebGPU. A collection of reusable shader building blocks for waves, morphing, raymarching, and procedural effects.
- 🌊 Wave Displacement - Spherical wave displacement with simplex noise modulation
- 🔀 Mesh Morphing - Smooth position-based geometry morphing
- 🎯 Raymarching - Adaptive raymarching and volumetric rendering utilities
- ⚡ Thunder Lightning - Volumetric contained-lightning with fluid-driven filaments
- 🧩 Composable - Pure TSL nodes that compose naturally with Three.js WebGPU
- 📦 Tree-shakeable - Modular exports for optimal bundle size
- 🎨 Example Gallery - 13+ interactive examples showcasing different techniques
pnpm add @pipefold/lib3Or with npm:
npm install @pipefold/lib3Requirements:
- Three.js >= 0.180.0 with WebGPU support
- Modern browser with WebGPU support
import * as THREE from "three/webgpu";
import { sphericalWaveDisplacement } from "@pipefold/lib3/waves";
import { float, vec3 } from "three/tsl";
// Create material with wave displacement
const material = new THREE.MeshStandardNodeMaterial();
material.positionNode = sphericalWaveDisplacement({
pos: positionGeometry,
phase: float(time),
waveAmplitude: float(0.2),
noiseScale: float(1.0),
noiseAmplitude: float(0.5),
center: vec3(0, 0, 0),
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);Creates spherical wave displacement with noise modulation.
Parameters:
pos- vec3: Position in local/object spacephase- float: Animation phase (typically time-based)waveAmplitude- float: Base wave amplitude (default: 0.2)noiseScale- float: Scale of noise modulation (default: 1.0)noiseAmplitude- float: Amplitude of noise effect (default: 0.5)center- vec3: Center point of spherical waves (default: vec3(0))
Returns: vec3 displacement
Compute displaced sampling coordinates for texture space [0,1]³.
Parameters:
texCoord- vec3: Original texture coordinatephase,waveAmplitude,noiseScale,noiseAmplitude- Same as abovescale- float: Displacement scale factor (default: 0.1)
Returns: vec3 displaced coordinate
Build a compute shader kernel for 3D texture displacement.
Parameters:
width,height,depth- numbers: Texture dimensionsstorageTexture- StorageTextureNode: Output texturesourceTextureNode- TextureNode: Input texturewaveAmplitude,noiseScale,noiseAmplitude,phase- uniformsintensityScale- uniform: Intensity multiplier (default: 1.0)
High-quality 3D simplex noise function.
Parameters:
v- vec3: Input position
Returns: float in [-1, 1]
Interpolate between geometry positions.
Parameters:
mixFactor- float: Blend factor [0,1] (default: 0)
Returns: vec3 morphed position
Usage:
// Add target positions as attribute
geometry.setAttribute(
"targetPosition",
new THREE.BufferAttribute(targetPositions, 3)
);
material.positionNode = knotMorphPosition({
mixFactor: float(animationValue),
});Volumetric contained-lightning effect driven by fluid simulation fields.
Creates a TSL raymarching node that renders lightning filaments inside a unit box.
Parameters:
densityTexture- Data3DTexture: Fluid density texturepressureTexture- Data3DTexture: Fluid pressure texturecurlTexture- Data3DTexture: Fluid curl texturepreset- object: Initial uniform values (default:THUNDER_PRESETS['Contained Cocoon'])
Returns: { node, uniforms } — the TSL node and all thunder uniforms
Creates the JS state machine that drives charge build-up and stochastic flash discharge.
Parameters:
uniforms- object: The uniforms returned bycreateThunderNodeconfig- object: Optional preset config (default: Contained Cocoon)
Returns: { update(dt), triggerFlash(), setPreset(name) }
Named parameter presets: 'Contained Cocoon', 'Silent Pressure', 'Caged Arc Storm', 'Overcharged Core'
Usage:
import { createThunderNode, createThunderStateMachine } from "@pipefold/lib3/thunder";
const { node, uniforms } = createThunderNode({
densityTexture: fluid.getDensityTexture3D(),
pressureTexture: fluid.getPressureTexture3D(),
curlTexture: fluid.getCurlTexture3D(),
});
const thunder = createThunderStateMachine(uniforms);
thunder.setPreset('Caged Arc Storm');
// In animation loop:
thunder.update(deltaTime);Adaptive distance-field raymarching within a unit box [-0.5, 0.5]³.
Parameters:
maxSteps- int: Maximum raymarch iterationscallback- Function:({ positionRay, maxStep }) => deltadistance functionthreshold- float: Hit detection threshold (default: 0.001)
Returns: Object with { positionRay, t, bounds, hit }
Average intensity projection for volumetric rendering.
Parameters:
texture- Texture3DNode: 3D volume texturesteps- int: Number of samplesintensityScale- float: Intensity multiplier (default: 1.0)
Returns: vec4 color
The package includes 13+ examples demonstrating various techniques:
- hello-world - Basic TSL function usage
- knot-morph - Geometry morphing between torus knots
- raymarch-head - 3D medical data visualization
- raymarch-head-wave-displacement - Volumetric waves
- portal-door-transition - Portal effects
- cinematic-gallery - Lighting and materials showcase
- wispy-projector-beams - Volumetric light beams
- anisotropic-fbm-streaks - Procedural noise patterns
- And more...
# Development server with example gallery
pnpm dev
# Build examples for deployment
pnpm build:examplesNavigate to http://localhost:5173 to see the example gallery.
# Install dependencies
pnpm install
# Build library
pnpm build
# Development mode (examples)
pnpm devlib3/
├── src/
│ ├── index.js # Main exports
│ ├── waves.js # Wave displacement functions
│ ├── knotMorph.js # Morphing utilities
│ ├── raymarch.js # Raymarching functions
│ ├── fluidSim.js # SmokeVolume fluid simulation
│ ├── smokeMaterial.js # Volumetric smoke material
│ ├── blueNoise.js # Compute mip-aware blue noise
│ └── thunder.js # Contained thunder effect
├── examples/ # Interactive examples
├── dist/ # Built library (published)
└── package.json
The package provides multiple entry points for tree-shaking:
// Main bundle (all utilities)
import { sphericalWaveDisplacement, knotMorphPosition } from "@pipefold/lib3";
// Individual modules (smaller bundles)
import { sphericalWaveDisplacement } from "@pipefold/lib3/waves";
import { knotMorphPosition } from "@pipefold/lib3/knotMorph";
import { createThunderNode, THUNDER_PRESETS } from "@pipefold/lib3/thunder";This library requires Three.js with WebGPU support. Import from three/webgpu:
import * as THREE from "three/webgpu";
import /* TSL nodes */ "three/tsl";Check browser compatibility: WebGPU Status
MIT
Contributions are welcome! Please feel free to submit issues or pull requests.