我正在使用OpenGL在C ++中开展一个小项目。我希望能够尽可能有效地渲染多种颜色或纹理的2D矩形。
但是,我在现代C ++中这样做,所以我在OpenGL API上写了很多包装器,这样我就有了更好的逻辑结构,RAII,......
本着这种精神,我想创建一个Rectangle类,它将有一个方法draw(),这个方法将激活相应的OpenGL上下文并调用glDrawArrays()。这工作正常,但后来我意识到,如果我想渲染更多的矩形,我将不得不循环通过许多实例。他们每个都会切换上下文,我认为这不是一个有效的解决方案。
经过一番思考后,我的解决方案是创建一个Renderer对象,它将为所有Rectangle,相关程序和巨大的缓冲区保存一个VAO,我将在其中保存我的对象的所有坐标(Rectangle实例将像一个更智能的指针到这个缓冲区),然后立即绘制它们。当然,它会增加我管理缓冲区本身(添加/删除矩形)的大量工作。会更好吗?
另外,你有什么提示我应该关注什么?
通常,您希望最大限度地减少绘图调用的数量。将大量几何数据放置在单个缓冲区对象中并将其全部批处理为单个glDraw…
调用绝对是可行的方法。解决这个问题的最好方法是不要认为使用OpenGL绘制的东西是单独的对象(没有勺子),而只是颜色的补丁,偶然看起来是矩形,盒子,球体,勺子......
使用C ++惯用法实现此目的的一种方法是使用缓冲区对象类,该类在内部管理缓冲区对象中包含的数据块。请记住,缓冲对象本身几乎没有形状,只有将它们用作顶点属性的源才能获得意义。然后你的各个矩形将从这样的缓冲对象实例中分配出来;返回的实例可以传递相对于某个内部偏移的矩形属性'索引(传递给glVertexAttribPointer
的内容);实际上有一个缓冲对象类,一个对象属性视图类(管理属性指针)和对属性视图进行操作的实际几何类是有意义的。
在准备实际的绘图调用时,几何实例将只发出它们各自顶点的实例;将它们连接起来并将其用于glDrawElements
调用。
如果你的几何没有改变那么最好的方法是用一个VBO创建VAO用于renctangle的几何,一个vbo用于你可以绘制的多个矩形的转换和一个用于纹理坐标的vbo,并且实例化你从cpu到gpu删除大量的交通如果值没有改变,也可以尝试缓存制服,并且不要在每次渲染调用时设置它们的值。尝试使用像gltrace这样的工具,看看你是否可以减少不必要的状态变化。收集尽可能多的数据,然后只进行渲染调用。