如何在 C++ 中高效地进行 2D OpenGL 渲染

How to make 2D OpenGL rendering efficient in C++

我正在使用 OpenGL 在 C++ 中开发一个小项目。我希望能够尽可能高效地以某种颜色或纹理渲染多个 2D 矩形。

但是,我在现代 C++ 中这样做,所以我在 OpenGL 上编写了很多包装器 API 以便我有更好的逻辑结构,RAII,...

本着这种精神,我想创建一个 class 矩形,它有一个 draw() 方法,这个方法将激活相应的 OpenGL 上下文并调用 glDrawArrays()。这工作正常,但后来我意识到,如果我想渲染更多的矩形,我将不得不循环遍历许多实例。他们每个人都会切换上下文,我认为这不是一个有效的解决方案。

经过一番思考,我的解决方案是创建一个 Renderer 对象,它将为所有 Rectangle、相关程序和巨大的缓冲区保存一个 VAO,我将在其中保存我的对象的所有坐标(Rectangle 实例然后将就像指向这个缓冲区的更智能的指针)然后一次绘制它们。当然,它会增加我管理缓冲区本身的大量工作(adding/removing 个矩形)。会更好吗?

另外,你有什么建议我还应该关注什么吗?

一般来说,您希望尽量减少绘图调用的次数。将大量几何数据放在单个缓冲区对象中,然后将其全部打包到单个 glDraw… 调用中绝对是可行的方法。解决这个问题的最好方法是不要认为使用 OpenGL 绘制的东西是单个对象(没有勺子),而只是颜色块,偶然看起来是矩形、盒子、球体、勺子……

使用 C++ 习语实现此目的的一种方法是拥有一个缓冲区对象 class,它在内部管理缓冲区对象中包含的数据块。请记住,缓冲区对象本身几乎没有形式,只有将它们用作顶点属性的来源,它们才有意义。然后您的各个矩形将从这样的缓冲区对象实例中分配; return 中的实例可以传递相对于某个内部偏移量的矩形属性索引(传递给 glVertexAttribPointer 的内容);拥有一个 缓冲区对象 class、一个 对象属性视图 class(它管理属性指针)和在属性视图上运行的实际几何 classes。

在准备实际的绘图调用时,几何实例将只发出它们各自顶点的实例;将它们连接起来并将其用于 glDrawElements 调用。

如果您的几何图形没有改变,那么最好的方法是创建 VAO,其中一个 VBO 用于矩形几何图形,一个 vbo 用于您可以绘制的多个矩形的转换,一个 vbo 用于纹理坐标并实例化您删除大量流量从 cpu 到 this.Also 的 gpu 尝试缓存制服,如果值没有改变,则不要在每次渲染调用时都设置它们的值。尝试使用 gltrace 之类的工具,看看是否可以减少不必要的状态更改。收集尽可能多的数据,然后只做渲染调用。