constructor( scene, camera, useDepthTexture = false, useNormals = false, resolution = new Vector2( 256, 256 ) ) {

    		super();

    		this.scene = scene;
    		this.camera = camera;

    		this.clear = true;
    		this.needsSwap = false;

    		this.supportsDepthTextureExtension = useDepthTexture;
    		this.supportsNormalTexture = useNormals;

    		this.originalClearColor = new Color();
    		this._oldClearColor = new Color();
    		this.oldClearAlpha = 1;

    		this.params = {
    			output: 0,
    			saoBias: 0.5,
    			saoIntensity: 0.18,
    			saoScale: 1,
    			saoKernelRadius: 100,
    			saoMinResolution: 0,
    			saoBlur: true,
    			saoBlurRadius: 8,
    			saoBlurStdDev: 4,
    			saoBlurDepthCutoff: 0.01
    		};

    		this.resolution = new Vector2( resolution.x, resolution.y );

    		this.saoRenderTarget = new WebGLRenderTarget( this.resolution.x, this.resolution.y, {
    			minFilter: LinearFilter,
    			magFilter: LinearFilter,
    			format: RGBAFormat
    		} );
    		this.blurIntermediateRenderTarget = this.saoRenderTarget.clone();
    		this.beautyRenderTarget = this.saoRenderTarget.clone();

    		this.normalRenderTarget = new WebGLRenderTarget( this.resolution.x, this.resolution.y, {
    			minFilter: NearestFilter,
    			magFilter: NearestFilter,
    			format: RGBAFormat
    		} );
    		this.depthRenderTarget = this.normalRenderTarget.clone();
    		
    		let depthTexture;

    		if ( this.supportsDepthTextureExtension ) {

    			depthTexture = new DepthTexture();
    			depthTexture.type = UnsignedShortType;

    			this.beautyRenderTarget.depthTexture = depthTexture;
    			this.beautyRenderTarget.depthBuffer = true;

    		}

    		this.depthMaterial = new MeshDepthMaterial();
    		this.depthMaterial.depthPacking = RGBADepthPacking;
    		this.depthMaterial.blending = NoBlending;

    		this.normalMaterial = new MeshNormalMaterial();
    		this.normalMaterial.blending = NoBlending;

    		if ( SAOShader === undefined ) {

    			console.error( 'THREE.SAOPass relies on SAOShader' );

    		}

    		this.saoMaterial = new ShaderMaterial( {
    			defines: Object.assign( {}, SAOShader.defines ),
    			fragmentShader: SAOShader.fragmentShader,
    			vertexShader: SAOShader.vertexShader,
    			uniforms: UniformsUtils.clone( SAOShader.uniforms )
    		} );
    		this.saoMaterial.extensions.derivatives = true;
    		this.saoMaterial.defines[ 'DEPTH_PACKING' ] = this.supportsDepthTextureExtension ? 0 : 1;
    		this.saoMaterial.defines[ 'NORMAL_TEXTURE' ] = this.supportsNormalTexture ? 1 : 0;
    		this.saoMaterial.defines[ 'PERSPECTIVE_CAMERA' ] = this.camera.isPerspectiveCamera ? 1 : 0;
    		this.saoMaterial.uniforms[ 'tDepth' ].value = ( this.supportsDepthTextureExtension ) ? depthTexture : this.depthRenderTarget.texture;
    		this.saoMaterial.uniforms[ 'tNormal' ].value = this.normalRenderTarget.texture;
    		this.saoMaterial.uniforms[ 'size' ].value.set( this.resolution.x, this.resolution.y );
    		this.saoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse );
    		this.saoMaterial.uniforms[ 'cameraProjectionMatrix' ].value = this.camera.projectionMatrix;
    		this.saoMaterial.blending = NoBlending;

    		if ( DepthLimitedBlurShader === undefined ) {

    			console.error( 'THREE.SAOPass relies on DepthLimitedBlurShader' );

    		}

    		this.vBlurMaterial = new ShaderMaterial( {
    			uniforms: UniformsUtils.clone( DepthLimitedBlurShader.uniforms ),
    			defines: Object.assign( {}, DepthLimitedBlurShader.defines ),
    			vertexShader: DepthLimitedBlurShader.vertexShader,
    			fragmentShader: DepthLimitedBlurShader.fragmentShader
    		} );
    		this.vBlurMaterial.defines[ 'DEPTH_PACKING' ] = this.supportsDepthTextureExtension ? 0 : 1;
    		this.vBlurMaterial.defines[ 'PERSPECTIVE_CAMERA' ] = this.camera.isPerspectiveCamera ? 1 : 0;
    		this.vBlurMaterial.uniforms[ 'tDiffuse' ].value = this.saoRenderTarget.texture;
    		this.vBlurMaterial.uniforms[ 'tDepth' ].value = ( this.supportsDepthTextureExtension ) ? depthTexture : this.depthRenderTarget.texture;
    		this.vBlurMaterial.uniforms[ 'size' ].value.set( this.resolution.x, this.resolution.y );
    		this.vBlurMaterial.blending = NoBlending;

    		this.hBlurMaterial = new ShaderMaterial( {
    			uniforms: UniformsUtils.clone( DepthLimitedBlurShader.uniforms ),
    			defines: Object.assign( {}, DepthLimitedBlurShader.defines ),
    			vertexShader: DepthLimitedBlurShader.vertexShader,
    			fragmentShader: DepthLimitedBlurShader.fragmentShader
    		} );
    		this.hBlurMaterial.defines[ 'DEPTH_PACKING' ] = this.supportsDepthTextureExtension ? 0 : 1;
    		this.hBlurMaterial.defines[ 'PERSPECTIVE_CAMERA' ] = this.camera.isPerspectiveCamera ? 1 : 0;
    		this.hBlurMaterial.uniforms[ 'tDiffuse' ].value = this.blurIntermediateRenderTarget.texture;
    		this.hBlurMaterial.uniforms[ 'tDepth' ].value = ( this.supportsDepthTextureExtension ) ? depthTexture : this.depthRenderTarget.texture;
    		this.hBlurMaterial.uniforms[ 'size' ].value.set( this.resolution.x, this.resolution.y );
    		this.hBlurMaterial.blending = NoBlending;

    		if ( CopyShader === undefined ) {

    			console.error( 'THREE.SAOPass relies on CopyShader' );

    		}

    		this.materialCopy = new ShaderMaterial( {
    			uniforms: UniformsUtils.clone( CopyShader.uniforms ),
    			vertexShader: CopyShader.vertexShader,
    			fragmentShader: CopyShader.fragmentShader,
    			blending: NoBlending
    		} );
    		this.materialCopy.transparent = true;
    		this.materialCopy.depthTest = false;
    		this.materialCopy.depthWrite = false;
    		this.materialCopy.blending = CustomBlending;
    		this.materialCopy.blendSrc = DstColorFactor;
    		this.materialCopy.blendDst = ZeroFactor;
    		this.materialCopy.blendEquation = AddEquation;
    		this.materialCopy.blendSrcAlpha = DstAlphaFactor;
    		this.materialCopy.blendDstAlpha = ZeroFactor;
    		this.materialCopy.blendEquationAlpha = AddEquation;

    		if ( UnpackDepthRGBAShader === undefined ) {

    			console.error( 'THREE.SAOPass relies on UnpackDepthRGBAShader' );

    		}

    		this.depthCopy = new ShaderMaterial( {
    			uniforms: UniformsUtils.clone( UnpackDepthRGBAShader.uniforms ),
    			vertexShader: UnpackDepthRGBAShader.vertexShader,
    			fragmentShader: UnpackDepthRGBAShader.fragmentShader,
    			blending: NoBlending
    		} );

    		this.fsQuad = new FullScreenQuad( null );

    	}
SAO implementation inspired from bhouston previous SAO work