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;