Friday, 23 November 2018

First Meetup in Cornwall - Beginner's Intro To Creative Coding

With my move to Cornwall, Algorithmic Art will meet in both London and Cornwall on alternating months.

This month was the first meetup in Cornwall, hosted by the Royal Cornwall Museum.


Slides with examples of algorithmic art are here: https://goo.gl/RyjnVb


Algorithmic Art?

We started with a brief overview of algorithmic art, looking at examples as broad as genetic algorithms creating music, to machine learning text to create verse performed by a robot, from infinitely detailed fractal forms to objects created in code and 3D printed.

We discussed the central element of algorithmic art being a mathematical or logical recipe rtha is central to the design of the work. For some, the appreciation of algorithmic art is purely the result. For others, it is the, often surprising, beauty and intricacy, hidden in mathematics that's revealed by the artist.

For some of us, we can't appreciate algorithmic art without appreciating the algorithm!

https://twitter.com/tylhobbs/status/1043961878282739712


Gentle Introduction to Creative Coding

This first session was intended for artists who may never have coded before.

It was also a chance to meet local artist fir the first time and start to understand what people are interested in.

We've previously run beginner's introductions to creative coding with P5js / Processing.


This time we didn't use a set of slides to work through. Instead we set out a broad set of concepts we wanted to work through, and decided to work more closely with the group and only go as fast or slow as needed.



OpenProcessing Makes Coding Really Easy

A question arose early about why we weren't using the locally installed Processing software.

It became clear through the session that openprocess.org makes coding really easy for both beginners and non-beginners alike:

  • there is no need to install any software - we can create code and see the resulting drawings all in a browser, any modern browser
  • we avoid the hassle of software conflicts and versions - all that's taken care of by openprocessing
  • we don't need to worry about source code files, or html code to contain our p5js code .. we just type code into the web page and click run
  • sketches can be saved, and then shared by sharing the link, and anyone with a web browser on their computer, laptop, tablet or smartphone can see your work, including your code - that's powerful!


Structure of a Sketch

We started by looking briefly at the structure of all p5js sketches.


We talked about how the setup() section contains instructions (code) which set up the drawing environment. That would be things like canvas background colour, canvas size, and so on.

The other section draw() is where we write code that actually does the drawing.


Making Things Even Simpler With Simple.JS

As easy as p5js is, and as easy as openprocessing makes working with it .. my experience is that there are still some barriers to newcomers because the language itself isn't designed for young or new learners, and also some of the defaults aren't that friendly.

So I wrote a library called simple.js which tries to smooth off these hard edges. For example, it provides instructions like circle() and square() which are missing from p5js. It also provides a much much simpler way of doing loops using a repeat() command. Sensible defaults include a visible stroke, background colour, and a yellow fill, as well as turning of he automatic looping of draw() which is only useful for animation.

We use openprocessing to "switch on" the library, and invoke it in setup() like this.


This minimal code above, is a good starting point for many projects.


Shapes, Colours

We started by asking what the computer code for drawing a circle would be if it was an intuitive language. Most people guessed circle() .. and we tried it. We didn't spend long going over the coordinate system other than to say it starts at the top left, not bottom left.

Everyone write code to draw a circle, and then experimented with different locations and sizes.

This is the point at which everyone in the room was a coder!

We then took on the challenge of drawing two different circles. Again the group successfully worked out how to use two circle() instructions.

Someone asked why the circle was yellow. Rather a answering we progressed to using the fill() instruction to define which colour to use for filling subsequent shapes. We used the named colours, such as 'red', 'green', 'pink', which is a great way to start using colours compared to the RGB method.


The valid named colours are actually CSS colours used by web developers:


I did explain that I had chosen yellow as a sane default in simple.js because the p5js default is a transparent no-colour.

We also tried using a square() instruction just to practise and start to see the comparative similarities between code - a useful skill even for advanced coders.



Variables, Randomness

Having used numbers for location and size, we introduced the idea of using variable.


The picture above illustrates a good way of thinking about variables. Instead of using the number 10, we put it inside a box called x, and then use x instead of the number.

This might not be useful for very simple code, but for more interesting code, we can generalise a problem by using variables instead of specific numbers. You can imagine a complex drawing of many parts, all of which depending on a size variable. We only need to change the size variable once and the while drawing is correctly rescaled. We could have used the name banana but size is more descriptive.

We created variables x and y and used these in the circle instruction instead of actual numbers for location.

We then introduced a big idea - randomness. Instead of setting x and y to specific numbers, we used randomNumber() to get our computers to randomly choose a number from a range. For example var x = randomNumber(0, 800) will choose a number between 0 and 800 and put that inside the variable x.

We ran our code and found the circle was drawn at different place to someone else's code. Running the code again results in a different location again. The code is choosing a random number every time the code is run.

As an exercise, the group tried to make the size of the circles random. Everyone got that working to great satisfaction!


Functions, Repetition

We the moved onto a more advanced topic - that of packaging useful code to it can be reused. These are called functions.

We decided our code which draws a circle of random size at a random location was pretty neat. So we looked at how to package it so it could be used again and again. A fun part of doing that is giving the packaged code a name. I called mine blob()!

We saw how we can call our code simply by using its name, in my case blob(). More importantly we saw how calling blob() twice, or even four times, calls the code four times. We started to see the benefits of functions - we didn't need to write the all the code that randomly chooses a location and size and draws the circle four times - we just called blob four times.

I then set the challenge of drawing 400 circles!

We talked about not writing all the code 400 times, and we also said it wouldn't be good to write blob() 400 times either!

We know computers are good at repeating things, and they are fast, and don't get bored. And this is why many coding languages make it easy to repeat instructions.

We used the repeat() instruction to repeatedly run code In my case it was repeat(400, blob) which calls blob() 400 times.

The simplicity and power of repetition started to become very apparent! And the resulting 400 circles on the canvas were pretty cool too!

Finally we introduced the ability to randomly pick a colour from a list, a colour palette, and use that to fill each circle.

The results were impressive and a great conclusion to the session!

Here's one example:


And another:



Conclusion

The class was quite full and everyone seem to enjoy the session. I was concerned that the already-coders might be bored but they said they weren't.

Most importantly, the first time coders all seemed enthused and weren't daunted by the idea of coding.

And best of all, some said they were inspired to continue!

I did let the group know that even in this short session they had actually covered quite a few computer science and programming concepts - the idea of code structure, variables, functions, repetition, and generalisation.


Resources




Wednesday, 24 October 2018

Automata, Chaos and Emergent Behaviour

This month's meetup was an introduction and tutorial by Peter Marks on automata, chaos and emergent behaviour.


Tutorial code examples and reference links are at http://art.spluko.com/ace/.


Key Themes

Rather than spend a long time trying to define the rather abstract idea of automata, Peter decided to briefly introduce it as a thing which evolves by following simple rules, and to develop the idea during the talk.

The word state is used to describe the current state of these "things". Again, this is an abstract idea, and could mean one of many things - state could be location, or colour, or size, or how healthy a thing is feeling.


These "things" could be pretty much anything, which gives us a lot of creative opportunities, rather than a cause for discomfort.


Peter set out the key themes we would explore during this journey through automata and their behaviour.

  • Iteration - the repeated application of rules, often mathematical rules

  • Multiplicity - Creating and evolving many automata. 

  • Interaction - Allowing the evolution of automata to depend on other automata, encoded again as the simple rules that define their next state.


Simple Example

Peter presented a simple example to illustrate the abstract idea of an automaton. He used a javascript class to define an object, the 'thing" which we will consider an automaton.

The automaton was named a Circle in his code, and it had two bits of state - a colour and a size. That's all that's needed to define a simple automaton - but we can't see it. We can add capabilities to this automaton to make it visible.  Peter added a javascript class method to draw this Circle object, and another to evolve its state. Drawing takes into account the automaton's state - colour and size.

The evolution is simple. Both colour and size are incremented at each step, and reset to a small value if they reach an upper limit, to prevent them from growing ever larger. Repeated application of these simple rules is the idea of iteration we set out above.

This all sounds like a lot of words for what is essentially doing simple things - but we're framing it in the context of automata.

Here is this simple automaton evolving - both in size and colour. The code is online at https://codepen.io/spluko/pen/WaZxyM.



More Than One Automaton

Peter then progressed to simulating more than one automaton. This is the idea of multiplicity we listed above.

Peter created 300 individual automata. Each of these 300 Particles, as he called them in code, have state and a way to evolve that state. A Particle was given two bits of state - a position and a velocity.

The position is used to determine where each Particle is drawn, and the velocity is used to determine how the position changes over time, using simple school-level physics. To make the simulation a little more realistic, gravity was also used to adjust a particle's velocity. You'll remember from school that gravity is a force, which directly affects velocity, which in turn affects position.

If school physics isn't exciting you, don't worry - the main point is having multiple automata, each evolving their state according to simple rules.

The following shows how 300 Particles move according to their own velocity and also the efffect of gravity. The code is online at https://codepen.io/spluko/pen/vVeJeW.


That is a rather nice fireworks effect!

Peter developed these simple simulations, for example to enhance the rules so the automata bounce off the edge of the canvas. You can find the code at http://art.spluko.com/ace/.


Chaos

Before proceeding to illustrate interaction between automata, Peter demonstrated numerical chaos.

Intuitively, we expect simple rules to generate simple behaviour. But in fact, some simple schemes result in apparently random and apparently unpredictable behaviour - chaos. Strictly speaking, numerical chaos is not random. The behaviour of a chaotic thing can be calculated. The key point is that it is not possible to predict future behaviour by following a trend - the behaviour is too erratic. Furthermore, two chaotic systems that have very very similar state, will diverge very quickly. Chaotic systems are very sensitive to initial state - and this is basis for the very common butterfly-effect analogy.

Peter's example of numerical chaos was very simple - simply taking a number and multiplying it by a large number, and then taking a modulus (remainder after division). The resulting number are very hard to predict as they follow no obvious pattern. In fact this scheme is the basis for many random number generators in computers. You can see an illustration of this randomness at https://codepen.io/spluko/pen/bmYjLg.

A more interesting simulation is creating automata which have a simple number as their state. The rule for evolution is simply to use that number to calculate another number to become its state. That calculation is the method for creating apparently random chaotic sequences above. As the automata evolve, these chaotic sequences can be used to define curves - which end up looking like scribbles.


You can find the code at https://codepen.io/spluko/pen/dqLOGg. The effect above is achieved by, in effect, darkening the canvas before drawing the next curve. Repeating this has the nice effect of making previous curves slowly disappear.


Interaction

Peter then introduced the final idea of interactions between automata. Up to now they've been evolving independently, each unaware and unaffected by other automata in the simulation. The slight exception to this was the balls bouncing off the edge of the screen - they took the environment into account as they moved.

Peter again implemented simple school physics to model the position and velocity of each automaton, drawn as balls. The rules for evolving the state are the same simple ones we saw before, position is changed according to velocity. In addition, a check for collision is made between balls and the edge of the canvas. Bouncing off the edge is relatively simple, the velocity is reversed. Balls colliding with each other also transfer their momentum according to school physics. We won't go into the details here as the main idea is interactivity, not a class on newtonian physics.

The following shows the rather satisfying, and also surprisingly realistic, simulation of bouncing balls. They start off as a simple Newton's Cradle. In theory the cradle would continue with its regular predictable movement forever. This simulation breaks down into chaos because one of the balls has its initial position shifted by a tiny tiny 1e-13 units. This shows how sensitive the system is to initial conditions. The code is at https://codepen.io/spluko/pen/wYvMzW.


This completes the key ideas of automata as abstract "things" having state which evolves according to simple rules, iteration, multiplicity, and interaction, with a nice detour looking at chaos.


Further Examples

Peter presented further examples of automata which better demonstrate how sophisticated the visual rendering of automata behaviour can be.

The following demonstrates the evolution of particles, determined by simple mathematical rules using only sine and cosine functions. The code is at https://codepen.io/spluko/pen/QZmwyp. Experiment by changing the parameters A, B, C and D in the code.


You can read more about these De Jong attractors here, here and here.

It is worth thinking a little more about this example. We have automata which follow very simple rules, yet their paths are chaotic. But out of that chaos appears a definite pattern - the emergence of order out of chaos.

Peter also extended the previous colliding balls simulation to include repulsion when balls are too close. This has analogies in atomic physics where atoms can attract but then repel when they get too close. You can see the code at https://codepen.io/spluko/pen/GYOwXo. In this example, the balls surprisingly arrange themselves into a circle because

A very compelling example of automata interacting is when the rules are similar to how flies or birds might adjust their flights in response to their neighbours. These flies behave as follows:

  • each one tries to fly towards the centre of mass of neighbouring boids
  • they try to avoid getting too close to other flies
  • they try to match the velocity of their neighbours
These are very simply rules, and they don't seem wrong if applied to birds of flies.

The resulting motion is pleasantly surprising flocking.


You can find the code at https://codepen.io/spluko/pen/ZqRyaE.


Conclusion

Peter succeeded in explaining automata as an intentionally abstract concept of "things" with state, which evolves through the repeated application of simple rules. He also set out and illustrated the key ideas for simulating automata:

  • iteration
  • multiplicity
  • interaction

Speaking to a few attendees, the feedback was really positive, indicating a desire for more sessions covering ideas and concepts.




Tuesday, 21 August 2018

Creative Uses for Not Quite Random Noise

This month we looked at creative uses for not quite random noise, including a brief insight into how Perlin noise works.

Noise is an important algorithm for digital artists, 3d designers and is used widely in visual effects.


This month there was no video recording of the talk, so this blog will be a little more narrative than usual.

The slides are at https://goo.gl/eYgqq6 and contain links to code and further references.


Motivation - When Random Isn't Useful

We started by looking at a very simple landscape.


We asked ourselves how we could generate such a landscape using our computers. An initial suggestion is to use random numbers for the height (altitude) of each part of the terrain. That's not an entirely bad suggestion.

We looked at an example of heights created by purely random numbers. The results didn't look very realistic.


We discussed what would need to be improved to make the terrain more like a natural landscape. The main idea was that the jump between successive values was too high, and a more realistic landscape would moderate the changes. In other words, the jump up or down between consecutive values wouldn't be too large.


This is a problem that something called noise solves. It is random, but no so random, because the values vary more smoothly. Noise values are not independent of the values before and after them, unlike purely random numbers which are totally independent of each other.

The results were much more realistic.


You can see the very simple p5js code here: https://www.openprocessing.org/sketch/501546


Why Noise Needs a Parameter

Th audience was asked to pick a random number. That was easy enough. The audience was then asked to pick a noise value.  That wasn't so easy. The reason is important.

To pick a noise value, we or. the computer, needs to know were we are in relation to neighbouring noise values. Without this context, we have no way of making sure the number we pick is not too different from the neighbouring ones.

One way to know this context is to use a parameter to describe how far long the sequence of noise values we are.


And that's why the noise() function provided by your favourite library takes a parameter. Noise values for similar parameters will be similar.

To encourage us to think about this, we considered what the noise parameter was that created these rings which have had noise added to them.


An initial thought might be that the radius of these circles has noise added using the radius as a parameter. This isn't correct, because the radius is the same all the way around the circles. What various around the circles? The angle. So the radius that is drawn is the basic circle radius plus noise(angle).


Two Dimensional Noise

Before thinking about two-dimensional noise, we looked at 2-dimensional randomness. The following shows a 2-dimensional array filled with random numbers, represented by colours from a grey scale.


As expected, the image is random, with no intentional pattern.

In contrast, 2-dimensional noise does have a discernible structure. The following is the same grid but with noise values deciding the colour of each pixel. The blue to white scale makes the image look like a photo of clouds.


Just as before, the noise values don't vary wildly, but change in a more moderated way as we follow them up or across the grid. It's easy to see that a 2-dimensional noise function takes 2 parameters so that it knows how far along and up the sequence of noise values it is.

The code for these clouds is at https://www.openprocessing.org/sketch/502021.


3D Landscape

Thinking back to the green landscape we started with, why don't we try again to recreate it more realistically. We don't actually need to implement a proper 3-dimensional model with perspective and so on. We can just have layers of 2-dimensional "fences" which have their height set using 2-dimensional noise.


We can start with a grid of points, which will be the points which will be raised (or lowered) according to the noise values at that position.


The results are impressive, given the simplicity of the idea.


That really does look like some kind of alien terrain, perhaps a scan of a planet's surface before landing...


Multiple Octaves of Noise

By stretching or squishing the parameters so they change slow for faster, we can control how lumpy or smooth the surface is. We saw this earlier in the talk with a simple 1-dimensional noise too.


It is common practise to combine different "octaves" of noise to have a result that has both a macro structure as well as finger-grained micro-structural detail.

You might be familiar with this idea from music or electronic signal processing.


Here's a comparison of a smooth landscape with one that has had finer-grained higher-frequency noise added to it.



Refining the Landscape

That landscape is simple and very effective. But we can do more with it.

Here is the landscape generated with 800 points. To avoid over saturation, each dot has been drawn with a high translucency. This allows detail to re-emerge even with large numbers of points being drawn - a broadly applicable technique.


The code for this sketch is at https://www.openprocessing.org/sketch/504970.

We can use the noise values, not just to determine the landscapes height, but also the colour. Here is an example showing more Earth-like greens and blues.


We can even cut-off the lower values to create what looks like a lake or a sea.


After seeing these examples, it's not a surprise that noise is used to generate landscapes in games and films.


Simple Textures

We looked at how noise can be used to generate textures - in fact, a common use for noise. Here is the simple starting point showing rings created by sin waves using the distance from the centre of the canvas as a parameter.


That's fairly regular as we'd expect. We can adjust the colour that's drawn using 2-dimensional noise that takes the (x,y) position as parameters. The result looks remarkably like wood or a sliced rock.


It doesn't take much to refine this further to make it look like polished wood - a slight change of colour palette and a vertical squish.


The code for this wood effect is at https://www.openprocessing.org/sketch/577875.

We also looked at an agate texture which is just the above but with a green-blue colour scale. We evens saw the use of noise to create a lumpy fog effect to be used in ray-tracing a 3-d scene.

Noise to create texture is a very popular technique, used directly by coders or indirectly by using modelling tools which provide textures based on noise.



Genuinely 3-Dimensional Noise

So ar we've only used 1-dimensional and 2-dimensinal noise, even when we're creating 3-dimensional scenes. The height values for the landscape are based on noise(x,y) for example.

It is possible to have 3-dimensional noise, based on 3 parameters.


The results can be used to create 3-dimensional structures. Some games use noise to create worlds which include caves.



Animated Noise

An interesting idea is to take 2-d slices of 3-d noise, and use that 3-rd parameter as time, or frame count. This way we can animate the 2-d slices.

We expect the resulting patterns to be smoothly changing because noise should vary smoothly along all its dimensions, inlacing any we consider time.

Here is an example of moving lava created by taking 2-d slices of 3-d noise and using a threshold to decide the colour.


That's rather effective! The simple code for this lava is at https://www.openprocessing.org/sketch/577863.


How Perlin Noise Actually Works

Many guides sadly don't give any insight into how this really useful not-so-random noise is actually created.

I wrote a blog explaining it on another blog http://makeyourownalgorithmicart.blogspot.com/2018/02/randomness-and-perlin-noise.html

Briefly, we discussed how even interpolating between random values wasn't good enough. That's because we have sharp bends (discontinuities) which we don't want for our smoother noise.


Even applying a smoothing function to this linear interpolation still has a problem.


The problem is that values that come from this process could remain high for too long a sequence, or alternatively, they could flip positive and negative too often. That is, the frequency is too free. Yo may be familiar with the term bandwidth-limited, which says that the frequency with which a signal is allowed to fluctuate is limited to a range. We want our noise to be band-width limited.

So a different approach is used. We start with a grid of regularly spaced points, but this time we place random unit vectors at each point. Their directions are totally random, and that's ok.


We then take a candidate point at x, and calculate the dot product of the vector from the previous grid point to x and the random unit vector at that grid point. Dot products, when normalised, only vary between -1 and +1 like a cosine wave. That gives us a nice smoothness (very smooth in fact because the first and second and derivatives of this value are also smooth). The dot product of the next unit vector and the vector from the next grid point to x is also calculated and the two are combined, even a simple addition is fine.

As x moves along the axis, the values that result from this process are smooth, based on an underlying pure randomness, and importantly are limited in frequency. You can see that between any two grid points, the values can only flip once or never. That gives us a tight bound on frequency.


You can find a Python notebook demonstrating this idea here:



Real libraries providing noise will combine several octaves of signals generated like this. And the extension to more than 2 dimensions still follows this basic idea.


OpenSimplex Noise

Ken Perlin, who invented the Perlin noise algorithm, updated it a few years later to address some weaknesses. In higher dimensions, the original algorithm started to display patterns that were too regular and not the desired lumpy noise.

Have a look at the following comparison. The top row is too "straight" in parts.


His updated algorithm was patented, so sadly is not open source friendly. Luckily, the open source community developed an open algorithm called OpenSimplex which you can find out more here:



I had previously used OpenSimplex to create 3-d textures for ray traced objects. This works better than mapping a 2-d pattern into 3-d spheres, which suffers from the well-known map projection distortion issues.



Moving Particles

Finally we looked at a rather different use of noise.

Following the path of one, or many, particles which move in a random direction at each step is a well known experiment. The results of can look interesting if we use the translucency technique to avoid over-saturation.


What if we changed the way these particles moved, so that they took a step in a direction determined by noise and not pure randomness?

The results are spectacular!


The image really looks like a pen and ink work. Amazing, given the simplicity of the underlying idea.

You can explore the code yourself at https://www.openprocessing.org/sketch/578607.

As a final extra idea, we can use an image like the following, and move particles based on the underlying colour/luminosity.


We can use the luminosity to determine the colour and the length of the stroke drawn at a point. the results is rather hairy!


You can explore the code here https://www.openprocessing.org/sketch/533299.


Feedback and Examples

Peter developed a couple of really nice animated sketches during the class using noise - take a look, they're really effective.



I was a little unsure if the audience would be bored by a talk which took a beginner-friendly approach and kept things fairly simple. I was pleased that quite a few people responded positively and - best of all - said they'd go and try using noise themselves!