web/examples/sky/README.md
This sample demonstrates a fully procedural, single-pass skybox shader capable of simulating a dynamic day-night cycle, atmospheric scattering, volumetric clouds, and water reflections.
It is designed for graphics engineers and technical artists who need a lightweight yet physically plausible environment background without relying on static HDRI textures.
The shader uses a "Uber-Shader" approach where all features are computed per-pixel. Features can be toggled or tuned via uniforms to balance quality vs performance.
| Feature | Cost | Control | Description |
|---|---|---|---|
| Atmosphere | 🟡 Medium | turbidity, rayleigh, mie | Analytic Rayleigh & Mie scattering. Physically based colors. |
| Sun Disk | 🟢 Low | sunHalo (Radius, Limb) | Analytic sphere intersection with limb darkening. Conservation of energy (Lux). |
| Moon & Earthshine | 🟢 Low | sunHalo2, moonIntensity | Resolved moon disk with geometric phases and dynamic Earthshine. |
| Stars | 🟢 Low | starControl (Density) | High-frequency procedural noise. Occluded by clouds/moon. |
| Clouds | 🔴 High | cloudControl (Coverage, Density) | 4-Octave 3D Fractal Brownian Motion (FBM). Dominates the cost when enabled. |
| Heat Shimmer | 🟡 Medium | shimmerControl | UV perturbation near the horizon to simulate mirages. |
| Water Reflection | 🟣 Very High | waterControl | Renders the sky twice. Includes procedural waves (FBM) and fresnel. |
Note: Rendering water (
V.y < 0) is significantly more expensive (~2.5x) than the sky because it requires re-evaluating the atmospheric scattering and cloud noise for the reflection vector.
Based on the Hoffman & Preetham model. It solves the single-scattering integral analytically for air molecules (Rayleigh) and aerosols (Mie).
Clouds are rendered as a spherical shell at a specific altitude.
When looking below the horizon, the shader switches to "Water Mode".
Applies a custom tone mapping curve that varies with Sun Elevation.
To use this in your own Filament application:
Compile the Material:
Use matc to compile simulated_skybox.mat into a .filamat file.
matc -p mobile -a opengl -o assets/simulated_skybox.filamat simulated_skybox.mat
Load in JavaScript/C++: Create a Skybox entity and assign the material.
// JavaScript Example
const material = engine.createMaterial('assets/simulated_skybox.filamat');
const skybox = engine.createSkybox(material);
scene.setSkybox(skybox);
Update Uniforms:
The shader requires specific uniforms (Sun Direction, Time, etc.) to be updated every frame. See SimulatedSkybox.js for a reference implementation of the uniform buffer management.