Home Reference Source

src/effects/blending/BlendMode.js

import { EventDispatcher, Uniform } from "three";
import { BlendFunction } from "../../enums/BlendFunction.js";

import add from "./glsl/add.frag";
import alpha from "./glsl/alpha.frag";
import average from "./glsl/average.frag";
import color from "./glsl/color.frag";
import colorBurn from "./glsl/color-burn.frag";
import colorDodge from "./glsl/color-dodge.frag";
import darken from "./glsl/darken.frag";
import difference from "./glsl/difference.frag";
import divide from "./glsl/divide.frag";
import exclusion from "./glsl/exclusion.frag";
import hardLight from "./glsl/hard-light.frag";
import hardMix from "./glsl/hard-mix.frag";
import hue from "./glsl/hue.frag";
import invert from "./glsl/invert.frag";
import invertRGB from "./glsl/invert-rgb.frag";
import lighten from "./glsl/lighten.frag";
import linearBurn from "./glsl/linear-burn.frag";
import linearDodge from "./glsl/linear-dodge.frag";
import linearLight from "./glsl/linear-light.frag";
import luminosity from "./glsl/luminosity.frag";
import multiply from "./glsl/multiply.frag";
import negation from "./glsl/negation.frag";
import normal from "./glsl/normal.frag";
import overlay from "./glsl/overlay.frag";
import pinLight from "./glsl/pin-light.frag";
import reflect from "./glsl/reflect.frag";
import saturation from "./glsl/saturation.frag";
import screen from "./glsl/screen.frag";
import softLight from "./glsl/soft-light.frag";
import src from "./glsl/src.frag";
import subtract from "./glsl/subtract.frag";
import vividLight from "./glsl/vivid-light.frag";

/**
 * A blend function shader code catalogue.
 *
 * @type {Map<BlendFunction, String>}
 * @private
 */

const blendFunctions = new Map([
	[BlendFunction.ADD, add],
	[BlendFunction.ALPHA, alpha],
	[BlendFunction.AVERAGE, average],
	[BlendFunction.COLOR, color],
	[BlendFunction.COLOR_BURN, colorBurn],
	[BlendFunction.COLOR_DODGE, colorDodge],
	[BlendFunction.DARKEN, darken],
	[BlendFunction.DIFFERENCE, difference],
	[BlendFunction.DIVIDE, divide],
	[BlendFunction.DST, null],
	[BlendFunction.EXCLUSION, exclusion],
	[BlendFunction.HARD_LIGHT, hardLight],
	[BlendFunction.HARD_MIX, hardMix],
	[BlendFunction.HUE, hue],
	[BlendFunction.INVERT, invert],
	[BlendFunction.INVERT_RGB, invertRGB],
	[BlendFunction.LIGHTEN, lighten],
	[BlendFunction.LINEAR_BURN, linearBurn],
	[BlendFunction.LINEAR_DODGE, linearDodge],
	[BlendFunction.LINEAR_LIGHT, linearLight],
	[BlendFunction.LUMINOSITY, luminosity],
	[BlendFunction.MULTIPLY, multiply],
	[BlendFunction.NEGATION, negation],
	[BlendFunction.NORMAL, normal],
	[BlendFunction.OVERLAY, overlay],
	[BlendFunction.PIN_LIGHT, pinLight],
	[BlendFunction.REFLECT, reflect],
	[BlendFunction.SATURATION, saturation],
	[BlendFunction.SCREEN, screen],
	[BlendFunction.SOFT_LIGHT, softLight],
	[BlendFunction.SRC, src],
	[BlendFunction.SUBTRACT, subtract],
	[BlendFunction.VIVID_LIGHT, vividLight]
]);

/**
 * A blend mode.
 */

export class BlendMode extends EventDispatcher {

	/**
	 * Constructs a new blend mode.
	 *
	 * @param {BlendFunction} blendFunction - The blend function.
	 * @param {Number} opacity - The opacity of the color that will be blended with the base color.
	 */

	constructor(blendFunction, opacity = 1.0) {

		super();

		/**
		 * Backing data for {@link blendFunction}.
		 *
		 * @type {BlendFunction}
		 * @private
		 */

		this._blendFunction = blendFunction;

		/**
		 * A uniform that controls the opacity of this blend mode.
		 *
		 * TODO Add opacity accessors for uniform value.
		 * @type {Uniform}
		 */

		this.opacity = new Uniform(opacity);

	}

	/**
	 * Returns the opacity.
	 *
	 * @return {Number} The opacity.
	 */

	getOpacity() {

		return this.opacity.value;

	}

	/**
	 * Sets the opacity.
	 *
	 * @param {Number} value - The opacity.
	 */

	setOpacity(value) {

		this.opacity.value = value;

	}

	/**
	 * The blend function.
	 *
	 * @type {BlendFunction}
	 */

	get blendFunction() {

		return this._blendFunction;

	}

	set blendFunction(value) {

		this._blendFunction = value;
		this.dispatchEvent({ type: "change" });

	}

	/**
	 * Returns the blend function.
	 *
	 * @deprecated Use blendFunction instead.
	 * @return {BlendFunction} The blend function.
	 */

	getBlendFunction() {

		return this.blendFunction;

	}

	/**
	 * Sets the blend function.
	 *
	 * @deprecated Use blendFunction instead.
	 * @param {BlendFunction} value - The blend function.
	 */

	setBlendFunction(value) {

		this.blendFunction = value;

	}

	/**
	 * Returns the blend function shader code.
	 *
	 * @return {String} The blend function shader code.
	 */

	getShaderCode() {

		return blendFunctions.get(this.blendFunction);

	}

}