OpenGL ES 学习教程 DEPTH_TEST(深度缓冲测试)
Posted _Captain
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenGL ES 学习教程 DEPTH_TEST(深度缓冲测试)相关的知识,希望对你有一定的参考价值。
接触到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);
EGLint numConfigs(0);
EGLint major;
EGLint minor;
//! 1
m_EGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
//! 2init
eglInitialize(m_EGLDisplay, &major, &minor);
//! 3
eglChooseConfig(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);
//! 5
EGLint attr[] = EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE ;
m_EGLContext = eglCreateContext(m_EGLDisplay, m_EGLConfig, 0, attr);
//! 6
if (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 api
SendMessage(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
以上是关于OpenGL ES 学习教程 DEPTH_TEST(深度缓冲测试)的主要内容,如果未能解决你的问题,请参考以下文章
IOS – OpenGL ES 调节图像色彩替换 GPUImageFalseColorFilter
IOS – OPenGL ES 调节图像饱和度 GPUImageSaturationFilter
IOS – OpenGL ES 图像漩涡 GPUImageSwirlFilter