2

CPUにClip-SpaceFrustumCullingを実装しました。単純な縮小の場合、GL_LINESモードでレンダリングする4つの異なるポイントに基づいて長方形を作成するだけです。

しかし、時々、私には間違った結果が出るように思えます。次に例を示します。

このレンダリングパスでは、錐台カリングの計算で、すべてのポイントがNDC座標の正のy座標の外側にあることが検出されます。

入力は次のとおりです。

ポイント:

P1: -5000, 3, -5000
P2: -5000, 3,  5000
P3:  5000, 3,  5000
P4:  5000, 3, -5000

MVP(四捨五入):

  1.0550   0.0000  -1.4521   1138.9092
 -1.1700   1.9331  -0.8500  -6573.4885
 -0.6481  -0.5993  -0.4708  -2129.3858
 -0.6478  -0.5990  -0.4707  -2108.5455

そして計算(MVP *ポジション)

P1       P2       P3       P4
3124     -11397   -847     13674
3532     -4968    -16668   -8168
3463     -1245    -7726    -3018
3482     -1225    -7703    -2996

そして最後に、パースペクティブディバイド(w-component)によって変換されます

P1       P2       P3       P4
0.897    9.304    0.110    -4.564
1.014    4.056    2.164    2.726
0.995    1.016    1.003    1.007
1.0      1.0      1.0      1.0

ご覧のとおり、変換されたすべてのポイントのy成分は1より大きく、ViewingFrustumの外側にある必要があります。

私はすでに自分の行列を再確認しました。また、Vertex Shaderで変換フィードバックを作成しました。確かに、CPUとGPUでの計算には同じ行列を使用します。MVP * Pointの結果でさえ、私のVertexShaderでもGPUと同じです。私のレンダリングパイプラインは可能な限りシンプルです。

頂点シェーダーは

vColor = aColor; 
gl_Position = MVP * aVertexPosition;

//With Transform Feedback enabled
//transOut = MVP * aVertexPosition

そしてフラグメントシェーダー

FragColor = vColor;

したがって、VertexShaderは私のCPU計算と同じ結果になります。それでも、それらは画面上に描かれた線です!なぜ線があるのか​​アイデアはありますか?パースペクティブディバイドで何か問題がありますか?

少なくとも1本の線が表示されているため、この長方形をカリングしないようにするには、何をする必要がありますか(基本的に、この例では別の線のストリップも表示されます)

役立つ場合:表示されている赤い線は、P1とP2の間の線です。

[編集]カメラの錐台法線とヘッセ標準形の方程式を計算して、ワールドスペースカリングを実装しました。これは正しい認識でうまく機能します。悲しいことに、私はそのポイントで他の計算を行うので、クリップ空間で正しい計算が必要です。誰かアイデアはありますか?

これが私の計算コードです:

int outOfBoundArray[6] = {0, 0, 0, 0, 0, 0};
std::vector<glm::dvec4> tileBounds = activeElem->getTileBounds(); //Same as I use for world space culling
const glm::dmat4& viewProj = cam->getCameraTransformations().viewProjectionMatrix; //Same camera which I use for world space culling.

for (int i=0; i<tileBounds.size(); i++) {

    //Apply ModelViewProjection Matrix, to Clip Space
    glm::dvec4 transformVec = viewProj * tileBounds[i];

    //To NDC space [-1,1]
    transformVec = transformVec / transformVec[3];

    //Culling test
    if ( transformVec.x >  1.0 ) outOfBoundArray[0]++;
    if ( transformVec.x < -1.0 ) outOfBoundArray[1]++;
    if ( transformVec.y >  1.0 ) outOfBoundArray[2]++;
    if ( transformVec.y < -1.0 ) outOfBoundArray[3]++;
    if ( transformVec.z >  1.0 ) outOfBoundArray[4]++;
    if ( transformVec.z < -1.0 ) outOfBoundArray[5]++;

    //Other computations...
}

for (int i=0; i<6; i++) {
    if (outOfBoundArray[i] == tileBounds.size()) {
        return false;
    }
}
return true;
4

1 に答える 1

2

問題は、w(3番目のコンポーネント)の符号がP1とP2で異なるように見えます。これは、射影幾何学の性質により、あらゆる種類の問題を引き起こします。

ポイントはNDCの同じ側にありますが、描画される線は実際には無限大を通ります。P1とP2の間を線形補間し、各ポイントで別々にwで除算するとどうなるかを考えてください。何が起こるかというと、wがゼロに近づくと、y値は正確にゼロではないため、線は無限大にズームオフします。そして、反対側からラップアラウンドします。

射影幾何学は奇妙なことです:)

ただし、解決策として、w = 0平面と交差する線をその平面の正の側でクリップするようにしてください。そうすれば、コードが機能するはずです。

于 2012-12-08T00:01:58.400 に答える