shader-矩阵

154 阅读3分钟

通过矩阵操作坐标系。

1.平移

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;  // uniform变量,用于传入画布分辨率
uniform float u_time;       // uniform变量,用于传入当前时间

// 定义一个函数,生成矩形形状
float box(in vec2 _st, in vec2 _size){
    _size = vec2(0.5) - _size*0.5;
    vec2 uv = smoothstep(_size,
                        _size+vec2(0.001),
                        _st);
    uv *= smoothstep(_size,
                    _size+vec2(0.001),
                    vec2(1.0)-_st);
    return uv.x * uv.y;
}

// 定义一个函数,生成十字形状
float cross(in vec2 _st, float _size){
    return  box(_st, vec2(_size,_size/4.)) +
            box(_st, vec2(_size/4.,_size));
}

void main(){
    vec2 st = gl_FragCoord.xy / u_resolution.xy;  // 将片元的坐标规范化到[0,1]的范围内
    vec3 color = vec3(0.0);                      // 初始化颜色为黑色

    vec2 translate = vec2(cos(u_time), sin(u_time));  // 根据当前时间计算平移向量
    st += translate * 0.35;                          // 将平移向量乘以0.35,应用于坐标空间,实现形状的移动效果

    color += vec3(cross(st, 0.25));  // 将生成的十字形状应用于当前坐标,将结果加到颜色上

    gl_FragColor = vec4(color, 1.0);  // 将最终的颜色值设置为输出颜色
}

效果如下。

image.png

image.png

2.旋转

#ifdef GL_ES
precision mediump float;
#endif

#define PI 3.14159265359

uniform vec2 u_resolution;  // uniform变量,用于传入画布分辨率
uniform float u_time;       // uniform变量,用于传入当前时间

// 定义一个函数,用于进行二维旋转
mat2 rotate2d(float _angle){
    return mat2(cos(_angle), -sin(_angle),
                sin(_angle), cos(_angle));
}

// 定义一个函数,生成矩形形状
float box(in vec2 _st, in vec2 _size){
    _size = vec2(0.5) - _size*0.5;
    vec2 uv = smoothstep(_size,
                        _size+vec2(0.001),
                        _st);
    uv *= smoothstep(_size,
                    _size+vec2(0.001),
                    vec2(1.0)-_st);
    return uv.x * uv.y;
}

// 定义一个函数,生成十字形状
float cross(in vec2 _st, float _size){
    return  box(_st, vec2(_size,_size/4.)) +
            box(_st, vec2(_size/4.,_size));
}

void main(){
    vec2 st = gl_FragCoord.xy / u_resolution.xy;  // 将片元的坐标规范化到[0,1]的范围内
    vec3 color = vec3(0.0);                      // 初始化颜色为黑色

    // 从中心将坐标空间移动到vec2(0.0)
    st -= vec2(0.5);
    // 对坐标空间进行旋转
    st = rotate2d(sin(u_time) * PI) * st;
    // 将坐标空间移动回原始位置
    st += vec2(0.5);

    // Show the coordinates of the space on the background
    // color = vec3(st.x,st.y,0.0);

    // Add the shape on the foreground
    color += vec3(cross(st, 0.4));

    gl_FragColor = vec4(color, 1.0);  // 将最终的颜色值设置为输出颜色
}

效果如下

image.png image.png

3.缩放

#ifdef GL_ES
precision mediump float;
#endif

#define PI 3.14159265359

uniform vec2 u_resolution;  // uniform变量,用于传入画布分辨率
uniform float u_time;       // uniform变量,用于传入当前时间

// 定义一个函数,用于进行缩放
mat2 scale(vec2 _scale){
    return mat2(_scale.x, 0.0,
                0.0, _scale.y);
}

// 定义一个函数,生成矩形形状
float box(in vec2 _st, in vec2 _size){
    _size = vec2(0.5) - _size*0.5;
    vec2 uv = smoothstep(_size,
                        _size+vec2(0.001),
                        _st);
    uv *= smoothstep(_size,
                    _size+vec2(0.001),
                    vec2(1.0)-_st);
    return uv.x * uv.y;
}

// 定义一个函数,生成十字形状
float cross(in vec2 _st, float _size){
    return  box(_st, vec2(_size,_size/4.)) +
            box(_st, vec2(_size/4.,_size));
}

void main(){
    vec2 st = gl_FragCoord.xy / u_resolution.xy;  // 将片元的坐标规范化到[0,1]的范围内
    vec3 color = vec3(0.0);                      // 初始化颜色为黑色

    st -= vec2(0.5);                              // 将坐标空间从中心移动到vec2(0.0)
    st = scale(vec2(sin(u_time) + 1.0)) * st;     // 对坐标空间进行缩放,缩放因子根据时间变化而变化
    st += vec2(0.5);                              // 将坐标空间移动回原始位置

    // Show the coordinates of the space on the background
    // color = vec3(st.x,st.y,0.0);

    // Add the shape on the foreground
    color += vec3(cross(st, 0.2));

    gl_FragColor = vec4(color, 1.0);  // 将最终的颜色值设置为输出颜色
}

效果如下

image.png

image.png

4. YUV颜色

YUV 是个用来模拟照片和视频的编码的色彩空间。这个色彩空间考虑人类的感知,减少色度的带宽。

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;  // uniform变量,用于传入画布分辨率
uniform float u_time;       // uniform变量,用于传入当前时间

// YUV转RGB矩阵
mat3 yuv2rgb = mat3(1.0, 0.0, 1.13983,
                    1.0, -0.39465, -0.58060,
                    1.0, 2.03211, 0.0);

// RGB转YUV矩阵
mat3 rgb2yuv = mat3(0.2126, 0.7152, 0.0722,
                    -0.09991, -0.33609, 0.43600,
                    0.615, -0.5586, -0.05639);

void main(){
    vec2 st = gl_FragCoord.xy / u_resolution;  // 将片元的坐标规范化到[0,1]的范围内
    vec3 color = vec3(0.0);                    // 初始化颜色为黑色

    // UV值范围为-1到1,所以需要重新映射st (0.0到1.0)
    st -= 0.5;  // 变为-0.5到0.5
    st *= 2.0;  // 变为-1.0到1.0

    // 将st作为三维向量的y和z值传入
    // 以便与一个3x3矩阵正确相乘
    color = yuv2rgb * vec3(0.5, st.x, st.y);

    gl_FragColor = vec4(color, 1.0);  // 将最终的颜色值设置为输出颜色
}

结果如下。

image.png