霧化效果(以下簡稱霧)提高了場景的真實性,可以用它來模擬逼真的天氣狀況。另外,霧可以大大減少遠剪裁面
(far-clip)在視覺上帶給觀者的不自然的感覺。Direct3D霧化是固定功能管線的一部份,受渲染狀態(tài)限制。
下面的效果文件設(shè)置頂點霧,以達到必要的霧化狀態(tài)。注意:Direct3D也支持像素霧(也叫表格霧table
fog),比頂點霧要更精確。
/**********************************************************************************
Effect file that handles device states for linear vertex fog.
**********************************************************************************/
technique FogTech
{
pass pass0
{
// set misc render states
pixelshader = null;
vertexshader = null;
fvf = XYZ | Normal;
Lighting = true;
NormalizeNormals = true;
SpecularEnable = false;
// fog states
FogVertexMode = LINEAR; // linear fog function
FogStart = 50.0f; // fog starts 50 units away from viewpoint
FogEnd = 300.0f; // fog ends 300 units away from viewpoint
FogColor = 0x00CCCCCC; // gray
FogEnable = true; // enable
}
}
就象你看到的,線性頂點霧能夠通過五個簡單的渲染狀態(tài)控制:
FogVertexMode—使用指定的霧函數(shù)用于頂點霧。霧函數(shù)指定霧如何根據(jù)距離增長,自然界的霧在近視口的地方比較薄并且根據(jù)距離增長變得厚起來了。有效的任務(wù)類型為LINEAR、EXP、EXP2。這些函數(shù)被定義為:

注意:如果你用EXP或EXP2霧化函數(shù),你不用設(shè)置FogStart
和
FogEnd,因為它們在這些霧函數(shù)類型中沒被用到。代替的你必須設(shè)置霧密度(fog
density)渲染狀態(tài)(如,F(xiàn)ogDensity
= someFloatType)
FogStart—標記了物體將開始霧化的起始深度。
FogEnd—標記了物體將結(jié)束霧化的結(jié)束深度。
注意:FogStart
與
FogEnd本質(zhì)上定義了物體被霧化的深度間隔(從視口)。
FogColor—一個DWORD
或
D3DCOLOR值,以描述霧的顏色
FogEnable—指定true以開啟頂點霧或false以關(guān)閉頂點霧
任何我們用FogShader.cxx效果渲染的幾何體將被霧化。通過這種方式,我們可以控制哪一物體得到霧化,而哪些不用霧化。這對只霧化特定區(qū)域是很有用的。例如,通常屋外是有霧的,屋里不被霧化。同樣的,一定地理部分可能有霧,而另外部分可能沒有。下圖展示了例程的屏幕截圖。

執(zhí)行程序:
/**************************************************************************************************
Demonstrates using an effect file. Use the arrwo keys, and M, N, W, S, keys to move.
**************************************************************************************************/
#include "d3dUtility.h"
#include "terrain.h"
#include "camera.h"
#pragma warning(disable : 4100)
using namespace std;
const int WIDTH = 640;
const int HEIGHT = 480;
IDirect3DDevice9* g_device;
cTerrain* g_terrain;
cCamera g_camera(AIR_CRAFT);
ID3DXEffect* g_fog_effect;
D3DXHANDLE g_fog_tech_handle;
////////////////////////////////////////////////////////////////////////////////////////////////////
bool setup()
{
// init scene
D3DXVECTOR3 dir_to_light(0.0f, 1.0f, 0.0f);
g_terrain = new cTerrain(g_device, "coastMountain64.raw", 64, 64, 6, 0.5f);
g_terrain->generate_texture(&dir_to_light);
// set texture filters
g_device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
g_device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
g_device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
// set camera position
g_camera.m_pos = D3DXVECTOR3(100.0f, 100.0f, -250.0f);
// create effect
ID3DXBuffer* error_buffer;
HRESULT hr = D3DXCreateEffectFromFile(g_device, "FogShader.cxx", NULL, NULL, D3DXSHADER_DEBUG, NULL,
&g_fog_effect, &error_buffer);
// output any error messages
if(error_buffer)
{
MessageBox(NULL, (char*) error_buffer->GetBufferPointer(), "ERROR", MB_OK);
safe_release<ID3DXBuffer*>(error_buffer);
}
if(FAILED(hr))
{
MessageBox(NULL, "D3DXCreateEffectFromFile() - FAILED", "ERROR", MB_OK);
return false;
}
// save frequently accessed parameter handles
g_fog_tech_handle = g_fog_effect->GetTechniqueByName("FogTech");
// set projection
D3DXMATRIX proj_matrix;
D3DXMatrixPerspectiveFovLH(&proj_matrix, D3DX_PI * 0.25f, (float)WIDTH/HEIGHT, 1.0f, 1000.0f);
g_device->SetTransform(D3DTS_PROJECTION, &proj_matrix);
//g_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
void cleanup()
{
safe_delete<cTerrain*>(g_terrain);
safe_release<ID3DXEffect*>(g_fog_effect);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
bool display(float time_delta)
{
// update the scene: allow user to rotate around scene.
if(GetAsyncKeyState(VK_UP) & 0x8000f)
g_camera.walk(100.0f * time_delta);
if(GetAsyncKeyState(VK_DOWN) & 0x8000f)
g_camera.walk(-100.0f * time_delta);
if(GetAsyncKeyState(VK_LEFT) & 0x8000f)
g_camera.yaw(-1.0f * time_delta);
if(GetAsyncKeyState(VK_RIGHT) & 0x8000f)
g_camera.yaw(1.0f * time_delta);
if(GetAsyncKeyState('N') & 0x8000f)
g_camera.strafe(-100.0f * time_delta);
if(GetAsyncKeyState('M') & 0x8000f)
g_camera.strafe(100.0f * time_delta);
if(GetAsyncKeyState('W') & 0x8000f)
g_camera.pitch(1.0f * time_delta);
if(GetAsyncKeyState('S') & 0x8000f)
g_camera.pitch(-1.0f * time_delta);
D3DXMATRIX view_matrix;
g_camera.get_view_matrix(&view_matrix);
g_device->SetTransform(D3DTS_VIEW, &view_matrix);
// activate the technique and render
g_device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00CCCCCC, 1.0f, 0);
g_device->BeginScene();
// set the technique to use
g_fog_effect->SetTechnique(g_fog_tech_handle);
UINT num_passes;
g_fog_effect->Begin(&num_passes, 0);
D3DXMATRIX world_matrix;
D3DXMatrixIdentity(&world_matrix);
for(UINT i = 0; i < num_passes; i++)
{
g_fog_effect->BeginPass(i);
g_terrain->draw(&world_matrix, false);
g_fog_effect->EndPass();
}
g_fog_effect->End();
g_device->EndScene();
g_device->Present(NULL, NULL, NULL, NULL);
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK wnd_proc(HWND hwnd, UINT msg, WPARAM word_param, LPARAM long_param)
{
switch(msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_KEYDOWN:
if(word_param == VK_ESCAPE)
DestroyWindow(hwnd);
break;
}
return DefWindowProc(hwnd, msg, word_param, long_param);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
int WINAPI WinMain(HINSTANCE inst, HINSTANCE, PSTR cmd_line, int cmd_show)
{
if(! init_d3d(inst, WIDTH, HEIGHT, true, D3DDEVTYPE_HAL, &g_device))
{
MessageBox(NULL, "init_d3d() - failed.", 0, MB_OK);
return 0;
}
if(! setup())
{
MessageBox(NULL, "Steup() - failed.", 0, MB_OK);
return 0;
}
enter_msg_loop(display);
cleanup();
g_device->Release();
return 0;
}
下載源程序