Search Unity

GPU Instancing + LOD Crossfade Error

Discussion in 'Shaders' started by flogelz, Feb 25, 2020.

  1. flogelz

    flogelz

    Joined:
    Aug 10, 2018
    Posts:
    142
    I recently noticed that instancing seems to break the LOD Crossfading when switching Lods. The shader is just the standard one, with the crossfade pragma activated. When not setting the checkbox for instancing on the material, everything works fine.

    As soon as gpu instancing is on, there appears to be a weird pop effect, which shouldn't be there. Has somebody an idea on how to get rid of this error?

    In the first half gpu instancing is off, while in the second half it's on:

    InstancingCrossfade_GIF1.gif
     
  2. flogelz

    flogelz

    Joined:
    Aug 10, 2018
    Posts:
    142
    Nobody knows a solution for this? Maybe i should post a bug report then.
     
  3. Philip_Zhang

    Philip_Zhang

    Joined:
    Feb 15, 2017
    Posts:
    25
    Hi, there shouldn't be a problem using gpu instancing with lod crossfade. I recently modified my shader to enable lod crossfade and I noticed similar pop effect like yours, but I then noticed that I put the UNITY_SETUP_INSTANCE_ID(IN); after UNITY_APPLY_DITHER_CROSSFADE(IN.vpos);
    So you should probably check if your shader code looks like this:
    UNITY_SETUP_INSTANCE_ID(IN);
    UNITY_APPLY_DITHER_CROSSFADE(IN.vpos);
     
    flogelz likes this.
  4. flogelz

    flogelz

    Joined:
    Aug 10, 2018
    Posts:
    142
    @Philip_Zhang Thanks for the tip! Gonna try it out, when i work on the shader again!
     
  5. Monil

    Monil

    Joined:
    Apr 24, 2012
    Posts:
    102
    Hi,

    I edited .cginc as recommended in the previous post, but I still have some problem with the shadows, can someone help me?



    This is UnityStandardShadow.cginc:


    Code (CSharp):
    1. // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
    2.  
    3. #ifndef UNITY_STANDARD_SHADOW_INCLUDED
    4. #define UNITY_STANDARD_SHADOW_INCLUDED
    5.  
    6. // NOTE: had to split shadow functions into separate file,
    7. // otherwise compiler gives trouble with LIGHTING_COORDS macro (in UnityStandardCore.cginc)
    8.  
    9.  
    10. #include "UnityCG.cginc"
    11. #include "UnityShaderVariables.cginc"
    12. #include "UnityStandardConfig.cginc"
    13. #include "UnityStandardUtils.cginc"
    14.  
    15. #if (defined(_ALPHABLEND_ON) || defined(_ALPHAPREMULTIPLY_ON)) && defined(UNITY_USE_DITHER_MASK_FOR_ALPHABLENDED_SHADOWS)
    16.     #define UNITY_STANDARD_USE_DITHER_MASK 1
    17. #endif
    18.  
    19. // Need to output UVs in shadow caster, since we need to sample texture and do clip/dithering based on it
    20. #if defined(_ALPHATEST_ON) || defined(_ALPHABLEND_ON) || defined(_ALPHAPREMULTIPLY_ON)
    21. #define UNITY_STANDARD_USE_SHADOW_UVS 1
    22. #endif
    23.  
    24. // Has a non-empty shadow caster output struct (it's an error to have empty structs on some platforms...)
    25. #if !defined(V2F_SHADOW_CASTER_NOPOS_IS_EMPTY) || defined(UNITY_STANDARD_USE_SHADOW_UVS)
    26. #define UNITY_STANDARD_USE_SHADOW_OUTPUT_STRUCT 1
    27. #endif
    28.  
    29. #ifdef UNITY_STEREO_INSTANCING_ENABLED
    30. #define UNITY_STANDARD_USE_STEREO_SHADOW_OUTPUT_STRUCT 1
    31. #endif
    32.  
    33.  
    34. half4       _Color;
    35. half        _Cutoff;
    36. sampler2D   _MainTex;
    37. float4      _MainTex_ST;
    38. #ifdef UNITY_STANDARD_USE_DITHER_MASK
    39. sampler3D   _DitherMaskLOD;
    40. #endif
    41.  
    42. // Handle PremultipliedAlpha from Fade or Transparent shading mode
    43. half4       _SpecColor;
    44. half        _Metallic;
    45. #ifdef _SPECGLOSSMAP
    46. sampler2D   _SpecGlossMap;
    47. #endif
    48. #ifdef _METALLICGLOSSMAP
    49. sampler2D   _MetallicGlossMap;
    50. #endif
    51.  
    52. #if defined(UNITY_STANDARD_USE_SHADOW_UVS) && defined(_PARALLAXMAP)
    53. sampler2D   _ParallaxMap;
    54. half        _Parallax;
    55. #endif
    56.  
    57. half MetallicSetup_ShadowGetOneMinusReflectivity(half2 uv)
    58. {
    59.     half metallicity = _Metallic;
    60.     #ifdef _METALLICGLOSSMAP
    61.         metallicity = tex2D(_MetallicGlossMap, uv).r;
    62.     #endif
    63.     return OneMinusReflectivityFromMetallic(metallicity);
    64. }
    65.  
    66. half RoughnessSetup_ShadowGetOneMinusReflectivity(half2 uv)
    67. {
    68.     half metallicity = _Metallic;
    69. #ifdef _METALLICGLOSSMAP
    70.     metallicity = tex2D(_MetallicGlossMap, uv).r;
    71. #endif
    72.     return OneMinusReflectivityFromMetallic(metallicity);
    73. }
    74.  
    75. half SpecularSetup_ShadowGetOneMinusReflectivity(half2 uv)
    76. {
    77.     half3 specColor = _SpecColor.rgb;
    78.     #ifdef _SPECGLOSSMAP
    79.         specColor = tex2D(_SpecGlossMap, uv).rgb;
    80.     #endif
    81.     return (1 - SpecularStrength(specColor));
    82. }
    83.  
    84. // SHADOW_ONEMINUSREFLECTIVITY(): workaround to get one minus reflectivity based on UNITY_SETUP_BRDF_INPUT
    85. #define SHADOW_JOIN2(a, b) a##b
    86. #define SHADOW_JOIN(a, b) SHADOW_JOIN2(a,b)
    87. #define SHADOW_ONEMINUSREFLECTIVITY SHADOW_JOIN(UNITY_SETUP_BRDF_INPUT, _ShadowGetOneMinusReflectivity)
    88.  
    89. struct VertexInput
    90. {
    91.     float4 vertex   : POSITION;
    92.     float3 normal   : NORMAL;
    93.     float2 uv0      : TEXCOORD0;
    94.     #if defined(UNITY_STANDARD_USE_SHADOW_UVS) && defined(_PARALLAXMAP)
    95.         half4 tangent   : TANGENT;
    96.     #endif
    97.     UNITY_VERTEX_INPUT_INSTANCE_ID
    98. };
    99.  
    100. #ifdef UNITY_STANDARD_USE_SHADOW_OUTPUT_STRUCT
    101. struct VertexOutputShadowCaster
    102. {
    103.     V2F_SHADOW_CASTER_NOPOS
    104.     #if defined(UNITY_STANDARD_USE_SHADOW_UVS)
    105.         float2 tex : TEXCOORD1;
    106.  
    107.         #if defined(_PARALLAXMAP)
    108.             half3 viewDirForParallax : TEXCOORD2;
    109.         #endif
    110.     #endif
    111. };
    112. #endif
    113.  
    114. #ifdef UNITY_STANDARD_USE_STEREO_SHADOW_OUTPUT_STRUCT
    115. struct VertexOutputStereoShadowCaster
    116. {
    117.     UNITY_VERTEX_OUTPUT_STEREO
    118. };
    119. #endif
    120.  
    121. // We have to do these dances of outputting SV_POSITION separately from the vertex shader,
    122. // and inputting VPOS in the pixel shader, since they both map to "POSITION" semantic on
    123. // some platforms, and then things don't go well.
    124.  
    125.  
    126. void vertShadowCaster (VertexInput v
    127.     , out float4 opos : SV_POSITION
    128.     #ifdef UNITY_STANDARD_USE_SHADOW_OUTPUT_STRUCT
    129.     , out VertexOutputShadowCaster o
    130.     #endif
    131.     #ifdef UNITY_STANDARD_USE_STEREO_SHADOW_OUTPUT_STRUCT
    132.     , out VertexOutputStereoShadowCaster os
    133.     #endif
    134. )
    135. {
    136.     UNITY_SETUP_INSTANCE_ID(v);
    137.     #ifdef UNITY_STANDARD_USE_STEREO_SHADOW_OUTPUT_STRUCT
    138.         UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(os);
    139.     #endif
    140.     TRANSFER_SHADOW_CASTER_NOPOS(o,opos)
    141.     #if defined(UNITY_STANDARD_USE_SHADOW_UVS)
    142.         o.tex = TRANSFORM_TEX(v.uv0, _MainTex);
    143.  
    144.         #ifdef _PARALLAXMAP
    145.             TANGENT_SPACE_ROTATION;
    146.             o.viewDirForParallax = mul (rotation, ObjSpaceViewDir(v.vertex));
    147.         #endif
    148.     #endif
    149. }
    150.  
    151. half4 fragShadowCaster (UNITY_POSITION(vpos)
    152. #ifdef UNITY_STANDARD_USE_SHADOW_OUTPUT_STRUCT
    153.     , VertexOutputShadowCaster i
    154. #endif
    155. ) : SV_Target
    156. {
    157.     #if defined(UNITY_STANDARD_USE_SHADOW_UVS)
    158.         #if defined(_PARALLAXMAP) && (SHADER_TARGET >= 30)
    159.             half3 viewDirForParallax = normalize(i.viewDirForParallax);
    160.             fixed h = tex2D (_ParallaxMap, i.tex.xy).g;
    161.             half2 offset = ParallaxOffset1Step (h, _Parallax, viewDirForParallax);
    162.             i.tex.xy += offset;
    163.         #endif
    164.  
    165.         #if defined(_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A)
    166.             half alpha = _Color.a;
    167.         #else
    168.             half alpha = tex2D(_MainTex, i.tex.xy).a * _Color.a;
    169.         #endif
    170.         #if defined(_ALPHATEST_ON)
    171.             clip (alpha - _Cutoff);
    172.         #endif
    173.         #if defined(_ALPHABLEND_ON) || defined(_ALPHAPREMULTIPLY_ON)
    174.             #if defined(_ALPHAPREMULTIPLY_ON)
    175.                 half outModifiedAlpha;
    176.                 PreMultiplyAlpha(half3(0, 0, 0), alpha, SHADOW_ONEMINUSREFLECTIVITY(i.tex), outModifiedAlpha);
    177.                 alpha = outModifiedAlpha;
    178.             #endif
    179.             #if defined(UNITY_STANDARD_USE_DITHER_MASK)
    180.                 // Use dither mask for alpha blended shadows, based on pixel position xy
    181.                 // and alpha level. Our dither texture is 4x4x16.
    182.                 #ifdef LOD_FADE_CROSSFADE
    183.                     #define _LOD_FADE_ON_ALPHA
    184.                     alpha *= unity_LODFade.y;
    185.                 #endif
    186.                 half alphaRef = tex3D(_DitherMaskLOD, float3(vpos.xy*0.25,alpha*0.9375)).a;
    187.                 clip (alphaRef - 0.01);
    188.             #else
    189.                 clip (alpha - _Cutoff);
    190.             #endif
    191.         #endif
    192.     #endif // #if defined(UNITY_STANDARD_USE_SHADOW_UVS)
    193.  
    194.     #ifdef LOD_FADE_CROSSFADE
    195.         #ifdef _LOD_FADE_ON_ALPHA
    196.             #undef _LOD_FADE_ON_ALPHA
    197.         #else
    198.             UnityApplyDitherCrossFade(vpos.xy);
    199.         #endif
    200.     #endif
    201.  
    202.     SHADOW_CASTER_FRAGMENT(i)
    203. }
    204.  
    205. #endif // UNITY_STANDARD_SHADOW_INCLUDED
    206.  
     
    Last edited: Aug 14, 2020
  6. Monil

    Monil

    Joined:
    Apr 24, 2012
    Posts:
    102
  7. Foulcloud

    Foulcloud

    Joined:
    Mar 23, 2014
    Posts:
    19
    Monil, could you please provide any details on how you fixed this? I can get LOD cross fading to work ok except when using GPU instanced - same problem that flogel illustrated. I checked the catlike tutorials but cannot figure what modifications are required in .cginc files.'

    Edit:
    Ok I got the fade working well with instanced. However I am stuck at the shadows like you were. Hoping you can enlighten me on changes you made to UnityStandardShadow.cginc. Thanks.
     
    Last edited: Jun 15, 2021
  8. Arycama

    Arycama

    Joined:
    May 25, 2014
    Posts:
    184
    You have to pass the instanceID from the vertex to the fragment shader, and then call UNITY_SETUP_INSTANCE_ID(IN); in the frag shader, before calling any lod fade functions.

    You need to do it for both your regular and shadow passes.

    The standard shader doesn't do this as it doesn't support lods.