shader glsl 函数图举例 转载https://juejin.cn/post/6844903671705108487
Shader 函数可视化
一、正弦余弦
正弦运动:y = sin(x)
余弦运动:y = cos(x)
动画演示:
通过给sin()
和cos()
添加一些处理,可以制作出更多有趣的效果:
二、smoothstep
在两个值之间取埃尔米特插值(Hermite interpolation)link,它的值永远是 0~1。
描述:在edge0
和edge1
之间取一个平缓的差值,在我们需要一个平滑的渐变的时候特别有用。当前值小于edge0
,取值为0
。当前值大于edge1
,取值1
。在这个区间内,取edge0
和edge1
的差值。
适用场景1:由于它的值永远介于 0~1,edge0 和 edge1 的差值只会决定曲线的陡或平缓,所以我们可以控制他们的差值来做一些动画速度的变化。比如:
zoom(uv, smoothstep(0.0, nQuick, progress));
复制代码
上面通过控制 nQuick 的值来决定 zoom 缩放速度了。
适用场景2:smoothstep
在edge0
,edge1
为0
的时候,相当于step
:
smoothstep(0.0, 0.0, x);
复制代码
那我们怎么实现类似 step(edge, x) 的 edge 移动的效果呢,只需要这么做就一样了:
smoothstep(0.0, 0.0, x-edge);
复制代码
smoothstep() 的运算同样可以制作出一些不同的变体曲线:
y = smoothstep(0.0,1.0,x) - smoothstep(1.0, 2.0, x);
复制代码
使用:
float smoothstep(float edge0, float edge1, float x)
vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x)
vec3 smoothstep(vec3 edge0, vec3 edge1, vec3 x)
vec4 smoothstep(vec4 edge0, vec4 edge1, vec4 x)
vec2 smoothstep(float edge0, float edge1, vec2 x)
vec3 smoothstep(float edge0, float edge1, vec3 x)
vec4 smoothstep(float edge0, float edge1, vec4 x)
复制代码
它等同于:
genType t; /* Or genDType t; */
t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
return t * t * (3.0 - 2.0 * t);
复制代码
可视化呈现:y = smoothstep(0.0,1.0,x);
三、clamp
将值限制在两个其他值之间。link
说明:clamp()
返回minVal
到maxVal
范围内的值。返回值计算:min(max(x, minVal), maxVal)。
使用:
float clamp(float x, float minVal, float maxVal)
vec2 clamp(vec2 x, vec2 minVal, vec2 maxVal)
vec3 clamp(vec3 x, vec3 minVal, vec3 maxVal)
vec4 clamp(vec4 x, vec4 minVal, vec4 maxVal)
vec2 clamp(vec2 x, float minVal, float maxVal)
vec3 clamp(vec3 x, float minVal, float maxVal)
vec4 clamp(vec4 x, float minVal, float maxVal)
复制代码
可视化呈现:y = clamp(x,0.,1.);
四、step
通过比较两个值生成步进函数。link
说明:step()
通过将x
与edge
进行比较来生成步进函数。对于返回值i
,如果x[i] < edge[i]
则返回0.0
,否则返回1.0
。
适用场景:step()
有着一个最大的特征,那就是非黑即白。edge 表示非黑即白的边界,小于edge
就是黑(0),大于edge
就是白(1)。当我们这么使用时,可以判断像素点是否存在归一化坐标系里:
step(0.0, p.y) * step(p.y, 1.0) * step(0.0, p.x) * step(p.x, 1.0)
复制代码
当它为 0 时,表示像素点在水平或垂直方向超出了边界;当它为 1 时,表示在坐标系内。当我我们把它和mix(texture2D_1, texture2D_2, step())
函数一起用时,就可以得到非黑即白的两张相连的纹理图(纹理图超过边界的部分会用纹理图2取代)。
使用:
float step(float edge, float x)
vec2 step(vec2 edge, vec2 x)
vec3 step(vec3 edge, vec3 x)
vec4 step(vec4 edge, vec4 x)
vec2 step(float edge, vec2 x)
vec3 step(float edge, vec3 x)
vec4 step(float edge, vec4 x)
复制代码
可视化呈现:y = step(0.5,x);
五、mod
以第二个模数计算第一个参数的值。
说明:x
指定要求模的值,y
指定要获取模数的值。计算公式为:x - y * floor(x / y)
。
使用:
float mod(float x, float y)
vec2 mod(vec2 x, vec2 y)
vec3 mod(vec3 x, vec3 y)
vec4 mod(vec4 x, vec4 y)
vec2 mod(vec2 x, float y)
vec3 mod(vec3 x, float y)
vec4 mod(vec4 x, float y)
复制代码
可视化呈现:y = mod(x,1.)
六、fract
计算参数的小数部分。
说明:fract()
返回x
的小数部分。计算公式为x - floor(x)
。
适用场景:假如我们在一个归一化的坐标系里,fract(uv)
能够让像素点永远都在坐标系里不会超出边界。以从上往下平移作为例子,fract()
可以让从上往下的平移无限循环,且首尾相连。
使用:
float fract(float x)
vec2 fract(vec2 x)
vec3 fract(vec3 x)
vec4 fract(vec4 x)
复制代码
可视化呈现:y = fract(x)
七、floor
找到小于或等于参数的最接近的整数。
说明:floor()
返回一个等于最小整数的值,该整数小于或等于x
。
使用:
float floor(float x)
vec2 floor(vec2 x)
vec3 floor(vec3 x)
vec4 floor(vec4 x)
复制代码
可视化呈现:y = floor(x)
八、ceil
找到大于或等于参数的最近整数。
说明:ceil()
返回一个等于最接近的整数的值,该整数大于或等于x
。
使用:
float ceil(float x)
vec2 ceil(vec2 x)
vec3 ceil(vec3 x)
vec4 ceil(vec4 x)
复制代码
可视化呈现:y = ceil(x);
九、sign
提取参数的符号。
说明:如果x
小于0.0
,则sign()
返回-1.0
,如果x
等于0.0
,则返回0.0
,如果x
大于0.0
,则返回+1.0
。
适用场景:sign()
用来判断运动方向非常高效,因为它的值只有 -1,0,1
,所以我们可以通过
vec2 direction = vec2(0.0, 1.0); // x, y 代表方向
sign(direction)
复制代码
来判断水平和垂直的方向,正数为正方向,负数为反方向,也不用担心用户传了超出长度为1
的值。
使用:
float sign(float x)
vec2 sign(vec2 x)
vec3 sign(vec3 x)
vec4 sign(vec4 x)
复制代码
可视化呈现:y = sign(x);
十、mix
将值限制在两个其他值之间并做融合,常用于颜色混合:
说明:mix()
在x
和y
之间执行线性插值,使用它们之间的权重。返回值计算为x*(1-a)+y*a
。可以这么理解,a
决定了x
,y
所占的比重,比如a < 0.5
,那么x
的比重更大,a > 0.5
,y
的比重更大。当 a = 0.5
时,x
和y
的比重各一半。
使用场景:我们经常会有一些动画,需要在单位时间内往返一次,比如先放大后缩小。通过以下公式可以轻松做到(scale 表示放大的倍数):
mix(scale, 1.0, 2.0 * abs(progress - 0.5))
复制代码
上面的公式即可做到先放大到scale
(当进度为0.5
时达到最大),然后再缩小到1
。
使用:
float mix(float x, float y, float a)
vec2 mix(vec2 x, vec2 y, vec2 a)
vec3 mix(vec3 x, vec3 y, vec3 a)
vec4 mix(vec4 x, vec4 y, vec4 a)
vec2 mix(vec2 x, vec2 y, float a)
vec3 mix(vec3 x, vec3 y, float a)
vec4 mix(vec4 x, vec4 y, float a)
复制代码
可视化呈现:y = mix(0.,1.,x);