 #define TWOPI 6.28318530718
 #define GOLDENANGLE 2.39996323
 
+float phi;
+
 // Reference: https://thebookofshaders.com/10/
 float random(vec2 p)
 {


void main(void)
{
  // Get base fragment color, which will be attenuated based on visible light
  vec4 color = gl_Color * texture2D(osgShadow_baseTexture, gl_TexCoord[0].xy);
  

  // Distance to center of shadow coverage circle
  float CoverageDistCenter = 0.5 * (CoverageDistUpper + CoverageDistLower);
  
  // Shadow coverage center and radius (in NDC)
  vec2 dir = (dist == 0.0) ? vec2(1.0, 0.0) : normalize(texCoordNDC.xy);
  vec2 center = CoverageDistCenter * dir;
  float radius = CoverageDistUpper - CoverageDistCenter;
  
  // If part of coverage circle is outside the texture, then only search samples inside the texture
  // and attenuate using percentage of coverage circle inside texture
  // This uses the circle-circle intersection area algorithm at:
  // https://diego.assencio.com/?index=8d6ca3d82151bad815f78addf9b5c1c6
  float r1 = 1.0;           // Radius of texture, assumes circular light
  float r2 = radius;        // Radius of coverage circle
  float d = length(center); // Distance from texture center (at origin) to coverage circle center
  
  float A1 = PI;
  float A2 = PI*r2*r2;
  
  float Aintersect = 0.0;
  if(d <= abs(r1 - r2)) Aintersect = min(A1, A2);
  else if(d < r1 + r2)
  {
    float r1_sq = 1.0;
    float r2_sq = r2*r2;
    float d1 = (r1_sq - r2_sq + d*d)/(2.0*d);
    float d2 = d - d1;
    Aintersect =  r1_sq*acos(d1/r1) - d1*sqrt(r1_sq - d1*d1);
    Aintersect += r2_sq*acos(d2/r2) - d2*sqrt(r2_sq - d2*d2);
  }
  
  // Convert center and radius from NDC [-1,1] -> texcoords [0, 1]
  center = center * 0.5 + 0.5;
  radius = radius * 0.5;
  
  return vec4(center, radius, Aintersect/A2);
}

vec2 SearchBlockers(sampler2D depthTex, vec4 texCoord, vec4 coverageCircle, vec2 zNearFarInv, float planeSign, const int numSearchSamples)
{
  //phi = random(texCoord.xy)*TWOPI;
  vec3 sampleTexCoord = texCoord.xyz;
  float clearDepth = (planeSign == 1.0) ? 0.0 : 1.0; // Depth value if there is no blocker (0 for umbra, 1 for penumbra)
  vec2 blockerData = vec2(0.0, 0.0); // (average blocker depth, number of blockers)
  float depth;
  
  // Get coverage circle in NDC [-1, 1] coordinates
  vec2 centerNDC = 2.0*coverageCircle.xy - 1.0;
  float radiusNDC = 2.0*coverageCircle.z;
  
  // Compute min/max distances to intersection area between coverage circle and texture (assuming circular light source)
  float rplus = length(centerNDC) + radiusNDC;
  float rminus = rplus - 2.0*radiusNDC;
  rplus = min(rplus, 1.0);
  rminus = max(rminus, -1.0);
  float dCenter = 0.5*(rplus + rminus);
  float rAverage = abs(rplus - dCenter);
  vec2 centerAverage = dCenter * normalize(centerNDC);
  centerAverage = centerAverage * 0.5 + 0.5;
  rAverage = rAverage*0.5;

  // Sample texture
  for (int i = 0; i < numSearchSamples; ++i)
  {
    // Get sample coordinates
    vec2 currsample = VogelDiskSample(i, numSearchSamples, phi);
    sampleTexCoord.xy = coverageCircle.xy + currsample*coverageCircle.z;
    
    if(length(sampleTexCoord.xy - vec2(0.5, 0.5)) > 0.5)
    {
      sampleTexCoord.xy = centerAverage + currsample*rAverage;
    }
    
    // Lookup sample depth and compare it to fragment depth
    depth = texture2D(depthTex, sampleTexCoord.xy).r;
