Search Unity

[Solved] Weird lighting glitch when using deferred rendering path & default terrain

Discussion in 'General Graphics' started by xVergilx, Jan 23, 2018.

  1. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    I'm trying to make a simple "night" scene, but for some weird reasons shadows are completely screwed when using deferred rendering path.

    This is on Unity 2017.3.0f3.
    Here's two screenshots of same scene spot, taken with realtime shadows. Terrain size is 3000x3000. Only one directional light source is used:

    Lighting settings:
    lighting_settings.PNG

    Sun:
    light.PNG

    Deferred:
    shadows issue (deffered).PNG

    Legacy deferred:
    shadows issue (legacy deffered).PNG

    However, when legacy deferred used - it's completely fine. I've tried bumping shadow draw distance and tweaking terrain distance settings, but it seems they've no effect at all. I've also tried building and running scene and got same result as above.

    I wonder, what could cause this? Default terrain shaders or something else?
     
    Last edited: Jan 23, 2018
  2. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Ok, so I've tested a bit, and figured that this was caused by default terrain shader. Changing terrain material to a custom one solves half of the problem (weird shadow artefacts in the distance), but doesn't fix shadow draw distance issue.
     
  3. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    My solution to this was previously switching to Legacy Deffered, which solved all my problems, except it's wrong rendering path for my current tasks.

    So, after a long time, I've decided to dig into terrain shader, to find out what's wrong with the default deffered path:

    I've got night scene.
    upload_2018-7-15_13-34-31.png
    (Please ignore terrain being completely lame, it's background)

    Terrain has default Nature/Terrain/Diffuse shader attached to it.
    As you can see, it's completely messed up by yellow "lights", but as it turns out - lights has nothing to do with this.

    Here's what's causing this artifact - it's SplatmapFinalGBuffer function in TerrainSplatmapCommon.cginc, which has the following:
    Code (CSharp):
    1. void SplatmapFinalGBuffer(Input IN, TERRAIN_SURFACE_OUTPUT o, inout half4 outGBuffer0, inout half4 outGBuffer1, inout half4 outGBuffer2, inout half4 emission)
    2. {
    3.     UnityStandardDataApplyWeightToGbuffer(outGBuffer0, outGBuffer1, outGBuffer2, o.Alpha);
    4.     emission *= o.Alpha;
    5. }
    That emision is the cause.

    Same scene, but without it:
    upload_2018-7-15_13-32-54.png
    Code (CSharp):
    1. void SplatmapFinalGBuffer(Input IN, TERRAIN_SURFACE_OUTPUT o, inout half4 outGBuffer0, inout half4 outGBuffer1, inout half4 outGBuffer2, inout half4 emission)
    2. {
    3.     UnityStandardDataApplyWeightToGbuffer(outGBuffer0, outGBuffer1, outGBuffer2, o.Alpha);
    4. }
    I pretty newbish when it comes to shaders, can anyone explain me why the emission multiplication is there?
    Is it a bug, or some weird "visual improvement"?

    This is Unity 2018.2f2 by the way.

    P.s. Finally I will be able to use deffered path. Should've looked the shader sources earlier.
     
    Last edited: Dec 15, 2018
    Romaleks360 likes this.
  4. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    For those who's interested in same terrain shader mod.
    Here's also .cginc file (extension not allowed for upload):

    Code (CSharp):
    1. // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
    2.  
    3. #ifndef CUSTOM_TERRAIN_SPLATMAP_COMMON_CGINC_INCLUDED
    4. #define CUSTOM_TERRAIN_SPLATMAP_COMMON_CGINC_INCLUDED
    5.  
    6. struct Input
    7. {
    8.     float2 uv_Splat0 : TEXCOORD0;
    9.     float2 uv_Splat1 : TEXCOORD1;
    10.     float2 uv_Splat2 : TEXCOORD2;
    11.     float2 uv_Splat3 : TEXCOORD3;
    12.     float2 tc_Control : TEXCOORD4;  // Not prefixing '_Contorl' with 'uv' allows a tighter packing of interpolators, which is necessary to support directional lightmap.
    13.     UNITY_FOG_COORDS(5)
    14. };
    15.  
    16. sampler2D _Control;
    17. float4 _Control_ST;
    18. sampler2D _Splat0,_Splat1,_Splat2,_Splat3;
    19.  
    20. #ifdef _TERRAIN_NORMAL_MAP
    21.     sampler2D _Normal0, _Normal1, _Normal2, _Normal3;
    22. #endif
    23.  
    24. void SplatmapVert(inout appdata_full v, out Input data)
    25. {
    26.     UNITY_INITIALIZE_OUTPUT(Input, data);
    27.     data.tc_Control = TRANSFORM_TEX(v.texcoord, _Control);  // Need to manually transform uv here, as we choose not to use 'uv' prefix for this texcoord.
    28.     float4 pos = UnityObjectToClipPos(v.vertex);
    29.     UNITY_TRANSFER_FOG(data, pos);
    30.  
    31. #ifdef _TERRAIN_NORMAL_MAP
    32.     v.tangent.xyz = cross(v.normal, float3(0,0,1));
    33.     v.tangent.w = -1;
    34. #endif
    35. }
    36.  
    37. #ifdef TERRAIN_STANDARD_SHADER
    38. void SplatmapMix(Input IN, half4 defaultAlpha, out half4 splat_control, out half weight, out fixed4 mixedDiffuse, inout fixed3 mixedNormal)
    39. #else
    40. void SplatmapMix(Input IN, out half4 splat_control, out half weight, out fixed4 mixedDiffuse, inout fixed3 mixedNormal)
    41. #endif
    42. {
    43.     splat_control = tex2D(_Control, IN.tc_Control);
    44.     weight = dot(splat_control, half4(1,1,1,1));
    45.  
    46.     #if !defined(SHADER_API_MOBILE) && defined(TERRAIN_SPLAT_ADDPASS)
    47.         clip(weight == 0.0f ? -1 : 1);
    48.     #endif
    49.  
    50.     // Normalize weights before lighting and restore weights in final modifier functions so that the overal
    51.     // lighting result can be correctly weighted.
    52.     splat_control /= (weight + 1e-3f);
    53.  
    54.     mixedDiffuse = 0.0f;
    55.     #ifdef TERRAIN_STANDARD_SHADER
    56.         mixedDiffuse += splat_control.r * tex2D(_Splat0, IN.uv_Splat0) * half4(1.0, 1.0, 1.0, defaultAlpha.r);
    57.         mixedDiffuse += splat_control.g * tex2D(_Splat1, IN.uv_Splat1) * half4(1.0, 1.0, 1.0, defaultAlpha.g);
    58.         mixedDiffuse += splat_control.b * tex2D(_Splat2, IN.uv_Splat2) * half4(1.0, 1.0, 1.0, defaultAlpha.b);
    59.         mixedDiffuse += splat_control.a * tex2D(_Splat3, IN.uv_Splat3) * half4(1.0, 1.0, 1.0, defaultAlpha.a);
    60.     #else
    61.         mixedDiffuse += splat_control.r * tex2D(_Splat0, IN.uv_Splat0);
    62.         mixedDiffuse += splat_control.g * tex2D(_Splat1, IN.uv_Splat1);
    63.         mixedDiffuse += splat_control.b * tex2D(_Splat2, IN.uv_Splat2);
    64.         mixedDiffuse += splat_control.a * tex2D(_Splat3, IN.uv_Splat3);
    65.     #endif
    66.  
    67.     #ifdef _TERRAIN_NORMAL_MAP
    68.         fixed4 nrm = 0.0f;
    69.         nrm += splat_control.r * tex2D(_Normal0, IN.uv_Splat0);
    70.         nrm += splat_control.g * tex2D(_Normal1, IN.uv_Splat1);
    71.         nrm += splat_control.b * tex2D(_Normal2, IN.uv_Splat2);
    72.         nrm += splat_control.a * tex2D(_Normal3, IN.uv_Splat3);
    73.         mixedNormal = UnpackNormal(nrm);
    74.     #endif
    75. }
    76.  
    77. #ifndef TERRAIN_SURFACE_OUTPUT
    78.     #define TERRAIN_SURFACE_OUTPUT SurfaceOutput
    79. #endif
    80.  
    81. void SplatmapFinalColor(Input IN, TERRAIN_SURFACE_OUTPUT o, inout fixed4 color)
    82. {
    83.     color *= o.Alpha;
    84.     #ifdef TERRAIN_SPLAT_ADDPASS
    85.         UNITY_APPLY_FOG_COLOR(IN.fogCoord, color, fixed4(0,0,0,0));
    86.     #else
    87.         UNITY_APPLY_FOG(IN.fogCoord, color);
    88.     #endif
    89. }
    90.  
    91. void SplatmapFinalPrepass(Input IN, TERRAIN_SURFACE_OUTPUT o, inout fixed4 normalSpec)
    92. {
    93.     normalSpec *= o.Alpha;
    94. }
    95.  
    96. void SplatmapFinalGBuffer(Input IN, TERRAIN_SURFACE_OUTPUT o, inout half4 outGBuffer0, inout half4 outGBuffer1, inout half4 outGBuffer2, inout half4 emission)
    97. {
    98.     UnityStandardDataApplyWeightToGbuffer(outGBuffer0, outGBuffer1, outGBuffer2, o.Alpha);
    99.     //emission *= o.Alpha;
    100. }
    101.  
    102. #endif // CUSTOM_TERRAIN_SPLATMAP_COMMON_CGINC_INCLUDED
    103.  
    How to use:
    1. Place both files under Assets;
    2. Create a new material, set shader to Custom -> Nature -> Terrain Diffuse
    3. Set material to custom one, under terrain settings.
     

    Attached Files:

    SomeGuy22 and Tiz010 like this.
  5. Tiz010

    Tiz010

    Joined:
    Jan 27, 2014
    Posts:
    7
    Very useful, i had a similar problem and this solution worked.
    You should submit a bug report (still present in unity 2018.3.02f)
     
  6. Quakeulf

    Quakeulf

    Joined:
    Mar 26, 2013
    Posts:
    40
    Yes, a bug report would be nice. I suffer greatly with vertex displacement in Deferred lighting.
     
  7. Finneganmac

    Finneganmac

    Joined:
    Oct 31, 2020
    Posts:
    2
    Wanted to contribute to this ancient thread, the issue I was having looks like this:

    upload_2023-1-12_17-55-52.png


    To fix this, go int your terrain component, click Terrain Settings under the Terrain component, and increase your Pixel Error slider until it looks like it should.


    Screenshot 2023-01-12 175723.png



    Here's what mine looks like after maxing it out:

    upload_2023-1-12_17-58-22.png


    Hope this helps, it should be noted I am just a guy that drags sliders around until it fixes my problem so I have no idea if this is horrid for optimization or things like that, but it does work.