C# 更新Direct3D网格顶点缓冲区的最快方法?

C# 更新Direct3D网格顶点缓冲区的最快方法?,c#,.net,directx,direct3d,mesh,C#,.net,Directx,Direct3d,Mesh,我有一个地形网格,其中每个顶点的Z值需要在每一帧更新。我当前的方法如下所示: int stepping = CustomVertex.PositionNormalTextured.StrideSize / 4; //ZPtr points to the Z value of the first PositionNormalTextured in the mesh. //This way we don't have to dereference ->Z for each vertex.

我有一个地形网格,其中每个顶点的Z值需要在每一帧更新。我当前的方法如下所示:

int stepping = CustomVertex.PositionNormalTextured.StrideSize / 4;

//ZPtr points to the Z value of the first PositionNormalTextured in the mesh.  
//This way we don't have to dereference ->Z for each vertex.
float* ZPtr = &(((CustomVertex.PositionNormalTextured*)
    TerrainMesh.LockVertexBuffer(LockFlags.NoOverwrite).InternalDataPointer)->Z);

float* DPtr = TerrainHeight; //point to begin scanning result
float* EndPtr = DPtr + TerrainMesh.NumberVertices; //point to stop scanning result

do { *ZPtr = *DPtr; ZPtr += stepping; } while (++DPtr < EndPtr); //copy data
TerrainMesh.UnlockVertexBuffer(); //unlock
这里,TerrainHeight是一个浮点数组,创建时使用Marshal.AllocHGlobal表示地形高度。基本上,它扫描整个TerrainHight阵列,并将每个值复制到网格中相应PositionNormal纹理的Z值。我使用LockFlags.NoOverwrite来避免创建数组的新副本,尽管这似乎并不比LockFlags.Discard快


更新网格所需的时间与在CPU中计算新地形所需的时间相同或更长,这让我相信应该有一种更快的方法。我在谷歌上找不到关于这个的信息。有更好的方法更新vertexbuffer吗?如果有关系,网格的大小由用户设置,可能包括超过一百万个顶点,这是通过多个网格实现的,但默认设置为32k顶点,这是单个D3D网格的最大值。

您似乎不了解丢弃和无覆盖标志的后果。阅读DirectX SDK帮助中“性能优化”下的“使用动态顶点和索引缓冲区”一节。假设您使用的是动态顶点缓冲区,那么丢弃意味着我将替换整个缓冲区,而NoOverwrite意味着我将写入缓冲区中未使用的部分,并且我保证不会更改我已经使用的任何部分

使用任一标志,都必须写入地形顶点的每个组件,即使是在新帧中未更改的组件

如果不使用动态顶点缓冲区,则如果GPU仍在使用,则在尝试锁定下一帧的顶点缓冲区时可能会遇到暂停。在这种情况下,您需要使用多个顶点缓冲区,并在地形高度更改的每一帧中使用不同的缓冲区进行锁定、更新、解锁和渲染。您还必须使用所有地形顶点数据初始化所有这些缓冲区

我建议将网格的z值分离到它们自己的顶点缓冲区中——假设您没有更新x和y的位置,如果z或纹理坐标发生变化,法线可能不正确。这样,您就可以使用PositionNormalTextured,而不必在每一帧都未触及位置z顶点缓冲区,并从一开始就使用Discard标志在每一帧中填充动态z位置缓冲区,而不必跨步到每个z值。既然步幅消失了,你可以用一个平面内存拷贝来完成

您将使用SetStreamSource 1、ZPositionVB等为顶点着色器提供z位置值。您需要调整顶点声明以从流1读取z位置值,并在变换之前调整顶点着色器以组合z位置值


如果其中一些不适合C,请道歉。

您一定要避免在每帧更新较大的顶点缓冲区。尤其是当它包括复制数据时。您的szenario是否允许硬件实现,例如,具有高度贴图的顶点着色器?我不知道您可以这样做!这听起来是一种更有效的方法,尽管我想我必须手动计算法线,也许我可以在顶点着色器中这样做。谢谢