DirectX学习---顶点缓存

今天在学习DirectX时发现了几个问题:

1、灵活顶点格式(FVF)的取值到底对图像的呈现有什么影响?

2、顶点的数据格式是否可以自己设置?

3、D3DXMatrixPerspectiveFovRH 和 D3DXMatrixPerspectiveFovLH有什么区别?

先贴出我的测试代码:

  1 /*
  2 运行所需的库文件:d3dx9d.lib,d3d9.lib,d3dx11.lib,dxerr.lib,dxguid.lib,winmm.lib,comctl32.lib
  3 */
  4 
  5 #include <windows.h>
  6 #include <windowsx.h>
  7 #include <d3d9.h>
  8 #include <D3DX10Math.h>
  9 
 10 #define WINDOW_WIDTH 600
 11 #define WINDOW_HEIGHT 800
 12 #define WINDOW_CLASS_NAME TEXT("C_class")
 13 #define SAFE_RELEASE(p) {if(p){(p)->Release();(p) = NULL;}}
 14 
 15 #pragma comment(lib,"winmm.lib")
 16 #pragma comment(lib,"d3d9.lib")
 17 #pragma comment(lib,"d3dx9d.lib")
 18 
 19 //结构定义
 20 struct MVertex {
 21     MVertex() {};
 22     MVertex(float x, float y, float z) {
 23         m_x = x; m_y = y; m_z = z;
 24     }
 25     float m_x, m_y, m_z;
 26     static const DWORD FVF;
 27 };
 28 const DWORD MVertex::FVF = D3DFVF_XYZ;
 29 
 30 //全局声明
 31 float time = 2.0f;
 32 HWND g_hdc = NULL;
 33 HINSTANCE g_hinstance = NULL;
 34 IDirect3DDevice9* g_device = NULL;
 35 IDirect3DVertexBuffer9* Vbuffer = NULL;
 36 typedef LRESULT(CALLBACK* WNDPROCRET)(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
 37 
 38 //全局函数
 39 LRESULT CALLBACK  WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
 40 WNDCLASSEX&       gCreateWindowsClass(HINSTANCE hInstance, LPCTSTR name, WNDPROCRET lpfnproc,UINT style = CS_HREDRAW | CS_VREDRAW);
 41 VOID              gMessageLoop();
 42 HRESULT           gGame_Init(HWND hwnd);
 43 VOID              gRender(HWND hwnd);
 44 VOID              Clean_Up(HWND hwnd);
 45 VOID              gCreateInterface_D3D(LPDIRECT3D9& pd3d);
 46 VOID              gGetHalinfo(LPDIRECT3D9 pd3d,int& vp);
 47 VOID              gFullParameter(HWND hwnd,D3DPRESENT_PARAMETERS& d3dpp);
 48 VOID              gCreateVertexBuffer(IDirect3DDevice9* pdevice);
 49 VOID              gCreatecamera(IDirect3DDevice9* pdevice, D3DXVECTOR3& pos, D3DXVECTOR3& target, D3DXVECTOR3& up);
 50 VOID              gTranslation(IDirect3DDevice9* pdevice);
 51 VOID              gMydraw(float time, IDirect3DDevice9* pdevice);
 52 
 53 
 54 int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
 55 {
 56     g_hinstance = hInstance;
 57 
 58     WNDCLASSEX WClass = gCreateWindowsClass(hInstance, WINDOW_CLASS_NAME, WindowProc);
 59 
 60     if (!RegisterClassEx(&WClass))
 61     {
 62         MessageBox(0, TEXT("error"), TEXT("注册失败!"), MB_OK);
 63         return 0;
 64     }
 65 
 66     g_hdc = CreateWindow(WINDOW_CLASS_NAME, TEXT("CYX"), WS_OVERLAPPEDWINDOW | WS_EX_TOPMOST,0,0,WINDOW_WIDTH,WINDOW_HEIGHT,0,0,hInstance,0);
 67     if (!g_hdc)
 68     {
 69         MessageBox(0, TEXT("error"), TEXT("窗口创建失败!"), MB_OK);
 70         return 0;
 71     }
 72 
 73     ShowWindow(g_hdc, nShowCmd);
 74     UpdateWindow(g_hdc);
 75 
 76     if (FAILED(gGame_Init(g_hdc))) {
 77         MessageBox(0, TEXT("error"), TEXT("游戏初始化失败!"), MB_OK);
 78         return 0;
 79     }
 80     
 81     gMessageLoop();
 82 
 83     UnregisterClass(WINDOW_CLASS_NAME, hInstance);
 84     return 0;
 85 }
 86 
 87 //函数定义
 88 LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
 89     switch (uMsg) {
 90     case WM_PAINT:
 91         BeginPaint(hwnd, NULL);
 92         gRender(hwnd);
 93         //ValidateRect(hwnd, NULL);//这个函数还不是很清楚
 94         EndPaint(hwnd, NULL);
 95         break;
 96     case WM_DESTROY:
 97         Clean_Up(hwnd);
 98         PostQuitMessage(0);
 99         break;
100     case WM_KEYDOWN:
101         switch (wParam) {
102         case VK_ESCAPE:
103             DestroyWindow(hwnd);
104             break;
105         case VK_UP:
106             time += 5.0f;
107             break;
108         case VK_DOWN:
109             time -= 5.0f;
110             break;
111         default:break;
112         }
113     default:
114         break;
115     }
116     return DefWindowProc(hwnd, uMsg, wParam, lParam);
117 }
118 
119 WNDCLASSEX& gCreateWindowsClass(HINSTANCE hInstance,LPCTSTR name, WNDPROCRET lpfnproc, UINT style /* = CS_HREDRAW | CS_VREDRAW */) {
120 
121     static WNDCLASSEX Mywindowclass;
122     Mywindowclass.cbSize = sizeof(Mywindowclass);
123     Mywindowclass.cbClsExtra = 0;
124     Mywindowclass.cbWndExtra = 0;
125     Mywindowclass.lpfnWndProc = lpfnproc;
126     Mywindowclass.hInstance = hInstance;
127     Mywindowclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
128     Mywindowclass.hCursor = LoadCursor(0, IDC_ARROW);
129     Mywindowclass.hIconSm = NULL;
130     Mywindowclass.hIcon = NULL;
131     Mywindowclass.lpszClassName = WINDOW_CLASS_NAME;
132     Mywindowclass.lpszMenuName = NULL;
133     Mywindowclass.style = style;
134 
135     return Mywindowclass;
136 }
137 
138 VOID gMessageLoop() {
139     MSG mmsg = { 0 };
140     while (mmsg.message != WM_QUIT)
141     {
142         if (PeekMessage(&mmsg, 0, 0, 0, PM_REMOVE))
143         {
144             TranslateMessage(&mmsg);
145             DispatchMessage(&mmsg);
146         }
147         else
148         {
149             gRender(g_hdc);
150         }
151     }
152 }
153 
154 HRESULT gGame_Init(HWND hwnd) {
155     LPDIRECT3D9 pd3d = NULL;
156     gCreateInterface_D3D(pd3d);
157 
158     int vp = 0;
159     gGetHalinfo(pd3d,vp);
160 
161     D3DPRESENT_PARAMETERS d3dpp;
162     gFullParameter(hwnd, d3dpp);
163 
164     if (FAILED(pd3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, vp, &d3dpp, &g_device)))
165     {
166         MessageBox(0, TEXT("error"), TEXT("设备创建失败!"), MB_OK);
167         return E_FAIL;
168     }
169 
170     SAFE_RELEASE(pd3d);
171 
172     //创建定点缓存
173     gCreateVertexBuffer(g_device);
174 
175     //设置摄像机
176     D3DXVECTOR3 pos(.0f, 5.0f, 10.0f);
177     D3DXVECTOR3 tar(0.0f, 0.0f, 0.0f);
178     D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
179     gCreatecamera(g_device,pos,tar,up);
180 
181     //变换
182     gTranslation(g_device);
183 
184     return S_OK;
185 }
186 
187 VOID gRender(HWND hwnd) {
188     gMydraw(time, g_device);
189 }
190 
191 VOID Clean_Up(HWND hwnd) {
192     SAFE_RELEASE(g_device);
193     SAFE_RELEASE(Vbuffer);
194 }
195 
196 VOID gCreateInterface_D3D(LPDIRECT3D9& pd3d) {
197     if (!(pd3d = Direct3DCreate9(D3D_SDK_VERSION)))
198     {
199         MessageBox(0, TEXT("error"), TEXT("接口创建失败!"), MB_OK);
200         return;
201     }
202 }
203 
204 VOID gGetHalinfo(LPDIRECT3D9 pd3d,int& vp) {
205     D3DCAPS9 caps;
206     if (FAILED(pd3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps)))
207     {
208         MessageBox(0, TEXT("error"), TEXT("获取设备信息失败!"), MB_OK);
209         return;
210     }
211     if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
212     {
213         vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
214     }
215     else
216         vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
217 }
218 
219 VOID gFullParameter(HWND hwnd,D3DPRESENT_PARAMETERS& d3dpp) {
220     ZeroMemory(&d3dpp, sizeof(d3dpp));
221     d3dpp.BackBufferWidth = WINDOW_WIDTH;
222     d3dpp.BackBufferHeight = WINDOW_HEIGHT;
223     d3dpp.BackBufferCount = 1;
224     d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
225     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
226     d3dpp.EnableAutoDepthStencil = TRUE;
227     d3dpp.Flags = 0;
228     d3dpp.hDeviceWindow = hwnd;
229     d3dpp.FullScreen_RefreshRateInHz = 0;
230     d3dpp.MultiSampleQuality = 0;
231     d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
232     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
233     d3dpp.Windowed = TRUE;
234     d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;//该参数是干什么的??
235 }
236 
237 VOID gCreateVertexBuffer(IDirect3DDevice9* pdevice) {
238     if (FAILED(pdevice->CreateVertexBuffer(
239         24 * sizeof(MVertex),
240         0,
241         MVertex::FVF,
242         D3DPOOL_MANAGED,
243         &Vbuffer,
244         0
245     )))
246     {
247         MessageBox(0, TEXT("定点缓存创建失败!"), TEXT("error"), MB_OK);
248         return;
249     }
250 
251     //填充定点缓存
252     MVertex* v = NULL;
253     Vbuffer->Lock(0, 0, (VOID**)&v, 0);
254 
255     v[0] = MVertex(0.0f, 1.4f, 0.0f);     v[6] = MVertex(0.0f,1.4f, 0.0f);
256     v[1] = MVertex(-1.0f, 0.0f, -1.0f);   v[7] = MVertex(1.0f, 0.0f, 1.0f);
257     v[2] = MVertex(-1.0f, 0.0f, 1.0f);    v[8] = MVertex(1.0f, 0.0f, -1.0f);
258 
259     v[3] = MVertex(0.0f, 1.4f, 0.0f);     v[9] = MVertex(0.0f, 1.4f, 0.0f);
260     v[4] = MVertex(-1.0f, 0.0f, 1.0f);    v[10] = MVertex(1.0f, 0.0f, -1.0f);
261     v[5] = MVertex(1.0f, 0.0f, 1.0f);     v[11] = MVertex(-1.0f, 0.0f, -1.0f);
262 
263     v[12] = MVertex(0.0f, -1.4f, 0.0f);   v[13] = MVertex(-1.0f, 0.0f, -1.0f);
264     v[14] = MVertex(1.0f, 0.0f, -1.0f);   v[15] = MVertex(0.0f, -1.4f, 0.0f);
265     v[16] = MVertex(1.0f, 0.0f, -1.0f);   v[17] = MVertex(1.0f, 0.0f, 1.0f);
266 
267     v[18] = MVertex(0.0f, -1.4f, 0.0f);   v[19] = MVertex(1.0f, 0.0f, 1.0f);
268     v[20] = MVertex(-1.0f, 0.0f, 1.0f);   v[21] = MVertex(0.0f, -1.4f, 0.0f);
269     v[22] = MVertex(-1.0f, 0.0f, 1.0f);   v[23] = MVertex(-1.0f, 0.0f, -1.0f);
270 
271     Vbuffer->Unlock();
272 }
273 
274 VOID gCreatecamera(IDirect3DDevice9* pdevice, D3DXVECTOR3& pos, D3DXVECTOR3& target, D3DXVECTOR3& up) {
275     D3DXMATRIX V;
276     D3DXMatrixLookAtLH(&V, &pos, &target, &up);
277     pdevice->SetTransform(D3DTS_VIEW, &V);
278 }
279 
280 VOID gTranslation(IDirect3DDevice9* pdevice) {
281     //投影变换
282     D3DXMATRIX proj;
283     //居然还有D3DMatrixPerspectiveFovRH()
284     D3DXMatrixPerspectiveFovLH(
285         &proj,
286         D3DX_PI*0.5f,
287         (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT,
288         1.0f,
289         1000.0f
290     );
291     pdevice->SetTransform(D3DTS_PROJECTION, &proj);
292 
293     //设置线型
294     pdevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
295     //打开光照
296     //pdevice->SetRenderState(D3DRS_LIGHTING, FALSE);
297 }
298 
299 VOID gMydraw(float time, IDirect3DDevice9* pdevice) {
300     if (pdevice)
301     {
302         D3DXMATRIX Rx;
303         static float y = 0.0f;
304         D3DXMatrixRotationX(&Rx, y);
305         y += time*0.002;
306         if (y > 6.28f)
307             y = 0.0f;
308         pdevice->SetTransform(D3DTS_WORLD, &Rx);
309 
310         pdevice->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(230, 230, 230), 1.0f, 0);
311         pdevice->BeginScene();
312         pdevice->SetStreamSource(0, Vbuffer, 0,sizeof(MVertex));
313         pdevice->SetFVF(MVertex::FVF);
314         pdevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 8);
315         pdevice->EndScene();
316         pdevice->Present(0, 0, 0, 0);
317     }
318 }
View Code

现在我们来解决问题吧、

一、灵活顶点格式(FVF)的取值到底对图像的呈现有什么影响?

首先,常用的灵活顶点格式的取值及含义如下:

D3DFVF_XYZ——顶点的三维坐标(分别代表X,Y,Z坐标),表示有位置,而且需要进行矩阵变换(世界,投影,视口,取景)和设置摄像机位置才能在屏幕上显示;
D3DFVF_XYZRHW——即平时所说rhw,它说明顶点有位置,而且经过了矩阵变换,不用再由Direct3D对它进行变换,通常用于做UI(用户界面);
D3DFVF_DIFFUSE——表示顶点格式中有漫反射颜色(这涉及到顶点数据格式的设置),同时,必须开启了光照才能看到设置的颜色,否则是本色(一般是白色)的;
D3DFVF_NORMAL——表示顶点有法线向量;
D3DFVF_TEX*——表示顶点有纹理坐标,*可以是1至8,表示有多少套纹理坐标

举例来说,上述测试代码中,我的想法是将顶点格式设置为包含三个原始坐标的类,所以在FVF设置时我就将其设置为D3DFF_XYZ,同时,在后续绘制于屏幕之前,我将

我的坐标进行了投影变换同时设置了摄像机的位置,如果将摄像机注释掉,则在屏幕上看不到任何东西。

*注意:

1、D3DFVF_XYZ默认的用户区中心坐标是(0,0),而D3DFVF_XYZRHW是左上角为(0,0)
用D3DFVF_XYZ默认的为非光照的,而D3DFVF_XYZRHW是高洛德光照。

二、顶点的数据格式是否可以自己设置?

答案当然是一定的,不过一般要根据自己的FVF需求去设置,比如,如果你使用D3DFVF_XYZ(D3DFVF_XYZRHW) | D3DFVF_DIFFUSE | D3DFVF_NORMAL,那么你的顶点数据结构

就应该有三种内容:坐标,颜色,法向量。对于我而言,我习惯于将FVF也定义到顶点数据结构中,这比较方便、

三、D3DXMatrixPerspectiveFovRH 和 D3DXMatrixPerspectiveFovLH有什么区别?

前者是创建右手坐标透视投影矩阵,而后者是创建左手坐标透视投影矩阵。回顾一下左手坐标与右手坐标:

左手坐标:伸出左手,让拇指和食指成“L”形,大拇指向右,食指向上。其余的手指指向前方。这样就建立了一个左手坐标系。拇指、食指和其余手指分别代表x,y,z轴的正方向。判断方法:在空间直角坐标系中,让左手拇指指向x轴的正方向,食指指向y轴的正方向,如果中指能指向z轴的正方向,则称这个坐标系为左手直角坐标系.反之则是右手直角坐标系。

右手坐标:右手坐标系在我们以前初中高中学几何的时候也经常用到。在三维坐标系中,Z轴的正轴方向是根据右手定则确定的。右手定则也决定三维空间中任一坐标轴的正旋转方向。要标注X、Y和Z轴的正轴方向,就将右手背对着屏幕放置,拇指即指向X轴的正方向。伸出食指和中指,如右图所示,食指指向Y轴的正方向,中指所指示的方向即是Z轴的正方向。要确定轴的正旋转方向,如下图所示,用右手的大拇指指向轴的正方向,弯曲手指。那么手指所指示的方向即是轴的正旋转方向。

猜你喜欢

转载自www.cnblogs.com/heisen/p/9384601.html