启用模板测试时,OpenGL会在内存中开辟一块空间作为模板缓冲区,里边保存了每个像素的“模板值”,模板测试的过程就是把每一个像素的模板值与一个设定的模板参考值进行比较,符合设定条件的通过测试,不符合条件的则不会绘制。

glClearStencil函数用来指定模板值复位后的初始值,跟使用glClearColor函数指定复位后画板的颜色一样。

glStencilFunc函数用来设置模板测试条件。第一个是模板测试条件,第二个是指定的当前模板的测试值,程序会使用改值与参考模板值进行比较,第三个是mask位,设置后,只会比较mask中二进制位位1的位。

glStencilOp (GLenum fail, GLenum zfail, GLenum zpass)用来设置模板值根据模板测试结果和深度测试结果的结果如何变化。

第一个参数表示模板测试未通过时该如何变化,第二个参数表示模板测试通过,但深度测试未通过时该如何变化,第三个参数表示模板测试和深度测试均通过时该如何变化。这种模板的变换可以是:

  • GL_KEEP(不改变,这也是默认值)
  • GL_ZERO(回零)
  • GL_REPLACE(使用测试条件中的设定值来代替当前模板值)
  • GL_INCR(增加1,但如果已经是最大值,则保持不变)
  • GL_INCR_WRAP(增加1,但如果已经是最大值,则从零重新开始)
  • GL_DECR(减少1,但如果已经是零,则保持不变)
  • GL_DECR_WRAP(减少1,但如果已经是零,则重新设置为最大值)
  • GL_INVERT(按位取反)

另外程序中用到了glPushMatrix和glPopMatrix两个函数,glPushMatrix函数将当前矩阵压入堆栈,使得之后的操作不受之前矩阵变换的影响,都是相对于原始的世界坐标系进行操作。
glPopMatrix将与之最近的一个glPushMatrix压入堆栈的矩阵取出,使得之前的矩阵变换对其后的运算有效。这两个函数的配合使用可以使得两者之间的矩阵操作不受之前生成的变换矩阵的影响,并且两者之间的矩阵操作也不会对主体的矩阵变换产生影响。

以下是使用模板测试功能,实现平面镜功能,镜子之外的物体不会绘制:

#define WindowWidth   400
#define WindowHeight 400
#define WindowTitle "OpenGL模板测试"
#include <gl/glut.h> GLfloat angle = 0.0f; void draw_sphere()
{
// 设置光源
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
{
GLfloat
pos[] = {5.0f, 5.0f, 0.0f, 1.0f},
ambient[] = {0.0f, 0.0f, 1.0f, 1.0f};
glLightfv(GL_LIGHT0, GL_POSITION, pos);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
} // 绘制一个球体
glPushMatrix();
glTranslatef(0, 0, 2);
glutSolidSphere(0.8, 20, 20);
glPopMatrix();
} void display(void)
{
// 清除屏幕
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 设置观察点
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, 1, 5, 25);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(5, 0, 6.5, 0, 0, 0, 0, 1, 0); glRotatef(angle,0,1,0); glEnable(GL_DEPTH_TEST); // 绘制球体
glDisable(GL_STENCIL_TEST);
draw_sphere(); // 绘制一个平面镜。在绘制的同时注意设置模板缓冲。
// 另外,为了保证平面镜之后的镜像能够正确绘制,在绘制平面镜时需要将深度缓冲区设置为只读的。
// 在绘制时暂时关闭光照效果
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glEnable(GL_STENCIL_TEST); glDisable(GL_LIGHTING);
glColor3f(0.5f, 0.5f, 0.5f);
glDepthMask(GL_FALSE);
glRectf(-2.0f, -2.0f, 1.6f, 1.6f);
glDepthMask(GL_TRUE); // 绘制一个与先前球体关于平面镜对称的球体,注意光源的位置也要发生对称改变
// 因为平面镜是在X轴和Y轴所确定的平面,所以只要Z坐标取反即可实现对称
// 为了保证球体的绘制范围被限制在平面镜内部,使用模板测试
glStencilFunc(GL_EQUAL, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glScalef(1.0f, 1.0f, -1.0f);
draw_sphere(); // 交换缓冲
glutSwapBuffers();
} void myIdle(void)
{
angle+=0.1f;
if( angle >= 360.0f )
angle = 0.0f;
display();
} int main(int argc, char* argv[])
{
// GLUT初始化
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100, 100);
glutInitWindowSize(WindowWidth, WindowHeight);
glutCreateWindow(WindowTitle);
glutDisplayFunc(&display);
glutIdleFunc(&myIdle);
// 开始显示
glutMainLoop();
return 0;
}

运行截图:
    

  

OpenGL(十四) 模板测试的更多相关文章

  1. opengl学习-利用模板测试勾画物体轮廓中出现的一个问题

    我在学习OpenGL模板测试勾画物体轮廓的时候,出现了这个问题: 这个出现的原因就是,改变摄像机的时候,每次绘制,上次绘制中模板缓冲区的数据没有清除的原因.也就是在while循环开始的时候,glCle ...

  2. NeHe OpenGL教程 第四十四课:3D光晕

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  3. NeHe OpenGL教程 第二十四课:扩展

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  4. Android OpenGL ES(十四)gl10方法解析

    Android 支持 OpenGL 列表 1.GL 2.GL 10 3.GL 10 EXT 4.GL 11 5.GL 11 EXT 6.GL 11 ExtensionPack 我们将使用 GL10 这 ...

  5. OpenGL ES 中的模板测试

    模板测试的主要功能是丢弃一部分片元,相对于深度检测来说,模板测试提出的片元数量相对较少.模板测试发生在剪裁测试之后,深度测试之前. 使用模板测试时很重要的代码提示: 1.glClear( GL_STE ...

  6. Kali Linux Web 渗透测试视频教程—第十四课-arp欺骗、嗅探、dns欺骗、session劫持

    Kali Linux Web 渗透测试视频教程—第十四课-arp欺骗.嗅探.dns欺骗.session劫持 文/玄魂 目录 Kali Linux Web 渗透测试—第十四课-arp欺骗.嗅探.dns欺 ...

  7. NeHe OpenGL教程 第三十四课:地形

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  8. NeHe OpenGL教程 第十四课:图形字体

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  9. OpenGL利用模板测试实现不规则裁剪

    本文是原创文章,如需转载,请注明文章出处 在游戏开发中,经常会有这样的需求:给定一张64x64的卡牌素材,要求只显示以图片中心为圆点.直径为64的圆形区域,这就要用到模板测试来进行不规则裁剪. 实现不 ...

随机推荐

  1. Delphi的指针(有图,很清楚)

    Pointers are like jumps, leading wildly from one part of the data structure to another. Their introd ...

  2. struts2-token防止重复提交解决办法

    1.配置struts.xml全局防重复提交拦截器栈: <struts> <package name="module" extends="struts-d ...

  3. tplink-如何远程WEB管理路由器?

    http://service.tp-link.com.cn/detail_article_185.html 如何远程WEB管理路由器? 新版tplink怎么远程Web管理? https://www.1 ...

  4. HTTPS和SSL/TLS协议

    要说清楚 HTTPS 协议的实现原理,至少需要如下几个背景知识.1. 大致了解几个基本术语(HTTPS.SSL.TLS)的含义2. 大致了解 HTTP 和 TCP 的关系(尤其是“短连接”VS“长连接 ...

  5. Xshell Update

    http://blog.netsarang.com/1629/xshell-update-5-0-1332/ Xshell Update (5.0.1332) By Alan Kim Thursday ...

  6. java 线程排查问题流程

    1. 通过top命令查看当前系统CPU使用情况,定位CPU使用率超过100%的进程ID:2. 通过ps aux | grep PID命令进一步确定具体的线程信息:3. 通过ps -mp pid -o ...

  7. AE属性表操作

    转自chanyinhelv原文AE属性表操作 实现的操作包括:1.打开属性表:2.编辑属性表:3.增加属性列:4.数据排序:5.字段计算…… 嗯,实现的功能目前就这些吧,后续还会继续跟进,还望大家多多 ...

  8. [Ramda] Refactor to Point Free Functions with Ramda using compose and converge

    In this lesson we'll take some existing code and refactor it using some functions from the Ramda lib ...

  9. TensorFlow 学习(八)—— 梯度计算(gradient computation)

    maxpooling 的 max 函数关于某变量的偏导也是分段的,关于它就是 1,不关于它就是 0: BP 是反向传播求关于参数的偏导,SGD 则是梯度更新,是优化算法: 1. 一个实例 relu = ...

  10. NYOJ 1076 计划数(公式 要么 递归)

    方案数量 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描写叙述 给出一个N*M的棋盘.左下角坐标是(0.0).右上角坐标是(N,M),规定每次仅仅能向上或者向右走.问从左下 ...