Advanced guide: Dynamic sky and fog¶
Time: ~15 minutes Level: Intermediate What you'll build: A scene with a time-of-day sun cycle and atmospheric fog
Overview¶
SceneView 3.2.0 adds two atmospheric composables:
DynamicSkyNode— drives a sun light based on time-of-day (sunrise, noon, sunset, night)FogNode— applies volumetric fog to the scene
Both are declarative: just change a parameter and the scene reacts.
Step 1 — Add a dynamic sun¶
@Composable
fun SkyScreen() {
val engine = rememberEngine()
val modelLoader = rememberModelLoader(engine)
// Animate time from 0 (midnight) to 24 over 30 seconds
val infiniteTransition = rememberInfiniteTransition(label = "DayCycle")
val timeOfDay by infiniteTransition.animateFloat(
initialValue = 6f, // sunrise
targetValue = 18f, // sunset
animationSpec = infiniteRepeatable(
animation = tween(durationMillis = 30_000, easing = LinearEasing),
repeatMode = RepeatMode.Reverse
),
label = "time"
)
Scene(engine = engine, modelLoader = modelLoader) {
DynamicSkyNode(
timeOfDay = timeOfDay, // 0–24 hour float
turbidity = 2f, // atmospheric haze [1–10]
sunIntensity = 110_000f // max illuminance at noon (lux)
)
// Place your model here — it will be lit by the sun
rememberModelInstance(modelLoader, "models/scene.glb")?.let {
ModelNode(modelInstance = it)
}
}
}
Sun colour model¶
| Time | Appearance |
|---|---|
| 0–5 (night) | Near-black, minimal light |
| 6 (sunrise) | Warm orange-red |
| 12 (noon) | Bright white (1.0, 0.98, 0.95) |
| 18 (sunset) | Warm orange-red |
| 19–24 (night) | Near-black |
Step 2 — Add atmospheric fog¶
val view = rememberView(engine)
var fogEnabled by remember { mutableStateOf(true) }
var fogDensity by remember { mutableFloatStateOf(0.05f) }
Scene(engine = engine, modelLoader = modelLoader, view = view) {
DynamicSkyNode(timeOfDay = timeOfDay)
FogNode(
view = view,
enabled = fogEnabled,
density = fogDensity, // [0.0–1.0], higher = thicker
height = 1.0f, // fog is denser below this Y
color = Color(0xFFCCDDFF) // light blue-grey
)
// Your scene content
}
Fog parameters¶
| Parameter | Effect |
|---|---|
density |
Volumetric fog thickness [0.0, 1.0]. Try 0.02 for light haze, 0.15 for dense fog |
height |
Height falloff — fog is denser below this world-space Y |
color |
Fog colour. Match your sky tint for realism |
enabled |
Toggle fog on/off reactively |
Step 3 — Combine sky + fog for atmosphere¶
The real power is combining both. As the sun sets, increase fog density for a moody twilight:
val fogDensity = if (timeOfDay in 6f..18f) 0.02f else 0.12f
Scene(engine = engine, modelLoader = modelLoader, view = view) {
DynamicSkyNode(timeOfDay = timeOfDay, turbidity = 3f)
FogNode(view = view, density = fogDensity, color = Color(0xFFEED8AA))
}
What's next¶
- See the
dynamic-skysample for a full interactive implementation with a time slider - Combine with
ReflectionProbeNodefor indoor/outdoor transitions