注意看,利用OpenGL的模板缓冲,可以轻松实现很多酷炫的效果。当然,它用起来也很简单。下面就跟着博主小编,一起来看看吧!

模板缓冲的使用

  假设有个大小为800x600的窗口,那么模板缓冲也是一个800x600的数组,每个值为一个字节,可以保存0x00~0xFF内的值,这就是模板缓冲的全部啦。

  之前介绍过深度测试,有了模板缓冲后,就可以启用模板测试。启用后,对于每一个待处理的点,只有通过模板测试后,才能绘制到窗口上。

  使用前,需要先启用模板测试:

glEnable(GL_STENCIL_TEST);

  

  对于模板缓冲,最基本的操作是将其全部清零:

glClear(GL_STENCIL_BUFFER_BIT);

  

  启用模板测试后,绘制物体到窗口的同时会写入模板缓冲。我们可以将某个值写入模板缓冲,但是这个值在写入前会与一个掩码进行逐位and运算,这个掩码的值可通过以下函数设置:

glStencilMask(GLuint mask);

最常用的掩码值是0x00和0xFF, 掩码的默认值为0xFF, 学过位运算的朋友都知道,0xFF不改变写入的值。

  

  写入模板的操作主要是通过以下函数指定:

glStencilFunc(GLenum func, GLint ref, GLuint mask);

模板缓冲中的值会与参考值ref执行某种运算,运算通过参数func指定,例如大于(GL_GREATER)、等于(GL_EQUAL)等等。如果比较的结果是true,则“通过了模板测试”。mask是一个掩码,用法和上面提到的基本相同。对于参数func,除了上面这些比较运算,还有两个另类的操作GL_ALWAYSGL_NEVER,从名字就可以看出,前者总是通过模板测试,后者总是无法通过模板测试。

  

  模板缓冲的写入还受到另一个函数的影响:

glStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass);

    sfail表示没有通过模板测试后应该做什么;

    dpfail表示模板测试通过,但深度测试没通过应该做什么;

    dppass表示模板和深度测试都通过后应该做什么。

以上描述中的“应该做什么”,其实是一个枚举值,常见的有GL_KEEP(保存当前值)、GL_REPLACE(替换为glStencilFunc中的参数ref)等等。这三个参数默认都是GL_KEEP, 即不修改模板缓冲的值。因此,如果想要写入模板缓冲,至少需要设置其中的某个参数。

以上函数中,深度测试与缓冲测试同时出现。我不太清楚这样设计的动机,不过从下面的两个例子可以看出,使用模板测试时,经常需要考虑深度缓冲。

  

  上面这些可能看上去还是让人云里雾里,下面来看两个使用模板测试的例子吧。

遮罩效果

  遮罩是一种常见的动画效果,例如射击游戏中的望远镜视角。下图展示了一红一绿两个正方形,其中绿色正方形在红色正方形的后面:

现在我想以红色正方形作为遮罩层,也就是说,只能看到被红色正方形遮挡的那一部分。

  启用模板测试后,确保模板测试可以写入模板缓冲:

glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);

这里设置为:只有模板和深度测试都通过后,才向模板缓冲写入值ref,所以最后一个参数设置为GL_REPLACE.

  初始时清空模板缓冲:

glClear(GL_STENCIL_BUFFER_BIT);

  在绘制红色正方形前,设置写入模板缓冲的条件:

glStencilFunc(GL_ALWAYS, 66, 0xFF);

这里,我们使用的是GL_ALWAYS, 即总是通过模板测试。因此,红色正方形在模板缓冲中的相应位置都会写入值66. (66是我随便设置的数字,我觉得这个数字还不错)。

  

  在绘制绿色正方形之前,先清空深度缓冲,否则这些被遮挡的绿色部分无法通过深度测试。

glClear(GL_DEPTH_BUFFER_BIT);

  

  现在,我们就可以根据模板缓冲来绘制啦!当前的模板缓冲中,红色正方形对应的位置被写入了66,我们只绘制模板缓冲中值为66的这部分区域:

glStencilFunc(GL_EQUAL, 66, 0xFF);

此函数表示,“在模板缓冲中对应位置为66”的像素点才能通过模板测试,最终被画出来。

  完成后,效果应该是下面这个样子:

  可以看到,只有通过红色正方形可以看到的部分被绘制出来。如果不希望出现左下角的红色部分,我能想到的简单解决方案是,在绘制红色正方形完成后,清空下颜色缓冲。

边缘绘制

  这是Learn OpenGL教程中的一个例子,用于绘制物体被选中时的的效果。

  首先启用模板缓冲,在绘制物体前,设置为“总是写入模板缓冲”,然后写入某个值,比如说写入1. 现在我们画一个机器人:

机器人画好后,机器人所占的这块区域在模板缓冲的对应位置都会写入1.

  最精彩的部分来了:我们把这个机器人稍微放大一些,然后仅在模板缓冲取值不为1的那些地方绘制像素点,写一个着色器,将这些点画成绿色。最后的效果如下:

上图的绿色部分就是模板缓冲中取值不为1的区域,里面的机器人所在的区域也就是模板缓冲中取值为1的区域。

小结

  模板缓冲其实很简单,可能我写得不是太清楚。就是这么简单的东西,能做出各种酷炫的视觉效果。如果有什么写得不对的地方,欢迎在评论区批评指正。我们下次,不见不散!

OpenGL的模板缓冲的更多相关文章

  1. windows API下的模板缓冲(stencil buffer)

    在windows API搭建的OpenGL窗口中使用模板缓冲,需要在像素格式描述表中设置stencil buffer位宽为8,这样窗口会自动生成stencil buffer,然后可以在opengl环境 ...

  2. Shader 模板缓冲和模板测试

    http://blog.sina.com.cn/s/blog_6e159df70102xa67.html 模板缓冲的概念 Unity官方的Shader文档根本没有提到这个玩意,这个概念也是看到了UGU ...

  3. 进一步使用 模板缓冲(stencil)

    最近做课题的时候需要计算一个 view(就是一次渲染得到的帧) 下的重叠像素个数(两个物体或更多的物体重叠). 最开始我的想法是渲染一个物体输出一张纹理,这样对比物体之间的纹理就知道重叠了.但是这样当 ...

  4. WebGL学习笔记(十五):模板缓冲

    可以用来干啥? 模板缓冲一般用来实现一些地面反射投影和类似镜子的特殊效果,如下: 开启模板缓冲 默认情况下,模板缓冲是关闭的,模板缓冲如果处于关闭状态,运行模板相关的代码不会报错,但是不会出现预期的效 ...

  5. 简单的opengl步骤模板

    以下内容整理自:https://learnopengl-cn.github.io/01%20Getting%20started/03%20Hello%20Window/ 一.初始化 glfw 并设置相 ...

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

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

  7. webgl 模板缓冲

    先思考个问题, 想实现遮罩怎么办? <!doctype html> <html> <head> <meta charset="utf-8" ...

  8. OpenGL ES 中的模板测试

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

  9. OpenGL核心技术之帧缓冲

    笔者介绍:姜雪伟.IT公司技术合伙人,IT高级讲师.CSDN社区专家.特邀编辑.畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D ...

  10. OpenGL(十四) 模板测试

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

随机推荐

  1. 深度 | 新兴软件研发范式崛起,云计算全面走向 Serverless 化

    11月3日,2022 杭州 · 云栖大会上,阿里云智能总裁张建锋表示,以云为核心的新型计算体系正在形成,软件研发范式正在发生新的变革,Serverless 是其中最重要的趋势之一,阿里云将坚定推进核心 ...

  2. vue学习笔记 十八、父子组件相互传递参数

    系列导航 vue学习笔记 一.环境搭建 vue学习笔记 二.环境搭建+项目创建 vue学习笔记 三.文件和目录结构 vue学习笔记 四.定义组件(组件基本结构) vue学习笔记 五.创建子组件实例 v ...

  3. 每天学五分钟 Liunx 0101 | 服务篇:创建进程

    创建子进程 上一节说过创建子进程的三种方式: 1. fork 复制进程:fork 会复制当前进程的副本,产生一个新的子进程,父子进程是完全独立的两个进程,他们掌握的资源(环境变量和普通变量)是一样的. ...

  4. c#(nanoframework)安装单片机环境;如何使用c#写类似于c的单片机驱动

    .NET nanoFramework 安装教程 准备材料​ esp32单片机(支持wifi蓝牙) 安卓数据线(需要支持传输) 注意!请先安装esp32驱动程序​ ESP32驱动链接 安装 .NET n ...

  5. [转帖]Kafka中offsets.retention.minutes和log.retention.minutes之间的区别

    https://www.cnblogs.com/lestatzhang/p/10771115.html 前言 在Kafka中,我们可能会发现两个与retention相关的配置: log.retenti ...

  6. [转帖]datax安装+配置+使用文档

    1 DataX离线同步工具DataX3.0介绍 DataX 是阿里巴巴集团内被广泛使用的离线数据同步工具/平台,实现包括 MySQL.Oracle.SqlServer.Postgre.HDFS.Hiv ...

  7. [转帖]Linux下AWK、SED、GREP、FIND命令详解

    https://www.jianshu.com/p/d54e0359db01 AWK AWK是一个优良的文本处理工具,Linux和Unix环境中现有的功能最强大的数据处理引擎之一. 语法 awk [选 ...

  8. Python学习之二:不同数据库相同表是否相同的比较方法

    摘要 昨天学习了使用python进行数据库主键异常的查看. 当时想我们有跨数据库的数据同步场景. 对应的我可以对不同数据库的相同表的核心字段进行对比. 这样的话能够极大的提高工作效率. 我之前写过很长 ...

  9. Nginx与Tomcat作为前端服务器的性能比较

    Nginx与Tomcat作为前端服务器的性能比较 摘要 最近总遇到使用tomcat还是使用nginx进行前端文件访问的争论 想着出差周末在酒店, 可以自己进行一下简单的测试. 希望能够对未来的工作进行 ...

  10. [转帖]Systemd 指令

    一.由来 历史上,Linux 的启动一直采用init进程. 下面的命令用来启动服务. $ sudo /etc/init.d/apache2 start # 或者 $ service apache2 s ...