2つのフレネル項を使用することは、任意の拡散パスがサーフェスを2回通過するという意味で正しいです。再び跳ね返るまで媒体を通るパスをトレースして拡散を解決する場合、サーフェスと相互作用するときにそのパスに対して2つ(またはそれ以上)のフレネル項が得られます。
ただし、それは拡散BRDFで行っていることではありません。拡散BRDFは、考えられるすべての拡散パスの平均を表すことを目的としています。ランベルトの場合、その平均は均一反射としてモデル化され、単一のアルベド値は拡散中の内部エネルギー損失を測定しますが、より複雑なモデルが可能です。重要:拡散BRDFには、さらに拡散するために媒体に反射されるいくつかのパスと、すぐに通過するいくつかのパスの集約効果が既に含まれています。はすでにBRDF¹に「ベイクイン」されており、再度ファクタリングする必要はありません。1 − FO U T
ランベルトの用語に含まれていないのは、光が拡散媒体に入る前に反射されることによって失われるエネルギーの部分です。これはビューに依存しますが、その上の正確な光沢のあるローブに依存します。反映されていないすべてはあなたが実際にしたいことはすなわち、すべての発信方向の上に表面における全エネルギー損失を統合することであることを意味し、屈折されますので(非金属)の表面界面で何のエネルギーロスがありません。1 - ∫glossy_bsdf( in、 out)d out
特定のBRDFの積分の近似値を事前に計算することができます。最終結果は、一般に、少なくともビューの方向、材料の粗さ、IORに依存します。最初の近似として、光沢のあるローブが完全な鏡面反射体であると仮定できます。それは重みを与え。これはまさにあなたが最初に提案したものです。1 - ∫つやつやd out =1− FI N
さらに、ランベルトBRDFはアルベドを除算したものであり、コサイン項は入射光が表面でどの程度減衰したかの尺度であることに注意してください。光沢反射率と拡散反射率の両方に適用されます。π
だから、大体:
// Assuming for example:
// diffuse = albedo / PI;
// specular = my_favorite_glossy_brdf(in_dir, out_dir, roughness);
// fresnel = f0 + (1.0 - f0) * pow(1.0 - dot(E, H), 5.0);
// total_surface_reflection = fresnel
color = lightIntensity * dot(L, N) * Lerp(diffuse, specular, total_surface_reflection);
¹ 本当にあなたのアウト方向をもたらす可能性のあるすべての入射内部拡散出口経路上のの積分ですが、私は脱線します。F