如何跨函数调用跟踪OpenGL状态?

时间:2009-08-06 20:35:13

标签: opengl oop

由于OpenGL是一个状态机,我在程序中经常使用glEnable()和glDisable()。我只在开始时选择了几个调用(例如glClearColor),但是大多数其他调用我打开和关闭(如照明,取决于我是渲染模型还是3d文本或gui)。

你如何跟踪状态?你是否经常在每个功能的顶部设置/重置这些东西?这不是很多不必要的开销吗?

例如,当我编写一个新函数时,有时我知道在调用函数时状态会是什么,并且我在函数顶部省略了glEnable或glDisable或其他相关的状态切换调用。其他时候,我只是提前编写函数,并添加了这些东西。所以我的函数最终变得非常凌乱,其中一些修改了OpenGL状态,而其他一些只是做出假设(后来被破坏了,然后我必须回过头来弄清楚为什么某些东西会变黄或为什么另一个东西是颠倒的等等。 )。

如何在面向对象的环境中跨函数跟踪OpenGL?


还与这个问题有关,是如何知道何时使用push和pop,以及何时只设置值。

例如,假设您有一个程序可以绘制一些3D内容,然后绘制一些2D内容。显然,投影矩阵在每种情况下都是不同的。所以你:

  1. 设置3d投影矩阵,绘制3D,设置2d投影矩阵,绘制2d,循环
  2. 在程序中设置一个三维投影矩阵;然后绘制3d,推动矩阵,绘制2d,pop矩阵,循环
  3. 为什么?

3 个答案:

答案 0 :(得分:2)

好问题。想想纹理是如何工作的。有一些疯狂的纹理供OpenGL切换,你需要在绘制每个对象后启用/禁用纹理。您通常会尝试通过一次性绘制具有相同纹理的所有对象来优化此功能,但仍然会有大量的状态切换继续进行。因为这个事实,我尽我所能同时绘制相同状态的所有内容,但我不确定以你的思维方式优化它是否非常重要。

对于3D和2D投影模式之间的推送和弹出,推送和弹出旨在用于分层建模。如果您需要将2D投影放在相对于3D对象的位置,请务必按下矩阵并切换到2D投影模式,然后在完成后弹出。但是,如果您正在编写一个在屏幕上具有恒定位置的2D GUI叠加层,我认为推送和弹出非常重要。

答案 1 :(得分:2)

您可能有兴趣阅读有关场景图库的更多信息。它们旨在从更高级别管理您的图形。他们不能很好地处理所有事情,但他们擅长组织几何体以优化渲染。它们还可以用于基于OpenGL状态对场景进行排序,尽管许多人不这样做。通过对状态进行排序,您可以按顺序渲染几何体,从而减少状态转换。这是关于场景图库的一个很好的概述:

http://www.realityprime.com/articles/scenegraphs-past-present-and-future

答案 2 :(得分:2)

我认为最简单的方法是编写自己的渲染类,包装您正在使用的所有OpenGL状态操作函数,并记录您设置的状态。您需要考虑到更改屏幕分辨率或切换全屏模式将使您当前的OpenGL渲染上下文的状态和数据无效,这意味着在此类事件之后您将必须设置所有状态,重新上载所有纹理和着色器程序等