高度な照明
ライティングの基本に関するレッスンでは、シーンにかなりのリアリズムを与えることができるPhongライティングモデルを簡単に検討しました。 Phongモデルはかなり良いように見えますが、このチュートリアルでは焦点を当てるいくつかの欠陥があります。
パート1.はじめに
パート2.基本的な照明
パート3. 3Dモデルをダウンロードする
パート4.高度なOpenGL機能
パート5.高度な照明
パート6. PBR
ブリンフォンモデル
Phongモデルは照明の計算に非常に効果的な近似ですが、特定の条件下では、鏡面反射成分の一部が失われる場合があります。 これは、鏡面反射の領域が非常に大きくなると、低い光沢度で見られます。 次の図は、平らなテクスチャサーフェスに1.0の鏡面光沢度を使用した場合に何が起こるかを示しています。
ご覧のとおり、鏡面反射の領域には明確に定義された境界があります。 これは、表示ベクトルと反射ベクトルの間の角度が90度を超えてはならないためです。そうしないと、スカラー積が負になり、ミラーフレア成分がゼロになります。 これは大した問題ではないと思うかもしれません。なぜなら、90度を超える角度で照明を当てるべきではないからです。
そうでもない。 これは拡散コンポーネントにのみ適用されます。法線ベクトルとライトの方向の間の角度が90度を超えると、光源は照明された表面の下にあるため、拡散照明の寄与はゼロになります。 ただし、ミラーコンポーネントの場合、光の方向と法線の間の角度ではなく、表示ベクトルと反射ベクトルの間の角度を測定します。 次の2つの写真を見てください。
今、問題が明らかになりつつあります。 左に、θが90度未満のFongovsky反射の通常の画像を示します。 右の図では、ビューの方向と反射の間の角度θは90度より大きく、その結果、鏡面照明の寄与はキャンセルされます。 通常、レビューベクトルは反射ベクトルから著しく離れていることが多いため、これは通常、懸念の原因にはなりません。 しかし、鏡面輝度の値が小さい場合、反射領域の半径は非常に大きくなり、全体像に顕著な貢献をします。 Phongモデルを使用して、90度を超える角度でこの寄与をキャンセルします(最初の画像を参照)。
1977年、ジェームズF.ブリンは、これまで使用してきたPhongモデルに加えて、Blinn-Fongライティングモデルを導入しました。 これは、Phongモデルにほぼ似ていますが、ミラーコンポーネントの計算にわずかに異なるアプローチを使用しているため、問題を解決できます。 反射ベクトルに依存する代わりに、いわゆるhalfwayベクトルを使用します。これは、視線方向と光の方向のちょうど中間にある単位ベクトルです。 このベクトルがサーフェス法線に近いほど、ミラーコンポーネントの寄与は大きくなります。
調査の方向が(現在の想像上の)反射ベクトルと完全に一致すると、中央ベクトルは表面の法線と一致します。 したがって、視線方向が反射方向に近づくほど、鏡面光沢は強くなります。
明らかに、観察者が見ている方向に関係なく、中央ベクトルとサーフェスの法線との間の角度が90度を超えることはありません(もちろん、光源がサーフェスの下にない限り)。 これにより、Phong反射と比較してわずかに異なる結果が得られ、一般に、特に鏡面反射光の値が低い場合、画像は視覚的にもっともらしいように見えます。 以前の固定OpenGLパイプラインで使用されていたのは、Blinn-Fongライティングモデルでした。
中央ベクトルを見つけるのは簡単です。レビューベクトルに光の方向ベクトルを追加し、結果を正規化する必要があります。
GLSLでは、次のようになります。
vec3 lightDir = normalize(lightPos - FragPos); vec3 viewDir = normalize(viewPos - FragPos); vec3 halfwayDir = normalize(lightDir + viewDir);
したがって、ミラー成分の計算は、表面の法線と中央ベクトル間のスカラー積の単純な計算に縮小され、それらの間の角度の余弦を取得します。
float spec = pow(max(dot(normal, halfwayDir), 0.0), shininess); vec3 specular = lightColor * spec;
実際、これはすべてBlinn-Fongモデルに関するものです。 Blinn-FongモデルとFongモデルの鏡面反射の唯一の違いは、視線方向と反射ベクトル間の角度ではなく、法線ベクトルと中央ベクトル間の角度を測定することです。
中央ベクトルを使用して鏡面フレア成分を計算すると、Phongモデルの特性である鏡面反射領域の鋭い境界に関する問題はなくなります。 下の画像は、鏡面反射輝度が0.5の両方の方法の鏡面反射領域を示しています。
PhongモデルとBlinn-Fongモデルのもう1つの小さな違いは、中央ベクトルとサーフェスの法線の間の角度が、表示ベクトルと反射ベクトルの間の角度よりも小さいことが多いことです。 したがって、同様のFongモデルの結果を得るには、鏡面光沢値をわずかに高くする必要があります。 Phongモデルよりも2〜4倍大きいことが経験的に確立されています。
以下は、Phongモデルでは鏡面光沢8、Blinn-Fongモデルでは32の鏡面光沢を持つモデル間のミラーコンポーネントの比較です。
ご覧のとおり、Blinn-Fongのミラーコンポーネントはシャープです。 通常、以前にPhongモデルを使用して得られた結果と同様の結果を得るには、少し調整する必要がありますが、一般的に、Blinn-Fongカバレッジはより妥当な画像を提供します。
このデモでは、通常のFong反射とBlinn-Fong反射を切り替えるシンプルなフラグメントシェーダーを使用しました。
void main() { [...] float spec = 0.0; if(blinn) { vec3 halfwayDir = normalize(lightDir + viewDir); spec = pow(max(dot(normal, halfwayDir), 0.0), 16.0); } else { vec3 reflectDir = reflect(-lightDir, normal); spec = pow(max(dot(viewDir, reflectDir), 0.0), 8.0); } [...]
このレッスンのソースコードはこちらです。 bを押すと、FongモデルからBlinn-Fongモデルに、またはその逆に切り替えることができます。
オリジナル記事 。