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
Modern OpenGL shader support providing utilities for compiling, linking, and managing vertex and fragment shaders. Includes error handling, uniform management, and integration with PyOpenGL's array system for high-performance graphics programming.
High-level utilities for compiling GLSL shader source code with comprehensive error reporting.
def compileShader(source: str, shaderType) -> int:
"""
Compile GLSL shader source code.
Parameters:
- source: GLSL shader source code string
- shaderType: Shader type (GL_VERTEX_SHADER, GL_FRAGMENT_SHADER, etc.)
Returns:
Compiled shader object identifier
Raises:
ShaderCompilationError: If compilation fails with error details
"""
def compileProgram(*shaders) -> int:
"""
Link compiled shaders into a shader program.
Parameters:
- shaders: Variable number of compiled shader objects
Returns:
Linked shader program identifier
Raises:
ShaderLinkError: If linking fails with error details
"""
class ShaderCompilationError(Exception):
"""
Exception raised when shader compilation fails.
Contains detailed error information from GLSL compiler.
"""
def __init__(self, message: str, shader_type: int, source: str):
"""
Parameters:
- message: Compiler error message
- shader_type: Type of shader that failed
- source: Original shader source code
"""
class ShaderLinkError(Exception):
"""
Exception raised when shader program linking fails.
Contains detailed error information from GLSL linker.
"""Functions for using and managing shader programs with uniform variable support.
def glUseProgram(program: int):
"""
Install shader program as part of rendering state.
Parameters:
- program: Shader program identifier, or 0 to use fixed-function pipeline
"""
def glDeleteShader(shader: int):
"""
Delete shader object.
Parameters:
- shader: Shader object identifier
"""
def glDeleteProgram(program: int):
"""
Delete shader program.
Parameters:
- program: Shader program identifier
"""
def glGetProgramiv(program: int, pname: int) -> int:
"""
Get shader program parameter.
Parameters:
- program: Shader program identifier
- pname: Parameter name (GL_LINK_STATUS, GL_ACTIVE_UNIFORMS, etc.)
Returns:
Parameter value
"""
def glGetShaderiv(shader: int, pname: int) -> int:
"""
Get shader object parameter.
Parameters:
- shader: Shader object identifier
- pname: Parameter name (GL_COMPILE_STATUS, GL_SHADER_TYPE, etc.)
Returns:
Parameter value
"""
def glGetProgramInfoLog(program: int) -> str:
"""
Get shader program information log.
Parameters:
- program: Shader program identifier
Returns:
Information log string (linking errors, warnings, etc.)
"""
def glGetShaderInfoLog(shader: int) -> str:
"""
Get shader object information log.
Parameters:
- shader: Shader object identifier
Returns:
Information log string (compilation errors, warnings, etc.)
"""Uniform variable location and value management for passing data to shaders.
def glGetUniformLocation(program: int, name: str) -> int:
"""
Get uniform variable location.
Parameters:
- program: Shader program identifier
- name: Uniform variable name in shader
Returns:
Uniform location identifier, or -1 if not found
"""
# Scalar uniform functions
def glUniform1f(location: int, v0: float):
"""Set single float uniform value."""
def glUniform2f(location: int, v0: float, v1: float):
"""Set 2-component float uniform value."""
def glUniform3f(location: int, v0: float, v1: float, v2: float):
"""Set 3-component float uniform value."""
def glUniform4f(location: int, v0: float, v1: float, v2: float, v3: float):
"""Set 4-component float uniform value."""
def glUniform1i(location: int, v0: int):
"""Set single integer uniform value."""
def glUniform2i(location: int, v0: int, v1: int):
"""Set 2-component integer uniform value."""
def glUniform3i(location: int, v0: int, v1: int, v2: int):
"""Set 3-component integer uniform value."""
def glUniform4i(location: int, v0: int, v1: int, v2: int, v3: int):
"""Set 4-component integer uniform value."""
# Array uniform functions
def glUniform1fv(location: int, count: int, value: list):
"""
Set array of float uniform values.
Parameters:
- location: Uniform location
- count: Number of elements to modify
- value: Array of float values
"""
def glUniform2fv(location: int, count: int, value: list):
"""Set array of 2-component float uniform values."""
def glUniform3fv(location: int, count: int, value: list):
"""Set array of 3-component float uniform values."""
def glUniform4fv(location: int, count: int, value: list):
"""Set array of 4-component float uniform values."""
def glUniform1iv(location: int, count: int, value: list):
"""Set array of integer uniform values."""
def glUniform2iv(location: int, count: int, value: list):
"""Set array of 2-component integer uniform values."""
def glUniform3iv(location: int, count: int, value: list):
"""Set array of 3-component integer uniform values."""
def glUniform4iv(location: int, count: int, value: list):
"""Set array of 4-component integer uniform values."""
# Matrix uniform functions
def glUniformMatrix2fv(location: int, count: int, transpose: bool, value: list):
"""
Set 2x2 matrix uniform values.
Parameters:
- location: Uniform location
- count: Number of matrices to modify
- transpose: Whether to transpose matrices
- value: Matrix values in column-major order
"""
def glUniformMatrix3fv(location: int, count: int, transpose: bool, value: list):
"""Set 3x3 matrix uniform values."""
def glUniformMatrix4fv(location: int, count: int, transpose: bool, value: list):
"""Set 4x4 matrix uniform values."""Vertex attribute management for modern shader-based rendering.
def glGetAttribLocation(program: int, name: str) -> int:
"""
Get vertex attribute location.
Parameters:
- program: Shader program identifier
- name: Attribute variable name in shader
Returns:
Attribute location identifier, or -1 if not found
"""
def glVertexAttribPointer(index: int, size: int, type: int, normalized: bool,
stride: int, pointer):
"""
Define vertex attribute array.
Parameters:
- index: Attribute location
- size: Components per attribute (1, 2, 3, or 4)
- type: Data type (GL_FLOAT, GL_INT, etc.)
- normalized: Whether to normalize integer values
- stride: Byte offset between attributes
- pointer: Array data or buffer offset
"""
def glEnableVertexAttribArray(index: int):
"""
Enable vertex attribute array.
Parameters:
- index: Attribute location to enable
"""
def glDisableVertexAttribArray(index: int):
"""
Disable vertex attribute array.
Parameters:
- index: Attribute location to disable
"""
def glVertexAttrib1f(index: int, x: float):
"""Set single-component vertex attribute value."""
def glVertexAttrib2f(index: int, x: float, y: float):
"""Set 2-component vertex attribute value."""
def glVertexAttrib3f(index: int, x: float, y: float, z: float):
"""Set 3-component vertex attribute value."""
def glVertexAttrib4f(index: int, x: float, y: float, z: float, w: float):
"""Set 4-component vertex attribute value."""Functions for querying shader and program properties.
def glGetActiveUniform(program: int, index: int) -> tuple:
"""
Get information about active uniform variable.
Parameters:
- program: Shader program identifier
- index: Uniform index (0 to GL_ACTIVE_UNIFORMS-1)
Returns:
Tuple of (size, type, name) where:
- size: Array size (1 for non-arrays)
- type: Variable type (GL_FLOAT, GL_FLOAT_VEC3, etc.)
- name: Variable name string
"""
def glGetActiveAttrib(program: int, index: int) -> tuple:
"""
Get information about active vertex attribute.
Parameters:
- program: Shader program identifier
- index: Attribute index (0 to GL_ACTIVE_ATTRIBUTES-1)
Returns:
Tuple of (size, type, name)
"""
def glGetShaderSource(shader: int) -> str:
"""
Get shader source code.
Parameters:
- shader: Shader object identifier
Returns:
Shader source code string
"""from OpenGL.GL import *
from OpenGL.GL import shaders
import numpy as np
# Vertex shader source
vertex_shader_source = """
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
out vec3 vertexColor;
uniform mat4 transform;
void main() {
gl_Position = transform * vec4(aPos, 1.0);
vertexColor = aColor;
}
"""
# Fragment shader source
fragment_shader_source = """
#version 330 core
in vec3 vertexColor;
out vec4 FragColor;
uniform float alpha;
void main() {
FragColor = vec4(vertexColor, alpha);
}
"""
try:
# Compile shaders
vertex_shader = shaders.compileShader(vertex_shader_source, GL_VERTEX_SHADER)
fragment_shader = shaders.compileShader(fragment_shader_source, GL_FRAGMENT_SHADER)
# Link program
shader_program = shaders.compileProgram(vertex_shader, fragment_shader)
# Clean up shader objects (no longer needed after linking)
glDeleteShader(vertex_shader)
glDeleteShader(fragment_shader)
except shaders.ShaderCompilationError as e:
print(f"Shader compilation failed: {e}")
except shaders.ShaderLinkError as e:
print(f"Shader linking failed: {e}")
# Get uniform locations
transform_loc = glGetUniformLocation(shader_program, "transform")
alpha_loc = glGetUniformLocation(shader_program, "alpha")
# Use shader program
glUseProgram(shader_program)
# Set uniform values
transform_matrix = np.eye(4, dtype=np.float32)
glUniformMatrix4fv(transform_loc, 1, GL_FALSE, transform_matrix)
glUniform1f(alpha_loc, 1.0)# Vertex data with positions and colors
vertices = np.array([
# Positions # Colors
-0.5, -0.5, 0.0, 1.0, 0.0, 0.0, # Bottom left, red
0.5, -0.5, 0.0, 0.0, 1.0, 0.0, # Bottom right, green
0.0, 0.5, 0.0, 0.0, 0.0, 1.0 # Top center, blue
], dtype=np.float32)
from OpenGL.arrays import vbo
# Create VBO
vertex_buffer = vbo.VBO(vertices)
# Setup vertex attributes
with vertex_buffer:
# Position attribute (location 0)
glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * 4, vertex_buffer)
# Color attribute (location 1)
glEnableVertexAttribArray(1)
color_offset = vertex_buffer + 12 # Offset 3 floats * 4 bytes
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * 4, color_offset)
# Draw triangle
glDrawArrays(GL_TRIANGLES, 0, 3)
# Cleanup
glDisableVertexAttribArray(0)
glDisableVertexAttribArray(1)import math
import time
# Animation loop
start_time = time.time()
def render_frame():
current_time = time.time() - start_time
# Animated rotation matrix
angle = current_time * 2.0 # 2 radians per second
cos_a = math.cos(angle)
sin_a = math.sin(angle)
rotation_matrix = np.array([
[cos_a, -sin_a, 0.0, 0.0],
[sin_a, cos_a, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 1.0]
], dtype=np.float32)
# Update uniform
glUseProgram(shader_program)
glUniformMatrix4fv(transform_loc, 1, GL_FALSE, rotation_matrix)
# Animated alpha
alpha = (math.sin(current_time * 3.0) + 1.0) * 0.5 # 0.0 to 1.0
glUniform1f(alpha_loc, alpha)
# Render geometry
render_triangle()def safe_compile_shader(source, shader_type):
try:
return shaders.compileShader(source, shader_type)
except shaders.ShaderCompilationError as e:
print(f"Compilation Error in {shader_type}:")
print(f"Error: {e}")
print("Source code:")
for i, line in enumerate(source.split('\n'), 1):
print(f"{i:3}: {line}")
return None
def safe_link_program(*shader_objects):
try:
return shaders.compileProgram(*shader_objects)
except shaders.ShaderLinkError as e:
print(f"Linking Error: {e}")
return NoneGL_VERTEX_SHADER: int
GL_FRAGMENT_SHADER: int
GL_GEOMETRY_SHADER: int # OpenGL 3.2+
GL_TESS_CONTROL_SHADER: int # OpenGL 4.0+
GL_TESS_EVALUATION_SHADER: int # OpenGL 4.0+
GL_COMPUTE_SHADER: int # OpenGL 4.3+GL_COMPILE_STATUS: int
GL_DELETE_STATUS: int
GL_INFO_LOG_LENGTH: int
GL_SHADER_SOURCE_LENGTH: int
GL_SHADER_TYPE: intGL_LINK_STATUS: int
GL_VALIDATE_STATUS: int
GL_ACTIVE_UNIFORMS: int
GL_ACTIVE_ATTRIBUTES: int
GL_ACTIVE_UNIFORM_MAX_LENGTH: int
GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: intGL_FLOAT: int
GL_FLOAT_VEC2: int
GL_FLOAT_VEC3: int
GL_FLOAT_VEC4: int
GL_INT: int
GL_INT_VEC2: int
GL_INT_VEC3: int
GL_INT_VEC4: int
GL_BOOL: int
GL_BOOL_VEC2: int
GL_BOOL_VEC3: int
GL_BOOL_VEC4: int
GL_FLOAT_MAT2: int
GL_FLOAT_MAT3: int
GL_FLOAT_MAT4: int
GL_SAMPLER_2D: int
GL_SAMPLER_CUBE: intInstall with Tessl CLI
npx tessl i tessl/pypi-pyopengl