opengl.py

lunaengine/backend/opengl.py

OpenGL-based hardware-accelerated renderer for LunaEngine
- GPU-accelerated particles via instancing (CPU physics)
- Full filter system (post-processing)
- 2D drawing primitives (lines, circles, polygons, etc.)
- Rounded rectangles with per-corner radii
- Texture and surface rendering

This version uses the reliable CPU particle system and only uses OpenGL
for rendering - no compute shaders, no GPU physics.

Shader files are now loaded from lunaengine/assets/shaders/ by default.
Users can add custom shader search paths via set_shader_folder().

class FilterType

Description

Enumeration of all available post-processing filter types.

Attributes
NONE: Any = 'none'
VIGNETTE: Any = 'vignette'
BLUR: Any = 'blur'
SEPIA: Any = 'sepia'
GRAYSCALE: Any = 'grayscale'
INVERT: Any = 'invert'
TEMPERATURE_WARM: Any = 'temperature_warm'
TEMPERATURE_COLD: Any = 'temperature_cold'
NIGHT_VISION: Any = 'night_vision'
CRT: Any = 'crt'
PIXELATE: Any = 'pixelate'
BLOOM: Any = 'bloom'
EDGE_DETECT: Any = 'edge_detect'
EMBOSS: Any = 'emboss'
SHARPEN: Any = 'sharpen'
POSTERIZE: Any = 'posterize'
NEON: Any = 'neon'
RADIAL_BLUR: Any = 'radial_blur'
FISHEYE: Any = 'fisheye'
TWIRL: Any = 'twirl'
Methods

No methods defined.

class FilterRegionType

Description

Defines the shape/region where a filter is applied.

Attributes
FULLSCREEN: Any = 'fullscreen'
RECTANGLE: Any = 'rectangle'
CIRCLE: Any = 'circle'
Methods

No methods defined.

class Filter

Description

Represents a post-processing filter with configurable region and intensity.

Attributes:
   filter_type (FilterType): The type of effect to apply.
   intensity (float): Strength of the effect (0.0 to 1.0).
   region_type (FilterRegionType): Shape of the affected area.
   region_pos (Tuple[float, float]): Position (top‑left for rect, center for circle).
   region_size (Tuple[float, float]): Width and height of rectangular region.
   radius (float): Radius for circular regions.
   feather (float): Edge softness in pixels.
   blend_mode (str): How the filter blends with the background (e.g., "normal").
   enabled (bool): Whether this filter is active.
   time (float): Accumulated time for animated filters.

Methods
def __init__(self: Any, filter_type: FilterType = FilterType.NONE, intensity: float = 1.0, region_type: FilterRegionType = FilterRegionType.FULLSCREEN, region_pos: Tuple[float, float] = (0, 0), region_size: Tuple[float, float] = (100, 100), radius: float = 50.0, feather: float = 10.0, blend_mode: str = 'normal') -> Any
Initialize a filter with all parameters.

Args:
   filter_type: Type of filter effect.
   intensity: Filter strength (0.0 to 1.0).
   region_type: Shape of filter region.
   region_pos: Position of region (top-left for rect, center for circle).
   region_size: Size of region (width, height).
   radius: Radius for circular regions.
   feather: Edge softness in pixels.
   blend_mode: How filter blends with background.
def update(self: Any, dt: float) -> None
Update filter for animation (e.g., time‑based effects).
def copy(self: Any) -> Filter
Create a deep copy of this filter.

class ShaderProgram

Description

Base shader program that loads from combined shader files using macros.

The shader source is taken from one of these (in order of priority):
 1. A dedicated file named '<shader_name>.vert' (or .frag/.geom) in the shader folder.
 2. A combined file 'shaders.vert' (or .frag/.geom) with a #define for the shader name.
 3. A raw string passed directly (if it contains '#version').

This allows both compact distribution and per‑shader overrides.

Methods
def __init__(self: Any, shader_name: str, has_geometry: bool = False) -> Any
Args:
   shader_name: e.g., 'particle', 'simple', 'texture', 'filter', 'rounded_rect', 'depth'
   has_geometry: True if this shader uses a geometry stage.
def _load_source(self: Any, stage: str) -> Optional[str]
Load source for a given stage ('vert', 'frag', 'geom').
Returns the source code string, or None if not found.
def _get_uniform_location(self: Any, name: str) -> int
No documentation
def _create_program(self: Any, vertex_source: str, fragment_source: str, geometry_source: Optional[str] = None) -> None
No documentation
def use(self: Any) -> None
No documentation
def unuse(self: Any) -> None
No documentation
def _setup_geometry(self: Any) -> None
Override in subclasses.

class ParticleShader

Description

No documentation

Methods
def __init__(self: Any) -> Any
No documentation
def _setup_geometry(self: Any) -> None
No documentation

class SimpleShader

Description

No documentation

Methods
def __init__(self: Any) -> Any
No documentation
def _setup_geometry(self: Any) -> None
No documentation

class TextureShader

Description

No documentation

Methods
def __init__(self: Any) -> Any
No documentation
def _setup_geometry(self: Any) -> None
No documentation

class RoundedRectShader

Description

No documentation

Methods
def __init__(self: Any) -> Any
No documentation
def _setup_geometry(self: Any) -> None
No documentation

class FilterShader

Description

No documentation

Methods
def __init__(self: Any) -> Any
No documentation
def _setup_geometry(self: Any) -> None
No documentation

class MaskShader

Description

No documentation

Methods
def __init__(self: Any) -> Any
No documentation
def _setup_geometry(self: Any) -> None
No documentation

class DepthShader

Description

No documentation

Methods
def __init__(self: Any) -> Any
No documentation
def _setup_geometry(self: Any) -> None
No documentation

class OpenGLRenderer

Description

Main hardware‑accelerated renderer for LunaEngine.

Attributes
camera_position: Any = pygame.math.Vector2(0, 0)
Methods
def __init__(self: Any, width: int, height: int) -> Any
No documentation
def get_opengl_version(self: Any) -> str
No documentation
def set_text_cache_timeout(self: Any, seconds: float) -> None
No documentation
def get_cache_usage(self: Any, target: str = 'all', humanize: bool = False) -> Any
No documentation
def max_particles(self: Any) -> int
No documentation
def max_particles(self: Any, value: int) -> None
No documentation
def initialize(self: Any) -> bool
No documentation
def _initialize_filter_framebuffer(self: Any) -> bool
No documentation
def add_filter(self: Any, filter_obj: Filter) -> None
No documentation
def remove_filter(self: Any, filter_obj: Filter) -> None
No documentation
def clear_filters(self: Any) -> None
No documentation
def create_quick_filter(self: Any, filter_type: FilterType, intensity: float = 1.0, x: float = 0, y: float = 0, width: float = None, height: float = None, radius: float = 50.0, feather: float = 10.0) -> Filter
No documentation
def apply_vignette(self: Any, intensity: float = 0.7, feather: float = 100.0) -> Filter
No documentation
def apply_blur(self: Any, intensity: float = 0.5, x: float = 0, y: float = 0, width: float = None, height: float = None) -> Filter
No documentation
def apply_sepia(self: Any, intensity: float = 1.0) -> Filter
No documentation
def apply_grayscale(self: Any, intensity: float = 1.0) -> Filter
No documentation
def apply_invert(self: Any, intensity: float = 1.0) -> Filter
No documentation
def apply_warm_temperature(self: Any, intensity: float = 0.5) -> Filter
No documentation
def apply_cold_temperature(self: Any, intensity: float = 0.5) -> Filter
No documentation
def apply_night_vision(self: Any, intensity: float = 0.9) -> Filter
No documentation
def apply_crt_effect(self: Any, intensity: float = 0.8) -> Filter
No documentation
def apply_pixelate(self: Any, intensity: float = 0.7) -> Filter
No documentation
def apply_bloom(self: Any, intensity: float = 0.5) -> Filter
No documentation
def apply_edge_detect(self: Any, intensity: float = 0.8) -> Filter
No documentation
def apply_emboss(self: Any, intensity: float = 0.7) -> Filter
No documentation
def apply_sharpen(self: Any, intensity: float = 0.5) -> Filter
No documentation
def apply_posterize(self: Any, intensity: float = 0.6) -> Filter
No documentation
def apply_neon(self: Any, intensity: float = 0.7) -> Filter
No documentation
def apply_radial_blur(self: Any, intensity: float = 0.5) -> Filter
No documentation
def apply_fisheye(self: Any, intensity: float = 0.4) -> Filter
No documentation
def apply_twirl(self: Any, intensity: float = 0.3) -> Filter
No documentation
def apply_circular_grayscale(self: Any, center_x: float, center_y: float, radius: float = 100.0, intensity: float = 1.0) -> Filter
No documentation
def apply_rectangular_blur(self: Any, x: float, y: float, width: float, height: float, intensity: float = 0.5) -> Filter
No documentation
def begin_frame(self: Any) -> None
No documentation
def end_frame(self: Any) -> None
No documentation
def _apply_filters(self: Any) -> None
No documentation
def get_surface(self: Any) -> pygame.Surface
No documentation
def set_surface(self: Any, surface: Optional[pygame.Surface]) -> None
No documentation
def _surface_to_texture(self: Any, surface: pygame.Surface) -> int
No documentation
def _surface_to_texture_cached(self: Any, surface: pygame.Surface, rect: Optional[pygame.Rect] = None, dest: Optional[pygame.Rect] = None, flags: int = 0) -> int
No documentation
def _convert_color(self: Any, color: Any) -> Any
No documentation
def _read_texture_pixel(self: Any, tex_id: int, x: int = 0, y: int = 0) -> Tuple[int, int, int, int]
Read a single pixel from an OpenGL texture (for debugging).
Returns (R, G, B, A) as integers 0-255.
def enable_scissor(self: Any, x: Any, y: Any, width: Any, height: Any) -> Any
No documentation
def disable_scissor(self: Any) -> Any
No documentation
def draw_rect(self: Any, x: Any, y: Any, width: Any, height: Any, color: Any = None, fill: Any = True, pivot: Any = (0.0, 0.0), border_width: Any = 1, surface: Any = None, corner_radius: Any = 0, border_color: Any = None, style: Optional[Dict[str, Any]] = None) -> Any
No documentation
def _draw_rect_fast(self: Any, x: Any, y: Any, width: Any, height: Any, color: Any, fill: Any = True, border_width: Any = 1, corner_radius: Any = 0, border_color: Any = None) -> Any
No documentation
def _draw_outline_rect(self: Any, x: Any, y: Any, width: Any, height: Any, color: Any, border_width: Any, radii: Any) -> Any
No documentation
def _draw_sharp_rect(self: Any, x: Any, y: Any, width: Any, height: Any, color: Any, fill: Any = True, border_width: Any = 1) -> Any
No documentation
def _draw_rounded_rect(self: Any, x: Any, y: Any, w: Any, h: Any, color: Any, fill: Any = True, border_width: Any = 1, radii: Any = (0, 0, 0, 0)) -> Any
No documentation
def draw_isosceles_triangle(self: Any, x: Any, y: Any, width: Any, height: Any, color: Any = None, fill: Any = True, border_width: Any = 1, border_color: Any = None, style: Optional[Dict[str, Any]] = None) -> Any
No documentation
def draw_equilateral_triangle(self: Any, x: Any, y: Any, width: Any, color: Any = None, fill: Any = True, border_width: Any = 1, border_color: Any = None, style: Optional[Dict[str, Any]] = None) -> Any
No documentation
def draw_line(self: Any, start_x: Any, start_y: Any, end_x: Any, end_y: Any, color: Any, width: Any = 2, surface: Any = None) -> Any
No documentation
def _draw_thick_line(self: Any, x1: Any, y1: Any, x2: Any, y2: Any, color: Any, width: Any) -> Any
No documentation
def draw_lines(self: Any, points: Any, color: Any, width: Any = 2, surface: Any = None) -> Any
No documentation
def draw_circle(self: Any, center_x: Any, center_y: Any, radius: Any, color: Any = None, fill: Any = True, border_width: Any = 1, surface: Any = None, pivot: Any = (0.5, 0.5), style: Optional[Dict[str, Any]] = None) -> Any
No documentation
def _draw_circle_fast(self: Any, center_x: Any, center_y: Any, radius: Any, color: Any, fill: Any = True, border_width: Any = 1, pivot: Any = (0.5, 0.5)) -> Any
Draw a circle using the simple shader (no style).
def _generate_filled_circle_geometry(self: Any, segments: Any) -> Any
No documentation
def _generate_hollow_circle_geometry(self: Any, segments: Any, border_width: Any, radius: Any) -> Any
No documentation
def _upload_geometry(self: Any, vertices: Any, indices: Any) -> Any
No documentation
def draw_polygon(self: Any, points: Any, color: Any = None, fill: Any = True, border_width: Any = 1, surface: Any = None, pivot: Any = (0.0, 0.0), style: Optional[Dict[str, Any]] = None) -> Any
No documentation
def _generate_filled_polygon_geometry(self: Any, points: Any) -> Any
No documentation
def _generate_hollow_polygon_geometry(self: Any, points: Any, border_width: Any) -> Any
No documentation
def _draw_polygon_fast(self: Any, points: Any, color: Any, fill: Any = True, border_width: Any = 1, pivot: Any = (0.0, 0.0)) -> Any
Draw a polygon using the simple shader (no style).
def draw_text(self: Any, text: str, x: int, y: int, color: Any, font: pygame.font.Font, surface: Optional[pygame.Surface] = None, pivot: Tuple[float, float] = (0.0, 0.0), flip: Tuple[bool, bool] = (False, False), rotate: float = 0.0, style: Optional[Dict] = None, *args: tuple, **kwargs: dict) -> None
Draw text using a pygame font, with optional flip, rotation, and caching.

Args:
   text: The string to render.
   x, y: Position (before anchor).
   color: Any colour format accepted (pygame.Color, tuple, etc.).
   font: Pygame font object.
   surface: Optional target surface.
   pivot: Anchor (fx, fy) relative to text size.
   flip: (flip_horizontal, flip_vertical).
   rotate: Rotation angle in degrees (clockwise).
def draw_rich_text(self: Any, text: Any, x: Any, y: Any, default_color: Any, font: Any, surface: Any = None, pivot: Any = (0.0, 0.0), **kwargs: dict) -> Any
No documentation
def draw_rich_text_line(self: Any, line: Any, x: Any, y: Any, default_color: Any, font: Any, surface: Any = None) -> Any
No documentation
def _cleanup_text_cache(self: Any, now: float) -> Any
No documentation
def _cleanup_texture_cache(self: Any, time_dur: Any = 5.0, force_cleanup: Any = False) -> Any
No documentation
def draw_surface(self: Any, surface: Any, x: Any, y: Any, pivot: Any = (0.0, 0.0), use_cache: Any = True) -> Any
No documentation
def blit(self: Any, source: Any, dest: Any, area: Any = None, special_flags: Any = 0, pivot: Any = (0.0, 0.0), use_cache: Any = True) -> Any
No documentation
def fill_screen(self: Any, color: Any) -> Any
No documentation
def clear(self: Any) -> Any
No documentation
def render_particles(self: Any, particle_data: Any, camera: Any) -> Any
No documentation
def _ensure_particle_capacity(self: Any, required: Any) -> Any
No documentation
def _ensure_temp_fbo(self: Any, width: int, height: int) -> None
Create or resize temporary FBOs and textures.
def _generate_gradient_texture(self: Any, color_keys: Any, width: int, height: int, gradient_type: str = 'linear', angle: float = 0.0) -> int
No documentation
def _apply_blur_to_texture(self: Any, tex_id: int, width: int, height: int, intensity: float) -> int
No documentation
def _apply_shadow_to_shape(self: Any, mask_tex: int, width: int, height: int, shadow_params: Dict) -> Tuple[int, int, int]
No documentation
def cleanup(self: Any) -> Any
No documentation
def set_blend_mode(self: Any, mode: str) -> Any
No documentation

Global Functions

def set_shader_folder(folder: str) -> None

Set the base folder where shader files are located.
This affects all ShaderProgram instances that load shader files by relative name.

Args:
   folder: Absolute path to the shader folder.

def get_shader_folder() -> str

Return the current shader folder path.

Back to Backend Module