UNPKG

postprocessing-fork

Version:

A post processing library for three.js.

1,525 lines (1,491 loc) 2.05 MB
/** * postprocessing-fork v6.37.4 build Mon Sep 15 2025 * https://github.com/pmndrs/postprocessing * Copyright 2015-2025 Raoul van Rüschen * @license Zlib */ if(typeof window==="object"&&!window.require)window.require=()=>window.THREE; "use strict"; var POSTPROCESSINGFORK = (() => { var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) { if (typeof require !== "undefined") return require.apply(this, arguments); throw Error('Dynamic require of "' + x + '" is not supported'); }); var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); // src/index.js var index_exports = {}; __export(index_exports, { ASCIIEffect: () => ASCIIEffect, ASCIITexture: () => ASCIITexture, AdaptiveLuminanceMaterial: () => AdaptiveLuminanceMaterial, AdaptiveLuminancePass: () => AdaptiveLuminancePass, AdaptiveSharpenEffect: () => AdaptiveSharpenEffect, BlendFunction: () => BlendFunction, BlendMode: () => BlendMode, BloomEffect: () => BloomEffect, BlurPass: () => KawaseBlurPass, BokehEffect: () => BokehEffect, BokehMaterial: () => BokehMaterial, BoxBlurMaterial: () => BoxBlurMaterial, BoxBlurPass: () => BoxBlurPass, BrightnessContrastEffect: () => BrightnessContrastEffect, ChromaticAberrationEffect: () => ChromaticAberrationEffect, CircleOfConfusionMaterial: () => CircleOfConfusionMaterial, ClearMaskPass: () => ClearMaskPass, ClearPass: () => ClearPass, ColorAverageEffect: () => ColorAverageEffect, ColorChannel: () => ColorChannel, ColorDepthEffect: () => ColorDepthEffect, ColorEdgesMaterial: () => EdgeDetectionMaterial, ConvolutionMaterial: () => KawaseBlurMaterial, CopyMaterial: () => CopyMaterial, CopyPass: () => CopyPass, CustomSSGIEffect: () => CustomSSGIEffect, DayNightCycleEffect: () => DayNightCycleEffect, DenoiseEffect: () => DenoiseEffect, DepthComparisonMaterial: () => DepthComparisonMaterial, DepthCopyMaterial: () => DepthCopyMaterial, DepthCopyMode: () => DepthCopyMode, DepthCopyPass: () => DepthCopyPass, DepthDownsamplingMaterial: () => DepthDownsamplingMaterial, DepthDownsamplingPass: () => DepthDownsamplingPass, DepthEffect: () => DepthEffect, DepthMaskMaterial: () => DepthMaskMaterial, DepthOfFieldEffect: () => DepthOfFieldEffect, DepthPass: () => DepthPass, DepthPickingPass: () => DepthPickingPass, DepthSavePass: () => DepthCopyPass, DepthTestStrategy: () => DepthTestStrategy, Disposable: () => Disposable, DotScreenEffect: () => DotScreenEffect, DownsamplingMaterial: () => DownsamplingMaterial, EdgeDetectionMaterial: () => EdgeDetectionMaterial, EdgeDetectionMode: () => EdgeDetectionMode, Effect: () => Effect, EffectAttribute: () => EffectAttribute, EffectComposer: () => EffectComposer, EffectMaterial: () => EffectMaterial, EffectPass: () => EffectPass, EffectShaderData: () => EffectShaderData, EffectShaderSection: () => EffectShaderSection, EnhancedThreeCompatPass: () => EnhancedThreeCompatPass, FXAAEffect: () => FXAAEffect, FakeInteriorMaterial: () => FakeInteriorMaterial, FlowRiverMaterial: () => FlowRiverMaterial, FoggyFlyoverEffect: () => FoggyFlyoverEffect, FoggyMountainsEffect: () => FoggyMountainsEffect, FoggyTerrainEffect: () => FoggyTerrainEffect, FrozenWastelandEffect: () => FrozenWastelandEffect, GammaCorrectionEffect: () => GammaCorrectionEffect, GaussKernel: () => GaussKernel, GaussianBlurMaterial: () => GaussianBlurMaterial, GaussianBlurPass: () => GaussianBlurPass, GlitchEffect: () => GlitchEffect, GlitchMode: () => GlitchMode, GodRaysEffect: () => GodRaysEffect, GodRaysMaterial: () => GodRaysMaterial, GridEffect: () => GridEffect, HBAOEffect: () => HBAOEffect, HueSaturationEffect: () => HueSaturationEffect, IdManager: () => IdManager, ImmutableTimer: () => ImmutableTimer, Initializable: () => Initializable, InteriorMappingMaterial: () => InteriorMappingMaterial, InteriorRoomMaterial: () => InteriorRoomMaterial, KawaseBlurMaterial: () => KawaseBlurMaterial, KawaseBlurPass: () => KawaseBlurPass, KernelSize: () => KernelSize, LUT1DEffect: () => LUT1DEffect, LUT3DEffect: () => LUT3DEffect, LUT3dlLoader: () => LUT3dlLoader, LUTCubeLoader: () => LUTCubeLoader, LUTEffect: () => LUT3DEffect, LUTOperation: () => LUTOperation, LakesMountainsEffect: () => LakesMountainsEffect, LambdaPass: () => LambdaPass, LensDistortionEffect: () => LensDistortionEffect, LookupTexture: () => LookupTexture, LookupTexture3D: () => LookupTexture, LuminanceMaterial: () => LuminanceMaterial, LuminancePass: () => LuminancePass, MRTRenderPass: () => MRTRenderPass, MaskFunction: () => MaskFunction, MaskMaterial: () => MaskMaterial, MaskPass: () => MaskPass, MipmapBlurPass: () => MipmapBlurPass, MotionBlurEffect: () => MotionBlurEffect2, MultiSampleDepthMaskMaterial: () => MultiSampleDepthMaskMaterial, NoiseEffect: () => NoiseEffect, NoiseTexture: () => NoiseTexture, NormalPass: () => NormalPass, OceanMaterial: () => OceanMaterial, OutlineEdgesMaterial: () => OutlineMaterial, OutlineEffect: () => OutlineEffect, OutlineManager: () => OutlineManager, OutlineMaterial: () => OutlineMaterial, OutlineMultiEffect: () => OutlineMultiEffect, OverrideMaterialManager: () => OverrideMaterialManager, Pass: () => Pass, PerformanceLogger: () => PerformanceLogger, PixelationEffect: () => PixelationEffect, PoissionDenoisePass: () => PoissionDenoisePass2, PoissonDenoisePass: () => PoissonDenoisePass, PredicationMode: () => PredicationMode, RAOPass: () => AOPass, RSSAOEffect: () => SSAOEffect3, RainfallEffect: () => RainfallEffect, RawImageData: () => RawImageData, RealismNew: () => realism_new_exports, RealismSSAOEffect: () => SSAOEffect3, RealisticBokehEffect: () => RealisticBokehEffect, ReflectorForSSRPass: () => ReflectorForSSRPass, RenderPass: () => RenderPass, Resizable: () => Resizable, Resizer: () => Resolution, Resolution: () => Resolution, RiverMaterial: () => RiverMaterial, SMAAAreaImageData: () => SMAAAreaImageData, SMAAEffect: () => SMAAEffect, SMAAImageGenerator: () => SMAAImageGenerator, SMAAImageLoader: () => SMAAImageLoader, SMAAPreset: () => SMAAPreset, SMAASearchImageData: () => SMAASearchImageData, SMAAWeightsMaterial: () => SMAAWeightsMaterial, SSAOEffect: () => SSAOEffect, SSAOMaterial: () => SSAOMaterial, SSDOEffect: () => SSDOEffect, SSGIEffect: () => SSGIEffect, SSREffect: () => SSREffect, SSRPass: () => SSRPass, SandStormEffect: () => SandStormEffect, SavePass: () => CopyPass, ScanlineEffect: () => ScanlineEffect, Section: () => EffectShaderSection, Selection: () => Selection, SelectiveBloomEffect: () => SelectiveBloomEffect, SelectiveSSAOEffect: () => SelectiveSSAOEffect, SelectiveSSRPass: () => SelectiveSSRPass, SepiaEffect: () => SepiaEffect, ShaderPass: () => ShaderPass, SharedOutlineEffect: () => SharedOutlineEffect, SharpenEffect: () => SharpenEffect, SharpnessEffect: () => SharpnessEffect, ShockWaveEffect: () => ShockWaveEffect, SkyAtmosphereEffect: () => SkyAtmosphereEffect, SkyAtmosphereUtils: () => SkyAtmosphereUtils, SnowOverlayEffect: () => SnowOverlayEffect, SnowfallEffect: () => SnowfallEffect, TRAAEffect: () => TRAAEffect, TangentSpaceInteriorMaterial: () => TangentSpaceInteriorMaterial, TetrahedralUpscaler: () => TetrahedralUpscaler, TextureEffect: () => TextureEffect, ThreeCompatPass: () => ThreeCompatPass, TiltShiftBlurMaterial: () => TiltShiftBlurMaterial, TiltShiftBlurPass: () => TiltShiftBlurPass, TiltShiftEffect: () => TiltShiftEffect, Timer: () => Timer, ToneMappingEffect: () => ToneMappingEffect, ToneMappingMode: () => ToneMappingMode, UniformFogEffect: () => UniformFogEffect, UpsamplingMaterial: () => UpsamplingMaterial, VelocityDepthNormalPass: () => VelocityDepthNormalPass, VelocityPass: () => VelocityPass2, VignetteEffect: () => VignetteEffect, VignetteTechnique: () => VignetteTechnique, VolumetricAtmosphereEffect: () => VolumetricAtmosphereEffect, VolumetricFogEffect: () => VolumetricFogEffect, VolumetricShadowEffect: () => VolumetricShadowEffect, WeatherManager: () => WeatherManager, WeatherSystemEffect: () => WeatherSystemEffect, WebGLExtension: () => WebGLExtension, clearTimeData: () => clearTimeData, disableLogs: () => disableLogs, disableTimeCollection: () => disableTimeCollection, enableLogs: () => enableLogs, enableTimeCollection: () => enableTimeCollection, error: () => error, getAssets: () => getAssets, getTimeData: () => getTimeData, log: () => log, orthographicDepthToViewZ: () => orthographicDepthToViewZ, printSummary: () => printSummary, renderUtils: () => renderUtils, timeEndLog: () => timeEndLog, timeLog: () => timeLog, version: () => version, viewZToOrthographicDepth: () => viewZToOrthographicDepth, warn: () => warn }); // package.json var version = "6.37.4"; // src/core/index.js var import_three9 = __require("three"); // src/core/Disposable.js var Disposable = class { /** * Frees internal resources. */ dispose() { } }; // src/core/EffectComposer.js var import_three7 = __require("three"); // src/core/Timer.js var MILLISECONDS_TO_SECONDS = 1 / 1e3; var SECONDS_TO_MILLISECONDS = 1e3; var Timer = class { /** * Constructs a new timer. */ constructor() { this.startTime = performance.now(); this.previousTime = 0; this.currentTime = 0; this._delta = 0; this._elapsed = 0; this._fixedDelta = 1e3 / 60; this.timescale = 1; this.useFixedDelta = false; this._autoReset = false; } /** * Enables or disables auto reset based on page visibility. * * If enabled, the timer will be reset when the page becomes visible. This effectively pauses the timer when the page * is hidden. Has no effect if the API is not supported. * * @type {Boolean} * @see https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API */ get autoReset() { return this._autoReset; } set autoReset(value) { if (typeof document !== "undefined" && document.hidden !== void 0) { if (value) { document.addEventListener("visibilitychange", this); } else { document.removeEventListener("visibilitychange", this); } this._autoReset = value; } } get delta() { return this._delta * MILLISECONDS_TO_SECONDS; } get fixedDelta() { return this._fixedDelta * MILLISECONDS_TO_SECONDS; } set fixedDelta(value) { this._fixedDelta = value * SECONDS_TO_MILLISECONDS; } get elapsed() { return this._elapsed * MILLISECONDS_TO_SECONDS; } /** * Updates this timer. * * @param {Boolean} [timestamp] - The current time in milliseconds. */ update(timestamp) { if (this.useFixedDelta) { this._delta = this.fixedDelta; } else { this.previousTime = this.currentTime; this.currentTime = (timestamp !== void 0 ? timestamp : performance.now()) - this.startTime; this._delta = this.currentTime - this.previousTime; } this._delta *= this.timescale; this._elapsed += this._delta; } /** * Resets this timer. */ reset() { this._delta = 0; this._elapsed = 0; this.currentTime = performance.now() - this.startTime; } getDelta() { return this.delta; } getElapsed() { return this.elapsed; } handleEvent(e) { if (!document.hidden) { this.currentTime = performance.now() - this.startTime; } } dispose() { this.autoReset = false; } }; // src/passes/Pass.js var import_run_scene_core = __require("run-scene-core"); var fullscreenGeometry = /* @__PURE__ */ (() => { const vertices = new Float32Array([-1, -1, 0, 3, -1, 0, -1, 3, 0]); const uvs = new Float32Array([0, 0, 2, 0, 0, 2]); const geometry = new import_run_scene_core.BufferGeometry(); geometry.setAttribute("position", new import_run_scene_core.BufferAttribute(vertices, 3)); geometry.setAttribute("uv", new import_run_scene_core.BufferAttribute(uvs, 2)); return geometry; })(); var Pass = class _Pass { /** * A shared fullscreen triangle. * * The screen size is 2x2 units (NDC). A triangle needs to be 4x4 units to fill the screen. * @see https://michaldrobot.com/2014/04/01/gcn-execution-patterns-in-full-screen-passes/ * @type {BufferGeometry} * @internal */ static get fullscreenGeometry() { return fullscreenGeometry; } /** * Constructs a new pass. * * @param {String} [name] - The name of this pass. Does not have to be unique. * @param {Scene} [scene] - The scene to render. The default scene contains a single mesh that fills the screen. * @param {Camera} [camera] - A camera. Fullscreen effect passes don't require a camera. */ constructor(name = "Pass", scene = new import_run_scene_core.Scene(), camera = new import_run_scene_core.Camera()) { this.name = name; this.renderer = null; this.scene = scene; this.camera = camera; this.screen = null; this.rtt = true; this.needsSwap = true; this.needsDepthTexture = false; this.needsNormalTexture = false; this.enabled = true; } /** * Sets the render to screen flag. * * If this flag is changed, the fullscreen material will be updated as well. * * @type {Boolean} */ get renderToScreen() { return !this.rtt; } set renderToScreen(value) { if (this.rtt === value) { const material = this.fullscreenMaterial; if (material !== null) { material.needsUpdate = true; } this.rtt = !value; } } /** * Sets the main scene. * * @type {Scene} */ set mainScene(value) { } /** * Sets the main camera. * * @type {Camera} */ set mainCamera(value) { } /** * Sets the renderer * * @deprecated * @param {WebGLRenderer} renderer - The renderer. */ setRenderer(renderer) { this.renderer = renderer; } /** * Indicates whether this pass is enabled. * * @deprecated Use enabled instead. * @return {Boolean} Whether this pass is enabled. */ isEnabled() { return this.enabled; } /** * Enables or disables this pass. * * @deprecated Use enabled instead. * @param {Boolean} value - Whether the pass should be enabled. */ setEnabled(value) { this.enabled = value; } /** * The fullscreen material. * * @type {Material} */ get fullscreenMaterial() { return this.screen !== null ? this.screen.material : null; } set fullscreenMaterial(value) { let screen = this.screen; if (screen !== null) { screen.material = value; } else { screen = new import_run_scene_core.Mesh(_Pass.fullscreenGeometry, value); screen.frustumCulled = false; if (this.scene === null) { this.scene = new import_run_scene_core.Scene(); } this.scene.add(screen); this.screen = screen; } } /** * Returns the current fullscreen material. * * @deprecated Use fullscreenMaterial instead. * @return {Material} The current fullscreen material, or null if there is none. */ getFullscreenMaterial() { return this.fullscreenMaterial; } /** * Sets the fullscreen material. * * @deprecated Use fullscreenMaterial instead. * @protected * @param {Material} value - A fullscreen material. */ setFullscreenMaterial(value) { this.fullscreenMaterial = value; } /** * Returns the current depth texture. * * @deprecated Use getDepthTexture instead. * @return {Texture} The current depth texture, or null if there is none. */ getDepthTexture() { return null; } /** * Sets the depth texture. * * This method will be called automatically by the {@link EffectComposer}. * You may override this method if your pass relies on the depth information of a preceding {@link RenderPass}. * * @param {Texture} depthTexture - A depth texture. * @param {DepthPackingStrategy} [depthPacking=BasicDepthPacking] - The depth packing. */ setDepthTexture(depthTexture, depthPacking = import_run_scene_core.BasicDepthPacking) { } /** * Returns the current normal texture. * * @return {Texture} The current normal texture, or null if there is none. */ getNormalTexture() { return null; } /** * Sets the normal texture. * * @param {Texture} normalTexture - A normal texture. */ setNormalTexture(normalTexture) { } /** * Renders this pass. * * This is an abstract method that must be overridden. * * @abstract * @throws {Error} An error is thrown if the method is not overridden. * @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. * @param {DepthPass} [depthPass] - An optional shared depth pass for optimizing multiple effects. */ render(renderer, inputBuffer, outputBuffer, deltaTime, stencilTest, depthPass) { throw new Error("Render method not implemented!"); } /** * Sets the size. * * You may override this method if you want to be informed about the size of the backbuffer/canvas. * This method is called before {@link initialize} and every time the size of the {@link EffectComposer} changes. * * @param {Number} width - The width. * @param {Number} height - The height. */ setSize(width, height) { } /** * Performs initialization tasks. * * This method is called when this pass is added to an {@link EffectComposer}. * * @param {WebGLRenderer} renderer - The renderer. * @param {Boolean} alpha - Whether the renderer uses the alpha channel or not. * @param {Number} frameBufferType - The type of the main frame buffers. */ initialize(renderer, alpha, frameBufferType) { } /** * Performs a shallow search for disposable properties and deletes them. * * The {@link EffectComposer} calls this method when it is being destroyed. You can use it independently to free * memory when you're certain that you don't need this pass anymore. */ dispose() { for (const key of Object.keys(this)) { const property = this[key]; const isDisposable = property instanceof import_run_scene_core.WebGLRenderTarget || property instanceof import_run_scene_core.Material || property instanceof import_run_scene_core.Texture || property instanceof _Pass; if (isDisposable) { this[key].dispose(); } } if (this.fullscreenMaterial !== null) { this.fullscreenMaterial.dispose(); } } }; // src/passes/ClearMaskPass.js var ClearMaskPass = class extends Pass { /** * Constructs a new clear mask pass. */ constructor() { super("ClearMaskPass", null, null); this.needsSwap = false; } /** * Disables the global stencil test. * * @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) { const stencil = renderer.state.buffers.stencil; stencil.setLocked(false); stencil.setTest(false); } }; // src/passes/CopyPass.js var import_three2 = __require("three"); // src/materials/CopyMaterial.js var import_three = __require("three"); // src/materials/glsl/copy.frag var copy_default = `#include <common> #include <dithering_pars_fragment> #ifdef FRAMEBUFFER_PRECISION_HIGH uniform mediump sampler2D inputBuffer; #else uniform lowp sampler2D inputBuffer; #endif uniform float opacity; varying vec2 vUv; void main() { vec4 texel = texture2D(inputBuffer, vUv); gl_FragColor = opacity * texel; #include <colorspace_fragment> #include <dithering_fragment> } `; // src/materials/glsl/common.vert var common_default = `varying vec2 vUv; void main() { vUv = position.xy * 0.5 + 0.5; gl_Position = vec4(position.xy, 1.0, 1.0); } `; // src/materials/CopyMaterial.js var CopyMaterial = class extends import_three.ShaderMaterial { /** * Constructs a new copy material. */ constructor() { super({ name: "CopyMaterial", uniforms: { inputBuffer: new import_three.Uniform(null), opacity: new import_three.Uniform(1) }, blending: import_three.NoBlending, toneMapped: false, depthWrite: false, depthTest: false, fragmentShader: copy_default, vertexShader: common_default }); } /** * The input buffer. * * @type {Texture} */ set inputBuffer(value) { this.uniforms.inputBuffer.value = value; } /** * Sets the input buffer. * * @deprecated Use inputBuffer instead. * @param {Number} value - The buffer. */ setInputBuffer(value) { this.uniforms.inputBuffer.value = value; } /** * Returns the opacity. * * @deprecated Use opacity instead. * @return {Number} The opacity. */ getOpacity(value) { return this.uniforms.opacity.value; } /** * Sets the opacity. * * @deprecated Use opacity instead. * @param {Number} value - The opacity. */ setOpacity(value) { this.uniforms.opacity.value = value; } }; // src/passes/CopyPass.js var CopyPass = class extends Pass { /** * Constructs a new save pass. * * @param {WebGLRenderTarget} [renderTarget] - A render target. * @param {Boolean} [autoResize=true] - Whether the render target size should be updated automatically. */ constructor(renderTarget, autoResize = true) { super("CopyPass"); this.fullscreenMaterial = new CopyMaterial(); this.needsSwap = false; this.renderTarget = renderTarget; if (renderTarget === void 0) { this.renderTarget = new import_three2.WebGLRenderTarget(1, 1, { minFilter: import_three2.LinearFilter, magFilter: import_three2.LinearFilter, stencilBuffer: false, depthBuffer: false }); this.renderTarget.texture.name = "CopyPass.Target"; } this.autoResize = autoResize; } /** * Enables or disables auto resizing of the render target. * * @deprecated Use autoResize instead. * @type {Boolean} */ get resize() { return this.autoResize; } set resize(value) { this.autoResize = value; } /** * The output texture. * * @type {Texture} */ get texture() { return this.renderTarget.texture; } /** * Returns the output texture. * * @deprecated Use texture instead. * @return {Texture} The texture. */ getTexture() { return this.renderTarget.texture; } /** * Enables or disables auto resizing of the render target. * * @deprecated Use autoResize instead. * @param {Boolean} value - Whether the render target size should be updated automatically. */ setAutoResizeEnabled(value) { this.autoResize = value; } /** * Saves the input buffer. * * @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) { this.fullscreenMaterial.inputBuffer = inputBuffer.texture; renderer.setRenderTarget(this.renderToScreen ? null : this.renderTarget); renderer.render(this.scene, this.camera); } /** * Updates the size of this pass. * * @param {Number} width - The width. * @param {Number} height - The height. */ setSize(width, height) { if (this.autoResize) { this.renderTarget.setSize(width, height); } } /** * Performs initialization tasks. * * @param {WebGLRenderer} renderer - A 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) { if (frameBufferType !== void 0) { this.renderTarget.texture.type = frameBufferType; if (frameBufferType !== import_three2.UnsignedByteType) { this.fullscreenMaterial.defines.FRAMEBUFFER_PRECISION_HIGH = "1"; } else if (renderer !== null && renderer.outputColorSpace === import_three2.SRGBColorSpace) { this.renderTarget.texture.colorSpace = import_three2.SRGBColorSpace; } } } }; // src/passes/DepthPass.js var import_three6 = __require("three"); // src/core/Resolution.js var import_three3 = __require("three"); var AUTO_SIZE = -1; var Resolution = class extends import_three3.EventDispatcher { /** * Constructs a new resolution. * * TODO Remove resizable param. * @param {Resizable} resizable - A resizable object. * @param {Number} [width=Resolution.AUTO_SIZE] - The preferred width. * @param {Number} [height=Resolution.AUTO_SIZE] - The preferred height. * @param {Number} [scale=1.0] - A resolution scale. */ constructor(resizable, width = AUTO_SIZE, height = AUTO_SIZE, scale = 1) { super(); this.resizable = resizable; this.baseSize = new import_three3.Vector2(1, 1); this.preferredSize = new import_three3.Vector2(width, height); this.target = this.preferredSize; this.s = scale; this.effectiveSize = new import_three3.Vector2(); this.addEventListener("change", () => this.updateEffectiveSize()); this.updateEffectiveSize(); } /** * Calculates the effective size. * * @private */ updateEffectiveSize() { const base3 = this.baseSize; const preferred = this.preferredSize; const effective = this.effectiveSize; const scale = this.scale; if (preferred.width !== AUTO_SIZE) { effective.width = preferred.width; } else if (preferred.height !== AUTO_SIZE) { effective.width = Math.round(preferred.height * (base3.width / Math.max(base3.height, 1))); } else { effective.width = Math.round(base3.width * scale); } if (preferred.height !== AUTO_SIZE) { effective.height = preferred.height; } else if (preferred.width !== AUTO_SIZE) { effective.height = Math.round(preferred.width / Math.max(base3.width / Math.max(base3.height, 1), 1)); } else { effective.height = Math.round(base3.height * scale); } } /** * The effective width. * * If the preferred width and height are set to {@link Resizer.AUTO_SIZE}, the base width will be returned. * * @type {Number} */ get width() { return this.effectiveSize.width; } set width(value) { this.preferredWidth = value; } /** * The effective height. * * If the preferred width and height are set to {@link Resizer.AUTO_SIZE}, the base height will be returned. * * @type {Number} */ get height() { return this.effectiveSize.height; } set height(value) { this.preferredHeight = value; } /** * Returns the effective width. * * If the preferred width and height are set to {@link Resizer.AUTO_SIZE}, the base width will be returned. * * @deprecated Use width instead. * @return {Number} The effective width. */ getWidth() { return this.width; } /** * Returns the effective height. * * If the preferred width and height are set to {@link Resizer.AUTO_SIZE}, the base height will be returned. * * @deprecated Use height instead. * @return {Number} The effective height. */ getHeight() { return this.height; } /** * The resolution scale. * * @type {Number} */ get scale() { return this.s; } set scale(value) { if (this.s !== value) { this.s = value; this.preferredSize.setScalar(AUTO_SIZE); this.dispatchEvent({ type: "change" }); this.resizable.setSize(this.baseSize.width, this.baseSize.height); } } /** * Returns the current resolution scale. * * @deprecated Use scale instead. * @return {Number} The scale. */ getScale() { return this.scale; } /** * Sets the resolution scale. * * Also sets the preferred resolution to {@link Resizer.AUTO_SIZE}. * * @deprecated Use scale instead. * @param {Number} value - The scale. */ setScale(value) { this.scale = value; } /** * The base width. * * @type {Number} */ get baseWidth() { return this.baseSize.width; } set baseWidth(value) { if (this.baseSize.width !== value) { this.baseSize.width = value; this.dispatchEvent({ type: "change" }); this.resizable.setSize(this.baseSize.width, this.baseSize.height); } } /** * Returns the base width. * * @deprecated Use baseWidth instead. * @return {Number} The base width. */ getBaseWidth() { return this.baseWidth; } /** * Sets the base width. * * @deprecated Use baseWidth instead. * @param {Number} value - The width. */ setBaseWidth(value) { this.baseWidth = value; } /** * The base height. * * @type {Number} */ get baseHeight() { return this.baseSize.height; } set baseHeight(value) { if (this.baseSize.height !== value) { this.baseSize.height = value; this.dispatchEvent({ type: "change" }); this.resizable.setSize(this.baseSize.width, this.baseSize.height); } } /** * Returns the base height. * * @deprecated Use baseHeight instead. * @return {Number} The base height. */ getBaseHeight() { return this.baseHeight; } /** * Sets the base height. * * @deprecated Use baseHeight instead. * @param {Number} value - The height. */ setBaseHeight(value) { this.baseHeight = value; } /** * Sets the base size. * * @param {Number} width - The width. * @param {Number} height - The height. */ setBaseSize(width, height) { if (this.baseSize.width !== width || this.baseSize.height !== height) { this.baseSize.set(width, height); this.dispatchEvent({ type: "change" }); this.resizable.setSize(this.baseSize.width, this.baseSize.height); } } /** * The preferred width. * * @type {Number} */ get preferredWidth() { return this.preferredSize.width; } set preferredWidth(value) { if (this.preferredSize.width !== value) { this.preferredSize.width = value; this.dispatchEvent({ type: "change" }); this.resizable.setSize(this.baseSize.width, this.baseSize.height); } } /** * Returns the preferred width. * * @deprecated Use preferredWidth instead. * @return {Number} The preferred width. */ getPreferredWidth() { return this.preferredWidth; } /** * Sets the preferred width. * * Use {@link Resizer.AUTO_SIZE} to automatically calculate the width based on the height and aspect ratio. * * @deprecated Use preferredWidth instead. * @param {Number} value - The width. */ setPreferredWidth(value) { this.preferredWidth = value; } /** * The preferred height. * * @type {Number} */ get preferredHeight() { return this.preferredSize.height; } set preferredHeight(value) { if (this.preferredSize.height !== value) { this.preferredSize.height = value; this.dispatchEvent({ type: "change" }); this.resizable.setSize(this.baseSize.width, this.baseSize.height); } } /** * Returns the preferred height. * * @deprecated Use preferredHeight instead. * @return {Number} The preferred height. */ getPreferredHeight() { return this.preferredHeight; } /** * Sets the preferred height. * * Use {@link Resizer.AUTO_SIZE} to automatically calculate the height based on the width and aspect ratio. * * @deprecated Use preferredHeight instead. * @param {Number} value - The height. */ setPreferredHeight(value) { this.preferredHeight = value; } /** * Sets the preferred size. * * @param {Number} width - The width. * @param {Number} height - The height. */ setPreferredSize(width, height) { if (this.preferredSize.width !== width || this.preferredSize.height !== height) { this.preferredSize.set(width, height); this.dispatchEvent({ type: "change" }); this.resizable.setSize(this.baseSize.width, this.baseSize.height); } } /** * Copies the given resolution. * * @param {Resolution} resolution - The resolution. */ copy(resolution) { this.s = resolution.scale; this.baseSize.set(resolution.baseWidth, resolution.baseHeight); this.preferredSize.set(resolution.preferredWidth, resolution.preferredHeight); this.dispatchEvent({ type: "change" }); this.resizable.setSize(this.baseSize.width, this.baseSize.height); } /** * An auto sizing constant. * * Can be used to automatically calculate the width or height based on the original aspect ratio. * * @type {Number} */ static get AUTO_SIZE() { return AUTO_SIZE; } }; // src/core/OverrideMaterialManager.js var import_three4 = __require("three"); var workaroundEnabled = false; var OverrideMaterialManager = class { /** * Constructs a new override material manager. * * @param {Material} [material=null] - An override material. */ constructor(material = null) { this.originalMaterials = /* @__PURE__ */ new Map(); this.material = null; this.materials = null; this.materialsBackSide = null; this.materialsDoubleSide = null; this.materialsFlatShaded = null; this.materialsFlatShadedBackSide = null; this.materialsFlatShadedDoubleSide = null; this.setMaterial(material); this.meshCount = 0; this.replaceMaterial = (node) => { if (node.isMesh) { let materials; if (node.material.flatShading) { switch (node.material.side) { case import_three4.DoubleSide: materials = this.materialsFlatShadedDoubleSide; break; case import_three4.BackSide: materials = this.materialsFlatShadedBackSide; break; default: materials = this.materialsFlatShaded; break; } } else { switch (node.material.side) { case import_three4.DoubleSide: materials = this.materialsDoubleSide; break; case import_three4.BackSide: materials = this.materialsBackSide; break; default: materials = this.materials; break; } } this.originalMaterials.set(node, node.material); if (node.isSkinnedMesh) { node.material = materials[2]; } else if (node.isInstancedMesh) { node.material = materials[1]; } else { node.material = materials[0]; } ++this.meshCount; } }; } /** * Clones the given material. * * @private * @param {Material} material - The material. * @return {Material} The cloned material. */ cloneMaterial(material) { if (!(material instanceof import_three4.ShaderMaterial)) { return material.clone(); } const uniforms = material.uniforms; const textureUniforms = /* @__PURE__ */ new Map(); for (const key in uniforms) { const value = uniforms[key].value; if (value.isRenderTargetTexture) { uniforms[key].value = null; textureUniforms.set(key, value); } } const clone = material.clone(); for (const entry of textureUniforms) { uniforms[entry[0]].value = entry[1]; clone.uniforms[entry[0]].value = entry[1]; } return clone; } /** * Sets the override material. * * @param {Material} material - The material. */ setMaterial(material) { this.disposeMaterials(); this.material = material; if (material !== null) { const materials = this.materials = [ this.cloneMaterial(material), this.cloneMaterial(material), this.cloneMaterial(material) ]; for (const m2 of materials) { m2.uniforms = Object.assign({}, material.uniforms); m2.side = import_three4.FrontSide; } materials[2].skinning = true; this.materialsBackSide = materials.map((m2) => { const c2 = this.cloneMaterial(m2); c2.uniforms = Object.assign({}, material.uniforms); c2.side = import_three4.BackSide; return c2; }); this.materialsDoubleSide = materials.map((m2) => { const c2 = this.cloneMaterial(m2); c2.uniforms = Object.assign({}, material.uniforms); c2.side = import_three4.DoubleSide; return c2; }); this.materialsFlatShaded = materials.map((m2) => { const c2 = this.cloneMaterial(m2); c2.uniforms = Object.assign({}, material.uniforms); c2.flatShading = true; return c2; }); this.materialsFlatShadedBackSide = materials.map((m2) => { const c2 = this.cloneMaterial(m2); c2.uniforms = Object.assign({}, material.uniforms); c2.flatShading = true; c2.side = import_three4.BackSide; return c2; }); this.materialsFlatShadedDoubleSide = materials.map((m2) => { const c2 = this.cloneMaterial(m2); c2.uniforms = Object.assign({}, material.uniforms); c2.flatShading = true; c2.side = import_three4.DoubleSide; return c2; }); } } /** * Renders the scene with the override material. * * @private * @param {WebGLRenderer} renderer - The renderer. * @param {Scene} scene - A scene. * @param {Camera} camera - A camera. */ render(renderer, scene, camera, renderOpts = {}) { const shadowMapEnabled = renderer.shadowMap.enabled; renderer.shadowMap.enabled = false; let renderResult = null; if (workaroundEnabled) { const originalMaterials = this.originalMaterials; this.meshCount = 0; scene.traverse(this.replaceMaterial); renderResult = renderer.render(scene, camera, renderOpts); for (const entry of originalMaterials) { entry[0].material = entry[1]; } if (this.meshCount !== originalMaterials.size) { originalMaterials.clear(); } } else { const overrideMaterial2 = scene.overrideMaterial; scene.overrideMaterial = this.material; renderResult = renderer.render(scene, camera, renderOpts); scene.overrideMaterial = overrideMaterial2; } renderer.shadowMap.enabled = shadowMapEnabled; return renderResult; } /** * Deletes cloned override materials. * * @private */ disposeMaterials() { if (this.material !== null) { const materials = this.materials.concat(this.materialsBackSide).concat(this.materialsDoubleSide).concat(this.materialsFlatShaded).concat(this.materialsFlatShadedBackSide).concat(this.materialsFlatShadedDoubleSide); for (const m2 of materials) { m2.dispose(); } } } /** * Performs cleanup tasks. */ dispose() { this.originalMaterials.clear(); this.disposeMaterials(); } /** * Indicates whether the override material workaround is enabled. * * @type {Boolean} */ static get workaroundEnabled() { return workaroundEnabled; } /** * Enables or disables the override material workaround globally. * * This only affects post processing passes and effects. * * @type {Boolean} */ static set workaroundEnabled(value) { workaroundEnabled = value; } }; // src/passes/ClearPass.js var import_three5 = __require("three"); var color = /* @__PURE__ */ new import_three5.Color(); var ClearPass = class extends Pass { /** * Constructs a new clear pass. * * @param {Boolean} [color=true] - Determines whether the color buffer should be cleared. * @param {Boolean} [depth=true] - Determines whether the depth buffer should be cleared. * @param {Boolean} [stencil=false] - Determines whether the stencil buffer should be cleared. */ constructor(color2 = true, depth = true, stencil = false) { super("ClearPass", null, null); this.needsSwap = false; this.color = color2; this.depth = depth; this.stencil = stencil; this.overrideClearColor = null; this.overrideClearAlpha = -1; } /** * Sets the clear flags. * * @param {Boolean} color - Whether the color buffer should be cleared. * @param {Boolean} depth - Whether the depth buffer should be cleared. * @param {Boolean} stencil - Whether the stencil buffer should be cleared. */ setClearFlags(color2, depth, stencil) { this.color = color2; this.depth = depth; this.stencil = stencil; } /** * Returns the override clear color. Default is null. * * @deprecated Use overrideClearColor instead. * @return {Color} The clear color. */ getOverrideClearColor() { return this.overrideClearColor; } /** * Sets the override clear color. * * @deprecated Use overrideClearColor instead. * @param {Color} value - The clear color. */ setOverrideClearColor(value) { this.overrideClearColor = value; } /** * Returns the override clear alpha. Default is -1. * * @deprecated Use overrideClearAlpha instead. * @return {Number} The clear alpha. */ getOverrideClearAlpha() { return this.overrideClearAlpha; } /** * Sets the override clear alpha. * * @deprecated Use overrideClearAlpha instead. * @param {Number} value - The clear alpha. */ setOverrideClearAlpha(value) { this.overrideClearAlpha = value; } /** * Clears the input buffer or the screen. * * @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) { const overrideClearColor = this.overrideClearColor; const overrideClearAlpha = this.overrideClearAlpha; const clearAlpha = renderer.getClearAlpha(); const hasOverrideClearColor = overrideClearColor !== null; const hasOverrideClearAlpha = overrideClearAlpha >= 0; if (hasOverrideClearColor) { renderer.getClearColor(color); renderer.setClearColor(overrideClearColor, hasOverrideClearAlpha ? overrideClearAlpha : clearAlpha); } else if (hasOverrideClearAlpha) { renderer.setClearAlpha(overrideClearAlpha); } renderer.setRenderTarget(this.renderToScreen ? null : inputBuffer); renderer.clear(this.color, this.depth, this.stencil); if (hasOverrideClearColor) { renderer.setClearColor(color, clearAlpha); } else if (hasOverrideClearAlpha) { renderer.setClearAlpha(clearAlpha); } } }; // src/utils/PerformanceLogger.js var theEnabled = false; var _PerformanceLogger = class _PerformanceLogger { /** * 获取单例实例 * @return {PerformanceLogger} 日志实例 */ static getInstance() { if (_PerformanceLogger.instance === null) { _PerformanceLogger.instance = new _PerformanceLogger(); } return _PerformanceLogger.instance; } /** * 创建一个新的性能日志实例 * @param {Boolean} enabled - 是否启用日志 */ constructor(enabled = theEnabled) { this.enabled = enabled; this.timers = /* @__PURE__ */ new Map(); this.collectTimes = false; this.timeData = /* @__PURE__ */ new Map(); } /** * 启用日志 */ enable() { this.enabled = true; } /** * 禁用日志 */ disable() { this.enabled = false; } /** * 启用时间数据收集,用于性能分析 */ enableTimeCollection() { this.collectTimes = true; } /** * 禁用时间数据收集 */ disableTimeCollection() { this.collectTimes = false; } /** * 获取收集的时间数据 * @return {Object} 时间数据 */ getTimeData() { const result = {}; for (const [key, times] of this.timeData.entries()) { if (times.length > 0) { const sum = times.reduce((a, b) => a + b, 0); result[key] = { count: times.length, total: sum, average: sum / times.length, min: Math.min(...times),