如何使用顶点缓冲区对象来渲染许多不同的圆圈?

Posted

技术标签:

【中文标题】如何使用顶点缓冲区对象来渲染许多不同的圆圈?【英文标题】:How do I use Vertex Buffer Objects to render many different circles? 【发布时间】:2009-09-27 21:49:06 【问题描述】:

我正在尝试编写一个涉及许多圈子的游戏(好吧,Triangle Fans,但你明白了)。每个圆都有一个 x 位置、一个 y 位置和一个质量属性。每个圆圈的质量属性都会不同。另外,我想给一些不同的圆圈组上色,同时保持一个透明的圆圈中心,并沿着圆圈的周边褪色到不透明。

我被告知要使用 VBO,并且整天都在谷歌上搜索。我想要一个完整的例子,说明我将如何绘制这些圆圈,并解释 VBO 的工作原理,同时保持解释简单。

【问题讨论】:

【参考方案1】:

我自己还没有实现 VBO,但据我了解,它们的工作方式类似于纹理对象。事实上,当我提醒自己并向其他人解释 VBO 是什么时,我喜欢错误地将纹理对象称为“纹理缓冲区对象”,以加强概念上的相似性。

(不得与来自 NVIDIA 指定扩展 GL_EXT_texture_buffer_object 的 buffer textures 混合。)

那么让我们想一想:什么是纹理对象?它们是您使用glGenTextures() 生成的对象。 glGenBuffersARB() 做类似的事情。类比适用于glBindTexture()glBindBufferARB()

(从 OpenGL 1.5 开始,函数 glGenBuffers()glBindBuffer() 已进入核心 OpenGL,因此您可以使用它们代替扩展等效项。)

但是这些“纹理对象”到底是什么,它们有什么作用?好吧,考虑一下您实际上可以在每一帧中使用glTexture2D() 来设置纹理。纹理对象仅用于减少 GPU 和主内存之间的流量;而不是发送整个像素数组,您只发送您知道是静态的纹理对象的“OpenGL 名称”(即整数标识符)

VBO 也有类似的用途。您无需一遍又一遍地发送顶点数组,而是使用glBufferData() 上传一次数组,然后只发送对象的“OpenGL 名称”。它们非常适合静态对象,而不适合动态对象。事实上,许多通用 3D 引擎(例如 Ogre3D)为您提供了一种指定网格是动态还是静态的方法,很可能是为了让您在 VBO 和顶点数组之间做出决定。

出于您的目的,VBO 不是正确答案。您需要大量不断变形和变化的简单对象。简单来说,我的意思是那些顶点少于 200 个的那些。除非您打算编写一个非常智能和复杂的顶点着色器,否则 VBO 不适合您。您想使用顶点数组,您可以轻松地从主 CPU 操作并在每帧更新它们,而无需对显卡进行特殊调用以将整个 VBO 重新上传到显卡上(这可能比仅发送顶点数组要慢)。

这是来自 nVidia about VBO API 的非常好的 letscallit “手册页”。阅读它以获取更多信息!

【讨论】:

谢谢!我想我会研究一下顶点数组。 @NicolBolas 1) 我喜欢尽可能支持早期版本的 GL。因此,我不同意使用扩展或将函数的起源视为扩展是一个问题。我认为应该庆幸的是,扩展在今天几乎无处不在。 2)另一方面,这看起来是一个很好的观察。我不知道缓冲区纹理的存在。不过,对于使用立即模式或顶点数组的人来说,与纹理进行类比仍然有助于理解 VBO。我会稍作修改。 @NicolBolas 我已经查看了文本。这确实是一团糟,尤其是考虑到指定缓冲区纹理的 NVIDIA 编写的扩展名。我还提到了核心 GL 功能。希望现在好多了。感谢您的意见!【参考方案2】:

good vbo tutorial

你正在做的看起来像粒子,你可能想谷歌“粒子渲染”以防万一。

【讨论】:

以上是关于如何使用顶点缓冲区对象来渲染许多不同的圆圈?的主要内容,如果未能解决你的问题,请参考以下文章

在两个不同的顶点数组对象中使用顶点缓冲区

OpenGL/C++:使用顶点缓冲区进行从后到前渲染

OpenGL顶点数组对象不记录VBO和IBO绑定

glDrawElement 的 OpenGL 渲染问题

在 OpenGL 中为索引缓冲区对象使用结构会导致段错误

Vulkan多线程渲染