smoke
smoke(node : Node<Texture>, options : SmokeOptions) : NodeSmoke Simulation (TSL) – a 2D velocity–pressure solver that runs in screen space.
Turns a fullscreen pass into a stylized, real-time smoke/ink flow using WebGPU compute through Three.js TSL. Uses StorageTexture resources and takes advantage of Tier2 read–write access whenever the adapter exposes it. It owns and ping-pongs its internal textures (velocity, pressure, density, curl, divergence) and updates itself every frame when used in a PostProcessing chain.
Features
- Semi-Lagrangian advection for velocity and density
- Vorticity confinement (curl) and divergence-free projection (pressure solve)
- Configurable dissipation, pressure iterations and curl strength
- Optional pointer-driven splats via a
vec2uniform (no global dispatcher) - Drop-in for post-processing:
postProcessing.outputNode = smoke(scenePass, { ... })
Example: Basic postprocessing setup
Example: Interactive pointer-driven splats
import { smoke } from '@three-blocks/core';
import { uniform } from 'three/tsl';
import { Vector2 } from 'three/webgpu';
// Create a uniform to track pointer position in NDC [-1, 1]
const pointer = uniform(new Vector2(0, 0));
const fluidNode = smoke(scenePass, {
pointer: pointer.value, // Pass the Vector2 directly
pointerScale: 3, // Stronger splat force
radius: 0.3 // Larger splat radius
});
// Update pointer on mouse move
document.addEventListener('mousemove', (e) => {
pointer.value.x = (e.clientX / window.innerWidth) * 2 - 1;
pointer.value.y = -(e.clientY / window.innerHeight) * 2 + 1;
});
Parameters
nodeoptionalNode<Texture>Scene/texture input to chain from (e.g. result of
pass(scene, camera)).optionsoptionalSmokeOptionsConfiguration options.
Returns
Node — Color node sampling the current dye texture of the fluid simulation.Example
import * as THREE from 'three/webgpu';
import { pass } from 'three/tsl';
import { smoke } from '@three-blocks/core';
// Create renderer, scene, camera
const renderer = new THREE.WebGPURenderer();
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight);
// Setup postprocessing with smoke effect
const postProcessing = new THREE.PostProcessing(renderer);
const scenePass = pass(scene, camera);
// Apply smoke simulation as post effect
const fluidNode = smoke(scenePass, {
simRes: 128,
dyeRes: 512,
curlStrength: 30,
densityDissipation: 0.98
});
postProcessing.outputNode = fluidNode;
// Render loop
function animate() {
requestAnimationFrame(animate);
postProcessing.render();
}