Post-Processing
Sky Pro outputs linear HDR color through THREE.RenderPipeline. Apply exposure and HDR effects before tone mapping, then place tone mapping last before display output. The demo uses ACES Filmic, but other tone-mapping curves are supported.
Standard Setup
import { pass, vec4, acesFilmicToneMapping } from "three/tsl";
import { bloom } from "three/addons/tsl/display/BloomNode.js";
const sky = await SkySystem.create({ renderer, camera, scene });
const scenePass = pass(scene, camera);
let output = scenePass.getTextureNode("output");
// Add distance fog and god rays. Clouds already render as scene backdrops. Splice
// this in before exposure so the result gets exposed and can bloom. Passing the
// scene pass lets both post-processing stages read depth.
output = sky.applyTo(output, scenePass);
// Apply exposure as an explicit multiply BEFORE bloom, so bloom (and its
// threshold) operate in the same exposed display space as the tonemap.
output = vec4(output.rgb.mul(sky.atmosphere.exposure), output.a);
// HDR effects (bloom, DOF) belong on the (now exposed) linear signal.
output = output.add(bloom(output));
// Tonemap is the LAST step before the swapchain. Exposure was already
// applied above, so the curve runs at unit exposure (1.0).
const tonemapped = vec4(
acesFilmicToneMapping(output.rgb, 1.0),
output.a,
);
const postProcessing = new THREE.RenderPipeline(renderer, tonemapped);
function animate() {
sky.update(dt);
postProcessing.render();
}Exposure
atmosphere.exposure controls display brightness. Multiply it into the linear HDR signal before bloom and tone mapping. 1.0 is the neutral default. Higher values brighten the image; lower values darken it.
// neutral
sky.atmosphere.exposure.value = 1.0;If you skip the tonemap and render raw HDR to an LDR swapchain, every bright pixel will clip to white.
Tone Mapping Options
Three exposes the standard set in three/tsl:
| Function | Notes |
|---|---|
acesFilmicToneMapping | Filmic shoulder, slight warming. Default. |
agxToneMapping | More neutral hue, longer toe. |
neutralToneMapping | Khronos PBR Neutral — minimal hue shift. |
reinhardToneMapping | Low-cost luminance mapping with soft contrast. |
Replace acesFilmicToneMapping with the preferred curve. The demo exposes this setting under Post-Processing → Tonemapping → Curve.
What applyTo Does
applyTo runs two stages in order:
- Distance fog fades opaque geometry toward the sky color behind each pixel. It does not affect open sky or clouds. Set
atmosphere.fogDensityto0to disable it. - God rays add volumetric Mie scattering along the view ray. Scene depth and cloud depth stop shafts at the nearest occluder.
Both stages read depth from scenePass. Clouds render directly in the scene rather than in post-processing.
Place the result before exposure and bloom. sceneColor may be the scene output or the result of an earlier post-processing stage, such as Water Pro.
Turning Stages Off
Disable each stage with its corresponding setting:
// no distance fog
sky.atmosphere.fogDensity.value = 0;
// no shafts
sky.godRays.enabled = false;
// no clouds
sky.clouds.enabled = false;Tune the shafts with godRays.strength (brightness), godRays.sharpness (streak contrast), godRays.extinction (density/length), and godRays.maxDistance (reach). The tint follows the active light automatically. See GodRays for the full reference and limitations.
