1.随机
随机数的产生主要有random()函数,利用正弦函数sin配合dot向量点乘实现。例如下面。
#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); // 将随机数作为颜色的红、绿、蓝分量,设置透明度为1.0
}
效果如下。
(图1)
2.混沌大法
在上面实现了随机,下面使用floor函数实现一个单元格。
#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; // 将坐标系缩放10倍
vec2 ipos = floor(st); // 获取整数坐标部分
vec2 fpos = fract(st); // 获取小数坐标部分
// 根据整数坐标分配一个随机值
vec3 color = vec3(random(ipos));
// 取消注释以查看细分的网格
// color = vec3(fpos, 0.0);
gl_FragColor = vec4(color, 1.0); // 将颜色作为片元的颜色,设置透明度为1.0
}
结果如下。
(图2)
3.随机和有序混合
例如迷宫的实现。
#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) {
// 将索引值归一化到0.0到1.0之间
_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; // 将坐标系缩放10倍
vec2 ipos = floor(st); // 整数部分
vec2 fpos = fract(st); // 小数部分
// 根据整数坐标和随机数生成特鲁谢图案的瓦片
vec2 tile = truchetPattern(fpos, random(ipos));
float color = 0.0;
// 迷宫效果
color = smoothstep(tile.x - 0.3, tile.x, tile.y) -
smoothstep(tile.x, tile.x + 0.3, tile.y);
// 圆形效果
// 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));
// 图案效果(2个三角形)
// color = step(tile.x, tile.y);
gl_FragColor = vec4(vec3(color), 1.0); // 将颜色作为片元的颜色,设置透明度为1.0
}
效果如下。
(图3)
使用圆形效果的图案如下。
(图4)
#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);
}
// 随机数生成函数,接受一个二维向量作为参数
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.0; // 列数
float freq = random(floor(u_time)) + abs(atan(u_time) * 0.1); // 随机频率
float t = 60.0 + u_time * (1.0 - freq) * 30.0; // 时间
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.0, t + offset),
randomSerie(st.x, freq * 100.0, t),
randomSerie(st.x, freq * 100.0, t - offset));
gl_FragColor = vec4(1.0 - color, 1.0); // 将颜色作为片元的颜色,设置透明度为1.0
}
效果如下。
(图5)
多行滚动
#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);
}
// 随机数生成函数,接受一个二维向量作为参数
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.0 + p * 0.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.0); // 网格大小
st *= grid;
vec2 ipos = floor(st); // 整数部分
vec2 fpos = fract(st); // 小数部分
vec2 vel = vec2(u_time * 2.0 * max(grid.x, grid.y)); // 速度
vel *= vec2(-1.0, 0.0) * random(1.0 + ipos.y); // 方向
vec2 offset = vec2(0.1, 0.0); // 偏移量
vec3 color = vec3(0.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);
// 边缘效果
color *= step(0.2, fpos.y);
gl_FragColor = vec4(1.0 - color, 1.0); // 将颜色作为片元的颜色,设置透明度为1.0
}
效果如下。
(图6)
有趣的效果
#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); }
float random (in 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.x *= u_resolution.x / u_resolution.y;
vec2 grid = vec2(100.0, 50.0);
st *= grid;
vec2 ipos = floor(st);
vec2 vel = floor(vec2(u_time * 10.0));
vel *= vec2(-1.0, 0.0);
vel *= (step(1.0, mod(ipos.y, 2.0)) - 0.5) * 2.0;
vel *= random(ipos.y);
float totalCells = grid.x * grid.y;
float t = mod(u_time * max(grid.x, grid.y) + floor(1.0 + u_time * u_mouse.y), totalCells);
vec2 head = vec2(mod(t, grid.x), floor(t / grid.x));
vec2 offset = vec2(0.1, 0.0);
vec3 color = vec3(1.0);
color *= step(grid.y - head.y, ipos.y);
color += (1.0 - step(head.x, ipos.x)) * step(grid.y - head.y, ipos.y + 1.0);
color = clamp(color, vec3(0.0), vec3(1.0));
color.r *= random(floor(st + vel + offset));
color.g *= random(floor(st + vel));
color.b *= random(floor(st + vel - offset));
color = smoothstep(0.0, 0.5 + u_mouse.x / u_resolution.x * 0.5, color * color);
color = step(0.5 + u_mouse.x / u_resolution.x * 0.5, color);
color *= step(0.1, fract(st.x + vel.x)) * step(0.1, fract(st.y + vel.y));
gl_FragColor = vec4(1.0 - color, 1.0);
}
效果如下。
(图7)