D3D中的Z缓存使用示例

在渲染多边形网格对象到场景中的时候,离观察者越远的对象应该越模糊,同时离观察者越近的物体应该越清楚,这就是深度排序(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.0f100.0f, 0.0f, D3DCOLOR_RGBA(255,0,0,255) },
      { 
100.0f, -100.0f, 0.0f, D3DCOLOR_RGBA(255,0,0,255) },
      { 
100.0f100.0f, 0.0f, D3DCOLOR_RGBA(255,0,0,255) },
      {
-100.0f, -100.0f, 0.0f, D3DCOLOR_RGBA(255,0,0,255) },
      {
-100.0f100.0f, 0.0f, D3DCOLOR_RGBA(255,0,0,255) },

      {
-100.0f, -100.0f, 0.0f, D3DCOLOR_RGBA(0,0,255,255) },
      {
-100.0f100.0f, 0.0f, D3DCOLOR_RGBA(0,0,255,255) },
      { 
100.0f, -100.0f, 0.0f, D3DCOLOR_RGBA(0,0,255,255) },
      { 
100.0f100.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;
}

效果图:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值