Feature Preview: Volumetric Fog
Hello again and welcome to the Flax Facts!
Recently we’re doing many feature previews (profiler, game cooker) and that’s because there are tons of new stuff going on here.
So every time something new shows up, we’re very excited to show it to you.
Today we’re gonna talk about the very cool visual effect which is: volumetric fog.
What is it? How it looks like and how to use it? Let’s begin!
Foggy environment with realistic light shafts
Purple Haze
Volumetric fog is a visual effect that renders realistic looking fog (as shown in a picture above).
The presented technique is based on two presentations:
- Volumetric fog: Unified, compute shader based solution to atmospheric scattering – Bart Wronski at Siggraph 2014 (link)
- Physically Based and Unified Volumetric Rendering in Frostbite – Sebastien Hillaire at Siggraph 2015 (link)
It features variable fog density, light scattering, volumetric albedo/emissive color, highly customizable parameters and solid performance.
It’s important to say that it isn’t a post-process effect or any other image-based trick but fully standalone visual feature that tries to push fog rendering into the limits.
The algorithm itself uses 3D textures as an intermediate data storage and whole logic is performed by Compute shaders with UAVs on GPU.
This results in efficiency and ability to render volumetric fog fully async during e.g. lighting pass.
What is even more, effect outputs a single 3D texture with fog color and fog density for every mapped world position in 3D space so it can be used not only by the deferred renderer (using fullscreen apply or similar) but also inside forward rendering shaders which gives more opportunities to take advantage of it.
Now let’s break down the algorithm and put some more light on it (as shown in a picture below).
Light shafts coming into the foggy library through the window
Algorithm overview
All 3D textures used by the algorithm are aligned to the viewport (XY device coordinates) and cover a significant amount of the view depth (Z coordinate).
Each voxel (voxel is kind of 3d pixel) is used to store data per world space position.
This gives many opportunities to efficiently iterate over the view ray (like final integration pass does) and sample the fog using hardware filtering when applying it.
Also, edge artifacts are reduced and any aliasing flickering is barely visible due to temporal filtering.
The only downside is that 3D has to have low resolution (e.g. 150x80x64) consequently it’s better to use with objects that have significant size and solid shape.
However, because it’s a global effect I think it can be used in almost every game that uses fog or light shafts!
Volumetric fog rendering algorithm can be divided into several steps:
- Initialize volume properties
- Lights Injection
- Light Scattering
- Final Integration
The first step writes fog attributes into the set of two 3D textures:
Initialized textures contain fog attributes that describe fog particles absorption and scattering color inside the every view frustum cell.
All is done of course by the compute shaders.
Flax uses only exponential fog for it with parameters shown in a below picture.
But also custom volumes also could write data to it (as far as I remember UE4 has this feature implemented).
Volumetric fog parameters
Next step is to calculate lighting contribution per volume cell.
To do this algorithm renders (in additive mode) every light into the 3D texture (using geometry shader) and stores light color multiplied by the visibility, intensity and the in-scattering phase function.
It’s also possible to sample per-light shadow map so the final effect looks even better.
Finally with calculated light and fog properties per volume cell light scattering and extinction can be evaluated.
Then the compute shader can run through the 3d texture and perform final integration along the view ray.
The resulting texture is ready to use and apply to the scene.
Moving point light
Smooth Fog
One of the biggest challenges was to implement proper temporal filter along with jittering. This was required to get rid of all the aliasing artifacts.
That’s because the effect is running in quite low resolution so sampling cascaded shadow map for the sun with only on-tap per cell introduced many visual artifacts (due to under-sampling).
The best results were achieved by using temporal Halton sequence to offset samples inside the voxels and then by performing temporal blending using history buffer (7% blend current frame with the previous). For the fast-moving camera when many samples don’t hit the history super-sampling was implemented in order to smooth the results out.
Spot light casting light in volumetric fog
Lastly speaking about the effect performance it does quite good. On my laptop (GeForce 840M – Witcher 3 runs in 21FPS in low quality on it) it takes around 1.1ms depending on the amount of lights and quality settings.
However, this effect excludes the post-fx light shafts and of course, be possibly more optimised in the future.
Engine profiler window with frame drawing stats. Note volumetric fog pass.
Moving forward
As you can see this fog looks stunning. I’m pretty happy with the final results and looking forward to release the engine so more people could use it.
At this point, I can say that visual features in the Flax Engine are in the very good condition (including some hot next-gen stuff too).
Also, Editor with included tools does a great job.
Now it’s time to prepare some sample games and projects with features examples and kick off the documentation writing process.
And as always, see you soon! 🙂
4 Comments
Mikołaj · January 18, 2018 at 11:18 PM
Jakiś Terrain System macie zamiar zrobić kiedyś tam? 🙂
Tak z ciekawosci tylko pytam czy będzie trzeba się pobawić samemu czy gotowe narzędzia będą, bo silnik zapowiada się bardzo ciekawie 😀
Mikołaj · January 19, 2018 at 12:00 AM
NEVERMIND 😀
Nie zauważyłem zakładki Terrain na road mapie 🙂
Wojciech Figat · January 20, 2018 at 1:44 PM
Na Trello jest wszystko 🙂 Jestem pewien, że Terrain pojawi się przed Betą (duży priorytet)
Jimoh · November 18, 2024 at 3:00 AM
I want to join