QT之OpenGL模板测试
- 1. 概述
- 2. 使用步骤及函数介绍
- 3. Demo
- 4. 参考
1. 概述
当片段着色器处理完一个片段之后,模板测试(Stencil Test)
会开始执行,和深度测试一样,它可能会丢弃片段。被保留下来的片段会进入深度测试。
一个模板缓冲中,(通常)每个模板值(Stencil Value)
是8位的。所以每个像素/片段一共能有256种不同的模板值。我们可以将这些模板值设置为我们想要的值,然后当某一个片段有某一个模板值的时候,我们就可以选择丢弃或是保留这个片段了。
模板缓冲示意图:
模板缓冲中1
的部分最后会被渲染出来,最终效果为一个回
字
2. 使用步骤及函数介绍
- 开启模板缓冲
glEnable(GL_STENCIL_TEST);
- 每一帧时清空模板缓冲
// GL_STENCIL_BUFFER_BIT 这个就表示要清除模板缓冲
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- 设置模板缓冲掩码
// 这里的掩码是表示允不允许向模板缓冲中写入数据
glStencilMask(0xFF); // 允许所有位写入
glStencilMask(0x00); // 不允许所有位写入
- 模板函数
/*
这个函数仅仅告诉OpenGL应该对模板缓冲中的内容做什么行为的操作,而不是应该如何更新缓冲
func:指定具体的行为 GL_NEVER、GL_LESS、GL_LEQUAL、GL_GREATER、GL_GEQUAL、GL_EQUAL、GL_NOTEQUAL和GL_ALWAYS
ref:表示func行为的参考值,如GL_EQUAL 则表示模板缓冲中的值等于 ref 时进行绘制,否则丢弃
mask:设置屏蔽位的,它会将ref值和模板缓冲中的值进行与运算后再使其比较,默认为0xFF
*/
glStencilFunc(GLenum func, GLint ref, GLuint mask)
/*
这个函数则指定应该如何更新模板缓冲的值,默认情况下均为 GL_KEEP
sfail:模板测试失败时应该如何更新缓冲区
dpfail:模板测试通过时应该如何更新缓冲区
dppass:模板测试和深度测试都通过时采取的行为
参数具体可以设定的值:
GL_KEEP 保持当前储存的模板值
GL_ZERO 将模板值设置为0
GL_REPLACE 将模板值设置为glStencilFunc函数设置的ref值
GL_INCR 如果模板值小于最大值则将模板值加1
GL_INCR_WRAP 与GL_INCR一样,但如果模板值超过了最大值则归零
GL_DECR 如果模板值大于最小值则将模板值减1
GL_DECR_WRAP 与GL_DECR一样,但如果模板值小于0则将其设置为最大值
GL_INVERT 按位翻转当前的模板缓冲值
*/
glStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass)
3. Demo
Demo中模仿OpenGL中的模型增加外边框的操作,核心步骤:
- 开启模板测试
glEnable(GL_STENCIL_TEST);
- 指定如何更新模板缓冲区的值
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
- 每帧情况模板测试缓冲并设置缓冲只读
// 使用 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // 不允许向模板缓冲区写入值 glStencilMask(0x00);
- 第一次绘制模型前,设置对缓冲区进行的操作
// 告诉OpenGL应该对模板缓冲中所有片段进行绘制,同时在通过模板测试及深度测试后模板缓冲区的内容会被替换成1(被替换的操作是由glStencilOp指定的,替换的值则是由glStencilFunc给定) glStencilFunc(GL_ALWAYS, 1, 0xFF); // 允许向模板缓冲区写入值 glStencilMask(0xFF);
- 指定第二次绘制时对缓冲区的操作
// 绘制不等于1的区域,由于第二次会模型会被放大,所以被放大的那一部分会被绘制 glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
模板测试Demo
4. 参考
- https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/02%20Stencil%20testing/