一、什么是模板测试

OpenGL基础30:模板测试

Unity官方文档:https://docs.unity3d.com/Manual/SL-Stencil.html

一个很经典的模板测试例子就是 UI Mask:

二、Unity 中的模板测试

SubShader
{Tags { …… }Pass{Stencil{//可选Ref referenceValueReadMask readMaskWriteMask writeMaskComp comparisonFunctionPass stencilOperationFail stencilOperationZFail stencilOperation}CGPROGRAM//……CGEND}
}

1):Ref

  • 对应 OpenGL 中 glStencilFunc(GLenum func, GLint ref, GLuint mask) 第二个参数 GLint ref
  • 范围 [0, 255]

指定模板测试的引用值,模板缓冲的内容会与这个值对比,模板缓冲默认值当然为0

2):ReadMask

  • 对应 OpenGL 中 glStencilFunc(GLenum func, GLint ref, GLuint mask) 第三个参数 GLuint mask
  • 范围 [0, 255],默认值 255

读遮罩,在模板测试对比引用值和储存的模板值前,对它们进行按位与操作

3):WriteMask

  • 对应 OpenGL 中 glStencilMask(GLint 0~255)
  • 范围 [0, 255],默认值 255

写遮罩,再写入模板缓冲时,对它们进行按位与操作(如果对应位为1,则对应位可写入缓存,如果对应位为0,则对应位不可写入缓存)

4):Comp

  • 对应 OpenGL 中 glStencilFunc(GLenum func, GLint ref, GLuint mask) 第一个参数 GLenum func
  • 枚举,默认值 Always

模板测试规则,也就是参考值和缓冲值比较规则

  • Always:永远通过测试
  • Never:永远不通过测试
  • Less:在片段模板值小于缓冲的模板值时通过测试
  • Equal:在片段模板值等于缓冲区的模板值时通过测试
  • LEqual:在片段模板值小于等于缓冲区的模板值时通过测试
  • Greater:在片段模板值大于缓冲区的模板值时通过测试
  • NotEqual:在片段模板值不等于缓冲区的模板值时通过测试
  • GEqual:在片段模板值大于等于缓冲区的模板值时通过测试

5):Pass

  • 对应 OpenGL 中 glStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass) 第三个参数 GLenum dppass
  • 枚举,默认值 Keep

当模板测试和深度测试都通过时,模板缓冲的值处理方式

  • Keep:保持现有的模板值
  • Zero:将模板值置为0
  • Replace:替换,将模板值设置为 Ref 值
  • IncrSat:如果模板值不是最大值就将模板值+1
  • IncrWrap:与 IncrSat 一样将模板值+1,如果模板值已经是最大值则设为0
  • DecrSat:如果模板值不是最小值就将模板值-1
  • DecrWrap:与 DecrSat 一样将模板值-1,如果模板值已经是最小值则设为最大值
  • Invert:将模板值按位反转

6):Fail

  • 对应 OpenGL 中 glStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass) 第三个参数 GLenum sfail
  • 枚举,默认值 Keep

当模板测试不通过时,模板缓冲的值处理方式

7):ZFail

  • 对应 OpenGL 中 glStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass) 第二个参数 GLenum dpfail
  • 枚举,默认值 Keep

当模板测试通过、深度测试通过时,模板缓冲的值处理方式

三、关于模板缓冲区

若 Shader 中应用了模板测试,那么对于每个像素,测试的过程如下:

  • StencilBufferValue:模板缓冲区当前模板值
(Ref & ReadMask) Comp (StencilBufferValue & ReadMask)

模板缓冲区的大小为固定的8位,这也是为什么 Ref 的值范围为 [0, 255],除此之外,若纹理缓冲设置为 Depth24Stencil8,那么8位模板值就会存在于 Zbuffer 中

在 Unity 屏幕后处理中使用 Stencil:

出乎意料之外:直接调用 Blit 无法实现模板测试效果,因为其无法识别深度模板缓冲,但是还好,如果是 Unity 默认的 Build-in 管线,可以使用下面的代码解决:

void OnRenderImage(RenderTexture src, RenderTexture dest)
{//……    material为你自己的材质RenderTexture buffer = RenderTexture.GetTemporary(src.width, src.height, 24);Graphics.SetRenderTarget(buffer.colorBuffer, src.depthBuffer);Graphics.Blit(src, buffer, material);Graphics.Blit(buffer, dest);RenderTexture.ReleaseTemporary(buffer);
}

原理是通过设置 SetRenderTarget() 让 Graphics.Blit 调用的时候能够获取到深度图信息,注意中间纹理的 depthBuffer 必须要为 24,这样才可以从中拿到模板信息

搞定之后就可以进行测试:

Subshader
{ZTest Always Cull Off ZWrite OffPass{Stencil{Ref 1Comp Equal}CGPROGRAM#pragma vertex vert#pragma fragment fragENDCG}
}

如果黑屏了那就是没问题!所有的像素都没有通过模板测试

参考资料:

  • https://docs.microsoft.com/zh-cn/windows/uwp/graphics-concepts/stencil-buffers
  • https://zhuanlan.zhihu.com/p/150306817
  • https://www.cnblogs.com/hont/p/6579848.html

UnityShader29:模板测试相关推荐

  1. opengl模板测试实例

    在opengl中, 可以开启模板测试功能,来限定某一部分是可画的,某一部分是不可画的.这可通过设置模板模式来控制哪部分是可画的, 有点类似在墙上喷字. 虽说剪刀测试也可以限定蓝屏的某一部分可画,但不适 ...

  2. Opengl-深度测试模板测试

    ###深度测试 深度缓冲:用来存储深度信息的,可以这么理解,在你屏幕上最后留下的裁剪区域你看到的东西其实是有深度的,就像现实世界里一样,有远近这样.然后这个远近的程度信息就存储在了深度缓冲里 深度测试 ...

  3. OpenGL stencil test模板测试的实例

    OpenGL stencil test模板测试 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <glad/glad.h> #incl ...

  4. OpenGL模板测试通俗理解

    看书籍或资料往往还是云里雾里的,这里写一下自己的理解.希望对需要的人有帮助. 简而言之: 模板缓冲区和帧缓冲区一样大 模板缓冲区初始状态是什么? 在glClearBuffer的时候清空,所以初始状态是 ...

  5. (zt)OpenGL中的Alpha测试,深度测试,模板测试,裁减测试

    转自http://www.cppblog.com/flashboy/archive/2009/09/01/94974.html 大家好.现在因为参加工作的关系,又是长时间没有更新.趁着国庆的空闲,总算 ...

  6. OpenGL基础30:模板测试

    前置:OpenGL基础29:深度测试 一.模板测试 前面一章提到过:深度缓冲测试在片段着色器运行.以及模板测试(Stencil Testing)之后,那么这下知道模板测试是在什么时候了吧,模板测试和深 ...

  7. 【Unity3D】基于模板测试和顶点膨胀的描边方法

    1 前言 选中物体描边特效 中介绍了基于模板纹理模糊膨胀的描边方法,该方法实现了软描边,效果较好,但是为了得到模糊纹理,对屏幕像素进行了多次渲染,效率欠佳.本文将介绍另一种描边方法:基于模板测试和顶点 ...

  8. Unity中使用模板测试模拟Mask组件效果

    本文分享Unity中使用模板测试模拟Mask组件效果 在上一篇文章中, 我们分享了模板测试的基础知识, 在今天的分享中, 我们会尝试使用模板测试来模拟遮罩效果. Unity中使用模板测试模拟Mask组 ...

  9. DirectX11 模板测试

    模板测试 1. 模板测试实现过程 如前所述,我们可以使用模板缓冲区来阻止像素片段渲染到后台缓冲区的某些区域.判断一个特定像素是否可以写入后台缓冲区的操作称为模板测试(stencil test),其实现 ...

最新文章

  1. js jquery关闭当前窗口
  2. 使用powershell一次性创建用户,OU及组
  3. centos7是php多少,centos7怎么安装php
  4. HTML 取消超链接下划线
  5. SAP Commerce Cloud(原Hybris) impex 里的美元(dollar $)符号
  6. 当前监管面比较关注的企业征信模型
  7. Hexo 入门指南(一) - 简介 准备
  8. java中KMP模式,Java数据结构-串及其应用-KMP模式匹配算法
  9. cartographer基于3d地图的纯定位模式
  10. 软件工程——2021软科中国大学专业排名
  11. 宝可梦 序列号认证服务器发生了错误,宝可梦探险寻宝无法连接服务器是什么原因...
  12. Qt控件之toggle()、triggered()、clicked()——triggered发射信号无响应
  13. 安恒如何扫描oracle,安恒明鉴数据库弱点扫描器
  14. 自由技艺 (Liberal arts)
  15. GIT之Rebase的使用
  16. ubuntu下安装网易云音乐
  17. IllegalStateException: Couldn‘t read row 0, col 10 from CursorWindow. Make sure the Cursor is initi
  18. 对《Mode-Adaptive Neural Networks for Quadruped Motion Control》一文的理解(上)
  19. docker docker compose 云效流水线
  20. Linux 之 开机自启动

热门文章

  1. python编程入门与案例详解-干货|| 清华大佬推荐的python400集入门资料
  2. 安装完python怎么打开-python安装后怎么启用
  3. 济南python工资一般多少-济南Python+人工智能
  4. python最适合做什么-python学完之后比较适合哪些职业工作呢?
  5. 从零开始学习python编程-从零开始学Python程序设计
  6. Linux下科大讯飞语音识别全面总结
  7. 嵌入式linux调试dsi,做嵌入式开发时,你是怎么实现LCD显示的?
  8. PUT与POST的相同点和不同点
  9. 【计算机网络笔记】编码与调制
  10. 计算机开题报告中的研究方法,开题报告:经济学写论文用到的五种研究方法