日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

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

發(fā)布時間:2023/11/16 windows 49 coder
生活随笔 收集整理的這篇文章主要介紹了 【躬行】-深度缓冲和模板缓冲是怎么存储的? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

概述

最近在工作中需要實現(xiàn)一個功能,用到了模板測試。但奇怪的是,模板測試竟然不起作用!在解決問題的過程中,發(fā)現(xiàn)了一些有趣的知識點。通過本文,可以了解在unity中,深度緩沖和模板緩沖到底是怎么存儲的。

測試環(huán)境的搭建

Unity版本:2021.3.16f1

URP版本:12.1.8

RenderDoc:1.29

需要注意的是,URP的版本迭代,代碼改動較大,最好與上面的版本一致。否則,可能會因為版本不同,產(chǎn)生無謂的麻煩。

后面的實驗需要使用到RenderDoc。關于怎么在Unity中使用RenderDoc,可以查看最后的參考文獻部分。

  1. 由于后續(xù)需要修改URP的源碼進行測試,所以需要移動URP源碼的路徑。新建URP項目,源碼的路徑是類似這種:xxx\Library\PackageCache(xxx是URP項目的文件夾名)。需要將以下兩個URP源碼文件夾移動到xxx\Packages文件夾下:

    移動后,Packages文件夾類似這樣:

  2. 實現(xiàn)一個基礎的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. 需要設置一下測試的場景環(huán)境。使用上面的Shader新建兩個材質(zhì)球:Far和Near,如下設置:

    Far材質(zhì)球,設置為總是通過模板測試,替換模板值3,Render Queue設為2000。

    Near材質(zhì)球,設置模板緩沖值為3時才通過,保留模板緩沖值,Render Queue設為2010。

    通過上面的設置,會先渲染Far材質(zhì)球,寫入模板緩沖3。然后再渲染Near材質(zhì)球,只有模板緩沖中值為3的區(qū)域才會渲染。

    使用Frame Debugger查看渲染流程,可以發(fā)現(xiàn),確實是先渲染Far,再渲染Near。整體的渲染流程如下:

    注意上圖中紅框中的部分,是顏色緩沖紋理的名稱。在代碼中使用全局搜索,可以找到如下部分:

    通過觀察分析,可以發(fā)現(xiàn),深度緩沖和模板緩沖,主要是受到下面代碼的影響:

    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。從這些內(nèi)容分析以下,應該是因為沒有了深度緩沖和模板緩沖,導致深度測試和模板測試不起作用了。

實驗二 設為16

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

  2. Frame Debugger 與上面相同,略

  3. RenderDoc

    分析:從場景效果看,顯示出Far和Near,但是模板測試并沒有起作用,因為完整的渲染出了Near。從Frame Debugger上看,流程并沒有改變。從RenderDoc看,除了顏色紋理RT0,還多渲染了一張紋理DS(從名字看,應該是Depth Stencil)。在RT0中右鍵選中Far范圍內(nèi)的一點,再切換到DS,可以在RenderDoc的底部看到選中點的深度、模板信息。從上圖可以看出,DS紋理的格式是R16,后面的值是選中點的深度緩沖值。這樣,可以推測,有了深度緩沖,深度測試應該是起作用了,但是模板緩沖還是沒有起作用,因為沒有模板緩沖。

實驗三 設為24

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

  2. Frame Debugger 與上面相同,略

  3. RenderDoc

    分析:從場景效果和Frame Debugger上看,效果和流程與開始實驗前完全一樣。從RenderDoc看,與設為16時一樣,都有RT0和DS兩張紋理。但DS紋理的格式和內(nèi)容是不同的,在上圖底部可以發(fā)現(xiàn),DS的格式是D32S8,后面還有深度緩沖值和模板緩沖值。與設為16時相比,DS紋理的格式不同,紋理的信息中,還多了模板緩沖值。這樣,可以推測,深度緩沖和模板緩沖都有了,深度測試和模板測試也都起作用了。

實驗四 設為32

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

  2. Frame Debugger 與上面相同,略

  3. RenderDoc與上面相同,略

可以發(fā)現(xiàn),設為32時,與設為24時的效果完全相同。這是為什么呢?

colorDescriptor.depthBufferBits的源碼如下:

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

設為24時,單步調(diào)試的結果如下:

設為32時,單步調(diào)試的結果如下:

從上面可以發(fā)現(xiàn),設置depthBufferBits的int值,并不會向一般的屬性那樣直接存儲int值。而是經(jīng)過計算之后,存儲到GraphicsFormat類型的變量中。而當設置的值是24和32時,保存的GraphicsFormat類型的變量都是D32_SFloat_S8_UInt。這也就解釋了為什么設為24和32時,RenderDoc中完全一致的問題。

實驗結論

上面的實驗結果,可以用下面的圖表簡潔表達:

DS紋理 深度測試 模板測試
0 ? ? ?
16 ? ? ?
24 ? ? ?
32 ? ? ?

回到最初遇到的問題:模板測試不起作用。根據(jù)上面的表格,在項目中查了一下,是因為depthBufferBits設為了0,導致深度測試和模板測試都不起作用了。思路延伸一下:從性能優(yōu)化的角度考慮,如果某種情況下不需要深度測試或模板測試,可以賦予depthBufferBits一個比較低的值,這樣,DS紋理占用的內(nèi)存會比較小,甚至不需要申請DS紋理的內(nèi)存。

參考

  • [1] RenderDoc Integration

總結

以上是生活随笔為你收集整理的【躬行】-深度缓冲和模板缓冲是怎么存储的?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。