Search Unity

Custom Shader doesn't fill depth and normals for post processing?

Discussion in 'Shaders' started by ClosingTime, Aug 14, 2021.

  1. ClosingTime

    ClosingTime

    Joined:
    Nov 23, 2016
    Posts:
    241
    Hi,

    I am trying to use PPv2 with the built in Render Pipeline.
    This works with objects that use the standards surface shader.
    But it doesn't work with my custom non surface shaders.
    They just don't draw into the depth of the PP or the deferred method.
    Is there a way to make my custom shader render the depth and normals output?
     
    Brodal likes this.
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    The depth and normals texture is generated in one of two ways.

    If you’re using the forward rendering path, the camera depth normals texture is created by rendering opaque queue objects using the Internal-DepthNormalsTexture.shader. The
    “RenderType”
    tag is matched between the shader used by each mesh, and the render type on the
    SubShader
    s in that internal shader. If you do not have a
    “RenderType”
    in your shader’s
    Tags
    , or have a type that’s not in that internal shader, it won’t be rendered.

    Deferred is a little more straightforward. If your shader isn’t using a Standard shader, it won’t appear in the normals, though can appear in the depth. If you use a Surface Shader with the Standard, Blinn Phong, or Lambert shading model, then it should work since when using deferred the later two options are emulated with the Standard shading model. This is because deferred only supports the Standard shading model. Understand the way deferred works is by rendering the surface properties, Albedo, Normal, Specular Color, Smoothness, AO, depth and ambient lighting, to multiple screen space textures called GBuffers. The camera depth normal texture is then constructed from the depth and normal data in those textures (though you’re better off using the normal gbuffer itself as it’s much higher quality). If you use a Surface Shader with a custom shading model, or an vertex fragment shader with no deferred pass, it’ll be rendered as a forward pass after the deferred pass, and thus won’t appear in the normals texture at all. It instead uses the shadow caster pass (which might come from a
    Fallback
    in your shader) to render to the GBuffers, filling all but the depth with black. And that’s the best you get.

    Unity could have done some extra work to add a special deferred-for-forward pass just to inject surface properties into the GBuffers for opaque forward shaders, it they did not. You can do it yourself though, either by using two separate materials on one or two identical mesh renderers where one is a using the Standard shader and one is your custom shader, or using command buffers to render a custom deferred shader into the GBuffers. And it does have to be two separate materials, because Unity will only render the deferred or the forward passes in a shader, not both. It’s kind of an ugly solution, but it is the only one that exists for the BIRP.


    TLDR: Try adding a shadow caster pass.
     
    ClosingTime likes this.
  3. ClosingTime

    ClosingTime

    Joined:
    Nov 23, 2016
    Posts:
    241
    I was able to solve this, thanks.
    You need another pass in your shader that has this tag => Tags {"LightMode"="ShadowCaster"}

    I found the solution on this forum post:

    https://forum.unity.com/threads/writing-to-depth-buffer-with-custom-shader.217814/

    I am not entirely sure when it's deferred and when it's forward.
    But I guess, deferred use more than just Depth and Normal. So it must be Forward?

    The issue with using Surface shader, is that I don't think I can deform the vertices in a vertex shader like I do with Forward.
    For the PPv2, I was able to deform the vertices for the depth pass for ShadowCaster.
    Currently I use PPv2 only for Ambient Occlusion, I am not sure how much I am happy about it, but it works.
    Not sure in terms of how it looks, and how it performs.
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    You absolutely can. Almost anything you can do with a vertex fragment shader you can do with a Surface Shader when it comes to vertex manipulation.

    And vertex fragment shaders are used for both forward and deferred rendering. Surface Shaders are just vertex fragment shader generators. For deferred you use a
    "LightMode"="Deferred"
    pass, and for forward you use
    "ForwardBase"
    and
    "ForwardAdd"
    .