地形编辑器的XNA VertexBuffer

本文关键字:XNA VertexBuffer 编辑器 | 更新日期: 2023-09-27 18:24:58

我正在进行一个个人项目,与许多XNA项目一样,该项目从地形置换图开始,该地图用于生成在Device.DrawIndexedPrimitives()调用中渲染的顶点集合。

我已经更新到自定义VertexDeclaration,但我现在无法访问该代码,所以我将发布稍旧但语法相同的(?)代码。

我将VertexBuffer定义为:

VertexBuffer = new VertexBuffer(device, VertexPositionNormalTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
VertexBuffer.SetData(vertices);

其中"顶点"定义为:

VertexPositionNormalTexture[] vertices

我还得到了两个索引缓冲区,它们在每次Update()迭代中交换。在Draw()调用中,我设置了GraphicsDevice缓冲区:

Device.SetVertexBuffer(_buffers.VertexBuffer);
Device.Indices = _buffers.IndexBuffer;

忽略我希望不相关的代码行,我有一种方法,可以在边界形状内进行检查,以确定顶点是否在鼠标光标的特定半径内,并根据按下的键来升高或降低这些顶点的位置。我的问题是VertexBuffer.SetData()在初始化容器类时只调用一次。

修改VertexPositionNormalTexture[]阵列的顶点位置不会反映到屏幕上,尽管顶点位置的值会发生更改。我相信这与VertexBuffer.SetData()调用有关,但在修改后不能简单地用顶点数组调用SetData()

在重新检查了IndexBuffer是如何处理的(2个缓冲区,在Update()时交换并传递到SetData())之后,我认为这应该是处理VertexBuffer操作的方法,但这有效吗?有没有更合适的方法?我在这里看到了另一个类似问题的参考,但源代码的链接在MegaUpload上,所以…

我将尝试我的VertexBuffer.Swap()想法,但我也看到了对DynamicVertexBuffer的引用,并想知道有什么好处?性能可能会受到影响,但对于地形编辑器来说,如果我可以动态操作顶点数据,我认为这不会是一个太大的权衡。

我可以发布更多的代码,但我认为这可能是对设备缓冲区的设置或数据流传输方式缺乏了解。

编辑:下面提出的解决方案是正确的。我将很快发布我的代码。

地形编辑器的XNA VertexBuffer

首先:我假设您没有从地形中添加或减去顶点。如果不是,则根本不需要更改索引缓冲区。

第二:您正确地认识到,简单地编辑顶点数组不会改变屏幕上显示的内容。"顶点缓冲区"(VertexBuffer)与创建它的顶点完全分离,并且不保留对它们的原始数组的引用。它是设置数据时顶点的"快照"。

我不确定你所做的一些假设。据我所知,您可以随时调用VertexBuffer.SetData()。如果不更改地形中的顶点数量,只更改它们的位置,这很好。每次更改顶点的位置时,只需重新设置缓冲区中的数据即可。[注意:如果我错了,你只能在缓冲区上设置一次数据,那么只需用新的缓冲区替换旧的缓冲区实例,然后在上面设置数据。不过,我认为你不需要,除非你改变了顶点的数量]

不过,对于大缓冲区来说,调用SetData是相当昂贵的。您可以考虑将地形"分块"到许多较小的缓冲区中,以避免在更改地形时设置数据所需的开销。

我对DynamicVertexBuffer类了解不多,但我认为它不适合这种情况(即使听起来是这样)。我认为它更多地用于粒子顶点。不过,我可能错了。一定要研究一下。

出于好奇,为什么需要两个索引缓冲区?如果顶点相同,为什么每帧使用不同的索引?

编辑:创建VertexBuffer的代码只使用BufferUsage.WriteOnly。好的做法是使BufferUsage与GraphicsDevice的BufferUsage匹配。如果你还没有设置设备的BufferUsage,你可能只想使用BufferUsage.None。如果你愿意,请同时尝试并检查性能差异。