Javascript, Processing, Scripts, Tutorials
comments 6

Generative Art In HTML5 [Processing, JavaScript, Tutorial]

generativehtml501

(A Generative Art Lost Chapter)

Through the process of writing Generative Art there were various tangents and miscellaneous-mad-shit that, usually in the name of brevity and clarity, ended up on the cutting room floor. What follows is one such tangent reworked into a brief tutorial. In the week that the Processing 2.0 Beta gets its release this would seem an appropriate time to share this on CAN, as it mentions one of P5-2′s coolest features: publishing to HTML5.

The tutorial is in three sections:

1. “… A Practical Guide Using HTML5″

To me, the why is always as important as the how. So first allow me to explain why this is relevant, even though it didn’t make the book.

2. Processing to JavaScript – The Ridiculously Easy Way

HTML Canvas for Processing Users. The two minute version.

3. Generative Art in JavaScript – The Harder, But Still Ridiculously Easy, Way

Cutting out the middle man. How you might get started with nothing but a JavaScript enabled browser to hand.

1. “… A Practical Guide Using HTML5″

Generative Art: A Practical Guide Using Processing was, as the title suggests, a book about generative art. But it was not necessarily, as the subtitle might suggest, a book about Processing. In it I spent the best part of a chapter making the case for why I chose Processing as the best tool for exploring the subject, and the book contains a complete beginners guide to the language, but I never wanted the reader to mistakenly believe Processing was the only tool they could use in their explorations of the subject matter.

In my original proposal I had the stupid idea of making the book entirely language agnostic, having the examples in a form of meta-code, which the user could adapt to their tech of choice. With hindsight I now appreciate this would have been a terrible idea, as what I might gain in shiny-happy all inclusiveness, I’d lose in clarity of message. Any extra thinking required on the part of the reader, adapting pseudo-code, would be an unnecessary barrier in getting from algorithm to sexy visuals.

Other ideas I toyed with, to hammer home the universality of these concepts, was to use multiple languages, or even do alternative editions of the book. Generative Art: A Practical Guide Using HTML5 seemed the obvious one to do first, as the Canvas/JavaScript combo is pretty hot right now. But, still, wouldn’t that just be redirecting the question rather than answering it?

Also, just around the corner was Processing 2.0, which would be a further step toward rendering this idea pointless. In Processing 1.5 the new concept of IDE states was introduced. A button toggles the compilation target between “Standard” (publish to the desktop or an applet) or “Android”, that allows you to publish to devices. Processing 2.0 adds a third option, “JavaScript”, which allows you to publish direct to HTML5 Canvas (using the now in-built Processing.js). And it works. It just works.

This doesn’t mean the computer code Tower of Babel is about to fall any day soon, but it was a significant enough advance to convince me not to waste my time on a meta-code/language-agnostic edition of the book, nor a series of quantum uncertain language multiverse editions. Instead, a very quick demonstration of how easily the generative concepts in the book can be realised in JavaScript as well as Processing, should suffice. I can then leave it with you to explore further.

Below I’m going to take the very first code example from my book and convert it to JavaScript. First the easy way, publishing it to JavaScript from the IDE. Second, a better, dirtier approach; coding in JavaScript direct.

2. Processing to JavaScript – The Ridiculously Easy Way

JavaScript has a very similar syntax to Processing, but the significant difference is context, context, context. A tool which is perfect for one scenario is not necessarily the best for another. HTML5′s obvious strength is in targeting the web, as it runs in a web browser natively, i.e. without any need for a plug in (like Flash or Java). It has disadvantages too though, first that it currently requires the most modern browsers (Google Chrome, Firefox 5+, Safari…), second that it is rather slow, especially if you are used to coding Processing, ActionScript or C++. But if we take these factors into consideration we can work with or around them and produce some easy in-browser GenArt.

If you are running a compatible browser you can see the simple generative animation we’ll end up with in the header of zenbullets.com.

Lets start with a chunk of Processing code, adapted from the example on page xxiii of my book’s intro. I’m assuming you’ve a rudimentary knowledge of Processing if you are reading this section. If you haven’t: see either Chapter 2 of my book, the online tutorials, or one of the other great Processing books out there. If you’re just here for the JavaScript, feel free to skip ahead to part 3.

 

float xstart, ystart, squaresize;

void setup() {
  size(500, 500);
  background(150);
  xstart = random(10);
  ystart = random(10);
  squaresize = height/8;
}

void draw() {
  fill(150, 150, 150, 15);
  noStroke();
  rect(0, 0, width, height);

  stroke(0, 50);
  fill(255, 200);

  xstart += 0.02;
  ystart += 0.01;

  translate(width/2, height/2);
  float ynoise = ystart;
  for (float y = -squaresize; y <= squaresize; y+=3) {
    ynoise += 0.02;
    float xnoise = xstart;
    for (float x = -squaresize; x <= squaresize; x+=3) {
      xnoise += 0.02;
      drawPoint(x, y, noise(xnoise, ynoise));
    }
  }
}

void drawPoint(float x, float y, float noiseFactor) {
  pushMatrix();
  translate(x * noiseFactor * 4, y * noiseFactor * 4);
  float edgeSize = noiseFactor * 20;
  ellipse(0, 0, edgeSize, edgeSize);
  popMatrix();
}

There are only two significant changes from the book version.

Firstly I’ve made it 2D rather than 3D, purely for the sake of simplicity. HTML5 can do 3D (the most sophisticated way of doing so being three.js currently), and Processing.js also handles 3D using WebGL, but there is a little more overhead doing this in the browser, which this example doesn’t need for such a simple effect. This change is just two lines:

size(500, 500);

and

translate(x * noiseFactor * 4, y * noiseFactor * 4);
float edgeSize = noiseFactor * 20;

I also made the canvas smaller with the size() change.

Secondly, the book version was designed to produce oversized, print quality, static images. For the browser it’d be more interesting if it were to animate. To do this I moved the significant drawing code from setup() to draw(), and added these lines:

xstart += 0.02;
ystart += 0.01;

… which makes the noise values ripple across frames (see Chapter 4 of my book for a fuller explanation of this technique).

Copy/paste this code into the Processing IDE (the code is here) and you’ll see something like the image above. Then, if you have Processing 2.0 (you can download the pre-release from here), you can switch the context to “JavaScript” and publish it to a HTML Canvas. And you’ll end up with this.

That’s all there is to it.

Too easy? Lets try it again, but without the safety net this time.

3. Generative Art in JavaScript – The Harder, But Still Ridiculously Easy, Way

So we’ve got a magic button which does all the work for us. But there’s a lot to be learned by understanding how the trick works behind the curtain. The point I’m trying to make with this tutorial is that, while it is a very useful convenience, we don’t actually need Processing to realise our ideas. So let’s try coding it directly in JavaScript ourselves.

It’s not hard. Allow me talk you through two steps.

Step 1: The context.

All you need to get started is a canvas tag, a JavaScript function to draw to it, and a command to trigger that function. This is all contained in the following HTML:

<html>
 <head>
  <script type="application/javascript">
	function setup() {
         var canvas = document.getElementById("scrawl");
         var ctx = canvas.getContext("2d");
         ctx.fillStyle = "rgb(255, 0, 0)";
	 ctx.fillRect (10, 10, 60, 60);
	}
  </script>
 </head>
 <body onload="setup()">
   <canvas id="scrawl" width="720" height="180"></canvas>
 </body>
</html>

You can see this running here. For consistency with Processing, I named the JavaScript function setup(). It is called from the “onload” event in the HTMLs <body> tag. The function establishes a reference to the canvas, then draws a red square just to prove it’s working.

Next, lets implement an equivalent of Processing‘s draw() function. We do this by creating an “interval“, and telling it to call our draw() function every 50 milliseconds (equivalent of setting a framerate in Processing).

var interval;
var width, height;
var x, y;

function setup() {
	width = 720;
	height = 180;
	canvas = document.getElementById("scrawl");
	ctx = canvas.getContext("2d");
	x = 0;
	y = 10;
	interval = setInterval(draw, 50);
}

function draw() {
	ctx.fillStyle = "rgba(255, 255, 255, 0.1)";
	ctx.fillRect (0, 0, width, height);

	x += 5;
	if (x > width) { x = 0; }
	ctx.fillStyle = "rgb(255, 0, 0)";
	ctx.fillRect (x, y, 60, 60);
}

I’ve also set up some variables, width, height, x, y, etc… You’ll notice JavaScript doesn’t require you to set the type of your variables (int, float, whatever), we just use var. Similarly, functions don’t need return types, we don’t need to define each function with void. In this sense it is easier to code, but consequently also easier to make mistakes.

Setting the fill style and drawing the rectangle show us how the Canvas syntax differs. The rest of the code is pretty much identical to Processing. Defining the fill style is done by setting a parameter rather than calling a function, I’ve done it in the form of a “rgb” (or “rgba” if we are using an alpha value too) string. This is a bit like setting a parameter in CSS, if you are familiar with that. Note that while the three colours values are 0 to 255, the alpha value is in the range 0.0 to 1.0.

The fillRect function is a direct equivalent of rect() in Processing, with the same four parameters.

You should now have a square skimming the screen, like so, with the canvas partially cleared between frames with a transparent rectangle to create a fade effect.

Okay, we’ve got the context. Now we just need to cram our Processing sketch into it.

Step 2: The Magic

The lions share of this next step was hitting copy and then paste from the Processing version above. But I also made a number of modifications, for either artistic or syntactical reasons, which I’ll talk you through. The final animation is here (use “view source” in your browser to get at the code).

We’ll take it in three chunks. Firstly, the setup:

var canvas, ctx;
var interval;
var width, height;

var perlin;
var xanchor, yanchor, midx, midy, xposnoise, yposnoise;
var xstart, ystart;
var squaresize;

function setup() {
	width = 720;
	height = 180;
	canvas = document.getElementById("scrawl");
	ctx = canvas.getContext("2d");

	xanchor = 550;
	yanchor = 50;
	perlin = new SimplexNoise();
	xstart = Math.random() * 10.0;
	ystart = Math.random() * 10.0;
	xposnoise = Math.random() * 10.0;
	yposnoise = Math.random() * 10.0;
	squaresize = 22;

	interval = setInterval(draw, 50);
}

There’s much that is already familiar here. We’ve defined a width and height, a reference to the canvas, and at the bottom, an interval to trigger the draw loop. All this is from the previous example.

The first change is defining xanchor and yanchor. To fit my 750×180 header I wanted the animation offset to the right – these variables set that position. But these variables don’t stick with these values, I will use Perlin Noise to make that point gently drift around when we get to the draw loop.

Perlin Noise, which is discussed at length in Chapters 3 and 4 of my book, isn’t built into JavaScript in the same way it is with Processing. But this isn’t a problem, we just find someone cleverer than us (there’s always someone cleverer than us) who has already coded up a JavaScript port and shared it. I went with one knocked together by the mighty Sean “banksean” McCulloch, which he has published here. Once downloaded we include it in the page, and so make it available to our code, with the HTML statement:

<script type="application/javascript"
   src="perlin-noise-simplex.js"></script>

It is then initialised in the setup() function with the line

perlin = new SimplexNoise();

We’ll see how this is used in the draw() loop in just a mo.

The remaining lines set four variables xstart, ystart, xposnoise, yposnoise with a random floating point number between 0 and 10 (again, note how the syntax for this differs slightly, but not greatly, from Processing). We’ll see how these are used in a second too. The squaresize variable defines how many rows and columns we have in the grid, just as it did in the Processing version.

Next, the draw() loop:

function draw() {
  ctx.fillStyle = "rgba(255, 255, 255, 0.1)";
  ctx.fillRect (0, 0, width, height);

  ctx.strokeStyle = "rgba(0, 0, 0, 0.15)";
  ctx.fillStyle = "rgba(255, 255, 255, 0.6)";

  xposnoise += 0.02;
  yposnoise += 0.01;
  midx = xanchor + Math.floor(perlin.noise(xposnoise, 0) * 50);
  midy = yanchor + Math.floor(perlin.noise(yposnoise, 0) * 50);
  xstart += 0.02;
  ystart += 0.01;
  var ynoise = ystart;
  for (var y = -squaresize; y < squaresize; y++) {
   ynoise += 0.02;
   var xnoise = xstart;
   for (var x = -squaresize; x < squaresize; x++) {
    xnoise += 0.02;
    var nFactor = Math.abs(perlin.noise(xnoise, ynoise));
    drawPoint(x, y, nFactor);
   }
  }
}

First it sets a style and draws a semi-transparent rectangle, as in the previous example, to create the fade effect. Then it sets the stroke and fill styles it will use to draw the 44×44 grid of undulating circles. If you read down the code a little further you’ll see two for loops that iterate from -squaresize to squaresize in the x and y directions to create this grid.

Next, xposnoise and yposnoise are bumped and then used to calculate the constantly shifting centre point, relative to the xanchor and yanchor variables we defined. By increasing these values slightly with each frame the resultant noise value changes gradually:

midx = xanchor + Math.floor(perlin.noise(xposnoise, 0) * 50);
midy = yanchor + Math.floor(perlin.noise(yposnoise, 0) * 50);

These two lines put our centre point into the variables midx and midy. I won’t go into how Perlin Noise works (see the book), but just draw your attention to the JavaScript syntax for returning the value – perlin.noise(xin, yin) * range – and rounding it down to an integer – Math.floor(value). Sean’s noise function is hardcoded to calculate two-dimensional noise, but we leave the y value as 0 to calculate it in just one-dimension.

The loop within a loop then does something similiar to get a nFactor variable, a two dimensional noise value, for each grid location. This is then passed to the drawPoint() function, which draws the circle at that point (just as it did in the Processing version). As before, the technique here is best described in Chapter 4 of my book, just note how the syntax is pretty much identical to the Processing version you saw in Part 2 above.

Finally, the drawPoint() function, which demonstrates how we draw a circle to Canvas.

function drawPoint(ex, why, noiseFactor) {
	var x = midx + (ex * noiseFactor * 13);
	var y = midy + (why * noiseFactor * 9);
	var edgeSize = noiseFactor * 26;

	ctx.beginPath();
	ctx.arc(x, y, edgeSize, 0, Math.PI*2,true);
	// x, y, rad, start angle, end angle, anti/clockwise
	ctx.fill();
	ctx.stroke();
}

Canvas doesn’t have an ellipse() function, but arc() does just as well, if in a slightly more trigonometric style. We pass it a centre point x and y, a start and end angle, and an optional boolean flag to tell it to go clockwise or anti-clockwise. If we make the start and end angle cover 360 degrees (which is 2 * PI in radians) we draw a circle.

The command beginPath() is the JavaScript equivalent of beginShape(). Notice that we don’t define whether the shape is to be a filled or outline shape (fill() or noFill() in Processing) until after the path is defined. Calling ctx.fill() draws the previously defined arc as a filled shape, with the “fillStyle” we set earlier, then ctx.stroke() renders the same shape again as an outline, using the “strokeStyle” last defined. This may feel slightly counter to the more usual sequential processing of instructions you may be used to, but it’s not particularly hard to get your head around.

And that’s all there is to it. I’m pretty sure my JavaScript isn’t perfect (much like my Processing), and there are probably smoother ways of achieving what I was trying to do. But that’s not important, it’s not the point here. All I wanted to demonstrate is how easy it is to adapt to a foreign language, and how any techniques you develop using Processing will translate to JavaScript, or other languages, without too many headaches.

Have fun.

Artists have always explored new media, and computer-based artists are no exception. Generative art, an emerging technique where print or onscreen images are created by use of computer algorithms, finds the artistic intersection between programming, computer graphics, and individual expression.

Generative Art presents both the technique and the beauty of algorithmic art. In it, you’ll find dozens of high-quality examples of generative art, along with the specific programmatic steps author and artist Matt Pearson followed to create each unique piece. The book includes concise tutorials for each of the technical components required to create the book’s examples, and it offers countless suggestions for how you can combine and reuse the various techniques to create your own works.

Available from amazon.comamazon.co.ukamazon.caamazon.cnamazon.framazon.de,amazon.co.jpManning (eBook)bulkbuy discounts.

Read CAN review here.

Processing.org fall 2011 T-Shirt Fundraiser

The team behind Processing has just kicked off a new t-shirt fundraiser with the TOXI design by Karsten Schmidt. You can browse the design in the Shop and at their partner Wire & Twine. This shirt is on sale only until 19 September 2011.

All profits support Processing development!

 

  • Alistair

    Very exciting news! I can’t seem to get Processing 2.0 beta to work with Toxiclibs. Does anyone have any ideas how to get  this to work? Thanks!

  • http://twitter.com/blprnt blprnt

    Hi Alistair - http://haptic-data.com/toxiclibsjs/

  • Marden

    html5 is gayshit

  • http://twitter.com/alidrongo alistair colling

    Much obliged, thanks Jer

  • David Humphrey

    Fantastic article.  I wrote a response on some other ways to mix the Processing and JavaScript, http://vocamus.net/dave/?p=1360.

    Dave Humphrey (humphd)

  • David Humphrey

    Fantastic article.  I wrote a response on some other ways to mix the Processing and JavaScript, http://vocamus.net/dave/?p=1360.

    Dave Humphrey (humphd)