天天看點

D3D學習筆記(我的第一個D3D程式)

原文出處:點選打開連結

        首先申明這個程式是根據翁雲兵翻譯的<<3D遊戲程式設計入門(DirectX® 9.0)>>修改的;

下面那個程式什麼都沒有完成,就是建立一個視窗.但是麻雀雖小,裡面的所有的D3D基本功能都包含了.

不怕笑話,這個程式我研究了2天。

把這個坎過去了就好辦了,接下來要學的東西就應該輕松點了.起碼了解起來沒什麼問題了.

        利用D3D做程式無非是兩步:

        1)建立裝置

        2)利用建立的裝置來完成要做的任務,然後釋放裝置

        還有下面的程式主要是研究這樣建立裝置的,至于利用這樣利用裝置是下次文章的主題了;

-----------------------------------------------------------------------------------------------------------------------

******test.cpp

#include "d3dUtility.h"

//全局變量,定義裝置

IDirect3DDevice9* Device = 0;

//在這個程式中,我們不需要使用任何資源或觸發任何事件,是以這兩個函數都為空

bool Setup()

{

       return true;

}

void Cleanup()

{

}

          //HRESULT IDirect3DDevice9::Clear(DWORD Count,const D3DRECT* pRects,DWORD Flags,D3DCOLOR Color

                                                                           ,float Z,DWORD Stencil);

         //IDirect3DDevice9::Clear函數的聲名

         //螢幕被填充後,要調用IDirecte3DDevice9::Present方法進行後備表面的交換

bool Display(float timeDelta)

{

       if( Device )

       {

              Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);

              Device->Present(0, 0, 0, 0);// present backbuffer

       }

       return true;

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);     

}

int WINAPI WinMain(HINSTANCE hinstance,HINSTANCE prevInstance,PSTR cmdLine,int showCmd)

{

       //初始化主顯示視窗和Direct3D

       if(!d3d::InitD3D(hinstance, 800, 600, true, D3DDEVTYPE_HAL, &Device)      

       {

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

              return 0;

       }

       //調用Setup進行程式的準備工作

       if(!Setup())

       {

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

              return 0;

       }

       //使用Display函數作為參數進入消息循環

       d3d::EnterMsgLoop( Display );

       //清除應用程式最後釋放IDirecte3DDevice9對象

       Cleanup();

       Device->Release();

       return 0;

}

--------------------------------------------------------------------------------------------------------------------------------

***********d3dUtility.h

#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__

#include "d3dUtility.h"

//InitD3D主要功能是注冊和建立主視窗,檢查裝置的相容性,決定是用硬體支援方式還是軟體支援方式

//

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(BLACK_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 ,

              0 ,

              hInstance,

              0 );

       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.

       //1.獲得一個IDirect3D9接口指針。

       //這個接口用于獲得實體裝置的資訊和建立一個IDirect3DDevice9接口,

       //它是一個代表我們顯示3D圖形的實體裝置的C++對象。

       IDirect3D9* d3d9 = 0;

       d3d9 = Direct3DCreate9(D3D_SDK_VERSION);

       if( !d3d9 )

       {

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

              return false;

       }

       // Step 2: Check for hardware vp.

       //檢查硬體是否支援,要是不支援那麼使用軟體方式,并且得到硬體資訊

       //deviceType 來記錄DeviceType的類型

       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結構

       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;

}