Я пытаюсь внедрить микроразмер BRDF в мой raytracer, но у меня возникают некоторые проблемы. Многие статьи и статьи, которые я прочитал, определяют термин частичной геометрии как функцию вида и половинных векторов: 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);
}