text: import {
  	BasicDepthPacking,
  	Color,
  	LinearFilter,
  	NotEqualDepth,
  	EqualDepth,
  	RGBADepthPacking,
  	sRGBEncoding,
  	WebGLRenderTarget
  } from "three";
  
  import { Selection } from "../core/Selection";
  import { DepthMaskMaterial, DepthTestStrategy } from "../materials";
  import { ClearPass, DepthPass, ShaderPass } from "../passes";
  import { BloomEffect } from "./BloomEffect";
  import { EffectAttribute } from "./Effect";
  
  /**
   * A selective bloom effect.
   *
   * This effect applies bloom to selected objects only.
   */
  
  export class SelectiveBloomEffect extends BloomEffect {
  
  	/**
  	 * Constructs a new selective bloom effect.
  	 *
  	 * @param {Scene} scene - The main scene.
  	 * @param {Camera} camera - The main camera.
  	 * @param {Object} [options] - The options. See {@link BloomEffect} for details.
  	 */
  
  	constructor(scene, camera, options) {
  
  		super(options);
  
  		this.setAttributes(this.getAttributes() | EffectAttribute.DEPTH);
  
  		/**
  		 * The main camera.
  		 *
  		 * @type {Camera}
  		 * @private
  		 */
  
  		this.camera = camera;
  
  		/**
  		 * A depth pass.
  		 *
  		 * @type {DepthPass}
  		 * @private
  		 */
  
  		this.depthPass = new DepthPass(scene, camera);
  
  		/**
  		 * A clear pass.
  		 *
  		 * @type {ClearPass}
  		 * @private
  		 */
  
  		this.clearPass = new ClearPass(true, false, false);
  		this.clearPass.overrideClearColor = new Color(0x000000);
  
  		/**
  		 * A depth mask pass.
  		 *
  		 * @type {ShaderPass}
  		 * @private
  		 */
  
  		this.depthMaskPass = new ShaderPass(new DepthMaskMaterial());
  
  		const depthMaskMaterial = this.depthMaskMaterial;
  		depthMaskMaterial.depthBuffer1 = this.depthPass.texture;
  		depthMaskMaterial.depthPacking1 = RGBADepthPacking;
  		depthMaskMaterial.depthMode = EqualDepth;
  
  		/**
  		 * A render target.
  		 *
  		 * @type {WebGLRenderTarget}
  		 * @private
  		 */
  
  		this.renderTargetMasked = new WebGLRenderTarget(1, 1, {
  			minFilter: LinearFilter,
  			magFilter: LinearFilter,
  			stencilBuffer: false,
  			depthBuffer: false
  		});
  
  		this.renderTargetMasked.texture.name = "Bloom.Masked";
  		this.renderTargetMasked.texture.generateMipmaps = false;
  
  		/**
  		 * Backing data.
  		 *
  		 * @type {Record<String, Boolean>}
  		 * @private
  		 */
  
  		this.data = {
  			inverted: false,
  			ignoreBackground: false
  		};
  
  		/**
  		 * A selection of objects.
  		 *
  		 * The default layer of this selection is 11.
  		 *
  		 * @type {Selection}
  		 */
  
  		this.selection = new Selection();
  		this.selection.layer = 11;
  
  	}
  
  	/**
  	 * Returns the selection.
  	 *
  	 * @deprecated Use selection instead.
  	 * @return {Selection} The selection.
  	 */
  
  	getSelection() {
  
  		return this.selection;
  
  	}
  
  	/**
  	 * The depth mask material.
  	 *
  	 * @type {DepthMaskMaterial}
  	 * @private
  	 */
  
  	get depthMaskMaterial() {
  
  		return this.depthMaskPass.fullscreenMaterial;
  
  	}
  
  	/**
  	 * Indicates whether the selection should be considered inverted.
  	 *
  	 * @type {Boolean}
  	 */
  
  	get inverted() {
  
  		return this.data.inverted;
  
  	}
  
  	set inverted(value) {
  
  		this.data.inverted = value;
  		this.depthMaskMaterial.depthMode = value ? NotEqualDepth : EqualDepth;
  
  	}
  
  	/**
  	 * Indicates whether the mask is inverted.
  	 *
  	 * @deprecated Use inverted instead.
  	 * @return {Boolean} Whether the mask is inverted.
  	 */
  
  	isInverted() {
  
  		return this.inverted;
  
  	}
  
  	/**
  	 * Enables or disable mask inversion.
  	 *
  	 * @deprecated Use inverted instead.
  	 * @param {Boolean} value - Whether the mask should be inverted.
  	 */
  
  	setInverted(value) {
  
  		this.inverted = value;
  
  	}
  
  	/**
  	 * Indicates whether the background colors will be ignored.
  	 *
  	 * @type {Boolean}
  	 */
  
  	get ignoreBackground() {
  
  		return this.data.ignoreBackground;
  
  	}
  
  	set ignoreBackground(value) {
  
  		this.data.ignoreBackground = value;
  		this.depthMaskMaterial.maxDepthStrategy = value ?
  			DepthTestStrategy.DISCARD_MAX_DEPTH :
  			DepthTestStrategy.KEEP_MAX_DEPTH;
  
  	}
  
  	/**
  	 * Indicates whether the background is disabled.
  	 *
  	 * @deprecated Use ignoreBackground instead.
  	 * @return {Boolean} Whether the background is disabled.
  	 */
  
  	isBackgroundDisabled() {
  
  		return this.ignoreBackground;
  
  	}
  
  	/**
  	 * Enables or disables the background.
  	 *
  	 * @deprecated Use ignoreBackground instead.
  	 * @param {Boolean} value - Whether the background should be disabled.
  	 */
  
  	setBackgroundDisabled(value) {
  
  		this.ignoreBackground = value;
  
  	}
  
  	/**
  	 * Sets the depth texture.
  	 *
  	 * @param {Texture} depthTexture - A depth texture.
  	 * @param {DepthPackingStrategies} [depthPacking=BasicDepthPacking] - The depth packing.
  	 */
  
  	setDepthTexture(depthTexture, depthPacking = BasicDepthPacking) {
  
  		this.depthMaskMaterial.depthBuffer0 = depthTexture;
  		this.depthMaskMaterial.depthPacking0 = depthPacking;
  
  	}
  
  	/**
  	 * Updates this effect.
  	 *
  	 * @param {WebGLRenderer} renderer - The renderer.
  	 * @param {WebGLRenderTarget} inputBuffer - A frame buffer that contains the result of the previous pass.
  	 * @param {Number} [deltaTime] - The time between the last frame and the current one in seconds.
  	 */
  
  	update(renderer, inputBuffer, deltaTime) {
  
  		const camera = this.camera;
  		const selection = this.selection;
  		const inverted = this.inverted;
  		let renderTarget = inputBuffer;
  
  		if(this.ignoreBackground || !inverted || selection.size > 0) {
  
  			// Render depth of selected objects.
  			const mask = camera.layers.mask;
  			camera.layers.set(selection.layer);
  			this.depthPass.render(renderer);
  			camera.layers.mask = mask;
  
  			// Discard colors based on depth.
  			renderTarget = this.renderTargetMasked;
  			this.clearPass.render(renderer, renderTarget);
  			this.depthMaskPass.render(renderer, inputBuffer, renderTarget);
  
  		}
  
  		// Render the bloom texture as usual.
  		super.update(renderer, renderTarget, deltaTime);
  
  	}
  
  	/**
  	 * Updates the size of internal render targets.
  	 *
  	 * @param {Number} width - The width.
  	 * @param {Number} height - The height.
  	 */
  
  	setSize(width, height) {
  
  		super.setSize(width, height);
  
  		this.clearPass.setSize(width, height);
  		this.depthPass.setSize(width, height);
  		this.depthMaskPass.setSize(width, height);
  		this.renderTargetMasked.setSize(width, height);
  
  	}
  
  	/**
  	 * Performs initialization tasks.
  	 *
  	 * @param {WebGLRenderer} renderer - The renderer.
  	 * @param {Boolean} alpha - Whether the renderer uses the alpha channel.
  	 * @param {Number} frameBufferType - The type of the main frame buffers.
  	 */
  
  	initialize(renderer, alpha, frameBufferType) {
  
  		super.initialize(renderer, alpha, frameBufferType);
  
  		this.clearPass.initialize(renderer, alpha, frameBufferType);
  		this.depthPass.initialize(renderer, alpha, frameBufferType);
  		this.depthMaskPass.initialize(renderer, alpha, frameBufferType);
  
  		if(frameBufferType !== undefined) {
  
  			this.renderTargetMasked.texture.type = frameBufferType;
  
  			if(renderer.outputEncoding === sRGBEncoding) {
  
  				this.renderTargetMasked.texture.encoding = sRGBEncoding;
  
  			}
  
  		}
  
  	}
  
  }
  