概述
实时图形中的很多着色模型只考虑光在物体表面的相互作用。但现实世界中,很多物体是半透明的,光射进表面,在材质里散射,然后从与入射点不同的地方退出表面。本文将介绍几种方法,近似实现次表面散射的效果。
一、URP中的多光源计算
在Build in渲染管线中,要计算多个光源的贡献,一般的方式是使用两个Pass。可以参考《Unity Shader入门精要》第九章。
但是在URP中,不需要多个Pass,可以在一个Pass中计算。参考URP内置的Lit.shader资源,可以发现计算多光源的方式。
1 |
|
主要的思路:使用GetAdditionalLightsCount()方法获得额外的光源数量,然后遍历这些光源;使用GetAdditionalLight()方法获得指定序号的光源信息。然后计算相应光源的贡献,叠加到主光源的贡献上。
二、环绕光照
使用经典的兰伯特定律计算漫反射时,使用的公式如下: \[ c_{diffuse} = (c_{light}*m_{diffuse})max(0,n \cdot l) \] 观察上式可以发现,当表面法线和光线的方向垂直时,漫反射提供的照明度为0。
环绕光照对上述公式进行一定的修改,使得光照环绕在物体的周围。这样,那些原本暗色的地方也会有亮度。
下面的代码,显示了如何改变漫反射公式:
1 | half diffuse = max(0, dot(N, L)); |
其中,环绕值wrap是范围为\([0,1]\)的浮点数,控制光照环绕物体的距离。如下图所示:
当wrap为0时,就是标准的兰伯特反射。观察与y轴的交点,原本照明度为0的情况,随着wrap的变化,交点也在变化,表明照明度不为0了。
这里需要用到多光源的计算,参考第一部分的内容。
效果如下:
三、快速次表面散射
快速次表面散射的实现,主要是根据《Approximating Translucency for a Fast, Cheap and Convincing Subsurface Scattering Look》实现的。
主要的思路是:对于不透明材质,光的贡献直接来自光源,相对于光的方向倾斜90度以上的顶点不接受光照(如下左图);根据演示文稿中提出的模型,半透明材质具有额外的光源贡献,\(-L\)。从几何上来看,\(-L\)可以看作是某些光线实际穿过了材质并到达了另一侧(如下右图)。
这样,最终的颜色包含两部分,第一部分是正常的照明,另一部分是来自虚拟光源的照明。
计算虚拟光源照明的公式如下: \[ I_{back} = sarutate(V \cdot -<L + N\delta>)^p*s \] 其中:
- L是光源的方向;
- V是视线的方向;
- N是法线的方向;
- \(\delta\)是次表面变形参数,该参数迫使向量\(-L\)指向\(N\);
- p(功率)和s(比例)用来改变曲线的属性
最终的效果如下所示:
四、总结
本文介绍了两种对次表面散射的近似方法,只是一种近似方法,可能不太适合真实物体渲染。如果需要更详细的介绍,可以参考下面的参考内容。