uniform sampler2D rand ;
uniform sampler2DShadow depth ; 
uniform sampler2D option_mask ;

uniform float uni_f_screen_size_x ;
uniform float uni_f_screen_size_y ;

void main()
{
	vec4 output_color = vec4(1.0) ;
	
	if( texture2D(option_mask, gl_TexCoord[0].xy).x > 0.5 )
	{
		vec2 screen_size = vec2(uni_f_screen_size_x, uni_f_screen_size_y) ;

		vec2 rotationTC = ((gl_TexCoord[0].xy * screen_size / 4) ) ;
		vec3 vRotation = 2.0*(texture2D( rand, rotationTC ).rgb)-1.0 ;
		
		mat3 rotMat ;
		float h = 1.0 / (1.0+vRotation.z) ;
		rotMat[0][0] = h*vRotation.y*vRotation.y+vRotation.z ;
		rotMat[1][0] = -h*vRotation.y*vRotation.x ;
		rotMat[2][0] = -vRotation.x ;
		rotMat[0][1] = -h*vRotation.y*vRotation.x ;
		rotMat[1][1] = h*vRotation.x*vRotation.x+vRotation.z ;
		rotMat[2][1] = -vRotation.y ;
		rotMat[1][2] = vRotation.y ;
		rotMat[2][0] = vRotation.x ;
		rotMat[2][2] = vRotation.z ;
		
		float depth_pow_fac = 10.0 ;
		
		float fDepth = pow( shadow2D( depth, vec3(gl_TexCoord[0].xy,1.0) ).x,depth_pow_fac) ;
		
		const int nSamplesNum = 24 ;
		float offsetScale = 0.0003 ;
		const float offsetScaleStep = 1.0 + 2.4/float(nSamplesNum) ;
		
		// accessibility
		float a = 0 ;
		
		for(int i=0; i<(nSamplesNum/8); ++i )
		for(int x=-1; x<=1; x+=2)
		for(int y=-1; y<=1; y+=2)
		for(int z=-1; z<=1; z+=2){
			
			vec3 vOffset = normalize( vec3(x, y, z) ) * 
			(offsetScale *= offsetScaleStep ) ;
			
			vec3 vRotatedOffset = ( rotMat * vOffset ) ;
			
			vec3 vSamplePos = vec3( gl_TexCoord[0].xy, fDepth ) ;
			

			vSamplePos += vec3( vRotatedOffset.xy,
								vRotatedOffset.z*fDepth ) ;
								
			float fDepthS = pow( shadow2D( depth, vec3(vSamplePos.xy,1.0) ).x, depth_pow_fac ) ;
			
	
			float fRangeIsInvalid = clamp( ( ( 2.0*fDepth - fDepthS ) ),0.0,1.0 ) ;
			
			a += mix( fDepthS > vSamplePos.z?1.0:0.0, 1.0, fRangeIsInvalid   ) ;
			
		}
		
		a = a / nSamplesNum ;
		output_color = vec4(clamp( a*a, 0.0,1.0 )) ;
	}
	
	gl_FragData[0] = output_color ;
	//gl_FragData[0] = vec4(clamp( a*a, 0.0,1.0 )) ;
	//gl_FragData[0] = vec4(fDepth) ;
	//gl_FragData[0] = vec4(texture(rand,gl_TexCoord[0].xy)) ;
}