Opengl es 无法在OpenGL中的二维(正交)之上绘制三维(平截头体)

Opengl es 无法在OpenGL中的二维(正交)之上绘制三维(平截头体),opengl-es,opengl-es-2.0,orthographic,frustum,projection-matrix,Opengl Es,Opengl Es 2.0,Orthographic,Frustum,Projection Matrix,我正在尝试在背景图像(正交投影)上使用截锥投影渲染一些网格。无论我做什么,背景图像始终位于场景顶部(隐藏网格) 我尝试了一个小测试——当我用相同的投影矩阵渲染它们时 以正确的顺序-背景图像位于网格后面 以下是投影矩阵和深度缓冲区初始化: glEnable(GL_DEPTH_TEST); glClearDepthf( 1.0f ); glDepthFunc( GL_LEQUAL ); glDepthMask (GL_TRUE); EGLConfig eglconfig; EGLint const

我正在尝试在背景图像(正交投影)上使用截锥投影渲染一些网格。无论我做什么,背景图像始终位于场景顶部(隐藏网格)

我尝试了一个小测试——当我用相同的投影矩阵渲染它们时 以正确的顺序-背景图像位于网格后面

以下是投影矩阵和深度缓冲区初始化:

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_颜色_缓冲_位| GL_深度_缓冲_位)

最后一件事。。 当我禁用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);
这就是我用平截头体投影绘制网格的方法:

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的设置、矩阵、纹理等都很好。只有第二点没有提到

  • 解决方案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并不知道:它所知道的只是深度到处都是1.0。因此,网格的深度测试将始终成功。因此,您将看到网格应该位于的位置,具有正确的z值,并且在其他任何地方都可以看到背景四边形

  • 解决方案2
在这里,您可以防止在绘制全屏四边形时更新深度值

禁用深度缓冲区上的写入:

glDepthMask(GL_FALSE);
glDepthMask(GL_TRUE);
画背景。颜色缓冲区将正常,z缓冲区仍将处处包含1.0,正如上面几行glClear()所设置的

现在重新启用深度缓冲区上的写入:

glDepthMask(GL_FALSE);
glDepthMask(GL_TRUE);
绘制另一个网格。如前所述,z缓冲区在任何地方都将为1.0,就像刚才调用glClear()一样,因此如果网格位于平截头体中(显然必须如此),其z将为0.5,并且将被绘制

  • 解决方案3
只需在远离摄影机、靠近远剪裁平面的位置绘制背景。(即具有大的Z分量)。它的z分量将是0.9999或类似的值,和以前一样,mesh将正确渲染


我真的,真的无法解释更多的细节。很抱歉,如果仍然不清楚,我尝试用几种方法重新表述每个想法,但无能为力。

到目前为止,您只显示了初始值。但要知道出了什么问题,我需要查看实际的绘图代码。@datenwolf-我添加了绘图代码:)因为znear、zfar对于两个绘图过程都是相等的,并且在每个过程中都使用深度测试,您必须清除绘图过程之间的深度缓冲区=>请参见@Calvin602给出的答案的解决方案1,解决方案#3的性能应该稍好一些,因为它避免了一次昂贵的逐帧清除。但是,是的,这很简单。首先,谢谢你的评论。我真正的问题是我真的需要深度。。。现在这只是背景。。但很快就会有广告牌在网上。。这是我的侧边滚动地图引擎。你将获得所有3种方法的网格深度(否则z-buffer将无法正常工作,你会看到人工制品)。如果背景必须具有精确的深度,请选择解决方案3,或使用glClearDepth(浮点)。解决方案1和2不使用dept。。不管它是z,所有的东西都会画在上面。。解决方案3不起作用。请更新您的问题并准确解释您正在尝试做什么?因为解决方案1和2确实使用深度,我不理解你的问题了。解决方案3应该可以工作,您绘制全屏四元屏幕的代码是什么?