【躬行】-深度缓冲和模板缓冲是怎么存储的?

这篇具有很好参考价值的文章主要介绍了【躬行】-深度缓冲和模板缓冲是怎么存储的?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

概述

最近在工作中需要实现一个功能,用到了模板测试。但奇怪的是,模板测试竟然不起作用!在解决问题的过程中,发现了一些有趣的知识点。通过本文,可以了解在unity中,深度缓冲和模板缓冲到底是怎么存储的。

测试环境的搭建

Unity版本:2021.3.16f1

URP版本:12.1.8

RenderDoc:1.29

需要注意的是,URP的版本迭代,代码改动较大,最好与上面的版本一致。否则,可能会因为版本不同,产生无谓的麻烦。

后面的实验需要使用到RenderDoc。关于怎么在Unity中使用RenderDoc,可以查看最后的参考文献部分。

  1. 由于后续需要修改URP的源码进行测试,所以需要移动URP源码的路径。新建URP项目,源码的路径是类似这种:xxx\Library\PackageCache(xxx是URP项目的文件夹名)。需要将以下两个URP源码文件夹移动到xxx\Packages文件夹下:

    移动后,Packages文件夹类似这样:

  2. 实现一个基础的Shader,包含了深度测试和模板测试。代码很简单,就不赘述了。如下所示:

    Shader "Test/Hello World"
    {
        Properties
        {
            _Color ("Main Color", Color) = (1,1,1,1)
            
            [Header(Stencil)]
            [Enum(UnityEngine.Rendering.CompareFunction)]_StencilComp ("Stencil Comparison", Float) = 8
            [IntRange]_Stencil ("Stencil ID", Range(0,255)) = 0
            [Enum(UnityEngine.Rendering.StencilOp)]_StencilPass ("Stencil Pass", Float) = 0
        }
        SubShader
        {
            Tags { "Queue" = "Geometry" "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }
            
            Pass
            {
                Tags { "LightMode" = "UniversalForward" }
                Cull Off
                ZTest LEqual
                ZWrite On
                
                Stencil
                {
                    Ref [_Stencil]
                    Comp [_StencilComp]
                    Pass [_StencilPass]
                }
                
                HLSLPROGRAM
                
                #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
                
                #pragma vertex vert
                #pragma fragment frag
                
                struct Attributes
                {
                    float4 positionOS: POSITION;
                };
                
                struct Varyings
                {
                    float4 vertex: SV_POSITION;
                };
                
                half4 _Color;
                
                Varyings vert(Attributes input)
                {
                    Varyings output = (Varyings)0;
                    
                    output.vertex = TransformObjectToHClip(input.positionOS.xyz);
                    
                    return output;
                }
                
                half4 frag(Varyings input): SV_Target
                {
                    return _Color;
                }
                ENDHLSL
                
            }
        }
    }
    
    
  3. 需要设置一下测试的场景环境。使用上面的Shader新建两个材质球:Far和Near,如下设置:

    Far材质球,设置为总是通过模板测试,替换模板值3,Render Queue设为2000。

    Near材质球,设置模板缓冲值为3时才通过,保留模板缓冲值,Render Queue设为2010。

    通过上面的设置,会先渲染Far材质球,写入模板缓冲3。然后再渲染Near材质球,只有模板缓冲中值为3的区域才会渲染。

    使用Frame Debugger查看渲染流程,可以发现,确实是先渲染Far,再渲染Near。整体的渲染流程如下:

    注意上图中红框中的部分,是颜色缓冲纹理的名称。在代码中使用全局搜索,可以找到如下部分:

    通过观察分析,可以发现,深度缓冲和模板缓冲,主要是受到下面代码的影响:

    colorDescriptor.depthBufferBits的代码注释如下:

    这个值代表渲染纹理的深度缓冲精度比特值,支持0,16,24,32这四个值。

    下面,分别把colorDescriptor.depthBufferBits设为上面的四个值,查看效果。

    实验

    实验一 设为0

    colorDescriptor.depthBufferBits = (useDepthRenderBuffer) ? 0 : 0;
    
    1. 场景效果

    2. Frame Debugger

    3. RenderDoc

      分析:从场景效果看,只渲染了天空盒,没有显示出Far或Near。但从Frame Debugger上看,流程并没有改变,还是先渲染Far,再渲染Near,接着再渲染天空盒。只是天空盒将Far和Near都覆盖了。从RenderDoc看,只有颜色纹理RT0。从这些内容分析以下,应该是因为没有了深度缓冲和模板缓冲,导致深度测试和模板测试不起作用了。

实验二 设为16

colorDescriptor.depthBufferBits = (useDepthRenderBuffer) ? 16 : 0;
  1. 场景效果

  2. Frame Debugger 与上面相同,略

  3. RenderDoc

    分析:从场景效果看,显示出Far和Near,但是模板测试并没有起作用,因为完整的渲染出了Near。从Frame Debugger上看,流程并没有改变。从RenderDoc看,除了颜色纹理RT0,还多渲染了一张纹理DS(从名字看,应该是Depth Stencil)。在RT0中右键选中Far范围内的一点,再切换到DS,可以在RenderDoc的底部看到选中点的深度、模板信息。从上图可以看出,DS纹理的格式是R16,后面的值是选中点的深度缓冲值。这样,可以推测,有了深度缓冲,深度测试应该是起作用了,但是模板缓冲还是没有起作用,因为没有模板缓冲。

实验三 设为24

colorDescriptor.depthBufferBits = (useDepthRenderBuffer) ? 24 : 0;
  1. 场景效果

  2. Frame Debugger 与上面相同,略

  3. RenderDoc

    分析:从场景效果和Frame Debugger上看,效果和流程与开始实验前完全一样。从RenderDoc看,与设为16时一样,都有RT0和DS两张纹理。但DS纹理的格式和内容是不同的,在上图底部可以发现,DS的格式是D32S8,后面还有深度缓冲值和模板缓冲值。与设为16时相比,DS纹理的格式不同,纹理的信息中,还多了模板缓冲值。这样,可以推测,深度缓冲和模板缓冲都有了,深度测试和模板测试也都起作用了。

实验四 设为32

colorDescriptor.depthBufferBits = (useDepthRenderBuffer) ? 32 : 0;
  1. 场景效果与上面相同,略

  2. Frame Debugger 与上面相同,略

  3. RenderDoc与上面相同,略

可以发现,设为32时,与设为24时的效果完全相同。这是为什么呢?

colorDescriptor.depthBufferBits的源码如下:

    public int depthBufferBits
    {
      get => GraphicsFormatUtility.GetDepthBits(this.depthStencilFormat);
      set => this.depthStencilFormat = RenderTexture.GetDepthStencilFormatLegacy(value, this.graphicsFormat);
    }

设为24时,单步调试的结果如下:

设为32时,单步调试的结果如下:

从上面可以发现,设置depthBufferBits的int值,并不会向一般的属性那样直接存储int值。而是经过计算之后,存储到GraphicsFormat类型的变量中。而当设置的值是24和32时,保存的GraphicsFormat类型的变量都是D32_SFloat_S8_UInt。这也就解释了为什么设为24和32时,RenderDoc中完全一致的问题。

实验结论

上面的实验结果,可以用下面的图表简洁表达:

DS纹理 深度测试 模板测试
0
16
24
32

回到最初遇到的问题:模板测试不起作用。根据上面的表格,在项目中查了一下,是因为depthBufferBits设为了0,导致深度测试和模板测试都不起作用了。思路延伸一下:从性能优化的角度考虑,如果某种情况下不需要深度测试或模板测试,可以赋予depthBufferBits一个比较低的值,这样,DS纹理占用的内存会比较小,甚至不需要申请DS纹理的内存。文章来源地址https://www.toymoban.com/news/detail-747072.html

参考

  • [1] RenderDoc Integration

到了这里,关于【躬行】-深度缓冲和模板缓冲是怎么存储的?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MySQL 存储引擎 InnoDB 内存结构之更改缓冲区

    更改缓冲区(Change Buffer)是一种特殊的数据结构,用于缓存不在缓冲池中的二级索引(secondary index)页的更改。可能来自于 INSERT 、 UPDATE 或 DELETE 操作(数据操作语言,DML)的缓冲更改,会在后续通过其他读操作将这些页加载到缓冲池时被合并。 与聚簇索引(clustered indexe

    2024年02月10日
    浏览(41)
  • OpenCv案例(十二):基于OpenCVSharp学习之模板匹配寻找距离中心位置最近的目标

    1:需求:在原图中,有多个特征点和模板图像一模一样,因此,寻找原图中中心位置最近的特征点位(模板匹配详解);原图如下所示: 模板图像:                                                                          2:现要求匹配找

    2024年01月24日
    浏览(58)
  • 【Linux】基础IO —— 缓冲区深度剖析

    (꒪ꇴ꒪(꒪ꇴ꒪ )🐣,我是 Scort 目前状态:大三非科班啃C++中 🌍博客主页:张小姐的猫~江湖背景 快上车🚘,握好方向盘跟我有一起打天下嘞! 送给自己的一句鸡汤🤔: 🔥真正的大师永远怀着一颗学徒的心 作者水平很有限,如果发现错误,可在评论区指正,感谢🙏 🎉🎉

    2024年02月02日
    浏览(55)
  • 【计算机组成原理】高速缓冲存储器 Cache 的写策略(Writing Policy)

    缓存的写策略指的是确定何时将数据写入缓存或主存的策略。 在全写法策略中,每次发生写操作时都会将数据同时写入缓存和主存。这样可以保证数据的一致性,但会增加主存的写入操作,降低写入性能。需要设置写缓存(Write Buffer)。 在写回策略中,当缓存中的数据发生

    2024年02月02日
    浏览(54)
  • GIS融合之路(二)CesiumJS和ThreeJS深度缓冲区整合

    在这篇文章开始前再次重申一下,山海鲸并没有使用ThreeJS引擎。但由于ThreeJS引擎使用广泛,下文中直接用ThreeJS同CesiumJS的整合方案代替山海鲸中3D引擎和CesiumJS整合。 系列传送门: 山海鲸可视化:GIS融合之路(一)技术选型CesiumJS/loaders.gl/iTowns 文章开始之前大家可以看下这

    2024年02月09日
    浏览(40)
  • 【计算机组成原理】高速缓冲存储器 Cache 的三种映射方式(Cache Mapping)

    缓存是计算机系统中常见的一种高速存储器,用于临时存储常用数据,以便快速访问。在缓存中,有三种常见的映射方式,分别是直接映射、全相联映射和组相联映射。 在直接映射中,每个主存块只能映射到缓存中的一个特定位置。该位置是通过对主存块的某个地址的一部分

    2024年01月19日
    浏览(50)
  • 最近基于深度学习大火的AIGC将会抢工作者的饭碗?

    NLG | CLIP | Diffusion Model GAN | AIGC | Stable Diffusion 随着CLIP、DALL·E、Diffusion Model、Magic3D、Stable Diffusion等技术的快速发展,AIGC在全球各大科技巨头间可谓是高频词汇,连带着AI这个老生常谈的话题也一并火热起来。 去年三月,OpenAI发布了人工智能绘画产品DALL·E,后来升级到DA

    2024年02月11日
    浏览(46)
  • 苹果Mac电脑怎么显示/取消显示最近使用的文档记录

    Mac可以隐藏最近使用的文档吗?有些小伙伴的mac打开finder会自动打开“ 最近使用 ”项目,将最近所有打开的图片,txt文档等都一一展现出来,没有任何隐私可言。那么该如何在 finder设置不显示最近文档 呢?下面小编就介绍一下该如何关闭最近使用这项功能。 1、在左上角,

    2024年02月10日
    浏览(105)
  • 最近怎么流量涨这么多?那我开始讲Hive特性了!

    Hive架构原理 a.用户接口:Client CLI(Hive shell)、JDBC/ODBC(java访问hive)、Hive WEBUI(浏览器访问hive)和Thrift服务器 b.驱动器:Driver 解析器(SQL Parser): 将SQL字符串转换成抽象语法树AST ,这一步一般都用第三方工具库完成,比如antlr;对AST进行语法分析,比如表是否存在、字段是

    2024年02月03日
    浏览(42)
  • 【Kubernetes】K8S到底是什么,最近怎么这么火

    前言 kubernetes,简称K8s,是用8代替名字中间的8个字符“ubernete”而成的缩写 。是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应用部署,规划,更新,维护的一种机制。 📕作者简介

    2024年02月16日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包