Random
One dimensional random
We can create pseudo random numbers in GLSL by taking the fract()
part of a sin()
value and then scale it with a big number.
We can manipulate the distribution of the random values by - multiplying it with itself
float ran = fract(sin(uv.x)*10000.);
//Values lie more towards y = 0
float y2 = ran *ran;
//Values lie more towards y = 1
float y3 = sqrt(ran);
float random(vec2 st){
return fract(sin(dot(st.xy,vec2(12.9898,78.233)))*43758.5453123);
}
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
float c = random(st);
gl_FragColor = vec4(vec3(c),1.0);
}
float random(vec2 st, float seed){
const float a = 12.9898;
cosnt float b = 78.233;
const float c = 43758.543123;
return fract(sin(dot(st,vec2(a,b))+seed)*c);
Two dimensional random
To distribute random values over two dimension we have to convert a two dimensional vector of for example the pixel position into a one dimensional value. We can use the dot()
function for that.
The dot()
function returns float number between 0.0 and 1.0, depending on how two vectors that build the skalar product are positioned to each other.
We can use random to draw different shapes or colors for each tile in a grid canvas.
float random(vec2 st){
return fract(sin(dot(st.xy,vec2(12.9898,78.233)))*43758.545312);
}
void main(){
vec2 st = gl_FragCoord.xy /u_resolution.xy;
//scale up the canvas
st*=10.0;
vec2 ipos = floor(st);//int values of scaled canvas
vec2 fpos = fract(st);//decimal values of scaled canvas
vec3 c = vec3(random(ipos));
vec3 c1 = vec3(random(fpos));
gl_FragColor = vec4(ipos,fpos,0.0,1.0);
}
By isolating the integer part of the coordinates we get the same value for all the Pixels that lie inside a grid tile. We then use this value to create the random value for the whole tile.
The fpos
allows us then to position what we want to draw properly.
This allows use to create even more sophisticated pattern and grids.
Random Series Generator
We can use the random()
function to create a random series that defines if something gets shown or not
float random(float x){
return fract(sin(x)*1e4);
}
float random(vec2 uv){
return fract(sin(dot(uv,vec2(12.9898,78.233)))*43758.5453123);
}
float ranSerie(float x,float freq,float time){
//This creates series of random binary(0-1) values that changes depending on space and time
float divXSegments = floor(x*freq);
float timeChanges = floor(t);
return step(0.8,random(divXSegments-timeChanges));
}
void main(){
vec2 uv = gl_FragCoord.xy/u_resolution.xy;
uv.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(0.0);
float cols = 3.0;
float freq = random(floor(u_time))+abs(atan(u_time)*0.1);
float t = 60.+u_time*(1.0-freq)*30.0;
//create different frequencies for each band
if(fract(uv.y*cols*0.5) <0.5){
t*= -3.0;
}
freq += random(floor(uv.y));
//color + offset
float offset = 0.025;
color = vec3(randomSerie(uv.x,freq*100.0,t+offset),
randomSerie(uv.x,freq*100.0,t),
randomSerie(uv.x,freq*100.0,t-offset));
gl_FragColor = vec4(1.0 - color,1.0);
}
https://thebookofshaders.com/edit.php#10/ikeda-03.frag
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
float random (in float x) {
return fract(sin(x)*1e4); // 1e4 is 10000
}
float random (in vec2 st) {
return fract(sin(dot(st.xy, vec2(12.9898,78.233)))* 43758.5453123);
}
// This function creates the visual pattern
float pattern(vec2 st, vec2 v, float threshold) {
// Add the velocity to the position and round down to create grid cells
vec2 p = floor(st+v);
// Generate pattern using random numbers and a threshold
// The 100.+ is an arbitrary offset to avoid patterns at origin
// The tiny multiplier .000001 creates subtle variations
// The random(p.x)*0.5 adds horizontal variation
return step(threshold, random(100.+p*.000001)+random(p.x)*0.5 );
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec2 grid = vec2(100.0,50.);
st *= grid;
vec2 ipos = floor(st); // Which grid cell we're in
vec2 fpos = fract(st); // Position within the cell (0.0-1.0)
// Create base velocity that increases with time
// max(grid.x,grid.y) makes sure it scales with grid size
vec2 vel = vec2(u_time*2.*max(grid.x,grid.y));
// Modify velocity based on row (y position):
// - vec2(-1.,0.0) makes it move horizontally left
// - random(1.0+ipos.y) gives each row a different random speed
vel *= vec2(-1.,0.0) * random(1.0+ipos.y);
// Create a slight horizontal offset for color channels (chromatic aberration)
vec2 offset = vec2(0.1,0.);
// Start with black color
vec3 color = vec3(0.);
// Calculate each color channel with different offsets
// The mouse x-position affects the threshold (density of points)
color.r = pattern(st+offset, vel, 0.5+u_mouse.x/u_resolution.x); // Red (shifted right)
color.g = pattern(st, vel, 0.5+u_mouse.x/u_resolution.x); // Green (centered)
color.b = pattern(st-offset, vel, 0.5+u_mouse.x/u_resolution.x); // Blue (shifted left)
// Create margins between rows (when y position < 0.1 in cell, make it black)
color *= step(0.1, fpos.y);
gl_FragColor = vec4(1.0-color, 1.0);
}
https://thebookofshaders.com/edit.php#10/ikeda-04.frag
Noise
Perlin noise collection https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83