新規記事の投稿を行うことで、非表示にすることが可能です。
2018年08月11日
《その435》シェーダ(点光源の場合)(2)
シェーダ(点光源の場合)(2)
前回《434》では、下記 (b) の効果について扱いました。
(a) 点光源からの光は、光源から離れるにつれて広い面積に拡散するので、明るさは減少します。
(b) ある面に光が当たるとき、光が面に垂直に当たるときが最も明るく、斜めに当たる場合は明るさが減少します。
(b) の効果のみで陰影処理を行うと、次のような不具合が生じます。
以下の3つの画像は、光源を少しずつ遠ざけていったときの様子です。光源が遠くなるにつれて、入射角が小さくなる(入射光と面のなす角が大きくなる)ので、画像が明るくなってしまっています。
光源が遠くなれば照らされる面の明るさは減少しなければなりません。
点光源の座標 (0.0, 0.7, 1.0) ・・・(b) の効果のみで描画しています。
点光源の座標 (0.0, 0.8, 1.5) ・・・(b) の効果のみで描画しています。
点光源の座標 (0.0, 0.9, 2.0) ・・・(b) の効果のみで描画しています。
(a) の効果
面の明るさは、光源からの距離の2乗に反比例します。実際に この法則通りに明るさを決めると、明るさの減り方が 期待通りにならない場合が多いので、計算式を少し変えることが多いようです。
以下の3つの画像は、(a) の効果のみで陰影処理を行った場合の結果です。とりあえず法則通りに、面の明るさが 光源からの距離の2乗に反比例するようにしてあります。
期待通り、出力された画像は、光源から遠くなるにつれて暗くなっています(ただし、光が面に当たる角度は考慮されていません)。
点光源の座標 (0.0, 0.7, 1.0) ・・・(a) の効果のみで描画しています。
点光源の座標 (0.0, 0.8, 1.5) ・・・(a) の効果のみで描画しています。
点光源の座標 (0.0, 0.9, 2.0) ・・・(a) の効果のみで描画しています。
(b) の効果を取り消して (a) の効果のみにするための、プログラム上の変更点は、
次の SamplePixelShader.hlsl の赤文字箇所のみです。
以下は、SamplePixelShader.hlsl です。
// ピクセルシェーダを通じて渡されるピクセルごとのデータ
struct PixelShaderInput
{
float4 pos : SV_POSITION;
float3 pos_ : POSITION;
float3 nrm : NORMAL;
};
//(補間済み)色データのパススルー関数
float4 main(PixelShaderInput input) : SV_TARGET
{
// light処理をしたピクセルの色成分を返します。
float3 light = float3(0.0, 0.9, 2.0); // 点光源の位置
float3 lightDirection = input.pos_ - light; // 光の方向ベクトル
float len = length(lightDirection); // 光の方向ベクトルを正規化(大きさを 1 にします)
// 正規化した法線ベクトル と 正規化した光の方向ベクトル のなす角から、その点の明るさの程度(0 〜 1)を算出。
// float lightMagnitude = saturate(dot(input.nrm, -normalize(lightDirection)));
// k は距離の2乗に反比例する係数です。比例定数を 0.8 にしてみました。
float k = saturate(0.8f / len / len);
// return float4(0,1,0,0) * lightMagnitude; // 緑色(R,G,B が 0,1,0)に明るさの程度を乗じます。
// ここでは k の効果のみを使いますが、実際には、k と lightMagnitude を合わせて使用します(次回《436》で 確認します)。
return float4(0, 1, 0, 0) * k;
}