
GPU Lightmap Baking in Unity (Custom Baking Tools Guide)
August 22, 2026
Real‑Time Volumetric Cloud Rendering in Unity Using Raymarching
August 29, 2026Volumetric 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.





![Lighting in Unity: A Practical Guide for Game Developers There’s something satisfying about watching a flat, boring plane turn into a mountain range. That’s exactly what a height map does in Unity. With a simple grayscale image, you can shape landscapes, add depth to materials, and create worlds that feel real instead of flat. It’s one of those tools that looks technical at first, but once you understand it, it becomes surprisingly simple and powerful. In this guide, we’ll break down what a height map is, how it works in Unity, how to use it for terrain, how it differs from normal maps, and how to control it with C#. What Is a Height Map? A height map is a grayscale image where each pixel represents elevation. Black = lowest height White = highest height Gray = values in between Think of it like a topographic map, but simplified into brightness levels. Unity reads this image and uses the brightness values to push parts of a surface up or down. The result? Hills, valleys, cliffs, and surface details created from a simple image. Height Maps in Unity Terrain The most common use of height maps in Unity is terrain generation. Unity’s Terrain system allows you to import a height map and automatically generate a 3D landscape from it. How to Import a Height Map into Terrain Create a Terrain: GameObject → 3D Object → Terrain Select the Terrain object. Open the Terrain Inspector. Choose Import Raw under the heightmap settings. Select your grayscale RAW file. Once imported, Unity converts the grayscale values into elevation data. If your height map is smooth, you’ll get rolling hills. If it has sharp contrast, you’ll get steep cliffs. Height Map Resolution Matters Resolution affects how detailed your terrain will be. A low-resolution height map creates blocky terrain. A high-resolution height map creates smoother, more detailed landscapes. However, higher resolution also increases memory usage and processing cost. If you're building for mobile, balance detail with performance. Height Maps vs Normal Maps This is where many beginners get confused. Height Map Actually changes geometry (in terrain or displacement). Creates real depth. More performance cost if geometry changes. Normal Map Does NOT change geometry. Fakes lighting to simulate bumps. Much cheaper performance-wise. If you need real terrain shape, use a height map. If you just want surface detail like cracks or scratches, a normal map is usually better. Using Height Maps in Materials (Parallax & Displacement) Height maps are not limited to terrain. You can also use them in materials. In Unity’s Standard Shader (or URP/HDRP equivalents), height maps can be used for: Parallax Mapping – creates depth illusion without changing geometry. Displacement Mapping – actually modifies mesh vertices (HDRP). For example, if you apply a brick texture, adding a height map can make the mortar appear recessed and bricks raised. Creating Height Maps You can create height maps using: Photoshop or GIMP (grayscale images) Blender (baked displacement maps) World Machine or Gaea (terrain generation tools) Procedural generation with code The key is keeping it grayscale and avoiding compression artifacts. Generating a Height Map with Code You can also generate terrain procedurally using Perlin Noise. This is common in open-world or survival games. Here’s a simple example: [csharp] using UnityEngine; public class TerrainGenerator : MonoBehaviour { public Terrain terrain; public int depth = 20; public int width = 256; public int height = 256; public float scale = 20f; void Start() { terrain.terrainData = GenerateTerrain(terrain.terrainData); } TerrainData GenerateTerrain(TerrainData terrainData) { terrainData.heightmapResolution = width + 1; terrainData.size = new Vector3(width, depth, height); terrainData.SetHeights(0, 0, GenerateHeights()); return terrainData; } float[,] GenerateHeights() { float[,] heights = new float[width, height]; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { heights[x, y] = Mathf.PerlinNoise(x / scale, y / scale); } } return heights; } } [/csharp] This script generates a terrain using Perlin Noise, which creates natural-looking hills and variation. Controlling Height Strength Sometimes height maps look too extreme. Other times they look flat. In terrain settings, you can adjust: Terrain height (Y scale) Brush strength (when sculpting manually) In materials, you can adjust height intensity inside the shader settings. Small adjustments make a big difference. Subtle depth often looks more realistic than exaggerated displacement. Common Problems and Fixes Terrain Looks Blocky Increase heightmap resolution or smooth the terrain. Edges Look Stretched Make sure your height map is square and uses proper dimensions (like 512x512 or 1024x1024). Lighting Looks Strange Check your normal settings and ensure lighting is baked or set correctly. When to Use Height Maps Use height maps when: You need large landscapes. You want realistic terrain shaping. You’re building procedural worlds. You need true geometric depth. Skip them when: You only need small surface detail. Performance is extremely limited. Final Thoughts Height maps are one of those tools that feel technical at first, but once you use them, they become creative tools. You’re not just editing numbers. You’re sculpting mountains. Carving valleys. Designing the shape of a world. Start simple. Import a grayscale image. Adjust the scale. Play with noise. Watch how small changes affect the landscape. Once you understand height maps, Unity stops feeling like a flat engine. It starts feeling like a world builder.](https://unityqueen.com/wp-content/uploads/2026/02/Lighting-in-Unity-150x150.jpg)



