转载请注明出处为KlayGE游戏引擎,本文的永久链接为http://www.klayge.org/?p=3006

上一篇重现了UE4的环境BRDF渲染框架。本篇会把GGX换成更常见的Blinn-Phong BRDF。在这个过程中,整个框架仍然保持不变,从importance sampling得到的ground truth开始,逐步推出用prefiltered环境光和预计算的LUT完成基于物理的环境光渲染。只是把BRDF换掉。

采样的细节

上一篇我只是简略地说了ground truth来自于采样1024次,但并没有给出如何计算采样点。这里会有具体的做法。

  1. 生成2D空间的随机点ξθξϕ
  2. 根据BRDF的概率密度函数pdf,从ξθξϕ计算importance sampling需要的球面坐标系sθsϕ
  3. 把球面坐标系的sθsϕ转换成直角坐标系的halfway
  4. -reflect(view, halfway),得到light方向
  5. 有了light、view、halfway,就可以计算出光照

从这个步骤可以看出,3-5都是显而易见的做法,只有前两步需要讨论。

对第一步来说,一个很好的选择是Hammersley采样。生成方法很简单,速度也很快。代码和原理都可以在这里找到。

第二步需要作比较细致的推导。下面就已blinn-phong为例解释如何推出sθsϕ。对于其他BRDF,步骤也是一样的,只是D不一样。

Blinn-Phong的importance sampling

(下面那些积分,其实很多我已经不记得怎么做了。好在有数学软件可以帮忙,比如开源的Maxima。)

Blinn-phong的D定义为

DBP=α+22π(nm)α

在球面坐标系里面表达,就是:

pdf(θ,ϕ)=n+22πcosnθsinθ

θϕ是独立的,可以先把ϕ积分掉

pdf(θ)=02πpdf(θ,ϕ)dϕ=(n+2)cosnθsinθ

两者相除就得到关于pdf(ϕ)pdf(ϕ|θ)条件下的条件密度函数:

pdf(ϕ|θ)=pdf(θ,ϕ)pdf(θ)=12π

因为这里只考虑各向同性的BRDF,所以最终结果不会受到ϕ值的影响,所以直接积分这个常量:

ξϕ=P(sϕ)=0sϕpdf(ϕ)dϕ=0sϕ12πdϕ=sϕ2π

所以

sϕ=2πξϕ

继续这么做,对pdf(theta)积分,可以得到

ξθ=P(sθ)=0sθpdf(θ)dθ=n+2n+1(1cosn+1sθ)

sθ,就得到

sθ=arccos((1ξθn+1n+2)1n+1)

另外,有一个BRDF上的不同是,GGX的roughness取值范围是0-1,线性分布。而blinn-phong的roughness没有上限。这里的处理方法和Getting More Physical in Call of Duty: Black Ops II一样,把roughness定义成

glossiness=8192roughness

也就是以8192为上限,呈指数分布。有了这些条件,就能按照上一篇的方法生成ground truth。

Env BRDF Blinn-Phong Ground Truth从这张图可以看出,blinn-phong和GGX渲染结果有所不同(实际上主要是来自于G一项,GGX用的是smith近似,这里的blinn-phong用的是更简单的隐式近似)。但它们对参数的反应还是很相似的,可以看到从粗糙到光滑比较线性的变化。

同样的,传统做法直接把prefilter的环境光当作光源,得到的是这样的结果,和ground truth偏差很大。

Env BRDF Blinn-Phong Prefiltered我们照样可以用roughness和cos(theta)作为参数,建立一个LUT。计算方法和上一篇一样,只是用这篇描述的blinn-phong的importance sampling公式。LUT长成这个样子,绿色通道的值非常低,大部分<5。和UE4不同的是,y的方向是反的。所以上下颠倒以后才会和UE4的LUT是同样的坐标系。

Env BRDF Blinn-Phong LUT

渲染的时候仍然是prefiltered-cubemap * (specular * LUT.x + LUT.y),得到的结果和ground truth很接近。只是中频部分的变化没那么线性。这个似乎是因为mipmap层级选择造成的问题,也许需要更精确地推导指数分布下mipmap应该如何选择。
Env BRDF Blinn-Phong Physically-based Prefiltered

本篇讲解了如何把BRDF换成blinn-phong。接下去我会尝试把LUT用数值方法近似,从而再减少一个纹理读取。如果成功的话,就会有下一篇。