fragplot Documentation

(Sept. 2013, published May 2015, revised Dec. 2021) 🅭🅯🄎 4.0 Daniel Woodworth

This is the documentation for fragplot, a small utility for plotting color functions over a plane using WebGL.

Background

fragplot was mostly inspired by this and developed concurrently with this, originally during a hack night. The original purpose of fragplot was to plot a Mandelbrot fractal, but since it can plot arbitrary color functions there are many other interesting uses for it too.

What It Does

fragplot has a very simple interface with a text box to enter the GLSL function to be plotted (vec4 color(vec2)) and a button to do the plotting by updating the background canvas. If there are compilation errors when updating the function, those are shown in a dialog window and the offending line might be highlighted depending on how the error message is formatted.

The plot itself can be panned by clicking and dragging and zoomed by scrolling. The numbers in the bottom right show the current center point of the viewport and its width in plot units. All of the UI including the main controls and the numbers can be hidden by double-clicking on the plot.

How It Works

fragplot is really just a tiny wrapper around a WebGL fragment shader: whenever the plot is updated the color function is “#include-linked” into a stub fragment shader that calls it with the right coordinates at each pixel. By using WebGL like this, fragplot is both able to take full advantage of hardware acceleration to plot functions in real time and able to take advantage of the OpenGL driver to handle all of the logic of actually parsing the function.

Examples

The default code plots a Mandelbrot fractal, but the code doesn't need to be that complicated. Listing 1 just makes the entire screen blue:

vec4 color(vec2 c) {
  return vec4(0, 0, 1, 1);
}
Listing 1: color function for a blue screen.

Listing 2 plots a simple logarithmic radial gradient:

vec4 color(vec2 c) {
  return vec4(1, 1, 1, exp(-length(c)));
}
Listing 2: color function for a logarithmic radial gradient.

Listing 3 plots a square:

vec4 color(vec2 c) {
  if (c.x < -1. || c.x > 1. || c.y < -1. || c.y > 1.) discard;
  return vec4(1, 1, 1, 1);
}
Listing 3: color function for a white square.

Listing 4 makes smoothed concentric rings:

float dabs(float a) {
  return min(a - floor(a), ceil(a) - a);
}
vec4 color(vec2 c) {
  float l = dabs(length(c));
  if (l > .1) discard;
  return vec4(1, 1, 1, 1. - l*10.);
}
Listing 4: color function for smoothed white concentric rings.

And Listing 5 produces the default luagraph uv grid:

float dabs(float a) {
  return min(a - floor(a), ceil(a) - a);
}
vec4 color(vec2 c) {
  if (dabs(c.x) > .02 && dabs(c.y) > .02) return vec4(.5, .5, .5, 1);
  return vec4(dabs(c.x) <= .02 ? 1 : 0, dabs(c.y) <= .02 ? 1 : 0, 0, 1);
}
Listing 5: color function for a unit grid with vertical lines in red and horizontal lines in green.