CindyGL

Jürgen Richter-Gebert and Aaron Montag

ICMS 2016

What is CindyGL?

f(z) := z^7 - 1;
colorplot(
  hue(im(log(f(complex(#)))) / (2*pi));
);
  • a plug-in for CindyJS.
  • provides access to the GPU fragment shader via WebGL.
  • WebGL: a JavaScript API for interactive 3D and 2D graphics without the use of plug-ins.

Why CindyGL?

t = seconds() - t0;
colorplot(
  (sin(|A,#|-t) + sin(|B,#|-t) + 2) 
   * (1/2, 1/3, 1/4) // rgb-vector
);

few line of code

efficient as native applications

  • Aim: Making WebGL easy for mathematically oriented users.
  • One programming language for both CPU and GPU
  • Tool for high level parallelization

Raycasting algebraic surfaces

F(x,y,z) = x2 + y2 + z2 + 2 ⋅ xyz − 1 = 0

  • possible using colorplot:
    • For every pixel #:
      • compute intersection of corresponding ray with surface
      • colorize according to normal of surface at intersection point

Technical background


colorplot(
  polyvalues = evaluate_F_at_ray(#);
  poly = inverse(
   [[0^0, 0^1, 0^2, 0^3],
    [1^0, 1^1, 1^2, 1^3],
    [2^0, 2^1, 2^2, 2^3],
    [3^0, 3^1, 3^2, 3^3]
   ])*polyvalues; // interpolate
   
  // ray intersection
  x = ray(#, firstroot(poly)); 
  
  // shading using dF
  colorize(x)
);

What happens if colorplot(...#...) is called?

  1. Obtain syntax tree of expression
  1. Extract those terms that dependent on # suitable for parallelization on GPU
  1. Detect the types
  1. Transpile into Shading Language
  1. Loading of textures, embedding into the WebGL-API

Image Feedback loops

Fractals (Julia set)

Initialization:

createimage("julia", 400, 400);

Rendering:

colorplot("julia", // plots to texture
 z = complex(#);
 // if |z|<2 take the color at z^2+c 
 if(|z|<2,
  imagergb("julia", z^2+c)// and make
   + (0.01, 0.02, 0.03),  // it brighter
 // otherwise: display black.
  (0, 0, 0)
 )
);

Enhancement: Conjugation

  • Internal computations can be done on an exp-log-conjugated texture.
  • Center of this conjugation: a fixed point of z2 + c.

Generating Fractals (IFS)

w1=map(A, B, C,  A, D, F); //matrices for
w2=map(A, B, C,  D, B, E); //affine maps
w3=map(A, B, C,  F, E, C);

colorplot("ifs", //plot and read same texture
  hom = [#.x, #.y, 1]; //Homogeneous coordinate
  imagergba("ifs", inverse(w1)*hom) +
  imagergba("ifs", inverse(w2)*hom) +
  imagergba("ifs", inverse(w3)*hom)
);

CAs (Game of Life)

get(x, y) := //function that reads texture "gol" as T2
  imagergb("gol", (mod(x, 80), mod(y, 80))).r;

newstate(x, y) := ( number = // # living neighbors
 get(x-1, y+1) + get(x, y+1) + get(x+1, y+1) +
 get(x-1, y) +                 get(x+1, y) +
 get(x-1, y-1) + get(x, y-1) + get(x+1, y-1);
 if(get(x,y)==1, //cell lives and less than 2 
                 //or more than 3 neighbors -> die
  if((number < 2) % (number > 3), 0, 1),
                 //cell dead + 3 neighbors -> born
  if(number==3, 1, 0)
 )
);

colorplot("gol", newstate(#.x, #.y));

A reaction diffusion system

  • Another application of feedbackloops: Numerical simulations of PDEs.
  • Here:

x′=a2x − xy2 + f (1 − x)

y′=b2y + xy2 − (f + k)y

Further work

  • Implement high-dimensional (>4) vectors and matrices
  • Not all operations have been transfered to Shading Language yet
  • Use floating-point expansions for higher accuracy (similarly to CAMPARY)

Function Explorer

Thank you!

Do you have any questions?