vec2 OffsetDist(float x,int s){
	float n=fract(x*1.414)*3.1415;
	return vec2(cos(n),sin(n))*x/s;
}

float AmbientOcclusion(sampler2D depth,float dither){
	float ao=0.;
	
	#if AA > 1
	int samples = AO_QUALITY / 2;
	dither=fract(frameTimeCounter*4.+dither);
	#else
	int samples = AO_QUALITY;
	#endif


	float d=texture2D(depth,texCoord).r;
	float hand=float(d<.56);
	d=GetLinearDepth(d);
	
	#if AO_FOVSCALE ==1
	float fovScaleAO = 2.74;
	#endif
	#if AO_FOVSCALE ==2
	float fovScaleAO = 2.055;
	#endif
	#if AO_FOVSCALE ==3
	float fovScaleAO = 1.37;
	#endif
	#if AO_FOVSCALE ==4
	float fovScaleAO = 0.685;
	#endif

	float sd=0.,angle=0.,dist=0.;
	float fovScale=gbufferProjection[1][1]/fovScaleAO;
	float distScale=max((far-near)*d+near,6.);
	vec2 scale=.4*vec2(1./aspectRatio,1.)*fovScale/distScale;
	
	for(int i=1;i<=samples;i++){
		vec2 offset=OffsetDist(i+dither,samples)*scale;
		
		sd=GetLinearDepth(texture2D(depth,texCoord+offset).r);
		float sample=(far-near)*(d-sd)*2.;
		if(hand>.5)sample*=1024.;
		angle=clamp(.5-sample,0.,1.);
		dist=clamp(.5*sample-1.,0.,1.);
		
		sd=GetLinearDepth(texture2D(depth,texCoord-offset).r);
		sample=(far-near)*(d-sd)*2.;
		if(hand>.5)sample*=1024.;
		angle+=clamp(.5-sample,0.,1.);
		dist+=clamp(.25*sample-1.,0.,1.);
		
		ao+=clamp(angle+dist,0.,1.);
	}
	ao/=samples;
	
	return pow(ao,AO_STRENGTH);
}