const vec2 poissonDisk[16] = vec2[](

    vec2(-0.94201624, -0.39906216),
    vec2( 0.94558609, -0.76890725),
    vec2(-0.09418410, -0.92938870),
    vec2( 0.34495938,  0.29387760),

    vec2(-0.91588581,  0.45771432),
    vec2(-0.81544232, -0.87912464),
    vec2(-0.38277543,  0.27676845),
    vec2( 0.97484398,  0.75648379),

    vec2( 0.44323325, -0.97511554),
    vec2( 0.53742981, -0.47373420),
    vec2(-0.26496911, -0.41893023),
    vec2( 0.79197514,  0.19090188),

    vec2(-0.24188840,  0.99706507),
    vec2(-0.81409955,  0.91437590),
    vec2( 0.19984126,  0.78641367),
    vec2( 0.14383161, -0.14100790)

);



vec3 vpShadowCoord(vec3 worldPos)
{
    vec4 shadow =shadowProjection *shadowModelView *vec4(worldPos,1.0);

    shadow.xy = DistortPosition(shadow.xy);

	
	shadow.xyz = shadow.xyz * 0.5 + 0.5;

    return shadow.xyz;
}

vec3 vpVolumetricLightCoord(vec3 worldPos)
{
    vec3 shadowWorld = worldPos - cameraPosition;

    vec4 shadow = shadowProjection *
                  shadowModelView *
                  vec4(shadowWorld, 1.0);

    shadow /= shadow.w;

    shadow.xy = DistortPosition(shadow.xy);

    shadow.xyz = shadow.xyz * 0.5 + 0.5;

    return shadow.xyz;
}


float Hash12(vec2 p)
{
    vec3 p3 = fract(vec3(p.xyx) * 0.1031);
    p3 += dot(p3, p3.yzx + 33.33);
    return fract((p3.x + p3.y) * p3.z);
}


float visibility (vec3 coord, sampler2D shadow )
{

    return step(coord.z-0.0001,texture(shadow,coord.xy)).r;

}


vec3 ColoredShadows(in vec3 coord)
{
    float ShadowVisibility_1 = visibility(coord, shadowtex0);
    float ShadowVisibility_2 = visibility(coord, shadowtex1);

    vec4 ShadowColored = texture(shadowcolor0,coord.xy);

    vec3 TransmitedColor = ShadowColored.rgb  * 4.0 * (1.0 - ShadowColored.a);

    vec3 OpaqueShadows = mix(TransmitedColor * ShadowVisibility_2, vec3(1.0), ShadowVisibility_1);

    return OpaqueShadows;

}

vec3 vpGetShadow(vec3 coord)
{
    vec3 shadow = vec3(0);

	float angle = Hash12(gl_FragCoord.xy) * 6.2831853;

	float s = sin(angle);
	float c = cos(angle);

	mat2 rot = mat2(
		c, -s,
		s,  c
	);

    for(int i = 0; i < 16; i++)
    {
        vec2 offset = rot * poissonDisk[i] * 2.0 / shadowMapResolution;
		
		float depth = texture(shadowtex0,coord.xy - offset).r;

        vec3 SoftShadow = vec3(coord.xy+offset,coord.z);

        shadow += ColoredShadows(SoftShadow);



        
    }

    

    return shadow / 16.0;
}


