焦散是模仿光透过水底的一个投影景象
有两个版本,改版最后效果如下
这里是简单的基于物体的焦散,基于水体的焦散思路是水面物体的shader中拿到ColorBuffer,然后用水体的屏幕空间坐标取采集ColorBuffer,然后用这个基于物体的焦散对采集到的颜色进行处理,这是不够的,因为这样做会使得焦散效果映射到水下就是一个平面一样,没有水下物体的纵深立体感。
解决办法是还要获取深度图,再根据深度图转世界坐标,原理不多说,玩的不能再烂了,忘记就参考Unity学习shader笔记[三十四]深度图采样和重建世界坐标的四种方式
然后根据世界坐标的xz值来进行焦散颜色的纹理映射,但是这种方法会有弊端,就是高低落差大的地方的焦散效果会比较拉长,比较扯,这时参考三向贴图的方式再进行一次处理,参考Unity学习shader笔记[六十]三向贴图 ,但是三向贴图需要片源的法线信息,那么这时就还需要后处理的法线贴图,再用屏幕坐标去采样, 关于如何获得,参考 Ta痕迹(9)——啃书之《Unity Shader入门精要》:深度纹理和法线纹理的屏幕后处理应用。关于法线贴图,在后处理中还能想到一种功能是基于深度法线贴图的边缘检测。
注意当摄像机创建一张深度+法线贴图时,深度纹理会被编码进zw分量中,法线信息则被编码进xy分量中,所以在采样后,我们要想使用它们还需要解码。
这种方式焦散效果是模仿光垂直照射到水底的,斜射还需要额外的处理, 另外世界坐标需要到01范围的映射,否则会出现焦散太大的情况。
至此水体的焦散效果的思路结束。
这是正常水体渲染时的焦散效果处理,焦散部分的原理和这里的是一样的,只是多了其他的处理。
配合对这些ColorBuffer扰动,还有水体本身的高度雾方式的水深和水纹水色等, 就比较接近水体效果了。
整体表现如下
如果只专注白色部分,确实挺像的,但是专注黑色部分就有种油污飘过的感觉了。
在侧面看的时候效果更逼真一些。
简单版的焦散效果是两张下图运动之后,颜色进行了一些处理的效果
存错格式成gif了,实际可以当jpg使用
这张图是首先随机生成黑色块较大的噪声图,然后对其中全部进行模糊,然后部分去掉模糊而成模糊的部分的黑块都有个区域最黑的,这个区域是随机的,并且是向周围逐渐变浅的,并且两个黑块变浅的速度不一样,并且同个黑块不同区域变浅的速率也不一样,可能在某个段变浅速率慢 ,在另一个段就快了。另外没有经过模糊的部分,白色和黑色都比较明显。 了解这张图对于后续的分析有作用。
焦散代码只有一句话要重点理解
o.Albedo.rgb += min(caustics2, caustics1);
这min的操作有点类似于合并混合中的min,可以一起去理解, 可以先看看 Shader Blend混合效果 中的各种透明处理的颜色混合的操作以及结果。
min函数的参数对于float3类型的变量
是每一位都用两个比较参数的相同分量的最低值代替
因为都是灰度图,rgb分量相同
当一张图偏白色部分和另一张图的偏灰色部分重合的时候
灰色部分会完全覆盖白色部分 这样白色部分看起来就会呈现不规则的形变
当两张图的缩放和运动速度和方向都差异比较大时
白色的部分就呈现的不规则会比较接近真实的水底焦散
对于两张图的黑色重叠的部分 因为黑色块部分是由边缘向中间的渐黑,
周围是偏灰的,中间才是黑
这样两张黑图在互相靠近的运动中,重叠部分选择显示较黑的,
结合黑块的特点,这样的选择在两个黑块的不同运动期间 ,会使黑块之间有几种重叠的效果:
两个速度方向刚好对着对方中心的黑块刚交锋时,两黑块的四周的灰白色部分会被挤压,表现为灰白色部分的形变和消失,这个形变和消失效果和焦散的效果是类似的。
上述两个黑块边缘部分重合到一定程度但是两个最黑区域部分还没有靠近时, 相交的部分表现
是一开始还是A覆盖B,过会就变成了B覆盖A。这种min操作使得两个黑块互相靠近的过程中,同个片源位置的颜色变深能够非常自然,因为这个片源对于单个黑块来说,是某个运动方向的,是渐变的,对于两个黑块来说的话,min操作使得该点只能取两个黑块中颜色较深的部分,当颜色较深的选择在某一帧由一个黑块切换到另一个黑块时,颜色的过渡肯定不会过大,因为上一帧该点选择了块A,说明上一帧块A比较深,下一帧的时候块B较深,黑块的颜色深浅不会突变,当下一帧又从B选择A的时候,也不会说选择A之后突然加深。
2描述的现象在整体表现来看,就是黑色部分的互相融合和互相分离的自然表现
上述涵盖了任意两个的黑块的交融效果,实际的效果还会因为两个黑块是否由进行模糊而产生不同, 对于没有模糊的黑块之间,那么这种白色的光影的压缩和形变就会比较明显。这是为了模仿水底光影中,有些部分比较闪亮并且突变比较明显的效果。当两个未模糊的黑块准备碰撞时,他们之间的min计算留下的白色部分的形变是比较明显的;当一个未模糊和模糊准备碰撞时,他们之间的光斑的亮度和形变效果会比两个未模糊的黑块稍微不那么明显。因为模糊的黑块其至白边的过度比较均匀,不像未模糊的那样突变。当两个模糊的黑块碰撞时,白色亮光这部分是变化最柔和的。
在shader中只是简单取最小,乾坤还是在图里面。图的网址来源
下面是逐帧运行图,方便分析效果。
对基础的焦散图都进行了扰动处理,扰动的方向和大小不同,使得看起来更加随机
在主贴图的基础上进行了焦散颜色叠加,另外添加了数值进行焦散强度控制
将表面着色器改成了顶点片源着色器,方便深入更改
焦散颜色与主图颜色的简单处理
基础原理还是和简单版的一致,这里对扰动的部分记录一下,首先最重要的还是这张图,扰动图的rgb构成和缩放直接决定了扰动的效果, 以前的博客对这个扰动效果进行过分析,现在是这个扰动效果的第三次应用了,前面的分别是
Unity学习shader笔记[十六]简单扰动shader 这篇分析过图
Unity学习shader笔记[四十一] 蜡烛火焰 shader
这里要注意扰动图的圈圈大小和焦散图的圈圈大小要差不多或者扰动图大一些才行,否则对焦散图的扰动会变得细腻,效果就不对了。为啥这样做还是看上面两篇文章就好。