1.step()函数
在 GLSL (OpenGL Shading Language) 中,step 是一个内置函数,其功能是产生一个阶梯函数。该函数有两个参数:edge 和 x。其功能定义如下:
float step(float edge, float x);
vec2 step(vec2 edge, vec2 x);
vec3 step(vec3 edge, vec3 x);
vec4 step(vec4 edge, vec4 x);
它的工作方式如下:
- 如果
x小于edge,那么返回 0。 - 否则,返回 1。
举例来说:
step(0.5, 0.2)将返回 0,因为 0.2 小于 0.5。step(0.5, 0.7)将返回 1,因为 0.7 不小于 0.5。
当传入的参数是向量时,step 函数会对向量的每个分量分别进行比较,并返回相应的结果向量。例如,step(vec2(0.5, 0.5), vec2(0.2, 0.7)) 将返回 vec2(0.0, 1.0)。
这个函数在着色器中常用于实现各种阶梯效果或阈值操作,例如在你提供的代码片段中,它用于确定一个矩形区域的位置。
2.用step画矩形
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec3 color = vec3(0.0);
// bottom-left
vec2 bl = step(vec2(0.1),st);
float pct = bl.x * bl.y;
// top-right
vec2 tr = step(vec2(0.1),1.0-st);
pct *= tr.x * tr.y;
color = vec3(pct);
gl_FragColor = vec4(color,1.0);
}
这段 GLSL 代码是在屏幕的左下角和右上角绘制两个矩形,并将这两个矩形的颜色映射到黑色和白色之间。代码的分析如下:
-
定义精度和统一变量:首先,代码定义了所使用的浮点数的精度为中等精度(mediump float),并初始化了一些预设的统一变量(uniforms):
u_resolution(渲染区域的分辨率),u_mouse(当前鼠标的位置)和u_time(当前的时间)。 -
主函数:
main函数是着色器的入口点,以下是主函数的各个部分:- 计算标准化屏幕坐标:使用当前的片元坐标(
gl_FragCoord.xy)除以屏幕分辨率(u_resolution.xy)得到一个范围在0和1之间的标准化屏幕坐标st。 - 计算左下角矩形的颜色:使用
step函数,如果st的 x 或 y 值小于 0.1,那么bl的对应值为 0,否则为 1。因此,当st在 (0.1, 0.1) 的范围内时,bl.x * bl.y的值为 1,否则为 0。这个结果赋值给pct。 - 计算右上角矩形的颜色:类似的,使用
step函数,如果1.0 - st的 x 或 y 值小于 0.1,那么tr的对应值为 0,否则为 1。然后,将pct和tr.x * tr.y的乘积赋值给pct。 - 设置片元颜色:最后,将
pct映射到黑色和白色之间,得到片元的颜色,并赋值给gl_FragColor。
- 计算标准化屏幕坐标:使用当前的片元坐标(
这样,这段代码的效果是:在屏幕的左下角和右上角各绘制一个边长为屏幕边长10%的矩形,这两个矩形的颜色是白色的,其余的部分是黑色的。
3.放置多个矩形
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform float u_time;
// 长方形函数
vec3 rect(vec2 st, vec2 pos, vec2 size, vec3 color) {
vec2 r = abs(st - pos) - size;
vec3 result = vec3(smoothstep(0.02, 0.03, r.x), smoothstep(0.02, 0.03, r.y), 1.0) * color;
return result;
}
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec3 color = vec3(0.0);
// 绘制红色长方形
vec2 pos1 = vec2(0.2, 0.3);
vec2 size1 = vec2(0.1, 0.2);
vec3 color1 = vec3(1.0, 0.0, 0.0);
color += rect(st, pos1, size1, color1);
// 绘制蓝色长方形
vec2 pos2 = vec2(0.6, 0.5);
vec2 size2 = vec2(0.2, 0.1);
vec3 color2 = vec3(0.0, 0.0, 1.0);
color += rect(st, pos2, size2, color2);
// 绘制绿色长方形
vec2 pos3 = vec2(0.4, 0.7);
vec2 size3 = vec2(0.1, 0.2);
vec3 color3 = vec3(0.0, 1.0, 0.0);
color += rect(st, pos3, size3, color3);
gl_FragColor = vec4(color,1.0);
}
在这个 GLSL 片段着色器中,rect 函数是一个自定义函数,用来绘制一个给定位置、尺寸和颜色的矩形。让我们一起详细解析这个函数:
vec3 rect(vec2 st, vec2 pos, vec2 size, vec3 color) {
vec2 r = abs(st - pos) - size;
vec3 result = vec3(smoothstep(0.02, 0.03, r.x), smoothstep(0.02, 0.03, r.y), 1.0) * color;
return result;
}
-
vec2 r = abs(st - pos) - size;这一行计算的是当前像素(st)到矩形中心点(pos)的绝对距离,然后再减去矩形的尺寸(size)。如果这个结果(r)的 x 和 y 分量都小于 0,那么意味着当前的像素位于矩形内部。 -
vec3 result = vec3(smoothstep(0.02, 0.03, r.x), smoothstep(0.02, 0.03, r.y), 1.0) * color;这一行的计算是在 x 和 y 轴上独立进行的。smoothstep(0.02, 0.03, r.x)函数会返回一个介于 0 和 1 之间的值,这个值表示r.x在0.02到0.03之间的插值。如果r.x小于0.02,那么smoothstep返回 0;如果r.x大于0.03,那么smoothstep返回 1。这个函数的主要目的是创建一个在边缘平滑过渡的效果。 -
* color;就是将前面计算得到的结果与矩形的颜色进行相乘,得到最终的颜色值。
所以,rect 函数的主要工作就是为了确定当前像素是否在矩形内,如果在矩形内,就返回矩形的颜色,如果在矩形边缘,就返回过渡的颜色,如果在矩形外,就返回黑色(颜色乘以0)。