constructor( scene, camera, params = {} ) {

		super( 'vec4' );

		const {
			selectedObjects = [],
			edgeThickness = float( 1 ),
			edgeGlow = float( 0 ),
			downSampleRatio = 2
		} = params;

		/**
		 * A reference to the scene.
		 *
		 * @type {Scene}
		 */
		this.scene = scene;

		/**
		 * The camera the scene is rendered with.
		 *
		 * @type {Camera}
		 */
		this.camera = camera;

		/**
		 * An array of selected objects.
		 *
		 * @type {Array<Object3D>}
		 */
		this.selectedObjects = selectedObjects;

		/**
		 * The thickness of the edges.
		 *
		 * @type {Node<float>}
		 */
		this.edgeThicknessNode = nodeObject( edgeThickness );

		/**
		 * Can be used for an animated glow/pulse effect.
		 *
		 * @type {Node<float>}
		 */
		this.edgeGlowNode = nodeObject( edgeGlow );

		/**
		 * The downsample ratio.
		 *
		 * @type {number}
		 * @default 2
		 */
		this.downSampleRatio = downSampleRatio;

		/**
		 * The `updateBeforeType` is set to `NodeUpdateType.FRAME` since the node renders
		 * its effect once per frame in `updateBefore()`.
		 *
		 * @type {string}
		 * @default 'frame'
		 */
		this.updateBeforeType = NodeUpdateType.FRAME;

		// render targets

		/**
		 * The render target for the depth pre-pass.
		 *
		 * @private
		 * @type {RenderTarget}
		 */
		this._renderTargetDepthBuffer = new RenderTarget();
		this._renderTargetDepthBuffer.depthTexture = new DepthTexture();
		this._renderTargetDepthBuffer.depthTexture.type = FloatType;

		/**
		 * The render target for the mask pass.
		 *
		 * @private
		 * @type {RenderTarget}
		 */
		this._renderTargetMaskBuffer = new RenderTarget();

		/**
		 * The render target for the mask downsample.
		 *
		 * @private
		 * @type {RenderTarget}
		 */
		this._renderTargetMaskDownSampleBuffer = new RenderTarget( 1, 1, { depthBuffer: false } );

		/**
		 * The first render target for the edge detection.
		 *
		 * @private
		 * @type {RenderTarget}
		 */
		this._renderTargetEdgeBuffer1 = new RenderTarget( 1, 1, { depthBuffer: false } );

		/**
		 * The second render target for the edge detection.
		 *
		 * @private
		 * @type {RenderTarget}
		 */
		this._renderTargetEdgeBuffer2 = new RenderTarget( 1, 1, { depthBuffer: false } );

		/**
		 * The first render target for the blur pass.
		 *
		 * @private
		 * @type {RenderTarget}
		 */
		this._renderTargetBlurBuffer1 = new RenderTarget( 1, 1, { depthBuffer: false } );

		/**
		 * The second render target for the blur pass.
		 *
		 * @private
		 * @type {RenderTarget}
		 */
		this._renderTargetBlurBuffer2 = new RenderTarget( 1, 1, { depthBuffer: false } );

		/**
		 * The render target for the final composite.
		 *
		 * @private
		 * @type {RenderTarget}
		 */
		this._renderTargetComposite = new RenderTarget( 1, 1, { depthBuffer: false } );

		// uniforms

		/**
		 * Represents the near value of the scene's camera.
		 *
		 * @private
		 * @type {ReferenceNode<float>}
		 */
		this._cameraNear = reference( 'near', 'float', camera );

		/**
		 * Represents the far value of the scene's camera.
		 *
		 * @private
		 * @type {ReferenceNode<float>}
		 */
		this._cameraFar = reference( 'far', 'float', camera );

		/**
		 * Uniform that represents the blur direction of the pass.
		 *
		 * @private
		 * @type {UniformNode<vec2>}
		 */
		this._blurDirection = uniform( new Vector2() );

		/**
		 * Texture node that holds the data from the depth pre-pass.
		 *
		 * @private
		 * @type {TextureNode}
		 */
		this._depthTextureUniform = texture( this._renderTargetDepthBuffer.depthTexture );

		/**
		 * Texture node that holds the data from the mask pass.
		 *
		 * @private
		 * @type {TextureNode}
		 */
		this._maskTextureUniform = texture( this._renderTargetMaskBuffer.texture );

		/**
		 * Texture node that holds the data from the mask downsample pass.
		 *
		 * @private
		 * @type {TextureNode}
		 */
		this._maskTextureDownsSampleUniform = texture( this._renderTargetMaskDownSampleBuffer.texture );

		/**
		 * Texture node that holds the data from the first edge detection pass.
		 *
		 * @private
		 * @type {TextureNode}
		 */
		this._edge1TextureUniform = texture( this._renderTargetEdgeBuffer1.texture );

		/**
		 * Texture node that holds the data from the second edge detection pass.
		 *
		 * @private
		 * @type {TextureNode}
		 */
		this._edge2TextureUniform = texture( this._renderTargetEdgeBuffer2.texture );

		/**
		 * Texture node that holds the current blurred color data.
		 *
		 * @private
		 * @type {TextureNode}
		 */
		this._blurColorTextureUniform = texture( this._renderTargetEdgeBuffer1.texture );

		// constants

		/**
		 * Visible edge color.
		 *
		 * @private
		 * @type {Node<vec3>}
		 */
		this._visibleEdgeColor = vec3( 1, 0, 0 );

		/**
		 * Hidden edge color.
		 *
		 * @private
		 * @type {Node<vec3>}
		 */
		this._hiddenEdgeColor = vec3( 0, 1, 0 );

		// materials

		/**
		 * The material for the depth pre-pass.
		 *
		 * @private
		 * @type {NodeMaterial}
		 */
		this._depthMaterial = new NodeMaterial();
		this._depthMaterial.fragmentNode = vec4( 0, 0, 0, 1 );
		this._depthMaterial.name = 'OutlineNode.depth';

		/**
		 * The material for preparing the mask.
		 *
		 * @private
		 * @type {NodeMaterial}
		 */
		this._prepareMaskMaterial = new NodeMaterial();
		this._prepareMaskMaterial.name = 'OutlineNode.prepareMask';

		/**
		 * The copy material
		 *
		 * @private
		 * @type {NodeMaterial}
		 */
		this._materialCopy = new NodeMaterial();
		this._materialCopy.name = 'OutlineNode.copy';

		/**
		 * The edge detection material.
		 *
		 * @private
		 * @type {NodeMaterial}
		 */
		this._edgeDetectionMaterial = new NodeMaterial();
		this._edgeDetectionMaterial.name = 'OutlineNode.edgeDetection';

		/**
		 * The material that is used to render in the blur pass.
		 *
		 * @private
		 * @type {NodeMaterial}
		 */
		this._separableBlurMaterial = new NodeMaterial();
		this._separableBlurMaterial.name = 'OutlineNode.separableBlur';

		/**
		 * The material that is used to render in the blur pass.
		 *
		 * @private
		 * @type {NodeMaterial}
		 */
		this._separableBlurMaterial2 = new NodeMaterial();
		this._separableBlurMaterial2.name = 'OutlineNode.separableBlur2';

		/**
		 * The final composite material.
		 *
		 * @private
		 * @type {NodeMaterial}
		 */
		this._compositeMaterial = new NodeMaterial();
		this._compositeMaterial.name = 'OutlineNode.composite';

		/**
		 * A set to cache selected objects in the scene.
		 *
		 * @private
		 * @type {Set<Object3D>}
		 */
		this._selectionCache = new Set();

		/**
		 * The result of the effect is represented as a separate texture node.
		 *
		 * @private
		 * @type {PassTextureNode}
		 */
		this._textureNode = passTexture( this, this._renderTargetComposite.texture );

	}
Constructs a new outline node.

@param {Scene} scene - A reference to the scene.
@param {Camera} camera - The camera the scene is rendered with.
@param {Object} params - The configuration parameters.
@param {Array<Object3D>} params.selectedObjects - An array of selected objects.
@param {Node<float>} [params.edgeThickness=float(1)] - The thickness of the edges.
@param {Node<float>} [params.edgeGlow=float(0)] - Can be used for an animated glow/pulse effects.
@param {number} [params.downSampleRatio=2] - The downsample ratio.