在螢幕繪製一個三角形(使用頂點快取)
阿新 • • 發佈:2018-11-22
首先標頭檔案d3dUtility.h裡面:
Init3D函式:裡面實現了Direct3D初始化的整個過程:包括獲取介面Direct3D9的指標,檢驗裝置的頂點運算,填充裝置屬性結構體的內容,建立IDirect3DDevice9的介面等。
EnterMsgLoop函式:該函式接受了一個顯示函式的函式指標,然後將應用程式的訊息迴圈進行封裝,穿進去的顯示函式就是進行繪製的函式,然後EnterMsgLoop函式需要知道什麼時候去呼叫這個顯示函式進行顯示。
Release模板和Delete模板:資源銷燬的時候呼叫。
標頭檔案可以在這篇部落格中找到,直接複製就能用。
還有就是d3dUtility.cpp檔案,裡面具體實現了剛才我們在d3dUtility.h檔案中宣告的兩個函式。
同樣也可以在這篇部落格中找到,直接複製拷貝就可以用。
然後在原始檔中我們還需要我們的主檔案,也就是繪製Triangle的檔案:triangle.cpp。我們在程式碼中以註釋的方式進行講解,會比較明瞭一點。
//包含我們剛才建立的d3dUtility.h標頭檔案 #include "d3dUtility.h" //定義一個用來指向裝置的指標 IDirect3DDevice9* Device = 0; //設定好我們視窗的寬和高 const int Width = 640; const int Height = 480; //定義一個用來頂點快取的指標,用來指向我們的三角形頂點的資料 IDirect3DVertexBuffer9* Triangle = 0; //定義一個點的結構,有x,y,z的座標,建構函式,還有靈活頂點格式 struct Vertex { Vertex() {} Vertex(float x, float y, float z) { _x = x; _y = y; _z = z; } float _x, _y, _z; //靈活頂點結構 static const DWORD FVF; }; const DWORD Vertex::FVF = D3DFVF_XYZ; bool Setup() { //使用介面:CreateVertexBuffer建立頂點快取 Device->CreateVertexBuffer( 3 * sizeof(Vertex), // 因為我們只去畫一個三角形,所以只有三個頂點,這裡就給他開闢三個頂點的空間 D3DUSAGE_WRITEONLY, // 這個標記代表現在建立的快取是:只能寫的靜態快取 Vertex::FVF, // 靈活頂點格式 D3DPOOL_MANAGED, // 記憶體池的型別 &Triangle, // 指向頂點快取的指標的指標 0); // CreatVertexBuffer的最後一個引數,不使用,設定為0,具體參見連結 //使用頂點結構體定義的頂點指標 Vertex* vertices; //使用之前將要訪問的頂點快取進行上鎖 Triangle->Lock(0, 0, (void**)&vertices, 0); //對頂點快取進行賦值操作 vertices[0] = Vertex(-1.0f, 0.0f, 2.0f); vertices[1] = Vertex(0.0f, 1.0f, 2.0f); vertices[2] = Vertex(1.0f, 0.0f, 2.0f); //對頂點快取使用完成之後進行解鎖 Triangle->Unlock(); /*正常來說,點設定好之後,經過的變換是:區域性座標系->世界座標系->觀察座標系->背面消隱 ->光照->裁剪->投影變換->視口變換->光柵化 但是現在只有一個2D的三角形,視窗中(也可以理解成世界座標和區域性座標是同一個座標)只有這麼一個圖形,所以直接進行投影變換 */ D3DXMATRIX proj; D3DXMatrixPerspectiveFovLH( &proj, // 要得到的投影矩陣 D3DX_PI * 0.5f, // 視域體中的視角 (float)Width / (float)Height, // 縱橫比,為了減少正方形矩陣對映到矩形螢幕而發生的畸變 1.0f, // 攝影機到近平面的距離 1000.0f); // 攝影機到原平面的距離 //使用剛才我們得到的投影矩陣 Device->SetTransform(D3DTS_PROJECTION, &proj); //設定繪製的狀態 Device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); return true; } void Cleanup() { //使用d3d裡面的Release模板,進行資源的釋放 d3d::Release<IDirect3DVertexBuffer9*>(Triangle); } //顯示韓式 bool Display(float timeDelta) { //如果Device存在或者不為空,則進入判斷 if (Device) { //使用此方法進行清除表面 Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0); //繪製必須是在BeginScene和EndScene之間 Device->BeginScene(); //將需要繪製的頂點快取和資料流進行連結 Device->SetStreamSource(0, Triangle, 0, sizeof(Vertex)); //設定靈活頂點格式 Device->SetFVF(Vertex::FVF); // 繪製三角形 Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1); Device->EndScene(); //在裝置擁有的後臺快取區中的顯示下一個快取的內容 Device->Present(0, 0, 0, 0); } return true; } /*這是一個回撥函式,引數和名字是固定的,代表這個視窗在收到對應的訊息的時候,應該做出什麼動作 現在這個函式裡面只是寫了當按下“ESC”的時候視窗結束 */ LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { //收到視窗摧毀的訊息的時候退出視窗 case WM_DESTROY: ::PostQuitMessage(0); break; //當按鍵 = ESC 的時候摧毀視窗,併發送一條WM_DESTROY訊息 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) { //初始化Direct3D if (!d3d::InitD3D(hinstance, Width, Height, true, D3DDEVTYPE_HAL, &Device)) { ::MessageBox(0, "InitD3D() - FAILED", 0, 0); return 0; } //分配資源,現在分配資源過程就是:建立頂點快取,訪問頂點快取,操作頂點快取, if (!Setup()) { ::MessageBox(0, "Setup() - FAILED", 0, 0); return 0; } //迴圈呼叫傳進去的函式 //穿進去的函式:Display,就是呼叫:DrawPrimitive進行繪製的過程 d3d::EnterMsgLoop(Display); Cleanup(); Device->Release(); return 0; }
triangle.cpp裡面提到的連結是這兩篇部落格,裡面對函式的使用以及一些相關的概念都有詳細的解釋: