模板测试
片段着色器处理完之后,模板测试就开始执行了,它能丢弃一些片段,被保留下来的片段会进入到深度测试,深度测试会丢弃更多的片段。
模板测试中的模板值通常是八位的,因此每个片段/像素共有256种不同的模板值,这样我们能将这些模板值设置为我们链接的,然后在模板测试时根据这个模板值,我们就可以决定丢弃或保留它了。
使用模板缓冲,要遵守的原则:
- 开始模板缓冲写入;
- 渲染物体,更新模板值;
- 关闭模板缓冲写入;
- 渲染(其他)物体,这次基于模板缓冲内容丢弃特定的片段;
开启模板缓冲写入
glEnable(GL_STENCIL_TEST);
清空模板缓冲
glClear(GL_COLOR_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
设置位遮罩(Bitmask)
glStencilMask(0xFF);
glStencilMask(0x00);
模板函数
模板函数有两个作用:
1,何时模板测试通过或者测试失败;
2,在测试通过/失败时如何操作模板值;
分别对应两个函数:
1,glStencilFunc(GLenum func, GLint ref, GLuint Mask);
func: : 模板测试函数
ref: : 指定模板测试的引用值,模板缓冲的内容和这个值比较;
Mask:* : 指定一个遮罩,在模板测试对比引用值和储存的模板值前,对它们进行按位与(and)操作,初始设置为1。
2,glStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass);
sfail:模板测试失败将采取的动作;
dpfail:模板测试通过,深度测试失败将采取的动作;
*dppass:模板测试,深度测试都通过将采取的动作;
可以采取的动作:
操作 | 描述 |
---|---|
GL_KEEP | 保持现在的模板值 |
GL_ZERO | 将模板值设置为0 |
GL_REPLACE | 将模板值设置为glStencilFunc中设置的ref值 |
GL_INCR | 如果模板值不是最大值则+1 |
GL_INCR_WRAP | 与GL_INCR一样将模板值+1,如已是最大则设置为0 |
GL_DECR | 将模板值减1 |
GL_DRCR_WRAP | 与GL_DECR一样将模板值减1,如已是最小,则设置为0 |
GL_INVERT | Bitwise inverts the current stencil buffer value. |
应用
模板测试特别有用的一个功能是:物体轮廓(Object Outlining)。
物体轮廓就像它的名字所描述的那样,它能够给每个(或一个)物体创建一个有颜色的边。在策略游戏中当你打算选择一个单位的时候它特别有用。给物体加上轮廓的步骤如下:
1,在绘制物体前,把模板方程设置为GL_ALWAYS,用1更新物体将被渲染的片段。
2,渲染物体,写入模板缓冲。
3,关闭模板写入和深度测试。
4,每个物体放大一点点。
5,使用一个不同的片段着色器用来输出一个纯颜色。
6,再次绘制物体,但只是当它们的片段的模板值不为1时才进行。
7,开启模板写入和深度测试。
最终实现效果图如下:
![](https://img.haomeiwen.com/i10035186/ad9ef27fd06d9f92.png)
网友评论