Skip to content

gl44

FreeBodyEngine.graphics.gl44 #

The OpenGL 4.4 implementation of the FB graphics system - a complete, separate backend from gl33/ (see gl44/renderer.py's docstring). Real compute shaders live in gl44/compute.py (GL44ComputeShader).

GL44Framebuffer(width, height, attachments, transparent=False) #

Bases: Framebuffer

The GL 4.4 implementation of Framebuffer: creates a real GL FBO with one 2D texture per color attachment and a shared renderbuffer for a depth/stencil/combined depth-stencil attachment (GL 4.4 has no functional need for a separate depth-only vs. combined path beyond which GL enum each is attached under).

Creates the FBO and, for each entry in attachments, its backing GPU resource: a texture for a COLOR attachment (assigned sequential GL_COLOR_ATTACHMENT0+n slots and registered as a draw buffer), or a renderbuffer for DEPTH/STENCIL/DEPTH_STENCIL. Raises RuntimeError if the resulting FBO isn't GL_FRAMEBUFFER_COMPLETE. transparent enables standard alpha blending for subsequent draws into this framebuffer.

depth_renderbuffer = glGenRenderbuffers(1) instance-attribute #

fbo = glGenFramebuffers(1) instance-attribute #

textures = {} instance-attribute #

bind() #

Binds this FBO as the current draw/read target and sets the GL viewport to its full size, so subsequent draw calls render into its attachments instead of the screen.

clear_color_attachment(name, value=(0.0, 0.0, 0.0, 0.0)) #

Clears the named color attachment to value via glClearBufferfv(GL_COLOR, draw_buffer_index, ...) - see GLFramebuffer.clear_color_attachment (gl33) for why this targets only one draw buffer rather than every bound one. This was missing entirely from GL44Framebuffer (PBRPipeline.draw() calls it unconditionally to keep gWorldPos.w a reliable sentinel), so PBRPipeline could never actually run on GL44Renderer before this.

draw(attachment, size=None) #

Draw a named attachment to the screen.

get_attachment_texture(attachment_name) #

Returns the raw GL texture name backing color attachment attachment_name (e.g. for wrapping via TextureManager.wrap_external_texture), logging an error instead of raising if it doesn't exist.

read(attachment_name) #

Synchronously reads back color attachment attachment_name (glReadPixels, always as GL_FLOAT) into a (height, width, channels) numpy array - a GPU/CPU sync point, so only meant for compute-emulation-style result readback, not per-frame use. Raises ValueError if attachment_name doesn't exist or isn't a color attachment.

resize(size) #

Recreates every attachment's backing texture/renderbuffer at the new size in place (same FBO, same attachment slots) - deletes each old GL object first rather than leaking it. Raises RuntimeError if the FBO isn't complete afterward, and leaves the GL viewport set to the new size.

set_draw_buffers(names) #

See Framebuffer.set_draw_buffers / GLFramebuffer.set_draw_buffers (gl33) - identical implementation. Assumes this FBO is already bound.

unbind() #

Rebinds the default framebuffer (id 0, the screen) - does not restore the previous viewport, so callers that resized it should reset that themselves.

GL44Image(data) #

Bases: Image

The GL 4.4 implementation of Image - identical to GLImage (graphics/gl33/image.py), since exposing a Texture's pixel data doesn't involve anything backend-specific beyond the Texture/TextureManager machinery both backends already share.

Wraps the given texture-backed data via the base Image constructor.

get_data() #

Returns this image's raw pixel data, read back from its backing Texture.

get_size() #

Returns this image's UV rect (the sub-region of its backing texture/atlas this image occupies), not literal pixel dimensions.

GL44Mesh(attributes, indices=None, primitive=None, index_type=None, usage=None) #

Bases: Mesh

The GL 4.4 implementation of Mesh: one VAO with one VBO per attribute (bound to sequential vertex attribute locations in attributes' dict order) plus an optional EBO for indexed drawing. Identical in mechanism to GLMesh (graphics/gl33/mesh.py) - core vertex array/buffer upload hasn't changed between GL 3.3 and 4.4.

Creates the VAO/VBOs/EBO (the EBO only if indices is given), picks the GL primitive enum matching primitive, and immediately uploads the given attribute/index data via upload().

ebo = glGenBuffers(1) if indices is not None else None instance-attribute #

vao = glGenVertexArrays(1) instance-attribute #

vbos = {} instance-attribute #

destroy() #

Deletes every VBO, the EBO (if any), and the VAO itself.

draw() #

Issues the draw call for this mesh's currently uploaded buffers: glDrawElements if it has an index buffer, otherwise glDrawArrays sized off the first attribute's vertex count (its raw element count divided by 3, so this assumes that attribute is 3-component - e.g. positions).

upload() #

Uploads every attribute in self.attributes to its own VBO and wires it to a sequential vertex attribute location (location 0, 1, 2, ... in dict iteration order - so the order attributes are passed in matters), then uploads self.indices to the EBO if present. Raises ValueError for an AttributeType this backend doesn't know how to map to a GL type/size (MAT3/MAT4/VEC5/VEC6/IVEC5/IVEC6).

GL44Renderer() #

Bases: Renderer

The OpenGL renderer. Uses OpenGL version 4.4 core - real compute shaders (glDispatchCompute), writable SSBOs, and image load/store, unlike GL33Renderer's fullscreen-fragment-shader compute emulation. A completely separate, independently selectable backend (see graphics/get_renderer()) - GL33Renderer is untouched and still exists for hardware/platforms that can't do better than 3.3.

Sets the backend's Mesh subclass; GPU context creation happens in on_initialize() instead, since it depends on a window (or lack thereof) that doesn't exist yet at construction time.

create_framebuffer property #

Returns GL44Framebuffer.

mesh_class = GL44Mesh instance-attribute #

clear(color) #

Clears the color and depth buffers of the currently bound framebuffer to color.

clear_scissor() #

See Renderer.clear_scissor().

create_buffer(data) #

Wraps data in a UBOBuffer, GL44's Buffer implementation.

destroy() #

Releases the OpenGL context (win32 only - wglMakeCurrent/wglDeleteContext are Windows-specific).

disable_depth_testing() #

Disables GL_DEPTH_TEST.

draw_circle(radius, position, color) #

Not yet implemented - always a no-op.

draw_line(start, end, width, color) #

Draws a line segment from start to end using a dedicated line shader program (self.line_program), building a fresh 2-point VAO/VBO every call.

draw_mesh(mesh, material) #

Binds material and draws mesh's indexed triangles. Temporarily switches to wireframe polygon mode if material.data['render_mode'] == "wireframe".

draw_mesh_instanced(mesh, material, model_matrices, camera) #

Draws one copy of mesh per row of model_matrices (shape (N, 4, 4)) in a single glDrawElementsInstanced call - see GL33Renderer.draw_mesh_instanced for the identical implementation and its docstring (GL44 doesn't need anything version-specific for instanced vertex-attribute arrays, so this is deliberately not using GL44-only features like SSBOs).

enable_depth_testing() #

Enables GL_DEPTH_TEST.

get_max_buffer_size() #

Returns the max size of a UBOBuffer, in bytes.

get_mesh_class() #

Returns GL44Mesh.

load_shader(vertex, fragment, injector=Injector(), geometry=None) #

Compiles vertex/fragment (and optional geometry) FBUSL source into a GL44Shader, using injector to resolve engine-provided builtins.

on_initialize() #

Creates (or attaches to) the OpenGL context for the current window backend (glfw/wayland/win32/x11), or - if no 'window' service is registered at all - assumes a raw offscreen context already exists and is current (a true headless compute session, see graphics.ensure_gpu_context()). Then warns (but doesn't raise) if the resulting context is below MIN_GL_VERSION, and enables GL_DEBUG_OUTPUT plus the initial viewport.

resize(size) #

Updates the GL viewport to size, and resizes the platform-specific window surface (wayland/x11) to match.

set_blend_mode(mode) #

See Renderer.set_blend_mode. Skips the actual GL calls if mode already matches the last mode set, since flush() calls this between every group even when consecutive groups share a mode.

set_scissor(x, y, width, height) #

See Renderer.set_scissor(). x/y come in top-left-origin, Y-down (UIRenderer's convention) - glScissor wants bottom-left origin, so y is flipped against the framebuffer height.

swap_buffers() #

Swaps the front/back buffers for a manually-created wayland/x11 context. glfw drives its own swap directly (see core/window/glfw.py) instead of going through the renderer, so this is a no-op there.

GL44Shader(vertex_source, fragment_source, injector, geometry_source=None) #

Bases: Shader

The GL 4.4 implementation of Shader: compiles FBUSL source via GL44Generator into a real GL program, introspects its uniforms, and caches each uniform's last-set value so set_uniform() can skip a redundant glUniform* call when the value hasn't actually changed.

Compiles vertex_source/fragment_source(/geometry_source) into a linked GL program (via GL44Generator) and introspects its active uniforms into self.uniforms, seeding uniform_cache with None for each so the first set_uniform() call for any uniform always goes through.

uniform_cache = {} instance-attribute #

uniforms = {} instance-attribute #

check_val_type(val, gl_type, name) #

Validates that val is an acceptable Python value for a uniform of GL type gl_type - logging an engine error and returning False if not. Color/Vector/Vector3 are accepted directly for the vector GL types they map onto, alongside a plain tuple/list/ndarray of the right length.

get_uniform(name) #

Returns the introspected GL44Uniform record (location/size/type) for uniform name.

rebuild(injector=..., vertex_source=None, fragment_source=None, geometry_source=...) #

See GLShader.rebuild() (graphics/gl33/shader.py) for why vertex_source/fragment_source default to re-using self's existing ones rather than being required, and why geometry_source's default is the ... sentinel rather than None.

set_buffer(name, buffer) #

Binds buffer to the uniform block declared as name in this shader's source (self.data['buffers'], populated by generator-produced metadata) - warns instead of raising if name isn't a known buffer block.

set_uniform(name, val) #

Sets uniform name to val, after check_val_type() validates it. Skips the actual glUniform* call (and the cache update) if val equals the value already cached for this uniform, avoiding redundant driver calls when the same value is set every frame - as material properties typically are.

setup_uniforms() #

Populates self.uniforms from the program's active uniforms (glGetActiveUniform), normalizing the name PyOpenGL hands back (which can come as str, bytes, or a numpy array depending on driver/binding) to a plain, null-terminated string.

use() #

Activates this shader's program, updates the TIME builtin uniform if the shader declares one, and binds every currently-cached texture/texture-stack uniform (see _bind_textures).