首页 > 代码库 > Directx10 龙书笔记- 雾效的实现

Directx10 龙书笔记- 雾效的实现

雾 : 说白了就是一层有颜色的(一般是白色,灰色) 蒙蒙的感觉 混在光线里面。 不管是白天还是黑天。

龙书里面是这样实现的:

1.  给雾定义一个颜色 float3 gFogColor={0.7f,0.7f,0.7f};

2. 然后呢在顶点着色器里面计算出 顶点级别的雾化需要的颜色加成比例

加成比例: 意思是当距离摄像机,就是你的眼睛越远,雾的浓度越大,就是颜色越深。 根据这个得出一个(0,1)的和距离有关的比例系数

vout.fogLerp = saturate((d-gFogStart)/gFogRange) ; 其中 gFogStart是可见范围,没有雾的范围,gFogRange是不可见范围,超出这个范围就全是雾

saturate是强制为(0,1)这个区间。

3. 在像素着色器像素级别的融合 纹理颜色和雾的颜色

float3 floggedColor = lerp(litColor,gFogColor,pIn.fogLerp);


具体fx代码为:

//=============================================================================
// fog.fx by Frank Luna (C) 2008 All Rights Reserved.
//
// Same as clip.fx, but adds fog in the vertex shader.
// Note that we could do fog in the pixel shader, but if the scene
// has sufficient triangle density, not much is gained. 
//=============================================================================


#include "lighthelper.fx"
 
cbuffer cbPerFrame
{
	Light gLight;
	float3 gEyePosW;
};

cbuffer cbPerObject
{
	float4x4 gWorld;
	float4x4 gWVP; 
	float4x4 gTexMtx;
};

cbuffer cbFixed
{
	// For this demo, we hardcode the fog values.  However, in a real
	// application, the program may want to change the fog settings
	// at runtime; for example, to fade the fog in and out based on 
	// the time of day or the location of the game player.
 	
	float  gFogStart = 5.0f;
	float  gFogRange = 140.0f;
	float3 gFogColor = {0.7f, 0.7f, 0.7f};
};

// Nonnumeric values cannot be added to a cbuffer.
Texture2D gDiffuseMap;
Texture2D gSpecMap;

SamplerState gTriLinearSam
{
	Filter = MIN_MAG_MIP_LINEAR;
	AddressU = Wrap;
	AddressV = Wrap;
};

struct VS_IN
{
	float3 posL    : POSITION;
	float3 normalL : NORMAL;
	float2 texC    : TEXCOORD;
};

struct VS_OUT
{
	float4 posH    : SV_POSITION;
    float3 posW    : POSITION;
    float3 normalW : NORMAL;
    float2 texC0   : TEXCOORD0;
    float2 texC1   : TEXCOORD1;
    float  fogLerp : FOG;
};
 
VS_OUT VS(VS_IN vIn)
{
	VS_OUT vOut;
	
	// Transform to world space space.
	vOut.posW    = mul(float4(vIn.posL, 1.0f), gWorld);
	vOut.normalW = mul(float4(vIn.normalL, 0.0f), gWorld);
		
	// Transform to homogeneous clip space.
	vOut.posH = mul(float4(vIn.posL, 1.0f), gWVP);
	
	// Output vertex attributes for interpolation across triangle.
	vOut.texC0  = vIn.texC;
	vOut.texC1  = mul(float4(vIn.texC, 0.0f, 1.0f), gTexMtx);
	
	float d      = distance(vOut.posW, gEyePosW);
	vOut.fogLerp = saturate( (d - gFogStart) / gFogRange ); 
	
	return vOut;
}

float4 PS(VS_OUT pIn) : SV_Target
{
	// Get materials from texture maps.
	float alpha    = gDiffuseMap.Sample( gTriLinearSam, pIn.texC0 ).a;
	
	// Discard pixel if texture alpha < 0.1.  Note that we do this
	// test as soon as possible so that we can potentially exit the shader 
	// early, thereby skipping the rest of the shader code.
	clip(alpha - 0.1f);
	
	float4 diffuse = gDiffuseMap.Sample( gTriLinearSam, pIn.texC1 );
	float4 spec    = gSpecMap.Sample( gTriLinearSam, pIn.texC1 );
	
	// Map [0,1] --> [0,256]
	spec.a *= 256.0f;
	
	// Interpolating normal can make it not be of unit length so normalize it.
    float3 normalW = normalize(pIn.normalW);
    
	// Compute the lit color for this pixel.
    SurfaceInfo v = {pIn.posW, normalW, diffuse, spec};
	float3 litColor = ParallelLight(v, gLight, gEyePosW);
	
	// Blend the fog color and the lit color.
	float3 foggedColor = lerp(litColor, gFogColor, pIn.fogLerp);
	
    return float4(foggedColor, alpha);
}

technique10 FogTech
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_4_0, VS() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PS() ) );
    }
}

因为这是笔记,详细代码就不贴了,龙书网站有

给个实现效果吧:


Directx10 龙书笔记- 雾效的实现