Start here
Quick start
A working sky in an ordinary three.js scene. It has PBR reflections of the live clouds, a sun that sets on schedule, and cloud shadows sweeping across the ground.
This is the complete examples/basic/ integration, with commentary. Every step is required except where it says optional.
#Set up the renderer with tone mapping
The sky writes linear HDR. Give the renderer a tone mapper, or noon will clip to white.
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { SkySystem } from 'naturegl-sky';
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
renderer.setSize(innerWidth, innerHeight);
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);#Build your scene as usual
NatureGL Sky assumes metres (set metersPerUnit if your world uses other units) and a far plane that can see the horizon, since clouds start around 1–2 km up.
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(55, innerWidth / innerHeight, 0.5, 20000);
camera.position.set(0, 6, 22);
const ground = new THREE.Mesh(
new THREE.CircleGeometry(3000, 96).rotateX(-Math.PI / 2),
new THREE.MeshStandardMaterial({ color: 0x4f6b3a, roughness: 0.95 }),
);
ground.receiveShadow = true;
scene.add(ground);
const sun = new THREE.DirectionalLight();
sun.castShadow = true;
scene.add(sun, sun.target);#Create the sky
create() is async. It adds the backdrop mesh to your scene, runs the first bakes and pre-compiles the shaders, so the first frame is complete.
const sky = await SkySystem.create({
renderer, scene, camera,
quality: 'high', // low | medium | high | ultra
preset: 'partlyCloudy',
});#Wire the outputs into your scene
scene.environment = sky.environment; // PBR ambient + reflections
sky.addEventListener('environmentchange', () => {
scene.environment = sky.environment; // new texture after quality changes
});
sky.bindLights(sun); // sun by day, moon by night
sky.patchMaterial(ground.material); // cloud shadows on the ground
sky.clock.running = true; // optional: let time pass#Update, then render
Call update(dt) once per frame after moving the camera. The cloud reconstruction needs this frame's camera matrices.
const controls = new OrbitControls(camera, renderer.domElement);
const timer = new THREE.Timer();
renderer.setAnimationLoop(t => {
timer.update(t);
controls.update();
sky.update(timer.getDelta());
renderer.render(scene, camera); // a plain render: the sky is a mesh in your scene
});
addEventListener('resize', () => {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
sky.resize();
});marine preset, cloud shadows on the sand, and the sky reflected in the chrome sphere through scene.environment.#Change the weather
sky.applyPreset('storm'); // ease over ~1–2 s
sky.loadPreset('clear'); // snap, history reset
sky.setParams({ humidity: 0.8, wind: 0.6 }); // partial, eased
sky.setTime(18.25); // hours, eases the short way round
sky.sun.setFromAngles(8, 250); // elevation°, azimuth°