Forma correcta del término de geometría GGX

9

Estoy tratando de implementar un microfacet BRDF en mi raytracer pero me encuentro con algunos problemas. Muchos de los artículos y artículos que he leído definen el término de geometría parcial en función de la vista y los medios vectores: G1 (v, h). Sin embargo, al implementar esto obtuve el siguiente resultado:

Término de Geometría GGX usando el medio vector

(La fila inferior es dieléctrica con rugosidad 1.0 - 0.0, la fila superior es metálica con rugosidad 1.0 - 0.0)

Hay un extraño resaltado alrededor de los bordes y un corte alrededor de nl == 0. Realmente no pude entender de dónde viene esto. Estoy usando Unity como referencia para verificar mis renders, así que verifiqué su fuente de sombreador para ver qué usan y, por lo que puedo decir, su término de geometría no está parametrizado en absoluto por el medio vector. Así que probé el mismo código pero usé macro superficie normal en lugar del medio vector y obtuve el siguiente resultado:

Término de geometría GGX usando la macro superficie normal

Para mi ojo inexperto, esto parece mucho más cercano al resultado deseado. Pero tengo la sensación de que esto no es correcto? La mayoría de los artículos que leo usan el medio vector, pero no todos. ¿Hay alguna razón para esta diferencia?

Yo uso el siguiente código como mi término de geometría:

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);
}

Y como referencia, esta es mi función de distribución normal:

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
fuente

Respuestas:

5

G1


Solo para evitar confusiones, supongo que la versión isotrópica del BRDF, el modelo de microfaceta Smith (en oposición al modelo de cavidad en V) y la distribución de microfaceta GGX.

G1

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

y según Walter 2007 , la fórmula es

χ+(ω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
fuente
Gracias por su respuesta. Implementé la fórmula que proporcionó y obtuve resultados idénticos a los míos (cuando uso la macro-superficie normal). Entonces parece que es solo una forma diferente (lo obtuve de: graphicrants.blogspot.nl/2013/08/specular-brdf-reference.html ) Estaba confundido sobre el medio vector porque el curso de matemáticas SIGGRAPH 2015 PBS establece específicamente la geometría función dependiente de la vista, luz y medios vectores. ¿Entonces esto es un error en las diapositivas?
Erwin
nvhv
Utilicé N dot V en mi nueva implementación, que me dio resultados idénticos a la segunda imagen que publiqué. Pero todavía no tengo claro por qué las diapositivas del curso PBS establecen que se debe usar el vector intermedio (Ver: blog.selfshadow.com/publications/s2015-shading-course/hoffman/… , Diapositiva 88).
Erwin
hvnvG1hv
Sí, ese era el problema. Pero mi pregunta principal fue: ¿para qué ES el medio vector utilizado, ya que aparece en la definición de la función? Hasta donde entiendo ahora, solo se usa en la verificación si H punto V es positivo. Gracias por tomarse el tiempo para escribir las respuestas.
Erwin