レイトレーサーにマイクロファセット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);
}