raytracer에서 microfacet BRDF를 구현하려고하는데 몇 가지 문제가 있습니다. 내가 읽은 많은 논문과 기사는 부분 기하 항을 뷰와 반 벡터의 함수로 정의합니다 : 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);
}