shader编程基础:画圆
前记
使用的在线编译工具shadertoy的编写shader语言。跳转链接:Shadertoy
基本实现
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = (fragCoord-0.5*iResolution.xy)/iResolution.y;
uv *= 2.;
float d = dot(uv, uv);
vec3 color = vec3(d);
fragColor = vec4(color,1.0);
}
- fragCoord:当前像素点
- iResolution:分辨率
- uv: fragCoord在当前分辨率的归一化坐标,这里做了移位和缩放
- (fragCoord-0.5iResolution.xy)/iResolution.y 这里 -0.5iResolution.xy往右上各移动半个屏幕, /iResolution.y 图像的宽高以分辨率的的高为基准进行归一化。
- uv *= 2 对uv进行缩放,考虑假设uv的轴区间是[0, 1],乘2之后映射到[0, 2]了,分辨率不变,像素点向uv方向偏移一半,视觉表现即图像缩小了一半
- float d = dot(uv, uv) 这里是把uv视为向量进行取模
- fragColor 是这个像素点计算完输出的颜色
进阶
绘制圆环,带有发光,边缘看起来更加平滑(可以参考画线和发光呼吸圆环的更优雅的实现)
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = (fragCoord-0.5*iResolution.xy)/ iResolution.y;
uv *= 2.;
float thicknessPix = 50.;
float thickness = thicknessPix / iResolution.y;
float r = 0.7;
float fadePix = 20.;
float fade = fadePix / iResolution.y;
float d = dot(uv, uv);
vec3 color = vec3(1. - smoothstep(r + thickness, r + thickness + fade, d));
color *= vec3(smoothstep(r, r + fade, d));
fragColor = vec4(color,1.0);
}
- thickness: 圆环厚度
- fade: 发光(渐变)厚度
- smoothstep: 生成发光函数(详解见下文)
- color *= vec3(smoothstep(r, r + fade, d)):大白园叠加里面那个小白圆
shader编程常用函数:
- smoothstep
float smoothstep(float t1, float t2, float x) {
x = clamp((x - t1) / (t2 - t1), 0.0, 1.0);
return x * x * (3 - 2 * x);
}
平滑函数计算一个值在两个边界之间的平滑过渡,通常用来产生渐变效果
(t1 = -2, t2 = 3)
(t1 = 3, t2 = -2)
如图示,函数根据参数t1, t2左右边界,取0,0~1,1,注意,根据t1,t2大小有两类函数图像。
- dot:dot函数计算两个向量的点积,即对应的元素相乘再求和,常用于计算光照,投影,反射等。
-cross: cross函数来计算两个向量的叉乘,它产生一个垂直于这两个向量的向量。常用于计算法向量和切向量。 - length: 用length函数计算一个向量的长度,该向量与原点的欧氏距离。它通常用于归一化向量、距离计算等。
- normallize: normallize函数是向量归一化,它的长度是1。通常用于计算光照、法向量等
- clamp: clamp函数将一个值限制在一个范围内,通常用于限制颜色值、坐标值等。
- mix: mix函数用于线性插值,即计算两个值之间的某个中间值。它通常用于动态地改变颜色、位置等。
- pow: pow函数将一个数值乘以自身n次方,通常用于计算光照、阴影等。