glsh.js Documentation

WebGL shader effects library — v1.5.3.
Zero dependencies. Real-time GPU effects for images and video in any modern browser.

Installation

Include the script directly in your HTML:

<!-- Via CDN / local file -->
<script src="glsh.js"></script>

<!-- Via npm -->
npm install glsh

When loaded via a <script> tag, glsh is available as a global. With a bundler, import it:

import glsh from 'glsh';
// or
const glsh = require('glsh');

Overview

glsh.js exposes four functions:

FunctionPurpose
glsl()Run any custom GLSL fragment shader on a canvas
effects()Apply a named built-in shader effect
imgsrc()Load an image and return an HTMLImageElement for use as a texture
videosrc()Load a video and return an HTMLVideoElement for use as a live texture

All rendering runs in a requestAnimationFrame loop. Both glsl() and effects() return an instance object with stop(), destroy(), and other control methods.

Core API

glsl(target, fragSrc, options?) function

Compiles and runs a custom GLSL fragment shader. The vertex shader and quad geometry are managed internally. The following uniforms are automatically injected into every shader:

UniformTypeDescription
u_timefloatElapsed time in seconds since rendering started
u_resolutionvec2Canvas width and height in pixels
u_texturesampler2DBound texture (if provided via options.texture)

Parameters:

ParameterTypeDescription
targetstring | HTMLCanvasElementCSS selector string or canvas element. If a selector points to a non-canvas element, a canvas is inserted after it.
fragSrcstringGLSL ES 1.00 fragment shader source code
optionsobjectOptional configuration (see below)

Options:

KeyTypeDefaultDescription
widthnumber512Canvas width in pixels
heightnumber512Canvas height in pixels
textureHTMLImageElement | HTMLVideoElement | HTMLCanvasElementSource bound to u_texture
uniformsobject{}Additional uniforms: { myFloat: 1.0, myVec2: [0.5, 0.5] }
Returns — Instance object
canvasHTMLCanvasElementThe rendering canvas
glWebGLRenderingContextRaw WebGL context
programWebGLProgramCompiled shader program
stop()voidCancels the animation frame loop
setUniform(name, value)voidUpdate a uniform value at runtime
destroy()voidStops rendering and frees GPU resources
const frag = `
  precision mediump float;
  uniform float u_time;
  uniform vec2  u_resolution;
  varying vec2  v_texCoord;
  void main() {
    vec2 uv = v_texCoord;
    vec3 col = 0.5 + 0.5 * cos(u_time + uv.xyx + vec3(0,2,4));
    gl_FragColor = vec4(col, 1.0);
  }
`;

const inst = glsh.glsl('#my-canvas', frag, {
  width: 800,
  height: 450
});

// Stop after 5 seconds
setTimeout(() => inst.stop(), 5000);

effects(target, effectName, options?) function

Applies a named built-in effect. All effects accept a texture (image or video source) plus effect-specific parameters. Transition effects additionally accept texture2.

Parameters:

ParameterTypeDescription
targetstring | HTMLCanvasElementCSS selector or canvas element
effectNamestringOne of the built-in effect names (see below)
optionsobjectConfiguration including texture and effect parameters

Common options (all effects):

KeyTypeDescription
textureHTMLImageElement | HTMLVideoElement | HTMLCanvasElementPrimary texture source
texture2HTMLImageElement | HTMLCanvasElementSecondary texture (transition effects only)
widthnumberCanvas width in pixels (default: 512)
heightnumberCanvas height in pixels (default: 512)
Returns — Instance object
canvasHTMLCanvasElementThe rendering canvas
stop()voidCancels the animation frame loop
setProgress(p)voidSet transition progress 0–1 (transition effects)
updateTexture(src)voidSwap the primary texture at runtime
destroy()voidStops rendering and frees GPU resources

imgsrc(src, callback) function

Loads an image from a URL and returns an HTMLImageElement ready for use as a WebGL texture. Cross-origin images are handled automatically (crossOrigin = 'anonymous').

ParameterTypeDescription
srcstringURL of the image to load
callbackfunction(err, img)Called when load completes. err is null on success, an Error on failure. img is the HTMLImageElement.
glsh.imgsrc('photo.jpg', function(err, img) {
  if (err) { console.error(err); return; }
  glsh.effects('#canvas', 'duotone', {
    texture: img,
    colorA: [0.05, 0.0, 0.3],
    colorB: [1.0, 0.85, 0.1]
  });
});

videosrc(src, options?, callback) function

Loads a video and returns an HTMLVideoElement for use as a live-updating texture. The video texture is re-uploaded to the GPU each frame.

ParameterTypeDescription
srcstringURL of the video
optionsobjectOptional: loop (true), muted (true), autoplay (true)
callbackfunction(err, video)Called when the video is ready to play
glsh.videosrc('clip.mp4', { loop: true, muted: true }, function(err, video) {
  if (err) { console.error(err); return; }
  glsh.effects('#canvas', 'glitch', {
    texture: video,
    intensity: 0.06
  });
});

Built-in Effects

All effect names are passed as strings to effects(). The parameters below are set as keys in the options object alongside texture.

customShader

Runs an arbitrary GLSL fragment shader through the effects() pipeline (texture binding, animation loop, etc.).

OptionTypeDefaultDescription
shaderstringpassthroughGLSL ES 1.00 fragment shader source
glsh.effects('#canvas', 'customShader', {
  texture: img,
  shader: `
    precision mediump float;
    uniform sampler2D u_texture;
    uniform float u_time;
    varying vec2 v_texCoord;
    void main() {
      vec2 uv = v_texCoord;
      uv.x += sin(uv.y * 10.0 + u_time) * 0.05;
      gl_FragColor = texture2D(u_texture, uv);
    }`
});

hue

Continuously rotates the hue of the image using an RGB rotation matrix. The rotation angle advances with u_time, so the image cycles through all hues automatically.

OptionTypeDefaultDescription
anglenumber0.0Base hue offset in radians. Added to the animated time component.
glsh.effects('#canvas', 'hue', { texture: img, angle: 1.57 });

saturation

Scales the distance of each pixel's color from its luminance (greyscale) equivalent. Static — does not animate.

OptionTypeDefaultDescription
amountnumber1.5Saturation multiplier. 0 = greyscale, 1 = original, 2+ = oversaturated.
glsh.effects('#canvas', 'saturation', { texture: img, amount: 2.0 });

rgbSplit

Samples the red and blue channels from horizontally offset UV coordinates while keeping green centered. Produces a chromatic aberration effect.

OptionTypeDefaultDescription
amountnumber0.01Channel offset in UV units (0–0.05 is typical).
glsh.effects('#canvas', 'rgbSplit', { texture: img, amount: 0.02 });

glitch

Applies randomised scanline horizontal displacement and RGB channel splitting, both keyed to time — producing a VHS/data-corruption aesthetic.

OptionTypeDefaultDescription
intensitynumber0.05Controls frequency of glitch events (0–0.5 range).
glsh.effects('#canvas', 'glitch', { texture: img, intensity: 0.1 });

bloom

Blurs bright regions and adds them on top of the original image, simulating lens flare / light bleed from luminous areas.

OptionTypeDefaultDescription
thresholdnumber0.7Luminance value above which bloom is applied (0–1).
intensitynumber1.5Bloom brightness multiplier.
glsh.effects('#canvas', 'bloom', {
  texture: img,
  threshold: 0.6,
  intensity: 2.0
});

GaussBlur

9×9 Gaussian kernel blur computed per-pixel. Radius is a multiplier on the per-pixel sample spacing.

OptionTypeDefaultDescription
radiusnumber2.0Blur spread multiplier. 1 = minimal, 10 = heavy.
glsh.effects('#canvas', 'GaussBlur', { texture: img, radius: 4.0 });

wave

Displaces UV coordinates along both axes using animated sine functions, creating a fluid warping motion.

OptionTypeDefaultDescription
amplitudenumber0.03Maximum UV displacement (0.01–0.1 typical).
frequencynumber10.0Spatial frequency of the waves.
glsh.effects('#canvas', 'wave', {
  texture: img,
  amplitude: 0.04,
  frequency: 8.0
});

rippleDistort

Ripple emanates radially from the image center. Modulates the distance to center with a sine wave, displacing each pixel outward or inward.

OptionTypeDefaultDescription
strengthnumber0.05Maximum radial displacement amount.
speednumber3.0Wave propagation speed multiplier.
glsh.effects('#canvas', 'rippleDistort', {
  texture: img,
  strength: 0.08,
  speed: 5.0
});

rippleTransition

Blends between two textures using a radial ripple warp on the transition boundary. Drive setProgress() externally to animate the transition.

OptionTypeDefaultDescription
textureimage/canvasFrom texture (source A)
texture2image/canvasTo texture (source B)
const inst = glsh.effects('#canvas', 'rippleTransition', {
  texture: imgA,
  texture2: imgB
});

// Animate progress 0 → 1 over 1 second
let t = 0;
function tick() {
  t += 0.01;
  inst.setProgress(t);
  if (t < 1.0) requestAnimationFrame(tick);
}
requestAnimationFrame(tick);

cubeTransition

Simulates a 3D cube flip between two textures using perspective projection shortening. Drive setProgress() from 0 to 1 to complete the transition.

OptionTypeDefaultDescription
textureimage/canvasFrom texture (source A)
texture2image/canvasTo texture (source B)
const inst = glsh.effects('#canvas', 'cubeTransition', {
  texture: imgA,
  texture2: imgB
});
inst.setProgress(0.5); // Paused mid-flip

halftone

Replaces the image with a dot-matrix halftone pattern. Each dot's radius is proportional to the local luminance. Black background is rendered for negative space.

OptionTypeDefaultDescription
dotSizenumber6.0Grid resolution (cells per axis). Higher = finer, more dots.
glsh.effects('#canvas', 'halftone', { texture: img, dotSize: 60 });

rainbow

Blends a UV-gradient hue cycle over the image, weighted by the image's luminance channel so highlights receive more rainbow color.

OptionTypeDefaultDescription
speednumber0.5Hue cycle animation speed.
glsh.effects('#canvas', 'rainbow', { texture: img, speed: 0.3 });

kaleidoScope

Divides the image into segments angular slices from the center and mirrors them symmetrically. The pattern slowly rotates over time.

OptionTypeDefaultDescription
segmentsnumber8.0Number of mirror facets. Typical values: 4, 6, 8, 12.
glsh.effects('#canvas', 'kaleidoScope', { texture: img, segments: 12 });

swirl

Applies a rotation twist that is strongest at the center and falls off with distance. The twist angle also animates with time.

OptionTypeDefaultDescription
anglenumber3.0Maximum twist angle in radians at center.
radiusnumber0.5Falloff radius in UV units (0–1). Beyond this, no twist is applied.
glsh.effects('#canvas', 'swirl', {
  texture: img,
  angle: 5.0,
  radius: 0.6
});

shear

Applies animated UV shear displacement: X coordinates are shifted by a function of Y, and Y by X, using animated sine/cosine coefficients. Areas outside the UV [0,1] boundary are rendered black.

OptionTypeDefaultDescription
amountXnumber0.2Shear intensity along the X axis.
amountYnumber0.0Shear intensity along the Y axis.
glsh.effects('#canvas', 'shear', {
  texture: img,
  amountX: 0.4,
  amountY: 0.1
});

duotone

Maps pixel luminance to a linear interpolation between two colors. Shadows map to colorA, highlights to colorB. Static — does not animate.

OptionTypeDefaultDescription
colorA[r, g, b][0.1, 0.0, 0.5]Shadow color (RGB, each 0–1)
colorB[r, g, b][1.0, 0.8, 0.0]Highlight color (RGB, each 0–1)
glsh.effects('#canvas', 'duotone', {
  texture: img,
  colorA: [0.05, 0.0, 0.3],
  colorB: [1.0,  0.85, 0.0]
});

tritone

Three-point tone map that divides luminance into shadows (0–0.5) and highlights (0.5–1) and linearly interpolates through three custom colors. Static — does not animate.

OptionTypeDefaultDescription
shadow[r, g, b][0.0, 0.0, 0.2]Color at luminance 0
mid[r, g, b][0.5, 0.0, 0.5]Color at luminance 0.5
highlight[r, g, b][1.0, 0.9, 0.5]Color at luminance 1
glsh.effects('#canvas', 'tritone', {
  texture: img,
  shadow:    [0.0, 0.0, 0.15],
  mid:       [0.6, 0.1, 0.4],
  highlight: [1.0, 1.0, 0.6]
});

Browser Compatibility

glsh.js requires WebGL 1.0 support. All modern browsers (Chrome 56+, Firefox 51+, Safari 15+, Edge 79+) and most mobile browsers support WebGL. The library falls back gracefully with an error if WebGL is unavailable.

Cross-Origin Images: When using imgsrc() or passing image elements as textures, the image server must include appropriate CORS headers (Access-Control-Allow-Origin). glsh.js sets crossOrigin = 'anonymous' automatically on elements it creates, but elements created outside the library must have this set manually before the src attribute.
Video Textures: Autoplay with sound requires user interaction in most browsers. Always use muted: true in videosrc() options for reliable autoplay behavior.