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

Soft shadows for point lights (my implementation)

Discussion in 'General Discussion' started by LifeKILLED, Dec 24, 2015.

  1. LifeKILLED

    LifeKILLED

    Joined:
    Nov 15, 2013
    Posts:
    3
    I made the realization of soft shadows for point lights. In order to make it work , you need to find in folder "...\Unity5\Editor\Data\CGIncludes" file "UnityShadowLibrary.cginc" and edit it.

    To see the result , you need to find a folder of your project . In it find the folder "Library". Remove from this folder directory "ShaderCache" and restart Unity. Yes, I restarted Unity after each compilation.

    See in "UnityShadowLibrary.cginc". We need this cut:

    Code (csharp):
    1.  
    2.     #if defined (SHADOWS_SOFT)
    3.  
    4.         float z = 1.0/128.0;
    5.         float4 shadowVals;
    6.         shadowVals.x = SampleCubeDistance (vec+float3( z, z, z));
    7.         shadowVals.y = SampleCubeDistance (vec+float3(-z,-z, z));
    8.         shadowVals.z = SampleCubeDistance (vec+float3(-z, z,-z));
    9.         shadowVals.w = SampleCubeDistance (vec+float3( z,-z,-z));
    10.         half4 shadows = (shadowVals < mydist.xxxx) ? _LightShadowData.rrrr : 1.0f;
    11.  
    12.         return dot(shadows,0.25);
    13.  
    14.     #else
    15.  
    16.  
    What do we see ? Artfully created a small offset vector. Works quickly, looks terrible:



    First of course you need to choose the offset is not in all three dimensions, but in a plane perpendicular to the vector from light. Thus, we will work with the cubemap as a flat texture. So you need to be less than the sample for best results.
    To obtain the virtual vector we start axes X and Y, then store them in different sequences , thereby selecting a point on the same virtual plane. No matrix , everything fast and simple.
    And second - we need some random. It was effect like Disk Bloor.

    Code (csharp):
    1.  
    2.   #if defined (SHADOWS_SOFT)
    3.  
    4.         // Smaller number is more blur
    5.         float downscale = 32.0f;
    6.  
    7.         // Random vector
    8.         const float3 rndseed = float3(12.9898,78.233,45.5432);
    9.         float3 randomvec = float3( dot(vec,rndseed) , dot(vec.yzx,rndseed) , dot(vec.zxy,rndseed) );
    10.         randomvec = frac(sin(randomvec) * 43758.5453);
    11.  
    12.         // Vectors of X and Y axis for virtual planar
    13.         float3 xvec = normalize(cross(vec,randomvec));
    14.         float3 yvec = normalize(cross(vec,xvec));
    15.  
    16.  
    17.         // Two offsets
    18.         float3 vec1 = xvec / downscale;
    19.         float3 vec2 = yvec / downscale;
    20.  
    21.         float4 shadowVals;
    22.  
    23.         // Four samples
    24.         shadowVals.x = SampleCubeDistance (vec+vec1);
    25.         shadowVals.y = SampleCubeDistance (vec+vec2);
    26.         shadowVals.z = SampleCubeDistance (vec-vec1);
    27.         shadowVals.w = SampleCubeDistance (vec-vec2);
    28.  
    29.         half4 shadows = (shadowVals < mydist.xxxx) ? _LightShadowData.rrrr : 1.0f;
    30.         return dot(shadows,0.25);
    31.  
    32.     #else
    33.  
    34.  
    And see:



    Here there are the same four samples , but the difference is enormous. Pixels are no longer visible. With good textures dithering was invisible. You can see what now there's not a bias problem.

    And now - warning! We can make Area Light like effect:

    Code (csharp):
    1.  
    2.    #if defined (SHADOWS_SOFT)
    3.  
    4.         #define SHADOWS_SOFT_AREALIGHT
    5.  
    6.         float downscale = 32.0f;
    7.         float areascalefactor  = 10.0f;
    8.  
    9.         const float3 rndseed = float3(12.9898,78.233,45.5432);
    10.         float3 randomvec = float3( dot(vec,rndseed) , dot(vec.yzx,rndseed) , dot(vec.zxy,rndseed) );
    11.         randomvec = frac(sin(randomvec) * 43758.5453);
    12.  
    13.         float3 xvec = normalize(cross(vec,randomvec));
    14.         float3 yvec = normalize(cross(vec,xvec));
    15.  
    16.         float3 vec1 = xvec / downscale;
    17.         float3 vec2 = yvec / downscale;
    18.  
    19.         float4 shadowVals;
    20.  
    21.         #if defined (SHADOWS_SOFT_AREALIGHT)
    22.  
    23.             // Lookup
    24.             shadowVals.x = SampleCubeDistance (vec+vec1);
    25.             shadowVals.y = SampleCubeDistance (vec+vec2);
    26.             shadowVals.z = SampleCubeDistance (vec-vec1);
    27.             shadowVals.w = SampleCubeDistance (vec-vec2);
    28.  
    29.             // Choose distances sum
    30.             float shadowdist = mydist - dot(shadowVals, 0.25f);
    31.  
    32.             // Change bloor factor
    33.             downscale *= 2.0f / (1.0 + (shadowdist > 0.0f) ? (shadowdist * areascalefactor ) : 0.0f);
    34.            
    35.             vec1 = xvec / downscale;
    36.             vec2 = yvec / downscale;
    37.  
    38.         #endif
    39.  
    40.         // Continue old operations
    41.         shadowVals.x = SampleCubeDistance (vec+vec1);
    42.         shadowVals.y = SampleCubeDistance (vec+vec2);
    43.         shadowVals.z = SampleCubeDistance (vec-vec1);
    44.         shadowVals.w = SampleCubeDistance (vec-vec2);
    45.  
    46.         half4 shadows = (shadowVals < mydist.xxxx) ? _LightShadowData.rrrr : 1.0f;
    47.         return dot(shadows,0.25);
    48.  
    49.     #else
    50.  
    51.  


    If you know russian language you can find more information in this thread:
    GameDev.ru
     
    Last edited: Dec 24, 2015
  2. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    Where is that value mydist came from?
    Edit : My Bad, haven't check the real code before. ignore my question