OpenGLの2D(Ortho)の上に3D(rustum)を描画できません
-
26-10-2019 - |
質問
背景画像の上にフラストム投影を伴ういくつかのメッシュをレンダリングしようとしています(正書法の投影)。私が何をしても、背景画像はシーンの上にあり続けます(メッシュを隠します)。
私は少しテストを試みました - 同じ投影マトリックスで両方をレンダリングしたとき、正しい順序であった - 背景画像はメッシュの背後にありました。
これらは投影マトリックスと深さバッファのinitです。
glEnable(GL_DEPTH_TEST);
glClearDepthf( 1.0f );
glDepthFunc( GL_LEQUAL );
glDepthMask (GL_TRUE);
EGLConfig eglconfig;
EGLint const attrib_list[] = {
EGL_DEPTH_SIZE, 16,
EGL_NONE
};
EGLint numreturned;
CHECK(eglChooseConfig(esContext.eglDisplay, attrib_list, &eglconfig, 1, &numreturned) != EGL_FALSE);
float fieldOfView = 60.0;
float znear = 0.1f;
float zfar = 100000;
float size = (float)(znear * tanf((fieldOfView * M_PI /180.0f) / 2.0f));
m_orthoProjMatrix.loadOrtho(0,
screenWidth,
0,
screenHeight,
znear,
zfar);
m_frustProjMatrix.loadFrustum(-size,
size,
-size / (screenWidth / screenHeight),
size / (screenWidth / screenHeight),
znear,
zfar);
バッファーをクリーニングしています:glclear(gl_color_buffer_bit | gl_depth_buffer_bit);
最後に.. GL_DEPTH_TESTを無効にすると、背景が最初に呼ばれているため、メッシュが背景画像の前で描画されています。
どちら、深さバッファーまたは投影行列が、この問題を引き起こします。ScreenWidth= 960およびScreenHeight = 640のマトリックスの値はわかりません。
Orthographic Proj Matrix:
0.00208 0.00000 0.00000 -1.00000
0.00000 0.00313 0.00000 -1.00000
0.00000 0.00000 0.00000 -1.00000
0.00000 0.00000 0.00000 1.00000
Frustum Proj Matrix:
1.73205 0.00000 0.00000 0.00000
0.00000 2.59808 0.00000 0.00000
0.00000 0.00000 -1.00000 -0.20000
0.00000 0.00000 -1.00000 0.00000
Camera Settings:
Vector3 pos(0,10,50);
Vector3 at(0,0,0);
Vector3 up(0,1,0);
LookAt(pos,at,up);
Scene Settings:
Vector3 BackgroundImagePosition (0,0, -430);
Vector3 SomeMesh(0,0,0);
私は何が間違っているのですか?アミール。
編集:これは、正書法の投影で画像を描画する方法:
GLfloat verts[] = {
image->x + image->width , image->y , image->z,
image->x + image->width , image->y + image->height, image->z,
image->x , image->y + image->height, image->z,
image->x , image->y , image->z};
Matrix4s mv(m_camera->getCameraViewMatrix());
Matrix4f proj(ResManPtr->getOrthoProjMatrix() * mv);
glUniformMatrix4fv(prog->getUniformLocation("u_projMatrix"), 1, GL_FALSE, &(*proj));
glActiveTexture(GL_TEXTURE0);
image->tex->bind();
glUniform1i(prog->getUniformLocation("s_texture"), 0);
glEnableVertexAttribArray(prog->getAttribLocation("a_position"));
glVertexAttribPointer(prog->getAttribLocation("a_position"), 3, GL_FLOAT, GL_FALSE, 0, verts);
glEnableVertexAttribArray(prog->getAttribLocation("a_texCoord"));
glVertexAttribPointer(prog->getAttribLocation("a_texCoord"), 2, GL_FLOAT, GL_FALSE, 0, m_texcoord);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
そして、これは私がフラストム投影でメッシュを描く方法です:
Matrix4f mv(world->getCamera()->getCameraViewMatrix());
const btVector3& dir = getDirection();
Scalar xzAngle = atan2s(dir.x(), dir.z()) - (Scalar)M_PI_2;
btVector3 origin = getGhostObject()->getWorldTransform().getOrigin();
mv.applyTranslate(origin.x(), origin.y() - m_width/2, origin.z());
mv.applyRotateY(xzAngle);
GLProgramPtr prog = ResManPtr->getProgramMap()[Consts::DEFAULT_PROGRAM_KEY];
Matrix4f proj(ResManPtr->getFrustProjMatrix() * mv);
glUniformMatrix4fv(prog->getUniformLocation("u_projMatrix"), 1, GL_FALSE, &(*proj));
glActiveTexture(GL_TEXTURE0);
m_texture->bind();
glUniform1i(prog->getUniformLocation("s_texture") , 0);
m_model->render(frame_number);
解決
私が正しく理解しているなら、あなたは次の別のことをしたい:
- テクスチャのあるフルスクリーンのクワッドを描きます
- このクワッドがzバッファで考慮されないように何かをしてください
- その後、その上にメッシュ(必要な投影、ビュー、モデルのマトリックスを使用して)を描画します。
「GL_DEPTH_TESTを無効にすると、背景が最初に呼ばれているため、メッシュが背景画像の前に描画されています。」したがって、VBOのセットアップ、マトリックス、テクスチャなどがすべて優れています。見逃しているのはポイント#2のみです。
- 解決策1:
いつものように、新しいフレームのすべてをクリアします。 Zバッファーはどこでも1.0になります
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
背景を描きます。カラーバッファーは問題ありませんが、Zバッファーにはクワッドの深さが含まれているため、0.5としましょう。したがって、メッシュをレンダリングする場合、新しい深度値が0.5より小さいように、または深さテストが失敗するように、幸運でなければなりません。しかし、私たちはそれについて何かをすることができます:Zバッファーを再び1.0に再びクリアするだけです:
glClear(GL_DEPTH_BUFFER_BIT);
次に、他のメッシュを通常どおり描画します。 ModelViewProjectionマトリックスは変更されましたが、OpenGLはそれを知りません。したがって、メッシュの深さテストは常に成功します。したがって、正しいz値を使用して、メッシュが存在する場所と、背景が他のどこにでも表示されます。
- 解決策2
ここでは、フルスクリーンのクワッドが描かれたときに深さの値が更新されるのを防ぎます。
深さバッファーに関する書き込みを無効にします。
glDepthMask(GL_FALSE);
背景を描きます。カラーバッファーは問題なく、Zバッファーにはどこでも1.0が含まれています。
今度は、深さバッファーに再び書き込みできるようになりました。
glDepthMask(GL_TRUE);
他のメッシュを描きます。前と同様に、Zバッファーはどこでも1.0になります。まるでglclear()と呼ばれているように、メッシュがフラストムにある場合(明らかにそうでなければなりません)、zは0.5になり、描画されます。
- ソリューション3
背景をカメラから遠く離れて、遠く離れた平面近くに描くだけです。 (つまり、大きなZコンポーネントがあります)。そのZコンポーネントは0.9999またはそのようなものになり、以前と同じように、メッシュは完全にレンダリングされます。
私は本当に、もっと詳細を説明することはできません。まだ明確でない場合は申し訳ありませんが、いくつかの方法で各アイデアを再定式化しようとしました。これ以上何もできません。