Breakdowns

Fog of War – Technical Breakdown

I recently had the pleasure of creating a Fog of War system for Tales of Fablecraft!

This one was a nice challenge, considering FoW systems have notoriously been heavy on performance since the dawn of time (or at least since 3D games). An added extra is that this game also runs on mobile and tablets, in addition to PC. So this FoW had to be very performant, and still look good.

The Fog of War in action. I set up some shortcuts for testing the removal of fog tiles.

I settled on using a single shuriken particle system for spawning a particle for each tile. Since this is not possible out of the box, I created a script that reads position data from a Data asset. It also sets the particle’s lifetime to ‘infinity’. Whenever a grid point gets removed, the lifetime is set to a user defined value, after which the particle can then fade out corresponding any lifetime changes set.
I built an editor around this that allows a designer to easily set points on the battlemap’s grid that defines the fog area. These positions are then stored in a data file that is then read by the script that’s hooked up to the particle system.

The editor allows a designer to easily set points on the grid that define the fog area. These positions are then stored in a data file.

But then came the biggest issue of the entire system: transparent overdraw. My personal favorite performance killer.

Because the fog needed soft edges, I had to scale up each particle significantly to accommodate this. But this would also mean I’d have a ton of overdraw because each particle can overlap multiple times. One thing I was sure of is that purely going with particles wouldn’t fly, so I decided to at least set up an additional system with a dedicated camera that renders the fog to a render texture. This texture is then sampled as an alpha input in another shader, and used on an overlaid quad. This technically solves overdraw, but.. All this does it move all the alpha calculations ‘out of sight’, so it’s not at all more performant.

This got me thinking that as long as we have these soft edges, and thus big overlapping particles, it’s going to remain a problem. Unless I don’t use transparent particles at all. I changed the particle shader to opaque, and added dithering to the alpha. This actually did solve the overdraw issue, but it didn’t look good at all.

The view that the fog camera sees. This is being written to a render texture which is then sampled on a higher mip level to hide the dithering.
The view of the actual particles, showing some of the shader features that control the edges and fade softness. Excuse the jittery visuals, compression and dithering don’t mix!

I then realized I could just sample the render texture on a higher mip level, effectively blurring the texture. And voila: a performant Fog of War, without transparent particles and only a single quad of overdraw. All that was left was improving the actual fog visuals, which is just a simple shader that utilizes a main texture, distort texture and dissolve texture.