Code Snippet : Fog Shader


In this code snippet we are going to show some simple ways to create a fog like effect in 3D games.
The fog effect is a post process (operates on a full screen quad) that recieves the framebuffer texture (the one with the game rendered content) and a depth texture as main parameters.
The depth texture (used normally in deferred shading) contains the post projected Z/W coordinate of all objects (the Z buffer content actually =P).


To generate it, you can use the following shader in all objects of your scene (prefer rendering it to a single 32 bits texture for better precision)

float4x4 WVP;

struct VertexToPixel
{
	half4 Position		: POSITION;
	half2 ScreenPos			: TEXCOORD0;
};
struct PixelToFrame
{
	half4 Color 			: COLOR0;
};

VertexToPixel MyVertexShader(half4 inPos: POSITION0)
{
	VertexToPixel Output = (VertexToPixel)0;
	Output.Position = mul(inPos, WVP);
	Output.ScreenPos = Output.Position .zw;
	return Output;	

}

PixelToFrame MyPixelShader(VertexToPixel PSIn) : COLOR0
{
	PixelToFrame Output = (PixelToFrame)0;
	Output.Color = PSIn.ScreenPos.x/PSIn.ScreenPos.y;
	return Output;
}

technique Depth
{
	pass Pass0
    {
    	VertexShader = compile vs_2_0 MyVertexShader();
        PixelShader  = compile ps_2_0 MyPixelShader();
    }
}

It just output the z/w of each rendered “pixel”. The post process shader that creates the fog effect is:

float2 halfPixel;
float dz;
float4x4 InvertViewProjection;
float3 cameraPosition;
float far;
float near;
float3 fcolor = {0.5, 0.5, 0.5};

texture cena;
sampler cenaSampler = sampler_state
{
   Texture = ;
   AddressU  = Clamp;
   AddressV  = Clamp;
};

texture depth;
sampler depthSampler = sampler_state
{
   Texture = ;
   MinFilter = POINT;
   MagFilter = POINT;
   MipFilter = POINT;
   AddressU  = Clamp;
   AddressV  = Clamp;
};
struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float2 TexCoord : TEXCOORD0;
};
VertexShaderOutput VShader( float4 Pos: POSITION, float2 Tex : TEXCOORD)
{
	VertexShaderOutput output;
	Pos.x =  Pos.x - 2*halfPixel.x;
	Pos.y =  Pos.y + 2*halfPixel.y;
    output.Position = float4(Pos);
    output.TexCoord = Tex;
    return output;
}

float4 Pshader(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.x * 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);
}

float4 PixelShaderExponencial(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 = exp(-d * dz);
	l = saturate(1 - l);

    return float4(lerp(cen,fcolor, l),1);
}

float4 PixelShaderExponencialSquared(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 = exp( - pow( d * dz , 2 ) );
	l = saturate(1 - l);

    return float4(lerp(cen,fcolor, l),1);
}

technique FogShader
{
	pass P0
	{
		VertexShader = compile vs_3_0 VShader();
		PixelShader = compile ps_3_0 Pshader();
	}
}

technique FogExponencialSquaredShader
{
	pass P0
	{
		VertexShader = compile vs_3_0 VShader();
		PixelShader = compile ps_3_0 PixelShaderExponencialSquared();
	}
}

technique FogExponencialShader
{
	pass P0
	{
		VertexShader = compile vs_3_0 VShader();
		PixelShader = compile ps_3_0 PixelShaderExponencial();
	}
}

The idea is very simple and naive, we just blend the scene color with the fog color using the scene distance (from depth texture) as a control parameter.
All the parameter used in the shaders are self explanatory (camera position, near plane, far plane …..). The only strange one is the dz (density) that we normally set to 0.001f.
The halfpixel is a directx 9c stuff (correction needed because of the directx rasterizer algorithm, in directx > 9c, this is not needed) and can be calculated in the following way (in XNA):

 Vector2 halfPixel = new Vector2()
            {
                X = 0.5f / (float)game.GraphicsDevice.PresentationParameters.BackBufferWidth,
                Y = 0.5f / (float)game.GraphicsDevice.PresentationParameters.BackBufferHeight
            };
           

We showed three ways of doing this (normal, exponencial and exponencial squared), you can choose each of then according with you quality/speed trade off.

, , ,

  1. #1 by Elmo Solito on 24 de julho de 2016 - 7:38 am

    Draftkings doesn’t use promo codes since Mar 2016 – just make an account, deposit and get a welcome bonus!

  2. #2 by fitflops outlet on 24 de julho de 2016 - 7:38 am

    A lot of thanks for all your valuable efforts on this web page. My daughter really loves going through internet research and it is simple to grasp why. Most of us hear all regarding the dynamic medium you convey simple tips on your blog and as well as improve response from some other people about this area of interest and our own princess is now understanding a great deal. Take advantage of the remaining portion of the year. You’re the one conducting a great job.

  3. #3 by brosciencethreds on 24 de julho de 2016 - 8:15 am

    Very informative article.Really looking forward to read more. Cool.

  4. #4 by Smart Balance Wheel on 24 de julho de 2016 - 9:23 am

    Most of these Smart Balance Wheel http://www.fashionhoverboard.com are the most useful you’ll find. They are usually comfotable stylish and above all just the thing for anyone. I have experienced my very own tall in height typical chesnut for just two yearsa plus they nonetheless glance completely new. I convey these products daily. I tremendously recomend all of these to be able to complete for the money.

  5. #5 by Matka Result on 24 de julho de 2016 - 9:24 am

    Wonderful story, reckoned we could combine a handful of unrelated information, nonetheless actually really worth taking a appear, whoa did one study about Mid East has got extra problerms too

1 41 42 43
(não será publicado)