雾 : 说白了就是一层有颜色的(一般是白色,灰色) 蒙蒙的感觉 混在光线里面。 不管是白天还是黑天。
龙书里面是这样实现的:
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() ) );
}
}
给个实现效果吧:
原文地址:http://blog.csdn.net/cq361106306/article/details/39453271