基于物理着色就是计算机图形学中用数学建模的方式模拟物体表面各种材质散射光线的属性从而渲染照片真实图片的技术。基于物理的材质模型已经被各种渲染器和游戏引擎使用,它不仅可以让最终的画面更加真实,同时也更容易设计出让Artists能够更直观的修改和编辑材质属性的系统。而本篇的重点要给大家介绍的就是UE4移动平台上基于物理的着色,一起来看看吧。
本文是继我的演讲虚幻引擎4中的真实着色后的后续文章。此演讲解释了在虚幻引擎4中使用的着色模型。本文假设读者已经熟悉了课程备注。
在演示后,我进行了一些小小的变更。我删除了Disney的"hotness"对几何方面的修改。根据Eric Heitz的 最新成果,我可能会再次改进它,在阴影和蒙板间添加关联。但我没有在其中加入孔洞(Cavity)参数。我们曾想在演示前进行此项变更,但发现使用了可控非传导性高光反射率。因此我们转而使用Disney模型中定义的高光参数。
我特别想谈到的是这个着色模型是如何适用于移动平台的。如您需要查看虚幻引擎4的移动平台渲染器,请查阅GDC的这些幻灯片。关于其使用的示例,请查看禅技术演示,这是在iPad Air上以4xMSAA 1080p在30hz下运行的。您也可以查看 灵魂技术演示。
在一开始我们的主要目标是想使用和高端PC相同的内容创建工作流程。我们还想要支持对相同资源的渲染,这样当我们在移动设备上运行它时,所有内容都尽我们所能地类似于采用高端渲染器所产生的效果。这意味着要完成许多细节,比如将gamma值调整正确,但同时也意味着我们需要让着色器也以相同方式运作,这样材质能在PC,游戏机平台和移动设备上也以相同方式运行。要完成这个目标,我们支持在我谈话中解释过的相同材质模型。而底色(BaseColor)、金属色(Metallic)、高光(SpeculAR)、粗糙度(Roughness)这些参数以完全同样的方式产生作用。
很明显,在移动设备上的运算能力要弱得多,所以我们不可能对每个光照都计算其BRDF(双向反射分布函数)。实际上,我们仅仅支持动态运算的单方向日光。对阴影进行预计算并将其作为贴图空间中带符号的距离场来存储。所有其它光照都被烘焙到光照贴图中。光照贴图使用类似HDR编码的SH定向表示来作为高端渲染器,但会根据不具有独立的、非关联的、alpha压缩的特点的PVRTC进行更高质量的压缩。类似于高端渲染器,预计算的高光使用预卷积的环境贴图。使用的是完全相同的预卷积,并且它们根据光照贴图进行类似的标准化和缩放。对于移动平台来说,每个像素仅提取一张环境贴图。
环境 BRDF
有趣的一点是我们如何计算环境BRDF,对于高端平台来说,它是使用Monte Carlo整合来进行预计算的,并存储于二维LUT中。对移动平台的硬件来说,依赖于贴图提取非常消耗系统资源,更糟的是,OpenGL ES2的8个采样器的限制造成了极大的使用限制。使用这个LUT来处理采样器是完全不行的。我转而基于Dimitar Lazarov的作品来作出了类似的解析版本。形式类似,但根据我们的着色模型和粗糙度参数进行了调整。函数列于下方:
[代码]:
01 | "3" >half3 EnvBRDFApprox( half3 SpecularColor, half Roughness, half NoV )
|
05 | const half4 c0 = { -1, -0.0275, -0.572, 0.022 }; |
07 | const half4 c1 = { 1, 0.0425, 1.04, -0.04 }; |
09 | half4 r = Roughness * c0 + c1; |
11 | half a004 = min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y; |
13 | half2 AB = half2( -1.04, 1.04 ) * a004 + r.zw; |
15 | return SpecularColor * AB.x + AB.y; |
这表示我们对基于光照的贴图具有较合理的Fresnel值和粗糙度。
在高端平台上使用的ENVBRDF
在移动平台上使用的ENVBRDF近似贴图
我们检测到金属色和高光材质输出并不连接在一起(这意味着使用了默认值)。传统的非金属材质就是这样的。本例中我们可以进一步优化函数。
[代码]:
01 | "3" >half EnvBRDFApproxNonmetal( half Roughness, half NoV )
|
07 | const half2 c0 = { -1, -0.0275 }; |
09 | const half2 c1 = { 1, 0.0425 }; |
11 | half2 r = Roughness * c0 + c1; |
13 | return min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y; |
我们进行类似的优化来完全避免使用环境贴图。一些游戏为不产生高光而进行优化,但并不减少性能消耗。我们转而使用"完全粗糙"的标识,它将Roughness(粗糙度)设置为1并优化常量因数。我们可以看到如下内容:
[代码]:
1 | "3" >EnvBRDFApprox( SpecularColor, 1, 1 ) == SpecularColor * 0.4524 - 0.0024
|
在此处我进行了简化:
[代码]:
1 | "3" >DiffuseColor += SpecularColor * 0.45;
|
我们仅对真正需要额外系统性能来处理的选定对象使用此标识。
定向光源(DIRECTIONAL LIGHT)
我最后要谈到的是如何计算日光。我之前谈到了太阳是唯一进行动态光照计算的。不幸的是,即使对于单个光照来说,全高端着色模型依然占用了过多的系统性能。而我们使用EnvBRDF来以类似于预集成的方式对其一部分进行计算。我们同时还有用来对环境贴图取样的反射向量。我们的想法是对用于预过滤环境贴图的径向对称叶片进行分析性评估,并随后将其结果与EnvBRDF值相乘,正如我们对IBL所进行的运算那样。将此视为对比入射光方向来分析性地整合叶片,而不是我们使用环境贴图所做的数值整合。
首先,我们使用Blinn来替代GGX NDF。我们随后使用径向的Phong叶片来近似处理Blinn。
Phong进一步使用球形高斯来近似处理(approximated with a Spherical Gaussian):
这让我们获得了最终的优化形式:
[代码]:
01 | "3" >half D_Approx( half Roughness, half RoL )
|
05 | half a = Roughness * Roughness; |
09 | float rcp_a2 = rcp(a2); |
13 | half c = 0.72134752 * rcp_a2 + 0.39674113; |
15 | return rcp_a2 * exp2( c * RoL - c ); |
这里 1π 被分解为光照颜色。
最后我们获得了占用系统性能极少而又合理的着色模型。高光保存了能量,在入射余角处较为灵敏,并且能同时与基于解析和图像的光源一起运行。即使是移动平台的硬件也能够基于物理来运行了。