十年代码生涯一瞬间,代码即人生!
<返回上一级
webgl滤镜--会呼吸的痛
WebGL前端

我们一起来完成一个webgl的滤镜效果,可能有的人会问?为什么要叫会呼吸的痛呢?没有为什么,因为刚睡醒
闲言少叙让我们直接看一下效果。


是的,上面就是我们要实现的效果,不是整张图片全部做一个滤镜效果,而是在图片的左上角做一个呼吸的红色渐变效果。
我们分三步完成这个效果,第一步把图片显示出来,也就是没有滤镜效果的图片显示出来。
第二步为整张图片做一个红色的滤镜效果。
第三步为局部做一个呼吸的红色滤镜,也就是最终的效果了。

一 显示整张图片

显示整张图片这里呢,你可以参考《webgl编程指南》这本书去做,当然我也会在最后附上我的代码,那里面也有,我不想在此赘述过多的代码问题。
直接上最后的效果吧!


上面效果的实现,包括初始化缓存区,向缓存区写入数据,为顶点赋值等等,因为此篇重点不在这,所以就不多说了。
通过上面呢,我们就将整张的图片显示了出来,接下来就是为整张图片添加一个红色的滤镜效果了。

二 整体添加红色滤镜

我们知道一般颜色的体现是基于三原色光模式的,也就是r(红色),g(绿色),b(蓝色),三原色的色光以不同的比例相加,从而产生多种多样的色光。
我们最后要实现的效果是在图片的上面添加一个红色的滤镜,那么我们需要改变的就是R值了。

上面的图片中看到的是显示整张图片时候的片源着色器代码,我们只需要在29行和30行之间加上一句代码,就可以实现整张图片的滤镜效果。


第30行代码的含义就是为texture的三原色中的R值添加0.2
因为三原色的值在片源着色器中的范围是0.0~1.0,因此我们添加的值需要控制在这个范围之内,其余的值你可以自己试一下看看是什么效果。 让我们看一下添加了全局的滤镜的效果。

OK,到此呢我们实现了主体的效果,接下来就是为右上角局部添加呼吸滤镜的效果了。重点来啦!

三 为局部添加滤镜效果

让我们先看一下webgl中坐标系的情况。

在webgl中,或者说在我这次添加的坐标系中是这个样子的,有的人会问:不对啊,明显这个y轴的长度大于x轴的长度,但是还都是1.0。
事实就是我画的这个样子的,你别慌。
OK那么我们接下来的思路就是获取右上角的部分,然后为其添加颜色,问题来了,你要怎么获取右上角呢?按照区域划分吗?
不不不,我们这次不需要区域划分,让我们换一种思路思考一下。
如果我们还是为全局添加滤镜,但是按照不同的区域添加不同的效果,但是不需要区域划分,我们先将每一个点的横竖坐标相乘。

图中列举了5个点,我们发现从左下角到右上角,横竖坐标相乘以后会变得越来越大,最大的是1.0。 那么我们为不同点的R值添加上其横竖坐标相乘以后的值会是什么效果呢?

最后的效果是不是就像单独为右上角添加了红色的滤镜。
其实呢我们还是为整张图片添加了滤镜只是左下角添加的色值比较小,因此在效果上面看着不是那么明显。
现在效果是添加上了,但是怎么让滤镜出现再消失呢?
我们在传入片源着色器中的参数一般会包含一个变量,这个变量一般是为了做动画的。这次我们就利用一下这个值。
我传入的是一个从0.01一直在变大的time变量,然后在片源着色器中使用sin(time)函数来得到一个会在一定范围内变化的变量值。

在上面的代码中,首先使用每一个点的x坐标乘y坐标(v_TexCoord.x*v_TexCoord.y)然后再乘sin(time)这样就会得到一个类似于sin函数曲线的波动效果,为了调节效果呢,我在最后除了2.0,这个2.0你们可以试着换一下。
经过这些操作我们就得到了一个波动的color值,然后我们将这个color值赋值给texture的R,最后赋值给gl_FragColor,让我们一起看一下效果。

前面的效果没有问题了,已经为右上角添加上了滤镜的效果,但是发现后半段会变成一个绿色的滤镜,这个是为什么呢?
原因在于sin()函数。


因为sin函数的波动是有正负值的(默认情况下),当color的值走到红框内的时候滤镜就会显示红色,当走到蓝框内的时候就会显示蓝色了,但是蓝色并不是我们想要的效果,如何修改代码来实现呢?
有人说做一个判断就OK了,当color的值小于0.0的时候我们就不做什么。
这样判断是可以,但是我们直接使用webgl的内置abs函数会更便捷一些。
最终的代码是:

以上呢我们就得到了我们想要的最终效果,一个呼吸的滤镜,但是我在添加滤镜的时候呢,使用的是加法,这样会用问题。
假如说背景图片是纯黑色或者纯白色的时候,那么显示的效果就会出现问题(也是一位大佬指点我才发现这个问题的),这个问题的解决方案呢,本次不会去赘述( https://juejin.im/post/5bcdad5ce51d457a997b7ef0 )这个链接就是指点我的大佬出的解决方案你可以移步去他那里看一下。

本文的最后我附上我的代码地址,你可以下载看一下,结构很简单,只有一个html文件,然后和引用的js,img文件,并且在html的94行那里我注释了引用纯黑除白的图片代码,你可以试着研究一下。
代码地址:https://gitee.com/wangtao_it_vip/filter-one-test/tree/master