Direct3D 初始化

Direct3D是一套底层图形API,借助API,我们能够利用硬件加速功能绘制3D场景,Direct3D 可以被视为应用程序与图形设备交互式的中介,它们之前的关系可以描述如下

应用程序--->Direct3D--->HAL--->图形设备

在Direct3D和图形设备之间有一个中间环节,HAL(Hardware Abstraction Layer)由于市面上的图形卡品种繁多,每种卡性能和实现方式功能和机理都有差异,所以Direct3D无法与图形设备直接交互,所以Direct3D就需要设备制造商实现一个HAL,HAL是一个指示设备完成一些操作的代码集.
设备制造商将其产品所支持的全部功能都实现都到HAL中,那些,Direct3D支持,但是设备不支持的功能无法在HAL中实现,调用一个没有在HAL中实现的Direct3D函数将会导致调用失败,除非它是一个项点运算,并且用户已经指定了使用软件运算方式,在这种情况下,用户所期望的实现的功能便可Direct3D运算以软件方式来模拟.

1.REF设备
有时,D3D 提供的某些功能键不为您的图形设备支持,但您希望使用这些功能,为了满足这种需求,D3D提供了参考光栅设备(Reference rasterizer device) 也就是REF 设备,它能以软件运算方式完全支持D3D API,借助REF,您可以在代码中使用那些当前硬件不支持的特性,并对特性进行测试,注意REF设备仅用于开发阶段,它与DX SDK 捆绑在一起,无法发布给最终用户,此外REF速度十分缓慢,在测试以外的场合都不实用

2.D3DDEVTYPE
在程序代码中,HAL值用D3DDEVTYPE_HAL来指定,该值是D3DDEVTYPE枚举类型之一,REF值用D3DDEVTYPE_HAL来指定,全部类型值可以看SDK开发文档



二.Direct3D 的初始化

1.获取接口IDirect3D 的指针,该接口用于获取系统中物理设备的信息并创建接口IDirect3DDevice9,
2.检查设备性能,判断主显卡是否支持硬件顶点运算功能,
3.初始化D3DPRESENT_PARAMETERS结构,
4.创建IDirect3dDevice9对像


2.1获取接口IDirect3D9的指针

IDirect3D9 * g_d3d = Direct3DCreate9(D3D_SDK_VERSION)

2.2校验硬件顶点运算

IDirect3D9::GetDeviceCaps Method
函数原型如下
HRESULT GetDeviceCaps(         
    UINT Adapter,        //指定的物理显示序号
    D3DDEVTYPE DeviceType,      //指定设备类型
    D3DCAPS9 *pCaps             //返回已初始化的设备性能结构实例
);

D3DCAPS9 caps;
d3d9->GetDeviceCaps(
    D3DADAPTER_DEFAULT,
    D3DDEVTYPE_HAL,
    &caps
)
int vp = 0;
if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
{
    vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
}
else
{
    vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING
}


2.3填充D3DPRESENT_PARAMETER结构
该结构的定义如下
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;

BackBufferWidth, BackBufferHeight;// 后台缓存中表面的宽度,高度,单位为像素
BackBufferFormat;//后台缓存的像素格式
UINT BackBufferCount;//后台缓存的个数,通常指定为1
MultiSampleType;//多重采样类型(当SwapEffect=D3DSWAPEFFECT_DISCARD ,该值必须为 D3DMULTISAMPLE_NONE )
hDeviceWindow;//与设备相关的窗口
BOOL Windowed;//值为true时,表示为窗口模式,为false时为全屏模式

填充该结构的一个示例如下
D3DPRESENT_PARAMETER d3dpp;
d3dpp.BackBufferWidth = 800;
d3dpp.BackBufferHeight = 600;
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dpp.MultiSampleQuality = 0;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hwnd;
d3dpp.Windowed = true;
d3dpp.EnableAutoDepthStencil = true;
d3dpp.Flags = 0;
d3dpp.FullScreen_RefreshRateInHZ = D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval = D3DPRENT_INTERVAL_IMMEDIATE


2.4创建IDirect3DDevice9接口
该函数原型如下
HRESULT CreateDevice(        
    UINT Adapter,
    D3DDEVTYPE DeviceType,
    HWND hFocusWindow,
    DWORD BehaviorFlags,
    D3DPRESENT_PARAMETERS *pPresentationParameters,
    IDirect3DDevice9** ppReturnedDeviceInterface
);

其中DWORD BehaviorFlags值可以为
D3DCREATE_HARDWARE_VERTEXPROCESSING
D3DCREATE_SOFTWARE_VERTEXPROCESSING
示例如下
IDirect3DDevice9 *g_device;
g_d3d->CreateDevice(
    D3DADAPTER_DEFAULT,
    D3DDEVTYPE_HAL,
    hwnd,
    D3DCRATE_HARDWARE_VERTEXPROCESSING,
    &d3dpp,
    &g_device
)

全部例子如下
#include <windows.h>
#include <d3d9.h>

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


LPDIRECT3D9        g_d3d;
LPDIRECT3DDEVICE9  g_device;

bool InitD3d(HWND hwnd,UINT width,UINT height)
{
    g_d3d = Direct3DCreate9(D3D_SDK_VERSION);
    if(g_d3d==NULL)
    {
        return false;    
    }
    D3DDISPLAYMODE displaymode;
    if(FAILED(g_d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&displaymode)))
    {
        return false;
    }
    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory(&d3dpp,sizeof(d3dpp));

    d3dpp.Windowed = true;
    d3dpp.BackBufferWidth = width;
    d3dpp.BackBufferHeight = height;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = displaymode.Format;

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

    return true;
}

void RenderScene()
{
    g_device->Clear(0,0,D3DCLEAR_TARGET,0xff000000,1.0f,0);

    g_device->BeginScene();

    //
    g_device->EndScene();

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

void Shutdown()
{
    if(g_d3d)
    {
        g_d3d->Release();
    }
    if(g_device)
    {
        g_device->Release();
    }
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT ("DX SDK 9.0");
    HWND         hwnd;
    MSG          msg;
    WNDCLASSEX   wndclassex = {0};
    wndclassex.cbSize        = sizeof(WNDCLASSEX);
    wndclassex.style         = CS_HREDRAW | CS_VREDRAW;
    wndclassex.lpfnWndProc   = WndProc;
    wndclassex.cbClsExtra    = 0;
    wndclassex.cbWndExtra    = 0;
    wndclassex.hInstance     = hInstance;
    wndclassex.hIcon         = LoadIcon (NULL, IDI_APPLICATION);
    wndclassex.hCursor       = LoadCursor (NULL, IDC_ARROW);
    wndclassex.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
    wndclassex.lpszMenuName  = NULL;
    wndclassex.lpszClassName = szAppName;
    wndclassex.hIconSm       = wndclassex.hIcon;
    
    if (!RegisterClassEx (&wndclassex))
    {
        MessageBox (NULL, TEXT ("RegisterClassEx failed!"), szAppName, MB_ICONERROR);
        return 0;
    }
    hwnd = CreateWindowEx (WS_EX_OVERLAPPEDWINDOW,
                          szAppName,
                          TEXT ("WindowTitle"),
                          WS_OVERLAPPEDWINDOW,
                          100,
                          100,
                          800,
                          600,
                          NULL,
                          NULL,
                          hInstance,
                          NULL);

    if(!InitD3d(hwnd,800,600))
        return -1;
                          
    ShowWindow (hwnd, iCmdShow);
    UpdateWindow (hwnd);
    ZeroMemory(&msg,sizeof(msg));

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

    Shutdown();
    return msg.wParam;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_DESTROY:
        PostQuitMessage (0);
        return (0);
    }
    return DefWindowProc (hwnd, message, wParam, lParam);
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值