Estou tentando implementar um BRDF de microfacet no meu raytracer, mas estou com alguns problemas. Muitos artigos e artigos que li definem o termo de geometria parcial como uma função da vista e dos meio vetores: G1 (v, h). No entanto, ao implementar isso, obtive o seguinte resultado:
(A linha inferior é dielétrica com rugosidade 1.0 - 0.0, A linha superior é metálica com rugosidade 1.0 - 0.0)
Há um destaque estranho nas bordas e um corte em torno de nl == 0. Eu realmente não conseguia descobrir de onde isso vem. Estou usando o Unity como referência para verificar minhas renderizações, então verifiquei sua fonte de sombreador para ver o que eles usam e, pelo que posso dizer, o termo geometria não é parametrizado pelo meio vetor! Então, tentei o mesmo código, mas costumava macro superfície normal em vez do meio vetor e obteve o seguinte resultado:
Para meus olhos destreinados, isso parece muito mais próximo do resultado desejado. Mas tenho a sensação de que isso não está correto? A maioria dos artigos que li usa o meio vetor, mas não todos. Existe uma razão para essa diferença?
Eu uso o seguinte código como meu termo de 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, para referência, esta é minha função de distribuição 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);
}