Cesium中实现全球体积云

RayMarching

RayMarching 也就是光线步进,是 3D 图形学中的一种渲染方法,常常用来作为体渲染的主要渲染方式。

基本实现原理是,在每个像素上计算一条光线,当光线进入体纹理范围内后,将光线细分成更小的光线片段进行步进迭代,每次步进时计算相应的强度信息。最终迭代结束后,将所有步进结果进行叠加计算,得到像素的颜色

RayMarching;

体积云

体积云是利用 RayMarching 方式渲染的云效果,在一些大型游戏中很常见。

与其他渲染云的方式不同,体积云是真正具有体积感的云,一个最简单的区分方式是,体积云能够进入到云的“内部”

体积云效果

如何渲染云

体积云的渲染步骤大致为:

  1. 计算每个像素的光线方向
  2. 计算沿光线方向是否能够和体积云范围相交
  3. 获取相交范围,并在该范围内进行光线步进
  4. 根据步进结果计算云的基础形状(也就是云的密度)
  5. 计算云的光照

而其实,上面列的步骤中,1-3 均为 RayMarching 的实现。因此事实上,真正渲染体积云的步骤只有两个:计算强度和计算光照

计算云的密度
计算云的光照

计算云的密度

体积云的密度计算比较简单,只需要在 RayMarching 的过程中,采样相应的噪声图,并累加噪声结果,直到达到噪声最大值或者结束步进。

最终累加的结果就是云的密度。

1
2
3
4
5
6
7
8
9
10
float cloudDensity = 0;
for(int iii = 0; iii < _Iteration; iii++) {
float3 stepPos = startPos + iii * _StepLength;
cloudDensity += SampleNoise(stepPos);

if(cloudDensity > MaxCloudDensity){
cloudDensity = MaxCloudDensity;
break;
}
}

计算云密度的方式

计算云的光照

通常,体积云的光照分为两个部分:

  1. 总光能(当前位置接收到的总光能)
  2. 光能反射比例(当前位置的总光能有多少能够进入到眼睛)

总光能

在每一个点,向光源方向再做步进,累加噪声值得到该点在光源方向的“深度”。

举个例子:

在某点向光源方向做 8 次步进,前 3 次在云的内部,后 5 次在云的外部。

该点的深度为(1 + 1 + 1 + 0 + 0 + 0 + 0 + 0)/ 8 = 0.375。

总光能计算

光能反射比例

我们算出了一个点接收到的总光能,但这些光能只有一部分能反射到我们的眼睛(摄像机)。

从该点向摄像机方向做步进,累加噪声值得到该点在摄像机方向的“深度”,深度越大损失的光能越多。

传递到摄像机的光能 = 接收到的总光能 - 中途损失的光能。

光能反射比例计算

蓝噪声

体渲染通常对性能消耗是很大的,因此为了保证帧数,体积云的渲染会采用较低的步进次数,这样做会导致云渲染出现分层。

未使用蓝噪声

为了解决这种问题,通常需要使用噪声对步进的起始点进行扰动。

使用蓝噪声

椭球体

由于 Cesium 是 GIS 相关的渲染引擎,因此体积云必须考虑适配 Cesium 的地球形状。

解决方式是,以云最低高程和最大高程,依据 WGS84 椭球外扩两个椭球范围。并以这两个椭球范围作为体渲染的范围进行 RayMarching 计算即可。

椭球体渲染范围

全球版体积云效果展示

“地平线”版体积云效果展示

参考资料

RayMarching 实时体积云渲染入门(上)
RayMarching 实时体积云渲染入门(下)
体积云渲染(Volumetric Clouds),技术美术教程
Unity URP RayMarching 体积云


Cesium中实现全球体积云
https://www.liaomz.top/2023/12/18/cesium-zhong-shi-xian-quan-qiu-ti-ji-yun/
作者
发布于
2023年12月18日
许可协议