OpenGL ES 学习教程(十二) DEPTH_TEST(深度缓冲测试)

来源:互联网 发布:河南评书下载软件 编辑:程序博客网 时间:2024/05/22 18:25

接触到3D,就一定会接触到深度这个概念,最直接的就是看Z轴,两个人在场景中,你的Z轴是1,我的Z轴是2,摄像机位于Z -10的位置,那么我的深度比你的大。

在OpenGL中,默认是没有开启深度检测的,也就是说,后绘制的物体覆盖先绘制的物体(颜色缓冲区中,先绘制的物体 被 后绘制的物体 覆盖)。

转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

来看代码例子:

//重写Render;virtual void render(){    glClearColor(0, 0, 0, 1.0);    glClear(GL_COLOR_BUFFER_BIT);        glViewport(0, 0, m_width, m_height);    {        //model;        glm::mat4 model = glm::mat4(1.0f);                //View        glm::mat4 view = glm::lookAt(glm::vec3(0, 0, -10.0f), glm::vec3(0, 0,0), glm::vec3(0, 1, 0));        //透视 注意近裁剪面 远裁剪面的值是相对于Camera Position的 这里Camera位于Z -10,那么近裁剪面是 0,远裁剪面是2.        glm::mat4 proj = glm::perspective(glm::radians(60.0f), 1.0f, 10.0f, 12.0f);        proj = proj*view*model;        m_program.begin();        {                        //红色            {                glm::vec4 pos[] =                {                    glm::vec4(-2.0f, -2.0f, 1.5f, 1.0f),                    glm::vec4(2.0f, -2.0f, 1.5f, 1.0f),                    glm::vec4(0.0f, 2.0f, 1.5f, 1.0f),                };                glm::vec4 color[] =                {                    glm::vec4(1, 0, 0, 1),                    glm::vec4(1, 0, 0, 1),                    glm::vec4(1, 0, 0, 1),                };                glUniformMatrix4fv(m_program.m_mvp, 1, false, &proj[0][0]);                glVertexAttribPointer(m_program.m_position, 4, GL_FLOAT, false, sizeof(glm::vec4), pos);                glVertexAttribPointer(m_program.m_color, 4, GL_FLOAT, false, sizeof(glm::vec4), color);                glDrawArrays(GL_TRIANGLES, 0, 3);            }            //黄色            {                glm::vec4 pos[] =                {                    glm::vec4(0.0f, -2.0f, 1.7f, 1.0f),                    glm::vec4(4.0f, -2.0f, 1.7f, 1.0f),                    glm::vec4(2.0f, 2.0f, 1.7f, 1.0f),                };                glm::vec4 color[] =                {                    glm::vec4(1, 1, 0, 1),                    glm::vec4(1, 1, 0, 1),                    glm::vec4(1, 1, 0, 1),                };                glUniformMatrix4fv(m_program.m_mvp, 1, false, &proj[0][0]);                glVertexAttribPointer(m_program.m_position, 4, GL_FLOAT, false, sizeof(glm::vec4), pos);                glVertexAttribPointer(m_program.m_color, 4, GL_FLOAT, false, sizeof(glm::vec4), color);                glDrawArrays(GL_TRIANGLES, 0, 3);            }        }        m_program.end();    }    eglSwapBuffers(m_EGLDisplay, m_EGLSurface);}

在上面的例子中,先绘制了一个红色的三角形,再绘制了一个黄色三角形。注意 到黄色三角形的 Z 轴,是比红色三角形  大的,所以理论上黄色三角形应该在红色三角形后面。

但是实际上


然而实际上黄色三角形却到了红色三角形前面。

这是因为 OpenGL中默认没有开启深度缓冲测试,就是说,后绘制的物体覆盖先绘制的物体(颜色缓冲区中,先绘制的物体 被 后绘制的物体 覆盖)。

所以这里红色三角形 被 后绘制的黄色三角形盖住了。


下面来启用 深度缓冲测试。

首先在创建窗口的时候请求一个深度缓冲区

bool initDevice(){const EGLint attribs[] ={EGL_SURFACE_TYPE, EGL_WINDOW_BIT,EGL_BLUE_SIZE, 8,EGL_GREEN_SIZE, 8,EGL_RED_SIZE, 8,EGL_ALPHA_SIZE,8,EGL_DEPTH_SIZE, 24, //请求深度缓冲区EGL_NONE};EGLint format(0);EGLintnumConfigs(0);EGLint  major;EGLint  minor;//! 1m_EGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);//! 2initeglInitialize(m_EGLDisplay, &major, &minor);//! 3eglChooseConfig(m_EGLDisplay, attribs, &m_EGLConfig, 1, &numConfigs);eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_NATIVE_VISUAL_ID, &format);//! 4 m_EGLSurface = eglCreateWindowSurface(m_EGLDisplay, m_EGLConfig, m_hWnd, NULL);//! 5EGLint attr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };m_EGLContext = eglCreateContext(m_EGLDisplay, m_EGLConfig, 0, attr);//! 6if (eglMakeCurrent(m_EGLDisplay, m_EGLSurface, m_EGLSurface, m_EGLContext) == EGL_FALSE){return false;}eglQuerySurface(m_EGLDisplay, m_EGLSurface, EGL_WIDTH, &m_width);eglQuerySurface(m_EGLDisplay, m_EGLSurface, EGL_HEIGHT, &m_height);//! windows apiSendMessage(m_hWnd, WM_SIZE, 0, 0);return  true;}

然后启用深度缓冲测试

转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

//重写初始化函数;virtual void onInit(){Light3dWinAPP::onInit();m_program.Initialize();glEnable(GL_DEPTH_TEST);glDepthFunc(GL_LESS); //基准设置为 1.0,那么GL_LESS 则深度小余 1.0 的通过测试}

glDepthFunc 用来修改深度比较运算符,参数枚举用来指定深度值比较函数。可能是 GL_LESS,GL_GREATER,GL_LEQUAL,GL_GEQUAL,GL_NOTEQUAL,GL_ALWAYS,GL_NEVER。

看英文就能看出来大概的意思,比如 GL_LESS 的意思就是说,比深度缓冲区中原来的深度值小,就通过测试。用新的值覆盖掉缓冲区中保存的值。深度值小,就是离摄像机近。


最后在绘制的时候,添加 glClearDepth

//重写Render;virtual void render(){glClearColor(0, 0, 0, 1.0);glClearDepthf(1.0f);//深度测试的基准,注意1.0代表从近裁剪面到远裁剪面 这一段范围!!并不是指Z轴的1个单位glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);glViewport(0, 0, m_width, m_height);............

glClearDepth(1.0f)

深度,是一个Normolized的值,范围是 0-1,对应Z轴是从近裁剪面到远裁剪面。

所以这里的 1.0f 指的是 ,深度缓冲区中默认值是远裁剪面。


启用深度缓冲测试后


当某些片段位于 近裁剪面与远裁剪面之外,就会被摄像机裁减掉。这是摄像机的功能。

m_program.begin();{{glm::vec4 pos[] ={glm::vec4(-2.0f, -2.0f, 1.5f, 1.0f),glm::vec4(2.0f, -2.0f, 1.5f, 1.0f),glm::vec4(0.0f, 2.0f, 2.5f, 1.0f), //这个点已经在远裁剪面之外了,所以被裁剪掉了。};............


红色三角形 底边深度比黄色三角形底边更小,所以红色三角形底边覆盖了黄色三角形底边。

红色三角形顶角深度比黄色三角形大,所以往上 是红色三角形被黄色三角形覆盖了。

而且由于红色三角形深度值大于1,也就是被远裁剪面裁剪了,所以上面缺了一个角。

转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn


示例代码工程下载:

http://pan.baidu.com/s/1eRJF8Im


0 0
原创粉丝点击