Linear depth + color perspective

Screenspace fog + color perspective using linearized depth.



Constants in

FOG_COLOR = Vec4(.7,.4,.3,1)
FOG_POWER = Vec4(.1,2,1,1) # (red, blue, gray, extinguish)

Red power: the nearer the object, the more red.
Blue power : the further the object, the more blue.
Gray power : nearest objects are more saturated, further objects are less saturated.
Extinguish power : 1 for blending with background color.

I changed code from last post, it should be more correct now.

Shader preview :

float4 scene = tex2D(k_originalmap, l_texcoord);
float lineardepth = tex2D(k_lineardepth, l_texcoord).x;
float4 color = scene;
float4 gray = 0.30*color.x + 0.59*color.y + 0.11*color.z;
float redpower = power.x;
float bluepower = power.y;
float graypower = power.z;
float extinguishpower = power.a;
color.r += scene.r * 1/lineardepth * power.x;         // nearer objects are warmer in color
color.b += scene.b * lineardepth * power.y;           // further objects are colder in color
color = lerp(color, gray, lineardepth * power.z) ;    // further objects lose saturation
color = lerp(color, fogcolor, lineardepth * power.a); // further objects extinguish (background color)
o_color =  color;

I’m not sure it looks like fog. It just seems to change from one color to another. Well, that’s judt my impression.


LIGHT_COLOR = Vec3(.7,.4,.3)
GLOBAL_AMBIANT = Vec3(.3,.6,.7)

FAR_CLIP = 1000

void vshader(float4 vtx_position : POSITION,
             out float4 l_position : POSITION,
             out float2 l_texcoord : TEXCOORD0,
             uniform float4 texpad_originalmap,
             uniform float4x4 mat_modelproj)
    l_position = mul(mat_modelproj, vtx_position);
    l_texcoord = (vtx_position.xz * texpad_originalmap.xy) + texpad_originalmap.xy;

void fshader(float2 l_texcoord : TEXCOORD0,
             uniform sampler2D k_originalmap : TEXUNIT1,
             uniform sampler2D k_lineardepth : TEXUNIT2,
             out float4 o_color : COLOR)

    float4 scene = tex2D(k_originalmap, l_texcoord);
    float lineardepth = tex2D(k_lineardepth, l_texcoord).x;
    float4 color = scene;
    float4 gray = 0.30*color.x + 0.59*color.y + 0.11*color.z;
    color.r *= scene.r * 1/lineardepth; // nearer objects are warmer in color
    color.g = scene.g;
    color.b *= scene.b * lineardepth; // further objects are colder in color
    color *= gray * lineardepth; // further objects lose saturation
    color /= lineardepth; // test
    color += lineardepth; // further objects are whiter (should be background color)
    o_color =  color; // output


Could you explain what the purpose of “linear depth” is? It seems counter-intuitive to me.

When I was testing my depth of field filter, I had problems, having more precision for objects near camera; I read then some articles about linear depth, so I wanted to have it in panda.

Main article, the depth calculation comes from here, there is more links inside :

Main post edited.

The whole point of non-linear depth is that the depth buffer has more resolution for objects closer to the camera than objects farther away from the camera. Having a non-linear depth buffer is essential to reducing z-fighting artifacts- you’ll quickly start running into these kinds of problems with a linear depth buffer if you start working with more complicated scenes.

Still, I suppose a linear depth buffer is quite useful for debug visualisation, as it is used for in the post you linked.

A linear depth buffer is very useful for SSAO.

Hi Manou,

Do you have any reference info. on the artistic merit/usuage of your fog? Most people just lerp the base color with a fog color, but you seem to be changing the saturation and tone as well. Why?


Here some nice articles : (chapter 5)

There are some videos of old painting showing the effect on youtube if you want examples.

The code is “true” for ground objects, it should be inverted for the sky.

The code is not for physically correct results, but for our brain, blue color recedes and red color advances, same for saturation. Our screen is still 2d so I think it can help if you want more vibrant or 3d-ish perception, but you need to keep the effect subbtle, in my code it’s very exagerated.

You can use the selective saturation too for making important objects be more visible (they do this in L4D2, can’t find the article).

My next step will be to have focused camera object to be more saturated and background less saturated. I’ll post there or in fur shading when done.