基于Tessellation的体积云
用Mesh+3D噪声采样+Tessellation制作动态体积云。
之前我写过一个类似毛发做法的沿着法线绘制多层的云(Bump Noise Cloud),因为那时候安卓机可能不支持Tessellation,现在主流安卓机基本都能支持openGL es 3.1+aep或者vulkan。所以现在用tessellation搞这个基于mesh的云是毫无压力的。
效果如下图:
Tessellation
Tessellation(曲面细分)可以在Vertex之后修改顶点数据,让模型更加细腻平滑,获得更好的渲染效果。
Unity官网给出的是CG include的方式,可以直接看官方文档:
https://docs.unity3d.com/Manual/SL-SurfaceShaderTessellation.html
如果要在URP里做,就手动把CG include的相关代码搬到.hlsl就好了。详细可以参考这篇:
https://catlikecoding.com/unity/tutorials/advanced-rendering/tessellation/
注意shader要加入“#pragma target 4.6”。如果是发布mobile平台要在player setting里设置Graphic API为“openGL es 3.1”+aep或者“vulkan”。注意Metal平台是不支持Geometry的,没法用Geometry直接做framewire效果。
采样3D贴图的做法
Unity支持3d贴图采样,所以我搞了个128x128x128像素的3D Perlin噪点图。噪声图生成器参考:https://github.com/mtwoodard/TextureGenerator
先做一个大致造型的简单云朵模型,顶点分布要尽量均匀。我是直接在houdini里制作的。可以用toplogic算法自动生成均匀顶点分布的模型。
Shader里准备好Tessellation的代码,用DistanceBasedTess函数,可以根据距离控制Tessellation系数。
然后材质通过采样这张3D噪声贴图模拟云朵效果。具体做法如下:
- 在tessellation阶段做顶点偏移,沿着法线方向往外挤压偏移,同时做uv滚动,模拟云层动态。
- 在PS阶段重新计算法线。算法线的方式是偏移UV采样3次,用差值计算法线方向,虽然不是很精确,但是用作模糊的云层足够了。
加上简易光照,光照计算可以参考之前那篇:Bump Noise Cloud
采样2D噪声图的做法
当然也可以采样2D噪声贴图来做。 还可以把法线放在rgb通道,高度图放在a通道。这样省去了之前在PS里用重算法线的过程。
采样方式就是在三个轴向分别采样2D噪声图。法线的采样稍微麻烦点,要先根据世界坐标朝向重新计算每个轴向的Tangent,之后才能采样到每个面正确的NormalWS,然后按角度比例混合。
因为面与面之间是blend的,所以必然会有一点混合不自然的地方,特别是切线/副法线方向向逆的边缘。这个我暂时也没有特别好的办法解决。采样效果如下:
后续优化
用深度做半透明混合,模拟云雾缭绕的效果。还可以把玩家的坐标传进shader做顶点偏移,模拟云和玩家的交互。
云朵不需要太精细,可以降分辨率渲染云朵。例如插Render Feature来绘制云朵,用半分辨率或者1/4分辨率的RT,再Blend到CBuffer上。
视频演示最终效果: