zoukankan      html  css  js  c++  java
  • 初始化Direct3D

    1.Direct3D概述

    Direct3D是一套底层图形API,借助该API,我们能够利用硬件加速功能来绘制3D场景。

     

    设备制造商将其产品支持的全部功能都实现到HAL中。

    1.1 Direct3D提供了参考光栅设备(REF设备),它以软件运算方式完全支持Direct3D API。REF速度缓慢,在测试以外的其他环节都不适用。

    1.2 D3DDEVTYPE枚举类型
       在程序中HAL设备用值D3DDEVTYPE_HAL来表示,REF设备用值D3DDEVTYPE_REF来表示。
    2.COM:创建COM接口时不可以使用new关键字,使用完用Realease方法释放。COM接口都有一个前缀I。
    3.预备知识

    3.1.表面是Direct3D主要用于存储2D图像数据的一个像素矩阵,实际上像素数据存储在一个线性数组中。

    在代码中我们用接口IDirect3DSurface9来描述表面,接口IDirect3DSurface9最重要的方法如下:LockRect()[该方法获取指向表面存储区的指针],UnlockRect(),GetDesc()[该方法通过填充结构D3DSURFACE_DESC来获取表面的描述信息]。

    3.2多重采样是一种用于平滑块状图像的技术。

      D3DMULTISAMPLE_TYPE枚举类型包含一系列枚举常量,用于对表面进行多重采样的级别。

      使用IDirect3D9:: CheckDeviceMultiSampleType()方法检查自己的图像设备是否支持所希望的多重采样类型。

    3.3像素格式 创建表面或纹理时,可以用D3DFORMAT枚举类型的枚举常量来定义。较常用的有:

    D3DFMT_R8G8B8,每个像素有24位组成,8位分给红色,8位给绿色,8位给蓝色。

    D3DFMT_X8R8G8B8,每个像素有32位组成,8位未用,8位红色,8位给绿色,8位给蓝色。

    D3DFMT_A8R8G8B8,每个像素有32位组成,8位Alpha值,8位红色,8位绿色,8位给蓝色。
    3.4内存池:表面和其他的Direct3D资源可以放在内存池中,内存池的类型可以用D3DPOOL枚举类型来定义。
    D3DPOOL_DEFAULT,D3DPOOL_MANAGED,D3DPOOL_SYSTEMMEM,D3DPOOL_SCRATCH ,D3DPOOL_FORCE_DWORD
    3.5交换链和页面置换
    交换链:该表面集合用接口IDirect3DSwapChain9来表示。目的是让页面显示的更加流畅。
    3.6深度缓存(Z-buffering)是一个只包含页面的深度信息,不包含图像数据的表面。深度缓存为每一个像素都保存了深度项。D3DFORMAT枚举其值。常用的如下:
    D3DFMT_D32  指定32位的深度缓存。
    D3DFMT_D24S8 32位Z-buffering,24位深度缓存,8位供模板缓存使用。
    D3DFMT_D24X8 32位Z-buffering,24位深度缓存,8位未用。
    D3DFMT_D24X4S4 32位Z-buffering,24位深度缓存,4位未用,4位供模板缓存使用。
    3.7顶点运算 顶点是3D几何学的基本元素,在Direct3D中我们可以使用软件顶点运算或者硬件顶点运算。始终优先考虑硬件顶点运算。
    3.8设备性能 Direct3D所提供的每一项性能都对应于结构D3DCAPS9中的一个数据成员或某一位。以某一硬件为基础,初始化一个D3DCAPS9类型的实例,然后和其实例相应的数据位进行比对。  D3DCAPS9::DevCaps表示设备性能。

    4.Direct3D的初始化分为以下步骤:

     

    4.1获取IDirect3D9的指针。

    IDirect3D9* d3d9 = 0;  

    if( NULL == (d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))

      {  return E_FAIL;}

    4.2校验硬件顶点运算。

    D3DCAPS9 caps;

    d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps);//初始化主显卡的性能参数。

    int vp = 0;

    if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )//对设备性能进行检查

         vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;

    else

    vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

    4.3填充D3DPRESENT_PARAMETERS结构

    D3DPRESENT_PARAMETERS d3dpp;

    d3dpp.BackBufferWidth            = width;

    d3dpp.BackBufferHeight           = height;

    d3dpp.BackBufferFormat           = D3DFMT_A8R8G8B8;

    d3dpp.BackBufferCount            = 1;

    d3dpp.MultiSampleType            = D3DMULTISAMPLE_NONE;

    d3dpp.MultiSampleQuality         = 0;

    d3dpp.SwapEffect                 = D3DSWAPEFFECT_DISCARD;

    d3dpp.hDeviceWindow              = hwnd;

    d3dpp.Windowed                   = windowed;

    d3dpp.EnableAutoDepthStencil     = true;

    d3dpp.AutoDepthStencilFormat     = D3DFMT_D24S8;

    d3dpp.Flags                      = 0;

    d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;

    d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;

    4.4创建IDirect3DDevice9接口,用CreateDevice()函数。

    hr = d3d9->CreateDevice(

         D3DADAPTER_DEFAULT, // primary adapter

         deviceType,         // device type

         hwnd,               // window associated with device

         vp,                 // vertex processing

        &d3dpp,             // present parameters

        device);            // return created device

    if( FAILED(hr) )

    {       

        d3d9->Release(); // done with d3d9 object

              ::MessageBox(0, "CreateDevice() - FAILED", 0, 0);

              return false;

    }

    创建每个程序都需要完成一些共性任务,如创建窗口,初始化Direct3D,进入消息循环等。这些我们将其封装在了d3dUtility.h和d3dUtility.cpp文件中。如下为具体代码,项目需加入库文件d3dx9.lib;d3d9.lib;winmm.lib;

    #ifndef __d3dUtilityH__
    #define __d3dUtilityH__
    
    #include <d3dx9.h>
    #include <string>
    
    namespace d3d
    {
        bool InitD3D(
            HINSTANCE hInstance,       // [in] Application instance.
            int width, int height,     // [in] Backbuffer dimensions.
            bool windowed,             // [in] Windowed (true)or full screen (false).
            D3DDEVTYPE deviceType,     // [in] HAL or REF
            IDirect3DDevice9** device);// [out]The created device.
    
        int EnterMsgLoop( 
            bool (*ptr_display)(float timeDelta));
    
        LRESULT CALLBACK WndProc(
            HWND hwnd,
            UINT msg, 
            WPARAM wParam,
            LPARAM lParam);
    
        template<class T> void Release(T t)
        {
            if( t )
            {
                t->Release();
                t = 0;
            }
        }
            
        template<class T> void Delete(T t)
        {
            if( t )
            {
                delete t;
                t = 0;
            }
        }
    }
    
    #endif // __d3dUtilityH__
    d3dUnility.h
    #include "d3dUtility.h"
    
    bool d3d::InitD3D(
        HINSTANCE hInstance,
        int width, int height,
        bool windowed,
        D3DDEVTYPE deviceType,
        IDirect3DDevice9** device)
    {
        //
        // Create the main application window.
        //
    
        WNDCLASS wc;
    
        wc.style         = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc   = (WNDPROC)d3d::WndProc; 
        wc.cbClsExtra    = 0;
        wc.cbWndExtra    = 0;
        wc.hInstance     = hInstance;
        wc.hIcon         = LoadIcon(0, IDI_APPLICATION);
        wc.hCursor       = LoadCursor(0, IDC_ARROW);
        wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wc.lpszMenuName  = 0;
        wc.lpszClassName = "Direct3D9App";
    
        if( !RegisterClass(&wc) ) 
        {
            ::MessageBox(0, "RegisterClass() - FAILED", 0, 0);
            return false;
        }
            
        HWND hwnd = 0;
        hwnd = ::CreateWindow("Direct3D9App", "Direct3D9App", 
            WS_EX_TOPMOST,
            0, 0, width, height,
            0 /*parent hwnd*/, 0 /* menu */, hInstance, 0 /*extra*/); 
    
        if( !hwnd )
        {
            ::MessageBox(0, "CreateWindow() - FAILED", 0, 0);
            return false;
        }
    
        ::ShowWindow(hwnd, SW_SHOW);
        ::UpdateWindow(hwnd);
    
        //
        // Init D3D: 
        //
    
        HRESULT hr = 0;
    
        // Step 1: Create the IDirect3D9 object.
    
        IDirect3D9* d3d9 = 0;
        d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
    
        if( !d3d9 )
        {
            ::MessageBox(0, "Direct3DCreate9() - FAILED", 0, 0);
            return false;
        }
    
        // Step 2: Check for hardware vp.
    
        D3DCAPS9 caps;
        d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps);
    
        int vp = 0;
        if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
            vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
        else
            vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
    
        // Step 3: Fill out the D3DPRESENT_PARAMETERS structure.
     
        D3DPRESENT_PARAMETERS d3dpp;
        d3dpp.BackBufferWidth            = width;
        d3dpp.BackBufferHeight           = height;
        d3dpp.BackBufferFormat           = D3DFMT_A8R8G8B8;
        d3dpp.BackBufferCount            = 1;
        d3dpp.MultiSampleType            = D3DMULTISAMPLE_NONE;
        d3dpp.MultiSampleQuality         = 0;
        d3dpp.SwapEffect                 = D3DSWAPEFFECT_DISCARD; 
        d3dpp.hDeviceWindow              = hwnd;
        d3dpp.Windowed                   = windowed;
        d3dpp.EnableAutoDepthStencil     = true; 
        d3dpp.AutoDepthStencilFormat     = D3DFMT_D24S8;
        d3dpp.Flags                      = 0;
        d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
        d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;
    
        // Step 4: Create the device.
    
        hr = d3d9->CreateDevice(
            D3DADAPTER_DEFAULT, // primary adapter
            deviceType,         // device type
            hwnd,               // window associated with device
            vp,                 // vertex processing
            &d3dpp,             // present parameters
            device);            // return created device
    
        if( FAILED(hr) )
        {
            // try again using a 16-bit depth buffer
            d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
            
            hr = d3d9->CreateDevice(
                D3DADAPTER_DEFAULT,
                deviceType,
                hwnd,
                vp,
                &d3dpp,
                device);
    
            if( FAILED(hr) )
            {
                d3d9->Release(); // done with d3d9 object
                ::MessageBox(0, "CreateDevice() - FAILED", 0, 0);
                return false;
            }
        }
    
        d3d9->Release(); // done with d3d9 object
        
        return true;
    }
    
    int d3d::EnterMsgLoop( bool (*ptr_display)(float timeDelta) )
    {
        MSG msg;
        ::ZeroMemory(&msg, sizeof(MSG));
    
        static float lastTime = (float)timeGetTime(); 
    
        while(msg.message != WM_QUIT)
        {
            if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
            {
                ::TranslateMessage(&msg);
                ::DispatchMessage(&msg);
            }
            else
            {    
                float currTime  = (float)timeGetTime();
                float timeDelta = (currTime - lastTime)*0.001f;
    
                ptr_display(timeDelta);
    
                lastTime = currTime;
            }
        }
        return msg.wParam;
    }
    d3dUnility.cpp
    #include "d3dUtility.h"
    
    
    IDirect3DDevice9* Device = 0; 
    
    //
    // Framework Functions
    //
    
    bool Setup()
    {
        // Nothing to setup in this sample.
    
        return true;
    }
    
    void Cleanup()
    {
        // Nothing to cleanup in this sample.
    }
    
    bool Display(float timeDelta)
    {
        if( Device ) // Only use Device methods if we have a valid device.
        {
            Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
            Device->Present(0, 0, 0, 0);
        }
        return true;
    }
    
    //
    // WndProc
    //
    LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch( msg )
        {
        case WM_DESTROY:
            ::PostQuitMessage(0);
            break;
            
        case WM_KEYDOWN:
            if( wParam == VK_ESCAPE )
                ::DestroyWindow(hwnd);
            break;
        }
        return ::DefWindowProc(hwnd, msg, wParam, lParam);
    }
    
    //
    // WinMain
    //
    int WINAPI WinMain(HINSTANCE hinstance,
                       HINSTANCE prevInstance, 
                       PSTR cmdLine,
                       int showCmd)
    {
        if(!d3d::InitD3D(hinstance,
            640, 480, true, D3DDEVTYPE_HAL, &Device))
        {
            ::MessageBox(0, "InitD3D() - FAILED", 0, 0);
            return 0;
        }
            
        if(!Setup())
        {
            ::MessageBox(0, "Setup() - FAILED", 0, 0);
            return 0;
        }
    
        d3d::EnterMsgLoop( Display );
    
        Cleanup();
    
        Device->Release();
    
        return 0;
    }
    main.cpp
  • 相关阅读:
    【转】JS模块化工具requirejs教程(二):基本知识
    【转】JS模块化工具requirejs教程(一):初识requirejs
    【转】批处理命令 For循环命令详解!
    【转】NodeJS教程--基于ExpressJS框架的文件上传
    【转】WebSocket 是什么原理?为什么可以实现持久连接?
    网页工具地址
    【转】DataURL在Web浏览器中的兼容性总结
    侯捷STL学习(一)--顺序容器测试
    strstr-strcat实现
    算法设计与分析
  • 原文地址:https://www.cnblogs.com/hometown/p/3650246.html
Copyright © 2011-2022 走看看