pythonopenglpyopengl

PyOpenGL - calling glEnd gives OpenGL error 1282 after modifying imports


I'm trying to follow this tutorial for PyOpenGL, but I get an OpenGL error 1282 when calling glEnd():

import OpenGL
import OpenGL.GL
from OpenGL.GLUT import *
import OpenGL.GLU
from OpenGL.raw.GL.VERSION.GL_1_1 import *
import time

def square():
    glBegin(GL_QUADS)
    glVertex2f(100,100)
    glVertex2f(200,100)
    glVertex2f(200, 200)
    glVertex2f(100, 200)
    glEnd()


def iterate():
    glViewport(0, 0, 500,500)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    glOrtho(0.0, 500, 0.0, 500, 0.0, 1.0)
    glMatrixMode (GL_MODELVIEW)
    glLoadIdentity()

def showScreen():
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glLoadIdentity()
    iterate()
    glColor3f(1.0, 0.0, 3.0)
    square()
    glutSwapBuffers()
    time.sleep(0.017)

glutInit()
glutInitDisplayMode(GLUT_RGBA)
glutInitWindowSize(500,500)
glutInitWindowPosition(0, 0)
wind = glutCreateWindow(b'OpenGL Coding Practice')
glutDisplayFunc(showScreen)
glutIdleFunc(showScreen)
glutMainLoop()

This my requirements.txt:

numpy==2.1.2
PyOpenGl==3.1.7

This is what the terminal showed:

Traceback (most recent call last):
  File "C:\Users\foo\OPENGLProject\.venv\Lib\site-packages\OpenGL\GLUT\special.py", line 130, in safeCall
    return function( *args, **named )
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\foo\OPENGLProject\src\main.py", line 37, in showScreen
    square()
  File "C:\Users\foo\OPENGLProject\src\main.py", line 14, in square
    glEnd()
  File "C:\Users\foo\OPENGLProject\.venv\Lib\site-packages\OpenGL\platform\baseplatform.py", line 415, in __call__
    return self( *args, **named )
           ^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\foo\OPENGLProject\.venv\Lib\site-packages\OpenGL\error.py", line 230, in glCheckError
    raise self._errorClass(
OpenGL.error.GLError: GLError(
    err = 1282,
    description = b'operaci\xf3n no v\xe1lida',
    baseOperation = glEnd,
    cArguments = ()
)
GLUT Display callback <function showScreen at 0x000002BB62CCFEC0> with (),{} failed: returning None GLError(
    err = 1282,
    description = b'operaci\xf3n no v\xe1lida',
    baseOperation = glEnd,
    cArguments = ()
)

I'm using Windows 10 and Python 3.12.3 in a venv.

What could be the cause of this?

As additional notes that might help: I had to manually install freeglut.dll. I didn't install PyOpenGL_accelerate since the installation produced errors.

I also tried to change the glBegin argument to GL_LINES and GL_TRIANGLES, use other methods for glVertex* like glVertex3f, glVertex3d or glVertex3fv and change the number of times glVertex* was called; all giving the same result.


Solution

  • Note that the OpenGL-related imports are different from the ones in the tutorial. The tutorial uses

    from OpenGL.GL import *
    from OpenGL.GLUT import *
    from OpenGL.GLU import *
    

    In particular, adding import OpenGL imports the PyOpenGL's default error checking mechanism, which accompanies every call to the OpenGL library with a call to glCheckError, and raises an exception if an error is found (ref).

    This is fine when using modern OpenGL (typically version >=3.3, using VAOs and VBOs), but runs into a problem when using the legacy interface (glBegin, glEnd). From the documentation:

    GL_INVALID_OPERATION is generated if a command other than glVertex, glColor, glSecondaryColor, glIndex, glNormal, glFogCoord, glTexCoord, glMultiTexCoord, glVertexAttrib, glEvalCoord, glEvalPoint, glArrayElement, glMaterial, glEdgeFlag, glCallList, or glCallLists is executed between the execution of glBegin and the corresponding execution glEnd.

    The problem is that the function glCheckError is not on this list and may not be called here. And hence there is an "invalid operation" error (or operación no válida in your language).

    One way to solve this, naturally, would be to replace the imports in the code of the question by the ones from the tutorial.

    Another way would be to at least not import plain OpenGL and the raw version. The latter provides access to the C-interface and this is currently not necessary. In other words, keep:

    import OpenGL.GL
    from OpenGL.GLUT import *
    import OpenGL.GLU
    

    Just as a demonstration, the error can also be made to go away by disabling the default error checking mechanism. The purple quad will still render:

    import OpenGL
    OpenGL.ERROR_CHECKING = False
    import OpenGL.GL
    from OpenGL.GLUT import *
    import OpenGL.GLU
    from OpenGL.raw.GL.VERSION.GL_1_1 import *