Search Unity

How to get the depth buffer after Graphics.DrawProcedural in OnRenderObject?

Discussion in 'General Graphics' started by PsyDev, Dec 4, 2015.

  1. PsyDev


    Sep 30, 2015
    I am trying to get a depth buffer for use in a post-processing effect. As I understand it, the camera's depth buffer gets written into in the ShadowCaster pipeline pass. By the time OnRenderObject is called, the usual rendering pipeline has finished, so ShadowCaster pass in not called when I do Graphics.DrawProcedural, even by including a Fallback "Diffuse" that does have a ShadowCaster pass. So the camera's depth buffer does not get written to.

    When I say "the camera's depth buffer", I'm referring to what gets returned by
    float depth = -LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, input.texCoords));

    Something is keeping track of the depth of the objects rendered by Graphics.DrawProcedural in OnRenderObject, because they draw in the correct depth order. Is there another depth buffer, separate from what gets returned by the above depth texture? How can I get access to it?

    As an alternative, I experimented with Render Targets, attempting to write into my own depth buffer. I don't want to do two draw calls though, one into the main window and then another into my own render texture. I'd like to be able to draw into the main windows color buffer, and into my own depth buffer. But I can't figure out how to do that either. is null, which from the docs I think is expected: "If the active RenderTexture is null everything is rendered in the main window.". This approach seems wrong anyway, because there must be a depth buffer somewhere when Graphics.DrawProcedural is called.

    And last option I can think of is to somehow inject the Graphics.DrawProcedural into the middle of the rendering pipeline, rather than at the end in OnRenderObject. I've only just touched the tip of the iceberg with Command Buffers, so I don't know if this is possible or not.

    Any advice would be greatly appreciated.
  2. PsyDev


    Sep 30, 2015
    I am not having any success trying to manually grab the depth. I tried the alternative mentioned above, setting a Render Target before DrawProcedural but it is not rendering into the target. Resulting render texture is empty.

    As a test to verify DrawProcedural does work at all with render textures, I created a second camera, set the render texture as the target, and dragged the render texture onto a plane in the scene. That does work. The objects from DrawProcedural show up in render texture. Seems setting the render target in OnObjectRender or manually in code is the problem.

    After dragging a render texture into a public variable in the editor, here is the code I'm using:

    void OnRenderObject()
    Graphics.DrawProcedural(MeshTopology.Triangles, 3, 1);

    Graphics.DrawProcedural(MeshTopology.Triangles, 3, 1);

    Seems others have hit a dead end on this topic:

    and @Simon Duan

    This seems silly. There is a depth buffer somewhere that is being written into, or else the objects behind would draw over others in front. How do I get access to it?
  3. trek7


    Feb 8, 2015
    Same question...
  4. delpino


    Nov 24, 2014
    I had the same problem and solved it using CommandBuffers executed AfterGBuffer. (Camera Rendering path : deferred)

    Camera.current.depthTextureMode = DepthTextureMode.Depth;
    cam.AddCommandBuffer(CameraEvent.AfterGBuffer, comBuf);
    comBuf.DrawProcedural(Matrix4x4.identity, material, 0, MeshTopology.Points, nbPts);

    The z-buffer was eventually filled.
  5. PsyDev


    Sep 30, 2015
    Interesting. Thanks for the reply. I'll revisit that sometime soon.
  6. RibsNGibs


    Jun 17, 2016
    Hi, I saw your post on Unity answers and followed it here. Did you find an answer? I'm not sure I'm having the same problem you are having, but maybe. I have a cut-out billboard shader (where I'm moving the points in the vert shader to face the camera and then drawing a texture) and it sure looks like it's writing to the Z buffer correctly (things in front and behind look sorted coorectly), but it doesn't show up when I try to sample _CameraDepthTexture it's not there (so my custom fog shader which samples depth doesn't see my billboard object.)

    I tried the Fallback "Diffuse" line and that does start drawing to the depth texture (and also now casts and receives shadows), but while the billboard color and alpha is correct, the depth that gets written is of the non-camera-facing, non-cutout quad that I originally threw the material on since my custom vert and frag shader aren't getting called anymore. Anyway, I was wondering if you figured out any elegant solution where the depth texture just gets written out correctly...
  7. PsyDev


    Sep 30, 2015
    Sorry, I don't have a solution. I actually haven't looked at it in quite a while. I am going to try using command buffers as suggested above when I do get back to it.
  8. foxes


    Oct 9, 2015
    I tried to make an example for the test but it does not work. I think DrawProcedural is not called.
    Work only on Deferred Render Path. But there is a detail, if the background is clean but the object is not visible. Displayed on the background of other objects.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Rendering;
    6. public class DrawTest2 : MonoBehaviour {
    8.   public Material testMat;
    10.   void Start () {
    11.     Camera.main.depthTextureMode = DepthTextureMode.Depth;
    12.     CommandBuffer com = new CommandBuffer();
    13.     Camera.main.AddCommandBuffer(CameraEvent.AfterGBuffer,com);
    14.     com.DrawProcedural(Matrix4x4.identity, testMat, 0, MeshTopology.Points, 1, 1);
    15.   }
    16. }
    Last edited: Sep 18, 2017