Search Unity

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