頭と尻尾はくれてやる!

パソコンおやじのiPhoneアプリ・サイト作成・運営日記


法線と光源の内積でテクスチャの明るさを決める

頭と尻尾はくれてやる! / Metalでテクスチャを貼る
↑この続きなんだけど、なんだか描画されたオブジェクトが暗いのよ。
シェーダ内でテクスチャに対して面の法線と光源の内積をかける、というよくある処理してるんだけど、正面から光をあてたりしても妙に暗い。
法線うんぬんの処理をせずにテクスチャ画像そのままで表示させるとちゃんとテクスチャ画像を拾ってるのは確認できるので、どうも法線関連部分がおかしいみたい。

参考にした”MetalBasic3D"ってAppleのサンプルコードでは次のようなコードで内積を求めている。
{
    float3 normal = normal_array[vid].position;//(1)
    float4 eye_normal = normalize(constants.normalMatrix * float4(normal, 0.0));//(2)
    float3 light_position = float3(1.0 , 1.0 , 1.0);//(3)
    float n_dot_l = dot(eye_normal.rgb, normalize(light_position));//(4)
}

(1)法線はfloat3でもらう。
(2)法線に一つの要素を追加しのと4x4のマトリックスとかけてる。
(3)float3の光源。
(4)(2)の結果の三要素(.rgb)と光源で内積を計算してる。

別にOpenGL ESで処理してた内容と変わらないよなあと思っていたんだけど、よく見るとこのコードではシェーダに4x4のマトリックスを渡してる。constants.normalMatrixってやつね。

OpenGL ESで使ってるコードを見るとこの部分、3x3のマトリックスを使ってるんだわ。

別に4x4で処理してる内容見ても問題ない(左上の3x3しか使っていない)ように見えるけど、他に思い付かないからとりあえずOpenGL ESと同じように3x3のマトリックスを渡してみると、、、

修正後のロボット

↑あら?意図通りになってる。謎だ、、、と思ったんだけど、今気が付いた。
(2)の部分で4つの要素で正規化(normalize)してるじゃねーかっ!4つめの要素がゼロとは限らないし。
{
    float4 raw_eye_normal = constants.normalMatrix * float4(normal, 0.0);
    float3 eye_normal = normalize(row_eye_normal.rgb);
}
確認のため三要素で正規化してやったらちゃんと意図通り表示されたよ!

どっちがいいのか知らないけどシェーダに無駄なデータを渡すのを避けて3x3要素を渡すことにするわ。

<< GarageBandで遊んでみる  TopPage  Metalでテクスチャを貼る >>

コメント


管理者にだけ表示を許可する
 

トラックバック

トラックバックURL
http://ringsbell.blog117.fc2.com/tb.php/942-b4cf3877




Copyright ©頭と尻尾はくれてやる!. Powered by FC2 Blog. Template by eriraha.

FC2Ad