Правильная форма термина геометрии GGX

9

Я пытаюсь внедрить микроразмер BRDF в мой raytracer, но у меня возникают некоторые проблемы. Многие статьи и статьи, которые я прочитал, определяют термин частичной геометрии как функцию вида и половинных векторов: G1 (v, h). Однако при реализации этого я получил следующий результат:

Термин GGX Geometry, использующий половину вектора

(Нижний ряд - диэлектрический с шероховатостью 1,0 - 0,0; Верхний ряд - металлический с шероховатостью 1,0 - 0,0)

По краям есть странная подсветка и отсечка около nl == 0. Я не мог понять, откуда это происходит. Я использую Unity в качестве эталона для проверки моих рендеров, поэтому я проверил их источник шейдеров, чтобы увидеть, что они используют, и из того, что я могу сказать, их геометрический термин вообще не параметризован половиной вектора! Поэтому я попробовал тот же код, но использовал для макроповерхности нормаль вместо половины вектора и получил следующий результат:

Геометрический термин GGX, использующий нормаль макроповерхности

На мой неопытный взгляд это кажется намного ближе к желаемому результату. Но у меня такое ощущение, что это не правильно? Большинство статей, которые я прочитал, используют половинный вектор, но не все. Есть ли причина для такой разницы?

Я использую следующий код в качестве моего геометрического термина:

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);
}
Erwin
источник

Ответы:

5

G1


Просто, чтобы избежать путаницы, я предполагаю изотропную версию BRDF, модель микроснимков Смита (в отличие от модели с V-образными полостями) и распределение микрофасет GGX.

G1

χ+(ωvωm)21+1+αo2tan2θv

и согласно Уолтеру 2007 , формула

χ+(ωvωgωvωm)21+1+α2tan2θv

ωmωgωvαχ+(a)a>0

ωmG1ωv

ωv

G1

float SmithMaskingFunctionGgx(
    const Vec3f &aDir,  // the direction to compute masking for (either incoming or outgoing)
    const Vec3f &aMicrofacetNormal,
    const float  aRoughnessAlpha)
{
    PG3_ASSERT_VEC3F_NORMALIZED(aDir);
    PG3_ASSERT_VEC3F_NORMALIZED(aMicrofacetNormal);
    PG3_ASSERT_FLOAT_NONNEGATIVE(aRoughnessAlpha);

    if (aMicrofacetNormal.z <= 0)
        return 0.0f;

    const float cosThetaVM = Dot(aDir, aMicrofacetNormal);
    if ((aDir.z * cosThetaVM) < 0.0f)
        return 0.0f; // up direction is below microfacet or vice versa

    const float roughnessAlphaSqr = aRoughnessAlpha * aRoughnessAlpha;
    const float tanThetaSqr = Geom::TanThetaSqr(aDir);
    const float root = std::sqrt(1.0f + roughnessAlphaSqr * tanThetaSqr);

    const float result = 2.0f / (1.0f + root);

    PG3_ASSERT_FLOAT_IN_RANGE(result, 0.0f, 1.0f);

    return result;
}
ivokabel
источник
Спасибо за ваш ответ. Я реализовал формулу, которую вы предоставили, и я получил те же результаты, что и мои собственные (при использовании нормальной макроповерхности). Так что, похоже, это просто другая форма (я получил ее от: graphicrants.blogspot.nl/2013/08/specular-brdf-reference.html ). Я был озадачен половинным вектором, потому что в курсе математики PBS SIGGRAPH 2015 специально указывается геометрия функция зависит от вида, света и половинных векторов. Так это ошибка в слайдах?
Эрвин
nvhv
Я использовал N dot V в моей новой реализации, которая дала мне результаты, идентичные второму изображению, которое я опубликовал. Но я до сих пор не понимаю, почему на слайдах курса PBS говорится , что следует использовать вектор на полпути (см. Blog.selfshadow.com/publications/s2015-shading-course/hoffman/… , слайд 88).
Эрвин
hvnvG1hv
Да, это была проблема. Но мой главный вопрос был: для чего используется половина вектора, поскольку она появляется в определении функции. Насколько я понимаю сейчас, он используется только при проверке, если H точка V положительна. Спасибо, что нашли время, чтобы написать ответы.
Эрвин