GGX节能

我正在尝试在渲染器中实现具有GGX密度函数的microfacet BDRF。 我上周读过几乎所有的论文,而且我有一堆应该可以正常工作的方程式,但是我认为他们不是。 我的问题是,BDRF的规范化函数返回镜面值的方式超过1:

我使用Schlick的近似值来描述菲涅耳项,唯一一个返回范围[0-1]的数值:

F = oSpecular + ( 1.0 - oSpecular ) * ( 1.0 - LH )^5 ; 

标准化的GGX分布函数具有粗糙度:

 D = a^2 / ( PI * NH^2 * ( a^2 - 1.0 ) + 1.0 )^2 

我使用的几何因素:

 G1 = 1.0 + sqrt( 1.0 + a^2 *( ( 1.0 - NL^2 ) / ( NL^2 ) ) ) ; G2 = 1.0 + sqrt( 1.0 + a^2 *( ( 1.0 - NV^2 ) / ( NV^2 ) ) ) ; 

而完整的BDRF:

 nSpecular = D * F * G1 * G2 / ( 4.0 * NL * NV ) 

我已经看到这个设置广泛使用。 但即使是NL因素,它在光线reflection的热点上的返回值也超过100.0。 我已经尝试了其他几何术语,没有运气。 BDRF总是过度燃烧。 看来我在这里错过了一些重要的一点。 任何想法?

编辑:

感谢你的回答。 所以对于使用代表点的区域灯光来说,能量守恒只是一个近似,这就解释了为什么低强度的灯光reflection比光源本身还要亮,这是一种可怜的,看起来并不正确。 我会尝试寻找另一种方法。 任何建议?

回到最初关于GGX和节能点灯的问题,还有一件事我仍然缺失。 由于NDF返回一个密度概率函数,其值可以超过1,这意味着你不能直接在着色器中使用从NDF返回的值。 由于镜面reflection分量后来乘以光源功率,它应该在0-1范围内,否则将会有比镜面光源本身亮400倍的镜面reflection,没有任何意义。 告诉我只有一个现实生活中的情况,当一个dx的reflection比我们能够获得更多的能量时,我们可以做生意。 密度概率函数应加权或解释某种方式将其返回到0-1范围? 如果是这样,为什么没有人呢?

(根据评论,这个问题实际上是关于使用区域指示灯的BRDF。)

这是一个微妙的问题。 首先,点光源的颜色与面光源的区别在于:点光源的颜色是辐照度,面光源的颜色是光源。

所以当使用代表点法来渲染区域光时,我们实际上需要将光源的颜色(辐射)转换为辐射 ,所以我们可以把它看作一个点光源。 因此,我们需要计算(或近似)从区域光线接收的阴影点的辐照度。

对于均匀的球面光源,Brian Karis的课程笔记中引用的结果是,辐照度与总功率相同的点光源相同。 因此,您可以计算球面光的功率π * area * radiance ,然后在阴影点power / (4π * distance²)处计算得到的辐照度(对于物理1 / r2衰减,或者如果您喜欢,则replace您自己的衰减函数) 。 对于其他形状的区域灯光,这将是更困难的,但你可以希望制定出一些近似的辐照度公式。

请注意,当阴影点离光线足够远时,辐照度将在数值上小于辐射亮度,所以这将有助于减lessreflection的强度。

另一个因素是代表点法本身并不节能。 Karis建议改变GGX标准化因子来近似解决这个问题。 他的课程笔记见方程式10和14。 这也会降低reflection的亮度。 在这两个因素之间,这个强度应该被降低到更合理的程度。

 G1 = NL + sqrt( 1.0 + a^2 * (( 1.0 - NL^2 ) / ( NL^2 )) ); G2 = NV + sqrt( 1.0 + a^2 * (( 1.0 - NV^2 ) / ( NV^2 )) ); 

完整的BDRF应该用于Smith GGX:

 nSpecular = D * F / (G1 * G2)