D3D的初始化

要开始D3D编程,首先是要初始化D3D环境,SDK文档的tutorial将整个过程分为几部

  1. 创建一个窗体
  2. 初始化D3D
    • 获取IDirect3D9的指针
    • 检查设备的性能、对API的支持能力
    • 初始化D3DPRESENT_PARAMETERS
    • 使用D3DPRESENT_PARAMETER的参数创建IDirectDDevice9
  3. 处理消息
  4. 渲染&显示场景
  5. 关闭D3D,退出程序

  1. 创建窗体
    之前说过,D3D程序是在一个windows窗体的客户区进行绘制,D3D相当于画笔的话,这个窗体就是画布,所以在初始化D3D之前首先要有一个窗体,根据简单的Windows API编程回顾的内容,创建一个简单窗体并不难。
    • 定义窗口类
    WNDCLASS wclass;
    • 注册窗口类
    RegisterClass(&wclass);
    • 创建窗口
    CreateWindow(...);
  2. 初始化D3D
    一旦创建好了窗体,就可以在这个基础上进一步去初始化D3D,创建D3D设备,以在窗体这个画布上进行绘图,初始化D3D的过程可以分为四部。
    • 获取IDirect3D9的指针,游戏开发中最常用的就是COM配合DirectX技术,这儿IDirect3D9就是一个表示D3D9的COM接口,因此不能直接使用C++的new操作符
    LPDIRECT3D9 g_pD3D9;    //IDirect3D9 *g_pD3D9;
    g_pD3D9 = Direct3DCreate9(D3D_SDK_VERSION);
    • 检查设备性能,对API的支持程度(如硬件TnL,这个是比较老的固定功能流水线中所采用的一些东西,现代的可编程流水线已经见不着了)
    //以硬件TnL为例
    D3DCAPS9 d3dcap;
    int hwTnL = 0;
    g_pD3D9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dcaps);
    if(caps.Devcaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
        hwTnL = D3DCREATE_HARDWARE_VERTEXPROCESSING;
    else
        hwTnL = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
    • 建立一个D3DPRESENT_PARAMETERS
    D3DPRESENT_PARAMETERS d3dpp;
    //按需设置d3dpp的各类属性
    • 建立D3D设备
    g_pD3D9->CreateDevice(D3DADAPTER,
                          D3DDEVTYPE,
                          HWND, BEHAVIOR_FLAGS
                          D3DPRESENT_PARAMETERS*,
                          IDirect3DDevice9 **);

    至此,D3D的初始化就完成了

  3. 处理消息
    就如简单的Windows API编程回顾中所述,游戏程序多数不是事件驱动的,因而可以使用PeekMessage处理消息

    MSG msg;
    while(PeekMessage(&msg, 0, 0, 0, 0))
    {
        if(msg.message == WM_QUIT)
            break;
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    //Game Codes
  4. 渲染&显示场景
    • 清除后台缓存,将后台缓存置为所设定的颜色,将深度或模板缓存设置为需要的值
    //IDirect3DDevice9::Clear
    g_pD3DDEV9->Clear(DWORD Count, const D3DRECT *pRects,
                      DWORD flags, D3DCOLOR Color, float Z, DWORD Stencil);
    • 向后台缓存绘制场景
    g_pD3DDEV9->BeginScene();
    //Render Codes
    g_pD3DDEV9->EndScene();
    • 提交下一帧后台缓存,仅仅是提交,还没有显示
    //IDirect3DDevice9::Present
    g_pD3DDEV9->Present(0,0,0,0);
  5. 关闭D3D,退出程序
    退出程序不困难,但之前要先关闭D3D。之前说了g_pD3D9和g_pD3DDEV9是两个COM接口指针,而COM不可以使用C++的new/delete操作符来创建和销毁,所以需要手动的来释放一下
g_pD3D9->Release();
g_pD3D9 = NULL;
g_pD3DDEV9->Release();
g_pD3DDEV9 = NULL;

至此,整个D3D程序流程就结束了

全部代码如下

#include <windows.h>
#include <d3d9.h>
#include <strsafe.h>

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


LPDIRECT3D9         g_pD3D9;
LPDIRECT3DDEVICE9   g_pD3D9dev;

HWND hMain;

bool initWinApp(HINSTANCE hInstance, int iCmdShow);
LRESULT CALLBACK MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

HRESULT D3DInit(HWND hWnd);
void D3DRender();
void D3DCleanup();


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmd, int iCmdShow)
{
    if( !initWinApp(hInstance, iCmdShow) )
    {
        ::MessageBox(0, TEXT("initWinApp Failed!"), TEXT("ERROR"), MB_OK);
        return 0;
    }

    if( SUCCEEDED(D3DInit(hMain)) )
    {
        ::ShowWindow(hMain, iCmdShow);
        ::UpdateWindow(hMain);

        MSG msg;
        while( PeekMessage(&msg, 0, 0, 0, 0 ) )
        {
            if( msg.message == WM_QUIT )
                break;
            msg.message = WM_PAINT;
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    D3DCleanup();
    UnregisterClass(L"D3DInit", hInstance);
    return 0;


}

bool initWinApp(HINSTANCE hInstance, int iCmdshow)
{
    WNDCLASS wc;
    wc.style        = CS_HREDRAW | CS_VREDRAW; 
    wc.lpfnWndProc  = MsgProc;
    wc.cbClsExtra   = 0;
    wc.cbWndExtra   = 0;
    wc.hInstance    = hInstance;
    wc.hIcon        = ::LoadIcon(0, IDI_APPLICATION);
    wc.hCursor      = ::LoadCursor(0, IDC_ARROW);
    wc.hbrBackground= static_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH));
    wc.lpszMenuName = 0;
    wc.lpszClassName= TEXT("D3DInit");

    if( !RegisterClass(&wc) )
    {
        ::MessageBox(0, TEXT("RegisterClass Failed!"), TEXT("ERROR"), MB_OK);
        return false;
    }

    if( (hMain = CreateWindow(TEXT("D3DInit"), TEXT("D3DInit"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
        CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL)) == NULL)
    {
        ::MessageBox(0, TEXT("CreateWindow Failed!"), TEXT("ERROR"), MB_OK);
        return false;
    }

    return true;
}

HRESULT D3DInit(HWND hWnd)
{
    //acquire pointer to IDirect3D9
    if( (g_pD3D9 = Direct3DCreate9(D3D_SDK_VERSION)) == NULL )
    {
        ::MessageBox(0, TEXT("Direct3DCreate Failed!"), TEXT("ERROR"), MB_OK);
        return E_FAIL;
    }

    //Check Device Capabilities, here we check the hardware TnL support
    D3DCAPS9 caps;
    g_pD3D9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
    int hardwareTnL = 0;
    if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
        hardwareTnL = D3DCREATE_HARDWARE_VERTEXPROCESSING;
    else
        hardwareTnL = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

    //setup D3DPRESENT_PARAMETERS which defines the behavior of the D3D app 
    D3DPRESENT_PARAMETERS d3dpp;
    d3dpp.BackBufferWidth           = 800;
    d3dpp.BackBufferHeight          = 600;
    d3dpp.BackBufferCount           = 2;
    d3dpp.BackBufferFormat          = D3DFMT_A8R8G8B8;
    d3dpp.MultiSampleType           = D3DMULTISAMPLE_NONE;
    d3dpp.MultiSampleQuality        = 0;
    d3dpp.SwapEffect                = D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow             = hMain;
    d3dpp.Windowed                  = 1;
    d3dpp.EnableAutoDepthStencil    = TRUE;
    d3dpp.AutoDepthStencilFormat    = D3DFMT_D24S8;
    d3dpp.Flags                     = 0;
    d3dpp.FullScreen_RefreshRateInHz= D3DPRESENT_RATE_DEFAULT;
    d3dpp.PresentationInterval      = D3DPRESENT_INTERVAL_IMMEDIATE;

    //Create D3D device
    if( FAILED(g_pD3D9->CreateDevice(D3DADAPTER_DEFAULT,
                                    D3DDEVTYPE_HAL,
                                    hWnd,
                                    hardwareTnL,
                                    &d3dpp,
                                    &g_pD3D9dev)) )
    {
        MessageBox(0, TEXT("CreateDevice Failed"), TEXT("ERROR"), MB_OK);
        return E_FAIL;
    }

    return S_OK;
}

LRESULT CALLBACK MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch( msg )
    {
    case WM_DESTROY:
        ::PostQuitMessage(0);
        return 0;
    case WM_PAINT:
        D3DRender();
        ValidateRect(hWnd, NULL);
        return 0;
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

void D3DRender()
{
    //Set BackBuffer
    g_pD3D9dev->Clear(0, NULL, D3DCLEAR_TARGET,D3DCOLOR_XRGB( 0, 255, 0 ), 1.0f, 0 );

    //Render in this section
    if( SUCCEEDED(g_pD3D9dev->BeginScene()) )
    {
        g_pD3D9dev->EndScene();
    }

    //Present BackBuffer
    g_pD3D9dev->Present(NULL, NULL, NULL, NULL);
}

void D3DCleanup()
{
    if( g_pD3D9dev != NULL )
    {
        g_pD3D9dev->Release();
    }
    if( g_pD3D9 != NULL )
    {
        g_pD3D9->Release();
    }
}

转载于:https://www.cnblogs.com/current/p/3984502.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值