前面发了一些关于 Shader 编程的文章,有读者反馈太碎片化了,希望这里能整理出来一个系列,方便系统的学习一下 Shader 编程。
由于主流的 Shader 编程网站,如 ShaderToy, gl-transitions 都是基于 GLSL 开发 Shader ,加上 MSL 和 GLSL 语法上差别不大,后面系列文章将以 GLSL 为主来介绍 Shader 编程。
后面 Shader 编程将使用 VSCode + ShaderToy 插件作为编程环境,步骤如下:
绘制多边形的思路跟画圆的思路一样,圆形可以看做一个有正无穷边的多边形。有了这个思路你就可以明白,我们需要为每条边划分对应的弧度,弧度相同它就是正多边形。
直接上代码:
#define PI 3.1415926535897932384626433832795
float polygonSDF(vec2 uv, float radius, float sides){
// 原点设置到中心位置
uv = uv * 2.0 - 1.0;
// 相对于原点的 atan,范围[-PI/2,PI/2]
float angle = atan(uv.x, uv.y) + PI / 2.0;
// 多边形每一条边占用的弧度
float slice = PI * 2.0 / sides;
// floor 向下取整来构造多边形的边
// smoothstep 作为边缘平滑过渡
return smoothstep(radius-0.005, radius + 0.005, cos(floor(0.5 + angle / slice) * slice - angle) * length(uv));
}
void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
vec2 uv = fragCoord / iResolution.x;
float n = ceil(mod(iTime, 8.0)) + 2.0;
vec3 color = vec3(0.0);
float val = polygonSDF(uv,0.3,n);
color = vec3(val);
fragColor = vec4(color,1.0);
}
代码里比较关键的就是 atan、floor、cos 这三个函数,你可以停下来琢磨一下。
这个直接绘制成正多边形的效果
上节其实牵扯到 SDF 算法,因为后面涉及高级特效的时候会经常用到,这里先提前对它做个简单的介绍,先在心里有个概念。
SDF(Signed Distance Field 有向距离场)算法是一种用于生成、存储和渲染字形(或图形)的技术。
SDF 算法能够快速而高效地计算出给定点与字形(或图形)边界之间的有符号距离,从而可以用于各种应用,如字体渲染、图像处理、形状变形等。
SDF 算法的基本原理是将字形(或图形)表示为一张包含有符号距离值的纹理。每个像素都存储了该像素距离最近的字形(或图形)轮廓的距离,并用正负号表示内部和外部。具体步骤如下:
使用生成的 SDF 纹理,可以进行以下操作:
SDF 算法在实际应用中被广泛使用,尤其在移动设备和游戏开发中,因为其高效性和渲染质量。