Fullscreen-triangle geometry shared by every post-processing pass.
Single-triangle covering the entire viewport with NDC positions
{ (-1,-1), (3,-1), (-1,3) }. The accompanying uv attribute makes
a passthrough sample texture(src, uv) return the pixel of src
that lies under the fragment — independently of which backend is
rendering. This abstracts away the WebGL2/WebGPU framebuffer-Y
convention difference: WebGL2 FBOs store row 0 at the bottom of the
viewport, real WebGPU framebuffers store row 0 at the top. Both
backends are handled by swapping the V coordinate in this geometry,
so every downstream pass (mega, bloom, FXAA) and both shader paths
(GLSL3 vUv = uv;, TSL uv()) consume the same contract.
Without the uv attribute, TSL's uv() would read a missing input
and fall back to (0, 0). Originally the GLSL3 vertex shaders
recomputed vUv = position.xy * 0.5 + 0.5 themselves; that worked
under WebGL2 only — under real WebGPU the resulting sample reads the
wrong row of the source target. The GLSL3 shaders now also read this
attribute (via vUv = uv;) so the correction lives in one place.
Fullscreen-triangle geometry shared by every post-processing pass.
Single-triangle covering the entire viewport with NDC positions
{ (-1,-1), (3,-1), (-1,3) }. The accompanyinguvattribute makes a passthrough sampletexture(src, uv)return the pixel ofsrcthat lies under the fragment — independently of which backend is rendering. This abstracts away the WebGL2/WebGPU framebuffer-Y convention difference: WebGL2 FBOs store row 0 at the bottom of the viewport, real WebGPU framebuffers store row 0 at the top. Both backends are handled by swapping the V coordinate in this geometry, so every downstream pass (mega, bloom, FXAA) and both shader paths (GLSL3 vUv = uv;, TSLuv()) consume the same contract.Without the
uvattribute, TSL'suv()would read a missing input and fall back to(0, 0). Originally the GLSL3 vertex shaders recomputedvUv = position.xy * 0.5 + 0.5themselves; that worked under WebGL2 only — under real WebGPU the resulting sample reads the wrong row of the source target. The GLSL3 shaders now also read this attribute (viavUv = uv;) so the correction lives in one place.