Flutter & GLSL - 陆 | 平滑过渡 smoothstep

本文介绍了如何在Flutter应用中利用GLSL的smoothstep函数实现图像平滑过渡,消除锯齿效果,通过圆区域控制和参数交互演示了这一技术的应用,以及如何结合纹理采样实现边缘模糊效果。
摘要由CSDN通过智能技术生成

theme: cyanosis

Flutter & GLSL 系列文章:

案例代码开源地址 【skeleton】

shader5.png


1. 去除锯齿

在上一篇中,我们通过 step 函数通过 像素与原点的距离 控制输出的颜色,从而达到如下右图展示白色圆形区域。但仔细观察不难发现圆的四周非常锯齿非常明显,所以视觉上很不美观。本篇将介绍一下 smoothstep 函数让值可以平滑过渡。

| 有锯齿 | 平滑过渡 | | --- | --- | | image.png | image.png |

内置函数 smoothstep(e0,e1,v) : v < e0 时, 返回 0; v > e1 时, 返回 1; v 在 [e0,e1] 之间 时,通过曲线函数在 0~1 间过渡插值

这样的话,通过圆形区域控制纹理采样,就可以得到边缘光滑的图片,如下右图:

| 有锯齿 | 平滑过渡 | | --- | --- | |image.png| image.png|


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 的过渡渐变,也就是两个虚线间 由白到黑 的渐变过渡。

image.png

```c

version 460 core

include

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 的作用:

46.gif

```c

version 460 core

include

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 | | --- | --- | | image.png | image.png |

这样就完成了图片边缘模糊渐变的小特效:

```c

version 460 core

include

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) 函数进行平滑过渡:

c 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],过渡时符合蓝框区域的曲线:

image.png

那本文就到这里,后面还会带来更多 Flutter & GLSL 的知识,我们下次再见 ~

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值