Volumetric Modifiers

In part 1 we took a look at the default volumetric system in UE4 and some of the problems it had for a use case like ours. We saw how using world transforms and world offsets allow us to control the mesh in which we contain our volumetric material. In this post, we will look at some of the primary functions that take our additive material and mirror its behaviors to that of a real stage light.

The first and possibly most crucial element of a volumetric is the particulate in which the light can be caught. Like in reality,  we need some way to create a smoke or dust that can catch the light in the air and create those iconic light shafts we see in shows. This particulate will also give our volumetrics some texture. By using randomized noise instanced in world space, we can move our mesh through a set of 3D data and apply it as a mask. Additionally, we can apply a panning to this data and give velocity to the noise itself.

Volumetric Fog Noise:

Volumetric Fog Scale:

With a particulate system implemented, I could move onto solutions for edge softness. Depending on the intensity of our light, or the mask of our gobo the strength of the volumetric beam edge will need a scaling opacity value. Using the dot product between our camera’s viewing angle of the light, and the static mesh’s normal direction, I can calculate when we are approaching the edge of our beam mesh. With that information, I can apply a dynamic mask to the beam and control its strength.

Volumetric Edge Softness:

One more crucial lighting behavior I needed to figure out was the falloff functionality. The intensity of light at any given point is proportional to the inverse square of its distance from the source. This light behavior was a bit tricky to implement on a mesh designed to dynamically scale its size based on the desired attenuation. I needed to find a way to calculate a distance value based on the individual pixel locations stretched along the volume mesh. To do this, I started by assigning a 0-1 value across the length of the mesh. Now every pixel on the beam will have a 0-1 decimal that I could use to multiply against its scale. Since our beam is unitized to a 1x1x1 scale, any transformations to the mesh lengthwise will end up being the number for our max intensity distance. We then simply multiply that distance across the 0-1 decimals we assigned to our mesh pixels, and we end up with a mesh that now has distance values proportional to its dynamically changing size.

Assigning Distance to a Mesh:

I can now use these values in our inverse square operation and produce an intensity falloff behavior quite similar to that of a real light fixture. There are additional refinements that can influence the intensity, like zoom angle and unit structure, however the majority of our light falloff calculations are now complete, and the results were a huge step towards our visual target.

Volumetric Falloff:

That’s it for part 2 of our look into custom volumetric solutions. In part 3 we will take a look at one of the most challenging problems faced when working on a volumetric; shadows! Keep an eye out for upcoming blogs and thanks for listening!

-Joe Bonura