天天看點

d3d基礎入門

#include<d3d9.h>
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
#define WINDOW_CLASS "UGPDX"//視窗類名
#define WINDOW_NAME  "Drawing Lines"//視窗名
bool InitializeD3D(HWND hWnd, bool fullscreen);//初始化D3D函數
bool InitializeObjects();
void RenderScene();
void Shutdown();
LPDIRECT3D9 g_D3D = NULL;//建立一個D3DCOM指針
LPDIRECT3DDEVICE9 g_D3DDevice = NULL;//建立一個裝置對象結構體指針
LPDIRECT3DVERTEXBUFFER9 g_VertexBuffer = NULL;//建立D3D頂點緩存指針
struct stD3DVertex
{
    float x, y, z, rhw;
    unsigned long color;
};//一個為我們自定義的頂點類型的結構體
#define D3DFVF_VERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)  //D3DFVF_DIFFUSE讓頂點資訊包含漫反射顔色的資訊,在希望頂點有顔色的時候使用.
                                                      //D3DFVF_XYZRHW 用這個參數定義的頂點的位置,不會參與D3D的所有變換,也就意味着x,y坐标就是螢幕上的點的坐标,z暫時沒有什麼用處
LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)//視窗的回調函數
{
   switch(msg)
      {
         case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
            break;
         case WM_KEYUP:
            if(wp == VK_ESCAPE) PostQuitMessage(0);//如果按下的事ESC鍵的話就一樣投遞一個退出消息
            break;
      }
   return DefWindowProc(hWnd, msg, wp, lp);
}
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE prevhInst,
                   LPSTR cmdLine, int show)
{
   WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc,
                     0, 0, GetModuleHandle(NULL), NULL, NULL,
                     NULL, NULL, WINDOW_CLASS, NULL };//建立一個回調函數為MsgProc,圖示和光标都使用預設window的程式圖示和光标,沒有菜單,沒有背景畫刷
   RegisterClassEx(&wc);
   HWND hWnd = CreateWindow(WINDOW_CLASS, WINDOW_NAME,
                            WS_OVERLAPPEDWINDOW, 100, 100,
                            640, 480, GetDesktopWindow(), NULL,
                            wc.hInstance, NULL);//建立一個視窗左上角頂點為(100,100)視窗大小寬640,高480層疊式視窗,無菜單,父視窗為windows桌面,不向WM_CREATE消息投遞其他消息
   if(InitializeD3D(hWnd, false))
      {
	     ShowWindow(hWnd, SW_SHOWDEFAULT);
         UpdateWindow(hWnd);
         MSG msg;
         ZeroMemory(&msg, sizeof(msg));
         while(msg.message != WM_QUIT)
            {
               if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
                  {
                     TranslateMessage(&msg);
                     DispatchMessage(&msg);
                  }
               else
                  RenderScene();
            }
      }
   Shutdown();
   UnregisterClass(WINDOW_CLASS, wc.hInstance);
   return 0;
}
bool InitializeD3D(HWND hWnd, bool fullscreen)
{
   D3DDISPLAYMODE displayMode;
   g_D3D=Direct3DCreate9(D3D_SDK_VERSION);//建立一個D3DCOM指針
   if(g_D3D == NULL) return false;
   if(FAILED(g_D3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,//取顯示器的資訊,判斷是否失敗
      &displayMode))) return false;
   D3DPRESENT_PARAMETERS d3dpp;//示範參數
   ZeroMemory(&d3dpp, sizeof(d3dpp));
   if(fullscreen)
      {
         d3dpp.Windowed = FALSE;//如果為全屏顯示的話設定windowed為FALSE,而且就必須設定後備的緩存高度和寬度
         d3dpp.BackBufferWidth = 640;
         d3dpp.BackBufferHeight = 480;
      }
   else
      d3dpp.Windowed=TRUE;
   d3dpp.SwapEffect =D3DSWAPEFFECT_DISCARD;
   d3dpp.BackBufferFormat=displayMode.Format;
   if(FAILED(g_D3D->CreateDevice(D3DADAPTER_DEFAULT,//建立和這個視窗相關聯的Direct3D 裝置對象. 在這裡,我們使用預設的擴充卡 (大多數的系統隻有一塊顯示卡, 除非我們有多卡互聯)
	   D3DDEVTYPE_HAL,hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING,//和需要硬體抽象層 (就像我們希望的是硬體裝置而非軟體當我們想知道它在所有的卡上都可以使用的時,我們會使用軟體頂點處理 。對于支援硬體頂點處理的顯示卡,會有性能上的較大提
      &d3dpp, &g_D3DDevice))) return false;
   if(!InitializeObjects()) return false;
   return true;
}
bool InitializeObjects()
{
   unsigned long col=D3DCOLOR_XRGB(255,0,0);
   stD3DVertex objData[] =
      {
         { 320.0f, 150.0f, 0.0f, 0, D3DCOLOR_XRGB(255, 255, 0) },
         { 420.0f, 350.0f, 10.0f, 0, D3DCOLOR_XRGB(255, 0, 0)},
         { 220.0f, 350.0f,10.0f, 0, D3DCOLOR_XRGB(0, 255, 0)}
      };
//這裡用數組初始化了頂點相關的資料,但是程式為了提高讀取資料的效率,使用了頂點緩存,把數組中的資料存入頂點緩存中
   if(FAILED(g_D3DDevice->CreateVertexBuffer(sizeof(objData),0,D3DFVF_VERTEX, D3DPOOL_DEFAULT, &g_VertexBuffer,NULL))) //建立頂點緩存,這裡隻有一個三角形,三個頂點
	   return false;                                                                                                    //使用預設緩存記憶體池
   void *ptr;
   if(FAILED(g_VertexBuffer->Lock(0, sizeof(objData),
      (void**)&ptr, 0))) return false;
   memcpy(ptr, objData, sizeof(objData));
   g_VertexBuffer->Unlock();
   return true;
}
void RenderScene()//這個渲染函數看上去怎麼跟MFC的OnPaint函數怎麼這麼像???在建立視窗的時候,就沒有指明要在視窗在某些情況下需要自繪的樣式,D3D程式
{                  //沒有響應WM_PAINT消息,而是在程式空閑的時候不斷的調用這個渲染函數,應該相當于OnPaint函數不斷的重新整理視窗,再又畫
	g_D3DDevice->Clear(0, NULL, D3DCLEAR_TARGET,
                      D3DCOLOR_XRGB(0,0,0), 1.0f, 0);//使用裝置對象進行清屏,這個裝置對象怎麼和MFC中的CDC*這麼像呢????
   g_D3DDevice->BeginScene();
   g_D3DDevice->SetStreamSource(0, g_VertexBuffer, 0,
                              sizeof(stD3DVertex));
   g_D3DDevice->SetFVF(D3DFVF_VERTEX);
   g_D3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,1);//畫的是一個三角形,如果畫一條線的話:g_D3DDevice->DrawPrimitive(D3DPT_LINELIST, 0, 1);
   g_D3DDevice->EndScene();                            //改一下InitializeObjects()中頂點數組資料
   g_D3DDevice->Present(NULL, NULL, NULL, NULL);
}
void Shutdown()
{
   if(g_D3DDevice != NULL) g_D3DDevice->Release();
   if(g_D3D != NULL) g_D3D->Release();
   if(g_VertexBuffer != NULL) g_VertexBuffer->Release();
   g_D3DDevice = NULL;
   g_D3D = NULL;
   g_VertexBuffer = NULL;
}
           
d3d基礎入門