【本文参与征文活动】
前言
最近在学习shader,本帖子主要是分享一下我的学习笔记与几个简单的效果,文中有任何不对的地方,希望各位大佬指点一下。
总结
本文实现了
文本的渐变色,扭动效果,扫光效果。
图片的扫光,消散,虚幻,替换,水波,倒影效果,多边形裁剪效果。
2020.11.11更新
新增了文本的打印机效果。
我发现大部分还是喜欢能直接拿来用的文件,而不是开始那种测试级的,因此提交了 一个可以跑的项目。
把项目上传到了git,需要的同学可以看看哦
https://github.com/kkstare/shader2.git
基础语法部分
如图,这是片元着色器的一部分,添加了一个 USE_COLOR ,并为其添加了2个vec4类型的变量用于传入颜色,
之后设置了该值的默认值,这两步之后,就可以在材质面板操作我们的变量了。
接下来就在main函数中使用传入的变量。
接下来在材质中选择我们喜欢的颜色,那就又黄又绿吧。

最后来看看显示的效果

tips
-
#if 用于编辑器内那些框框的显示,如果是代码逻辑 使用if
2.in 传入的变量 不可被修改 out 传出的变量,如下所示,不过我搞不懂为什么顶点着色器能拿到a_uv0这个值,下面的片元着色器就拿不到了,希望有大佬解惑。
3.不能传入float,vec4之类的变量,需要把它加到一个模块中,这个我觉得是我的写法有问题,求大佬解惑。
4.编辑器与浏览器显示效果不一致时,一般是合图导致的,这时只需关掉图片的合图即可。
文本部分
在上面的语法部分中实现了从左到右的渐变效果,只需要简单的修改,就能改变其渐变的方向了。
a_color = beginColor + (endColor-beginColor)*uv.y;
a_color = beginColor + (endColor-beginColor)*(uv.x+uv.y)/2.0
刚刚修改了文本的颜色信息,现在来修改它的uv坐标试一下
uv.y = uv.y + 0.2 *sin( 3.14 * uv.x);
这段代码有个小故事,当时是在大佬群里看到他们在讨论弯曲的文本怎么实现,很久很久以前,也有策划向我提过这个需求,带着无法解决需求,就解决提出需求的人这个理念,我把那个策划喷了一顿告诉他这个实现起来太浪费性能了,因为我的想法就是用N个字符串去拼接并修改角度。看到有人来实现这个蛋疼的需求,我那一瞬间有点感同身受,正在他们激烈讨论的时候,有一个巨佬出来了,并抛出了这段代码。我盯着这段代码看了好久,好像看懂了,又好像没懂,我也不知道自己在第几层,我只知道那个下午我就那样度过了,这样划水带来的快感是前所未有的,打错字了,学习带来的快感是无与伦比的。就那样,我开始了我的shader学习之旅。
好了,废话说完了,现在看效果。
接下来使用cc_time实现可以动的文字。在此之前,先导入两个文件
接下来,最简单的用cc_time.x的正弦函数来看看效果
uv.y = uv.y + 0.2 *sin( 3.14 * uv.x)*sin(7.77*cc_time.x);
接下来,再试试修改修改颜色带来的效果
a_color = beginColor + (endColor-beginColor)*( uv.x + sin(7.77*cc_time.x)) ;
然后尝试添加一个扫光效果,因为黄绿色不明显,改了个红色演示,而且此处的扫光颜色也是使用的endColor,根据开始写的传变量的方法,就能随意修改哦。
if( abs( tan(cc_time.x) - (uv.x+uv.y)/2.0 ) <0.05 ) { a_color = endColor ; }
// if( abs( sin(cc_time.x) - (uv.x+uv.y)/2.0 ) <0.05 ) { // a_color = endColor ; // }else if(abs( sin(cc_time.x) - (1.0-uv.x+uv.y)/2.0 ) <0.05){ // a_color = beginColor ; // }
更新了一个打印的效果,并通过代码激活并传值到effect文件中,
这边主要是在脚本中获取游戏的运行时间,使得shader中的时间计算是从0开始的。
录制的gif有点卡,实际效果可以打开项目看
文本部分就这样告一段落啦。代码里面还写了一些不过效果不好看也不实用就不演示了。
图片部分
新建一个图片,可以发现它和文本用的是同一个材质。就说明他们的实现本身就是一致的,昨天看书刚好看到计算机渲染文本,所有的文字都是一个位图文件,可能就是这个原因吧。
接下来就从最简单图片开始操作了。如下图所示的jpg图片,有很多的白色部分,现在的任务就是把他们消除掉。
最简单的思路了,就是获取到该点的像素值,白色是(255,255,255),在shader中处理时,需要进行归一化,因此判断三个值都为1的时候弃置该像素。
理想很美好,现实很残酷。这就是效果,不难想到,这是我们给的条件太苛刻了,稍作修改
这里我将cutValue的值设置为了0.9,再看看效果。
这个效果非常有用,为什么非常有用呢,因为他帮我凑了这么多字数。
好吧,这个效果 我想了半天,没想到他有什么实际用途,平时不可能用它去去除图片的背景色,如果美术真的给了一张这样的图,我们应该去找美术解决这个问题的。
接下来也是一个流光效果,和之前的label实现类似。
//流光效果 #if IS_FLUXAY if( abs( tan(cc_time.x) - (uv.x+uv.y)/2.0 ) <0.02 ) { a_color = fluaxyColor; } #endif
接下来的一个虚幻效果,类似于马赛克的效果。这个卷积的代码网上还是很好找的,提问:这个地方我有个问题啊,for循环里面的RADIUS必须是常量,而我又不能传参来给常量赋值, 难道要修改这个值必须通过代码吗?
接下来一个消散效果,这个效果用到了噪声图,什么是噪声图呢,简单的来说就是一张乱七八糟,没有规律的图,下面这个就是我用的噪声图。提问:shader里面要怎么用随机数?
然后看代码,这边的texture2就是我用的噪声图的纹理资源。
再看效果
上述代码中,是直接抛弃了一部分像素的,稍作修改。加入了第三张图片,texture3就是他的纹理。
看效果,不过这个还是根据颜色来处理的,看起来效果并不自然。
接下来就是一个水面效果了,这个好多大佬都写过了。

接下来就是一个倒影的实现了,这棵树长这样,

我这边在顶点着色器中做了修改将他的高度变成了2倍,毕竟要倒影,不能直接压缩吧。

然后就是改变他的uv坐标了,y坐标是从上到下,从0到1,我们将他的高度变大后,他的uv坐标就对应的拉伸了,因此,上半部分直接拉伸,下半部分就取到沿y=0.5的对称点再拉伸。

最后加上水波特效看效果。
接下来一个圆形裁剪。这个size是我传进来的,好像在shader中没办法获取,传进来的还有需要剪的圆的半径。

这就是刚刚和大家见过面的石子地,现在已经被打磨了棱角,变的光滑无比了。

接下来就是任意多边形的裁剪,我这边是用了一张自己预制的多边形文件,如下。

代码也是比较简单的,就是判断传进来的多边形文件像素。
<img src="/uploads/default/original/3X/2/1/21932314bcf4edf8b46a779fb6af282a0715db94.png" width=“328” height=“230”
最后看效果
