- 前段时间去听了xzw大佬的体积云线下授课,记了好几张笔记
- 根据与课期间所做的笔记和课后的复习,有了不少的知识积累
- 授课内容主要包括:体积云渲染的理论基础与实现方案、光学特征角度出发对这些特征进行建模、渲染效果和性能两方面的优化方案
- 我在下面会分享这次课程的部分所得(先在知乎发表了一下)
最终能实现的效果(未添加云投影)大概就是下面这样:
⭐️常见的云渲染方案
基于 纹理 / 粒子系统 / 几何体扰动 / 体渲染 的云渲染
⭐️不同云渲染方案的优缺点
⭐️大气的概念
所谓大气就是围绕行星/卫星等天体的气态物质外壳,模拟地球大气的视觉特征时,我们要考虑三种大气成分:
- 尺寸明显小于可见光波长的介质粒子(氧气/氮气)
- 大小接近或超过可见光波长的介质粒子(水滴)
- 具有特殊视觉效果和单独密度分布的介质粒子(臭氧)
⭐️云的分类
Luke Howard 在1803年根据云的类型划分了七种不同的云形态:
⭐️云的形态模拟
云具有不定形特征,通常采用噪声去模拟云的这种不定形特征。对于体渲染而言,一般采用3D纹理。确定纹理维度后,再考虑采用何种噪声模拟形态。DECIMA团队曾提到的 Perlin-Worley 噪声就具备很好的云形态特征。
Tileable Perlin-Worley 3D (shadertoy.com)www.shadertoy.com/view/3dVXDc
柏林噪声 基于随机,在此基础上利用缓动曲线进行平滑插值,最终效果更加趋于自然,具有较好的空间连续性。
沃利噪声 属于细胞噪声的一类实现,有明显的晶胞特征,这一特征比较好的模拟自然界云的胞状体。
柏林-沃利噪声 兼具两种云特征,有较好的连续性和晶胞效果。具体而言,可把柏林噪声以沃利噪声为下界,重映射到0~1的值域空间,从而得到柏林沃利噪声。
低频噪声与高频噪声 在体积云的制作中,常以低频噪声构建云的基本形状,并用高频噪声侵蚀云的基本形状从而塑造单朵云。
低频噪声 是一个4通道的3D纹理,R通道存储柏林-沃利噪声,G\B\A对应逐渐提升的3个沃利噪声。
高频噪声 用于为云的基本形状增加细节的3D纹理具备3个通道,分别存储频率逐渐提升的3个沃利噪声,这三个通道的沃利噪声低频噪声的G\B\A三个通道存储的沃利噪声的不同处在于其频率相对更高。
⭐️云的类别模拟
通过噪声和采样噪声,我们可以塑造出普通的云形状,但这与现实中的云的差距还是比较大。云的形态分类中很重要的一点就是“云因为水滴随着海拔高度变化具备的分布密度差异而具备了多种多样的云种类 ”,相应的,可以通过密度关于海拔高度的分布函数进行建模。
一般的,通过所谓海拔-密度映射对云的形状进行侵蚀或者增益,该映射的提供有两种思路:一种是基于计算建模、一种是基于纹理查表。
1. 数值模型
有两种常见的计算建模方法,一种基于 Remap 函数,另一种基于 Smoothstep 函数。
Remap 函数的功能是将一个值从一个定义域映射到另一个定义域。
remap(value,original_min, original_max, new_min, new_max)
{
return new_min + ( ((value-original_min) / (original_max-original_min)) * (new_max-new_min));
}
通过以下数值处理,可以塑造出一种海拔-密度映射:
float density = saturate( remap(height_fraction, bottom_start, bottom_end, 0.0, 1.0) * remap(heightFraction, upper_start, upper_end, 1.0, 0.0) );
其中,height_fraction 是归一化的海拔高度(也可以理解为云层高度比例),bottom_start、bottom_end、upper_start、upper_end 是由下到上的云层底部羽化开始、云层底部羽化结束、云层顶部羽化开始、云层顶部羽化结束。通过给定不同的参数值,可以塑造得到不同的云类型的海拔高度-密度映射。
另一种基于 Smoothstep 的计算建模如下:
float density = smoothstep(bottom_start, bottom_end, height_fraction) - smoothstep(upper_start, upper_end, height_fraction);
建模结果与 Remap 处理类似,参数含义相同
虽然不同云的形态各异,但在模拟时,可以指定少数几种云的参数设置,并通过对其参数插值,从而在指定的云形态间过度产生更多的云类型。但要注意,“先得到映射再对输入参数得到的高度-密度映射进行插值” 和 “对参数先进行插值再拿插值参数得到高度-密度映射” 是不同的,后者才是正确的。
2. 纹理查表
除了通过数值方法对云随海变化而存在的密度变化进行建模之外,还可以通过预生产或运行时生成的纹理表进行建模。下面几个例子中都采用了该种方式。
寒霜引擎的思路是将不同的云类型对应的高度-密度映射存储在R通道,将云的高度-侵蚀系数映射存储与G通道,从而实现更为细致的云类型的形态控制。
R星的思路是通过将不同的云类型对应的高度-密度映射存储在纹理通道,并通过将不同的天气参数对应的云类型状态分存于不同通道,从而实现每一种天气参数能有独有的云类型分布。
Unity的思路是将不同云类型对应的高度-密度映射存储于R通道,将云的含雨量存储于G通道,将云的AO信息存储于B通道,从而产生更多的云细节。
时间吃紧,待后续补充