随机
随机性是熵的最大表现。我们如何在看似可预测而且严苛的代码环境中生成随机性呢?
让我们从分析下面的函数着手:
y = fract(sin(x)*1.0);
我们提取了sin函数其波形的分数部分。值域为-1.0 到 1.0 之间的sin() 函数被取了小数点后的部分(这里实际是指模1)),返回0.0 到 1.0 间的正值。我们可以用这种效果通过把正弦函数打散成小片段来得到一些伪随机数。如何实现呢?通过在sin(x)的值上乘以大些的数。点击上面的函数,在1后面加些0。
当你加到 100000.0 (方程看起来是这样的:y = fract(sin(x)*100000.0) ),你再也区分不出sin波了。小数部分的粒度将sine的循环变成了伪随机的混沌。
控制混沌
使用随机会很难;它不是太混沌难测就是有时又不够混乱。
y = rand(x);
2D 随机
将一个二维向量转化为一维浮点数。这里有几种不同的方法来实现,但 dot() 函数在这个例子中尤其有用。它根据两个向量的方向返回一个 0.0 到 1.0 之间的值。
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
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 rnd = random( st );
gl_FragColor = vec4(vec3(rnd),1.0);
}
使用混沌
二维的随机看起来是不是像电视的噪点?对组成图像来说,随机是个难用的原始素材。让我们来学着如何来利用它。
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
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;
st *= 10.0; // Scale the coordinate system by 10
vec2 ipos = floor(st); // get the integer coords
vec2 fpos = fract(st); // get the fractional coords
// Assign a random value based on the integer coord
vec3 color = vec3(random( ipos ));
// Uncomment to see the subdivided grid
// color = vec3(fpos,0.0);
gl_FragColor = vec4(color,1.0);
}
#ifdef GL_ES
precision mediump float;
#endif
#define PI 3.14159265358979323846
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);
}
vec2 truchetPattern(in vec2 _st, in float _index){
_index = fract(((_index-0.5)*2.0));
if (_index > 0.75) {
_st = vec2(1.0) - _st;
} else if (_index > 0.5) {
_st = vec2(1.0-_st.x,_st.y);
} else if (_index > 0.25) {
_st = 1.0-vec2(1.0-_st.x,_st.y);
}
return _st;
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st *= 10.0;
// st = (st-vec2(5.0))*(abs(sin(u_time*0.2))*5.);
// st.x += u_time*3.0;
vec2 ipos = floor(st); // integer
vec2 fpos = fract(st); // fraction
vec2 tile = truchetPattern(fpos, random( ipos ));
float color = 0.0;
// Maze
color = smoothstep(tile.x-0.3,tile.x,tile.y)-
smoothstep(tile.x,tile.x+0.3,tile.y);
// Circles
// color = (step(length(tile),0.6) -
// step(length(tile),0.4) ) +
// (step(length(tile-vec2(1.)),0.6) -
// step(length(tile-vec2(1.)),0.4) );
// Truchet (2 triangles)
// color = step(tile.x,tile.y);
gl_FragColor = vec4(vec3(color),1.0);
}
掌握随机
- 做按行随机移动的单元(以相反方向)。只显示亮一些的单元。让各行的速度随时间变化
#ifdef GL_ES
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
float random (in float x) {
return fract(sin(x)*1e4);
}
float random (in vec2 st) {
return fract(sin(dot(st.xy, vec2(12.9898,78.233)))* 43758.5453123);
}
float randomSerie(float x, float freq, float t) {
return step(.8,random( floor(x*freq)-floor(t) ));
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(0.0);
float cols = 2.;
float freq = random(floor(u_time))+abs(atan(u_time)*0.1);
float t = 60.+u_time*(1.0-freq)*30.;
if (fract(st.y*cols* 0.5) < 0.5){
t *= -1.0;
}
freq += random(floor(st.y));
float offset = 0.025;
color = vec3(randomSerie(st.x, freq*100., t+offset),
randomSerie(st.x, freq*100., t),
randomSerie(st.x, freq*100., t-offset));
gl_FragColor = vec4(1.0-color,1.0);
}
- 让某几行以不同的速度和方向。用鼠标位置关联显示单元的阀值。
#ifdef GL_ES
precision mediump float;
#endif
// Copyright (c) Patricio Gonzalez Vivo, 2015 - http://patriciogonzalezvivo.com/
// I am the sole copyright owner of this Work.
//
// You cannot host, display, distribute or share this Work in any form,
// including physical and digital. You cannot use this Work in any
// commercial or non-commercial product, website or project. You cannot
// sell this Work and you cannot mint an NFTs of it.
// I share this Work for educational purposes, and you can link to it,
// through an URL, proper attribution and unmodified screenshot, as part
// of your educational material. If these conditions are too restrictive
// please contact me and we'll definitely work it out.
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
float random (in float x) {
return fract(sin(x)*1e4);
}
float random (in vec2 st) {
return fract(sin(dot(st.xy, vec2(12.9898,78.233)))* 43758.5453123);
}
float pattern(vec2 st, vec2 v, float t) {
vec2 p = floor(st+v);
return step(t, 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); // integer
vec2 fpos = fract(st); // fraction
vec2 vel = vec2(u_time*2.*max(grid.x,grid.y)); // time
vel *= vec2(-1.,0.0) * random(1.0+ipos.y); // direction
// Assign a random value base on the integer coord
vec2 offset = vec2(0.1,0.);
vec3 color = vec3(0.);
color.r = pattern(st+offset,vel,0.5+u_mouse.x/u_resolution.x);
color.g = pattern(st,vel,0.5+u_mouse.x/u_resolution.x);
color.b = pattern(st-offset,vel,0.5+u_mouse.x/u_resolution.x);
// Margins
color *= step(0.2,fpos.y);
gl_FragColor = vec4(1.0-color,1.0);
}