Wavefront OBJ 与 Monte Carlo

去年十月搬家到现在一直没有对 Nuo Model Viewer 做大改动。年前忙于布置新家。到新年前后稍感安定想增加些新功能,但越想越感觉已有的 ray tracing 代码缺乏数学依据,于是开始温习数学概念。

粗糙的实现

首先,考虑仅支持理想方向光源直射,以及理想纯漫反射材质 (Lambertian) 的 shading 公式 [1]:

这是两年前开始做 Nuo Model Viewer 时最先实现的公式。其实要分析很多细节才能保证完全正确的实现 —— 如何从模型材质描述中得到,如何处理 π 相关的系数,场景的光源描述如何与相对应。对于 Wavefront OBJ 格式来说,几乎找不到直接阐述 Kd 参数和的关系的文档。因为当时只支持直接光照和理想方向光源,对这些细节的分析都偷懒了,在用户界面上放个 slider 解释为,其中 k 为任意系数。如此一来 Kd 参数和的系数关系以及光源描述如何与相对应都无需精确考虑,通过 slider 的取值进行补偿达到最终结果美观即可。

去年实现了几个基于 ray tracing 的功能:area light source 产生的软阴影;ambient 环境光 [2];自发光物体的光照。当时并未多想通过 slider 补偿系数的做法是否还成立。现在发现,要继续做新东西有必要彻底理解这些细节。接下两节先分析 shading 公式中具体系数的意义。然后解释实现 ray tracing 要注意什么。

光源的理解

引入 area light source 后,光线方向不再限于单一角度。直接光照公式变为积分形式(这里只考虑 Lambtian 材质,在所有方向上为常数):

若将理想方向光源应用于积分形式,即为对单一方向上的冲击分布积分:

这与一开始的简单公式非常类似,要让二者等价只需保证。下面就来看看、以及 Kd 参数的关系。

材质的理解

、和 Kd 中,的物理意义最明确,是材质表面反射能量比值的微分形式,其一般形式定义如下:

现在来寻找的物理意义。如果去掉直接光照公式里的,即认为其在各个方向均为 1,就得到了材质的 directional-hemispherical reflectance,对一般材质和 Lambertian 材质分别是:

按照这个定义,就是 Lambertian 材质的。在《Real-Time Rendering, 3ed》里称其为 diffuse color。

现在看来,有两点证据说明 Wavefront OBJ 中的 Kd 就是:第一,Kd 在很多文档中也被称为 diffuse color;第二,对物理真实材质来说,能量守恒定律要求 小于 1,而 Kd 的取值范围一般是 [0, 1] 区间 [3]。这两点都不能说是完全确定的证据,但 Wavefront OBJ 是个老旧的格式,其材质描述方面的正式文档很少,这大概是可以得到的最好解释了。

Monte Carlo 方法

前两节解释了 shading 公式的细节,现在回到原来的问题 —— 加入基于 ray tracing 的功能之后是否还能用 slider 补偿系数关系,需要做出什么改变?首先从 ray tracing 使用的 Monte Carlo 方法说起。用简单的一重积分来说明,若求积分 [4]:

可以在 [a, b] 区间内通过均匀随机分布取一组 sample ,通过它们取得近似的结果:

或者用任意的随机分布来取样,近似结果为

 

这里求和式中的单项被称为 Monte Carlo estimator:

 

把应用扩展到多重积分,如果用均匀随机分布取样求积分:

那么其 estimator 为:

现在可以想到,若 ray tracing 实现里涉及多重积分,且每重都包含一定的系数关系,就不一定能用界面上的 slider 进行补偿。下一节分析在 ray tracing 多重积分中的系数关系。

Monte Carlo 方法与 Ray Tracing

现在把 Monte Carlo 方法应用到光线的路径函数上。表面反射次数为 n 的光路上的传播函数为 [5]:

去年给 Nuo Model Viewer 加入环境光和自发光物体光照时,并没有认真保证代码准确反映上面的多重积分公式。相反,当时还是惯性思维地觉得凭 slider 就能补偿一切系数问题,所以凭感觉写了一个 estimator:

现在来看数学上正确的 Monte Carlo estimator,如果采用均匀随机分布:

如果只考虑 diffuse 效果:

它们都带有含 n 次方的系数。在一个场景的 ray tracing 中,每条路径的 n 可以不同,可能是随机遇到了光源 (自发光物体),也可以是 tracer 主动在某个长度上向光源直接采样。看起来 Nuo Model Viewer 的效果正确性令人担忧。不过 Nuo Model Viewer 并没有采用均匀随机分布,而是以 cosθ 成正比的概率分布做 importance sampling。那么正确的 estimator 应该是:

其中的 k 是保证  归一化的系数,满足:

将 k 带入原式,得到:

居然恰好和最初乱写的一样!几个月没动代码,但总算搞清了其中的意义。

脚注:

  1. 见《Real-Time Rendering, 3ed》,p110。
  2. 不是基于 occlusion 计算的阴影,而是基于 ray tracing 直接计算 ambient lighting。
  3. 如果加入对 specular term 的考虑,并且类似的考虑 Ks 参数,则需要满足 Kd + Ks < 1。这在绝大多数 OBJ 材质中也是满足的。
  4. 本节中的 ) 表示任意函数,注意不要和下文中的 BRDF 分布函数混淆。
  5. 见《Physically-Based Rendering, 3ed》,p867。这里把公式改写为 solid angle 形式,并且用嵌套括号强调了其递归模式。简单的乘法结合交换就可以变成单个多元函数的多重积分。

发表评论

Fill in your details below or click an icon to log in:

WordPress.com 徽标

You are commenting using your WordPress.com account. Log Out /  更改 )

Google photo

You are commenting using your Google account. Log Out /  更改 )

Twitter picture

You are commenting using your Twitter account. Log Out /  更改 )

Facebook photo

You are commenting using your Facebook account. Log Out /  更改 )

Connecting to %s


%d 博主赞过: