opengl tao-framework

opengl - ¿Cuándo debería uno llamar a glGetError?



tao-framework (3)

Algunas filosofías de codificación esperan que cada programa compruebe todos los errores posibles y los maneje adecuadamente. Sin embargo, seguir una de esas filosofías requiere una gran cantidad de código adicional y puede ralentizar significativamente un programa. En la práctica, solo uso glGetError cuando estoy diagnosticando un problema, o escribo un código que tiene una posibilidad significativa de fallar y una acción apropiada después del error.

En el primer caso, al diagnosticar un problema, utilizo una de dos estrategias. Debido a que OpenGL no registra nuevos errores hasta que se llama a glGetError, puedo verificar los errores una vez cada vez a través de mi bucle principal. Eso me dice el primer error, que luego busco, y espero que solucione. La otra estrategia que utilizo cuando he reducido a un código problemático, pero no estoy seguro de qué llamada está causando el problema. Después de cada gl ... llamar fuera de un glBegin. . . bloque glEnd Llamaré a glGetError e informaré cualquier error. Esto me dirá exactamente qué llamada de gl ... está causando el problema, y ​​espero que empiece en el camino hacia una solución.

En el segundo caso, programando defensivamente un error probable, llamaré a glGetError para borrar el indicador de error, hacer mis otras llamadas de gl ..., luego llamar a glGetError. Luego tomo todas las medidas necesarias para lidiar con los informes de glGetError.

glLoadIdentity dice

GL_INVALID_OPERATION se genera si se ejecuta glLoadIdentity entre la ejecución de glBegin y la ejecución correspondiente de glEnd .

Pero GL_INVALID_OPERATION es una glGetError devuelta por glGetError .

Mi pregunta es, ¿cuándo deberíamos llamar a glGetError (para saber si estamos llamando a opengl en la secuencia correcta)?


No estoy seguro si su pregunta es sobre cuándo puede llamar a glGetError si está dentro de glBegin / End o si es una pregunta más general sobre el uso de glGetError en general. Así que voy a responder a las dos.

Lo que puede hacer entre glBegin y glEnd es muy limitado. Esto es a propósito, ya que pone el GL en un modo muy específico, en medio de un sorteo. Como tal, cualquier cosa que no se relacione directamente con los atributos por vértice es simplemente inválida. Incluso un glGetError no es válido en ese contexto. Pruebe y piense en glBegin + todas las llamadas GL entre + glEnd como una única llamada de Draw al GL, que ayuda a acercarse a lo que realmente hace el GL.

Ahora, nunca debería realmente tener un error de GL activado dentro del par Begin / End si se adhiere a la regla simple para llamar solo a los métodos de atributo (glNormal, glTexCoord, glColor, glSecondaryColor, glIndex, glMultiTexCoord, glVertexAttrib, glVertex y un par más ). Cualquier otra cosa provocará un error. (err ... bueno, glMaterial es un poco una excepción. Funciona, pero su uso ha sido desaconsejado)

Si su pregunta es cuándo puede llamar a glGetError cuando el error se activó dentro de un par de Inicio / Fin, ChrisF respondió en un comentario: después de la llamada a GlEnd.

Ahora, en un sentido más amplio, use glGetError solo como una herramienta de depuración. Mi sesgo personal es doble:

  • compruebe glGetError una vez por fotograma para asegurarse de que no haya ningún error
  • envuelva la mayoría de las llamadas GL con una macro que puede verificar el código de error de GL y enciéndalo solo cuando la verificación por trama falla.

Por supuesto, dado que los métodos de atributo se pueden llamar fuera de un par de Inicio / Fin, es un poco difícil hacerlos bien. Pero en la práctica, esos métodos nunca fallan de todos modos, por lo que no me molesto en verificarlos en macro.

Un dato curioso: la API de GL se diseñó originalmente para que la implementación del cliente no pudiera saber si hubo un error en el sitio de la llamada. Por ejemplo, si el GL se implementó realmente en una máquina remota (como en los días de SGI), una llamada a, por ejemplo, glTexEnv con un objetivo que no sea GL_TEXTURE_ENV podría simplemente agregarse al búfer de comandos, y no se registraría ningún error en ese punto .

Si luego llamaba a glGetError, el lado del cliente tendría que vaciar el búfer de comandos en el servidor de GL, esperar a que se procesen los comandos que están en búfer, recuperar el código de error y devolver el código de error apropiado a la aplicación.

Si esto suena pesado, es porque lo fue. Esta fue la razón principal por la que no todas las llamadas devolvían un código de error, por cierto, y por qué llamar a glGetError solo se consideraba correcto para fines de depuración. En estos días, la mayoría de las implementaciones de GL están manejando toda la administración del estado en el mismo proceso, por lo que como dije, es realmente trivial para la mayoría de los usuarios.

Por último, cada vez que hablo de Begin / End, siento que debo decir que probablemente debería mirar para no usarlo en absoluto. Se trata de la peor manera de dibujar con GL.


Normalmente, debe llamar a glGetError después de cada otra llamada gl... ya que uno de los efectos de la llamada es eliminar el error de la pila ( de la MSDN ):

Cuando se produce un error, el indicador de error se establece en el valor de código de error adecuado. No se registran otros errores hasta que se llama a glGetError, se devuelve el código de error y se restablece el indicador a GL_NO_ERROR.

Sin embargo, si tiene llamadas envueltas en glBegin y glEnd llame a glError después del glEnd . Esto debería devolverle el código de error correcto (si lo hubiera) y borrar la pila de errores.