(自用)learnOpenGL学习总结-高级OpenGL-模板测试


模板测试

模板测试简单来说就是一个mask,根据你的mask来保留或者丢弃片段。

那么可以用来显示什么功能呢?剪切,镂空、透明度等操作。

和深度缓冲的关系是: 先片段着色器,然后进入深度测试,最后加入模板测试。模板测试是根据又一个缓冲来进行的,它叫做模板缓冲(Stencil Buffer),我们可以在渲染的时候更新它来获得一些很有意思的效果。

具体流程为:

  • 启用模板缓冲
  • 渲染物体, loop中更新模板内容
  •  禁用模板缓冲的写入
  • 渲染其他物体,根据模板缓冲的内容丢弃特定的片段

所以,通过使用模板缓冲,我们可以根据场景中已绘制的其它物体的片段,来决定是否丢弃特定的片段。

这段话很有意思,其他物体的片段可以用来下一次的模板。

和深度一样,都需要先开启,然后再每次迭代前清除

glEnable(GL_STENCIL_TEST);
...
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);



模板函数

和深度函数一样,我们也可以自定义控制模板测试。

但是这个函数只描述了模板缓冲内容如何变化,还需要知道如何更新缓冲

实例-物体轮廓

会通过模板测试来给物体周围加上一圈色带。就像是游戏中选中一个单位之后那个单位会高亮标出一样。步骤如下:

思路很简单,这个过程将每个物体的片段的模板缓冲设置为1,当我们想要绘制边框的时候,我们主要绘制放大版本的物体中模板测试通过的部分,也就是物体的边框的位置。我们主要使用模板缓冲丢弃了放大版本中属于原物体片段的部分。

首先重新定义一个片段着色器,用来画边框,直接输出一个颜色就好。

#version 330 core									out vec4 FragColor;								   
void main(){				FragColor = vec4(0.04, 0.28, 0.26, 1.0);
}

接下来我先按照教程的思路来做,然后我自己再多测试测试其他情况。

我现在只给箱子加上边框,我不想给机器人加边框。所有我应该先画机器人再画箱子。第一遍画正常的箱子,并写入模板缓冲,然后画放大的箱子,并丢弃覆盖了之前箱子的那些片段。

首先开启模板测试

glEnable(GL_STENCIL_TEST);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);

最后一个gl_replace,表示当深度和模板测试都通过的时候,那么我们希望将储存的模板值设置为参考值,参考值能够通过glStencilFunc来设置,我们之后会设置为1。

先来看下对于箱子如何操作。

				glStencilFunc(GL_ALWAYS, 1, 0xFF); // 更新模板缓冲函数,所有的片段都要写入模板glStencilMask(0xFF); // 启用模板缓冲写入//正常绘制十个正方体,而后记录模板值cube.DrawArray(myMaterial->shader, myMaterial->diffuse, myMaterial->specular, myMaterial->emission);//现在模板缓冲在箱子被绘制的地方都更新为1了,我们将要绘制放大的箱子,也就是绘制边框glStencilFunc(GL_NOTEQUAL, 1, 0xFF);glStencilMask(0x00); // 禁止模板缓冲的写入glDisable(GL_DEPTH_TEST);border->use();//Set Model matrixmodelMat = glm::translate(glm::mat4(1.0f), cubePositions[i - 1]);float angle = 20.0f * (i - 1);modelMat = glm::rotate(modelMat, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));modelMat = glm::scale(modelMat, glm::vec3(1.2, 1.2, 1.2));glUniformMatrix4fv(glGetUniformLocation(border->ID, "modelMat"), 1, GL_FALSE, glm::value_ptr(modelMat));glUniformMatrix4fv(glGetUniformLocation(border->ID, "viewMat"), 1, GL_FALSE, glm::value_ptr(viewMat));glUniformMatrix4fv(glGetUniformLocation(border->ID, "projMat"), 1, GL_FALSE, glm::value_ptr(projMat));//因为之前设置了GL_NOTEQUAL,它会保证我们只绘制箱子上模板值不为1的部分cube.DrawArray(border, 1, 1, 1);glStencilMask(0xFF);glEnable(GL_DEPTH_TEST);

先通过glstenciFunc和glstenciMask来更新模板缓冲和启用模板缓存写入。

然后再draw的过程中,所有箱子绘制的地方都会被设置为1。其他地方都是0.

然后就是要画变大的箱子,但是这里就不能再写入了,而是比较

可以看到在第二次的时候模板函数为gl_notequal 保证只绘制箱子模板值不为1的地方。可以想象一个场景,在之前的模板缓冲中,有箱子的地方都为1,其他都是0.然后现在画一个大一点的箱子上去。有1的地方就不画了,只在不为1的地方画,也就是边框之外的地方。

而且 可以看到这里再画第二次的时候禁止了深度测试

现在来分析一下为什么会有这样的画面。

在机器人后面的那个箱子为什么露出来的部分是原来的,被机器人盖住的地方以及边框部分是纯色?为什么边框是连在一起的?

有这样的一个时间轴,在画的过程中依次进行了机器人、箱子、放大箱子的绘制。

其中,深度测试覆盖机器人和箱子,模板测试覆盖箱子和放大的箱子。

ok,现在按照时间轴走下去吧。

  • 首先画了一个机器人,因为有深度测试,所以更新了深度缓冲。又因为glStencilMask(0x00); 保证我们在绘制机器人的时候不会更新模板缓冲。
  • 现在轮到画箱子了,并启用了模板缓冲写入。所以在画箱子的过程中所有画着箱子的地方模板为1,其他为0.(但是因为深度测试,被遮挡的地方没有画箱子,也就是被遮挡的地方模板缓冲为0
  • 最后就是画放大的箱子。而且这时候是关闭了深度测试,也就是说 现在画的纯色是在最上面一层的。那么画在什么地方呢,画在放大的箱子覆盖的地方中模板缓冲为0的地方。

还记得之前的glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);,这个表示的意思是只有在深度和模板都开启的情况下去吧储存的模板值设置为参考值。

这也就解释了为什么箱子被盖住的地方会被画上纯色了。又因为没有了深度,纯色色块是连在一起的,没有前后之分。

一些测试

现在我们如何不把深度关上,会出现什么情况呢?

这里面由几个地方比较奇怪,可以看到蓝圈这里,前面的边框挡住了后面的木箱本体,而红圈内的边框被后面木箱挡住。

这里是个疑问点,我暂时还想不出来如何解释。唯一能解释的是因为深度的原因,红圈部分的边框深度在后面。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/653487.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023年中国工控自动化市场现状及竞争分析,美日占主角,国产品牌初崭头角

工控自动化是一种运用控制理论、仪器仪表理论、计算机和信息技术,对工业生产过程实现检测、控制、优化、调度、管理和决策,达到增加产量、提高质量、降低消耗、确保安全等目的综合性技术。产品应用领域广泛,可分为OEM型行业和项目型行业。 近…

2024年最新 MySQL的下载、安装、启动与停止

一、MySQL的下载 MySQL最常用的2个版本: 社区版:免费开源,自由下载,不提供官方技术支持,大多数普通用户选择这个即可。企业版:需要付费,不能在线下载,可以使用30天,提供…

aio-max-nr达到上限导致数据库性能问题

问题说明: rac数据库节点一表面上看由于归档等待事件导致业务性能问题。 问题分析过程: 查看awr报告top事件,等待事件主要为归档切换问题: 查看事件,归档等待达到20多分钟 检查节点alert日志发现,最…

Linux第37步_解决“Boot interface 6 not supported”之问题

在使用USB OTG将“自己移植的固件”烧写到eMMC中时,串口会输出“Boot interface 6 not supported”,发现很多人踩坑,我也一样。 见下图: 解决办法: 1、打开终端 输入“ls回车”,列出当前目录下所有的文件…

SpringCloud-高级篇(十六)

前面学习了Lua的语法,就可以在nginx去做编程,去实现nginx类里面的业务,查询Redis,查询tomcat等 ,业务逻辑的编写依赖于其他组件,这些组件会用到OpenResty的工具去实现 (1)安装OpenRe…

C++(16)——vector的模拟实现

前面的文章中,给出了对于的模拟实现,本篇文章将给出关于的模拟实现。 目录 1.基本框架: 2. 返回值与迭代器: 2.1 返回值capacity与size: 2.2 两种迭代器iterator和const_iterator: 3. 扩容与push_back与pop_back&#xff1a…

后端学习:数据库MySQL学习

数据库简介 数据库:英文为 DataBase,简称DB,它是存储和管理数据的仓库。   接下来,我们来学习Mysql的数据模型,数据库是如何来存储和管理数据的。在介绍 Mysql的数据模型之前,需要先了解一个概念&#xf…

log4j2 配置入门介绍

配置 将日志请求插入到应用程序代码中需要进行大量的计划和工作。 观察表明,大约4%的代码专门用于日志记录。因此,即使是中等规模的应用程序也会在其代码中嵌入数千条日志记录语句。 考虑到它们的数量,必须管理这些日志语句,而…

【QT+QGIS跨平台编译】之十三:【giflib+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

文章目录 一、giflib介绍二、文件下载三、文件分析四、pro文件五、编译实践一、giflib介绍 GIFlib(又称为Libgif)是一个开源的C语言库,用于处理GIF图像格式。它提供了一组函数和工具,使得开发者可以读取、写入和操作GIF图像文件。 GIFlib支持GIF87a和GIF89a两种版本的GIF格…

【项目管理】CMMI-管理性能与度量

管理性能与度量 (Managing Performance and Measurement, MPM)的目的在于开发和维持度量能力来管理开发过程性能,以实现公司业务目标,更直接来说,将管理和改进工作集中在成本、进度表和质量性能上,最大限度地提高业务投资回报。 1…

linux(进程概念)

目录 前言: 正文 冯诺依曼体系结构 操作系统 (Operator System) 概念 目的 定位 如何理解“管理” 进程组织 基本概念 内核数据结构 代码和数据 查看进程 ps指令 top指令 父子进程 fork创建进程 小结: 前…

【Redis】Redis有哪些适合的场景

🍎个人博客:个人主页 🏆个人专栏:Redis ⛳️ 功不唐捐,玉汝于成 目录 前言 正文 (1)会话缓存(Session Cache) (2)全页缓存(FPC…

深入理解TCP网络协议(1)

目录 1.TCP协议的段格式 2.TCP原理 2.1确认应答 2.2超时重传 3.三次握手(重点) 4.四次挥手 1.TCP协议的段格式 我们先来观察一下TCP协议的段格式图解: 源/目的端口号:标识数据从哪个进程来,到哪个进程去 32位序号/32位确认号:TCP会话的每一端都包含一个32位&#xff08…

Windows 7 x64 SP1 安装 Google Chrome 109.0.5414.120 (正式版本) (64 位)

1 使用 IE 浏览器 输入网址 Google Chrome 网络浏览器得益于 Google 智能工具,Chrome 现在更易用、更安全、更快速。https://www.google.cn/chrome/,点击下载 Chrome。 2 点击 接受并安装。 3 提示。 4 保存。 5 双击 运行 ChromeSetup.exe。 6 等待安…

9.异步爬虫

异步爬虫可以理解为非只单线程爬虫 我们下面做个例子,之前我们通过单线程爬取过梨视频 https://blog.csdn.net/potato123232/article/details/135672504 在保存视频的时候会慢一些,为了提升效率,我们使用异步爬虫爬取 目录 1 线程池 2 …

类和对象 第五部分第三小节:递增运算符重载

作用&#xff1a;通过重载递增运算符&#xff0c;实现自己的整型数据递增 代码案例 1.重载前置运算符 #include <iostream> #include <string> using namespace std;class MyInteger {friend ostream& operator<<(ostream& out, const MyInteger&…

简盒工具箱iapp源码

一款工具箱兼做软件库。 新增远程更新功能 修复了部分失效功能 修复了偶尔会卡在启动页的情况 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/88776737 更多资源下载&#xff1a;关注我。

Open CASCADE学习|读取STEP文件并显示

STEP文件是基于ISO 10303标准创建的三维模型数据交换文件&#xff0c;也称为产品模型数据交换标准&#xff08;Standard Exchange of Product data model&#xff09;。这种文件格式旨在提供一个不依赖具体系统的中性机制&#xff0c;实现产品数据的交换和共享。 STEP文件是一…

C#实现带光标的截图

1&#xff0c;目的&#xff1a; 可通过热键实现带光标与不带光标两种模式的截图。 2&#xff0c;知识点&#xff1a; 快捷键的注册与注销。 [DllImport("user32.dll", SetLastError true)] public static extern bool RegisterHotKey(IntPtr hWnd, int id, KeyMo…

【算法与数据结构】139、LeetCode单词拆分

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;本题可以看做一个动态规划问题。其中&#xff0c;字符串s是背包&#xff0c;而字典中的单词就是物品。…