使用 VBO 的最佳方式 [英] The best way to use VBOs

查看:36
本文介绍了使用 VBO 的最佳方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 VBO 的最快和最灵活(适用于大多数情况)的方法是什么?

我正在开发一个 openGL 应用程序,我希望它达到最佳性能,所以我需要有人来回答这些问题.我阅读了很多问题和答案,但我想有太多我不需要的信息会弄乱我的大脑......

I am developing an openGL application and i want it to get to the best performance, so i need someone to answer these questions. I read many questions and anwers but i guess there's to much information that i don't need which messes up my brain...

  • 我应该使用多少个 vbo?
  • 我应该如何创建 vbos?
  • 如果数据大小不固定,我应该如何更新 vbos 数据?
  • 我应该如何渲染 vbos?
  • 我应该如何处理 vbos 中不想再渲染的数据?

推荐答案

  • 我应该使用多少个 vbo?

尽可能少.切换 VBO 的成本虽小,但可衡量.通常,您会尝试将类似的数据分组到 VBO 中.比如在一个FPS游戏中,街边各种垃圾、小道具等等,通常会出现在同一个或少数几个VBO中.

As few as possible. Switching VBOs comes with a small, but measureable cost. In general you'll try to group similar data into VBOs. For example in a FPS game all the different kinds of garbage lying on the street, small props, etc., will be usually located in the same or only a small number of VBOs.

这也归结为绘制批量大小.glDraw... 渲染少于大约 100 个基元的调用是次优的(即使在 15 年前也是如此).因此,您希望尽可能批处理至少 100 个基元.但是,如果单个网格只有,比如说 20 个三角形(用于实例化的低多边形道具等),每个都在自己的 VBO 中,您不能再批量处理.

It also comes down to drawing batch sizes. glDraw… calls which render less than about 100 primitives are suboptimal (this has always been the case, even 15 years ago). So you want to batch at least 100 primitives where possible. But if a single mesh has only, say 20 triangles (low polycount props for instancing or such), each in its own VBO you can no longer batch more.

  • 我应该如何创建 vbos?

glGenBuffers → glBindBuffer → glBufferData

glGenBuffers → glBindBuffer → glBufferData

UPDATE 可以给glBufferData的data参数传递一个空指针,在不设置数据的情况下初始化buffer对象.

UPDATE You can pass a null pointer to the data parameter of glBufferData to initialize the buffer object without setting the data.

  • 如果数据大小不固定,我应该如何更新 vbos 数据?

创建比数据大小更粗粒度的 VBO.您的操作系统无论如何都会为您的主机端数据执行此操作,这称为分页.此外,如果您想使用 glMapBuffer 使缓冲区对象成为主机页面大小的倍数,这对整个系统来说非常好.

Create VBOs with a coarser size granularity than your data size is. Your operating system is doing this anyway for your host side data, it's called paging. Also if you want to use glMapBuffer making the buffer object a multiple of the host page size is very nice to the whole system.

当前系统上通常的页面大小是 4kiB.这就是我选择的 VBO 大小粒度.更新: 顺便说一句,您可以询问您的操作系统正在使用哪种页面大小.不过这取决于操作系统,我会问另一个问题.

The usual page size on current systems is 4kiB. So that's the VBO size granularity I'd choose. UPDATE: You can BTW ask your operating system which page size it is using. That's OS dependent though, I'd ask another question for that.

使用 glBufferSubData 更新数据或在主机端映射内存中使用 glMapBuffer modify 映射它,然后使用 glUnmapBuffer.

Update the data using glBufferSubData or map it with glMapBuffer modify in the host side mapped memory, then glUnmapBuffer.

如果数据超过缓冲区对象,则创建一个新的更大的对象并使用 glCopyBufferSubData 进行复制.见最后一段.

If the data outgrows the buffer object, create a new, larger one and copy with glCopyBufferSubData. See the lase paragraph.

  • 我应该如何渲染 vbos?

glBindBuffer → glDraw...

glBindBuffer → glDraw…

  • 我应该如何处理 vbos 中不想再渲染的数据?

如果数据仅消耗 VBO 的一部分并与其他数据共享,并且您没有耗尽内存,那么,不要访问它.理想情况下,您保留一些索引,您可以在其中跟踪哪个 VBO 的哪些部分可用于哪种任务.这很像内存管理,特别是一种称为对象堆栈(obstacks)的方案.

If the data consumes only a part of the VBO and shares it with other data and you're not running out of memory then, well, just don't access it. Ideally you keep around some index in which you keep track of which VBO has which parts of it available for what kind of task. This is very much like memory management, specifically a scheme known as object stacks (obstacks).

但是最终压缩现有的缓冲区对象可能是有意义的.为此,您将创建一个新的缓冲区对象,将其绑定为写入目标,旧的缓冲区对象被选为读取目标.然后使用 glCopyBufferSubData 将内容复制到一个新的、收紧的缓冲区对象中.当然,您随后必须更新对缓冲区对象名称(=OpenGL ID)和偏移量的所有引用.

However eventually it may make sense to compactify an existing buffer object. For this you'd create a new buffer object, bind it as writing target, with the old buffer object being selected as reading target. Then use glCopyBufferSubData to copy the contents into a new, tightened buffer object. Of course you will then have to update all references to buffer object name (=OpenGL ID) and offsets.

出于这个原因,在 OpenGL 缓冲区对象之上编写一个薄的抽象层是有意义的,用于跟踪 OpenGL 缓冲区对象所在的无结构 blob 中的实际类型数据.

For this reason it makes sense to write a thin abstraction layer on top of OpenGL buffer objects that keeps track of the actual typed data within the structureless blobs OpenGL buffer objects are.

这篇关于使用 VBO 的最佳方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆