shader-控制生成-随机

398 阅读4分钟

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
}

效果如下。

image.png(图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
}

结果如下。

image.png(图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
}

效果如下。

image.png(图3)

使用圆形效果的图案如下。

image.png(图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
}

效果如下。

image.png(图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
}

效果如下。

image.png(图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);
}

效果如下。

image.png(图7)