fail模板测试未通过时该如何变化;zfail表示模板测试通过,但深度测试未通过时该如何变化;zpass表示模板测试和深度测试或者未执行深度测试均通过时该如何变化
也就是说对模板缓冲区有三种操作方式:分别是:
1. 模板缓冲区测试失败了:那么执行glStencilOp中第一个参数fail的操作方式;
2.模板缓冲区测试通过了:那么执行glStencilOp中第二个参数zfail的操作方式;
3.模板缓冲区测试通过了:那么执行glStencilOp中第三个参数zpass的操作方式;
注意三者的共同点都是对模板缓冲区进行操作。
如果模板缓冲区测试失败了,那么对颜色缓冲区就不会写入任何值。利用这个特点,我们可以如下操作:
// 设置模板缓冲区测试失败,后续的绘制操作只会在模板缓冲区中进行
glStencilFunc(GL_NEVER, 0x0, 0x0);
glStencilOp(GL_INCR, GL_INCR, GL_INCR);
//绘制模板对象
draw_template_object()
//接着在非模板对象的缓冲区绘制,这样就可以把模板部分空出来,有种被模板楼空的感觉
glStencilFunc(GL_NOTEQUAL, 0x1, 0x1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
在这里我想通过这样一个例子来说明一下:
#include <math.h>
#include <iostream>
#include <assert.h>
#include <GL/glut.h>
#pragma comment(lib, "glut32.lib")
// #include <GL/glew.h>
// #pragma comment(lib, "glew32.lib")
void init()
{ glClearColor(0.0, 0.0, 1.0, 0.0);
glClearStencil(0);
glEnable(GL_STENCIL_TEST);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0, 0.0, -20.0);
glStencilFunc(GL_ALWAYS, 0, 0x00);
//glStencilFunc(GL_NEVER, 0x0, 0x0);
//glStencilOp(GL_INCR, GL_INCR, GL_INCR);//
glColor3f(1.0f, 1.0f, 1.0f);
float dRadius = 5.0 * (sqrt(2.0) / 2.0);
glBegin(GL_LINE_STRIP);
for (float dAngel = 0; dAngel < 380.0; dAngel += 0.1)
{
glVertex2d(dRadius * cos(dAngel), dRadius * sin(dAngel));
dRadius *= 1.003;
}
glEnd();
//glStencilFunc(GL_NOTEQUAL,0x1,0x1);
//glStencilOp(GL_INCR,GL_INCR,GL_INCR);//
glColor3f(1.0f, 0.0f, 0.0f);
glRectf(-5, -5, 5, 5);
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
float aspect = (w * 1.0) / h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, aspect, 1, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_STENCIL);
glutInitWindowPosition(200,200);
glutInitWindowSize(600,600);
glutCreateWindow(argv[0]);
// assert(GLEW_NO_ERROR == glewInit());
init();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
结果如下:
加入模板控制之后的结果:
#include <math.h>
#include <iostream>
#include <assert.h>
#include <GL/glut.h>
#pragma comment(lib, "glut32.lib")
// #include <GL/glew.h>
// #pragma comment(lib, "glew32.lib")
void init()
{
glClearColor(0.0, 0.0, 1.0, 0.0);
glClearStencil(0);
glEnable(GL_STENCIL_TEST);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // 1
glLoadIdentity();
glTranslatef(0.0, 0.0, -20.0);
//glStencilFunc(GL_ALWAYS, 0, 0x00);
glStencilFunc(GL_NEVER, 0x0, 0x0); // 2
glStencilOp(GL_INCR, GL_INCR,GL_INCR);// 3
glColor3f(1.0f, 1.0f, 1.0f);
float dRadius = 5.0 * (sqrt(2.0) / 2.0);
glBegin(GL_LINE_STRIP);
for (float dAngel = 0; dAngel < 380.0; dAngel += 0.1)
{
glVertex2d(dRadius * cos(dAngel), dRadius * sin(dAngel));
dRadius *= 1.003;
}
glEnd();
glStencilFunc(GL_NOTEQUAL, 0x1, 0x1); // 4
glStencilOp(GL_INCR, GL_INCR, GL_INCR);// 5
glColor3f(1.0f, 0.0f, 0.0f);
glRectf(-5.0, -5.0, 5.0, 5.0);
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
float aspect = (w * 1.0) / h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, aspect, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_STENCIL);
glutInitWindowPosition(200, 200);
glutInitWindowSize(600, 600);
glutCreateWindow(argv[0]);
// assert(GLEW_NO_ERROR == glewInit());
init();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
运行结果如下:
当执行到1处,3个缓冲区都被清空
颜色缓冲区:每个像素点颜色都是蓝色
深度缓冲区:每个像素点深度都是1.0(注:执行
glClear后会使深度缓冲区中的值恢复成默认值1
)
模板缓冲区:每个像素点模板值都是0
执行到2,3处,模板测试条件是从不通过测试,且不通过测试结果后使模板值加1
接着应用模板测试进行绘制一组点,由于模板测试条件是从不通过测试,所以颜色缓冲区值不会变化,
但是绘制的点对应的像素点的模板值变为1,此时
颜色缓冲区:每个像素点颜色都是蓝色
深度缓冲区:每个像素点深度都是1.0
模板缓冲区:点数组对应的模板值是1,其他区域像素点的模板值还是0
执行到4,5处,模板测试条件是模板值不等于1则通过测试,且不通过测试结果是模板值加1
接着应用刚才的模板测试进行绘制一个(-5,-5,5,5)的矩形,在这个矩形区域内,
像素点的模板值分为2种,值为1的是上一步点数组中的像素点。值为0的是 上一步非点数组中的像素点。
根据
那个模板测试条件,模板值为0的像素点通过测试,通过测试的像素点就用绘制目标
(这里指绘制的红色矩形)
的 颜色,即通过测试的像素点可以进行替换颜色缓冲区的值(替换成红色),
模板值为1的像素点不能通过测 试,因此不能改变颜色缓冲区的值,就用颜色缓冲区中原来的颜色即蓝色。
故:
颜色缓冲区:(-5,-5,5,5)区域内 模板值为0的像素点为红色,其他区域都为蓝色
深度缓冲区:每个像素点深度都是1.0
模板缓冲区:点数组对应的模板值是1,其他区域像素点的模板值还是0
本文参考:
http://www.cnblogs.com/dragon2012/p/3757790.html
http://blog.csdn.net/csxiaoshui/article/details/23457273
http://blog.csdn.net/augusdi/article/details/20456923