玩过ShaderToy的肯定都听过iq这个名字,即使没有听过,肯定也见过他的一些作品,比如随便截两张:
千万不要误会,上图中的两个效果可不是建模渲染的展示,而是由纯GLSL语言(说纯语言不准确,倒是有用到一些纹理图片)生成的哦,并且还是有动态效果的?
有兴趣的可以去他的个人主页观摩下,同时iq也是ShaderToy的创始人,在上面创作了非常多很有启发性的作品。
好了,让我们回到残酷的现实中来,先从iq大神的一篇极其简单的作品开始吧?
为了更准确的表达此篇文章的内容,我会在移植到Unity中时做一些删减与修改,以便读者能更好的理解与阅读。
先放上这次的最终效果视频:
顶点著色器中与以往一样,没有什么特别的,我们重点来关注下片断著色器。
i.uv 表示的是屏幕上0-1的归一化坐标, ScreenParams.xy表示的是屏幕的长宽像素,而i.uv*ScreenParams即可得到屏幕上的每个像素点的坐标。
所得到值再除以_ScreenParams.x(注意这里是.x),即可得到以宽像素为基准的UV分布图。
细观察得到的uv值,在x的值上是0-1的值,但是在y值上却不是0-1,看效果感觉是0-0.45左右,这就是我们除以_ScreenParams.x得到的效果,目的是为了使画面不变形,以实际像素为基准进行表现。
二维向量p根据式子拆分后可以看出是为了得到以下的动画效果:
其中p.x在后面会表示为方格到细胞格的变化因子。
p.y则表示为清晰到模糊的变化因子。
return iqnoise(24*uv,p.x,p.y);
是我们最终返回的颜色值,其中iqnosie是我们自定义的一个函数,是整个效果的核心实现,代码如下:
按照执行顺序,我们先来分析下iqnoise函数。
float2 p = floor(x);
floor(x),表示对x值进行向下取整。
这里的x值就是frag中调用iqnoise方法的第一个参数24*uv,也就是将现有的uv乘以24倍。
float2 f = frac(x);
frac(x),返回x值的小数部分
对24倍的uv取小数,其实就是将其分成24份独立的小uv块,y轴上由于上面做了特珠处理,所以不会是24份,同时保证了不变形。
由于p.x与p.y分别表示了格子的变化与模糊的变化,那么为了更直观的分析,让我们假设p.x=0时,p.y保持原有不变,则效果如下:
iqnoise同步修改后部分代码如下:
k值先忽略,继续往下看。。。
分别定义了va与wt,都初始化为0
然后开始一个5x5的嵌套循环,值域如下:
定义二维向量g,值为当前循环中的坐标点
定义三维向量o,默认初始化为0
o的z值等于hash3(p2+g).z;
也就是当计算当前像素点时,会对此像素周围的24个像素点分别取值采样(是不是感觉和我们平时做图像模糊时用到的卷积演算法很相似?)。
好,现在让我们来看下自定义的随机函数hash3.
hash3函数,它的主要作用是为了返回随机的方格效果
在之前的案例中我们有知道随机噪波的常用公式为:
frac(sin(dot(i.uv.xy, float2(12.9898, 78.233))) * 43758.5453);
其中dot()的部分在我们这里是用q来表示,q是三维向量,分别代表著RGB三个不同的通道。
以R通道为例,可拆解为:
q.r=frac(sin(dot(p2,float2(127.1,311.7)))*43758.5453);
效果如下:
可以看出其实就是通过p2的UV特性来实现类似这种马赛克的随机效果。
通过在dot中指定不同的数值来实现三个通道不一致的效果,最终RGB效果如下:
不错的彩色马赛克效果,是不是又学会了一招~
不得不说,ShaderToy中处处有惊喜!
其实hash3中我们也可以改成这样的简化版:
不过只有单通道,并且颜色在取值上会偏暗些。
好了,hash3了解完毕后,让我们继续回到上面的循环嵌套中
定义二维向量r,值为g-f,并对其做点积运算,同时利用smoothstep来实现柔和过渡效果,而这里的k就是决定模糊程度的。
float k = 1.0+63.0*pow(1.0-p.y,4.0);
可以得出k的取值在(1-64)之间,随著时间变化的曲线如下图所示:
峰谷时为模糊效果,持续一段模糊后会向清晰过渡,然后再过渡回来,就是这样的一个循环。
va与wt就是利用卷积演算法来实现加权平均后最终的像素结果。
由此可见iqnoise中的u与v值不同时可以得到不同的效果,有以下几种情况:
return iqnoise( 24.0*uv, 0,0 );
return iqnoise( 24.0*uv, 0,1 );
return iqnoise( 24.0*uv, 1,0 );
return iqnoise( 24.0*uv, 1,1 );
也就是说如果u值是0-1间的动画,那么结果就是方格到细胞格的过渡动画效果
同样v值如果是0-1的动画,那么结果就是清晰到模糊的过渡动画
同时两者也可以互相组合,最终得出本例的最终效果。
欢迎大家关注更多干货的公众号:Unity技术美术 ( ID:gh_8b69cca044dc )
Unity技术美术QQ交流分享群:19470667
推荐阅读: