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:
#if defined (SHADOWS_SOFT)
float z = 1.0/128.0;
float4 shadowVals;
shadowVals.x = SampleCubeDistance (vec+float3( z, z, z));
shadowVals.y = SampleCubeDistance (vec+float3(-z,-z, z));
shadowVals.z = SampleCubeDistance (vec+float3(-z, z,-z));
shadowVals.w = SampleCubeDistance (vec+float3( z,-z,-z));
half4 shadows = (shadowVals < mydist.xxxx) ? _LightShadowData.rrrr : 1.0f;
return dot(shadows,0.25);
#else
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.
#if defined (SHADOWS_SOFT)
// Smaller number is more blur
float downscale = 32.0f;
// Random vector
const float3 rndseed = float3(12.9898,78.233,45.5432);
float3 randomvec = float3( dot(vec,rndseed) , dot(vec.yzx,rndseed) , dot(vec.zxy,rndseed) );
randomvec = frac(sin(randomvec) * 43758.5453);
// Vectors of X and Y axis for virtual planar
float3 xvec = normalize(cross(vec,randomvec));
float3 yvec = normalize(cross(vec,xvec));
// Two offsets
float3 vec1 = xvec / downscale;
float3 vec2 = yvec / downscale;
float4 shadowVals;
// Four samples
shadowVals.x = SampleCubeDistance (vec+vec1);
shadowVals.y = SampleCubeDistance (vec+vec2);
shadowVals.z = SampleCubeDistance (vec-vec1);
shadowVals.w = SampleCubeDistance (vec-vec2);
half4 shadows = (shadowVals < mydist.xxxx) ? _LightShadowData.rrrr : 1.0f;
return dot(shadows,0.25);
#else
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:
#if defined (SHADOWS_SOFT)
#define SHADOWS_SOFT_AREALIGHT
float downscale = 32.0f;
float areascalefactor = 10.0f;
const float3 rndseed = float3(12.9898,78.233,45.5432);
float3 randomvec = float3( dot(vec,rndseed) , dot(vec.yzx,rndseed) , dot(vec.zxy,rndseed) );
randomvec = frac(sin(randomvec) * 43758.5453);
float3 xvec = normalize(cross(vec,randomvec));
float3 yvec = normalize(cross(vec,xvec));
float3 vec1 = xvec / downscale;
float3 vec2 = yvec / downscale;
float4 shadowVals;
#if defined (SHADOWS_SOFT_AREALIGHT)
// Lookup
shadowVals.x = SampleCubeDistance (vec+vec1);
shadowVals.y = SampleCubeDistance (vec+vec2);
shadowVals.z = SampleCubeDistance (vec-vec1);
shadowVals.w = SampleCubeDistance (vec-vec2);
// Choose distances sum
float shadowdist = mydist - dot(shadowVals, 0.25f);
// Change bloor factor
downscale *= 2.0f / (1.0 + (shadowdist > 0.0f) ? (shadowdist * areascalefactor ) : 0.0f);
vec1 = xvec / downscale;
vec2 = yvec / downscale;
#endif
// Continue old operations
shadowVals.x = SampleCubeDistance (vec+vec1);
shadowVals.y = SampleCubeDistance (vec+vec2);
shadowVals.z = SampleCubeDistance (vec-vec1);
shadowVals.w = SampleCubeDistance (vec-vec2);
half4 shadows = (shadowVals < mydist.xxxx) ? _LightShadowData.rrrr : 1.0f;
return dot(shadows,0.25);
#else
If you know russian language you can find more information in this thread:
GameDev.ru