在螢幕繪製兩個三角形(平面著色模式和Gouraud著色模式)
阿新 • • 發佈:2018-11-22
該例程有三個檔案:d3dUtility.cpp,colorTriangle.cpp,d3dUtility.h
關於d3dUtility.cpp以及d3dUtility.h兩個檔案裡面內容在部落格:Direct3D初始化例程中有詳細的解釋以及拿來就能用的原始碼
但是在初始化以及繪製普通的三角形的例子中我們沒有涉及到顏色,現在我們使用顏色,就需要在.h檔案中定義一些全域性的顏色,供圖元中的頂點使用。
所以我們在.h檔案中的d3d namespace加入以下內容:
const D3DXCOLOR WHITE(D3DCOLOR_XRGB(255, 255, 255)); const D3DXCOLOR BLACK(D3DCOLOR_XRGB(0, 0, 0)); const D3DXCOLOR RED(D3DCOLOR_XRGB(255, 0, 0)); const D3DXCOLOR GREEN(D3DCOLOR_XRGB(0, 255, 0)); const D3DXCOLOR BLUE(D3DCOLOR_XRGB(0, 0, 255)); const D3DXCOLOR YELLOW(D3DCOLOR_XRGB(255, 255, 0)); const D3DXCOLOR CYAN(D3DCOLOR_XRGB(0, 255, 255)); const D3DXCOLOR MAGENTA(D3DCOLOR_XRGB(255, 0, 255));
裡面使用的型別:D3DXCOLOR 以及使用的巨集:D3DXCOLOR_XRGB在部落格:Direct3D基礎——顏色中有詳細的介紹。
d3dUtility.cpp檔案裡面的內容不需要有任何的改變。
然後現在就是我們主要的colorTriangle.cpp檔案了,按照慣例,我們在程式碼中以註釋的方式進行講解:
//包含剛才我們建立的d3dUtility.h標頭檔案 #include "d3dUtility.h" //建立即將用來指向裝置的指標 IDirect3DDevice9* Device = 0; //即將建立的視窗的寬和高 const int Width = 640; const int Height = 480; //世界矩陣 D3DXMATRIX WorldMatrix; //即將指向三角形的頂點快取的指標 IDirect3DVertexBuffer9* Triangle = 0; //頂點的結構:位置座標和顏色資訊 struct ColorVertex { ColorVertex() {} ColorVertex(float x, float y, float z, D3DCOLOR c) { _x = x; _y = y; _z = z; _color = c; } float _x, _y, _z; D3DCOLOR _color; //靈活頂點格式 static const DWORD FVF; }; const DWORD ColorVertex::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE; //資源的分配 bool Setup() { //使用介面將剛才定義的頂點快取的指標進行例項化 Device->CreateVertexBuffer( 3 * sizeof(ColorVertex), D3DUSAGE_WRITEONLY, ColorVertex::FVF, D3DPOOL_MANAGED, &Triangle, 0); //頂點結構體定義的指標 ColorVertex* v; //對頂點進行操作之前要進行上鎖 Triangle->Lock(0, 0, (void**)&v, 0); //將三角形圖元的是三個頂點分別賦值:座標位置和顏色 v[0] = ColorVertex(-1.0f, 0.0f, 2.0f, D3DCOLOR_XRGB(255, 0, 0)); v[1] = ColorVertex(0.0f, 1.0f, 2.0f, D3DCOLOR_XRGB(0, 255, 0)); v[2] = ColorVertex(1.0f, 0.0f, 2.0f, D3DCOLOR_XRGB(0, 0, 255)); //操作完成之後就解鎖 Triangle->Unlock(); //定義投影矩陣 D3DXMATRIX proj; //使用介面獲得投影矩陣 D3DXMatrixPerspectiveFovLH( &proj, D3DX_PI * 0.5f, // 90 - degree (float)Width / (float)Height, 1.0f, 1000.0f); //設定投影矩陣 Device->SetTransform(D3DTS_PROJECTION, &proj); //關閉光照 Device->SetRenderState(D3DRS_LIGHTING, false); return true; } void Cleanup() { d3d::Release<IDirect3DVertexBuffer9*>(Triangle); } //顯示函式:先使用平面著色模式,在使用Gouraud著色模式,分別畫出三角形 bool Display(float timeDelta) { //如果Device存在或者與裝置進行綁定了,則進入迴圈 if (Device) { //清屏 Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0); //畫圖形之前必須使用的介面 Device->BeginScene(); //設定頂點格式 Device->SetFVF(ColorVertex::FVF); //頂點快取和資料流進行連結 Device->SetStreamSource(0, Triangle, 0, sizeof(ColorVertex)); // 執行平移操作,得到一個沿x負軸平移1.25f距離的世界矩陣 D3DXMatrixTranslation(&WorldMatrix, -1.25f, 0.0f, 0.0f); //設定世界矩陣 Device->SetTransform(D3DTS_WORLD, &WorldMatrix); //設定著色模式為:平面模式 Device->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); //將三角形畫出來,但是現在的三角形不在螢幕上,還在我們的後臺快取中,使用Present函式才能將後臺快取中的圖畫提交到前臺快取中 Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1); //繪製完成之後必須要使用的介面 Device->EndScene(); //將後臺快取中已經繪製好的圖畫提交到前臺快取 Device->Present(0, 0, 0, 0); //下面這些繪製和上面是一樣的步驟,只是著色的模式設定的是Gouraud著色模式 Device->BeginScene(); Device->SetFVF(ColorVertex::FVF); Device->SetStreamSource(0, Triangle, 0, sizeof(ColorVertex)); //執行平移操作,得到一個沿x正軸平移1.25f距離的世界矩陣 D3DXMatrixTranslation(&WorldMatrix, 1.25f, 0.0f, 0.0f); Device->SetTransform(D3DTS_WORLD, &WorldMatrix); //設定著色模式是Gouraud著色模式 Device->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); 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; 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, 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函式進行圖形的繪製 d3d::EnterMsgLoop(Display); Cleanup(); Device->Release(); return 0; }