1

変換行列のコードがいくつかあり、錐台と遠近法を処理する関数をいくつか追加しました。

パースペクティブと呼ぶと、すべてが本当に大きな視野を持っているように見えます(画面の中央では、端が非常に伸びています)。ニア値を大きくすると、この効果はさらに悪くなります。

    void Frustum(T left, T right, T bottom, T top, T zNear, T zFar)
    {
        m[0][0]=2.0f*zNear/(right-left);
        m[1][0]=0.0f;
        m[2][0]=(right+left)/(right-left);
        m[3][0]=0.0f;
        m[0][1]=0.0f;
        m[1][1]=2.0f*zNear/(top-bottom);
        m[2][1]=(top+bottom)/(top-bottom);
        m[3][1]=0.0f;
        m[0][2]=0.0f;
        m[1][2]=0.0f;
        m[2][2]=-(zFar+zNear)/(zFar-zNear);
        m[3][2]=-2.0f*zFar*zNear/(zFar-zNear);
        m[0][3]=0.0f;
        m[1][3]=0.0f;
        m[2][3]=-1.0f;
        m[3][3]=0.0f;
    }

    void Perspective(T fovy,T aspectRatio,T zNear,T zFar)
    {
        T xmin,xmax,ymin,ymax;
        ymax= zNear* tan(fovy*Math<T>::PI/360.0);
        ymin= -ymax;
        xmin= ymin*aspectRatio;
        xmax= ymax*aspectRatio;
        Frustum(xmin,xmax,ymin,ymax,zNear,zFar);
    }

クラスがテンプレート化されているため、Tはfloatまたはdoubleです(テストではfloatのみを使用しました)。

私が使用するテスト値はfovy="60" znear="1.0" zfar="1000.0"であり、それらを変更するとfovy="60" znear="10.0" zfar="1000.0"、さらに悪化します。

行列はDirectXスタイルですが、OpenGLで使用しているため、シェーダーでの乗算の順序を変更していることに注意してください。

私のコードに何か問題がありますか?

ありがとう

4

3 に答える 3

2

問題は、転置された行列(DirectXスタイル)を使い始めたときに、錐台の数学も転置する必要があると考えたということでした。これは良い考えではありません。

Frustum関数は次のようになります。

    void Frustum(T left, T right, T bottom, T top, T zNear, T zFar)
    {
        T zDelta = (zFar-zNear);
        T dir = (right-left);
        T height = (top-bottom);
        T zNear2 = 2*zNear;

        m[0][0]=2.0f*zNear/dir;
        m[0][1]=0.0f;
        m[0][2]=(right+left)/dir;
        m[0][3]=0.0f;
        m[1][0]=0.0f;
        m[1][1]=zNear2/height;
        m[1][2]=(top+bottom)/height;
        m[1][3]=0.0f;
        m[2][0]=0.0f;
        m[2][1]=0.0f;
        m[2][2]=-(zFar+zNear)/zDelta;
        m[2][3]=-zNear2*zFar/zDelta;
        m[3][0]=0.0f;
        m[3][1]=0.0f;
        m[3][2]=-1.0f;
        m[3][3]=0.0f;
    }
于 2012-07-20T08:44:33.720 に答える
1

計算する

z_delta=(zfar-znear);//used two times!
direction=(right-left);//used two times!
height=(top-bottom);//used two times!
znear_2=2.0f*znear; //used 3 times!

1回だけ!好きな場所で使用できます

また、除算は非常に高価であるため、除算を事前に計算して配列に格納できます。実行時に、事前に計算された要素を配列からフェッチするだけで済みます。

例:上部と下部の範囲が小さい場合は、計算を小さな配列で表すことができます(実際には、除算器と除算器のマッピングです)

于 2012-07-19T09:20:31.460 に答える
0

問題は次のとおりだと思います。Perspective()計算するときはymax、を掛けてはいけませんzNear数学的には、平面ではなく、単位距離で平面に投影していますzNear。その価値はそこには何の関係もありません。

ymax= tan(fovy*Math<T>::PI/360.0)代わりに設定してみてください。それが正しいという保証はまだありませんが、それはかなり正気であるはずです...

于 2012-07-19T18:21:52.563 に答える