ShaderGif Documentation

ShaderGif helps you create looping GIF art with code, from quick 2D sketches to GPU-powered shader experiments. This documentation is for creative coders who want a clear starting point, plus practical notes on how rendering and recording work inside the editor.

Introduction

ShaderGif supports two main creative coding paths: JavaScript (2D canvas / p5.js) and GLSL (fragment shaders). Choose the approach that matches what you want to build: draw shapes and systems in 2D, or render fully procedural visuals on the GPU.

Supported platforms

JavaScript (Canvas 2D)

JavaScript is a flexible option for creative 2D work: particles, generative drawings, fractals, simple games, and animated sketches. In ShaderGif, JavaScript mode is built around a frame callback that you implement, which is invoked repeatedly while the GIF is being recorded.

If you already know JavaScript, open the editor and choose the JavaScript mode to render through the Canvas API:

Open the editor selector

How the render loop works

In JavaScript mode, ShaderGif calls a function like render(canvas, time) for every frame. The canvas is your drawing surface, and time is a normalised progress value that loops from 0 to 1 over the duration of the recording (with 1 representing the end of the loop).

// Example structure (Canvas 2D)
export function render(canvas, time) {
  const ctx = canvas.getContext("2d");

  // Clear
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  // Use time (0..1) to animate deterministically
  const t = time * Math.PI * 2;

  // Draw something simple
  ctx.save();
  ctx.translate(canvas.width / 2, canvas.height / 2);
  ctx.rotate(t);
  ctx.fillRect(-60, -60, 120, 120);
  ctx.restore();
}

If you’re new to Canvas 2D, the MDN reference is the best place to learn the core drawing primitives, compositing, and transforms.

JavaScript with p5.js

If you prefer a friendlier creative coding workflow, p5.js provides a familiar “sketch” structure and a large set of drawing helpers. In ShaderGif’s p5.js mode, you typically work with setup() and draw(), just like standard p5.js sketches.

To start in p5.js mode, head to the editor selector and choose p5.js:

Start a p5.js sketch

What to expect in the template

  • setup(): one-time initialisation (canvas size, background, colour mode, etc.).
  • draw(): runs every frame and should be written to loop seamlessly.
  • Deterministic animation: aim to derive motion from a looping time variable so your GIF repeats cleanly.
// Example structure (p5.js-style)
function setup() {
  createCanvas(512, 512);
  noStroke();
}

function draw() {
  // Use a looping phase for seamless motion
  const phase = (frameCount % 120) / 120; // 0..1
  const t = phase * TWO_PI;

  background(255);
  fill(0);

  const r = 160;
  const x = width / 2 + cos(t) * r;
  const y = height / 2 + sin(t) * r;

  circle(x, y, 60);
}

For deeper exploration, use the official p5.js reference and examples to learn shapes, noise, blending, typography, and interaction patterns you can adapt to looping GIFs.

Using the GPU with GLSL (Shaders)

GLSL is a shading language that runs on your GPU. It’s ideal for smooth procedural visuals, raymarching, signed distance fields, lighting effects, and richly layered patterns that would be slow to compute on the CPU.

If you’ve never written shaders before, it’s worth starting with a short primer on shader coordinate systems, fragment shaders, and common utility functions (noise, palettes, distance fields).

Get started with shaders

ShaderGif-style mental model

  • You write a fragment shader that computes a colour for each pixel.
  • Time is a first-class input and should be used to create a clean loop.
  • Normalised coordinates are commonly used so your shader scales to different output sizes.
// Minimal fragment shader sketch (illustrative)
#ifdef GL_ES
precision highp float;
#endif

uniform vec2  iResolution;
uniform float iTime;

void main() {
  vec2 uv = (gl_FragCoord.xy - 0.5 * iResolution.xy) / iResolution.y;

  // Looping time (example)
  float t = mod(iTime, 6.2831853);

  float v = 0.5 + 0.5 * sin(10.0 * length(uv) - t);
  vec3 col = vec3(v);

  gl_FragColor = vec4(col, 1.0);
}

Practical tips for clean looping GIFs

  • Animate from a looping phase: use a 0..1 progress value (or an angle 0..2π) and derive all motion from it.
  • Avoid frame-to-frame randomness: if you need variation, base it on coordinates or a fixed seed.
  • Keep motion periodic: sine/cosine, rotations, and repeating noise domains tend to loop naturally.
  • Test at the intended duration: small timing changes can introduce visible “pops” at the loop boundary.

Internal link suggestions

  • Try the online editor — Suggested target: /editor/ (create and preview GIFs from code)
  • Browse the GIF gallery — Suggested target: /gifs/ (study existing sketches and shaders)
  • Shader basics and examples — Suggested target: /docs/shaders/ (GLSL concepts, coordinate systems, looping)
  • ImageMagick tips for exporting — Suggested target: /docs/imagemagick-tips/ (optimisation, palette, size/quality trade-offs)
  • Contributing & development notes — Suggested target: /docs/development/ (local setup, project structure, workflow)

Last updated: 28 December 2025