Flutter & GLSL 系列文章:
- 《Flutter & GLSL – 壹 | Shader 让制作无限强壮》
- 《Flutter & GLSL – 贰 | 从坐标到色彩》
- 《Flutter & GLSL – 叁 | 变量传参》
- 《Flutter & GLSL – 肆 | 从条纹到马赛克》
- 《Flutter & GLSL – 伍 | 图形区域操控》
- 《Flutter & GLSL – 陆 | 滑润过渡 smoothstep》
事例代码开源地址 【skeleton】
1. 去除锯齿
在上一篇中,我们经过 step 函数经过 像素与原点的间隔 操控输出的色彩,从而到达如下右图展现白色圆形区域。但仔细观察不难发现圆的四周十分锯齿十分显着,所以视觉上很不漂亮。本篇将介绍一下 smoothstep 函数让值能够滑润过渡。
有锯齿 | 滑润过渡 |
---|---|
内置函数 smoothstep(e0,e1,v) :
v < e0
时, 返回 0;
v > e1
时, 返回 1;
v 在 [e0,e1] 之间
时,经过曲线函数在 0~1 间过渡插值
这样的话,经过圆形区域操控纹理采样,就能够得到边际光滑的图片,如下右图:
有锯齿 | 滑润过渡 |
---|---|
smoothstep 办法能够让结果在 [e0,e1] 区间内逐步改动,而不是像 step 非 0 即 1 的忽然改动。下面的 circle 函数中,len 表明像素坐标间隔,区间是 [r, r + 0.1]
:
-
当 len 小于 r : smoothstep(r, r + 0.1, len) = 0 ;
1-0 = 1
,表明白色(如下内虚线区域)。 -
当 len 大于 r : smoothstep(r, r + 0.1, len) = 1 ;
1-1 = 0
,表明黑色(如下外虚线外部)。 -
当 在 [e0,e1] 之间 : smoothstep(r, r + 0.1, len) 会从 0~1 过渡插值,
1 - 结果
便是从1~0
的过渡突变,也便是两个虚线间 由白到黑 的突变过渡。
#version 460 core
#include <flutter/runtime_effect.glsl>
precision mediump float;
out vec4 fragColor;
uniform vec2 uSize;
float circle(vec2 coo, float r) {
float len = length(coo);
return 1 - smoothstep(r, r + 0.1, len);
}
void main() {
vec2 coo = FlutterFragCoord() / uSize;
coo = coo * 2 - 1;
float ret = circle(coo, 0.5);
fragColor = vec4(ret, ret, ret, 1);
}
2. 经过交互来操控过渡区域巨细
前面介绍过 Flutter 向着色器中传参,如下所示,定义 uThreshold
变量操控突变区域的巨细。经过 Slider 的拖拽事件改动 uThreshold 的值,从而更直观地展现 smoothstep 的作用:
#version 460 core
#include <flutter/runtime_effect.glsl>
precision mediump float;
uniform float uThreshold;
uniform vec2 uSize;
out vec4 fragColor;
float circle(vec2 coo, float r) {
float len = length(coo);
return 1 - smoothstep(r, r + uThreshold, len);
}
void main() {
vec2 coo = FlutterFragCoord() / uSize;
coo = coo * 2 - 1;
float ret = circle(coo, 0.5);
fragColor = vec4(ret, ret, ret, 1);
}
3. 图片纹理和滑润过渡的结合
上节介绍过经过圆形区域来采样图片的色彩,这儿也是类似。经过 color*ret
就能够到达想要的作用。因为:
- 黑色时
ret = 0
,任何色彩乘 0 后透明度都会变成 0 ,作用是不显示。 - 白色时
ret = 1
,任何色彩乘 1 不变,作用是原样显示。 - 在中心的过渡区域内,即色彩的各个分量减少必定的百分比
uThreshold = 0.2 | uThreshold = 0.3 |
---|---|
这样就完成了图片边际模糊突变的小特效:
#version 460 core
#include <flutter/runtime_effect.glsl>
precision mediump float;
uniform vec2 uSize;
uniform float uThreshold;
uniform sampler2D uTexture;
out vec4 fragColor;
float circle(vec2 coo, float r) {
float len = length(coo);
return 1 - smoothstep(r, r + uThreshold, len);
}
void main() {
vec2 coo = FlutterFragCoord() / uSize;
coo = coo * 2 - 1;
float ret = circle(coo, 0.5);
vec2 picCoo = (coo + 1) / 2;
vec4 color = texture(uTexture, picCoo);
fragColor = color*ret;
}
本文主要介绍 smoothstep 的使用,让某段区域能够滑润过渡,从而在视觉上消除锯齿或者其他过渡不和谐的改动。尽管 smoothstep 很强壮,但是本质上是十分简单的。在 e0 ~ e1 直接经过 x * x * (3 - 2 * x)
函数进行滑润过渡:
float smoothstep(float e0, float e1, float x) {
x = clamp((x - e0) / (e1 - e0), 0.0, 1.0);
return x * x * (3 - 2 * x);
}
也便是说过渡区域内输入的值,将被以如下的曲线转化输出:比如上面第一个事例区域在 [0.5,0.6],过渡时符合蓝框区域的曲线:
那本文就到这儿,后边还会带来更多 Flutter & GLSL 的知识,我们下次再见 ~