Skip to content
Search

PyOpenGL

lastmod 2025-02-14created 2024-02-2918 edits

PyOpenGL is the most common cross platform Python binding to OpenGL and related APIs. The binding is created using the standard ctypes library, and is provided under an extremely liberal BSD-style Open-Source license.

Categories

PyOpenGL_accelerate

pip install PyOpenGL PyOpenGL_accelerate

INFORMATION

Note that PyOpenGL_accelerate is fully compatible with PyOpenGL, so you get the performance improvement without modifying existing PyOpenGL code.

PyOpenGL_accelerate can be turned ON/OFF with the USE_ACCELERATE environment variable.

The following is the content of the OpenGL/acceleratesupport.py file:

"""Common code for accelerated modules"""
import logging
from OpenGL import _configflags

needed_version = (3, 1, 6)
_log = logging.getLogger("OpenGL.acceleratesupport")
try:
    import OpenGL_accelerate

    if _configflags.USE_ACCELERATE:
        if OpenGL_accelerate.__version_tuple__ < needed_version:
            _log.warning(
                """Incompatible version of OpenGL_accelerate found, need at least %s found %s""",
                needed_version,
                OpenGL_accelerate.__version_tuple__,
            )
            raise ImportError("""Old version of OpenGL_accelerate""")
        ACCELERATE_AVAILABLE = True
        _log.debug("""OpenGL_accelerate module loaded""")
    else:
        raise ImportError("""Acceleration disabled""")
except ImportError as err:
    _log.info("""No OpenGL_accelerate module loaded: %s""", err)
    ACCELERATE_AVAILABLE = False

_configflags.USE_ACCELERATE is the code that reads the USE_ACCELERATE environment variable.

Environment Variables

  • PYOPENGL_ERROR_CHECKING = True
  • PYOPENGL_ERROR_LOGGING = False
  • PYOPENGL_ERROR_ON_COPY = False
  • PYOPENGL_ARRAY_SIZE_CHECKING = True
  • PYOPENGL_STORE_POINTERS = True
  • PYOPENGL_USE_ACCELERATE = True - Whether to use PyOpenGL_accelerate
  • PYOPENGL_CONTEXT_CHECKING = False
  • PYOPENGL_FULL_LOGGING = False
  • PYOPENGL_ALLOW_NUMPY_SCALARS = False
  • PYOPENGL_UNSIGNED_BYTE_IMAGES_AS_STRING = True
  • PYOPENGL_UNSIGNED_BYTE_IMAGES_AS_STRING = True
  • PYOPENGL_PLATFORM = '...' - Specify the platform

Platforms

PlatformPlugin("nt", "OpenGL.platform.win32.Win32Platform")
PlatformPlugin("darwin", "OpenGL.platform.darwin.DarwinPlatform")
PlatformPlugin("linux2", "OpenGL.platform.glx.GLXPlatform")
PlatformPlugin("linux", "OpenGL.platform.glx.GLXPlatform")
PlatformPlugin("glx", "OpenGL.platform.glx.GLXPlatform")
PlatformPlugin("posix", "OpenGL.platform.glx.GLXPlatform")
PlatformPlugin("x11", "OpenGL.platform.glx.GLXPlatform")  # xdg session type
PlatformPlugin("osmesa", "OpenGL.platform.osmesa.OSMesaPlatform")
PlatformPlugin("egl", "OpenGL.platform.egl.EGLPlatform")
PlatformPlugin("wayland", "OpenGL.platform.egl.EGLPlatform")  # xdg session type
PlatformPlugin(
    "xwayland", "OpenGL.platform.egl.EGLPlatform"
)  # xdg session type, but use egl even though normally you'd expect GLX

You can call something like OpenGL.setPlatform('egl'), or set the PYOPENGL_PLATFORM environment variable.

Example

pip install PyOpenGL PyOpenGL_accelerate glfw

PyOpenGL_accelerate seems to be hardware acceleration.

Sample code:

import glfw
from OpenGL.GL import *
import OpenGL.GL.shaders
import numpy


def main():

    # initialize glfw
    if not glfw.init():
        return

    window = glfw.create_window(800, 600, "My OpenGL window", None, None)

    if not window:
        glfw.terminate()
        return

    glfw.make_context_current(window)
    #            positions        colors
    triangle = [-0.5, -0.5, 0.0, 1.0, 0.0, 0.0,
                 0.5, -0.5, 0.0, 0.0, 1.0, 0.0,
                 0.0,  0.5, 0.0, 0.0, 0.0, 1.0]

    triangle = numpy.array(triangle, dtype = numpy.float32)

    vertex_shader = """
    #version 330
    in vec3 position;
    in vec3 color;
    out vec3 newColor;
    void main()
    {
        gl_Position = vec4(position, 1.0f);
        newColor = color;
    }
    """

    fragment_shader = """
    #version 330
    in vec3 newColor;
    out vec4 outColor;
    void main()
    {
        outColor = vec4(newColor, 1.0f);
    }
    """
    shader = OpenGL.GL.shaders.compileProgram(OpenGL.GL.shaders.compileShader(vertex_shader, GL_VERTEX_SHADER),
                                              OpenGL.GL.shaders.compileShader(fragment_shader, GL_FRAGMENT_SHADER))

    VBO = glGenBuffers(1)
    glBindBuffer(GL_ARRAY_BUFFER, VBO)
    glBufferData(GL_ARRAY_BUFFER, 72, triangle, GL_STATIC_DRAW)

    position = glGetAttribLocation(shader, "position")
    glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, 24, ctypes.c_void_p(0))
    glEnableVertexAttribArray(position)

    color = glGetAttribLocation(shader, "color")
    glVertexAttribPointer(color, 3, GL_FLOAT, GL_FALSE, 24, ctypes.c_void_p(12))
    glEnableVertexAttribArray(color)


    glUseProgram(shader)

    glClearColor(0.2, 0.3, 0.2, 1.0)

    while not glfw.window_should_close(window):
        glfw.poll_events()

        glClear(GL_COLOR_BUFFER_BIT)

        glDrawArrays(GL_TRIANGLES, 0, 3)

        glfw.swap_buffers(window)

    glfw.terminate()

if __name__ == "__main__":
    main()

Rotating cube example

OpenGL with PyOpenGL introduction and creation of Rotating Cube

import pygame
from pygame.locals import *

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

verticies = (
    (1, -1, -1),
    (1, 1, -1),
    (-1, 1, -1),
    (-1, -1, -1),
    (1, -1, 1),
    (1, 1, 1),
    (-1, -1, 1),
    (-1, 1, 1)
    )

edges = (
    (0,1),
    (0,3),
    (0,4),
    (2,1),
    (2,3),
    (2,7),
    (6,3),
    (6,4),
    (6,7),
    (5,1),
    (5,4),
    (5,7)
    )


def Cube():
    glBegin(GL_LINES)
    for edge in edges:
        for vertex in edge:
            glVertex3fv(verticies[vertex])
    glEnd()


def main():
    pygame.init()
    display = (800,600)
    pygame.display.set_mode(display, DOUBLEBUF|OPENGL)

    gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)

    glTranslatef(0.0,0.0, -5)

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        glRotatef(1, 3, 1, 1)
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
        Cube()
        pygame.display.flip()
        pygame.time.wait(10)


main()

Drawing Object

Troubleshooting

__________________ ERROR collecting tester/test_entrypoint.py __________________
tester/test_entrypoint.py:8: in <module>
    from ddrm.entrypoint import main as entrypoint_main
ddrm/entrypoint.py:8: in <module>
    from ddrm.apps import run_app
ddrm/apps/__init__.py:21: in <module>
    from ddrm.apps.player import Player
ddrm/apps/player/__init__.py:10: in <module>
    from OpenGL import GL
/usr/local/lib/python3.11/site-packages/OpenGL/GL/__init__.py:4: in <module>
    from OpenGL.GL.VERSION.GL_1_1 import *
/usr/local/lib/python3.11/site-packages/OpenGL/GL/VERSION/GL_1_1.py:14: in <module>
    from OpenGL.raw.GL.VERSION.GL_1_1 import *
/usr/local/lib/python3.11/site-packages/OpenGL/raw/GL/VERSION/GL_1_1.py:7: in <module>
    from OpenGL.raw.GL import _errors
/usr/local/lib/python3.11/site-packages/OpenGL/raw/GL/_errors.py:4: in <module>
    _error_checker = _ErrorChecker( _p, _p.GL.glGetError )
E   AttributeError: 'NoneType' object has no attribute 'glGetError'

Install libgl1-mesa-dev:

apt-get install -y libgl1-mesa-dev

OpenGL.error.Error: Attempt to retrieve context when no valid context

When running under Wayland on Ubuntu 20.04 or later, the following error may be printed:

pygame-ce 2.4.1 (SDL 2.28.5, Python 3.11.4)
/home/your/Project/ddrm/test.py:13: Warning: PyGame seems to be running through X11 on top of wayland, instead of wayland directly
...
OpenGL.error.Error: Attempt to retrieve context when no valid context

Set the SDL_VIDEO_X11_FORCE_EGL=1 environment variable as follows:

import os
os.environ["SDL_VIDEO_X11_FORCE_EGL"] = "1"

numpy.dtype size changed, may indicate binary incompatibility

('numpy.dtype size changed, may indicate binary incompatibility. Expected 96 from C header, got 88 from PyObject', 1, <OpenGL.platform.baseplatform.glGenTextures object at 0x72b5e17db840>)
Traceback (most recent call last):
  File "/home/your/Project/ddrm/ddrm/apps/__init__.py", line 96, in run_app
    app.start()
  File "/home/your/Project/ddrm/ddrm/apps/player/__init__.py", line 52, in start
    self.on_init()
  File "/home/your/Project/ddrm/ddrm/apps/player/__init__.py", line 73, in on_init
    self._renderer = PygameRenderer()
                     ^^^^^^^^^^^^^^^^
  File "/home/your/Project/ddrm/ddrm/apps/player/renderer.py", line 18, in __init__
    super().__init__()
  File "/home/your/Project/ddrm/.venv/lib/python3.11/site-packages/imgui/integrations/base.py", line 18, in __init__
    self.refresh_font_texture()
  File "/home/your/Project/ddrm/.venv/lib/python3.11/site-packages/imgui/integrations/opengl.py", line 247, in refresh_font_texture
    self._font_texture = gl.glGenTextures(1)
                         ^^^^^^^^^^^^^^^^^^^
  File "src/latebind.pyx", line 39, in OpenGL_accelerate.latebind.LateBind.__call__
  File "src/wrapper.pyx", line 303, in OpenGL_accelerate.wrapper.Wrapper.__call__
  File "src/wrapper.pyx", line 88, in OpenGL_accelerate.wrapper.CArgCalculator.c_call
  File "src/wrapper.pyx", line 69, in OpenGL_accelerate.wrapper.CArgCalculatorElement.c_call
  File "src/wrapper.pyx", line 64, in OpenGL_accelerate.wrapper.CArgCalculatorElement.c_call
  File "src/arraydatatype.pyx", line 355, in OpenGL_accelerate.arraydatatype.SizedOutputOrInput.c_call
  File "src/arraydatatype.pyx", line 224, in OpenGL_accelerate.arraydatatype.ArrayDatatype.c_zeros
  File "src/arraydatatype.pyx", line 69, in OpenGL_accelerate.arraydatatype.HandlerRegistry.c_get_output_handler
  File "src/arraydatatype.pyx", line 80, in OpenGL_accelerate.arraydatatype.HandlerRegistry.c_handler_by_plugin_name
  File "/home/your/Project/ddrm/.venv/lib/python3.11/site-packages/OpenGL/plugins.py", line 18, in load
    return importByName( self.import_path )
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/your/Project/ddrm/.venv/lib/python3.11/site-packages/OpenGL/plugins.py", line 45, in importByName
    module = __import__( ".".join(moduleName), {}, {}, moduleName)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/your/Project/ddrm/.venv/lib/python3.11/site-packages/OpenGL/arrays/numpymodule.py", line 28, in <module>
    from OpenGL_accelerate.numpy_formathandler import NumpyHandler
  File "src/numpy_formathandler.pyx", line 1, in init OpenGL_accelerate.numpy_formathandler
ValueError: ('numpy.dtype size changed, may indicate binary incompatibility. Expected 96 from C header, got 88 from PyObject', 1, <OpenGL.platform.baseplatform.glGenTextures object at 0x72b5e17db840>)

Just remove PyOpenGL_accelerate.

See also

Favorite site

author Zer0 sitemap