How to generate Depth Buffers in a CommandBuffer?

I am simply trying to for now display a depth buffer as a texture on a debugging plane.
I need to generate several depth buffers and compare them. So the only way I found I can do this is forcing CommandBuffers to draw selected objects into the buffer.
While I had success getting the depth buffer to display with _CameraDepthTexture in the frag shader I could not figure out how to generate that myself for several others AND OR clear it and render over it by forcing the next camera.Render() the render function did not seem to do anything

Right now the below code is rendering all objects as solid no depth
So its getting there from yesterdays nothingness

I know CommandBuffers are a bit less examplesness. I could just try doing this in GL since I dont know how or when _CameraDepthTexture happens and that makes this more complicated then it should be

RenderTexture _g;
int texID;

void OnPostRender(){
    // create new command buffer
    m_MagicBuffer = new CommandBuffer();
    m_MagicBuffer.name = "Island Depth";
    if (islandObjects.Count == 0 && islandObjects != null)
    {
        BuildIslandObjects();
    }
    texID = Shader.PropertyToID("_Temp1");
    // _rt_cam = new RenderTexture(Screen.width, Screen.height, 16, RenderTextureFormat.ARGB32);
    // _rt_cam = new RenderTexture(Screen.width, Screen.height, 16, RenderTextureFormat.Depth);
    m_MagicBuffer.GetTemporaryRT(texID, Screen.width, Screen.height, 16, FilterMode.Bilinear, RenderTextureFormat.Depth, RenderTextureReadWrite.Default, QualitySettings.antiAliasing);
    m_MagicBuffer.SetRenderTarget(_rt_cam);
    m_MagicBuffer.ClearRenderTarget(true, true, Color.blue); // clear before drawing to it each frame!!
   
    foreach(GameObject o in islandObjects)
    {
        MeshRenderer r = o.GetComponent<MeshRenderer>();
        // print("wakka");
        if(r && basicRenderMat)
            // print("narf");
            m_MagicBuffer.DrawRenderer(r, basicRenderMat);
    }

    _cam.targetTexture = _rt_cam;

    _cam.Render();

    // _cam.targetTexture = new RenderTexture(256, 256, 16, RenderTextureFormat.ARGB32);
    // _g = new RenderTexture(Screen.width, Screen.height, 16, RenderTextureFormat.ARGB32);
    // _g = new RenderTexture(Screen.width, Screen.height, 16, RenderTextureFormat.Depth);
    // m_MagicBuffer.Blit(_cam.targetTexture.depthBuffer, _g, _mat_Zbuffer);

    // m_MagicBuffer.SetGlobalTexture("_Depth01", _cam.targetTexture.depthBuffer );
    m_MagicBuffer.SetGlobalTexture("_Depth01", _rt_cam );
    // m_MagicBuffer.SetGlobalTexture("_Depth01", _cam.targetTexture );


    Graphics.ExecuteCommandBuffer(m_MagicBuffer);


    // _islandMat.SetTexture("_MainTex", _rt_cam);


    // _cam.AddCommandBuffer(CameraEvent.BeforeForwardOpaque, m_MagicBuffer);


}


frag {
    float2 uv = i.uv.xy;

    // float depth = 1 - Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv) * _Scalar);
    float depth = 1 - Linear01Depth(SAMPLE_DEPTH_TEXTURE(_Depth01, uv));
    return fixed4(depth, depth, depth, 1);
}

at least can specify events when things get called,

I was trying to get it to run immediately instead of the event call, either way here’s the updated function call trying to add the event instead of Graphics.ExecuteCommandBuffer(m_MagicBuffer);

I can get _rt2_colors to render its colors but depth is no go, should I be using a custom material when running DrawRenderer ?
Its simply frag { return _Color; } I tried changing that shader to Standard but either I get artifacts or no change

Odly the Frame debugger is not working unless I add a targettexture in the interface to to main camera

Im in Forward rendering path

    int depthTexId = Shader.PropertyToID("_DepthTex");
    int colorTexId = Shader.PropertyToID("_ColorTex");

    RenderTexture _rt2_colors;
    RenderTexture _rt2_depth;
    RenderTexture _gC;
    RenderTexture _gD;

    void OnPostRender(){
        m_MagicBuffer = new CommandBuffer();
        m_MagicBuffer.name = "Island Depth";
        if (islandObjects.Count == 0 && islandObjects != null)
        {
            BuildIslandObjects();
        }
        // m_MagicBuffer.GetTemporaryRT(colorTexId, Screen.width, Screen.height);
        // m_MagicBuffer.GetTemporaryRT(depthTexId, Screen.width, Screen.height, 24,
        //         FilterMode.Point, RenderTextureFormat.Depth);

        _rt2_colors = new RenderTexture(Screen.width, Screen.height, 16, RenderTextureFormat.ARGB32);
        _rt2_depth = new RenderTexture(Screen.width, Screen.height, 16, RenderTextureFormat.Depth);

        // m_MagicBuffer.SetRenderTarget(_rt2_colors);
        m_MagicBuffer.SetRenderTarget(_rt2_depth);
      
        m_MagicBuffer.ClearRenderTarget(true, true, Color.green); // clear before drawing to it each frame!!
      
        // draw all picked objects to it
        foreach(GameObject o in islandObjects)
        {
            MeshRenderer r = o.GetComponent<MeshRenderer>();
            // print("wakka");
            if(r && basicRenderMat)
                // print("narf");
                m_MagicBuffer.DrawRenderer(r, basicRenderMat);
        }
      
        _cam.SetTargetBuffers(_rt2_colors.colorBuffer, _rt2_depth.depthBuffer);
        // _cam.targetTexture = _rt_cam;
        // _cam.Render();

        // _cam.targetTexture = new RenderTexture(256, 256, 16, RenderTextureFormat.ARGB32);
        // m_MagicBuffer.Blit(_cam.targetTexture.depthBuffer, _g, _mat_Zbuffer);
        // BuiltinRenderTextureType
        _gC = new RenderTexture(Screen.width, Screen.height, 16, RenderTextureFormat.ARGB32);
        _gD = new RenderTexture(Screen.width, Screen.height, 16, RenderTextureFormat.Depth);
        // Graphics.Blit here works better then m_MagicBuffer.Blit
        // this was a common finding in the forums
        Graphics.Blit(_rt2_colors, _gC);
        Graphics.Blit(_rt2_depth, _gD);


        m_MagicBuffer.SetGlobalTexture("_ColorTex", _rt2_colors );
        m_MagicBuffer.SetGlobalTexture("_DepthTex", _rt2_depth );
        // m_MagicBuffer.SetGlobalTexture("_ColorTex", _gC );
        // m_MagicBuffer.SetGlobalTexture("_DepthTex", _gD );

        // Graphics.ExecuteCommandBuffer(m_MagicBuffer);

        // m_MagicBuffer.ReleaseTemporaryRT(colorTexId);
        // m_MagicBuffer.ReleaseTemporaryRT(depthTexId);

        // _islandMat.SetTexture("_MainTex", _rt_cam);
        // _islandMat.SetTexture("_MainTex", _g);


        _cam.AddCommandBuffer(CameraEvent.AfterDepthTexture, m_MagicBuffer);

        _cam.Render();

    }


frag {
// return tex2D(_ColorTex, i.uv);
// return tex2D(_DepthTex, i.uv);
return 1 - Linear01Depth(SAMPLE_DEPTH_TEXTURE(_DepthTex, uv));
// return 1 - Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv));
}

These are the shaders for the renderer function and the plane object
No real update, I simply dont think you have access to the depth data in a command buffer despite the settings
I can only get it to show solid colors.

Its some untold shader thing in the Renderer() material thats passed in, but a standard shader wreks all things a and a plain shader draws flat colors.

This is as far as I can get without just accessing GL commands of which I will do next

Zbuffer script

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;

[ExecuteAlways]
public class zbuffer3 : MonoBehaviour
{
 


    public Material _mat_Zbuffer;
 
    public Camera _cam;

    public Camera _DepthCam;
    // public Material basicRendererMat;


    public GameObject _plane_island;
    public Material _islandMat;
 




    // the commandbuffers if added to camera will flood the cache
    private Dictionary<Camera, CommandBuffer> m_Cameras = new Dictionary<Camera, CommandBuffer>();
    void Cleanup()
    {
        foreach(var cam in m_Cameras)
        {
            // this event enum has to match the add
            if(cam.Key)
                cam.Key.RemoveCommandBuffer(CameraEvent.BeforeForwardOpaque, cam.Value);
        }
        m_Cameras.Clear();
    }


    void Update()
    {
        _cam.depthTextureMode = DepthTextureMode.Depth;
    }


 
    void OnEnable(){
        print("nerf");
        // _cam.targetTexture = new RenderTexture(Screen.width, Screen.height, 16, RenderTextureFormat.ARGB32);
        _cam.targetTexture = new RenderTexture(Screen.width, Screen.height, 16);
        _DepthCam.targetTexture = new RenderTexture(Screen.width, Screen.height, 16);

    }

    /*
    void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        Graphics.Blit(source, destination, _mat_Zbuffer);
 
        print("sldkfjd");
 
        // this set texture will not work if the camera targetTexture is null
        // not sure why
        _islandMat.SetTexture("_MainTex", destination);
        // _islandMat.SetTexture("_MainTex", source);

    }
    */


 
    // complicated system
    CommandBuffer m_MagicBuffer;

    RenderTexture _rt2_colors;
    RenderTexture _rt2_depth;

    public Material basicRenderMat;

    // Render texture has two buffers color[] and depth
    // the buffers are pointers to GPU data only

    int depthTexId = Shader.PropertyToID("_DepthTex");
    int colorTexId = Shader.PropertyToID("_ColorTex");
    RenderTexture _gC;
    RenderTexture _gD;

    void OnRenderImage(RenderTexture source, RenderTexture destination)
    // void OnPreRender()
    {

        Cleanup();

        // generate this onEnable and use .Clear() instead
        m_MagicBuffer = new CommandBuffer();

        m_MagicBuffer.name = "Island Depth";
        m_Cameras[_DepthCam] = m_MagicBuffer;

        if (islandObjects.Count == 0 && islandObjects != null)
        {
            BuildIslandObjects();
        }

 



        m_MagicBuffer.ClearRenderTarget(true, true, Color.green); // clear before drawing to it each frame!!

        // m_MagicBuffer.GetTemporaryRT(colorTexId, Screen.width, Screen.height);
        // m_MagicBuffer.GetTemporaryRT(depthTexId, Screen.width, Screen.height, 24,
        //         FilterMode.Point, RenderTextureFormat.Depth);
        // or try the other temporarty method
        RenderTexture _rt2_colors = RenderTexture.GetTemporary( Screen.width, Screen.height, 16, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
        RenderTexture _rt2_depth = RenderTexture.GetTemporary( Screen.width, Screen.height, 16, RenderTextureFormat.Depth);
        // or just use the normal way
        // _rt2_colors = new RenderTexture(Screen.width, Screen.height, 16, RenderTextureFormat.ARGB32);
        // _rt2_depth = new RenderTexture(Screen.width, Screen.height, 16, RenderTextureFormat.Depth);

        // m_MagicBuffer.SetRenderTarget(_rt2_colors);
        // m_MagicBuffer.SetRenderTarget(_rt2_depth);
        // m_MagicBuffer.SetRenderTarget(colorTexId);
        // m_MagicBuffer.SetRenderTarget(depthTexId);
        // what is the difference here for these two?
        _DepthCam.SetTargetBuffers(_rt2_colors.colorBuffer, _rt2_depth.depthBuffer);


        // draw all picked objects to it
        foreach(GameObject o in islandObjects)
        {
            MeshRenderer r = o.GetComponent<MeshRenderer>();
            if(r && basicRenderMat)
                // print("narf");
                m_MagicBuffer.DrawRenderer(r, basicRenderMat);
        }

        // _gC = new RenderTexture(Screen.width, Screen.height, 16, RenderTextureFormat.ARGB32);
        // _gD = new RenderTexture(Screen.width, Screen.height, 16, RenderTextureFormat.Depth);
        // Graphics.Blit here works better then m_MagicBuffer.Blit
        // this was a common finding in the forums
        // Graphics.Blit(_rt2_colors, _gC);
        // Graphics.Blit(_rt2_depth, _gD);

        // m_MagicBuffer.SetGlobalTexture("_ColorTex", colorTexId );
        // m_MagicBuffer.SetGlobalTexture("_DepthTex", depthTexId );
        m_MagicBuffer.SetGlobalTexture("_ColorTex", _rt2_colors );
        m_MagicBuffer.SetGlobalTexture("_DepthTex", _rt2_depth.depthBuffer );

        // Graphics.ExecuteCommandBuffer(m_MagicBuffer);

        // m_MagicBuffer.ReleaseTemporaryRT(colorTexId);
        // m_MagicBuffer.ReleaseTemporaryRT(depthTexId);

        _DepthCam.AddCommandBuffer(CameraEvent.BeforeForwardOpaque, m_MagicBuffer);
 
        _DepthCam.Render();

    // m_MagicBuffer.Clear();


 
    }









    //
    // build the island objects array
    //
    GameObject[] tempObjects;
    public GameObject rootIsland;
    public List<GameObject> islandObjects = new List<GameObject>();

    void BuildIslandObjects(){
        if (rootIsland != null)
        {
            islandObjects = new List<GameObject>();
     
            tempObjects = UnityEngine.Object.FindObjectsOfType<GameObject>();
     
            foreach(GameObject go in tempObjects){
                if (go.activeInHierarchy){
                    if (go.layer == LayerMask.NameToLayer("island")){
                        if (go.GetComponent<MeshRenderer>())
                        {
                            islandObjects.Add(go);
                        }
                    }
                }

            }

        }
    } // weeeeeee brackets!!!



}

The display planes debugger shader

Shader "Unlit/islandMat"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            sampler2D _CameraDepthTexture;
            sampler2D _ColorTex;
            sampler2D _DepthTex;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {

float2 uv = i.uv.xy;


// return tex2D(_ColorTex, i.uv);
// return tex2D(_DepthTex, i.uv);

float depth = 1 - Linear01Depth(SAMPLE_DEPTH_TEXTURE(_DepthTex, uv));
// float depth = SAMPLE_DEPTH_TEXTURE(_DepthTex, uv);
return fixed4(depth, depth, depth, 1);

// return 1 - Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv));


            }
            ENDCG
        }
    }
}

The Renderer() function (m_MagicBuffer.DrawRenderer(r, basicRenderMat)) passed in surface shader basic lambert, this one makes a tinge of zdepth I think… But its blocked by some invisible stuff thats not in the scene and just acts eratic
But if you replace it with a flat shader you get a flat image like a stencil

 Shader "Example/Diffuse Simple" {
    SubShader {
      Tags { "RenderType" = "Opaque" }
      CGPROGRAM
      #pragma surface surf Lambert
      struct Input {
          float4 color : COLOR;
      };
      void surf (Input IN, inout SurfaceOutput o) {
          o.Albedo = 1;
      }
      ENDCG
    }
    Fallback "Diffuse"
  }

plain shader I would like to somehow do a basic something like this
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glDepthFunc(GL_LEQUAL);
glDepthRange(0.0f, 1.0f);
with

Shader "Unlit/basicMat"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        ZWrite On
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag


            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            float4 _Color;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                return _Color;
            }
            ENDCG
        }
    }
}

I found that unity has an internal shader, but no difference made

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

// Simple "just colors" shader that's used for built-in debug visualizations,
// in the editor etc. Just outputs _Color * vertex color; and blend/Z/cull/bias
// controlled by material parameters.

Shader "Narf/Internal-ColoredZ"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _SrcBlend ("SrcBlend", Int) = 5.0 // SrcAlpha
        _DstBlend ("DstBlend", Int) = 10.0 // OneMinusSrcAlpha
        _ZWrite ("ZWrite", Int) = 1.0 // On
        _ZTest ("ZTest", Int) = 4.0 // LEqual
        _Cull ("Cull", Int) = 0.0 // Off
        _ZBias ("ZBias", Float) = 0.0
    }


    SubShader
    {
        Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
        Pass
        {
            Blend [_SrcBlend] [_DstBlend]
            ZWrite [_ZWrite]
            ZTest [_ZTest]
            Cull [_Cull]
            Offset [_ZBias], [_ZBias]

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            struct appdata_t {
                float4 vertex : POSITION;
                float4 color : COLOR;
            };
            struct v2f {
                fixed4 color : COLOR;
                float4 vertex : SV_POSITION;
            };
            float4 _Color;
            v2f vert (appdata_t v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.color = v.color * _Color;
                return o;
            }
            fixed4 frag (v2f i) : SV_Target
            {
                return i.color;
            }
            ENDCG 
        } 
    }
}

Its something to do with the shadowcaster shader pass
Ive found a thread from Writing depth value in fragment program
And I just stared at the frame debugger values

and sure enough hidden in the text is

“The shadowmap is only the depth buffer, so even the color output by the fragment shader does not really matter.”

Soooooo depthbuffer coloring is named shadowcaster < Soooo Obvious!!!<<< :eyes:

still trying to load or hack at the standard shader to just load that pass, just getting black render for objects but its different
https://forum.unity.com/threads/can-not-find-basic-shader-shadowcaster.805359/

SOLVED IT!!! Partially. It was the shadowcaster pass ill make an cleaned up example when(if) I get the second pass working found the basics for the shader for now, theres some vertex breaking thing but its fine for now

Shader "Lit/Diffuse With Shadows"
{
    Properties
    {
        [NoScaleOffset] _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
      
        // shadow casting support
        UsePass "Legacy Shaders/VertexLit/SHADOWCASTER"
    }
}

While its still not directly editing the DepthBuffer there seems to be no proper C# access to that. But there is a C access Unity - Scripting API: RenderTexture.GetNativeDepthBufferPtr

1 Like