我正在开发一个个人项目,与许多XNA项目一样,它开始使用地形位移贴图,该贴图用于生成在Device.DrawIndexedPrimitives()
调用中呈现的顶点集合。
我已更新为自定义VertexDeclaration
,但我现在无权访问该代码,因此我会发布稍微较旧但范式相同的(?)代码。
我将VertexBuffer
定义为:
VertexBuffer = new VertexBuffer(device, VertexPositionNormalTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
VertexBuffer.SetData(vertices);
其中'vertices'定义为:
VertexPositionNormalTexture[] vertices
我还有两个在每次Update()迭代时交换的索引缓冲区。在Draw()
调用中,我设置了GraphicsDevice
个缓冲区:
Device.SetVertexBuffer(_buffers.VertexBuffer);
Device.Indices = _buffers.IndexBuffer;
忽略我希望的不相关的代码行,我有一个方法可以检查一个边界形状,以确定一个顶点是否在鼠标光标的某个半径范围内,并根据哪个键提升或降低这些顶点位置被压了。我的问题是VertexBuffer.SetData()
仅在容器类的初始化时被调用一次。
虽然顶点位置的值已更改,但修改VertexPositionNormalTexture[]
数组的顶点位置不会反映到屏幕上。我认为这与VertexBuffer.SetData()
调用相关联,但在修改后,您不能简单地使用顶点数组调用SetData()
。
重新检查IndexBuffer的处理方式(2个缓冲区,交换并在SetData()
时传递到Update()
),我认为这应该是处理VertexBuffer
的方法操纵,但这有效吗?有更合适的方法吗?我在这里看到了对类似问题的另一个引用,但是源代码的链接是在MegaUpload上,所以......
我会尝试我的VertexBuffer.Swap()
想法,但我也看到了对DynamicVertexBuffer
的引用,并想知道它的收益是什么?性能可能会受到影响,但对于地形编辑器,如果我能动态操作顶点数据,我不认为这是一个太大的权衡。
我可以发布更多代码,但我认为这可能是缺乏对如何设置设备缓冲区或将数据流传输给它们的理解。
编辑:下面提出的解决方案是正确的。我将很快发布我的代码。
答案 0 :(得分:1)
首先:我假设您没有在地形中添加或减去顶点。如果不是,则根本不需要改变索引缓冲区。
第二:你认识到简单地编辑顶点数组不会改变屏幕上显示的内容是正确的。 VertexBuffer完全独立于创建它的顶点,并且不保留对它们的原始数组的引用。设置数据时,它是顶点的“快照”。
我不确定你所做的一些假设。据我所知,你可以随时调用VertexBuffer.SetData()。如果你没有改变地形中的顶点数量,只改变它们的位置,这是好的。每次更改顶点的位置时,只需在缓冲区中重新设置数据即可。 [注意:如果我错了,你只能在缓冲区上设置一次数据,那么只需用新的缓冲区替换旧的缓冲区实例,然后在其上设置数据。不过,除非你改变了顶点的数量,否则我认为你不需要这样做
但是,对于大型缓冲区,调用SetData相当昂贵。您可以考虑将地形“分块”为许多较小的缓冲区,以避免在更改地形时设置数据所需的开销。
我对DynamicVertexBuffer类知之甚少,但我认为它不适合这种情况(即使听起来像是这样)。我认为它更多地用于粒子顶点。不过我可能错了。绝对研究它。
出于好奇,你为什么需要两个索引缓冲区?如果您的顶点相同,为什么每帧使用不同的索引?
编辑:您创建VertexBuffer的代码使用BufferUsage.WriteOnly。好的做法是使BufferUsage与GraphicsDevice的匹配。如果您尚未设置设备的BufferUsage,则可能只想使用BufferUsage.None。如果您愿意,请尝试两者并检查性能差异。