1

私の趣味のシェーダーベースの(非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行列を変更せずに、これらすべてを実行するスマートな方法はありますか?

4

1 に答える 1

1

パースペクティブでは、me[11] を -1 から 1 に変更すると、説明したように z 軸が反転するはずです。それが正しくない場合は、私を否定してみてください [10]。もちろん、z 軸が反転しているため、回転の方向も同様に影響を受けます。y 軸を中心とした右回転を思い出すと、x 軸が反転する可能性があります。この場合は、回転を無効にしてそれを打ち消すことができるはずです。

于 2013-03-11T03:08:04.093 に答える