web-dev-qa-db-ja.com

個別の射影行列を持ちながら、モデルとビュー行列を組み合わせることが有益なのはなぜですか?

3Dプログラミングを学習しているとき、3つの変換行列の観点から考えるのが最も簡単であると教えられます。

  1. モデル行列。このマトリックスはすべてのモデルに固有であり、必要に応じてオブジェクトを回転およびスケーリングし、最終的に3Dワールド内の最終位置に移動します。 「モデル行列はモデル座標を世界座標に変換します」。

  2. ビューマトリックス。このマトリックスは通常、多数のオブジェクト(すべてではない場合)で同じであり、現在の「カメラ位置」に従ってすべてのオブジェクトを回転および移動します。 3Dシーンがカメラによって撮影され、画面にレンダリングされるのがこのカメラによってキャプチャされた画像であるとイメージする場合、カメラの位置とその表示方向によって、シーンのどの部分が表示され、オブジェクトがどのように表示されるかが決まります。キャプチャした画像に表示されます。単一フレームのレンダリング中にビューマトリックスを変更する理由はほとんどありませんが、実際には存在します(たとえば、シーンを2回レンダリングし、その間にビューマトリックスを変更することで、シーン内に非常にシンプルで印象的なミラーを作成できます) 。通常、ビューマトリックスは、描画される2つのフレーム間で1回だけ変更されます。 「ビューマトリックスは、世界座標を目の座標に変換します」。

  3. 射影行列。射影行列は、これらの3D座標を2D座標にマッピングする方法を決定します。それらに適用される遠近法がある場合(オブジェクトがビューアから離れるほど小さくなる)、または適用されない場合(正射影)。射影行列はほとんど変化しません。ウィンドウにレンダリングしてウィンドウサイズが変更された場合、またはフルスクリーンでレンダリングして解像度が変更された場合は、変更が必要になる場合があります。ただし、新しいウィンドウサイズ/画面解像度の表示アスペクト比が以前と異なる場合に限ります。このマトリックスを変更したいというクレイジーな効果がいくつかありますが、ほとんどの場合、プログラムのライブ全体でほぼ一定です。 「射影行列は目の座標を画面の座標に変換します」。

これは私にとって非常に理にかなっています。もちろん、最初に行列Aを掛け、次に行列Bを掛けるのは、ベクトルに行列C、 どこ C = B * A

ここで、古典的なOpenGL(OpenGL 1.x/2.x)を見ると、OpenGLは射影行列を知っています。ただし、OpenGLはモデルまたはビューマトリックスを提供せず、結合されたモデル-ビューマトリックスのみを提供します。 なぜ?この設計では、モデル変換が適用されると「破棄」されるため、「ビューマトリックス」を永続的に保存および復元する必要があります。なぜ3つの別々の行列がないのですか?

新しいOpenGLバージョン(OpenGL 3.x/4.x)を見て、従来のレンダリングパイプラインを使用せず、シェーダー(GLSL)ですべてをカスタマイズする場合、使用可能なマトリックスはもうありません。独自の行列を定義します。それでもほとんどの人は、射影行列とモデルビュー行列の古い概念を維持しています。 なぜそうするのですか? 3つのマトリックスを使用しないのはなぜですか。つまり、モデルビューマトリックスを永続的に保存および復元する必要がないか、単一の結合モデルビュープロジェクション(MVP)を使用します。 )matrix。これにより、レンダリングされた単一の頂点の頂点シェーダーでの行列の乗算が保存されます(結局、このような乗算も無料ではありません)。

だから私の質問を要約すると:3つの別々のマトリックスまたは単一のMVPマトリックスを持つよりも、別々の投影マトリックスと一緒に結合されたモデルビューマトリックスを持っている利点はどれですか?

49
Mecki

実際に見てください。まず、送信する行列が少ないほど、位置/法線などで乗算する必要のある行列が少なくなります。したがって、頂点シェーダーが高速になります。

したがって、ポイント1:行列は少ないほど良いです。

ただし、おそらく実行する必要がある特定のことがあります。 2Dレンダリングまたはいくつかの単純な3Dデモアプリケーションを実行しているのでない限り、ライティングを実行する必要があります。これは通常、位置と法線をワールドまたはカメラ(ビュー)空間に変換してから、それらに対していくつかのライティング操作を実行する必要があることを意味します(頂点シェーダーまたはフラグメントシェーダーのいずれかで)。

モデル空間から投影空間に移動するだけでは、それはできません。投影後の空間は非線形であるため、その空間で照明を行うことはできません。数学ははるかに複雑になります。

したがって、ポイント2:モデルと投影の間に少なくとも1つの停止が必要です。

したがって、少なくとも2つの行列が必要です。なぜモデルから世界ではなくモデルからカメラへ? シェーダーでワールド空間で作業することは悪い考えです。 原点から離れた平行移動に関連する数値精度の問題が発生する可能性があるためです。一方、カメラスペースで作業している場合は、カメラから遠すぎるものはないため、これらの問題は発生しません(遠すぎる場合は、おそらく遠方の深度平面の外側にあるはずです)。

したがって、照明の中間スペースとしてカメラスペースを使用します。

38
Nicol Bolas

ほとんどの場合、シェーダーはシェーディングのためにワールド座標またはアイ座標のジオメトリを必要とするため、モデルおよびビューマトリックスから射影マトリックスを分離する必要があります。

シェーダーにジオメトリを2つのマトリックスで乗算させると、パフォーマンスが低下します。各モデルにthousends(またはそれ以上)の頂点があると仮定すると、CPUでモデルビュー行列を1回計算し、シェーダーにmtrixベクトルの乗算を1つ少なくする方が効率的です。

2
Tal Darom