top of page

The Solace

Dynamic fog for puzzle game
Unreal Engine
My Role
VFX artist
Time Spent

The Solace  is a 3rd person puzzle game where the player must make due with a single lantern in a deep mystical fog.

​

Gameplay is centered around managing and spreading light to reveal the pieces required to solve the puzzle. The fog in the game responds to and moves away from light sources in real time.

2 weeks
Year
2023

Dynamic Fog

This effect is created with a volumetric shader together with a companion c++ class managing communications with the outside world.

​

The shader works by filling a volume with fog and carving out vertical cylinders of empty space. Extinction value is calculated based on fog density and distance to a reference point. A threshold variable is used to control size of the cylinder.

Side Stuff(7).png

To add movement to the borders of each fogless area, the distance threshold is modulated over time. This behavior is controlled by a sine wave which is itself phase modulated by world space noise.

​

Finally, by assuming uniform density in the fog we can calculate the extinction rate base on distance to the nearest threshold.

​

Movement in the vertical axis is created with a fall-of function with a similar threshold, but for height. Squared fall-of is used as a base that is then combined with fractal Brownian motion.

​

In order to control the fog at runtime, the reference locations need to be parametrized. Since material shaders run directly on the GPU, the exact memory footprint needs to be known at compile time. This means dynamic arrays or lists are out the window.

​

To solve this issue I used a material parameter collection with a set amount of vector parameters, representing fog free areas. Our level called for upwards of 30 different fog dispelling sources, which would require 30+ vector parameters to be reserved at all times. While the scaling pattern for the algorithm is linear over the number of sources, I noticed slowdowns anyway with higher numbers.

​

The solution became a c++ subsystem, which could register when a memory slot was first requested and recycle the oldest slot when there is no more room. This also made communicating with the fog more convenient for our gameplay elements since subsystems are universally reachable in a single player game.

What I would change

I only had two weeks to make this fog effect and integrate it with the game. With more time on this project, there are a few improvements I would have tried.

 

First up, implementing self-shadowing could help bring out the shape of the fog more, with the risk of having a too cloud-like of an appearance.

​

Secondly, with only two weeks there was no time to experiment with different noise types and parameter combinations to my liking. With more time I would explore the capabilities of the shader much more.

​

Third, I would have spent more time on shifting color in the fog. I did implement the fog moving between a darker and brighter color, and I would love to expand this system to have more depth and a more organic look.

What I learned

Making realistic looking billowing shapes is both hard, and really really satisfying. Working with a natural phenomenon like fog allowed me to leverage my background in mathematics to it's fullest. I now know both the importance of doing your research for realistic shaders and a lot more trivia about fog.

​

This project also taught me just how reusable elements of calculations that go into shaders can be. The undulating movement I used for the fog radius also came in handy later for a post-processing vignette to indicate fear.

bottom of page