### Basic GLUT Window Setup and Event Loop Source: https://context7.com/mcfletch/pyopengl/llms.txt Initializes GLUT, sets up a display window, registers callbacks for display, reshape, keyboard, and timer events, and starts the main event loop. Includes basic OpenGL state setup. ```python import sys from OpenGL.GL import * from OpenGL.GLU import * from OpenGL.GLUT import * angle = [0.0] def display(): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() glRotatef(angle[0], 0, 1, 0) glutWireCube(1.0) glutSwapBuffers() def reshape(w, h): glViewport(0, 0, w, h) glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(45, w / max(h, 1), 0.1, 50.0) glMatrixMode(GL_MODELVIEW) def keyboard(key, x, y): if key == b'\x1b': # ESC glutLeaveMainLoop() def timer(value): angle[0] = (angle[0] + 1.0) % 360.0 glutPostRedisplay() glutTimerFunc(16, timer, 0) # ~60 fps glutInit(sys.argv) glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH) glutInitWindowSize(800, 600) glutCreateWindow(b"Spinning Cube") gglClearColor(0.05, 0.05, 0.05, 1.0) glEnable(GL_DEPTH_TEST) glutDisplayFunc(display) glutReshapeFunc(reshape) glutKeyboardFunc(keyboard) glutTimerFunc(16, timer, 0) glutMainLoop() ``` -------------------------------- ### Install PyOpenGL and Accelerator Source: https://context7.com/mcfletch/pyopengl/llms.txt Install PyOpenGL and its optional C accelerator package from PyPI using pip. ```bash pip install PyOpenGL PyOpenGL_accelerate ``` -------------------------------- ### Framebuffer Objects (FBOs) Setup Source: https://context7.com/mcfletch/pyopengl/llms.txt Provides a unified API for ARB and EXT framebuffer objects. checkFramebufferStatus() raises a GLError if the FBO is incomplete. This example shows basic FBO creation with a color texture and depth renderbuffer attachment. ```python from OpenGL.GL import * from OpenGL.GL.framebufferobjects import * WIDTH, HEIGHT = 1024, 1024 # Create FBO + colour texture attachment + depth renderbuffer fbo = glGenFramebuffers(1) bindFramebuffer(GL_FRAMEBUFFER, fbo) ``` -------------------------------- ### Projection Setup with gluPerspective Source: https://context7.com/mcfletch/pyopengl/llms.txt Demonstrates how to set up a perspective projection matrix using `gluPerspective`. This is typically done when the `GL_PROJECTION` matrix is active. ```APIDOC ## gluPerspective ### Description Sets up a perspective projection matrix. This function is used to create a viewing frustum with a perspective effect, where objects farther away appear smaller. ### Method `gluPerspective(fovy, aspect, zNear, zFar)` ### Parameters - **fovy** (float) - Specifies the field of view angle, in degrees, in the y direction. - **aspect** (float) - Specifies the aspect ratio that determines the field of view in the x direction relative to the y direction. It is the ratio of x width to y height. - **zNear** (float) - Specifies the distance from the viewer to the near clipping plane (always positive). - **zFar** (float) - Specifies the distance from the viewer to the far clipping plane (always positive). ### Request Example ```python from OpenGL.GL import * from OpenGL.GLU import * glMatrixMode(GL_PROJECTION) glLoadIdentity() # Example: 45 degree field of view, 16:9 aspect ratio, near clipping plane at 0.1, far at 1000.0 gluPerspective(45.0, 16/9, 0.1, 1000.0) glMatrixMode(GL_MODELVIEW) ``` ### Response This function modifies the current matrix (typically `GL_PROJECTION`) and does not return a value. ``` -------------------------------- ### Install PyOpenGL for Development Source: https://github.com/mcfletch/pyopengl/blob/master/documentation/using.html Install the checked-out PyOpenGL package into your Python path for active development. ```bash ./setupegg.py develop --install-dir=~/YOUR-WORKING-DIRECTORY-ON-PYTHONPATH-HERE ``` -------------------------------- ### Install PyOpenGL from CVS Source: https://github.com/mcfletch/pyopengl/blob/master/documentation/using.html Use this command to check out the current development version of PyOpenGL from its CVS repository. ```bash cvs -z3 -d:pserver:anonymous@pyopengl.cvs.sourceforge.net:/cvsroot/pyopengl co -P OpenGL-ctypes ``` -------------------------------- ### Core GL Entry Points with Pygame Source: https://context7.com/mcfletch/pyopengl/llms.txt Demonstrates basic OpenGL rendering using PyOpenGL's core GL entry points and Pygame for windowing. Enables error and context checking, sets up rendering state, projection, and draws a simple triangle using immediate mode. ```python import pygame, pygame.display import OpenGL OpenGL.ERROR_CHECKING = True # raise GLError on every GL error (default True) OpenGL.CONTEXT_CHECKING = True # catch calls made without a current context from OpenGL.GL import * from OpenGL.GLU import * pygame.display.init() screen = pygame.display.set_mode((800, 600), pygame.OPENGL | pygame.DOUBLEBUF) pygame.display.set_caption("PyOpenGL Core Demo") # State setup gglClearColor(0.1, 0.1, 0.1, 1.0) g glEnable(GL_DEPTH_TEST) g glEnable(GL_LIGHTING) g glEnable(GL_LIGHT0) # Projection glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(60.0, 800/600, 0.1, 100.0) glMatrixMode(GL_MODELVIEW) glLoadIdentity() gluLookAt(0, 0, 5, 0, 0, 0, 0, 1, 0) # Query state — output buffer allocated automatically, returns Python int/float max_tex_units = glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS) vendor = glGetString(GL_VENDOR).decode() renderer = glGetString(GL_RENDERER).decode() print(f"Renderer: {renderer} ({vendor}), max texture units: {max_tex_units}") # Draw a frame gglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glPushMatrix() glRotatef(45.0, 0.0, 1.0, 0.0) # Immediate-mode triangle (legacy GL 1.x) glBegin(GL_TRIANGLES) gglColor3f(1.0, 0.0, 0.0); glVertex3f(-1.0, -1.0, 0.0) gglColor3f(0.0, 1.0, 0.0); glVertex3f( 1.0, -1.0, 0.0) gglColor3f(0.0, 0.0, 1.0); glVertex3f( 0.0, 1.0, 0.0) glEnd() glPopMatrix() pygame.display.flip() ``` -------------------------------- ### Set up Projection and Modelview Matrices with GLU Source: https://context7.com/mcfletch/pyopengl/llms.txt Configures the OpenGL projection and modelview matrices using GLU functions. Requires importing OpenGL.GL and OpenGL.GLU. ```python from OpenGL.GL import * from OpenGL.GLU import * # ── Projection ────────────────────────────────────────────────────────────── glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(45.0, 16/9, 0.1, 1000.0) # fov_y, aspect, near, far glMatrixMode(GL_MODELVIEW) glLoadIdentity() gluLookAt(0, 3, 8, # eye 0, 0, 0, # center 0, 1, 0) # up ``` -------------------------------- ### Create and Use Framebuffer with Color and Depth Attachments Source: https://context7.com/mcfletch/pyopengl/llms.txt This snippet demonstrates setting up a framebuffer with a color texture and a depth renderbuffer for off-screen rendering. It includes validation, rendering, reading back the result, and cleanup. ```python from OpenGL.GL import * from OpenGL.GLU import * # Assuming WIDTH, HEIGHT, and fbo are defined elsewhere # WIDTH = 800 # HEIGHT = 600 # fbo = glGenFramebuffers(1) # glBindFramebuffer(GL_FRAMEBUFFER, fbo) # Colour attachment colour_tex = glGenTextures(1) bindTexture(GL_TEXTURE_2D, int(colour_tex)) temp_image = (GLubyte * (WIDTH * HEIGHT * 4))() glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp_image) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colour_tex, 0) # Depth attachment depth_rb = glGenRenderbuffers(1) bindRenderbuffer(GL_RENDERBUFFER, depth_rb) glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, WIDTH, HEIGHT) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_rb) # Validate (raises GLError with reason string if incomplete) checkFramebufferStatus() # Render off-screen glViewport(0, 0, WIDTH, HEIGHT) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # ... draw calls here ... # Read back result pixels = glReadPixels(0, 0, WIDTH, HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE) # Restore default framebuffer bindFramebuffer(GL_FRAMEBUFFER, 0) glDeleteFramebuffers(1, [fbo]) glDeleteTextures([colour_tex]) glDeleteRenderbuffers(1, [depth_rb]) ``` -------------------------------- ### Import Basic OpenGL and GLU Functionality Source: https://github.com/mcfletch/pyopengl/blob/master/documentation/using.html Import the core OpenGL and GLU functionalities for general use. This is the standard way to access basic OpenGL commands. ```python from OpenGL.GL import * from OpenGL.GLU import * ``` -------------------------------- ### Initialize EGL Display for Headless Rendering Source: https://context7.com/mcfletch/pyopengl/llms.txt Sets the PYOPENGL_PLATFORM environment variable to 'egl' and obtains the default EGL display, initializing the EGL connection. Useful for server-side or embedded rendering without a window system. ```python import os os.environ['PYOPENGL_PLATFORM'] = 'egl' from OpenGL.EGL import * from OpenGL.GL import * # Obtain the default EGL display display = eglGetDisplay(EGL_DEFAULT_DISPLAY) eglInitialize(display, None, None) ``` -------------------------------- ### Regenerate PyOpenGL Modules Source: https://github.com/mcfletch/pyopengl/blob/master/src/README.md Navigate to the src directory and execute the xml_generate.py script to clone/update the Khronos registry and parse XML files for module generation. ```bash cd src ./xml_generate.py ``` -------------------------------- ### Checking OpenGL Extension Availability and Fallbacks Source: https://context7.com/mcfletch/pyopengl/llms.txt Demonstrates how to check for OpenGL extension support using `hasGLExtension` and create fallback functions with `alternate`. Useful for writing portable OpenGL code. ```python from OpenGL.GL import * from OpenGL.extensions import hasGLExtension, alternate, GLQuerier # Query GL version version = GLQuerier.getVersion() print("GL version tuple:", version) # e.g. (4, 6) # Check for specific extensions if hasGLExtension('GL_ARB_texture_compression'): print("Texture compression available") if hasGLExtension('GL_EXT_texture_filter_anisotropic'): from OpenGL.GL.EXT.texture_filter_anisotropic import GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT max_aniso = glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT) print(f"Max anisotropy: {max_aniso}") # Build a portable multi-draw function that prefers core but accepts EXT from OpenGL.GL.EXT.multi_draw_arrays import glMultiDrawElementsEXT portable_multi_draw = alternate(glMultiDrawElements, glMultiDrawElementsEXT) # Per-version extension init guards (autogenerated in each VERSION module) from OpenGL.GL.VERSION.GL_4_6 import glInitGl46VERSION if glInitGl46VERSION(): print("GL 4.6 available — can use glSpecializeShader") ``` -------------------------------- ### Generate PyOpenGL Documentation Source: https://github.com/mcfletch/pyopengl/blob/master/directdocs/README.md Execute these Python scripts in order to generate the PyOpenGL documentation. This process creates a manual-X.Y directory containing the resulting HTML files. ```bash ./acquireoriginal.py ./samples.py ./references.py ./generate.py ``` -------------------------------- ### Create and Draw Shapes with GLU Quadrics Source: https://context7.com/mcfletch/pyopengl/llms.txt Demonstrates creating a GLU quadric object, setting its properties, and drawing basic shapes like spheres and cylinders. Remember to delete the quadric object when done. ```python from OpenGL.GL import * from OpenGL.GLU import * # ── Quadrics ───────────────────────────────────────────────────────────────── q = gluNewQuadric() gluQuadricNormals(q, GLU_SMOOTH) gluQuadricTexture(q, GL_TRUE) # Draw shapes glColor3f(0.8, 0.3, 0.1) gluSphere(q, radius=1.0, slices=32, stacks=32) glPushMatrix() translatef(3.0, 0.0, 0.0) glColor3f(0.2, 0.7, 0.2) gluCylinder(q, base=0.5, top=0.5, height=2.0, slices=24, stacks=8) glPopMatrix() gluDeleteQuadric(q) ``` -------------------------------- ### Quadric Object Creation and Configuration Source: https://context7.com/mcfletch/pyopengl/llms.txt Shows how to create and configure a quadric object using `gluNewQuadric`, `gluQuadricNormals`, and `gluQuadricTexture`. Quadrics are used for drawing surfaces of revolution like spheres, cylinders, and disks. ```APIDOC ## Quadric Object Management ### Description Functions for creating, configuring, and deleting quadric objects, which are used to render surfaces of revolution. ### Methods - **`gluNewQuadric()`**: Creates a new quadric object. - **`gluQuadricNormals(quadObject, normals)`**: Sets the normal vector computation for the quadric object. - **`normals`**: Can be `GLU_NONE`, `GLU_FLAT`, or `GLU_SMOOTH`. - **`gluQuadricTexture(quadObject, textureCoords)`**: Specifies whether texture coordinates should be generated for the quadric object. - **`textureCoords`**: Can be `GL_FALSE` or `GL_TRUE`. - **`gluDeleteQuadric(quadObject)`**: Deletes the specified quadric object, freeing its resources. ### Request Example ```python from OpenGL.GL import * from OpenGL.GLU import * # Create a quadric object q = gluNewQuadric() # Configure normals to be smooth gluQuadricNormals(q, GLU_SMOOTH) # Enable texture coordinate generation gluQuadricTexture(q, GL_TRUE) # ... use q for drawing ... # Delete the quadric object when done gluDeleteQuadric(q) ``` ### Response These functions manage quadric objects and do not return significant values, other than the quadric object itself from `gluNewQuadric`. ``` -------------------------------- ### Configuring PyOpenGL Global Flags Source: https://context7.com/mcfletch/pyopengl/llms.txt Illustrates setting global configuration flags for PyOpenGL before importing GL sub-modules. These flags control error checking, context checking, logging, and compatibility. ```python import OpenGL from OpenGL.GL import * from OpenGL.error import GLError, NoContext # Error checking (default True) — raises GLError after every GL call # Set to False for production performance OpenGL.ERROR_CHECKING = True # Context checking — raises NoContext when calling GL without a context OpenGL.CONTEXT_CHECKING = True # Full logging — logs every GL call and its arguments; very verbose OpenGL.FULL_LOGGING = False # Use the C-extension accelerators (PyOpenGL_accelerate) if available OpenGL.USE_ACCELERATE = True # Return GL_UNSIGNED_BYTE image data as Python bytes rather than numpy array OpenGL.UNSIGNED_BYTE_IMAGES_AS_STRING = False # Forward-compatible mode — disallow deprecated functions even in compat profile OpenGL.FORWARD_COMPATIBLE_ONLY = False # Now safe to import try: glGetError() except NoContext: print("No current context — expected before window creation") try: glClear(GL_INVALID_VALUE) except GLError as err: print(f"GL error {err.err}: {err}") # err.err == 1281 (GL_INVALID_VALUE) ``` -------------------------------- ### OpenGL.GL.framebufferobjects Source: https://context7.com/mcfletch/pyopengl/llms.txt Provides a unified API for Framebuffer Objects (FBOs), unifying ARB and EXT entry points. `checkFramebufferStatus()` raises a descriptive `GLError` if the FBO is incomplete. ```APIDOC ## `OpenGL.GL.framebufferobjects` — Framebuffer Objects (FBOs) Convenience module that unifies the ARB and EXT framebuffer object entry points into a single consistent API. `checkFramebufferStatus()` raises a descriptive `GLError` if the FBO is incomplete. ### Example ```python from OpenGL.GL import * from OpenGL.GL.framebufferobjects import * WIDTH, HEIGHT = 1024, 1024 # Create FBO + colour texture attachment + depth renderbuffer fbo = glGenFramebuffers(1) bindFramebuffer(GL_FRAMEBUFFER, fbo) # ... (further FBO configuration would go here) ``` ``` -------------------------------- ### Compile and Link Shaders into a Program Source: https://context7.com/mcfletch/pyopengl/llms.txt Links compiled vertex and fragment shaders into a shader program. Validates the program unless validate=False. Individual shaders are deleted after a successful link. Use the program as a context manager for glUseProgram. ```python from OpenGL.GL import * from OpenGL.GL.shaders import compileShader, compileProgram, ShaderLinkError VERT = """ #version 330 core layout(location=0) in vec3 pos; void main() { gl_Position = vec4(pos, 1.0); } """ FRAG = """ #version 330 core out vec4 color; void main() { color = vec4(0.2, 0.6, 1.0, 1.0); } """ try: program = compileProgram( compileShader(VERT, GL_VERTEX_SHADER), compileShader(FRAG, GL_FRAGMENT_SHADER), validate=True, ) except ShaderLinkError as e: print("Link error:", e) raise # Context-manager usage (glUseProgram / glUseProgram(0)) with program: mvp_loc = glGetUniformLocation(program, "mvp") glUniformMatrix4fv(mvp_loc, 1, GL_FALSE, [ 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 # identity ]) glDrawArrays(GL_TRIANGLES, 0, 3) # Manual retrieve/reload for caching compiled binaries fmt, binary = program.retrieve() # returns (GLenum format, bytes-like binary) new_prog = ShaderProgram(glCreateProgram()) new_prog.load(fmt, binary) # reloads from binary cache ``` -------------------------------- ### Import OpenGL Extension Functionality Source: https://github.com/mcfletch/pyopengl/blob/master/documentation/using.html Import specific OpenGL extension modules to access advanced features. Ensure the extension is available before use. ```python from OpenGL.GL.ARB.shader_objects import * from OpenGL.GL.ARB.fragment_shader import * from OpenGL.GL.ARB.vertex_shader import * ``` -------------------------------- ### Create and Populate Vertex Buffer Objects (VBOs) Source: https://context7.com/mcfletch/pyopengl/llms.txt Allocates GPU-side buffer objects and uploads data from Python arrays (NumPy, ctypes, lists). The size argument for glBufferData can be omitted when using arrays. VAOs are used to store vertex attribute configurations. ```python import numpy as np from OpenGL.GL import * vertices = np.array([ # x y z r g b -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, ], dtype=np.float32) # VAO vao = glGenVertexArrays(1) glBindVertexArray(vao) # VBO — size is inferred from the numpy array automatically vbo = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, vbo) glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW) stride = 6 * vertices.itemsize # 6 floats per vertex # Position attribute (location 0) glEnableVertexAttribArray(0) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, ctypes.c_void_p(0)) # Color attribute (location 1) glEnableVertexAttribArray(1) glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, ctypes.c_void_p(3 * vertices.itemsize)) # Draw with program: glDrawArrays(GL_TRIANGLES, 0, 3) # Cleanup glDeleteBuffers(1, [vbo]) glDeleteVertexArrays(1, [vao]) ``` -------------------------------- ### Convert Screen Coordinates to World Coordinates with gluUnProject Source: https://context7.com/mcfletch/pyopengl/llms.txt Uses gluUnProject to transform screen coordinates (x, y, z) into world coordinates. Requires retrieving viewport, modelview, and projection matrices. ```python from OpenGL.GL import * from OpenGL.GLU import * # ── gluUnProject (screen → world coordinates) ──────────────────────────────── viewport = glGetIntegerv(GL_VIEWPORT) # (x, y, w, h) modelview = glGetDoublev(GL_MODELVIEW_MATRIX) projection = glGetDoublev(GL_PROJECTION_MATRIX) win_x, win_y = 400.0, 300.0 win_z = glReadPixelsf(int(win_x), int(win_y), 1, 1, GL_DEPTH_COMPONENT)[0][0] obj_x, obj_y, obj_z = gluUnProject(win_x, win_y, win_z, modelview, projection, viewport) print(f"World coords: ({obj_x:.3f}, {obj_y:.3f}, {obj_z:.3f})") ``` -------------------------------- ### Drawing Shapes with Quadrics Source: https://context7.com/mcfletch/pyopengl/llms.txt Illustrates how to draw basic 3D shapes like spheres and cylinders using the configured quadric object. ```APIDOC ## Drawing Quadric Shapes ### Description Functions to draw specific shapes using a previously created and configured quadric object. ### Methods - **`gluSphere(quadObject, radius, slices, stacks)`**: Draws a sphere. - **`radius`**: The radius of the sphere. - **`slices`**: The number of divisions along the sphere's longitude. - **`stacks`**: The number of divisions along the sphere's latitude. - **`gluCylinder(quadObject, baseRadius, topRadius, height, slices, stacks)`**: Draws a cylinder. - **`baseRadius`**: The radius of the base. - **`topRadius`**: The radius of the top. - **`height`**: The height of the cylinder. - **`slices`**: The number of divisions around the cylinder's circumference. - **`stacks`**: The number of divisions along the cylinder's height. ### Request Example ```python from OpenGL.GL import * from OpenGL.GLU import * q = gluNewQuadric() # ... configure q ... # Draw a sphere glColor3f(0.8, 0.3, 0.1) gluSphere(q, radius=1.0, slices=32, stacks=32) # Draw a cylinder glPushMatrix() translatef(3.0, 0.0, 0.0) glColor3f(0.2, 0.7, 0.2) gluCylinder(q, base=0.5, top=0.5, height=2.0, slices=24, stacks=8) g glPopMatrix() gluDeleteQuadric(q) ``` ### Response These functions render geometry to the current OpenGL buffer and do not return values. ``` -------------------------------- ### Create Context Cleanup Callback Source: https://github.com/mcfletch/pyopengl/blob/master/documentation/using.html Creates a callback function to clean up context-specific storage for the current OpenGL context. This is crucial for preventing memory leaks when contexts are destroyed. ```python from OpenGL import contextdata def cleanupCallback( context=None ): """Create a cleanup callback to clear context-specific storage for the current context""" def callback( context = contextdata.getContext( context ) ): """Clean up the context, assumes that the context will *not* render again!""" contextdata.cleanupContext( context ) return callback ``` -------------------------------- ### Uploading Vertex Data with PyOpenGL Source: https://context7.com/mcfletch/pyopengl/llms.txt Demonstrates uploading vertex data to a buffer using glBufferData. PyOpenGL automatically deduces the byte count from NumPy arrays. ```python from OpenGL.GL import * import numpy # Assume 'positions' is a NumPy array positions = numpy.array([[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]], dtype=numpy.float32) glBufferData(GL_ARRAY_BUFFER, positions, GL_STATIC_DRAW) # Byte count helper byte_count = positions.nbytes print(f"Bytes uploaded: {byte_count}") ``` -------------------------------- ### EGL Off-screen Rendering with OpenGL ES 2 Source: https://context7.com/mcfletch/pyopengl/llms.txt Configures EGL for OpenGL ES 2, creates an off-screen pbuffer surface, and performs basic GL rendering. Ensure EGL display is initialized before use. ```python attribs = [ EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_NONE, ] configs = (EGLConfig * 1)() num_configs = EGLint() eglChooseConfig(display, attribs, configs, 1, num_configs) config = configs[0] # Create an off-screen (pbuffer) surface pbuf_attribs = [EGL_WIDTH, 512, EGL_HEIGHT, 512, EGL_NONE] surface = eglCreatePbufferSurface(display, config, pbuf_attribs) # Create ES 2 context and make current ctx_attribs = [EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE] eglBindAPI(EGL_OPENGL_ES_API) ctx = eglCreateContext(display, config, EGL_NO_CONTEXT, ctx_attribs) eglMakeCurrent(display, surface, surface, ctx) # Now regular GL calls work glClearColor(0.0, 0.5, 1.0, 1.0) glClear(GL_COLOR_BUFFER_BIT) pixels = glReadPixels(0, 0, 512, 512, GL_RGBA, GL_UNSIGNED_BYTE) eglDestroyContext(display, ctx) eglDestroySurface(display, surface) eglTerminate(display) ``` -------------------------------- ### Camera Positioning with gluLookAt Source: https://context7.com/mcfletch/pyopengl/llms.txt Configures the camera's position and orientation in the scene using `gluLookAt`. This function sets up a "viewing transformation" by translating and rotating the coordinates so that all objects are seen from the perspective of an eye in a particular position in world space. ```APIDOC ## gluLookAt ### Description Defines the position and orientation of the viewer. It establishes a coordinate system for the view volume. ### Method `gluLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ)` ### Parameters - **eyeX, eyeY, eyeZ** (float) - The position of the eye point. - **centerX, centerY, centerZ** (float) - The position of the reference point, or target, in three-dimensional space. - **upX, upY, upZ** (float) - The direction of the "up" vector. ### Request Example ```python from OpenGL.GL import * from OpenGL.GLU import * glMatrixMode(GL_MODELVIEW) glLoadIdentity() # Example: Eye at (0, 3, 8), looking at (0, 0, 0), with the up direction as (0, 1, 0) gluLookAt(0, 3, 8, # eye 0, 0, 0, # center 0, 1, 0) # up ``` ### Response This function modifies the current matrix (typically `GL_MODELVIEW`) and does not return a value. ``` -------------------------------- ### Check Availability of ARB Shader Objects Extension Source: https://github.com/mcfletch/pyopengl/blob/master/documentation/using.html Verify if the ARB Shader Objects extension is supported on the current machine before using its functions. This is crucial for compatibility. ```python if not glInitShaderObjectsARB(): raise RuntimeError( """ARB Shader Objects extension is required """ """but not supported on this machine!""" ) ``` -------------------------------- ### glGenTextures, glBindTexture, glTexImage2D Source: https://context7.com/mcfletch/pyopengl/llms.txt Creates a texture object and uploads pixel data. `glTexImage2D` accepts NumPy arrays, PIL images, or `None`. Convenience wrappers like `glReadPixels` are available. ```APIDOC ## `glGenTextures` / `glBindTexture` / `glTexImage2D` — Texture upload and binding Creates a texture object and uploads pixel data. `glTexImage2D` accepts NumPy arrays, PIL images, or `None` (allocate without data). `glReadPixels`, `glReadPixelsub`, and `glReadPixelsf` are convenience wrappers that return appropriately typed arrays without manual buffer allocation. ### Parameters - `target` (GLenum): The texture target (e.g., `GL_TEXTURE_2D`). - `level` (int): The texture level (usually 0 for base level). - `internalformat` (GLenum): The internal format of the texture (e.g., `GL_RGBA`). - `width` (int): The width of the texture. - `height` (int): The height of the texture. - `border` (int): The border width (must be 0). - `format` (GLenum): The pixel format (e.g., `GL_RGBA`). - `type` (GLenum): The data type of the pixel data (e.g., `GL_UNSIGNED_BYTE`). - `pixels` (Buffer-like or None): The pixel data. Can be a NumPy array, PIL image, or `None`. ### Example ```python import numpy as np from OpenGL.GL import * # Upload a 2×2 checkerboard texture pixels = np.array([ [255, 0, 0, 255], # red [ 0, 255, 0, 255], # green [ 0, 0, 255, 255], # blue [255, 255, 0, 255], # yellow ], dtype=np.uint8) tex = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, int(tex)) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexImage2D( GL_TEXTURE_2D, # target 0, # mip level GL_RGBA, # internal format 2, 2, # width, height 0, # border (must be 0) GL_RGBA, # format GL_UNSIGNED_BYTE, pixels, ) glGenerateMipmap(GL_TEXTURE_2D) # Read back pixels from the framebuffer width, height = 800, 600 rgb_bytes = glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE) # returns bytes rgb_array = glReadPixelsub(0, 0, width, height, GL_RGB) # returns uint8 array rgb_float = glReadPixelsf(0, 0, width, height, GL_RGB) # returns float array glDeleteTextures([tex]) ``` ``` -------------------------------- ### NumPy Interoperability with OpenGL Arrays Source: https://context7.com/mcfletch/pyopengl/llms.txt Shows how to use `OpenGL.arrays` for converting Python sequences and NumPy arrays to GL-compatible typed pointers, and pre-allocating output buffers. ```python import numpy as np import ctypes from OpenGL.GL import * from OpenGL.arrays import GLfloatArray, GLubyteArray, arraydatatype # Pre-allocate an output buffer with the correct ctypes type pixel_buf = GLubyteArray.zeros((480, 640, 3)) glReadPixels(0, 0, 640, 480, GL_RGB, GL_UNSIGNED_BYTE, pixel_buf) # Convert a Python list to a typed GL array colour_data = GLfloatArray.asArray([1.0, 0.5, 0.0, 1.0]) print("Element type:", GLfloatArray.getHandler(colour_data)) # NumPy arrays are accepted directly everywhere positions = np.array([[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.5, 1.0, 0.0]], dtype=np.float32) vbo = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, vbo) ``` -------------------------------- ### Screen to World Coordinates with gluUnProject Source: https://context7.com/mcfletch/pyopengl/llms.txt Converts screen coordinates (from mouse clicks or pixel reads) into world coordinates using `gluUnProject`. This is essential for interacting with objects in a 3D scene based on 2D input. ```APIDOC ## gluUnProject ### Description Converts normalized device coordinates (from window coordinates) back into object coordinates. This is useful for tasks like picking objects with the mouse. ### Method `gluUnProject(winX, winY, winZ, modelMatrix, projMatrix, viewport)` ### Parameters - **winX, winY, winZ** (float) - The window coordinates and depth value to unproject. - **modelMatrix** (list/tuple) - The current modelview matrix. - **projMatrix** (list/tuple) - The current projection matrix. - **viewport** (list/tuple) - The current viewport (x, y, width, height). ### Request Example ```python from OpenGL.GL import * from OpenGL.GLU import * # Get current matrices and viewport viewport = glGetIntegerv(GL_VIEWPORT) modelview = glGetDoublev(GL_MODELVIEW_MATRIX) projection = glGetDoublev(GL_PROJECTION_MATRIX) # Example screen coordinates (e.g., from a mouse click) win_x, win_y = 400.0, 300.0 # Read the depth buffer value at the screen coordinate # Note: glReadPixelsf might require specific setup or might not be available in all contexts. # A common alternative is to use glReadPixels with GL_DEPTH_COMPONENT and convert. win_z = glReadPixelsf(int(win_x), int(win_y), 1, 1, GL_DEPTH_COMPONENT)[0][0] # Perform the unprojection obj_x, obj_y, obj_z = gluUnProject(win_x, win_y, win_z, modelview, projection, viewport) print(f"World coords: ({obj_x:.3f}, {obj_y:.3f}, {obj_z:.3f})") ``` ### Response Returns a tuple `(objX, objY, objZ)` representing the calculated world coordinates. ``` -------------------------------- ### OSMesa Off-screen Rendering with PyOpenGL Source: https://context7.com/mcfletch/pyopengl/llms.txt Renders directly into a memory buffer using OSMesa, suitable for CI or server-side image generation. Requires setting the PYOPENGL_PLATFORM environment variable. ```python import os os.environ['PYOPENGL_PLATFORM'] = 'osmesa' from OpenGL.GL import * from OpenGL.GLU import * from OpenGL.osmesa import * from OpenGL import arrays import numpy as np WIDTH, HEIGHT = 400, 400 ctx = OSMesaCreateContext(OSMESA_RGBA, None) buf = arrays.GLubyteArray.zeros((HEIGHT, WIDTH, 4)) # RGBA buffer assert OSMesaMakeCurrent(ctx, buf, GL_UNSIGNED_BYTE, WIDTH, HEIGHT) # Standard GL rendering glClearColor(0.2, 0.2, 0.2, 1.0) glEnable(GL_DEPTH_TEST) glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(-2, 2, -2, 2, -5, 5) glMatrixMode(GL_MODELVIEW) glLoadIdentity() glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glBegin(GL_TRIANGLES) glColor3f(1, 0, 0); glVertex3f(-1, -1, 0) glColor3f(0, 1, 0); glVertex3f( 1, -1, 0) glColor3f(0, 0, 1); glVertex3f( 0, 1, 0) glEnd() glFinish() # buf now contains the rendered RGBA pixels as a NumPy array print("Pixel at centre:", buf[HEIGHT//2, WIDTH//2]) # e.g. [r, g, b, a] # Save as PPM img = np.flipud(buf[:, :, :3]) # flip Y, drop alpha with open("output.ppm", "wb") as f: f.write(f"P6\n{WIDTH} {HEIGHT}\n255\n".encode()) f.write(img.tobytes()) OSMesaDestroyContext(ctx) ``` -------------------------------- ### compileProgram Source: https://context7.com/mcfletch/pyopengl/llms.txt Links compiled shader objects into a ShaderProgram. It validates the program and deletes individual shader objects after a successful link. ShaderProgram supports context-manager protocol for glUseProgram. ```APIDOC ## `OpenGL.GL.shaders.compileProgram` — Link shader stages into a program Links any number of compiled shader objects into a `ShaderProgram` (an `int` subclass). Validates the program against the current GL state unless `validate=False`. Deletes the individual shader objects after a successful link. Raises `ShaderLinkError` or `ShaderValidationError` on failure. `ShaderProgram` supports the context-manager protocol for `glUseProgram`. ### Parameters - `shaders`: A list of compiled shader objects (integers). - `validate` (bool): Whether to validate the program after linking. Defaults to `True`. ### Returns - `ShaderProgram`: An integer subclass representing the linked program. ### Raises - `ShaderLinkError`: If the shader program fails to link. - `ShaderValidationError`: If the shader program fails validation. ### Example ```python from OpenGL.GL import * from OpenGL.GL.shaders import compileShader, compileProgram, ShaderLinkError VERT = """ #version 330 core layout(location=0) in vec3 pos; void main() { gl_Position = vec4(pos, 1.0); } """ FRAG = """ #version 330 core out vec4 color; void main() { color = vec4(0.2, 0.6, 1.0, 1.0); } """ try: program = compileProgram( compileShader(VERT, GL_VERTEX_SHADER), compileShader(FRAG, GL_FRAGMENT_SHADER), validate=True, ) except ShaderLinkError as e: print("Link error:", e) raise # Context-manager usage (glUseProgram / glUseProgram(0)) with program: mvp_loc = glGetUniformLocation(program, "mvp") glUniformMatrix4fv(mvp_loc, 1, GL_FALSE, [ 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 # identity ]) glDrawArrays(GL_TRIANGLES, 0, 3) # Manual retrieve/reload for caching compiled binaries fmt, binary = program.retrieve() # returns (GLenum format, bytes-like binary) new_prog = ShaderProgram(glCreateProgram()) new_prog.load(fmt, binary) # reloads from binary cache ``` ``` -------------------------------- ### Upload and Bind Textures Source: https://context7.com/mcfletch/pyopengl/llms.txt Creates a texture object and uploads pixel data from NumPy arrays, PIL images, or None. glTexImage2D automatically deduces byte count from arrays. glReadPixels variants provide convenience for reading back framebuffer data. ```python import numpy as np from OpenGL.GL import * # Upload a 2×2 checkerboard texture pixels = np.array([ [255, 0, 0, 255], # red [ 0, 255, 0, 255], # green [ 0, 0, 255, 255], # blue [255, 255, 0, 255], # yellow ], dtype=np.uint8) tex = glGenTextures(1) bindTexture(GL_TEXTURE_2D, int(tex)) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexImage2D( GL_TEXTURE_2D, # target 0, # mip level GL_RGBA, # internal format 2, 2, # width, height 0, # border (must be 0) GL_RGBA, # format GL_UNSIGNED_BYTE, pixels, ) glGenerateMipmap(GL_TEXTURE_2D) # Read back pixels from the framebuffer width, height = 800, 600 rgb_bytes = glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE) # returns bytes rgb_array = glReadPixelsub(0, 0, width, height, GL_RGB) # returns uint8 array rgb_float = glReadPixelsf(0, 0, width, height, GL_RGB) # returns float array glDeleteTextures([tex]) ``` -------------------------------- ### Retrieving Transform Feedback Data Source: https://context7.com/mcfletch/pyopengl/llms.txt Shows how to retrieve data from a transform feedback buffer using glGetBufferSubData. Pre-allocates a ctypes float array for the feedback data. ```python import ctypes from OpenGL.GL import * # Transform-feedback output: pre-allocate ctypes float array feedback = (GLfloat * 15)(*([0] * 15)) glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, ctypes.sizeof(feedback), feedback) print("Feedback values:", list(feedback)) ``` -------------------------------- ### Compile GLSL Shaders Source: https://context7.com/mcfletch/pyopengl/llms.txt Compiles GLSL source strings into shader objects for vertex, fragment, or geometry stages. Raises ShaderCompilationError on failure, providing the driver's info-log. ```python from OpenGL.GL import * from OpenGL.GL.shaders import compileShader, ShaderCompilationError VERT_SRC = """ #version 330 core layout(location = 0) in vec3 position; layout(location = 1) in vec2 texCoord; out vec2 vTexCoord; uniform mat4 mvp; void main() { gl_Position = mvp * vec4(position, 1.0); vTexCoord = texCoord; } """ FRAG_SRC = """ #version 330 core in vec2 vTexCoord; out vec4 fragColor; uniform sampler2D tex; void main() { fragColor = texture(tex, vTexCoord); } """ try: vert = compileShader(VERT_SRC, GL_VERTEX_SHADER) frag = compileShader(FRAG_SRC, GL_FRAGMENT_SHADER) print("Shaders compiled successfully:", vert, frag) except ShaderCompilationError as e: print("Compilation failed:", e) # e.args[0] contains the info log, e.args[1] the source, e.args[2] the stage ``` -------------------------------- ### Enable Array Copy Error Checking in PyOpenGL Source: https://github.com/mcfletch/pyopengl/blob/master/documentation/using.html Set OpenGL.ERROR_ON_COPY to True before any other OpenGL imports to raise errors when array data is copied. This helps identify performance bottlenecks. ```python import OpenGL OpenGL.ERROR_ON_COPY = True ``` -------------------------------- ### glGenBuffers, glBindBuffer, glBufferData Source: https://context7.com/mcfletch/pyopengl/llms.txt Allocates GPU-side buffer objects and uploads data from Python arrays. `glBufferData` automatically deduces the byte-count from NumPy arrays, ctypes arrays, or Python lists. ```APIDOC ## `glGenBuffers` / `glBindBuffer` / `glBufferData` — Vertex Buffer Objects (VBOs) Allocates GPU-side buffer objects and uploads data from Python arrays. `glBufferData` accepts NumPy arrays, `ctypes` arrays, or Python lists and deduces the byte-count automatically (the `size` argument may be omitted). The ARB variant (`OpenGL.GL.ARB.vertex_buffer_object`) is also available as a fallback on older hardware. ### Parameters - `target` (GLenum): The target buffer object (e.g., `GL_ARRAY_BUFFER`). - `data` (Buffer-like): The data to upload. Can be a NumPy array, ctypes array, or list. - `usage` (GLenum): The usage hint for the buffer data (e.g., `GL_STATIC_DRAW`). ### Example ```python import numpy as np from OpenGL.GL import * vertices = np.array([ # x y z r g b -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, ], dtype=np.float32) # VAO vao = glGenVertexArrays(1) glBindVertexArray(vao) # VBO — size is inferred from the numpy array automatically vbo = glGenBuffers(1) bindBuffer(GL_ARRAY_BUFFER, vbo) glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW) stride = 6 * vertices.itemsize # 6 floats per vertex # Position attribute (location 0) glEnableVertexAttribArray(0) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, ctypes.c_void_p(0)) # Color attribute (location 1) glEnableVertexAttribArray(1) glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, ctypes.c_void_p(3 * vertices.itemsize)) # Draw # Assuming 'program' is a valid ShaderProgram object from compileProgram # with program: # glDrawArrays(GL_TRIANGLES, 0, 3) # Cleanup glDeleteBuffers(1, [vbo]) glDeleteVertexArrays(1, [vao]) ``` ``` -------------------------------- ### Register Custom Error Checker in PyOpenGL Source: https://github.com/mcfletch/pyopengl/blob/master/documentation/using.html Register an alternate function as the error checker to potentially avoid overhead from context-validity checks, for instance, if a valid context is always present. ```python from OpenGL import error error.ErrorChecker.registerChecker( myAlternateFunction ) ```