Repository navigation
Volumetric Clouds
SparkEngine ships a ray-marched volumetric cloud model inspired by the Decima "Nubis" system and GPU Pro 7. Coverage, cloud type, and wetness are driven by a 2D weather map; density is modulated by a low-frequency Perlin base and detail-eroded by a high-frequency Worley noise; lighting is evaluated with the Henyey-Greenstein phase function and a multiple-scattering approximation.
Source: SparkEngine/Source/Graphics/VolumetricClouds.h
Namespace: Spark::Graphics
Tests: Tests/TestVolumetricClouds.cpp
- Overview
- Two-scale density model
- Settings
- Lighting & Phase Function
- CPU reference vs GPU path
- Weather map driver
- Usage
- Integration
- See Also
VolumetricCloudSystem is a singleton. It owns three small CPU noise
textures (base 32³, detail 16³, weather 64²) plus optional RHI-backed
3D textures for the GPU raymarch.
┌──────────────────────┐ weather map ┌───────────────────────┐
│ WeatherSystem │─── coverage/type ───▶│ VolumetricCloudSystem │
│ (rain, humidity) │ │ │
└──────────────────────┘ │ base noise (32³) │
│ detail noise (16³) │
┌──────────────────────┐ sun direction │ weather map (64²) │
│ Day/Night Cycle │─────────────────────▶│ │
└──────────────────────┘ │ CPU ray marcher │
│ GPU textures (RHI) │
└──────────┬────────────┘
│
▼
Sky rendering pass
Cloud density at a world-space point is evaluated as:
base = SampleBaseNoise(p * baseNoiseScale) // low-freq, Perlin-like
detail = SampleDetailNoise(p * detailNoiseScale) // high-freq, Worley-like
height = HeightGradient(altitude, cloudType) // stratus / cumulus / cumulonimbus
weather = SampleWeatherMap(p.xz * weatherScale) // coverage + type + rain
density = saturate(base * weather.coverage - (1 - detail) * detailStrength) * height
The two-scale separation means coverage can change at weather-map rate without forcing the detail noise to be retiled, and detail erosion can sharpen cloud edges without affecting the coarse silhouette.
VolumetricCloudSettings is a plain struct with the controls
operators want to touch:
| Field | Default | Meaning |
|---|---|---|
coverage |
0.55 |
Global coverage multiplier ([0..1]) |
cloudType |
0.5 |
0 stratus, 0.5 cumulus, 1 cumulonimbus |
density |
0.04 |
Peak extinction per metre |
anvilBias |
0.1 |
Flattens the top of cumulonimbus |
baseAltitude |
1500 m |
Bottom of the cloud layer |
topAltitude |
4000 m |
Top of the cloud layer |
baseNoiseScale |
1 / 2048 |
World-space frequency of the Perlin base |
detailNoiseScale |
1 / 128 |
World-space frequency of the Worley detail |
detailStrength |
0.35 |
How aggressively detail erodes the base |
weatherScale |
1 / 32768 |
World-space frequency of the weather map |
windDirection + windSpeed
|
(1,0,0) × 5 m/s |
UV advection of the noise textures |
phaseG0, phaseG1, phaseBlend
|
0.8, -0.3, 0.5 |
Dual-lobe Henyey-Greenstein |
silverLining |
0.6 |
Artistic front-lit bias |
marchSteps |
64 |
Primary raymarch steps (GPU quality hint) |
lightSteps |
6 |
Light raymarch steps |
lightMarchDistance |
600 m |
Shadow march depth toward the sun |
enabled |
true |
Master switch |
Each primary march step estimates in-scattered light with a dual-lobe Henyey-Greenstein phase function:
phase(cosθ) = lerp(HG(cosθ, g0), HG(cosθ, g1), blend)
g0 ≈ 0.8 produces a sharp forward lobe that gives clouds their bright
silver edge when the sun is behind them; g1 ≈ -0.3 produces the mild
back-scatter that keeps the shadowed side from going black. A short
secondary light march (lightSteps samples out to lightMarchDistance)
approximates in-scattering with a Beer-Lambert fall-off toward the sun.
-
CPU path. Everything the GPU does, the CPU also does — in
VolumetricCloudSystem::SampleAlongRay— so the model can be unit-tested headlessly (no device required).Tests/TestVolumetricClouds.cppexercises coverage, density, sample-along-ray, wind advection, and sun-direction invariants. -
GPU path.
CreateGPUResources(device)allocates two 3D textures (base + detail noise) and a 2D texture (weather).UploadToGPU(device)pushes the latest CPU noise/weather grids; the compute/pixel shader samples them with the same formulas for full resolution per-pixel raymarch.
The GPU shader lives in the same author-time HLSL tree as the rest of
the sky pipeline — it consumes the textures exposed by
GetBaseNoiseTexture(), GetDetailNoiseTexture(), and
GetWeatherMapTexture().
The weather map is a 64×64 RG texture where:
- R channel = local coverage override
- G channel = local cloud type
SetWeather(coverage, cloudType, rain) mixes the authored weather
texture with a dynamic overlay so WeatherSystem can push
rain/humidity/coverage from the simulation without stomping the
artist-authored map. The rain value also feeds the wetness darkening
factor applied at integration time.
#include "Graphics/VolumetricClouds.h"
auto& clouds = Spark::Graphics::VolumetricCloudSystem::GetInstance();
Spark::Graphics::VolumetricCloudSettings settings;
settings.coverage = 0.55f;
settings.cloudType = 0.7f; // lean toward cumulonimbus
settings.windDirectionX = 1.0f;
settings.windSpeed = 8.0f;
clouds.Initialize(settings);
// Per frame:
clouds.Update(dt);
clouds.SetSunDirection(sun.x, sun.y, sun.z);
clouds.SetWeather(weather.coverage, weather.cloudType, weather.rain);
// Optional CPU sample (for ambient probes, shadow queries, tests):
auto s = clouds.SampleAlongRay(origin.x, origin.y, origin.z,
dir.x, dir.y, dir.z,
20'000.0f);
sky.AddInscatter(s.luminanceR, s.luminanceG, s.luminanceB);
sky.MultiplyTransmittance(s.transmittance);For the GPU path, create resources once after an RHI device is available and re-upload whenever the CPU noise is regenerated:
clouds.CreateGPUResources(rhiDevice);
// ... on settings change:
clouds.UploadToGPU(rhiDevice);-
Sky rendering —
SkyAtmospherecomposites the inscattered cloud luminance and transmittance over the analytical sky model so clouds inherit the Preetham sun/horizon colour. -
Volumetric fog —
FroxelVolumetricFogruns underneath the cloud layer and shares the sun direction + wetness inputs for consistent weather transitions. -
Weather system —
WeatherSystem::Tickforwards(coverage, cloudType, rain)toSetWeatherevery frame. -
Day/Night cycle — the cycle pushes
SetSunDirection+ sun colour so a single update propagates to sky, clouds, and fog in lockstep.
- Sky and Atmosphere — base sky model
- Volumetric Fog — ground-level volumetrics
- Day Night Cycle and Weather
-
Tests/TestVolumetricClouds.cpp— reference test suite
Published from 2b03dc797148. Edit the canonical source in wiki/.
- Documentation
- Docs route
- Wiki index
- Guides
- Tutorials
- Samples
- Examples
- API Reference
- API route
- Reference
- Build Guide
- Dependencies
- FAQ
- Changelog
- Roadmap
- Contributing
- Code of Conduct
- Home
- FAQ
- Getting Started
- Quick-Start Tutorial
- Making Your First Game
- Making Your First Multiplayer Game
- Artist Workflow Guide
- Editor Walkthrough
- Migration Guide
- How SparkEngine Works
- Architecture Overview
- Engine Architecture Flowchart
- Creating a Game Module
- Game Modules (catalog)
- Entity Component System
- Rendering and Graphics
- Physics
- Cloth Simulation
- Audio
- Input System
- Camera System
- Scripting with AngelScript
- Visual Scripting
- AI and Navigation
- Animation
- 2D Systems
- Networking
- Dedicated Server
- Multiplayer Quick Start
- Area Server Architecture
- Scene Management
- Large World Support
- Collaborative Editing
- Coroutine System
- Event System
- Event Response System
- Job System
- UI System
- UI Layout Extensions
- Localization
- Dialogue System
- Destruction System
- Replay System
- Achievement System
- Loading System
- Mod System
- Content Delivery
- Tween System
- Memory Integrity
- Gameplay Systems
- Terrain and Procedural Generation
- Save System
- Persistence System
- Day Night Cycle and Weather
- Cinematic Sequencer
- Runtime Prefabs
- SparkEditor
- Editor Tutorials
- SparkConsole
- SparkDaemon
- Shader Pipeline
- Asset Pipeline
- Asset Validation
- Asset Migration
- Game Packaging
- Online Services
- DataTable System
- Loot and Crafting System
- CSG System
- Font System
- Timer Manager
- Movie Render Pipeline
- HLOD and World Partition
- Remote Debug System
- Selection Manager
- Asset Dependency Graph
- Editor Automation
- File Watcher
- Project Templates
- System Requirements
- VR Support
- Mobile Platform
- Accessibility
- Platform Input
- Platform Certification
- Cross-Compilation: Wine Testing
- RHI Abstraction Layer
- D3D11 Backend
- D3D12 Backend
- Vulkan Backend
- OpenGL Backend
- Metal Backend
- DXR Raytracing
- Hybrid Ray Tracing
- Upscaling (DLSS/FSR)
- Render Graph
- Shader Graph
- GPU Particles
- GPU-Driven Rendering
- Volumetric Fog
- Volumetric Clouds
- Global Illumination
- Virtual Texturing
- Water Rendering
- Clustered Lighting
- Material System
- Post-Processing
- Shadow System
- Particle System
- Decal System
- Sky and Atmosphere
- Foliage System
- Mesh Shaders
- Neural Rendering
- Configuration Reference
- Performance Tips
- Benchmark Framework
- Threading Model
- Fuzz Policy and Parser Security
- Memory Safety
- Memory Management Patterns
- Build System and CMake Modules
- Profiler and Debugging
- Performance Profiling Guide
- Telemetry System
- Crash Reporting
- Golden Image Testing
- Utilities
- Testing
- Fuzz Policy and Parser Security
- Codebase Statistics
- Codebase Health
- Error Handling Patterns
- Hot Reload Overview
- Troubleshooting
- Contributing
- Workflow Patterns
- Build Optimizations
- CI Reproducible Builds
- GitHub API and PR Checks
- Git Rebase Conflicts
- Clang-Format
- Code Quality Violations
- AI Bloat Pattern
- MinGW + Wine Cross-Compilation
- Live Editor Testing
- Engine & Renderer Landscape
- DuetOS Portability Catalog
- Five-Engine Analysis
- Eleven-Engine Analysis
- ThorVG / Unity Graphics Analysis
- Advanced Techniques Catalog
- Third-Party Library Evaluation
- Engine Viability Evaluation
- Engine Feature Recommendations
- Project Recommendations
- Mac Compatibility Analysis
- Codebase Observations
- Codebase Bloat Audit
- Test Suite Audit
- Documentation Coverage Audit
- ThirdParty Dependencies Audit
- Load Test Baseline
- Gameplay Systems Status
- SparkGame Module Status
- Stub and Abandoned Features
- Memory Integrity System
- Memory Safety Evaluation
- Hardware Acceleration Systems
- Jolt Physics Integration
- GPU/CPU Separation Plan
- Daemon Services Architecture
- Reflection & Polymorphism Refactoring Plan
- SparkBuild In-Tree
- Wine No-JobSystem Breakthrough
- Wine Role and Fallback Tiers