Deferred Rendering 5: Foggy Haze

This time I have made my first modification to the base test harness. I’ve added a hazy fog. The purpose is to help establish depth. I think it works quite well.

I previously had a heavy fog;  fully obscuring at around 200m. The idea behind this was to cull the level geometry beyond this range for performance and to add an eerie feel. This worked, fps was higher and it did indeed feel spookier.

The only problem was the weapons that used scopes. They became pointless, and in effect all weapons had the same maximum range of 200m. I asked myself  what was the point in making each weapon have it’s own unique characteristics if they all are limited to 200m.

So my new solution: The haze never fully obscures any geometry. You could in theory make a 2km kill with the bolt action sniper rifle, if you held your breath and were lucky. Any moodier mist will be implemented with a particle system. The particles will be in layers,like a Bob Ross painting. That way the skeletons will appear through the mist in an incremental more dramatic way. I can also heavily specific areas of the map for dramatic reasons, rather than having a dense universal blanket fog.

From a technical point, I am always looking to improve performance. So instead of converting the depth to world space, I just left it as is. I think it works fine and saves quite a few GPU instructions.

//read depth
 float depthVal = tex2D(depthSampler,input.TexCoord).r;
 float lerpAmount = saturate((depthVal - FogStart) / (FogEnd - FogStart));
...
...
return float4 (lerp(combinedColor,FogColor,lerpAmount),1)

Whereas the standard way is

float4 PixelShader(VertexShaderOutput input) : COLOR
{ 
 float depthVal = tex2D(depthSampler,input.TexCoord).r;
 float3 cen = tex2D(cenaSampler ,input.TexCoord );
//compute screen-space position
 float4 position;
 position.x = input.TexCoord.x * 2.0f - 1.0f;
 position.y = -(input.TexCoord.y * 2.0f - 1.0f);
 position.z = depthVal;
 position.w = 1.0f;
 //transform to world space
 position = mul(position, InvertViewProjection);
 position /= position.w;

 float d = length(position - cameraPosition);
 float l = saturate((d-near)/(far-near)); 
 return float4(lerp(cen,fcolor, l),1); 
}

Obviously the above method is more flexible in terms of being able to specify real world distance, but it is slower.

Any suggestions or comments are welcome.

The next thing is altering the buffers to allow alpha blending…

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s