opengl 射影行列で符号が重要なのはなぜですか
-
21-09-2019 - |
質問
私は、キャリブレーションされたカメラを使用して 3D モデルをレンダリングする必要があるコンピューター ビジョンの問題に取り組んでいます。私はキャリブレーションされたカメラ行列をモデルビュー行列と投影行列に分割する関数を書いていますが、opengl で (少なくとも私には) 説明できない興味深い現象に遭遇しました。
簡単に説明すると、射影行列を否定すると、(少なくとも私の経験では) 何もレンダリングされないということです。射影行列にスカラーを乗算しても、スケーリングの影響を受けない同次座標を変換するため、効果はないと予想します。
以下は、これが予想外であると私が思う理由です。もしかしたら誰かが私の推論のどこが間違っているかを指摘してくれるかもしれない。
正しい結果が得られる次の透視投影行列を想像してください。
[ a b c 0 ]
P = [ 0 d e 0 ]
[ 0 0 f g ]
[ 0 0 h 0 ]
これにカメラ座標を乗算すると、均一なクリップ座標が得られます。
[x_c] [ a b c 0 ] [X_e]
[y_c] = [ 0 d e 0 ] * [Y_e]
[z_c] [ 0 0 f g ] [Z_e]
[w_c] [ 0 0 h 0 ] [W_e]
最後に、正規化されたデバイス座標を取得するために、x_c、y_c、z_c を w_c で除算します。
[x_n] [x_c/w_c]
[y_n] = [y_c/w_c]
[z_n] [z_c/w_c]
ここで、P を否定すると、結果として得られるクリップ座標も否定されるはずですが、それらは同次座標であるため、任意のスカラー (例:-1) は、結果として得られる正規化されたデバイス座標に影響を与えるべきではありません。ただし、openGl では、P を否定すると何も表示されません。P に負でないスカラーを乗算すると、まったく同じレンダリング結果が得られますが、負のスカラーを乗算するとすぐに何もレンダリングされなくなります。ここで何が起こっているのですか?
ありがとう!
解決
まあ、それの要旨はクリッピングのテストを介して行われていることです
-w_c < x_c < w_c
-w_c < y_c < w_c
-w_c < z_c < w_c
は、負の値を掛けるが、このテストを壊します。
他のヒント
私は答えに向かって進行するこのちらほらを見つけます:
レッドブックから、付録Gます:
頂点座標と負のqテクスチャ座標wは負の使用を避けます。 OpenGLは正確な座標をクリップしていない可能性があると、このような座標で定義されたプリミティブをシェーディングするとき補間誤差を作るかもしれません。
射影行列を反転する座標負Wクリッピングを生じ、そして明らかにOpenGLは、このようにしないであろう。しかし、缶誰OpenGLはこのケースを処理しない理由を説明?
私が考えられる理由は次のとおりです。
- 射影行列を反転すると、座標は視錐台の zNear 平面および zFar 平面内になくなります (必ず 0 より大きくなります)。
- ウィンドウ座標を作成するには、正規化されたデバイス座標がビューポートによって変換/スケーリングされます。したがって、クリップ座標に負のスカラーを使用した場合、正規化されたデバイス座標 (現在は反転) がビューポートをウィンドウ座標に変換します。窓の外(できれば左側と下)
また、カメラ行列を使用し、射影行列を反転したと述べたので、質問する必要があります...カメラ マトリックスの何をどのマトリックスに適用しますか?近/遠/フォービー/アスペクト保存の投影行列を操作すると、z を使用するもの (深度テスト、顔カリングなど) を含む深度バッファーであらゆる種類の問題が発生します。
OpenGL FAQ セクション 変換 にはさらに詳細があります。