1

我正在学习 PBR 和 Unity 标准着色器。GGX 分布术语的真正大结果让我感到困惑。

Unity 标准着色器使用 GGX 分布项:

// I re-write it into C#
private float GGXTerm(float NdotH, float roughness)
{
  float a2 = roughness * roughness;
  float d = (NdotH * a2 - NdotH) * NdotH + 1.0f;
  return a2 / (Mathf.PI * (d * d + 1e-7f));
}

这是让我感到困惑的问题:

  1. 将 NdotH 设置为 1(视图方向正好在镜面反射方向)。
  2. 将粗糙度设置为较低的值,例如 0.015

GGX 项的结果是 868.58123。这是一个非常大的数字,使得最终的颜色远远大于1。BRDF中的所有其他项都小于1。如果入射光只是1,那么这个大的反射能量似乎不符合能量守恒定律。我认为反射的能量肯定比事件小。

我知道我的理解一定有问题。感谢您的指导。

4

1 回答 1

0

Khronos glTF Sample Viewer或许可以作为额外的参考。

看起来您已经实现了该D()术语,示例查看器在 BRDF 着色器的第 41 - 46 行实现了该术语。

但这不是完整的镜面术语。该函数在第 108 - 115 行被调用,作为函数 BRDF_specularGGX 的一部分。在用作镜面反射值之前,您得到的结果与其他几个术语混合在一起。

在glTF 规范的 B.3 节中有一些进一步的阅读。

于 2022-01-03T20:12:30.160 回答