Search Unity

Shader Transparency or Render Order Issue with Deferred Rendering

Discussion in 'General Graphics' started by PhoenixAdvanced, Aug 25, 2019.

  1. PhoenixAdvanced

    PhoenixAdvanced

    Joined:
    Sep 30, 2016
    Posts:
    316
    Hi.

    I am trying to fix a longstanding bug with a shader that I have been modifying.

    I am using a grass shader that I got from the asset store.

    It is a paid asset (I am making changes to it) so I can't post the whole thing, but the shader works fine in forward rendering, but has a strange issue in deferred rendering.

    These shader tags:

    Code (CSharp):
    1.    
    2.  
    3.  Subshader
    4.     {
    5.         Tags {"Queue" = "AlphaTest" "LightMode" = "Deferred" }
    6.         Lod 1500
    7.  
    8.     Pass
    9.         {          
    10.         Name "Deferred1"
    11.         ColorMask RGB
    12.         Cull Off
    13.      
    14.         CGPROGRAM
    15.  
    16.  
    Make the shader work in deferred mode, which looks great, but it leaves an obvious white, uncoloured area where the grass protrodes above the terrain. I am guessing this is some kind of render order issue between the grass and the sky background?

    This is how it looks:

    https://imgur.com/UQMY59w

    When I remove the Tags (Alpha Test and Lightmode), the shader runs in forward mode:


    Code (CSharp):
    1.    
    2.  
    3.  Subshader
    4.     {
    5.         Lod 1500
    6.  
    7.     Pass
    8.         {            
    9.         Name "Deferred1"
    10.         ColorMask RGB
    11.         Cull Off
    12.      
    13.         CGPROGRAM
    14.  
    15.  
    This results in the below image:

    https://imgur.com/xk5BFxU

    Which fixes the white border issue, however forward mode doesn't look nearly as good as deferred mode, so I need to fix the issue with deferred mode.

    Can anyone provide any advice as to what could be going on here? I am guessing it is an issue with shader tags, render order, etc? I have tried a lot of solutions, modifying render type, ztest, zwrite, alphatomask, blendop, etc, etc, and I can't seem to fix this.

    Thanks for any advice!
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    If I understand correctly, you're taking a shader written for forward rendering and just adding the deferred lighting tag to it?

    That won't work at all. Deferred and forward shaders are fundamental different in what they output. You would need to be rewriting far more of the shader than just adding the deferred tag to get anything useful out of it. Plus, deferred shaders should never, ever use ColorMask. If you don't understand why, I suggest you read up on deferred rendering some more.

    https://catlikecoding.com/unity/tutorials/rendering/part-13/
     
    v_d3us and dudleyhk like this.
  3. PhoenixAdvanced

    PhoenixAdvanced

    Joined:
    Sep 30, 2016
    Posts:
    316
    I think that is pretty much what I did, but it actually works great, and looks far, far better than with forward rendering only.

    For example this is deferred rendering:
    https://imgur.com/HRJLPX3

    You can see the issue that I am having on the right, the grass is transparent where it extends past the ground.

    This is the same scene in forward rendering:

    https://imgur.com/7r6dD79

    The grass renders correctly, but looks a lot worse. The golden sunlight on the grass, and the shadows, etc, look far, far better in deferred lighting mode.

    I think I have found the issue though. The background is rendering on top of the grass when I use deferred rendering. This image shows what happens when I change the background to "solid color" and set it to red:

    https://imgur.com/QMpGY7x

    You can see that most of the grass renders fine, but the part of the grass at the top right of the image has the red background rendering on top of it. This is the issue.

    So, even though what I am doing may be wrong, is it possible to fix this one issue without rewriting the entire shader?
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    There are a couple of additional things I'm guessing you've left out of what you're showing.

    I suspect the shader you're using is using transparency blending (Blend SrcAlpha OneMinusSrcAlpha), has ZWrite Off, and is normally using the Transparent queue. The first two are big no-nos for deferred, the later it's why it looks so bad when using forward. In Unity, transparent queue objects do not receive shadows, so your grass that should be getting shadowed by the terrain is instead way too bright. It’s possible the shader you’re using simply doesn’t implement shadow receiving at all even if you did use the AlphaTest queue. I also have no idea if it’s a surface shader or a vertex fragment shader that’s being used here. If the original shader is using surface shader (there’s a #pragma surface line someplace) then a lot of these settings might be getting set behind the scenes, and the Surface Shader is using the alpha or alpha:fade in that #pragma line.

    If the shader is using a surface shader, the good news is all you need to do to make the shader work properly is set the queue to AlphaTest, use alphatest:_Cutoff instead of alpha in the #pragma surface line, get rid of the ColorMask, and the surface shader should take care of the rest.

    If the shader isn’t using a surface shader, than no, there isn’t really an option apart from fully rewriting it.
     
  5. PhoenixAdvanced

    PhoenixAdvanced

    Joined:
    Sep 30, 2016
    Posts:
    316
    Hi,

    Thanks for your reply.

    It seems that it isn't using a surface shader, but vertex and fragment:

    Code (CSharp):
    1.              
    2.                 #pragma vertex vert
    3.                 #pragma hull hullShader
    4.                 #pragma domain domainShader
    5.                 #pragma geometry geom
    6.                 #pragma fragment frag
    7.  
    So I'm not sure if this is fixable.

    Is there are way to add the lighting and shading to the forward shader? The forward shader renders when I set my camera to "deferred" lighting, so would it be easier to modify the forward shader to add the advanced lighting features?
     
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Way easier to make a shader work with deferred than add shadows to a forward shader if they don’t support it already, especially once you add in geometry and tessellation (hull & domain) shader stages. See that catlike coding article I linked to. Most likely the fragment shader is already calculating most if not all of the values you need, it’s just a matter of modifying the fragment function definition to output to multiple targets, and output the proper values ... and deleting a lot of unused lighting code.
     
  7. PhoenixAdvanced

    PhoenixAdvanced

    Joined:
    Sep 30, 2016
    Posts:
    316
    Thank you very much, I am reading through that article.

    So, the issue with the background rendering on top of the grass is likely to be in the fragment shader? Is there anything in particular I could look out for?
     
  8. PhoenixAdvanced

    PhoenixAdvanced

    Joined:
    Sep 30, 2016
    Posts:
    316
    I have stepped through each of the different shaders that are used, and manually specified a colour and a transparency value at each step, but the background is still being displayed through the shader.

    These are the shaders that are loaded:

    Code (CSharp):
    1.    
    2.  
    3.             #include "UnityCG.cginc"
    4.             #include "Tessellation.cginc"
    5.             #include "UnityPBSLighting.cginc"
    6.             #include "AutoLight.cginc"
    7.             #include "UnityShaderVariables.cginc"
    8.  
    9.             #include "GrassConfig.cginc"
    10.             #include "GrassDefinitionsAndFunctions.cginc"
    11.  
    12.             #include "GrassVertex.cginc"
    13.             #include "GrassTessellation.cginc"
    14.             #include "GrassGeom.cginc"
    15.             #include "GrassSurface.cginc"
    16.             #include "GrassLighting.cginc"
    17.             #include "GrassFrag.cginc"
    18.  
    19.             ENDCG
    20.         }
    21.  
    22.  
    Is it possible that the issue isn't actually with the shader itself? That there is some other render order issue?
     
  9. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    From those files you posted I can tell what asset you're using from the store. It already has Deferred rendering support, there shouldn't be anything you need to do if you're using the correct shader from the asset for your grass. Try e-mailing the author directly.
     
  10. PhoenixAdvanced

    PhoenixAdvanced

    Joined:
    Sep 30, 2016
    Posts:
    316
    Does it really? I can't seem to find any deferred rendering option in the shaders themselves.

    It may have been added in a later version?

    I will contact the dev, thank you.