如何正确更新 DirectX 10 中的顶点缓冲区
背景知识:我正在开发一个 C++ 项目,在该项目中我尝试根据实时轮廓数据绘制对象的 3D 表示。分析数据是从外部分析硬件收集的。该系统沿着一个物体移动,并以每秒 300 次的速度为我的软件提供轮廓切片。每个切片由约 8000 个 XY 点的列表组成。轮廓仪的运动由编码器记录。编码器信息提供扫描的第三维。
另一件需要注意的重要事情是探查器可能会在对象上来回移动。发生这种情况时,我想用新的切片替换以前读取/绘制的切片(基于编码器位置)。到目前为止,我正在通过按编码器计数存储的切片循环缓冲区来实现这一目标。这也意味着当缓冲区填满并开始覆盖旧切片时,我将想要丢弃切片。为了在屏幕上显示适当数量的主题片段 - 我需要一次绘制 1000 个剖面数据切片。现在我将对象渲染为点云。将来我们可能会尝试附加相邻的切片并渲染为三角形列表。
我是 DirectX 新手,但通过书籍和在线示例,我已经达到了在 3D 中绘制对象的程度,但我确信我没有有效/正确地使用顶点缓冲区。我发现的大多数示例都适用于非常静态的模型。因此,他们倾向于使用点列表创建单个顶点缓冲区,然后仅通过矩阵变换进行操作。另一方面,当我从硬件检索配置文件数据时,我将非常快速地更新场景。
目前,我正在为读入的每个切片创建一个新的顶点缓冲区。当我绘制场景时,我循环遍历最多 1000 个缓冲区的列表,并为每个缓冲区调用 Draw()。我注意到,如果我将一次绘制的顶点缓冲区数量减少一半,我的 FPS 会显着增加,而将每个缓冲区的顶点点数减半时几乎没有什么改进 - 所以我认为这表明多个顶点缓冲区这不是解决这个问题的正确方法。
所以对于我的问题的核心...我想知道当顶点变化如此频繁时我是否可以将所有这些顶点放入一个顶点缓冲区中。我可以更新现有顶点缓冲区中的点吗?或者我应该在每次更新场景时重新创建一个全新的缓冲区?最后要记住的一件事是,硬件中每个切片的点数会有所不同 - 因此,当涉及到覆盖以前的切片时,新切片可能比被替换的切片具有更多或更少的点。
感谢您抽出时间。任何建议将不胜感激!
For a little background: I am working on a project in C++ in which I am trying to draw 3D representations of objects based on real time profile data. The profiling data is gathered from external profiling hardware. The system travels along an object and at a rate of 300 times per second provides my software with a profile slice. Each slice consists of a list of ~8000 X-Y points. The movement of the profiler is recorded by an encoder. The encoder information provides the 3rd dimension of the scan.
Another important thing to note is that the profiler may move back and forth over the object. As this happens, I want to replace previously read/drawn slices with new ones (based on encoder position). As of now, I am achieving this with a circular buffer of slices that I store by the encoder count. This also means that I will want to throw out slices as the buffer fills and begins overwriting old slices. In order to show the proper amount of the subject piece on the screen - I need to draw 1000 slices of profile data at a time. For now I am rendering the object as a point cloud. In the future we may attempt to attach adjacent slices and render as a triangle list.
I am new to DirectX, but using books and online examples I've gotten to the point where I am drawing the object in 3D, but I am convinced that I am not efficiently/properly using Vertex Buffers. Most examples I've found work with very static models. Therefore, they tend to create a single Vertex Buffer with their list of points, and then are just manipulated by matrix transformations. I, on the other hand, will be updating the scene very quickly as I retrieve profile data from our hardware.
Currently I am creating a new Vertex Buffer for each slice I read in. When I draw the scene I loop through my list of up to 1000 buffers and call Draw() for each one. I noticed that if I cut in half the number of Vertex Buffers drawn at a time, my FPS increased significantly, whereas there was little improvement when halving the number of Vertex Points per buffer - so I take that as an indication that the multiple Vertex Buffers is not the proper way to approach this.
So to the guts of my question... I'm wondering if I can put all these vertices in a single Vertex Buffer when the Vertices change so frequently. Can I update the points within an existing Vertex Buffer? Or should I just recreate a single brand new Buffer each time I update the scene? One last thing to keep in mind is that the number of points per slice from the hardware will vary - so when it comes to over-writing previous slices, the new slice may have more or fewer points than the slice being replaced.
Thanks for your time. Any advice will be much appreciated!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
只要使缓冲区动态化,您就可以随时更新顶点缓冲区内的点(指定
D3D10_USAGE_DYNAMIC
并使用ID3D10Device::CopySubresourceRegion
仅有效更新缓冲区的部分内容) 。这应该比过于频繁地重新创建缓冲区更有效。然而,每个切片的大小不同是不好的。您可以实现某种内存管理器来保持顶点缓冲区的整体碎片较低,否则使用多个 vb 是不可避免的。一种方法是将所有切片大小四舍五入到合理的限制,并为每个大小分配一个 vb。
You can always update the points within a vertex buffer as long as you make the buffer dynamic (specify
D3D10_USAGE_DYNAMIC
and useID3D10Device::CopySubresourceRegion
to update only parts of the buffer efficiently). That should be more efficient than re-creating buffers too frequently.Having different sizes for each slice is bad, however. You could either implement some kind of memory manager to keep the overall fragmentation of your vertex buffers low or this is the point where using multiple vb's is unavoidable. One way would be to round all slices sizes up to a reasonable limit and have one vb for each size.