Search Unity

Resolved How to use Blitter with stencil buffer?

Discussion in 'Universal Render Pipeline' started by Kichang-Kim, Nov 24, 2022.

  1. Kichang-Kim

    Kichang-Kim

    Joined:
    Oct 19, 2010
    Posts:
    1,011
    Hi. Blitter is Unity's recommended class to blit full-screen effect. But it has no method for using stencil buffer, so you can't implement custom full-screen effect using stencil buffer.

    Is there any method for that?

    Thanks.
     
  2. bluescrn

    bluescrn

    Joined:
    Feb 25, 2013
    Posts:
    642
    You can blit with a custom material+shader (via Blitter.BlitTexture), and should be able to do whatever stencil tests/writes you want within the shader?

    What are you trying to do that seems unsupported?
     
  3. Kichang-Kim

    Kichang-Kim

    Joined:
    Oct 19, 2010
    Posts:
    1,011
    I tried to blit with my own shader, but its stencil test simply not worked. So I debugged it with RenderDoc and found that there is no depth/stencil buffer when render pass is executed. Same code did work in Unity 2021.3 and 2022.2.0b16 did not.

    I used CommandBuffer directly in ScriptableRenderPass:
    Code (CSharp):
    1. cmd.SetRenderTarget(cameraColorTarget, cameraDepthTarget);
    2. cmd.DrawProcedural(Matrix4x4.identity, _material, shaderPass: 0, MeshTopology.Triangles, 3);
     
  4. bluescrn

    bluescrn

    Joined:
    Feb 25, 2013
    Posts:
    642
    Ah, so it's not specifically a stencil issue, it's a problem with SetRenderTarget and depth buffer targets?

    I think the recommended way to do things in 2022.2 is to use RTHandle instead of RenderTargetIdentifier, and use CoreUtils.SetRenderTarget() (with RTHandle) to set the render target. Might be worth trying that, and see if it helps?
     
  5. Kichang-Kim

    Kichang-Kim

    Joined:
    Oct 19, 2010
    Posts:
    1,011
    I didn't know about CoreUtils.SetRenderTarget(). I'll try it. Thanks.
     
  6. AurochChris

    AurochChris

    Joined:
    Jan 7, 2014
    Posts:
    24
    When I was looking into this, I found some old threads from 2016 that mentioned that the Blit commands optimized out the depth/stencil testing.

    Instead, using the DepthStencil texture required you to manually blit to the screen by drawing a full-screen quad in front of the camera.

    I've tried to use the Blitter API, but I didn't have any luck (but there's a lot of methods in the Blitter API, so perhaps someone from Unity would be able to tell us if any work?) so I used the full-screen quad method instead.

    Note: you may not see the DepthStencil attachment as an input to your Blit shader in RenderDoc when you debug this, but it should work. (RenderDoc will show the DepthAttachment as an input if you use it inside your shader's fragment function IIRC and it doesn't get optimized out by the compiler.)

    Code (CSharp):
    1.  
    2.  // The render target is the cameraColorAttachment:
    3.  
    4.  public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    5.     {
    6.         CommandBuffer cmd = CommandBufferPool.Get();
    7.         using (new ProfilingScope(cmd, profilingSampler))
    8.         {
    9.             context.ExecuteCommandBuffer(cmd);
    10.             cmd.Clear();
    11.  
    12.             // If  you use Blit(cmd, source, target) functions, the renderer optimizes out the use of the Depth buffer.
    13.             // Instead we draw a fullscreen quad 1 unit in front of the camera. (Vector3.Forward = (1, 0 , 0));
    14.             // The sample code is found here: https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@12.1/manual/renderer-features/how-to-fullscreen-blit-in-xr-spi.html
    15.  
    16.             // TODO: Test various Core.Blitter API functions (such as BlitQuad) to see if this is still an issue with those.
    17.             Camera cam = renderingData.cameraData.camera;
    18.             Matrix4x4 PlaneTransform = Matrix4x4.TRS(cam.transform.TransformPoint(Vector3.forward), cam.transform.rotation, Vector3.one);
    19.             cmd.DrawMesh(RenderingUtils.fullscreenMesh, PlaneTransform, _outlineMaterial, 0, 4);
    20.         }
    21.  
    22.         context.ExecuteCommandBuffer(cmd);
    23.         CommandBufferPool.Release(cmd);
    24.     }
     
    Last edited: Nov 27, 2022
    bluescrn likes this.
  7. Kichang-Kim

    Kichang-Kim

    Joined:
    Oct 19, 2010
    Posts:
    1,011
    I found a solution for this issue. The problem is that renderer.cameraDepthTargetHandle in Execute() method is not a real camera depth buffer, but its name is cameraColorAttachment!

    And renderer.cameraDepthTargetHandle in OnCameraSetup() is actual camera depth "cameraDepthAttachment". So I captured cameraDepthTargetHandle variable from OnCameraSetup() and used it in Execute(). Now, all of stencil related shader works without any problem.
     
  8. yyysukiii

    yyysukiii

    Joined:
    Jun 13, 2020
    Posts:
    9
    Could you explain it more detailedly how to do it?