学习笔记·体积渲染

※ RTR(chap.9)和GPU Gems阅读笔记

✅ 物理背景和数学模型

✅ 简易体渲染方案

🟩 主流体渲染方案

⬜️ 体积渲染阴影

⬜️ 体积照明

⬜️ 体积渲后处理方案

物理背景和数学模型

光子在传播过程中,会与介质发生碰撞反射,形成散射现象(light scattering)。

光子在遭遇介质时,大致会发生以下四类事件:

综上,传播过程中,光子的消耗量计算为$\sigma_t = \sigma_a + \sigma_s$,介质的吸收散射系数被定义为

$$\rho = \frac{\sigma_s}{\sigma_s+\sigma_a} = \frac{\sigma_s}{\sigma_t},\rho \in [0,1]$$

牛奶之所以呈现不透明乳白色,是因为其光照散射效应强($\rho > 0.999$);而红酒呈现透明红色,是因为其几乎无散射现象但吸收率高($\rho$值小)

上述这些属性与光的波长相关,在图形学中,用RGB来替代光谱值进行计算。

考虑散射的辐射量计算

在考虑散射影响后,光照传播的radiance计算公式从无消耗假设下的$L_i(c,-v)=L_o(p,v)$扩充为

\[L_i(c,-v)=T_r(c,p)L_o(p,v) + \int^{\|p-c\|}_{t=0}{Tr(c,c-vt)L_{scat}(c-vt,v)\sigma_sdt}\]

透射率

其中$Tr$为从点$x$到摄像机位置$c$的光照通过率(transmittance),计算由Beer-Lambert Law定义,

$$T_r(x_a,x_b) = e^{-\tau},其中\tau = \int^{x_b}_{x=x_a}\sigma_t(x)||dx||$$

$\tau$为光学深度(optical depth),是一个无单位量,代表光在介质中传播路径上被散射或吸收而被移除的量,举例,$\tau_t = (0.5,1,2)$时,光在经过1米传播后,$T_r = e^{-d\sigma_t} ≈ (0.61,0.37,0.14)$。$\tau_t = (0.5,1,2)$的$T_r$图像如下,

$R$通道的值为0.5,意味着红色光因散射/吸收导致的损耗较少,即红光的通过率较高,物体最终呈现颜色会偏向红色。

散射计算

散射计算的公式如下

$$L_{scat}(x,v) = \pi\sum_{i=1}^np(v,l_{c_i})v(x,p_{light_i})c_{light_i}(|| x-p_{light_i}|| )) $$

$v(x,p_{light_i})$是可视度函数(visibility function),计算成功从光源处抵达视角位置的光的比例(即阴影的影响)。

\[v(x,p_{light_i}) = shadowMap(x,p_{light_i})·volShad(x,p_{light_i}),\] \[其中,volShad(x,p_{light_i}) = T_r(x,p_{light_i})\]

实际上阴影由两个部分组成,一是不透明物体的阴影,即$shadowMap(x,p_{light_i})$,使用shadowmap来计算;一是体积阴影,$volShad(x,p_{light_i})$,这部分阴影不仅要考虑体积在其他物体上的投影,还要考虑体积的自阴影,通常使用raymarching来计算,后文再议。

$p(v,l_{c_i})$是相位函数(phase function)。

介质有拥有不同辐射范围的粒子构成,这些粒子的尺寸分布和光的方向会共同影响光散射的可能路径。相位函数就是从微观角度描述内散射方向的分布和概率。

如图,红色区域包含顺光照方向的一个lobe和逆光照方向的一个lobe,这俩lobe是光照在x点处发生散射的范围,显然顺光照方向的散射效应更强。遵循能量守恒,这个相位函数的lobe总值在单位圆上守恒为1。

RTR中提到了三种相位函数,分别为Rayleigh、Mie、geometric散射,应用于不同尺寸介质粒子$s_p$的情况。这里说的粒子尺寸不是粒子的半径啊什么的,而是粒子半径$r$与波长$\lambda$相关的一个参数

$$s_p=\frac{2\pi r}{\lambda}$$

1) $s_p « 1$时,即粒子极小时,对应Rayleigh散射。此模型用于描述天空大气的散射,有俩lobe。

$$ Rayleigh: p(\theta) = \frac{3}{16\pi}(1+cos^2\theta) $$

在该模型下,散射程度与波长成强关联,散射系数$\sigma_s$有关系如下

$$\sigma_s \propto \frac{1}{\lambda^4}$$

这意味着短波长的蓝色或紫色光的散射会比红光强,也意味着天蓝是因为Rayleigh散射(大声)。

2) $s_p ≈ 1$时,即粒子半径与波长差不多时,对应Mie散射。这一情况下的散射与波长(即光的颜色)关系不大。但由于这个方程可能太复杂了,书中直接介绍了俩平替函数,HG和Schlick相位函数,可以较好地模拟其中单一lobe的图像(ps.$g=0$时可获得瑞利散射图像)。其中Schlick效率更高,是HG的平替,因为公式中没有复杂的幂运算只有一个平方。

$$ HG: p_{hg}(\theta,g) = \frac{1-g^2}{4\pi(1+g^2-2gcos\theta)^{1.5}} $$

$$ Schlick: p_{schlick}(\theta,k) = \frac{1-k^2}{4\pi(1+kcos\theta)^2} $$

3) $s_p » 1$时,即粒子超大时,对应Geometry散射。这一情况下,光照会在粒子表面发生反射和折射,相当复杂,对应此散射的一个现实例子——彩虹,就是光在水汽发生内部反射所致。

※ 上述几个函数的图像画在这里了

简易体渲染方案

※ 有些方法可能会有点过时

雾效

之前在S站写过一个这种方法实现的雾效→Alfx Fog 1,基本的深度雾和高度雾也是这个原理。

体积光

最简单的体积光就是借用透明mesh制作fake light shaft效果,在mesh上应用粒子材质可以模拟体积光中的飞舞的尘埃营造体积感。缺点在于透明会比较耗。

此外屏幕后处理也可以模拟近似散射效果,这个稍后再议。

主流体渲染方案

※ 基于物理的渲染方案。需要考虑进场景中其他物体与体积物体的交互效果。目前主流方案为3D texture。

3D贴图

简单来说就是将数据储存在体素(voxel)单位中,每个体素可以用来生成三维空间图像。在医学上的应用即CT。

在实时渲染中,体素信息会被存储在一个三维矩阵中,生成一整套2D切片贴图,为方便数值读取,通常会将这一整套2D贴图存储为一张较大的贴图,贴图尺寸设置为2的n次方最佳(因为内存二进制),比如打算切片采样256次,单张2D切片尺寸为128,则包含整个图集的贴图尺寸为($\sqrt{256} × 128)^2 = 2048 × 2048$。

举个例子,按上述尺寸制作的湖底泥猪头3D贴图素材如下:

基于3D贴图的代理几何体生成

渲染时,引入了代理几何体(proxy geometry)的概念,即先根据boudning box和3D贴图在视角空间绘制出代理几何体,再将代理几何体转换到物体空间。GPU Gems中对此技术的实现算法大致如下:

  1. 根据3D贴图给出的体素信息获得boudning box垂直视角方向的切片,将这些切片的顶点坐标转换到视角空间。

  2. 找到最小z坐标和最大z坐标,根据采样切片数计算出采样距离。

  3. 对每个切片依序(从前到后或者从后到前都可)进行如下操作:

    1) 测试切片与bounding box的交界点,获取一个交界点数组,因为正方体的斜切面最多只有6个交点,所以这个数组的大小固定。

    2) 根据这些交界点,计算出代理几何面片的中心,根据中心对代理几何体面片的顶点进行顺时针或逆时针的排序,并以第一个顶点为参考计算出一个伪角度(pseudo-angle),用于排序。

    3) 将代理几何面细分为三角面(其实就是新增一个顶点在面中),并将顶点加入前述的顶点数组,根据之前的顶点排序按照triangle fan或者triangle strip的方式生成三角面。

    4)最后根据渲染算法,可能还需要将代理几何体转换回物体空间,也可能直接渲染到世界空间。

转换函数

简单来说,转换函数是为了凸显体渲染中的重要信息,原理就是函数值映射到3D贴图的颜色和透明度上,影响渲染出的图像。

早年在体渲染中只用到一维转换函数,但是后来发现一维函数无法准确地渲染体积。例如CT扫描成像中,最后成像的空气、骨头、软组织、血管、体液等,只用一维转换函数无法清楚地渲染不同层级的边界。

应用1D转换函数的体渲染图像如下,可以通过调整曲线分别修改rgba通道,x轴表示距体积中心的距离,y轴表示强度。图中曲线调节R通道凸显皮肤,GB通道凸显骨骼和静脉,但是无法避免同一像素点处颜色重叠的现象。

应用2D转换函数的体渲染图像如下,转换函数图中背景两个渐变弧度表示不同材质以及材质的边界,俩正方形表示期望渲染的颜色和位置,可以看见红色框所在的位置渲出了皮肤部分,黄色框则渲出了内部的骨骼部分。相较上图1D转换函数,2D转换函数可以更准确地定义在什么位置显示什么材质/颜色。

转换函数是体渲染中相当难设计的一个点,维度越多可以获得更加精确的体渲染效果。如果感兴趣可以在这个页面下载ImageVis3D这个软件,配套还有几个体积模型和转换函数的sample可以玩。

另外在这篇文章的p.5有一个比较清晰易懂的例子,解释了1D和2D交互曲线的含义。

参考

  1. RTR第14章

  2. GPU Gems Chapter 39. Volume Rendering Techniques

  3. GPU Gems 3 Chapter 13. Volumetric Light Scattering as a Post-Process

  4. Multi-Dimensional Transfer Functions for Volume Rendering