热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

StencilBuffer简单应用

写在前面:本文章为个人学习笔记,方便以后自己复习,也希望能帮助到他人。由于本人水平有限难免出现错误,还请评论区指出,多多指教。部分图元和素材来源于网络,如有侵权请联系本人删除。

写在前面:

本文章为个人学习笔记,方便以后自己复习,也希望能帮助到他人。

由于本人水平有限难免出现错误,还请评论区指出,多多指教。

部分图元和素材来源于网络,如有侵权请联系本人删除。

参考资料与链接会在文章末尾贴出。

=======================================================================

还记得深度缓冲区吗?它帮助我们比较对象的深度,以确保它们有正确相互遮挡关系。而本文会简单介绍模板缓冲区,模板缓冲区主要用于仅渲染对象的一部分而丢弃其他对象。

1 Writing from the Stencil Buffer

模板缓冲区为每个像素存储一个 8 位整数值(0-255)在帧缓冲区中。在执行片段着色器之前对于给定的像素,GPU 可以将模板缓冲区中的当前值与给定的参考值进行比较,这称为模板测试(Stencil Test)。如果模板测试通过,GPU 将执行深度测试。如果模板测试失败,GPU 会跳过该像素的其余处理。这意味着我们可以使用模板缓冲区作为掩码来告诉 GPU 哪些像素要绘制,哪些像素要丢弃。

模板测试是可配置的,所有的模板操作都是通过我们的 hlsl 代码之外的一个小的模板代码块来完成的。像大多数shaderlab的东西一样,我们可以在我们的子着色器中编写它们以将它们用于整个subshader或仅在某个shader pass中使用它们。

模板测试的基本公式是:


整一块模板测试的语义:

看着非常多,但其实我们并不需要为所有的signature指定值,因为很多signature都有默认值,本文的例子中我们只需要指定几个参数就能做出我们想要的效果。

本文例子将会有两个shader,一个write shader,一个read shader。

stencil 操作最重要的参数是 Ref,它标记了我们操作的模板参考值。默认值为 0,这是缓冲区在写入任何内容之前的默认值。我们首先将它设置为 0,这目前不会改变任何东西,但是现在输入它会使代码结构更清晰一些,且后面更改起来更轻松。

我们需要的模板操作的另一个参数是 Comp,它定义了模板操作何时通过。默认值为 Always,这意味着无论我们使用什么参考值,对象都将始终被绘制。对于read shader,我们将使用 Equal,意思是我们标记的Ref值与该位置的模板缓冲区Ref值相等时才绘制对象。

场景中我们简单搭建了一个窗框,窗框前后各有一个plane,现在把write shader的材质赋给front plane,并在fragment shader 中return 0,意料之中没有什么改变:

这是因为现在所有默认的stencil ref都是0,假如我们将ref改为1:

现在我们将ref作为属性暴露在外方便后续调试,[IntRange] attribute是保证我们的值为整数值。

目前的效果仍然是0为可见,其他的值全都不可见。

2 Reading to the Stencil Buffer

首先我们会完善之前的write shader,我们暴露Ref值,并把Comp改为always,这样它总是会通过模板测试,在通过模板测试后会把当前模板缓冲区的值改为自己当前的值,还有就是把深度写入关闭,不然会遮挡后面的物体:


接下来我们需要编写read shader,我们将之前光照模型的shader作为基础,再加上Stencil部分即可:


这里Comp改为Equal,即当前ref值与模板缓冲区ref值相等才会通过模板测试。

 

这样说明可能会更好理解一点,我们的plane实际上就是提前为屏幕中某片区域设置好了stencil value(这里为1),我们这里叫作write(Stencil Ref)shader;而真正想要渲染的物体也设定一个当前的Stencil value,但只有当此物体与模板缓冲区的值一致时才会渲染,假如我们设为1,那么因为默认为0,该物体无法通过模板测试自然不会渲染。当时当我们透过之前的plane观察此物体时,由于这个plane覆盖区域的stecil value被设为1,该物体Stencil value与之相等,因此就会被渲染。

先上效果图:


可以看到,假如不是透过plane的话是无法看到此物体的,因为没有通过模板测试不会被渲染。


接下来我们需要编写read shader

为了真正使用从模板缓冲区读取的着色器,我们将编写第二个从模板缓冲区读取的着色器。第二个着色器本身不会写入屏幕,而是在第一个着色器之前渲染,因此我们确保模板缓冲区在读取时已经写入了正确的值。

对于这个着色器,我们从一个基本的无光照着色器开始,就像在基础中一样,因为它非常简单而且我们不需要太多。为了让它根本不渲染到屏幕上,而只是操纵模板缓冲区,我们将向它添加一些其他的小细节。

我们可以继续完善一下write shader,因为我们在fragment shader中return0,所以看到背景是黑色的,我们可以把ColorMask设为0,这样就完全不输出颜色;此外,按照上面的逻辑我们需要write shader在read shader之前渲染,因为我们把其渲染队列改为Geometry-1,而read shader则保持Geometry:


我们把画框的另一面也做同样的配置,只不过前面的ref值为1,后面的ref值为2:


实际上两个物体处于相近的位置,却因为我们利用了模板缓冲区,呈现了这种效果。




推荐阅读
  • 本文整理了315道Python基础题目及答案,帮助读者检验学习成果。文章介绍了学习Python的途径、Python与其他编程语言的对比、解释型和编译型编程语言的简述、Python解释器的种类和特点、位和字节的关系、以及至少5个PEP8规范。对于想要检验自己学习成果的读者,这些题目将是一个不错的选择。请注意,答案在视频中,本文不提供答案。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 也就是|小窗_卷积的特征提取与参数计算
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了卷积的特征提取与参数计算相关的知识,希望对你有一定的参考价值。Dense和Conv2D根本区别在于,Den ... [详细]
  • MySQL数据库锁机制及其应用(数据库锁的概念)
    本文介绍了MySQL数据库锁机制及其应用。数据库锁是计算机协调多个进程或线程并发访问某一资源的机制,在数据库中,数据是一种供许多用户共享的资源,如何保证数据并发访问的一致性和有效性是数据库必须解决的问题。MySQL的锁机制相对简单,不同的存储引擎支持不同的锁机制,主要包括表级锁、行级锁和页面锁。本文详细介绍了MySQL表级锁的锁模式和特点,以及行级锁和页面锁的特点和应用场景。同时还讨论了锁冲突对数据库并发访问性能的影响。 ... [详细]
  • 深入理解线程、进程、多线程、线程池
    本文以QT的方式来走进线程池的应用、线程、进程、线程池、线程锁、互斥量、信号量、线程同步等的详解,一文让你小白变大神!为什么要使用多线程、线程锁、互斥量、信号量?为什么需要线程 ... [详细]
  • vb.net不用多线程如何同时运行两个过程?不用多线程?即使用多线程,也不会是“同时”执行,题主只要略懂一些计算机编译原理就能明白了。不用多线程更不可能让两个过程同步执行了。不过可 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • Learning to Paint with Model-based Deep Reinforcement Learning
    本文介绍了一种基于模型的深度强化学习方法,通过结合神经渲染器,教机器像人类画家一样进行绘画。该方法能够生成笔画的坐标点、半径、透明度、颜色值等,以生成类似于给定目标图像的绘画。文章还讨论了该方法面临的挑战,包括绘制纹理丰富的图像等。通过对比实验的结果,作者证明了基于模型的深度强化学习方法相对于基于模型的DDPG和模型无关的DDPG方法的优势。该研究对于深度强化学习在绘画领域的应用具有重要意义。 ... [详细]
  • 背景应用安全领域,各类攻击长久以来都危害着互联网上的应用,在web应用安全风险中,各类注入、跨站等攻击仍然占据着较前的位置。WAF(Web应用防火墙)正是为防御和阻断这类攻击而存在 ... [详细]
  • 本文讨论了如何使用GStreamer来删除H264格式视频文件中的中间部分,而不需要进行重编码。作者提出了使用gst_element_seek(...)函数来实现这个目标的思路,并提到遇到了一个解决不了的BUG。文章还列举了8个解决方案,希望能够得到更好的思路。 ... [详细]
  • OpenMap教程4 – 图层概述
    本文介绍了OpenMap教程4中关于地图图层的内容,包括将ShapeLayer添加到MapBean中的方法,OpenMap支持的图层类型以及使用BufferedLayer创建图像的MapBean。此外,还介绍了Layer背景标志的作用和OMGraphicHandlerLayer的基础层类。 ... [详细]
  • 数据结构与算法的重要性及基本概念、存储结构和算法分析
    数据结构与算法在编程领域中的重要性不可忽视,无论从事何种岗位,都需要掌握数据结构和算法。本文介绍了数据结构与算法的基本概念、存储结构和算法分析。其中包括线性结构、树结构、图结构、栈、队列、串、查找、排序等内容。此外,还介绍了图论算法、贪婪算法、分治算法、动态规划、随机化算法和回溯算法等高级数据结构和算法。掌握这些知识对于提高编程能力、解决问题具有重要意义。 ... [详细]
  • 重组蛋白/细胞因子的实验操作
    在我们进行抗体制备、ELISA、药物研究、免疫实验、细胞培养、晶体结构分析等实验时,免不了要和重组蛋白打交道。MCE重组蛋白产品涵盖超过2000种不同功能的重组蛋白& ... [详细]
author-avatar
爱与嫉妒咋
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有