私の趣味のシェーダーベースの(非FFP)GL(3.2+コア)「エンジン」では、ワールドスペースとモデルスペースのすべてが設計上「左利き」であるため(そしてその状態を維持するため)、X軸-1(「左」)から1(「右」)、Yから-1(「下」)から1(「上」)、Zから-1(「近く」)から1(「遠」)になります。 。
これで、OpenGLのデフォルトでは、NDCスペースは同じように機能しますが、クリップスペースは機能しません。私が収集したものから、ここでzは1(「近い」)から-1(「遠い」)に拡張されます。
同時に、私は理想的には、現在次のように定義されている、ルックアットとパースペクティブのための「ちょっとした非公式の準標準」行列関数を使い続けたいと思っています。
func (me *Mat4) Lookat(eyePos, lookTarget, upVec *Vec3) {
l := lookTarget.Sub(eyePos)
l.Normalize()
s := l.Cross(upVec)
s.Normalize()
u := s.Cross(l)
me[0], me[4], me[8], me[12] = s.X, u.X, -l.X, -eyePos.X
me[1], me[5], me[9], me[13] = s.Y, u.Y, -l.Y, -eyePos.Y
me[2], me[6], me[10], me[14] = s.Z, u.Z, -l.Z, -eyePos.Z
me[3], me[7], me[11], me[15] = 0, 0, 0, 1
}
// a: aspect ratio. n: near-plane. f: far-plane.
func (me *Mat4) Perspective(fovY, a, n, f float64) {
s := 1 / math.Tan(DegToRad(fovY)/2) // scaling
me[0], me[4], me[8], me[12] = s/a, 0, 0, 0
me[1], me[5], me[9], me[13] = 0, s, 0, 0
me[2], me[6], me[10], me[14] = 0, 0, (f+n)/(n-f), (2*f*n)/(n-f)
me[3], me[7], me[11], me[15] = 0, 0, -1, 0
}
したがって、lookat-partで、ワールドスペースカメラ(positive-Z)がlookat(negative-Z)で動作するようにするには、次の擬似コードに従います。
// world-space position:
camPos := cam.Pos
// normalized direction-vector, up/right/forward are 1 not -1:
camTarget := cam.Dir
// lookat-target:
camTarget.Add(&camPos)
// invert both Z:
camPos.Z, camTarget.Z = -camPos.Z, -camTarget.Z
// compute lookat-matrix:
cam.mat.Lookat(&camPos, &camTarget, &Vec3{0, 1, 0})
それはうまくいきます。カメラを6自由度すべてで動かすと、画面上で正しい動きが得られ、新しいカメラのワールドスペース座標が正しくなります。
ただし、ジオメトリはZ軸上で反転したままです。Aを(-2、1、-2)に配置して左に表示し、B(2、1、2)を右端に表示すると、Aは左端に表示され、Bは右に表示されます。 。Zはまだここで反転しています。
現在、これらのノードには独自の世界空間座標があり、それらの独自のモデルから世界への行列から更新されます。posZは、親の変換などで乗算されるサブノードの階層を形成するため、そこで反転するべきではありません。彼らはまだモデルまたは世界空間にあり、私の命令によれば、それは左利きのままであることになっています。
それらのワールドからカメラへの計算は、単一の最終(mvp /クリップスペース)マトリックスを取得する頂点シェーダーではなく、私の最後のCPUで行われます。
それが起こったとき-ワールドスペースオブジェクトマトリックスとクリップスペースルックアットアンドプロジェクションマトリックスの乗算-その時点で私はどういうわけかZを反転する必要があります。
これを行うための最良の方法は何ですか?または、より一般的に言えば、機能する一般的な方法は何ですか?左利きであるが出力からGLへの右利きを受け入れるように投影を変更する必要がありますか?もしそうなら、どのように?そして、私もlookatを変更する必要はありませんか?左手系の座標でmodel-transform-matricesを維持しながら、ある程度標準的なlookat / Projection行列を変更せずに、これらすべてを実行するスマートな方法はありますか?