我正在尝试在raytracer中实现微面BRDF,但是遇到了一些问题。我读过的许多论文和文章都将局部几何术语定义为视图和半矢量的函数:G1(v,h)。但是,实现此目标时,我得到以下结果:
(最下面一行是粗糙度为1.0-0.0的电介质,最上面一行是粗糙度为1.0-0.0的金属电介质)
边缘周围有一个怪异的高光,nl == 0附近有一个截止。我使用Unity作为参考来检查我的渲染,因此我检查了它们的着色器源,以查看它们的用途,并从中可以看出它们的几何项根本没有被半向量参数化!因此,我尝试了相同的代码,但使用了宏观表面法线而不是半向量,并得到以下结果:
在我未经训练的眼睛看来,这似乎更接近预期的结果。但是我有感觉这是不正确的?我阅读的大多数文章都使用半向量,但不是全部。是否有这种差异的原因?
我将以下代码用作几何术语:
float RayTracer::GeometryGGX(const Vector3& v, const Vector3& l, const Vector3& n, const Vector3& h, float a)
{
return G1GGX(v, h, a) * G1GGX(l, h, a);
}
float RayTracer::G1GGX(const Vector3& v, const Vector3& h, float a)
{
float NoV = Util::Clamp01(cml::dot(v, h));
float a2 = a * a;
return (2.0f * NoV) / std::max(NoV + sqrt(a2 + (1.0f - a2) * NoV * NoV), 1e-7f);
}
供参考,这是我的正态分布函数:
float RayTracer::DistributionGGX(const Vector3& n, const Vector3& h, float alpha)
{
float alpha2 = alpha * alpha;
float NoH = Util::Clamp01(cml::dot(n, h));
float denom = (NoH * NoH * (alpha2 - 1.0f)) + 1.0f;
return alpha2 / std::max((float)PI * denom * denom, 1e-7f);
}