前言
Shader Toy 就是着色玩具的意思。
在Shader Toy的官网里,大家可以找到许许多多的炫酷案例。
shadertoy 存在的意义,除了好玩、好看,还可以成为许多实战、创新项目的算法支撑和灵感来源。
1-Shader Toy 牛刀小试
我们可以在vscode 里安装一个Shader Toy,然后建立glsl 文件,用来书写shader 代码。
1.建立一个项目文件夹,然后在其中建立一个01-fragColor.glsl 文件
2.绘制一片蓝色。
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
fragColor = vec4(0, 0, 1, 1);
}
- mainImage() :主函数。
- fragColor :输出变量,用于设置canvas 画布中每个片元的颜色。
3.右击页面,在提示面板中选择Shader Toy:Show GLSL Preview
这样便可以在Shader Toy的显示窗口中看见一张蓝色的画布。
4.我们基于fragCoord 还可以绘制一片线性渐变背景。
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 coord = fragCoord / iResolution.xy;
fragColor = vec4(coord, 1, 1);
}
效果如下:
- fragCoord: 输入变量,当前片元的像素位置,其对应的坐标系就是canvas画布坐标系:
w、h 代表canvas画布的宽高。
- iResolution: canvas画布的宽高尺寸
到现在我们已经知道了Shader Toy 的正确解锁方式,接下来我们再画个圆形练练手。
2-绘制圆形
一般而言,我们在使用shader toy 绘图的时候,不会用canvas画布坐标系,而是使用一种原点在canvas画布中心,宽高为2 的裁剪坐标系:
接下来咱们就构建一个这样的坐标系,然后绘制圆形。
1.建立裁剪坐标系。
vec2 ClipCoord(in vec2 fragCoord) {
return 2. * (fragCoord / iResolution.xy - 0.5);
}
2.在mainImage()方法中,将fragCoord转换为裁剪坐标。
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = ClipCoord(fragCoord);
fragColor = vec4(uv, 1, 1);
}
现在右下方都变成了蓝色:
3.以uv的长度为rgb色值,可以绘制一个径向渐变。
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 coord = ClipCoord(fragCoord);
float coordlen = length(coord);
fragColor = vec4(vec3(coordlen), 1);
}
4.以uv的长度为判断依据,还可以绘制一个实色填充的圆。
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 coord = ClipCoord(fragCoord);
float coordlen = length(coord);
vec3 rgb = vec3(coordlen > 0.1 ? 1 : 0);
fragColor = vec4(rgb, 1);
}
上面的图形是一个椭圆,这是因为canvas画布的宽高并不相同,所以圆形被拉伸了。
5.基于canvas画布中的最小边,构建一个不会让图形发生拉伸的坐标系,在此我暂且称之为投影坐标系了。
vec2 ProjectionCoord(in vec2 fragCoord) {
return 2. * (fragCoord - 0.5 * iResolution.xy) / min(iResolution.x, iResolution.y);
}
这个投影坐标系跟svg中viewBox 有点类似。
无论canvas画布的尺寸如何,在其内部都会基于其最小的边显示一个正方形。
如下图所示:
6.在投影坐标系中画圆。
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 coord = ProjectionCoord(fragCoord);
float coordlen = length(coord);
vec3 rgb = vec3(coordlen > 0.1 ? 1 : 0);
fragColor = vec4(rgb, 1);
}
效果如下:
关于图像周边的锯齿我们后面会说。
现在我们已经知道了如何构建坐标系。接下我们再说一下如何把坐标系显示出来,以方便我们更好的绘图。