UNPKG

@mesmotronic/three-retropass

Version:

RetroPass applies a retro aesthetic to your Three.js project, emulating the visual style of classic 8-bit and 16-bit games

194 lines (193 loc) 7.65 kB
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var _RetroPass_colorPalette, _RetroPass_autoDitheringOffset, _RetroPass_autoResolution, _RetroPass_pixelRatio; import * as THREE from 'three'; import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js'; import { RetroShader } from '../shaders/RetroShader'; import { createColorPalette } from '../../utils/createColorPalette'; import { createColorTexture } from '../../utils/createColorTexture'; import { isValidColorCount } from "../../utils/isValidColorCount"; /** * Post-processing pass for applying a retro-style effect with color quantization and dithering */ export class RetroPass extends ShaderPass { /** * Creates a new RetroPass instance * @param parameters - Configuration parameters for the retro effect */ constructor({ colorCount = 16, colorPalette, dithering = true, ditheringOffset = 0.2, autoDitheringOffset = false, pixelRatio = 0.25, resolution = new THREE.Vector2(320, 200), autoResolution = false, } = {}) { super(RetroShader); Object.defineProperty(this, "size", { enumerable: true, configurable: true, writable: true, value: new THREE.Vector2() }); _RetroPass_colorPalette.set(this, void 0); _RetroPass_autoDitheringOffset.set(this, false); _RetroPass_autoResolution.set(this, false); _RetroPass_pixelRatio.set(this, 0); this.dithering = dithering; this.ditheringOffset = ditheringOffset; this.autoDitheringOffset = autoDitheringOffset; this.pixelRatio = pixelRatio; this.resolution = resolution; this.autoResolution = autoResolution; if (colorPalette) { this.colorPalette = colorPalette; } else { this.colorCount = colorCount; } } /** * Pixel resolution to use */ get resolution() { return this.uniforms.uResolution.value; } set resolution(value) { if (!value.equals(this.uniforms.uResolution.value)) { this.uniforms.uResolution.value.copy(value); } } /** * Whether to automatically update the resolution based on the specified pixelRatio */ get autoResolution() { return __classPrivateFieldGet(this, _RetroPass_autoResolution, "f"); } set autoResolution(value) { if (__classPrivateFieldGet(this, _RetroPass_autoResolution, "f") !== value) { __classPrivateFieldSet(this, _RetroPass_autoResolution, value, "f"); this.updateResolution(); } } /** * Pixel ratio to use if autoResolution is true, typically 0.0-1.0 (optional) */ get pixelRatio() { return __classPrivateFieldGet(this, _RetroPass_pixelRatio, "f"); } set pixelRatio(value) { if (__classPrivateFieldGet(this, _RetroPass_pixelRatio, "f") !== value) { __classPrivateFieldSet(this, _RetroPass_pixelRatio, value, "f"); this.updateResolution(); } } /** * The number of colors in the palette */ get colorCount() { return this.uniforms.uColorCount.value; } set colorCount(value) { if (value !== this.colorCount) { if (!isValidColorCount(value)) { throw new Error(`Invalid colorPalette, must contain between 2 and 4096 colours`); } this.uniforms.uIsQuantized.value = true; this.setColorPalette(createColorPalette(value)); } } /** * The current color palette */ get colorPalette() { return __classPrivateFieldGet(this, _RetroPass_colorPalette, "f"); } set colorPalette(colors) { const colorCount = colors?.length; if (!isValidColorCount(colorCount)) { throw new Error(`Invalid colorPalette, must contain between 2 and 4096 colours`); } this.uniforms.uIsQuantized.value = false; this.setColorPalette(colors); } /** * Whether or not to apply dithering */ get dithering() { return this.uniforms.uDithering.value; } set dithering(value) { this.uniforms.uDithering.value = value; } /** * The amount of dithering to apply, typically 0.0 to 1.0 */ get ditheringOffset() { return this.uniforms.uDitheringOffset.value; } set ditheringOffset(value) { this.uniforms.uDitheringOffset.value = value; } /** * Whether to automatically update the dithering offset based on the color count */ get autoDitheringOffset() { return __classPrivateFieldGet(this, _RetroPass_autoDitheringOffset, "f"); } set autoDitheringOffset(value) { if (__classPrivateFieldGet(this, _RetroPass_autoDitheringOffset, "f") !== value) { __classPrivateFieldSet(this, _RetroPass_autoDitheringOffset, value, "f"); if (value) { this.updateDitheringOffset(); } } } /** * Whether to invert the image before processing */ get inverted() { return this.uniforms.uInverted.value; } set inverted(value) { this.uniforms.uInverted.value = value; } /** * Set the pixel resolution to use (used by EffectComposer) * @see {@link RetroPass.resolution} */ setSize(width, height) { this.size.set(width, height); this.updateResolution(); } /** * Updates the resolution based on the current pixel ratio and size */ updateResolution() { if (this.autoResolution) { this.resolution.set(this.size.x * this.pixelRatio, this.size.y * this.pixelRatio); } } /** * Updates the dithering offset based on the current color count */ updateDitheringOffset() { if (this.autoDitheringOffset) { this.ditheringOffset = 0.03 + 0.97 / (this.colorCount - 1); } } setColorPalette(colors) { const colorCount = colors?.length; const colorTexture = createColorTexture(colors); this.uniforms.uColorCount.value = colorCount; this.uniforms.uColorTexture.value?.dispose(); this.uniforms.uColorTexture.value = colorTexture; if (this.autoDitheringOffset) { this.updateDitheringOffset(); } __classPrivateFieldSet(this, _RetroPass_colorPalette, colors.slice(), "f"); } } _RetroPass_colorPalette = new WeakMap(), _RetroPass_autoDitheringOffset = new WeakMap(), _RetroPass_autoResolution = new WeakMap(), _RetroPass_pixelRatio = new WeakMap();