Skip to content

Sky & Atmosphere

Strata’s sky system provides physically-based atmospheric scattering with a dynamic day/night cycle, stars, sun/moon positioning, and horizon fog blending.

import { ProceduralSky } from '@strata-game-library/core';
<ProceduralSky sunPosition={[100, 50, 100]} />

Complete procedural sky with all features:

import { ProceduralSky, createTimeOfDay } from '@strata-game-library/core';
<ProceduralSky
// Sun position (can use sunPosition or timeOfDay)
sunPosition={[100, 50, 100]}
// OR
timeOfDay={createTimeOfDay(14, 30)} // 2:30 PM
// Atmosphere
turbidity={10} // Haziness (2-20)
rayleigh={2} // Blue scattering
mieCoefficient={0.005} // Sun halo
mieDirectionalG={0.8} // Halo sharpness
// Sun
sunIntensity={1}
sunColor="#ffffff"
sunSize={0.04}
// Moon (visible at night)
moon
moonPhase={0.5} // 0=new, 0.5=full, 1=new
moonIntensity={0.1}
// Stars
stars
starCount={5000}
starBrightness={1}
starTwinkle
// Horizon
horizonFog
horizonColor="#8899aa"
horizonBlend={0.3}
// Exposure
exposure={0.5}
/>
PropTypeDefaultDescription
sunPosition[number, number, number][0, 1, 0]Sun position vector
timeOfDayTimeOfDay-Time-based sun position
turbiditynumber10Atmospheric haziness
rayleighnumber2Blue sky scattering
mieCoefficientnumber0.005Sun halo coefficient
mieDirectionalGnumber0.8Halo directionality
sunIntensitynumber1Sun brightness
moonbooleanfalseShow moon at night
starsbooleanfalseShow stars at night
horizonFogbooleanfalseFog at horizon
import { createTimeOfDay } from '@strata-game-library/core';
// Specific time
const noon = createTimeOfDay(12, 0); // 12:00 PM
const sunset = createTimeOfDay(18, 30); // 6:30 PM
const midnight = createTimeOfDay(0, 0); // 12:00 AM
<ProceduralSky timeOfDay={noon} />
import { useState, useEffect } from 'react';
import { createTimeOfDay } from '@strata-game-library/core';
function AnimatedSky() {
const [hour, setHour] = useState(12);
useEffect(() => {
const interval = setInterval(() => {
setHour(h => (h + 0.05) % 24); // Cycle through day
}, 50);
return () => clearInterval(interval);
}, []);
const minutes = (hour % 1) * 60;
return (
<ProceduralSky
timeOfDay={createTimeOfDay(Math.floor(hour), minutes)}
stars
moon
/>
);
}
import { calculateSunPosition } from '@strata-game-library/core';
const sunPos = calculateSunPosition({
latitude: 40.7128, // NYC
longitude: -74.0060,
date: new Date(),
timezone: -5
});
<ProceduralSky sunPosition={sunPos} />

Controls blue sky color:

// Deep blue sky
<ProceduralSky rayleigh={3} turbidity={2} />
// Pale sky
<ProceduralSky rayleigh={0.5} turbidity={15} />
// Alien purple sky
<ProceduralSky
rayleigh={4}
rayleighColor={[0.5, 0.2, 0.8]} // Custom scattering
/>

Controls sun halo:

// Large soft halo
<ProceduralSky mieCoefficient={0.01} mieDirectionalG={0.7} />
// Small sharp halo
<ProceduralSky mieCoefficient={0.003} mieDirectionalG={0.95} />
// No halo
<ProceduralSky mieCoefficient={0} />

Controls atmospheric haziness:

// Crystal clear
<ProceduralSky turbidity={2} />
// Light haze
<ProceduralSky turbidity={10} />
// Heavy fog/smog
<ProceduralSky turbidity={20} />
<ProceduralSky
sunSize={0.06} // Larger sun
sunIntensity={1.5} // Brighter
sunColor="#ffdd88" // Warm color
sunCorona // Add corona effect
sunCoronaSize={0.2}
/>
<ProceduralSky
moon
moonPhase={0.5} // Full moon
moonSize={0.03}
moonIntensity={0.15}
moonColor="#eeeeee"
moonTexture={moonTexture} // Optional texture
/>
<ProceduralSky
stars
starCount={8000}
starBrightness={1.2}
starTwinkle
starTwinkleSpeed={0.5}
// Milky Way (optional)
milkyWay
milkyWayTexture={milkyWayTexture}
milkyWayIntensity={0.3}
/>
import { SkyPresets } from '@strata-game-library/presets';
<ProceduralSky {...SkyPresets.CLEAR_DAY} />
<ProceduralSky {...SkyPresets.SUNSET} />
// Or manual
<ProceduralSky
timeOfDay={createTimeOfDay(18, 45)}
turbidity={8}
rayleigh={1}
mieCoefficient={0.01}
/>
<ProceduralSky {...SkyPresets.OVERCAST} />
// Or manual
<ProceduralSky
turbidity={20}
rayleigh={0.5}
exposure={0.3}
/>
<ProceduralSky {...SkyPresets.NIGHT} />
// Or manual
<ProceduralSky
timeOfDay={createTimeOfDay(2, 0)}
stars
starCount={8000}
moon
moonPhase={0.75}
/>
<ProceduralSky
// Purple sky
rayleighColor={[0.4, 0.1, 0.6]}
rayleigh={5}
// Green sun
sunColor="#88ff44"
sunSize={0.1}
// Two moons
moons={[
{ phase: 0.3, size: 0.05, color: '#ff8844' },
{ phase: 0.7, size: 0.02, color: '#88ffff' }
]}
/>

The sky automatically provides scene lighting:

import { ProceduralSky, SkyLight } from '@strata-game-library/core';
<ProceduralSky timeOfDay={createTimeOfDay(14, 0)}>
{/* Directional light follows sun */}
<SkyLight
intensity={1.2}
castShadow
shadow-mapSize={[2048, 2048]}
/>
</ProceduralSky>
// Or manually link
const skyRef = useRef();
const lightRef = useRef();
useFrame(() => {
if (skyRef.current && lightRef.current) {
lightRef.current.position.copy(skyRef.current.sunPosition);
}
});

Use sky shaders directly:

import {
skyVertexShader,
skyFragmentShader,
atmosphereVertexShader,
atmosphereFragmentShader
} from '@strata-game-library/shaders';
const skyMaterial = new THREE.ShaderMaterial({
vertexShader: skyVertexShader,
fragmentShader: skyFragmentShader,
uniforms: {
sunPosition: { value: new THREE.Vector3(100, 50, 100) },
turbidity: { value: 10 },
rayleigh: { value: 2 },
mieCoefficient: { value: 0.005 },
mieDirectionalG: { value: 0.8 }
},
side: THREE.BackSide
});

The sky shader is efficient, but consider:

// Mobile optimization
<ProceduralSky
stars={false} // Disable stars
moon={false} // Disable moon
resolution={256} // Lower sky resolution
/>
// Desktop
<ProceduralSky
stars
starCount={5000}
moon
resolution={512}
/>

See the interactive sky & volumetrics demo running live in your browser.

View Live Demo | View Source