0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【シェーダー】法線の変換をちゃんと理解する

Posted at

導入

こんな感じのプログラムについての話です。
かっこが多い!

// normalOS : オブジェクトローカル座標系の法線
// normal   : ビュー       座標系の法線
// MY_IT_MV 行列を用いて, normalOS → normal に変換 (最後に正規化している)
float3 normal = normalize(mul((float3x3)MY_IT_MV, normalOS));

この計算式の意味を理解した、みたいな感じです。

その1 - 必要なのは「回転」「拡縮」のみ

CGには、基本の座標操作があります。

  • 拡縮
  • 回転
  • (並行)移動

あとはスキューとかがありますが、今回は考えないです。

さて、法線の変換に移動の情報は要らないです。
「移動の情報」とはつまり、「法線のワールド座標」です。
法線は方向ベクトルですので、いくら並行移動しようが意味はありません。
従って移動の情報は捨てても良いです。
で、その結果として、めっちゃ嬉しいことがあります。

その2 - 線形変換じゃん!

CGでは 4x4 のアフィン変換行列を用いると思います。
それで、そもそもなぜ 3x3 じゃダメなのかというと、
移動があるせいで線形変換じゃなくなり、そのため 3x3 で表現しきれない からです。

アフィン変換行列のテンプレを見てください。
右端の列、移動成分 (tx, ty, tz) がスゴい主張しています。

\left|
\begin{matrix}
a & b & c & <tx> \\
d & e & f & <ty> \\
g & h & i & <tz> \\
0 & 0 & 0 & 1 \\
\end{matrix}
\right|

法線の変換で移動が要らないということは、
つまりアフィン変換に拡張する意味が無くなったということです。
なので、左上 3x3 (線形変換の情報がある部分) を使えば十分です。

// 左上 3x3 を使えば十分
(float3x3)MY_IT_MV

その3 - 逆転置の意味

本題かな?とは思うんですが、他の人が解説しているので飛ばします!!
素晴らしい解説記事

僭越ながら簡単に要約すると、

  • オブジェクトの回転はそのまま反映 - 逆行列→転置行列で、回転行列は変化しない
  • オブジェクトの拡縮には反比例する - 逆行列→転置行列で、拡縮成分は逆数になる

的な感じです。

// 逆(inverse) → 転置(transport) なので、「IT」がくっついている。
(float3x3)MY_IT_MV

その4 - 最後の仕上げ

ここまでで変換行列が求まったので、適用していきます。

mul((float3x3)MY_IT_MV, normalOS)

拡縮行列のせいで、法線の長さが変わってしまいました。
正規化しましょう。

normalize(mul((float3x3)MY_IT_MV, normalOS))

完成!!

float3 normal = normalize(mul((float3x3)MY_IT_MV, normalOS));

最後に

分かりにくい所があれば、ご指摘お願いします。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?