在写模板缓冲OpenGL相关的API时,看了半天帖子都没有搞清楚模板缓冲区到底是什么时候写入值的。
下面总结一下。
模板缓冲区的理解
模板测试
在OpenGL中,模板测试(Stencil Testing)是一种用于控制像素绘制的方式。它允许开发者根据模板缓冲区(Stencil Buffer)中的值来决定是否绘制某个像素。模板测试通常用于实现一些高级的图形效果,如阴影、反射、折射等。
模板缓冲区
我们怎么填充模板缓冲区?
如果我们想在模板缓冲区中将一块矩形区域填充为1,那们我需要“绘制一个矩形”,并进行以下操作。
glStencilFunc(GL_ALWAYS,1,0XFF);
glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE);
glStencilMask(0xFF)
通过将glStencilFunc的第一个参数设置为GL_ALWAYS,使得任意模板值都能通过测试,这样如果深度测试也通过的话,就会通过glStencilOp的第三个参数设置的GL_REPLACE将模板值都替换为glStencilFunc的第二个参数。这样一来,我们就达到了在规定区域中将模板值设置为1的目的。glStencilMask(0xFF)的作用是设置模板缓冲区的写入掩码。0xFF表示所有位都可以被写入。在这个例子中,0xFF表示所有位都可以被写入。
而矩形并不需要真正的绘制,它只是用来指定哪些像素有效,哪些无效。怎么做到这个矩形没有被真正的绘制呢?用的是下面这段代码来屏蔽颜色和深度缓存。
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,FL_FALSE);
glDepthMask(GL_FALSE);
glColorMask函数允许你指定哪些数据输入颜色缓存,4个参数分别对应RGBA值,这里我们将4个参数都置为GL_FALSE,意味着所有颜色数据都不会输入到颜色缓存中。而深度缓存需要另外调用glDepthMask并传入GL_FALSE参数来屏蔽深度值。这样我们矩形区域外的所有像素的颜色和深度都被屏蔽了,所以我们的绘制就不会影响到这些像素。
怎么应用模板缓冲区
由上面得到的模板缓冲区中已经有一个矩形区域被设置为1了,如下图所示。
那我们应该如何应用这个缓冲区呢?
如果我想只有在这个绘制的矩形范围内,能够被出图,也就是裁剪功能,那我们可以通过设置如下测试函数来进行绘制,并且记住要将之前禁用的深度和颜色绘制重新启用。
glStencilFunc(GL_EQUAL,1,0xFF);
但需要注意的是,此时无论我们想在屏幕上绘制什么,我们并不需要我们的模板缓冲区被更新了,所以我们需要将模板缓冲区写入的掩码设置为0,这样,我们对模板缓冲区的任何写入操作都会被屏幕。
glStencilMask(0x00);
模板缓冲区为什么需要更新?
由“我们怎么填充模板缓冲区?”这一节可以看出,更新模板缓冲区可以直接通过绘制来填充模板缓冲区。
一段简单的裁剪例子
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS,1,0XFF);
glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE);
glStencilMask(0xFF);
glDepthMask(GL_FALSE);
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,FL_FALSE);
glClear(GL_STENCIL_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES,0,6);
glStencilFunc(GL_EQUAL,1,0xFF);
glStencilMask(0x00);
glDepthMask(GL_TRUE);
glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
glDrawArrays(GL_TRIANGLES,6,3);