maltadirk 发表于 2022-3-9 11:26

[Unity][翻译]云朵Shader步骤分解


人工翻译自Alexandre Stroukoff的文章《CLOUDS SHADER BREAKDOWN》,原文链接:http://astroukoff.blogspot.com/2019/09/clouds-shader-breakdown.html

在正文之前,先说下作者的制作过程,大致分为三步:
Houdini中创建云朵网格,通过“clouds”节点创建粗糙的云朵形状,生成低面数网格,并平滑法线。导入3ds Max,烘焙天光与平行光到顶点色,然后模糊。导入Unity,顶部加上滚动的云朵纹理与更多细节。

从作者的介绍来看,第一步目的是创建云朵模型,第二步目的是烘焙光照,理论上也可以用别的软件来做,并且提前烘焙光照意味着云朵在引擎中是静态不受光照的,这点需要注意,文章末尾也有关于动态光照的说明。

前两步作者只是简单介绍了一下,并且视频很糊,就不贴了,以下是正片,文章中的引用段是我的注释。

正片

原文:http://astroukoff.blogspot.com/2019/09/clouds-shader-breakdown.html
作者:Alexandre Stroukoff

我根据ThatGameCompany的游戏《Sky 光遇》制作了一个云朵Shader,本篇文章是关于它的一个小小的步骤分解。

效果中作用最大的是云朵Mesh本身,其次是烘焙光照,我使用Houdini + 3ds Max来生成它们。在这篇文章中我仅注重于介绍Shader部分,Shader使用Amplify Shader Editor(ASE)制作。

第一步连接Vertex Color(顶点色)到Emission(自发光),为了显示先前(在3ds Max中)烘焙的光照,我使用了一个0.454545的指数来校正顶点色(因为sRGB/Linear/Gamma叭啦叭啦)。

这里的0.454545幂运算将Vertex Color从线性空间变换到了Gamma0.45空间(sRGB),作者的工程设置中颜色空间为Gamma,这种情况下Unity不会帮我们做这个校正,所以需要手动做一下,如果你的颜色空间是Linear就不需要了。

大量的三角面能带来更丝滑的移位效果,如果性能上吃得消,Tesselation(曲面细分)是个好办法,在左侧面板勾上“tesselation”选项,选择distance based模式。

调整距离与tesselation参数直到你和你的电脑都满意为止,这里调一个非常近的距离就不错。

现在好玩的来了,我加了一个Noise Generator(噪声生成器),这个节点很方便,它可以根据世界位置生成3D噪声。使用3D噪声比较吃性能,你可以换成Simplex(单形噪声),我很确定整个效果都可以用噪声纹理和UV搞定。我用世界坐标乘以一个浮点数,用作噪声节点的“Size”输入,这个浮点数用来控制噪声的tiling。
并且从-1/1 映射到 0/1,避免出现负值。
在Debug输入中加入了这个(指上面的浮点数)。

通过这个浮点数调整tiling的效果


虽然tiling一般指纹理的平铺,但这里控制的是噪声纹理的大小,参数的命名也是“3dNoise Size A”。

现在,不直接使用World Position,而是将它乘以一个Vector3("NoiseScaleA"),这样可以对噪声做非统一缩放,非常方便!(就像对Mesh进行缩放一样,但你只是缩放输入位置)。这里我沿Z轴对噪声进行拉伸示范一下效果。

是时候加点移动了,很直接,在我将缩放后的世界坐标连接到噪声之前,我增加一个Vector3,令时间与它相乘,这样就可以控制噪声移动的方向。

改变噪声方向的效果(因为是3D噪声,所以看起来不错,用2D噪声比较难做到)


现在将它连到Local Vertex Offset,并与两个东西相乘:
一个范围在0-1的浮点数,用来调整强度;一个Vector3(0,1,0),用来强制让噪声只在世界Y轴上移位,只是这样看起来更不错,你也可以使用Mesh的法线。

调整新的参数,Speed(噪声速度),Size(噪声大小),Strength(移位力度)


我决定把噪声重复3次。复制所有参数,并且把它们加在一起。这让我想起了以前做过的一个项目(卡通火山碎屑噪声)。思路很简单:对于每个噪声,将力度降低一半,双倍tiling,双倍速度,然后再调整!

每个噪声之间的关系很重要,这里我只调整Strength(力度),单独调整噪声很容易(将除当前噪声外的所有力度调为0),然后调整力度。

近距离观察噪声是如何融合在一起的


对于渐变的边缘,使用透明材质和Depth Fade节点简单设置。

这一部分比较取巧(hack),但它增添了许多细节。大体上来说我就是添加了一个黑白的云朵纹理,并使用Triplanar Mapping(三面映射)采样,为了让Triplanar Mapping动起来,我使用了来自噪声C的修改后的世界位置(看下面的图1),并且我让所有东西与噪声A相乘来“抹去”这里那里的纹理(看下面的图2)。

图1 来自噪声C的世界位置


图2 噪声A

我使用了Register/Get Local Var节点,避免我的连线乱得像兜里打结的耳机线,ASE的这个功能真是太棒了。

这是云朵纹理


ASE内置了Triplanar Sampler节点,与简单的纹理采样相比,Tri-Planar Mapping在模型陡峭部分较多、UV不规范的情况下很有用。

你可以看到加入云朵纹理后的效果,真系好靓!

仓库地址: https://github.com/AlexStrook/UnlitClouds

备注:
这全都是静态的、烘焙好的(指光照),但我很确定你可以把它做成受动态光照的。你可能需要重新构造移位所需要的法线,你可以用这些节点:

我本来还想加上Flowmap,但没时间做了。Flowmap可以帮助控制云朵材质平铺的方向与噪声的滚动。我之前看到另一个很有意思的技术, 视频链接(约10分钟),他们通过微调广告牌(billboard)位置实现了战地1中的云朵。看起来相当不错,但我猜他们在幕后肯定用了什么疯狂的魔法来达到这种效果...当然说不定你也能做到!ThatGameCompany的Mike Lester说他们的做法使用了光线步进(Raymarching) 链接
页: [1]
查看完整版本: [Unity][翻译]云朵Shader步骤分解