Unreal Demo

Introduction

Volumetrics are widely considered one of the most intricate technologies within the realm of computer graphics. The inherent complexity arises primarily because traditional rendering techniques struggle with volumetric objects due to their complex structure involving both depth and transparency. Unlike solid surfaces that require calculations at a single point, volumetric models necessitate that each sample delve into the object, demanding significantly more computational power to determine accurate lighting.

Despite advanced platforms such as Unreal Engine and the Niagara module offering sophisticated tools for volumetric modeling—enabling realistic smoke and fire simulations—their integration into gaming projects remains economically challenging. The high costs and technical demands lead many developers to prefer more conventional and cost-effective methods, such as leveraging sprite sheets.

The Six-Point Lighting Model

Material Function

In a previous article, I illustrated how to create a seamlessly looped cycle from a traditional smoke simulation. Building on that foundation, I now aim to delve into a crucial aspect of volumetrics: simulating lighting within volumetric objects.

For scenes illuminated by diffuse light, baking the light as is might suffice. However, to achieve more directional lighting, a technique exists that allows for plausible shading using precomputed data baked into textures. This approach dynamically responds to shifts in lighting direction and considers viewer orientation relative to the object.

Central to this technique is the six-point lighting model. This method involves rendering the object twice, with light information baked from six distinct directions, each allocated to its channel. To streamline the process, rather than employing a sprite sheet, two static textures are used:

  • mapA: Right, Top, Back
  • mapB: Left, Bottom, Front

Six Point Light

Use your mouse wheel to easily adjust Light Depth

HLSL Snippet for Light Mixing

Below is an HLSL code snippet demonstrating the mixing of maps based on the light direction:

float3 l = normalize(light);
float x = dot(float3(-1,0,0),l);
float y = dot(float3(0,1,0),l);
float z = dot(float3(0,0,1),l);

float intensity = 0;
intensity += x > 0 ? mapA.x * x : mapB.x * -x;
intensity += y > 0 ? mapA.y * y : mapB.y * -y;
intensity += z > 0 ? mapA.z * z : mapB.z * -z;
intensity = pow(i,2.2)*4;

float3 color = float3(1.0, 1.0, 1.0);
return color * intensity;

Note: The GLSL code is identical, with the exception of using vec3 instead of float3.

Conclusion

Using this method, even with limited computational resources, it becomes possible to achieve a realistic shading effect in volumetric objects.