您的位置:首页 > 其它

D3D中的Z缓存使用示例

2016-06-20 00:00 323 查看
在渲染多边形网格对象到场景中的时候,离观察者越远的对象应该越模糊,同时离观察者越近的物体应该越清楚,这就是深度排序(depth sorting)。深度排序有两种常用的方法。

第一种方法称为画家算法(painter's algorithm)。这种方法将对象划分成不同的多边形,由后往前对这些多边形进行排序,再按照排好的顺序绘制出这些多边形。采用这种方法绘制多边形,能够确保前面的多边形总是在其后多边形之前进行绘制。

深度排序的第二种方法称为z缓冲方法(z- buffer),它是图形硬件设备使用最多的方法。这种方法依赖于像素,每个像素都有一个z值(z值是像素距离观察者的距离)。当每个像素被写入时,渲染器首先检查是否已经存在一个z值更小的像素,如果不存在,这个像素就被绘制出来;如果存在,就跳过该像素。

许多 3D图形加速卡都有一个内置的z缓冲,这也是深度排序选择z缓冲方法的原因。在应用程序中使用z缓冲,最容易的方法就是在创建设备对象以及设置显示方式的时候初始化z缓冲,如下所示:

D3DPRESENT_PARAMETERS d3dpp;

ZeroMemory(
&
d3dpp,
sizeof
(d3dpp));

d3dpp.Windowed
=
TRUE;
d3dpp.SwapEffect
=
D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat
=
d3ddm.Format;
d3dpp.EnableAutoDepthStencil
=
TRUE;
d3dpp.AutoDepthStencilFormat
=
D3DFMT_D16;

if
(FAILED(g_pD3D
->
CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&
d3dpp,
&
g_pD3DDevice)))

return
FALSE;

//
Set the rendering states

g_pD3DDevice
->
SetRenderState(D3DRS_LIGHTING, FALSE);
g_pD3DDevice
->
SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);

同时在绘制每帧之前应该用IDirect3DDevice9::Clear来清除z缓存。

//
clear device back buffer

g_d3d_device
->
Clear(
0
, NULL, D3DCLEAR_TARGET
|
D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(
0
,
0
,
0
,
255
),
1.0f
,
0
);

完整代码如下所示:

/*
**************************************************************************************
PURPOSE:
ZBuffer Demo

Required libraries:
WINMM.LIB, D3D9.LIB, D3DX9.LIB.
**************************************************************************************
*/

#include
<
windows.h
>

#include
<
stdio.h
>

#include
"
d3d9.h
"

#include
"
d3dx9.h
"

#pragma comment(lib,
"
winmm.lib
"
)
#pragma comment(lib,
"
d3d9.lib
"
)
#pragma comment(lib,
"
d3dx9.lib
"
)

#pragma warning(disable :
4305
)

#define
WINDOW_WIDTH 400

#define
WINDOW_HEIGHT 400

#define
Safe_Release(p) if((p)) (p)->Release();

//
window handles, class and caption text.

HWND g_hwnd;
HINSTANCE g_inst;

static

char
g_class_name[]
=

"
ZBufferClass
"
;

static

char
g_caption[]
=

"
ZBuffer Demo
"
;

//
the Direct3D and device object

IDirect3D9
*
g_d3d
=
NULL;
IDirect3DDevice9
*
g_d3d_device
=
NULL;

//
The 3D vertex format and descriptor

typedef
struct

{

float
x, y, z;
//
3D coordinates

D3DCOLOR color;
//
diffuse color

} VERTEX;

#define
VERTEX_FVF (D3DFVF_XYZ | D3DFVF_DIFFUSE)

IDirect3DVertexBuffer9
*
g_vertex_buffer
=
NULL;

//
--------------------------------------------------------------------------------

//
Window procedure.

//
--------------------------------------------------------------------------------

long
WINAPI Window_Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{

switch
(msg)
{

case
WM_DESTROY:
PostQuitMessage(
0
);

return

0
;
}

return
(
long
) DefWindowProc(hwnd, msg, wParam, lParam);
}

//
--------------------------------------------------------------------------------

//
Initialize d3d, d3d device, vertex buffer; set render state for d3d;

//
set perspective matrix and view matrix.

//
--------------------------------------------------------------------------------

BOOL Do_Init()
{
D3DPRESENT_PARAMETERS present_param;
D3DDISPLAYMODE display_mode;
D3DXMATRIX mat_proj, mat_view;
BYTE
*
vertex_ptr;

//
initialize vertex data

VERTEX verts[]
=
{
{
-
100.0f
,
-
100.0f
,
0.0f
, D3DCOLOR_RGBA(
255
,
0
,
0
,
255
) },
{
-
100.0f
,
100.0f
,
0.0f
, D3DCOLOR_RGBA(
255
,
0
,
0
,
255
) },
{
100.0f
,
-
100.0f
,
0.0f
, D3DCOLOR_RGBA(
255
,
0
,
0
,
255
) },
{
100.0f
,
100.0f
,
0.0f
, D3DCOLOR_RGBA(
255
,
0
,
0
,
255
) },
{
-
100.0f
,
-
100.0f
,
0.0f
, D3DCOLOR_RGBA(
255
,
0
,
0
,
255
) },
{
-
100.0f
,
100.0f
,
0.0f
, D3DCOLOR_RGBA(
255
,
0
,
0
,
255
) },

{
-
100.0f
,
-
100.0f
,
0.0f
, D3DCOLOR_RGBA(
0
,
0
,
255
,
255
) },
{
-
100.0f
,
100.0f
,
0.0f
, D3DCOLOR_RGBA(
0
,
0
,
255
,
255
) },
{
100.0f
,
-
100.0f
,
0.0f
, D3DCOLOR_RGBA(
0
,
0
,
255
,
255
) },
{
100.0f
,
100.0f
,
0.0f
, D3DCOLOR_RGBA(
0
,
0
,
255
,
255
) },
};

//
do a windowed mode initialization of Direct3D

if
((g_d3d
=
Direct3DCreate9(D3D_SDK_VERSION))
==
NULL)

return
FALSE;

//
retrieves the current display mode of the adapter

if
(FAILED(g_d3d
->
GetAdapterDisplayMode(D3DADAPTER_DEFAULT,
&
display_mode)))

return
FALSE;

ZeroMemory(
&
present_param,
sizeof
(present_param));

//
initialize d3d presentation parameter

present_param.Windowed
=
TRUE;
present_param.SwapEffect
=
D3DSWAPEFFECT_DISCARD;
present_param.BackBufferFormat
=
display_mode.Format;
present_param.EnableAutoDepthStencil
=
TRUE;
present_param.AutoDepthStencilFormat
=
D3DFMT_D16;

//
creates a device to represent the display adapter

if
(FAILED(g_d3d
->
CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&
present_param,
&
g_d3d_device)))

return
FALSE;

//
set render state

//
disable d3d lighting

g_d3d_device
->
SetRenderState(D3DRS_LIGHTING, FALSE);

//
enable z-buffer

g_d3d_device
->
SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);

//
create and set the projection matrix

//
builds a left-handed perspective projection matrix based on a field of view

D3DXMatrixPerspectiveFovLH(
&
mat_proj, D3DX_PI
/
4.0
,
1.33333
,
1.0
,
1000.0
);

//
sets a single device transformation-related state

g_d3d_device
->
SetTransform(D3DTS_PROJECTION,
&
mat_proj);

//
create and set the view matrix

D3DXMatrixLookAtLH(
&
mat_view,

&
D3DXVECTOR3(
0.0
,
0.0
,
-
500.0
),

&
D3DXVECTOR3(
0.0f
,
0.0f
,
0.0f
),

&
D3DXVECTOR3(
0.0f
,
1.0f
,
0.0f
));

g_d3d_device
->
SetTransform(D3DTS_VIEW,
&
mat_view);

//
create the vertex buffer and set data

g_d3d_device
->
CreateVertexBuffer(
sizeof
(verts),
0
, VERTEX_FVF, D3DPOOL_DEFAULT,
&
g_vertex_buffer, NULL);

//
locks a range of vertex data and obtains a pointer to the vertex buffer memory

g_vertex_buffer
->
Lock(
0
,
0
, (
void
**
)
&
vertex_ptr,
0
);

memcpy(vertex_ptr, verts,
sizeof
(verts));

//
unlocks vertex data

g_vertex_buffer
->
Unlock();

return
TRUE;
}

//
--------------------------------------------------------------------------------

//
Release all d3d resource.

//
--------------------------------------------------------------------------------

BOOL Do_Shutdown()
{
Safe_Release(g_vertex_buffer);
Safe_Release(g_d3d_device);
Safe_Release(g_d3d);

return
TRUE;
}

//
--------------------------------------------------------------------------------

//
Render a frame.

//
--------------------------------------------------------------------------------

BOOL Do_Frame()
{
D3DXMATRIX mat_world;

//
clear device back buffer

g_d3d_device
->
Clear(
0
, NULL, D3DCLEAR_TARGET
|
D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(
0
,
0
,
0
,
255
),
1.0f
,
0
);

//
Begin scene

if
(SUCCEEDED(g_d3d_device
->
BeginScene()))
{

//
set the vertex stream, shader.

//
binds a vertex buffer to a device data stream

g_d3d_device
->
SetStreamSource(
0
, g_vertex_buffer,
0
,
sizeof
(VERTEX));

//
set the current vertex stream declation

g_d3d_device
->
SetFVF(VERTEX_FVF);

//
create and set the world transformation matrix

//
rotate object along y-axis

D3DXMatrixRotationY(
&
mat_world, (
float
) (timeGetTime()
/

1000.0
));

g_d3d_device
->
SetTransform(D3DTS_WORLD,
&
mat_world);

//
renders a sequence of noindexed, geometric primitives of the specified type from the current set

//
of data input stream.

g_d3d_device
->
DrawPrimitive(D3DPT_TRIANGLESTRIP,
0
,
4
);

//
draw next four polygons, but rotate on z-axis.

D3DXMatrixRotationZ(
&
mat_world,
-
(
float
)(timeGetTime()
/

1000.0
));
g_d3d_device
->
SetTransform(D3DTS_WORLD,
&
mat_world);
g_d3d_device
->
DrawPrimitive(D3DPT_TRIANGLESTRIP,
6
,
2
);

//
end the scene

g_d3d_device
->
EndScene();
}

//
present the contents of the next buffer in the sequence of back buffers owned by the device

g_d3d_device
->
Present(NULL, NULL, NULL, NULL);

return
TRUE;
}

//
--------------------------------------------------------------------------------

//
Main function, routine entry.

//
--------------------------------------------------------------------------------

int
WINAPI WinMain(HINSTANCE inst, HINSTANCE, LPSTR cmd_line,
int
cmd_show)
{
WNDCLASSEX win_class;
MSG msg;

g_inst
=
inst;

//
create window class and register it

win_class.cbSize
=

sizeof
(win_class);
win_class.style
=
CS_CLASSDC;
win_class.lpfnWndProc
=
Window_Proc;
win_class.cbClsExtra
=

0
;
win_class.cbWndExtra
=

0
;
win_class.hInstance
=
inst;
win_class.hIcon
=
LoadIcon(NULL, IDI_APPLICATION);
win_class.hCursor
=
LoadCursor(NULL, IDC_ARROW);
win_class.hbrBackground
=
NULL;
win_class.lpszMenuName
=
NULL;
win_class.lpszClassName
=
g_class_name;
win_class.hIconSm
=
LoadIcon(NULL, IDI_APPLICATION);

if
(
!
RegisterClassEx(
&
win_class))

return
FALSE;

//
create the main window

g_hwnd
=
CreateWindow(g_class_name, g_caption, WS_CAPTION
|
WS_SYSMENU,
0
,
0
,
WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, inst, NULL);

if
(g_hwnd
==
NULL)

return
FALSE;

ShowWindow(g_hwnd, SW_NORMAL);
UpdateWindow(g_hwnd);

//
initialize game

if
(Do_Init()
==
FALSE)

return
FALSE;

//
start message pump, waiting for signal to quit.

ZeroMemory(
&
msg,
sizeof
(MSG));

while
(msg.message
!=
WM_QUIT)
{

if
(PeekMessage(
&
msg, NULL,
0
,
0
, PM_REMOVE))
{
TranslateMessage(
&
msg);
DispatchMessage(
&
msg);
}

//
draw a frame

if
(Do_Frame()
==
FALSE)

break
;
}

//
run shutdown function

Do_Shutdown();

UnregisterClass(g_class_name, inst);

return
(
int
) msg.wParam;
}

效果图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: