Skip to content

@bloopjs/toodle


@bloopjs/toodle / backends/webgl2/glsl/text.glsl / vertexShader

Variable: vertexShader

const vertexShader: "#version 300 es\nprecision highp float;\n\n// Engine uniforms\nuniform mat3 u_viewProjection;\n\n// Per-text-block uniforms\nuniform mat3 u_textTransform;\nuniform vec4 u_textColor;\nuniform float u_fontSize;\nuniform float u_blockWidth;\nuniform float u_blockHeight;\nuniform float u_lineHeight;\n\n// Character data texture (RGBA32F, 2 texels per character)\n// Texel 0: texOffset.xy, texExtent.xy\n// Texel 1: size.xy, offset.xy\nuniform sampler2D u_charData;\n\n// Text buffer texture (RGBA32F, 1 texel per glyph)\n// Each texel: xy = glyph position, z = char index\nuniform sampler2D u_textBuffer;\n\n// Outputs to fragment shader\nout vec2 v_texcoord;\n\n// Quad vertex positions for a character (matches WGSL)\nconst vec2 pos[4] = vec2[4](\n vec2(0.0, -1.0),\n vec2(1.0, -1.0),\n vec2(0.0, 0.0),\n vec2(1.0, 0.0)\n);\n\nvoid main() {\n // gl_VertexID gives us 0-3 for the quad vertices\n // gl_InstanceID gives us which glyph we're rendering\n int vertexIndex = gl_VertexID;\n int glyphIndex = gl_InstanceID;\n\n // Fetch glyph data from text buffer texture\n vec4 glyphData = texelFetch(u_textBuffer, ivec2(glyphIndex, 0), 0);\n vec2 glyphPos = glyphData.xy;\n int charIndex = int(glyphData.z);\n\n // Fetch character metrics (2 texels per char)\n // Texel 0: texOffset.x, texOffset.y, texExtent.x, texExtent.y\n // Texel 1: size.x, size.y, offset.x, offset.y\n vec4 charData0 = texelFetch(u_charData, ivec2(charIndex * 2, 0), 0);\n vec4 charData1 = texelFetch(u_charData, ivec2(charIndex * 2 + 1, 0), 0);\n\n vec2 texOffset = charData0.xy;\n vec2 texExtent = charData0.zw;\n vec2 charSize = charData1.xy;\n vec2 charOffset = charData1.zw;\n\n // Center text vertically; origin is mid-height\n vec2 offset = vec2(0.0, -u_blockHeight / 2.0);\n\n // Glyph position in ems (quad pos * size + per-char offset)\n vec2 emPos = pos[vertexIndex] * charSize + charOffset + glyphPos - offset;\n vec2 charPos = emPos * (u_fontSize / u_lineHeight);\n\n // Transform position through model and view-projection matrices\n vec3 worldPos = u_textTransform * vec3(charPos, 1.0);\n vec3 clipPos = u_viewProjection * worldPos;\n\n gl_Position = vec4(clipPos.xy, 0.0, 1.0);\n\n // Calculate texture coordinates\n v_texcoord = pos[vertexIndex] * vec2(1.0, -1.0);\n v_texcoord *= texExtent;\n v_texcoord += texOffset;\n}\n"

Defined in: backends/webgl2/glsl/text.glsl.ts:11

GLSL ES 3.0 port of the WGSL text shader for MSDF font rendering.

Key differences from WebGPU version:

  • Uses texelFetch() to read from data textures instead of storage buffers
  • Character metrics stored in RGBA32F texture (8 floats per char = 2 texels)
  • Per-glyph positions stored in RGBA32F texture (vec4: xy = pos, z = charIndex)
  • Each TextNode is rendered separately with uniforms (no firstInstance)