注意看,利用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. 源码深度解析 Handler 机制及应用

    本文以源码分析+实际应用的形式,详细讲解了 Handler 机制的原理,以及在开发中的使用场景和要注意的地方. 一.基本原理回顾 在 Android 开发中,Handler及相关衍生类的应用经常用到, ...

  2. 数字孪生 3D 风电场,智慧风电之陆上风电

    前言 "十四五"期间,在传统产业数字化升级和绿色改造领域.绿色低碳城镇化和现代城市建设领域.绿色低碳消费领域,和可再生能源或电力系统建设等领域,总投资可以达到近 45 万亿,平均每 ...

  3. java两个list取交集

    直接上代码 List<Integer> list1 = new ArrayList<>(); list1.add(1); list1.add(2); list1.add(3); ...

  4. Asp .Net Core 系列:集成 Ocelot+Nacos+Swagger+Cors实现网关、服务注册、服务发现

    目录 简介 什么是 Ocelot ? 什么是 Nacos ? 什么是 Swagger ? 什么是 Cors ? Asp .Net Core 集成 Ocelot 网关集成 Nacos 下游配置 Naco ...

  5. vant下拉加载更多,上拉刷新

    https://www.bilibili.com/video/BV1zq4y1p7ga?p=218 List 组件通过 loading 和 finished 两个变量控制加载状态,当组件滚动到底部时, ...

  6. paddlespeech on centos7

    概述 paddlespeech是百度飞桨平台的开源工具包,主要用于语音和音频的分析处理,其中包含多个可选模型,提供语音识别.语音合成.说话人验证.关键词识别.音频分类和语音翻译等功能. paddles ...

  7. 【FreeRTOS】内核查找最高优先级就绪任务

    查找最高优先级就绪任务 FreeRTOS\Source\tasks.c #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 ) /* If confi ...

  8. [转帖]聊聊字符串数据长度和nls_length_semantics参数

    字符串是我们设计数据库经常用到的类型,从传统的ASCII格式到UTF-8格式,不同应用需求对应不同的字符类型和长度配置.针对Oracle而言,最常用的类型无外乎char和varchar2两个基本类型. ...

  9. [转帖]docker exec 失败问题排查之旅

    https://plpan.github.io/docker-exec-%E5%A4%B1%E8%B4%A5%E9%97%AE%E9%A2%98%E6%8E%92%E6%9F%A5%E4%B9%8B% ...

  10. [转帖]DevOps & CI/CD 常见面试题汇总

    https://www.cnblogs.com/Dev0ps/p/15123168.html 什么是 DevOps答:用最简单的术语来说,DevOps 是产品开发过程中开发(Dev)和运营(Ops) ...