写在前面
写在前面唉,最近筋疲力竭,课题组的东西一堆没做,才刚刚开始带着思考准备练习作品,从去年5月份开始到现在真得学了快一年了,转行学其他的真的好累,,不过还是加油!
下面是做面片云的部分,关于日月、天空渐变、大气散射(忘了记录了,后面一定补上)记录在了:【程序化天空盒】过程记录01:日月 天空渐变 大气散射
准备
前置知识
面片云这块儿我卡了挺久的了,主要太多知识漏洞了,带着问题学习的话完成了以下内容的学习:
分析他人作品
目前我能找到的各位大佬做完并展示出来的有以下几个(仅限于我自己有刷到的,可能还有遗漏的):
首先还是之前博客里就提到的两位加上了sdf消散效果的作品:
Unity 卡通渲染 程序化天空盒 昼夜变化_哔哩哔哩_bilibili
云是单独的面片,不同通道放不同的信息,shader中获取。
以及这位UP的Unity NPR 原神Cloud,Sky,Shader_网络游戏热门视频 (bilibili.com):
再补充一些最近看到的很棒的作品里的云:
首先是这位程序化天空盒实现昼夜变换 - 知乎 (zhihu.com)大佬的效果,截图来自文章末尾的gif链接:
【技术美术】风格化动态天空效果_哔哩哔哩_bilibili
b站上一个好厉害的UP做的,没说怎么做的,从他云的效果来看,首先边缘光是会根据太阳的位置而产生变化,但是没有上面三位大佬那样的消散效果,所以我猜测是放了一整个云贴图上去,采样得到的。看着看着我突然发现这些云就是原神的云贴图,也是我准备用的哈哈哈。
【unity练习1√】urp程序化skybox_哔哩哔哩_bilibili
这位UP没有说实现方法,但从他展示的shader面板可以猜测,实现方法是直接给了整个天空的cloud贴图:以及单独的a通道控制一些bloom之类效果吧(猜的
正是因为是整张贴图,没办法根据太阳光的位置去做一些散射、云消散的动态效果。
【作品】技术美术Demo海滩小屋(风格化场景渲染)_哔哩哔哩_bilibili
这位UP在评论区说了云的制作:
思路概括
既然做都做了,那一定要尝试动态消散效果!
Unity 卡通渲染 程序化天空盒 - 知乎 (zhihu.com)还是跟着这位大佬实现!试着总结一下文章给出的思路,
- maya或任何建模软件,建云的面片模型
- 面片模型需要给到两套UV,准确映射到想要的云贴图上
- fbx导入unity,给一个shader完成需要的效果
1 模型和贴图
暂时先不自己画白嫖原神的图(后面有时间想尝试Houdini程序化生成云来着,再看吧,蛮有趣的),原神的图R是shadow layer,G是Rim,B是SDF,A就是外黑内白的透明度了。
之前分析篇【Unity天空盒】卡通渲染中如何实现云的消散效果在SD里拆开看过:
blender里摆了摆面片,我是mesh球直接拆看弄的,摆的乱七八糟,映射也是没分层123层混用了,效果调出来了之后再优化一下吧!现在就先这么着:
导出fbx就行。(哦,记得法线要flip一下,面片没有厚度,不然算是外面一层才能穿上贴图。
我的贴图感觉融合了一下变得乱七八糟,尝试分了一下通道是下面这样的结果,不管了后续再优化,现在先放着:
检查一下我们的面片是否正确:
简单先用shadowlayer通道上个色,好的,是正常的,可以进行下一步了: (果然天空盒还是要有云的!!)
2 上色
2.1 基础色 阴影色
由r通道控制,给个lerp就行,初版代码:
效果就是上面那张图啦,但是我想要更加动态,先浅加一个早晨和傍晚的_BrightColor不同,后期可以根据需要,让早晨、白天、傍晚和晚上的颜色都不同,想要云颜色更有层次的话甚至可以把云分为两层来着色,目前颜色就先这样吧!主要代码如下,
暴露的参数如下,
效果如下,就简单放个对比图了,搞gif太费劲,最后呈现效果的时候再放gif:
可以发现边缘的BrightColor是由浅肤色->橘色靠拢,根据天空的颜色适当的调整就行。
2.2 边缘光
边缘光要跟着太阳(光源方向)走,首先要lightDor和worldNormal点积解决,初版代码:
效果如下:
这太僵硬了,想要更加动态,
- 边缘光颜色:早晨Bloom和傍晚Bloom颜色不同,由lighDir.z控制就好
- 边缘光强度:随着太阳升起和落下强度由弱->强->弱:由lightDir.y控制就好,至于强弱变化,善用smoothstep完美解决(不理解的话可以看看我之前写的【Unity云消散】巩固step,lerp和smoothstep,事实上所有变化效果基本都是靠lerp和smoothstep完成的)
主要代码如下,
Shader面板暴露参如下,
改后傍晚的Bloom光相比起早晨的白色,改成了橘黄色,更加和谐了(maybe),后期可以再调整,现在就先这样:
边缘光强动态就先不放了,后期放个完整的gif效果。
问题还是很大,首先,看看大佬的边缘光成果:
目前只是严格按照G通道做边缘光,G通道是这样的:
所以得到的效果一定是规规矩矩的描边。想要上面那种随意的模糊感,就要给个noise贴图扰动一下uv,再去采样_CloudTex,拿一张noisemap:
扰动之后,没那么整整齐齐的边缘了:
【补充】用脚本控制颜色
由于想让云的颜色和天空颜色有关联,让整个天空更加完整,最好整个天空盒部分的所有颜色都趋向于脚本控制,这里赶紧搞一下~把参数全部挪到脚本里。
【补充】重做了云面片
blender里重新摆了一下。
2.3 消散效果
云贴图整整齐齐的通道给我们省去了不少麻烦!Unity 卡通渲染 程序化天空盒这位大佬在实现的时候,是完全自己做的云贴图,没有把SDF信息塞到a通道里,而是另外给的贴图。我们的云贴图就不用了,直接获取B通道的SDF信息就行。
实现起来分两步走,首先消散效果应该分为两个部分,
- 日出日落剧烈的消散
- 白天和晚上正常时间,云的消散
第二个比较简单,我们先来实现这个。
我们知道,片元着色器这边最终输出的颜色Alpha值是取的云贴图的a通道透明度信息:
关于SDF图,一开始理解错了SDF的意思,,SDF记录的信息并不是透明度,而是距离啊!!!以下理解才正确:
我们需要规定一个临界值_LerpSize,那么对于SDF图上的某一点,大于则留下(计入透明度),小于则舍去(不计入透明度)。这样控制才是正确的,_LerpSize越大消散越剧烈,意味着云也就越小。
现在要让这个消散效果动起来:又要建立函数了,_Time.y作为自变量,那_LerpSize就是随着_Time.y变化的因变量,再增加一个控制量,用cos。
那么随着时间变化m在变化,云的大小也会发生改变,如果不做一点过渡,云的范围会变化的很突然,如何过渡?m由0->1的路上,如果不断接近SDF,则Alpha由1到0。
SDF值由0变大接近m的时候,Alpha值是0逐渐变到1的,同理SDF值由1变小接近m的时候,Alpha值是由1逐渐变到0的。
结合上述关系,最后的代码如下,
这里写的很乱,是边做边写的,纯当一个技术记录吧,后面有时间的话再完善。
2.4 云颜色和天空联系
用脚本获取天空颜色,再用天空颜色一样的方法去给颜色变换就行,主要代码如下,
可控的颜色有这么多,
云部分到这里就结束了,其他部分其实也做了挺多调整的,这里就记录主要的实现过程。 之后的话,还有高空旋转云、太阳光晕、夜晚的星空和银河、整体雾效没加上,这些效果很多教程都有,后面可能就不会再写这样的博客记录了,最后摆摆相机会放个整体展示效果。