wolfhece.opengl.gl_utils

This module helps to upload shaders and textures in the GPU. It also provides a lot of controls to ensure compatibility of textures, samplers, uniforms types (because OpenGL is pretty silent about them and incompatibilities lead to mindbending debugging) It is very basic and tuned to our needs.

Module Contents

wolfhece.opengl.gl_utils.GL_COLOR_ATTACHMENTS[source]
wolfhece.opengl.gl_utils.TEXTURE_UNITS[source]
wolfhece.opengl.gl_utils.TEX_SAMPLERS_RE[source]
wolfhece.opengl.gl_utils.IMAGE_UNIT_RE[source]
wolfhece.opengl.gl_utils.check_gl_error()[source]
wolfhece.opengl.gl_utils.rgb_to_rgba(t)[source]
wolfhece.opengl.gl_utils.memory_aligned_byte_array(size, value)[source]
wolfhece.opengl.gl_utils._get_format_type_from_internal_format(internal_format)[source]
wolfhece.opengl.gl_utils.read_texture2(tex_id, desired_format, width: int = None, height: int = None) numpy.ndarray[source]

Read a texture tex_id out of the GPU and returns it as an array.

The desired_fromat is the one you want to get the texture in. Be aware that some formats are not supported by python OpenGL (right now, we know of RG16UI).

wolfhece.opengl.gl_utils.read_texture(frame_buffer_id, color_attachment_ndx, width, height, internal_format)[source]

DEPRECATED Use the version 2 (this one needs framebuffers which is painful to manage).

Read a rectangle (0,0,width, height) in a texture of size at least (width, height).

color_attachment_ndx: either an int or a GL_COLOR_ATTACHMENTx

FIXME Check things up with : https://registry.khronos.org/OpenGL-Refpages/gl4/html/glGetFramebufferAttachmentParameter.xhtml

FIXME This code is limited as we read from a frame buffer (and not directly from a texture id). So one has to provide framebuffer and attachment number (which is not quite convenient).

The internal format of a texture can be found in the dictioneary textures_formats FIXME again, this is sub optimal. It’d be nicer to resolve a texture ID to its corresponding frame buffer/attachment (but it dosen’t make too much sense since a texture may be attached to several FB and since I sometimes hack the fb/textures directly (so I don’t maintaint an FB/attach <-> tex. id correspondance)

wolfhece.opengl.gl_utils.upload_geometry_to_vao(triangles: numpy.ndarray, attr_loc: int = 0, normalized: bool = True)[source]

Geometry is a n rows * [x,y,z] columns matrix representing the vertices, each having x,y,z coordinates (NDC coordinates, that is, each in [-1,+1].

The vertices will be wired to the vertex attribute attr_loc

VAO only stores info about buffers (not transformation, not parameters, etc.)

Returns a Vertex Array Object.

wolfhece.opengl.gl_utils.make_quad(xmin, xmax, ymin, ymax)[source]
wolfhece.opengl.gl_utils.make_unit_quad(texture_width, texture_height)[source]
wolfhece.opengl.gl_utils.query_gl_caps()[source]

Query the GPU for its capabilities.

class wolfhece.opengl.gl_utils.GL_cache_tools[source]

This class helps to upload shaders and textures in the GPU.

samplers_in_shader: dict[tuple[int, str], str][source]
shaders_programs: dict[int, int][source]
shaders_names: dict[int, str][source]
describe_program(pid: int)[source]
load_shader_from_source(shader_type, source: str) int[source]
track_texture_size(tex_id: int, img_data, w: int, h: int, format) int[source]
total_textures_size() int[source]

Return the total size of all textures in bytes.

drop_textures(texture_ids: list[int] | int)[source]

Drop one or more textures. Expect texture id’s.

upload_np_array_to_gpu(context, format, img_data: numpy.ndarray, texture_id: int | None = None) int[source]

The goal of this function is to standardize textures configuration and upload to GPU. We trade generality for ease of use.

If you pass in a texture_id, then the texture will be updated instead of created.

Returns the texture OpenGL id.

upload_blank_texture_to_gpu(w: int, h: int, context, format=GL_R32F, value=0.0)[source]

Make and upload a blank (or one color) texture to the GPU.

format: some texture format. The way it is done here means that we will derive the texture format in the GPU as well as the texture format of the “value” data. context: either GL_TEXTURE_RECTANGLE, GL_TEXTURE_2D value: will be set on each components of the texels.

clear_texture(texture_id: int)[source]
load_shader_from_file(fpath: pathlib.Path, log_path: pathlib.Path = None, shader_type=None)[source]

Load a shader from a file - can contain %%includes. The extension of the file determines the type of shader :

  • .vs : vertex shader

  • .frs : fragment shader

  • .gs : geometry shader

  • .comp : compute shader (.cs is deprecated)

create_frame_buffer_for_computation(destination_texture: int | list[int], out_to_fragdata: bool = False, depth_buffer: bool = False, texture_target=GL_TEXTURE_RECTANGLE)[source]

destination_texture: a texture or a list of textures. If list of textures, one frame buffer will be attached to each texture, via COLOR_ATTACHMENT0,1,2,… (in list order)

out_to_fragdata: if the FB will be used as output of a shader that issues FragData instead of colors. In that case, we create link buffers so that will receive these FragData.

depth_buffer: attach a depth buffer to the framebuffer. None or pass in the dimensions of the buffer. # FIXME don’t pass the dimensions, guess them from the texture.

load_program(vertex_shader: int = None, fragment_shader: int = None, geometry_shader: int = None, compute_shader: int = None)[source]
set_uniform(program: int, name: str, value)[source]
set_texture(program: int, unif_name: str, tex_index: int, tex_unit)[source]
wire_program(program: int, uniforms=dict(), textures=dict())[source]

Binds texture to (read) sampler. Sets uniforms. This doesn’t touch the framebuffer bindings.

program : OpenGL id of the program uniforms: map uniform names (str) to their values textures: map texture sampler names to their texture id. Instead of texture_id you can pass a tuple (texture_id, access) where access is either: GL_READ_ONLY, GL_WRITE_ONLY, or GL_READ_WRITE. See https://www.khronos.org/opengl/wiki/Image_Load_Store

wolfhece.opengl.gl_utils.init_gl(width, height)[source]

Initialize the OpenGL context and create a window with pygame