generator
FreeBodyEngine.graphics.webgl.generator
#
WebGL2Generator(*args, **kwargs)
#
Bases: GL33Generator
Emits GLSL ES 3.00 (WebGL2's shading language) - inherits GL33Generator
wholesale (the actual codegen for expressions/statements/functions is
identical between desktop GLSL 330 and GLSL ES 300; they diverged from
the same OpenGL ES lineage and neither this engine nor FBUSL uses any
construct where they differ) and overrides only what actually differs:
the version header, ES's mandatory float precision qualifier that
desktop GLSL doesn't have at all, and the "sample" builtin's generated
function name (see _WEBGL2_IMPLEMENTATIONS above - sample itself is
a reserved word in GLSL ES, unlike desktop GLSL 330).
CAPABILITIES covers everything GL33Generator's does except
"geometry.native" - WebGL2 genuinely has no geometry shader stage at
all (that's ES 3.2/desktop only), so @geometry still raises a clear
FBUSL "capability not supported" error targeting web. Compute/raytrace
support (buffer_read/dispatch/invocation_id/image_read/
query_emulated), though, carries over just fine - GL33's own emulation
of all of it is already built entirely from ordinary draw calls,
framebuffers and textures (see graphics/gl33/compute.py's module
docstring), none of which are desktop-only. The one piece that
genuinely doesn't exist in WebGL2 is samplerBuffer/GL_TEXTURE_BUFFER
itself (ES 3.2+/desktop-only, no WebGL2 extension exposes it) - see
generate_buffer_block()/_generate_raytrace_intrinsics() below for the
2D-data-texture emulation (graphics/webgl/buffer.py's
WebGL2TextureBuffer) that replaces it.
Same as GL33Generator.init(), except self.implementations
is the WebGL2-specific table above (renamed "sample") instead of
GL33Generator's own.
CAPABILITIES = frozenset({'compute.dispatch', 'compute.invocation_id', 'compute.buffer_read', 'compute.image_read', 'raytrace.query_emulated'})
class-attribute
instance-attribute
#
implementations = _WEBGL2_IMPLEMENTATIONS
instance-attribute
#
generate()
#
Same shape as GL33Generator.generate() - version/extension
header, then IMPLEMENTATIONS injections, then (for a RAYTRACE
stage) the ray-intrinsics, then one generated line per top-level
AST node - but with a GLSL ES header instead of desktop GLSL's,
no geometry-layout handling (CAPABILITIES above still has no
"geometry.native", so reaching that FBUSL construct raises
first), and the _ENGINE_buf_idx() overload pair every buffer-
block/raytrace-intrinsic access below calls to turn a 1D index
into this backend's 2D-data-texture coordinates.
generate_buffer_block(node)
#
Same contract as GL33Generator.generate_buffer_block() (declares
one uniform per field, plus a _load_<struct>_<block>_<field>()
loader for struct-typed fields) but backed by sampler2D instead
of samplerBuffer - see this module's own docstring and
graphics/webgl/buffer.py's WebGL2TextureBuffer for why. Every
field here is float data (even an int-typed struct field - see
_generate_struct_field_loader's int() cast), matching
GL33Generator's own choice to always use samplerBuffer (never
isamplerBuffer) for ordinary buffer blocks; only the raytrace
intrinsics' bvh_meta needs a real int texture (see
_generate_raytrace_intrinsics).
generate_inout(node)
#
Same as GL33Generator.generate_inout(), except layout(location=
...) is only emitted where GLSL ES 3.00 core actually allows it:
a vertex shader's in (attribute) declarations, and a fragment
shader's out (color attachment) declarations. Desktop GLSL 330
can put an explicit location on every in/out, including a
vertex shader's out varyings and a fragment shader's matching
in varyings, because GL33Generator's header enables
GL_ARB_separate_shader_objects - WebGL2 has no equivalent
extension at all, and ES 3.00 core requires varyings to match
between stages by name instead, with no location qualifier on
either side. Emitting one anyway compiled fine in isolation but
failed exactly at the vertex stage (before this was ever caught)
with "invalid layout qualifier: only valid on program inputs and
outputs" - GLSL ES's own error wording for "not a real attribute/
fragment-output".
self.input_index/self.output_index still advance on every
Input/Output regardless of whether a location actually gets
printed, matching GL33Generator's own counting so mixed vertex/
fragment field ordering behaves identically to desktop wherever a
location is emitted.