Home Reference Source

src/passes/AdaptiveLuminancePass.js

import { NearestFilter, WebGLRenderTarget } from "three";
import { AdaptiveLuminanceMaterial } from "../materials/AdaptiveLuminanceMaterial.js";
import { CopyPass } from "./CopyPass.js";
import { Pass } from "./Pass.js";

/**
 * A pass that renders an adaptive luminance map.
 */

export class AdaptiveLuminancePass extends Pass {

	/**
	 * Constructs a new adaptive luminance pass.
	 *
	 * @param {Texture} luminanceBuffer - A buffer that contains the current scene luminance.
	 * @param {Object} [options] - The options.
	 * @param {Number} [options.minLuminance=0.01] - The minimum luminance.
	 * @param {Number} [options.adaptationRate=1.0] - The luminance adaptation rate.
	 */

	constructor(luminanceBuffer, { minLuminance = 0.01, adaptationRate = 1.0 } = {}) {

		super("AdaptiveLuminancePass");

		this.fullscreenMaterial = new AdaptiveLuminanceMaterial();
		this.needsSwap = false;

		/**
		 * A 1x1 render target that stores a copy of the last adapted luminance.
		 *
		 * @type {WebGLRenderTarget}
		 * @private
		 */

		this.renderTargetPrevious = new WebGLRenderTarget(1, 1, {
			minFilter: NearestFilter,
			magFilter: NearestFilter,
			depthBuffer: false
		});

		this.renderTargetPrevious.texture.name = "Luminance.Previous";

		const material = this.fullscreenMaterial;
		material.luminanceBuffer0 = this.renderTargetPrevious.texture;
		material.luminanceBuffer1 = luminanceBuffer;
		material.minLuminance = minLuminance;
		material.adaptationRate = adaptationRate;

		/**
		 * A 1x1 render target that stores the adapted average luminance.
		 *
		 * @type {WebGLRenderTarget}
		 * @private
		 */

		this.renderTargetAdapted = this.renderTargetPrevious.clone();
		this.renderTargetAdapted.texture.name = "Luminance.Adapted";

		/**
		 * A save pass.
		 *
		 * @type {CopyPass}
		 * @private
		 */

		this.copyPass = new CopyPass(this.renderTargetPrevious, false);

	}

	/**
	 * The adaptive luminance texture.
	 *
	 * @type {Texture}
	 */

	get texture() {

		return this.renderTargetAdapted.texture;

	}

	/**
	 * Returns the adaptive 1x1 luminance texture.
	 *
	 * @deprecated Use texture instead.
	 * @return {Texture} The texture.
	 */

	getTexture() {

		return this.renderTargetAdapted.texture;

	}

	/**
	 * Sets the 1x1 mipmap level.
	 *
	 * This level is used to identify the smallest mipmap of the main luminance texture which contains the downsampled
	 * average scene luminance.
	 *
	 * @type {Number}
	 * @deprecated Use fullscreenMaterial.mipLevel1x1 instead.
	 */

	set mipLevel1x1(value) {

		this.fullscreenMaterial.mipLevel1x1 = value;

	}

	/**
	 * The luminance adaptation rate.
	 *
	 * @type {Number}
	 * @deprecated Use fullscreenMaterial.adaptationRate instead.
	 */

	get adaptationRate() {

		return this.fullscreenMaterial.adaptationRate;

	}

	/**
	 * @type {Number}
	 * @deprecated Use fullscreenMaterial.adaptationRate instead.
	 */

	set adaptationRate(value) {

		this.fullscreenMaterial.adaptationRate = value;

	}

	/**
	 * Renders the scene normals.
	 *
	 * @param {WebGLRenderer} renderer - The renderer.
	 * @param {WebGLRenderTarget} inputBuffer - A frame buffer that contains the result of the previous pass.
	 * @param {WebGLRenderTarget} outputBuffer - A frame buffer that serves as the output render target unless this pass renders to screen.
	 * @param {Number} [deltaTime] - The time between the last frame and the current one in seconds.
	 * @param {Boolean} [stencilTest] - Indicates whether a stencil mask is active.
	 */

	render(renderer, inputBuffer, outputBuffer, deltaTime, stencilTest) {

		// Use the frame delta time to chase after the current luminance.
		this.fullscreenMaterial.deltaTime = deltaTime;
		renderer.setRenderTarget(this.renderToScreen ? null : this.renderTargetAdapted);
		renderer.render(this.scene, this.camera);

		// Save the adapted luminance for the next frame.
		this.copyPass.render(renderer, this.renderTargetAdapted);

	}

}