Sky and Backdrop
Source: room-at-dawn (MIT), from src/scene/sky.js, src/scene/parts/exterior.js.
Core idea: Describe the sky only once.
- The baker uses an analytical sky: a gradient from horizon to zenith, plus a glow around the sun direction.
- The visible sky dome adds clouds on top of the same gradient, but preserves the same average brightness as the gradient: sky between clouds is darker than average, cloud edges brighter, cloud centers roughly equal.
- This way the sky seen through the window matches the light falling into the room.
measureDomeverifies this.
Files
| Path | Content |
|---|---|
scripts/sky.js | SKIES (dawn, day, overcast, golden), skyRadiance (same formula as the threejs-baked-gi worker), bakeCfg, skyDome, SKY_U (uTime), skyLights, skyEnvironment, measureDome |
scripts/backdrop.js | windowVisibility (window hole visibility with LOD), hazePatch (atmospheric haze, preserves existing shader patches), grassTexture, roofTexture, windowTexture, crownTexture, Soup, houses, lawn, gravelPath, hedge, crownWall |
example/ | Second-floor room (floor 5.5 m above garden) looking out at: lawn, path, hedge, three houses, trees, distant tree wall |
example/preview*.jpg | Four skies from inside the room; in front of window, looking up; outside overview |
references/sky.md | Each layer of the sky shader, default parameters, how to adjust, integration with baking |
references/backdrop.md | Visibility culling, haze, each backdrop element, performance data, known issues, porting to other engines |
The example trees use threejs-procedural-vegetation (relative path ../../threejs-procedural-vegetation/).
Running the Example
cd <skill folder>/.. && python3 -m http.server 5426 --bind 127.0.0.1
# http://127.0.0.1:5426/threejs-sky-backdrop/example/
(<skill folder> is the Base directory shown when loading this skill; when installed as a plugin, it's under ~/.claude/plugins/cache/)
?sky=dawn|day|overcast|golden: Sky preset.?cam=window|wide|up|out: View from room / in front of window / looking up / outside overview.?cull=0: Disable visibility culling for comparison.?t=5: Freeze time, clouds don't move.
window.__sky contains timing, triangle count, leaf count, and the ratio of the sky dome to the analytical sky.
Usage
import { SKIES, skyDome, bakeCfg, skyLights, skyEnvironment, measureDome, SKY_U } from './scripts/sky.js';
const S = SKIES.dawn;
scene.add(skyDome(S)); // Baked interior: display 0.3 (default); outdoors: skyDome(S, { display: 1 })
const cfg = { ...bakeCfg(S), portal, room }; // Pass to threejs-baked-gi's runBake
// Unbaked scene:
const { sun, hemi } = skyLights(S); scene.add(hemi); if (sun) scene.add(sun, sun.target);
scene.environment = skyEnvironment(renderer, S);
console.log(measureDome(renderer, S)); // ratio 0.85–1.15
renderer.setAnimationLoop((ms) => { SKY_U.uTime.value = ms / 1000; ... });
Must Follow
- Describe the sky only once: Baking, sky dome, and lights all come from the same preset. If you change the sky color, rebake.
- Run
measureDomeafter adjusting clouds. It renders the sky dome into a float cube map, computes the upper hemisphere average weighted by cos, and compares it to the analytical sky.- Ratio must be between 0.85–1.15, otherwise the sky outside won't match the light coming in.
- Adding
{ pure: true }renders only the gradient; the result must be exactly 1.000, confirming the measurement itself is correct.
- Cloud colors are absolute brightness, in the same unit as the sky, not a multiplier. I tried scaling them with the gradient, but the dawn ratio dropped to 0.73, so I reverted to the original project's approach.
- In a baked interior, draw the sky dome darker (
displayaround 0.3). Exposure is set for the interior; drawing the sky at full brightness washes it out to white, losing color—this is unrelated to lighting intensity. - Only build what is visible.
windowVisibilitylooks from multiple eye positions inside the room, through window openings with thickness.- Invisible leaves: return 0 from the vegetation skill's
lodAt, leaving only a few large cards so that baking still produces shadows. - Leaves only visible at an angle: return 1, sparser.
- Invisible leaves: return 0 from the vegetation skill's
- Apply
hazePatchto the backdrop. Beyond 10 m, colors fade toward the horizon; otherwise distant houses and trees look as deep and saturated as close objects, like stickers.
Benchmarks (RTX 4090, Chrome headless, 1280×800)
| Item | Value |
|---|---|
| Sky dome ÷ analytical sky | dawn 0.934, day 1.080, overcast 1.034, golden 1.034; pure mode 1.000 |
| Backdrop (lawn, path, hedge, houses, tree wall) | 31–34 ms |
| Trees (4 main, 8 mid, 26 distant) | Generation 0.14–0.16 s, mesh construction 0.31 s |
| Visibility culling | Leaves 117,808 → 97,589 (−17%), triangles 425k → 383k. Savings mainly from trees flush against the outer wall and on both sides of the windows |
| Sky environment map plus two measurements | ~0.09 s |