[direct3D 9.0] 程序二 纹理立方体

这个程序是基于上个程序修改而来,为每一个面贴图。但是之前一直有问题,纹理一直不能正确显示

1.不显示纹理。如下图所示

经排查,问题出在Render函数里面设置顶点格式d3dDevice->SetFVF(D3DFVF_XYZ).然后我就修改成了自定义的格式Vertex::FVF。

2.上面修改完成后,纹理显示不正常,并不是每个面分别一个贴图。而是贴图混乱。如下图所示:

最后参考了http://blog.csdn.net/poem_qianmo/article/details/8523341这篇博文,发现自定义的顶点格式有问题

const DWORD Vertex::FVF=D3DFVF_XYZ  | D3DFVF_TEX1 | D3DFVF_NORMAL;

去掉D3DFVF_NORMAL程序运行就正常了。如下图所示

至于原因,我google了一下,D3DFVF_NORMAL的定义是这样的:

还是不明白为什么它影响纹理贴图。

下面是源代码

  1 #include <Windows.h>
  2 #include <d3d9.h>
  3 #include <D3DX9math.h>
  4 #include <strsafe.h>
  5 #include <d3dx9tex.h>
  6 //全局变量 
  7 
  8 LPDIRECT3D9 d3D9 = NULL;                                         // IDirect3D9接口指针,用于获得物理设备信息和创建IDirect3DDeivce9接口。
  9 LPDIRECT3DDEVICE9 d3dDevice = NULL;                    // 代表显示3d图形的物理设备的C++对象。
 10 LPDIRECT3DVERTEXBUFFER9 vertexBuffer = NULL;   // 顶点缓存,用于存储顶点坐标。
 11 LPDIRECT3DINDEXBUFFER9 indexBuffer = NULL;     // 索引缓存,用于存储组成各个三角形的顶点的索引
 12 LPDIRECT3DTEXTURE9 tex = NULL;   // 材质
 13 struct Vertex  // 三维中顶点结构
 14 {
 15     float x, y, z;
 16     float _u, _v; //texture coordinates 
 17     static const DWORD FVF;
 18 };
 19 const DWORD Vertex::FVF=D3DFVF_XYZ  | D3DFVF_TEX1;
 20 
 21 //初始化 Direct3D
 22 BOOL InitD3D(HWND hwnd)
 23 {
 24     if( NULL == (d3D9 = Direct3DCreate9(D3D_SDK_VERSION))) //  该初始化函数保证应用程序通过正确的头文件被生成。
 25         return E_FAIL;  
 26 
 27 
 28 
 29     D3DCAPS9 caps;                            //device capabilitites
 30     d3D9->GetDeviceCaps(                 // 获取设备信息
 31         D3DADAPTER_DEFAULT,            //Adapter 指定获取哪个显示适配器的特性
 32         D3DDEVTYPE_HAL,                   // 设备类型 硬件设备:D3DDEVTYPE_HAL 软件设备:D3DDEVTYPE_REF
 33         &caps);                                    //返回填充后的D3DCAPS9结构。
 34 
 35     int vp = 0;                               //代表是否支持硬件顶点处理
 36     if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)  //显卡是否支持硬件几何转换和光源计算
 37     {
 38         vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; //支持,硬件方式处理顶点
 39     }
 40     else
 41     {
 42         vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;  //软件方式处理顶点
 43     }
 44 
 45     D3DPRESENT_PARAMETERS d3dparam;   // 这个结构用于设定我们将要创建的IDirect3DDevice9对象的一些特性
 46     ZeroMemory(&d3dparam, sizeof(d3dparam));
 47     d3dparam.BackBufferWidth = 800;                   //后备缓冲表面的宽度
 48     d3dparam.BackBufferHeight = 600;                    //后备缓冲表面的高度
 49     d3dparam.BackBufferFormat = D3DFMT_A8R8G8B8;  //后备缓冲表面的像素格式
 50     d3dparam.BackBufferCount = 1;                                 // 后备表面的个数
 51     d3dparam.MultiSampleType = D3DMULTISAMPLE_NONE;  //全屏抗锯齿的类型
 52     d3dparam.MultiSampleQuality = 0;                                   //全屏抗锯齿的质量等级
 53     d3dparam.SwapEffect = D3DSWAPEFFECT_DISCARD;            // 指定表面在交换链中是如何被交换的
 54     d3dparam.hDeviceWindow = hwnd;                          // 窗口句柄
 55     d3dparam.Windowed = true;                      //是否窗口模式
 56     d3dparam.EnableAutoDepthStencil = true;                // 深度/模板缓冲
 57     d3dparam.AutoDepthStencilFormat = D3DFMT_D24S8;            //深度/模板缓冲的等级
 58     d3dparam.Flags = 0;    // 一些附加特性
 59     d3dparam.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;    //刷新率
 60     d3dparam.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;  //属于D3DPRESENT 成员,又有两个常用标志,其余请查SDK:
 61     
 62     //创建IDirect3DDevcie9对象
 63     if(FAILED(d3D9->CreateDevice(        
 64         D3DADAPTER_DEFAULT,            //adapter
 65         D3DDEVTYPE_HAL,             //设备类型
 66         hwnd,                             //窗口句柄
 67         vp,                                 //顶点处理方式
 68         &d3dparam, &d3dDevice)))
 69     {
 70         return E_FAIL;
 71     }
 72     return true;
 73 }
 74  
 75 // 创建顶点缓存
 76 bool InitVertexBuffer()
 77 {
 78 
 79     // 初始化正方体的24顶点
 80     Vertex vertex[] = 
 81     {  //正面
 82         {-1.0f, 1.0f, -1.0f,    0.0f, 0.0f},
 83         {1.0f,  1.0f, -1.0f, 1.0f, 0.0f},
 84         {1.0f, -1.0f, -1.0f, 1.0f, 1.0f},
 85         {-1.0f, -1.0f, -1.0f, 0.0f, 1.0f},
 86         //背面
 87         {1.0f, 1.0f, 1.0f,0.0f, 0.0f},
 88         {-1.0f, 1.0f, 1.0f, 1.0f, 0.0f},
 89         {-1.0f, -1.0f, 1.0f, 1.0f, 1.0f},
 90         {1.0f, -1.0f, 1.0f, 0.0f, 1.0f},
 91         //左面
 92         {-1.0f, 1.0f, 1.0f, 0.0f, 0.0f},
 93         {-1.0f, 1.0f, -1.0f,1.0f, 0.0f},
 94         {-1.0f, -1.0f, -1.0f, 1.0f, 1.0f},
 95         {-1.0f,  -1.0f, 1.0f, 0.0f, 1.0f},
 96         //右面
 97         {1.0f, 1.0f, -1.0f, 0.0f, 0.0f},
 98         {1.0f, 1.0f, 1.0f, 1.0f, 0.0f},
 99         {1.0f, -1.0f, 1.0f, 1.0f, 1.0f},
100         {1.0f, -1.0f, -1.0f, 0.0f, 1.0f},
101         //底面
102         {-1.0f, -1.0f, -1.0f,    0.0f, 0.0f},
103         {1.0f, -1.0f, -1.0f, 1.0f, 0.0f},
104         {1.0f, -1.0f, 1.0f, 1.0f, 1.0f},
105         {-1.0f, -1.0f, 1.0f, 0.0f, 1.0f},
106         //上面
107         {-1.0f,  1.0f, 1.0f, 0.0f, 0.0f},
108         {1.0f, 1.0f, 1.0f, 1.0f, 0.0f},
109         {1.0f, 1.0f, -1.0f, 1.0f, 1.0f},
110         {-1.0f, 1.0f, -1.0f, 0.0f, 1.0f}
111 
112     };
113     if(FAILED(d3dDevice->CreateVertexBuffer(          //创建顶点缓存
114         24*sizeof(Vertex),           // 分配给缓存的字节大小         
115         0,                                 //指定关于怎样使用缓存的额外信息
116         Vertex::FVF,               // 存储杂牌缓存中的顶点格式
117         D3DPOOL_DEFAULT,      //缓存放置在哪一个内存池中
118         &vertexBuffer,                //返回创建好的顶点缓存的指针
119         NULL)))                          // 没有使用
120     {
121         return false;
122     }
123     Vertex *vetices;
124     vertexBuffer->Lock(0, 0, (void**)&vetices, 0);          //锁存整个缓存
125     memcpy(vetices, vertex, sizeof(vertex));                   //想缓存里写顶点
126     vertexBuffer->Unlock();                                         //解锁缓存
127     return true;
128 }
129 
130 //设置照相机和投影
131 void SetupMatrices()
132 {
133     D3DXMATRIX matWorld, Rx, Ry, Rz;  
134     D3DXMatrixIdentity(&matWorld);                  // 单位化世界矩阵  
135     D3DXMatrixRotationX(&Rx, D3DX_PI *(::timeGetTime() / 1000.0f));    // 绕X轴旋转  
136     D3DXMatrixRotationY(&Ry, D3DX_PI *( ::timeGetTime() / 1000.0f/2));    // 绕Y轴旋转  
137     D3DXMatrixRotationZ(&Rz, D3DX_PI *( ::timeGetTime() / 1000.0f/3));   // 绕Z轴旋转  
138     matWorld = Rx * Ry * Rz * matWorld;             // 得到最终的组合矩阵  
139     d3dDevice->SetTransform(D3DTS_WORLD, &matWorld);  //设置世界变换矩阵  
140 
141     D3DXVECTOR3 position(3.0f, 3.0f, 3.0f);            //虚拟照相机坐标
142     D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);                 // 目标物体坐标
143     D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);                        //正上方坐标
144     D3DXMATRIX v;                                                          
145     D3DXMatrixLookAtLH(&v, &position, &target, &up);      //计算视图坐标系的变换矩阵   
146 
147     d3dDevice->SetTransform(D3DTS_VIEW, &v);    //视图坐标系变换
148 
149     D3DXMATRIX proj;                 //投影矩阵
150     //计算投影矩阵
151     D3DXMatrixPerspectiveFovLH(&proj,               
152         D3DX_PI*0.5f,         //视野角度
153         800.0/600.0,            //宽高比
154         1.0f,                       //前裁剪面距离
155         1000.0f);                   //后裁剪面距离
156     d3dDevice->SetTransform(D3DTS_PROJECTION, &proj);        //设置投影变换
157 
158 }
159 
160 void InitTexture() 
161 {
162     D3DXCreateTextureFromFile(d3dDevice, L"texture.bmp", &tex);   // 创建纹理
163     d3dDevice->SetTexture(0, tex);
164 
165     //设置过滤器
166     d3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
167     d3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
168     d3dDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
169 
170     d3dDevice->SetRenderState(D3DRS_LIGHTING, false);  //关闭灯光
171 }
172 //初始化索引缓存
173 bool InitIntextBuffer()
174 {
175     d3dDevice->CreateIndexBuffer(36*sizeof(WORD),        
176         D3DUSAGE_WRITEONLY, 
177         D3DFMT_INDEX16,                     //指定索引的大小
178         D3DPOOL_MANAGED, 
179         &indexBuffer, 
180         0);
181     WORD* indices = 0;
182     indexBuffer->Lock(0, 0, (void**)&indices, 0);
183     //前面
184     indices[0] = 0; indices[1] = 1; indices[2] = 2;
185     indices[3] = 0; indices[4] = 2; indices[5] = 3;
186     // 背面
187     indices[6] = 4; indices[7] = 5; indices[8] = 6;
188     indices[9] = 4; indices[10] = 6; indices[11] = 7;
189     // 左面
190     indices[12] =8; indices[13] =9; indices[14] = 10;
191     indices[15] = 8; indices[16] = 10; indices[17] = 11;
192     // 右面
193     indices[18] = 12; indices[19] = 13; indices[20] =14;
194     indices[21] = 12; indices[22] = 14; indices[23] =15;
195     //底面
196     indices[24] = 16; indices[25] = 17; indices[26] =18;
197     indices[27] = 16; indices[28] = 18; indices[29] = 19;
198     //顶面
199     indices[30] =20; indices[31] = 21; indices[32] =22;
200     indices[33] = 20; indices[34] = 22; indices[35] = 23;
201 
202     indexBuffer->Unlock();
203     return true;
204 }
205 //释放COM资源
206 bool CleanUp()
207 {
208     if(indexBuffer != NULL)
209         indexBuffer->Release();
210     if(vertexBuffer != NULL)
211         vertexBuffer->Release();
212     if(d3dDevice != NULL)
213         d3dDevice->Release();
214     if(d3D9 != NULL)
215         d3D9->Release();
216     return true;
217 }
218 //渲染
219 bool Render()         
220 {
221     d3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff000000, 1.0f, 0);
222     if(SUCCEEDED(d3dDevice->BeginScene()))        //开始场景绘制
223     {
224         SetupMatrices();    //设置照相机和投影
225 
226         // 设置资源流与一个顶点缓存挂钩
227         d3dDevice->SetStreamSource(0, vertexBuffer, 0, sizeof(Vertex));
228         d3dDevice->SetIndices(indexBuffer);           //设置索引缓存
229         d3dDevice->SetFVF(Vertex::FVF);               //设置顶点格式
230 
231          //使用索引来绘制图元
232         d3dDevice->DrawIndexedPrimitive(
233             D3DPT_TRIANGLELIST,         //图元类型 
234             0,                                         //一个基本数字,在调用中用它去加上索引
235             0,                                         //将被引用的最小索引值
236             24,                                         //顶点数
237             0,                                         //开始渲染的开始索引点 
238             12);                                       //绘制图元的个数
239         d3dDevice->EndScene();             //结束场景绘制
240     }
241     d3dDevice->Present(NULL, NULL, NULL, NULL);        //翻转表面
242     return true;
243 }
244 //消息处理函数
245 LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
246 {
247     switch( msg )
248     {
249     case WM_DESTROY:
250         CleanUp();
251         PostQuitMessage( 0 );
252         return 0;
253     }
254     return DefWindowProc( hwnd, msg, wParam, lParam );
255 }
256 
257 //main函数
258 INT WINAPI wWinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in LPWSTR lpCmdLine, __in int nShowCmd )
259 {
260     UNREFERENCED_PARAMETER(hInstance);
261     WNDCLASSEX wc = {
262         sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, 
263         GetModuleHandle(NULL), NULL, NULL, NULL, NULL, 
264         L"Cubedemo", NULL
265     };
266     RegisterClassEx(&wc);
267     
268     HWND hwnd = CreateWindow(L"CubeDemo", L"CubeDemo", 
269         WS_OVERLAPPEDWINDOW, 100, 100, 800, 600, NULL, NULL, hInstance, NULL);
270 
271     if(InitD3D(hwnd))
272     {
273         if(InitVertexBuffer() && InitIntextBuffer())
274         {
275             InitTexture();
276             ShowWindow(hwnd, SW_SHOWDEFAULT);
277             UpdateWindow(hwnd);
278             MSG msg;
279             ZeroMemory(&msg, sizeof(msg));
280             while(msg.message != WM_QUIT)
281             {
282                 if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
283                 {
284                     TranslateMessage(&msg);
285                     DispatchMessage(&msg);
286                 }
287                 else
288                 {
289                     Render();
290                 }    
291             }
292 
293         }
294     }
295     UnregisterClass(L"CubeDemo", wc.hInstance);
296     return 0;
297 
298 }
原文地址:https://www.cnblogs.com/wangke1020/p/3696159.html