Firewatch-Style Sky & Fog

After seeing this presentation from Jane Ng about her work on Firewatch, I fell in love with their backgrounds and tried to build a similar sky and fog shader. Their blog entry on the topic helped me get started by defining the parameters they use for their system, but it was a little light on implementation details.

I started by just generating simple gradients for the sky, set from user-defined colors. From there I projected the sun as a circle onto the sky from a position on the unit circle (to allow the user to set the time of day) and added some exponential falloff from the sun's base color to the sky near the sun's position. The fog itself is a simple exponential function, with the density of the fog increasing with distance from the camera and with decreasing height. Scattering effects from sunlight into the fog are handled with a similar exponential decay function to the halo around the sun in the sky.

The coolest idea Campo Santo had, though, was their adjustment of the fog's color from a gradient map. This was easy to implement, but makes a huge difference. We just sample from a 1D texture based on the distance from the camera for each point (normalized to the 0..1 range based on the max draw distance) and use the color from the texture in the fog calculation instead of using a constant color value.

Using these gradient textures for the fog makes it really easy to create some very nice silhouettes off in the distance, and by adjusting the fog's density & height parameters you can still maintain a great deal of detail in the foreground, which lets the system provide photo-realistic rendering for objects near the user, and more stylistic rendering for distant objects.

It also lets you do some crazy things, like this rainbow map I used to debug some distance calculations.

There are GUI controls for all of the fog, sky, and sun parameters, which should be fairly self-explanatory. The fog uses a constant color by default (also settable in the GUI), but to use a gradient image instead just drag and drop any image onto the scene. Your gradients should be 1px tall, and some power-of-two px wide. Here are some examples:

If you have a Leap Motion and a VR HMD, you can also view the sky in VR and control some of the sun & fog parameters through hand gestures:

  1. With your right hand: Make a fist, and move your hand vertically to move the sun. Pinch your thumb & forefinger and move your hand side-to-side to change the size of the sun.
  2. With your left hand: Pinch your thumb and forefinger together, then move your hand vertically to adjust the fog height, or horizontally to adjust the fog density.

Play online here
NOTE: It will render at the size of your browser window! If you have performance issues, try resizing your browser.