高级OpenGL-模板测试

OpenGL-Stenciltest

1. 模板测试

模板缓冲在片段着色器处理完之后开始执行,被保留的片段则会继续进入深度测试。GLFW会自动帮助我们创建模板缓冲,但是我们应当关注窗口库的文档,检查它是否会帮助我们创建模板缓冲。

模板缓冲允许我们将模板缓冲设定成为一个特定的值,在渲染的时候修改模板缓冲的内容。在每一个渲染迭代中,读取这些值并决定丢弃还是保留某个片段。

形象点来讲的话,模板缓冲就像是印刷时的制版,每次制作好特定的模板,然后套用模板在屏幕上进行绘制。我们可以操作的就是什么时候采用模板与采用什么样子的模板,已经绘制的时候应当怎样取舍。

我们通过GL_STENCIL_TEST来开启模板测试

glEnable(GL_STENCIL_TEST);

并且我们也需要在每次迭代前清除模板缓冲

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

我们还可以设置位掩码,它会与将要写入缓冲的模板值进行与(AND)运算。默认位掩码所有位都是1。

glStencilMask(0xFF);	// 每一位写入模板缓冲时保持原样
glStencilMask(0x00);	// 每一位写入模板缓冲时变成0(禁用写入)

2.模板函数

我们可以通过glStencilFuncglStencilOp来配置模板测试

glStencilFunc(GLenum func, GLint ref, GLuint mask)其中共有三个参数

  • func: 模板测试函数。这个测试函数标志了模板值与标准值的判断条件,可用的选项类似深度缓冲:GL_NEVERGL_LESSGL_LEQUALGL_GREATERGL_GEQUALGL_EQUALGL_NOTEQUALGL_ALWAYS
  • ref: 模板测试的参考值。模板缓冲的内容会与这个值进行比较。
  • mask: 掩码。在测试之前会与模板值进行与(AND)运算,默认所有位均为1。

举个栗子:

glStencilFunc(GL_EQUAL, 1, 0xFF);

这会告诉OpenGL,当片段的模板值等于参考值1的时候,片段会通过测试从而进入下一步深度测试中,否则就会被丢弃。

glStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass)其中也是有三个参数

  • sfail: 模板测试失败时采取的动作。
  • dpfail: 模板测试通过,但深度测试失败时采取的动作。
  • dppass: 模板测试和深度测试都通过时采取的动作。
动作 内容
GL_KEEP 保持当前存储的模板值
GL_ZERO 将模板值设置为0
GL_REPLACE 将模板值设置为ref
GL_INCR 如果模板值小于最大值则将模板值加1
GL_INCR_WRAP GL_INCR且模板值超过最大值则归零
GL_DECR 如果模板值大于最小值则将模板值减1
GL_DECR_WRAP GL_DECR且模板值小于0则设置为最大值
GL_INVERT 按位翻转当前的模板缓冲值

默认的动作都是GL_KEEP,也就是不论测试结果如何模板缓冲都会被保留。因此通过使用glStencilFuncglStencilOp我们就可以精确地指定更新模板缓冲的时机与行为了。

3.物体轮廓

下面我们通过实践来更加深刻地体会模板缓冲,也就是为一个物体描出它的轮廓。

高级OpenGL-模板测试_第1张图片

首先我用文章中的方法为之前案例中Assimp导入的模型进行了描边,从效果可以看出,这种描边方式对于不规则边框的物体来说就有些差强人意了。我们可能需要进一步寻找更加合适的描边实现方式。

通过这个例子的实践,我个人对于模板测试的理解,就好像套版印刷一样,而模板缓冲就是我们的“版”,我们可以设置并开启模板测试,从而制出我们需要的“版”。然后设置模板缓冲为只读,借助“版”来实现一些特殊的视觉效果。

你可能感兴趣的:(OpenGL,学习笔记)