Playing with generative art

A friend of mine, David Kjellin, publisher and artist, is into the border of art and poetry, always emphasizes the element of interaction, both with the material and the consumers, when making art of this kind. David and I, whom I am met when studying philosophy at University, have had long discussions about the 'meaning' of such art.

Surely it does not convey meaning in the same way as other forms of art. But still, it conveys meaning just the same - just like music conveys meaning even when lacking lyrics. A form of non-linguistic communication that by speaking to emotions and senses may (or may not) trigger cognitive responses.

This kind of art cannot trigger cognitive responses (thoughts) in the same manner as literature, poems, or even medieval European art (in which symbols have a very clear meaning; often aiming to educate illiterates on the Bible).

Discussing this is quite meaningless in the sense that we cannot arrive at an answer. But sometimes the task of philosophy is not to provide answers, but to exclude possible answers. Anyhow, it does not matter. I enjoy art like this and find it fascinating to compare some branches of modernism (and modernity) with artists like Wassily Kandinsky, Paul Klee, and others with the generative art made with computers.

In some sense, I believe we can call this a renaissance. Today, books are written about the beauty of scientific images (be it photographs of nebulas or a enlargement of some particle). Much of contemporary art seems preoccupied (too much I think, but this is not the time and place…) with abstract dealings. In this, I perhaps should have not been too surprised when I discovered generative art to be something of a movement with an active community of hobbyists (now including me).

I think the love of beauty in shapes is something innate, a part of human nature. And generative art consists of nothing but shape and color.

An aspect I also enjoy is the interactivity. The element of "discovery" and "chance"; how you "mix" with the "settings", experiments and produces an experience you find aesthetically pleasing. Of course, there is nothing random about it (I am not speaking about random values in this context) - I think more of the aspect of our littleness, our inability to precalculate how the end-result will turn out. Although I would guess this experience is present in all artistic creations it is perhaps more apparent in a context such as this one? You're not even enclosed in 3d, but can add "time" and permits a user to participate and co-create the art in dialogue with a set-up environment (a set of 'rules').

My first attempt is very simplistic. I have used a Sierpiński triangle (triangles inside triangles, recursed to a depth), a shadow effect, and rotation (spinning a triangle until a result crystalizes).

function convertToRadians(degree) {
  return degree * (Math.PI / 180);

function sTriangle (context, depth = 4, angle = -Math.PI / 2, alpha = 0.05) {
  if(!context) {
    const canvas = document.querySelector('#animation');
    canvas.height = window.innerHeight;
    canvas.width = window.innerWidth;
    const ctx = canvas.getContext('2d');
    ctx.translate(canvas.width * 0.5, canvas.height * 0.5);
    ctx.scale(canvas.height * 0.5, canvas.height * 0.5);
    return sTriangle(ctx);
  if (depth === 0) {
    context.moveTo(Math.cos(angle), Math.sin(angle));
    for(let i = 0, a = angle; i < 3; a += Math.PI * 2 / 3, i++) {
      context.lineTo(Math.cos(a), Math.sin(a));
    context.shadowBlur = 0;
    context.shadowOffsetX = 2;
    context.shadowOffsetY = 2;
    context.shadowColor = '#bf616a';
    context.fillStyle = `rgba(0,0,0,${alpha})`;
  } else {
   for(let i = 0, a = angle; i < 3; a += Math.PI * 2 / 3, i++) {;
     context.translate(Math.cos(a) * 0.5, Math.sin(a) * 0.5);
     context.scale(0.5, 0.5);
     sTriangle(context, depth - 1, angle, alpha + 0.02);
  return context;

const drawingAngle = () => {
  let angle = 0;
  return () => angle > 360
    ? 0
    : angle++;

function animate(ctx) {
  window.requestAnimationFrame(() => animate(ctx));

const initialContext = sTriangle();
const getAngle = drawingAngle();
window.requestAnimationFrame(() => animate(initialContext));