diff --git a/10/README.md b/10/README.md index 1c6e344..cadfc1a 100644 --- a/10/README.md +++ b/10/README.md @@ -14,9 +14,24 @@ As you can see, we are extracting only the fractional part of a sine wave. We ha By the time you get to 100000 ( and the equation looks like this: ```y = fract(sin(x)*100000.0)``` ) you probably are not hable to distinguish the sine wave any more. The granulary of the fractions have corrupt the flow of the sine in random chaos. +## Controling chaos + +Using random could be hard, is both too chaotic and, sometimes, not random enought. Take a look to the following graph. Inside it, we are using a ```rand()``` fuction implemented exactly like we describe above. + +Taking a closer look, you can se the ```sin()``` wave crest and though at -1s.5707 and 1.5707. I bet you know understand why. Also, if you see the distribution of it seem to be more likely to get values between 0.5 than on the edges. + +
+ +A while ago [Pixelero](pixelero.wordpress.com) made an [interersting article about random distribution](https://pixelero.wordpress.com/2008/04/24/various-functions-and-various-distributions-with-mathrandom/). I add some of the function he use in the following lines of the previus graph for you to play and observe how the distribution changes. Un comment them and see how the distribution change. + +If you read [Pixelero's article](https://pixelero.wordpress.com/2008/04/24/various-functions-and-various-distributions-with-mathrandom/) , is important to have in mind that our ```rand()``` function is a deterministic random or also known as pseudo-random. Which means, for example ```rand(1.)``` is going to return always the same value. [Pixelero](https://pixelero.wordpress.com/2008/04/24/various-functions-and-various-distributions-with-mathrandom/) makes reference to the ActionScript function ```Math.random()``` which is non-deterministic, every call will return a different value. + ## 2D Random -Now is time to apply this same principle on both *x* and *y* axis. For that we need a way to transform a two dimensional vector into a one dimensional float point value. There are different ways to do this, but the ```dot()``` function can be very particulary helpfull in this case, becuse of it avility to return a float values between 0 and 1 depending if two vectors are align. +Now we understand better randomness, is time to apply it on both *x* and *y* axis. For that we need a way to transform a two dimensional vector into a one dimensional float point value. There are different ways to do this, but the ```dot()``` function can be very particulary helpfull in this case, becuse of it avility to return a float values between 0 and 1 depending if two vectors are align.
@@ -26,9 +41,9 @@ Take a look to line 11 and 12 and how we are comparing the ```in vec2 _st``` wit ## Using the chaos -Actually randomness in pure form can be too chaotic, letres try to balance it entropy with some order. +Random in two dimensions looks a lot like TV noise. Right? Which is a hard raw material to use to compose images. Let's learn how to make use of it. -Take close look to the following code. Specially on lines 20 and 21. +Our first step is going to apply it on a grid. Take a look to the following code. Specially on lines 20 and 21.
diff --git a/11/1d-noise.frag b/11/1d-noise.frag index 9a1314c..04594da 100644 --- a/11/1d-noise.frag +++ b/11/1d-noise.frag @@ -3,6 +3,7 @@ precision mediump float; #endif uniform vec2 u_resolution; +uniform vec2 u_mouse; uniform float u_time; float plot(vec2 _st, float _pct){ diff --git a/11/2d-noise.frag b/11/2d-noise.frag index 7360584..0ba60a3 100644 --- a/11/2d-noise.frag +++ b/11/2d-noise.frag @@ -3,6 +3,7 @@ precision mediump float; #endif uniform vec2 u_resolution; +uniform vec2 u_mouse; uniform float u_time; float random (in vec2 _st) { @@ -30,33 +31,13 @@ float noise (in vec2 _st) { (d - b) * u.x * u.y; } -#define NUM_OCTAVES 5 - -float fbm ( in vec2 _st) { - float v = 0.0; - float a = 0.5; - vec2 shift = vec2(100.0); - // Rotate to reduce axial bias - mat2 rot = mat2(cos(0.5),sin(0.5), - -sin(0.5),cos(0.50)); - for (int i = 0; i < NUM_OCTAVES; ++i) { - v += a * noise(_st); - _st = rot * _st * 2.0 + shift; - a *= 0.5; - } - return v; -} - void main() { vec2 st = gl_FragCoord.xy/u_resolution.xy; vec3 color = vec3(0.0); vec2 pos = vec2(st*5.0+u_time); - float noise = noise(pos); - float fbm = fbm(pos); - - color = vec3( mix(noise, fbm, abs(sin(u_time)))); + color = vec3( noise(pos) ); gl_FragColor = vec4(color,1.0); } \ No newline at end of file diff --git a/11/3d-noise.frag b/11/3d-noise.frag index db542f9..8a1f2ac 100644 --- a/11/3d-noise.frag +++ b/11/3d-noise.frag @@ -3,6 +3,7 @@ precision mediump float; #endif uniform vec2 u_resolution; +uniform vec2 u_mouse; uniform float u_time; float random (in float _x) { @@ -41,30 +42,13 @@ float noise (in vec3 _p) { u.z); } -#define NUM_OCTAVES 5 - -float fbm ( in vec3 _p) { - float v = 0.0; - float a = 0.5; - vec3 shift = vec3(100); - for (int i = 0; i < NUM_OCTAVES; ++i) { - v += a * noise(_p); - _p = _p * 2.0 + shift; - a *= 0.5; - } - return v; -} - void main() { vec2 st = gl_FragCoord.xy/u_resolution.xy; vec3 color = vec3(0.0); vec3 pos = vec3(st*5.0,u_time*0.1); - float noise = noise(pos); - float fbm = fbm(pos); - - color = vec3( mix(noise, fbm, abs(sin(u_time)))); + color = vec3(noise(pos)); gl_FragColor = vec4(color,1.0); } \ No newline at end of file diff --git a/11/README.md b/11/README.md index 6afbb3b..2c99fd5 100644 --- a/11/README.md +++ b/11/README.md @@ -1,6 +1,94 @@ + +![NASA / WMAP science team](mcb.jpg) + ## Noise -Coming soon… +Break time! We have been playing with all this random functions that looks like TV white noise, our head is still spinning arround thinking on shaders, and our eyes are tired. Time to get out side and walk! + +We feel the air in our face, the sun in our nose and chicks. The world is such a vivid and rich places. Colors, textures, sounds. While we walk we can avoid notice the surface of the roads, rocks, trees and clouds. Sudently all seams random. But defenetly not the type of random we were making. The real world is such a rich place. How we can aproximate to this level of variarety computationally? + +We are on the same path of thoughts that Ken Perlin's walk through on 1982 when he was commisioned 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. + +The following is not the Perlin noise algorithm, but is a good starting point to start getting out head arround the idea of how to generate *noise* o *smooth random*. + +Look the following graph, is in escense what we where doing on line 36 and 37 on the last example of the previus chapter. We are computing the ```rand()``` of the integers of `x` (the `i` variable). + +
+ +By uncomenting the following line, you can make a linear interpolation between the random value of an integer to the next one. + +```glsl +y = mix(rand(i), rand(i + 1.0), f); +``` + +At this point we have learn that we can do better than a linear interpolation. Right? By uncomenting the following line, we will use the native ```smoothstep()``` to make a *smooth* transition between the previus random values. + +```glsl +y = mix(rand(i), rand(i + 1.0), smoothstep(0.,1.,f)); +``` + +You will find in other implementations that people use cubic curves ( like the following formula) instead of using a ```smoothstep()```. + +```glsl +float u = f * f * (3.0 - 2.0 * f ); +y = mix(rand(i), rand(i + 1.0), u); +``` + +## 2D Noise + +Now that we understand how noise is made in one dimetion, is time to port it to two dimensions. Check how on the following code the interpolation (line 29) is made between the for coorners of a square (lines 22-25). + +
+ +At this point you can recognice what's going on at line 40. We are scaling and "moving" the space, right? + +Try: + +* Change the multiplier. 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. + +## Using 2D Noise + +Time recapitulate, refresh some of the previus knowladge and jump foward. In the following code you will find: + +* Shaping functions to create: random (line 13), noise (line 32) and a line pattern (line 46). +* A color gradient (line 68). +* A matrix to rotate the line pattern (line 37-40 and 45) +* A 2d random function (line 12-16) +* A 2d noise function (line 20-35) + +
+ +By uncommenting line 60 you will see the line pattern we are talking about. +Revealing line 63 you can see how we can alterate this pattern in a "natural-like" way, to then finally, uncommenting line 66 we can streach the noise pattern in *y* axis. + +Wow! You really should be proud of your self. He have went from nothing to generating our own wood procedural texture! + +Now is time for you to play with it: + +* What do you thing it will happen if the patter looks like this: + +```glsl +pattern = sin(lines(pos, noise(pos*vec2(2.,0.5)),0.5)*3.14); +``` + +Or like this + +```glsl +pattern = fract(lines(pos, noise(pos*vec2(2.,0.5)),0.5)*2.0); +``` + +* What other generative pattern can you make? What about granit? marble? magma? water? +* What about noise apply to motion? Go back to the Matrix chapter and use the translation example that move a the "+" arround to apply some *random* and *noise* movements to it. -
+Nothing like having some control over the chaos and chances. Right? +Noise is one of those subjects that you can digg and alwyas find new exciting formulas. In fact, noise means different things for different people. Musicians will think in audio noise, comminicators into interference, and astrophysics on cosmic microwave background. On the next chapter we will use some related concepts from sign and audio behaviur to our noise function to explore more uses of noise. diff --git a/11/mcb.jpg b/11/mcb.jpg new file mode 100644 index 0000000..1754345 Binary files /dev/null and b/11/mcb.jpg differ diff --git a/11/noise-move.frag b/11/noise-move.frag new file mode 100644 index 0000000..7091ad6 --- /dev/null +++ b/11/noise-move.frag @@ -0,0 +1,56 @@ +// Author @patriciogv - 2015 +// http://patriciogonzalezvivo.com + +#ifdef GL_ES +precision mediump float; +#endif + +uniform vec2 u_resolution; +uniform float u_time; + +float random (in float _x) { + return fract(sin(_x)*1e4); +} + +// Based on Morgan McGuire @morgan3d +// https://www.shadertoy.com/view/4dS3Wd +float noise (in float _x) { + float i = floor(_x); + float f = fract(_x); + float u = f * f * (3.0 - 2.0 * f); + return mix(random(i), random(i + 1.0), u); +} + +float box(in vec2 _st, in vec2 _size){ + _size = vec2(0.5) - _size*0.5; + vec2 uv = smoothstep(_size, + _size+vec2(0.001), + _st); + uv *= smoothstep(_size, + _size+vec2(0.001), + vec2(1.0)-_st); + return uv.x*uv.y; +} + +float cross(in vec2 _st, float _size){ + return box(_st, vec2(_size,_size/4.)) + + box(_st, vec2(_size/4.,_size)); +} + +void main(){ + vec2 st = gl_FragCoord.xy/u_resolution.xy; + vec3 color = vec3(0.0); + + // To move the cross we move the space + vec2 translate = vec2(cos(noise(u_time)*3.1415*2.0), + sin(noise(u_time)*3.1415*2.0)); + st += translate*0.35; + + // Show the coordinates of the space on the background + // color = vec3(st.x,st.y,0.0); + + // Add the shape on the foreground + color += vec3(cross(st,0.25)); + + gl_FragColor = vec4(color,1.0); +} \ No newline at end of file diff --git a/11/wood.frag b/11/wood.frag new file mode 100644 index 0000000..6aed44a --- /dev/null +++ b/11/wood.frag @@ -0,0 +1,73 @@ +// Author @patriciogv - 2015 +// http://patriciogonzalezvivo.com + +#ifdef GL_ES +precision mediump float; +#endif + +uniform vec2 u_resolution; +uniform vec2 u_mouse; +uniform float u_time; + +float random (in vec2 _st) { + return fract(sin(dot(_st.xy, + vec2(12.9898,78.233)))* + 43758.5453123); +} + +// Based on Morgan McGuire @morgan3d +// https://www.shadertoy.com/view/4dS3Wd +float noise (in vec2 _st) { + vec2 i = floor(_st); + vec2 f = fract(_st); + + // Four corners in 2D of a tile + float a = random(i); + float b = random(i + vec2(1.0, 0.0)); + float c = random(i + vec2(0.0, 1.0)); + float d = random(i + vec2(1.0, 1.0)); + + vec2 u = f * f * (3.0 - 2.0 * f); + + return mix(a, b, u.x) + + (c - a)* u.y * (1.0 - u.x) + + (d - b) * u.x * u.y; +} + +mat2 rotate2d(float _angle){ + return mat2(cos(_angle),-sin(_angle), + sin(_angle),cos(_angle)); +} + +float lines(in vec2 _pos, float _angle, float _b){ + float scale = 10.0; + _pos *= scale; + _pos = rotate2d( _angle ) * _pos; + return smoothstep(0.0, + 0.5+_b*0.5, + abs((sin(_pos.x*3.1415)+_b*2.0))*0.5); +} + +void main() { + vec2 st = gl_FragCoord.xy/u_resolution.xy; + vec3 color = vec3(0.0); + + vec2 pos = vec2(st*5.0); + + float pattern = pos.x; + + // Stripes + // pattern = lines(pos*0.1, 0.0, 0.5 ); + + // Add noise + // pattern = lines(pos, noise(pos), 0.5 ); + + // Strech the noise pattern + //pattern = lines(pos, noise(pos*vec2(2.,0.5)),0.5); + + color = mix(vec3(0.275,0.145,0.059), + vec3(0.761,0.529,0.239), + pattern*1.7); + + gl_FragColor = vec4(color,1.0); +} \ No newline at end of file diff --git a/12/1d-fbm.frag b/12/1d-fbm.frag index 53299e8..e46c019 100644 --- a/12/1d-fbm.frag +++ b/12/1d-fbm.frag @@ -3,6 +3,7 @@ precision mediump float; #endif uniform vec2 u_resolution; +uniform vec2 u_mouse; uniform float u_time; float plot(vec2 _st, float _pct){ diff --git a/12/2d-fbm.frag b/12/2d-fbm.frag new file mode 100644 index 0000000..1651d96 --- /dev/null +++ b/12/2d-fbm.frag @@ -0,0 +1,61 @@ +#ifdef GL_ES +precision mediump float; +#endif + +uniform vec2 u_resolution; +uniform vec2 u_mouse; +uniform float u_time; + +float random (in vec2 _st) { + return fract(sin(dot(_st.xy, + vec2(12.9898,78.233)))* + 43758.5453123); +} + +// Based on Morgan McGuire @morgan3d +// https://www.shadertoy.com/view/4dS3Wd +float noise (in vec2 _st) { + vec2 i = floor(_st); + vec2 f = fract(_st); + + // Four corners in 2D of a tile + float a = random(i); + float b = random(i + vec2(1.0, 0.0)); + float c = random(i + vec2(0.0, 1.0)); + float d = random(i + vec2(1.0, 1.0)); + + vec2 u = f * f * (3.0 - 2.0 * f); + + return mix(a, b, u.x) + + (c - a)* u.y * (1.0 - u.x) + + (d - b) * u.x * u.y; +} + +#define NUM_OCTAVES 5 + +float fbm ( in vec2 _st) { + float v = 0.0; + float a = 0.5; + vec2 shift = vec2(100.0); + // Rotate to reduce axial bias + mat2 rot = mat2(cos(0.5), sin(0.5), + -sin(0.5), cos(0.50)); + for (int i = 0; i < NUM_OCTAVES; ++i) { + v += a * noise(_st); + _st = rot * _st * 2.0 + shift; + a *= 0.5; + } + return v; +} + +void main() { + vec2 st = gl_FragCoord.xy/u_resolution.xy; + st.x *= u_resolution.x/u_resolution.y; + vec3 color = vec3(0.0); + + float noise = noise(st*3.0); + float fractal = fbm(st*3.0); + color = vec3(mix(noise,fractal,abs(sin(u_time)))); + + gl_FragColor = vec4(color,1.0); +} \ No newline at end of file diff --git a/12/README.md b/12/README.md index f73ea4f..6295d9a 100644 --- a/12/README.md +++ b/12/README.md @@ -1,5 +1,56 @@ -## Fractional Brownian Motion +## Fractal Brownian Motion -Coming soon… +At the end of previus chapter we were thinking on noise as random waves. This *wavely* nature of noise is what makes it such an interdisciplinary concept. In fact, in acustics, sound is be constructed by the manipulation of the amplitud and frecuency of a sin wave; + +```glsl +y = amplitud + sin( frequency ); +``` + +### Harmonics + +An interesting property of waves is that they can be add up. For example, adding harmonic octaves together produce that something like the following graph. + +
+ +But on other side adding sine waves of different frequencies and amplituds will produce something very chaotic. + +
+ +Think on the surface of the ocean. This massive amount of water is propagating waves across it surface. Waves of diferent amplitud and frequencies. + +## 1D Fractal Brownian Motion + +By adding different octaves of the same noise function we can gain some extra granularity from the noise. Take a look to the following example and progresively change the for loop to do 2,3,4,5,6,7 and 8 iterations. See how incrisinly fragmented this wave function becomes. + +
+ +## 2D Fractal Brownian Motion + +This fine level of fragmentation is what we are interested. ... + +
+ +... + +
+ +great! -
diff --git a/12/clouds.frag b/12/clouds.frag new file mode 100644 index 0000000..df9e34d --- /dev/null +++ b/12/clouds.frag @@ -0,0 +1,78 @@ +#ifdef GL_ES +precision mediump float; +#endif + +uniform vec2 u_resolution; +uniform vec2 u_mouse; +uniform float u_time; + +float random (in vec2 _st) { + return fract(sin(dot(_st.xy, + vec2(12.9898,78.233)))* + 43758.5453123); +} + +// Based on Morgan McGuire @morgan3d +// https://www.shadertoy.com/view/4dS3Wd +float noise (in vec2 _st) { + vec2 i = floor(_st); + vec2 f = fract(_st); + + // Four corners in 2D of a tile + float a = random(i); + float b = random(i + vec2(1.0, 0.0)); + float c = random(i + vec2(0.0, 1.0)); + float d = random(i + vec2(1.0, 1.0)); + + vec2 u = f * f * (3.0 - 2.0 * f); + + return mix(a, b, u.x) + + (c - a)* u.y * (1.0 - u.x) + + (d - b) * u.x * u.y; +} + +#define NUM_OCTAVES 5 + +float fbm ( in vec2 _st) { + float v = 0.0; + float a = 0.5; + vec2 shift = vec2(100.0); + // Rotate to reduce axial bias + mat2 rot = mat2(cos(0.5), sin(0.5), + -sin(0.5), cos(0.50)); + for (int i = 0; i < NUM_OCTAVES; ++i) { + v += a * noise(_st); + _st = rot * _st * 2.0 + shift; + a *= 0.5; + } + return v; +} + +void main() { + vec2 st = gl_FragCoord.xy/u_resolution.xy*3.; + vec3 color = vec3(0.0); + + vec2 q = vec2(0.); + q.x = fbm( st + 0.00*u_time); + q.y = fbm( st + vec2(1.0)); + + vec2 r = vec2(0.); + r.x = fbm( st + 1.0*q + vec2(1.7,9.2)+ 0.15*u_time ); + r.y = fbm( st + 1.0*q + vec2(8.3,2.8)+ 0.126*u_time); + + float f = fbm(st+r); + + color = mix(vec3(0.101961,0.619608,0.666667), + vec3(0.666667,0.666667,0.498039), + clamp((f*f)*4.0,0.0,1.0)); + + color = mix(color, + vec3(0,0,0.164706), + clamp(length(q),0.0,1.0)); + + color = mix(color, + vec3(0.666667,1,1), + clamp(length(r.x),0.0,1.0)); + + gl_FragColor = vec4((f*f*f+.6*f*f+.5*f)*color,1.); +} \ No newline at end of file