私はいくつかのシェーダーに取り組んでおり、法線を変換する必要があります。
いくつかのチュートリアルで、法線を変換する方法は、モデルビュー行列の逆行列の転置でそれらを乗算することです。しかし、なぜそうなのか、そしてその背後にある論理は何であるのかについての説明を見つけることができません。
私はいくつかのシェーダーに取り組んでおり、法線を変換する必要があります。
いくつかのチュートリアルで、法線を変換する方法は、モデルビュー行列の逆行列の転置でそれらを乗算することです。しかし、なぜそうなのか、そしてその背後にある論理は何であるのかについての説明を見つけることができません。
法線の定義から流れます。
オブジェクトの法線と同じ位置に、法線、、N
およびベクトル、、接線ベクトルがあるとします。V
次に、定義によりN·V = 0
。
接線ベクトルは、オブジェクトの表面と同じ方向に実行されます。したがって、サーフェスが平面の場合、接線はオブジェクト上の2つの識別可能なポイント間の差です。したがってV = Q - R
、Q
とR
がサーフェス上のポイントである場合、オブジェクトを次のように変換すると、次のようになりますB
。
V' = BQ - BR
= B(Q - R)
= BV
同じロジックが、制限を考慮して非平面サーフェスに適用されます。
この場合、行列によってモデルを変換しようとしていると仮定しますB
。したがってB
、ジオメトリに適用されます。次に、法線をどうするかを理解するために、行列を解く必要がありますA
。
(AN)·(BV) = 0
これを行と列の関係に変換して、明示的な内積を削除します。
[tranpose(AN)](BV) = 0
トランスポーズを外側に引き出し、ブラケットを削除します。
transpose(N)*transpose(A)*B*V = 0
つまり、「法線の転置」[積]「既知の変換行列の転置」[積]「解く変換」[積]「モデルの表面上のベクトル」= 0
しかしtranspose(N)*V = 0
、それはそれを言うことと同じなので、私たちはそれを述べることから始めましたN·V = 0
。したがって、制約を満たすには、式の中央部分— transpose(A)*B
—をなくす必要があります。
したがって、次のように結論付けることができます。
transpose(A)*B = identity
=> transpose(A) = identity*inverse(B)
=> transpose(A) = inverse(B)
=> A = transpose(inverse(B))
私のお気に入りの証明は以下のとおりです。ここで、Nは法線、Vは接線ベクトルです。それらは垂直であるため、それらの内積はゼロです。Mは、任意の3x3の可逆変換です(M -1 * M = I)。N'とV'はMによって変換されたベクトルです。
直感的に理解するために、以下のせん断変換を検討してください。
これは接線ベクトルには適用されないことに注意してください。
このチュートリアルを見てください:
https://paroj.github.io/gltut/Illumination/Tut09%20Normal%20Transformation.html
球の表面が伸びると(球が1つの軸などに沿って拡大縮小される)、その表面の法線はすべて互いに向かって「曲がる」と想像できます。これを実現するには、法線に適用されているスケールを反転する必要があることがわかります。これは、逆転置行列を使用した変換と同じです。上記のリンクは、これから逆転置行列を導出する方法を示しています。
また、スケールが均一の場合、元の行列を通常の行列として渡すことができることにも注意してください。同じ球がすべての軸に沿って均一にスケーリングされていると想像してください。サーフェスは伸びたり曲がったりせず、法線も伸びません。
モデル行列が平行移動、回転、およびスケールで構成されている場合、正規行列を計算するために逆転置を行う必要はありません。法線を二乗スケールで割り、モデル行列を掛けるだけで完了です。これを垂直軸を持つ任意の行列に拡張できます。代わりに、使用している行列の各軸の2乗スケールを計算するだけです。
詳細はブログに書きました:https ://lxjk.github.io/2017/10/01/Stop-Using-Normal-Matrix.html
モデル行列を乗算する前に、方向ベクトルの4番目の要素をゼロにしない理由がわかりません。逆行列や転置は必要ありません。方向ベクトルを2点の差と考えてください。モデルの残りの部分と一緒に2つのポイントを移動します。これらのポイントは、モデルに対して同じ相対位置にあります。2つのポイントの差をとって新しい方向を取得し、4番目の要素はゼロにキャンセルされます。ずっと安い。