Skip to main content

glsl

Callable

  • glsl(strings: TemplateStringsArray, ...values: any[]): string

  • Tagged template literal for authoring Excalibur Material fragment shaders.

    It handles the boilerplate and, most importantly, the alpha space bookkeeping.

    Automatic alpha premultiplication

    Excalibur's WebGL pipeline is premultiplied end to end. Textures are uploaded with UNPACK_PREMULTIPLY_ALPHA_WEBGL, so a raw texture(u_graphic, uv) hands back a premultiplied value, and the blend function is (ONE, ONE_MINUS_SRC_ALPHA), so the fragment output must be premultiplied too. Doing your own alpha math in the middle of that is a reliable source of washed out blending and dark halos on antialiased edges.

    Shaders written with this tag instead get a straight (un-premultiplied) alpha authoring space. Sampling calls are un-premultiplied on the way in and your color output is premultiplied on the way out, so ordinary intuitive alpha math works in between:

    const material = game.graphicsContext.createMaterial({
      name: 'fade',
      fragmentSource: glsl`
        in vec2 v_uv;
        uniform sampler2D u_graphic;
        out vec4 fragColor;
        void main() {
          vec4 color = texture(u_graphic, v_uv);
          color.a *= 0.5; // just works, no manual premultiply needed
          fragColor = color;
        }`
    });

    Filtering still happens in premultiplied space where it belongs, only the filtered result is converted. See https://www.realtimerendering.com/blog/gpus-prefer-premultiplication/

    To sample a texture that is not color data (a lookup table, a noise or data texture) use ex_texture_raw(tex, uv), which is passed through untouched. To turn the whole transform off for a shader, add #pragma excalibur premultiply(off) to its source.

    Other conveniences

    • Adds #version 300 es and a precision declaration if you did not write them
    • Injects the pixel_texture(sampler2D, vec2) pixel art filter if your source references it
    • Injects uniform vec2 u_graphic_resolution; alongside it if you have not declared it
    • Exposes ex_premultiply(vec4) / ex_unpremultiply(vec4) if you need to convert by hand

    Parameters

    • strings: TemplateStringsArray
    • rest...values: any[]

    Returns string