本系列源自于对Real Shading in Unreal Engine 4和Getting More Physical in Call of Duty: Black Ops II的理解。打算按照以前游戏中基于物理的渲染的思路,介绍一下如何在游戏这样的实时应用中使用基于物理的环境光。
回顾
在游戏中基于物理的渲染中列出了渲染方程的简化版,这是整个基于物理的体系的源头。
其中,根据microfacet理论,BRDF可以表达成:
如之前的系列所述,这个公式只适合点光源。如果需要用到环境光,也就用cubemap光源做image based lighting(IBL),就需要推一个基于物理的环境BRDF。
Ground truth
仍然从渲染方程的简化版出发。因为不管是实时还是离线,要在的渲染中完成那个积分(即便是离散化)都是不实际的。一般来说需要用importance sampling减少计算量,也就是。
其中pdf是概率密度函数,根据Physically-Based Shading at Disney,
用这个方程来计算specular的话,可以得到这样的结果:
上图的每个pixel都根据BRDF做了importance sampling,N=1024,BRDF是GGX,cubemap分辨率是512。在NVS 4200M上,只有2FPS的速度,即便在GTX 680上也只有30FPS。
传统做法
以前对于环境光,常见的做法就是prefilter。用AMD的cubemapgen对cubemap做一个prefilter,把卷积过的值存到mipmap的下几层。在渲染的时候,用roughness选择mipmap层次,根据反射方向采一个点,当作个方向光源来计算shading。Prefilter相当于对光源积分,所以这么做相当于把渲染方程组织成这样:
用这样的方式虽然能得到一个看起来不错的结果,但和ground truth比较的话,差别还是较大的。
接下去我会开始推导一个基于物理的环境BRDF。结果你会发现,基于物理的方法效果优于传统做法,并且开销更低了。
基于物理的做法
如果改变拆分的方式,把原方程近似成两个积分的乘积,就得到
其中,第一个积分仍是prefiltered cubemap。第二个积分还需要进一步推导。BRDF中的fresnel项是
把fresnel项带入,就得到
方程右边的两个积分项可以分别预计算成一个LUT的两个通道,查找参数是roughness和cos(theta),LUT的输出又很好地能落在[0, 1]之间。
使用的时候,只需要用roughness和cos(theta)读取这个LUT,这样就能计算出specular的IBL结果:prefiltered-cubemap * (specular * LUT.x + LUT.y),得到的结果和ground truth很接近。由于有了这个LUT,不再需要计算BRDF,只要一次乘加。Prefiltered cubemap只要采样一次,在NVS 4200M上也可以轻松达到110FPS,完全到了实用的范围。
本篇重现了UE4的环境BRDF,用的是GGX的BRDF。下一篇会试着换用KlayGE的blinn-phong BRDF。
Comments