SSAO

Fragment shader :
uniform sampler2D screenTexture;
uniform sampler2D tDepth;
uniform float cameraNear;
uniform float cameraFar;
uniform vec2 size;
uniform int byp;
varying vec2 vUv;
	
const int samples = 32;
	
float uRadius = 0.1;
	
#include <packing>
	
vec2 inverseScreenSize;
	
float readDepth( const in vec2 coord ) {

float cameraFarPlusNear = cameraFar + cameraNear;
float cameraFarMinusNear = cameraFar - cameraNear;
float cameraCoef = 2.0 * cameraFar * cameraNear;

#ifdef USE_LOGDEPTHBUF

	float logz = unpackRGBAToDepth( texture2D( tDepth, coord ) );
	float w = pow(2.0, (logz / logDepthBufFC)) - 1.0;
	float z = (logz / w) + 1.0;

#else

	float z = unpackRGBAToDepth( texture2D( tDepth, coord ) );

#endif

z = z * 2.0 - 1.0;

return cameraCoef / ( cameraFarPlusNear - z * cameraFarMinusNear );


}
	
vec3 calculNormal( float depth, vec2 uv ) {

vec2 offset1 = vec2(0,1)*inverseScreenSize.y;
vec2 offset2 = vec2(1,0)*inverseScreenSize.x;
		  
float depth1 = readDepth( uv + offset1);
float depth2 = readDepth( uv + offset2);
		  
vec3 p1 = vec3(offset1, depth1 - depth);
vec3 p2 = vec3(offset2, depth2 - depth);
		  
vec3 normal = cross(p1, p2);
		  
return normalize(normal);


}
	
float rand(vec2 co){
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
	
void main() {
inverseScreenSize = vec2(1.0/size.x, 1.0/size.y);
		//get depth
float depth = readDepth(vUv);
		//calculate informations of the point : normal(world) + position(x,y,z) screen space
vec3 normal = calculNormal( depth, vUv);
vec3 position = vec3( vUv, depth);
		//generate hemisphere
vec3 kernel[samples];
for(int i = 0; i < samples; ++i) {
	kernel[i] = vec3(
	rand(vUv*(0.1*(float(i)+1.0)))*2.0-1.0,
	rand(vUv*(0.11*(float(i)+1.0)))*2.0-1.0,
	rand(vUv*(0.12*(float(i)+1.0)))*1.0);
	kernel[i] = normalize(kernel[i]);
	float scale = float(i) / float(samples);
	scale = clamp(scale * scale, 0.1, 1.0);
	kernel[i] *= scale;
}
		//rotation matrix
vec3 tangent = normalize(kernel[0] - normal * dot(kernel[0], normal));
vec3 bitangent = cross(normal, tangent);
mat3 tbn = mat3(tangent, bitangent, normal);
		
float occlusion = 0.0;
for (int i = 0; i < samples; ++i) {
		// get sample position:
	vec3 sample = tbn * kernel[i];
	sample = sample * uRadius + position;
		  
		// get sample depth:
	float sampleDepth = readDepth(sample.xy);
		  
		// range check & accumulate:
	float rangeCheck= abs(position.z - sampleDepth) < uRadius * 2.0 ? 1.0 : 0.0;
	occlusion += (sampleDepth <= sample.z ? 1.0 : 0.0) * rangeCheck;
}

occlusion = 1.0 - occlusion / float(samples);

if(byp==2){
	gl_FragColor = vec4(vec3(occlusion),1.0);
}
else if(byp==1){
	gl_FragColor = vec4(normal*0.5+0.5,1.0);
}
else{
	gl_FragColor = vec4(texture2D(screenTexture, vUv).rgb*occlusion,1.0);
}
}