Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Deferred multi-pass with standard shader ignoring fragment pass

Discussion in 'Shaders' started by Ellenack, Feb 3, 2016.

  1. Ellenack

    Ellenack

    Joined:
    Feb 16, 2014
    Posts:
    41
    Hi ! I am having an issue with a multi pass shader. There are two pass : the first one use front culling and extrude the mesh so I have an outline, the second pass use the standard pass. There is no issue in forward rendering, but I want to use deferred rendering. And when I do so, my outline pass is completely ignored. Am I missing something ?

    Code (CSharp):
    1. Shader "Custom/ToonShader"
    2. {
    3.     Properties
    4.     {
    5.         _Color ("Color", Color) = (1,1,1,1)
    6.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
    7.         _Glossiness ("Smoothness", Range(0,1)) = 0.5
    8.         _Metallic ("Metallic", Range(0,1)) = 0.0
    9.         _Outline ("Outline Color", Color) = (1,1,1,1)
    10.         _OutlineSize ("Outline Size", Range(0,1)) = 0.0
    11.     }
    12.     SubShader
    13.     {
    14.         Pass
    15.         {
    16.             Cull Front
    17.            
    18.             CGPROGRAM
    19.             #pragma vertex vert
    20.             #pragma fragment frag
    21.  
    22.             fixed4 _Outline;
    23.             float _OutlineSize;
    24.  
    25.             struct appData
    26.             {
    27.                 float4 pos : POSITION;
    28.                 float4 nor : NORMAL;
    29.             };
    30.  
    31.             struct v2f
    32.             {
    33.                 float4 pos : SV_POSITION;
    34.             };
    35.  
    36.             v2f vert( appData i )
    37.             {
    38.                 v2f o;
    39.  
    40.                 float4 wPos = mul( _Object2World, i.pos );
    41.                 float4 wNor = mul( _Object2World, float4( i.nor.xyz, 0.0f ) );
    42.                 o.pos = mul( UNITY_MATRIX_VP, wPos + wNor * _OutlineSize );
    43.  
    44.                 return o;
    45.             }
    46.  
    47.             fixed4 frag( v2f i ) : SV_Target
    48.             {
    49.                 return _Outline;
    50.             }
    51.             ENDCG
    52.         }
    53.        
    54.         CGPROGRAM
    55.         #pragma surface surf Standard fullforwardshadows
    56.  
    57.         #pragma target 5.0
    58.  
    59.         sampler2D _MainTex;
    60.  
    61.         struct Input
    62.         {
    63.             float2 uv_MainTex;
    64.         };
    65.  
    66.         half _Glossiness;
    67.         half _Metallic;
    68.         fixed4 _Color;
    69.  
    70.         void surf (Input IN, inout SurfaceOutputStandard o)
    71.         {
    72.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    73.             o.Albedo = c.rgb;
    74.             o.Metallic = _Metallic;
    75.             o.Smoothness = _Glossiness;
    76.             o.Alpha = c.a;
    77.         }
    78.         ENDCG
    79.     }
    80.     //FallBack "Diffuse"
    81. }
    82.  
     

    Attached Files:

  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,209
    Any pass that's left unspecified is assumed to be a forward pass. If you have a shader with forward passes and deferred passes it'll ignore all of the forward passes and only do the deferred pass(es).

    It's important to understand what happens with deferred. Everything that is deferred renders first so deferred opaque, then deferred alpha test, then forward opaque, then forward alpha test, then transparent (which is always forward). If you have something that is opaque but forward rendered it's not possible to render it before the deferred pass unless you use multiple cameras and composite them together.

    However, you could just render the outline as a deferred pass as well. It's a little more involved than the forward pass version though. You'll need:

    Code (CSharp):
    1. Tags { "LightMode" = "Deferred" }
    2.  
    3. ...
    4.  
    5. void frag (
    6.     v2f i,
    7.     out half4 outDiffuse : SV_Target0,            // RT0: diffuse color (rgb), occlusion (a)
    8.     out half4 outSpecSmoothness : SV_Target1,    // RT1: spec color (rgb), smoothness (a)
    9.     out half4 outNormal : SV_Target2,            // RT2: normal (rgb), --unused, very low precision-- (a)
    10.     out half4 outEmission : SV_Target3            // RT3: emission (rgb), --unused-- (a)
    11. )
    12. {
    13.    outDiffuse = half4(0.0, 0.0, 0.0, 0.0);
    14.    outSpecSmoothness = half4(0.0, 0.0, 0.0, 1.0);
    15.    outNormal = half4(0.5, 0.5, 0.5, 1.0); // this normal might cause some weirdness if you use any post processes that use normals
    16.    outEmission = half4(_Outline.rgb, 1.0);
    17.    #ifndef UNITY_HDR_ON
    18.    outEmission.rgb = exp2(-outEmission.rgb);
    19.    #endif
    20. }
     
  3. Ellenack

    Ellenack

    Joined:
    Feb 16, 2014
    Posts:
    41
    Hi !

    Sorry for the delay in my answer. Thanks for the explanation on the rendering order of the different types of shaders, I didn't know that. :) Your solution fixed the issue, thanks a lot !
     
  4. McDev02

    McDev02

    Joined:
    Nov 22, 2010
    Posts:
    661
    It workes for the second pass but if I add this to my shader it suddenly becomes darker independently of that second pass:

    render.jpg

    Any idea? Here is the shader

    Code (CSharp):
    1. Shader "Template/Multipass Surface Fragment" {
    2.     Properties{
    3.     _MainTex("BaseMap (RGB)", 2D) = "white" {}
    4.     _Color("Main Color", Color) = (1,1,1,1)
    5.     _Color2("Secondary Color", Color) = (0,0,0,0.5)
    6.     _NormalMap1("Main Normal", 2D) = "bump" {}
    7.     _NormalMap2("Secondary Normal", 2D) = "bump" {}
    8.     }
    9.  
    10.         SubShader{
    11.         Tags{
    12.         //"LightMode" = "Deferred"
    13.         "Queue" = "Geometry-100"
    14.         "RenderType" = "Opaque"
    15.     }
    16.  
    17.         CGPROGRAM
    18. #pragma surface surf StandardSpecular vertex:vert
    19. #pragma target 3.0
    20.         // needs more than 8 texcoords
    21. #pragma exclude_renderers gles
    22. #include "UnityPBSLighting.cginc"
    23.  
    24.  
    25.     struct Input
    26.     {
    27.         float3 wPos : TEXCOORD0;
    28.     };
    29.  
    30.     sampler2D _MainTex, _NormalMap1;
    31.     half4 _Color;
    32.  
    33.     void vert(inout appdata_full v, out Input data)
    34.     {
    35.         UNITY_INITIALIZE_OUTPUT(Input, data);
    36.         float4 pos = mul(UNITY_MATRIX_MVP, v.vertex);
    37.         data.wPos = mul(_Object2World, v.vertex).xyz;
    38.     }
    39.  
    40.     void surf(Input IN, inout SurfaceOutputStandardSpecular o) {
    41.         half3 wPos = IN.wPos;
    42.  
    43.         o.Albedo = tex2D(_MainTex, wPos).rgb * _Color.rgb;
    44.         o.Normal = UnpackNormal(tex2D(_NormalMap1, wPos));
    45.         o.Smoothness = 0.3;
    46.         o.Specular = 0.2;
    47.     }
    48.  
    49.     ENDCG
    50.         //END BaseShader
    51.  
    52.  
    53.         Pass
    54.     {
    55.         Name "OverlayData"
    56.         Blend Off//SrcAlpha OneMinusSrcAlpha
    57.         CGPROGRAM
    58. #pragma vertex vert
    59. #pragma fragment frag
    60. #pragma fragmentoption ARB_precision_hint_fastest
    61. #pragma multi_compile __ LAYER_ON
    62. #include "UnityCG.cginc"
    63.  
    64.  
    65.     struct v2f {
    66.         float4 pos          : POSITION;
    67.         float2 uv           : TEXCOORD0;
    68.     };
    69.  
    70.     v2f vert(appdata_full v)
    71.     {
    72.         v2f o;
    73.         o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    74.         o.uv = v.texcoord.xy;
    75.         return o;
    76.     }
    77.  
    78.  
    79.  
    80.     half4 _Color2;
    81.     sampler2D _NormalMap2;
    82.  
    83.         void frag(
    84.             v2f i,
    85.             out half4 outDiffuse : SV_Target0            // RT0: diffuse color (rgb), occlusion (a)
    86.             //out half4 outSpecSmoothness : SV_Target1,    // RT1: spec color (rgb), smoothness (a)
    87.             //out half4 outNormal : SV_Target2,            // RT2: normal (rgb), --unused, very low precision-- (a)
    88.             //out half4 outEmission : SV_Target3            // RT3: emission (rgb), --unused-- (a)
    89.             )
    90.     {
    91.         outDiffuse = _Color2;
    92.     }
    93.  
    94.     ENDCG
    95.         //END OverlayShader
    96.     }
    97.  
    98.     //END SUBSHADER
    99.     }
    100.  
    101.         Fallback "Legacy Shaders/VertexLit"
    102. }
     
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,209
    The above applies only to pure vertex / fragment shaders. You're using a surface shader which is likely to cause undesirable effects. You also shouldn't ever be setting LightMode on a SubShader unless there's only one pass, you should be setting it on the Pass itself.
     
    McDev02 likes this.