Guides
In your scene
NatureGL Fire renders into a scene you own. You place the simulation box in your world, feed it your meshes, give it your key light, and let its lights and embers join your scene graph.
#The contract
- Your scene stays yours.
render()draws yourscenewith yourcamera, then composites the fire over it. Nothing insrc/touches the DOM or adds scenery. - Three things are added to your scene:
fire.fireLightandfire.fillLight(unlessaddLights: false), andfire.embersif you add it yourself forcomposite().dispose()removes them. - The offscreen work is in
update(dt). Every solver pass, the light volume, the ember step and the GPU probe run there.dtis in seconds and clamped to 1/120–1/30 s per step, so a slow frame slows the fire down instead of making it unstable. - The fire lives in a box.
domainis in world units, which are treated as metres.
#Place the fire in your world
const fire = await FireSystem.create({
renderer, scene, camera,
domain: { center: [12, 2, -4], size: [3, 4, 3] }, // a smaller box, standing on y = 0
preset: 'torch',
});Presets are anchored to the box's floor centre, here (12, 0, -4). The torch preset's origin is 1.6 m above it. To put a preset somewhere else in the box, pass an origin or move it later:
fire.loadPreset('campfire', { origin: [12.5, 0, -4] });
fire.setOrigin(new THREE.Vector3(11.5, 0, -3.5));#Burn your own meshes
Presets refer to mesh slots. Pass your meshes at creation, register them later, or build mesh emitters directly. See Mesh emitters.
const fire = await FireSystem.create({ renderer, scene, camera, meshes: { logs: myLogs, shape: myStatue } });
fire.addEmitter({ type: 'mesh', mesh: burningCar, fuel: 9, temperature: 1.2 });#Match the scene lighting
The smoke is lit by one key light and an ambient term, which you set with setLighting(). Point them at your sun or moon so the smoke is lit from the same side as everything else. The demo aims the key light at its moon:
const MOON_DIR = new THREE.Vector3(-0.45, 0.75, -0.5).normalize();
fire.setLighting({ sunDirection: MOON_DIR });| Option | Type | |
|---|---|---|
sunDirection | Vector3 | Direction toward the key light (normalised for you) |
sunColor | Color or Vector3 | Key light colour |
sunIntensity | number | Multiplies sunColor (default 1) |
ambient | Color or Vector3 | Ambient colour. The light volume's upward transmittance shadows it inside thick smoke |
You can call it every frame, for example to follow a day/night cycle.
#Under a NatureGL Sky sky
NatureGL Sky exposes its key light (the sun by day, the moon at night) and its ambient as plain properties, so you can feed them straight to the fire:
renderer.setAnimationLoop(() => {
sky.update(dt);
fire.setLighting({
sunDirection: sky.keyLight.direction,
sunColor: sky.keyLight.color,
sunIntensity: sky.keyLight.intensity,
ambient: sky.ambient.color,
});
fire.update(dt);
// …render (see below)
});Both libraries want to finish the frame: NatureGL Sky's post pass and fire.render() each do bloom and tone mapping. To use both, render the scene once and chain the two linear-HDR composites. NatureGL Fire's composite() goes first, then NatureGL Sky's SkyPostPass.composite():
const post = sky.createPostPass();
scene.add(fire.embers);
renderer.setRenderTarget(sceneRT); // HalfFloat colour + DepthTexture
renderer.render(scene, camera); // your scene + the sky backdrop
fire.composite(sceneRT.texture, sceneRT.depthTexture, hdrRT);
post.composite(hdrRT.texture, sceneRT.depthTexture, camera); // fog, god rays, bloom, tone mapping#Your own post-processing
If you have an EffectComposer or your own passes, use composite() as the first HDR step and do bloom and tone mapping yourself. See composite(): your own pipeline.
#Siblings
The other packs render into the same kind of scene. NatureGL Weather and NatureGL Grass also take their light through setLighting.