什么时候应该调用glGetError?

16

glLoadIdentity表示:

如果在执行glBegin和相应的glEnd之间执行glLoadIdentity,则会生成GL_INVALID_OPERATION

但是GL_INVALID_OPERATION是由glGetError返回的标志。

我的问题是,我们应该在什么时候调用glGetError(以便知道我们是否按正确的顺序调用opengl)?


1
注意:glBeginglEnd已经被弃用。 - patryk.beza
3个回答

22

我不确定你的问题是关于在glBegin/End中何时可以调用glGetError,还是更一般性的关于glGetError用法的问题。因此,我将回答两个问题。

在glBegin和glEnd之间,你能做的事情非常有限。这是故意设计的,因为你将GL置于一个非常特定的模式中 - 在绘制过程中。因此,任何与每个顶点属性不直接相关的内容都是无效的。即使在这种上下文中调用glGetError也是无效的。试想一下glBegin+所有在它们之间调用的GL命令+glEnd实际上是对GL的单次绘制调用,这有助于更好地了解GL的操作方式。

现在,如果你遵循简单的规则,只调用属性方法(如glNormal、glTexCoord、glColor、glSecondaryColor、glIndex、glMultiTexCoord、glVertexAttrib、glVertex及其他几种方法),那么你永远不会在Begin/End对中触发GL错误。任何其他方法都会触发错误。(哦...嗯,glMaterial有点例外。它可以工作,但使用已经不再推荐了)

如果你的问题是当错误在Begin/End对内部被触发时,何时可以调用glGetError,ChrisF在评论中回答:在glEnd调用之后。

更广义地说,将glGetError仅用作调试工具。我的个人偏见有两个方面:

  • 每帧检查一次glGetError以确保没有错误
  • 使用宏包装大多数GL调用,以检查GL错误代码,并仅在每帧检查失败时打开它。

当然,由于属性方法可以在Begin/End对外部被调用,因此正确使用它们有点棘手。但是在实践中,这些方法从未失败,因此我不费心去宏检查它们。

一则有趣的小知识:GL API最初是设计成客户端实现可能不知道调用点是否出现错误。例如,如果GL实际上是在远程计算机上实现的(就像在SGI时代),对于使用错误目标调用glTexEnv等函数,可以将其添加到命令缓冲区中,并且此时不会记录任何错误。

然后,如果您调用了glGetError,则客户端必须刷新命令缓冲区到GL服务器,等待缓冲的命令被处理,获取错误代码并返回适当的错误代码给应用程序。

如果这听起来很繁重,那是因为确实如此。顺便说一下,这也是为什么不每次调用都返回错误代码的主要原因,以及为什么只考虑调用glGetError进行调试。如今,大多数GL实现都在同一个进程中处理所有状态管理,因此正如我所说,对于大多数用户来说这只是个小细节。

最后提醒一下,每当我谈到Begin/End时,我都觉得需要指出您可能根本不应该使用它。这是使用GL进行绘制的性能最差的方式。


4
通常情况下,在每个其他的gl...调用之后,应该调用glGetError,因为该调用的一个效果是从堆栈中清除错误(来自MSDN):

当发生错误时,错误标志被设置为适当的错误代码值。在调用glGetError、返回错误代码并将标志重置为GL_NO_ERROR之前,不会记录任何其他错误。

但是,如果您在glBeginglEnd调用中包装了调用,则应在glEnd之后调用glError。这应该会返回正确的错误代码(如果有错误),并清除错误堆栈。

然而,如果在glBegin和glEnd调用之间调用glGetError,则会生成GL_INVALID_OPERATION错误。因此,不能在每个OpenGL调用后立即调用glGetError。 - Mr. Berna
啊 - 我误解了。如果您的调用被包含在 glBeginglEnd 中,请在 glEnd 后调用 glError - ChrisF

3
有些编码哲学认为每个程序都要检查每种可能的错误,并适当处理这些错误。但是,遵循这些哲学需要大量的额外代码,可能会显著减慢程序运行速度。实践中,我只在诊断问题时使用glGetError,或者编写一些可能失败并且有适当操作的代码。
在第一种情况下,诊断问题时,我使用两种策略之一。因为OpenGL直到调用glGetError时才记录新错误,所以我可以在主循环中每次检查错误一次。这告诉我第一个错误,然后我追踪并希望修复它。另一种策略是在我缩小范围到某些有问题的代码时使用的,但我不确定哪个调用引起了问题。在glBegin ... glEnd块外的每个gl...调用后,我将调用glGetError,并报告任何错误。这将告诉我哪个gl...调用导致了问题,并希望开始解决问题的路径。
在第二种情况下,为可能出现的错误进行防御性编程,我将调用glGetError来清除错误标志,进行其他gl...调用,然后调用glGetError。然后我采取必要的措施来处理glGetError报告的任何内容。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接