Skip to content

shader

FreeBodyEngine.graphics.webgl.shader #

WebGL2Shader: the WebGL2 implementation of Shader. Mirrors GL33Shader's shape closely (compile via a Generator, introspect uniforms, cache their last-set value) - the real difference throughout this file is mechanical, not conceptual: PyOpenGL's glFoo(...) global-state calls become self.gl.foo(...) calls against this specific canvas's WebGL2RenderingContext object (JS has no implicit "current context" the way desktop GL does), and raw ints/floats/bools that PyOpenGL happily takes straight from a numpy array need to cross into JS as an explicit typed array first (see graphics/webgl/interop.py).

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

Bases: Shader

The WebGL2 implementation of Shader - see this module's own docstring.

Compiles vertex_source/fragment_source into a linked WebGL2 program (via WebGL2Generator) and introspects its active uniforms into self.uniforms. geometry_source is accepted only for interface parity with GLShader/the abstract Shader signature - WebGL2 has no geometry shader stage at all, so a non-None value here would already have failed inside WebGL2Generator's (deliberately empty) CAPABILITIES before ever reaching this constructor.

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

uniform_cache = {name: None for name in (self.uniforms)} instance-attribute #

uniforms = {} instance-attribute #

check_val_type(val, gl_type, name) #

Same validation GLShader.check_val_type() does - WebGL2's type enum values line up with desktop GL's for every type this engine actually uses, so the exact same dispatch works unchanged.

get_uniform(name) #

Returns the introspected WebGLUniform record for uniform name.

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

Recompiles this shader in place - see GLShader.rebuild()'s own docstring, same reasoning applies unchanged.

set_buffer(name, buffer) #

Not supported - WebGL2Generator's empty CAPABILITIES already rejects any FBUSL @buffer block before a shader referencing one could compile, so this should never actually be reached; kept as a clear error rather than silently doing nothing if it somehow is.

set_uniform(name, val) #

Sets uniform name to val - same skip-if-unchanged caching as GLShader.set_uniform().

setup_uniforms() #

Populates self.uniforms from the program's active uniforms (getActiveUniform/getUniformLocation) - the WebGL2 equivalent of GLShader.setup_uniforms(), just against JS's object-returning introspection calls instead of PyOpenGL's.

use() #

Activates this shader's program, updates the TIME builtin uniform if declared, and binds every cached texture uniform.

Resets the texture manager's slot allocation here (not just from Renderer.draw_mesh()) so a caller that draws directly - shader.use() + mesh.draw(), bypassing draw_mesh() entirely, as phonon's VisualizerPipeline does for its ping-pong fullscreen quad - still gets a clean, fully-unbound set of texture units every draw. See WebGL2TextureManager.begin_draw()'s own docstring for why a stale binding left over from a path that skips this causes WebGL2's "Feedback loop formed between Framebuffer and active Texture" error.

WebGLUniform(location, size, type) dataclass #

One introspected active uniform: its WebGL location handle (an opaque JS object, unlike GL33's plain int), array size, and WebGL type enum (a plain int - WebGL2's GLenum values for e.g. FLOAT/FLOAT_VEC3/SAMPLER_2D are numerically identical to desktop GL's, both being derived from the same OpenGL ES lineage, so GL33Shader's own type-name table/dispatch logic below carries over unchanged).

location instance-attribute #

size instance-attribute #

type instance-attribute #

create_shader_program(gl, vertex_src, fragment_src) #

Compiles and links vertex_src/fragment_src into a linked WebGL2 program, raising RuntimeError with the driver's log on a compile or link failure - same contract as gl33/shader.py's own create_shader_program().

set_gl_uniform(gl, loc, t, val) #

The actual gl.uniform*/gl.uniformMatrix* type dispatch, shared by WebGL2Shader._set_gl_uniform() (an already-introspected uniform on an ordinary shader) and WebGL2ComputeShader (graphics/webgl/compute.py - a compute/raytrace kernel's own uniforms, introspected the same way but with no per-shader wrapper object of its own) - mirrors gl33/shader.py's own module-level set_gl_uniform() being shared with GLComputeShader for the same reason.