管理OpenGL状态机的策略

时间:2011-05-12 03:58:43

标签: c++ design-patterns opengl

我目前正在处理OpenGL。我从GLUT开始,但决定"毕业"到SFML库。 SFML实际上提供的GL实用程序甚至比GLUT少,但它是可移植的并提供了一些其他功能。所以它真的只有我,GL和GLU。是的,我是一个惩罚的傻瓜。

我想问一下人们管理矩阵变化,颜色变化,材料变化等方面的策略。

目前我正在使用" Naked Objects"设计理念。即。每个图形对象都有一个Render()函数,可以完成绘制工作。这些对象本身可以是其他对象的聚合,或图形基元的聚合。当一个特定的Render()被调用时,它没有关于在它之前调用了什么变换/材料变化的信息(肯定是好事)。

随着事情的发展,我已经确定了某些策略,比如让每个函数都有希望推送,然后在执行任何转换时弹出矩阵。使用其他设置,我在调用glBegin()之前显式设置了需要设置的任何内容,并且没有理所当然。当一个渲染函数对不太常见的状态变量进行一些更改时,问题就会蔓延,我开始考虑使用一些RAII来强制撤销范围内所做的所有状态更改。使用OpenGL有时会让我想起很多汇编编程。

为了保持这一切,并帮助调试,我发现我实际上正在开发自己的openGL包装器,所以我认为听听其他人使用的策略,或者关于这个主题的想法和考虑因素会很好。或者也许是时候切换到类似场景图库的东西了?

更新:13/5/11

现在看一下使用顶点/普通/颜色数组和VBO的渲染,我决定将所有实际的openGL通信整合到一个单独的模块中。渲染过程包括从我的对象中获取GL独立的空间/材料数据,然后以可解释的格式将所有这些信息传递给openGL。这意味着所有原始数组处理和状态操作将合并到一个区域中。它为渲染过程增加了额外的间接性和一点点计算开销,但这意味着我可以为我的所有数据使用单个VBO /数组,然后一次性传递一次,每帧一次传递给openGL。

2 个答案:

答案 0 :(得分:7)

  

所以它真的只有我,GL和GLU

我认为没什么不好的。如果可能的话,我甚至会摆脱GLU。

  

使用其他设置,我明确设置   以前需要设置的任何东西   调用glBegin()并不采取任何措施   理所当然的。

这也是一个很好的策略,但当然你应该将昂贵的状态开关保持在最低限度。您应该迁移到使用顶点数组和可用的顶点缓冲区对象,而不是立即模式( glBegin / glEnd )。

  

渲染时出现问题   功能使一些变化更少   常见的状态变量,我   开始考虑使用一些RAII   强制执行所有国家的逆转   在范围内进行的更改。

较旧版本的OpenGL为您提供了访问函数 glPushAttrib / glPopAttrib glPushClientAttrib <的属性堆栈/ em> / glPopClientAttrib 表示客户端状态。

但是,是的,较旧的OpenGL版本的巨大状态空间是减少OpenGL-3的主要原因之一;现在通过着色器配置和访问许多固定功能管道状态所涵盖的内容,其中每个着色器封装了几十个OpenGL状态变量值。

  

使用OpenGL有时会让我想起很多   汇编程序设计。

这根本不是一件令人费解的事情,因为OpenGL的第一个版本设计假设一些抽象机器(实现),OpenGL调用它就是那台机器的操作代码。

答案 1 :(得分:2)

首先,尽量不要使用glBegin / glEnd调用进行新开发。它们在OpenGL 3中被弃用,并且在OpenGL ES(iOS,WebOS,Android)中不起作用。相反,使用顶点数组和VBO来合并绘图。

其次,不要编写自己的包装器,而是查看一些最近的开源包装器,看看它们是如何做的。例如,查看可视化库(http://www.visualizationlibrary.com/jetcms/)。它是OpenGL的一个相当薄的包装器,所以值得一看。