上一篇重现了UE4的环境BRDF渲染框架。本篇会把GGX换成更常见的Blinn-Phong BRDF。在这个过程中,整个框架仍然保持不变,从importance sampling得到的ground truth开始,逐步推出用prefiltered环境光和预计算的LUT完成基于物理的环境光渲染。只是把BRDF换掉。
采样的细节
上一篇我只是简略地说了ground truth来自于采样1024次,但并没有给出如何计算采样点。这里会有具体的做法。
- 生成2D空间的随机点$\xi_{\theta}$和$\xi_{\phi}$
- 根据BRDF的概率密度函数pdf,从$\xi_{\theta}$和$\xi_{\phi}$计算importance sampling需要的球面坐标系$s_{\theta}$和$s_{\phi}$
- 把球面坐标系的$s_{\theta}$和$s_{\phi}$转换成直角坐标系的halfway
- -reflect(view, halfway),得到light方向
- 有了light、view、halfway,就可以计算出光照
从这个步骤可以看出,3-5都是显而易见的做法,只有前两步需要讨论。
对第一步来说,一个很好的选择是Hammersley采样。生成方法很简单,速度也很快。代码和原理都可以在这里找到。
第二步需要作比较细致的推导。下面就已blinn-phong为例解释如何推出$s_{\theta}$和$s_{\phi}$。对于其他BRDF,步骤也是一样的,只是D不一样。
Blinn-Phong的importance sampling
(下面那些积分,其实很多我已经不记得怎么做了。好在有数学软件可以帮忙,比如开源的Maxima。)
Blinn-phong的D定义为
$D_{BP}=\frac {\alpha + 2} {2\pi}(\mathbf{n} \cdot \mathbf{m})^{\alpha}$
在球面坐标系里面表达,就是:
$pdf(\theta, \phi)=\frac{n+2}{2\pi}\cos^n\theta \sin \theta$
$\theta$和$\phi$是独立的,可以先把$\phi$积分掉
$pdf(\theta)=\int_{0}^{2\pi}pdf(\theta, \phi)\, d\phi=(n+2)\cos^n\theta \sin \theta$
两者相除就得到关于$pdf(\phi)$在$pdf(\phi|\theta)$条件下的条件密度函数:
$pdf(\phi|\theta)=\frac{pdf(\theta, \phi)}{pdf(\theta)}=\frac{1}{2\pi}$
因为这里只考虑各向同性的BRDF,所以最终结果不会受到$\phi$值的影响,所以直接积分这个常量:
$\xi_{\phi}=P(s_{\phi})=\int_{0}^{s_{\phi}}pdf(\phi)\, d\phi=\int_{0}^{s_{\phi}}\frac{1}{2\pi}\, d\phi=\frac{s_{\phi}}{2\pi}$
所以
$s_{\phi}=2\pi \xi_{\phi}$
继续这么做,对pdf(theta)积分,可以得到
$\xi_{\theta}=P(s_{\theta})=\int_{0}^{s_{\theta}}pdf(\theta)\, d\theta=\frac{n+2}{n+1}\left(1-\cos^{n+1} s_{\theta}\right)$
解$s_{\theta}$,就得到
$s_{\theta}=\arccos\left( (1-\xi_{\theta}\frac{n+1}{n+2})^{\frac{1}{n+1}} \right)$
另外,有一个BRDF上的不同是,GGX的roughness取值范围是0-1,线性分布。而blinn-phong的roughness没有上限。这里的处理方法和Getting More Physical in Call of Duty: Black Ops II一样,把roughness定义成
$glossiness = 8192^{roughness}$
也就是以8192为上限,呈指数分布。有了这些条件,就能按照上一篇的方法生成ground truth。
从这张图可以看出,blinn-phong和GGX渲染结果有所不同(实际上主要是来自于G一项,GGX用的是smith近似,这里的blinn-phong用的是更简单的隐式近似)。但它们对参数的反应还是很相似的,可以看到从粗糙到光滑比较线性的变化。
同样的,传统做法直接把prefilter的环境光当作光源,得到的是这样的结果,和ground truth偏差很大。
我们照样可以用roughness和cos(theta)作为参数,建立一个LUT。计算方法和上一篇一样,只是用这篇描述的blinn-phong的importance sampling公式。LUT长成这个样子,绿色通道的值非常低,大部分<5。和UE4不同的是,y的方向是反的。所以上下颠倒以后才会和UE4的LUT是同样的坐标系。
渲染的时候仍然是prefiltered-cubemap * (specular * LUT.x + LUT.y),得到的结果和ground truth很接近。只是中频部分的变化没那么线性。这个似乎是因为mipmap层级选择造成的问题,也许需要更精确地推导指数分布下mipmap应该如何选择。
本篇讲解了如何把BRDF换成blinn-phong。接下去我会尝试把LUT用数值方法近似,从而再减少一个纹理读取。如果成功的话,就会有下一篇。
Comments