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