+#ifdef COLORED_SHADOWS
+float getHardShadowDepth(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
+{
+ vec4 texDepth = texture2D(shadowsampler, smTexCoord.xy);
+ float depth = max(realDistance - texDepth.r, realDistance - texDepth.b);
+ return depth;
+}
+#else
+float getHardShadowDepth(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
+{
+ float texDepth = texture2D(shadowsampler, smTexCoord.xy).r;
+ float depth = realDistance - texDepth;
+ return depth;
+}
+#endif
+
+float getBaseLength(vec2 smTexCoord)
+{
+ float l = length(2.0 * smTexCoord.xy - 1.0); // length in texture coords
+ return bias1 / (1.0 / l - bias0); // return to undistorted coords
+}
+
+float getDeltaPerspectiveFactor(float l)
+{
+ return 0.1 / (bias0 * l + bias1); // original distortion factor, divided by 10
+}
+
+float getPenumbraRadius(sampler2D shadowsampler, vec2 smTexCoord, float realDistance, float multiplier)
+{
+ float baseLength = getBaseLength(smTexCoord);
+ float perspectiveFactor;
+
+ // Return fast if sharp shadows are requested
+ if (SOFTSHADOWRADIUS <= 1.0) {
+ perspectiveFactor = getDeltaPerspectiveFactor(baseLength);
+ return max(2 * length(smTexCoord.xy) * 2048 / f_textureresolution / pow(perspectiveFactor, 3), SOFTSHADOWRADIUS);
+ }
+
+ vec2 clampedpos;
+ float texture_size = 1.0 / (2048 /*f_textureresolution*/ * 0.5);
+ float y, x;
+ float depth = 0.0;
+ float pointDepth;
+ float maxRadius = SOFTSHADOWRADIUS * 5.0 * multiplier;
+
+ float bound = clamp(PCFBOUND * (1 - baseLength), 0.0, PCFBOUND);
+ int n = 0;
+
+ for (y = -bound; y <= bound; y += 1.0)
+ for (x = -bound; x <= bound; x += 1.0) {
+ clampedpos = vec2(x,y);
+ perspectiveFactor = getDeltaPerspectiveFactor(baseLength + length(clampedpos) * texture_size * maxRadius);
+ clampedpos = clampedpos * texture_size * perspectiveFactor * maxRadius * perspectiveFactor + smTexCoord.xy;
+
+ pointDepth = getHardShadowDepth(shadowsampler, clampedpos.xy, realDistance);
+ if (pointDepth > -0.01) {
+ depth += pointDepth;
+ n += 1;
+ }
+ }
+
+ depth = depth / n;
+ depth = pow(clamp(depth, 0.0, 1000.0), 1.6) / 0.001;
+
+ perspectiveFactor = getDeltaPerspectiveFactor(baseLength);
+ return max(length(smTexCoord.xy) * 2 * 2048 / f_textureresolution / pow(perspectiveFactor, 3), depth * maxRadius);
+}