顶点缓存Vertices

D3D学习二:顶点缓存Vertices

最近真的是忙得要死了,所有课都开了,要应付必修课,又要准备设计师考试,三头六臂都不够用了,还好每天还能勉强的抽点时间学D3D。今天早上梦到了猪和去学开飞机了,好兆头,只要努力就能够成功。

开始一时大意在创建注册窗口和创建窗口是把窗口名称搞错了,查了半天才弄出来,忙活得够呛了,还好最后翻查《Windows程序设计》解决了,还是电子书好,不用天天扛着。

以后要更加努力才行!可怜

 

源代码(代码非原创,是书上敲的)

  1. //《3D游戏编程》金容俊/肖永亮  
  1. //创建顶点缓冲区Vertex Buffer   
  2. //所谓顶点缓冲就是指存储顶点D3D对象,用户可以使用FVF随意定义格式。  
  3. //这里将要使用的顶点是完成变换和光源处理的顶点。  
  4.   
  5. #include <d3d9.h>  
  6.   
  7. //全局参数  
  8. LPDIRECT3D9         g_pD3D       = NULL;  //创建D3D设备的D3D对象参数  
  9. LPDIRECT3DDEVICE9       g_pd3dDevice = NULL; //渲染使用中的D3D设备  
  10. LPDIRECT3DVERTEXBUFFER9     g_pVB        = NULL; //存储顶点的顶点缓冲  
  11.   
  12. //定义用户顶点的结构体  
  13. struct CUSTOMVERTEX  
  14. {  
  15.     FLOAT x, y, z, rhw;     //顶点的变换坐标(具有rhw值是完成变换的顶点)  
  16.     DWORD color;            //顶点的颜色  
  17. };  
  18.   
  19. //表现用户顶点结构体信息的FVF  
  20. //结构体由X, Y, Z, RHW值和Diffuse颜色组成  
  21. #define D3DFVF_CUSTOMVERTEX  (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)  
  22.   
  23.   
  24. //Direct3D初始化  
  25. HRESULT InitD3D(HWND hWnd)  
  26. {  
  27.     //创建一个用来创建设备的D3D对象  
  28.     if(NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))  
  29.         return E_FAIL;  
  30.   
  31.     //创建设备的结构体  
  32.     D3DPRESENT_PARAMETERS d3dpp;  
  33.     ZeroMemory(&d3dpp, sizeof(d3dpp));  
  34.     d3dpp.Windowed = TRUE;  
  35.     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;  
  36.     d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;  
  37.   
  38.     //创建设备  
  39.     if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,  
  40.                 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice)))  
  41.     {  
  42.         return E_FAIL;  
  43.     }  
  44.   
  45.     //这里对设备状态信息进行处理  
  46.     return S_OK;  
  47. }  
  48.   
  49.   
  50. ///创建顶点缓冲,设置顶点缓冲  
  51. ///顶点缓冲就是基本包含顶点数据的存储器块  
  52. ///创建顶点缓冲之后,必须调用Lock()函数Unlock()函数来定义指针将顶点数据写入顶点缓冲  
  53. HRESULT InitVB()  
  54. {  
  55.     //渲染三角形的三个顶点声明  
  56.     CUSTOMVERTEX vertices[] =   
  57.     {  
  58.         //x, y, z, rhw, color  
  59.         {150.0f,   50.0f, 0.5f, 1.0f, 0xffff0000, },  
  60.         {250.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, },  
  61.         {   50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff,  },  
  62.     };  
  63.   
  64.     //创建顶点缓冲  
  65.     //分配存储三个用户顶点的存储器  
  66.     //指定存储FVF的数据格式  
  67.     if(FAILED(g_pd3dDevice->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX,   
  68.                         D3DPOOL_DEFAULT, &g_pVB, NULL)))  
  69.     {  
  70.         return E_FAIL;  
  71.     }  
  72.   
  73.     //将数据写入顶点缓冲  
  74.     //调用顶点缓冲的Lock()函数,定义指针  
  75.     VOID* pVertices;  
  76.     if(FAILED(g_pVB->Lock(0, sizeof(vertices), (void**)&pVertices, 0)))  
  77.         return E_FAIL;  
  78.     memcpy(pVertices, vertices, sizeof(vertices));  
  79.     g_pVB->Unlock();  
  80.   
  81.     return S_OK;  
  82. }  
  83.   
  84. //删除初始化对象  
  85. VOID Cleanup()  
  86. {  
  87.     if(g_pVB != NULL)  
  88.         g_pVB->Release();  
  89.   
  90.     if(g_pd3dDevice != NULL)  
  91.         g_pd3dDevice->Release();  
  92.   
  93.     if(g_pD3D != NULL)  
  94.         g_pD3D->Release();  
  95. }  
  96.   
  97. //绘图  
  98. VOID Render()  
  99. {  
  100.     //将后置缓冲清除,同时设置为蓝色(0,0,255)  
  101.     g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0);  
  102.   
  103.     //开始渲染  
  104.     if(SUCCEEDED(g_pd3dDevice->BeginScene()))  
  105.     {  
  106.         //绘制顶点缓冲的三角形  
  107.         //1.使包含顶点的缓冲绑定一个设备数据流  
  108.         g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX));  
  109.         //2.想D3D指定顶点着色信息,大多数情况下只指定FVF格式  
  110.         g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);  
  111.         //3.调用输出几何的DrawPrimitive()函数  
  112.         g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);  
  113.   
  114.         //结束渲染  
  115.         g_pd3dDevice->EndScene();  
  116.     }  
  117.   
  118.     //显示后置缓冲的动画  
  119.     g_pd3dDevice->Present(NULL, NULL, NULL, NULL);  
  120.   
  121. }  
  122.   
  123. //窗口过程  
  124. LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)  
  125. {  
  126.     switch(msg)  
  127.     {  
  128.     case WM_DESTROY:  
  129.             Cleanup();  
  130.             PostQuitMessage(0);  
  131.             return 0;  
  132.     }  
  133.   
  134.     return DefWindowProc(hWnd, msg, wParam, lParam);  
  135. }  
  136.   
  137. //程序的起始地址  
  138. INT WINAPI WinMain(HINSTANCE hInst, HINSTANCELPSTRINT)  
  139. {  
  140.     //注册窗口类  
  141.     WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,  
  142.             GetModuleHandle(NULL), NULL, NULL, NULL, NULL,  
  143.             TEXT("D3D Tutorial"), NULL };  
  144.     RegisterClassEx(&wc);  
  145.   
  146.     //创建窗口 GetDesktopWindow()  
  147.     HWND hWnd = CreateWindow(TEXT("D3D Tutorial"), TEXT("D3D Tutorial 02:Vertices"),  
  148.                 WS_OVERLAPPEDWINDOW, 100, 100, 640, 480,  
  149.                 GetDesktopWindow(), NULL, wc.hInstance, NULL);  
  150.   
  151.     //Direct3D初始化  
  152.     if(SUCCEEDED(InitD3D(hWnd)))  
  153.     {  
  154.         //顶点缓冲  
  155.         if(SUCCEEDED(InitVB()))  
  156.         {  
  157.             //显示窗口  
  158.             ShowWindow(hWnd,SW_SHOWDEFAULT);  
  159.             UpdateWindow(hWnd);  
  160.   
  161.             //消息循环  
  162.             MSG msg;  
  163.             ZeroMemory(&msg, sizeof(msg));  
  164.             while(msg.message != WM_QUIT)  
  165.             {  
  166.                 //消息队列中友消息时,调用相应的处理过程  
  167.                 if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))  
  168.                 {  
  169.                     TranslateMessage(&msg);  
  170.                     DispatchMessage(&msg);  
  171.                 }  
  172.                 else  
  173.                     //如果没有需要处理的消息,调用Reader()函数  
  174.                     Render();  
  175.             }  
  176.         }  
  177.     }  
  178.   
  179.     //删除注册的类  
  180.     UnregisterClass(TEXT("D3D Tutorial"), wc.hInstance);  
  181.     return 0;  
  182. }  
优化OBJ文件中的顶点数据是提升3D模型渲染性能的重要手段,尤其在降低内存占用和提高加载速度方面具有显著效果。以下是一些常见的优化方法: ### 1. **去除重复顶点** 在OBJ文件中,顶点数据可能包含大量重复项,尤其是在模型由多个面共享相同顶点的情况下。通过识别并合并这些重复顶点,可以显著减少顶点数量。具体实现方式是构建一个顶点索引表,将相同的顶点映射到同一个索引上,从而减少冗余数据[^2]。 ### 2. **顶点位置精度优化** OBJ文件中顶点坐标的精度通常以浮点数表示,精度越高,文件体积越大。在不影响模型视觉效果的前提下,可以通过四舍五入或截断的方式减少小数位数。例如,将顶点坐标保留到小数点后四位,通常可以满足大多数应用场景的需求,同时减少文件大小。 ### 3. **使用顶点缓存优化** 在渲染过程中,顶点缓存的使用效率直接影响性能。通过重新排列顶点索引,使相邻的面共享的顶点尽可能在内存中连续存储,可以提高缓存命中率。这种优化方式通常需要结合多边形简化算法进行[^1]。 ### 4. **多边形简化算法** 多边形简化算法是优化顶点数据的重要工具,通过减少多边形数量来降低模型复杂度。常用算法包括: - **边折叠(Edge Collapse)**:通过逐步合并模型中的边来减少顶点数量,同时保持模型的整体形状。 - **渐进式网格(Progressive Meshes)**:将模型简化为不同分辨率的网格,根据渲染需求选择适当的分辨率。 ### 5. **纹理坐标与法线优化** OBJ文件中通常包含纹理坐标和法线信息,这些数据也可能存在冗余。优化时可以通过以下方式: - **合并相同纹理坐标**:与顶点优化类似,合并重复的纹理坐标。 - **简化法线计算**:如果模型对光照效果要求不高,可以使用简化的法线计算方法,减少计算开销。 ### 6. **压缩OBJ文件** 通过压缩工具(如gzip)对OBJ文件进行压缩,可以显著减少文件体积,便于传输和加载。此外,还可以使用二进制格式(如PLY或GLB)存储模型数据,进一步提高性能。 ### 示例代码片段 以下是一个简单的MATLAB代码示例,展示如何去除重复顶点并优化顶点数据: ```matlab % 读取OBJ文件 [vertices, faces] = readOBJ('model.obj'); % 去除重复顶点 [uniqueVertices, ~, idx] = unique(vertices, 'rows'); faces = idx(faces); % 写入优化后的OBJ文件 writeOBJ('optimized_model.obj', uniqueVertices, faces); ``` ### 7. **使用外部工具** 除了手动优化,还可以借助外部工具(如Blender、MeshLab)对OBJ文件进行自动化处理。这些工具通常集成了多种优化算法,能够快速生成优化后的模型。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值