【着色器】day1基础入门(shader-learn平台)

内容参考来源:GLSL学习平台

基础概念

片段着色器(Fragment Shader)

片段着色器是GPU渲染管线中的一个重要阶段,它决定屏幕上每个像素的最终颜色。每个像素都会执行一次片段着色器程序。

代码框架

precision mediump float; // 设置浮点精度
void main() { // 主函数入口
  // 你的代码
}

vUv

表示每个片元的 UV 坐标

  • 从左到右,0 → 1
  • 从下到上,0 → 1

双色混合渐变

vUv:纹理坐标

vUv 是从顶点着色器传入片元着色器的二维坐标,范围通常为 [0.0, 1.0],表示当前片元在屏幕中的位置

varying vec2 vUv;

mix(a, b, t):线性插值

mix 函数可用于在两个值之间做线性过度
t 是混合因子,将 abt 比例混合,在 [0.0, 1.0] 取值,0.0返回a,1.0返回b

vec3 color = mix(colorA, colorB, vUv.x);

gl_FragColor:输出

最终颜色通过设置 gl_FragColor 输出

gl_FragColor = vec4(blendedColor, 1.0);

点击查看代码
precision mediump float;

varying vec2 vUv;

void main() {
    vec3 color1 = vec3(1.0, 0.0, 0.0);
    vec3 color2 = vec3(0.0, 1.0, 0.0);
    vec3 blendedColor = mix(color1, color2, vUv.x);
    gl_FragColor = vec4(blendedColor, 1.0);
}

基础渐变效果

获取当前像素位置

在片元着色器中,每个像素都有一个固定的位置坐标,使用 gl_FragCood.xy 获取,单位是像素。进一步说明着色器是以像素为单位进行渲染的

坐标归一化为 UV

不同设备分辨率不同,为了统一处理逻辑,我们通常将像素坐标转换成 0~1 范围的比例坐标,即 UV

做法是:将每个像素的位置除以画布总尺寸(用 u_resolution 传入)

vec2 uv = gl_FragCoord.xy / u_resolution.xy;

  • 左下角是 (0.0, 0.0)
    右上角是 (1.0, 1.0)

使用UV控制颜色通道

绘制图形

坐标系转换

代码例子
vec2 uv = gl_FragCoord.xy / u_resolution.xy; // 转换为 0~1
vec2 center = uv - vec2(0.5); // 移动原点到中心

距离函数

  • distance(a, b):两点距离
  • length(v):计算向量长度(到原点的距离),用于判断点是否在图形内部

step 函数

step(edge, x) 是一个阶跃函数,常用于创建硬边界:

  • x < edge,返回 0.0
  • x ≥ edge,返回 1.0

smoothstep 函数

smoothstep(edge0, edge1, x) 在 edge0 和 edge1 之间创建平滑的 S 型曲线过度

  • x ≤ edge0,返回 0.0
  • x ≥ edge1,返回 1.0
  • edge0 < x < edge1,返回平滑插值
边缘宽度控制
float radius = 0.5;
float edgeWidth = 0.1; // 边缘宽度
float edge0 = radius - edgeWidth;
float edge1 = radius + edgeWidth;
float mask = smoothstep(edge0, edge1, distance);
反向平滑
// 从 1.0 到 0.0 的平滑过渡
float inverseMask = 1.0 - smoothstep(edge0, edge1, distance);

图形代码示例

  • 圆形
点击查看代码
precision mediump float;
uniform vec2 u_resolution;

void main() {
    // 练习:绘制简单圆形
    // 目标:学习基础的距离函数和条件判断
    
    // 获取当前像素的归一化坐标 (0.0 到 1.0)
    vec2 uv = gl_FragCoord.xy / u_resolution.xy;
    
    // 练习1:将坐标原点移到屏幕中心
    // 提示:减去0.5使坐标范围变为[-0.5, 0.5]
    vec2 center = uv - vec2(0.5);
    
    // 练习2:计算当前像素到中心的距离
    // 提示:使用length()函数
    float distance = length(center);
    
    // 练习3:定义圆的半径
    float radius = 0.3;
    
    // 练习4:创建圆形
    // 提示:当距离小于半径时为1.0,否则为0.0
    float circle = step(distance, radius);
    
    // 练习5:设置颜色
    // 提示:圆内为白色,圆外为黑色
    vec3 color = vec3(circle);
    
    gl_FragColor = vec4(color, 1.0);
}
  • 矩形
点击查看代码
precision mediump float;
uniform vec2 u_resolution;

void main() {
    // 练习:绘制一个简单的矩形
    // 目标:在屏幕中央绘制一个白色矩形,背景为黑色
    
    // 获取当前像素的归一化坐标 (0.0 到 1.0)
    vec2 uv = gl_FragCoord.xy / u_resolution.xy;
    
    // 练习1:定义矩形的边界
    // 矩形应该在 x: 0.3-0.7, y: 0.4-0.6 的范围内
    float left = 0.2;
    float right = 0.8;
    float bottom = 0.3;
    float top = 0.7;
    
    // 练习2:判断当前像素是否在矩形内
    // 提示:使用逻辑运算符 && 来组合条件
    bool insideRect = (uv.x >= left && uv.x <= right) && 
                      (uv.y >= bottom && uv.y <= top);
    
    // 练习3:根据位置设置颜色
    vec3 color;
    if (insideRect) {
        color = vec3(1.0, 0.0, 0.0);
    } else {
        color = vec3(0.0);
    }
    
    gl_FragColor = vec4(color, 1.0);
}

其他

  • fract(x):返回x的小数部分
posted @ 2025-10-05 22:43  鼓舞人心的杰克森  阅读(28)  评论(0)    收藏  举报