Search Unity

Question Shader not receiving Normal Bias offset.

Discussion in 'Shaders' started by R4s3tsu, Aug 8, 2020.

  1. R4s3tsu

    R4s3tsu

    Joined:
    Mar 21, 2020
    Posts:
    13
    Hello there, can shader sirs help me with some problem with custom lighting pass shader?
    I'm implementing a screen space sss for the skin, both forward+deferred paths, so need to use custom lighting pass, which is vertex frag shader, but I've got a problem with it, looks like it's not receiving the normal bias offset from the light settings, causing shadow acne. I'm not much familiar with hlsl and especially vertex frag shaders, but I've got
    TRANSFER_SHADOW_CASTER_NORMALOFFSET(o) which should be responspible for that for some reason but not.



    Code (CSharp):
    1. Shader "Hidden/LightingPass"
    2. {
    3.     Properties
    4.     {
    5.         _Color ("Main Color", Color) = (1,1,1,1)
    6.         _MainTex ("Base (RGB)", 2D) = "white" {}
    7.         _Cutoff("Mask Clip Value", Float) = 0.5
    8.         [HideInInspector] __dirty("", Int) = 1
    9.  
    10.     }
    11.  
    12.     //SSS pass
    13.     SubShader
    14.     {
    15.         //Tags { "RenderType" = "SSS" }
    16.         Tags { "RenderType" = "Opaque" }
    17.         LOD 100
    18.    
    19.         CGPROGRAM
    20.         //SSS_LightingPass
    21.         #pragma surface surf SSS_LightingPass vertex:vert fullforwardshadows nometa nodynlightmap nodirlightmap nofog noshadowmask
    22.         #pragma target 3.0
    23.         #include "../Resources/SSS_Common.hlsl"
    24.         #pragma multi_compile _ TRANSMISSION
    25.         #pragma multi_compile _ SUBSURFACE_ALBEDO
    26.         #pragma multi_compile _ ENABLE_ALPHA_TEST
    27.  
    28.  
    29.         half _Cutoff;
    30.  
    31.     struct Input {
    32.         float2 uv_MainTex;
    33.         float3 worldNormal;
    34.         float4 screenPos;
    35.  
    36.         INTERNAL_DATA
    37.     };
    38.  
    39.     struct DataStructure
    40.     {
    41.         fixed3 Albedo;  // diffuse color
    42.         fixed3 Normal;  // tangent space normal, if written
    43.         fixed3 Emission;
    44.         fixed Alpha;
    45.         fixed3 Occlusion;
    46.         fixed Glossiness;
    47.         fixed3 Transmission;
    48.         fixed2 screenUV;
    49.     };
    50.  
    51.     void vert(inout appdata_full v, out Input o)
    52.     {
    53.     UNITY_INITIALIZE_OUTPUT(Input, o);  
    54.     //experimental
    55.     //v.vertex.xyz += v.normal * .0001;
    56.     }
    57.     half4 LightingSSS_LightingPass(DataStructure s, half3 lightDir, half3 viewDir, half atten)
    58.     {
    59.     #if defined (__INTELLISENSE__)
    60.     #define TRANSMISSION
    61.     #endif
    62.  
    63.     half NdotL = max(0.0, dot(lightDir, s.Normal));
    64.     half3 Lighting = atten * _LightColor0.rgb;
    65.  
    66.     half3 Diffuse = Lighting * NdotL * s.Albedo;
    67.        
    68.     //return float4(Lighting, atten);
    69.     //#ifdef TRANSMISSION
    70.     Diffuse += ADDITIVE_PASS_TRANSMISSION
    71.     //#endif
    72.     //return saturate (dot(normalize(viewDir), normalize(-lightDir)));
    73.     return float4(Diffuse, 1);
    74.            
    75.     }
    76.  
    77.     // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
    78.         // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
    79.         // #pragma instancing_options assumeuniformscaling
    80.         UNITY_INSTANCING_BUFFER_START(Props)
    81.             // put more per-instance properties here
    82.         UNITY_INSTANCING_BUFFER_END(Props)
    83.  
    84.     void surf (Input IN, inout DataStructure o)
    85.     {
    86.     //if (SSS_shader != 1)discard;
    87.     #if defined (__INTELLISENSE__)
    88.     #define TRANSMISSION
    89.     #endif
    90.  
    91.     half2 uv = IN.uv_MainTex;
    92.    
    93.     SSS_OCCLUSION
    94.  
    95.     _Color.rgb *= lerp(1.0, tex2D(_SubsurfaceAlbedo, uv).rgb, _SubsurfaceAlbedoOpacity);
    96.  
    97.     float3 MainTex = 0, Final = 0;
    98.     if (SSS_shader != 1)
    99.     Final = 0;
    100.     else
    101.     Final = _Color.rgb * OcclusionColored.rgb;
    102.    
    103.     #ifdef ENABLE_ALPHA_TEST
    104.     clip(tex2D(_MainTex, IN.uv_MainTex).a - _Cutoff);
    105.     #endif
    106.  
    107.     o.Albedo =  Final;
    108.     o.Alpha = 1;
    109.     o.Normal = BumpMap(uv);
    110.     float3 Emission = 0;
    111.     #ifdef TRANSMISSION
    112.     BASE_TRANSMISSION
    113.     #endif
    114.     o.Emission = Emission;
    115.     float4 coords = UNITY_PROJ_COORD(IN.screenPos);
    116.     coords.w += 1e-9f;
    117.     float2 screenUV = coords.xy / coords.w;
    118.     o.screenUV = screenUV;
    119.     }
    120.     ENDCG
    121.     }
    122.  
    123.     SubShader
    124.     {
    125.         Tags{ "RenderType" = "TransparentCutout" "LightMode" = "ShadowCaster"}
    126.  
    127.         CGPROGRAM
    128.         #pragma target 3.0
    129.         #pragma surface surf Unlit  addshadow fullforwardshadows noshadow noambient novertexlights nolightmap  nodynlightmap nodirlightmap nofog nometa noforwardadd
    130.  
    131.  
    132.         sampler2D _MainTex;
    133.         fixed4 _Color;
    134.  
    135.         struct Input {
    136.             float2 uv_MainTex;
    137. };
    138.         uniform float _Cutoff = 0.94;
    139.         inline half4 LightingUnlit(SurfaceOutput s, half3 lightDir, half atten)
    140.         {
    141.             return half4 (0, 0, 0, s.Alpha);
    142.         }
    143.         void surf(Input i , inout SurfaceOutput o)
    144.         {
    145.             fixed4 c = tex2D(_MainTex, i.uv_MainTex) * _Color;
    146.             o.Albedo = 0;
    147.             o.Alpha = c.a;
    148.             clip(c.a - _Cutoff);
    149.         }
    150.  
    151.         ENDCG
    152.        
    153.         }
    154.  
    155.     //Transparent Shadows pass
    156.     SubShader
    157. {
    158.     Tags{ "RenderType" = "Transparent" }
    159.  
    160.  
    161.     Pass
    162.     {
    163.         Name "ShadowCaster"
    164.         Tags{ "LightMode" = "ShadowCaster" }
    165.         ZWrite On
    166.         CGPROGRAM
    167.         #pragma vertex vert
    168.         #pragma fragment frag
    169.         #pragma target 3.0
    170.         #pragma multi_compile_shadowcaster
    171.         #pragma multi_compile UNITY_PASS_SHADOWCASTER
    172.         #pragma skip_variants FOG_LINEAR FOG_EXP FOG_EXP2
    173.         #include "HLSLSupport.cginc"
    174.         #if ( SHADER_API_D3D11 || SHADER_API_GLCORE || SHADER_API_GLES || SHADER_API_GLES3 || SHADER_API_METAL || SHADER_API_VULKAN )
    175.             #define CAN_SKIP_VPOS
    176.         #endif
    177.         #include "UnityCG.cginc"
    178.         #include "Lighting.cginc"
    179.         #include "UnityPBSLighting.cginc"
    180.         sampler3D _DitherMaskLOD;
    181.         struct v2f
    182.         {
    183.             V2F_SHADOW_CASTER;
    184.             float2 customPack1 : TEXCOORD1;
    185.             float3 worldPos : TEXCOORD2;
    186.             UNITY_VERTEX_INPUT_INSTANCE_ID
    187.         };
    188.         struct Input
    189.     {
    190.         float2 uv_MainTex;
    191.  
    192.     };
    193.         v2f vert(appdata_full v)
    194.         {
    195.             v2f o;
    196.             UNITY_SETUP_INSTANCE_ID(v);
    197.             UNITY_INITIALIZE_OUTPUT(v2f, o);
    198.             UNITY_TRANSFER_INSTANCE_ID(v, o);
    199.             Input customInputData;
    200.             float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    201.             half3 worldNormal = UnityObjectToWorldNormal(v.normal);
    202.             o.customPack1.xy = customInputData.uv_MainTex;
    203.             o.customPack1.xy = v.texcoord;
    204.             o.worldPos = worldPos;
    205.             TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
    206.             return o;
    207.         }
    208.  
    209.         sampler2D _MainTex;
    210.         uniform float4 _MainTex_ST;
    211.     fixed4 _Color;
    212.         void surf(Input i , inout SurfaceOutputStandard o)
    213.     {
    214.         fixed4 c = tex2D(_MainTex, i.uv_MainTex* _MainTex_ST.xy + _MainTex_ST.zw) * _Color;
    215.         o.Albedo = c.rgb;
    216.         o.Alpha = c.a;
    217.  
    218.     }
    219.  
    220.         half4 frag(v2f IN
    221.         #if !defined( CAN_SKIP_VPOS )
    222.         , UNITY_VPOS_TYPE vpos : VPOS
    223.         #endif
    224.         ) : SV_Target
    225.         {
    226.             UNITY_SETUP_INSTANCE_ID(IN);
    227.             Input surfIN;
    228.             UNITY_INITIALIZE_OUTPUT(Input, surfIN);
    229.             surfIN.uv_MainTex = IN.customPack1.xy;
    230.             float3 worldPos = IN.worldPos;
    231.             half3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
    232.             SurfaceOutputStandard o;
    233.             UNITY_INITIALIZE_OUTPUT(SurfaceOutputStandard, o)
    234.             surf(surfIN, o);
    235.             #if defined( CAN_SKIP_VPOS )
    236.             float2 vpos = IN.pos;
    237.             #endif
    238.             half alphaRef = tex3D(_DitherMaskLOD, float3(vpos.xy * 0.25, o.Alpha * 0.9375)).a;
    239.             clip(alphaRef - 0.01);
    240.             SHADOW_CASTER_FRAGMENT(IN)
    241.         }
    242.         ENDCG
    243.     }
    244. }
    245.  
    246. Fallback "Legacy Shaders/VertexLit"
    247.  
    248.    
    249. }
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    The shadowcaster pass(es?) you have in your shader aren't being used at all, because they're in separate
    SubShader
    s. If you have a shader file with multiple
    SubShader
    s only the first one the current platform / GPU can use will be used and all others will be ignored. You want to define multiple shader passes within a single
    SubShader
    using a
    Pass
    to separate them, not multiple
    SubShader
    s with their own
    Pass
    . You also can't define multiple
    RenderQueue
    or
    RenderType
    tags in the same shader, only the first one will ever be used from the
    SubShader
    . And you can't use the
    "LightMode"
    in a
    SubShader
    , only inside a
    Pass
    . And you can't make a Surface Shader that is only a shadow caster, because Surface Shaders generate multiple passes with their own
    "LightMode"
    flags assigned.

    However none of that really matters, as the issue here isn't so much that the bias isn't working, it is working exactly as it should since your shader is using the built in shadow caster pass from the
    Fallback
    you have defined. The issue is any shader that has "wrap" style lighting, or more specifically any shader that has lighting from a specific light extend to where the surface normal is facing away from the light direction, will start to show artifacts like this. These are shadow map artifacts that are usually hidden by the lighting. The fix is to increase the bias much higher, or just live with the artifacts.