Real‑Time Volumetric Fog in Unity Using 3D Textures and Compute Shaders

GPU Lightmap Baking in Unity (Custom Baking Tools Guide)
August 22, 2026
Real‑Time Volumetric Cloud Rendering in Unity Using Raymarching
August 29, 2026
GPU Lightmap Baking in Unity (Custom Baking Tools Guide)
August 22, 2026
Real‑Time Volumetric Cloud Rendering in Unity Using Raymarching
August 29, 2026

Real‑Time Volumetric Fog in Unity Using 3D Textures and Compute Shaders

Volumetric fog is a rendering technique that simulates how light scatters inside a volume such as mist, smoke, or atmospheric fog.
Unlike traditional distance fog, volumetric fog allows light beams, shadowed fog, and density variations inside space.

In modern engines this effect is usually implemented using 3D textures and compute shaders that simulate light scattering across a voxelized volume of the scene.

In this guide we will build a simplified real‑time volumetric fog system in Unity using:

  • 3D density textures
  • Compute shader light scattering
  • Ray marching in screen space
  • Temporal accumulation

1. How Volumetric Fog Works

Instead of calculating fog per pixel, volumetric fog divides the camera space into a 3D grid of voxels.
Each voxel stores fog density and lighting information.

Rendering then samples this volume while marching along the camera ray.

Pipeline overview:

Scene → Fog Volume Grid → Compute Shader Lighting → 3D Texture → Ray March → Final Fog Color

2. Creating a Fog Volume Grid

The first step is creating a 3D texture representing fog density.
This grid usually covers the camera frustum.

Example grid resolution:

  • Width: 160
  • Height: 90
  • Depth: 64

Lower resolution keeps performance stable.

Unity setup script:

public class VolumetricFogVolume : MonoBehaviour
{
    public int width = 160;
    public int height = 90;
    public int depth = 64;

    public RenderTexture fogVolume;

    void Start()
    {
        fogVolume = new RenderTexture(width, height, 0);
        fogVolume.dimension = UnityEngine.Rendering.TextureDimension.Tex3D;
        fogVolume.volumeDepth = depth;
        fogVolume.enableRandomWrite = true;
        fogVolume.graphicsFormat = UnityEngine.Experimental.Rendering.GraphicsFormat.R16G16B16A16_SFloat;

        fogVolume.Create();
    }
}

3. Populating Fog Density

Fog density can be generated in multiple ways:

  • Height-based fog
  • 3D noise
  • Weather simulation
  • Particle injection

Example compute shader for density generation:

// FogDensity.compute

#pragma kernel CSMain

RWTexture3D<float4> FogVolume;

float fogHeight = 5;
float density = 0.04;

[numthreads(8,8,4)]
void CSMain(uint3 id : SV_DispatchThreadID)
{
    float heightFactor = saturate(1 - id.y / fogHeight);

    float fog = density * heightFactor;

    FogVolume[id] = float4(fog,fog,fog,1);
}

This creates denser fog closer to the ground.


4. Volumetric Light Scattering

Now we simulate light scattering inside the fog.
Each voxel samples light visibility from the scene.

Basic scattering equation:

LightContribution = LightColor × Density × PhaseFunction

Example compute shader for lighting:

// FogLighting.compute

#pragma kernel CSMain

RWTexture3D<float4> FogVolume;

float3 lightDirection;
float3 lightColor;

[numthreads(8,8,4)]
void CSMain(uint3 id : SV_DispatchThreadID)
{
    float density = FogVolume[id].r;

    float scatter = saturate(dot(normalize(float3(0,1,0)), -lightDirection));

    float3 lighting = lightColor * density * scatter;

    FogVolume[id] = float4(lighting, density);
}

5. Ray Marching the Fog

After the volume is built, the camera ray marches through it.
Each step samples the 3D texture and accumulates fog color.

Fragment shader example:

float4 RaymarchFog(float3 rayOrigin, float3 rayDir)
{
    float stepSize = 0.5;
    float3 pos = rayOrigin;

    float3 color = 0;
    float transmittance = 1;

    for(int i=0;i<64;i++)
    {
        float4 fog = SAMPLE_TEXTURE3D(_FogVolume, sampler_FogVolume, pos);

        color += fog.rgb * transmittance;
        transmittance *= exp(-fog.a * stepSize);

        pos += rayDir * stepSize;
    }

    return float4(color,1);
}

This integrates fog color along the viewing ray.


6. Adding Temporal Reprojection

Volumetric fog often uses temporal accumulation to reduce noise.
Each frame reuses previous results.

Advantages:

  • Higher visual quality
  • Lower ray marching cost
  • Stable lighting

Typical blend:

NewFrame = lerp(CurrentFrame, PreviousFrame, 0.9)

7. Performance Optimization

Volumetric fog can be expensive, so several optimizations are used.

  • Low resolution froxel grids
  • Checkerboard updates
  • Temporal accumulation
  • Half resolution rendering
  • Depth-aware upscaling

Most AAA games run fog at 1/4 resolution.


8. Optional Advanced Features

Once the base system works, you can extend it with advanced effects.

  • Shadowed volumetric fog
  • Volumetric light shafts
  • Noise-driven fog movement
  • Weather simulation
  • Local fog volumes

9. Result

With a 3D fog volume, compute shader lighting, and ray marching integration,
you can achieve real-time volumetric fog effects similar to modern AAA engines.

This system allows:

  • Light beams through fog
  • Dense atmospheric environments
  • Dynam weather systems
  • Realistic fog shadows

10. Conclusion

Real-time volumetric fog is one of the most powerful atmospheric effects in modern rendering.
By combining 3D textures, compute shaders, and ray marching, Unity can produce highly realistic fog systems.

Although the technique is GPU heavy, careful optimization and temporal accumulation make it practical even for real-time applications.

 

 

Leave a Reply

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


Skip to toolbar