tech art thing: mist-dispelling lights

A while ago I made a cool effect for Sleight of Hand, where (since you hide in clouds of smoke sometimes in this magic-themed game), we were experimenting with a type of lantern that guards could carry around and it would dispel any smoke or fog around the light. The fog is all volumetric, so cutting through it in a way that looks good is easily done with a spheremask, but that doesn’t handle occlusion (removing smoke on the other side of a wall from the light). In our game it’s probably not important to handle that case, but I did it anyway using Niagara, and the result looks pretty sick.

This looks pretty cool when a guard is carrying one of these lights around:

What I’m doing here is colliding particles against distance fields to find occluders in the radius of the light, and using a Niagara simulation stage to paint that information into a rendertarget that can be sampled in the smoke material to mask out the occluded areas. Here’s an early gif that doesn’t fully reflect the current approach but looks cool:

I spawn a bunch of particles in a grid, and then trace from each of them to the position of the light (this is a sphere trace against the global distance field). If the particle is unoccluded, I paint that point on the rendertarget white; otherwise, I paint a little black into it. The rendertarget is persistent from frame to frame, I don’t clear it unless the light teleports, so painting just a little black in each frame (which doesn’t happen in the above gif, but you can see it in the video) means the areas that used to be unoccluded but aren’t anymore “fade in” and have their fog appear to return gradually over time. All lights of this type also share the same RT, so as you see in the video, multiple can overlap and the “shadows” still behave correctly. This all happens on the GPU, so it’s quite performant. Meanwhile, the actual gameplay code determining “am I hidden in smoke” is a simple trace every so often between the player and the light.

This isn’t a tutorial or I would clean this up, but most of this happens in this small niagara graph. In this case the RT is 2D so the occlusion effect is too, but it would be easy to use a 3D grid instead and get the same result “properly” (it just doesn’t matter for this game – so far, anyway).

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *