review of noise chap

pull/19/head
Patricio Gonzalez Vivo 9 years ago
parent 6f05911da8
commit be5d044355

@ -3,7 +3,7 @@
## Noise
Break time! We have been playing with all this random functions that looks like TV white noise, our head is still spinning around thinking on shaders, and our eyes are tired. Time to get out for a walk!
It's time for a break! We have been playing with all this random functions that looks like TV white noise, our head is still spinning around thinking on shaders, and our eyes are tired. Time to get out for a walk!
We feel the air in our skin, the sun in our face. The world is such a vivid and rich place. Colors, textures, sounds. While we walk we can't avoid noticing the surface of the roads, rocks, trees and clouds.
@ -15,24 +15,14 @@ We feel the air in our skin, the sun in our face. The world is such a vivid and
![](texture-05.jpg)
![](texture-06.jpg)
The stochasticity of this textures could be call "random", but definitely not the type of random we were playing before in the previus chapter. The “real world” is such a rich place! It's rando is way complex. How we can approximate to this level of variety computationally?
The stochasticity of this textures could be call "random", but definitely they don't look like the random we were playing before. The “real world” is such a rich and complex place! So, how can we approximate to this level of variety computationally?
This was the question [Ken Perlin](https://mrl.nyu.edu/~perlin/) was trying to solve arround 1982 when he was commissioned with the job of generating "more realistic" textures for a new disney movie call "Tron". In response to that he came up with an elegant *oscar winner* noise algorithm.
This was the question [Ken Perlin](https://mrl.nyu.edu/~perlin/) was trying to solve arround 1982 when he was commissioned with the job of generating a "more realistic" textures for a new disney movie call "Tron". In response to that he came up with an elegant *oscar winner* noise algorithm. No biggie.
![Disney - Tron (1982)](tron.jpg)
The following is not the clasic Perlin noise algorithm, but is a good starting point to understand how to generate *smooth random* aka *noise*.
In the following graph you will see what we were doing on the previus chapter, obtaining ```rand()``` numbers of the integers of the `x` position (assigning it to `i` variable), while we keep the [```fract()```](.../glossary/?search=fract) part of it (and storing it on the `f` variable).
You will also see, two commented lines. The first one interpolates linearly between the random value of the integer position and it next one.
```glsl
y = mix(rand(i), rand(i + 1.0), f);
```
Uncomment it an see how that looks. See how we use the [```fract()```](.../glossary/?search=fract) value store in `f` to [```mix()```](.../glossary/?search=mix) the two random values.
<div class="simpleFunction" data="
float i = floor(x); // integer
float f = fract(x); // fraction
@ -41,21 +31,31 @@ y = rand(i);
//y = mix(rand(i), rand(i + 1.0), smoothstep(0.,1.,f));
"></div>
In this lines we are doing something similar than the previus chapters, We are subdividing a continus floating value (```x````) in integers (```i```) using [```floor()```](.../glossary/?search=floor) and obtaining a random (```rand()```) number for each integer. At the same time we are storing the fractional part of each section using [```fract()```](.../glossary/?search=fract) and storing it on the ```f``` variable.
After that you will also see, two commented lines. The first one interpolates each random value linearly.
```glsl
y = mix(rand(i), rand(i + 1.0), f);
```
Go ahead and uncomment this line an see how that looks. We use the [```fract()```](.../glossary/?search=fract) value store in `f` to [```mix()```](.../glossary/?search=mix) the two random values.
At this point on the book, we learned that we can do better than a linear interpolation. Right?
The following commented line, will transfor the linear interpolation of `f` with a [```smoothstep()```](.../glossary/?search=smoothstep) interpolation.
Now try uncommenting the following line, which use a [```smoothstep()```](.../glossary/?search=smoothstep) interpolation instead of a linear one.
```glsl
y = mix(rand(i), rand(i + 1.0), smoothstep(0.,1.,f));
```
Uncomment that line and notice how the transition between the peaks got smooth. On some noise implementations you will find that people that some programers prefere to code their own cubic curves (like the following formula) instead of using the [```smoothstep()```](.../glossary/?search=smoothstep).
After uncommenting it, notice how the transition between the peaks got smooth. On some noise implementations you will find that some programers prefere to code their own cubic curves (like the following formula) instead of using the [```smoothstep()```](.../glossary/?search=smoothstep).
```glsl
float u = f * f * (3.0 - 2.0 * f ); // custom cubic curve
y = mix(rand(i), rand(i + 1.0), u); // using it in the interpolation
```
The *smooth random* is a game changer for graphical coders, it provides the hability to generate images and geometries with an organic feeling. Perlin's Noise Algorithm have been reimplemented over and over in different lenguage and dimensions for all kind of uses to create all sort of mesmerizing pieces.
The *smooth random* is a game changer for graphical engeneers, it provides the hability to generate images and geometries with an organic feeling. Perlin's Noise Algorithm have been reimplemented over and over in different lenguage and dimensions for all kind of creative uses to make all sort of mesmerizing pieces.
![Robert Hodgin - Written Images (2010)](robert_hodgin.jpg)
@ -71,31 +71,33 @@ Now is your turn:
![](02.png)
Now that we know how to do noise in one dimension, is time to port it to two. For that instead of interpolating between two points (```fract(x)``` and ```fract(x)+1.0```) we are going to interpolate between the four coorners of square (```fract(st)```, ```fract(st)+vec2(1.,0.)```, ```fract(st)+vec2(0.,1.)``` and ```fract(st)+vec2(1.,1.)```).
Now that we know how to do noise in 1D, is time to port it to 2D. For that instead of interpolating between two points of a line (```fract(x)``` and ```fract(x)+1.0```) we are going to interpolate between the four coorners of a square area of a plane(```fract(st)```, ```fract(st)+vec2(1.,0.)```, ```fract(st)+vec2(0.,1.)``` and ```fract(st)+vec2(1.,1.)```).
![](01.png)
Take a look to the following 2D noise function, see how on line 32 we interpolate random values (lines 25-28) acording to the the position of ```st``` the four corners of the squared area.
Similarly if we want to obtain 3D noise we need to interpolate between the eight coorners of a cube. This technique it's all about interpolating values of random. That's why is call **value noise**.
![](04.jpg)
If you pay atention is not just a linear interpolation but a cubic one which smoothly interpolates any points inside a squared grid
Similarly to the previus example this interpolation is not liner but cubic, which smoothly interpolates any points inside our squared grid
![](05.jpg)
In the following implementation of 2D noise we scale the size of the grid by 5 (line 41).
Take a look to the following noise function.
<div class="codeAndCanvas" data="2d-noise.frag"></div>
We start by scaling the space by 5 (line 45) in order. Then inside the noise function we subdived the space in cells similarly that we have done before. We store the integer position of the cell together with fractional inside values. We use the integer position to calculate the four corners corinates and obtain a random value for each one (lines 23-26). Then, finally in line 35 we interpolate 4 random values of the coorners using the fractional value we store before.
Now is your turn, try the following excersices:
* Change the multiplier. Try to animate it.
* Change the multiplier of line 45. Try to animate it.
* At what level of zoom the noise start looking like random again?
* At what zoom level the noise is imperceptible.
* Change the u_time by the normalize values of the mouse coordinates.
* Try to hook up this noise function to the mouse coordinates.
* What if we treat the gradient of the noise as a distance field? Make something interesing with it.
@ -105,19 +107,19 @@ Now is your turn, try the following excersices:
## Using Noise on generative designs
As we saw, noise algorithms was original designed to give a natural *je ne sais quoi* to digital textures. Our first step to use it will be to differenciate different types of noise algorithms. So far all the implementations in 1D and 2D we saw, were interpolation between values and so they are usually call **Value Noise**.
As we saw, noise algorithms was original designed to give a natural *je ne sais quoi* to digital textures. So far all the implementations in 1D and 2D we saw, were interpolation between values reason why is usually call **Value Noise**, but there are more...
[ ![Inigo Quilez - Value Noise](value-noise.png) ](../edit.html#11/2d-vnoise.frag)
As you discovery on the previus excercises this type of noise tends to look "block", as a solution to this effect in 1985 again [Ken Perlin](https://mrl.nyu.edu/~perlin/) develop another implementation of the algorithm call **Gradient Noise**. In it what is interpolated per coorner is not a value but a direction (represented by a ```vec2```).
As you discovery on the previus excercises this type of noise tends to look "block", as a solution to this effect in 1985, again, [Ken Perlin](https://mrl.nyu.edu/~perlin/) develop another implementation of the algorithm call **Gradient Noise**. In it Ken figure out how to interpolate **random gradients** instead of values. This gradients where the result of 2D noise function that returns directions (represented by a ```vec2```) instead of single values (```float```). Click in the foolowing image to see the code and how it works.
[ ![Inigo Quilez - Gradient Noise](gradient-noise.png) ](../edit.html#11/2d-gnoise.frag)
Take a minute to look to these two examples by [Inigo Quilez](http://www.iquilezles.org/) and pay attention on the differences between [value noise](https://www.shadertoy.com/view/lsf3WH) and [gradient noise](https://www.shadertoy.com/view/XdXGW8).
As a painter that understand how the pigments of their paint works, the more we know about noise implementations the better we will learn how to use it. The following step is to find interesting way of combining and using it.
As a painter that understand how the pigments of their paints works, the more we know about noise implementations the better we will learn how to use it. The following step is to find interesting way of combine and use it.
For example, if we use a two dimensional noise implementation to rotate the "grid" we can produce the following effect that looks a lot like wood
For example, if we use a two dimensional noise implementation to rotate the space where strign lines are render, we can produce the following swirly effect that looks like wood. Again you can click on the image to see how the code looks like
[ ![Wood texture](wood.png) ](../edit.html#11/wood.frag)
@ -126,7 +128,7 @@ For example, if we use a two dimensional noise implementation to rotate the "gri
pattern = lines(pos,.5); // draw lines
```
Another way to get interesting patterns from noise is to treat it like a distance field and apply some of the tricks described on the [Shapes chapter](../07/)
Another way to get interesting patterns from noise is to treat it like a distance field and apply some of the tricks described on the [Shapes chapter](../07/).
[ ![Splatter texture](splatter.png) ](../edit.html#11/splatter.frag)
@ -135,10 +137,12 @@ Another way to get interesting patterns from noise is to treat it like a distanc
color -= smoothstep(.35,.4,noise(st*10.)); // Holes on splatter
```
The third way of using the noise function is using it to modulate a shapes, this probably require reviewing the [Shapes Chapter](../07/)
A third way of using the noise function is to modulate a shapes, this also requires some of the techniques we learn on the [chapter about shapes](../07/)
<a href="../edit.html#11/circleWave-noise.frag"><canvas id="custom" class="canvas" data-fragment-url="circleWave-noise.frag" width="300px" height="300"></canvas></a>
For you to practice:
* What other generative pattern can you make? What about granite? marble? magma? water? Find three pictures of textures you are interested and implement them algorithmically using noise.
* Use noise to modulate a shapes.
* What about using noise for motion? Go back to the [Matrix chapter](../08/) and use the translation example that move a the "+" around to apply some *random* and *noise* movements to it.
@ -156,25 +160,27 @@ For Ken Perlin the success of his algorithm wasn't enough. He thought it could p
* A noise with well-defined and continuous gradients that can be computed quite cheaply
* An algorithm that is easy to implemnt in hardware
Yeah, right? I know what you are thinking... "Who is this man?". Yes, his work is fantastic. But seriusly, How he did that? Well we saw how for two dimensions he was interpolating 4 points (coorners of a square); also we can correctly preasume that for [three (see an implementation here)](../edit.html#11/3d-noise.frag) and four dimensions we need to interpolate 8 and 16 points. Right? In other words for N dimensions you need to smoothly interpolate 2 to the N points (2^N). But Ken smartly notice that although the obvious choice for a space-filling shape is a squar, but actually the formal simplex shape in 2D is an equilateral triangle.
Yeah, right? I know what you are thinking... "Who is this man?". Yes, his work is fantastic! But seriusly, How he did that? Well we saw how for two dimensions he was interpolating 4 points (coorners of a square); also we can correctly preasume that for [three (see an implementation here)](../edit.html#11/3d-noise.frag) and four dimensions we need to interpolate 8 and 16 points. Right? In other words for N dimensions you need to smoothly interpolate 2 to the N points (2^N). But Ken smartly notice that although the obvious choice for a space-filling shape is a squar, the actually simpliest shape in 2D is the equilateral triangle. So he start by replace the squared grid (we finnaly learn how to use) for a simplex grid of equilateral triangles.
![](simplex-grid-00.png)
That means that the simplex shape for N dimensions is a shape with N + 1 corners. In other words one less corner to compute in 2D, 4 less coorners in 3D and 11 less coorners in 4D! That's a huge improvement!
The simplex shape for N dimensions is a shape with N + 1 corners. In other words one less corner to compute in 2D, 4 less coorners in 3D and 11 less coorners in 4D! That's a huge improvement!
So, in two dimension the interpolation happens, in a similar way than regular noise, by interpolating the values of the corners of a section. But, in this particular case, because we are using a simplex grid we just need to interpolate the sum of only 3 coornes (or contributors) to interpolate.
So then, in two dimension the interpolation happens, similarly than regular noise, by interpolating the values of the corners of a section. But, in this particular case, because we are using a simplex grid, we just need to interpolate the sum of only 3 coornes ( contributors).
![](simplex-grid-01.png)
How the simplex grid works? In another brillant and elegant move, simplex grid can be obtain by subdividing the cells of a regular 4 corners grid into two isoceles triangles and then skewing it unitl each triangle is equilateral.
How the simplex grid works? In another brillant and elegant move, the simplex grid can be obtain by subdividing the cells of a regular 4 corners grid into two isoceles triangles and then skewing it unitl each triangle is equilateral.
![](simplex-grid-02.png)
Then, as [Stefan Gustavson describe in this paper](http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf): _"...by looking at the integer parts of the transformed coordinates (x,y) for the point we want to evaluate, we can quickly determine which cell of two simplices that contain the point. By also compareing the magnitudes of x and y, we can determine whether the points is in the upper or the lower simplex, and traverse the correct three corners points."_. On the following code you can un comment the line 44 to see how the grid is skew and then line 47 to see how a simplex grid can be constructed. Note how on line 22 we are subdiving the skewed squared on two equilateral triangles just buy detecting if ```x > y``` ("lower" triangle) or ```y > x``` ("upper" triangle).
Then, as [Stefan Gustavson describe in this paper](http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf): _"...by looking at the integer parts of the transformed coordinates (x,y) for the point we want to evaluate, we can quickly determine which cell of two simplices that contain the point. By also compareing the magnitudes of x and y, we can determine whether the points is in the upper or the lower simplex, and traverse the correct three corners points."_.
On the following code you can uncomment the line 44 to see how the grid is skew and then line 47 to see how a simplex grid can be constructed. Note how on line 22 we are subdiving the skewed squared on two equilateral triangles just buy detecting if ```x > y``` ("lower" triangle) or ```y > x``` ("upper" triangle).
<div class="codeAndCanvas" data="simplex-grid.frag"></div>
Other improvements introduce by Perlin, is the replacement of the Cubic Hermite Curve ( _f(x) = 3x^2-2x^3_ ) for a Quintic Hermite Curve ( _f(x) = 6x^5-15x^4+10x^3_ ). In an efford to keep the "math stuff" simple this makes both ends of the curve more flat and by that a more continuos transition with the next interpolation. You can watch it for your self by uncommenting the second formula on the following graph example (or by see the [two equations side by side here](https://www.desmos.com/calculator/2xvlk5xp8b)). Note how the ends of the curve changes. You can read more about this in [on words of Ken it self in this paper](http://mrl.nyu.edu/~perlin/paper445.pdf).
Other improvements introduce by Perlin in the **Simplex Noise**, is the replacement of the Cubic Hermite Curve ( _f(x) = 3x^2-2x^3_ , wich is identical to the (.../glossary/?search=smoothstep) function ) for a Quintic Hermite Curve ( _f(x) = 6x^5-15x^4+10x^3_ ). This makes both ends of the curve more "flat" and by gracefully stiching with the next one. On other words you get more continuos transition between the cells. You can watch this by uncommenting the second formula on the following graph example (or by see the [two equations side by side here](https://www.desmos.com/calculator/2xvlk5xp8b)).
<div class="simpleFunction" data="
// Cubic Hermine Curve. Same as SmoothStep()
@ -183,7 +189,9 @@ y = x*x*(3.0-2.0*x);
//y = x*x*x*(x*(x*6.-15.)+10.);
"></div>
Following is an actual GLSL implementation of this algorithm made by Ian McEwan (and presented in [this paper](http://webstaff.itn.liu.se/~stegu/jgt2012/article.pdf)) which is probably over complicated for educational porposes because have been higly optimized, but you will be happy to click on it and see that is less cryptic than you expect.
Note how the ends of the curve changes. You can read more about this in [on words of Ken it self in this paper](http://mrl.nyu.edu/~perlin/paper445.pdf).
All this improvements result on a master peach of algorithms known as **Simplex Noise**. The following is an GLSL implementation of this algorithm made by Ian McEwan (and presented in [this paper](http://webstaff.itn.liu.se/~stegu/jgt2012/article.pdf)) which is probably over complicated for educational porposes because have been higly optimized, but you will be happy to click on it and see that is less cryptic than you expect.
[ ![Ian McEwan of Ashima Arts - Simplex Noise](simplex-noise.png) ](../edit.html#11/2d-snoise-clear.frag)
@ -199,4 +207,9 @@ Well enought technicalities, is time for you to use this resource in your own ex
<a href="../edit.html#11/iching-03.frag"><canvas id="custom" class="canvas" data-fragment-url="iching-03.frag" width="520px" height="520px"></canvas></a>
Well in this chapter we have introduce some control over the chaos. Is not an easy job. Becoming a noise bender master takes time and efford. On the following chapters we will review some "well-know" techniques to perfect your skills and get more out of your noise functions to design generative content on shaders.
In this chapter we have introduce some control over the chaos. Is not an easy job! Becoming a noise-bender-master takes time and efford.
On the following chapters we will see some "well-know" techniques to perfect your skills and get more out of your noise to design quality generative content with shaders. Until then enjoy some time outside contemplating nature and their intricate patterns. Your hability to observe need's equal (or probably more) dedication than your making skills. Go outside and enjoy the rest of day!
<p style="text-align:center; font-style: italic;">"Talk to the tree, make friends with it." Bob Ross
</p>

Loading…
Cancel
Save