Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question What causes highlighted shadow edge?

Discussion in 'General Graphics' started by benyazhosh, Feb 20, 2023.

  1. benyazhosh

    benyazhosh

    Joined:
    Jul 14, 2019
    Posts:
    9
    Hi everyone!
    I was writing toon shader and I noticed that attenuation shadow edges results in a very bright color.
    I'm using saturate before multiply attenuation on diffuse, so I can't understand how the result value could be greater than diffuse. Below you can see screenshots with and without attenuation.

    My fragment shader:
    Code (Boo):
    1. float4 frag (Interpolators i) : SV_Target
    2. {
    3.     float attenuation = LIGHT_ATTENUATION(i);
    4.                
    5.     float3 normal = normalize(i.normal);
    6.     float3 light_diff = UnityWorldSpaceLightDir(i.wpos);
    7.     float diffuse = saturate(dot(normal, normalize(light_diff)));
    8.  
    9. #ifdef DIRECTIONAL
    10.     diffuse *= saturate(attenuation);
    11.  
    12.     float main_diffuse = floor(diffuse * _ToneLength);
    13.     float diff = (diffuse * _ToneLength) - floor(diffuse * _ToneLength);
    14.    
    15.     float4 main_tone = tex2D(_ToneTex, float2(main_diffuse / _ToneLength, 0.5));
    16.     float4 near_tone = tex2D(_ToneTex, float2((main_diffuse + 1) / _ToneLength, 0.5));
    17.    
    18.     float4 color = lerp(main_tone, near_tone, smoothstep(0.5 - _Smoothness / 2, 0.5 + _Smoothness / 2, diff));
    19. #else
    20.     diffuse *= round(saturate(attenuation) * _Quantization) / _Quantization;
    21.     float4 color = diffuse;
    22. #endif
    23.  
    24.     return color * _LightColor0;
    25. }
    In Scene window:
    Screenshot 2023-02-20 at 14.08.16.png
    With attenuation:
    Screenshot 2023-02-20 at 14.00.06.png
    Only diffuse (line 10 "diffuse *= saturate(attenuation)" commented):
    Screenshot 2023-02-20 at 13.59.56.png
     
  2. benyazhosh

    benyazhosh

    Joined:
    Jul 14, 2019
    Posts:
    9
    Ok, I figured out by myself)
    When I was sampling the _ToneText, I used tex2D, so I was sampling through textures mipmap.
    I just changed tex2D on tex2Dlod, and now everything works fine.
    Here is the correct fragment shader code:
    Code (Boo):
    1. float4 frag (Interpolators i) : SV_Target
    2. {
    3.     float attenuation = LIGHT_ATTENUATION(i);
    4.                
    5.     float3 normal = normalize(i.normal);
    6.     float3 light_diff = UnityWorldSpaceLightDir(i.wpos);
    7.     float diffuse = saturate(dot(normal, normalize(light_diff)));
    8.  
    9. #ifdef DIRECTIONAL
    10.     diffuse *= saturate(attenuation);
    11.  
    12.     float main_diffuse = floor(diffuse * _ToneLength);
    13.     float diff = (diffuse * _ToneLength) - floor(diffuse * _ToneLength);
    14.    
    15.     float4 main_tone = tex2Dlod(_ToneTex, float4(main_diffuse / _ToneLength, 0.5, 0, 0));
    16.     float4 near_tone = tex2Dlod(_ToneTex, float4((main_diffuse + 1) / _ToneLength, 0.5, 0, 0));
    17.    
    18.     float4 color = lerp(main_tone, near_tone, smoothstep(0.5 - _Smoothness / 2, 0.5 + _Smoothness / 2, diff));
    19. #else
    20.     diffuse *= round(saturate(attenuation) * _Quantization) / _Quantization;
    21.     float4 color = diffuse;
    22. #endif
    23.  
    24.     return color * _LightColor0;
    25. }