除了用來實作透明效果之外,我們還可以用alpha blend來實作霧(fog)的效果。通過逐漸清晰的霧氣效果,可以增加場景的真實感。
霧的效果實作很簡單,首先我們要一種顔色來表示霧,通常使用用灰色。
其實霧的效果和視點有很大關系,距離視點越近,霧就越淡,距離越遠,霧就越濃。
最終物體顔色是霧的顔色和計算出的pixel顔色的混合,我們使用的公式如下:
Final Color = FogFactor * computed pixel color + (1.0 - FogFactor) * FogColor
可以看出,最終的顔色是霧的顔色和計算的pixel顔色基于霧因子的權重平均。
下面我看看如何計算霧因子:
首先定義一個霧範圍(fogstart, fogend),在這個範圍内,霧逐漸由淡變濃,超出fogend後,就完全是霧的顔色了,再假定頂點到視點的距離為ViewDistance,則霧因子的計算公式有以下幾種:
1、線性因子
Linear Fog = (FogEnd - ViewpointDistance) / (FogEnd - FogStart)
2、指數因子
Exponential Fog = exp2(-abs(ViewpointDistance * FogDensity))
3、二次指數因子
Exponential Fog 2 = exp2(- (ViewpointDistance * FogDensity) *(ViewpointDistance * FogDensity))
下面我們在myTutorialD3D11_41的基礎上來實作霧的效果:
首先需要修改的是lighttex.vs和lighttex.ps, 在vs中,我們定義一個常量緩沖,表示fog的參數,然後根據這幾個參數來計算霧因子,并把霧因子傳遞到ps階段。
lighttex.vs代碼:
cbuffer FogBuffer
{
float fogStart;
float fogEnd;
float fogDensity;
float padding;
};
…
// 計算錄影機的位置.
cameraPosition = mul(input.position, worldMatrix);
cameraPosition = mul(cameraPosition, viewMatrix);
// 計算線性霧.
output.fogFactor = saturate((fogEnd - cameraPosition.z) / (fogEnd - fogStart));
lighttex.ps代碼:
// 混合霧顔色.
finalcolor = input.fogFactor * finalcolor1 + (1.0 - input.fogFactor) * fogColor;
另外在LightTexShaderClass中,也要做一些小改動,增加設定FogBuffer的代碼,并在Render函數和 SetShaderParameters中,增加三個參數,用來設定fog。
最後,在GraphicsClass中,定義四個參數,并把它們傳入shader。
float fogColor, fogStart, fogEnd, fogDensity;
// 霧顔色.
fogColor = 0.5f;
// 霧距離.
fogStart = 20.0f;
fogEnd = 80.0f;
fogDensity = 0.04f;
首先用fogColor設定背景,這樣很遠的地方就是霧的顔色,…
程式執行後,界面如下:
下面我們在vs中嘗試修改霧因子的計算方法,看看指數因子和二次指數因子的效果。
指數因子:
// 計算指數因子.
output.fogFactor = saturate(exp2(-abs( cameraPosition.z *fogDensity)) );
二次指數因子:
fogDensity = 0.02f;
// 計算指數因子.
output.fogFactor = saturate(exp2(- ( cameraPosition.z *fogDensity)*( cameraPosition.z *fogDensity)) );
完整的代碼請參考:
工程檔案myTutorialD3D11_42
代碼下載下傳:
<a href="http://files.cnblogs.com/mikewolf2002/d3d1139-49.zip">http://files.cnblogs.com/mikewolf2002/d3d1139-49.zip</a>
<a href="http://files.cnblogs.com/mikewolf2002/pictures.zip">http://files.cnblogs.com/mikewolf2002/pictures.zip</a>