Dea*_*con 3 c++ directx 3d graphics vertex-buffer
如果我的顶点位置是共享的,但是我的法线和UV不是(为了保留硬边等),是否可以在DirectX11中使用非交错缓冲区来解决这个内存表示,这样我就可以使用indice缓冲区了?或者我应该在交错缓冲区中坚持重复的顶点位置?
交错和非交错顶点缓冲区之间是否有任何性能问题?谢谢!
Iva*_*rop 12
有几种方法.我将描述最简单的一个.
只需创建单独的顶点缓冲区:
ID3D11Buffer* positions;
ID3D11Buffer* texcoords;
ID3D11Buffer* normals;
Run Code Online (Sandbox Code Playgroud)
创建输入布局元素,InputSlot为每个组件递增成员:
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 1, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 2, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
// ^
// InputSlot
Run Code Online (Sandbox Code Playgroud)
将缓冲区绑定到它们的插槽(一次性更好):
ID3D11Buffer** vbs = {positions, texcoords, normals};
unsigned int strides[] = { /*strides go here*/ };
unsigned int offsets [] = { /*offsets go here*/ };
m_Context->IASetVertexBuffers(0, 3, vbs, strides, offsets );
Run Code Online (Sandbox Code Playgroud)
像往常一样画画.您不需要更改HLSL代码(HLSL会认为它具有单个缓冲区).
请注意,代码片段是即时编写的,可能包含错误.
编辑:您可以改进此方法,按更新速率组合缓冲区:如果texcoords且normals从未更改,请合并它们.
这完全是关于引用的位置:数据越近,访问速度越快.
在大多数情况下,交错缓冲区为GPU侧(即渲染)提供(到目前为止)更高的性能:对于每个顶点,每个属性彼此靠近.但是,单独的缓冲区可以提供更快的CPU访问:数组是连续的,每个下一个数据都接近前一个.
因此,总体而言,性能问题取决于您写入缓冲区的频率.如果您的限制因素是CPU写入,请坚持使用单独的缓冲区.如果没有,请选择单身.
你怎么知道的?只有一种方式 - 个人资料.CPU端和GPU端(通过GPU供应商提供的图形调试器/分析器).
最佳做法是限制CPU写入,因此,如果您发现受限于缓冲区更新,则可能需要重新查看您的方法.如果我们有500 fps,我们是否需要更新每帧的缓冲区?如果将缓冲区更新速率降低到每秒30-60次(从帧更新解除绑定缓冲区更新),用户将看不到差异.因此,如果您的更新策略合理,您可能永远不会受CPU限制,最佳方法是经典交错.
您还可以考虑重新设计数据管道,甚至以某种方式离线准备数据(我们称之为"烘焙"),因此您不需要处理非交错缓冲区.这也是非常合理的.
内存与性能之间的权衡.这是永恒的问题.重复内存以利用交错?或不?
答案是......"这取决于".您正在编写新的CryEngine,针对具有千兆字节内存的顶级GPU?或者您正在为移动平台的嵌入式系统编程,其中内存资源缓慢且有限?1兆字节的内存值得麻烦吗?或者你有巨大的型号,每个100 MB?我们不知道.
这完全取决于你的决定.但请记住:没有免费的糖果.如果您发现内存经济值得性能损失,那就去做吧.简介和比较,以确保.
希望它能以某种方式帮助.快乐的编码!=)
| 归档时间: |
|
| 查看次数: |
3673 次 |
| 最近记录: |