preintegrated skin rendering

预积分皮肤渲染

本文主要记录预积分皮肤渲染的思路以及一些要点解析

算法思路

正常而言次表面散射通常需要模拟光线通过皮肤或收集周边皮肤位置的光照贡献。

屏幕空间扩散(TSD)的方案就是通过在纹理空间保存入射光信息,并通过模糊操作实现扩散

这种渲染方式需要多Pass且性能不高。而预积分的方案则可以在局部着色模型下实现,无需多Pass

首先引入扩散剖面(Diffusion Profile)的概念,其表示有多少光照扩散到入口点一定距离的皮肤着色点

预积分模拟散射效果主要分为以下三个层面:

  • 光照模型
  • 表面细节
  • 光照遮挡(即阴影)

首先假设一个均匀方向光完全照射一块平整的皮肤,在该特定情况下,由于入射光处处相等,不会发生可见的散射

只有三种情况下会导致可见的散射:

  • 非平整的面元,即存在曲率变化
  • 法线贴图产生的凹凸
  • 光线遮挡

光照模型层面

首先考虑平滑且弯曲的表面,会由于表面弯曲而导致光照发生透射,产生散射现象

而两个主要因素为:

  • $N\cdot L$的衰减,导致入射光不一致
  • 表面曲率

首先定义一个皮肤的渲染模型:

Skin Render Model

以下推导搬运自幽玄大佬的知乎文章:

N为表面法线,L为入射光方向,P为法线方向与球面的交点, $\theta$为N与L的夹角

假设P会且仅会受到法线正方向半径为r的半球表面各点的散射光影响

假设L方向的光的辐射亮度为1, 在APB半球空间的任意一点Q,其直接光照的亮度为:
$$
L_Q = 1\cdot dot(OQ, OL) = cos(x+\theta)
$$
假设Q点对P点的散射率为$q(x)$,$x$为OQ与法线的夹角,设Q所占半球的弧度为$\Delta{x}$,则Q对P的贡献为:
$$
L_Q \times q(x) \times \Delta{x} = cos(x+\theta)q(x)\Delta{x}
$$
对于整个半球积分:
$$
\int_{-\pi}^cos(x+\theta)q(x)\Delta{x}
$$
根据能量守恒,$q(x)$作为散射率函数,需要满足整个球面积分的结果为1:
$$
\int_{-{\pi}}^{\pi}q(x) = 1
$$
这里我们选用扩散剖面作为散射率函数,扩散剖面是一个关于距离的函数,且其积分并不一定为1
$$
\because d = 2rsin(\frac{x}{2}) \
\Rightarrow R(d) = R(2rsin(\frac{x}{2}))
$$
但是我们可以假设如下关系:
$$
q(x) = kR(d) = kR(2rsin(\frac{x}{2}))
$$
因此:
$$
\int_{-{\pi}}^q(x) = \int_{-{\pi}}^kR(d) = k\int_{-{\pi}}^R(d) = 1
$$
求解k:
$$
k = \frac{1}{\int_{-{\pi}}^R(d)}
$$
因此:
$$
q(x) = \frac{R(d)}{\int_{-{\pi}}^R(d)}
$$
代入3式中:
$$
\int_{-{\pi}}^\frac{cos(x+\theta)R(d)}{\int_{-{\pi}}^R(d)}\Delta{x}
$$

由于$\int_{-{\pi}}^R(x)$为常数,因此上式等价于:
$$
\frac{\int_{-{\pi}}^cos(x+\theta)R(d)\Delta{x}}{\int_{-{\pi}}^R(d)}
$$

结合(5)式可得:
$$
\frac{\int_{-{\pi}}^cos(x+\theta)\cdot R(2rsin(\frac{x}{2}))\Delta{x}}{\int_{-{\pi}}^R(2rsin(\frac{x}{2}))}
$$

DiffusionProfileWeights

高斯函数使用:
$$
G(v, r) = \frac{1}{\sqrt{2\pi v }}e^{-\frac{r^2}{2v}}
$$
因此上述高斯和等价于:

1
2
3
4
5
6
7
G(r) = 
G(0.0064 * 1.414, r) * float3(0.233, 0.455, 0.649) +
G(0.0484 * 1.414, r) * float3(0.100, 0.336, 0.344) +
G(0.1870 * 1.414, r) * float3(0.118, 0.198, 0.000) +
G(0.5670 * 1.414, r) * float3(0.113, 0.007, 0.007) +
G(1.9900 * 1.414, r) * float3(0.358, 0.004, 0.000) +
G(7.4100 * 1.414, r) * float3(0.078, 0.000, 0.000);

左图表示使用上述高斯和时红,绿,蓝光在皮肤下的扩散剖面可视化

右图表示如何对散射效果进行预积分

DiffusionProfileIntegrate

自定义Hexo博客显示 debug tool for game develop

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×