无法在 OpenGL 中在 2D(正交)之上绘制 3D(视锥体)
我正在尝试在背景图像(正交投影)之上使用平截头体投影渲染一些网格。无论我做什么,背景图像始终位于场景顶部(隐藏网格)。
我尝试了一些测试 - 当我用相同的投影矩阵渲染它们时 以正确的顺序 - 背景图像位于网格后面。
这些是投影矩阵和深度缓冲区初始化:
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);
I'm trying to render some meshes with Frustum projection on top of a background image (orthographic projection). No matter what I do, the background image keeps being on top of the scene (hiding the meshes).
I've tried a little test - when I've rendered them both with the same projection matrix the were
in the right order - the background image was behind the meshes.
These are the projection matrices and the Depth-Buffer 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);
I'm cleaning the buffers with:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
One last thing..
When I disable GL_DEPTH_TEST, the meshes are being drawn in front of the background image because the background is being called first..
I can't tell which, the Depth-Buffer or the Projection matrices, causing this problem..
The values of the matrices with screenWidth=960 and 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);
What am i doing wrong?
Amir.
Edit:
This how i'm drawing the images with the orthographic projection:
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);
and this is how I'm drawing the meshes with the frustum projection:
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);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果我理解正确的话,你想要做以下单独的事情:
“当我禁用 GL_DEPTH_TEST 时,网格将被绘制在背景图像前面,因为首先调用背景......” ->我认为您可以分别绘制全屏四边形和网格。所以 VBO 设置、矩阵、纹理等等都很好。只有第二点没有被注意到。
像往常一样清除新框架的所有内容。 Z-buffer 到处都是 1.0
绘制背景。你的颜色缓冲区没问题,但它很糟糕,因为 z 缓冲区将包含四边形的深度,假设为 0.5。因此,当您渲染网格时,您必须足够幸运,以便新的深度值小于 0.5,否则深度测试将失败。但我们可以做点什么:只需再次将 z 缓冲区清除为 1.0:
现在,像往常一样绘制另一个网格。 ModelViewProjection 矩阵已更改,但 OpenGL 不知道这一点:它只知道深度到处都是 1.0。因此,深度测试对于您的网格来说总是会成功。因此,您将看到网格体应在的位置,具有正确的 z 值,并且在其他位置都看到背景四边形。
在这里,您可以防止在绘制全屏四边形时更新深度值。
禁用深度缓冲区上的写入:
绘制背景。颜色缓冲区将正常,并且 z 缓冲区仍将在各处包含 1.0,如上面几行 glClear() 设置的那样。
现在重新启用深度缓冲区的写入:
绘制另一个网格。和以前一样,z-buffer在任何地方都将是1.0,就像你刚刚调用了glClear()一样,所以如果你的网格位于平截头体中(显然必须是),它的z将是,比如说,0.5,并且它会被绘制。
只需将背景绘制得远离相机,靠近远剪裁平面即可。 (即具有大的 Z 分量)。它的 z 分量将为 0.9999 或类似的值,就像以前一样,网格将渲染正常。
我真的真的无法解释得更详细。抱歉,如果还不清楚,我尝试以多种方式重新表述每个想法,但无能为力。
If I understand correctly, you want to do the following separate things :
"When I disable GL_DEPTH_TEST, the meshes are being drawn in front of the background image because the background is being called first.." -> I take it that you can draw both your fullscreen quad and our mesh separately. So VBO setup, matrices, textures and stuff are all good. It's only point #2 that misses.
Clear everything for a new frame, just as usual. Z-buffer will be 1.0 everywhere
Draw the background. Your color buffer is OK, but it suck because the z-buffer will contain the depth of your quad, let's say 0.5. So when you will render your mesh, you will have to be lucky enough so that the new depth values are smaller than 0.5, or the depth test will fail. But we can do something about it : simply clear the z-buffer again to 1.0 :
Now, draw the other mesh as usual. The ModelViewProjection matrix has changed, but OpenGL doesn't know that : all it know is that depth is 1.0 everywhere. So the depth test will always succeed for your mesh. You will thus see your mesh where it shoud be, with correct z-values, and the background quad everywhere else.
Here, you prevent depth values from beeing updated when the fullscreen quad is drawn.
Disable writes on the depth buffer :
Draw the background. Color buffer will be OK, and z-buffer will still contain 1.0 everywhere, as set by glClear() a few lines above.
Now re-enable writes on the depth buffer :
Draw the other mesh. As before, z-buffer will be 1.0 everywhere, just as if you had just called glClear(), so if your mesh is in the frustum (it obviously has to be), its z will be, say, 0.5, and it will be drawn.
Simply draw your background far away from the camera, near the far clipping plane. ( i.e with a big Z component ). Its z-component will be 0.9999 or something like that, and just as before, mesh will render allright.
I really, really can't explain in more details. Sorry if it's still not clear, I tried to reformulate each idea in several ways, can't do anything more.