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 whatsapp for pc on 9 de dezembro de 2016 - 1:35 pm

    Hello.This post was extremely fascinating, particularly because I was searching for thoughts on this subject last Sunday.

  2. #2 by unhappyOn on 9 de dezembro de 2016 - 4:05 pm

    el Talento, nada dirГЎs.
    unhappyOn

  3. #3 by weiterhin das Lesen on 9 de dezembro de 2016 - 6:06 pm

    Besonders für die männlichen Geschlechtsorgane soll Yohimbin einschlägige, nämlich durchblutungsfördernde Folgen haben.

  4. #4 by movers gumtree on 9 de dezembro de 2016 - 8:02 pm

    Sites of interest we have a link to

  5. #6 by Penis Sleeve on 9 de dezembro de 2016 - 10:15 pm

    check below, are some entirely unrelated web sites to ours, even so, they may be most trustworthy sources that we use

  6. #7 by Educational Games on 9 de dezembro de 2016 - 11:35 pm

    Great goods from you, man. I have understand your stuff previous to and you are just too great. I really like what you have acquired here, certainly like what you are stating and the way in which you say it. You make it entertaining and you still take care of to keep it sensible. I cant wait to read far more from you. This is really a great web site.

  7. #8 by Yvone Killin on 10 de dezembro de 2016 - 12:33 am

    Any way I’ll be subscribing to your feed and I hope you post once more soon. I don’t feel I could have put it greater myself.

  8. #9 by ルイ ヴィトン ジャージ on 10 de dezembro de 2016 - 5:50 am

    正規販売代理店,100%品質保証!
    超激得通販!
    【超人気新品】史上最も激安い!最安値に挑戦!
    クリスマス賛発売!
    超人気高品質100%品質保障!
    今79%OFF、税金入れ、ベストプライスをお楽しみください
    送料無料で販売、最大70%の割引
    発売中高級品アウトレット割引を提供
    割引80%オフまで
    【正規品】激安専門店.
    超安値登場!品質保証、最安値に挑戦!
    オンラインストアオファー激安輸出
    高品質とリーズナブルで販売
    超人気【楽天市場】
    オンラインストアは、ご来店ありがとうございます.
    ルイ ヴィトン ジャージ http://www.okakaku.com/brand-17-copy-0.html

1 123 124 125
(não será publicado)