效果框架(3)
雾化效果(以下简称雾)提高了场景的真实性,可以用它来模拟逼真的天气状况。另外,雾可以大大减少远剪裁面 (far-clip)在视觉上带给观者的不自然的感觉。Direct3D雾化是固定功能管线的一部份,受渲染状态限制。
下面的效果文件设置顶点雾,以达到必要的雾化状态。注意: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
}
}
就象你看到的,线性顶点雾能够通过五个简单的渲染状态控制:
FogVertexMode—使用指定的雾函数用于顶点雾。雾函数指定雾如何根据距离增长,自然界的雾在近视口的地方比较薄并且根据距离增长变得厚起来了。有效的任务类型为LINEAR、EXP、EXP2。这些函数被定义为:
注意:如果你用EXP或EXP2雾化函数,你不用设置FogStart 和 FogEnd,因为它们在这些雾函数类型中没被用到。代替的你必须设置雾密度(fog density)渲染状态(如,FogDensity = someFloatType)
FogStart—标记了物体将开始雾化的起始深度。
FogEnd—标记了物体将结束雾化的结束深度。
注意:FogStart 与 FogEnd本质上定义了物体被雾化的深度间隔(从视口)。
FogColor—一个DWORD 或 D3DCOLOR值,以描述雾的颜色
FogEnable—指定true以开启顶点雾或false以关闭顶点雾
任何我们用FogShader.cxx效果渲染的几何体将被雾化。通过这种方式,我们可以控制哪一物体得到雾化,而哪些不用雾化。这对只雾化特定区域是很有用的。例如,通常屋外是有雾的,屋里不被雾化。同样的,一定地理部分可能有雾,而另外部分可能没有。下图展示了例程的屏幕截图。
执行程序:
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 ;
}
下载源程序