Fork me on GitHub
Oops ... your browser doesn't support the HTML5 canvas element
To the right are three code editing areas which are pre-filled with some default code. All of the code is GLSL and is subject to its restrictions. Of particular note, in most cases, there is no automatic conversion between integers and floats. For example, the expression 1 + 2.0 will not compile: since the literal 1 is an integer and the literal 2.0 is a float.

The function plotter has two distinct modes of operation: 2d mode and 3d mode.

In 2d mode, the user specified function of x and y will be plotted. The output value of the function is output as a 'heat map'. Specifically, the (user modifiable) getcolor() function determines the color for a z-value. The user can use the mouse wheel to 'zoom' in and out and click and drag to pan and zoom (this is nothing more than specifying the dom in of the function). Additionally, the arrow keys will pan and the up and down arrow keys will also zoom if the shift key is pressed.

Once the user has set the function to be plotted and is satisfied with the bounds and the coloring the function can be plotted in 3d. The actual z value of the function is computed for each pixel. Vertices correspondin to each pixel in the canvas are generated and the image that was rendered in 2d mode is used as a texture to shade the vertices.

In 3d mode, there are a couple more options to be aware of: render mode, and normalize mode. There are two render modes. The first is triangle- strip mode which will render function as a solid surface. The second is point-mode where each vertex is simply rendered as a point. This often gives the impression of a mesh.

3d mouse interaction is as follows: Clicking and dragging will rotate the plot in the direction of the drag (along the x and y axis). The plot can be moved up and down by holding the shift key and dragging the mouse up and down. The plot can be rotated on the z-axis by holding the shift key while clicking and dragging left or right.

This plotter is extremely versatile and can plot absolutely any function of x and y. In fact the only limitation is inherent in the name 'function'. That is to say that this plotter can only plot functions in the mathematical sense that a function can have only one output for a given input. This means that you cannot plot spheres or cubes etc. To demonstrate the versatility of this plotter, the following code is provided to plot the mandelbrot set and the julia set. Just copy and paste the getcolor() function into the color function area and the mandelbrot() or julia() into the helper function area. Then put mandelbrot(x,y) into the expression area.

vec4 getcolor(float z)
  if (z == max - 1.0) return vec4(0,0,0,1);
  float r = z + z > 1.0 ? 1.0 / (z + z) : z + z;
  float g = z     > 1.0 ? 1.0 / (z * z) : z;
  float b = z     > 1.0 ? 1.0 / z       : z * z;
  return vec4(r, g, b, 1.0);

const float max = 100.0;
float mandelbrot(float fx, float fy) {
  float iteration  = 0.0;
  float x          = 0.0;
  float y          = 0.0;
  float xtemp      = 0.0;

  for ( float i = 0.0; i < max; ++i  )
    if ( sqrt(x * x + y * y) <= 4.0 ) {
      xtemp = x * x - y * y + fx;
      y = 2.0 * x * y + fy;
      x = xtemp;
      iteration = i;
    else{ break; }
  return iteration;

const float max = 100.0;
float julia( float x, float y ) {
  float cRe = -0.7;
  float cIm = 0.27015;
  float z = 0.0;
  float xtemp;
  for(float i = 0.0; i < max; i++)
    xtemp = x * x - y * y + cRe;
    y = 2.0 * x * y + cIm;
    x = xtemp;
    if((x * x + y * y) > 4.0) break;
    z = i;
  return z;

/// Here are some interesting functions to manipulate complex values:
/// Most of these take a vec2 as input 

#define complexMult(a,b) vec2(a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x)
#define complexMag(z) float(pow(length(z), 2.0))
#define complexReciprocal(z) vec2(z.x / complexMag(z), -z.y / complexMag(z))
#define complexDivision(a,b) complexMult(a, complexReciprocal(b))
#define complexArg(z) float(atan(z.y, z.x))
#define complexLog(z) vec2(log(length(z)), complexArg(z))
#define complexExp(z) vec2(exp(z.x) * cos(z.y), exp(z.x) * sin(z.y))
#define sinh(x) float((exp(x) - exp(-x)) / 2.0)
#define cosh(x) float((exp(x) + exp(-x)) / 2.0)
#define complexSin(z) vec2(sin(z.x) * cosh(z.y), cos(z.x) * sinh(z.y))
#define complexCos(z) vec2(cos(z.x) * cosh(z.y), -sin(z.x) * sinh(z.y))
#define complexTan(z) vec2(sin(2.0 * z.x)/(cos(2.0 * z.x) + cosh(2.0 * z.y)), sinh(2.0 * z.y)/(cos(2.0 * z.x) + cosh(2.0 * z.y)))
#define complexSinh(z) vec2(sinh(z.x) * cos(z.y), cosh(z.x) * sin(z.y))
#define complexCosh(z) vec2(cosh(z.x) * cos(z.y), sinh(z.x) * sin(z.y))
#define complexTanh(z) vec2(sinh(2.0 * z.x)/(cosh(2.0 * z.a) + cos(2.0 * z.y)), sin(2.0 * z.y)/(cosh(2.0 * z.x) + cos(2.0 * z.y)))
#define polar(r,a) vec2(cos(a) * r, sin(a) * r)
#define complexPower(z,p) vec2(polar(pow(length(z), float(p)), float(p) * complexArg(z)))
#define complexPower2(z, p) vec2(complexExp(complexMult(p, complexLog(z))))


Function Plotter

Works best in Chrome! (there are known issues with Firefox)

Please review the README for detailed documentation

Feel Free to modify the getcolor() function (just don't change it's name)
vec4 getcolor(float z)
  float r = z + z > 1.0 ? 1.0 / (z + z) : z + z;
  float g = z     > 1.0 ? 1.0 / (z * z) : z;
  float b = z     > 1.0 ? 1.0 / z       : z * z;
  return vec4(r, g, b, 1.0);

Helper function(s) ( optional -- just remember to use glsl syntax ...):
//  Write any custom functions here ...

Required: Input an expression in terms of x and y e.g.: sin( x*x + y*y )
// enter an expression to plot here (or use this example)
sin( x*x + y*y )

Current Render mode: Triangle Strip
Current Normalize mode: Normalized

Set bounds:
Min X:

Max X:

Min Y:

Max Y: