天行健 君子当自强而不息

Direct3D程序设计基础(1)

Direct3D对象

Microsoft Direct3D的一种实现方式是通过组件对象模型(Component Object Model, COM)及其接口实现的,在用C++语言和COM接口方式开发的程序中可以直接访问这些接口和对象。Direct3D对象是Direct3D程序中需要创建的第一个对象,也是需要最后一个释放的对象,这里所说的对象是指COM对象。通过Direct3D对象,可以枚举和检索Direct3D设备,这样应用程序就可以在不需要创建设备对象的前提下选择Direct3D渲染设备。

在用C++语言编写Direct3D程序时,需要先获取一个指向IDirect3D9接口的指针,从而可以通过该接口调用Direct3D对象的功能。

 

创建Direct3D设备对象

创建Direct3D设备对象时,需要先创建Direct3D对象,然后再调用Direct3D对象的接口函数IDirect3D9::CreateDevice创建Direct3D设备对象。通过同一个Direct3D对象创建的所有Direct3D设备对象共享相同的物理资源(显卡)。因为共享同一硬件,所以如果通过一个Direct3D对象创建多个Direct3D渲染设备对象会明显降低系统性能。

在创建Direct3D设备对象之前,还需要先初始化D3DPRESENT_PARAMETERS结构,该结构用于创建Direct3D设备对象。D3DPRESENT_PARAMETERS结构定义了Direct3D设备对象的相关信息,而这些信息将会影响Direct3D设备的显示方法。该结构的定义如下:

Describes the presentation parameters.

typedef struct D3DPRESENT_PARAMETERS {
UINT BackBufferWidth, BackBufferHeight;
D3DFORMAT BackBufferFormat;
UINT BackBufferCount;
D3DMULTISAMPLE_TYPE MultiSampleType;
DWORD MultiSampleQuality;
D3DSWAPEFFECT SwapEffect;
HWND hDeviceWindow;
BOOL Windowed;
BOOL EnableAutoDepthStencil;
D3DFORMAT AutoDepthStencilFormat;
DWORD Flags;
UINT FullScreen_RefreshRateInHz;
UINT PresentationInterval;
} D3DPRESENT_PARAMETERS, *LPD3DPRESENT_PARAMETERS;

Members

BackBufferWidth, BackBufferHeight
Width and height of the new swap chain's back buffers, in pixels. If Windowed is FALSE (the presentation is full-screen), these values must equal the width and height of one of the enumerated display modes found through IDirect3D9::EnumAdapterModes. If Windowed is TRUE and either of these values is zero, the corresponding dimension of the client area of the hDeviceWindow (or the focus window, if hDeviceWindow is NULL) is taken.
BackBufferFormat
The back buffer format. For more information about formats, see D3DFORMAT. This value must be one of the render-target formats as validated by IDirect3D9::CheckDeviceType. You can use IDirect3DDevice9::GetDisplayMode to obtain the current format.

In fact, D3DFMT_UNKNOWN can be specified for the BackBufferFormat while in windowed mode. This tells the runtime to use the current display-mode format and eliminates the need to call IDirect3DDevice9::GetDisplayMode.

For windowed applications, the back buffer format no longer needs to match the display-mode format because color conversion can now be done by the hardware (if the hardware supports color conversion). The set of possible back buffer formats is constrained, but the runtime will allow any valid back buffer format to be presented to any desktop format. (There is the additional requirement that the device be operable in the desktop mode; devices typically do not operate in 8 bits per pixel modes.)

Full-screen applications cannot do color conversion.

BackBufferCount
This value can be between 0 and D3DPRESENT_BACK_BUFFERS_MAX (or D3DPRESENT_BACK_BUFFERS_MAX_EX when using Direct3D 9Ex). Values of 0 are treated as 1. If the number of back buffers cannot be created, the runtime will fail the method call and fill this value with the number of back buffers that could be created. As a result, an application can call the method twice with the same D3DPRESENT_PARAMETERS structure and expect it to work the second time.

The method fails if one back buffer cannot be created. The value of BackBufferCount influences what set of swap effects are allowed. Specifically, any D3DSWAPEFFECT_COPY swap effect requires that there be exactly one back buffer.

MultiSampleType
Member of the D3DMULTISAMPLE_TYPE enumerated type. The value must be D3DMULTISAMPLE_NONE unless SwapEffect has been set to D3DSWAPEFFECT_DISCARD. Multisampling is supported only if the swap effect is D3DSWAPEFFECT_DISCARD.
MultiSampleQuality
Quality level. The valid range is between zero and one less than the level returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType. Passing a larger value returns the error D3DERR_INVALIDCALL. Paired values of render targets or of depth stencil surfaces and D3DMULTISAMPLE_TYPE must match.
SwapEffect
Member of the D3DSWAPEFFECT enumerated type. The runtime will guarantee the implied semantics concerning buffer swap behavior; therefore, if Windowed is TRUE and SwapEffect is set to D3DSWAPEFFECT_FLIP, the runtime will create one extra back buffer and copy whichever becomes the front buffer at presentation time.

D3DSWAPEFFECT_COPY requires that BackBufferCount be set to 1.

D3DSWAPEFFECT_DISCARD will be enforced in the debug runtime by filling any buffer with noise after it is presented.

hDeviceWindow
The device window determines the location and size of the back buffer on screen. This is used by Direct3D when the back buffer contents are copied to the front buffer during IDirect3DDevice9::Present.
  • For a full-screen application, this is a handle to the top window (which is the focus window).

    For applications that use multiple full-screen devices (such as a multimonitor system), exactly one device can use the focus window as the device window. All other devices must have unique device windows.

  • For a windowed-mode application, this handle will be the default target window for IDirect3DDevice9::Present. If this handle is NULL, the focus window will be taken.

Note that no attempt is made by the runtime to reflect user changes in window size. The back buffer is not implicitly reset when this window is reset. However, the IDirect3DDevice9::Present method does automatically track window position changes.

Windowed
TRUE if the application runs windowed; FALSE if the application runs full-screen.
EnableAutoDepthStencil
If this value is TRUE, Direct3D will manage depth buffers for the application. The device will create a depth-stencil buffer when it is created. The depth-stencil buffer will be automatically set as the render target of the device. When the device is reset, the depth-stencil buffer will be automatically destroyed and recreated in the new size.

If EnableAutoDepthStencil is TRUE, then AutoDepthStencilFormat must be a valid depth-stencil format.

AutoDepthStencilFormat
Member of the D3DFORMAT enumerated type. The format of the automatic depth-stencil surface that the device will create. This member is ignored unless EnableAutoDepthStencil is TRUE.
Flags
One of the D3DPRESENTFLAG constants.
FullScreen_RefreshRateInHz
The rate at which the display adapter refreshes the screen. The value depends on the mode in which the application is running:
  • For windowed mode, the refresh rate must be 0.
  • For full-screen mode, the refresh rate is one of the refresh rates returned by IDirect3D9::EnumAdapterModes.
PresentationInterval
The maximum rate at which the swap chain's back buffers can be presented to the front buffer. For a detailed explanation of the modes and the intervals that are supported, see D3DPRESENT.

 

Direct3D程序基本结构

虽然Direct3D功能非常强大,但是Direct3D程序的基本结构非常简单清晰,它主要有5个步骤:

(1)创建一个Windows窗口。

(2)初始化Direct3D,包括创建Direct3D对象、Direct3D设备对象以及要渲染的图形对象。

(3)消息循环。

(4)渲染图形。

(5)清除在初始化时创建的所有COM对象,退出程序。

其中消息循环和渲染图形不断进行,如果程序有消息需要处理,则先处理消息,然后再渲染图形;如果没有消息处理,则一直不停地渲染图形,直到退出Direct3D程序。

 

最简单的Direct3D程序

#include <d3d9.h>

#define CLASS_NAME    "GameApp"

#define release_com(p)    { if(p) { (p)->Release(); (p) = NULL; } }

IDirect3D9
*            g_d3d;
IDirect3DDevice9
*    g_device;

bool init_d3d(HWND hwnd)
{
    g_d3d 
= Direct3DCreate9(D3D_SDK_VERSION);

    
if(g_d3d == NULL)
        
return false;

    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory(
&d3dpp, sizeof(d3dpp));

    d3dpp.Windowed            
= TRUE;
    d3dpp.SwapEffect        
= D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat    
= D3DFMT_UNKNOWN;

    
if(FAILED(g_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                  
&d3dpp, &g_device)))
    {
        
return false;
    }

    
return true;
}

void cleanup()
{
    release_com(g_device);
    release_com(g_d3d);
}

void render()
{
    g_device
->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(4550170), 1.0f0);

    g_device
->BeginScene();

    
// render game scene here 

    g_device
->EndScene();

    g_device
->Present(NULL, NULL, NULL, NULL);
}

LRESULT WINAPI WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    
switch(msg)
    {
    
case WM_KEYDOWN:
        
if(wParam == VK_ESCAPE)
            DestroyWindow(hwnd);
        
break;

    
case WM_DESTROY:        
        PostQuitMessage(
0);
        
return 0;
    }

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

int WINAPI WinMain(HINSTANCE inst, HINSTANCE, LPSTR, INT)
{
    WNDCLASSEX wc;

    wc.cbSize            
= sizeof(WNDCLASSEX);
    wc.style            
= CS_CLASSDC;
    wc.lpfnWndProc        
= WinProc;
    wc.cbClsExtra        
= 0;
    wc.cbWndExtra        
= 0;
    wc.hInstance        
= inst;
    wc.hIcon            
= NULL;
    wc.hCursor            
= NULL;
    wc.hbrBackground    
= NULL;
    wc.lpszMenuName        
= NULL;
    wc.lpszClassName    
= CLASS_NAME;
    wc.hIconSm            
= NULL;

    
if(! RegisterClassEx(&wc))
        
return -1;

    HWND hwnd 
= CreateWindow(CLASS_NAME, "Direct3D App", WS_OVERLAPPEDWINDOW, 200100600500,
                             NULL, NULL, wc.hInstance, NULL);

    
if(hwnd == NULL)
        
return -1;

    
if(init_d3d(hwnd))
    {
        ShowWindow(hwnd, SW_SHOWDEFAULT);
        UpdateWindow(hwnd);

        MSG msg;
        ZeroMemory(
&msg, sizeof(msg));

        
while(msg.message != WM_QUIT)
        {
            
if(PeekMessage(&msg, NULL, 00, PM_REMOVE))
            {
                TranslateMessage(
&msg);
                DispatchMessage(
&msg);
            }
            
else
            {
                render();
            }
        }
    }

    cleanup();

    UnregisterClass(CLASS_NAME, wc.hInstance);    

    
return 0;
}

 

运行截图:


posted on 2008-04-29 12:57 lovedday 阅读(2782) 评论(2)  编辑 收藏 引用

评论

# re: Direct3D程序设计基础(1) 2008-07-19 17:58 riki

真佩服你,你是从哪里找来那么全的资料的。我看你资料好久了。  回复  更多评论   

# re: Direct3D程序设计基础(1) 2008-08-18 05:10 lyra

我也很佩服 人真好啊 弄这么多资料让我们学习  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


公告

导航

统计

常用链接

随笔分类(178)

3D游戏编程相关链接

搜索

最新评论