C++言語でDirectX 11を使ったアプリケーションを開発してみよう。
今回はライティングの手法の一つ拡散反射についてまとめてみようと思います。
ちなみに平行光源ライティングや点光源ライティングではこの拡散反射を使ったものになっています。
拡散反射 (Diffuse reflection)
拡散反射はザラザラした表面からの光の反射を表現します。
物体に当たった光は様々な方向に乱反射するという考え方で反射光は全方向に均等に広がっていくので、見ている人の位置は関係なく計算できます。
拡散反射の強さはランバートの余弦則というもので計算できます。ランバートの余弦則とは、入射光と面の法線との間の角度θの余弦と正比例することを示す法則です。
同じ強さの光でも入射角が大きくなるほど広い面積が照らされる事になるため、同一面積当たりの光は弱くなるという理屈です。
法則を計算式にすると以下のようになります。
I =(L・N)* KD * ID
面の正規化法線ベクトルNと面から光源への正規化ベクトルLの内積を計算し、そこに面の色KDと入射光の輝度IDを掛け合わせて求められます。
※Lは方向に注意(面から光源へ)
※内積の結果がマイナスの場合は裏側から光が当たっている状態。マイナスのままではなく0にして計算する必要がある
ピクセルシェーダー
上記の計算をHLSLで書くとこんな感じになります。
struct PS_IN { float4 pos : SV_POSITION; float4 posw : POSITION0; //ワールド座標系の座標 float4 norw : NORMAL0; //ワールド座標系の法線 }; cbuffer ConstantBuffer { float4 pntlightPos; //点光源座標 float4 pntlightCol; //点光源の色 float4 materialDiffuse; //物体の色 } float4 ps_main( PS_IN input ) : SV_Target { float3 l; float3 n; float i; l = normalize(pntlightPos.xyz - input.posw.xyz); n = normalize(input.norw.xyz); i = saturate(dot(l, n)); return float4(i * materialDiffuse.xyz * pntlightCol.xyz, 1.0); }
ピクセルの座標と光源の座標から光源へ向かう正規化ベクトルを求めます。(21行目)
法線ベクトルも正規化します(頂点シェーダーでやっておくべきかもしれませんが)。(22行目)
dot(内積)で角度を求めsturateでマイナスの時は0になるようにします。(23行目)
- ~プログラミング~ DirectX 11を始めよう
- ~プログラミング~ DirectX 11はDirectX 9と何が違うか その1
- ~プログラミング~ DirectX 11はDirectX 9と何が違うか その2
- ~プログラミング~ DirectX 11の初期化をしよう その1
- ~プログラミング~ DirectX 11の初期化をしよう その2
- ~プログラミング~ DirectX 11で深度/ステンシルバッファを準備しよう
- ~プログラミング~ DirectX 11でシェーダーをコンパイルしよう
- ~プログラミング~ DirectX 11で三角形を表示しよう
- ~プログラミング~ DirectX 11の頂点バッファとインデックスバッファ
- ~プログラミング~ DirectX 11で立体を表示しよう その1
- ~プログラミング~ DirectX 11で立体を表示しよう その2
- ~プログラミング~ DirectX 11で平行光源ライティング
- ~プログラミング~ DirectX 11で点光源ライティング
- ~プログラミング~ DirectX 11で拡散反射 (Diffuse reflection)
- ~プログラミング~ DirectX 11で鏡面反射 (Specular reflection)
- ~プログラミング~ DirectX 11で環境反射 (Ambient reflection)
- ~プログラミング~ DirectX 11でフォン反射モデル
- ~プログラミング~ DirectXTexライブラリを導入しよう
- ~プログラミング~ DirectX 11でテクスチャマッピング
コメントをお書きください