Comprehensive ctypes-based OpenGL binding for Python providing access to OpenGL, GLU, and GLUT functionality
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Unified array handling system providing seamless integration between OpenGL and various Python array types including NumPy arrays, Python lists, ctypes arrays, and buffer objects. Includes high-performance Vertex Buffer Object (VBO) support for modern graphics programming.
High-performance buffer objects for storing vertex data in GPU memory with automatic memory management and context-aware binding.
class VBO:
"""
Vertex Buffer Object wrapper providing high-performance vertex data storage.
Usage:
vbo = VBO(data)
with vbo:
glVertexPointer(3, GL_FLOAT, 0, vbo)
glDrawArrays(GL_TRIANGLES, 0, len(data))
"""
def __init__(self, data, usage=GL_STATIC_DRAW, target=GL_ARRAY_BUFFER):
"""
Create VBO from array data.
Parameters:
- data: Array-like data (NumPy array, list, etc.)
- usage: Buffer usage hint (GL_STATIC_DRAW, GL_DYNAMIC_DRAW, GL_STREAM_DRAW)
- target: Buffer target (GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER)
"""
def bind(self):
"""Bind VBO to its target."""
def unbind(self):
"""Unbind VBO from its target."""
def delete(self):
"""Delete VBO and free GPU memory."""
def copy(self, array):
"""
Copy data to VBO.
Parameters:
- array: New data to copy to buffer
"""
def __enter__(self):
"""Context manager entry - binds VBO."""
def __exit__(self, exc_type, exc_val, exc_tb):
"""Context manager exit - unbinds VBO."""
def __add__(self, offset: int):
"""
Create VBO offset for sub-arrays.
Parameters:
- offset: Byte offset into buffer
Returns:
VBOOffset object
"""
@property
def data(self):
"""Get original array data."""
@property
def size(self) -> int:
"""Get buffer size in bytes."""
@property
def target(self) -> int:
"""Get buffer target."""
@property
def usage(self) -> int:
"""Get buffer usage hint."""
class VBOOffset:
"""
Represents an offset into a VBO for rendering sub-arrays.
Usage:
vertices = VBO(vertex_data)
normals = vertices + 12 # Offset 12 bytes into buffer
with vertices:
glVertexPointer(3, GL_FLOAT, 24, vertices)
glNormalPointer(GL_FLOAT, 24, normals)
"""
def __init__(self, vbo: VBO, offset: int):
"""
Create VBO offset.
Parameters:
- vbo: Parent VBO object
- offset: Byte offset into buffer
"""Automatic detection and conversion between different array formats with plugin architecture for extensibility.
class ArrayDatatype:
"""
Base class for array format handlers providing unified interface
to different array types (NumPy, ctypes, Python lists, etc.).
"""
@classmethod
def from_param(cls, value):
"""
Convert value to appropriate array representation.
Parameters:
- value: Input data in any supported format
Returns:
Converted array data
"""
@classmethod
def dataPointer(cls, value):
"""
Get memory pointer to array data.
Parameters:
- value: Array data
Returns:
Memory pointer suitable for OpenGL functions
"""
@classmethod
def arraySize(cls, value) -> int:
"""
Get array size in bytes.
Parameters:
- value: Array data
Returns:
Size in bytes
"""
@classmethod
def arrayByteCount(cls, value) -> int:
"""Get total byte count of array."""
@classmethod
def unitSize(cls, value) -> int:
"""Get size of single array element in bytes."""
@classmethod
def dimensions(cls, value) -> tuple:
"""
Get array dimensions.
Returns:
Tuple of dimension sizes
"""
def asArray(value, typeCode=None):
"""
Convert value to array format suitable for OpenGL.
Parameters:
- value: Input data in any supported format
- typeCode: Optional type specification
Returns:
Array in appropriate format for OpenGL operations
"""Seamless NumPy array support with automatic type mapping and memory layout handling.
# NumPy arrays are automatically supported
import numpy as np
# Create vertex data
vertices = np.array([
[0.0, 1.0, 0.0],
[-1.0, -1.0, 0.0],
[1.0, -1.0, 0.0]
], dtype=np.float32)
# Use directly with OpenGL functions
glVertexPointer(3, GL_FLOAT, 0, vertices)
# Or with VBO for better performance
vbo = VBO(vertices)
with vbo:
glVertexPointer(3, GL_FLOAT, 0, vbo)
glDrawArrays(GL_TRIANGLES, 0, len(vertices))Native Python list and tuple support with automatic conversion to appropriate OpenGL formats.
# Python lists work automatically
vertices = [
[0.0, 1.0, 0.0],
[-1.0, -1.0, 0.0],
[1.0, -1.0, 0.0]
]
colors = [
[1.0, 0.0, 0.0], # Red
[0.0, 1.0, 0.0], # Green
[0.0, 0.0, 1.0] # Blue
]
# Use directly with OpenGL
glVertexPointer(3, GL_FLOAT, 0, vertices)
glColorPointer(3, GL_FLOAT, 0, colors)Direct ctypes array support for low-level control and C library integration.
import ctypes
# ctypes arrays
FloatArray = ctypes.c_float * 9
vertex_array = FloatArray(
0.0, 1.0, 0.0, # Vertex 1
-1.0, -1.0, 0.0, # Vertex 2
1.0, -1.0, 0.0 # Vertex 3
)
# Use with OpenGL functions
glVertexPointer(3, GL_FLOAT, 0, vertex_array)Support for Python buffer protocol objects including bytes, bytearray, and memoryview.
# Buffer objects supported
data = bytearray(36) # 9 floats * 4 bytes each
buffer_view = memoryview(data)
# Can be used with OpenGL functions
glBufferData(GL_ARRAY_BUFFER, len(data), data, GL_STATIC_DRAW)Automatic memory management with optional pointer storage for safety and performance control.
# Configuration flags affecting array handling
import OpenGL
# Prevent data copying (raises CopyError if copy would occur)
OpenGL.ERROR_ON_COPY = True
# Store array pointers to prevent garbage collection issues
OpenGL.STORE_POINTERS = True # Default: True
# Enable/disable size checking
OpenGL.ARRAY_SIZE_CHECKING = True # Default: TrueHelper functions for VBO management and memory mapping.
def mapVBO(vbo: VBO, access=GL_READ_WRITE):
"""
Map VBO memory for direct CPU access.
Parameters:
- vbo: VBO object to map
- access: Access mode (GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE)
Returns:
Memory pointer for direct access
Usage:
with vbo:
ptr = mapVBO(vbo, GL_WRITE_ONLY)
# Modify data through ptr
glUnmapBuffer(vbo.target)
"""
class VBOHandler:
"""Format handler for VBO objects in the array system."""Plugin architecture for supporting additional array formats.
class FormatHandler:
"""
Base class for array format plugins.
Allows registration of handlers for custom array types.
"""
def __init__(self, name: str, module: str, types: list,
isOutput: bool = False):
"""
Register format handler.
Parameters:
- name: Handler name
- module: Python module containing handler
- types: List of type names this handler supports
- isOutput: Whether handler can produce output arrays
"""
# Pre-registered handlers
handlers = {
'numpy': 'numpy.ndarray, numpy.core.memmap.memmap, numpy scalar types',
'lists': 'list, tuple',
'ctypes': 'ctypes arrays, parameters, pointers',
'strings': 'str, bytes, unicode (Python 2)',
'numbers': 'int, float, long (Python 2)',
'buffers': 'buffer protocol objects (bytearray, memoryview)',
'vbo': 'VBO, VBOOffset objects'
}import numpy as np
from OpenGL.GL import *
from OpenGL.arrays import vbo
# Create vertex data
vertices = np.array([
[-1.0, -1.0, 0.0],
[ 1.0, -1.0, 0.0],
[ 0.0, 1.0, 0.0]
], dtype=np.float32)
# Create VBO
vertex_buffer = vbo.VBO(vertices)
# Use in render loop
with vertex_buffer:
glEnableClientState(GL_VERTEX_ARRAY)
glVertexPointer(3, GL_FLOAT, 0, vertex_buffer)
glDrawArrays(GL_TRIANGLES, 0, 3)
glDisableClientState(GL_VERTEX_ARRAY)# Interleaved vertex and color data
# Format: [x, y, z, r, g, b, x, y, z, r, g, b, ...]
interleaved_data = np.array([
# Vertex 1: position + color
-1.0, -1.0, 0.0, 1.0, 0.0, 0.0,
# Vertex 2: position + color
1.0, -1.0, 0.0, 0.0, 1.0, 0.0,
# Vertex 3: position + color
0.0, 1.0, 0.0, 0.0, 0.0, 1.0
], dtype=np.float32)
stride = 6 * 4 # 6 floats * 4 bytes per float
vertex_buffer = vbo.VBO(interleaved_data)
with vertex_buffer:
glEnableClientState(GL_VERTEX_ARRAY)
glEnableClientState(GL_COLOR_ARRAY)
# Vertices start at offset 0
glVertexPointer(3, GL_FLOAT, stride, vertex_buffer)
# Colors start at offset 12 bytes (3 floats * 4 bytes)
color_offset = vertex_buffer + 12
glColorPointer(3, GL_FLOAT, stride, color_offset)
glDrawArrays(GL_TRIANGLES, 0, 3)
glDisableClientState(GL_COLOR_ARRAY)
glDisableClientState(GL_VERTEX_ARRAY)# Create dynamic VBO
dynamic_data = np.zeros((100, 3), dtype=np.float32)
vertex_buffer = vbo.VBO(dynamic_data, usage=GL_DYNAMIC_DRAW)
# Update data each frame
def update_vertices(time):
# Modify vertex positions based on time
for i in range(100):
dynamic_data[i] = [
np.sin(time + i * 0.1),
np.cos(time + i * 0.1),
0.0
]
# Copy updated data to VBO
vertex_buffer.copy(dynamic_data)
# In render loop
update_vertices(current_time)
with vertex_buffer:
glVertexPointer(3, GL_FLOAT, 0, vertex_buffer)
glDrawArrays(GL_POINTS, 0, 100)GL_STATIC_DRAW: int # Data rarely changes
GL_DYNAMIC_DRAW: int # Data changes frequently
GL_STREAM_DRAW: int # Data changes every frameGL_ARRAY_BUFFER: int # Vertex attribute data
GL_ELEMENT_ARRAY_BUFFER: int # Index dataGL_READ_ONLY: int
GL_WRITE_ONLY: int
GL_READ_WRITE: intInstall with Tessl CLI
npx tessl i tessl/pypi-pyopengl