管理OpenGL状态机的策略

EdF*_*EdF 14 c++ opengl design-patterns

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

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

目前,我正在遵循"裸体对象"设计理念从单个线程渲染.即.每个图形对象都有一个Render()功能,可以完成绘制工作.这些对象本身可以是其他对象的聚合,或图形基元的聚合.当一个特定的Render()被调用时,它没有关于在它之前调用了什么变换/材料变化的信息(当然是好事).

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

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

更新:13/5/11

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

dat*_*olf 7

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

我没有看到任何坏事.如果可能的话,我甚至会摆脱GLU.

使用其他设置,我在调用glBegin()之前显式设置了任何需要设置的内容,并且没有理所当然.

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

当一个渲染函数对不常见的状态变量进行一些更改时,问题就会蔓延,我开始考虑使用一些RAII来强制撤销范围内所做的所有状态更改.

较旧版本的OpenGL为您提供了属性堆栈,其中包含访问客户端状态的函数glPushAttrib/glPopAttribglPushClientAttrib/glPopClientAttrib.

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

使用OpenGL有时会让我想起很多汇编编程.

这根本不是什么惊喜,因为OpenGL的第一个版本是在假设一些抽象机器(实现)设计的,OpenGL调用它就是那台机器的操作代码.