【Unity】【シェーダー】ランバート反射モデル (フォンシェーディング)
下の記事で解説したランバート反射モデルではバーテックスシェーダーで法線と光源方向ベクトルの内積を拡散反射の反射量としました。頂点単位なのでピクセルシェーダー に渡った時点で反射量が補間されるため、精度がイマイチです。
そこで、フラグメントシェーダーで反射量を計算することでピクセル単位の計算になりますので、精度が高まります。
このようにピクセル単位で内積計算を行うランバート拡散反射を「パーピクセルフォンシェーディング」と言います。
逆に頂点単位で内積計算を行うランバート拡散反射を「グローシェーディング」と言います。
ソース
解説
バーテックスシェーダー
//法線ベクトルをワールド座標に変換 o.worldNormal = UnityObjectToWorldNormal(v.normal);
法線ベクトルをフラグメントシェーダー渡したいのでワールド座標系に変換して戻り値用変数に代入してます。
フラグメントシェーダー
//法線ベクトル
float3 nNormal = normalize(i.worldNormal);
バーテックスシェーダーから受け取ったi.worldNormalhはプリミティブの3頂点
の法線ベクトルから線形補間されているので単位ベクトルではありません。
よって正規化してます。
//ライトベクトル float3 nLightDir = normalize(_WorldSpaceLightPos0.xyz);
_WorldSpaceLightPosθはUnityの組み込み変数でワールド座標系のライト方向ベクトルが格納されています。
こちらも単位ベクトルでないので正規化します。
//法線ベクトル-ライトベクトルの角度量 float NdotL = dot(nNormal, nLightDir); //拡散係数の決定 float diffuse = max(0, NdotL);
グローシェーディングではバーテックスシェーダーで行なっていた内積計算をフラグメントシェーダーで行なっています。
法線ベクトルをフラグメントシェーダーにまで運んだのはこの為です。