模板缓冲测试,是指 将模版缓冲区中的值 与 一个参考值 进行比较,根据比较的结果,来对缓冲区中的值进行修改。进而决定该片段是否有效。
在应用中的体现就比如:Unity中的Mask 。
大致的工作流程:
1、第一次Draw的时候,将所有的片段都设置为不通过模版测试。然后修改模版缓冲区的值,比如+1.
2、第二次Draw的时候,给定一个值 与 模版缓冲区中的值进行比较,比如用 1 与模版缓冲区中的值进行比较 。 因为第一步中,已经+1,所以模版缓冲区中值已经是1,然后用相等 作为条件判定 模版测试通过。那么这个片段就可以绘制。
3、这样做的最终效果是,只有第一次绘制的区域,第二次绘制才可以显示。就如同Unity中的Mask,用一张图,Mask掉第二张图。
转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
在不使用模版测试的情况下,画了两个三角形。
首先 就如同深度测试一样,也要申请模版缓冲区。
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_STENCIL_SIZE, 8,//请求模版缓冲区 EGL_NONE }; EGLint format(0); EGLint numConfigs(0); EGLint major; EGLint minor; //! 1 m_EGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); ...... }
然后要开启模版测试
//重写初始化函数; virtual void onInit() { Light3dWinAPP::onInit(); m_program.Initialize(); glEnable(GL_STENCIL_TEST);//开启模版测试 glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); //基准设置为 1.0,那么GL_LESS 则深度小余 1.0 的通过测试 }
然后要设置默认模版值
//重写Render; virtual void render() { glClearColor(0, 0, 0, 1.0); glClearDepthf(1.0f);//深度测试的基准,注意1.0代表从近裁剪面到远裁剪面 这一段范围!!并不是指Z轴的1个单位 glClearStencil(0); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT |GL_STENCIL_BUFFER_BIT);
转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
然后在第一次绘制的时候,指定所有的都不通过模版测试,并且模版值 +1 。
m_program.begin(); { glStencilFunc(GL_NEVER, 0x0, 0xFF);//第一次绘制,通通不通过模版测试。 glStencilOp(GL_INCR, GL_INCR, GL_INCR);//第一次绘制的像素的模版值 0+1 = 1
然后在第二次绘制的时候,比较深度缓冲区中的值,值为 1 的通过测试。
{ glStencilFunc(GL_EQUAL, 0x1, 0xFF);//等于1 通过测试 ,就是上次绘制的图 的范围 才通过测试。 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);//没有通过测试的,保留原来的,也就是保留上一次的值。 glm::vec4 pos[] = { glm::vec4(0.0f, -2.0f, 1.5f, 1.0f), glm::vec4(4.0f, -2.0f, 1.5f, 1.0f), glm::vec4(2.0f, 2.0f, 1.5f, 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); }
这样我们得到的效果就是Mask的效果,只有第一次绘制的范围里,才能显示第二次绘制。
如果将比较修改为 不等于 1 的通过测试,那么效果就是第一次绘制的区域被抹除掉。
{ glStencilFunc(GL_EQUAL, 0x1, 0xFF);//等于1 通过测试 ,就是上次绘制的图 的范围 才通过测试。 glStencilFunc(GL_NOTEQUAL, 0x1, 0xFF);//不等于1 通过测试 就是除了上次绘制的图案之外的像素通过测试,所以上次绘制的像素之外的像素才可以进行第二幅图的绘制。 //glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);//没有通过测试的,保留原来的,也就是保留上一次的值。 glm::vec4 pos[] = { glm::vec4(0.0f, -2.0f, 1.5f, 1.0f), glm::vec4(4.0f, -2.0f, 1.5f, 1.0f), glm::vec4(2.0f, 2.0f, 1.5f, 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); }
转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
示例项目下载:
链接: http://pan.baidu.com/s/1mhMlVAg 密码: 77cg
时间: 2024-11-03 00:44:16