Skip to content

webgl

FreeBodyEngine.graphics.webgl #

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

Bases: Framebuffer

The WebGL2 implementation of Framebuffer - see GLFramebuffer's own docstring, same shape: one GL_TEXTURE_2D per color attachment, a shared renderbuffer for depth/stencil/depth-stencil. Floating-point color attachments (RGBA16F/RGBA32F/R32F/RG32F - used throughout this engine's HDR/compute-emulation paths) need the EXT_color_buffer_float extension explicitly requested up front; unlike desktop GL 3.3 (where float render targets are core), WebGL2 only guarantees 8-bit/sRGB color-renderable formats without it.

depth_renderbuffer = None instance-attribute #

depth_texture_name = None instance-attribute #

fbo = gl.createFramebuffer() instance-attribute #

gl = get_service('renderer').gl instance-attribute #

textures = {} instance-attribute #

bind() #

Binds this FBO and sets the viewport to its full size.

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

See GLFramebuffer.clear_color_attachment() - clearBufferfv targets one draw-buffer index at a time, same as desktop GL.

draw(attachment, size=None) #

Blits a named color attachment to the currently bound framebuffer (the default/window framebuffer, in the common case - see FramePresenter-style callers) via blitFramebuffer, which WebGL2 has natively (unlike WebGL1, which needed a fullscreen-quad shader trick for this).

get_attachment_texture(attachment_name) #

Returns the raw WebGLTexture backing the named color attachment.

read(attachment_name) #

Synchronous GPU->CPU readback via readPixels - see the abstract method's own docstring for when that's acceptable. readPixels needs a pre-sized JS typed array to write into (unlike PyOpenGL's glReadPixels, which allocates and returns one), so one is created up front and copied back out via .to_py().

resize(size) #

Recreates every attachment's storage at the new size - deletes and regenerates each one (WebGL2, like desktop GL, can't resize a texture/renderbuffer's storage in place).

set_draw_buffers(names) #

See Framebuffer.set_draw_buffers(). Assumes this FBO is already bound.

Unlike desktop GL (glDrawBuffers there can list attachments in any order or subset - array index N just means "fragment output N goes to whichever attachment is listed here"), WebGL2 requires array index i to be either NONE or exactly COLOR_ATTACHMENTi - the array position IS the attachment index, and can't reorder or compact them. So this can't just be gl.drawBuffers([self. attachments[n] for n in names]) the way GLFramebuffer's desktop equivalent is (that mapped straight through and failed the instant names requested a non-contiguous-from-zero subset, e.g. a G-buffer's attachments 1-3 without attachment 0 - the WebGL2 error is literally "drawBuffers: COLOR_ATTACHMENTi_EXT or NONE"). Building a full-width array covering every color attachment this FBO has, with NONE at every index not in names, satisfies that restriction regardless of which subset was requested.

unbind() #

Rebinds the default framebuffer (the canvas's own backbuffer).

WebGL2Image(data) #

Bases: Image

The WebGL2 implementation of Image - a thin wrapper reading its pixel data/rect straight off the underlying WebGL2TextureManager-owned Texture, same as GLImage.

get_data() #

Returns the wrapped texture's raw pixel data.

get_size() #

Returns the wrapped texture's UV rect (x, y, w, h).

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

Bases: Mesh

The WebGL2 implementation of Mesh - see GLMesh's own docstring, same shape: one real VAO, one VBO per vertex attribute, an optional EBO for indexed drawing. WebGL2 (unlike WebGL1) has native createVertexArray/ bindVertexArray, so this needs no OES_vertex_array_object shim.

ebo = gl.createBuffer() if indices is not None else None instance-attribute #

gl = get_service('renderer').gl instance-attribute #

vao = gl.createVertexArray() instance-attribute #

vbos = {} instance-attribute #

destroy() #

Deletes every attribute VBO, the EBO if this mesh has one, and the VAO itself.

draw() #

Issues the draw call - drawElements against the EBO if this mesh has indices, else drawArrays (same non-indexed vertex-count assumption GLMesh.draw() makes: the first attribute is a 3-wide channel).

upload() #

(Re)creates one VBO per entry in self.attributes and uploads its data, wiring each up as a sequential vertex attribute starting at location 0, in the same declaration order GLMesh.upload() uses - see its own docstring for why that order matters.