Forma corretta del termine della geometria GGX


9

Sto cercando di implementare un microfacet BRDF nel mio raytracer ma sto riscontrando alcuni problemi. Molti dei documenti e degli articoli che ho letto definiscono il termine di geometria parziale in funzione della vista e dei mezzi vettori: G1 (v, h). Tuttavia, durante l'implementazione ho ottenuto il seguente risultato:

Termine GGX Geometry utilizzando il mezzo vettore

(La riga inferiore è dielettrica con rugosità 1,0 - 0,0, la riga superiore è metallica con rugosità 1,0 - 0,0)

C'è uno strano punto culminante intorno ai bordi e un taglio intorno a nl == 0. Non riuscivo davvero a capire da dove venisse. Sto usando Unity come riferimento per controllare i miei rendering, quindi ho controllato la loro fonte di shader per vedere cosa usano e da quello che posso dire che il loro termine di geometria non è affatto parametrizzato dal mezzo vettore! Quindi ho provato lo stesso codice ma ho usato la macro superficie normale invece del mezzo vettore e ho ottenuto il seguente risultato:

Termine della geometria GGX che utilizza la normale superficie macro

A mio avviso non allenato questo sembra molto più vicino al risultato desiderato. Ma ho la sensazione che non sia corretto? La maggior parte degli articoli che leggo usano il mezzo vettore ma non tutti. C'è una ragione per questa differenza?

Uso il seguente codice come termine di geometria:

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

E per riferimento, questa è la mia normale funzione di distribuzione:

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

Risposte:


5

G1


Giusto per evitare confusione, presumo la versione isotropica del BRDF, il modello di microfacet Smith (al contrario del modello con cavità a V) e la distribuzione di microfacet GGX.

G1

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

e secondo Walter 2007 , la formula è

χ+(ω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;
}

Grazie per la risposta. Ho implementato la formula che hai fornito e ho ottenuto risultati identici a quelli della mia (usando la normale macrosuperficie). Quindi sembra che sia solo una forma diversa (l'ho preso da: graphicrants.blogspot.nl/2013/08/specular-brdf-reference.html ) Ero confuso sul mezzo vettore perché il corso di matematica PIG SIGGRAPH 2015 afferma specificamente la geometria funzione che dipende dalla vista, dalla luce e dai mezzi vettori. Quindi questo è un errore nelle diapositive?
Erwin,

nvhv

Ho usato N punto V nella mia nuova implementazione, che mi ha dato risultati identici alla seconda immagine che ho pubblicato. Ma non sono ancora chiaro il motivo per cui le diapositive del corso PBS affermano che il vettore a metà strada dovrebbe essere usato (vedi: blog.selfshadow.com/publications/s2015-shading-course/hoffman/… , Slide 88).
Erwin,

hvnvG1hv

Sì, quello era il problema. Ma la mia domanda principale era: A cosa serve il mezzo vettore, poiché appare nella definizione della funzione. Per quanto ne so ora, viene utilizzato nel controllo solo se H punto V è positivo. Grazie per aver dedicato del tempo a scrivere le risposte.
Erwin,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.