noise and examples

This commit is contained in:
Patricio Gonzalez Vivo 2015-09-09 10:32:52 -04:00
parent cf7ff5655b
commit d567dcd8f2
9 changed files with 192 additions and 93 deletions

39
11/2d-gnoise.frag Normal file
View File

@ -0,0 +1,39 @@
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
vec2 random2(vec2 st){
st = vec2( dot(st,vec2(127.1,311.7)),
dot(st,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(st)*43758.5453123);
}
// Value Noise by Inigo Quilez - iq/2013
// https://www.shadertoy.com/view/lsf3WH
float noise(vec2 st) {
vec2 i = floor(st);
vec2 f = fract(st);
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( random2(i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( random2(i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( random2(i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( random2(i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(0.0);
vec2 pos = vec2(st*10.0);
color = vec3( noise(pos)*.5+.5 );
gl_FragColor = vec4(color,1.0);
}

View File

@ -38,7 +38,7 @@ void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec3 color = vec3(0.0);
vec2 pos = vec2(st*5.0+u_time);
vec2 pos = vec2(st*5.0);
color = vec3( noise(pos) );

38
11/2d-vnoise.frag Normal file
View File

@ -0,0 +1,38 @@
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
float hash(vec2 st) {
float h = dot(st,vec2(127.1,311.7));
return -1.0 + 2.0*fract(sin(h)*43758.5453123);
}
// Gradient Noise by Inigo Quilez - iq/2013
// https://www.shadertoy.com/view/XdXGW8
float noise(vec2 st) {
vec2 i = floor(st);
vec2 f = fract(st);
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( hash( i + vec2(0.0,0.0) ),
hash( i + vec2(1.0,0.0) ), u.x),
mix( hash( i + vec2(0.0,1.0) ),
hash( i + vec2(1.0,1.0) ), u.x), u.y);
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(0.0);
vec2 pos = vec2(st*10.0);
color = vec3(noise(pos)*.5+.5);
gl_FragColor = vec4(color,1.0);
}

View File

@ -7,7 +7,7 @@ Break time! We have been playing with all this random functions that looks like
We feel the air in our face, the sun in our nose and chicks. 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. We note the stochasticity of textures, there is random on nature. But definitely not the type of random we were making in the previus chapter. The “real world” is such a rich place. How we can approximate to this level of variety computationally?
We are on the same path of thoughts that Ken Perlin's walk through on 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.
We are on the same path of thoughts that [Ken Perlin](https://mrl.nyu.edu/~perlin/)'s walk through on 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.
The following is not the clasic Perlin noise algorithm, but is a good starting point to understand how to generate *smooth random* aka *noise*.
@ -57,13 +57,25 @@ Now is your turn:
## 2D Noise
![](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.)```).
![](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.
![](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
![](05.jpg)
In the following implementation of 2D noise we scale the size of the grid by 5 (line 41).
<div class="codeAndCanvas" data="2d-noise.frag"></div>
To this 2D noise at line 41 we scale the space by 5 and "move" it acording to time. No try:
Now is your turn, try the following excersices:
* Change the multiplier. Try to animate it.
@ -79,40 +91,44 @@ To this 2D noise at line 41 we scale the space by 5 and "move" it acording to ti
![Mark Rothko - Three (1950)](rothko.jpg)
## Using 2D Noise to rotate the space
## Using Noise on generative designs
As we saw, noise was designed to give a natural *je ne sais quoi* to digital textures, and could be use to make convincing generative textures. Lets refresh some of the previous knowledge and then jump forward learning how to mix all the knowledge we have learn so far.
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**.
In the following code you will find:
<a href="../edit.html#11/2d-vnoise.frag"><canvas id="custom" class="canvas" data-fragment-url="2d-vnoise.frag" width="520px" height="200px"></canvas> <p style="text-align: center;font-style: italic;">Value Noise by IQ</p></a>
* 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)
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```).
<div class="codeAndCanvas" data="wood.frag"></div>
<a href="../edit.html#11/2d-gnoise.frag"><canvas id="custom" class="canvas" data-fragment-url="2d-gnoise.frag" width="520px" height="200px"></canvas> <p style="text-align: center;font-style: italic;">Gradient Noise by IQ</p></a>
By uncommenting line 60 you will see the line pattern we are talking about.
Revealing line 63 you can see how we can alternate this pattern in a "natural-like" way, to then finally, uncommenting line 66 we can stretch the noise pattern in *y* axis.
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).
Wow! You really should be proud of your self. He have went from nothing to generating our own wood procedural texture!
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.
Now is time for you to play with 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
* What do you thing it will happen if the patter looks like this:
<a href="../edit.html#11/wood.frag"><canvas id="custom" class="canvas" data-fragment-url="wood.frag" width="520px" height="200px"></canvas></a>
```glsl
pattern = sin(lines(pos, noise(pos*vec2(2.,0.5)),0.5)*3.14);
pos = rotate2d( noise(pos) ) * pos; // rotate the space
pattern = lines(pos,.5); // draw lines
```
Or like this
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)
<a href="../edit.html#11/splatter.frag"><canvas id="custom" class="canvas" data-fragment-url="splatter.frag" width="520px" height="200px"></canvas></a>
```glsl
pattern = fract(lines(pos, noise(pos*vec2(2.,0.5)),0.5)*2.0);
color += smoothstep(.15,.2,noise(st*10.)); // Black splatter
color -= smoothstep(.35,.4,noise(st*10.)); // Holes on splatter
```
* What other generative pattern can you make? What about granite? marble? magma? water?
The third way of using the noise function is using it to modulate a shapes, this probably require reviewing the [Shapes Chapter](../07)
<a href="../edit.html#11/circleWave-noise.frag"><canvas id="custom" class="canvas" data-fragment-url="circleWave-noise.frag" width="520px" height="520"></canvas></a>
* What other generative pattern can you make? What about granite? marble? magma? water? Find a picture of three textures you are interested and implement it algorithmically using noise.
* Use noise to modulate three shapes.
* What about noise apply to motion? Go back to the Matrix chapter and use the translation example that move a the "+" around to apply some *random* and *noise* movements to it.
Nothing like having some control over the chaos and chances. Right?

View File

@ -12,51 +12,24 @@ uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
vec3 mod289(vec3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
vec2 mod289(vec2 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
vec3 permute(vec3 x) { return mod289(((x*34.0)+1.0)*x); }
vec2 random2(vec2 st){
st = vec2( dot(st,vec2(127.1,311.7)),
dot(st,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(st)*43758.5453123);
}
float snoise(vec2 v) {
const vec4 C = vec4(0.211324865405187, // (3.0-sqrt(3.0))/6.0
0.366025403784439, // 0.5*(sqrt(3.0)-1.0)
-0.577350269189626, // -1.0 + 2.0 * C.x
0.024390243902439); // 1.0 / 41.0
// First corner
vec2 i = floor(v + dot(v, C.yy) );
vec2 x0 = v - i + dot(i, C.xx);
// Value Noise by Inigo Quilez - iq/2013
// https://www.shadertoy.com/view/lsf3WH
float noise(vec2 st) {
vec2 i = floor(st);
vec2 f = fract(st);
// Other corners
vec2 i1;
i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
vec4 x12 = x0.xyxy + C.xxzz;
x12.xy -= i1;
vec2 u = f*f*(3.0-2.0*f);
// Permutations
i = mod289(i); // Avoid truncation effects in permutation
vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 ))
+ i.x + vec3(0.0, i1.x, 1.0 ));
vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0);
m = m*m ;
m = m*m ;
// Gradients: 41 points uniformly over a line, mapped onto a diamond.
// The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287)
vec3 x = 2.0 * fract(p * C.www) - 1.0;
vec3 h = abs(x) - 0.5;
vec3 ox = floor(x + 0.5);
vec3 a0 = x - ox;
// Normalise gradients implicitly by scaling m
// Approximation of: m *= inversesqrt( a0*a0 + h*h );
m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );
// Compute final noise value at P
vec3 g;
g.x = a0.x * x0.x + h.x * x0.y;
g.yz = a0.yz * x12.xz + h.yz * x12.yw;
return 130.0 * dot(m, g);
return mix( mix( dot( random2(i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( random2(i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( random2(i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( random2(i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
mat2 rotate2d(float _angle){
@ -69,13 +42,12 @@ float shape(vec2 st, float radius) {
float r = length(st)*2.0;
float a = atan(st.y,st.x);
float m = abs(mod(a+u_time*2.,3.14*2.)-3.14)/3.6;
m += snoise(st+u_time*0.1)*.8;
a *= 1.+abs(atan(u_time*0.2))*.1;
// a *= 1.+snoise(st+u_time*0.1)*0.1;
// a *= 1.+snoise(vec2(a,r)+u_time*0.1)*.1;
float f = radius;
// f += sin(a*10.)*snoise(st+u_time*.2)*.1;
f += (cos(a*50.)*.1*pow(m,2.));
m += noise(st+u_time*0.1)*.5;
// a *= 1.+abs(atan(u_time*0.2))*.1;
// a *= 1.+noise(st+u_time*0.1)*0.1;
f += sin(a*50.)*noise(st+u_time*.2)*.1;
f += (sin(a*20.)*.1*pow(m,2.));
return 1.-smoothstep(f,f+0.007,r);
}
@ -87,5 +59,5 @@ void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec3 color = vec3(1.0) * shapeBorder(st,0.8,0.02);
gl_FragColor = vec4( color, 1.0 );
gl_FragColor = vec4( 1.-color, 1.0 );
}

View File

@ -44,6 +44,7 @@ float snoise(vec2 v) {
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(0.0);
vec2 pos = vec2(st*3.);

View File

@ -76,12 +76,12 @@ vec3 nNoise(vec2 st) {
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
float scale = 10.0;
st *= scale;
st += nNoise(st).xy*.1*sin(u_time);
float df = sin(fract(st.y)*10.);
gl_FragColor= vec4(vec3(smoothstep(.9,.99,df)),1.);
gl_FragColor= vec4(vec3(1.0-smoothstep(.9,.99,df)),1.);
}

41
11/splatter.frag Normal file
View File

@ -0,0 +1,41 @@
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
vec2 random2(vec2 st){
st = vec2( dot(st,vec2(127.1,311.7)),
dot(st,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(st)*43758.5453123);
}
// Value Noise by Inigo Quilez - iq/2013
// https://www.shadertoy.com/view/lsf3WH
float noise(vec2 st) {
vec2 i = floor(st);
vec2 f = fract(st);
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( random2(i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( random2(i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( random2(i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( random2(i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(0.0);
// Comment and uncomment the following lines:
st += noise(st*2.)*abs(1.0-sin(u_time*.1))*5.; // Animate the coordinate space
color = vec3(1.) * smoothstep(.18,.2,noise(st)); // Big black drops
color += smoothstep(.15,.2,noise(st*10.)); // Black splatter
color -= smoothstep(.35,.4,noise(st*10.)); // Holes on splatter
gl_FragColor = vec4(1.-color,1.0);
}

View File

@ -15,23 +15,16 @@ float random (in vec2 st) {
* 43758.5453123);
}
// Based on Morgan McGuire @morgan3d
// https://www.shadertoy.com/view/4dS3Wd
float noise (in vec2 st) {
// Value noise by Inigo Quilez - iq/2013
// https://www.shadertoy.com/view/lsf3WH
float noise(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;
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( random( i + vec2(0.0,0.0) ),
random( i + vec2(1.0,0.0) ), u.x),
mix( random( i + vec2(0.0,1.0) ),
random( i + vec2(1.0,1.0) ), u.x), u.y);
}
mat2 rotate2d(float angle){
@ -39,10 +32,9 @@ mat2 rotate2d(float angle){
sin(angle),cos(angle));
}
float lines(in vec2 pos, float angle, float b){
float lines(in vec2 pos, float b){
float scale = 10.0;
pos *= scale;
pos = rotate2d( angle ) * pos;
return smoothstep(0.0,
.5+b*.5,
abs((sin(pos.x*3.1415)+b*2.0))*.5);
@ -56,11 +48,11 @@ void main() {
float pattern = pos.x;
// Stripes
pattern = lines(pos, 0.0, 0.5 );
// Add noise
pattern = lines(pos, noise(pos), .5 );
pos = rotate2d( noise(pos) ) * pos;
// Draw lines
pattern = lines(pos,.5);
gl_FragColor = vec4(vec3(pattern),1.0);
}