该原创文章首发于微信公众号:字节流动
未经作者(微信ID:Byte-Flow)允许,禁止转载
SDF 有向距离场
上节其实牵扯到 SDF 算法,因为后面涉及高级特效的时候会经常用到,这里先提前对它做个简单的介绍,先在心里有个概念。
SDF(Signed Distance Field)算法是一种用于生成、存储和渲染字形(或图形)的技术。SDF 算法能够快速而高效地计算出给定点与字形(或图形)边界之间的有符号距离,从而可以用于各种应用,如字体渲染、图像处理、形状变形等。
SDF 算法的基本原理是将字形(或图形)表示为一张包含有符号距离值的纹理。每个像素都存储了该像素距离最近的字形(或图形)轮廓的距离,并用正负号表示内部和外部。具体步骤如下:
-
生成轮廓:将字形(或图形)转换为轮廓线,通常使用矢量图形描述,如 TrueType 字体或 SVG 图形。
-
计算距离场:为了生成有符号距离场,需要遍历像素,并计算每个像素到最近轮廓线的距离值。可以使用一种快速的近似算法,如距离变换算法(如 Chamfer Distance Transform)或区域增长算法。
-
构建 SDF 纹理:将每个像素的距离值存储为纹理数据。正距离值用白色表示,负距离值用黑色表示,灰色用于表示距离为零的轮廓线。
使用生成的 SDF 纹理,可以进行以下操作:
- 字体渲染:通过采样和插值技术,在不同大小和分辨率的设备上高效地渲染字形。
- 文字渲染效果:通过分析有符号距离场的值,可以实现一些特殊的字体效果,如描边、阴影、模糊等。
- 图像处理:由于 SDF 纹理存储了距离信息,可以进行各种图像处理和操作,如形变、缩放、旋转等。
SDF 算法在实际应用中被广泛使用,尤其在移动设备和游戏开发中,因为其高效性和渲染质量。
绘制多边形
绘制多边形的思路跟画圆的思路一样,圆形可以看做一个正无穷边的多边形。有了这个思路你就可以明白,我们需要为每条边划分对应的弧度,弧度相同它就是正多边形。
直接上代码:
#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 这三个函数,你可以停下来琢磨一下。
后续安排
后面 OpenGL & Metal Shader 编程系列文章大致安排:
- ShaderToy 内置全局变量
- 重要的内置函数
- 基本图形
- 距离场
- 噪声函数
- 基础特效…
- 转场特效…
- 高阶特效…
联系交流
技术交流可以添加我的微信:Byte-Flow