diff --git a/.eslintrc.json b/.eslintrc.json index 76ce0a75b88690..1851d68bd2bb89 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -41,7 +41,8 @@ "CodeMirror": "readonly", "esprima": "readonly", "jsonlint": "readonly", - "VideoFrame": "readonly" + "VideoFrame": "readonly", + "VideoDecoder": "readonly" }, "rules": { "no-throw-literal": [ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ef55565e7a67c1..c32007d964992b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -89,7 +89,7 @@ jobs: - name: === E2E testing === run: npm run test-e2e - name: Upload output screenshots - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4 if: always() with: name: Output screenshots-${{ matrix.os }}-${{ matrix.CI }} diff --git a/.github/workflows/codeql-code-scanning.yml b/.github/workflows/codeql-code-scanning.yml index ea6c95462d53cb..541cc89ffaf754 100644 --- a/.github/workflows/codeql-code-scanning.yml +++ b/.github/workflows/codeql-code-scanning.yml @@ -30,16 +30,16 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3 + uses: github/codeql-action/init@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3 with: languages: ${{ matrix.language }} config-file: ./.github/codeql-config.yml queries: security-and-quality - name: Autobuild - uses: github/codeql-action/autobuild@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3 + uses: github/codeql-action/autobuild@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3 + uses: github/codeql-action/analyze@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/read-size.yml b/.github/workflows/read-size.yml index 1280688714ebcd..ad28721a9ff527 100644 --- a/.github/workflows/read-size.yml +++ b/.github/workflows/read-size.yml @@ -61,7 +61,7 @@ jobs: # write the output in a json file to upload it as artifact node -pe "JSON.stringify({ filesize: $WEBGL_FILESIZE, gzip: $WEBGL_FILESIZE_GZIP, treeshaken: $WEBGL_TREESHAKEN, treeshakenGzip: $WEBGL_TREESHAKEN_GZIP, filesize2: $WEBGPU_FILESIZE, gzip2: $WEBGPU_FILESIZE_GZIP, treeshaken2: $WEBGPU_TREESHAKEN, treeshakenGzip2: $WEBGPU_TREESHAKEN_GZIP, filesize3: $WEBGPU_NODES_FILESIZE, gzip3: $WEBGPU_NODES_FILESIZE_GZIP, treeshaken3: $WEBGPU_NODES_TREESHAKEN, treeshakenGzip3: $WEBGPU_NODES_TREESHAKEN_GZIP, pr: $PR })" > sizes.json - name: Upload artifact - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4 with: name: sizes path: sizes.json diff --git a/LICENSE b/LICENSE index d33709fbf00f10..cf781430404b0a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright © 2010-2024 three.js authors +Copyright © 2010-2025 three.js authors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 0027148a242f94..8fc47bf453fb99 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ #### JavaScript 3D library -The aim of the project is to create an easy-to-use, lightweight, cross-browser, general-purpose 3D library. The current builds only include a WebGL renderer but WebGPU (experimental), SVG and CSS3D renderers are also available as addons. +The aim of the project is to create an easy-to-use, lightweight, cross-browser, general-purpose 3D library. The current builds only include WebGL and WebGPU renderers but SVG and CSS3D renderers are also available as addons. [Examples](https://threejs.org/examples/) — [Docs](https://threejs.org/docs/) — diff --git a/build/three.cjs b/build/three.cjs index 3d947c0982fd08..2d63cd5f451800 100644 --- a/build/three.cjs +++ b/build/three.cjs @@ -1,11 +1,11 @@ /** * @license - * Copyright 2010-2024 Three.js Authors + * Copyright 2010-2025 Three.js Authors * SPDX-License-Identifier: MIT */ 'use strict'; -const REVISION = '172dev'; +const REVISION = '173dev'; const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }; const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }; @@ -3276,9 +3276,9 @@ class Data3DTexture extends Texture { constructor( data = null, width = 1, height = 1, depth = 1 ) { // We're going to add .setXXX() methods for setting properties later. - // Users can still set in DataTexture3D directly. + // Users can still set in Data3DTexture directly. // - // const texture = new THREE.DataTexture3D( data, width, height, depth ); + // const texture = new THREE.Data3DTexture( data, width, height, depth ); // texture.anisotropy = 16; // // See #14839 @@ -34381,6 +34381,42 @@ class AnimationMixer extends EventDispatcher { } +class RenderTarget3D extends RenderTarget { + + constructor( width = 1, height = 1, depth = 1, options = {} ) { + + super( width, height, options ); + + this.isRenderTarget3D = true; + + this.depth = depth; + + this.texture = new Data3DTexture( null, width, height, depth ); + + this.texture.isRenderTargetTexture = true; + + } + +} + +class RenderTargetArray extends RenderTarget { + + constructor( width = 1, height = 1, depth = 1, options = {} ) { + + super( width, height, options ); + + this.isRenderTargetArray = true; + + this.depth = depth; + + this.texture = new DataArrayTexture( null, width, height, depth ); + + this.texture.isRenderTargetTexture = true; + + } + +} + class Uniform { constructor( value ) { @@ -38541,6 +38577,8 @@ function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, boxMesh.geometry.dispose(); boxMesh.material.dispose(); + boxMesh = undefined; + } if ( planeMesh !== undefined ) { @@ -38548,6 +38586,8 @@ function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, planeMesh.geometry.dispose(); planeMesh.material.dispose(); + planeMesh = undefined; + } } @@ -50700,8 +50740,11 @@ class WebXRManager extends EventDispatcher { // const enabledFeatures = session.enabledFeatures; + const gpuDepthSensingEnabled = enabledFeatures && + enabledFeatures.includes( 'depth-sensing' ) && + session.depthUsage == 'gpu-optimized'; - if ( enabledFeatures && enabledFeatures.includes( 'depth-sensing' ) ) { + if ( gpuDepthSensingEnabled && glBinding ) { const depthData = glBinding.getDepthInformation( views[ 0 ] ); @@ -52950,7 +52993,7 @@ class WebGLRenderer { // - if ( _currentRenderTarget !== null ) { + if ( _currentRenderTarget !== null && _currentActiveMipmapLevel === 0 ) { // resolve multisample renderbuffers to a single-sample texture if necessary @@ -53945,6 +53988,7 @@ class WebGLRenderer { }; + const _scratchFrameBuffer = _gl.createFramebuffer(); this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) { _currentRenderTarget = renderTarget; @@ -54053,6 +54097,14 @@ class WebGLRenderer { } + // Use a scratch frame buffer if rendering to a mip level to avoid depth buffers + // being bound that are different sizes. + if ( activeMipmapLevel !== 0 ) { + + framebuffer = _scratchFrameBuffer; + + } + const framebufferBound = state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); if ( framebufferBound && useDefaultFramebuffer ) { @@ -54073,8 +54125,15 @@ class WebGLRenderer { } else if ( isRenderTarget3D ) { const textureProperties = properties.get( renderTarget.texture ); - const layer = activeCubeFace || 0; - _gl.framebufferTextureLayer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureProperties.__webglTexture, activeMipmapLevel || 0, layer ); + const layer = activeCubeFace; + _gl.framebufferTextureLayer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureProperties.__webglTexture, activeMipmapLevel, layer ); + + } else if ( renderTarget !== null && activeMipmapLevel !== 0 ) { + + // Only bind the frame buffer if we are using a scratch frame buffer to render to a mipmap. + // If we rebind the texture when using a multi sample buffer then an error about inconsistent samples will be thrown. + const textureProperties = properties.get( renderTarget.texture ); + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, textureProperties.__webglTexture, activeMipmapLevel ); } @@ -54933,6 +54992,8 @@ exports.RedFormat = RedFormat; exports.RedIntegerFormat = RedIntegerFormat; exports.ReinhardToneMapping = ReinhardToneMapping; exports.RenderTarget = RenderTarget; +exports.RenderTarget3D = RenderTarget3D; +exports.RenderTargetArray = RenderTargetArray; exports.RepeatWrapping = RepeatWrapping; exports.ReplaceStencilOp = ReplaceStencilOp; exports.ReverseSubtractEquation = ReverseSubtractEquation; diff --git a/build/three.core.js b/build/three.core.js index e20f3a4ec6bf17..505c54d355caff 100644 --- a/build/three.core.js +++ b/build/three.core.js @@ -1,9 +1,9 @@ /** * @license - * Copyright 2010-2024 Three.js Authors + * Copyright 2010-2025 Three.js Authors * SPDX-License-Identifier: MIT */ -const REVISION = '172dev'; +const REVISION = '173dev'; const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }; const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }; @@ -3274,9 +3274,9 @@ class Data3DTexture extends Texture { constructor( data = null, width = 1, height = 1, depth = 1 ) { // We're going to add .setXXX() methods for setting properties later. - // Users can still set in DataTexture3D directly. + // Users can still set in Data3DTexture directly. // - // const texture = new THREE.DataTexture3D( data, width, height, depth ); + // const texture = new THREE.Data3DTexture( data, width, height, depth ); // texture.anisotropy = 16; // // See #14839 @@ -34379,6 +34379,42 @@ class AnimationMixer extends EventDispatcher { } +class RenderTarget3D extends RenderTarget { + + constructor( width = 1, height = 1, depth = 1, options = {} ) { + + super( width, height, options ); + + this.isRenderTarget3D = true; + + this.depth = depth; + + this.texture = new Data3DTexture( null, width, height, depth ); + + this.texture.isRenderTargetTexture = true; + + } + +} + +class RenderTargetArray extends RenderTarget { + + constructor( width = 1, height = 1, depth = 1, options = {} ) { + + super( width, height, options ); + + this.isRenderTargetArray = true; + + this.depth = depth; + + this.texture = new DataArrayTexture( null, width, height, depth ); + + this.texture.isRenderTargetTexture = true; + + } + +} + class Uniform { constructor( value ) { @@ -37010,4 +37046,4 @@ if ( typeof window !== 'undefined' ) { } -export { ACESFilmicToneMapping, AddEquation, AddOperation, AdditiveAnimationBlendMode, AdditiveBlending, AgXToneMapping, AlphaFormat, AlwaysCompare, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AnimationAction, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrayCamera, ArrowHelper, AttachedBindMode, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BackSide, BasicDepthPacking, BasicShadowMap, BatchedMesh, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxGeometry, BoxHelper, BufferAttribute, BufferGeometry, BufferGeometryLoader, ByteType, Cache, Camera, CameraHelper, CanvasTexture, CapsuleGeometry, CatmullRomCurve3, CineonToneMapping, CircleGeometry, ClampToEdgeWrapping, Clock, Color, ColorKeyframeTrack, ColorManagement, CompressedArrayTexture, CompressedCubeTexture, CompressedTexture, CompressedTextureLoader, ConeGeometry, ConstantAlphaFactor, ConstantColorFactor, Controls, CubeCamera, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureLoader, CubeUVReflectionMapping, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceBack, CullFaceFront, CullFaceFrontBack, CullFaceNone, Curve, CurvePath, CustomBlending, CustomToneMapping, CylinderGeometry, Cylindrical, Data3DTexture, DataArrayTexture, DataTexture, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DepthTexture, DetachedBindMode, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DodecahedronGeometry, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EllipseCurve, EqualCompare, EqualDepth, EqualStencilFunc, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExtrudeGeometry, FileLoader, Float16BufferAttribute, Float32BufferAttribute, FloatType, Fog, FogExp2, FramebufferTexture, FrontSide, Frustum, GLBufferAttribute, GLSL1, GLSL3, GreaterCompare, GreaterDepth, GreaterEqualCompare, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HalfFloatType, HemisphereLight, HemisphereLightHelper, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, IntType, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InvertStencilOp, KeepStencilOp, KeyframeTrack, LOD, LatheGeometry, Layers, LessCompare, LessDepth, LessEqualCompare, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LineSegments, LinearFilter, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearSRGBColorSpace, LinearToneMapping, LinearTransfer, Loader, LoaderUtils, LoadingManager, LoopOnce, LoopPingPong, LoopRepeat, LuminanceAlphaFormat, LuminanceFormat, MOUSE, Material, MaterialLoader, MathUtils, Matrix2, Matrix3, Matrix4, MaxEquation, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshDistanceMaterial, MeshLambertMaterial, MeshMatcapMaterial, MeshNormalMaterial, MeshPhongMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshToonMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeutralToneMapping, NeverCompare, NeverDepth, NeverStencilFunc, NoBlending, NoColorSpace, NoToneMapping, NormalAnimationBlendMode, NormalBlending, NotEqualCompare, NotEqualDepth, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, ObjectSpaceNormalMap, OctahedronGeometry, OneFactor, OneMinusConstantAlphaFactor, OneMinusConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, PCFShadowMap, PCFSoftShadowMap, Path, PerspectiveCamera, Plane, PlaneGeometry, PlaneHelper, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, RAD2DEG, RED_GREEN_RGTC2_Format, RED_RGTC1_Format, REVISION, RGBADepthPacking, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBDepthPacking, RGBFormat, RGBIntegerFormat, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGDepthPacking, RGFormat, RGIntegerFormat, RawShaderMaterial, Ray, Raycaster, RectAreaLight, RedFormat, RedIntegerFormat, ReinhardToneMapping, RenderTarget, RepeatWrapping, ReplaceStencilOp, ReverseSubtractEquation, RingGeometry, SIGNED_RED_GREEN_RGTC2_Format, SIGNED_RED_RGTC1_Format, SRGBColorSpace, SRGBTransfer, Scene, ShaderMaterial, ShadowMaterial, Shape, ShapeGeometry, ShapePath, ShapeUtils, ShortType, Skeleton, SkeletonHelper, SkinnedMesh, Source, Sphere, SphereGeometry, Spherical, SphericalHarmonics3, SplineCurve, SpotLight, SpotLightHelper, Sprite, SpriteMaterial, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, SubtractEquation, SubtractiveBlending, TOUCH, TangentSpaceNormalMap, TetrahedronGeometry, Texture, TextureLoader, TextureUtils, TorusGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeGeometry, UVMapping, Uint16BufferAttribute, Uint32BufferAttribute, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, UniformsUtils, UnsignedByteType, UnsignedInt248Type, UnsignedInt5999Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VSMShadowMap, Vector2, Vector3, Vector4, VectorKeyframeTrack, VideoTexture, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGLCoordinateSystem, WebGLCubeRenderTarget, WebGLRenderTarget, WebGPUCoordinateSystem, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroFactor, ZeroSlopeEnding, ZeroStencilOp, arrayNeedsUint32, cloneUniforms, createCanvasElement, createElementNS, getByteLength, getUnlitUniformColorSpace, mergeUniforms, probeAsync, toNormalizedProjectionMatrix, toReversedProjectionMatrix, warnOnce }; +export { ACESFilmicToneMapping, AddEquation, AddOperation, AdditiveAnimationBlendMode, AdditiveBlending, AgXToneMapping, AlphaFormat, AlwaysCompare, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AnimationAction, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrayCamera, ArrowHelper, AttachedBindMode, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BackSide, BasicDepthPacking, BasicShadowMap, BatchedMesh, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxGeometry, BoxHelper, BufferAttribute, BufferGeometry, BufferGeometryLoader, ByteType, Cache, Camera, CameraHelper, CanvasTexture, CapsuleGeometry, CatmullRomCurve3, CineonToneMapping, CircleGeometry, ClampToEdgeWrapping, Clock, Color, ColorKeyframeTrack, ColorManagement, CompressedArrayTexture, CompressedCubeTexture, CompressedTexture, CompressedTextureLoader, ConeGeometry, ConstantAlphaFactor, ConstantColorFactor, Controls, CubeCamera, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureLoader, CubeUVReflectionMapping, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceBack, CullFaceFront, CullFaceFrontBack, CullFaceNone, Curve, CurvePath, CustomBlending, CustomToneMapping, CylinderGeometry, Cylindrical, Data3DTexture, DataArrayTexture, DataTexture, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DepthTexture, DetachedBindMode, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DodecahedronGeometry, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EllipseCurve, EqualCompare, EqualDepth, EqualStencilFunc, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExtrudeGeometry, FileLoader, Float16BufferAttribute, Float32BufferAttribute, FloatType, Fog, FogExp2, FramebufferTexture, FrontSide, Frustum, GLBufferAttribute, GLSL1, GLSL3, GreaterCompare, GreaterDepth, GreaterEqualCompare, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HalfFloatType, HemisphereLight, HemisphereLightHelper, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, IntType, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InvertStencilOp, KeepStencilOp, KeyframeTrack, LOD, LatheGeometry, Layers, LessCompare, LessDepth, LessEqualCompare, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LineSegments, LinearFilter, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearSRGBColorSpace, LinearToneMapping, LinearTransfer, Loader, LoaderUtils, LoadingManager, LoopOnce, LoopPingPong, LoopRepeat, LuminanceAlphaFormat, LuminanceFormat, MOUSE, Material, MaterialLoader, MathUtils, Matrix2, Matrix3, Matrix4, MaxEquation, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshDistanceMaterial, MeshLambertMaterial, MeshMatcapMaterial, MeshNormalMaterial, MeshPhongMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshToonMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeutralToneMapping, NeverCompare, NeverDepth, NeverStencilFunc, NoBlending, NoColorSpace, NoToneMapping, NormalAnimationBlendMode, NormalBlending, NotEqualCompare, NotEqualDepth, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, ObjectSpaceNormalMap, OctahedronGeometry, OneFactor, OneMinusConstantAlphaFactor, OneMinusConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, PCFShadowMap, PCFSoftShadowMap, Path, PerspectiveCamera, Plane, PlaneGeometry, PlaneHelper, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, RAD2DEG, RED_GREEN_RGTC2_Format, RED_RGTC1_Format, REVISION, RGBADepthPacking, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBDepthPacking, RGBFormat, RGBIntegerFormat, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGDepthPacking, RGFormat, RGIntegerFormat, RawShaderMaterial, Ray, Raycaster, RectAreaLight, RedFormat, RedIntegerFormat, ReinhardToneMapping, RenderTarget, RenderTarget3D, RenderTargetArray, RepeatWrapping, ReplaceStencilOp, ReverseSubtractEquation, RingGeometry, SIGNED_RED_GREEN_RGTC2_Format, SIGNED_RED_RGTC1_Format, SRGBColorSpace, SRGBTransfer, Scene, ShaderMaterial, ShadowMaterial, Shape, ShapeGeometry, ShapePath, ShapeUtils, ShortType, Skeleton, SkeletonHelper, SkinnedMesh, Source, Sphere, SphereGeometry, Spherical, SphericalHarmonics3, SplineCurve, SpotLight, SpotLightHelper, Sprite, SpriteMaterial, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, SubtractEquation, SubtractiveBlending, TOUCH, TangentSpaceNormalMap, TetrahedronGeometry, Texture, TextureLoader, TextureUtils, TorusGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeGeometry, UVMapping, Uint16BufferAttribute, Uint32BufferAttribute, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, UniformsUtils, UnsignedByteType, UnsignedInt248Type, UnsignedInt5999Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VSMShadowMap, Vector2, Vector3, Vector4, VectorKeyframeTrack, VideoTexture, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGLCoordinateSystem, WebGLCubeRenderTarget, WebGLRenderTarget, WebGPUCoordinateSystem, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroFactor, ZeroSlopeEnding, ZeroStencilOp, arrayNeedsUint32, cloneUniforms, createCanvasElement, createElementNS, getByteLength, getUnlitUniformColorSpace, mergeUniforms, probeAsync, toNormalizedProjectionMatrix, toReversedProjectionMatrix, warnOnce }; diff --git a/build/three.core.min.js b/build/three.core.min.js index bca1c2127fd23d..e5e5905a557368 100644 --- a/build/three.core.min.js +++ b/build/three.core.min.js @@ -1,6 +1,6 @@ /** * @license - * Copyright 2010-2024 Three.js Authors + * Copyright 2010-2025 Three.js Authors * SPDX-License-Identifier: MIT */ -const t="172dev",e={LEFT:0,MIDDLE:1,RIGHT:2,ROTATE:0,DOLLY:1,PAN:2},s={ROTATE:0,PAN:1,DOLLY_PAN:2,DOLLY_ROTATE:3},i=0,r=1,n=2,o=3,a=0,h=1,l=2,c=3,u=0,d=1,p=2,m=0,y=1,f=2,g=3,x=4,b=5,v=100,w=101,M=102,S=103,_=104,A=200,T=201,z=202,C=203,I=204,B=205,k=206,E=207,P=208,R=209,O=210,F=211,N=212,L=213,V=214,W=0,j=1,U=2,D=3,H=4,q=5,J=6,X=7,Y=0,Z=1,G=2,$=0,Q=1,K=2,tt=3,et=4,st=5,it=6,rt=7,nt="attached",ot="detached",at=300,ht=301,lt=302,ct=303,ut=304,dt=306,pt=1e3,mt=1001,yt=1002,ft=1003,gt=1004,xt=1004,bt=1005,vt=1005,wt=1006,Mt=1007,St=1007,_t=1008,At=1008,Tt=1009,zt=1010,Ct=1011,It=1012,Bt=1013,kt=1014,Et=1015,Pt=1016,Rt=1017,Ot=1018,Ft=1020,Nt=35902,Lt=1021,Vt=1022,Wt=1023,jt=1024,Ut=1025,Dt=1026,Ht=1027,qt=1028,Jt=1029,Xt=1030,Yt=1031,Zt=1032,Gt=1033,$t=33776,Qt=33777,Kt=33778,te=33779,ee=35840,se=35841,ie=35842,re=35843,ne=36196,oe=37492,ae=37496,he=37808,le=37809,ce=37810,ue=37811,de=37812,pe=37813,me=37814,ye=37815,fe=37816,ge=37817,xe=37818,be=37819,ve=37820,we=37821,Me=36492,Se=36494,_e=36495,Ae=36283,Te=36284,ze=36285,Ce=36286,Ie=2200,Be=2201,ke=2202,Ee=2300,Pe=2301,Re=2302,Oe=2400,Fe=2401,Ne=2402,Le=2500,Ve=2501,We=0,je=1,Ue=2,De=3200,He=3201,qe=3202,Je=3203,Xe=0,Ye=1,Ze="",Ge="srgb",$e="srgb-linear",Qe="linear",Ke="srgb",ts=0,es=7680,ss=7681,is=7682,rs=7683,ns=34055,os=34056,as=5386,hs=512,ls=513,cs=514,us=515,ds=516,ps=517,ms=518,ys=519,fs=512,gs=513,xs=514,bs=515,vs=516,ws=517,Ms=518,Ss=519,_s=35044,As=35048,Ts=35040,zs=35045,Cs=35049,Is=35041,Bs=35046,ks=35050,Es=35042,Ps="100",Rs="300 es",Os=2e3,Fs=2001;class Ns{addEventListener(t,e){void 0===this._listeners&&(this._listeners={});const s=this._listeners;void 0===s[t]&&(s[t]=[]),-1===s[t].indexOf(e)&&s[t].push(e)}hasEventListener(t,e){if(void 0===this._listeners)return!1;const s=this._listeners;return void 0!==s[t]&&-1!==s[t].indexOf(e)}removeEventListener(t,e){if(void 0===this._listeners)return;const s=this._listeners[t];if(void 0!==s){const t=s.indexOf(e);-1!==t&&s.splice(t,1)}}dispatchEvent(t){if(void 0===this._listeners)return;const e=this._listeners[t.type];if(void 0!==e){t.target=this;const s=e.slice(0);for(let e=0,i=s.length;e>8&255]+Ls[t>>16&255]+Ls[t>>24&255]+"-"+Ls[255&e]+Ls[e>>8&255]+"-"+Ls[e>>16&15|64]+Ls[e>>24&255]+"-"+Ls[63&s|128]+Ls[s>>8&255]+"-"+Ls[s>>16&255]+Ls[s>>24&255]+Ls[255&i]+Ls[i>>8&255]+Ls[i>>16&255]+Ls[i>>24&255]).toLowerCase()}function Ds(t,e,s){return Math.max(e,Math.min(s,t))}function Hs(t,e){return(t%e+e)%e}function qs(t,e,s){return(1-s)*t+s*e}function Js(t,e){switch(e.constructor){case Float32Array:return t;case Uint32Array:return t/4294967295;case Uint16Array:return t/65535;case Uint8Array:return t/255;case Int32Array:return Math.max(t/2147483647,-1);case Int16Array:return Math.max(t/32767,-1);case Int8Array:return Math.max(t/127,-1);default:throw new Error("Invalid component type.")}}function Xs(t,e){switch(e.constructor){case Float32Array:return t;case Uint32Array:return Math.round(4294967295*t);case Uint16Array:return Math.round(65535*t);case Uint8Array:return Math.round(255*t);case Int32Array:return Math.round(2147483647*t);case Int16Array:return Math.round(32767*t);case Int8Array:return Math.round(127*t);default:throw new Error("Invalid component type.")}}const Ys={DEG2RAD:Ws,RAD2DEG:js,generateUUID:Us,clamp:Ds,euclideanModulo:Hs,mapLinear:function(t,e,s,i,r){return i+(t-e)*(r-i)/(s-e)},inverseLerp:function(t,e,s){return t!==e?(s-t)/(e-t):0},lerp:qs,damp:function(t,e,s,i){return qs(t,e,1-Math.exp(-s*i))},pingpong:function(t,e=1){return e-Math.abs(Hs(t,2*e)-e)},smoothstep:function(t,e,s){return t<=e?0:t>=s?1:(t=(t-e)/(s-e))*t*(3-2*t)},smootherstep:function(t,e,s){return t<=e?0:t>=s?1:(t=(t-e)/(s-e))*t*t*(t*(6*t-15)+10)},randInt:function(t,e){return t+Math.floor(Math.random()*(e-t+1))},randFloat:function(t,e){return t+Math.random()*(e-t)},randFloatSpread:function(t){return t*(.5-Math.random())},seededRandom:function(t){void 0!==t&&(Vs=t);let e=Vs+=1831565813;return e=Math.imul(e^e>>>15,1|e),e^=e+Math.imul(e^e>>>7,61|e),((e^e>>>14)>>>0)/4294967296},degToRad:function(t){return t*Ws},radToDeg:function(t){return t*js},isPowerOfTwo:function(t){return!(t&t-1)&&0!==t},ceilPowerOfTwo:function(t){return Math.pow(2,Math.ceil(Math.log(t)/Math.LN2))},floorPowerOfTwo:function(t){return Math.pow(2,Math.floor(Math.log(t)/Math.LN2))},setQuaternionFromProperEuler:function(t,e,s,i,r){const n=Math.cos,o=Math.sin,a=n(s/2),h=o(s/2),l=n((e+i)/2),c=o((e+i)/2),u=n((e-i)/2),d=o((e-i)/2),p=n((i-e)/2),m=o((i-e)/2);switch(r){case"XYX":t.set(a*c,h*u,h*d,a*l);break;case"YZY":t.set(h*d,a*c,h*u,a*l);break;case"ZXZ":t.set(h*u,h*d,a*c,a*l);break;case"XZX":t.set(a*c,h*m,h*p,a*l);break;case"YXY":t.set(h*p,a*c,h*m,a*l);break;case"ZYZ":t.set(h*m,h*p,a*c,a*l);break;default:console.warn("THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: "+r)}},normalize:Xs,denormalize:Js};class Zs{constructor(t=0,e=0){Zs.prototype.isVector2=!0,this.x=t,this.y=e}get width(){return this.x}set width(t){this.x=t}get height(){return this.y}set height(t){this.y=t}set(t,e){return this.x=t,this.y=e,this}setScalar(t){return this.x=t,this.y=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y)}copy(t){return this.x=t.x,this.y=t.y,this}add(t){return this.x+=t.x,this.y+=t.y,this}addScalar(t){return this.x+=t,this.y+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this}subScalar(t){return this.x-=t,this.y-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this}multiply(t){return this.x*=t.x,this.y*=t.y,this}multiplyScalar(t){return this.x*=t,this.y*=t,this}divide(t){return this.x/=t.x,this.y/=t.y,this}divideScalar(t){return this.multiplyScalar(1/t)}applyMatrix3(t){const e=this.x,s=this.y,i=t.elements;return this.x=i[0]*e+i[3]*s+i[6],this.y=i[1]*e+i[4]*s+i[7],this}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this}clamp(t,e){return this.x=Ds(this.x,t.x,e.x),this.y=Ds(this.y,t.y,e.y),this}clampScalar(t,e){return this.x=Ds(this.x,t,e),this.y=Ds(this.y,t,e),this}clampLength(t,e){const s=this.length();return this.divideScalar(s||1).multiplyScalar(Ds(s,t,e))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(t){return this.x*t.x+this.y*t.y}cross(t){return this.x*t.y-this.y*t.x}lengthSq(){return this.x*this.x+this.y*this.y}length(){return Math.sqrt(this.x*this.x+this.y*this.y)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)}normalize(){return this.divideScalar(this.length()||1)}angle(){return Math.atan2(-this.y,-this.x)+Math.PI}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(0===e)return Math.PI/2;const s=this.dot(t)/e;return Math.acos(Ds(s,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,s=this.y-t.y;return e*e+s*s}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this}lerpVectors(t,e,s){return this.x=t.x+(e.x-t.x)*s,this.y=t.y+(e.y-t.y)*s,this}equals(t){return t.x===this.x&&t.y===this.y}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this}rotateAround(t,e){const s=Math.cos(e),i=Math.sin(e),r=this.x-t.x,n=this.y-t.y;return this.x=r*s-n*i+t.x,this.y=r*i+n*s+t.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class Gs{constructor(t,e,s,i,r,n,o,a,h){Gs.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1],void 0!==t&&this.set(t,e,s,i,r,n,o,a,h)}set(t,e,s,i,r,n,o,a,h){const l=this.elements;return l[0]=t,l[1]=i,l[2]=o,l[3]=e,l[4]=r,l[5]=a,l[6]=s,l[7]=n,l[8]=h,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(t){const e=this.elements,s=t.elements;return e[0]=s[0],e[1]=s[1],e[2]=s[2],e[3]=s[3],e[4]=s[4],e[5]=s[5],e[6]=s[6],e[7]=s[7],e[8]=s[8],this}extractBasis(t,e,s){return t.setFromMatrix3Column(this,0),e.setFromMatrix3Column(this,1),s.setFromMatrix3Column(this,2),this}setFromMatrix4(t){const e=t.elements;return this.set(e[0],e[4],e[8],e[1],e[5],e[9],e[2],e[6],e[10]),this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const s=t.elements,i=e.elements,r=this.elements,n=s[0],o=s[3],a=s[6],h=s[1],l=s[4],c=s[7],u=s[2],d=s[5],p=s[8],m=i[0],y=i[3],f=i[6],g=i[1],x=i[4],b=i[7],v=i[2],w=i[5],M=i[8];return r[0]=n*m+o*g+a*v,r[3]=n*y+o*x+a*w,r[6]=n*f+o*b+a*M,r[1]=h*m+l*g+c*v,r[4]=h*y+l*x+c*w,r[7]=h*f+l*b+c*M,r[2]=u*m+d*g+p*v,r[5]=u*y+d*x+p*w,r[8]=u*f+d*b+p*M,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[3]*=t,e[6]*=t,e[1]*=t,e[4]*=t,e[7]*=t,e[2]*=t,e[5]*=t,e[8]*=t,this}determinant(){const t=this.elements,e=t[0],s=t[1],i=t[2],r=t[3],n=t[4],o=t[5],a=t[6],h=t[7],l=t[8];return e*n*l-e*o*h-s*r*l+s*o*a+i*r*h-i*n*a}invert(){const t=this.elements,e=t[0],s=t[1],i=t[2],r=t[3],n=t[4],o=t[5],a=t[6],h=t[7],l=t[8],c=l*n-o*h,u=o*a-l*r,d=h*r-n*a,p=e*c+s*u+i*d;if(0===p)return this.set(0,0,0,0,0,0,0,0,0);const m=1/p;return t[0]=c*m,t[1]=(i*h-l*s)*m,t[2]=(o*s-i*n)*m,t[3]=u*m,t[4]=(l*e-i*a)*m,t[5]=(i*r-o*e)*m,t[6]=d*m,t[7]=(s*a-h*e)*m,t[8]=(n*e-s*r)*m,this}transpose(){let t;const e=this.elements;return t=e[1],e[1]=e[3],e[3]=t,t=e[2],e[2]=e[6],e[6]=t,t=e[5],e[5]=e[7],e[7]=t,this}getNormalMatrix(t){return this.setFromMatrix4(t).invert().transpose()}transposeIntoArray(t){const e=this.elements;return t[0]=e[0],t[1]=e[3],t[2]=e[6],t[3]=e[1],t[4]=e[4],t[5]=e[7],t[6]=e[2],t[7]=e[5],t[8]=e[8],this}setUvTransform(t,e,s,i,r,n,o){const a=Math.cos(r),h=Math.sin(r);return this.set(s*a,s*h,-s*(a*n+h*o)+n+t,-i*h,i*a,-i*(-h*n+a*o)+o+e,0,0,1),this}scale(t,e){return this.premultiply($s.makeScale(t,e)),this}rotate(t){return this.premultiply($s.makeRotation(-t)),this}translate(t,e){return this.premultiply($s.makeTranslation(t,e)),this}makeTranslation(t,e){return t.isVector2?this.set(1,0,t.x,0,1,t.y,0,0,1):this.set(1,0,t,0,1,e,0,0,1),this}makeRotation(t){const e=Math.cos(t),s=Math.sin(t);return this.set(e,-s,0,s,e,0,0,0,1),this}makeScale(t,e){return this.set(t,0,0,0,e,0,0,0,1),this}equals(t){const e=this.elements,s=t.elements;for(let t=0;t<9;t++)if(e[t]!==s[t])return!1;return!0}fromArray(t,e=0){for(let s=0;s<9;s++)this.elements[s]=t[s+e];return this}toArray(t=[],e=0){const s=this.elements;return t[e]=s[0],t[e+1]=s[1],t[e+2]=s[2],t[e+3]=s[3],t[e+4]=s[4],t[e+5]=s[5],t[e+6]=s[6],t[e+7]=s[7],t[e+8]=s[8],t}clone(){return(new this.constructor).fromArray(this.elements)}}const $s=new Gs;function Qs(t){for(let e=t.length-1;e>=0;--e)if(t[e]>=65535)return!0;return!1}const Ks={Int8Array:Int8Array,Uint8Array:Uint8Array,Uint8ClampedArray:Uint8ClampedArray,Int16Array:Int16Array,Uint16Array:Uint16Array,Int32Array:Int32Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array};function ti(t,e){return new Ks[t](e)}function ei(t){return document.createElementNS("http://www.w3.org/1999/xhtml",t)}function si(){const t=ei("canvas");return t.style.display="block",t}const ii={};function ri(t){t in ii||(ii[t]=!0,console.warn(t))}function ni(t,e,s){return new Promise((function(i,r){setTimeout((function n(){switch(t.clientWaitSync(e,t.SYNC_FLUSH_COMMANDS_BIT,0)){case t.WAIT_FAILED:r();break;case t.TIMEOUT_EXPIRED:setTimeout(n,s);break;default:i()}}),s)}))}function oi(t){const e=t.elements;e[2]=.5*e[2]+.5*e[3],e[6]=.5*e[6]+.5*e[7],e[10]=.5*e[10]+.5*e[11],e[14]=.5*e[14]+.5*e[15]}function ai(t){const e=t.elements;-1===e[11]?(e[10]=-e[10]-1,e[14]=-e[14]):(e[10]=-e[10],e[14]=1-e[14])}const hi=(new Gs).set(.4123908,.3575843,.1804808,.212639,.7151687,.0721923,.0193308,.1191948,.9505322),li=(new Gs).set(3.2409699,-1.5373832,-.4986108,-.9692436,1.8759675,.0415551,.0556301,-.203977,1.0569715);function ci(){const t={enabled:!0,workingColorSpace:$e,spaces:{},convert:function(t,e,s){return!1!==this.enabled&&e!==s&&e&&s?(this.spaces[e].transfer===Ke&&(t.r=di(t.r),t.g=di(t.g),t.b=di(t.b)),this.spaces[e].primaries!==this.spaces[s].primaries&&(t.applyMatrix3(this.spaces[e].toXYZ),t.applyMatrix3(this.spaces[s].fromXYZ)),this.spaces[s].transfer===Ke&&(t.r=pi(t.r),t.g=pi(t.g),t.b=pi(t.b)),t):t},fromWorkingColorSpace:function(t,e){return this.convert(t,this.workingColorSpace,e)},toWorkingColorSpace:function(t,e){return this.convert(t,e,this.workingColorSpace)},getPrimaries:function(t){return this.spaces[t].primaries},getTransfer:function(t){return""===t?Qe:this.spaces[t].transfer},getLuminanceCoefficients:function(t,e=this.workingColorSpace){return t.fromArray(this.spaces[e].luminanceCoefficients)},define:function(t){Object.assign(this.spaces,t)},_getMatrix:function(t,e,s){return t.copy(this.spaces[e].toXYZ).multiply(this.spaces[s].fromXYZ)},_getDrawingBufferColorSpace:function(t){return this.spaces[t].outputColorSpaceConfig.drawingBufferColorSpace},_getUnpackColorSpace:function(t=this.workingColorSpace){return this.spaces[t].workingColorSpaceConfig.unpackColorSpace}},e=[.64,.33,.3,.6,.15,.06],s=[.2126,.7152,.0722],i=[.3127,.329];return t.define({[$e]:{primaries:e,whitePoint:i,transfer:Qe,toXYZ:hi,fromXYZ:li,luminanceCoefficients:s,workingColorSpaceConfig:{unpackColorSpace:Ge},outputColorSpaceConfig:{drawingBufferColorSpace:Ge}},[Ge]:{primaries:e,whitePoint:i,transfer:Ke,toXYZ:hi,fromXYZ:li,luminanceCoefficients:s,outputColorSpaceConfig:{drawingBufferColorSpace:Ge}}}),t}const ui=ci();function di(t){return t<.04045?.0773993808*t:Math.pow(.9478672986*t+.0521327014,2.4)}function pi(t){return t<.0031308?12.92*t:1.055*Math.pow(t,.41666)-.055}let mi;class yi{static getDataURL(t){if(/^data:/i.test(t.src))return t.src;if("undefined"==typeof HTMLCanvasElement)return t.src;let e;if(t instanceof HTMLCanvasElement)e=t;else{void 0===mi&&(mi=ei("canvas")),mi.width=t.width,mi.height=t.height;const s=mi.getContext("2d");t instanceof ImageData?s.putImageData(t,0,0):s.drawImage(t,0,0,t.width,t.height),e=mi}return e.width>2048||e.height>2048?(console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons",t),e.toDataURL("image/jpeg",.6)):e.toDataURL("image/png")}static sRGBToLinear(t){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap){const e=ei("canvas");e.width=t.width,e.height=t.height;const s=e.getContext("2d");s.drawImage(t,0,0,t.width,t.height);const i=s.getImageData(0,0,t.width,t.height),r=i.data;for(let t=0;t0&&(s.userData=this.userData),e||(t.textures[this.uuid]=s),s}dispose(){this.dispatchEvent({type:"dispose"})}transformUv(t){if(this.mapping!==at)return t;if(t.applyMatrix3(this.matrix),t.x<0||t.x>1)switch(this.wrapS){case pt:t.x=t.x-Math.floor(t.x);break;case mt:t.x=t.x<0?0:1;break;case yt:1===Math.abs(Math.floor(t.x)%2)?t.x=Math.ceil(t.x)-t.x:t.x=t.x-Math.floor(t.x)}if(t.y<0||t.y>1)switch(this.wrapT){case pt:t.y=t.y-Math.floor(t.y);break;case mt:t.y=t.y<0?0:1;break;case yt:1===Math.abs(Math.floor(t.y)%2)?t.y=Math.ceil(t.y)-t.y:t.y=t.y-Math.floor(t.y)}return this.flipY&&(t.y=1-t.y),t}set needsUpdate(t){!0===t&&(this.version++,this.source.needsUpdate=!0)}set needsPMREMUpdate(t){!0===t&&this.pmremVersion++}}vi.DEFAULT_IMAGE=null,vi.DEFAULT_MAPPING=at,vi.DEFAULT_ANISOTROPY=1;class wi{constructor(t=0,e=0,s=0,i=1){wi.prototype.isVector4=!0,this.x=t,this.y=e,this.z=s,this.w=i}get width(){return this.z}set width(t){this.z=t}get height(){return this.w}set height(t){this.w=t}set(t,e,s,i){return this.x=t,this.y=e,this.z=s,this.w=i,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this.w=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setW(t){return this.w=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;case 3:this.w=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this.w=void 0!==t.w?t.w:1,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this.w+=t.w,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this.w+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this.w=t.w+e.w,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this.w+=t.w*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this.w-=t.w,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this.w-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this.w=t.w-e.w,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this.w*=t.w,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this.w*=t,this}applyMatrix4(t){const e=this.x,s=this.y,i=this.z,r=this.w,n=t.elements;return this.x=n[0]*e+n[4]*s+n[8]*i+n[12]*r,this.y=n[1]*e+n[5]*s+n[9]*i+n[13]*r,this.z=n[2]*e+n[6]*s+n[10]*i+n[14]*r,this.w=n[3]*e+n[7]*s+n[11]*i+n[15]*r,this}divide(t){return this.x/=t.x,this.y/=t.y,this.z/=t.z,this.w/=t.w,this}divideScalar(t){return this.multiplyScalar(1/t)}setAxisAngleFromQuaternion(t){this.w=2*Math.acos(t.w);const e=Math.sqrt(1-t.w*t.w);return e<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=t.x/e,this.y=t.y/e,this.z=t.z/e),this}setAxisAngleFromRotationMatrix(t){let e,s,i,r;const n=.01,o=.1,a=t.elements,h=a[0],l=a[4],c=a[8],u=a[1],d=a[5],p=a[9],m=a[2],y=a[6],f=a[10];if(Math.abs(l-u)a&&t>g?tg?a=0?1:-1,i=1-e*e;if(i>Number.EPSILON){const r=Math.sqrt(i),n=Math.atan2(r,e*s);t=Math.sin(t*n)/r,o=Math.sin(o*n)/r}const r=o*s;if(a=a*t+u*r,h=h*t+d*r,l=l*t+p*r,c=c*t+m*r,t===1-o){const t=1/Math.sqrt(a*a+h*h+l*l+c*c);a*=t,h*=t,l*=t,c*=t}}t[e]=a,t[e+1]=h,t[e+2]=l,t[e+3]=c}static multiplyQuaternionsFlat(t,e,s,i,r,n){const o=s[i],a=s[i+1],h=s[i+2],l=s[i+3],c=r[n],u=r[n+1],d=r[n+2],p=r[n+3];return t[e]=o*p+l*c+a*d-h*u,t[e+1]=a*p+l*u+h*c-o*d,t[e+2]=h*p+l*d+o*u-a*c,t[e+3]=l*p-o*c-a*u-h*d,t}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get w(){return this._w}set w(t){this._w=t,this._onChangeCallback()}set(t,e,s,i){return this._x=t,this._y=e,this._z=s,this._w=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(t){return this._x=t.x,this._y=t.y,this._z=t.z,this._w=t.w,this._onChangeCallback(),this}setFromEuler(t,e=!0){const s=t._x,i=t._y,r=t._z,n=t._order,o=Math.cos,a=Math.sin,h=o(s/2),l=o(i/2),c=o(r/2),u=a(s/2),d=a(i/2),p=a(r/2);switch(n){case"XYZ":this._x=u*l*c+h*d*p,this._y=h*d*c-u*l*p,this._z=h*l*p+u*d*c,this._w=h*l*c-u*d*p;break;case"YXZ":this._x=u*l*c+h*d*p,this._y=h*d*c-u*l*p,this._z=h*l*p-u*d*c,this._w=h*l*c+u*d*p;break;case"ZXY":this._x=u*l*c-h*d*p,this._y=h*d*c+u*l*p,this._z=h*l*p+u*d*c,this._w=h*l*c-u*d*p;break;case"ZYX":this._x=u*l*c-h*d*p,this._y=h*d*c+u*l*p,this._z=h*l*p-u*d*c,this._w=h*l*c+u*d*p;break;case"YZX":this._x=u*l*c+h*d*p,this._y=h*d*c+u*l*p,this._z=h*l*p-u*d*c,this._w=h*l*c-u*d*p;break;case"XZY":this._x=u*l*c-h*d*p,this._y=h*d*c-u*l*p,this._z=h*l*p+u*d*c,this._w=h*l*c+u*d*p;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+n)}return!0===e&&this._onChangeCallback(),this}setFromAxisAngle(t,e){const s=e/2,i=Math.sin(s);return this._x=t.x*i,this._y=t.y*i,this._z=t.z*i,this._w=Math.cos(s),this._onChangeCallback(),this}setFromRotationMatrix(t){const e=t.elements,s=e[0],i=e[4],r=e[8],n=e[1],o=e[5],a=e[9],h=e[2],l=e[6],c=e[10],u=s+o+c;if(u>0){const t=.5/Math.sqrt(u+1);this._w=.25/t,this._x=(l-a)*t,this._y=(r-h)*t,this._z=(n-i)*t}else if(s>o&&s>c){const t=2*Math.sqrt(1+s-o-c);this._w=(l-a)/t,this._x=.25*t,this._y=(i+n)/t,this._z=(r+h)/t}else if(o>c){const t=2*Math.sqrt(1+o-s-c);this._w=(r-h)/t,this._x=(i+n)/t,this._y=.25*t,this._z=(a+l)/t}else{const t=2*Math.sqrt(1+c-s-o);this._w=(n-i)/t,this._x=(r+h)/t,this._y=(a+l)/t,this._z=.25*t}return this._onChangeCallback(),this}setFromUnitVectors(t,e){let s=t.dot(e)+1;return sMath.abs(t.z)?(this._x=-t.y,this._y=t.x,this._z=0,this._w=s):(this._x=0,this._y=-t.z,this._z=t.y,this._w=s)):(this._x=t.y*e.z-t.z*e.y,this._y=t.z*e.x-t.x*e.z,this._z=t.x*e.y-t.y*e.x,this._w=s),this.normalize()}angleTo(t){return 2*Math.acos(Math.abs(Ds(this.dot(t),-1,1)))}rotateTowards(t,e){const s=this.angleTo(t);if(0===s)return this;const i=Math.min(1,e/s);return this.slerp(t,i),this}identity(){return this.set(0,0,0,1)}invert(){return this.conjugate()}conjugate(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this}dot(t){return this._x*t._x+this._y*t._y+this._z*t._z+this._w*t._w}lengthSq(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w}length(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)}normalize(){let t=this.length();return 0===t?(this._x=0,this._y=0,this._z=0,this._w=1):(t=1/t,this._x=this._x*t,this._y=this._y*t,this._z=this._z*t,this._w=this._w*t),this._onChangeCallback(),this}multiply(t){return this.multiplyQuaternions(this,t)}premultiply(t){return this.multiplyQuaternions(t,this)}multiplyQuaternions(t,e){const s=t._x,i=t._y,r=t._z,n=t._w,o=e._x,a=e._y,h=e._z,l=e._w;return this._x=s*l+n*o+i*h-r*a,this._y=i*l+n*a+r*o-s*h,this._z=r*l+n*h+s*a-i*o,this._w=n*l-s*o-i*a-r*h,this._onChangeCallback(),this}slerp(t,e){if(0===e)return this;if(1===e)return this.copy(t);const s=this._x,i=this._y,r=this._z,n=this._w;let o=n*t._w+s*t._x+i*t._y+r*t._z;if(o<0?(this._w=-t._w,this._x=-t._x,this._y=-t._y,this._z=-t._z,o=-o):this.copy(t),o>=1)return this._w=n,this._x=s,this._y=i,this._z=r,this;const a=1-o*o;if(a<=Number.EPSILON){const t=1-e;return this._w=t*n+e*this._w,this._x=t*s+e*this._x,this._y=t*i+e*this._y,this._z=t*r+e*this._z,this.normalize(),this}const h=Math.sqrt(a),l=Math.atan2(h,o),c=Math.sin((1-e)*l)/h,u=Math.sin(e*l)/h;return this._w=n*c+this._w*u,this._x=s*c+this._x*u,this._y=i*c+this._y*u,this._z=r*c+this._z*u,this._onChangeCallback(),this}slerpQuaternions(t,e,s){return this.copy(t).slerp(e,s)}random(){const t=2*Math.PI*Math.random(),e=2*Math.PI*Math.random(),s=Math.random(),i=Math.sqrt(1-s),r=Math.sqrt(s);return this.set(i*Math.sin(t),i*Math.cos(t),r*Math.sin(e),r*Math.cos(e))}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._w===this._w}fromArray(t,e=0){return this._x=t[e],this._y=t[e+1],this._z=t[e+2],this._w=t[e+3],this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._w,t}fromBufferAttribute(t,e){return this._x=t.getX(e),this._y=t.getY(e),this._z=t.getZ(e),this._w=t.getW(e),this._onChangeCallback(),this}toJSON(){return this.toArray()}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class Ii{constructor(t=0,e=0,s=0){Ii.prototype.isVector3=!0,this.x=t,this.y=e,this.z=s}set(t,e,s){return void 0===s&&(s=this.z),this.x=t,this.y=e,this.z=s,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this}multiplyVectors(t,e){return this.x=t.x*e.x,this.y=t.y*e.y,this.z=t.z*e.z,this}applyEuler(t){return this.applyQuaternion(ki.setFromEuler(t))}applyAxisAngle(t,e){return this.applyQuaternion(ki.setFromAxisAngle(t,e))}applyMatrix3(t){const e=this.x,s=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[3]*s+r[6]*i,this.y=r[1]*e+r[4]*s+r[7]*i,this.z=r[2]*e+r[5]*s+r[8]*i,this}applyNormalMatrix(t){return this.applyMatrix3(t).normalize()}applyMatrix4(t){const e=this.x,s=this.y,i=this.z,r=t.elements,n=1/(r[3]*e+r[7]*s+r[11]*i+r[15]);return this.x=(r[0]*e+r[4]*s+r[8]*i+r[12])*n,this.y=(r[1]*e+r[5]*s+r[9]*i+r[13])*n,this.z=(r[2]*e+r[6]*s+r[10]*i+r[14])*n,this}applyQuaternion(t){const e=this.x,s=this.y,i=this.z,r=t.x,n=t.y,o=t.z,a=t.w,h=2*(n*i-o*s),l=2*(o*e-r*i),c=2*(r*s-n*e);return this.x=e+a*h+n*c-o*l,this.y=s+a*l+o*h-r*c,this.z=i+a*c+r*l-n*h,this}project(t){return this.applyMatrix4(t.matrixWorldInverse).applyMatrix4(t.projectionMatrix)}unproject(t){return this.applyMatrix4(t.projectionMatrixInverse).applyMatrix4(t.matrixWorld)}transformDirection(t){const e=this.x,s=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[4]*s+r[8]*i,this.y=r[1]*e+r[5]*s+r[9]*i,this.z=r[2]*e+r[6]*s+r[10]*i,this.normalize()}divide(t){return this.x/=t.x,this.y/=t.y,this.z/=t.z,this}divideScalar(t){return this.multiplyScalar(1/t)}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this}clamp(t,e){return this.x=Ds(this.x,t.x,e.x),this.y=Ds(this.y,t.y,e.y),this.z=Ds(this.z,t.z,e.z),this}clampScalar(t,e){return this.x=Ds(this.x,t,e),this.y=Ds(this.y,t,e),this.z=Ds(this.z,t,e),this}clampLength(t,e){const s=this.length();return this.divideScalar(s||1).multiplyScalar(Ds(s,t,e))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)}normalize(){return this.divideScalar(this.length()||1)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this}lerpVectors(t,e,s){return this.x=t.x+(e.x-t.x)*s,this.y=t.y+(e.y-t.y)*s,this.z=t.z+(e.z-t.z)*s,this}cross(t){return this.crossVectors(this,t)}crossVectors(t,e){const s=t.x,i=t.y,r=t.z,n=e.x,o=e.y,a=e.z;return this.x=i*a-r*o,this.y=r*n-s*a,this.z=s*o-i*n,this}projectOnVector(t){const e=t.lengthSq();if(0===e)return this.set(0,0,0);const s=t.dot(this)/e;return this.copy(t).multiplyScalar(s)}projectOnPlane(t){return Bi.copy(this).projectOnVector(t),this.sub(Bi)}reflect(t){return this.sub(Bi.copy(t).multiplyScalar(2*this.dot(t)))}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(0===e)return Math.PI/2;const s=this.dot(t)/e;return Math.acos(Ds(s,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,s=this.y-t.y,i=this.z-t.z;return e*e+s*s+i*i}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)+Math.abs(this.z-t.z)}setFromSpherical(t){return this.setFromSphericalCoords(t.radius,t.phi,t.theta)}setFromSphericalCoords(t,e,s){const i=Math.sin(e)*t;return this.x=i*Math.sin(s),this.y=Math.cos(e)*t,this.z=i*Math.cos(s),this}setFromCylindrical(t){return this.setFromCylindricalCoords(t.radius,t.theta,t.y)}setFromCylindricalCoords(t,e,s){return this.x=t*Math.sin(e),this.y=s,this.z=t*Math.cos(e),this}setFromMatrixPosition(t){const e=t.elements;return this.x=e[12],this.y=e[13],this.z=e[14],this}setFromMatrixScale(t){const e=this.setFromMatrixColumn(t,0).length(),s=this.setFromMatrixColumn(t,1).length(),i=this.setFromMatrixColumn(t,2).length();return this.x=e,this.y=s,this.z=i,this}setFromMatrixColumn(t,e){return this.fromArray(t.elements,4*e)}setFromMatrix3Column(t,e){return this.fromArray(t.elements,3*e)}setFromEuler(t){return this.x=t._x,this.y=t._y,this.z=t._z,this}setFromColor(t){return this.x=t.r,this.y=t.g,this.z=t.b,this}equals(t){return t.x===this.x&&t.y===this.y&&t.z===this.z}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this.z=t[e+2],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){const t=Math.random()*Math.PI*2,e=2*Math.random()-1,s=Math.sqrt(1-e*e);return this.x=s*Math.cos(t),this.y=e,this.z=s*Math.sin(t),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}const Bi=new Ii,ki=new Ci;class Ei{constructor(t=new Ii(1/0,1/0,1/0),e=new Ii(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=t,this.max=e}set(t,e){return this.min.copy(t),this.max.copy(e),this}setFromArray(t){this.makeEmpty();for(let e=0,s=t.length;e=this.min.x&&t.x<=this.max.x&&t.y>=this.min.y&&t.y<=this.max.y&&t.z>=this.min.z&&t.z<=this.max.z}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y&&this.min.z<=t.min.z&&t.max.z<=this.max.z}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y),(t.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(t){return t.max.x>=this.min.x&&t.min.x<=this.max.x&&t.max.y>=this.min.y&&t.min.y<=this.max.y&&t.max.z>=this.min.z&&t.min.z<=this.max.z}intersectsSphere(t){return this.clampPoint(t.center,Ri),Ri.distanceToSquared(t.center)<=t.radius*t.radius}intersectsPlane(t){let e,s;return t.normal.x>0?(e=t.normal.x*this.min.x,s=t.normal.x*this.max.x):(e=t.normal.x*this.max.x,s=t.normal.x*this.min.x),t.normal.y>0?(e+=t.normal.y*this.min.y,s+=t.normal.y*this.max.y):(e+=t.normal.y*this.max.y,s+=t.normal.y*this.min.y),t.normal.z>0?(e+=t.normal.z*this.min.z,s+=t.normal.z*this.max.z):(e+=t.normal.z*this.max.z,s+=t.normal.z*this.min.z),e<=-t.constant&&s>=-t.constant}intersectsTriangle(t){if(this.isEmpty())return!1;this.getCenter(Ui),Di.subVectors(this.max,Ui),Fi.subVectors(t.a,Ui),Ni.subVectors(t.b,Ui),Li.subVectors(t.c,Ui),Vi.subVectors(Ni,Fi),Wi.subVectors(Li,Ni),ji.subVectors(Fi,Li);let e=[0,-Vi.z,Vi.y,0,-Wi.z,Wi.y,0,-ji.z,ji.y,Vi.z,0,-Vi.x,Wi.z,0,-Wi.x,ji.z,0,-ji.x,-Vi.y,Vi.x,0,-Wi.y,Wi.x,0,-ji.y,ji.x,0];return!!Ji(e,Fi,Ni,Li,Di)&&(e=[1,0,0,0,1,0,0,0,1],!!Ji(e,Fi,Ni,Li,Di)&&(Hi.crossVectors(Vi,Wi),e=[Hi.x,Hi.y,Hi.z],Ji(e,Fi,Ni,Li,Di)))}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return this.clampPoint(t,Ri).distanceTo(t)}getBoundingSphere(t){return this.isEmpty()?t.makeEmpty():(this.getCenter(t.center),t.radius=.5*this.getSize(Ri).length()),t}intersect(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&&this.makeEmpty(),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}applyMatrix4(t){return this.isEmpty()||(Pi[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(t),Pi[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(t),Pi[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(t),Pi[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(t),Pi[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(t),Pi[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(t),Pi[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(t),Pi[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(t),this.setFromPoints(Pi)),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}}const Pi=[new Ii,new Ii,new Ii,new Ii,new Ii,new Ii,new Ii,new Ii],Ri=new Ii,Oi=new Ei,Fi=new Ii,Ni=new Ii,Li=new Ii,Vi=new Ii,Wi=new Ii,ji=new Ii,Ui=new Ii,Di=new Ii,Hi=new Ii,qi=new Ii;function Ji(t,e,s,i,r){for(let n=0,o=t.length-3;n<=o;n+=3){qi.fromArray(t,n);const o=r.x*Math.abs(qi.x)+r.y*Math.abs(qi.y)+r.z*Math.abs(qi.z),a=e.dot(qi),h=s.dot(qi),l=i.dot(qi);if(Math.max(-Math.max(a,h,l),Math.min(a,h,l))>o)return!1}return!0}const Xi=new Ei,Yi=new Ii,Zi=new Ii;class Gi{constructor(t=new Ii,e=-1){this.isSphere=!0,this.center=t,this.radius=e}set(t,e){return this.center.copy(t),this.radius=e,this}setFromPoints(t,e){const s=this.center;void 0!==e?s.copy(e):Xi.setFromPoints(t).getCenter(s);let i=0;for(let e=0,r=t.length;ethis.radius*this.radius&&(e.sub(this.center).normalize(),e.multiplyScalar(this.radius).add(this.center)),e}getBoundingBox(t){return this.isEmpty()?(t.makeEmpty(),t):(t.set(this.center,this.center),t.expandByScalar(this.radius),t)}applyMatrix4(t){return this.center.applyMatrix4(t),this.radius=this.radius*t.getMaxScaleOnAxis(),this}translate(t){return this.center.add(t),this}expandByPoint(t){if(this.isEmpty())return this.center.copy(t),this.radius=0,this;Yi.subVectors(t,this.center);const e=Yi.lengthSq();if(e>this.radius*this.radius){const t=Math.sqrt(e),s=.5*(t-this.radius);this.center.addScaledVector(Yi,s/t),this.radius+=s}return this}union(t){return t.isEmpty()?this:this.isEmpty()?(this.copy(t),this):(!0===this.center.equals(t.center)?this.radius=Math.max(this.radius,t.radius):(Zi.subVectors(t.center,this.center).setLength(t.radius),this.expandByPoint(Yi.copy(t.center).add(Zi)),this.expandByPoint(Yi.copy(t.center).sub(Zi))),this)}equals(t){return t.center.equals(this.center)&&t.radius===this.radius}clone(){return(new this.constructor).copy(this)}}const $i=new Ii,Qi=new Ii,Ki=new Ii,tr=new Ii,er=new Ii,sr=new Ii,ir=new Ii;class rr{constructor(t=new Ii,e=new Ii(0,0,-1)){this.origin=t,this.direction=e}set(t,e){return this.origin.copy(t),this.direction.copy(e),this}copy(t){return this.origin.copy(t.origin),this.direction.copy(t.direction),this}at(t,e){return e.copy(this.origin).addScaledVector(this.direction,t)}lookAt(t){return this.direction.copy(t).sub(this.origin).normalize(),this}recast(t){return this.origin.copy(this.at(t,$i)),this}closestPointToPoint(t,e){e.subVectors(t,this.origin);const s=e.dot(this.direction);return s<0?e.copy(this.origin):e.copy(this.origin).addScaledVector(this.direction,s)}distanceToPoint(t){return Math.sqrt(this.distanceSqToPoint(t))}distanceSqToPoint(t){const e=$i.subVectors(t,this.origin).dot(this.direction);return e<0?this.origin.distanceToSquared(t):($i.copy(this.origin).addScaledVector(this.direction,e),$i.distanceToSquared(t))}distanceSqToSegment(t,e,s,i){Qi.copy(t).add(e).multiplyScalar(.5),Ki.copy(e).sub(t).normalize(),tr.copy(this.origin).sub(Qi);const r=.5*t.distanceTo(e),n=-this.direction.dot(Ki),o=tr.dot(this.direction),a=-tr.dot(Ki),h=tr.lengthSq(),l=Math.abs(1-n*n);let c,u,d,p;if(l>0)if(c=n*a-o,u=n*o-a,p=r*l,c>=0)if(u>=-p)if(u<=p){const t=1/l;c*=t,u*=t,d=c*(c+n*u+2*o)+u*(n*c+u+2*a)+h}else u=r,c=Math.max(0,-(n*u+o)),d=-c*c+u*(u+2*a)+h;else u=-r,c=Math.max(0,-(n*u+o)),d=-c*c+u*(u+2*a)+h;else u<=-p?(c=Math.max(0,-(-n*r+o)),u=c>0?-r:Math.min(Math.max(-r,-a),r),d=-c*c+u*(u+2*a)+h):u<=p?(c=0,u=Math.min(Math.max(-r,-a),r),d=u*(u+2*a)+h):(c=Math.max(0,-(n*r+o)),u=c>0?r:Math.min(Math.max(-r,-a),r),d=-c*c+u*(u+2*a)+h);else u=n>0?-r:r,c=Math.max(0,-(n*u+o)),d=-c*c+u*(u+2*a)+h;return s&&s.copy(this.origin).addScaledVector(this.direction,c),i&&i.copy(Qi).addScaledVector(Ki,u),d}intersectSphere(t,e){$i.subVectors(t.center,this.origin);const s=$i.dot(this.direction),i=$i.dot($i)-s*s,r=t.radius*t.radius;if(i>r)return null;const n=Math.sqrt(r-i),o=s-n,a=s+n;return a<0?null:o<0?this.at(a,e):this.at(o,e)}intersectsSphere(t){return this.distanceSqToPoint(t.center)<=t.radius*t.radius}distanceToPlane(t){const e=t.normal.dot(this.direction);if(0===e)return 0===t.distanceToPoint(this.origin)?0:null;const s=-(this.origin.dot(t.normal)+t.constant)/e;return s>=0?s:null}intersectPlane(t,e){const s=this.distanceToPlane(t);return null===s?null:this.at(s,e)}intersectsPlane(t){const e=t.distanceToPoint(this.origin);if(0===e)return!0;return t.normal.dot(this.direction)*e<0}intersectBox(t,e){let s,i,r,n,o,a;const h=1/this.direction.x,l=1/this.direction.y,c=1/this.direction.z,u=this.origin;return h>=0?(s=(t.min.x-u.x)*h,i=(t.max.x-u.x)*h):(s=(t.max.x-u.x)*h,i=(t.min.x-u.x)*h),l>=0?(r=(t.min.y-u.y)*l,n=(t.max.y-u.y)*l):(r=(t.max.y-u.y)*l,n=(t.min.y-u.y)*l),s>n||r>i?null:((r>s||isNaN(s))&&(s=r),(n=0?(o=(t.min.z-u.z)*c,a=(t.max.z-u.z)*c):(o=(t.max.z-u.z)*c,a=(t.min.z-u.z)*c),s>a||o>i?null:((o>s||s!=s)&&(s=o),(a=0?s:i,e)))}intersectsBox(t){return null!==this.intersectBox(t,$i)}intersectTriangle(t,e,s,i,r){er.subVectors(e,t),sr.subVectors(s,t),ir.crossVectors(er,sr);let n,o=this.direction.dot(ir);if(o>0){if(i)return null;n=1}else{if(!(o<0))return null;n=-1,o=-o}tr.subVectors(this.origin,t);const a=n*this.direction.dot(sr.crossVectors(tr,sr));if(a<0)return null;const h=n*this.direction.dot(er.cross(tr));if(h<0)return null;if(a+h>o)return null;const l=-n*tr.dot(ir);return l<0?null:this.at(l/o,r)}applyMatrix4(t){return this.origin.applyMatrix4(t),this.direction.transformDirection(t),this}equals(t){return t.origin.equals(this.origin)&&t.direction.equals(this.direction)}clone(){return(new this.constructor).copy(this)}}class nr{constructor(t,e,s,i,r,n,o,a,h,l,c,u,d,p,m,y){nr.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],void 0!==t&&this.set(t,e,s,i,r,n,o,a,h,l,c,u,d,p,m,y)}set(t,e,s,i,r,n,o,a,h,l,c,u,d,p,m,y){const f=this.elements;return f[0]=t,f[4]=e,f[8]=s,f[12]=i,f[1]=r,f[5]=n,f[9]=o,f[13]=a,f[2]=h,f[6]=l,f[10]=c,f[14]=u,f[3]=d,f[7]=p,f[11]=m,f[15]=y,this}identity(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this}clone(){return(new nr).fromArray(this.elements)}copy(t){const e=this.elements,s=t.elements;return e[0]=s[0],e[1]=s[1],e[2]=s[2],e[3]=s[3],e[4]=s[4],e[5]=s[5],e[6]=s[6],e[7]=s[7],e[8]=s[8],e[9]=s[9],e[10]=s[10],e[11]=s[11],e[12]=s[12],e[13]=s[13],e[14]=s[14],e[15]=s[15],this}copyPosition(t){const e=this.elements,s=t.elements;return e[12]=s[12],e[13]=s[13],e[14]=s[14],this}setFromMatrix3(t){const e=t.elements;return this.set(e[0],e[3],e[6],0,e[1],e[4],e[7],0,e[2],e[5],e[8],0,0,0,0,1),this}extractBasis(t,e,s){return t.setFromMatrixColumn(this,0),e.setFromMatrixColumn(this,1),s.setFromMatrixColumn(this,2),this}makeBasis(t,e,s){return this.set(t.x,e.x,s.x,0,t.y,e.y,s.y,0,t.z,e.z,s.z,0,0,0,0,1),this}extractRotation(t){const e=this.elements,s=t.elements,i=1/or.setFromMatrixColumn(t,0).length(),r=1/or.setFromMatrixColumn(t,1).length(),n=1/or.setFromMatrixColumn(t,2).length();return e[0]=s[0]*i,e[1]=s[1]*i,e[2]=s[2]*i,e[3]=0,e[4]=s[4]*r,e[5]=s[5]*r,e[6]=s[6]*r,e[7]=0,e[8]=s[8]*n,e[9]=s[9]*n,e[10]=s[10]*n,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromEuler(t){const e=this.elements,s=t.x,i=t.y,r=t.z,n=Math.cos(s),o=Math.sin(s),a=Math.cos(i),h=Math.sin(i),l=Math.cos(r),c=Math.sin(r);if("XYZ"===t.order){const t=n*l,s=n*c,i=o*l,r=o*c;e[0]=a*l,e[4]=-a*c,e[8]=h,e[1]=s+i*h,e[5]=t-r*h,e[9]=-o*a,e[2]=r-t*h,e[6]=i+s*h,e[10]=n*a}else if("YXZ"===t.order){const t=a*l,s=a*c,i=h*l,r=h*c;e[0]=t+r*o,e[4]=i*o-s,e[8]=n*h,e[1]=n*c,e[5]=n*l,e[9]=-o,e[2]=s*o-i,e[6]=r+t*o,e[10]=n*a}else if("ZXY"===t.order){const t=a*l,s=a*c,i=h*l,r=h*c;e[0]=t-r*o,e[4]=-n*c,e[8]=i+s*o,e[1]=s+i*o,e[5]=n*l,e[9]=r-t*o,e[2]=-n*h,e[6]=o,e[10]=n*a}else if("ZYX"===t.order){const t=n*l,s=n*c,i=o*l,r=o*c;e[0]=a*l,e[4]=i*h-s,e[8]=t*h+r,e[1]=a*c,e[5]=r*h+t,e[9]=s*h-i,e[2]=-h,e[6]=o*a,e[10]=n*a}else if("YZX"===t.order){const t=n*a,s=n*h,i=o*a,r=o*h;e[0]=a*l,e[4]=r-t*c,e[8]=i*c+s,e[1]=c,e[5]=n*l,e[9]=-o*l,e[2]=-h*l,e[6]=s*c+i,e[10]=t-r*c}else if("XZY"===t.order){const t=n*a,s=n*h,i=o*a,r=o*h;e[0]=a*l,e[4]=-c,e[8]=h*l,e[1]=t*c+r,e[5]=n*l,e[9]=s*c-i,e[2]=i*c-s,e[6]=o*l,e[10]=r*c+t}return e[3]=0,e[7]=0,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromQuaternion(t){return this.compose(hr,t,lr)}lookAt(t,e,s){const i=this.elements;return dr.subVectors(t,e),0===dr.lengthSq()&&(dr.z=1),dr.normalize(),cr.crossVectors(s,dr),0===cr.lengthSq()&&(1===Math.abs(s.z)?dr.x+=1e-4:dr.z+=1e-4,dr.normalize(),cr.crossVectors(s,dr)),cr.normalize(),ur.crossVectors(dr,cr),i[0]=cr.x,i[4]=ur.x,i[8]=dr.x,i[1]=cr.y,i[5]=ur.y,i[9]=dr.y,i[2]=cr.z,i[6]=ur.z,i[10]=dr.z,this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const s=t.elements,i=e.elements,r=this.elements,n=s[0],o=s[4],a=s[8],h=s[12],l=s[1],c=s[5],u=s[9],d=s[13],p=s[2],m=s[6],y=s[10],f=s[14],g=s[3],x=s[7],b=s[11],v=s[15],w=i[0],M=i[4],S=i[8],_=i[12],A=i[1],T=i[5],z=i[9],C=i[13],I=i[2],B=i[6],k=i[10],E=i[14],P=i[3],R=i[7],O=i[11],F=i[15];return r[0]=n*w+o*A+a*I+h*P,r[4]=n*M+o*T+a*B+h*R,r[8]=n*S+o*z+a*k+h*O,r[12]=n*_+o*C+a*E+h*F,r[1]=l*w+c*A+u*I+d*P,r[5]=l*M+c*T+u*B+d*R,r[9]=l*S+c*z+u*k+d*O,r[13]=l*_+c*C+u*E+d*F,r[2]=p*w+m*A+y*I+f*P,r[6]=p*M+m*T+y*B+f*R,r[10]=p*S+m*z+y*k+f*O,r[14]=p*_+m*C+y*E+f*F,r[3]=g*w+x*A+b*I+v*P,r[7]=g*M+x*T+b*B+v*R,r[11]=g*S+x*z+b*k+v*O,r[15]=g*_+x*C+b*E+v*F,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[4]*=t,e[8]*=t,e[12]*=t,e[1]*=t,e[5]*=t,e[9]*=t,e[13]*=t,e[2]*=t,e[6]*=t,e[10]*=t,e[14]*=t,e[3]*=t,e[7]*=t,e[11]*=t,e[15]*=t,this}determinant(){const t=this.elements,e=t[0],s=t[4],i=t[8],r=t[12],n=t[1],o=t[5],a=t[9],h=t[13],l=t[2],c=t[6],u=t[10],d=t[14];return t[3]*(+r*a*c-i*h*c-r*o*u+s*h*u+i*o*d-s*a*d)+t[7]*(+e*a*d-e*h*u+r*n*u-i*n*d+i*h*l-r*a*l)+t[11]*(+e*h*c-e*o*d-r*n*c+s*n*d+r*o*l-s*h*l)+t[15]*(-i*o*l-e*a*c+e*o*u+i*n*c-s*n*u+s*a*l)}transpose(){const t=this.elements;let e;return e=t[1],t[1]=t[4],t[4]=e,e=t[2],t[2]=t[8],t[8]=e,e=t[6],t[6]=t[9],t[9]=e,e=t[3],t[3]=t[12],t[12]=e,e=t[7],t[7]=t[13],t[13]=e,e=t[11],t[11]=t[14],t[14]=e,this}setPosition(t,e,s){const i=this.elements;return t.isVector3?(i[12]=t.x,i[13]=t.y,i[14]=t.z):(i[12]=t,i[13]=e,i[14]=s),this}invert(){const t=this.elements,e=t[0],s=t[1],i=t[2],r=t[3],n=t[4],o=t[5],a=t[6],h=t[7],l=t[8],c=t[9],u=t[10],d=t[11],p=t[12],m=t[13],y=t[14],f=t[15],g=c*y*h-m*u*h+m*a*d-o*y*d-c*a*f+o*u*f,x=p*u*h-l*y*h-p*a*d+n*y*d+l*a*f-n*u*f,b=l*m*h-p*c*h+p*o*d-n*m*d-l*o*f+n*c*f,v=p*c*a-l*m*a-p*o*u+n*m*u+l*o*y-n*c*y,w=e*g+s*x+i*b+r*v;if(0===w)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const M=1/w;return t[0]=g*M,t[1]=(m*u*r-c*y*r-m*i*d+s*y*d+c*i*f-s*u*f)*M,t[2]=(o*y*r-m*a*r+m*i*h-s*y*h-o*i*f+s*a*f)*M,t[3]=(c*a*r-o*u*r-c*i*h+s*u*h+o*i*d-s*a*d)*M,t[4]=x*M,t[5]=(l*y*r-p*u*r+p*i*d-e*y*d-l*i*f+e*u*f)*M,t[6]=(p*a*r-n*y*r-p*i*h+e*y*h+n*i*f-e*a*f)*M,t[7]=(n*u*r-l*a*r+l*i*h-e*u*h-n*i*d+e*a*d)*M,t[8]=b*M,t[9]=(p*c*r-l*m*r-p*s*d+e*m*d+l*s*f-e*c*f)*M,t[10]=(n*m*r-p*o*r+p*s*h-e*m*h-n*s*f+e*o*f)*M,t[11]=(l*o*r-n*c*r-l*s*h+e*c*h+n*s*d-e*o*d)*M,t[12]=v*M,t[13]=(l*m*i-p*c*i+p*s*u-e*m*u-l*s*y+e*c*y)*M,t[14]=(p*o*i-n*m*i-p*s*a+e*m*a+n*s*y-e*o*y)*M,t[15]=(n*c*i-l*o*i+l*s*a-e*c*a-n*s*u+e*o*u)*M,this}scale(t){const e=this.elements,s=t.x,i=t.y,r=t.z;return e[0]*=s,e[4]*=i,e[8]*=r,e[1]*=s,e[5]*=i,e[9]*=r,e[2]*=s,e[6]*=i,e[10]*=r,e[3]*=s,e[7]*=i,e[11]*=r,this}getMaxScaleOnAxis(){const t=this.elements,e=t[0]*t[0]+t[1]*t[1]+t[2]*t[2],s=t[4]*t[4]+t[5]*t[5]+t[6]*t[6],i=t[8]*t[8]+t[9]*t[9]+t[10]*t[10];return Math.sqrt(Math.max(e,s,i))}makeTranslation(t,e,s){return t.isVector3?this.set(1,0,0,t.x,0,1,0,t.y,0,0,1,t.z,0,0,0,1):this.set(1,0,0,t,0,1,0,e,0,0,1,s,0,0,0,1),this}makeRotationX(t){const e=Math.cos(t),s=Math.sin(t);return this.set(1,0,0,0,0,e,-s,0,0,s,e,0,0,0,0,1),this}makeRotationY(t){const e=Math.cos(t),s=Math.sin(t);return this.set(e,0,s,0,0,1,0,0,-s,0,e,0,0,0,0,1),this}makeRotationZ(t){const e=Math.cos(t),s=Math.sin(t);return this.set(e,-s,0,0,s,e,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(t,e){const s=Math.cos(e),i=Math.sin(e),r=1-s,n=t.x,o=t.y,a=t.z,h=r*n,l=r*o;return this.set(h*n+s,h*o-i*a,h*a+i*o,0,h*o+i*a,l*o+s,l*a-i*n,0,h*a-i*o,l*a+i*n,r*a*a+s,0,0,0,0,1),this}makeScale(t,e,s){return this.set(t,0,0,0,0,e,0,0,0,0,s,0,0,0,0,1),this}makeShear(t,e,s,i,r,n){return this.set(1,s,r,0,t,1,n,0,e,i,1,0,0,0,0,1),this}compose(t,e,s){const i=this.elements,r=e._x,n=e._y,o=e._z,a=e._w,h=r+r,l=n+n,c=o+o,u=r*h,d=r*l,p=r*c,m=n*l,y=n*c,f=o*c,g=a*h,x=a*l,b=a*c,v=s.x,w=s.y,M=s.z;return i[0]=(1-(m+f))*v,i[1]=(d+b)*v,i[2]=(p-x)*v,i[3]=0,i[4]=(d-b)*w,i[5]=(1-(u+f))*w,i[6]=(y+g)*w,i[7]=0,i[8]=(p+x)*M,i[9]=(y-g)*M,i[10]=(1-(u+m))*M,i[11]=0,i[12]=t.x,i[13]=t.y,i[14]=t.z,i[15]=1,this}decompose(t,e,s){const i=this.elements;let r=or.set(i[0],i[1],i[2]).length();const n=or.set(i[4],i[5],i[6]).length(),o=or.set(i[8],i[9],i[10]).length();this.determinant()<0&&(r=-r),t.x=i[12],t.y=i[13],t.z=i[14],ar.copy(this);const a=1/r,h=1/n,l=1/o;return ar.elements[0]*=a,ar.elements[1]*=a,ar.elements[2]*=a,ar.elements[4]*=h,ar.elements[5]*=h,ar.elements[6]*=h,ar.elements[8]*=l,ar.elements[9]*=l,ar.elements[10]*=l,e.setFromRotationMatrix(ar),s.x=r,s.y=n,s.z=o,this}makePerspective(t,e,s,i,r,n,o=2e3){const a=this.elements,h=2*r/(e-t),l=2*r/(s-i),c=(e+t)/(e-t),u=(s+i)/(s-i);let d,p;if(o===Os)d=-(n+r)/(n-r),p=-2*n*r/(n-r);else{if(o!==Fs)throw new Error("THREE.Matrix4.makePerspective(): Invalid coordinate system: "+o);d=-n/(n-r),p=-n*r/(n-r)}return a[0]=h,a[4]=0,a[8]=c,a[12]=0,a[1]=0,a[5]=l,a[9]=u,a[13]=0,a[2]=0,a[6]=0,a[10]=d,a[14]=p,a[3]=0,a[7]=0,a[11]=-1,a[15]=0,this}makeOrthographic(t,e,s,i,r,n,o=2e3){const a=this.elements,h=1/(e-t),l=1/(s-i),c=1/(n-r),u=(e+t)*h,d=(s+i)*l;let p,m;if(o===Os)p=(n+r)*c,m=-2*c;else{if(o!==Fs)throw new Error("THREE.Matrix4.makeOrthographic(): Invalid coordinate system: "+o);p=r*c,m=-1*c}return a[0]=2*h,a[4]=0,a[8]=0,a[12]=-u,a[1]=0,a[5]=2*l,a[9]=0,a[13]=-d,a[2]=0,a[6]=0,a[10]=m,a[14]=-p,a[3]=0,a[7]=0,a[11]=0,a[15]=1,this}equals(t){const e=this.elements,s=t.elements;for(let t=0;t<16;t++)if(e[t]!==s[t])return!1;return!0}fromArray(t,e=0){for(let s=0;s<16;s++)this.elements[s]=t[s+e];return this}toArray(t=[],e=0){const s=this.elements;return t[e]=s[0],t[e+1]=s[1],t[e+2]=s[2],t[e+3]=s[3],t[e+4]=s[4],t[e+5]=s[5],t[e+6]=s[6],t[e+7]=s[7],t[e+8]=s[8],t[e+9]=s[9],t[e+10]=s[10],t[e+11]=s[11],t[e+12]=s[12],t[e+13]=s[13],t[e+14]=s[14],t[e+15]=s[15],t}}const or=new Ii,ar=new nr,hr=new Ii(0,0,0),lr=new Ii(1,1,1),cr=new Ii,ur=new Ii,dr=new Ii,pr=new nr,mr=new Ci;class yr{constructor(t=0,e=0,s=0,i=yr.DEFAULT_ORDER){this.isEuler=!0,this._x=t,this._y=e,this._z=s,this._order=i}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get order(){return this._order}set order(t){this._order=t,this._onChangeCallback()}set(t,e,s,i=this._order){return this._x=t,this._y=e,this._z=s,this._order=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(t){return this._x=t._x,this._y=t._y,this._z=t._z,this._order=t._order,this._onChangeCallback(),this}setFromRotationMatrix(t,e=this._order,s=!0){const i=t.elements,r=i[0],n=i[4],o=i[8],a=i[1],h=i[5],l=i[9],c=i[2],u=i[6],d=i[10];switch(e){case"XYZ":this._y=Math.asin(Ds(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-l,d),this._z=Math.atan2(-n,r)):(this._x=Math.atan2(u,h),this._z=0);break;case"YXZ":this._x=Math.asin(-Ds(l,-1,1)),Math.abs(l)<.9999999?(this._y=Math.atan2(o,d),this._z=Math.atan2(a,h)):(this._y=Math.atan2(-c,r),this._z=0);break;case"ZXY":this._x=Math.asin(Ds(u,-1,1)),Math.abs(u)<.9999999?(this._y=Math.atan2(-c,d),this._z=Math.atan2(-n,h)):(this._y=0,this._z=Math.atan2(a,r));break;case"ZYX":this._y=Math.asin(-Ds(c,-1,1)),Math.abs(c)<.9999999?(this._x=Math.atan2(u,d),this._z=Math.atan2(a,r)):(this._x=0,this._z=Math.atan2(-n,h));break;case"YZX":this._z=Math.asin(Ds(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(-l,h),this._y=Math.atan2(-c,r)):(this._x=0,this._y=Math.atan2(o,d));break;case"XZY":this._z=Math.asin(-Ds(n,-1,1)),Math.abs(n)<.9999999?(this._x=Math.atan2(u,h),this._y=Math.atan2(o,r)):(this._x=Math.atan2(-l,d),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+e)}return this._order=e,!0===s&&this._onChangeCallback(),this}setFromQuaternion(t,e,s){return pr.makeRotationFromQuaternion(t),this.setFromRotationMatrix(pr,e,s)}setFromVector3(t,e=this._order){return this.set(t.x,t.y,t.z,e)}reorder(t){return mr.setFromEuler(this),this.setFromQuaternion(mr,t)}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._order===this._order}fromArray(t){return this._x=t[0],this._y=t[1],this._z=t[2],void 0!==t[3]&&(this._order=t[3]),this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._order,t}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._order}}yr.DEFAULT_ORDER="XYZ";class fr{constructor(){this.mask=1}set(t){this.mask=1<>>0}enable(t){this.mask|=1<1){for(let t=0;t1){for(let t=0;t0&&(i.userData=this.userData),i.layers=this.layers.mask,i.matrix=this.matrix.toArray(),i.up=this.up.toArray(),!1===this.matrixAutoUpdate&&(i.matrixAutoUpdate=!1),this.isInstancedMesh&&(i.type="InstancedMesh",i.count=this.count,i.instanceMatrix=this.instanceMatrix.toJSON(),null!==this.instanceColor&&(i.instanceColor=this.instanceColor.toJSON())),this.isBatchedMesh&&(i.type="BatchedMesh",i.perObjectFrustumCulled=this.perObjectFrustumCulled,i.sortObjects=this.sortObjects,i.drawRanges=this._drawRanges,i.reservedRanges=this._reservedRanges,i.visibility=this._visibility,i.active=this._active,i.bounds=this._bounds.map((t=>({boxInitialized:t.boxInitialized,boxMin:t.box.min.toArray(),boxMax:t.box.max.toArray(),sphereInitialized:t.sphereInitialized,sphereRadius:t.sphere.radius,sphereCenter:t.sphere.center.toArray()}))),i.maxInstanceCount=this._maxInstanceCount,i.maxVertexCount=this._maxVertexCount,i.maxIndexCount=this._maxIndexCount,i.geometryInitialized=this._geometryInitialized,i.geometryCount=this._geometryCount,i.matricesTexture=this._matricesTexture.toJSON(t),null!==this._colorsTexture&&(i.colorsTexture=this._colorsTexture.toJSON(t)),null!==this.boundingSphere&&(i.boundingSphere={center:i.boundingSphere.center.toArray(),radius:i.boundingSphere.radius}),null!==this.boundingBox&&(i.boundingBox={min:i.boundingBox.min.toArray(),max:i.boundingBox.max.toArray()})),this.isScene)this.background&&(this.background.isColor?i.background=this.background.toJSON():this.background.isTexture&&(i.background=this.background.toJSON(t).uuid)),this.environment&&this.environment.isTexture&&!0!==this.environment.isRenderTargetTexture&&(i.environment=this.environment.toJSON(t).uuid);else if(this.isMesh||this.isLine||this.isPoints){i.geometry=r(t.geometries,this.geometry);const e=this.geometry.parameters;if(void 0!==e&&void 0!==e.shapes){const s=e.shapes;if(Array.isArray(s))for(let e=0,i=s.length;e0){i.children=[];for(let e=0;e0){i.animations=[];for(let e=0;e0&&(s.geometries=e),i.length>0&&(s.materials=i),r.length>0&&(s.textures=r),o.length>0&&(s.images=o),a.length>0&&(s.shapes=a),h.length>0&&(s.skeletons=h),l.length>0&&(s.animations=l),c.length>0&&(s.nodes=c)}return s.object=i,s;function n(t){const e=[];for(const s in t){const i=t[s];delete i.metadata,e.push(i)}return e}}clone(t){return(new this.constructor).copy(this,t)}copy(t,e=!0){if(this.name=t.name,this.up.copy(t.up),this.position.copy(t.position),this.rotation.order=t.rotation.order,this.quaternion.copy(t.quaternion),this.scale.copy(t.scale),this.matrix.copy(t.matrix),this.matrixWorld.copy(t.matrixWorld),this.matrixAutoUpdate=t.matrixAutoUpdate,this.matrixWorldAutoUpdate=t.matrixWorldAutoUpdate,this.matrixWorldNeedsUpdate=t.matrixWorldNeedsUpdate,this.layers.mask=t.layers.mask,this.visible=t.visible,this.castShadow=t.castShadow,this.receiveShadow=t.receiveShadow,this.frustumCulled=t.frustumCulled,this.renderOrder=t.renderOrder,this.animations=t.animations.slice(),this.userData=JSON.parse(JSON.stringify(t.userData)),!0===e)for(let e=0;e0?i.multiplyScalar(1/Math.sqrt(r)):i.set(0,0,0)}static getBarycoord(t,e,s,i,r){Pr.subVectors(i,e),Rr.subVectors(s,e),Or.subVectors(t,e);const n=Pr.dot(Pr),o=Pr.dot(Rr),a=Pr.dot(Or),h=Rr.dot(Rr),l=Rr.dot(Or),c=n*h-o*o;if(0===c)return r.set(0,0,0),null;const u=1/c,d=(h*a-o*l)*u,p=(n*l-o*a)*u;return r.set(1-d-p,p,d)}static containsPoint(t,e,s,i){return null!==this.getBarycoord(t,e,s,i,Fr)&&(Fr.x>=0&&Fr.y>=0&&Fr.x+Fr.y<=1)}static getInterpolation(t,e,s,i,r,n,o,a){return null===this.getBarycoord(t,e,s,i,Fr)?(a.x=0,a.y=0,"z"in a&&(a.z=0),"w"in a&&(a.w=0),null):(a.setScalar(0),a.addScaledVector(r,Fr.x),a.addScaledVector(n,Fr.y),a.addScaledVector(o,Fr.z),a)}static getInterpolatedAttribute(t,e,s,i,r,n){return Dr.setScalar(0),Hr.setScalar(0),qr.setScalar(0),Dr.fromBufferAttribute(t,e),Hr.fromBufferAttribute(t,s),qr.fromBufferAttribute(t,i),n.setScalar(0),n.addScaledVector(Dr,r.x),n.addScaledVector(Hr,r.y),n.addScaledVector(qr,r.z),n}static isFrontFacing(t,e,s,i){return Pr.subVectors(s,e),Rr.subVectors(t,e),Pr.cross(Rr).dot(i)<0}set(t,e,s){return this.a.copy(t),this.b.copy(e),this.c.copy(s),this}setFromPointsAndIndices(t,e,s,i){return this.a.copy(t[e]),this.b.copy(t[s]),this.c.copy(t[i]),this}setFromAttributeAndIndices(t,e,s,i){return this.a.fromBufferAttribute(t,e),this.b.fromBufferAttribute(t,s),this.c.fromBufferAttribute(t,i),this}clone(){return(new this.constructor).copy(this)}copy(t){return this.a.copy(t.a),this.b.copy(t.b),this.c.copy(t.c),this}getArea(){return Pr.subVectors(this.c,this.b),Rr.subVectors(this.a,this.b),.5*Pr.cross(Rr).length()}getMidpoint(t){return t.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(t){return Jr.getNormal(this.a,this.b,this.c,t)}getPlane(t){return t.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(t,e){return Jr.getBarycoord(t,this.a,this.b,this.c,e)}getInterpolation(t,e,s,i,r){return Jr.getInterpolation(t,this.a,this.b,this.c,e,s,i,r)}containsPoint(t){return Jr.containsPoint(t,this.a,this.b,this.c)}isFrontFacing(t){return Jr.isFrontFacing(this.a,this.b,this.c,t)}intersectsBox(t){return t.intersectsTriangle(this)}closestPointToPoint(t,e){const s=this.a,i=this.b,r=this.c;let n,o;Nr.subVectors(i,s),Lr.subVectors(r,s),Wr.subVectors(t,s);const a=Nr.dot(Wr),h=Lr.dot(Wr);if(a<=0&&h<=0)return e.copy(s);jr.subVectors(t,i);const l=Nr.dot(jr),c=Lr.dot(jr);if(l>=0&&c<=l)return e.copy(i);const u=a*c-l*h;if(u<=0&&a>=0&&l<=0)return n=a/(a-l),e.copy(s).addScaledVector(Nr,n);Ur.subVectors(t,r);const d=Nr.dot(Ur),p=Lr.dot(Ur);if(p>=0&&d<=p)return e.copy(r);const m=d*h-a*p;if(m<=0&&h>=0&&p<=0)return o=h/(h-p),e.copy(s).addScaledVector(Lr,o);const y=l*p-d*c;if(y<=0&&c-l>=0&&d-p>=0)return Vr.subVectors(r,i),o=(c-l)/(c-l+(d-p)),e.copy(i).addScaledVector(Vr,o);const f=1/(y+m+u);return n=m*f,o=u*f,e.copy(s).addScaledVector(Nr,n).addScaledVector(Lr,o)}equals(t){return t.a.equals(this.a)&&t.b.equals(this.b)&&t.c.equals(this.c)}}const Xr={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074},Yr={h:0,s:0,l:0},Zr={h:0,s:0,l:0};function Gr(t,e,s){return s<0&&(s+=1),s>1&&(s-=1),s<1/6?t+6*(e-t)*s:s<.5?e:s<2/3?t+6*(e-t)*(2/3-s):t}class $r{constructor(t,e,s){return this.isColor=!0,this.r=1,this.g=1,this.b=1,this.set(t,e,s)}set(t,e,s){if(void 0===e&&void 0===s){const e=t;e&&e.isColor?this.copy(e):"number"==typeof e?this.setHex(e):"string"==typeof e&&this.setStyle(e)}else this.setRGB(t,e,s);return this}setScalar(t){return this.r=t,this.g=t,this.b=t,this}setHex(t,e=Ge){return t=Math.floor(t),this.r=(t>>16&255)/255,this.g=(t>>8&255)/255,this.b=(255&t)/255,ui.toWorkingColorSpace(this,e),this}setRGB(t,e,s,i=ui.workingColorSpace){return this.r=t,this.g=e,this.b=s,ui.toWorkingColorSpace(this,i),this}setHSL(t,e,s,i=ui.workingColorSpace){if(t=Hs(t,1),e=Ds(e,0,1),s=Ds(s,0,1),0===e)this.r=this.g=this.b=s;else{const i=s<=.5?s*(1+e):s+e-s*e,r=2*s-i;this.r=Gr(r,i,t+1/3),this.g=Gr(r,i,t),this.b=Gr(r,i,t-1/3)}return ui.toWorkingColorSpace(this,i),this}setStyle(t,e=Ge){function s(e){void 0!==e&&parseFloat(e)<1&&console.warn("THREE.Color: Alpha component of "+t+" will be ignored.")}let i;if(i=/^(\w+)\(([^\)]*)\)/.exec(t)){let r;const n=i[1],o=i[2];switch(n){case"rgb":case"rgba":if(r=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return s(r[4]),this.setRGB(Math.min(255,parseInt(r[1],10))/255,Math.min(255,parseInt(r[2],10))/255,Math.min(255,parseInt(r[3],10))/255,e);if(r=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return s(r[4]),this.setRGB(Math.min(100,parseInt(r[1],10))/100,Math.min(100,parseInt(r[2],10))/100,Math.min(100,parseInt(r[3],10))/100,e);break;case"hsl":case"hsla":if(r=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return s(r[4]),this.setHSL(parseFloat(r[1])/360,parseFloat(r[2])/100,parseFloat(r[3])/100,e);break;default:console.warn("THREE.Color: Unknown color model "+t)}}else if(i=/^\#([A-Fa-f\d]+)$/.exec(t)){const s=i[1],r=s.length;if(3===r)return this.setRGB(parseInt(s.charAt(0),16)/15,parseInt(s.charAt(1),16)/15,parseInt(s.charAt(2),16)/15,e);if(6===r)return this.setHex(parseInt(s,16),e);console.warn("THREE.Color: Invalid hex color "+t)}else if(t&&t.length>0)return this.setColorName(t,e);return this}setColorName(t,e=Ge){const s=Xr[t.toLowerCase()];return void 0!==s?this.setHex(s,e):console.warn("THREE.Color: Unknown color "+t),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(t){return this.r=t.r,this.g=t.g,this.b=t.b,this}copySRGBToLinear(t){return this.r=di(t.r),this.g=di(t.g),this.b=di(t.b),this}copyLinearToSRGB(t){return this.r=pi(t.r),this.g=pi(t.g),this.b=pi(t.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(t=Ge){return ui.fromWorkingColorSpace(Qr.copy(this),t),65536*Math.round(Ds(255*Qr.r,0,255))+256*Math.round(Ds(255*Qr.g,0,255))+Math.round(Ds(255*Qr.b,0,255))}getHexString(t=Ge){return("000000"+this.getHex(t).toString(16)).slice(-6)}getHSL(t,e=ui.workingColorSpace){ui.fromWorkingColorSpace(Qr.copy(this),e);const s=Qr.r,i=Qr.g,r=Qr.b,n=Math.max(s,i,r),o=Math.min(s,i,r);let a,h;const l=(o+n)/2;if(o===n)a=0,h=0;else{const t=n-o;switch(h=l<=.5?t/(n+o):t/(2-n-o),n){case s:a=(i-r)/t+(i0!=t>0&&this.version++,this._alphaTest=t}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(t){if(void 0!==t)for(const e in t){const s=t[e];if(void 0===s){console.warn(`THREE.Material: parameter '${e}' has value of undefined.`);continue}const i=this[e];void 0!==i?i&&i.isColor?i.set(s):i&&i.isVector3&&s&&s.isVector3?i.copy(s):this[e]=s:console.warn(`THREE.Material: '${e}' is not a property of THREE.${this.type}.`)}}toJSON(t){const e=void 0===t||"string"==typeof t;e&&(t={textures:{},images:{}});const s={metadata:{version:4.6,type:"Material",generator:"Material.toJSON"}};function i(t){const e=[];for(const s in t){const i=t[s];delete i.metadata,e.push(i)}return e}if(s.uuid=this.uuid,s.type=this.type,""!==this.name&&(s.name=this.name),this.color&&this.color.isColor&&(s.color=this.color.getHex()),void 0!==this.roughness&&(s.roughness=this.roughness),void 0!==this.metalness&&(s.metalness=this.metalness),void 0!==this.sheen&&(s.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(s.sheenColor=this.sheenColor.getHex()),void 0!==this.sheenRoughness&&(s.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(s.emissive=this.emissive.getHex()),void 0!==this.emissiveIntensity&&1!==this.emissiveIntensity&&(s.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(s.specular=this.specular.getHex()),void 0!==this.specularIntensity&&(s.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(s.specularColor=this.specularColor.getHex()),void 0!==this.shininess&&(s.shininess=this.shininess),void 0!==this.clearcoat&&(s.clearcoat=this.clearcoat),void 0!==this.clearcoatRoughness&&(s.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(s.clearcoatMap=this.clearcoatMap.toJSON(t).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(s.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(t).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(s.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(t).uuid,s.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),void 0!==this.dispersion&&(s.dispersion=this.dispersion),void 0!==this.iridescence&&(s.iridescence=this.iridescence),void 0!==this.iridescenceIOR&&(s.iridescenceIOR=this.iridescenceIOR),void 0!==this.iridescenceThicknessRange&&(s.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(s.iridescenceMap=this.iridescenceMap.toJSON(t).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(s.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(t).uuid),void 0!==this.anisotropy&&(s.anisotropy=this.anisotropy),void 0!==this.anisotropyRotation&&(s.anisotropyRotation=this.anisotropyRotation),this.anisotropyMap&&this.anisotropyMap.isTexture&&(s.anisotropyMap=this.anisotropyMap.toJSON(t).uuid),this.map&&this.map.isTexture&&(s.map=this.map.toJSON(t).uuid),this.matcap&&this.matcap.isTexture&&(s.matcap=this.matcap.toJSON(t).uuid),this.alphaMap&&this.alphaMap.isTexture&&(s.alphaMap=this.alphaMap.toJSON(t).uuid),this.lightMap&&this.lightMap.isTexture&&(s.lightMap=this.lightMap.toJSON(t).uuid,s.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(s.aoMap=this.aoMap.toJSON(t).uuid,s.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(s.bumpMap=this.bumpMap.toJSON(t).uuid,s.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(s.normalMap=this.normalMap.toJSON(t).uuid,s.normalMapType=this.normalMapType,s.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(s.displacementMap=this.displacementMap.toJSON(t).uuid,s.displacementScale=this.displacementScale,s.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(s.roughnessMap=this.roughnessMap.toJSON(t).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(s.metalnessMap=this.metalnessMap.toJSON(t).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(s.emissiveMap=this.emissiveMap.toJSON(t).uuid),this.specularMap&&this.specularMap.isTexture&&(s.specularMap=this.specularMap.toJSON(t).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(s.specularIntensityMap=this.specularIntensityMap.toJSON(t).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(s.specularColorMap=this.specularColorMap.toJSON(t).uuid),this.envMap&&this.envMap.isTexture&&(s.envMap=this.envMap.toJSON(t).uuid,void 0!==this.combine&&(s.combine=this.combine)),void 0!==this.envMapRotation&&(s.envMapRotation=this.envMapRotation.toArray()),void 0!==this.envMapIntensity&&(s.envMapIntensity=this.envMapIntensity),void 0!==this.reflectivity&&(s.reflectivity=this.reflectivity),void 0!==this.refractionRatio&&(s.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(s.gradientMap=this.gradientMap.toJSON(t).uuid),void 0!==this.transmission&&(s.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(s.transmissionMap=this.transmissionMap.toJSON(t).uuid),void 0!==this.thickness&&(s.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(s.thicknessMap=this.thicknessMap.toJSON(t).uuid),void 0!==this.attenuationDistance&&this.attenuationDistance!==1/0&&(s.attenuationDistance=this.attenuationDistance),void 0!==this.attenuationColor&&(s.attenuationColor=this.attenuationColor.getHex()),void 0!==this.size&&(s.size=this.size),null!==this.shadowSide&&(s.shadowSide=this.shadowSide),void 0!==this.sizeAttenuation&&(s.sizeAttenuation=this.sizeAttenuation),1!==this.blending&&(s.blending=this.blending),0!==this.side&&(s.side=this.side),!0===this.vertexColors&&(s.vertexColors=!0),this.opacity<1&&(s.opacity=this.opacity),!0===this.transparent&&(s.transparent=!0),204!==this.blendSrc&&(s.blendSrc=this.blendSrc),205!==this.blendDst&&(s.blendDst=this.blendDst),100!==this.blendEquation&&(s.blendEquation=this.blendEquation),null!==this.blendSrcAlpha&&(s.blendSrcAlpha=this.blendSrcAlpha),null!==this.blendDstAlpha&&(s.blendDstAlpha=this.blendDstAlpha),null!==this.blendEquationAlpha&&(s.blendEquationAlpha=this.blendEquationAlpha),this.blendColor&&this.blendColor.isColor&&(s.blendColor=this.blendColor.getHex()),0!==this.blendAlpha&&(s.blendAlpha=this.blendAlpha),3!==this.depthFunc&&(s.depthFunc=this.depthFunc),!1===this.depthTest&&(s.depthTest=this.depthTest),!1===this.depthWrite&&(s.depthWrite=this.depthWrite),!1===this.colorWrite&&(s.colorWrite=this.colorWrite),255!==this.stencilWriteMask&&(s.stencilWriteMask=this.stencilWriteMask),519!==this.stencilFunc&&(s.stencilFunc=this.stencilFunc),0!==this.stencilRef&&(s.stencilRef=this.stencilRef),255!==this.stencilFuncMask&&(s.stencilFuncMask=this.stencilFuncMask),this.stencilFail!==es&&(s.stencilFail=this.stencilFail),this.stencilZFail!==es&&(s.stencilZFail=this.stencilZFail),this.stencilZPass!==es&&(s.stencilZPass=this.stencilZPass),!0===this.stencilWrite&&(s.stencilWrite=this.stencilWrite),void 0!==this.rotation&&0!==this.rotation&&(s.rotation=this.rotation),!0===this.polygonOffset&&(s.polygonOffset=!0),0!==this.polygonOffsetFactor&&(s.polygonOffsetFactor=this.polygonOffsetFactor),0!==this.polygonOffsetUnits&&(s.polygonOffsetUnits=this.polygonOffsetUnits),void 0!==this.linewidth&&1!==this.linewidth&&(s.linewidth=this.linewidth),void 0!==this.dashSize&&(s.dashSize=this.dashSize),void 0!==this.gapSize&&(s.gapSize=this.gapSize),void 0!==this.scale&&(s.scale=this.scale),!0===this.dithering&&(s.dithering=!0),this.alphaTest>0&&(s.alphaTest=this.alphaTest),!0===this.alphaHash&&(s.alphaHash=!0),!0===this.alphaToCoverage&&(s.alphaToCoverage=!0),!0===this.premultipliedAlpha&&(s.premultipliedAlpha=!0),!0===this.forceSinglePass&&(s.forceSinglePass=!0),!0===this.wireframe&&(s.wireframe=!0),this.wireframeLinewidth>1&&(s.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(s.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(s.wireframeLinejoin=this.wireframeLinejoin),!0===this.flatShading&&(s.flatShading=!0),!1===this.visible&&(s.visible=!1),!1===this.toneMapped&&(s.toneMapped=!1),!1===this.fog&&(s.fog=!1),Object.keys(this.userData).length>0&&(s.userData=this.userData),e){const e=i(t.textures),r=i(t.images);e.length>0&&(s.textures=e),r.length>0&&(s.images=r)}return s}clone(){return(new this.constructor).copy(this)}copy(t){this.name=t.name,this.blending=t.blending,this.side=t.side,this.vertexColors=t.vertexColors,this.opacity=t.opacity,this.transparent=t.transparent,this.blendSrc=t.blendSrc,this.blendDst=t.blendDst,this.blendEquation=t.blendEquation,this.blendSrcAlpha=t.blendSrcAlpha,this.blendDstAlpha=t.blendDstAlpha,this.blendEquationAlpha=t.blendEquationAlpha,this.blendColor.copy(t.blendColor),this.blendAlpha=t.blendAlpha,this.depthFunc=t.depthFunc,this.depthTest=t.depthTest,this.depthWrite=t.depthWrite,this.stencilWriteMask=t.stencilWriteMask,this.stencilFunc=t.stencilFunc,this.stencilRef=t.stencilRef,this.stencilFuncMask=t.stencilFuncMask,this.stencilFail=t.stencilFail,this.stencilZFail=t.stencilZFail,this.stencilZPass=t.stencilZPass,this.stencilWrite=t.stencilWrite;const e=t.clippingPlanes;let s=null;if(null!==e){const t=e.length;s=new Array(t);for(let i=0;i!==t;++i)s[i]=e[i].clone()}return this.clippingPlanes=s,this.clipIntersection=t.clipIntersection,this.clipShadows=t.clipShadows,this.shadowSide=t.shadowSide,this.colorWrite=t.colorWrite,this.precision=t.precision,this.polygonOffset=t.polygonOffset,this.polygonOffsetFactor=t.polygonOffsetFactor,this.polygonOffsetUnits=t.polygonOffsetUnits,this.dithering=t.dithering,this.alphaTest=t.alphaTest,this.alphaHash=t.alphaHash,this.alphaToCoverage=t.alphaToCoverage,this.premultipliedAlpha=t.premultipliedAlpha,this.forceSinglePass=t.forceSinglePass,this.visible=t.visible,this.toneMapped=t.toneMapped,this.userData=JSON.parse(JSON.stringify(t.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(t){!0===t&&this.version++}onBuild(){console.warn("Material: onBuild() has been removed.")}}class en extends tn{constructor(t){super(),this.isMeshBasicMaterial=!0,this.type="MeshBasicMaterial",this.color=new $r(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new yr,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.envMapRotation.copy(t.envMapRotation),this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.fog=t.fog,this}}const sn=rn();function rn(){const t=new ArrayBuffer(4),e=new Float32Array(t),s=new Uint32Array(t),i=new Uint32Array(512),r=new Uint32Array(512);for(let t=0;t<256;++t){const e=t-127;e<-27?(i[t]=0,i[256|t]=32768,r[t]=24,r[256|t]=24):e<-14?(i[t]=1024>>-e-14,i[256|t]=1024>>-e-14|32768,r[t]=-e-1,r[256|t]=-e-1):e<=15?(i[t]=e+15<<10,i[256|t]=e+15<<10|32768,r[t]=13,r[256|t]=13):e<128?(i[t]=31744,i[256|t]=64512,r[t]=24,r[256|t]=24):(i[t]=31744,i[256|t]=64512,r[t]=13,r[256|t]=13)}const n=new Uint32Array(2048),o=new Uint32Array(64),a=new Uint32Array(64);for(let t=1;t<1024;++t){let e=t<<13,s=0;for(;!(8388608&e);)e<<=1,s-=8388608;e&=-8388609,s+=947912704,n[t]=e|s}for(let t=1024;t<2048;++t)n[t]=939524096+(t-1024<<13);for(let t=1;t<31;++t)o[t]=t<<23;o[31]=1199570944,o[32]=2147483648;for(let t=33;t<63;++t)o[t]=2147483648+(t-32<<23);o[63]=3347054592;for(let t=1;t<64;++t)32!==t&&(a[t]=1024);return{floatView:e,uint32View:s,baseTable:i,shiftTable:r,mantissaTable:n,exponentTable:o,offsetTable:a}}function nn(t){Math.abs(t)>65504&&console.warn("THREE.DataUtils.toHalfFloat(): Value out of range."),t=Ds(t,-65504,65504),sn.floatView[0]=t;const e=sn.uint32View[0],s=e>>23&511;return sn.baseTable[s]+((8388607&e)>>sn.shiftTable[s])}function on(t){const e=t>>10;return sn.uint32View[0]=sn.mantissaTable[sn.offsetTable[e]+(1023&t)]+sn.exponentTable[e],sn.floatView[0]}const an={toHalfFloat:nn,fromHalfFloat:on},hn=new Ii,ln=new Zs;class cn{constructor(t,e,s=!1){if(Array.isArray(t))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.isBufferAttribute=!0,this.name="",this.array=t,this.itemSize=e,this.count=void 0!==t?t.length/e:0,this.normalized=s,this.usage=_s,this.updateRanges=[],this.gpuType=Et,this.version=0}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}addUpdateRange(t,e){this.updateRanges.push({start:t,count:e})}clearUpdateRanges(){this.updateRanges.length=0}copy(t){return this.name=t.name,this.array=new t.array.constructor(t.array),this.itemSize=t.itemSize,this.count=t.count,this.normalized=t.normalized,this.usage=t.usage,this.gpuType=t.gpuType,this}copyAt(t,e,s){t*=this.itemSize,s*=e.itemSize;for(let i=0,r=this.itemSize;ie.count&&console.warn("THREE.BufferGeometry: Buffer size too small for points data. Use .dispose() and create a new geometry."),e.needsUpdate=!0}return this}computeBoundingBox(){null===this.boundingBox&&(this.boundingBox=new Ei);const t=this.attributes.position,e=this.morphAttributes.position;if(t&&t.isGLBufferAttribute)return console.error("THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box.",this),void this.boundingBox.set(new Ii(-1/0,-1/0,-1/0),new Ii(1/0,1/0,1/0));if(void 0!==t){if(this.boundingBox.setFromBufferAttribute(t),e)for(let t=0,s=e.length;t0&&(t.userData=this.userData),void 0!==this.parameters){const e=this.parameters;for(const s in e)void 0!==e[s]&&(t[s]=e[s]);return t}t.data={attributes:{}};const e=this.index;null!==e&&(t.data.index={type:e.array.constructor.name,array:Array.prototype.slice.call(e.array)});const s=this.attributes;for(const e in s){const i=s[e];t.data.attributes[e]=i.toJSON(t.data)}const i={};let r=!1;for(const e in this.morphAttributes){const s=this.morphAttributes[e],n=[];for(let e=0,i=s.length;e0&&(i[e]=n,r=!0)}r&&(t.data.morphAttributes=i,t.data.morphTargetsRelative=this.morphTargetsRelative);const n=this.groups;n.length>0&&(t.data.groups=JSON.parse(JSON.stringify(n)));const o=this.boundingSphere;return null!==o&&(t.data.boundingSphere={center:o.center.toArray(),radius:o.radius}),t}clone(){return(new this.constructor).copy(this)}copy(t){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;const e={};this.name=t.name;const s=t.index;null!==s&&this.setIndex(s.clone(e));const i=t.attributes;for(const t in i){const s=i[t];this.setAttribute(t,s.clone(e))}const r=t.morphAttributes;for(const t in r){const s=[],i=r[t];for(let t=0,r=i.length;t0){const s=t[e[0]];if(void 0!==s){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=s.length;t(t.far-t.near)**2)return}Cn.copy(r).invert(),In.copy(t.ray).applyMatrix4(Cn),null!==s.boundingBox&&!1===In.intersectsBox(s.boundingBox)||this._computeIntersections(t,e,In)}}_computeIntersections(t,e,s){let i;const r=this.geometry,n=this.material,o=r.index,a=r.attributes.position,h=r.attributes.uv,l=r.attributes.uv1,c=r.attributes.normal,u=r.groups,d=r.drawRange;if(null!==o)if(Array.isArray(n))for(let r=0,a=u.length;rs.far?null:{distance:l,point:Ln.clone(),object:t}}(t,e,s,i,En,Pn,Rn,Nn);if(c){const t=new Ii;Jr.getBarycoord(Nn,En,Pn,Rn,t),r&&(c.uv=Jr.getInterpolatedAttribute(r,a,h,l,t,new Zs)),n&&(c.uv1=Jr.getInterpolatedAttribute(n,a,h,l,t,new Zs)),o&&(c.normal=Jr.getInterpolatedAttribute(o,a,h,l,t,new Ii),c.normal.dot(i.direction)>0&&c.normal.multiplyScalar(-1));const e={a:a,b:h,c:l,normal:new Ii,materialIndex:0};Jr.getNormal(En,Pn,Rn,e.normal),c.face=e,c.barycoord=t}return c}class jn extends zn{constructor(t=1,e=1,s=1,i=1,r=1,n=1){super(),this.type="BoxGeometry",this.parameters={width:t,height:e,depth:s,widthSegments:i,heightSegments:r,depthSegments:n};const o=this;i=Math.floor(i),r=Math.floor(r),n=Math.floor(n);const a=[],h=[],l=[],c=[];let u=0,d=0;function p(t,e,s,i,r,n,p,m,y,f,g){const x=n/y,b=p/f,v=n/2,w=p/2,M=m/2,S=y+1,_=f+1;let A=0,T=0;const z=new Ii;for(let n=0;n<_;n++){const o=n*b-w;for(let a=0;a0?1:-1,l.push(z.x,z.y,z.z),c.push(a/y),c.push(1-n/f),A+=1}}for(let t=0;t0&&(e.defines=this.defines),e.vertexShader=this.vertexShader,e.fragmentShader=this.fragmentShader,e.lights=this.lights,e.clipping=this.clipping;const s={};for(const t in this.extensions)!0===this.extensions[t]&&(s[t]=!0);return Object.keys(s).length>0&&(e.extensions=s),e}}class Xn extends Er{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new nr,this.projectionMatrix=new nr,this.projectionMatrixInverse=new nr,this.coordinateSystem=Os}copy(t,e){return super.copy(t,e),this.matrixWorldInverse.copy(t.matrixWorldInverse),this.projectionMatrix.copy(t.projectionMatrix),this.projectionMatrixInverse.copy(t.projectionMatrixInverse),this.coordinateSystem=t.coordinateSystem,this}getWorldDirection(t){return super.getWorldDirection(t).negate()}updateMatrixWorld(t){super.updateMatrixWorld(t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(t,e){super.updateWorldMatrix(t,e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return(new this.constructor).copy(this)}}const Yn=new Ii,Zn=new Zs,Gn=new Zs;class $n extends Xn{constructor(t=50,e=1,s=.1,i=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=t,this.zoom=1,this.near=s,this.far=i,this.focus=10,this.aspect=e,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.fov=t.fov,this.zoom=t.zoom,this.near=t.near,this.far=t.far,this.focus=t.focus,this.aspect=t.aspect,this.view=null===t.view?null:Object.assign({},t.view),this.filmGauge=t.filmGauge,this.filmOffset=t.filmOffset,this}setFocalLength(t){const e=.5*this.getFilmHeight()/t;this.fov=2*js*Math.atan(e),this.updateProjectionMatrix()}getFocalLength(){const t=Math.tan(.5*Ws*this.fov);return.5*this.getFilmHeight()/t}getEffectiveFOV(){return 2*js*Math.atan(Math.tan(.5*Ws*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}getViewBounds(t,e,s){Yn.set(-1,-1,.5).applyMatrix4(this.projectionMatrixInverse),e.set(Yn.x,Yn.y).multiplyScalar(-t/Yn.z),Yn.set(1,1,.5).applyMatrix4(this.projectionMatrixInverse),s.set(Yn.x,Yn.y).multiplyScalar(-t/Yn.z)}getViewSize(t,e){return this.getViewBounds(t,Zn,Gn),e.subVectors(Gn,Zn)}setViewOffset(t,e,s,i,r,n){this.aspect=t/e,null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=s,this.view.offsetY=i,this.view.width=r,this.view.height=n,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=this.near;let e=t*Math.tan(.5*Ws*this.fov)/this.zoom,s=2*e,i=this.aspect*s,r=-.5*i;const n=this.view;if(null!==this.view&&this.view.enabled){const t=n.fullWidth,o=n.fullHeight;r+=n.offsetX*i/t,e-=n.offsetY*s/o,i*=n.width/t,s*=n.height/o}const o=this.filmOffset;0!==o&&(r+=t*o/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+i,e,e-s,t,this.far,this.coordinateSystem),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.fov=this.fov,e.object.zoom=this.zoom,e.object.near=this.near,e.object.far=this.far,e.object.focus=this.focus,e.object.aspect=this.aspect,null!==this.view&&(e.object.view=Object.assign({},this.view)),e.object.filmGauge=this.filmGauge,e.object.filmOffset=this.filmOffset,e}}const Qn=-90;class Kn extends Er{constructor(t,e,s){super(),this.type="CubeCamera",this.renderTarget=s,this.coordinateSystem=null,this.activeMipmapLevel=0;const i=new $n(Qn,1,t,e);i.layers=this.layers,this.add(i);const r=new $n(Qn,1,t,e);r.layers=this.layers,this.add(r);const n=new $n(Qn,1,t,e);n.layers=this.layers,this.add(n);const o=new $n(Qn,1,t,e);o.layers=this.layers,this.add(o);const a=new $n(Qn,1,t,e);a.layers=this.layers,this.add(a);const h=new $n(Qn,1,t,e);h.layers=this.layers,this.add(h)}updateCoordinateSystem(){const t=this.coordinateSystem,e=this.children.concat(),[s,i,r,n,o,a]=e;for(const t of e)this.remove(t);if(t===Os)s.up.set(0,1,0),s.lookAt(1,0,0),i.up.set(0,1,0),i.lookAt(-1,0,0),r.up.set(0,0,-1),r.lookAt(0,1,0),n.up.set(0,0,1),n.lookAt(0,-1,0),o.up.set(0,1,0),o.lookAt(0,0,1),a.up.set(0,1,0),a.lookAt(0,0,-1);else{if(t!==Fs)throw new Error("THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: "+t);s.up.set(0,-1,0),s.lookAt(-1,0,0),i.up.set(0,-1,0),i.lookAt(1,0,0),r.up.set(0,0,1),r.lookAt(0,1,0),n.up.set(0,0,-1),n.lookAt(0,-1,0),o.up.set(0,-1,0),o.lookAt(0,0,1),a.up.set(0,-1,0),a.lookAt(0,0,-1)}for(const t of e)this.add(t),t.updateMatrixWorld()}update(t,e){null===this.parent&&this.updateMatrixWorld();const{renderTarget:s,activeMipmapLevel:i}=this;this.coordinateSystem!==t.coordinateSystem&&(this.coordinateSystem=t.coordinateSystem,this.updateCoordinateSystem());const[r,n,o,a,h,l]=this.children,c=t.getRenderTarget(),u=t.getActiveCubeFace(),d=t.getActiveMipmapLevel(),p=t.xr.enabled;t.xr.enabled=!1;const m=s.texture.generateMipmaps;s.texture.generateMipmaps=!1,t.setRenderTarget(s,0,i),t.render(e,r),t.setRenderTarget(s,1,i),t.render(e,n),t.setRenderTarget(s,2,i),t.render(e,o),t.setRenderTarget(s,3,i),t.render(e,a),t.setRenderTarget(s,4,i),t.render(e,h),s.texture.generateMipmaps=m,t.setRenderTarget(s,5,i),t.render(e,l),t.setRenderTarget(c,u,d),t.xr.enabled=p,s.texture.needsPMREMUpdate=!0}}class to extends vi{constructor(t,e,s,i,r,n,o,a,h,l){super(t=void 0!==t?t:[],e=void 0!==e?e:ht,s,i,r,n,o,a,h,l),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(t){this.image=t}}class eo extends Si{constructor(t=1,e={}){super(t,t,e),this.isWebGLCubeRenderTarget=!0;const s={width:t,height:t,depth:1},i=[s,s,s,s,s,s];this.texture=new to(i,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.colorSpace),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=void 0!==e.generateMipmaps&&e.generateMipmaps,this.texture.minFilter=void 0!==e.minFilter?e.minFilter:wt}fromEquirectangularTexture(t,e){this.texture.type=e.type,this.texture.colorSpace=e.colorSpace,this.texture.generateMipmaps=e.generateMipmaps,this.texture.minFilter=e.minFilter,this.texture.magFilter=e.magFilter;const s={uniforms:{tEquirect:{value:null}},vertexShader:"\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\tvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\n\t\t\t\t\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n\n\t\t\t\t}\n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvWorldDirection = transformDirection( position, modelMatrix );\n\n\t\t\t\t\t#include \n\t\t\t\t\t#include \n\n\t\t\t\t}\n\t\t\t",fragmentShader:"\n\n\t\t\t\tuniform sampler2D tEquirect;\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\t#include \n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvec3 direction = normalize( vWorldDirection );\n\n\t\t\t\t\tvec2 sampleUV = equirectUv( direction );\n\n\t\t\t\t\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\n\t\t\t\t}\n\t\t\t"},i=new jn(5,5,5),r=new Jn({name:"CubemapFromEquirect",uniforms:Un(s.uniforms),vertexShader:s.vertexShader,fragmentShader:s.fragmentShader,side:1,blending:0});r.uniforms.tEquirect.value=e;const n=new Vn(i,r),o=e.minFilter;e.minFilter===_t&&(e.minFilter=wt);return new Kn(1,10,this).update(t,n),e.minFilter=o,n.geometry.dispose(),n.material.dispose(),this}clear(t,e,s,i){const r=t.getRenderTarget();for(let r=0;r<6;r++)t.setRenderTarget(this,r),t.clear(e,s,i);t.setRenderTarget(r)}}class so{constructor(t,e=25e-5){this.isFogExp2=!0,this.name="",this.color=new $r(t),this.density=e}clone(){return new so(this.color,this.density)}toJSON(){return{type:"FogExp2",name:this.name,color:this.color.getHex(),density:this.density}}}class io{constructor(t,e=1,s=1e3){this.isFog=!0,this.name="",this.color=new $r(t),this.near=e,this.far=s}clone(){return new io(this.color,this.near,this.far)}toJSON(){return{type:"Fog",name:this.name,color:this.color.getHex(),near:this.near,far:this.far}}}class ro extends Er{constructor(){super(),this.isScene=!0,this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.backgroundRotation=new yr,this.environmentIntensity=1,this.environmentRotation=new yr,this.overrideMaterial=null,"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}copy(t,e){return super.copy(t,e),null!==t.background&&(this.background=t.background.clone()),null!==t.environment&&(this.environment=t.environment.clone()),null!==t.fog&&(this.fog=t.fog.clone()),this.backgroundBlurriness=t.backgroundBlurriness,this.backgroundIntensity=t.backgroundIntensity,this.backgroundRotation.copy(t.backgroundRotation),this.environmentIntensity=t.environmentIntensity,this.environmentRotation.copy(t.environmentRotation),null!==t.overrideMaterial&&(this.overrideMaterial=t.overrideMaterial.clone()),this.matrixAutoUpdate=t.matrixAutoUpdate,this}toJSON(t){const e=super.toJSON(t);return null!==this.fog&&(e.object.fog=this.fog.toJSON()),this.backgroundBlurriness>0&&(e.object.backgroundBlurriness=this.backgroundBlurriness),1!==this.backgroundIntensity&&(e.object.backgroundIntensity=this.backgroundIntensity),e.object.backgroundRotation=this.backgroundRotation.toArray(),1!==this.environmentIntensity&&(e.object.environmentIntensity=this.environmentIntensity),e.object.environmentRotation=this.environmentRotation.toArray(),e}}class no{constructor(t,e){this.isInterleavedBuffer=!0,this.array=t,this.stride=e,this.count=void 0!==t?t.length/e:0,this.usage=_s,this.updateRanges=[],this.version=0,this.uuid=Us()}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}addUpdateRange(t,e){this.updateRanges.push({start:t,count:e})}clearUpdateRanges(){this.updateRanges.length=0}copy(t){return this.array=new t.array.constructor(t.array),this.count=t.count,this.stride=t.stride,this.usage=t.usage,this}copyAt(t,e,s){t*=this.stride,s*=e.stride;for(let i=0,r=this.stride;it.far||e.push({distance:a,point:co.clone(),uv:Jr.getInterpolation(co,go,xo,bo,vo,wo,Mo,new Zs),face:null,object:this})}copy(t,e){return super.copy(t,e),void 0!==t.center&&this.center.copy(t.center),this.material=t.material,this}}function _o(t,e,s,i,r,n){mo.subVectors(t,s).addScalar(.5).multiply(i),void 0!==r?(yo.x=n*mo.x-r*mo.y,yo.y=r*mo.x+n*mo.y):yo.copy(mo),t.copy(e),t.x+=yo.x,t.y+=yo.y,t.applyMatrix4(fo)}const Ao=new Ii,To=new Ii;class zo extends Er{constructor(){super(),this._currentLevel=0,this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]},isLOD:{value:!0}}),this.autoUpdate=!0}copy(t){super.copy(t,!1);const e=t.levels;for(let t=0,s=e.length;t0){let s,i;for(s=1,i=e.length;s0){Ao.setFromMatrixPosition(this.matrixWorld);const s=t.ray.origin.distanceTo(Ao);this.getObjectForDistance(s).raycast(t,e)}}update(t){const e=this.levels;if(e.length>1){Ao.setFromMatrixPosition(t.matrixWorld),To.setFromMatrixPosition(this.matrixWorld);const s=Ao.distanceTo(To)/t.zoom;let i,r;for(e[0].object.visible=!0,i=1,r=e.length;i=t))break;e[i-1].object.visible=!1,e[i].object.visible=!0}for(this._currentLevel=i-1;i1?null:e.copy(t.start).addScaledVector(s,r)}intersectsLine(t){const e=this.distanceToPoint(t.start),s=this.distanceToPoint(t.end);return e<0&&s>0||s<0&&e>0}intersectsBox(t){return t.intersectsPlane(this)}intersectsSphere(t){return t.intersectsPlane(this)}coplanarPoint(t){return t.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(t,e){const s=e||ta.getNormalMatrix(t),i=this.coplanarPoint(Qo).applyMatrix4(t),r=this.normal.applyMatrix3(s).normalize();return this.constant=-i.dot(r),this}translate(t){return this.constant-=t.dot(this.normal),this}equals(t){return t.normal.equals(this.normal)&&t.constant===this.constant}clone(){return(new this.constructor).copy(this)}}const sa=new Gi,ia=new Ii;class ra{constructor(t=new ea,e=new ea,s=new ea,i=new ea,r=new ea,n=new ea){this.planes=[t,e,s,i,r,n]}set(t,e,s,i,r,n){const o=this.planes;return o[0].copy(t),o[1].copy(e),o[2].copy(s),o[3].copy(i),o[4].copy(r),o[5].copy(n),this}copy(t){const e=this.planes;for(let s=0;s<6;s++)e[s].copy(t.planes[s]);return this}setFromProjectionMatrix(t,e=2e3){const s=this.planes,i=t.elements,r=i[0],n=i[1],o=i[2],a=i[3],h=i[4],l=i[5],c=i[6],u=i[7],d=i[8],p=i[9],m=i[10],y=i[11],f=i[12],g=i[13],x=i[14],b=i[15];if(s[0].setComponents(a-r,u-h,y-d,b-f).normalize(),s[1].setComponents(a+r,u+h,y+d,b+f).normalize(),s[2].setComponents(a+n,u+l,y+p,b+g).normalize(),s[3].setComponents(a-n,u-l,y-p,b-g).normalize(),s[4].setComponents(a-o,u-c,y-m,b-x).normalize(),e===Os)s[5].setComponents(a+o,u+c,y+m,b+x).normalize();else{if(e!==Fs)throw new Error("THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: "+e);s[5].setComponents(o,c,m,x).normalize()}return this}intersectsObject(t){if(void 0!==t.boundingSphere)null===t.boundingSphere&&t.computeBoundingSphere(),sa.copy(t.boundingSphere).applyMatrix4(t.matrixWorld);else{const e=t.geometry;null===e.boundingSphere&&e.computeBoundingSphere(),sa.copy(e.boundingSphere).applyMatrix4(t.matrixWorld)}return this.intersectsSphere(sa)}intersectsSprite(t){return sa.center.set(0,0,0),sa.radius=.7071067811865476,sa.applyMatrix4(t.matrixWorld),this.intersectsSphere(sa)}intersectsSphere(t){const e=this.planes,s=t.center,i=-t.radius;for(let t=0;t<6;t++){if(e[t].distanceToPoint(s)0?t.max.x:t.min.x,ia.y=i.normal.y>0?t.max.y:t.min.y,ia.z=i.normal.z>0?t.max.z:t.min.z,i.distanceToPoint(ia)<0)return!1}return!0}containsPoint(t){const e=this.planes;for(let s=0;s<6;s++)if(e[s].distanceToPoint(t)<0)return!1;return!0}clone(){return(new this.constructor).copy(this)}}function na(t,e){return t-e}function oa(t,e){return t.z-e.z}function aa(t,e){return e.z-t.z}class ha{constructor(){this.index=0,this.pool=[],this.list=[]}push(t,e,s,i){const r=this.pool,n=this.list;this.index>=r.length&&r.push({start:-1,count:-1,z:-1,index:-1});const o=r[this.index];n.push(o),this.index++,o.start=t,o.count=e,o.z=s,o.index=i}reset(){this.list.length=0,this.index=0}}const la=new nr,ca=new $r(1,1,1),ua=new ra,da=new Ei,pa=new Gi,ma=new Ii,ya=new Ii,fa=new Ii,ga=new ha,xa=new Vn,ba=[];function va(t,e,s=0){const i=e.itemSize;if(t.isInterleavedBufferAttribute||t.array.constructor!==e.array.constructor){const r=t.count;for(let n=0;n65535?new Uint32Array(i):new Uint16Array(i);e.setIndex(new cn(t,1))}this._geometryInitialized=!0}}_validateGeometry(t){const e=this.geometry;if(Boolean(t.getIndex())!==Boolean(e.getIndex()))throw new Error('THREE.BatchedMesh: All geometries must consistently have "index".');for(const s in e.attributes){if(!t.hasAttribute(s))throw new Error(`THREE.BatchedMesh: Added geometry missing "${s}". All geometries must have consistent attributes.`);const i=t.getAttribute(s),r=e.getAttribute(s);if(i.itemSize!==r.itemSize||i.normalized!==r.normalized)throw new Error("THREE.BatchedMesh: All attributes must have a consistent itemSize and normalized value.")}}validateInstanceId(t){const e=this._instanceInfo;if(t<0||t>=e.length||!1===e[t].active)throw new Error(`THREE.BatchedMesh: Invalid instanceId ${t}. Instance is either out of range or has been deleted.`)}validateGeometryId(t){const e=this._geometryInfo;if(t<0||t>=e.length||!1===e[t].active)throw new Error(`THREE.BatchedMesh: Invalid geometryId ${t}. Geometry is either out of range or has been deleted.`)}setCustomSort(t){return this.customSort=t,this}computeBoundingBox(){null===this.boundingBox&&(this.boundingBox=new Ei);const t=this.boundingBox,e=this._instanceInfo;t.makeEmpty();for(let s=0,i=e.length;s=this.maxInstanceCount&&0===this._availableInstanceIds.length)throw new Error("THREE.BatchedMesh: Maximum item count reached.");const e={visible:!0,active:!0,geometryIndex:t};let s=null;this._availableInstanceIds.length>0?(this._availableInstanceIds.sort(na),s=this._availableInstanceIds.shift(),this._instanceInfo[s]=e):(s=this._instanceInfo.length,this._instanceInfo.push(e));const i=this._matricesTexture;la.identity().toArray(i.image.data,16*s),i.needsUpdate=!0;const r=this._colorsTexture;return r&&(ca.toArray(r.image.data,4*s),r.needsUpdate=!0),this._visibilityChanged=!0,s}addGeometry(t,e=-1,s=-1){this._initializeGeometry(t),this._validateGeometry(t);const i={vertexStart:-1,vertexCount:-1,reservedVertexCount:-1,indexStart:-1,indexCount:-1,reservedIndexCount:-1,start:-1,count:-1,boundingBox:null,boundingSphere:null,active:!0},r=this._geometryInfo;i.vertexStart=this._nextVertexStart,i.reservedVertexCount=-1===e?t.getAttribute("position").count:e;const n=t.getIndex();if(null!==n&&(i.indexStart=this._nextIndexStart,i.reservedIndexCount=-1===s?n.count:s),-1!==i.indexStart&&i.indexStart+i.reservedIndexCount>this._maxIndexCount||i.vertexStart+i.reservedVertexCount>this._maxVertexCount)throw new Error("THREE.BatchedMesh: Reserved space request exceeds the maximum buffer size.");let o;return this._availableGeometryIds.length>0?(this._availableGeometryIds.sort(na),o=this._availableGeometryIds.shift(),r[o]=i):(o=this._geometryCount,this._geometryCount++,r.push(i)),this.setGeometryAt(o,t),this._nextIndexStart=i.indexStart+i.reservedIndexCount,this._nextVertexStart=i.vertexStart+i.reservedVertexCount,o}setGeometryAt(t,e){if(t>=this._geometryCount)throw new Error("THREE.BatchedMesh: Maximum geometry count reached.");this._validateGeometry(e);const s=this.geometry,i=null!==s.getIndex(),r=s.getIndex(),n=e.getIndex(),o=this._geometryInfo[t];if(i&&n.count>o.reservedIndexCount||e.attributes.position.count>o.reservedVertexCount)throw new Error("THREE.BatchedMesh: Reserved space not large enough for provided geometry.");const a=o.vertexStart,h=o.reservedVertexCount;o.vertexCount=e.getAttribute("position").count;for(const t in s.attributes){const i=e.getAttribute(t),r=s.getAttribute(t);va(i,r,a);const n=i.itemSize;for(let t=i.count,e=h;t=e.length||!1===e[t].active)return this;const s=this._instanceInfo;for(let e=0,i=s.length;ee)).sort(((t,e)=>s[t].vertexStart-s[e].vertexStart)),r=this.geometry;for(let n=0,o=s.length;n=this._geometryCount)return null;const s=this.geometry,i=this._geometryInfo[t];if(null===i.boundingBox){const t=new Ei,e=s.index,r=s.attributes.position;for(let s=i.start,n=i.start+i.count;s=this._geometryCount)return null;const s=this.geometry,i=this._geometryInfo[t];if(null===i.boundingSphere){const e=new Gi;this.getBoundingBoxAt(t,da),da.getCenter(e.center);const r=s.index,n=s.attributes.position;let o=0;for(let t=i.start,s=i.start+i.count;tt.active));if(Math.max(...s.map((t=>t.vertexStart+t.reservedVertexCount)))>t)throw new Error(`BatchedMesh: Geometry vertex values are being used outside the range ${e}. Cannot shrink further.`);if(this.geometry.index){if(Math.max(...s.map((t=>t.indexStart+t.reservedIndexCount)))>e)throw new Error(`BatchedMesh: Geometry index values are being used outside the range ${e}. Cannot shrink further.`)}const i=this.geometry;i.dispose(),this._maxVertexCount=t,this._maxIndexCount=e,this._geometryInitialized&&(this._geometryInitialized=!1,this.geometry=new zn,this._initializeGeometry(i));const r=this.geometry;i.index&&wa(i.index.array,r.index.array);for(const t in i.attributes)wa(i.attributes[t].array,r.attributes[t].array)}raycast(t,e){const s=this._instanceInfo,i=this._geometryInfo,r=this.matrixWorld,n=this.geometry;xa.material=this.material,xa.geometry.index=n.index,xa.geometry.attributes=n.attributes,null===xa.geometry.boundingBox&&(xa.geometry.boundingBox=new Ei),null===xa.geometry.boundingSphere&&(xa.geometry.boundingSphere=new Gi);for(let n=0,o=s.length;n({...t,boundingBox:null!==t.boundingBox?t.boundingBox.clone():null,boundingSphere:null!==t.boundingSphere?t.boundingSphere.clone():null}))),this._instanceInfo=t._instanceInfo.map((t=>({...t}))),this._maxInstanceCount=t._maxInstanceCount,this._maxVertexCount=t._maxVertexCount,this._maxIndexCount=t._maxIndexCount,this._geometryInitialized=t._geometryInitialized,this._geometryCount=t._geometryCount,this._multiDrawCounts=t._multiDrawCounts.slice(),this._multiDrawStarts=t._multiDrawStarts.slice(),this._matricesTexture=t._matricesTexture.clone(),this._matricesTexture.image.data=this._matricesTexture.image.data.slice(),null!==this._colorsTexture&&(this._colorsTexture=t._colorsTexture.clone(),this._colorsTexture.image.data=this._colorsTexture.image.data.slice()),this}dispose(){return this.geometry.dispose(),this._matricesTexture.dispose(),this._matricesTexture=null,this._indirectTexture.dispose(),this._indirectTexture=null,null!==this._colorsTexture&&(this._colorsTexture.dispose(),this._colorsTexture=null),this}onBeforeRender(t,e,s,i,r){if(!this._visibilityChanged&&!this.perObjectFrustumCulled&&!this.sortObjects)return;const n=i.getIndex(),o=null===n?1:n.array.BYTES_PER_ELEMENT,a=this._instanceInfo,h=this._multiDrawStarts,l=this._multiDrawCounts,c=this._geometryInfo,u=this.perObjectFrustumCulled,d=this._indirectTexture,p=d.image.data;u&&(la.multiplyMatrices(s.projectionMatrix,s.matrixWorldInverse).multiply(this.matrixWorld),ua.setFromProjectionMatrix(la,t.coordinateSystem));let m=0;if(this.sortObjects){la.copy(this.matrixWorld).invert(),ma.setFromMatrixPosition(s.matrixWorld).applyMatrix4(la),ya.set(0,0,-1).transformDirection(s.matrixWorld).transformDirection(la);for(let t=0,e=a.length;t0){const s=t[e[0]];if(void 0!==s){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=s.length;ti)return;Ia.applyMatrix4(t.matrixWorld);const a=e.ray.origin.distanceTo(Ia);return ae.far?void 0:{distance:a,point:Ba.clone().applyMatrix4(t.matrixWorld),index:r,face:null,faceIndex:null,barycoord:null,object:t}}const Pa=new Ii,Ra=new Ii;class Oa extends ka{constructor(t,e){super(t,e),this.isLineSegments=!0,this.type="LineSegments"}computeLineDistances(){const t=this.geometry;if(null===t.index){const e=t.attributes.position,s=[];for(let t=0,i=e.count;t0){const s=t[e[0]];if(void 0!==s){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=s.length;tr.far)return;n.push({distance:h,distanceToRay:Math.sqrt(a),point:s,index:e,face:null,faceIndex:null,barycoord:null,object:o})}}class Ha extends Er{constructor(){super(),this.isGroup=!0,this.type="Group"}}class qa extends vi{constructor(t,e,s,i,r,n,o,a,h){super(t,e,s,i,r,n,o,a,h),this.isVideoTexture=!0,this.minFilter=void 0!==n?n:wt,this.magFilter=void 0!==r?r:wt,this.generateMipmaps=!1;const l=this;"requestVideoFrameCallback"in t&&t.requestVideoFrameCallback((function e(){l.needsUpdate=!0,t.requestVideoFrameCallback(e)}))}clone(){return new this.constructor(this.image).copy(this)}update(){const t=this.image;!1==="requestVideoFrameCallback"in t&&t.readyState>=t.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}}class Ja extends vi{constructor(t,e){super({width:t,height:e}),this.isFramebufferTexture=!0,this.magFilter=ft,this.minFilter=ft,this.generateMipmaps=!1,this.needsUpdate=!0}}class Xa extends vi{constructor(t,e,s,i,r,n,o,a,h,l,c,u){super(null,n,o,a,h,l,i,r,c,u),this.isCompressedTexture=!0,this.image={width:e,height:s},this.mipmaps=t,this.flipY=!1,this.generateMipmaps=!1}}class Ya extends Xa{constructor(t,e,s,i,r,n){super(t,e,s,r,n),this.isCompressedArrayTexture=!0,this.image.depth=i,this.wrapR=mt,this.layerUpdates=new Set}addLayerUpdate(t){this.layerUpdates.add(t)}clearLayerUpdates(){this.layerUpdates.clear()}}class Za extends Xa{constructor(t,e,s){super(void 0,t[0].width,t[0].height,e,s,ht),this.isCompressedCubeTexture=!0,this.isCubeTexture=!0,this.image=t}}class Ga extends vi{constructor(t,e,s,i,r,n,o,a,h){super(t,e,s,i,r,n,o,a,h),this.isCanvasTexture=!0,this.needsUpdate=!0}}class $a extends vi{constructor(t,e,s,i,r,n,o,a,h,l=1026){if(l!==Dt&&l!==Ht)throw new Error("DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat");void 0===s&&l===Dt&&(s=kt),void 0===s&&l===Ht&&(s=1020),super(null,i,r,n,o,a,l,s,h),this.isDepthTexture=!0,this.image={width:t,height:e},this.magFilter=void 0!==o?o:ft,this.minFilter=void 0!==a?a:ft,this.flipY=!1,this.generateMipmaps=!1,this.compareFunction=null}copy(t){return super.copy(t),this.compareFunction=t.compareFunction,this}toJSON(t){const e=super.toJSON(t);return null!==this.compareFunction&&(e.compareFunction=this.compareFunction),e}}class Qa{constructor(){this.type="Curve",this.arcLengthDivisions=200}getPoint(){return console.warn("THREE.Curve: .getPoint() not implemented."),null}getPointAt(t,e){const s=this.getUtoTmapping(t);return this.getPoint(s,e)}getPoints(t=5){const e=[];for(let s=0;s<=t;s++)e.push(this.getPoint(s/t));return e}getSpacedPoints(t=5){const e=[];for(let s=0;s<=t;s++)e.push(this.getPointAt(s/t));return e}getLength(){const t=this.getLengths();return t[t.length-1]}getLengths(t=this.arcLengthDivisions){if(this.cacheArcLengths&&this.cacheArcLengths.length===t+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;const e=[];let s,i=this.getPoint(0),r=0;e.push(0);for(let n=1;n<=t;n++)s=this.getPoint(n/t),r+=s.distanceTo(i),e.push(r),i=s;return this.cacheArcLengths=e,e}updateArcLengths(){this.needsUpdate=!0,this.getLengths()}getUtoTmapping(t,e){const s=this.getLengths();let i=0;const r=s.length;let n;n=e||t*s[r-1];let o,a=0,h=r-1;for(;a<=h;)if(i=Math.floor(a+(h-a)/2),o=s[i]-n,o<0)a=i+1;else{if(!(o>0)){h=i;break}h=i-1}if(i=h,s[i]===n)return i/(r-1);const l=s[i];return(i+(n-l)/(s[i+1]-l))/(r-1)}getTangent(t,e){const s=1e-4;let i=t-s,r=t+s;i<0&&(i=0),r>1&&(r=1);const n=this.getPoint(i),o=this.getPoint(r),a=e||(n.isVector2?new Zs:new Ii);return a.copy(o).sub(n).normalize(),a}getTangentAt(t,e){const s=this.getUtoTmapping(t);return this.getTangent(s,e)}computeFrenetFrames(t,e){const s=new Ii,i=[],r=[],n=[],o=new Ii,a=new nr;for(let e=0;e<=t;e++){const s=e/t;i[e]=this.getTangentAt(s,new Ii)}r[0]=new Ii,n[0]=new Ii;let h=Number.MAX_VALUE;const l=Math.abs(i[0].x),c=Math.abs(i[0].y),u=Math.abs(i[0].z);l<=h&&(h=l,s.set(1,0,0)),c<=h&&(h=c,s.set(0,1,0)),u<=h&&s.set(0,0,1),o.crossVectors(i[0],s).normalize(),r[0].crossVectors(i[0],o),n[0].crossVectors(i[0],r[0]);for(let e=1;e<=t;e++){if(r[e]=r[e-1].clone(),n[e]=n[e-1].clone(),o.crossVectors(i[e-1],i[e]),o.length()>Number.EPSILON){o.normalize();const t=Math.acos(Ds(i[e-1].dot(i[e]),-1,1));r[e].applyMatrix4(a.makeRotationAxis(o,t))}n[e].crossVectors(i[e],r[e])}if(!0===e){let e=Math.acos(Ds(r[0].dot(r[t]),-1,1));e/=t,i[0].dot(o.crossVectors(r[0],r[t]))>0&&(e=-e);for(let s=1;s<=t;s++)r[s].applyMatrix4(a.makeRotationAxis(i[s],e*s)),n[s].crossVectors(i[s],r[s])}return{tangents:i,normals:r,binormals:n}}clone(){return(new this.constructor).copy(this)}copy(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}toJSON(){const t={metadata:{version:4.6,type:"Curve",generator:"Curve.toJSON"}};return t.arcLengthDivisions=this.arcLengthDivisions,t.type=this.type,t}fromJSON(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}}class Ka extends Qa{constructor(t=0,e=0,s=1,i=1,r=0,n=2*Math.PI,o=!1,a=0){super(),this.isEllipseCurve=!0,this.type="EllipseCurve",this.aX=t,this.aY=e,this.xRadius=s,this.yRadius=i,this.aStartAngle=r,this.aEndAngle=n,this.aClockwise=o,this.aRotation=a}getPoint(t,e=new Zs){const s=e,i=2*Math.PI;let r=this.aEndAngle-this.aStartAngle;const n=Math.abs(r)i;)r-=i;r0?0:(Math.floor(Math.abs(h)/r)+1)*r:0===l&&h===r-1&&(h=r-2,l=1),this.closed||h>0?o=i[(h-1)%r]:(sh.subVectors(i[0],i[1]).add(i[0]),o=sh);const c=i[h%r],u=i[(h+1)%r];if(this.closed||h+2i.length-2?i.length-1:n+1],c=i[n>i.length-3?i.length-1:n+2];return s.set(ah(o,a.x,h.x,l.x,c.x),ah(o,a.y,h.y,l.y,c.y)),s}copy(t){super.copy(t),this.points=[];for(let e=0,s=t.points.length;e=s){const t=i[r]-s,n=this.curves[r],o=n.getLength(),a=0===o?0:1-t/o;return n.getPointAt(a,e)}r++}return null}getLength(){const t=this.getCurveLengths();return t[t.length-1]}updateArcLengths(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()}getCurveLengths(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;const t=[];let e=0;for(let s=0,i=this.curves.length;s1&&!e[e.length-1].equals(e[0])&&e.push(e[0]),e}copy(t){super.copy(t),this.curves=[];for(let e=0,s=t.curves.length;e0){const t=h.getPoint(0);t.equals(this.currentPoint)||this.lineTo(t.x,t.y)}this.curves.push(h);const l=h.getPoint(1);return this.currentPoint.copy(l),this}copy(t){return super.copy(t),this.currentPoint.copy(t.currentPoint),this}toJSON(){const t=super.toJSON();return t.currentPoint=this.currentPoint.toArray(),t}fromJSON(t){return super.fromJSON(t),this.currentPoint.fromArray(t.currentPoint),this}}class vh extends zn{constructor(t=[new Zs(0,-.5),new Zs(.5,0),new Zs(0,.5)],e=12,s=0,i=2*Math.PI){super(),this.type="LatheGeometry",this.parameters={points:t,segments:e,phiStart:s,phiLength:i},e=Math.floor(e),i=Ds(i,0,2*Math.PI);const r=[],n=[],o=[],a=[],h=[],l=1/e,c=new Ii,u=new Zs,d=new Ii,p=new Ii,m=new Ii;let y=0,f=0;for(let e=0;e<=t.length-1;e++)switch(e){case 0:y=t[e+1].x-t[e].x,f=t[e+1].y-t[e].y,d.x=1*f,d.y=-y,d.z=0*f,m.copy(d),d.normalize(),a.push(d.x,d.y,d.z);break;case t.length-1:a.push(m.x,m.y,m.z);break;default:y=t[e+1].x-t[e].x,f=t[e+1].y-t[e].y,d.x=1*f,d.y=-y,d.z=0*f,p.copy(d),d.x+=m.x,d.y+=m.y,d.z+=m.z,d.normalize(),a.push(d.x,d.y,d.z),m.copy(p)}for(let r=0;r<=e;r++){const d=s+r*l*i,p=Math.sin(d),m=Math.cos(d);for(let s=0;s<=t.length-1;s++){c.x=t[s].x*p,c.y=t[s].y,c.z=t[s].x*m,n.push(c.x,c.y,c.z),u.x=r/e,u.y=s/(t.length-1),o.push(u.x,u.y);const i=a[3*s+0]*p,l=a[3*s+1],d=a[3*s+0]*m;h.push(i,l,d)}}for(let s=0;s0||0!==i)&&(l.push(n,o,h),x+=3),(e>0||i!==r-1)&&(l.push(o,a,h),x+=3)}h.addGroup(f,x,0),f+=x}(),!1===n&&(t>0&&g(!0),e>0&&g(!1)),this.setIndex(l),this.setAttribute("position",new bn(c,3)),this.setAttribute("normal",new bn(u,3)),this.setAttribute("uv",new bn(d,2))}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new Sh(t.radiusTop,t.radiusBottom,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class _h extends Sh{constructor(t=1,e=1,s=32,i=1,r=!1,n=0,o=2*Math.PI){super(0,t,e,s,i,r,n,o),this.type="ConeGeometry",this.parameters={radius:t,height:e,radialSegments:s,heightSegments:i,openEnded:r,thetaStart:n,thetaLength:o}}static fromJSON(t){return new _h(t.radius,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class Ah extends zn{constructor(t=[],e=[],s=1,i=0){super(),this.type="PolyhedronGeometry",this.parameters={vertices:t,indices:e,radius:s,detail:i};const r=[],n=[];function o(t,e,s,i){const r=i+1,n=[];for(let i=0;i<=r;i++){n[i]=[];const o=t.clone().lerp(s,i/r),a=e.clone().lerp(s,i/r),h=r-i;for(let t=0;t<=h;t++)n[i][t]=0===t&&i===r?o:o.clone().lerp(a,t/h)}for(let t=0;t.9&&o<.1&&(e<.2&&(n[t+0]+=1),s<.2&&(n[t+2]+=1),i<.2&&(n[t+4]+=1))}}()}(),this.setAttribute("position",new bn(r,3)),this.setAttribute("normal",new bn(r.slice(),3)),this.setAttribute("uv",new bn(n,2)),0===i?this.computeVertexNormals():this.normalizeNormals()}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new Ah(t.vertices,t.indices,t.radius,t.details)}}class Th extends Ah{constructor(t=1,e=0){const s=(1+Math.sqrt(5))/2,i=1/s;super([-1,-1,-1,-1,-1,1,-1,1,-1,-1,1,1,1,-1,-1,1,-1,1,1,1,-1,1,1,1,0,-i,-s,0,-i,s,0,i,-s,0,i,s,-i,-s,0,-i,s,0,i,-s,0,i,s,0,-s,0,-i,s,0,-i,-s,0,i,s,0,i],[3,11,7,3,7,15,3,15,13,7,19,17,7,17,6,7,6,15,17,4,8,17,8,10,17,10,6,8,0,16,8,16,2,8,2,10,0,12,1,0,1,18,0,18,16,6,10,2,6,2,13,6,13,15,2,16,18,2,18,3,2,3,13,18,1,9,18,9,11,18,11,3,4,14,12,4,12,0,4,0,8,11,9,5,11,5,19,11,19,7,19,5,14,19,14,4,19,4,17,1,12,14,1,14,5,1,5,9],t,e),this.type="DodecahedronGeometry",this.parameters={radius:t,detail:e}}static fromJSON(t){return new Th(t.radius,t.detail)}}const zh=new Ii,Ch=new Ii,Ih=new Ii,Bh=new Jr;class kh extends zn{constructor(t=null,e=1){if(super(),this.type="EdgesGeometry",this.parameters={geometry:t,thresholdAngle:e},null!==t){const s=4,i=Math.pow(10,s),r=Math.cos(Ws*e),n=t.getIndex(),o=t.getAttribute("position"),a=n?n.count:o.count,h=[0,0,0],l=["a","b","c"],c=new Array(3),u={},d=[];for(let t=0;t80*s){a=l=t[0],h=c=t[1];for(let e=s;el&&(l=u),d>c&&(c=d);p=Math.max(l-a,c-h),p=0!==p?32767/p:0}return Fh(n,o,s,a,h,p,0),o};function Rh(t,e,s,i,r){let n,o;if(r===function(t,e,s,i){let r=0;for(let n=e,o=s-i;n0)for(n=e;n=e;n-=i)o=el(n,t[n],t[n+1],o);return o&&Zh(o,o.next)&&(sl(o),o=o.next),o}function Oh(t,e){if(!t)return t;e||(e=t);let s,i=t;do{if(s=!1,i.steiner||!Zh(i,i.next)&&0!==Yh(i.prev,i,i.next))i=i.next;else{if(sl(i),i=e=i.prev,i===i.next)break;s=!0}}while(s||i!==e);return e}function Fh(t,e,s,i,r,n,o){if(!t)return;!o&&n&&function(t,e,s,i){let r=t;do{0===r.z&&(r.z=Hh(r.x,r.y,e,s,i)),r.prevZ=r.prev,r.nextZ=r.next,r=r.next}while(r!==t);r.prevZ.nextZ=null,r.prevZ=null,function(t){let e,s,i,r,n,o,a,h,l=1;do{for(s=t,t=null,n=null,o=0;s;){for(o++,i=s,a=0,e=0;e0||h>0&&i;)0!==a&&(0===h||!i||s.z<=i.z)?(r=s,s=s.nextZ,a--):(r=i,i=i.nextZ,h--),n?n.nextZ=r:t=r,r.prevZ=n,n=r;s=i}n.nextZ=null,l*=2}while(o>1)}(r)}(t,i,r,n);let a,h,l=t;for(;t.prev!==t.next;)if(a=t.prev,h=t.next,n?Lh(t,i,r,n):Nh(t))e.push(a.i/s|0),e.push(t.i/s|0),e.push(h.i/s|0),sl(t),t=h.next,l=h.next;else if((t=h)===l){o?1===o?Fh(t=Vh(Oh(t),e,s),e,s,i,r,n,2):2===o&&Wh(t,e,s,i,r,n):Fh(Oh(t),e,s,i,r,n,1);break}}function Nh(t){const e=t.prev,s=t,i=t.next;if(Yh(e,s,i)>=0)return!1;const r=e.x,n=s.x,o=i.x,a=e.y,h=s.y,l=i.y,c=rn?r>o?r:o:n>o?n:o,p=a>h?a>l?a:l:h>l?h:l;let m=i.next;for(;m!==e;){if(m.x>=c&&m.x<=d&&m.y>=u&&m.y<=p&&Jh(r,a,n,h,o,l,m.x,m.y)&&Yh(m.prev,m,m.next)>=0)return!1;m=m.next}return!0}function Lh(t,e,s,i){const r=t.prev,n=t,o=t.next;if(Yh(r,n,o)>=0)return!1;const a=r.x,h=n.x,l=o.x,c=r.y,u=n.y,d=o.y,p=ah?a>l?a:l:h>l?h:l,f=c>u?c>d?c:d:u>d?u:d,g=Hh(p,m,e,s,i),x=Hh(y,f,e,s,i);let b=t.prevZ,v=t.nextZ;for(;b&&b.z>=g&&v&&v.z<=x;){if(b.x>=p&&b.x<=y&&b.y>=m&&b.y<=f&&b!==r&&b!==o&&Jh(a,c,h,u,l,d,b.x,b.y)&&Yh(b.prev,b,b.next)>=0)return!1;if(b=b.prevZ,v.x>=p&&v.x<=y&&v.y>=m&&v.y<=f&&v!==r&&v!==o&&Jh(a,c,h,u,l,d,v.x,v.y)&&Yh(v.prev,v,v.next)>=0)return!1;v=v.nextZ}for(;b&&b.z>=g;){if(b.x>=p&&b.x<=y&&b.y>=m&&b.y<=f&&b!==r&&b!==o&&Jh(a,c,h,u,l,d,b.x,b.y)&&Yh(b.prev,b,b.next)>=0)return!1;b=b.prevZ}for(;v&&v.z<=x;){if(v.x>=p&&v.x<=y&&v.y>=m&&v.y<=f&&v!==r&&v!==o&&Jh(a,c,h,u,l,d,v.x,v.y)&&Yh(v.prev,v,v.next)>=0)return!1;v=v.nextZ}return!0}function Vh(t,e,s){let i=t;do{const r=i.prev,n=i.next.next;!Zh(r,n)&&Gh(r,i,i.next,n)&&Kh(r,n)&&Kh(n,r)&&(e.push(r.i/s|0),e.push(i.i/s|0),e.push(n.i/s|0),sl(i),sl(i.next),i=t=n),i=i.next}while(i!==t);return Oh(i)}function Wh(t,e,s,i,r,n){let o=t;do{let t=o.next.next;for(;t!==o.prev;){if(o.i!==t.i&&Xh(o,t)){let a=tl(o,t);return o=Oh(o,o.next),a=Oh(a,a.next),Fh(o,e,s,i,r,n,0),void Fh(a,e,s,i,r,n,0)}t=t.next}o=o.next}while(o!==t)}function jh(t,e){return t.x-e.x}function Uh(t,e){const s=function(t,e){let s,i=e,r=-1/0;const n=t.x,o=t.y;do{if(o<=i.y&&o>=i.next.y&&i.next.y!==i.y){const t=i.x+(o-i.y)*(i.next.x-i.x)/(i.next.y-i.y);if(t<=n&&t>r&&(r=t,s=i.x=i.x&&i.x>=h&&n!==i.x&&Jh(os.x||i.x===s.x&&Dh(s,i)))&&(s=i,u=c)),i=i.next}while(i!==a);return s}(t,e);if(!s)return e;const i=tl(s,t);return Oh(i,i.next),Oh(s,s.next)}function Dh(t,e){return Yh(t.prev,t,e.prev)<0&&Yh(e.next,t,t.next)<0}function Hh(t,e,s,i,r){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=(t-s)*r|0)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=(e-i)*r|0)|e<<8))|e<<4))|e<<2))|e<<1))<<1}function qh(t){let e=t,s=t;do{(e.x=(t-o)*(n-a)&&(t-o)*(i-a)>=(s-o)*(e-a)&&(s-o)*(n-a)>=(r-o)*(i-a)}function Xh(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!function(t,e){let s=t;do{if(s.i!==t.i&&s.next.i!==t.i&&s.i!==e.i&&s.next.i!==e.i&&Gh(s,s.next,t,e))return!0;s=s.next}while(s!==t);return!1}(t,e)&&(Kh(t,e)&&Kh(e,t)&&function(t,e){let s=t,i=!1;const r=(t.x+e.x)/2,n=(t.y+e.y)/2;do{s.y>n!=s.next.y>n&&s.next.y!==s.y&&r<(s.next.x-s.x)*(n-s.y)/(s.next.y-s.y)+s.x&&(i=!i),s=s.next}while(s!==t);return i}(t,e)&&(Yh(t.prev,t,e.prev)||Yh(t,e.prev,e))||Zh(t,e)&&Yh(t.prev,t,t.next)>0&&Yh(e.prev,e,e.next)>0)}function Yh(t,e,s){return(e.y-t.y)*(s.x-e.x)-(e.x-t.x)*(s.y-e.y)}function Zh(t,e){return t.x===e.x&&t.y===e.y}function Gh(t,e,s,i){const r=Qh(Yh(t,e,s)),n=Qh(Yh(t,e,i)),o=Qh(Yh(s,i,t)),a=Qh(Yh(s,i,e));return r!==n&&o!==a||(!(0!==r||!$h(t,s,e))||(!(0!==n||!$h(t,i,e))||(!(0!==o||!$h(s,t,i))||!(0!==a||!$h(s,e,i)))))}function $h(t,e,s){return e.x<=Math.max(t.x,s.x)&&e.x>=Math.min(t.x,s.x)&&e.y<=Math.max(t.y,s.y)&&e.y>=Math.min(t.y,s.y)}function Qh(t){return t>0?1:t<0?-1:0}function Kh(t,e){return Yh(t.prev,t,t.next)<0?Yh(t,e,t.next)>=0&&Yh(t,t.prev,e)>=0:Yh(t,e,t.prev)<0||Yh(t,t.next,e)<0}function tl(t,e){const s=new il(t.i,t.x,t.y),i=new il(e.i,e.x,e.y),r=t.next,n=e.prev;return t.next=e,e.prev=t,s.next=r,r.prev=s,i.next=s,s.prev=i,n.next=i,i.prev=n,i}function el(t,e,s,i){const r=new il(t,e,s);return i?(r.next=i.next,r.prev=i,i.next.prev=r,i.next=r):(r.prev=r,r.next=r),r}function sl(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&&(t.prevZ.nextZ=t.nextZ),t.nextZ&&(t.nextZ.prevZ=t.prevZ)}function il(t,e,s){this.i=t,this.x=e,this.y=s,this.prev=null,this.next=null,this.z=0,this.prevZ=null,this.nextZ=null,this.steiner=!1}class rl{static area(t){const e=t.length;let s=0;for(let i=e-1,r=0;r2&&t[e-1].equals(t[0])&&t.pop()}function ol(t,e){for(let s=0;sNumber.EPSILON){const u=Math.sqrt(c),d=Math.sqrt(h*h+l*l),p=e.x-a/u,m=e.y+o/u,y=((s.x-l/d-p)*l-(s.y+h/d-m)*h)/(o*l-a*h);i=p+o*y-t.x,r=m+a*y-t.y;const f=i*i+r*r;if(f<=2)return new Zs(i,r);n=Math.sqrt(f/2)}else{let t=!1;o>Number.EPSILON?h>Number.EPSILON&&(t=!0):o<-Number.EPSILON?h<-Number.EPSILON&&(t=!0):Math.sign(a)===Math.sign(l)&&(t=!0),t?(i=-a,r=o,n=Math.sqrt(c)):(i=o,r=a,n=Math.sqrt(c/2))}return new Zs(i/n,r/n)}const k=[];for(let t=0,e=T.length,s=e-1,i=t+1;t=0;t--){const e=t/p,s=c*Math.cos(e*Math.PI/2),i=u*Math.sin(e*Math.PI/2)+d;for(let t=0,e=T.length;t=0;){const i=s;let r=s-1;r<0&&(r=t.length-1);for(let t=0,s=a+2*p;t0)&&d.push(e,r,h),(t!==s-1||a0!=t>0&&this.version++,this._anisotropy=t}get clearcoat(){return this._clearcoat}set clearcoat(t){this._clearcoat>0!=t>0&&this.version++,this._clearcoat=t}get iridescence(){return this._iridescence}set iridescence(t){this._iridescence>0!=t>0&&this.version++,this._iridescence=t}get dispersion(){return this._dispersion}set dispersion(t){this._dispersion>0!=t>0&&this.version++,this._dispersion=t}get sheen(){return this._sheen}set sheen(t){this._sheen>0!=t>0&&this.version++,this._sheen=t}get transmission(){return this._transmission}set transmission(t){this._transmission>0!=t>0&&this.version++,this._transmission=t}copy(t){return super.copy(t),this.defines={STANDARD:"",PHYSICAL:""},this.anisotropy=t.anisotropy,this.anisotropyRotation=t.anisotropyRotation,this.anisotropyMap=t.anisotropyMap,this.clearcoat=t.clearcoat,this.clearcoatMap=t.clearcoatMap,this.clearcoatRoughness=t.clearcoatRoughness,this.clearcoatRoughnessMap=t.clearcoatRoughnessMap,this.clearcoatNormalMap=t.clearcoatNormalMap,this.clearcoatNormalScale.copy(t.clearcoatNormalScale),this.dispersion=t.dispersion,this.ior=t.ior,this.iridescence=t.iridescence,this.iridescenceMap=t.iridescenceMap,this.iridescenceIOR=t.iridescenceIOR,this.iridescenceThicknessRange=[...t.iridescenceThicknessRange],this.iridescenceThicknessMap=t.iridescenceThicknessMap,this.sheen=t.sheen,this.sheenColor.copy(t.sheenColor),this.sheenColorMap=t.sheenColorMap,this.sheenRoughness=t.sheenRoughness,this.sheenRoughnessMap=t.sheenRoughnessMap,this.transmission=t.transmission,this.transmissionMap=t.transmissionMap,this.thickness=t.thickness,this.thicknessMap=t.thicknessMap,this.attenuationDistance=t.attenuationDistance,this.attenuationColor.copy(t.attenuationColor),this.specularIntensity=t.specularIntensity,this.specularIntensityMap=t.specularIntensityMap,this.specularColor.copy(t.specularColor),this.specularColorMap=t.specularColorMap,this}}class Tl extends tn{constructor(t){super(),this.isMeshPhongMaterial=!0,this.type="MeshPhongMaterial",this.color=new $r(16777215),this.specular=new $r(1118481),this.shininess=30,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new $r(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Zs(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new yr,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.specular.copy(t.specular),this.shininess=t.shininess,this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.envMapRotation.copy(t.envMapRotation),this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this.fog=t.fog,this}}class zl extends tn{constructor(t){super(),this.isMeshToonMaterial=!0,this.defines={TOON:""},this.type="MeshToonMaterial",this.color=new $r(16777215),this.map=null,this.gradientMap=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new $r(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Zs(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.gradientMap=t.gradientMap,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.fog=t.fog,this}}class Cl extends tn{constructor(t){super(),this.isMeshNormalMaterial=!0,this.type="MeshNormalMaterial",this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Zs(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.flatShading=!1,this.setValues(t)}copy(t){return super.copy(t),this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.flatShading=t.flatShading,this}}class Il extends tn{constructor(t){super(),this.isMeshLambertMaterial=!0,this.type="MeshLambertMaterial",this.color=new $r(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new $r(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Zs(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new yr,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.envMapRotation.copy(t.envMapRotation),this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this.fog=t.fog,this}}class Bl extends tn{constructor(t){super(),this.isMeshDepthMaterial=!0,this.type="MeshDepthMaterial",this.depthPacking=3200,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.setValues(t)}copy(t){return super.copy(t),this.depthPacking=t.depthPacking,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this}}class kl extends tn{constructor(t){super(),this.isMeshDistanceMaterial=!0,this.type="MeshDistanceMaterial",this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.setValues(t)}copy(t){return super.copy(t),this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this}}class El extends tn{constructor(t){super(),this.isMeshMatcapMaterial=!0,this.defines={MATCAP:""},this.type="MeshMatcapMaterial",this.color=new $r(16777215),this.matcap=null,this.map=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Zs(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.defines={MATCAP:""},this.color.copy(t.color),this.matcap=t.matcap,this.map=t.map,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.flatShading=t.flatShading,this.fog=t.fog,this}}class Pl extends Sa{constructor(t){super(),this.isLineDashedMaterial=!0,this.type="LineDashedMaterial",this.scale=1,this.dashSize=3,this.gapSize=1,this.setValues(t)}copy(t){return super.copy(t),this.scale=t.scale,this.dashSize=t.dashSize,this.gapSize=t.gapSize,this}}function Rl(t,e,s){return!t||!s&&t.constructor===e?t:"number"==typeof e.BYTES_PER_ELEMENT?new e(t):Array.prototype.slice.call(t)}function Ol(t){return ArrayBuffer.isView(t)&&!(t instanceof DataView)}function Fl(t){const e=t.length,s=new Array(e);for(let t=0;t!==e;++t)s[t]=t;return s.sort((function(e,s){return t[e]-t[s]})),s}function Nl(t,e,s){const i=t.length,r=new t.constructor(i);for(let n=0,o=0;o!==i;++n){const i=s[n]*e;for(let s=0;s!==e;++s)r[o++]=t[i+s]}return r}function Ll(t,e,s,i){let r=1,n=t[0];for(;void 0!==n&&void 0===n[i];)n=t[r++];if(void 0===n)return;let o=n[i];if(void 0!==o)if(Array.isArray(o))do{o=n[i],void 0!==o&&(e.push(n.time),s.push.apply(s,o)),n=t[r++]}while(void 0!==n);else if(void 0!==o.toArray)do{o=n[i],void 0!==o&&(e.push(n.time),o.toArray(s,s.length)),n=t[r++]}while(void 0!==n);else do{o=n[i],void 0!==o&&(e.push(n.time),s.push(o)),n=t[r++]}while(void 0!==n)}const Vl={convertArray:Rl,isTypedArray:Ol,getKeyframeOrder:Fl,sortedArray:Nl,flattenJSON:Ll,subclip:function(t,e,s,i,r=30){const n=t.clone();n.name=e;const o=[];for(let t=0;t=i)){h.push(e.times[t]);for(let s=0;sn.tracks[t].times[0]&&(a=n.tracks[t].times[0]);for(let t=0;t=i.times[u]){const t=u*h+a,e=t+h-a;d=i.values.slice(t,e)}else{const t=i.createInterpolant(),e=a,s=h-a;t.evaluate(n),d=t.resultBuffer.slice(e,s)}if("quaternion"===r){(new Ci).fromArray(d).normalize().conjugate().toArray(d)}const p=o.times.length;for(let t=0;t=r)break t;{const o=e[1];t=r)break e}n=s,s=0}}for(;s>>1;te;)--n;if(++n,0!==r||n!==i){r>=n&&(n=Math.max(n,1),r=n-1);const t=this.getValueSize();this.times=s.slice(r,n),this.values=this.values.slice(r*t,n*t)}return this}validate(){let t=!0;const e=this.getValueSize();e-Math.floor(e)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),t=!1);const s=this.times,i=this.values,r=s.length;0===r&&(console.error("THREE.KeyframeTrack: Track is empty.",this),t=!1);let n=null;for(let e=0;e!==r;e++){const i=s[e];if("number"==typeof i&&isNaN(i)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,e,i),t=!1;break}if(null!==n&&n>i){console.error("THREE.KeyframeTrack: Out of order keys.",this,e,i,n),t=!1;break}n=i}if(void 0!==i&&Ol(i))for(let e=0,s=i.length;e!==s;++e){const s=i[e];if(isNaN(s)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,e,s),t=!1;break}}return t}optimize(){const t=this.times.slice(),e=this.values.slice(),s=this.getValueSize(),i=this.getInterpolation()===Re,r=t.length-1;let n=1;for(let o=1;o0){t[n]=t[r];for(let t=r*s,i=n*s,o=0;o!==s;++o)e[i+o]=e[t+o];++n}return n!==t.length?(this.times=t.slice(0,n),this.values=e.slice(0,n*s)):(this.times=t,this.values=e),this}clone(){const t=this.times.slice(),e=this.values.slice(),s=new(0,this.constructor)(this.name,t,e);return s.createInterpolant=this.createInterpolant,s}}Hl.prototype.TimeBufferType=Float32Array,Hl.prototype.ValueBufferType=Float32Array,Hl.prototype.DefaultInterpolation=Pe;class ql extends Hl{constructor(t,e,s){super(t,e,s)}}ql.prototype.ValueTypeName="bool",ql.prototype.ValueBufferType=Array,ql.prototype.DefaultInterpolation=Ee,ql.prototype.InterpolantFactoryMethodLinear=void 0,ql.prototype.InterpolantFactoryMethodSmooth=void 0;class Jl extends Hl{}Jl.prototype.ValueTypeName="color";class Xl extends Hl{}Xl.prototype.ValueTypeName="number";class Yl extends Wl{constructor(t,e,s,i){super(t,e,s,i)}interpolate_(t,e,s,i){const r=this.resultBuffer,n=this.sampleValues,o=this.valueSize,a=(s-e)/(i-e);let h=t*o;for(let t=h+o;h!==t;h+=4)Ci.slerpFlat(r,0,n,h-o,n,h,a);return r}}class Zl extends Hl{InterpolantFactoryMethodLinear(t){return new Yl(this.times,this.values,this.getValueSize(),t)}}Zl.prototype.ValueTypeName="quaternion",Zl.prototype.InterpolantFactoryMethodSmooth=void 0;class Gl extends Hl{constructor(t,e,s){super(t,e,s)}}Gl.prototype.ValueTypeName="string",Gl.prototype.ValueBufferType=Array,Gl.prototype.DefaultInterpolation=Ee,Gl.prototype.InterpolantFactoryMethodLinear=void 0,Gl.prototype.InterpolantFactoryMethodSmooth=void 0;class $l extends Hl{}$l.prototype.ValueTypeName="vector";class Ql{constructor(t="",e=-1,s=[],i=2500){this.name=t,this.tracks=s,this.duration=e,this.blendMode=i,this.uuid=Us(),this.duration<0&&this.resetDuration()}static parse(t){const e=[],s=t.tracks,i=1/(t.fps||1);for(let t=0,r=s.length;t!==r;++t)e.push(Kl(s[t]).scale(i));const r=new this(t.name,t.duration,e,t.blendMode);return r.uuid=t.uuid,r}static toJSON(t){const e=[],s=t.tracks,i={name:t.name,duration:t.duration,tracks:e,uuid:t.uuid,blendMode:t.blendMode};for(let t=0,i=s.length;t!==i;++t)e.push(Hl.toJSON(s[t]));return i}static CreateFromMorphTargetSequence(t,e,s,i){const r=e.length,n=[];for(let t=0;t1){const t=n[1];let e=i[t];e||(i[t]=e=[]),e.push(s)}}const n=[];for(const t in i)n.push(this.CreateFromMorphTargetSequence(t,i[t],e,s));return n}static parseAnimation(t,e){if(!t)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;const s=function(t,e,s,i,r){if(0!==s.length){const n=[],o=[];Ll(s,n,o,i),0!==n.length&&r.push(new t(e,n,o))}},i=[],r=t.name||"default",n=t.fps||30,o=t.blendMode;let a=t.length||-1;const h=t.hierarchy||[];for(let t=0;t{e&&e(r),this.manager.itemEnd(t)}),0),r;if(void 0!==rc[t])return void rc[t].push({onLoad:e,onProgress:s,onError:i});rc[t]=[],rc[t].push({onLoad:e,onProgress:s,onError:i});const n=new Request(t,{headers:new Headers(this.requestHeader),credentials:this.withCredentials?"include":"same-origin"}),o=this.mimeType,a=this.responseType;fetch(n).then((e=>{if(200===e.status||0===e.status){if(0===e.status&&console.warn("THREE.FileLoader: HTTP Status 0 received."),"undefined"==typeof ReadableStream||void 0===e.body||void 0===e.body.getReader)return e;const s=rc[t],i=e.body.getReader(),r=e.headers.get("X-File-Size")||e.headers.get("Content-Length"),n=r?parseInt(r):0,o=0!==n;let a=0;const h=new ReadableStream({start(t){!function e(){i.read().then((({done:i,value:r})=>{if(i)t.close();else{a+=r.byteLength;const i=new ProgressEvent("progress",{lengthComputable:o,loaded:a,total:n});for(let t=0,e=s.length;t{t.error(e)}))}()}});return new Response(h)}throw new nc(`fetch for "${e.url}" responded with ${e.status}: ${e.statusText}`,e)})).then((t=>{switch(a){case"arraybuffer":return t.arrayBuffer();case"blob":return t.blob();case"document":return t.text().then((t=>(new DOMParser).parseFromString(t,o)));case"json":return t.json();default:if(void 0===o)return t.text();{const e=/charset="?([^;"\s]*)"?/i.exec(o),s=e&&e[1]?e[1].toLowerCase():void 0,i=new TextDecoder(s);return t.arrayBuffer().then((t=>i.decode(t)))}}})).then((e=>{tc.add(t,e);const s=rc[t];delete rc[t];for(let t=0,i=s.length;t{const s=rc[t];if(void 0===s)throw this.manager.itemError(t),e;delete rc[t];for(let t=0,i=s.length;t{this.manager.itemEnd(t)})),this.manager.itemStart(t)}setResponseType(t){return this.responseType=t,this}setMimeType(t){return this.mimeType=t,this}}class ac extends ic{constructor(t){super(t)}load(t,e,s,i){const r=this,n=new oc(this.manager);n.setPath(this.path),n.setRequestHeader(this.requestHeader),n.setWithCredentials(this.withCredentials),n.load(t,(function(s){try{e(r.parse(JSON.parse(s)))}catch(e){i?i(e):console.error(e),r.manager.itemError(t)}}),s,i)}parse(t){const e=[];for(let s=0;s0:i.vertexColors=t.vertexColors),void 0!==t.uniforms)for(const e in t.uniforms){const r=t.uniforms[e];switch(i.uniforms[e]={},r.type){case"t":i.uniforms[e].value=s(r.value);break;case"c":i.uniforms[e].value=(new $r).setHex(r.value);break;case"v2":i.uniforms[e].value=(new Zs).fromArray(r.value);break;case"v3":i.uniforms[e].value=(new Ii).fromArray(r.value);break;case"v4":i.uniforms[e].value=(new wi).fromArray(r.value);break;case"m3":i.uniforms[e].value=(new Gs).fromArray(r.value);break;case"m4":i.uniforms[e].value=(new nr).fromArray(r.value);break;default:i.uniforms[e].value=r.value}}if(void 0!==t.defines&&(i.defines=t.defines),void 0!==t.vertexShader&&(i.vertexShader=t.vertexShader),void 0!==t.fragmentShader&&(i.fragmentShader=t.fragmentShader),void 0!==t.glslVersion&&(i.glslVersion=t.glslVersion),void 0!==t.extensions)for(const e in t.extensions)i.extensions[e]=t.extensions[e];if(void 0!==t.lights&&(i.lights=t.lights),void 0!==t.clipping&&(i.clipping=t.clipping),void 0!==t.size&&(i.size=t.size),void 0!==t.sizeAttenuation&&(i.sizeAttenuation=t.sizeAttenuation),void 0!==t.map&&(i.map=s(t.map)),void 0!==t.matcap&&(i.matcap=s(t.matcap)),void 0!==t.alphaMap&&(i.alphaMap=s(t.alphaMap)),void 0!==t.bumpMap&&(i.bumpMap=s(t.bumpMap)),void 0!==t.bumpScale&&(i.bumpScale=t.bumpScale),void 0!==t.normalMap&&(i.normalMap=s(t.normalMap)),void 0!==t.normalMapType&&(i.normalMapType=t.normalMapType),void 0!==t.normalScale){let e=t.normalScale;!1===Array.isArray(e)&&(e=[e,e]),i.normalScale=(new Zs).fromArray(e)}return void 0!==t.displacementMap&&(i.displacementMap=s(t.displacementMap)),void 0!==t.displacementScale&&(i.displacementScale=t.displacementScale),void 0!==t.displacementBias&&(i.displacementBias=t.displacementBias),void 0!==t.roughnessMap&&(i.roughnessMap=s(t.roughnessMap)),void 0!==t.metalnessMap&&(i.metalnessMap=s(t.metalnessMap)),void 0!==t.emissiveMap&&(i.emissiveMap=s(t.emissiveMap)),void 0!==t.emissiveIntensity&&(i.emissiveIntensity=t.emissiveIntensity),void 0!==t.specularMap&&(i.specularMap=s(t.specularMap)),void 0!==t.specularIntensityMap&&(i.specularIntensityMap=s(t.specularIntensityMap)),void 0!==t.specularColorMap&&(i.specularColorMap=s(t.specularColorMap)),void 0!==t.envMap&&(i.envMap=s(t.envMap)),void 0!==t.envMapRotation&&i.envMapRotation.fromArray(t.envMapRotation),void 0!==t.envMapIntensity&&(i.envMapIntensity=t.envMapIntensity),void 0!==t.reflectivity&&(i.reflectivity=t.reflectivity),void 0!==t.refractionRatio&&(i.refractionRatio=t.refractionRatio),void 0!==t.lightMap&&(i.lightMap=s(t.lightMap)),void 0!==t.lightMapIntensity&&(i.lightMapIntensity=t.lightMapIntensity),void 0!==t.aoMap&&(i.aoMap=s(t.aoMap)),void 0!==t.aoMapIntensity&&(i.aoMapIntensity=t.aoMapIntensity),void 0!==t.gradientMap&&(i.gradientMap=s(t.gradientMap)),void 0!==t.clearcoatMap&&(i.clearcoatMap=s(t.clearcoatMap)),void 0!==t.clearcoatRoughnessMap&&(i.clearcoatRoughnessMap=s(t.clearcoatRoughnessMap)),void 0!==t.clearcoatNormalMap&&(i.clearcoatNormalMap=s(t.clearcoatNormalMap)),void 0!==t.clearcoatNormalScale&&(i.clearcoatNormalScale=(new Zs).fromArray(t.clearcoatNormalScale)),void 0!==t.iridescenceMap&&(i.iridescenceMap=s(t.iridescenceMap)),void 0!==t.iridescenceThicknessMap&&(i.iridescenceThicknessMap=s(t.iridescenceThicknessMap)),void 0!==t.transmissionMap&&(i.transmissionMap=s(t.transmissionMap)),void 0!==t.thicknessMap&&(i.thicknessMap=s(t.thicknessMap)),void 0!==t.anisotropyMap&&(i.anisotropyMap=s(t.anisotropyMap)),void 0!==t.sheenColorMap&&(i.sheenColorMap=s(t.sheenColorMap)),void 0!==t.sheenRoughnessMap&&(i.sheenRoughnessMap=s(t.sheenRoughnessMap)),i}setTextures(t){return this.textures=t,this}createMaterialFromType(t){return Pc.createMaterialFromType(t)}static createMaterialFromType(t){return new{ShadowMaterial:Ml,SpriteMaterial:ho,RawShaderMaterial:Sl,ShaderMaterial:Jn,PointsMaterial:Na,MeshPhysicalMaterial:Al,MeshStandardMaterial:_l,MeshPhongMaterial:Tl,MeshToonMaterial:zl,MeshNormalMaterial:Cl,MeshLambertMaterial:Il,MeshDepthMaterial:Bl,MeshDistanceMaterial:kl,MeshBasicMaterial:en,MeshMatcapMaterial:El,LineDashedMaterial:Pl,LineBasicMaterial:Sa,Material:tn}[t]}}class Rc{static decodeText(t){if(console.warn("THREE.LoaderUtils: decodeText() has been deprecated with r165 and will be removed with r175. Use TextDecoder instead."),"undefined"!=typeof TextDecoder)return(new TextDecoder).decode(t);let e="";for(let s=0,i=t.length;s0){const s=new ec(e);r=new lc(s),r.setCrossOrigin(this.crossOrigin);for(let e=0,s=t.length;e0){i=new lc(this.manager),i.setCrossOrigin(this.crossOrigin);for(let e=0,i=t.length;e{const e=new Ei;e.min.fromArray(t.boxMin),e.max.fromArray(t.boxMax);const s=new Gi;return s.radius=t.sphereRadius,s.center.fromArray(t.sphereCenter),{boxInitialized:t.boxInitialized,box:e,sphereInitialized:t.sphereInitialized,sphere:s}})),n._maxInstanceCount=t.maxInstanceCount,n._maxVertexCount=t.maxVertexCount,n._maxIndexCount=t.maxIndexCount,n._geometryInitialized=t.geometryInitialized,n._geometryCount=t.geometryCount,n._matricesTexture=c(t.matricesTexture.uuid),void 0!==t.colorsTexture&&(n._colorsTexture=c(t.colorsTexture.uuid));break;case"LOD":n=new zo;break;case"Line":n=new ka(h(t.geometry),l(t.material));break;case"LineLoop":n=new Fa(h(t.geometry),l(t.material));break;case"LineSegments":n=new Oa(h(t.geometry),l(t.material));break;case"PointCloud":case"Points":n=new Ua(h(t.geometry),l(t.material));break;case"Sprite":n=new So(l(t.material));break;case"Group":n=new Ha;break;case"Bone":n=new Lo;break;default:n=new Er}if(n.uuid=t.uuid,void 0!==t.name&&(n.name=t.name),void 0!==t.matrix?(n.matrix.fromArray(t.matrix),void 0!==t.matrixAutoUpdate&&(n.matrixAutoUpdate=t.matrixAutoUpdate),n.matrixAutoUpdate&&n.matrix.decompose(n.position,n.quaternion,n.scale)):(void 0!==t.position&&n.position.fromArray(t.position),void 0!==t.rotation&&n.rotation.fromArray(t.rotation),void 0!==t.quaternion&&n.quaternion.fromArray(t.quaternion),void 0!==t.scale&&n.scale.fromArray(t.scale)),void 0!==t.up&&n.up.fromArray(t.up),void 0!==t.castShadow&&(n.castShadow=t.castShadow),void 0!==t.receiveShadow&&(n.receiveShadow=t.receiveShadow),t.shadow&&(void 0!==t.shadow.intensity&&(n.shadow.intensity=t.shadow.intensity),void 0!==t.shadow.bias&&(n.shadow.bias=t.shadow.bias),void 0!==t.shadow.normalBias&&(n.shadow.normalBias=t.shadow.normalBias),void 0!==t.shadow.radius&&(n.shadow.radius=t.shadow.radius),void 0!==t.shadow.mapSize&&n.shadow.mapSize.fromArray(t.shadow.mapSize),void 0!==t.shadow.camera&&(n.shadow.camera=this.parseObject(t.shadow.camera))),void 0!==t.visible&&(n.visible=t.visible),void 0!==t.frustumCulled&&(n.frustumCulled=t.frustumCulled),void 0!==t.renderOrder&&(n.renderOrder=t.renderOrder),void 0!==t.userData&&(n.userData=t.userData),void 0!==t.layers&&(n.layers.mask=t.layers),void 0!==t.children){const o=t.children;for(let t=0;t{e&&e(s),r.manager.itemEnd(t)})).catch((t=>{i&&i(t)})):(setTimeout((function(){e&&e(n),r.manager.itemEnd(t)}),0),n);const o={};o.credentials="anonymous"===this.crossOrigin?"same-origin":"include",o.headers=this.requestHeader;const a=fetch(t,o).then((function(t){return t.blob()})).then((function(t){return createImageBitmap(t,Object.assign(r.options,{colorSpaceConversion:"none"}))})).then((function(s){return tc.add(t,s),e&&e(s),r.manager.itemEnd(t),s})).catch((function(e){i&&i(e),tc.remove(t),r.manager.itemError(t),r.manager.itemEnd(t)}));tc.add(t,a),r.manager.itemStart(t)}}let Uc;class Dc{static getContext(){return void 0===Uc&&(Uc=new(window.AudioContext||window.webkitAudioContext)),Uc}static setContext(t){Uc=t}}class Hc extends ic{constructor(t){super(t)}load(t,e,s,i){const r=this,n=new oc(this.manager);function o(e){i?i(e):console.error(e),r.manager.itemError(t)}n.setResponseType("arraybuffer"),n.setPath(this.path),n.setRequestHeader(this.requestHeader),n.setWithCredentials(this.withCredentials),n.load(t,(function(t){try{const s=t.slice(0);Dc.getContext().decodeAudioData(s,(function(t){e(t)})).catch(o)}catch(t){o(t)}}),s,i)}}const qc=new nr,Jc=new nr,Xc=new nr;class Yc{constructor(){this.type="StereoCamera",this.aspect=1,this.eyeSep=.064,this.cameraL=new $n,this.cameraL.layers.enable(1),this.cameraL.matrixAutoUpdate=!1,this.cameraR=new $n,this.cameraR.layers.enable(2),this.cameraR.matrixAutoUpdate=!1,this._cache={focus:null,fov:null,aspect:null,near:null,far:null,zoom:null,eyeSep:null}}update(t){const e=this._cache;if(e.focus!==t.focus||e.fov!==t.fov||e.aspect!==t.aspect*this.aspect||e.near!==t.near||e.far!==t.far||e.zoom!==t.zoom||e.eyeSep!==this.eyeSep){e.focus=t.focus,e.fov=t.fov,e.aspect=t.aspect*this.aspect,e.near=t.near,e.far=t.far,e.zoom=t.zoom,e.eyeSep=this.eyeSep,Xc.copy(t.projectionMatrix);const s=e.eyeSep/2,i=s*e.near/e.focus,r=e.near*Math.tan(Ws*e.fov*.5)/e.zoom;let n,o;Jc.elements[12]=-s,qc.elements[12]=s,n=-r*e.aspect+i,o=r*e.aspect+i,Xc.elements[0]=2*e.near/(o-n),Xc.elements[8]=(o+n)/(o-n),this.cameraL.projectionMatrix.copy(Xc),n=-r*e.aspect-i,o=r*e.aspect-i,Xc.elements[0]=2*e.near/(o-n),Xc.elements[8]=(o+n)/(o-n),this.cameraR.projectionMatrix.copy(Xc)}this.cameraL.matrixWorld.copy(t.matrixWorld).multiply(Jc),this.cameraR.matrixWorld.copy(t.matrixWorld).multiply(qc)}}class Zc extends $n{constructor(t=[]){super(),this.isArrayCamera=!0,this.cameras=t}}class Gc{constructor(t=!0){this.autoStart=t,this.startTime=0,this.oldTime=0,this.elapsedTime=0,this.running=!1}start(){this.startTime=$c(),this.oldTime=this.startTime,this.elapsedTime=0,this.running=!0}stop(){this.getElapsedTime(),this.running=!1,this.autoStart=!1}getElapsedTime(){return this.getDelta(),this.elapsedTime}getDelta(){let t=0;if(this.autoStart&&!this.running)return this.start(),0;if(this.running){const e=$c();t=(e-this.oldTime)/1e3,this.oldTime=e,this.elapsedTime+=t}return t}}function $c(){return performance.now()}const Qc=new Ii,Kc=new Ci,tu=new Ii,eu=new Ii;class su extends Er{constructor(){super(),this.type="AudioListener",this.context=Dc.getContext(),this.gain=this.context.createGain(),this.gain.connect(this.context.destination),this.filter=null,this.timeDelta=0,this._clock=new Gc}getInput(){return this.gain}removeFilter(){return null!==this.filter&&(this.gain.disconnect(this.filter),this.filter.disconnect(this.context.destination),this.gain.connect(this.context.destination),this.filter=null),this}getFilter(){return this.filter}setFilter(t){return null!==this.filter?(this.gain.disconnect(this.filter),this.filter.disconnect(this.context.destination)):this.gain.disconnect(this.context.destination),this.filter=t,this.gain.connect(this.filter),this.filter.connect(this.context.destination),this}getMasterVolume(){return this.gain.gain.value}setMasterVolume(t){return this.gain.gain.setTargetAtTime(t,this.context.currentTime,.01),this}updateMatrixWorld(t){super.updateMatrixWorld(t);const e=this.context.listener,s=this.up;if(this.timeDelta=this._clock.getDelta(),this.matrixWorld.decompose(Qc,Kc,tu),eu.set(0,0,-1).applyQuaternion(Kc),e.positionX){const t=this.context.currentTime+this.timeDelta;e.positionX.linearRampToValueAtTime(Qc.x,t),e.positionY.linearRampToValueAtTime(Qc.y,t),e.positionZ.linearRampToValueAtTime(Qc.z,t),e.forwardX.linearRampToValueAtTime(eu.x,t),e.forwardY.linearRampToValueAtTime(eu.y,t),e.forwardZ.linearRampToValueAtTime(eu.z,t),e.upX.linearRampToValueAtTime(s.x,t),e.upY.linearRampToValueAtTime(s.y,t),e.upZ.linearRampToValueAtTime(s.z,t)}else e.setPosition(Qc.x,Qc.y,Qc.z),e.setOrientation(eu.x,eu.y,eu.z,s.x,s.y,s.z)}}class iu extends Er{constructor(t){super(),this.type="Audio",this.listener=t,this.context=t.context,this.gain=this.context.createGain(),this.gain.connect(t.getInput()),this.autoplay=!1,this.buffer=null,this.detune=0,this.loop=!1,this.loopStart=0,this.loopEnd=0,this.offset=0,this.duration=void 0,this.playbackRate=1,this.isPlaying=!1,this.hasPlaybackControl=!0,this.source=null,this.sourceType="empty",this._startedAt=0,this._progress=0,this._connected=!1,this.filters=[]}getOutput(){return this.gain}setNodeSource(t){return this.hasPlaybackControl=!1,this.sourceType="audioNode",this.source=t,this.connect(),this}setMediaElementSource(t){return this.hasPlaybackControl=!1,this.sourceType="mediaNode",this.source=this.context.createMediaElementSource(t),this.connect(),this}setMediaStreamSource(t){return this.hasPlaybackControl=!1,this.sourceType="mediaStreamNode",this.source=this.context.createMediaStreamSource(t),this.connect(),this}setBuffer(t){return this.buffer=t,this.sourceType="buffer",this.autoplay&&this.play(),this}play(t=0){if(!0===this.isPlaying)return void console.warn("THREE.Audio: Audio is already playing.");if(!1===this.hasPlaybackControl)return void console.warn("THREE.Audio: this Audio has no playback control.");this._startedAt=this.context.currentTime+t;const e=this.context.createBufferSource();return e.buffer=this.buffer,e.loop=this.loop,e.loopStart=this.loopStart,e.loopEnd=this.loopEnd,e.onended=this.onEnded.bind(this),e.start(this._startedAt,this._progress+this.offset,this.duration),this.isPlaying=!0,this.source=e,this.setDetune(this.detune),this.setPlaybackRate(this.playbackRate),this.connect()}pause(){if(!1!==this.hasPlaybackControl)return!0===this.isPlaying&&(this._progress+=Math.max(this.context.currentTime-this._startedAt,0)*this.playbackRate,!0===this.loop&&(this._progress=this._progress%(this.duration||this.buffer.duration)),this.source.stop(),this.source.onended=null,this.isPlaying=!1),this;console.warn("THREE.Audio: this Audio has no playback control.")}stop(t=0){if(!1!==this.hasPlaybackControl)return this._progress=0,null!==this.source&&(this.source.stop(this.context.currentTime+t),this.source.onended=null),this.isPlaying=!1,this;console.warn("THREE.Audio: this Audio has no playback control.")}connect(){if(this.filters.length>0){this.source.connect(this.filters[0]);for(let t=1,e=this.filters.length;t0){this.source.disconnect(this.filters[0]);for(let t=1,e=this.filters.length;t0&&this._mixBufferRegionAdditive(s,i,this._addIndex*e,1,e);for(let t=e,r=e+e;t!==r;++t)if(s[t]!==s[t+e]){o.setValue(s,i);break}}saveOriginalState(){const t=this.binding,e=this.buffer,s=this.valueSize,i=s*this._origIndex;t.getValue(e,i);for(let t=s,r=i;t!==r;++t)e[t]=e[i+t%s];this._setIdentity(),this.cumulativeWeight=0,this.cumulativeWeightAdditive=0}restoreOriginalState(){const t=3*this.valueSize;this.binding.setValue(this.buffer,t)}_setAdditiveIdentityNumeric(){const t=this._addIndex*this.valueSize,e=t+this.valueSize;for(let s=t;s=.5)for(let i=0;i!==r;++i)t[e+i]=t[s+i]}_slerp(t,e,s,i){Ci.slerpFlat(t,e,t,e,t,s,i)}_slerpAdditive(t,e,s,i,r){const n=this._workIndex*r;Ci.multiplyQuaternionsFlat(t,n,t,e,t,s),Ci.slerpFlat(t,e,t,e,t,n,i)}_lerp(t,e,s,i,r){const n=1-i;for(let o=0;o!==r;++o){const r=e+o;t[r]=t[r]*n+t[s+o]*i}}_lerpAdditive(t,e,s,i,r){for(let n=0;n!==r;++n){const r=e+n;t[r]=t[r]+t[s+n]*i}}}const uu="\\[\\]\\.:\\/",du=new RegExp("["+uu+"]","g"),pu="[^"+uu+"]",mu="[^"+uu.replace("\\.","")+"]",yu=new RegExp("^"+/((?:WC+[\/:])*)/.source.replace("WC",pu)+/(WCOD+)?/.source.replace("WCOD",mu)+/(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC",pu)+/\.(WC+)(?:\[(.+)\])?/.source.replace("WC",pu)+"$"),fu=["material","materials","bones","map"];class gu{constructor(t,e,s){this.path=e,this.parsedPath=s||gu.parseTrackName(e),this.node=gu.findNode(t,this.parsedPath.nodeName),this.rootNode=t,this.getValue=this._getValue_unbound,this.setValue=this._setValue_unbound}static create(t,e,s){return t&&t.isAnimationObjectGroup?new gu.Composite(t,e,s):new gu(t,e,s)}static sanitizeNodeName(t){return t.replace(/\s/g,"_").replace(du,"")}static parseTrackName(t){const e=yu.exec(t);if(null===e)throw new Error("PropertyBinding: Cannot parse trackName: "+t);const s={nodeName:e[2],objectName:e[3],objectIndex:e[4],propertyName:e[5],propertyIndex:e[6]},i=s.nodeName&&s.nodeName.lastIndexOf(".");if(void 0!==i&&-1!==i){const t=s.nodeName.substring(i+1);-1!==fu.indexOf(t)&&(s.nodeName=s.nodeName.substring(0,i),s.objectName=t)}if(null===s.propertyName||0===s.propertyName.length)throw new Error("PropertyBinding: can not parse propertyName from trackName: "+t);return s}static findNode(t,e){if(void 0===e||""===e||"."===e||-1===e||e===t.name||e===t.uuid)return t;if(t.skeleton){const s=t.skeleton.getBoneByName(e);if(void 0!==s)return s}if(t.children){const s=function(t){for(let i=0;i=r){const n=r++,l=t[n];e[l.uuid]=h,t[h]=l,e[a]=n,t[n]=o;for(let t=0,e=i;t!==e;++t){const e=s[t],i=e[n],r=e[h];e[h]=i,e[n]=r}}}this.nCachedObjects_=r}uncache(){const t=this._objects,e=this._indicesByUUID,s=this._bindings,i=s.length;let r=this.nCachedObjects_,n=t.length;for(let o=0,a=arguments.length;o!==a;++o){const a=arguments[o].uuid,h=e[a];if(void 0!==h)if(delete e[a],h0&&(e[o.uuid]=h),t[h]=o,t.pop();for(let t=0,e=i;t!==e;++t){const e=s[t];e[h]=e[r],e.pop()}}}this.nCachedObjects_=r}subscribe_(t,e){const s=this._bindingsIndicesByPath;let i=s[t];const r=this._bindings;if(void 0!==i)return r[i];const n=this._paths,o=this._parsedPaths,a=this._objects,h=a.length,l=this.nCachedObjects_,c=new Array(h);i=r.length,s[t]=i,n.push(t),o.push(e),r.push(c);for(let s=l,i=a.length;s!==i;++s){const i=a[s];c[s]=new gu(i,t,e)}return c}unsubscribe_(t){const e=this._bindingsIndicesByPath,s=e[t];if(void 0!==s){const i=this._paths,r=this._parsedPaths,n=this._bindings,o=n.length-1,a=n[o];e[t[o]]=s,n[s]=a,n.pop(),r[s]=r[o],r.pop(),i[s]=i[o],i.pop()}}}class bu{constructor(t,e,s=null,i=e.blendMode){this._mixer=t,this._clip=e,this._localRoot=s,this.blendMode=i;const r=e.tracks,n=r.length,o=new Array(n),a={endingStart:Oe,endingEnd:Oe};for(let t=0;t!==n;++t){const e=r[t].createInterpolant(null);o[t]=e,e.settings=a}this._interpolantSettings=a,this._interpolants=o,this._propertyBindings=new Array(n),this._cacheIndex=null,this._byClipCacheIndex=null,this._timeScaleInterpolant=null,this._weightInterpolant=null,this.loop=2201,this._loopCount=-1,this._startTime=null,this.time=0,this.timeScale=1,this._effectiveTimeScale=1,this.weight=1,this._effectiveWeight=1,this.repetitions=1/0,this.paused=!1,this.enabled=!0,this.clampWhenFinished=!1,this.zeroSlopeAtStart=!0,this.zeroSlopeAtEnd=!0}play(){return this._mixer._activateAction(this),this}stop(){return this._mixer._deactivateAction(this),this.reset()}reset(){return this.paused=!1,this.enabled=!0,this.time=0,this._loopCount=-1,this._startTime=null,this.stopFading().stopWarping()}isRunning(){return this.enabled&&!this.paused&&0!==this.timeScale&&null===this._startTime&&this._mixer._isActiveAction(this)}isScheduled(){return this._mixer._isActiveAction(this)}startAt(t){return this._startTime=t,this}setLoop(t,e){return this.loop=t,this.repetitions=e,this}setEffectiveWeight(t){return this.weight=t,this._effectiveWeight=this.enabled?t:0,this.stopFading()}getEffectiveWeight(){return this._effectiveWeight}fadeIn(t){return this._scheduleFading(t,0,1)}fadeOut(t){return this._scheduleFading(t,1,0)}crossFadeFrom(t,e,s){if(t.fadeOut(e),this.fadeIn(e),s){const s=this._clip.duration,i=t._clip.duration,r=i/s,n=s/i;t.warp(1,r,e),this.warp(n,1,e)}return this}crossFadeTo(t,e,s){return t.crossFadeFrom(this,e,s)}stopFading(){const t=this._weightInterpolant;return null!==t&&(this._weightInterpolant=null,this._mixer._takeBackControlInterpolant(t)),this}setEffectiveTimeScale(t){return this.timeScale=t,this._effectiveTimeScale=this.paused?0:t,this.stopWarping()}getEffectiveTimeScale(){return this._effectiveTimeScale}setDuration(t){return this.timeScale=this._clip.duration/t,this.stopWarping()}syncWith(t){return this.time=t.time,this.timeScale=t.timeScale,this.stopWarping()}halt(t){return this.warp(this._effectiveTimeScale,0,t)}warp(t,e,s){const i=this._mixer,r=i.time,n=this.timeScale;let o=this._timeScaleInterpolant;null===o&&(o=i._lendControlInterpolant(),this._timeScaleInterpolant=o);const a=o.parameterPositions,h=o.sampleValues;return a[0]=r,a[1]=r+s,h[0]=t/n,h[1]=e/n,this}stopWarping(){const t=this._timeScaleInterpolant;return null!==t&&(this._timeScaleInterpolant=null,this._mixer._takeBackControlInterpolant(t)),this}getMixer(){return this._mixer}getClip(){return this._clip}getRoot(){return this._localRoot||this._mixer._root}_update(t,e,s,i){if(!this.enabled)return void this._updateWeight(t);const r=this._startTime;if(null!==r){const i=(t-r)*s;i<0||0===s?e=0:(this._startTime=null,e=s*i)}e*=this._updateTimeScale(t);const n=this._updateTime(e),o=this._updateWeight(t);if(o>0){const t=this._interpolants,e=this._propertyBindings;if(this.blendMode===Ve)for(let s=0,i=t.length;s!==i;++s)t[s].evaluate(n),e[s].accumulateAdditive(o);else for(let s=0,r=t.length;s!==r;++s)t[s].evaluate(n),e[s].accumulate(i,o)}}_updateWeight(t){let e=0;if(this.enabled){e=this.weight;const s=this._weightInterpolant;if(null!==s){const i=s.evaluate(t)[0];e*=i,t>s.parameterPositions[1]&&(this.stopFading(),0===i&&(this.enabled=!1))}}return this._effectiveWeight=e,e}_updateTimeScale(t){let e=0;if(!this.paused){e=this.timeScale;const s=this._timeScaleInterpolant;if(null!==s){e*=s.evaluate(t)[0],t>s.parameterPositions[1]&&(this.stopWarping(),0===e?this.paused=!0:this.timeScale=e)}}return this._effectiveTimeScale=e,e}_updateTime(t){const e=this._clip.duration,s=this.loop;let i=this.time+t,r=this._loopCount;const n=2202===s;if(0===t)return-1===r||!n||1&~r?i:e-i;if(2200===s){-1===r&&(this._loopCount=0,this._setEndings(!0,!0,!1));t:{if(i>=e)i=e;else{if(!(i<0)){this.time=i;break t}i=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this.time=i,this._mixer.dispatchEvent({type:"finished",action:this,direction:t<0?-1:1})}}else{if(-1===r&&(t>=0?(r=0,this._setEndings(!0,0===this.repetitions,n)):this._setEndings(0===this.repetitions,!0,n)),i>=e||i<0){const s=Math.floor(i/e);i-=e*s,r+=Math.abs(s);const o=this.repetitions-r;if(o<=0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,i=t>0?e:0,this.time=i,this._mixer.dispatchEvent({type:"finished",action:this,direction:t>0?1:-1});else{if(1===o){const e=t<0;this._setEndings(e,!e,n)}else this._setEndings(!1,!1,n);this._loopCount=r,this.time=i,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:s})}}else this.time=i;if(n&&!(1&~r))return e-i}return i}_setEndings(t,e,s){const i=this._interpolantSettings;s?(i.endingStart=Fe,i.endingEnd=Fe):(i.endingStart=t?this.zeroSlopeAtStart?Fe:Oe:Ne,i.endingEnd=e?this.zeroSlopeAtEnd?Fe:Oe:Ne)}_scheduleFading(t,e,s){const i=this._mixer,r=i.time;let n=this._weightInterpolant;null===n&&(n=i._lendControlInterpolant(),this._weightInterpolant=n);const o=n.parameterPositions,a=n.sampleValues;return o[0]=r,a[0]=e,o[1]=r+t,a[1]=s,this}}const vu=new Float32Array(1);class wu extends Ns{constructor(t){super(),this._root=t,this._initMemoryManager(),this._accuIndex=0,this.time=0,this.timeScale=1}_bindAction(t,e){const s=t._localRoot||this._root,i=t._clip.tracks,r=i.length,n=t._propertyBindings,o=t._interpolants,a=s.uuid,h=this._bindingsByRootAndName;let l=h[a];void 0===l&&(l={},h[a]=l);for(let t=0;t!==r;++t){const r=i[t],h=r.name;let c=l[h];if(void 0!==c)++c.referenceCount,n[t]=c;else{if(c=n[t],void 0!==c){null===c._cacheIndex&&(++c.referenceCount,this._addInactiveBinding(c,a,h));continue}const i=e&&e._propertyBindings[t].binding.parsedPath;c=new cu(gu.create(s,h,i),r.ValueTypeName,r.getValueSize()),++c.referenceCount,this._addInactiveBinding(c,a,h),n[t]=c}o[t].resultBuffer=c.buffer}}_activateAction(t){if(!this._isActiveAction(t)){if(null===t._cacheIndex){const e=(t._localRoot||this._root).uuid,s=t._clip.uuid,i=this._actionsByClip[s];this._bindAction(t,i&&i.knownActions[0]),this._addInactiveAction(t,s,e)}const e=t._propertyBindings;for(let t=0,s=e.length;t!==s;++t){const s=e[t];0==s.useCount++&&(this._lendBinding(s),s.saveOriginalState())}this._lendAction(t)}}_deactivateAction(t){if(this._isActiveAction(t)){const e=t._propertyBindings;for(let t=0,s=e.length;t!==s;++t){const s=e[t];0==--s.useCount&&(s.restoreOriginalState(),this._takeBackBinding(s))}this._takeBackAction(t)}}_initMemoryManager(){this._actions=[],this._nActiveActions=0,this._actionsByClip={},this._bindings=[],this._nActiveBindings=0,this._bindingsByRootAndName={},this._controlInterpolants=[],this._nActiveControlInterpolants=0;const t=this;this.stats={actions:{get total(){return t._actions.length},get inUse(){return t._nActiveActions}},bindings:{get total(){return t._bindings.length},get inUse(){return t._nActiveBindings}},controlInterpolants:{get total(){return t._controlInterpolants.length},get inUse(){return t._nActiveControlInterpolants}}}}_isActiveAction(t){const e=t._cacheIndex;return null!==e&&e=0;--e)t[e].stop();return this}update(t){t*=this.timeScale;const e=this._actions,s=this._nActiveActions,i=this.time+=t,r=Math.sign(t),n=this._accuIndex^=1;for(let o=0;o!==s;++o){e[o]._update(i,t,r,n)}const o=this._bindings,a=this._nActiveBindings;for(let t=0;t!==a;++t)o[t].apply(n);return this}setTime(t){this.time=0;for(let t=0;t=this.min.x&&t.x<=this.max.x&&t.y>=this.min.y&&t.y<=this.max.y}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y))}intersectsBox(t){return t.max.x>=this.min.x&&t.min.x<=this.max.x&&t.max.y>=this.min.y&&t.min.y<=this.max.y}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return this.clampPoint(t,Ru).distanceTo(t)}intersect(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&&this.makeEmpty(),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}}const Fu=new Ii,Nu=new Ii;class Lu{constructor(t=new Ii,e=new Ii){this.start=t,this.end=e}set(t,e){return this.start.copy(t),this.end.copy(e),this}copy(t){return this.start.copy(t.start),this.end.copy(t.end),this}getCenter(t){return t.addVectors(this.start,this.end).multiplyScalar(.5)}delta(t){return t.subVectors(this.end,this.start)}distanceSq(){return this.start.distanceToSquared(this.end)}distance(){return this.start.distanceTo(this.end)}at(t,e){return this.delta(e).multiplyScalar(t).add(this.start)}closestPointToPointParameter(t,e){Fu.subVectors(t,this.start),Nu.subVectors(this.end,this.start);const s=Nu.dot(Nu);let i=Nu.dot(Fu)/s;return e&&(i=Ds(i,0,1)),i}closestPointToPoint(t,e,s){const i=this.closestPointToPointParameter(t,e);return this.delta(s).multiplyScalar(i).add(this.start)}applyMatrix4(t){return this.start.applyMatrix4(t),this.end.applyMatrix4(t),this}equals(t){return t.start.equals(this.start)&&t.end.equals(this.end)}clone(){return(new this.constructor).copy(this)}}const Vu=new Ii;class Wu extends Er{constructor(t,e){super(),this.light=t,this.matrixAutoUpdate=!1,this.color=e,this.type="SpotLightHelper";const s=new zn,i=[0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,-1,0,1,0,0,0,0,1,1,0,0,0,0,-1,1];for(let t=0,e=1,s=32;t1)for(let s=0;s.99999)this.quaternion.set(0,0,0,1);else if(t.y<-.99999)this.quaternion.set(1,0,0,0);else{ud.set(t.z,0,-t.x).normalize();const e=Math.acos(t.y);this.quaternion.setFromAxisAngle(ud,e)}}setLength(t,e=.2*t,s=.2*e){this.line.scale.set(1,Math.max(1e-4,t-e),1),this.line.updateMatrix(),this.cone.scale.set(s,e,s),this.cone.position.y=t,this.cone.updateMatrix()}setColor(t){this.line.material.color.set(t),this.cone.material.color.set(t)}copy(t){return super.copy(t,!1),this.line.copy(t.line),this.cone.copy(t.cone),this}dispose(){this.line.geometry.dispose(),this.line.material.dispose(),this.cone.geometry.dispose(),this.cone.material.dispose()}}class yd extends Oa{constructor(t=1){const e=[0,0,0,t,0,0,0,0,0,0,t,0,0,0,0,0,0,t],s=new zn;s.setAttribute("position",new bn(e,3)),s.setAttribute("color",new bn([1,0,0,1,.6,0,0,1,0,.6,1,0,0,0,1,0,.6,1],3));super(s,new Sa({vertexColors:!0,toneMapped:!1})),this.type="AxesHelper"}setColors(t,e,s){const i=new $r,r=this.geometry.attributes.color.array;return i.set(t),i.toArray(r,0),i.toArray(r,3),i.set(e),i.toArray(r,6),i.toArray(r,9),i.set(s),i.toArray(r,12),i.toArray(r,15),this.geometry.attributes.color.needsUpdate=!0,this}dispose(){this.geometry.dispose(),this.material.dispose()}}class fd{constructor(){this.type="ShapePath",this.color=new $r,this.subPaths=[],this.currentPath=null}moveTo(t,e){return this.currentPath=new bh,this.subPaths.push(this.currentPath),this.currentPath.moveTo(t,e),this}lineTo(t,e){return this.currentPath.lineTo(t,e),this}quadraticCurveTo(t,e,s,i){return this.currentPath.quadraticCurveTo(t,e,s,i),this}bezierCurveTo(t,e,s,i,r,n){return this.currentPath.bezierCurveTo(t,e,s,i,r,n),this}splineThru(t){return this.currentPath.splineThru(t),this}toShapes(t){function e(t,e){const s=e.length;let i=!1;for(let r=s-1,n=0;nNumber.EPSILON){if(h<0&&(s=e[n],a=-a,o=e[r],h=-h),t.yo.y)continue;if(t.y===s.y){if(t.x===s.x)return!0}else{const e=h*(t.x-s.x)-a*(t.y-s.y);if(0===e)return!0;if(e<0)continue;i=!i}}else{if(t.y!==s.y)continue;if(o.x<=t.x&&t.x<=s.x||s.x<=t.x&&t.x<=o.x)return!0}}return i}const s=rl.isClockWise,i=this.subPaths;if(0===i.length)return[];let r,n,o;const a=[];if(1===i.length)return n=i[0],o=new Eh,o.curves=n.curves,a.push(o),a;let h=!s(i[0].getPoints());h=t?!h:h;const l=[],c=[];let u,d,p=[],m=0;c[m]=void 0,p[m]=[];for(let e=0,o=i.length;e1){let t=!1,s=0;for(let t=0,e=c.length;t0&&!1===t&&(p=l)}for(let t=0,e=c.length;te?(t.repeat.x=1,t.repeat.y=s/e,t.offset.x=0,t.offset.y=(1-t.repeat.y)/2):(t.repeat.x=e/s,t.repeat.y=1,t.offset.x=(1-t.repeat.x)/2,t.offset.y=0),t},cover:function(t,e){const s=t.image&&t.image.width?t.image.width/t.image.height:1;return s>e?(t.repeat.x=e/s,t.repeat.y=1,t.offset.x=(1-t.repeat.x)/2,t.offset.y=0):(t.repeat.x=1,t.repeat.y=s/e,t.offset.x=0,t.offset.y=(1-t.repeat.y)/2),t},fill:function(t){return t.repeat.x=1,t.repeat.y=1,t.offset.x=0,t.offset.y=0,t},getByteLength:xd};"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("register",{detail:{revision:t}})),"undefined"!=typeof window&&(window.__THREE__?console.warn("WARNING: Multiple instances of Three.js being imported."):window.__THREE__=t);export{et as ACESFilmicToneMapping,v as AddEquation,G as AddOperation,Ve as AdditiveAnimationBlendMode,f as AdditiveBlending,it as AgXToneMapping,Lt as AlphaFormat,Ss as AlwaysCompare,j as AlwaysDepth,ys as AlwaysStencilFunc,Ic as AmbientLight,bu as AnimationAction,Ql as AnimationClip,ac as AnimationLoader,wu as AnimationMixer,xu as AnimationObjectGroup,Vl as AnimationUtils,th as ArcCurve,Zc as ArrayCamera,md as ArrowHelper,nt as AttachedBindMode,iu as Audio,lu as AudioAnalyser,Dc as AudioContext,su as AudioListener,Hc as AudioLoader,yd as AxesHelper,d as BackSide,De as BasicDepthPacking,a as BasicShadowMap,Ma as BatchedMesh,Lo as Bone,ql as BooleanKeyframeTrack,Ou as Box2,Ei as Box3,ld as Box3Helper,jn as BoxGeometry,hd as BoxHelper,cn as BufferAttribute,zn as BufferGeometry,Fc as BufferGeometryLoader,zt as ByteType,tc as Cache,Xn as Camera,nd as CameraHelper,Ga as CanvasTexture,wh as CapsuleGeometry,oh as CatmullRomCurve3,tt as CineonToneMapping,Mh as CircleGeometry,mt as ClampToEdgeWrapping,Gc as Clock,$r as Color,Jl as ColorKeyframeTrack,ui as ColorManagement,Ya as CompressedArrayTexture,Za as CompressedCubeTexture,Xa as CompressedTexture,hc as CompressedTextureLoader,_h as ConeGeometry,L as ConstantAlphaFactor,F as ConstantColorFactor,gd as Controls,Kn as CubeCamera,ht as CubeReflectionMapping,lt as CubeRefractionMapping,to as CubeTexture,cc as CubeTextureLoader,dt as CubeUVReflectionMapping,ch as CubicBezierCurve,uh as CubicBezierCurve3,jl as CubicInterpolant,r as CullFaceBack,n as CullFaceFront,o as CullFaceFrontBack,i as CullFaceNone,Qa as Curve,xh as CurvePath,b as CustomBlending,st as CustomToneMapping,Sh as CylinderGeometry,Eu as Cylindrical,Ti as Data3DTexture,_i as DataArrayTexture,Vo as DataTexture,uc as DataTextureLoader,an as DataUtils,rs as DecrementStencilOp,os as DecrementWrapStencilOp,sc as DefaultLoadingManager,Dt as DepthFormat,Ht as DepthStencilFormat,$a as DepthTexture,ot as DetachedBindMode,Cc as DirectionalLight,sd as DirectionalLightHelper,Dl as DiscreteInterpolant,Th as DodecahedronGeometry,p as DoubleSide,k as DstAlphaFactor,P as DstColorFactor,ks as DynamicCopyUsage,As as DynamicDrawUsage,Cs as DynamicReadUsage,kh as EdgesGeometry,Ka as EllipseCurve,xs as EqualCompare,H as EqualDepth,cs as EqualStencilFunc,ct as EquirectangularReflectionMapping,ut as EquirectangularRefractionMapping,yr as Euler,Ns as EventDispatcher,al as ExtrudeGeometry,oc as FileLoader,xn as Float16BufferAttribute,bn as Float32BufferAttribute,Et as FloatType,io as Fog,so as FogExp2,Ja as FramebufferTexture,u as FrontSide,ra as Frustum,Tu as GLBufferAttribute,Ps as GLSL1,Rs as GLSL3,vs as GreaterCompare,J as GreaterDepth,Ms as GreaterEqualCompare,q as GreaterEqualDepth,ms as GreaterEqualStencilFunc,ds as GreaterStencilFunc,$u as GridHelper,Ha as Group,Pt as HalfFloatType,mc as HemisphereLight,Gu as HemisphereLightHelper,ll as IcosahedronGeometry,jc as ImageBitmapLoader,lc as ImageLoader,yi as ImageUtils,is as IncrementStencilOp,ns as IncrementWrapStencilOp,Do as InstancedBufferAttribute,Oc as InstancedBufferGeometry,Au as InstancedInterleavedBuffer,$o as InstancedMesh,mn as Int16BufferAttribute,fn as Int32BufferAttribute,un as Int8BufferAttribute,Bt as IntType,no as InterleavedBuffer,ao as InterleavedBufferAttribute,Wl as Interpolant,Ee as InterpolateDiscrete,Pe as InterpolateLinear,Re as InterpolateSmooth,as as InvertStencilOp,es as KeepStencilOp,Hl as KeyframeTrack,zo as LOD,vh as LatheGeometry,fr as Layers,gs as LessCompare,U as LessDepth,bs as LessEqualCompare,D as LessEqualDepth,us as LessEqualStencilFunc,ls as LessStencilFunc,pc as Light,Ec as LightProbe,ka as Line,Lu as Line3,Sa as LineBasicMaterial,dh as LineCurve,ph as LineCurve3,Pl as LineDashedMaterial,Fa as LineLoop,Oa as LineSegments,wt as LinearFilter,Ul as LinearInterpolant,At as LinearMipMapLinearFilter,St as LinearMipMapNearestFilter,_t as LinearMipmapLinearFilter,Mt as LinearMipmapNearestFilter,$e as LinearSRGBColorSpace,Q as LinearToneMapping,Qe as LinearTransfer,ic as Loader,Rc as LoaderUtils,ec as LoadingManager,Ie as LoopOnce,ke as LoopPingPong,Be as LoopRepeat,Ut as LuminanceAlphaFormat,jt as LuminanceFormat,e as MOUSE,tn as Material,Pc as MaterialLoader,Ys as MathUtils,Pu as Matrix2,Gs as Matrix3,nr as Matrix4,_ as MaxEquation,Vn as Mesh,en as MeshBasicMaterial,Bl as MeshDepthMaterial,kl as MeshDistanceMaterial,Il as MeshLambertMaterial,El as MeshMatcapMaterial,Cl as MeshNormalMaterial,Tl as MeshPhongMaterial,Al as MeshPhysicalMaterial,_l as MeshStandardMaterial,zl as MeshToonMaterial,S as MinEquation,yt as MirroredRepeatWrapping,Z as MixOperation,x as MultiplyBlending,Y as MultiplyOperation,ft as NearestFilter,vt as NearestMipMapLinearFilter,xt as NearestMipMapNearestFilter,bt as NearestMipmapLinearFilter,gt as NearestMipmapNearestFilter,rt as NeutralToneMapping,fs as NeverCompare,W as NeverDepth,hs as NeverStencilFunc,m as NoBlending,Ze as NoColorSpace,$ as NoToneMapping,Le as NormalAnimationBlendMode,y as NormalBlending,ws as NotEqualCompare,X as NotEqualDepth,ps as NotEqualStencilFunc,Xl as NumberKeyframeTrack,Er as Object3D,Nc as ObjectLoader,Ye as ObjectSpaceNormalMap,cl as OctahedronGeometry,T as OneFactor,V as OneMinusConstantAlphaFactor,N as OneMinusConstantColorFactor,E as OneMinusDstAlphaFactor,R as OneMinusDstColorFactor,B as OneMinusSrcAlphaFactor,C as OneMinusSrcColorFactor,Tc as OrthographicCamera,h as PCFShadowMap,l as PCFSoftShadowMap,bh as Path,$n as PerspectiveCamera,ea as Plane,ul as PlaneGeometry,cd as PlaneHelper,Ac as PointLight,Ju as PointLightHelper,Ua as Points,Na as PointsMaterial,Qu as PolarGridHelper,Ah as PolyhedronGeometry,hu as PositionalAudio,gu as PropertyBinding,cu as PropertyMixer,mh as QuadraticBezierCurve,yh as QuadraticBezierCurve3,Ci as Quaternion,Zl as QuaternionKeyframeTrack,Yl as QuaternionLinearInterpolant,js as RAD2DEG,ze as RED_GREEN_RGTC2_Format,Ae as RED_RGTC1_Format,t as REVISION,He as RGBADepthPacking,Wt as RGBAFormat,Gt as RGBAIntegerFormat,be as RGBA_ASTC_10x10_Format,fe as RGBA_ASTC_10x5_Format,ge as RGBA_ASTC_10x6_Format,xe as RGBA_ASTC_10x8_Format,ve as RGBA_ASTC_12x10_Format,we as RGBA_ASTC_12x12_Format,he as RGBA_ASTC_4x4_Format,le as RGBA_ASTC_5x4_Format,ce as RGBA_ASTC_5x5_Format,ue as RGBA_ASTC_6x5_Format,de as RGBA_ASTC_6x6_Format,pe as RGBA_ASTC_8x5_Format,me as RGBA_ASTC_8x6_Format,ye as RGBA_ASTC_8x8_Format,Me as RGBA_BPTC_Format,ae as RGBA_ETC2_EAC_Format,re as RGBA_PVRTC_2BPPV1_Format,ie as RGBA_PVRTC_4BPPV1_Format,Qt as RGBA_S3TC_DXT1_Format,Kt as RGBA_S3TC_DXT3_Format,te as RGBA_S3TC_DXT5_Format,qe as RGBDepthPacking,Vt as RGBFormat,Zt as RGBIntegerFormat,Se as RGB_BPTC_SIGNED_Format,_e as RGB_BPTC_UNSIGNED_Format,ne as RGB_ETC1_Format,oe as RGB_ETC2_Format,se as RGB_PVRTC_2BPPV1_Format,ee as RGB_PVRTC_4BPPV1_Format,$t as RGB_S3TC_DXT1_Format,Je as RGDepthPacking,Xt as RGFormat,Yt as RGIntegerFormat,Sl as RawShaderMaterial,rr as Ray,Cu as Raycaster,Bc as RectAreaLight,qt as RedFormat,Jt as RedIntegerFormat,K as ReinhardToneMapping,Mi as RenderTarget,pt as RepeatWrapping,ss as ReplaceStencilOp,M as ReverseSubtractEquation,dl as RingGeometry,Ce as SIGNED_RED_GREEN_RGTC2_Format,Te as SIGNED_RED_RGTC1_Format,Ge as SRGBColorSpace,Ke as SRGBTransfer,ro as Scene,Jn as ShaderMaterial,Ml as ShadowMaterial,Eh as Shape,pl as ShapeGeometry,fd as ShapePath,rl as ShapeUtils,Ct as ShortType,Uo as Skeleton,Hu as SkeletonHelper,No as SkinnedMesh,gi as Source,Gi as Sphere,ml as SphereGeometry,ku as Spherical,kc as SphericalHarmonics3,fh as SplineCurve,vc as SpotLight,Wu as SpotLightHelper,So as Sprite,ho as SpriteMaterial,I as SrcAlphaFactor,O as SrcAlphaSaturateFactor,z as SrcColorFactor,Bs as StaticCopyUsage,_s as StaticDrawUsage,zs as StaticReadUsage,Yc as StereoCamera,Es as StreamCopyUsage,Ts as StreamDrawUsage,Is as StreamReadUsage,Gl as StringKeyframeTrack,w as SubtractEquation,g as SubtractiveBlending,s as TOUCH,Xe as TangentSpaceNormalMap,yl as TetrahedronGeometry,vi as Texture,dc as TextureLoader,bd as TextureUtils,fl as TorusGeometry,gl as TorusKnotGeometry,Jr as Triangle,Ue as TriangleFanDrawMode,je as TriangleStripDrawMode,We as TrianglesDrawMode,xl as TubeGeometry,at as UVMapping,yn as Uint16BufferAttribute,gn as Uint32BufferAttribute,dn as Uint8BufferAttribute,pn as Uint8ClampedBufferAttribute,Mu as Uniform,_u as UniformsGroup,qn as UniformsUtils,Tt as UnsignedByteType,Ft as UnsignedInt248Type,Nt as UnsignedInt5999Type,kt as UnsignedIntType,Rt as UnsignedShort4444Type,Ot as UnsignedShort5551Type,It as UnsignedShortType,c as VSMShadowMap,Zs as Vector2,Ii as Vector3,wi as Vector4,$l as VectorKeyframeTrack,qa as VideoTexture,zi as WebGL3DRenderTarget,Ai as WebGLArrayRenderTarget,Os as WebGLCoordinateSystem,eo as WebGLCubeRenderTarget,Si as WebGLRenderTarget,Fs as WebGPUCoordinateSystem,bl as WireframeGeometry,Ne as WrapAroundEnding,Oe as ZeroCurvatureEnding,A as ZeroFactor,Fe as ZeroSlopeEnding,ts as ZeroStencilOp,Qs as arrayNeedsUint32,Un as cloneUniforms,si as createCanvasElement,ei as createElementNS,xd as getByteLength,Hn as getUnlitUniformColorSpace,Dn as mergeUniforms,ni as probeAsync,oi as toNormalizedProjectionMatrix,ai as toReversedProjectionMatrix,ri as warnOnce}; +const t="173dev",e={LEFT:0,MIDDLE:1,RIGHT:2,ROTATE:0,DOLLY:1,PAN:2},s={ROTATE:0,PAN:1,DOLLY_PAN:2,DOLLY_ROTATE:3},i=0,r=1,n=2,o=3,a=0,h=1,l=2,c=3,u=0,d=1,p=2,m=0,y=1,f=2,g=3,x=4,b=5,v=100,w=101,M=102,S=103,_=104,A=200,T=201,z=202,C=203,I=204,B=205,k=206,R=207,E=208,P=209,O=210,F=211,N=212,L=213,V=214,W=0,j=1,U=2,D=3,H=4,q=5,J=6,X=7,Y=0,Z=1,G=2,$=0,Q=1,K=2,tt=3,et=4,st=5,it=6,rt=7,nt="attached",ot="detached",at=300,ht=301,lt=302,ct=303,ut=304,dt=306,pt=1e3,mt=1001,yt=1002,ft=1003,gt=1004,xt=1004,bt=1005,vt=1005,wt=1006,Mt=1007,St=1007,_t=1008,At=1008,Tt=1009,zt=1010,Ct=1011,It=1012,Bt=1013,kt=1014,Rt=1015,Et=1016,Pt=1017,Ot=1018,Ft=1020,Nt=35902,Lt=1021,Vt=1022,Wt=1023,jt=1024,Ut=1025,Dt=1026,Ht=1027,qt=1028,Jt=1029,Xt=1030,Yt=1031,Zt=1032,Gt=1033,$t=33776,Qt=33777,Kt=33778,te=33779,ee=35840,se=35841,ie=35842,re=35843,ne=36196,oe=37492,ae=37496,he=37808,le=37809,ce=37810,ue=37811,de=37812,pe=37813,me=37814,ye=37815,fe=37816,ge=37817,xe=37818,be=37819,ve=37820,we=37821,Me=36492,Se=36494,_e=36495,Ae=36283,Te=36284,ze=36285,Ce=36286,Ie=2200,Be=2201,ke=2202,Re=2300,Ee=2301,Pe=2302,Oe=2400,Fe=2401,Ne=2402,Le=2500,Ve=2501,We=0,je=1,Ue=2,De=3200,He=3201,qe=3202,Je=3203,Xe=0,Ye=1,Ze="",Ge="srgb",$e="srgb-linear",Qe="linear",Ke="srgb",ts=0,es=7680,ss=7681,is=7682,rs=7683,ns=34055,os=34056,as=5386,hs=512,ls=513,cs=514,us=515,ds=516,ps=517,ms=518,ys=519,fs=512,gs=513,xs=514,bs=515,vs=516,ws=517,Ms=518,Ss=519,_s=35044,As=35048,Ts=35040,zs=35045,Cs=35049,Is=35041,Bs=35046,ks=35050,Rs=35042,Es="100",Ps="300 es",Os=2e3,Fs=2001;class Ns{addEventListener(t,e){void 0===this._listeners&&(this._listeners={});const s=this._listeners;void 0===s[t]&&(s[t]=[]),-1===s[t].indexOf(e)&&s[t].push(e)}hasEventListener(t,e){if(void 0===this._listeners)return!1;const s=this._listeners;return void 0!==s[t]&&-1!==s[t].indexOf(e)}removeEventListener(t,e){if(void 0===this._listeners)return;const s=this._listeners[t];if(void 0!==s){const t=s.indexOf(e);-1!==t&&s.splice(t,1)}}dispatchEvent(t){if(void 0===this._listeners)return;const e=this._listeners[t.type];if(void 0!==e){t.target=this;const s=e.slice(0);for(let e=0,i=s.length;e>8&255]+Ls[t>>16&255]+Ls[t>>24&255]+"-"+Ls[255&e]+Ls[e>>8&255]+"-"+Ls[e>>16&15|64]+Ls[e>>24&255]+"-"+Ls[63&s|128]+Ls[s>>8&255]+"-"+Ls[s>>16&255]+Ls[s>>24&255]+Ls[255&i]+Ls[i>>8&255]+Ls[i>>16&255]+Ls[i>>24&255]).toLowerCase()}function Ds(t,e,s){return Math.max(e,Math.min(s,t))}function Hs(t,e){return(t%e+e)%e}function qs(t,e,s){return(1-s)*t+s*e}function Js(t,e){switch(e.constructor){case Float32Array:return t;case Uint32Array:return t/4294967295;case Uint16Array:return t/65535;case Uint8Array:return t/255;case Int32Array:return Math.max(t/2147483647,-1);case Int16Array:return Math.max(t/32767,-1);case Int8Array:return Math.max(t/127,-1);default:throw new Error("Invalid component type.")}}function Xs(t,e){switch(e.constructor){case Float32Array:return t;case Uint32Array:return Math.round(4294967295*t);case Uint16Array:return Math.round(65535*t);case Uint8Array:return Math.round(255*t);case Int32Array:return Math.round(2147483647*t);case Int16Array:return Math.round(32767*t);case Int8Array:return Math.round(127*t);default:throw new Error("Invalid component type.")}}const Ys={DEG2RAD:Ws,RAD2DEG:js,generateUUID:Us,clamp:Ds,euclideanModulo:Hs,mapLinear:function(t,e,s,i,r){return i+(t-e)*(r-i)/(s-e)},inverseLerp:function(t,e,s){return t!==e?(s-t)/(e-t):0},lerp:qs,damp:function(t,e,s,i){return qs(t,e,1-Math.exp(-s*i))},pingpong:function(t,e=1){return e-Math.abs(Hs(t,2*e)-e)},smoothstep:function(t,e,s){return t<=e?0:t>=s?1:(t=(t-e)/(s-e))*t*(3-2*t)},smootherstep:function(t,e,s){return t<=e?0:t>=s?1:(t=(t-e)/(s-e))*t*t*(t*(6*t-15)+10)},randInt:function(t,e){return t+Math.floor(Math.random()*(e-t+1))},randFloat:function(t,e){return t+Math.random()*(e-t)},randFloatSpread:function(t){return t*(.5-Math.random())},seededRandom:function(t){void 0!==t&&(Vs=t);let e=Vs+=1831565813;return e=Math.imul(e^e>>>15,1|e),e^=e+Math.imul(e^e>>>7,61|e),((e^e>>>14)>>>0)/4294967296},degToRad:function(t){return t*Ws},radToDeg:function(t){return t*js},isPowerOfTwo:function(t){return!(t&t-1)&&0!==t},ceilPowerOfTwo:function(t){return Math.pow(2,Math.ceil(Math.log(t)/Math.LN2))},floorPowerOfTwo:function(t){return Math.pow(2,Math.floor(Math.log(t)/Math.LN2))},setQuaternionFromProperEuler:function(t,e,s,i,r){const n=Math.cos,o=Math.sin,a=n(s/2),h=o(s/2),l=n((e+i)/2),c=o((e+i)/2),u=n((e-i)/2),d=o((e-i)/2),p=n((i-e)/2),m=o((i-e)/2);switch(r){case"XYX":t.set(a*c,h*u,h*d,a*l);break;case"YZY":t.set(h*d,a*c,h*u,a*l);break;case"ZXZ":t.set(h*u,h*d,a*c,a*l);break;case"XZX":t.set(a*c,h*m,h*p,a*l);break;case"YXY":t.set(h*p,a*c,h*m,a*l);break;case"ZYZ":t.set(h*m,h*p,a*c,a*l);break;default:console.warn("THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: "+r)}},normalize:Xs,denormalize:Js};class Zs{constructor(t=0,e=0){Zs.prototype.isVector2=!0,this.x=t,this.y=e}get width(){return this.x}set width(t){this.x=t}get height(){return this.y}set height(t){this.y=t}set(t,e){return this.x=t,this.y=e,this}setScalar(t){return this.x=t,this.y=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y)}copy(t){return this.x=t.x,this.y=t.y,this}add(t){return this.x+=t.x,this.y+=t.y,this}addScalar(t){return this.x+=t,this.y+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this}subScalar(t){return this.x-=t,this.y-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this}multiply(t){return this.x*=t.x,this.y*=t.y,this}multiplyScalar(t){return this.x*=t,this.y*=t,this}divide(t){return this.x/=t.x,this.y/=t.y,this}divideScalar(t){return this.multiplyScalar(1/t)}applyMatrix3(t){const e=this.x,s=this.y,i=t.elements;return this.x=i[0]*e+i[3]*s+i[6],this.y=i[1]*e+i[4]*s+i[7],this}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this}clamp(t,e){return this.x=Ds(this.x,t.x,e.x),this.y=Ds(this.y,t.y,e.y),this}clampScalar(t,e){return this.x=Ds(this.x,t,e),this.y=Ds(this.y,t,e),this}clampLength(t,e){const s=this.length();return this.divideScalar(s||1).multiplyScalar(Ds(s,t,e))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(t){return this.x*t.x+this.y*t.y}cross(t){return this.x*t.y-this.y*t.x}lengthSq(){return this.x*this.x+this.y*this.y}length(){return Math.sqrt(this.x*this.x+this.y*this.y)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)}normalize(){return this.divideScalar(this.length()||1)}angle(){return Math.atan2(-this.y,-this.x)+Math.PI}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(0===e)return Math.PI/2;const s=this.dot(t)/e;return Math.acos(Ds(s,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,s=this.y-t.y;return e*e+s*s}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this}lerpVectors(t,e,s){return this.x=t.x+(e.x-t.x)*s,this.y=t.y+(e.y-t.y)*s,this}equals(t){return t.x===this.x&&t.y===this.y}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this}rotateAround(t,e){const s=Math.cos(e),i=Math.sin(e),r=this.x-t.x,n=this.y-t.y;return this.x=r*s-n*i+t.x,this.y=r*i+n*s+t.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class Gs{constructor(t,e,s,i,r,n,o,a,h){Gs.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1],void 0!==t&&this.set(t,e,s,i,r,n,o,a,h)}set(t,e,s,i,r,n,o,a,h){const l=this.elements;return l[0]=t,l[1]=i,l[2]=o,l[3]=e,l[4]=r,l[5]=a,l[6]=s,l[7]=n,l[8]=h,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(t){const e=this.elements,s=t.elements;return e[0]=s[0],e[1]=s[1],e[2]=s[2],e[3]=s[3],e[4]=s[4],e[5]=s[5],e[6]=s[6],e[7]=s[7],e[8]=s[8],this}extractBasis(t,e,s){return t.setFromMatrix3Column(this,0),e.setFromMatrix3Column(this,1),s.setFromMatrix3Column(this,2),this}setFromMatrix4(t){const e=t.elements;return this.set(e[0],e[4],e[8],e[1],e[5],e[9],e[2],e[6],e[10]),this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const s=t.elements,i=e.elements,r=this.elements,n=s[0],o=s[3],a=s[6],h=s[1],l=s[4],c=s[7],u=s[2],d=s[5],p=s[8],m=i[0],y=i[3],f=i[6],g=i[1],x=i[4],b=i[7],v=i[2],w=i[5],M=i[8];return r[0]=n*m+o*g+a*v,r[3]=n*y+o*x+a*w,r[6]=n*f+o*b+a*M,r[1]=h*m+l*g+c*v,r[4]=h*y+l*x+c*w,r[7]=h*f+l*b+c*M,r[2]=u*m+d*g+p*v,r[5]=u*y+d*x+p*w,r[8]=u*f+d*b+p*M,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[3]*=t,e[6]*=t,e[1]*=t,e[4]*=t,e[7]*=t,e[2]*=t,e[5]*=t,e[8]*=t,this}determinant(){const t=this.elements,e=t[0],s=t[1],i=t[2],r=t[3],n=t[4],o=t[5],a=t[6],h=t[7],l=t[8];return e*n*l-e*o*h-s*r*l+s*o*a+i*r*h-i*n*a}invert(){const t=this.elements,e=t[0],s=t[1],i=t[2],r=t[3],n=t[4],o=t[5],a=t[6],h=t[7],l=t[8],c=l*n-o*h,u=o*a-l*r,d=h*r-n*a,p=e*c+s*u+i*d;if(0===p)return this.set(0,0,0,0,0,0,0,0,0);const m=1/p;return t[0]=c*m,t[1]=(i*h-l*s)*m,t[2]=(o*s-i*n)*m,t[3]=u*m,t[4]=(l*e-i*a)*m,t[5]=(i*r-o*e)*m,t[6]=d*m,t[7]=(s*a-h*e)*m,t[8]=(n*e-s*r)*m,this}transpose(){let t;const e=this.elements;return t=e[1],e[1]=e[3],e[3]=t,t=e[2],e[2]=e[6],e[6]=t,t=e[5],e[5]=e[7],e[7]=t,this}getNormalMatrix(t){return this.setFromMatrix4(t).invert().transpose()}transposeIntoArray(t){const e=this.elements;return t[0]=e[0],t[1]=e[3],t[2]=e[6],t[3]=e[1],t[4]=e[4],t[5]=e[7],t[6]=e[2],t[7]=e[5],t[8]=e[8],this}setUvTransform(t,e,s,i,r,n,o){const a=Math.cos(r),h=Math.sin(r);return this.set(s*a,s*h,-s*(a*n+h*o)+n+t,-i*h,i*a,-i*(-h*n+a*o)+o+e,0,0,1),this}scale(t,e){return this.premultiply($s.makeScale(t,e)),this}rotate(t){return this.premultiply($s.makeRotation(-t)),this}translate(t,e){return this.premultiply($s.makeTranslation(t,e)),this}makeTranslation(t,e){return t.isVector2?this.set(1,0,t.x,0,1,t.y,0,0,1):this.set(1,0,t,0,1,e,0,0,1),this}makeRotation(t){const e=Math.cos(t),s=Math.sin(t);return this.set(e,-s,0,s,e,0,0,0,1),this}makeScale(t,e){return this.set(t,0,0,0,e,0,0,0,1),this}equals(t){const e=this.elements,s=t.elements;for(let t=0;t<9;t++)if(e[t]!==s[t])return!1;return!0}fromArray(t,e=0){for(let s=0;s<9;s++)this.elements[s]=t[s+e];return this}toArray(t=[],e=0){const s=this.elements;return t[e]=s[0],t[e+1]=s[1],t[e+2]=s[2],t[e+3]=s[3],t[e+4]=s[4],t[e+5]=s[5],t[e+6]=s[6],t[e+7]=s[7],t[e+8]=s[8],t}clone(){return(new this.constructor).fromArray(this.elements)}}const $s=new Gs;function Qs(t){for(let e=t.length-1;e>=0;--e)if(t[e]>=65535)return!0;return!1}const Ks={Int8Array:Int8Array,Uint8Array:Uint8Array,Uint8ClampedArray:Uint8ClampedArray,Int16Array:Int16Array,Uint16Array:Uint16Array,Int32Array:Int32Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array};function ti(t,e){return new Ks[t](e)}function ei(t){return document.createElementNS("http://www.w3.org/1999/xhtml",t)}function si(){const t=ei("canvas");return t.style.display="block",t}const ii={};function ri(t){t in ii||(ii[t]=!0,console.warn(t))}function ni(t,e,s){return new Promise((function(i,r){setTimeout((function n(){switch(t.clientWaitSync(e,t.SYNC_FLUSH_COMMANDS_BIT,0)){case t.WAIT_FAILED:r();break;case t.TIMEOUT_EXPIRED:setTimeout(n,s);break;default:i()}}),s)}))}function oi(t){const e=t.elements;e[2]=.5*e[2]+.5*e[3],e[6]=.5*e[6]+.5*e[7],e[10]=.5*e[10]+.5*e[11],e[14]=.5*e[14]+.5*e[15]}function ai(t){const e=t.elements;-1===e[11]?(e[10]=-e[10]-1,e[14]=-e[14]):(e[10]=-e[10],e[14]=1-e[14])}const hi=(new Gs).set(.4123908,.3575843,.1804808,.212639,.7151687,.0721923,.0193308,.1191948,.9505322),li=(new Gs).set(3.2409699,-1.5373832,-.4986108,-.9692436,1.8759675,.0415551,.0556301,-.203977,1.0569715);function ci(){const t={enabled:!0,workingColorSpace:$e,spaces:{},convert:function(t,e,s){return!1!==this.enabled&&e!==s&&e&&s?(this.spaces[e].transfer===Ke&&(t.r=di(t.r),t.g=di(t.g),t.b=di(t.b)),this.spaces[e].primaries!==this.spaces[s].primaries&&(t.applyMatrix3(this.spaces[e].toXYZ),t.applyMatrix3(this.spaces[s].fromXYZ)),this.spaces[s].transfer===Ke&&(t.r=pi(t.r),t.g=pi(t.g),t.b=pi(t.b)),t):t},fromWorkingColorSpace:function(t,e){return this.convert(t,this.workingColorSpace,e)},toWorkingColorSpace:function(t,e){return this.convert(t,e,this.workingColorSpace)},getPrimaries:function(t){return this.spaces[t].primaries},getTransfer:function(t){return""===t?Qe:this.spaces[t].transfer},getLuminanceCoefficients:function(t,e=this.workingColorSpace){return t.fromArray(this.spaces[e].luminanceCoefficients)},define:function(t){Object.assign(this.spaces,t)},_getMatrix:function(t,e,s){return t.copy(this.spaces[e].toXYZ).multiply(this.spaces[s].fromXYZ)},_getDrawingBufferColorSpace:function(t){return this.spaces[t].outputColorSpaceConfig.drawingBufferColorSpace},_getUnpackColorSpace:function(t=this.workingColorSpace){return this.spaces[t].workingColorSpaceConfig.unpackColorSpace}},e=[.64,.33,.3,.6,.15,.06],s=[.2126,.7152,.0722],i=[.3127,.329];return t.define({[$e]:{primaries:e,whitePoint:i,transfer:Qe,toXYZ:hi,fromXYZ:li,luminanceCoefficients:s,workingColorSpaceConfig:{unpackColorSpace:Ge},outputColorSpaceConfig:{drawingBufferColorSpace:Ge}},[Ge]:{primaries:e,whitePoint:i,transfer:Ke,toXYZ:hi,fromXYZ:li,luminanceCoefficients:s,outputColorSpaceConfig:{drawingBufferColorSpace:Ge}}}),t}const ui=ci();function di(t){return t<.04045?.0773993808*t:Math.pow(.9478672986*t+.0521327014,2.4)}function pi(t){return t<.0031308?12.92*t:1.055*Math.pow(t,.41666)-.055}let mi;class yi{static getDataURL(t){if(/^data:/i.test(t.src))return t.src;if("undefined"==typeof HTMLCanvasElement)return t.src;let e;if(t instanceof HTMLCanvasElement)e=t;else{void 0===mi&&(mi=ei("canvas")),mi.width=t.width,mi.height=t.height;const s=mi.getContext("2d");t instanceof ImageData?s.putImageData(t,0,0):s.drawImage(t,0,0,t.width,t.height),e=mi}return e.width>2048||e.height>2048?(console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons",t),e.toDataURL("image/jpeg",.6)):e.toDataURL("image/png")}static sRGBToLinear(t){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap){const e=ei("canvas");e.width=t.width,e.height=t.height;const s=e.getContext("2d");s.drawImage(t,0,0,t.width,t.height);const i=s.getImageData(0,0,t.width,t.height),r=i.data;for(let t=0;t0&&(s.userData=this.userData),e||(t.textures[this.uuid]=s),s}dispose(){this.dispatchEvent({type:"dispose"})}transformUv(t){if(this.mapping!==at)return t;if(t.applyMatrix3(this.matrix),t.x<0||t.x>1)switch(this.wrapS){case pt:t.x=t.x-Math.floor(t.x);break;case mt:t.x=t.x<0?0:1;break;case yt:1===Math.abs(Math.floor(t.x)%2)?t.x=Math.ceil(t.x)-t.x:t.x=t.x-Math.floor(t.x)}if(t.y<0||t.y>1)switch(this.wrapT){case pt:t.y=t.y-Math.floor(t.y);break;case mt:t.y=t.y<0?0:1;break;case yt:1===Math.abs(Math.floor(t.y)%2)?t.y=Math.ceil(t.y)-t.y:t.y=t.y-Math.floor(t.y)}return this.flipY&&(t.y=1-t.y),t}set needsUpdate(t){!0===t&&(this.version++,this.source.needsUpdate=!0)}set needsPMREMUpdate(t){!0===t&&this.pmremVersion++}}vi.DEFAULT_IMAGE=null,vi.DEFAULT_MAPPING=at,vi.DEFAULT_ANISOTROPY=1;class wi{constructor(t=0,e=0,s=0,i=1){wi.prototype.isVector4=!0,this.x=t,this.y=e,this.z=s,this.w=i}get width(){return this.z}set width(t){this.z=t}get height(){return this.w}set height(t){this.w=t}set(t,e,s,i){return this.x=t,this.y=e,this.z=s,this.w=i,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this.w=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setW(t){return this.w=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;case 3:this.w=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this.w=void 0!==t.w?t.w:1,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this.w+=t.w,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this.w+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this.w=t.w+e.w,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this.w+=t.w*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this.w-=t.w,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this.w-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this.w=t.w-e.w,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this.w*=t.w,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this.w*=t,this}applyMatrix4(t){const e=this.x,s=this.y,i=this.z,r=this.w,n=t.elements;return this.x=n[0]*e+n[4]*s+n[8]*i+n[12]*r,this.y=n[1]*e+n[5]*s+n[9]*i+n[13]*r,this.z=n[2]*e+n[6]*s+n[10]*i+n[14]*r,this.w=n[3]*e+n[7]*s+n[11]*i+n[15]*r,this}divide(t){return this.x/=t.x,this.y/=t.y,this.z/=t.z,this.w/=t.w,this}divideScalar(t){return this.multiplyScalar(1/t)}setAxisAngleFromQuaternion(t){this.w=2*Math.acos(t.w);const e=Math.sqrt(1-t.w*t.w);return e<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=t.x/e,this.y=t.y/e,this.z=t.z/e),this}setAxisAngleFromRotationMatrix(t){let e,s,i,r;const n=.01,o=.1,a=t.elements,h=a[0],l=a[4],c=a[8],u=a[1],d=a[5],p=a[9],m=a[2],y=a[6],f=a[10];if(Math.abs(l-u)a&&t>g?tg?a=0?1:-1,i=1-e*e;if(i>Number.EPSILON){const r=Math.sqrt(i),n=Math.atan2(r,e*s);t=Math.sin(t*n)/r,o=Math.sin(o*n)/r}const r=o*s;if(a=a*t+u*r,h=h*t+d*r,l=l*t+p*r,c=c*t+m*r,t===1-o){const t=1/Math.sqrt(a*a+h*h+l*l+c*c);a*=t,h*=t,l*=t,c*=t}}t[e]=a,t[e+1]=h,t[e+2]=l,t[e+3]=c}static multiplyQuaternionsFlat(t,e,s,i,r,n){const o=s[i],a=s[i+1],h=s[i+2],l=s[i+3],c=r[n],u=r[n+1],d=r[n+2],p=r[n+3];return t[e]=o*p+l*c+a*d-h*u,t[e+1]=a*p+l*u+h*c-o*d,t[e+2]=h*p+l*d+o*u-a*c,t[e+3]=l*p-o*c-a*u-h*d,t}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get w(){return this._w}set w(t){this._w=t,this._onChangeCallback()}set(t,e,s,i){return this._x=t,this._y=e,this._z=s,this._w=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(t){return this._x=t.x,this._y=t.y,this._z=t.z,this._w=t.w,this._onChangeCallback(),this}setFromEuler(t,e=!0){const s=t._x,i=t._y,r=t._z,n=t._order,o=Math.cos,a=Math.sin,h=o(s/2),l=o(i/2),c=o(r/2),u=a(s/2),d=a(i/2),p=a(r/2);switch(n){case"XYZ":this._x=u*l*c+h*d*p,this._y=h*d*c-u*l*p,this._z=h*l*p+u*d*c,this._w=h*l*c-u*d*p;break;case"YXZ":this._x=u*l*c+h*d*p,this._y=h*d*c-u*l*p,this._z=h*l*p-u*d*c,this._w=h*l*c+u*d*p;break;case"ZXY":this._x=u*l*c-h*d*p,this._y=h*d*c+u*l*p,this._z=h*l*p+u*d*c,this._w=h*l*c-u*d*p;break;case"ZYX":this._x=u*l*c-h*d*p,this._y=h*d*c+u*l*p,this._z=h*l*p-u*d*c,this._w=h*l*c+u*d*p;break;case"YZX":this._x=u*l*c+h*d*p,this._y=h*d*c+u*l*p,this._z=h*l*p-u*d*c,this._w=h*l*c-u*d*p;break;case"XZY":this._x=u*l*c-h*d*p,this._y=h*d*c-u*l*p,this._z=h*l*p+u*d*c,this._w=h*l*c+u*d*p;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+n)}return!0===e&&this._onChangeCallback(),this}setFromAxisAngle(t,e){const s=e/2,i=Math.sin(s);return this._x=t.x*i,this._y=t.y*i,this._z=t.z*i,this._w=Math.cos(s),this._onChangeCallback(),this}setFromRotationMatrix(t){const e=t.elements,s=e[0],i=e[4],r=e[8],n=e[1],o=e[5],a=e[9],h=e[2],l=e[6],c=e[10],u=s+o+c;if(u>0){const t=.5/Math.sqrt(u+1);this._w=.25/t,this._x=(l-a)*t,this._y=(r-h)*t,this._z=(n-i)*t}else if(s>o&&s>c){const t=2*Math.sqrt(1+s-o-c);this._w=(l-a)/t,this._x=.25*t,this._y=(i+n)/t,this._z=(r+h)/t}else if(o>c){const t=2*Math.sqrt(1+o-s-c);this._w=(r-h)/t,this._x=(i+n)/t,this._y=.25*t,this._z=(a+l)/t}else{const t=2*Math.sqrt(1+c-s-o);this._w=(n-i)/t,this._x=(r+h)/t,this._y=(a+l)/t,this._z=.25*t}return this._onChangeCallback(),this}setFromUnitVectors(t,e){let s=t.dot(e)+1;return sMath.abs(t.z)?(this._x=-t.y,this._y=t.x,this._z=0,this._w=s):(this._x=0,this._y=-t.z,this._z=t.y,this._w=s)):(this._x=t.y*e.z-t.z*e.y,this._y=t.z*e.x-t.x*e.z,this._z=t.x*e.y-t.y*e.x,this._w=s),this.normalize()}angleTo(t){return 2*Math.acos(Math.abs(Ds(this.dot(t),-1,1)))}rotateTowards(t,e){const s=this.angleTo(t);if(0===s)return this;const i=Math.min(1,e/s);return this.slerp(t,i),this}identity(){return this.set(0,0,0,1)}invert(){return this.conjugate()}conjugate(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this}dot(t){return this._x*t._x+this._y*t._y+this._z*t._z+this._w*t._w}lengthSq(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w}length(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)}normalize(){let t=this.length();return 0===t?(this._x=0,this._y=0,this._z=0,this._w=1):(t=1/t,this._x=this._x*t,this._y=this._y*t,this._z=this._z*t,this._w=this._w*t),this._onChangeCallback(),this}multiply(t){return this.multiplyQuaternions(this,t)}premultiply(t){return this.multiplyQuaternions(t,this)}multiplyQuaternions(t,e){const s=t._x,i=t._y,r=t._z,n=t._w,o=e._x,a=e._y,h=e._z,l=e._w;return this._x=s*l+n*o+i*h-r*a,this._y=i*l+n*a+r*o-s*h,this._z=r*l+n*h+s*a-i*o,this._w=n*l-s*o-i*a-r*h,this._onChangeCallback(),this}slerp(t,e){if(0===e)return this;if(1===e)return this.copy(t);const s=this._x,i=this._y,r=this._z,n=this._w;let o=n*t._w+s*t._x+i*t._y+r*t._z;if(o<0?(this._w=-t._w,this._x=-t._x,this._y=-t._y,this._z=-t._z,o=-o):this.copy(t),o>=1)return this._w=n,this._x=s,this._y=i,this._z=r,this;const a=1-o*o;if(a<=Number.EPSILON){const t=1-e;return this._w=t*n+e*this._w,this._x=t*s+e*this._x,this._y=t*i+e*this._y,this._z=t*r+e*this._z,this.normalize(),this}const h=Math.sqrt(a),l=Math.atan2(h,o),c=Math.sin((1-e)*l)/h,u=Math.sin(e*l)/h;return this._w=n*c+this._w*u,this._x=s*c+this._x*u,this._y=i*c+this._y*u,this._z=r*c+this._z*u,this._onChangeCallback(),this}slerpQuaternions(t,e,s){return this.copy(t).slerp(e,s)}random(){const t=2*Math.PI*Math.random(),e=2*Math.PI*Math.random(),s=Math.random(),i=Math.sqrt(1-s),r=Math.sqrt(s);return this.set(i*Math.sin(t),i*Math.cos(t),r*Math.sin(e),r*Math.cos(e))}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._w===this._w}fromArray(t,e=0){return this._x=t[e],this._y=t[e+1],this._z=t[e+2],this._w=t[e+3],this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._w,t}fromBufferAttribute(t,e){return this._x=t.getX(e),this._y=t.getY(e),this._z=t.getZ(e),this._w=t.getW(e),this._onChangeCallback(),this}toJSON(){return this.toArray()}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class Ii{constructor(t=0,e=0,s=0){Ii.prototype.isVector3=!0,this.x=t,this.y=e,this.z=s}set(t,e,s){return void 0===s&&(s=this.z),this.x=t,this.y=e,this.z=s,this}setScalar(t){return this.x=t,this.y=t,this.z=t,this}setX(t){return this.x=t,this}setY(t){return this.y=t,this}setZ(t){return this.z=t,this}setComponent(t,e){switch(t){case 0:this.x=e;break;case 1:this.y=e;break;case 2:this.z=e;break;default:throw new Error("index is out of range: "+t)}return this}getComponent(t){switch(t){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+t)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(t){return this.x=t.x,this.y=t.y,this.z=t.z,this}add(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this}addScalar(t){return this.x+=t,this.y+=t,this.z+=t,this}addVectors(t,e){return this.x=t.x+e.x,this.y=t.y+e.y,this.z=t.z+e.z,this}addScaledVector(t,e){return this.x+=t.x*e,this.y+=t.y*e,this.z+=t.z*e,this}sub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this}subScalar(t){return this.x-=t,this.y-=t,this.z-=t,this}subVectors(t,e){return this.x=t.x-e.x,this.y=t.y-e.y,this.z=t.z-e.z,this}multiply(t){return this.x*=t.x,this.y*=t.y,this.z*=t.z,this}multiplyScalar(t){return this.x*=t,this.y*=t,this.z*=t,this}multiplyVectors(t,e){return this.x=t.x*e.x,this.y=t.y*e.y,this.z=t.z*e.z,this}applyEuler(t){return this.applyQuaternion(ki.setFromEuler(t))}applyAxisAngle(t,e){return this.applyQuaternion(ki.setFromAxisAngle(t,e))}applyMatrix3(t){const e=this.x,s=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[3]*s+r[6]*i,this.y=r[1]*e+r[4]*s+r[7]*i,this.z=r[2]*e+r[5]*s+r[8]*i,this}applyNormalMatrix(t){return this.applyMatrix3(t).normalize()}applyMatrix4(t){const e=this.x,s=this.y,i=this.z,r=t.elements,n=1/(r[3]*e+r[7]*s+r[11]*i+r[15]);return this.x=(r[0]*e+r[4]*s+r[8]*i+r[12])*n,this.y=(r[1]*e+r[5]*s+r[9]*i+r[13])*n,this.z=(r[2]*e+r[6]*s+r[10]*i+r[14])*n,this}applyQuaternion(t){const e=this.x,s=this.y,i=this.z,r=t.x,n=t.y,o=t.z,a=t.w,h=2*(n*i-o*s),l=2*(o*e-r*i),c=2*(r*s-n*e);return this.x=e+a*h+n*c-o*l,this.y=s+a*l+o*h-r*c,this.z=i+a*c+r*l-n*h,this}project(t){return this.applyMatrix4(t.matrixWorldInverse).applyMatrix4(t.projectionMatrix)}unproject(t){return this.applyMatrix4(t.projectionMatrixInverse).applyMatrix4(t.matrixWorld)}transformDirection(t){const e=this.x,s=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[4]*s+r[8]*i,this.y=r[1]*e+r[5]*s+r[9]*i,this.z=r[2]*e+r[6]*s+r[10]*i,this.normalize()}divide(t){return this.x/=t.x,this.y/=t.y,this.z/=t.z,this}divideScalar(t){return this.multiplyScalar(1/t)}min(t){return this.x=Math.min(this.x,t.x),this.y=Math.min(this.y,t.y),this.z=Math.min(this.z,t.z),this}max(t){return this.x=Math.max(this.x,t.x),this.y=Math.max(this.y,t.y),this.z=Math.max(this.z,t.z),this}clamp(t,e){return this.x=Ds(this.x,t.x,e.x),this.y=Ds(this.y,t.y,e.y),this.z=Ds(this.z,t.z,e.z),this}clampScalar(t,e){return this.x=Ds(this.x,t,e),this.y=Ds(this.y,t,e),this.z=Ds(this.z,t,e),this}clampLength(t,e){const s=this.length();return this.divideScalar(s||1).multiplyScalar(Ds(s,t,e))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(t){return this.x*t.x+this.y*t.y+this.z*t.z}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)}normalize(){return this.divideScalar(this.length()||1)}setLength(t){return this.normalize().multiplyScalar(t)}lerp(t,e){return this.x+=(t.x-this.x)*e,this.y+=(t.y-this.y)*e,this.z+=(t.z-this.z)*e,this}lerpVectors(t,e,s){return this.x=t.x+(e.x-t.x)*s,this.y=t.y+(e.y-t.y)*s,this.z=t.z+(e.z-t.z)*s,this}cross(t){return this.crossVectors(this,t)}crossVectors(t,e){const s=t.x,i=t.y,r=t.z,n=e.x,o=e.y,a=e.z;return this.x=i*a-r*o,this.y=r*n-s*a,this.z=s*o-i*n,this}projectOnVector(t){const e=t.lengthSq();if(0===e)return this.set(0,0,0);const s=t.dot(this)/e;return this.copy(t).multiplyScalar(s)}projectOnPlane(t){return Bi.copy(this).projectOnVector(t),this.sub(Bi)}reflect(t){return this.sub(Bi.copy(t).multiplyScalar(2*this.dot(t)))}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(0===e)return Math.PI/2;const s=this.dot(t)/e;return Math.acos(Ds(s,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,s=this.y-t.y,i=this.z-t.z;return e*e+s*s+i*i}manhattanDistanceTo(t){return Math.abs(this.x-t.x)+Math.abs(this.y-t.y)+Math.abs(this.z-t.z)}setFromSpherical(t){return this.setFromSphericalCoords(t.radius,t.phi,t.theta)}setFromSphericalCoords(t,e,s){const i=Math.sin(e)*t;return this.x=i*Math.sin(s),this.y=Math.cos(e)*t,this.z=i*Math.cos(s),this}setFromCylindrical(t){return this.setFromCylindricalCoords(t.radius,t.theta,t.y)}setFromCylindricalCoords(t,e,s){return this.x=t*Math.sin(e),this.y=s,this.z=t*Math.cos(e),this}setFromMatrixPosition(t){const e=t.elements;return this.x=e[12],this.y=e[13],this.z=e[14],this}setFromMatrixScale(t){const e=this.setFromMatrixColumn(t,0).length(),s=this.setFromMatrixColumn(t,1).length(),i=this.setFromMatrixColumn(t,2).length();return this.x=e,this.y=s,this.z=i,this}setFromMatrixColumn(t,e){return this.fromArray(t.elements,4*e)}setFromMatrix3Column(t,e){return this.fromArray(t.elements,3*e)}setFromEuler(t){return this.x=t._x,this.y=t._y,this.z=t._z,this}setFromColor(t){return this.x=t.r,this.y=t.g,this.z=t.b,this}equals(t){return t.x===this.x&&t.y===this.y&&t.z===this.z}fromArray(t,e=0){return this.x=t[e],this.y=t[e+1],this.z=t[e+2],this}toArray(t=[],e=0){return t[e]=this.x,t[e+1]=this.y,t[e+2]=this.z,t}fromBufferAttribute(t,e){return this.x=t.getX(e),this.y=t.getY(e),this.z=t.getZ(e),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){const t=Math.random()*Math.PI*2,e=2*Math.random()-1,s=Math.sqrt(1-e*e);return this.x=s*Math.cos(t),this.y=e,this.z=s*Math.sin(t),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}const Bi=new Ii,ki=new Ci;class Ri{constructor(t=new Ii(1/0,1/0,1/0),e=new Ii(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=t,this.max=e}set(t,e){return this.min.copy(t),this.max.copy(e),this}setFromArray(t){this.makeEmpty();for(let e=0,s=t.length;e=this.min.x&&t.x<=this.max.x&&t.y>=this.min.y&&t.y<=this.max.y&&t.z>=this.min.z&&t.z<=this.max.z}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y&&this.min.z<=t.min.z&&t.max.z<=this.max.z}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y),(t.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(t){return t.max.x>=this.min.x&&t.min.x<=this.max.x&&t.max.y>=this.min.y&&t.min.y<=this.max.y&&t.max.z>=this.min.z&&t.min.z<=this.max.z}intersectsSphere(t){return this.clampPoint(t.center,Pi),Pi.distanceToSquared(t.center)<=t.radius*t.radius}intersectsPlane(t){let e,s;return t.normal.x>0?(e=t.normal.x*this.min.x,s=t.normal.x*this.max.x):(e=t.normal.x*this.max.x,s=t.normal.x*this.min.x),t.normal.y>0?(e+=t.normal.y*this.min.y,s+=t.normal.y*this.max.y):(e+=t.normal.y*this.max.y,s+=t.normal.y*this.min.y),t.normal.z>0?(e+=t.normal.z*this.min.z,s+=t.normal.z*this.max.z):(e+=t.normal.z*this.max.z,s+=t.normal.z*this.min.z),e<=-t.constant&&s>=-t.constant}intersectsTriangle(t){if(this.isEmpty())return!1;this.getCenter(Ui),Di.subVectors(this.max,Ui),Fi.subVectors(t.a,Ui),Ni.subVectors(t.b,Ui),Li.subVectors(t.c,Ui),Vi.subVectors(Ni,Fi),Wi.subVectors(Li,Ni),ji.subVectors(Fi,Li);let e=[0,-Vi.z,Vi.y,0,-Wi.z,Wi.y,0,-ji.z,ji.y,Vi.z,0,-Vi.x,Wi.z,0,-Wi.x,ji.z,0,-ji.x,-Vi.y,Vi.x,0,-Wi.y,Wi.x,0,-ji.y,ji.x,0];return!!Ji(e,Fi,Ni,Li,Di)&&(e=[1,0,0,0,1,0,0,0,1],!!Ji(e,Fi,Ni,Li,Di)&&(Hi.crossVectors(Vi,Wi),e=[Hi.x,Hi.y,Hi.z],Ji(e,Fi,Ni,Li,Di)))}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return this.clampPoint(t,Pi).distanceTo(t)}getBoundingSphere(t){return this.isEmpty()?t.makeEmpty():(this.getCenter(t.center),t.radius=.5*this.getSize(Pi).length()),t}intersect(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&&this.makeEmpty(),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}applyMatrix4(t){return this.isEmpty()||(Ei[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(t),Ei[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(t),Ei[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(t),Ei[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(t),Ei[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(t),Ei[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(t),Ei[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(t),Ei[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(t),this.setFromPoints(Ei)),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}}const Ei=[new Ii,new Ii,new Ii,new Ii,new Ii,new Ii,new Ii,new Ii],Pi=new Ii,Oi=new Ri,Fi=new Ii,Ni=new Ii,Li=new Ii,Vi=new Ii,Wi=new Ii,ji=new Ii,Ui=new Ii,Di=new Ii,Hi=new Ii,qi=new Ii;function Ji(t,e,s,i,r){for(let n=0,o=t.length-3;n<=o;n+=3){qi.fromArray(t,n);const o=r.x*Math.abs(qi.x)+r.y*Math.abs(qi.y)+r.z*Math.abs(qi.z),a=e.dot(qi),h=s.dot(qi),l=i.dot(qi);if(Math.max(-Math.max(a,h,l),Math.min(a,h,l))>o)return!1}return!0}const Xi=new Ri,Yi=new Ii,Zi=new Ii;class Gi{constructor(t=new Ii,e=-1){this.isSphere=!0,this.center=t,this.radius=e}set(t,e){return this.center.copy(t),this.radius=e,this}setFromPoints(t,e){const s=this.center;void 0!==e?s.copy(e):Xi.setFromPoints(t).getCenter(s);let i=0;for(let e=0,r=t.length;ethis.radius*this.radius&&(e.sub(this.center).normalize(),e.multiplyScalar(this.radius).add(this.center)),e}getBoundingBox(t){return this.isEmpty()?(t.makeEmpty(),t):(t.set(this.center,this.center),t.expandByScalar(this.radius),t)}applyMatrix4(t){return this.center.applyMatrix4(t),this.radius=this.radius*t.getMaxScaleOnAxis(),this}translate(t){return this.center.add(t),this}expandByPoint(t){if(this.isEmpty())return this.center.copy(t),this.radius=0,this;Yi.subVectors(t,this.center);const e=Yi.lengthSq();if(e>this.radius*this.radius){const t=Math.sqrt(e),s=.5*(t-this.radius);this.center.addScaledVector(Yi,s/t),this.radius+=s}return this}union(t){return t.isEmpty()?this:this.isEmpty()?(this.copy(t),this):(!0===this.center.equals(t.center)?this.radius=Math.max(this.radius,t.radius):(Zi.subVectors(t.center,this.center).setLength(t.radius),this.expandByPoint(Yi.copy(t.center).add(Zi)),this.expandByPoint(Yi.copy(t.center).sub(Zi))),this)}equals(t){return t.center.equals(this.center)&&t.radius===this.radius}clone(){return(new this.constructor).copy(this)}}const $i=new Ii,Qi=new Ii,Ki=new Ii,tr=new Ii,er=new Ii,sr=new Ii,ir=new Ii;class rr{constructor(t=new Ii,e=new Ii(0,0,-1)){this.origin=t,this.direction=e}set(t,e){return this.origin.copy(t),this.direction.copy(e),this}copy(t){return this.origin.copy(t.origin),this.direction.copy(t.direction),this}at(t,e){return e.copy(this.origin).addScaledVector(this.direction,t)}lookAt(t){return this.direction.copy(t).sub(this.origin).normalize(),this}recast(t){return this.origin.copy(this.at(t,$i)),this}closestPointToPoint(t,e){e.subVectors(t,this.origin);const s=e.dot(this.direction);return s<0?e.copy(this.origin):e.copy(this.origin).addScaledVector(this.direction,s)}distanceToPoint(t){return Math.sqrt(this.distanceSqToPoint(t))}distanceSqToPoint(t){const e=$i.subVectors(t,this.origin).dot(this.direction);return e<0?this.origin.distanceToSquared(t):($i.copy(this.origin).addScaledVector(this.direction,e),$i.distanceToSquared(t))}distanceSqToSegment(t,e,s,i){Qi.copy(t).add(e).multiplyScalar(.5),Ki.copy(e).sub(t).normalize(),tr.copy(this.origin).sub(Qi);const r=.5*t.distanceTo(e),n=-this.direction.dot(Ki),o=tr.dot(this.direction),a=-tr.dot(Ki),h=tr.lengthSq(),l=Math.abs(1-n*n);let c,u,d,p;if(l>0)if(c=n*a-o,u=n*o-a,p=r*l,c>=0)if(u>=-p)if(u<=p){const t=1/l;c*=t,u*=t,d=c*(c+n*u+2*o)+u*(n*c+u+2*a)+h}else u=r,c=Math.max(0,-(n*u+o)),d=-c*c+u*(u+2*a)+h;else u=-r,c=Math.max(0,-(n*u+o)),d=-c*c+u*(u+2*a)+h;else u<=-p?(c=Math.max(0,-(-n*r+o)),u=c>0?-r:Math.min(Math.max(-r,-a),r),d=-c*c+u*(u+2*a)+h):u<=p?(c=0,u=Math.min(Math.max(-r,-a),r),d=u*(u+2*a)+h):(c=Math.max(0,-(n*r+o)),u=c>0?r:Math.min(Math.max(-r,-a),r),d=-c*c+u*(u+2*a)+h);else u=n>0?-r:r,c=Math.max(0,-(n*u+o)),d=-c*c+u*(u+2*a)+h;return s&&s.copy(this.origin).addScaledVector(this.direction,c),i&&i.copy(Qi).addScaledVector(Ki,u),d}intersectSphere(t,e){$i.subVectors(t.center,this.origin);const s=$i.dot(this.direction),i=$i.dot($i)-s*s,r=t.radius*t.radius;if(i>r)return null;const n=Math.sqrt(r-i),o=s-n,a=s+n;return a<0?null:o<0?this.at(a,e):this.at(o,e)}intersectsSphere(t){return this.distanceSqToPoint(t.center)<=t.radius*t.radius}distanceToPlane(t){const e=t.normal.dot(this.direction);if(0===e)return 0===t.distanceToPoint(this.origin)?0:null;const s=-(this.origin.dot(t.normal)+t.constant)/e;return s>=0?s:null}intersectPlane(t,e){const s=this.distanceToPlane(t);return null===s?null:this.at(s,e)}intersectsPlane(t){const e=t.distanceToPoint(this.origin);if(0===e)return!0;return t.normal.dot(this.direction)*e<0}intersectBox(t,e){let s,i,r,n,o,a;const h=1/this.direction.x,l=1/this.direction.y,c=1/this.direction.z,u=this.origin;return h>=0?(s=(t.min.x-u.x)*h,i=(t.max.x-u.x)*h):(s=(t.max.x-u.x)*h,i=(t.min.x-u.x)*h),l>=0?(r=(t.min.y-u.y)*l,n=(t.max.y-u.y)*l):(r=(t.max.y-u.y)*l,n=(t.min.y-u.y)*l),s>n||r>i?null:((r>s||isNaN(s))&&(s=r),(n=0?(o=(t.min.z-u.z)*c,a=(t.max.z-u.z)*c):(o=(t.max.z-u.z)*c,a=(t.min.z-u.z)*c),s>a||o>i?null:((o>s||s!=s)&&(s=o),(a=0?s:i,e)))}intersectsBox(t){return null!==this.intersectBox(t,$i)}intersectTriangle(t,e,s,i,r){er.subVectors(e,t),sr.subVectors(s,t),ir.crossVectors(er,sr);let n,o=this.direction.dot(ir);if(o>0){if(i)return null;n=1}else{if(!(o<0))return null;n=-1,o=-o}tr.subVectors(this.origin,t);const a=n*this.direction.dot(sr.crossVectors(tr,sr));if(a<0)return null;const h=n*this.direction.dot(er.cross(tr));if(h<0)return null;if(a+h>o)return null;const l=-n*tr.dot(ir);return l<0?null:this.at(l/o,r)}applyMatrix4(t){return this.origin.applyMatrix4(t),this.direction.transformDirection(t),this}equals(t){return t.origin.equals(this.origin)&&t.direction.equals(this.direction)}clone(){return(new this.constructor).copy(this)}}class nr{constructor(t,e,s,i,r,n,o,a,h,l,c,u,d,p,m,y){nr.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],void 0!==t&&this.set(t,e,s,i,r,n,o,a,h,l,c,u,d,p,m,y)}set(t,e,s,i,r,n,o,a,h,l,c,u,d,p,m,y){const f=this.elements;return f[0]=t,f[4]=e,f[8]=s,f[12]=i,f[1]=r,f[5]=n,f[9]=o,f[13]=a,f[2]=h,f[6]=l,f[10]=c,f[14]=u,f[3]=d,f[7]=p,f[11]=m,f[15]=y,this}identity(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this}clone(){return(new nr).fromArray(this.elements)}copy(t){const e=this.elements,s=t.elements;return e[0]=s[0],e[1]=s[1],e[2]=s[2],e[3]=s[3],e[4]=s[4],e[5]=s[5],e[6]=s[6],e[7]=s[7],e[8]=s[8],e[9]=s[9],e[10]=s[10],e[11]=s[11],e[12]=s[12],e[13]=s[13],e[14]=s[14],e[15]=s[15],this}copyPosition(t){const e=this.elements,s=t.elements;return e[12]=s[12],e[13]=s[13],e[14]=s[14],this}setFromMatrix3(t){const e=t.elements;return this.set(e[0],e[3],e[6],0,e[1],e[4],e[7],0,e[2],e[5],e[8],0,0,0,0,1),this}extractBasis(t,e,s){return t.setFromMatrixColumn(this,0),e.setFromMatrixColumn(this,1),s.setFromMatrixColumn(this,2),this}makeBasis(t,e,s){return this.set(t.x,e.x,s.x,0,t.y,e.y,s.y,0,t.z,e.z,s.z,0,0,0,0,1),this}extractRotation(t){const e=this.elements,s=t.elements,i=1/or.setFromMatrixColumn(t,0).length(),r=1/or.setFromMatrixColumn(t,1).length(),n=1/or.setFromMatrixColumn(t,2).length();return e[0]=s[0]*i,e[1]=s[1]*i,e[2]=s[2]*i,e[3]=0,e[4]=s[4]*r,e[5]=s[5]*r,e[6]=s[6]*r,e[7]=0,e[8]=s[8]*n,e[9]=s[9]*n,e[10]=s[10]*n,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromEuler(t){const e=this.elements,s=t.x,i=t.y,r=t.z,n=Math.cos(s),o=Math.sin(s),a=Math.cos(i),h=Math.sin(i),l=Math.cos(r),c=Math.sin(r);if("XYZ"===t.order){const t=n*l,s=n*c,i=o*l,r=o*c;e[0]=a*l,e[4]=-a*c,e[8]=h,e[1]=s+i*h,e[5]=t-r*h,e[9]=-o*a,e[2]=r-t*h,e[6]=i+s*h,e[10]=n*a}else if("YXZ"===t.order){const t=a*l,s=a*c,i=h*l,r=h*c;e[0]=t+r*o,e[4]=i*o-s,e[8]=n*h,e[1]=n*c,e[5]=n*l,e[9]=-o,e[2]=s*o-i,e[6]=r+t*o,e[10]=n*a}else if("ZXY"===t.order){const t=a*l,s=a*c,i=h*l,r=h*c;e[0]=t-r*o,e[4]=-n*c,e[8]=i+s*o,e[1]=s+i*o,e[5]=n*l,e[9]=r-t*o,e[2]=-n*h,e[6]=o,e[10]=n*a}else if("ZYX"===t.order){const t=n*l,s=n*c,i=o*l,r=o*c;e[0]=a*l,e[4]=i*h-s,e[8]=t*h+r,e[1]=a*c,e[5]=r*h+t,e[9]=s*h-i,e[2]=-h,e[6]=o*a,e[10]=n*a}else if("YZX"===t.order){const t=n*a,s=n*h,i=o*a,r=o*h;e[0]=a*l,e[4]=r-t*c,e[8]=i*c+s,e[1]=c,e[5]=n*l,e[9]=-o*l,e[2]=-h*l,e[6]=s*c+i,e[10]=t-r*c}else if("XZY"===t.order){const t=n*a,s=n*h,i=o*a,r=o*h;e[0]=a*l,e[4]=-c,e[8]=h*l,e[1]=t*c+r,e[5]=n*l,e[9]=s*c-i,e[2]=i*c-s,e[6]=o*l,e[10]=r*c+t}return e[3]=0,e[7]=0,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromQuaternion(t){return this.compose(hr,t,lr)}lookAt(t,e,s){const i=this.elements;return dr.subVectors(t,e),0===dr.lengthSq()&&(dr.z=1),dr.normalize(),cr.crossVectors(s,dr),0===cr.lengthSq()&&(1===Math.abs(s.z)?dr.x+=1e-4:dr.z+=1e-4,dr.normalize(),cr.crossVectors(s,dr)),cr.normalize(),ur.crossVectors(dr,cr),i[0]=cr.x,i[4]=ur.x,i[8]=dr.x,i[1]=cr.y,i[5]=ur.y,i[9]=dr.y,i[2]=cr.z,i[6]=ur.z,i[10]=dr.z,this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const s=t.elements,i=e.elements,r=this.elements,n=s[0],o=s[4],a=s[8],h=s[12],l=s[1],c=s[5],u=s[9],d=s[13],p=s[2],m=s[6],y=s[10],f=s[14],g=s[3],x=s[7],b=s[11],v=s[15],w=i[0],M=i[4],S=i[8],_=i[12],A=i[1],T=i[5],z=i[9],C=i[13],I=i[2],B=i[6],k=i[10],R=i[14],E=i[3],P=i[7],O=i[11],F=i[15];return r[0]=n*w+o*A+a*I+h*E,r[4]=n*M+o*T+a*B+h*P,r[8]=n*S+o*z+a*k+h*O,r[12]=n*_+o*C+a*R+h*F,r[1]=l*w+c*A+u*I+d*E,r[5]=l*M+c*T+u*B+d*P,r[9]=l*S+c*z+u*k+d*O,r[13]=l*_+c*C+u*R+d*F,r[2]=p*w+m*A+y*I+f*E,r[6]=p*M+m*T+y*B+f*P,r[10]=p*S+m*z+y*k+f*O,r[14]=p*_+m*C+y*R+f*F,r[3]=g*w+x*A+b*I+v*E,r[7]=g*M+x*T+b*B+v*P,r[11]=g*S+x*z+b*k+v*O,r[15]=g*_+x*C+b*R+v*F,this}multiplyScalar(t){const e=this.elements;return e[0]*=t,e[4]*=t,e[8]*=t,e[12]*=t,e[1]*=t,e[5]*=t,e[9]*=t,e[13]*=t,e[2]*=t,e[6]*=t,e[10]*=t,e[14]*=t,e[3]*=t,e[7]*=t,e[11]*=t,e[15]*=t,this}determinant(){const t=this.elements,e=t[0],s=t[4],i=t[8],r=t[12],n=t[1],o=t[5],a=t[9],h=t[13],l=t[2],c=t[6],u=t[10],d=t[14];return t[3]*(+r*a*c-i*h*c-r*o*u+s*h*u+i*o*d-s*a*d)+t[7]*(+e*a*d-e*h*u+r*n*u-i*n*d+i*h*l-r*a*l)+t[11]*(+e*h*c-e*o*d-r*n*c+s*n*d+r*o*l-s*h*l)+t[15]*(-i*o*l-e*a*c+e*o*u+i*n*c-s*n*u+s*a*l)}transpose(){const t=this.elements;let e;return e=t[1],t[1]=t[4],t[4]=e,e=t[2],t[2]=t[8],t[8]=e,e=t[6],t[6]=t[9],t[9]=e,e=t[3],t[3]=t[12],t[12]=e,e=t[7],t[7]=t[13],t[13]=e,e=t[11],t[11]=t[14],t[14]=e,this}setPosition(t,e,s){const i=this.elements;return t.isVector3?(i[12]=t.x,i[13]=t.y,i[14]=t.z):(i[12]=t,i[13]=e,i[14]=s),this}invert(){const t=this.elements,e=t[0],s=t[1],i=t[2],r=t[3],n=t[4],o=t[5],a=t[6],h=t[7],l=t[8],c=t[9],u=t[10],d=t[11],p=t[12],m=t[13],y=t[14],f=t[15],g=c*y*h-m*u*h+m*a*d-o*y*d-c*a*f+o*u*f,x=p*u*h-l*y*h-p*a*d+n*y*d+l*a*f-n*u*f,b=l*m*h-p*c*h+p*o*d-n*m*d-l*o*f+n*c*f,v=p*c*a-l*m*a-p*o*u+n*m*u+l*o*y-n*c*y,w=e*g+s*x+i*b+r*v;if(0===w)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const M=1/w;return t[0]=g*M,t[1]=(m*u*r-c*y*r-m*i*d+s*y*d+c*i*f-s*u*f)*M,t[2]=(o*y*r-m*a*r+m*i*h-s*y*h-o*i*f+s*a*f)*M,t[3]=(c*a*r-o*u*r-c*i*h+s*u*h+o*i*d-s*a*d)*M,t[4]=x*M,t[5]=(l*y*r-p*u*r+p*i*d-e*y*d-l*i*f+e*u*f)*M,t[6]=(p*a*r-n*y*r-p*i*h+e*y*h+n*i*f-e*a*f)*M,t[7]=(n*u*r-l*a*r+l*i*h-e*u*h-n*i*d+e*a*d)*M,t[8]=b*M,t[9]=(p*c*r-l*m*r-p*s*d+e*m*d+l*s*f-e*c*f)*M,t[10]=(n*m*r-p*o*r+p*s*h-e*m*h-n*s*f+e*o*f)*M,t[11]=(l*o*r-n*c*r-l*s*h+e*c*h+n*s*d-e*o*d)*M,t[12]=v*M,t[13]=(l*m*i-p*c*i+p*s*u-e*m*u-l*s*y+e*c*y)*M,t[14]=(p*o*i-n*m*i-p*s*a+e*m*a+n*s*y-e*o*y)*M,t[15]=(n*c*i-l*o*i+l*s*a-e*c*a-n*s*u+e*o*u)*M,this}scale(t){const e=this.elements,s=t.x,i=t.y,r=t.z;return e[0]*=s,e[4]*=i,e[8]*=r,e[1]*=s,e[5]*=i,e[9]*=r,e[2]*=s,e[6]*=i,e[10]*=r,e[3]*=s,e[7]*=i,e[11]*=r,this}getMaxScaleOnAxis(){const t=this.elements,e=t[0]*t[0]+t[1]*t[1]+t[2]*t[2],s=t[4]*t[4]+t[5]*t[5]+t[6]*t[6],i=t[8]*t[8]+t[9]*t[9]+t[10]*t[10];return Math.sqrt(Math.max(e,s,i))}makeTranslation(t,e,s){return t.isVector3?this.set(1,0,0,t.x,0,1,0,t.y,0,0,1,t.z,0,0,0,1):this.set(1,0,0,t,0,1,0,e,0,0,1,s,0,0,0,1),this}makeRotationX(t){const e=Math.cos(t),s=Math.sin(t);return this.set(1,0,0,0,0,e,-s,0,0,s,e,0,0,0,0,1),this}makeRotationY(t){const e=Math.cos(t),s=Math.sin(t);return this.set(e,0,s,0,0,1,0,0,-s,0,e,0,0,0,0,1),this}makeRotationZ(t){const e=Math.cos(t),s=Math.sin(t);return this.set(e,-s,0,0,s,e,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(t,e){const s=Math.cos(e),i=Math.sin(e),r=1-s,n=t.x,o=t.y,a=t.z,h=r*n,l=r*o;return this.set(h*n+s,h*o-i*a,h*a+i*o,0,h*o+i*a,l*o+s,l*a-i*n,0,h*a-i*o,l*a+i*n,r*a*a+s,0,0,0,0,1),this}makeScale(t,e,s){return this.set(t,0,0,0,0,e,0,0,0,0,s,0,0,0,0,1),this}makeShear(t,e,s,i,r,n){return this.set(1,s,r,0,t,1,n,0,e,i,1,0,0,0,0,1),this}compose(t,e,s){const i=this.elements,r=e._x,n=e._y,o=e._z,a=e._w,h=r+r,l=n+n,c=o+o,u=r*h,d=r*l,p=r*c,m=n*l,y=n*c,f=o*c,g=a*h,x=a*l,b=a*c,v=s.x,w=s.y,M=s.z;return i[0]=(1-(m+f))*v,i[1]=(d+b)*v,i[2]=(p-x)*v,i[3]=0,i[4]=(d-b)*w,i[5]=(1-(u+f))*w,i[6]=(y+g)*w,i[7]=0,i[8]=(p+x)*M,i[9]=(y-g)*M,i[10]=(1-(u+m))*M,i[11]=0,i[12]=t.x,i[13]=t.y,i[14]=t.z,i[15]=1,this}decompose(t,e,s){const i=this.elements;let r=or.set(i[0],i[1],i[2]).length();const n=or.set(i[4],i[5],i[6]).length(),o=or.set(i[8],i[9],i[10]).length();this.determinant()<0&&(r=-r),t.x=i[12],t.y=i[13],t.z=i[14],ar.copy(this);const a=1/r,h=1/n,l=1/o;return ar.elements[0]*=a,ar.elements[1]*=a,ar.elements[2]*=a,ar.elements[4]*=h,ar.elements[5]*=h,ar.elements[6]*=h,ar.elements[8]*=l,ar.elements[9]*=l,ar.elements[10]*=l,e.setFromRotationMatrix(ar),s.x=r,s.y=n,s.z=o,this}makePerspective(t,e,s,i,r,n,o=2e3){const a=this.elements,h=2*r/(e-t),l=2*r/(s-i),c=(e+t)/(e-t),u=(s+i)/(s-i);let d,p;if(o===Os)d=-(n+r)/(n-r),p=-2*n*r/(n-r);else{if(o!==Fs)throw new Error("THREE.Matrix4.makePerspective(): Invalid coordinate system: "+o);d=-n/(n-r),p=-n*r/(n-r)}return a[0]=h,a[4]=0,a[8]=c,a[12]=0,a[1]=0,a[5]=l,a[9]=u,a[13]=0,a[2]=0,a[6]=0,a[10]=d,a[14]=p,a[3]=0,a[7]=0,a[11]=-1,a[15]=0,this}makeOrthographic(t,e,s,i,r,n,o=2e3){const a=this.elements,h=1/(e-t),l=1/(s-i),c=1/(n-r),u=(e+t)*h,d=(s+i)*l;let p,m;if(o===Os)p=(n+r)*c,m=-2*c;else{if(o!==Fs)throw new Error("THREE.Matrix4.makeOrthographic(): Invalid coordinate system: "+o);p=r*c,m=-1*c}return a[0]=2*h,a[4]=0,a[8]=0,a[12]=-u,a[1]=0,a[5]=2*l,a[9]=0,a[13]=-d,a[2]=0,a[6]=0,a[10]=m,a[14]=-p,a[3]=0,a[7]=0,a[11]=0,a[15]=1,this}equals(t){const e=this.elements,s=t.elements;for(let t=0;t<16;t++)if(e[t]!==s[t])return!1;return!0}fromArray(t,e=0){for(let s=0;s<16;s++)this.elements[s]=t[s+e];return this}toArray(t=[],e=0){const s=this.elements;return t[e]=s[0],t[e+1]=s[1],t[e+2]=s[2],t[e+3]=s[3],t[e+4]=s[4],t[e+5]=s[5],t[e+6]=s[6],t[e+7]=s[7],t[e+8]=s[8],t[e+9]=s[9],t[e+10]=s[10],t[e+11]=s[11],t[e+12]=s[12],t[e+13]=s[13],t[e+14]=s[14],t[e+15]=s[15],t}}const or=new Ii,ar=new nr,hr=new Ii(0,0,0),lr=new Ii(1,1,1),cr=new Ii,ur=new Ii,dr=new Ii,pr=new nr,mr=new Ci;class yr{constructor(t=0,e=0,s=0,i=yr.DEFAULT_ORDER){this.isEuler=!0,this._x=t,this._y=e,this._z=s,this._order=i}get x(){return this._x}set x(t){this._x=t,this._onChangeCallback()}get y(){return this._y}set y(t){this._y=t,this._onChangeCallback()}get z(){return this._z}set z(t){this._z=t,this._onChangeCallback()}get order(){return this._order}set order(t){this._order=t,this._onChangeCallback()}set(t,e,s,i=this._order){return this._x=t,this._y=e,this._z=s,this._order=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(t){return this._x=t._x,this._y=t._y,this._z=t._z,this._order=t._order,this._onChangeCallback(),this}setFromRotationMatrix(t,e=this._order,s=!0){const i=t.elements,r=i[0],n=i[4],o=i[8],a=i[1],h=i[5],l=i[9],c=i[2],u=i[6],d=i[10];switch(e){case"XYZ":this._y=Math.asin(Ds(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-l,d),this._z=Math.atan2(-n,r)):(this._x=Math.atan2(u,h),this._z=0);break;case"YXZ":this._x=Math.asin(-Ds(l,-1,1)),Math.abs(l)<.9999999?(this._y=Math.atan2(o,d),this._z=Math.atan2(a,h)):(this._y=Math.atan2(-c,r),this._z=0);break;case"ZXY":this._x=Math.asin(Ds(u,-1,1)),Math.abs(u)<.9999999?(this._y=Math.atan2(-c,d),this._z=Math.atan2(-n,h)):(this._y=0,this._z=Math.atan2(a,r));break;case"ZYX":this._y=Math.asin(-Ds(c,-1,1)),Math.abs(c)<.9999999?(this._x=Math.atan2(u,d),this._z=Math.atan2(a,r)):(this._x=0,this._z=Math.atan2(-n,h));break;case"YZX":this._z=Math.asin(Ds(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(-l,h),this._y=Math.atan2(-c,r)):(this._x=0,this._y=Math.atan2(o,d));break;case"XZY":this._z=Math.asin(-Ds(n,-1,1)),Math.abs(n)<.9999999?(this._x=Math.atan2(u,h),this._y=Math.atan2(o,r)):(this._x=Math.atan2(-l,d),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+e)}return this._order=e,!0===s&&this._onChangeCallback(),this}setFromQuaternion(t,e,s){return pr.makeRotationFromQuaternion(t),this.setFromRotationMatrix(pr,e,s)}setFromVector3(t,e=this._order){return this.set(t.x,t.y,t.z,e)}reorder(t){return mr.setFromEuler(this),this.setFromQuaternion(mr,t)}equals(t){return t._x===this._x&&t._y===this._y&&t._z===this._z&&t._order===this._order}fromArray(t){return this._x=t[0],this._y=t[1],this._z=t[2],void 0!==t[3]&&(this._order=t[3]),this._onChangeCallback(),this}toArray(t=[],e=0){return t[e]=this._x,t[e+1]=this._y,t[e+2]=this._z,t[e+3]=this._order,t}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._order}}yr.DEFAULT_ORDER="XYZ";class fr{constructor(){this.mask=1}set(t){this.mask=1<>>0}enable(t){this.mask|=1<1){for(let t=0;t1){for(let t=0;t0&&(i.userData=this.userData),i.layers=this.layers.mask,i.matrix=this.matrix.toArray(),i.up=this.up.toArray(),!1===this.matrixAutoUpdate&&(i.matrixAutoUpdate=!1),this.isInstancedMesh&&(i.type="InstancedMesh",i.count=this.count,i.instanceMatrix=this.instanceMatrix.toJSON(),null!==this.instanceColor&&(i.instanceColor=this.instanceColor.toJSON())),this.isBatchedMesh&&(i.type="BatchedMesh",i.perObjectFrustumCulled=this.perObjectFrustumCulled,i.sortObjects=this.sortObjects,i.drawRanges=this._drawRanges,i.reservedRanges=this._reservedRanges,i.visibility=this._visibility,i.active=this._active,i.bounds=this._bounds.map((t=>({boxInitialized:t.boxInitialized,boxMin:t.box.min.toArray(),boxMax:t.box.max.toArray(),sphereInitialized:t.sphereInitialized,sphereRadius:t.sphere.radius,sphereCenter:t.sphere.center.toArray()}))),i.maxInstanceCount=this._maxInstanceCount,i.maxVertexCount=this._maxVertexCount,i.maxIndexCount=this._maxIndexCount,i.geometryInitialized=this._geometryInitialized,i.geometryCount=this._geometryCount,i.matricesTexture=this._matricesTexture.toJSON(t),null!==this._colorsTexture&&(i.colorsTexture=this._colorsTexture.toJSON(t)),null!==this.boundingSphere&&(i.boundingSphere={center:i.boundingSphere.center.toArray(),radius:i.boundingSphere.radius}),null!==this.boundingBox&&(i.boundingBox={min:i.boundingBox.min.toArray(),max:i.boundingBox.max.toArray()})),this.isScene)this.background&&(this.background.isColor?i.background=this.background.toJSON():this.background.isTexture&&(i.background=this.background.toJSON(t).uuid)),this.environment&&this.environment.isTexture&&!0!==this.environment.isRenderTargetTexture&&(i.environment=this.environment.toJSON(t).uuid);else if(this.isMesh||this.isLine||this.isPoints){i.geometry=r(t.geometries,this.geometry);const e=this.geometry.parameters;if(void 0!==e&&void 0!==e.shapes){const s=e.shapes;if(Array.isArray(s))for(let e=0,i=s.length;e0){i.children=[];for(let e=0;e0){i.animations=[];for(let e=0;e0&&(s.geometries=e),i.length>0&&(s.materials=i),r.length>0&&(s.textures=r),o.length>0&&(s.images=o),a.length>0&&(s.shapes=a),h.length>0&&(s.skeletons=h),l.length>0&&(s.animations=l),c.length>0&&(s.nodes=c)}return s.object=i,s;function n(t){const e=[];for(const s in t){const i=t[s];delete i.metadata,e.push(i)}return e}}clone(t){return(new this.constructor).copy(this,t)}copy(t,e=!0){if(this.name=t.name,this.up.copy(t.up),this.position.copy(t.position),this.rotation.order=t.rotation.order,this.quaternion.copy(t.quaternion),this.scale.copy(t.scale),this.matrix.copy(t.matrix),this.matrixWorld.copy(t.matrixWorld),this.matrixAutoUpdate=t.matrixAutoUpdate,this.matrixWorldAutoUpdate=t.matrixWorldAutoUpdate,this.matrixWorldNeedsUpdate=t.matrixWorldNeedsUpdate,this.layers.mask=t.layers.mask,this.visible=t.visible,this.castShadow=t.castShadow,this.receiveShadow=t.receiveShadow,this.frustumCulled=t.frustumCulled,this.renderOrder=t.renderOrder,this.animations=t.animations.slice(),this.userData=JSON.parse(JSON.stringify(t.userData)),!0===e)for(let e=0;e0?i.multiplyScalar(1/Math.sqrt(r)):i.set(0,0,0)}static getBarycoord(t,e,s,i,r){Er.subVectors(i,e),Pr.subVectors(s,e),Or.subVectors(t,e);const n=Er.dot(Er),o=Er.dot(Pr),a=Er.dot(Or),h=Pr.dot(Pr),l=Pr.dot(Or),c=n*h-o*o;if(0===c)return r.set(0,0,0),null;const u=1/c,d=(h*a-o*l)*u,p=(n*l-o*a)*u;return r.set(1-d-p,p,d)}static containsPoint(t,e,s,i){return null!==this.getBarycoord(t,e,s,i,Fr)&&(Fr.x>=0&&Fr.y>=0&&Fr.x+Fr.y<=1)}static getInterpolation(t,e,s,i,r,n,o,a){return null===this.getBarycoord(t,e,s,i,Fr)?(a.x=0,a.y=0,"z"in a&&(a.z=0),"w"in a&&(a.w=0),null):(a.setScalar(0),a.addScaledVector(r,Fr.x),a.addScaledVector(n,Fr.y),a.addScaledVector(o,Fr.z),a)}static getInterpolatedAttribute(t,e,s,i,r,n){return Dr.setScalar(0),Hr.setScalar(0),qr.setScalar(0),Dr.fromBufferAttribute(t,e),Hr.fromBufferAttribute(t,s),qr.fromBufferAttribute(t,i),n.setScalar(0),n.addScaledVector(Dr,r.x),n.addScaledVector(Hr,r.y),n.addScaledVector(qr,r.z),n}static isFrontFacing(t,e,s,i){return Er.subVectors(s,e),Pr.subVectors(t,e),Er.cross(Pr).dot(i)<0}set(t,e,s){return this.a.copy(t),this.b.copy(e),this.c.copy(s),this}setFromPointsAndIndices(t,e,s,i){return this.a.copy(t[e]),this.b.copy(t[s]),this.c.copy(t[i]),this}setFromAttributeAndIndices(t,e,s,i){return this.a.fromBufferAttribute(t,e),this.b.fromBufferAttribute(t,s),this.c.fromBufferAttribute(t,i),this}clone(){return(new this.constructor).copy(this)}copy(t){return this.a.copy(t.a),this.b.copy(t.b),this.c.copy(t.c),this}getArea(){return Er.subVectors(this.c,this.b),Pr.subVectors(this.a,this.b),.5*Er.cross(Pr).length()}getMidpoint(t){return t.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(t){return Jr.getNormal(this.a,this.b,this.c,t)}getPlane(t){return t.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(t,e){return Jr.getBarycoord(t,this.a,this.b,this.c,e)}getInterpolation(t,e,s,i,r){return Jr.getInterpolation(t,this.a,this.b,this.c,e,s,i,r)}containsPoint(t){return Jr.containsPoint(t,this.a,this.b,this.c)}isFrontFacing(t){return Jr.isFrontFacing(this.a,this.b,this.c,t)}intersectsBox(t){return t.intersectsTriangle(this)}closestPointToPoint(t,e){const s=this.a,i=this.b,r=this.c;let n,o;Nr.subVectors(i,s),Lr.subVectors(r,s),Wr.subVectors(t,s);const a=Nr.dot(Wr),h=Lr.dot(Wr);if(a<=0&&h<=0)return e.copy(s);jr.subVectors(t,i);const l=Nr.dot(jr),c=Lr.dot(jr);if(l>=0&&c<=l)return e.copy(i);const u=a*c-l*h;if(u<=0&&a>=0&&l<=0)return n=a/(a-l),e.copy(s).addScaledVector(Nr,n);Ur.subVectors(t,r);const d=Nr.dot(Ur),p=Lr.dot(Ur);if(p>=0&&d<=p)return e.copy(r);const m=d*h-a*p;if(m<=0&&h>=0&&p<=0)return o=h/(h-p),e.copy(s).addScaledVector(Lr,o);const y=l*p-d*c;if(y<=0&&c-l>=0&&d-p>=0)return Vr.subVectors(r,i),o=(c-l)/(c-l+(d-p)),e.copy(i).addScaledVector(Vr,o);const f=1/(y+m+u);return n=m*f,o=u*f,e.copy(s).addScaledVector(Nr,n).addScaledVector(Lr,o)}equals(t){return t.a.equals(this.a)&&t.b.equals(this.b)&&t.c.equals(this.c)}}const Xr={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074},Yr={h:0,s:0,l:0},Zr={h:0,s:0,l:0};function Gr(t,e,s){return s<0&&(s+=1),s>1&&(s-=1),s<1/6?t+6*(e-t)*s:s<.5?e:s<2/3?t+6*(e-t)*(2/3-s):t}class $r{constructor(t,e,s){return this.isColor=!0,this.r=1,this.g=1,this.b=1,this.set(t,e,s)}set(t,e,s){if(void 0===e&&void 0===s){const e=t;e&&e.isColor?this.copy(e):"number"==typeof e?this.setHex(e):"string"==typeof e&&this.setStyle(e)}else this.setRGB(t,e,s);return this}setScalar(t){return this.r=t,this.g=t,this.b=t,this}setHex(t,e=Ge){return t=Math.floor(t),this.r=(t>>16&255)/255,this.g=(t>>8&255)/255,this.b=(255&t)/255,ui.toWorkingColorSpace(this,e),this}setRGB(t,e,s,i=ui.workingColorSpace){return this.r=t,this.g=e,this.b=s,ui.toWorkingColorSpace(this,i),this}setHSL(t,e,s,i=ui.workingColorSpace){if(t=Hs(t,1),e=Ds(e,0,1),s=Ds(s,0,1),0===e)this.r=this.g=this.b=s;else{const i=s<=.5?s*(1+e):s+e-s*e,r=2*s-i;this.r=Gr(r,i,t+1/3),this.g=Gr(r,i,t),this.b=Gr(r,i,t-1/3)}return ui.toWorkingColorSpace(this,i),this}setStyle(t,e=Ge){function s(e){void 0!==e&&parseFloat(e)<1&&console.warn("THREE.Color: Alpha component of "+t+" will be ignored.")}let i;if(i=/^(\w+)\(([^\)]*)\)/.exec(t)){let r;const n=i[1],o=i[2];switch(n){case"rgb":case"rgba":if(r=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return s(r[4]),this.setRGB(Math.min(255,parseInt(r[1],10))/255,Math.min(255,parseInt(r[2],10))/255,Math.min(255,parseInt(r[3],10))/255,e);if(r=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return s(r[4]),this.setRGB(Math.min(100,parseInt(r[1],10))/100,Math.min(100,parseInt(r[2],10))/100,Math.min(100,parseInt(r[3],10))/100,e);break;case"hsl":case"hsla":if(r=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return s(r[4]),this.setHSL(parseFloat(r[1])/360,parseFloat(r[2])/100,parseFloat(r[3])/100,e);break;default:console.warn("THREE.Color: Unknown color model "+t)}}else if(i=/^\#([A-Fa-f\d]+)$/.exec(t)){const s=i[1],r=s.length;if(3===r)return this.setRGB(parseInt(s.charAt(0),16)/15,parseInt(s.charAt(1),16)/15,parseInt(s.charAt(2),16)/15,e);if(6===r)return this.setHex(parseInt(s,16),e);console.warn("THREE.Color: Invalid hex color "+t)}else if(t&&t.length>0)return this.setColorName(t,e);return this}setColorName(t,e=Ge){const s=Xr[t.toLowerCase()];return void 0!==s?this.setHex(s,e):console.warn("THREE.Color: Unknown color "+t),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(t){return this.r=t.r,this.g=t.g,this.b=t.b,this}copySRGBToLinear(t){return this.r=di(t.r),this.g=di(t.g),this.b=di(t.b),this}copyLinearToSRGB(t){return this.r=pi(t.r),this.g=pi(t.g),this.b=pi(t.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(t=Ge){return ui.fromWorkingColorSpace(Qr.copy(this),t),65536*Math.round(Ds(255*Qr.r,0,255))+256*Math.round(Ds(255*Qr.g,0,255))+Math.round(Ds(255*Qr.b,0,255))}getHexString(t=Ge){return("000000"+this.getHex(t).toString(16)).slice(-6)}getHSL(t,e=ui.workingColorSpace){ui.fromWorkingColorSpace(Qr.copy(this),e);const s=Qr.r,i=Qr.g,r=Qr.b,n=Math.max(s,i,r),o=Math.min(s,i,r);let a,h;const l=(o+n)/2;if(o===n)a=0,h=0;else{const t=n-o;switch(h=l<=.5?t/(n+o):t/(2-n-o),n){case s:a=(i-r)/t+(i0!=t>0&&this.version++,this._alphaTest=t}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(t){if(void 0!==t)for(const e in t){const s=t[e];if(void 0===s){console.warn(`THREE.Material: parameter '${e}' has value of undefined.`);continue}const i=this[e];void 0!==i?i&&i.isColor?i.set(s):i&&i.isVector3&&s&&s.isVector3?i.copy(s):this[e]=s:console.warn(`THREE.Material: '${e}' is not a property of THREE.${this.type}.`)}}toJSON(t){const e=void 0===t||"string"==typeof t;e&&(t={textures:{},images:{}});const s={metadata:{version:4.6,type:"Material",generator:"Material.toJSON"}};function i(t){const e=[];for(const s in t){const i=t[s];delete i.metadata,e.push(i)}return e}if(s.uuid=this.uuid,s.type=this.type,""!==this.name&&(s.name=this.name),this.color&&this.color.isColor&&(s.color=this.color.getHex()),void 0!==this.roughness&&(s.roughness=this.roughness),void 0!==this.metalness&&(s.metalness=this.metalness),void 0!==this.sheen&&(s.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(s.sheenColor=this.sheenColor.getHex()),void 0!==this.sheenRoughness&&(s.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(s.emissive=this.emissive.getHex()),void 0!==this.emissiveIntensity&&1!==this.emissiveIntensity&&(s.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(s.specular=this.specular.getHex()),void 0!==this.specularIntensity&&(s.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(s.specularColor=this.specularColor.getHex()),void 0!==this.shininess&&(s.shininess=this.shininess),void 0!==this.clearcoat&&(s.clearcoat=this.clearcoat),void 0!==this.clearcoatRoughness&&(s.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(s.clearcoatMap=this.clearcoatMap.toJSON(t).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(s.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(t).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(s.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(t).uuid,s.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),void 0!==this.dispersion&&(s.dispersion=this.dispersion),void 0!==this.iridescence&&(s.iridescence=this.iridescence),void 0!==this.iridescenceIOR&&(s.iridescenceIOR=this.iridescenceIOR),void 0!==this.iridescenceThicknessRange&&(s.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(s.iridescenceMap=this.iridescenceMap.toJSON(t).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(s.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(t).uuid),void 0!==this.anisotropy&&(s.anisotropy=this.anisotropy),void 0!==this.anisotropyRotation&&(s.anisotropyRotation=this.anisotropyRotation),this.anisotropyMap&&this.anisotropyMap.isTexture&&(s.anisotropyMap=this.anisotropyMap.toJSON(t).uuid),this.map&&this.map.isTexture&&(s.map=this.map.toJSON(t).uuid),this.matcap&&this.matcap.isTexture&&(s.matcap=this.matcap.toJSON(t).uuid),this.alphaMap&&this.alphaMap.isTexture&&(s.alphaMap=this.alphaMap.toJSON(t).uuid),this.lightMap&&this.lightMap.isTexture&&(s.lightMap=this.lightMap.toJSON(t).uuid,s.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(s.aoMap=this.aoMap.toJSON(t).uuid,s.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(s.bumpMap=this.bumpMap.toJSON(t).uuid,s.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(s.normalMap=this.normalMap.toJSON(t).uuid,s.normalMapType=this.normalMapType,s.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(s.displacementMap=this.displacementMap.toJSON(t).uuid,s.displacementScale=this.displacementScale,s.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(s.roughnessMap=this.roughnessMap.toJSON(t).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(s.metalnessMap=this.metalnessMap.toJSON(t).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(s.emissiveMap=this.emissiveMap.toJSON(t).uuid),this.specularMap&&this.specularMap.isTexture&&(s.specularMap=this.specularMap.toJSON(t).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(s.specularIntensityMap=this.specularIntensityMap.toJSON(t).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(s.specularColorMap=this.specularColorMap.toJSON(t).uuid),this.envMap&&this.envMap.isTexture&&(s.envMap=this.envMap.toJSON(t).uuid,void 0!==this.combine&&(s.combine=this.combine)),void 0!==this.envMapRotation&&(s.envMapRotation=this.envMapRotation.toArray()),void 0!==this.envMapIntensity&&(s.envMapIntensity=this.envMapIntensity),void 0!==this.reflectivity&&(s.reflectivity=this.reflectivity),void 0!==this.refractionRatio&&(s.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(s.gradientMap=this.gradientMap.toJSON(t).uuid),void 0!==this.transmission&&(s.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(s.transmissionMap=this.transmissionMap.toJSON(t).uuid),void 0!==this.thickness&&(s.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(s.thicknessMap=this.thicknessMap.toJSON(t).uuid),void 0!==this.attenuationDistance&&this.attenuationDistance!==1/0&&(s.attenuationDistance=this.attenuationDistance),void 0!==this.attenuationColor&&(s.attenuationColor=this.attenuationColor.getHex()),void 0!==this.size&&(s.size=this.size),null!==this.shadowSide&&(s.shadowSide=this.shadowSide),void 0!==this.sizeAttenuation&&(s.sizeAttenuation=this.sizeAttenuation),1!==this.blending&&(s.blending=this.blending),0!==this.side&&(s.side=this.side),!0===this.vertexColors&&(s.vertexColors=!0),this.opacity<1&&(s.opacity=this.opacity),!0===this.transparent&&(s.transparent=!0),204!==this.blendSrc&&(s.blendSrc=this.blendSrc),205!==this.blendDst&&(s.blendDst=this.blendDst),100!==this.blendEquation&&(s.blendEquation=this.blendEquation),null!==this.blendSrcAlpha&&(s.blendSrcAlpha=this.blendSrcAlpha),null!==this.blendDstAlpha&&(s.blendDstAlpha=this.blendDstAlpha),null!==this.blendEquationAlpha&&(s.blendEquationAlpha=this.blendEquationAlpha),this.blendColor&&this.blendColor.isColor&&(s.blendColor=this.blendColor.getHex()),0!==this.blendAlpha&&(s.blendAlpha=this.blendAlpha),3!==this.depthFunc&&(s.depthFunc=this.depthFunc),!1===this.depthTest&&(s.depthTest=this.depthTest),!1===this.depthWrite&&(s.depthWrite=this.depthWrite),!1===this.colorWrite&&(s.colorWrite=this.colorWrite),255!==this.stencilWriteMask&&(s.stencilWriteMask=this.stencilWriteMask),519!==this.stencilFunc&&(s.stencilFunc=this.stencilFunc),0!==this.stencilRef&&(s.stencilRef=this.stencilRef),255!==this.stencilFuncMask&&(s.stencilFuncMask=this.stencilFuncMask),this.stencilFail!==es&&(s.stencilFail=this.stencilFail),this.stencilZFail!==es&&(s.stencilZFail=this.stencilZFail),this.stencilZPass!==es&&(s.stencilZPass=this.stencilZPass),!0===this.stencilWrite&&(s.stencilWrite=this.stencilWrite),void 0!==this.rotation&&0!==this.rotation&&(s.rotation=this.rotation),!0===this.polygonOffset&&(s.polygonOffset=!0),0!==this.polygonOffsetFactor&&(s.polygonOffsetFactor=this.polygonOffsetFactor),0!==this.polygonOffsetUnits&&(s.polygonOffsetUnits=this.polygonOffsetUnits),void 0!==this.linewidth&&1!==this.linewidth&&(s.linewidth=this.linewidth),void 0!==this.dashSize&&(s.dashSize=this.dashSize),void 0!==this.gapSize&&(s.gapSize=this.gapSize),void 0!==this.scale&&(s.scale=this.scale),!0===this.dithering&&(s.dithering=!0),this.alphaTest>0&&(s.alphaTest=this.alphaTest),!0===this.alphaHash&&(s.alphaHash=!0),!0===this.alphaToCoverage&&(s.alphaToCoverage=!0),!0===this.premultipliedAlpha&&(s.premultipliedAlpha=!0),!0===this.forceSinglePass&&(s.forceSinglePass=!0),!0===this.wireframe&&(s.wireframe=!0),this.wireframeLinewidth>1&&(s.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(s.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(s.wireframeLinejoin=this.wireframeLinejoin),!0===this.flatShading&&(s.flatShading=!0),!1===this.visible&&(s.visible=!1),!1===this.toneMapped&&(s.toneMapped=!1),!1===this.fog&&(s.fog=!1),Object.keys(this.userData).length>0&&(s.userData=this.userData),e){const e=i(t.textures),r=i(t.images);e.length>0&&(s.textures=e),r.length>0&&(s.images=r)}return s}clone(){return(new this.constructor).copy(this)}copy(t){this.name=t.name,this.blending=t.blending,this.side=t.side,this.vertexColors=t.vertexColors,this.opacity=t.opacity,this.transparent=t.transparent,this.blendSrc=t.blendSrc,this.blendDst=t.blendDst,this.blendEquation=t.blendEquation,this.blendSrcAlpha=t.blendSrcAlpha,this.blendDstAlpha=t.blendDstAlpha,this.blendEquationAlpha=t.blendEquationAlpha,this.blendColor.copy(t.blendColor),this.blendAlpha=t.blendAlpha,this.depthFunc=t.depthFunc,this.depthTest=t.depthTest,this.depthWrite=t.depthWrite,this.stencilWriteMask=t.stencilWriteMask,this.stencilFunc=t.stencilFunc,this.stencilRef=t.stencilRef,this.stencilFuncMask=t.stencilFuncMask,this.stencilFail=t.stencilFail,this.stencilZFail=t.stencilZFail,this.stencilZPass=t.stencilZPass,this.stencilWrite=t.stencilWrite;const e=t.clippingPlanes;let s=null;if(null!==e){const t=e.length;s=new Array(t);for(let i=0;i!==t;++i)s[i]=e[i].clone()}return this.clippingPlanes=s,this.clipIntersection=t.clipIntersection,this.clipShadows=t.clipShadows,this.shadowSide=t.shadowSide,this.colorWrite=t.colorWrite,this.precision=t.precision,this.polygonOffset=t.polygonOffset,this.polygonOffsetFactor=t.polygonOffsetFactor,this.polygonOffsetUnits=t.polygonOffsetUnits,this.dithering=t.dithering,this.alphaTest=t.alphaTest,this.alphaHash=t.alphaHash,this.alphaToCoverage=t.alphaToCoverage,this.premultipliedAlpha=t.premultipliedAlpha,this.forceSinglePass=t.forceSinglePass,this.visible=t.visible,this.toneMapped=t.toneMapped,this.userData=JSON.parse(JSON.stringify(t.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(t){!0===t&&this.version++}onBuild(){console.warn("Material: onBuild() has been removed.")}}class en extends tn{constructor(t){super(),this.isMeshBasicMaterial=!0,this.type="MeshBasicMaterial",this.color=new $r(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new yr,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.envMapRotation.copy(t.envMapRotation),this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.fog=t.fog,this}}const sn=rn();function rn(){const t=new ArrayBuffer(4),e=new Float32Array(t),s=new Uint32Array(t),i=new Uint32Array(512),r=new Uint32Array(512);for(let t=0;t<256;++t){const e=t-127;e<-27?(i[t]=0,i[256|t]=32768,r[t]=24,r[256|t]=24):e<-14?(i[t]=1024>>-e-14,i[256|t]=1024>>-e-14|32768,r[t]=-e-1,r[256|t]=-e-1):e<=15?(i[t]=e+15<<10,i[256|t]=e+15<<10|32768,r[t]=13,r[256|t]=13):e<128?(i[t]=31744,i[256|t]=64512,r[t]=24,r[256|t]=24):(i[t]=31744,i[256|t]=64512,r[t]=13,r[256|t]=13)}const n=new Uint32Array(2048),o=new Uint32Array(64),a=new Uint32Array(64);for(let t=1;t<1024;++t){let e=t<<13,s=0;for(;!(8388608&e);)e<<=1,s-=8388608;e&=-8388609,s+=947912704,n[t]=e|s}for(let t=1024;t<2048;++t)n[t]=939524096+(t-1024<<13);for(let t=1;t<31;++t)o[t]=t<<23;o[31]=1199570944,o[32]=2147483648;for(let t=33;t<63;++t)o[t]=2147483648+(t-32<<23);o[63]=3347054592;for(let t=1;t<64;++t)32!==t&&(a[t]=1024);return{floatView:e,uint32View:s,baseTable:i,shiftTable:r,mantissaTable:n,exponentTable:o,offsetTable:a}}function nn(t){Math.abs(t)>65504&&console.warn("THREE.DataUtils.toHalfFloat(): Value out of range."),t=Ds(t,-65504,65504),sn.floatView[0]=t;const e=sn.uint32View[0],s=e>>23&511;return sn.baseTable[s]+((8388607&e)>>sn.shiftTable[s])}function on(t){const e=t>>10;return sn.uint32View[0]=sn.mantissaTable[sn.offsetTable[e]+(1023&t)]+sn.exponentTable[e],sn.floatView[0]}const an={toHalfFloat:nn,fromHalfFloat:on},hn=new Ii,ln=new Zs;class cn{constructor(t,e,s=!1){if(Array.isArray(t))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.isBufferAttribute=!0,this.name="",this.array=t,this.itemSize=e,this.count=void 0!==t?t.length/e:0,this.normalized=s,this.usage=_s,this.updateRanges=[],this.gpuType=Rt,this.version=0}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}addUpdateRange(t,e){this.updateRanges.push({start:t,count:e})}clearUpdateRanges(){this.updateRanges.length=0}copy(t){return this.name=t.name,this.array=new t.array.constructor(t.array),this.itemSize=t.itemSize,this.count=t.count,this.normalized=t.normalized,this.usage=t.usage,this.gpuType=t.gpuType,this}copyAt(t,e,s){t*=this.itemSize,s*=e.itemSize;for(let i=0,r=this.itemSize;ie.count&&console.warn("THREE.BufferGeometry: Buffer size too small for points data. Use .dispose() and create a new geometry."),e.needsUpdate=!0}return this}computeBoundingBox(){null===this.boundingBox&&(this.boundingBox=new Ri);const t=this.attributes.position,e=this.morphAttributes.position;if(t&&t.isGLBufferAttribute)return console.error("THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box.",this),void this.boundingBox.set(new Ii(-1/0,-1/0,-1/0),new Ii(1/0,1/0,1/0));if(void 0!==t){if(this.boundingBox.setFromBufferAttribute(t),e)for(let t=0,s=e.length;t0&&(t.userData=this.userData),void 0!==this.parameters){const e=this.parameters;for(const s in e)void 0!==e[s]&&(t[s]=e[s]);return t}t.data={attributes:{}};const e=this.index;null!==e&&(t.data.index={type:e.array.constructor.name,array:Array.prototype.slice.call(e.array)});const s=this.attributes;for(const e in s){const i=s[e];t.data.attributes[e]=i.toJSON(t.data)}const i={};let r=!1;for(const e in this.morphAttributes){const s=this.morphAttributes[e],n=[];for(let e=0,i=s.length;e0&&(i[e]=n,r=!0)}r&&(t.data.morphAttributes=i,t.data.morphTargetsRelative=this.morphTargetsRelative);const n=this.groups;n.length>0&&(t.data.groups=JSON.parse(JSON.stringify(n)));const o=this.boundingSphere;return null!==o&&(t.data.boundingSphere={center:o.center.toArray(),radius:o.radius}),t}clone(){return(new this.constructor).copy(this)}copy(t){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;const e={};this.name=t.name;const s=t.index;null!==s&&this.setIndex(s.clone(e));const i=t.attributes;for(const t in i){const s=i[t];this.setAttribute(t,s.clone(e))}const r=t.morphAttributes;for(const t in r){const s=[],i=r[t];for(let t=0,r=i.length;t0){const s=t[e[0]];if(void 0!==s){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=s.length;t(t.far-t.near)**2)return}Cn.copy(r).invert(),In.copy(t.ray).applyMatrix4(Cn),null!==s.boundingBox&&!1===In.intersectsBox(s.boundingBox)||this._computeIntersections(t,e,In)}}_computeIntersections(t,e,s){let i;const r=this.geometry,n=this.material,o=r.index,a=r.attributes.position,h=r.attributes.uv,l=r.attributes.uv1,c=r.attributes.normal,u=r.groups,d=r.drawRange;if(null!==o)if(Array.isArray(n))for(let r=0,a=u.length;rs.far?null:{distance:l,point:Ln.clone(),object:t}}(t,e,s,i,Rn,En,Pn,Nn);if(c){const t=new Ii;Jr.getBarycoord(Nn,Rn,En,Pn,t),r&&(c.uv=Jr.getInterpolatedAttribute(r,a,h,l,t,new Zs)),n&&(c.uv1=Jr.getInterpolatedAttribute(n,a,h,l,t,new Zs)),o&&(c.normal=Jr.getInterpolatedAttribute(o,a,h,l,t,new Ii),c.normal.dot(i.direction)>0&&c.normal.multiplyScalar(-1));const e={a:a,b:h,c:l,normal:new Ii,materialIndex:0};Jr.getNormal(Rn,En,Pn,e.normal),c.face=e,c.barycoord=t}return c}class jn extends zn{constructor(t=1,e=1,s=1,i=1,r=1,n=1){super(),this.type="BoxGeometry",this.parameters={width:t,height:e,depth:s,widthSegments:i,heightSegments:r,depthSegments:n};const o=this;i=Math.floor(i),r=Math.floor(r),n=Math.floor(n);const a=[],h=[],l=[],c=[];let u=0,d=0;function p(t,e,s,i,r,n,p,m,y,f,g){const x=n/y,b=p/f,v=n/2,w=p/2,M=m/2,S=y+1,_=f+1;let A=0,T=0;const z=new Ii;for(let n=0;n<_;n++){const o=n*b-w;for(let a=0;a0?1:-1,l.push(z.x,z.y,z.z),c.push(a/y),c.push(1-n/f),A+=1}}for(let t=0;t0&&(e.defines=this.defines),e.vertexShader=this.vertexShader,e.fragmentShader=this.fragmentShader,e.lights=this.lights,e.clipping=this.clipping;const s={};for(const t in this.extensions)!0===this.extensions[t]&&(s[t]=!0);return Object.keys(s).length>0&&(e.extensions=s),e}}class Xn extends Rr{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new nr,this.projectionMatrix=new nr,this.projectionMatrixInverse=new nr,this.coordinateSystem=Os}copy(t,e){return super.copy(t,e),this.matrixWorldInverse.copy(t.matrixWorldInverse),this.projectionMatrix.copy(t.projectionMatrix),this.projectionMatrixInverse.copy(t.projectionMatrixInverse),this.coordinateSystem=t.coordinateSystem,this}getWorldDirection(t){return super.getWorldDirection(t).negate()}updateMatrixWorld(t){super.updateMatrixWorld(t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(t,e){super.updateWorldMatrix(t,e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return(new this.constructor).copy(this)}}const Yn=new Ii,Zn=new Zs,Gn=new Zs;class $n extends Xn{constructor(t=50,e=1,s=.1,i=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=t,this.zoom=1,this.near=s,this.far=i,this.focus=10,this.aspect=e,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(t,e){return super.copy(t,e),this.fov=t.fov,this.zoom=t.zoom,this.near=t.near,this.far=t.far,this.focus=t.focus,this.aspect=t.aspect,this.view=null===t.view?null:Object.assign({},t.view),this.filmGauge=t.filmGauge,this.filmOffset=t.filmOffset,this}setFocalLength(t){const e=.5*this.getFilmHeight()/t;this.fov=2*js*Math.atan(e),this.updateProjectionMatrix()}getFocalLength(){const t=Math.tan(.5*Ws*this.fov);return.5*this.getFilmHeight()/t}getEffectiveFOV(){return 2*js*Math.atan(Math.tan(.5*Ws*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}getViewBounds(t,e,s){Yn.set(-1,-1,.5).applyMatrix4(this.projectionMatrixInverse),e.set(Yn.x,Yn.y).multiplyScalar(-t/Yn.z),Yn.set(1,1,.5).applyMatrix4(this.projectionMatrixInverse),s.set(Yn.x,Yn.y).multiplyScalar(-t/Yn.z)}getViewSize(t,e){return this.getViewBounds(t,Zn,Gn),e.subVectors(Gn,Zn)}setViewOffset(t,e,s,i,r,n){this.aspect=t/e,null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=t,this.view.fullHeight=e,this.view.offsetX=s,this.view.offsetY=i,this.view.width=r,this.view.height=n,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const t=this.near;let e=t*Math.tan(.5*Ws*this.fov)/this.zoom,s=2*e,i=this.aspect*s,r=-.5*i;const n=this.view;if(null!==this.view&&this.view.enabled){const t=n.fullWidth,o=n.fullHeight;r+=n.offsetX*i/t,e-=n.offsetY*s/o,i*=n.width/t,s*=n.height/o}const o=this.filmOffset;0!==o&&(r+=t*o/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+i,e,e-s,t,this.far,this.coordinateSystem),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(t){const e=super.toJSON(t);return e.object.fov=this.fov,e.object.zoom=this.zoom,e.object.near=this.near,e.object.far=this.far,e.object.focus=this.focus,e.object.aspect=this.aspect,null!==this.view&&(e.object.view=Object.assign({},this.view)),e.object.filmGauge=this.filmGauge,e.object.filmOffset=this.filmOffset,e}}const Qn=-90;class Kn extends Rr{constructor(t,e,s){super(),this.type="CubeCamera",this.renderTarget=s,this.coordinateSystem=null,this.activeMipmapLevel=0;const i=new $n(Qn,1,t,e);i.layers=this.layers,this.add(i);const r=new $n(Qn,1,t,e);r.layers=this.layers,this.add(r);const n=new $n(Qn,1,t,e);n.layers=this.layers,this.add(n);const o=new $n(Qn,1,t,e);o.layers=this.layers,this.add(o);const a=new $n(Qn,1,t,e);a.layers=this.layers,this.add(a);const h=new $n(Qn,1,t,e);h.layers=this.layers,this.add(h)}updateCoordinateSystem(){const t=this.coordinateSystem,e=this.children.concat(),[s,i,r,n,o,a]=e;for(const t of e)this.remove(t);if(t===Os)s.up.set(0,1,0),s.lookAt(1,0,0),i.up.set(0,1,0),i.lookAt(-1,0,0),r.up.set(0,0,-1),r.lookAt(0,1,0),n.up.set(0,0,1),n.lookAt(0,-1,0),o.up.set(0,1,0),o.lookAt(0,0,1),a.up.set(0,1,0),a.lookAt(0,0,-1);else{if(t!==Fs)throw new Error("THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: "+t);s.up.set(0,-1,0),s.lookAt(-1,0,0),i.up.set(0,-1,0),i.lookAt(1,0,0),r.up.set(0,0,1),r.lookAt(0,1,0),n.up.set(0,0,-1),n.lookAt(0,-1,0),o.up.set(0,-1,0),o.lookAt(0,0,1),a.up.set(0,-1,0),a.lookAt(0,0,-1)}for(const t of e)this.add(t),t.updateMatrixWorld()}update(t,e){null===this.parent&&this.updateMatrixWorld();const{renderTarget:s,activeMipmapLevel:i}=this;this.coordinateSystem!==t.coordinateSystem&&(this.coordinateSystem=t.coordinateSystem,this.updateCoordinateSystem());const[r,n,o,a,h,l]=this.children,c=t.getRenderTarget(),u=t.getActiveCubeFace(),d=t.getActiveMipmapLevel(),p=t.xr.enabled;t.xr.enabled=!1;const m=s.texture.generateMipmaps;s.texture.generateMipmaps=!1,t.setRenderTarget(s,0,i),t.render(e,r),t.setRenderTarget(s,1,i),t.render(e,n),t.setRenderTarget(s,2,i),t.render(e,o),t.setRenderTarget(s,3,i),t.render(e,a),t.setRenderTarget(s,4,i),t.render(e,h),s.texture.generateMipmaps=m,t.setRenderTarget(s,5,i),t.render(e,l),t.setRenderTarget(c,u,d),t.xr.enabled=p,s.texture.needsPMREMUpdate=!0}}class to extends vi{constructor(t,e,s,i,r,n,o,a,h,l){super(t=void 0!==t?t:[],e=void 0!==e?e:ht,s,i,r,n,o,a,h,l),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(t){this.image=t}}class eo extends Si{constructor(t=1,e={}){super(t,t,e),this.isWebGLCubeRenderTarget=!0;const s={width:t,height:t,depth:1},i=[s,s,s,s,s,s];this.texture=new to(i,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.colorSpace),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=void 0!==e.generateMipmaps&&e.generateMipmaps,this.texture.minFilter=void 0!==e.minFilter?e.minFilter:wt}fromEquirectangularTexture(t,e){this.texture.type=e.type,this.texture.colorSpace=e.colorSpace,this.texture.generateMipmaps=e.generateMipmaps,this.texture.minFilter=e.minFilter,this.texture.magFilter=e.magFilter;const s={uniforms:{tEquirect:{value:null}},vertexShader:"\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\tvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\n\t\t\t\t\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n\n\t\t\t\t}\n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvWorldDirection = transformDirection( position, modelMatrix );\n\n\t\t\t\t\t#include \n\t\t\t\t\t#include \n\n\t\t\t\t}\n\t\t\t",fragmentShader:"\n\n\t\t\t\tuniform sampler2D tEquirect;\n\n\t\t\t\tvarying vec3 vWorldDirection;\n\n\t\t\t\t#include \n\n\t\t\t\tvoid main() {\n\n\t\t\t\t\tvec3 direction = normalize( vWorldDirection );\n\n\t\t\t\t\tvec2 sampleUV = equirectUv( direction );\n\n\t\t\t\t\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\n\t\t\t\t}\n\t\t\t"},i=new jn(5,5,5),r=new Jn({name:"CubemapFromEquirect",uniforms:Un(s.uniforms),vertexShader:s.vertexShader,fragmentShader:s.fragmentShader,side:1,blending:0});r.uniforms.tEquirect.value=e;const n=new Vn(i,r),o=e.minFilter;e.minFilter===_t&&(e.minFilter=wt);return new Kn(1,10,this).update(t,n),e.minFilter=o,n.geometry.dispose(),n.material.dispose(),this}clear(t,e,s,i){const r=t.getRenderTarget();for(let r=0;r<6;r++)t.setRenderTarget(this,r),t.clear(e,s,i);t.setRenderTarget(r)}}class so{constructor(t,e=25e-5){this.isFogExp2=!0,this.name="",this.color=new $r(t),this.density=e}clone(){return new so(this.color,this.density)}toJSON(){return{type:"FogExp2",name:this.name,color:this.color.getHex(),density:this.density}}}class io{constructor(t,e=1,s=1e3){this.isFog=!0,this.name="",this.color=new $r(t),this.near=e,this.far=s}clone(){return new io(this.color,this.near,this.far)}toJSON(){return{type:"Fog",name:this.name,color:this.color.getHex(),near:this.near,far:this.far}}}class ro extends Rr{constructor(){super(),this.isScene=!0,this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.backgroundRotation=new yr,this.environmentIntensity=1,this.environmentRotation=new yr,this.overrideMaterial=null,"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}copy(t,e){return super.copy(t,e),null!==t.background&&(this.background=t.background.clone()),null!==t.environment&&(this.environment=t.environment.clone()),null!==t.fog&&(this.fog=t.fog.clone()),this.backgroundBlurriness=t.backgroundBlurriness,this.backgroundIntensity=t.backgroundIntensity,this.backgroundRotation.copy(t.backgroundRotation),this.environmentIntensity=t.environmentIntensity,this.environmentRotation.copy(t.environmentRotation),null!==t.overrideMaterial&&(this.overrideMaterial=t.overrideMaterial.clone()),this.matrixAutoUpdate=t.matrixAutoUpdate,this}toJSON(t){const e=super.toJSON(t);return null!==this.fog&&(e.object.fog=this.fog.toJSON()),this.backgroundBlurriness>0&&(e.object.backgroundBlurriness=this.backgroundBlurriness),1!==this.backgroundIntensity&&(e.object.backgroundIntensity=this.backgroundIntensity),e.object.backgroundRotation=this.backgroundRotation.toArray(),1!==this.environmentIntensity&&(e.object.environmentIntensity=this.environmentIntensity),e.object.environmentRotation=this.environmentRotation.toArray(),e}}class no{constructor(t,e){this.isInterleavedBuffer=!0,this.array=t,this.stride=e,this.count=void 0!==t?t.length/e:0,this.usage=_s,this.updateRanges=[],this.version=0,this.uuid=Us()}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}addUpdateRange(t,e){this.updateRanges.push({start:t,count:e})}clearUpdateRanges(){this.updateRanges.length=0}copy(t){return this.array=new t.array.constructor(t.array),this.count=t.count,this.stride=t.stride,this.usage=t.usage,this}copyAt(t,e,s){t*=this.stride,s*=e.stride;for(let i=0,r=this.stride;it.far||e.push({distance:a,point:co.clone(),uv:Jr.getInterpolation(co,go,xo,bo,vo,wo,Mo,new Zs),face:null,object:this})}copy(t,e){return super.copy(t,e),void 0!==t.center&&this.center.copy(t.center),this.material=t.material,this}}function _o(t,e,s,i,r,n){mo.subVectors(t,s).addScalar(.5).multiply(i),void 0!==r?(yo.x=n*mo.x-r*mo.y,yo.y=r*mo.x+n*mo.y):yo.copy(mo),t.copy(e),t.x+=yo.x,t.y+=yo.y,t.applyMatrix4(fo)}const Ao=new Ii,To=new Ii;class zo extends Rr{constructor(){super(),this._currentLevel=0,this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]},isLOD:{value:!0}}),this.autoUpdate=!0}copy(t){super.copy(t,!1);const e=t.levels;for(let t=0,s=e.length;t0){let s,i;for(s=1,i=e.length;s0){Ao.setFromMatrixPosition(this.matrixWorld);const s=t.ray.origin.distanceTo(Ao);this.getObjectForDistance(s).raycast(t,e)}}update(t){const e=this.levels;if(e.length>1){Ao.setFromMatrixPosition(t.matrixWorld),To.setFromMatrixPosition(this.matrixWorld);const s=Ao.distanceTo(To)/t.zoom;let i,r;for(e[0].object.visible=!0,i=1,r=e.length;i=t))break;e[i-1].object.visible=!1,e[i].object.visible=!0}for(this._currentLevel=i-1;i1?null:e.copy(t.start).addScaledVector(s,r)}intersectsLine(t){const e=this.distanceToPoint(t.start),s=this.distanceToPoint(t.end);return e<0&&s>0||s<0&&e>0}intersectsBox(t){return t.intersectsPlane(this)}intersectsSphere(t){return t.intersectsPlane(this)}coplanarPoint(t){return t.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(t,e){const s=e||ta.getNormalMatrix(t),i=this.coplanarPoint(Qo).applyMatrix4(t),r=this.normal.applyMatrix3(s).normalize();return this.constant=-i.dot(r),this}translate(t){return this.constant-=t.dot(this.normal),this}equals(t){return t.normal.equals(this.normal)&&t.constant===this.constant}clone(){return(new this.constructor).copy(this)}}const sa=new Gi,ia=new Ii;class ra{constructor(t=new ea,e=new ea,s=new ea,i=new ea,r=new ea,n=new ea){this.planes=[t,e,s,i,r,n]}set(t,e,s,i,r,n){const o=this.planes;return o[0].copy(t),o[1].copy(e),o[2].copy(s),o[3].copy(i),o[4].copy(r),o[5].copy(n),this}copy(t){const e=this.planes;for(let s=0;s<6;s++)e[s].copy(t.planes[s]);return this}setFromProjectionMatrix(t,e=2e3){const s=this.planes,i=t.elements,r=i[0],n=i[1],o=i[2],a=i[3],h=i[4],l=i[5],c=i[6],u=i[7],d=i[8],p=i[9],m=i[10],y=i[11],f=i[12],g=i[13],x=i[14],b=i[15];if(s[0].setComponents(a-r,u-h,y-d,b-f).normalize(),s[1].setComponents(a+r,u+h,y+d,b+f).normalize(),s[2].setComponents(a+n,u+l,y+p,b+g).normalize(),s[3].setComponents(a-n,u-l,y-p,b-g).normalize(),s[4].setComponents(a-o,u-c,y-m,b-x).normalize(),e===Os)s[5].setComponents(a+o,u+c,y+m,b+x).normalize();else{if(e!==Fs)throw new Error("THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: "+e);s[5].setComponents(o,c,m,x).normalize()}return this}intersectsObject(t){if(void 0!==t.boundingSphere)null===t.boundingSphere&&t.computeBoundingSphere(),sa.copy(t.boundingSphere).applyMatrix4(t.matrixWorld);else{const e=t.geometry;null===e.boundingSphere&&e.computeBoundingSphere(),sa.copy(e.boundingSphere).applyMatrix4(t.matrixWorld)}return this.intersectsSphere(sa)}intersectsSprite(t){return sa.center.set(0,0,0),sa.radius=.7071067811865476,sa.applyMatrix4(t.matrixWorld),this.intersectsSphere(sa)}intersectsSphere(t){const e=this.planes,s=t.center,i=-t.radius;for(let t=0;t<6;t++){if(e[t].distanceToPoint(s)0?t.max.x:t.min.x,ia.y=i.normal.y>0?t.max.y:t.min.y,ia.z=i.normal.z>0?t.max.z:t.min.z,i.distanceToPoint(ia)<0)return!1}return!0}containsPoint(t){const e=this.planes;for(let s=0;s<6;s++)if(e[s].distanceToPoint(t)<0)return!1;return!0}clone(){return(new this.constructor).copy(this)}}function na(t,e){return t-e}function oa(t,e){return t.z-e.z}function aa(t,e){return e.z-t.z}class ha{constructor(){this.index=0,this.pool=[],this.list=[]}push(t,e,s,i){const r=this.pool,n=this.list;this.index>=r.length&&r.push({start:-1,count:-1,z:-1,index:-1});const o=r[this.index];n.push(o),this.index++,o.start=t,o.count=e,o.z=s,o.index=i}reset(){this.list.length=0,this.index=0}}const la=new nr,ca=new $r(1,1,1),ua=new ra,da=new Ri,pa=new Gi,ma=new Ii,ya=new Ii,fa=new Ii,ga=new ha,xa=new Vn,ba=[];function va(t,e,s=0){const i=e.itemSize;if(t.isInterleavedBufferAttribute||t.array.constructor!==e.array.constructor){const r=t.count;for(let n=0;n65535?new Uint32Array(i):new Uint16Array(i);e.setIndex(new cn(t,1))}this._geometryInitialized=!0}}_validateGeometry(t){const e=this.geometry;if(Boolean(t.getIndex())!==Boolean(e.getIndex()))throw new Error('THREE.BatchedMesh: All geometries must consistently have "index".');for(const s in e.attributes){if(!t.hasAttribute(s))throw new Error(`THREE.BatchedMesh: Added geometry missing "${s}". All geometries must have consistent attributes.`);const i=t.getAttribute(s),r=e.getAttribute(s);if(i.itemSize!==r.itemSize||i.normalized!==r.normalized)throw new Error("THREE.BatchedMesh: All attributes must have a consistent itemSize and normalized value.")}}validateInstanceId(t){const e=this._instanceInfo;if(t<0||t>=e.length||!1===e[t].active)throw new Error(`THREE.BatchedMesh: Invalid instanceId ${t}. Instance is either out of range or has been deleted.`)}validateGeometryId(t){const e=this._geometryInfo;if(t<0||t>=e.length||!1===e[t].active)throw new Error(`THREE.BatchedMesh: Invalid geometryId ${t}. Geometry is either out of range or has been deleted.`)}setCustomSort(t){return this.customSort=t,this}computeBoundingBox(){null===this.boundingBox&&(this.boundingBox=new Ri);const t=this.boundingBox,e=this._instanceInfo;t.makeEmpty();for(let s=0,i=e.length;s=this.maxInstanceCount&&0===this._availableInstanceIds.length)throw new Error("THREE.BatchedMesh: Maximum item count reached.");const e={visible:!0,active:!0,geometryIndex:t};let s=null;this._availableInstanceIds.length>0?(this._availableInstanceIds.sort(na),s=this._availableInstanceIds.shift(),this._instanceInfo[s]=e):(s=this._instanceInfo.length,this._instanceInfo.push(e));const i=this._matricesTexture;la.identity().toArray(i.image.data,16*s),i.needsUpdate=!0;const r=this._colorsTexture;return r&&(ca.toArray(r.image.data,4*s),r.needsUpdate=!0),this._visibilityChanged=!0,s}addGeometry(t,e=-1,s=-1){this._initializeGeometry(t),this._validateGeometry(t);const i={vertexStart:-1,vertexCount:-1,reservedVertexCount:-1,indexStart:-1,indexCount:-1,reservedIndexCount:-1,start:-1,count:-1,boundingBox:null,boundingSphere:null,active:!0},r=this._geometryInfo;i.vertexStart=this._nextVertexStart,i.reservedVertexCount=-1===e?t.getAttribute("position").count:e;const n=t.getIndex();if(null!==n&&(i.indexStart=this._nextIndexStart,i.reservedIndexCount=-1===s?n.count:s),-1!==i.indexStart&&i.indexStart+i.reservedIndexCount>this._maxIndexCount||i.vertexStart+i.reservedVertexCount>this._maxVertexCount)throw new Error("THREE.BatchedMesh: Reserved space request exceeds the maximum buffer size.");let o;return this._availableGeometryIds.length>0?(this._availableGeometryIds.sort(na),o=this._availableGeometryIds.shift(),r[o]=i):(o=this._geometryCount,this._geometryCount++,r.push(i)),this.setGeometryAt(o,t),this._nextIndexStart=i.indexStart+i.reservedIndexCount,this._nextVertexStart=i.vertexStart+i.reservedVertexCount,o}setGeometryAt(t,e){if(t>=this._geometryCount)throw new Error("THREE.BatchedMesh: Maximum geometry count reached.");this._validateGeometry(e);const s=this.geometry,i=null!==s.getIndex(),r=s.getIndex(),n=e.getIndex(),o=this._geometryInfo[t];if(i&&n.count>o.reservedIndexCount||e.attributes.position.count>o.reservedVertexCount)throw new Error("THREE.BatchedMesh: Reserved space not large enough for provided geometry.");const a=o.vertexStart,h=o.reservedVertexCount;o.vertexCount=e.getAttribute("position").count;for(const t in s.attributes){const i=e.getAttribute(t),r=s.getAttribute(t);va(i,r,a);const n=i.itemSize;for(let t=i.count,e=h;t=e.length||!1===e[t].active)return this;const s=this._instanceInfo;for(let e=0,i=s.length;ee)).sort(((t,e)=>s[t].vertexStart-s[e].vertexStart)),r=this.geometry;for(let n=0,o=s.length;n=this._geometryCount)return null;const s=this.geometry,i=this._geometryInfo[t];if(null===i.boundingBox){const t=new Ri,e=s.index,r=s.attributes.position;for(let s=i.start,n=i.start+i.count;s=this._geometryCount)return null;const s=this.geometry,i=this._geometryInfo[t];if(null===i.boundingSphere){const e=new Gi;this.getBoundingBoxAt(t,da),da.getCenter(e.center);const r=s.index,n=s.attributes.position;let o=0;for(let t=i.start,s=i.start+i.count;tt.active));if(Math.max(...s.map((t=>t.vertexStart+t.reservedVertexCount)))>t)throw new Error(`BatchedMesh: Geometry vertex values are being used outside the range ${e}. Cannot shrink further.`);if(this.geometry.index){if(Math.max(...s.map((t=>t.indexStart+t.reservedIndexCount)))>e)throw new Error(`BatchedMesh: Geometry index values are being used outside the range ${e}. Cannot shrink further.`)}const i=this.geometry;i.dispose(),this._maxVertexCount=t,this._maxIndexCount=e,this._geometryInitialized&&(this._geometryInitialized=!1,this.geometry=new zn,this._initializeGeometry(i));const r=this.geometry;i.index&&wa(i.index.array,r.index.array);for(const t in i.attributes)wa(i.attributes[t].array,r.attributes[t].array)}raycast(t,e){const s=this._instanceInfo,i=this._geometryInfo,r=this.matrixWorld,n=this.geometry;xa.material=this.material,xa.geometry.index=n.index,xa.geometry.attributes=n.attributes,null===xa.geometry.boundingBox&&(xa.geometry.boundingBox=new Ri),null===xa.geometry.boundingSphere&&(xa.geometry.boundingSphere=new Gi);for(let n=0,o=s.length;n({...t,boundingBox:null!==t.boundingBox?t.boundingBox.clone():null,boundingSphere:null!==t.boundingSphere?t.boundingSphere.clone():null}))),this._instanceInfo=t._instanceInfo.map((t=>({...t}))),this._maxInstanceCount=t._maxInstanceCount,this._maxVertexCount=t._maxVertexCount,this._maxIndexCount=t._maxIndexCount,this._geometryInitialized=t._geometryInitialized,this._geometryCount=t._geometryCount,this._multiDrawCounts=t._multiDrawCounts.slice(),this._multiDrawStarts=t._multiDrawStarts.slice(),this._matricesTexture=t._matricesTexture.clone(),this._matricesTexture.image.data=this._matricesTexture.image.data.slice(),null!==this._colorsTexture&&(this._colorsTexture=t._colorsTexture.clone(),this._colorsTexture.image.data=this._colorsTexture.image.data.slice()),this}dispose(){return this.geometry.dispose(),this._matricesTexture.dispose(),this._matricesTexture=null,this._indirectTexture.dispose(),this._indirectTexture=null,null!==this._colorsTexture&&(this._colorsTexture.dispose(),this._colorsTexture=null),this}onBeforeRender(t,e,s,i,r){if(!this._visibilityChanged&&!this.perObjectFrustumCulled&&!this.sortObjects)return;const n=i.getIndex(),o=null===n?1:n.array.BYTES_PER_ELEMENT,a=this._instanceInfo,h=this._multiDrawStarts,l=this._multiDrawCounts,c=this._geometryInfo,u=this.perObjectFrustumCulled,d=this._indirectTexture,p=d.image.data;u&&(la.multiplyMatrices(s.projectionMatrix,s.matrixWorldInverse).multiply(this.matrixWorld),ua.setFromProjectionMatrix(la,t.coordinateSystem));let m=0;if(this.sortObjects){la.copy(this.matrixWorld).invert(),ma.setFromMatrixPosition(s.matrixWorld).applyMatrix4(la),ya.set(0,0,-1).transformDirection(s.matrixWorld).transformDirection(la);for(let t=0,e=a.length;t0){const s=t[e[0]];if(void 0!==s){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=s.length;ti)return;Ia.applyMatrix4(t.matrixWorld);const a=e.ray.origin.distanceTo(Ia);return ae.far?void 0:{distance:a,point:Ba.clone().applyMatrix4(t.matrixWorld),index:r,face:null,faceIndex:null,barycoord:null,object:t}}const Ea=new Ii,Pa=new Ii;class Oa extends ka{constructor(t,e){super(t,e),this.isLineSegments=!0,this.type="LineSegments"}computeLineDistances(){const t=this.geometry;if(null===t.index){const e=t.attributes.position,s=[];for(let t=0,i=e.count;t0){const s=t[e[0]];if(void 0!==s){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=s.length;tr.far)return;n.push({distance:h,distanceToRay:Math.sqrt(a),point:s,index:e,face:null,faceIndex:null,barycoord:null,object:o})}}class Ha extends Rr{constructor(){super(),this.isGroup=!0,this.type="Group"}}class qa extends vi{constructor(t,e,s,i,r,n,o,a,h){super(t,e,s,i,r,n,o,a,h),this.isVideoTexture=!0,this.minFilter=void 0!==n?n:wt,this.magFilter=void 0!==r?r:wt,this.generateMipmaps=!1;const l=this;"requestVideoFrameCallback"in t&&t.requestVideoFrameCallback((function e(){l.needsUpdate=!0,t.requestVideoFrameCallback(e)}))}clone(){return new this.constructor(this.image).copy(this)}update(){const t=this.image;!1==="requestVideoFrameCallback"in t&&t.readyState>=t.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}}class Ja extends vi{constructor(t,e){super({width:t,height:e}),this.isFramebufferTexture=!0,this.magFilter=ft,this.minFilter=ft,this.generateMipmaps=!1,this.needsUpdate=!0}}class Xa extends vi{constructor(t,e,s,i,r,n,o,a,h,l,c,u){super(null,n,o,a,h,l,i,r,c,u),this.isCompressedTexture=!0,this.image={width:e,height:s},this.mipmaps=t,this.flipY=!1,this.generateMipmaps=!1}}class Ya extends Xa{constructor(t,e,s,i,r,n){super(t,e,s,r,n),this.isCompressedArrayTexture=!0,this.image.depth=i,this.wrapR=mt,this.layerUpdates=new Set}addLayerUpdate(t){this.layerUpdates.add(t)}clearLayerUpdates(){this.layerUpdates.clear()}}class Za extends Xa{constructor(t,e,s){super(void 0,t[0].width,t[0].height,e,s,ht),this.isCompressedCubeTexture=!0,this.isCubeTexture=!0,this.image=t}}class Ga extends vi{constructor(t,e,s,i,r,n,o,a,h){super(t,e,s,i,r,n,o,a,h),this.isCanvasTexture=!0,this.needsUpdate=!0}}class $a extends vi{constructor(t,e,s,i,r,n,o,a,h,l=1026){if(l!==Dt&&l!==Ht)throw new Error("DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat");void 0===s&&l===Dt&&(s=kt),void 0===s&&l===Ht&&(s=1020),super(null,i,r,n,o,a,l,s,h),this.isDepthTexture=!0,this.image={width:t,height:e},this.magFilter=void 0!==o?o:ft,this.minFilter=void 0!==a?a:ft,this.flipY=!1,this.generateMipmaps=!1,this.compareFunction=null}copy(t){return super.copy(t),this.compareFunction=t.compareFunction,this}toJSON(t){const e=super.toJSON(t);return null!==this.compareFunction&&(e.compareFunction=this.compareFunction),e}}class Qa{constructor(){this.type="Curve",this.arcLengthDivisions=200}getPoint(){return console.warn("THREE.Curve: .getPoint() not implemented."),null}getPointAt(t,e){const s=this.getUtoTmapping(t);return this.getPoint(s,e)}getPoints(t=5){const e=[];for(let s=0;s<=t;s++)e.push(this.getPoint(s/t));return e}getSpacedPoints(t=5){const e=[];for(let s=0;s<=t;s++)e.push(this.getPointAt(s/t));return e}getLength(){const t=this.getLengths();return t[t.length-1]}getLengths(t=this.arcLengthDivisions){if(this.cacheArcLengths&&this.cacheArcLengths.length===t+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;const e=[];let s,i=this.getPoint(0),r=0;e.push(0);for(let n=1;n<=t;n++)s=this.getPoint(n/t),r+=s.distanceTo(i),e.push(r),i=s;return this.cacheArcLengths=e,e}updateArcLengths(){this.needsUpdate=!0,this.getLengths()}getUtoTmapping(t,e){const s=this.getLengths();let i=0;const r=s.length;let n;n=e||t*s[r-1];let o,a=0,h=r-1;for(;a<=h;)if(i=Math.floor(a+(h-a)/2),o=s[i]-n,o<0)a=i+1;else{if(!(o>0)){h=i;break}h=i-1}if(i=h,s[i]===n)return i/(r-1);const l=s[i];return(i+(n-l)/(s[i+1]-l))/(r-1)}getTangent(t,e){const s=1e-4;let i=t-s,r=t+s;i<0&&(i=0),r>1&&(r=1);const n=this.getPoint(i),o=this.getPoint(r),a=e||(n.isVector2?new Zs:new Ii);return a.copy(o).sub(n).normalize(),a}getTangentAt(t,e){const s=this.getUtoTmapping(t);return this.getTangent(s,e)}computeFrenetFrames(t,e){const s=new Ii,i=[],r=[],n=[],o=new Ii,a=new nr;for(let e=0;e<=t;e++){const s=e/t;i[e]=this.getTangentAt(s,new Ii)}r[0]=new Ii,n[0]=new Ii;let h=Number.MAX_VALUE;const l=Math.abs(i[0].x),c=Math.abs(i[0].y),u=Math.abs(i[0].z);l<=h&&(h=l,s.set(1,0,0)),c<=h&&(h=c,s.set(0,1,0)),u<=h&&s.set(0,0,1),o.crossVectors(i[0],s).normalize(),r[0].crossVectors(i[0],o),n[0].crossVectors(i[0],r[0]);for(let e=1;e<=t;e++){if(r[e]=r[e-1].clone(),n[e]=n[e-1].clone(),o.crossVectors(i[e-1],i[e]),o.length()>Number.EPSILON){o.normalize();const t=Math.acos(Ds(i[e-1].dot(i[e]),-1,1));r[e].applyMatrix4(a.makeRotationAxis(o,t))}n[e].crossVectors(i[e],r[e])}if(!0===e){let e=Math.acos(Ds(r[0].dot(r[t]),-1,1));e/=t,i[0].dot(o.crossVectors(r[0],r[t]))>0&&(e=-e);for(let s=1;s<=t;s++)r[s].applyMatrix4(a.makeRotationAxis(i[s],e*s)),n[s].crossVectors(i[s],r[s])}return{tangents:i,normals:r,binormals:n}}clone(){return(new this.constructor).copy(this)}copy(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}toJSON(){const t={metadata:{version:4.6,type:"Curve",generator:"Curve.toJSON"}};return t.arcLengthDivisions=this.arcLengthDivisions,t.type=this.type,t}fromJSON(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}}class Ka extends Qa{constructor(t=0,e=0,s=1,i=1,r=0,n=2*Math.PI,o=!1,a=0){super(),this.isEllipseCurve=!0,this.type="EllipseCurve",this.aX=t,this.aY=e,this.xRadius=s,this.yRadius=i,this.aStartAngle=r,this.aEndAngle=n,this.aClockwise=o,this.aRotation=a}getPoint(t,e=new Zs){const s=e,i=2*Math.PI;let r=this.aEndAngle-this.aStartAngle;const n=Math.abs(r)i;)r-=i;r0?0:(Math.floor(Math.abs(h)/r)+1)*r:0===l&&h===r-1&&(h=r-2,l=1),this.closed||h>0?o=i[(h-1)%r]:(sh.subVectors(i[0],i[1]).add(i[0]),o=sh);const c=i[h%r],u=i[(h+1)%r];if(this.closed||h+2i.length-2?i.length-1:n+1],c=i[n>i.length-3?i.length-1:n+2];return s.set(ah(o,a.x,h.x,l.x,c.x),ah(o,a.y,h.y,l.y,c.y)),s}copy(t){super.copy(t),this.points=[];for(let e=0,s=t.points.length;e=s){const t=i[r]-s,n=this.curves[r],o=n.getLength(),a=0===o?0:1-t/o;return n.getPointAt(a,e)}r++}return null}getLength(){const t=this.getCurveLengths();return t[t.length-1]}updateArcLengths(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()}getCurveLengths(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;const t=[];let e=0;for(let s=0,i=this.curves.length;s1&&!e[e.length-1].equals(e[0])&&e.push(e[0]),e}copy(t){super.copy(t),this.curves=[];for(let e=0,s=t.curves.length;e0){const t=h.getPoint(0);t.equals(this.currentPoint)||this.lineTo(t.x,t.y)}this.curves.push(h);const l=h.getPoint(1);return this.currentPoint.copy(l),this}copy(t){return super.copy(t),this.currentPoint.copy(t.currentPoint),this}toJSON(){const t=super.toJSON();return t.currentPoint=this.currentPoint.toArray(),t}fromJSON(t){return super.fromJSON(t),this.currentPoint.fromArray(t.currentPoint),this}}class vh extends zn{constructor(t=[new Zs(0,-.5),new Zs(.5,0),new Zs(0,.5)],e=12,s=0,i=2*Math.PI){super(),this.type="LatheGeometry",this.parameters={points:t,segments:e,phiStart:s,phiLength:i},e=Math.floor(e),i=Ds(i,0,2*Math.PI);const r=[],n=[],o=[],a=[],h=[],l=1/e,c=new Ii,u=new Zs,d=new Ii,p=new Ii,m=new Ii;let y=0,f=0;for(let e=0;e<=t.length-1;e++)switch(e){case 0:y=t[e+1].x-t[e].x,f=t[e+1].y-t[e].y,d.x=1*f,d.y=-y,d.z=0*f,m.copy(d),d.normalize(),a.push(d.x,d.y,d.z);break;case t.length-1:a.push(m.x,m.y,m.z);break;default:y=t[e+1].x-t[e].x,f=t[e+1].y-t[e].y,d.x=1*f,d.y=-y,d.z=0*f,p.copy(d),d.x+=m.x,d.y+=m.y,d.z+=m.z,d.normalize(),a.push(d.x,d.y,d.z),m.copy(p)}for(let r=0;r<=e;r++){const d=s+r*l*i,p=Math.sin(d),m=Math.cos(d);for(let s=0;s<=t.length-1;s++){c.x=t[s].x*p,c.y=t[s].y,c.z=t[s].x*m,n.push(c.x,c.y,c.z),u.x=r/e,u.y=s/(t.length-1),o.push(u.x,u.y);const i=a[3*s+0]*p,l=a[3*s+1],d=a[3*s+0]*m;h.push(i,l,d)}}for(let s=0;s0||0!==i)&&(l.push(n,o,h),x+=3),(e>0||i!==r-1)&&(l.push(o,a,h),x+=3)}h.addGroup(f,x,0),f+=x}(),!1===n&&(t>0&&g(!0),e>0&&g(!1)),this.setIndex(l),this.setAttribute("position",new bn(c,3)),this.setAttribute("normal",new bn(u,3)),this.setAttribute("uv",new bn(d,2))}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new Sh(t.radiusTop,t.radiusBottom,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class _h extends Sh{constructor(t=1,e=1,s=32,i=1,r=!1,n=0,o=2*Math.PI){super(0,t,e,s,i,r,n,o),this.type="ConeGeometry",this.parameters={radius:t,height:e,radialSegments:s,heightSegments:i,openEnded:r,thetaStart:n,thetaLength:o}}static fromJSON(t){return new _h(t.radius,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class Ah extends zn{constructor(t=[],e=[],s=1,i=0){super(),this.type="PolyhedronGeometry",this.parameters={vertices:t,indices:e,radius:s,detail:i};const r=[],n=[];function o(t,e,s,i){const r=i+1,n=[];for(let i=0;i<=r;i++){n[i]=[];const o=t.clone().lerp(s,i/r),a=e.clone().lerp(s,i/r),h=r-i;for(let t=0;t<=h;t++)n[i][t]=0===t&&i===r?o:o.clone().lerp(a,t/h)}for(let t=0;t.9&&o<.1&&(e<.2&&(n[t+0]+=1),s<.2&&(n[t+2]+=1),i<.2&&(n[t+4]+=1))}}()}(),this.setAttribute("position",new bn(r,3)),this.setAttribute("normal",new bn(r.slice(),3)),this.setAttribute("uv",new bn(n,2)),0===i?this.computeVertexNormals():this.normalizeNormals()}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new Ah(t.vertices,t.indices,t.radius,t.details)}}class Th extends Ah{constructor(t=1,e=0){const s=(1+Math.sqrt(5))/2,i=1/s;super([-1,-1,-1,-1,-1,1,-1,1,-1,-1,1,1,1,-1,-1,1,-1,1,1,1,-1,1,1,1,0,-i,-s,0,-i,s,0,i,-s,0,i,s,-i,-s,0,-i,s,0,i,-s,0,i,s,0,-s,0,-i,s,0,-i,-s,0,i,s,0,i],[3,11,7,3,7,15,3,15,13,7,19,17,7,17,6,7,6,15,17,4,8,17,8,10,17,10,6,8,0,16,8,16,2,8,2,10,0,12,1,0,1,18,0,18,16,6,10,2,6,2,13,6,13,15,2,16,18,2,18,3,2,3,13,18,1,9,18,9,11,18,11,3,4,14,12,4,12,0,4,0,8,11,9,5,11,5,19,11,19,7,19,5,14,19,14,4,19,4,17,1,12,14,1,14,5,1,5,9],t,e),this.type="DodecahedronGeometry",this.parameters={radius:t,detail:e}}static fromJSON(t){return new Th(t.radius,t.detail)}}const zh=new Ii,Ch=new Ii,Ih=new Ii,Bh=new Jr;class kh extends zn{constructor(t=null,e=1){if(super(),this.type="EdgesGeometry",this.parameters={geometry:t,thresholdAngle:e},null!==t){const s=4,i=Math.pow(10,s),r=Math.cos(Ws*e),n=t.getIndex(),o=t.getAttribute("position"),a=n?n.count:o.count,h=[0,0,0],l=["a","b","c"],c=new Array(3),u={},d=[];for(let t=0;t80*s){a=l=t[0],h=c=t[1];for(let e=s;el&&(l=u),d>c&&(c=d);p=Math.max(l-a,c-h),p=0!==p?32767/p:0}return Fh(n,o,s,a,h,p,0),o};function Ph(t,e,s,i,r){let n,o;if(r===function(t,e,s,i){let r=0;for(let n=e,o=s-i;n0)for(n=e;n=e;n-=i)o=el(n,t[n],t[n+1],o);return o&&Zh(o,o.next)&&(sl(o),o=o.next),o}function Oh(t,e){if(!t)return t;e||(e=t);let s,i=t;do{if(s=!1,i.steiner||!Zh(i,i.next)&&0!==Yh(i.prev,i,i.next))i=i.next;else{if(sl(i),i=e=i.prev,i===i.next)break;s=!0}}while(s||i!==e);return e}function Fh(t,e,s,i,r,n,o){if(!t)return;!o&&n&&function(t,e,s,i){let r=t;do{0===r.z&&(r.z=Hh(r.x,r.y,e,s,i)),r.prevZ=r.prev,r.nextZ=r.next,r=r.next}while(r!==t);r.prevZ.nextZ=null,r.prevZ=null,function(t){let e,s,i,r,n,o,a,h,l=1;do{for(s=t,t=null,n=null,o=0;s;){for(o++,i=s,a=0,e=0;e0||h>0&&i;)0!==a&&(0===h||!i||s.z<=i.z)?(r=s,s=s.nextZ,a--):(r=i,i=i.nextZ,h--),n?n.nextZ=r:t=r,r.prevZ=n,n=r;s=i}n.nextZ=null,l*=2}while(o>1)}(r)}(t,i,r,n);let a,h,l=t;for(;t.prev!==t.next;)if(a=t.prev,h=t.next,n?Lh(t,i,r,n):Nh(t))e.push(a.i/s|0),e.push(t.i/s|0),e.push(h.i/s|0),sl(t),t=h.next,l=h.next;else if((t=h)===l){o?1===o?Fh(t=Vh(Oh(t),e,s),e,s,i,r,n,2):2===o&&Wh(t,e,s,i,r,n):Fh(Oh(t),e,s,i,r,n,1);break}}function Nh(t){const e=t.prev,s=t,i=t.next;if(Yh(e,s,i)>=0)return!1;const r=e.x,n=s.x,o=i.x,a=e.y,h=s.y,l=i.y,c=rn?r>o?r:o:n>o?n:o,p=a>h?a>l?a:l:h>l?h:l;let m=i.next;for(;m!==e;){if(m.x>=c&&m.x<=d&&m.y>=u&&m.y<=p&&Jh(r,a,n,h,o,l,m.x,m.y)&&Yh(m.prev,m,m.next)>=0)return!1;m=m.next}return!0}function Lh(t,e,s,i){const r=t.prev,n=t,o=t.next;if(Yh(r,n,o)>=0)return!1;const a=r.x,h=n.x,l=o.x,c=r.y,u=n.y,d=o.y,p=ah?a>l?a:l:h>l?h:l,f=c>u?c>d?c:d:u>d?u:d,g=Hh(p,m,e,s,i),x=Hh(y,f,e,s,i);let b=t.prevZ,v=t.nextZ;for(;b&&b.z>=g&&v&&v.z<=x;){if(b.x>=p&&b.x<=y&&b.y>=m&&b.y<=f&&b!==r&&b!==o&&Jh(a,c,h,u,l,d,b.x,b.y)&&Yh(b.prev,b,b.next)>=0)return!1;if(b=b.prevZ,v.x>=p&&v.x<=y&&v.y>=m&&v.y<=f&&v!==r&&v!==o&&Jh(a,c,h,u,l,d,v.x,v.y)&&Yh(v.prev,v,v.next)>=0)return!1;v=v.nextZ}for(;b&&b.z>=g;){if(b.x>=p&&b.x<=y&&b.y>=m&&b.y<=f&&b!==r&&b!==o&&Jh(a,c,h,u,l,d,b.x,b.y)&&Yh(b.prev,b,b.next)>=0)return!1;b=b.prevZ}for(;v&&v.z<=x;){if(v.x>=p&&v.x<=y&&v.y>=m&&v.y<=f&&v!==r&&v!==o&&Jh(a,c,h,u,l,d,v.x,v.y)&&Yh(v.prev,v,v.next)>=0)return!1;v=v.nextZ}return!0}function Vh(t,e,s){let i=t;do{const r=i.prev,n=i.next.next;!Zh(r,n)&&Gh(r,i,i.next,n)&&Kh(r,n)&&Kh(n,r)&&(e.push(r.i/s|0),e.push(i.i/s|0),e.push(n.i/s|0),sl(i),sl(i.next),i=t=n),i=i.next}while(i!==t);return Oh(i)}function Wh(t,e,s,i,r,n){let o=t;do{let t=o.next.next;for(;t!==o.prev;){if(o.i!==t.i&&Xh(o,t)){let a=tl(o,t);return o=Oh(o,o.next),a=Oh(a,a.next),Fh(o,e,s,i,r,n,0),void Fh(a,e,s,i,r,n,0)}t=t.next}o=o.next}while(o!==t)}function jh(t,e){return t.x-e.x}function Uh(t,e){const s=function(t,e){let s,i=e,r=-1/0;const n=t.x,o=t.y;do{if(o<=i.y&&o>=i.next.y&&i.next.y!==i.y){const t=i.x+(o-i.y)*(i.next.x-i.x)/(i.next.y-i.y);if(t<=n&&t>r&&(r=t,s=i.x=i.x&&i.x>=h&&n!==i.x&&Jh(os.x||i.x===s.x&&Dh(s,i)))&&(s=i,u=c)),i=i.next}while(i!==a);return s}(t,e);if(!s)return e;const i=tl(s,t);return Oh(i,i.next),Oh(s,s.next)}function Dh(t,e){return Yh(t.prev,t,e.prev)<0&&Yh(e.next,t,t.next)<0}function Hh(t,e,s,i,r){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=(t-s)*r|0)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=(e-i)*r|0)|e<<8))|e<<4))|e<<2))|e<<1))<<1}function qh(t){let e=t,s=t;do{(e.x=(t-o)*(n-a)&&(t-o)*(i-a)>=(s-o)*(e-a)&&(s-o)*(n-a)>=(r-o)*(i-a)}function Xh(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!function(t,e){let s=t;do{if(s.i!==t.i&&s.next.i!==t.i&&s.i!==e.i&&s.next.i!==e.i&&Gh(s,s.next,t,e))return!0;s=s.next}while(s!==t);return!1}(t,e)&&(Kh(t,e)&&Kh(e,t)&&function(t,e){let s=t,i=!1;const r=(t.x+e.x)/2,n=(t.y+e.y)/2;do{s.y>n!=s.next.y>n&&s.next.y!==s.y&&r<(s.next.x-s.x)*(n-s.y)/(s.next.y-s.y)+s.x&&(i=!i),s=s.next}while(s!==t);return i}(t,e)&&(Yh(t.prev,t,e.prev)||Yh(t,e.prev,e))||Zh(t,e)&&Yh(t.prev,t,t.next)>0&&Yh(e.prev,e,e.next)>0)}function Yh(t,e,s){return(e.y-t.y)*(s.x-e.x)-(e.x-t.x)*(s.y-e.y)}function Zh(t,e){return t.x===e.x&&t.y===e.y}function Gh(t,e,s,i){const r=Qh(Yh(t,e,s)),n=Qh(Yh(t,e,i)),o=Qh(Yh(s,i,t)),a=Qh(Yh(s,i,e));return r!==n&&o!==a||(!(0!==r||!$h(t,s,e))||(!(0!==n||!$h(t,i,e))||(!(0!==o||!$h(s,t,i))||!(0!==a||!$h(s,e,i)))))}function $h(t,e,s){return e.x<=Math.max(t.x,s.x)&&e.x>=Math.min(t.x,s.x)&&e.y<=Math.max(t.y,s.y)&&e.y>=Math.min(t.y,s.y)}function Qh(t){return t>0?1:t<0?-1:0}function Kh(t,e){return Yh(t.prev,t,t.next)<0?Yh(t,e,t.next)>=0&&Yh(t,t.prev,e)>=0:Yh(t,e,t.prev)<0||Yh(t,t.next,e)<0}function tl(t,e){const s=new il(t.i,t.x,t.y),i=new il(e.i,e.x,e.y),r=t.next,n=e.prev;return t.next=e,e.prev=t,s.next=r,r.prev=s,i.next=s,s.prev=i,n.next=i,i.prev=n,i}function el(t,e,s,i){const r=new il(t,e,s);return i?(r.next=i.next,r.prev=i,i.next.prev=r,i.next=r):(r.prev=r,r.next=r),r}function sl(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&&(t.prevZ.nextZ=t.nextZ),t.nextZ&&(t.nextZ.prevZ=t.prevZ)}function il(t,e,s){this.i=t,this.x=e,this.y=s,this.prev=null,this.next=null,this.z=0,this.prevZ=null,this.nextZ=null,this.steiner=!1}class rl{static area(t){const e=t.length;let s=0;for(let i=e-1,r=0;r2&&t[e-1].equals(t[0])&&t.pop()}function ol(t,e){for(let s=0;sNumber.EPSILON){const u=Math.sqrt(c),d=Math.sqrt(h*h+l*l),p=e.x-a/u,m=e.y+o/u,y=((s.x-l/d-p)*l-(s.y+h/d-m)*h)/(o*l-a*h);i=p+o*y-t.x,r=m+a*y-t.y;const f=i*i+r*r;if(f<=2)return new Zs(i,r);n=Math.sqrt(f/2)}else{let t=!1;o>Number.EPSILON?h>Number.EPSILON&&(t=!0):o<-Number.EPSILON?h<-Number.EPSILON&&(t=!0):Math.sign(a)===Math.sign(l)&&(t=!0),t?(i=-a,r=o,n=Math.sqrt(c)):(i=o,r=a,n=Math.sqrt(c/2))}return new Zs(i/n,r/n)}const k=[];for(let t=0,e=T.length,s=e-1,i=t+1;t=0;t--){const e=t/p,s=c*Math.cos(e*Math.PI/2),i=u*Math.sin(e*Math.PI/2)+d;for(let t=0,e=T.length;t=0;){const i=s;let r=s-1;r<0&&(r=t.length-1);for(let t=0,s=a+2*p;t0)&&d.push(e,r,h),(t!==s-1||a0!=t>0&&this.version++,this._anisotropy=t}get clearcoat(){return this._clearcoat}set clearcoat(t){this._clearcoat>0!=t>0&&this.version++,this._clearcoat=t}get iridescence(){return this._iridescence}set iridescence(t){this._iridescence>0!=t>0&&this.version++,this._iridescence=t}get dispersion(){return this._dispersion}set dispersion(t){this._dispersion>0!=t>0&&this.version++,this._dispersion=t}get sheen(){return this._sheen}set sheen(t){this._sheen>0!=t>0&&this.version++,this._sheen=t}get transmission(){return this._transmission}set transmission(t){this._transmission>0!=t>0&&this.version++,this._transmission=t}copy(t){return super.copy(t),this.defines={STANDARD:"",PHYSICAL:""},this.anisotropy=t.anisotropy,this.anisotropyRotation=t.anisotropyRotation,this.anisotropyMap=t.anisotropyMap,this.clearcoat=t.clearcoat,this.clearcoatMap=t.clearcoatMap,this.clearcoatRoughness=t.clearcoatRoughness,this.clearcoatRoughnessMap=t.clearcoatRoughnessMap,this.clearcoatNormalMap=t.clearcoatNormalMap,this.clearcoatNormalScale.copy(t.clearcoatNormalScale),this.dispersion=t.dispersion,this.ior=t.ior,this.iridescence=t.iridescence,this.iridescenceMap=t.iridescenceMap,this.iridescenceIOR=t.iridescenceIOR,this.iridescenceThicknessRange=[...t.iridescenceThicknessRange],this.iridescenceThicknessMap=t.iridescenceThicknessMap,this.sheen=t.sheen,this.sheenColor.copy(t.sheenColor),this.sheenColorMap=t.sheenColorMap,this.sheenRoughness=t.sheenRoughness,this.sheenRoughnessMap=t.sheenRoughnessMap,this.transmission=t.transmission,this.transmissionMap=t.transmissionMap,this.thickness=t.thickness,this.thicknessMap=t.thicknessMap,this.attenuationDistance=t.attenuationDistance,this.attenuationColor.copy(t.attenuationColor),this.specularIntensity=t.specularIntensity,this.specularIntensityMap=t.specularIntensityMap,this.specularColor.copy(t.specularColor),this.specularColorMap=t.specularColorMap,this}}class Tl extends tn{constructor(t){super(),this.isMeshPhongMaterial=!0,this.type="MeshPhongMaterial",this.color=new $r(16777215),this.specular=new $r(1118481),this.shininess=30,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new $r(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Zs(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new yr,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.specular.copy(t.specular),this.shininess=t.shininess,this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.envMapRotation.copy(t.envMapRotation),this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this.fog=t.fog,this}}class zl extends tn{constructor(t){super(),this.isMeshToonMaterial=!0,this.defines={TOON:""},this.type="MeshToonMaterial",this.color=new $r(16777215),this.map=null,this.gradientMap=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new $r(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Zs(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.gradientMap=t.gradientMap,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.fog=t.fog,this}}class Cl extends tn{constructor(t){super(),this.isMeshNormalMaterial=!0,this.type="MeshNormalMaterial",this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Zs(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.flatShading=!1,this.setValues(t)}copy(t){return super.copy(t),this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.flatShading=t.flatShading,this}}class Il extends tn{constructor(t){super(),this.isMeshLambertMaterial=!0,this.type="MeshLambertMaterial",this.color=new $r(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new $r(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Zs(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new yr,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.color.copy(t.color),this.map=t.map,this.lightMap=t.lightMap,this.lightMapIntensity=t.lightMapIntensity,this.aoMap=t.aoMap,this.aoMapIntensity=t.aoMapIntensity,this.emissive.copy(t.emissive),this.emissiveMap=t.emissiveMap,this.emissiveIntensity=t.emissiveIntensity,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.specularMap=t.specularMap,this.alphaMap=t.alphaMap,this.envMap=t.envMap,this.envMapRotation.copy(t.envMapRotation),this.combine=t.combine,this.reflectivity=t.reflectivity,this.refractionRatio=t.refractionRatio,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this.wireframeLinecap=t.wireframeLinecap,this.wireframeLinejoin=t.wireframeLinejoin,this.flatShading=t.flatShading,this.fog=t.fog,this}}class Bl extends tn{constructor(t){super(),this.isMeshDepthMaterial=!0,this.type="MeshDepthMaterial",this.depthPacking=3200,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.setValues(t)}copy(t){return super.copy(t),this.depthPacking=t.depthPacking,this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.wireframe=t.wireframe,this.wireframeLinewidth=t.wireframeLinewidth,this}}class kl extends tn{constructor(t){super(),this.isMeshDistanceMaterial=!0,this.type="MeshDistanceMaterial",this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.setValues(t)}copy(t){return super.copy(t),this.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this}}class Rl extends tn{constructor(t){super(),this.isMeshMatcapMaterial=!0,this.defines={MATCAP:""},this.type="MeshMatcapMaterial",this.color=new $r(16777215),this.matcap=null,this.map=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Zs(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.flatShading=!1,this.fog=!0,this.setValues(t)}copy(t){return super.copy(t),this.defines={MATCAP:""},this.color.copy(t.color),this.matcap=t.matcap,this.map=t.map,this.bumpMap=t.bumpMap,this.bumpScale=t.bumpScale,this.normalMap=t.normalMap,this.normalMapType=t.normalMapType,this.normalScale.copy(t.normalScale),this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this.alphaMap=t.alphaMap,this.flatShading=t.flatShading,this.fog=t.fog,this}}class El extends Sa{constructor(t){super(),this.isLineDashedMaterial=!0,this.type="LineDashedMaterial",this.scale=1,this.dashSize=3,this.gapSize=1,this.setValues(t)}copy(t){return super.copy(t),this.scale=t.scale,this.dashSize=t.dashSize,this.gapSize=t.gapSize,this}}function Pl(t,e,s){return!t||!s&&t.constructor===e?t:"number"==typeof e.BYTES_PER_ELEMENT?new e(t):Array.prototype.slice.call(t)}function Ol(t){return ArrayBuffer.isView(t)&&!(t instanceof DataView)}function Fl(t){const e=t.length,s=new Array(e);for(let t=0;t!==e;++t)s[t]=t;return s.sort((function(e,s){return t[e]-t[s]})),s}function Nl(t,e,s){const i=t.length,r=new t.constructor(i);for(let n=0,o=0;o!==i;++n){const i=s[n]*e;for(let s=0;s!==e;++s)r[o++]=t[i+s]}return r}function Ll(t,e,s,i){let r=1,n=t[0];for(;void 0!==n&&void 0===n[i];)n=t[r++];if(void 0===n)return;let o=n[i];if(void 0!==o)if(Array.isArray(o))do{o=n[i],void 0!==o&&(e.push(n.time),s.push.apply(s,o)),n=t[r++]}while(void 0!==n);else if(void 0!==o.toArray)do{o=n[i],void 0!==o&&(e.push(n.time),o.toArray(s,s.length)),n=t[r++]}while(void 0!==n);else do{o=n[i],void 0!==o&&(e.push(n.time),s.push(o)),n=t[r++]}while(void 0!==n)}const Vl={convertArray:Pl,isTypedArray:Ol,getKeyframeOrder:Fl,sortedArray:Nl,flattenJSON:Ll,subclip:function(t,e,s,i,r=30){const n=t.clone();n.name=e;const o=[];for(let t=0;t=i)){h.push(e.times[t]);for(let s=0;sn.tracks[t].times[0]&&(a=n.tracks[t].times[0]);for(let t=0;t=i.times[u]){const t=u*h+a,e=t+h-a;d=i.values.slice(t,e)}else{const t=i.createInterpolant(),e=a,s=h-a;t.evaluate(n),d=t.resultBuffer.slice(e,s)}if("quaternion"===r){(new Ci).fromArray(d).normalize().conjugate().toArray(d)}const p=o.times.length;for(let t=0;t=r)break t;{const o=e[1];t=r)break e}n=s,s=0}}for(;s>>1;te;)--n;if(++n,0!==r||n!==i){r>=n&&(n=Math.max(n,1),r=n-1);const t=this.getValueSize();this.times=s.slice(r,n),this.values=this.values.slice(r*t,n*t)}return this}validate(){let t=!0;const e=this.getValueSize();e-Math.floor(e)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),t=!1);const s=this.times,i=this.values,r=s.length;0===r&&(console.error("THREE.KeyframeTrack: Track is empty.",this),t=!1);let n=null;for(let e=0;e!==r;e++){const i=s[e];if("number"==typeof i&&isNaN(i)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,e,i),t=!1;break}if(null!==n&&n>i){console.error("THREE.KeyframeTrack: Out of order keys.",this,e,i,n),t=!1;break}n=i}if(void 0!==i&&Ol(i))for(let e=0,s=i.length;e!==s;++e){const s=i[e];if(isNaN(s)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,e,s),t=!1;break}}return t}optimize(){const t=this.times.slice(),e=this.values.slice(),s=this.getValueSize(),i=this.getInterpolation()===Pe,r=t.length-1;let n=1;for(let o=1;o0){t[n]=t[r];for(let t=r*s,i=n*s,o=0;o!==s;++o)e[i+o]=e[t+o];++n}return n!==t.length?(this.times=t.slice(0,n),this.values=e.slice(0,n*s)):(this.times=t,this.values=e),this}clone(){const t=this.times.slice(),e=this.values.slice(),s=new(0,this.constructor)(this.name,t,e);return s.createInterpolant=this.createInterpolant,s}}Hl.prototype.TimeBufferType=Float32Array,Hl.prototype.ValueBufferType=Float32Array,Hl.prototype.DefaultInterpolation=Ee;class ql extends Hl{constructor(t,e,s){super(t,e,s)}}ql.prototype.ValueTypeName="bool",ql.prototype.ValueBufferType=Array,ql.prototype.DefaultInterpolation=Re,ql.prototype.InterpolantFactoryMethodLinear=void 0,ql.prototype.InterpolantFactoryMethodSmooth=void 0;class Jl extends Hl{}Jl.prototype.ValueTypeName="color";class Xl extends Hl{}Xl.prototype.ValueTypeName="number";class Yl extends Wl{constructor(t,e,s,i){super(t,e,s,i)}interpolate_(t,e,s,i){const r=this.resultBuffer,n=this.sampleValues,o=this.valueSize,a=(s-e)/(i-e);let h=t*o;for(let t=h+o;h!==t;h+=4)Ci.slerpFlat(r,0,n,h-o,n,h,a);return r}}class Zl extends Hl{InterpolantFactoryMethodLinear(t){return new Yl(this.times,this.values,this.getValueSize(),t)}}Zl.prototype.ValueTypeName="quaternion",Zl.prototype.InterpolantFactoryMethodSmooth=void 0;class Gl extends Hl{constructor(t,e,s){super(t,e,s)}}Gl.prototype.ValueTypeName="string",Gl.prototype.ValueBufferType=Array,Gl.prototype.DefaultInterpolation=Re,Gl.prototype.InterpolantFactoryMethodLinear=void 0,Gl.prototype.InterpolantFactoryMethodSmooth=void 0;class $l extends Hl{}$l.prototype.ValueTypeName="vector";class Ql{constructor(t="",e=-1,s=[],i=2500){this.name=t,this.tracks=s,this.duration=e,this.blendMode=i,this.uuid=Us(),this.duration<0&&this.resetDuration()}static parse(t){const e=[],s=t.tracks,i=1/(t.fps||1);for(let t=0,r=s.length;t!==r;++t)e.push(Kl(s[t]).scale(i));const r=new this(t.name,t.duration,e,t.blendMode);return r.uuid=t.uuid,r}static toJSON(t){const e=[],s=t.tracks,i={name:t.name,duration:t.duration,tracks:e,uuid:t.uuid,blendMode:t.blendMode};for(let t=0,i=s.length;t!==i;++t)e.push(Hl.toJSON(s[t]));return i}static CreateFromMorphTargetSequence(t,e,s,i){const r=e.length,n=[];for(let t=0;t1){const t=n[1];let e=i[t];e||(i[t]=e=[]),e.push(s)}}const n=[];for(const t in i)n.push(this.CreateFromMorphTargetSequence(t,i[t],e,s));return n}static parseAnimation(t,e){if(!t)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;const s=function(t,e,s,i,r){if(0!==s.length){const n=[],o=[];Ll(s,n,o,i),0!==n.length&&r.push(new t(e,n,o))}},i=[],r=t.name||"default",n=t.fps||30,o=t.blendMode;let a=t.length||-1;const h=t.hierarchy||[];for(let t=0;t{e&&e(r),this.manager.itemEnd(t)}),0),r;if(void 0!==rc[t])return void rc[t].push({onLoad:e,onProgress:s,onError:i});rc[t]=[],rc[t].push({onLoad:e,onProgress:s,onError:i});const n=new Request(t,{headers:new Headers(this.requestHeader),credentials:this.withCredentials?"include":"same-origin"}),o=this.mimeType,a=this.responseType;fetch(n).then((e=>{if(200===e.status||0===e.status){if(0===e.status&&console.warn("THREE.FileLoader: HTTP Status 0 received."),"undefined"==typeof ReadableStream||void 0===e.body||void 0===e.body.getReader)return e;const s=rc[t],i=e.body.getReader(),r=e.headers.get("X-File-Size")||e.headers.get("Content-Length"),n=r?parseInt(r):0,o=0!==n;let a=0;const h=new ReadableStream({start(t){!function e(){i.read().then((({done:i,value:r})=>{if(i)t.close();else{a+=r.byteLength;const i=new ProgressEvent("progress",{lengthComputable:o,loaded:a,total:n});for(let t=0,e=s.length;t{t.error(e)}))}()}});return new Response(h)}throw new nc(`fetch for "${e.url}" responded with ${e.status}: ${e.statusText}`,e)})).then((t=>{switch(a){case"arraybuffer":return t.arrayBuffer();case"blob":return t.blob();case"document":return t.text().then((t=>(new DOMParser).parseFromString(t,o)));case"json":return t.json();default:if(void 0===o)return t.text();{const e=/charset="?([^;"\s]*)"?/i.exec(o),s=e&&e[1]?e[1].toLowerCase():void 0,i=new TextDecoder(s);return t.arrayBuffer().then((t=>i.decode(t)))}}})).then((e=>{tc.add(t,e);const s=rc[t];delete rc[t];for(let t=0,i=s.length;t{const s=rc[t];if(void 0===s)throw this.manager.itemError(t),e;delete rc[t];for(let t=0,i=s.length;t{this.manager.itemEnd(t)})),this.manager.itemStart(t)}setResponseType(t){return this.responseType=t,this}setMimeType(t){return this.mimeType=t,this}}class ac extends ic{constructor(t){super(t)}load(t,e,s,i){const r=this,n=new oc(this.manager);n.setPath(this.path),n.setRequestHeader(this.requestHeader),n.setWithCredentials(this.withCredentials),n.load(t,(function(s){try{e(r.parse(JSON.parse(s)))}catch(e){i?i(e):console.error(e),r.manager.itemError(t)}}),s,i)}parse(t){const e=[];for(let s=0;s0:i.vertexColors=t.vertexColors),void 0!==t.uniforms)for(const e in t.uniforms){const r=t.uniforms[e];switch(i.uniforms[e]={},r.type){case"t":i.uniforms[e].value=s(r.value);break;case"c":i.uniforms[e].value=(new $r).setHex(r.value);break;case"v2":i.uniforms[e].value=(new Zs).fromArray(r.value);break;case"v3":i.uniforms[e].value=(new Ii).fromArray(r.value);break;case"v4":i.uniforms[e].value=(new wi).fromArray(r.value);break;case"m3":i.uniforms[e].value=(new Gs).fromArray(r.value);break;case"m4":i.uniforms[e].value=(new nr).fromArray(r.value);break;default:i.uniforms[e].value=r.value}}if(void 0!==t.defines&&(i.defines=t.defines),void 0!==t.vertexShader&&(i.vertexShader=t.vertexShader),void 0!==t.fragmentShader&&(i.fragmentShader=t.fragmentShader),void 0!==t.glslVersion&&(i.glslVersion=t.glslVersion),void 0!==t.extensions)for(const e in t.extensions)i.extensions[e]=t.extensions[e];if(void 0!==t.lights&&(i.lights=t.lights),void 0!==t.clipping&&(i.clipping=t.clipping),void 0!==t.size&&(i.size=t.size),void 0!==t.sizeAttenuation&&(i.sizeAttenuation=t.sizeAttenuation),void 0!==t.map&&(i.map=s(t.map)),void 0!==t.matcap&&(i.matcap=s(t.matcap)),void 0!==t.alphaMap&&(i.alphaMap=s(t.alphaMap)),void 0!==t.bumpMap&&(i.bumpMap=s(t.bumpMap)),void 0!==t.bumpScale&&(i.bumpScale=t.bumpScale),void 0!==t.normalMap&&(i.normalMap=s(t.normalMap)),void 0!==t.normalMapType&&(i.normalMapType=t.normalMapType),void 0!==t.normalScale){let e=t.normalScale;!1===Array.isArray(e)&&(e=[e,e]),i.normalScale=(new Zs).fromArray(e)}return void 0!==t.displacementMap&&(i.displacementMap=s(t.displacementMap)),void 0!==t.displacementScale&&(i.displacementScale=t.displacementScale),void 0!==t.displacementBias&&(i.displacementBias=t.displacementBias),void 0!==t.roughnessMap&&(i.roughnessMap=s(t.roughnessMap)),void 0!==t.metalnessMap&&(i.metalnessMap=s(t.metalnessMap)),void 0!==t.emissiveMap&&(i.emissiveMap=s(t.emissiveMap)),void 0!==t.emissiveIntensity&&(i.emissiveIntensity=t.emissiveIntensity),void 0!==t.specularMap&&(i.specularMap=s(t.specularMap)),void 0!==t.specularIntensityMap&&(i.specularIntensityMap=s(t.specularIntensityMap)),void 0!==t.specularColorMap&&(i.specularColorMap=s(t.specularColorMap)),void 0!==t.envMap&&(i.envMap=s(t.envMap)),void 0!==t.envMapRotation&&i.envMapRotation.fromArray(t.envMapRotation),void 0!==t.envMapIntensity&&(i.envMapIntensity=t.envMapIntensity),void 0!==t.reflectivity&&(i.reflectivity=t.reflectivity),void 0!==t.refractionRatio&&(i.refractionRatio=t.refractionRatio),void 0!==t.lightMap&&(i.lightMap=s(t.lightMap)),void 0!==t.lightMapIntensity&&(i.lightMapIntensity=t.lightMapIntensity),void 0!==t.aoMap&&(i.aoMap=s(t.aoMap)),void 0!==t.aoMapIntensity&&(i.aoMapIntensity=t.aoMapIntensity),void 0!==t.gradientMap&&(i.gradientMap=s(t.gradientMap)),void 0!==t.clearcoatMap&&(i.clearcoatMap=s(t.clearcoatMap)),void 0!==t.clearcoatRoughnessMap&&(i.clearcoatRoughnessMap=s(t.clearcoatRoughnessMap)),void 0!==t.clearcoatNormalMap&&(i.clearcoatNormalMap=s(t.clearcoatNormalMap)),void 0!==t.clearcoatNormalScale&&(i.clearcoatNormalScale=(new Zs).fromArray(t.clearcoatNormalScale)),void 0!==t.iridescenceMap&&(i.iridescenceMap=s(t.iridescenceMap)),void 0!==t.iridescenceThicknessMap&&(i.iridescenceThicknessMap=s(t.iridescenceThicknessMap)),void 0!==t.transmissionMap&&(i.transmissionMap=s(t.transmissionMap)),void 0!==t.thicknessMap&&(i.thicknessMap=s(t.thicknessMap)),void 0!==t.anisotropyMap&&(i.anisotropyMap=s(t.anisotropyMap)),void 0!==t.sheenColorMap&&(i.sheenColorMap=s(t.sheenColorMap)),void 0!==t.sheenRoughnessMap&&(i.sheenRoughnessMap=s(t.sheenRoughnessMap)),i}setTextures(t){return this.textures=t,this}createMaterialFromType(t){return Ec.createMaterialFromType(t)}static createMaterialFromType(t){return new{ShadowMaterial:Ml,SpriteMaterial:ho,RawShaderMaterial:Sl,ShaderMaterial:Jn,PointsMaterial:Na,MeshPhysicalMaterial:Al,MeshStandardMaterial:_l,MeshPhongMaterial:Tl,MeshToonMaterial:zl,MeshNormalMaterial:Cl,MeshLambertMaterial:Il,MeshDepthMaterial:Bl,MeshDistanceMaterial:kl,MeshBasicMaterial:en,MeshMatcapMaterial:Rl,LineDashedMaterial:El,LineBasicMaterial:Sa,Material:tn}[t]}}class Pc{static decodeText(t){if(console.warn("THREE.LoaderUtils: decodeText() has been deprecated with r165 and will be removed with r175. Use TextDecoder instead."),"undefined"!=typeof TextDecoder)return(new TextDecoder).decode(t);let e="";for(let s=0,i=t.length;s0){const s=new ec(e);r=new lc(s),r.setCrossOrigin(this.crossOrigin);for(let e=0,s=t.length;e0){i=new lc(this.manager),i.setCrossOrigin(this.crossOrigin);for(let e=0,i=t.length;e{const e=new Ri;e.min.fromArray(t.boxMin),e.max.fromArray(t.boxMax);const s=new Gi;return s.radius=t.sphereRadius,s.center.fromArray(t.sphereCenter),{boxInitialized:t.boxInitialized,box:e,sphereInitialized:t.sphereInitialized,sphere:s}})),n._maxInstanceCount=t.maxInstanceCount,n._maxVertexCount=t.maxVertexCount,n._maxIndexCount=t.maxIndexCount,n._geometryInitialized=t.geometryInitialized,n._geometryCount=t.geometryCount,n._matricesTexture=c(t.matricesTexture.uuid),void 0!==t.colorsTexture&&(n._colorsTexture=c(t.colorsTexture.uuid));break;case"LOD":n=new zo;break;case"Line":n=new ka(h(t.geometry),l(t.material));break;case"LineLoop":n=new Fa(h(t.geometry),l(t.material));break;case"LineSegments":n=new Oa(h(t.geometry),l(t.material));break;case"PointCloud":case"Points":n=new Ua(h(t.geometry),l(t.material));break;case"Sprite":n=new So(l(t.material));break;case"Group":n=new Ha;break;case"Bone":n=new Lo;break;default:n=new Rr}if(n.uuid=t.uuid,void 0!==t.name&&(n.name=t.name),void 0!==t.matrix?(n.matrix.fromArray(t.matrix),void 0!==t.matrixAutoUpdate&&(n.matrixAutoUpdate=t.matrixAutoUpdate),n.matrixAutoUpdate&&n.matrix.decompose(n.position,n.quaternion,n.scale)):(void 0!==t.position&&n.position.fromArray(t.position),void 0!==t.rotation&&n.rotation.fromArray(t.rotation),void 0!==t.quaternion&&n.quaternion.fromArray(t.quaternion),void 0!==t.scale&&n.scale.fromArray(t.scale)),void 0!==t.up&&n.up.fromArray(t.up),void 0!==t.castShadow&&(n.castShadow=t.castShadow),void 0!==t.receiveShadow&&(n.receiveShadow=t.receiveShadow),t.shadow&&(void 0!==t.shadow.intensity&&(n.shadow.intensity=t.shadow.intensity),void 0!==t.shadow.bias&&(n.shadow.bias=t.shadow.bias),void 0!==t.shadow.normalBias&&(n.shadow.normalBias=t.shadow.normalBias),void 0!==t.shadow.radius&&(n.shadow.radius=t.shadow.radius),void 0!==t.shadow.mapSize&&n.shadow.mapSize.fromArray(t.shadow.mapSize),void 0!==t.shadow.camera&&(n.shadow.camera=this.parseObject(t.shadow.camera))),void 0!==t.visible&&(n.visible=t.visible),void 0!==t.frustumCulled&&(n.frustumCulled=t.frustumCulled),void 0!==t.renderOrder&&(n.renderOrder=t.renderOrder),void 0!==t.userData&&(n.userData=t.userData),void 0!==t.layers&&(n.layers.mask=t.layers),void 0!==t.children){const o=t.children;for(let t=0;t{e&&e(s),r.manager.itemEnd(t)})).catch((t=>{i&&i(t)})):(setTimeout((function(){e&&e(n),r.manager.itemEnd(t)}),0),n);const o={};o.credentials="anonymous"===this.crossOrigin?"same-origin":"include",o.headers=this.requestHeader;const a=fetch(t,o).then((function(t){return t.blob()})).then((function(t){return createImageBitmap(t,Object.assign(r.options,{colorSpaceConversion:"none"}))})).then((function(s){return tc.add(t,s),e&&e(s),r.manager.itemEnd(t),s})).catch((function(e){i&&i(e),tc.remove(t),r.manager.itemError(t),r.manager.itemEnd(t)}));tc.add(t,a),r.manager.itemStart(t)}}let Uc;class Dc{static getContext(){return void 0===Uc&&(Uc=new(window.AudioContext||window.webkitAudioContext)),Uc}static setContext(t){Uc=t}}class Hc extends ic{constructor(t){super(t)}load(t,e,s,i){const r=this,n=new oc(this.manager);function o(e){i?i(e):console.error(e),r.manager.itemError(t)}n.setResponseType("arraybuffer"),n.setPath(this.path),n.setRequestHeader(this.requestHeader),n.setWithCredentials(this.withCredentials),n.load(t,(function(t){try{const s=t.slice(0);Dc.getContext().decodeAudioData(s,(function(t){e(t)})).catch(o)}catch(t){o(t)}}),s,i)}}const qc=new nr,Jc=new nr,Xc=new nr;class Yc{constructor(){this.type="StereoCamera",this.aspect=1,this.eyeSep=.064,this.cameraL=new $n,this.cameraL.layers.enable(1),this.cameraL.matrixAutoUpdate=!1,this.cameraR=new $n,this.cameraR.layers.enable(2),this.cameraR.matrixAutoUpdate=!1,this._cache={focus:null,fov:null,aspect:null,near:null,far:null,zoom:null,eyeSep:null}}update(t){const e=this._cache;if(e.focus!==t.focus||e.fov!==t.fov||e.aspect!==t.aspect*this.aspect||e.near!==t.near||e.far!==t.far||e.zoom!==t.zoom||e.eyeSep!==this.eyeSep){e.focus=t.focus,e.fov=t.fov,e.aspect=t.aspect*this.aspect,e.near=t.near,e.far=t.far,e.zoom=t.zoom,e.eyeSep=this.eyeSep,Xc.copy(t.projectionMatrix);const s=e.eyeSep/2,i=s*e.near/e.focus,r=e.near*Math.tan(Ws*e.fov*.5)/e.zoom;let n,o;Jc.elements[12]=-s,qc.elements[12]=s,n=-r*e.aspect+i,o=r*e.aspect+i,Xc.elements[0]=2*e.near/(o-n),Xc.elements[8]=(o+n)/(o-n),this.cameraL.projectionMatrix.copy(Xc),n=-r*e.aspect-i,o=r*e.aspect-i,Xc.elements[0]=2*e.near/(o-n),Xc.elements[8]=(o+n)/(o-n),this.cameraR.projectionMatrix.copy(Xc)}this.cameraL.matrixWorld.copy(t.matrixWorld).multiply(Jc),this.cameraR.matrixWorld.copy(t.matrixWorld).multiply(qc)}}class Zc extends $n{constructor(t=[]){super(),this.isArrayCamera=!0,this.cameras=t}}class Gc{constructor(t=!0){this.autoStart=t,this.startTime=0,this.oldTime=0,this.elapsedTime=0,this.running=!1}start(){this.startTime=$c(),this.oldTime=this.startTime,this.elapsedTime=0,this.running=!0}stop(){this.getElapsedTime(),this.running=!1,this.autoStart=!1}getElapsedTime(){return this.getDelta(),this.elapsedTime}getDelta(){let t=0;if(this.autoStart&&!this.running)return this.start(),0;if(this.running){const e=$c();t=(e-this.oldTime)/1e3,this.oldTime=e,this.elapsedTime+=t}return t}}function $c(){return performance.now()}const Qc=new Ii,Kc=new Ci,tu=new Ii,eu=new Ii;class su extends Rr{constructor(){super(),this.type="AudioListener",this.context=Dc.getContext(),this.gain=this.context.createGain(),this.gain.connect(this.context.destination),this.filter=null,this.timeDelta=0,this._clock=new Gc}getInput(){return this.gain}removeFilter(){return null!==this.filter&&(this.gain.disconnect(this.filter),this.filter.disconnect(this.context.destination),this.gain.connect(this.context.destination),this.filter=null),this}getFilter(){return this.filter}setFilter(t){return null!==this.filter?(this.gain.disconnect(this.filter),this.filter.disconnect(this.context.destination)):this.gain.disconnect(this.context.destination),this.filter=t,this.gain.connect(this.filter),this.filter.connect(this.context.destination),this}getMasterVolume(){return this.gain.gain.value}setMasterVolume(t){return this.gain.gain.setTargetAtTime(t,this.context.currentTime,.01),this}updateMatrixWorld(t){super.updateMatrixWorld(t);const e=this.context.listener,s=this.up;if(this.timeDelta=this._clock.getDelta(),this.matrixWorld.decompose(Qc,Kc,tu),eu.set(0,0,-1).applyQuaternion(Kc),e.positionX){const t=this.context.currentTime+this.timeDelta;e.positionX.linearRampToValueAtTime(Qc.x,t),e.positionY.linearRampToValueAtTime(Qc.y,t),e.positionZ.linearRampToValueAtTime(Qc.z,t),e.forwardX.linearRampToValueAtTime(eu.x,t),e.forwardY.linearRampToValueAtTime(eu.y,t),e.forwardZ.linearRampToValueAtTime(eu.z,t),e.upX.linearRampToValueAtTime(s.x,t),e.upY.linearRampToValueAtTime(s.y,t),e.upZ.linearRampToValueAtTime(s.z,t)}else e.setPosition(Qc.x,Qc.y,Qc.z),e.setOrientation(eu.x,eu.y,eu.z,s.x,s.y,s.z)}}class iu extends Rr{constructor(t){super(),this.type="Audio",this.listener=t,this.context=t.context,this.gain=this.context.createGain(),this.gain.connect(t.getInput()),this.autoplay=!1,this.buffer=null,this.detune=0,this.loop=!1,this.loopStart=0,this.loopEnd=0,this.offset=0,this.duration=void 0,this.playbackRate=1,this.isPlaying=!1,this.hasPlaybackControl=!0,this.source=null,this.sourceType="empty",this._startedAt=0,this._progress=0,this._connected=!1,this.filters=[]}getOutput(){return this.gain}setNodeSource(t){return this.hasPlaybackControl=!1,this.sourceType="audioNode",this.source=t,this.connect(),this}setMediaElementSource(t){return this.hasPlaybackControl=!1,this.sourceType="mediaNode",this.source=this.context.createMediaElementSource(t),this.connect(),this}setMediaStreamSource(t){return this.hasPlaybackControl=!1,this.sourceType="mediaStreamNode",this.source=this.context.createMediaStreamSource(t),this.connect(),this}setBuffer(t){return this.buffer=t,this.sourceType="buffer",this.autoplay&&this.play(),this}play(t=0){if(!0===this.isPlaying)return void console.warn("THREE.Audio: Audio is already playing.");if(!1===this.hasPlaybackControl)return void console.warn("THREE.Audio: this Audio has no playback control.");this._startedAt=this.context.currentTime+t;const e=this.context.createBufferSource();return e.buffer=this.buffer,e.loop=this.loop,e.loopStart=this.loopStart,e.loopEnd=this.loopEnd,e.onended=this.onEnded.bind(this),e.start(this._startedAt,this._progress+this.offset,this.duration),this.isPlaying=!0,this.source=e,this.setDetune(this.detune),this.setPlaybackRate(this.playbackRate),this.connect()}pause(){if(!1!==this.hasPlaybackControl)return!0===this.isPlaying&&(this._progress+=Math.max(this.context.currentTime-this._startedAt,0)*this.playbackRate,!0===this.loop&&(this._progress=this._progress%(this.duration||this.buffer.duration)),this.source.stop(),this.source.onended=null,this.isPlaying=!1),this;console.warn("THREE.Audio: this Audio has no playback control.")}stop(t=0){if(!1!==this.hasPlaybackControl)return this._progress=0,null!==this.source&&(this.source.stop(this.context.currentTime+t),this.source.onended=null),this.isPlaying=!1,this;console.warn("THREE.Audio: this Audio has no playback control.")}connect(){if(this.filters.length>0){this.source.connect(this.filters[0]);for(let t=1,e=this.filters.length;t0){this.source.disconnect(this.filters[0]);for(let t=1,e=this.filters.length;t0&&this._mixBufferRegionAdditive(s,i,this._addIndex*e,1,e);for(let t=e,r=e+e;t!==r;++t)if(s[t]!==s[t+e]){o.setValue(s,i);break}}saveOriginalState(){const t=this.binding,e=this.buffer,s=this.valueSize,i=s*this._origIndex;t.getValue(e,i);for(let t=s,r=i;t!==r;++t)e[t]=e[i+t%s];this._setIdentity(),this.cumulativeWeight=0,this.cumulativeWeightAdditive=0}restoreOriginalState(){const t=3*this.valueSize;this.binding.setValue(this.buffer,t)}_setAdditiveIdentityNumeric(){const t=this._addIndex*this.valueSize,e=t+this.valueSize;for(let s=t;s=.5)for(let i=0;i!==r;++i)t[e+i]=t[s+i]}_slerp(t,e,s,i){Ci.slerpFlat(t,e,t,e,t,s,i)}_slerpAdditive(t,e,s,i,r){const n=this._workIndex*r;Ci.multiplyQuaternionsFlat(t,n,t,e,t,s),Ci.slerpFlat(t,e,t,e,t,n,i)}_lerp(t,e,s,i,r){const n=1-i;for(let o=0;o!==r;++o){const r=e+o;t[r]=t[r]*n+t[s+o]*i}}_lerpAdditive(t,e,s,i,r){for(let n=0;n!==r;++n){const r=e+n;t[r]=t[r]+t[s+n]*i}}}const uu="\\[\\]\\.:\\/",du=new RegExp("["+uu+"]","g"),pu="[^"+uu+"]",mu="[^"+uu.replace("\\.","")+"]",yu=new RegExp("^"+/((?:WC+[\/:])*)/.source.replace("WC",pu)+/(WCOD+)?/.source.replace("WCOD",mu)+/(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC",pu)+/\.(WC+)(?:\[(.+)\])?/.source.replace("WC",pu)+"$"),fu=["material","materials","bones","map"];class gu{constructor(t,e,s){this.path=e,this.parsedPath=s||gu.parseTrackName(e),this.node=gu.findNode(t,this.parsedPath.nodeName),this.rootNode=t,this.getValue=this._getValue_unbound,this.setValue=this._setValue_unbound}static create(t,e,s){return t&&t.isAnimationObjectGroup?new gu.Composite(t,e,s):new gu(t,e,s)}static sanitizeNodeName(t){return t.replace(/\s/g,"_").replace(du,"")}static parseTrackName(t){const e=yu.exec(t);if(null===e)throw new Error("PropertyBinding: Cannot parse trackName: "+t);const s={nodeName:e[2],objectName:e[3],objectIndex:e[4],propertyName:e[5],propertyIndex:e[6]},i=s.nodeName&&s.nodeName.lastIndexOf(".");if(void 0!==i&&-1!==i){const t=s.nodeName.substring(i+1);-1!==fu.indexOf(t)&&(s.nodeName=s.nodeName.substring(0,i),s.objectName=t)}if(null===s.propertyName||0===s.propertyName.length)throw new Error("PropertyBinding: can not parse propertyName from trackName: "+t);return s}static findNode(t,e){if(void 0===e||""===e||"."===e||-1===e||e===t.name||e===t.uuid)return t;if(t.skeleton){const s=t.skeleton.getBoneByName(e);if(void 0!==s)return s}if(t.children){const s=function(t){for(let i=0;i=r){const n=r++,l=t[n];e[l.uuid]=h,t[h]=l,e[a]=n,t[n]=o;for(let t=0,e=i;t!==e;++t){const e=s[t],i=e[n],r=e[h];e[h]=i,e[n]=r}}}this.nCachedObjects_=r}uncache(){const t=this._objects,e=this._indicesByUUID,s=this._bindings,i=s.length;let r=this.nCachedObjects_,n=t.length;for(let o=0,a=arguments.length;o!==a;++o){const a=arguments[o].uuid,h=e[a];if(void 0!==h)if(delete e[a],h0&&(e[o.uuid]=h),t[h]=o,t.pop();for(let t=0,e=i;t!==e;++t){const e=s[t];e[h]=e[r],e.pop()}}}this.nCachedObjects_=r}subscribe_(t,e){const s=this._bindingsIndicesByPath;let i=s[t];const r=this._bindings;if(void 0!==i)return r[i];const n=this._paths,o=this._parsedPaths,a=this._objects,h=a.length,l=this.nCachedObjects_,c=new Array(h);i=r.length,s[t]=i,n.push(t),o.push(e),r.push(c);for(let s=l,i=a.length;s!==i;++s){const i=a[s];c[s]=new gu(i,t,e)}return c}unsubscribe_(t){const e=this._bindingsIndicesByPath,s=e[t];if(void 0!==s){const i=this._paths,r=this._parsedPaths,n=this._bindings,o=n.length-1,a=n[o];e[t[o]]=s,n[s]=a,n.pop(),r[s]=r[o],r.pop(),i[s]=i[o],i.pop()}}}class bu{constructor(t,e,s=null,i=e.blendMode){this._mixer=t,this._clip=e,this._localRoot=s,this.blendMode=i;const r=e.tracks,n=r.length,o=new Array(n),a={endingStart:Oe,endingEnd:Oe};for(let t=0;t!==n;++t){const e=r[t].createInterpolant(null);o[t]=e,e.settings=a}this._interpolantSettings=a,this._interpolants=o,this._propertyBindings=new Array(n),this._cacheIndex=null,this._byClipCacheIndex=null,this._timeScaleInterpolant=null,this._weightInterpolant=null,this.loop=2201,this._loopCount=-1,this._startTime=null,this.time=0,this.timeScale=1,this._effectiveTimeScale=1,this.weight=1,this._effectiveWeight=1,this.repetitions=1/0,this.paused=!1,this.enabled=!0,this.clampWhenFinished=!1,this.zeroSlopeAtStart=!0,this.zeroSlopeAtEnd=!0}play(){return this._mixer._activateAction(this),this}stop(){return this._mixer._deactivateAction(this),this.reset()}reset(){return this.paused=!1,this.enabled=!0,this.time=0,this._loopCount=-1,this._startTime=null,this.stopFading().stopWarping()}isRunning(){return this.enabled&&!this.paused&&0!==this.timeScale&&null===this._startTime&&this._mixer._isActiveAction(this)}isScheduled(){return this._mixer._isActiveAction(this)}startAt(t){return this._startTime=t,this}setLoop(t,e){return this.loop=t,this.repetitions=e,this}setEffectiveWeight(t){return this.weight=t,this._effectiveWeight=this.enabled?t:0,this.stopFading()}getEffectiveWeight(){return this._effectiveWeight}fadeIn(t){return this._scheduleFading(t,0,1)}fadeOut(t){return this._scheduleFading(t,1,0)}crossFadeFrom(t,e,s){if(t.fadeOut(e),this.fadeIn(e),s){const s=this._clip.duration,i=t._clip.duration,r=i/s,n=s/i;t.warp(1,r,e),this.warp(n,1,e)}return this}crossFadeTo(t,e,s){return t.crossFadeFrom(this,e,s)}stopFading(){const t=this._weightInterpolant;return null!==t&&(this._weightInterpolant=null,this._mixer._takeBackControlInterpolant(t)),this}setEffectiveTimeScale(t){return this.timeScale=t,this._effectiveTimeScale=this.paused?0:t,this.stopWarping()}getEffectiveTimeScale(){return this._effectiveTimeScale}setDuration(t){return this.timeScale=this._clip.duration/t,this.stopWarping()}syncWith(t){return this.time=t.time,this.timeScale=t.timeScale,this.stopWarping()}halt(t){return this.warp(this._effectiveTimeScale,0,t)}warp(t,e,s){const i=this._mixer,r=i.time,n=this.timeScale;let o=this._timeScaleInterpolant;null===o&&(o=i._lendControlInterpolant(),this._timeScaleInterpolant=o);const a=o.parameterPositions,h=o.sampleValues;return a[0]=r,a[1]=r+s,h[0]=t/n,h[1]=e/n,this}stopWarping(){const t=this._timeScaleInterpolant;return null!==t&&(this._timeScaleInterpolant=null,this._mixer._takeBackControlInterpolant(t)),this}getMixer(){return this._mixer}getClip(){return this._clip}getRoot(){return this._localRoot||this._mixer._root}_update(t,e,s,i){if(!this.enabled)return void this._updateWeight(t);const r=this._startTime;if(null!==r){const i=(t-r)*s;i<0||0===s?e=0:(this._startTime=null,e=s*i)}e*=this._updateTimeScale(t);const n=this._updateTime(e),o=this._updateWeight(t);if(o>0){const t=this._interpolants,e=this._propertyBindings;if(this.blendMode===Ve)for(let s=0,i=t.length;s!==i;++s)t[s].evaluate(n),e[s].accumulateAdditive(o);else for(let s=0,r=t.length;s!==r;++s)t[s].evaluate(n),e[s].accumulate(i,o)}}_updateWeight(t){let e=0;if(this.enabled){e=this.weight;const s=this._weightInterpolant;if(null!==s){const i=s.evaluate(t)[0];e*=i,t>s.parameterPositions[1]&&(this.stopFading(),0===i&&(this.enabled=!1))}}return this._effectiveWeight=e,e}_updateTimeScale(t){let e=0;if(!this.paused){e=this.timeScale;const s=this._timeScaleInterpolant;if(null!==s){e*=s.evaluate(t)[0],t>s.parameterPositions[1]&&(this.stopWarping(),0===e?this.paused=!0:this.timeScale=e)}}return this._effectiveTimeScale=e,e}_updateTime(t){const e=this._clip.duration,s=this.loop;let i=this.time+t,r=this._loopCount;const n=2202===s;if(0===t)return-1===r||!n||1&~r?i:e-i;if(2200===s){-1===r&&(this._loopCount=0,this._setEndings(!0,!0,!1));t:{if(i>=e)i=e;else{if(!(i<0)){this.time=i;break t}i=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this.time=i,this._mixer.dispatchEvent({type:"finished",action:this,direction:t<0?-1:1})}}else{if(-1===r&&(t>=0?(r=0,this._setEndings(!0,0===this.repetitions,n)):this._setEndings(0===this.repetitions,!0,n)),i>=e||i<0){const s=Math.floor(i/e);i-=e*s,r+=Math.abs(s);const o=this.repetitions-r;if(o<=0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,i=t>0?e:0,this.time=i,this._mixer.dispatchEvent({type:"finished",action:this,direction:t>0?1:-1});else{if(1===o){const e=t<0;this._setEndings(e,!e,n)}else this._setEndings(!1,!1,n);this._loopCount=r,this.time=i,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:s})}}else this.time=i;if(n&&!(1&~r))return e-i}return i}_setEndings(t,e,s){const i=this._interpolantSettings;s?(i.endingStart=Fe,i.endingEnd=Fe):(i.endingStart=t?this.zeroSlopeAtStart?Fe:Oe:Ne,i.endingEnd=e?this.zeroSlopeAtEnd?Fe:Oe:Ne)}_scheduleFading(t,e,s){const i=this._mixer,r=i.time;let n=this._weightInterpolant;null===n&&(n=i._lendControlInterpolant(),this._weightInterpolant=n);const o=n.parameterPositions,a=n.sampleValues;return o[0]=r,a[0]=e,o[1]=r+t,a[1]=s,this}}const vu=new Float32Array(1);class wu extends Ns{constructor(t){super(),this._root=t,this._initMemoryManager(),this._accuIndex=0,this.time=0,this.timeScale=1}_bindAction(t,e){const s=t._localRoot||this._root,i=t._clip.tracks,r=i.length,n=t._propertyBindings,o=t._interpolants,a=s.uuid,h=this._bindingsByRootAndName;let l=h[a];void 0===l&&(l={},h[a]=l);for(let t=0;t!==r;++t){const r=i[t],h=r.name;let c=l[h];if(void 0!==c)++c.referenceCount,n[t]=c;else{if(c=n[t],void 0!==c){null===c._cacheIndex&&(++c.referenceCount,this._addInactiveBinding(c,a,h));continue}const i=e&&e._propertyBindings[t].binding.parsedPath;c=new cu(gu.create(s,h,i),r.ValueTypeName,r.getValueSize()),++c.referenceCount,this._addInactiveBinding(c,a,h),n[t]=c}o[t].resultBuffer=c.buffer}}_activateAction(t){if(!this._isActiveAction(t)){if(null===t._cacheIndex){const e=(t._localRoot||this._root).uuid,s=t._clip.uuid,i=this._actionsByClip[s];this._bindAction(t,i&&i.knownActions[0]),this._addInactiveAction(t,s,e)}const e=t._propertyBindings;for(let t=0,s=e.length;t!==s;++t){const s=e[t];0==s.useCount++&&(this._lendBinding(s),s.saveOriginalState())}this._lendAction(t)}}_deactivateAction(t){if(this._isActiveAction(t)){const e=t._propertyBindings;for(let t=0,s=e.length;t!==s;++t){const s=e[t];0==--s.useCount&&(s.restoreOriginalState(),this._takeBackBinding(s))}this._takeBackAction(t)}}_initMemoryManager(){this._actions=[],this._nActiveActions=0,this._actionsByClip={},this._bindings=[],this._nActiveBindings=0,this._bindingsByRootAndName={},this._controlInterpolants=[],this._nActiveControlInterpolants=0;const t=this;this.stats={actions:{get total(){return t._actions.length},get inUse(){return t._nActiveActions}},bindings:{get total(){return t._bindings.length},get inUse(){return t._nActiveBindings}},controlInterpolants:{get total(){return t._controlInterpolants.length},get inUse(){return t._nActiveControlInterpolants}}}}_isActiveAction(t){const e=t._cacheIndex;return null!==e&&e=0;--e)t[e].stop();return this}update(t){t*=this.timeScale;const e=this._actions,s=this._nActiveActions,i=this.time+=t,r=Math.sign(t),n=this._accuIndex^=1;for(let o=0;o!==s;++o){e[o]._update(i,t,r,n)}const o=this._bindings,a=this._nActiveBindings;for(let t=0;t!==a;++t)o[t].apply(n);return this}setTime(t){this.time=0;for(let t=0;t=this.min.x&&t.x<=this.max.x&&t.y>=this.min.y&&t.y<=this.max.y}containsBox(t){return this.min.x<=t.min.x&&t.max.x<=this.max.x&&this.min.y<=t.min.y&&t.max.y<=this.max.y}getParameter(t,e){return e.set((t.x-this.min.x)/(this.max.x-this.min.x),(t.y-this.min.y)/(this.max.y-this.min.y))}intersectsBox(t){return t.max.x>=this.min.x&&t.min.x<=this.max.x&&t.max.y>=this.min.y&&t.min.y<=this.max.y}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return this.clampPoint(t,Fu).distanceTo(t)}intersect(t){return this.min.max(t.min),this.max.min(t.max),this.isEmpty()&&this.makeEmpty(),this}union(t){return this.min.min(t.min),this.max.max(t.max),this}translate(t){return this.min.add(t),this.max.add(t),this}equals(t){return t.min.equals(this.min)&&t.max.equals(this.max)}}const Lu=new Ii,Vu=new Ii;class Wu{constructor(t=new Ii,e=new Ii){this.start=t,this.end=e}set(t,e){return this.start.copy(t),this.end.copy(e),this}copy(t){return this.start.copy(t.start),this.end.copy(t.end),this}getCenter(t){return t.addVectors(this.start,this.end).multiplyScalar(.5)}delta(t){return t.subVectors(this.end,this.start)}distanceSq(){return this.start.distanceToSquared(this.end)}distance(){return this.start.distanceTo(this.end)}at(t,e){return this.delta(e).multiplyScalar(t).add(this.start)}closestPointToPointParameter(t,e){Lu.subVectors(t,this.start),Vu.subVectors(this.end,this.start);const s=Vu.dot(Vu);let i=Vu.dot(Lu)/s;return e&&(i=Ds(i,0,1)),i}closestPointToPoint(t,e,s){const i=this.closestPointToPointParameter(t,e);return this.delta(s).multiplyScalar(i).add(this.start)}applyMatrix4(t){return this.start.applyMatrix4(t),this.end.applyMatrix4(t),this}equals(t){return t.start.equals(this.start)&&t.end.equals(this.end)}clone(){return(new this.constructor).copy(this)}}const ju=new Ii;class Uu extends Rr{constructor(t,e){super(),this.light=t,this.matrixAutoUpdate=!1,this.color=e,this.type="SpotLightHelper";const s=new zn,i=[0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,-1,0,1,0,0,0,0,1,1,0,0,0,0,-1,1];for(let t=0,e=1,s=32;t1)for(let s=0;s.99999)this.quaternion.set(0,0,0,1);else if(t.y<-.99999)this.quaternion.set(1,0,0,0);else{pd.set(t.z,0,-t.x).normalize();const e=Math.acos(t.y);this.quaternion.setFromAxisAngle(pd,e)}}setLength(t,e=.2*t,s=.2*e){this.line.scale.set(1,Math.max(1e-4,t-e),1),this.line.updateMatrix(),this.cone.scale.set(s,e,s),this.cone.position.y=t,this.cone.updateMatrix()}setColor(t){this.line.material.color.set(t),this.cone.material.color.set(t)}copy(t){return super.copy(t,!1),this.line.copy(t.line),this.cone.copy(t.cone),this}dispose(){this.line.geometry.dispose(),this.line.material.dispose(),this.cone.geometry.dispose(),this.cone.material.dispose()}}class gd extends Oa{constructor(t=1){const e=[0,0,0,t,0,0,0,0,0,0,t,0,0,0,0,0,0,t],s=new zn;s.setAttribute("position",new bn(e,3)),s.setAttribute("color",new bn([1,0,0,1,.6,0,0,1,0,.6,1,0,0,0,1,0,.6,1],3));super(s,new Sa({vertexColors:!0,toneMapped:!1})),this.type="AxesHelper"}setColors(t,e,s){const i=new $r,r=this.geometry.attributes.color.array;return i.set(t),i.toArray(r,0),i.toArray(r,3),i.set(e),i.toArray(r,6),i.toArray(r,9),i.set(s),i.toArray(r,12),i.toArray(r,15),this.geometry.attributes.color.needsUpdate=!0,this}dispose(){this.geometry.dispose(),this.material.dispose()}}class xd{constructor(){this.type="ShapePath",this.color=new $r,this.subPaths=[],this.currentPath=null}moveTo(t,e){return this.currentPath=new bh,this.subPaths.push(this.currentPath),this.currentPath.moveTo(t,e),this}lineTo(t,e){return this.currentPath.lineTo(t,e),this}quadraticCurveTo(t,e,s,i){return this.currentPath.quadraticCurveTo(t,e,s,i),this}bezierCurveTo(t,e,s,i,r,n){return this.currentPath.bezierCurveTo(t,e,s,i,r,n),this}splineThru(t){return this.currentPath.splineThru(t),this}toShapes(t){function e(t,e){const s=e.length;let i=!1;for(let r=s-1,n=0;nNumber.EPSILON){if(h<0&&(s=e[n],a=-a,o=e[r],h=-h),t.yo.y)continue;if(t.y===s.y){if(t.x===s.x)return!0}else{const e=h*(t.x-s.x)-a*(t.y-s.y);if(0===e)return!0;if(e<0)continue;i=!i}}else{if(t.y!==s.y)continue;if(o.x<=t.x&&t.x<=s.x||s.x<=t.x&&t.x<=o.x)return!0}}return i}const s=rl.isClockWise,i=this.subPaths;if(0===i.length)return[];let r,n,o;const a=[];if(1===i.length)return n=i[0],o=new Rh,o.curves=n.curves,a.push(o),a;let h=!s(i[0].getPoints());h=t?!h:h;const l=[],c=[];let u,d,p=[],m=0;c[m]=void 0,p[m]=[];for(let e=0,o=i.length;e1){let t=!1,s=0;for(let t=0,e=c.length;t0&&!1===t&&(p=l)}for(let t=0,e=c.length;te?(t.repeat.x=1,t.repeat.y=s/e,t.offset.x=0,t.offset.y=(1-t.repeat.y)/2):(t.repeat.x=e/s,t.repeat.y=1,t.offset.x=(1-t.repeat.x)/2,t.offset.y=0),t},cover:function(t,e){const s=t.image&&t.image.width?t.image.width/t.image.height:1;return s>e?(t.repeat.x=e/s,t.repeat.y=1,t.offset.x=(1-t.repeat.x)/2,t.offset.y=0):(t.repeat.x=1,t.repeat.y=s/e,t.offset.x=0,t.offset.y=(1-t.repeat.y)/2),t},fill:function(t){return t.repeat.x=1,t.repeat.y=1,t.offset.x=0,t.offset.y=0,t},getByteLength:vd};"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("register",{detail:{revision:t}})),"undefined"!=typeof window&&(window.__THREE__?console.warn("WARNING: Multiple instances of Three.js being imported."):window.__THREE__=t);export{et as ACESFilmicToneMapping,v as AddEquation,G as AddOperation,Ve as AdditiveAnimationBlendMode,f as AdditiveBlending,it as AgXToneMapping,Lt as AlphaFormat,Ss as AlwaysCompare,j as AlwaysDepth,ys as AlwaysStencilFunc,Ic as AmbientLight,bu as AnimationAction,Ql as AnimationClip,ac as AnimationLoader,wu as AnimationMixer,xu as AnimationObjectGroup,Vl as AnimationUtils,th as ArcCurve,Zc as ArrayCamera,fd as ArrowHelper,nt as AttachedBindMode,iu as Audio,lu as AudioAnalyser,Dc as AudioContext,su as AudioListener,Hc as AudioLoader,gd as AxesHelper,d as BackSide,De as BasicDepthPacking,a as BasicShadowMap,Ma as BatchedMesh,Lo as Bone,ql as BooleanKeyframeTrack,Nu as Box2,Ri as Box3,ud as Box3Helper,jn as BoxGeometry,cd as BoxHelper,cn as BufferAttribute,zn as BufferGeometry,Fc as BufferGeometryLoader,zt as ByteType,tc as Cache,Xn as Camera,ad as CameraHelper,Ga as CanvasTexture,wh as CapsuleGeometry,oh as CatmullRomCurve3,tt as CineonToneMapping,Mh as CircleGeometry,mt as ClampToEdgeWrapping,Gc as Clock,$r as Color,Jl as ColorKeyframeTrack,ui as ColorManagement,Ya as CompressedArrayTexture,Za as CompressedCubeTexture,Xa as CompressedTexture,hc as CompressedTextureLoader,_h as ConeGeometry,L as ConstantAlphaFactor,F as ConstantColorFactor,bd as Controls,Kn as CubeCamera,ht as CubeReflectionMapping,lt as CubeRefractionMapping,to as CubeTexture,cc as CubeTextureLoader,dt as CubeUVReflectionMapping,ch as CubicBezierCurve,uh as CubicBezierCurve3,jl as CubicInterpolant,r as CullFaceBack,n as CullFaceFront,o as CullFaceFrontBack,i as CullFaceNone,Qa as Curve,xh as CurvePath,b as CustomBlending,st as CustomToneMapping,Sh as CylinderGeometry,Pu as Cylindrical,Ti as Data3DTexture,_i as DataArrayTexture,Vo as DataTexture,uc as DataTextureLoader,an as DataUtils,rs as DecrementStencilOp,os as DecrementWrapStencilOp,sc as DefaultLoadingManager,Dt as DepthFormat,Ht as DepthStencilFormat,$a as DepthTexture,ot as DetachedBindMode,Cc as DirectionalLight,rd as DirectionalLightHelper,Dl as DiscreteInterpolant,Th as DodecahedronGeometry,p as DoubleSide,k as DstAlphaFactor,E as DstColorFactor,ks as DynamicCopyUsage,As as DynamicDrawUsage,Cs as DynamicReadUsage,kh as EdgesGeometry,Ka as EllipseCurve,xs as EqualCompare,H as EqualDepth,cs as EqualStencilFunc,ct as EquirectangularReflectionMapping,ut as EquirectangularRefractionMapping,yr as Euler,Ns as EventDispatcher,al as ExtrudeGeometry,oc as FileLoader,xn as Float16BufferAttribute,bn as Float32BufferAttribute,Rt as FloatType,io as Fog,so as FogExp2,Ja as FramebufferTexture,u as FrontSide,ra as Frustum,Cu as GLBufferAttribute,Es as GLSL1,Ps as GLSL3,vs as GreaterCompare,J as GreaterDepth,Ms as GreaterEqualCompare,q as GreaterEqualDepth,ms as GreaterEqualStencilFunc,ds as GreaterStencilFunc,Ku as GridHelper,Ha as Group,Et as HalfFloatType,mc as HemisphereLight,Qu as HemisphereLightHelper,ll as IcosahedronGeometry,jc as ImageBitmapLoader,lc as ImageLoader,yi as ImageUtils,is as IncrementStencilOp,ns as IncrementWrapStencilOp,Do as InstancedBufferAttribute,Oc as InstancedBufferGeometry,zu as InstancedInterleavedBuffer,$o as InstancedMesh,mn as Int16BufferAttribute,fn as Int32BufferAttribute,un as Int8BufferAttribute,Bt as IntType,no as InterleavedBuffer,ao as InterleavedBufferAttribute,Wl as Interpolant,Re as InterpolateDiscrete,Ee as InterpolateLinear,Pe as InterpolateSmooth,as as InvertStencilOp,es as KeepStencilOp,Hl as KeyframeTrack,zo as LOD,vh as LatheGeometry,fr as Layers,gs as LessCompare,U as LessDepth,bs as LessEqualCompare,D as LessEqualDepth,us as LessEqualStencilFunc,ls as LessStencilFunc,pc as Light,Rc as LightProbe,ka as Line,Wu as Line3,Sa as LineBasicMaterial,dh as LineCurve,ph as LineCurve3,El as LineDashedMaterial,Fa as LineLoop,Oa as LineSegments,wt as LinearFilter,Ul as LinearInterpolant,At as LinearMipMapLinearFilter,St as LinearMipMapNearestFilter,_t as LinearMipmapLinearFilter,Mt as LinearMipmapNearestFilter,$e as LinearSRGBColorSpace,Q as LinearToneMapping,Qe as LinearTransfer,ic as Loader,Pc as LoaderUtils,ec as LoadingManager,Ie as LoopOnce,ke as LoopPingPong,Be as LoopRepeat,Ut as LuminanceAlphaFormat,jt as LuminanceFormat,e as MOUSE,tn as Material,Ec as MaterialLoader,Ys as MathUtils,Ou as Matrix2,Gs as Matrix3,nr as Matrix4,_ as MaxEquation,Vn as Mesh,en as MeshBasicMaterial,Bl as MeshDepthMaterial,kl as MeshDistanceMaterial,Il as MeshLambertMaterial,Rl as MeshMatcapMaterial,Cl as MeshNormalMaterial,Tl as MeshPhongMaterial,Al as MeshPhysicalMaterial,_l as MeshStandardMaterial,zl as MeshToonMaterial,S as MinEquation,yt as MirroredRepeatWrapping,Z as MixOperation,x as MultiplyBlending,Y as MultiplyOperation,ft as NearestFilter,vt as NearestMipMapLinearFilter,xt as NearestMipMapNearestFilter,bt as NearestMipmapLinearFilter,gt as NearestMipmapNearestFilter,rt as NeutralToneMapping,fs as NeverCompare,W as NeverDepth,hs as NeverStencilFunc,m as NoBlending,Ze as NoColorSpace,$ as NoToneMapping,Le as NormalAnimationBlendMode,y as NormalBlending,ws as NotEqualCompare,X as NotEqualDepth,ps as NotEqualStencilFunc,Xl as NumberKeyframeTrack,Rr as Object3D,Nc as ObjectLoader,Ye as ObjectSpaceNormalMap,cl as OctahedronGeometry,T as OneFactor,V as OneMinusConstantAlphaFactor,N as OneMinusConstantColorFactor,R as OneMinusDstAlphaFactor,P as OneMinusDstColorFactor,B as OneMinusSrcAlphaFactor,C as OneMinusSrcColorFactor,Tc as OrthographicCamera,h as PCFShadowMap,l as PCFSoftShadowMap,bh as Path,$n as PerspectiveCamera,ea as Plane,ul as PlaneGeometry,dd as PlaneHelper,Ac as PointLight,Yu as PointLightHelper,Ua as Points,Na as PointsMaterial,td as PolarGridHelper,Ah as PolyhedronGeometry,hu as PositionalAudio,gu as PropertyBinding,cu as PropertyMixer,mh as QuadraticBezierCurve,yh as QuadraticBezierCurve3,Ci as Quaternion,Zl as QuaternionKeyframeTrack,Yl as QuaternionLinearInterpolant,js as RAD2DEG,ze as RED_GREEN_RGTC2_Format,Ae as RED_RGTC1_Format,t as REVISION,He as RGBADepthPacking,Wt as RGBAFormat,Gt as RGBAIntegerFormat,be as RGBA_ASTC_10x10_Format,fe as RGBA_ASTC_10x5_Format,ge as RGBA_ASTC_10x6_Format,xe as RGBA_ASTC_10x8_Format,ve as RGBA_ASTC_12x10_Format,we as RGBA_ASTC_12x12_Format,he as RGBA_ASTC_4x4_Format,le as RGBA_ASTC_5x4_Format,ce as RGBA_ASTC_5x5_Format,ue as RGBA_ASTC_6x5_Format,de as RGBA_ASTC_6x6_Format,pe as RGBA_ASTC_8x5_Format,me as RGBA_ASTC_8x6_Format,ye as RGBA_ASTC_8x8_Format,Me as RGBA_BPTC_Format,ae as RGBA_ETC2_EAC_Format,re as RGBA_PVRTC_2BPPV1_Format,ie as RGBA_PVRTC_4BPPV1_Format,Qt as RGBA_S3TC_DXT1_Format,Kt as RGBA_S3TC_DXT3_Format,te as RGBA_S3TC_DXT5_Format,qe as RGBDepthPacking,Vt as RGBFormat,Zt as RGBIntegerFormat,Se as RGB_BPTC_SIGNED_Format,_e as RGB_BPTC_UNSIGNED_Format,ne as RGB_ETC1_Format,oe as RGB_ETC2_Format,se as RGB_PVRTC_2BPPV1_Format,ee as RGB_PVRTC_4BPPV1_Format,$t as RGB_S3TC_DXT1_Format,Je as RGDepthPacking,Xt as RGFormat,Yt as RGIntegerFormat,Sl as RawShaderMaterial,rr as Ray,Bu as Raycaster,Bc as RectAreaLight,qt as RedFormat,Jt as RedIntegerFormat,K as ReinhardToneMapping,Mi as RenderTarget,Mu as RenderTarget3D,Su as RenderTargetArray,pt as RepeatWrapping,ss as ReplaceStencilOp,M as ReverseSubtractEquation,dl as RingGeometry,Ce as SIGNED_RED_GREEN_RGTC2_Format,Te as SIGNED_RED_RGTC1_Format,Ge as SRGBColorSpace,Ke as SRGBTransfer,ro as Scene,Jn as ShaderMaterial,Ml as ShadowMaterial,Rh as Shape,pl as ShapeGeometry,xd as ShapePath,rl as ShapeUtils,Ct as ShortType,Uo as Skeleton,Ju as SkeletonHelper,No as SkinnedMesh,gi as Source,Gi as Sphere,ml as SphereGeometry,Eu as Spherical,kc as SphericalHarmonics3,fh as SplineCurve,vc as SpotLight,Uu as SpotLightHelper,So as Sprite,ho as SpriteMaterial,I as SrcAlphaFactor,O as SrcAlphaSaturateFactor,z as SrcColorFactor,Bs as StaticCopyUsage,_s as StaticDrawUsage,zs as StaticReadUsage,Yc as StereoCamera,Rs as StreamCopyUsage,Ts as StreamDrawUsage,Is as StreamReadUsage,Gl as StringKeyframeTrack,w as SubtractEquation,g as SubtractiveBlending,s as TOUCH,Xe as TangentSpaceNormalMap,yl as TetrahedronGeometry,vi as Texture,dc as TextureLoader,wd as TextureUtils,fl as TorusGeometry,gl as TorusKnotGeometry,Jr as Triangle,Ue as TriangleFanDrawMode,je as TriangleStripDrawMode,We as TrianglesDrawMode,xl as TubeGeometry,at as UVMapping,yn as Uint16BufferAttribute,gn as Uint32BufferAttribute,dn as Uint8BufferAttribute,pn as Uint8ClampedBufferAttribute,_u as Uniform,Tu as UniformsGroup,qn as UniformsUtils,Tt as UnsignedByteType,Ft as UnsignedInt248Type,Nt as UnsignedInt5999Type,kt as UnsignedIntType,Pt as UnsignedShort4444Type,Ot as UnsignedShort5551Type,It as UnsignedShortType,c as VSMShadowMap,Zs as Vector2,Ii as Vector3,wi as Vector4,$l as VectorKeyframeTrack,qa as VideoTexture,zi as WebGL3DRenderTarget,Ai as WebGLArrayRenderTarget,Os as WebGLCoordinateSystem,eo as WebGLCubeRenderTarget,Si as WebGLRenderTarget,Fs as WebGPUCoordinateSystem,bl as WireframeGeometry,Ne as WrapAroundEnding,Oe as ZeroCurvatureEnding,A as ZeroFactor,Fe as ZeroSlopeEnding,ts as ZeroStencilOp,Qs as arrayNeedsUint32,Un as cloneUniforms,si as createCanvasElement,ei as createElementNS,vd as getByteLength,Hn as getUnlitUniformColorSpace,Dn as mergeUniforms,ni as probeAsync,oi as toNormalizedProjectionMatrix,ai as toReversedProjectionMatrix,ri as warnOnce}; diff --git a/build/three.module.js b/build/three.module.js index 104e7ca53542cb..421b9419921391 100644 --- a/build/three.module.js +++ b/build/three.module.js @@ -1,10 +1,10 @@ /** * @license - * Copyright 2010-2024 Three.js Authors + * Copyright 2010-2025 Three.js Authors * SPDX-License-Identifier: MIT */ import { Color, Matrix3, Vector2, mergeUniforms, Vector3, CubeUVReflectionMapping, Mesh, BoxGeometry, ShaderMaterial, cloneUniforms, BackSide, ColorManagement, SRGBTransfer, PlaneGeometry, FrontSide, getUnlitUniformColorSpace, Euler, Matrix4, IntType, RGBAFormat, HalfFloatType, UnsignedByteType, FloatType, Plane, EquirectangularReflectionMapping, EquirectangularRefractionMapping, WebGLCubeRenderTarget, CubeReflectionMapping, CubeRefractionMapping, PerspectiveCamera, NoToneMapping, MeshBasicMaterial, BufferGeometry, BufferAttribute, WebGLRenderTarget, NoBlending, OrthographicCamera, LinearFilter, LinearSRGBColorSpace, warnOnce, arrayNeedsUint32, Uint32BufferAttribute, Uint16BufferAttribute, Vector4, DataArrayTexture, LessEqualCompare, Texture, DepthTexture, Data3DTexture, CubeTexture, GLSL3, CustomToneMapping, NeutralToneMapping, AgXToneMapping, ACESFilmicToneMapping, CineonToneMapping, ReinhardToneMapping, LinearToneMapping, PCFShadowMap, PCFSoftShadowMap, VSMShadowMap, LinearTransfer, AddOperation, MixOperation, MultiplyOperation, ObjectSpaceNormalMap, TangentSpaceNormalMap, NormalBlending, DoubleSide, UniformsUtils, Layers, Frustum, MeshDepthMaterial, RGBADepthPacking, MeshDistanceMaterial, NearestFilter, LessEqualDepth, AddEquation, SubtractEquation, ReverseSubtractEquation, ZeroFactor, OneFactor, SrcColorFactor, SrcAlphaFactor, SrcAlphaSaturateFactor, DstColorFactor, DstAlphaFactor, OneMinusSrcColorFactor, OneMinusSrcAlphaFactor, OneMinusDstColorFactor, OneMinusDstAlphaFactor, ConstantColorFactor, OneMinusConstantColorFactor, ConstantAlphaFactor, OneMinusConstantAlphaFactor, CustomBlending, MultiplyBlending, SubtractiveBlending, AdditiveBlending, CullFaceNone, CullFaceBack, CullFaceFront, NotEqualDepth, GreaterDepth, GreaterEqualDepth, EqualDepth, LessDepth, AlwaysDepth, NeverDepth, MinEquation, MaxEquation, RepeatWrapping, ClampToEdgeWrapping, MirroredRepeatWrapping, NearestMipmapNearestFilter, NearestMipmapLinearFilter, LinearMipmapNearestFilter, LinearMipmapLinearFilter, NeverCompare, AlwaysCompare, LessCompare, EqualCompare, GreaterEqualCompare, GreaterCompare, NotEqualCompare, NoColorSpace, DepthStencilFormat, getByteLength, UnsignedIntType, UnsignedInt248Type, UnsignedShortType, DepthFormat, createElementNS, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedInt5999Type, ByteType, ShortType, AlphaFormat, RGBFormat, LuminanceFormat, LuminanceAlphaFormat, RedFormat, RedIntegerFormat, RGFormat, RGIntegerFormat, RGBAIntegerFormat, RGB_S3TC_DXT1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGB_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_PVRTC_2BPPV1_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_BPTC_Format, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RED_RGTC1_Format, SIGNED_RED_RGTC1_Format, RED_GREEN_RGTC2_Format, SIGNED_RED_GREEN_RGTC2_Format, Group, EventDispatcher, ArrayCamera, RAD2DEG, createCanvasElement, SRGBColorSpace, REVISION, toNormalizedProjectionMatrix, toReversedProjectionMatrix, probeAsync, WebGLCoordinateSystem } from './three.core.js'; -export { AdditiveAnimationBlendMode, AlwaysStencilFunc, AmbientLight, AnimationAction, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrowHelper, AttachedBindMode, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BasicDepthPacking, BasicShadowMap, BatchedMesh, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxHelper, BufferGeometryLoader, Cache, Camera, CameraHelper, CanvasTexture, CapsuleGeometry, CatmullRomCurve3, CircleGeometry, Clock, ColorKeyframeTrack, CompressedArrayTexture, CompressedCubeTexture, CompressedTexture, CompressedTextureLoader, ConeGeometry, Controls, CubeCamera, CubeTextureLoader, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceFrontBack, Curve, CurvePath, CylinderGeometry, Cylindrical, DataTexture, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DetachedBindMode, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DodecahedronGeometry, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EllipseCurve, EqualStencilFunc, ExtrudeGeometry, FileLoader, Float16BufferAttribute, Float32BufferAttribute, Fog, FogExp2, FramebufferTexture, GLBufferAttribute, GLSL1, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, HemisphereLight, HemisphereLightHelper, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InvertStencilOp, KeepStencilOp, KeyframeTrack, LOD, LatheGeometry, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LineSegments, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, Loader, LoaderUtils, LoadingManager, LoopOnce, LoopPingPong, LoopRepeat, MOUSE, Material, MaterialLoader, MathUtils, Matrix2, MeshLambertMaterial, MeshMatcapMaterial, MeshNormalMaterial, MeshPhongMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshToonMaterial, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NeverStencilFunc, NormalAnimationBlendMode, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, OctahedronGeometry, Path, PlaneHelper, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, RGBDepthPacking, RGBIntegerFormat, RGDepthPacking, RawShaderMaterial, Ray, Raycaster, RectAreaLight, RenderTarget, ReplaceStencilOp, RingGeometry, Scene, ShadowMaterial, Shape, ShapeGeometry, ShapePath, ShapeUtils, Skeleton, SkeletonHelper, SkinnedMesh, Source, Sphere, SphereGeometry, Spherical, SphericalHarmonics3, SplineCurve, SpotLight, SpotLightHelper, Sprite, SpriteMaterial, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, TOUCH, TetrahedronGeometry, TextureLoader, TextureUtils, TorusGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeGeometry, UVMapping, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, VectorKeyframeTrack, VideoTexture, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGPUCoordinateSystem, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroSlopeEnding, ZeroStencilOp } from './three.core.js'; +export { AdditiveAnimationBlendMode, AlwaysStencilFunc, AmbientLight, AnimationAction, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrowHelper, AttachedBindMode, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BasicDepthPacking, BasicShadowMap, BatchedMesh, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxHelper, BufferGeometryLoader, Cache, Camera, CameraHelper, CanvasTexture, CapsuleGeometry, CatmullRomCurve3, CircleGeometry, Clock, ColorKeyframeTrack, CompressedArrayTexture, CompressedCubeTexture, CompressedTexture, CompressedTextureLoader, ConeGeometry, Controls, CubeCamera, CubeTextureLoader, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceFrontBack, Curve, CurvePath, CylinderGeometry, Cylindrical, DataTexture, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DetachedBindMode, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DodecahedronGeometry, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EllipseCurve, EqualStencilFunc, ExtrudeGeometry, FileLoader, Float16BufferAttribute, Float32BufferAttribute, Fog, FogExp2, FramebufferTexture, GLBufferAttribute, GLSL1, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, HemisphereLight, HemisphereLightHelper, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InvertStencilOp, KeepStencilOp, KeyframeTrack, LOD, LatheGeometry, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LineSegments, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, Loader, LoaderUtils, LoadingManager, LoopOnce, LoopPingPong, LoopRepeat, MOUSE, Material, MaterialLoader, MathUtils, Matrix2, MeshLambertMaterial, MeshMatcapMaterial, MeshNormalMaterial, MeshPhongMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshToonMaterial, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NeverStencilFunc, NormalAnimationBlendMode, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, OctahedronGeometry, Path, PlaneHelper, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, RGBDepthPacking, RGBIntegerFormat, RGDepthPacking, RawShaderMaterial, Ray, Raycaster, RectAreaLight, RenderTarget, RenderTarget3D, RenderTargetArray, ReplaceStencilOp, RingGeometry, Scene, ShadowMaterial, Shape, ShapeGeometry, ShapePath, ShapeUtils, Skeleton, SkeletonHelper, SkinnedMesh, Source, Sphere, SphereGeometry, Spherical, SphericalHarmonics3, SplineCurve, SpotLight, SpotLightHelper, Sprite, SpriteMaterial, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, TOUCH, TetrahedronGeometry, TextureLoader, TextureUtils, TorusGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeGeometry, UVMapping, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, VectorKeyframeTrack, VideoTexture, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGPUCoordinateSystem, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroSlopeEnding, ZeroStencilOp } from './three.core.js'; function WebGLAnimation() { @@ -1535,6 +1535,8 @@ function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, boxMesh.geometry.dispose(); boxMesh.material.dispose(); + boxMesh = undefined; + } if ( planeMesh !== undefined ) { @@ -1542,6 +1544,8 @@ function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, planeMesh.geometry.dispose(); planeMesh.material.dispose(); + planeMesh = undefined; + } } @@ -13694,8 +13698,11 @@ class WebXRManager extends EventDispatcher { // const enabledFeatures = session.enabledFeatures; + const gpuDepthSensingEnabled = enabledFeatures && + enabledFeatures.includes( 'depth-sensing' ) && + session.depthUsage == 'gpu-optimized'; - if ( enabledFeatures && enabledFeatures.includes( 'depth-sensing' ) ) { + if ( gpuDepthSensingEnabled && glBinding ) { const depthData = glBinding.getDepthInformation( views[ 0 ] ); @@ -15944,7 +15951,7 @@ class WebGLRenderer { // - if ( _currentRenderTarget !== null ) { + if ( _currentRenderTarget !== null && _currentActiveMipmapLevel === 0 ) { // resolve multisample renderbuffers to a single-sample texture if necessary @@ -16939,6 +16946,7 @@ class WebGLRenderer { }; + const _scratchFrameBuffer = _gl.createFramebuffer(); this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) { _currentRenderTarget = renderTarget; @@ -17047,6 +17055,14 @@ class WebGLRenderer { } + // Use a scratch frame buffer if rendering to a mip level to avoid depth buffers + // being bound that are different sizes. + if ( activeMipmapLevel !== 0 ) { + + framebuffer = _scratchFrameBuffer; + + } + const framebufferBound = state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); if ( framebufferBound && useDefaultFramebuffer ) { @@ -17067,8 +17083,15 @@ class WebGLRenderer { } else if ( isRenderTarget3D ) { const textureProperties = properties.get( renderTarget.texture ); - const layer = activeCubeFace || 0; - _gl.framebufferTextureLayer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureProperties.__webglTexture, activeMipmapLevel || 0, layer ); + const layer = activeCubeFace; + _gl.framebufferTextureLayer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureProperties.__webglTexture, activeMipmapLevel, layer ); + + } else if ( renderTarget !== null && activeMipmapLevel !== 0 ) { + + // Only bind the frame buffer if we are using a scratch frame buffer to render to a mipmap. + // If we rebind the texture when using a multi sample buffer then an error about inconsistent samples will be thrown. + const textureProperties = properties.get( renderTarget.texture ); + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, textureProperties.__webglTexture, activeMipmapLevel ); } diff --git a/build/three.module.min.js b/build/three.module.min.js index 4090891b0cfbb4..d7b2620a3807c3 100644 --- a/build/three.module.min.js +++ b/build/three.module.min.js @@ -1,6 +1,6 @@ /** * @license - * Copyright 2010-2024 Three.js Authors + * Copyright 2010-2025 Three.js Authors * SPDX-License-Identifier: MIT */ -import{Color as e,Matrix3 as t,Vector2 as n,mergeUniforms as i,Vector3 as r,CubeUVReflectionMapping as a,Mesh as o,BoxGeometry as s,ShaderMaterial as l,cloneUniforms as c,BackSide as d,ColorManagement as u,SRGBTransfer as f,PlaneGeometry as p,FrontSide as m,getUnlitUniformColorSpace as h,Euler as _,Matrix4 as g,IntType as v,RGBAFormat as E,HalfFloatType as S,UnsignedByteType as T,FloatType as M,Plane as x,EquirectangularReflectionMapping as R,EquirectangularRefractionMapping as A,WebGLCubeRenderTarget as b,CubeReflectionMapping as C,CubeRefractionMapping as L,PerspectiveCamera as P,NoToneMapping as U,MeshBasicMaterial as w,BufferGeometry as D,BufferAttribute as y,WebGLRenderTarget as I,NoBlending as N,OrthographicCamera as O,LinearFilter as F,LinearSRGBColorSpace as B,warnOnce as H,arrayNeedsUint32 as G,Uint32BufferAttribute as V,Uint16BufferAttribute as z,Vector4 as k,DataArrayTexture as W,LessEqualCompare as X,Texture as Y,DepthTexture as j,Data3DTexture as K,CubeTexture as q,GLSL3 as Z,CustomToneMapping as $,NeutralToneMapping as Q,AgXToneMapping as J,ACESFilmicToneMapping as ee,CineonToneMapping as te,ReinhardToneMapping as ne,LinearToneMapping as ie,PCFShadowMap as re,PCFSoftShadowMap as ae,VSMShadowMap as oe,LinearTransfer as se,AddOperation as le,MixOperation as ce,MultiplyOperation as de,ObjectSpaceNormalMap as ue,TangentSpaceNormalMap as fe,NormalBlending as pe,DoubleSide as me,UniformsUtils as he,Layers as _e,Frustum as ge,MeshDepthMaterial as ve,RGBADepthPacking as Ee,MeshDistanceMaterial as Se,NearestFilter as Te,LessEqualDepth as Me,AddEquation as xe,SubtractEquation as Re,ReverseSubtractEquation as Ae,ZeroFactor as be,OneFactor as Ce,SrcColorFactor as Le,SrcAlphaFactor as Pe,SrcAlphaSaturateFactor as Ue,DstColorFactor as we,DstAlphaFactor as De,OneMinusSrcColorFactor as ye,OneMinusSrcAlphaFactor as Ie,OneMinusDstColorFactor as Ne,OneMinusDstAlphaFactor as Oe,ConstantColorFactor as Fe,OneMinusConstantColorFactor as Be,ConstantAlphaFactor as He,OneMinusConstantAlphaFactor as Ge,CustomBlending as Ve,MultiplyBlending as ze,SubtractiveBlending as ke,AdditiveBlending as We,CullFaceNone as Xe,CullFaceBack as Ye,CullFaceFront as je,NotEqualDepth as Ke,GreaterDepth as qe,GreaterEqualDepth as Ze,EqualDepth as $e,LessDepth as Qe,AlwaysDepth as Je,NeverDepth as et,MinEquation as tt,MaxEquation as nt,RepeatWrapping as it,ClampToEdgeWrapping as rt,MirroredRepeatWrapping as at,NearestMipmapNearestFilter as ot,NearestMipmapLinearFilter as st,LinearMipmapNearestFilter as lt,LinearMipmapLinearFilter as ct,NeverCompare as dt,AlwaysCompare as ut,LessCompare as ft,EqualCompare as pt,GreaterEqualCompare as mt,GreaterCompare as ht,NotEqualCompare as _t,NoColorSpace as gt,DepthStencilFormat as vt,getByteLength as Et,UnsignedIntType as St,UnsignedInt248Type as Tt,UnsignedShortType as Mt,DepthFormat as xt,createElementNS as Rt,UnsignedShort4444Type as At,UnsignedShort5551Type as bt,UnsignedInt5999Type as Ct,ByteType as Lt,ShortType as Pt,AlphaFormat as Ut,RGBFormat as wt,LuminanceFormat as Dt,LuminanceAlphaFormat as yt,RedFormat as It,RedIntegerFormat as Nt,RGFormat as Ot,RGIntegerFormat as Ft,RGBAIntegerFormat as Bt,RGB_S3TC_DXT1_Format as Ht,RGBA_S3TC_DXT1_Format as Gt,RGBA_S3TC_DXT3_Format as Vt,RGBA_S3TC_DXT5_Format as zt,RGB_PVRTC_4BPPV1_Format as kt,RGB_PVRTC_2BPPV1_Format as Wt,RGBA_PVRTC_4BPPV1_Format as Xt,RGBA_PVRTC_2BPPV1_Format as Yt,RGB_ETC1_Format as jt,RGB_ETC2_Format as Kt,RGBA_ETC2_EAC_Format as qt,RGBA_ASTC_4x4_Format as Zt,RGBA_ASTC_5x4_Format as $t,RGBA_ASTC_5x5_Format as Qt,RGBA_ASTC_6x5_Format as Jt,RGBA_ASTC_6x6_Format as en,RGBA_ASTC_8x5_Format as tn,RGBA_ASTC_8x6_Format as nn,RGBA_ASTC_8x8_Format as rn,RGBA_ASTC_10x5_Format as an,RGBA_ASTC_10x6_Format as on,RGBA_ASTC_10x8_Format as sn,RGBA_ASTC_10x10_Format as ln,RGBA_ASTC_12x10_Format as cn,RGBA_ASTC_12x12_Format as dn,RGBA_BPTC_Format as un,RGB_BPTC_SIGNED_Format as fn,RGB_BPTC_UNSIGNED_Format as pn,RED_RGTC1_Format as mn,SIGNED_RED_RGTC1_Format as hn,RED_GREEN_RGTC2_Format as _n,SIGNED_RED_GREEN_RGTC2_Format as gn,Group as vn,EventDispatcher as En,ArrayCamera as Sn,RAD2DEG as Tn,createCanvasElement as Mn,SRGBColorSpace as xn,REVISION as Rn,toNormalizedProjectionMatrix as An,toReversedProjectionMatrix as bn,probeAsync as Cn,WebGLCoordinateSystem as Ln}from"./three.core.min.js";export{AdditiveAnimationBlendMode,AlwaysStencilFunc,AmbientLight,AnimationAction,AnimationClip,AnimationLoader,AnimationMixer,AnimationObjectGroup,AnimationUtils,ArcCurve,ArrowHelper,AttachedBindMode,Audio,AudioAnalyser,AudioContext,AudioListener,AudioLoader,AxesHelper,BasicDepthPacking,BasicShadowMap,BatchedMesh,Bone,BooleanKeyframeTrack,Box2,Box3,Box3Helper,BoxHelper,BufferGeometryLoader,Cache,Camera,CameraHelper,CanvasTexture,CapsuleGeometry,CatmullRomCurve3,CircleGeometry,Clock,ColorKeyframeTrack,CompressedArrayTexture,CompressedCubeTexture,CompressedTexture,CompressedTextureLoader,ConeGeometry,Controls,CubeCamera,CubeTextureLoader,CubicBezierCurve,CubicBezierCurve3,CubicInterpolant,CullFaceFrontBack,Curve,CurvePath,CylinderGeometry,Cylindrical,DataTexture,DataTextureLoader,DataUtils,DecrementStencilOp,DecrementWrapStencilOp,DefaultLoadingManager,DetachedBindMode,DirectionalLight,DirectionalLightHelper,DiscreteInterpolant,DodecahedronGeometry,DynamicCopyUsage,DynamicDrawUsage,DynamicReadUsage,EdgesGeometry,EllipseCurve,EqualStencilFunc,ExtrudeGeometry,FileLoader,Float16BufferAttribute,Float32BufferAttribute,Fog,FogExp2,FramebufferTexture,GLBufferAttribute,GLSL1,GreaterEqualStencilFunc,GreaterStencilFunc,GridHelper,HemisphereLight,HemisphereLightHelper,IcosahedronGeometry,ImageBitmapLoader,ImageLoader,ImageUtils,IncrementStencilOp,IncrementWrapStencilOp,InstancedBufferAttribute,InstancedBufferGeometry,InstancedInterleavedBuffer,InstancedMesh,Int16BufferAttribute,Int32BufferAttribute,Int8BufferAttribute,InterleavedBuffer,InterleavedBufferAttribute,Interpolant,InterpolateDiscrete,InterpolateLinear,InterpolateSmooth,InvertStencilOp,KeepStencilOp,KeyframeTrack,LOD,LatheGeometry,LessEqualStencilFunc,LessStencilFunc,Light,LightProbe,Line,Line3,LineBasicMaterial,LineCurve,LineCurve3,LineDashedMaterial,LineLoop,LineSegments,LinearInterpolant,LinearMipMapLinearFilter,LinearMipMapNearestFilter,Loader,LoaderUtils,LoadingManager,LoopOnce,LoopPingPong,LoopRepeat,MOUSE,Material,MaterialLoader,MathUtils,Matrix2,MeshLambertMaterial,MeshMatcapMaterial,MeshNormalMaterial,MeshPhongMaterial,MeshPhysicalMaterial,MeshStandardMaterial,MeshToonMaterial,NearestMipMapLinearFilter,NearestMipMapNearestFilter,NeverStencilFunc,NormalAnimationBlendMode,NotEqualStencilFunc,NumberKeyframeTrack,Object3D,ObjectLoader,OctahedronGeometry,Path,PlaneHelper,PointLight,PointLightHelper,Points,PointsMaterial,PolarGridHelper,PolyhedronGeometry,PositionalAudio,PropertyBinding,PropertyMixer,QuadraticBezierCurve,QuadraticBezierCurve3,Quaternion,QuaternionKeyframeTrack,QuaternionLinearInterpolant,RGBDepthPacking,RGBIntegerFormat,RGDepthPacking,RawShaderMaterial,Ray,Raycaster,RectAreaLight,RenderTarget,ReplaceStencilOp,RingGeometry,Scene,ShadowMaterial,Shape,ShapeGeometry,ShapePath,ShapeUtils,Skeleton,SkeletonHelper,SkinnedMesh,Source,Sphere,SphereGeometry,Spherical,SphericalHarmonics3,SplineCurve,SpotLight,SpotLightHelper,Sprite,SpriteMaterial,StaticCopyUsage,StaticDrawUsage,StaticReadUsage,StereoCamera,StreamCopyUsage,StreamDrawUsage,StreamReadUsage,StringKeyframeTrack,TOUCH,TetrahedronGeometry,TextureLoader,TextureUtils,TorusGeometry,TorusKnotGeometry,Triangle,TriangleFanDrawMode,TriangleStripDrawMode,TrianglesDrawMode,TubeGeometry,UVMapping,Uint8BufferAttribute,Uint8ClampedBufferAttribute,Uniform,UniformsGroup,VectorKeyframeTrack,VideoTexture,WebGL3DRenderTarget,WebGLArrayRenderTarget,WebGPUCoordinateSystem,WireframeGeometry,WrapAroundEnding,ZeroCurvatureEnding,ZeroSlopeEnding,ZeroStencilOp}from"./three.core.min.js";function Pn(){let e=null,t=!1,n=null,i=null;function r(t,a){n(t,a),i=e.requestAnimationFrame(r)}return{start:function(){!0!==t&&null!==n&&(i=e.requestAnimationFrame(r),t=!0)},stop:function(){e.cancelAnimationFrame(i),t=!1},setAnimationLoop:function(e){n=e},setContext:function(t){e=t}}}function Un(e){const t=new WeakMap;return{get:function(e){return e.isInterleavedBufferAttribute&&(e=e.data),t.get(e)},remove:function(n){n.isInterleavedBufferAttribute&&(n=n.data);const i=t.get(n);i&&(e.deleteBuffer(i.buffer),t.delete(n))},update:function(n,i){if(n.isInterleavedBufferAttribute&&(n=n.data),n.isGLBufferAttribute){const e=t.get(n);return void((!e||e.versione.start-t.start));let t=0;for(let e=1;e 0\n\tvec4 plane;\n\t#ifdef ALPHA_TO_COVERAGE\n\t\tfloat distanceToPlane, distanceGradient;\n\t\tfloat clipOpacity = 1.0;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\tclipOpacity *= smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\tif ( clipOpacity == 0.0 ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tfloat unionClipOpacity = 1.0;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\t\tunionClipOpacity *= 1.0 - smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tclipOpacity *= 1.0 - unionClipOpacity;\n\t\t#endif\n\t\tdiffuseColor.a *= clipOpacity;\n\t\tif ( diffuseColor.a == 0.0 ) discard;\n\t#else\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tbool clipped = true;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tif ( clipped ) discard;\n\t\t#endif\n\t#endif\n#endif",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif",color_fragment:"#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif",color_pars_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )\n\tvarying vec3 vColor;\n#endif",color_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif\n#ifdef USE_BATCHING_COLOR\n\tvec3 batchingColor = getBatchingColor( getIndirectIndex( gl_DrawID ) );\n\tvColor.xyz *= batchingColor.xyz;\n#endif",common:"#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\n#ifdef USE_ALPHAHASH\n\tvarying vec3 vPosition;\n#endif\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}\nvec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n} // validated",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\thighp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif",defaultnormal_vertex:"vec3 transformedNormal = objectNormal;\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = objectTangent;\n#endif\n#ifdef USE_BATCHING\n\tmat3 bm = mat3( batchingMatrix );\n\ttransformedNormal /= vec3( dot( bm[ 0 ], bm[ 0 ] ), dot( bm[ 1 ], bm[ 1 ] ), dot( bm[ 2 ], bm[ 2 ] ) );\n\ttransformedNormal = bm * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = bm * transformedTangent;\n\t#endif\n#endif\n#ifdef USE_INSTANCING\n\tmat3 im = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( im[ 0 ], im[ 0 ] ), dot( im[ 1 ], im[ 1 ] ), dot( im[ 2 ], im[ 2 ] ) );\n\ttransformedNormal = im * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = im * transformedTangent;\n\t#endif\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\ttransformedTangent = ( modelViewMatrix * vec4( transformedTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\t#ifdef DECODE_VIDEO_TEXTURE_EMISSIVE\n\t\temissiveColor = sRGBTransferEOTF( emissiveColor );\n\t#endif\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif",colorspace_fragment:"gl_FragColor = linearToOutputTexel( gl_FragColor );",colorspace_pars_fragment:"vec4 LinearTransferOETF( in vec4 value ) {\n\treturn value;\n}\nvec4 sRGBTransferEOTF( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.a );\n}\nvec4 sRGBTransferOETF( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}",envmap_fragment:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, envMapRotation * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif",envmap_common_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\tuniform mat3 envMapRotation;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif",envmap_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif",envmap_physical_pars_fragment:"#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n#endif",envmap_vertex:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif",fog_vertex:"#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif",gradientmap_pars_fragment:"#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\tvec2 fw = fwidth( coord ) * 0.5;\n\t\treturn mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );\n\t#endif\n}",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_fragment:"LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;",lights_lambert_pars_fragment:"varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert",lights_pars_begin:"uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\n#if defined( USE_LIGHT_PROBES )\n\tuniform vec3 lightProbe[ 9 ];\n#endif\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\tif ( cutoffDistance > 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif",lights_toon_fragment:"ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;",lights_toon_pars_fragment:"varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometryNormal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;",lights_phong_pars_fragment:"varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_DISPERSION\n\tmaterial.dispersion = dispersion;\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tif( material.anisotropy == 0.0 ) {\n\t\tanisotropyV = vec2( 1.0, 0.0 );\n\t} else {\n\t\tanisotropyV /= material.anisotropy;\n\t\tmaterial.anisotropy = saturate( material.anisotropy );\n\t}\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;\n#endif",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\tfloat dispersion;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecularDirect = vec3( 0.0 );\nvec3 clearcoatSpecularIndirect = vec3( 0.0 );\nvec3 sheenSpecularDirect = vec3( 0.0 );\nvec3 sheenSpecularIndirect = vec3(0.0 );\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}",lights_fragment_begin:"\nvec3 geometryPosition = - vViewPosition;\nvec3 geometryNormal = normal;\nvec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\nvec3 geometryClearcoatNormal = vec3( 0.0 );\n#ifdef USE_CLEARCOAT\n\tgeometryClearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometryViewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometryPosition, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowIntensity, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometryPosition, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowIntensity, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowIntensity, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#if defined( USE_LIGHT_PROBES )\n\t\tirradiance += getLightProbeIrradiance( lightProbe, geometryNormal );\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometryNormal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif",lights_fragment_maps:"#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometryNormal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometryViewDir, geometryNormal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif",lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF )\n\tgl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#if defined( USE_LOGDEPTHBUF )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\tvFragDepth = 1.0 + gl_Position.w;\n\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n#endif",map_fragment:"#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vMapUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = sRGBTransferEOTF( sampledDiffuseColor );\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif",map_particle_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t#if defined( USE_POINTS_UV )\n\t\tvec2 uv = vUv;\n\t#else\n\t\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif",map_particle_pars_fragment:"#if defined( USE_POINTS_UV )\n\tvarying vec2 vUv;\n#else\n\t#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t\tuniform mat3 uvTransform;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphinstance_vertex:"#ifdef USE_INSTANCING_MORPH\n\tfloat morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\tfloat morphTargetBaseInfluence = texelFetch( morphTexture, ivec2( 0, gl_InstanceID ), 0 ).r;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tmorphTargetInfluences[i] = texelFetch( morphTexture, ivec2( i + 1, gl_InstanceID ), 0 ).r;\n\t}\n#endif",morphcolor_vertex:"#if defined( USE_MORPHCOLORS )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t}\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\t#ifndef USE_INSTANCING_MORPH\n\t\tuniform float morphTargetBaseInfluence;\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t#endif\n\tuniform sampler2DArray morphTargetsTexture;\n\tuniform ivec2 morphTargetsTextureSize;\n\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t}\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t}\n#endif",normal_fragment_begin:"float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal *= faceDirection;\n\t#endif\n#endif\n#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY )\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn = getTangentFrame( - vViewPosition, normal,\n\t\t#if defined( USE_NORMALMAP )\n\t\t\tvNormalMapUv\n\t\t#elif defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tvClearcoatNormalMapUv\n\t\t#else\n\t\t\tvUv\n\t\t#endif\n\t\t);\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn[0] *= faceDirection;\n\t\ttbn[1] *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn2[0] *= faceDirection;\n\t\ttbn2[1] *= faceDirection;\n\t#endif\n#endif\nvec3 nonPerturbedNormal = normal;",normal_fragment_maps:"#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif",normal_pars_fragment:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_pars_vertex:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_vertex:"#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef USE_NORMALMAP_OBJECTSPACE\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) )\n\tmat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( uv.st );\n\t\tvec2 st1 = dFdy( uv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det );\n\t\treturn mat3( T * scale, B * scale, N );\n\t}\n#endif",clearcoat_normal_fragment_begin:"#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = nonPerturbedNormal;\n#endif",clearcoat_normal_fragment_maps:"#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\tclearcoatNormal = normalize( tbn2 * clearcoatMapN );\n#endif",clearcoat_pars_fragment:"#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif",iridescence_pars_fragment:"#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif",opaque_fragment:"#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;const float ShiftRight8 = 1. / 256.;\nconst float Inv255 = 1. / 255.;\nconst vec4 PackFactors = vec4( 1.0, 256.0, 256.0 * 256.0, 256.0 * 256.0 * 256.0 );\nconst vec2 UnpackFactors2 = vec2( UnpackDownscale, 1.0 / PackFactors.g );\nconst vec3 UnpackFactors3 = vec3( UnpackDownscale / PackFactors.rg, 1.0 / PackFactors.b );\nconst vec4 UnpackFactors4 = vec4( UnpackDownscale / PackFactors.rgb, 1.0 / PackFactors.a );\nvec4 packDepthToRGBA( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec4( 0., 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec4( 1., 1., 1., 1. );\n\tfloat vuf;\n\tfloat af = modf( v * PackFactors.a, vuf );\n\tfloat bf = modf( vuf * ShiftRight8, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec4( vuf * Inv255, gf * PackUpscale, bf * PackUpscale, af );\n}\nvec3 packDepthToRGB( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec3( 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec3( 1., 1., 1. );\n\tfloat vuf;\n\tfloat bf = modf( v * PackFactors.b, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec3( vuf * Inv255, gf * PackUpscale, bf );\n}\nvec2 packDepthToRG( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec2( 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec2( 1., 1. );\n\tfloat vuf;\n\tfloat gf = modf( v * 256., vuf );\n\treturn vec2( vuf * Inv255, gf );\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors4 );\n}\nfloat unpackRGBToDepth( const in vec3 v ) {\n\treturn dot( v, UnpackFactors3 );\n}\nfloat unpackRGToDepth( const in vec2 v ) {\n\treturn v.r * UnpackFactors2.r + v.g * UnpackFactors2.g;\n}\nvec4 pack2HalfToRGBA( const in vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( const in vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn depth * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * depth - far );\n}",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif",project_vertex:"vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_BATCHING\n\tmvPosition = batchingMatrix * mvPosition;\n#endif\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;",dithering_fragment:"#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif",dithering_pars_fragment:"#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tfloat shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\t\n\t\tfloat lightToPositionLength = length( lightToPosition );\n\t\tif ( lightToPositionLength - shadowCameraFar <= 0.0 && lightToPositionLength - shadowCameraNear >= 0.0 ) {\n\t\t\tfloat dp = ( lightToPositionLength - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\t\tdp += shadowBias;\n\t\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\t\tshadow = (\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t\t) * ( 1.0 / 9.0 );\n\t\t\t#else\n\t\t\t\tshadow = texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t\t#endif\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n#endif",shadowmap_pars_vertex:"#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif",shadowmap_vertex:"#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowIntensity, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowIntensity, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowIntensity, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tint size = textureSize( boneTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( boneTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( boneTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( boneTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( boneTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\n\t}\n#endif",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vSpecularMapUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif",tonemapping_pars_fragment:"#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn saturate( toneMappingExposure * color );\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 CineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nconst mat3 LINEAR_REC2020_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.6605, - 0.1246, - 0.0182 ),\n\tvec3( - 0.5876, 1.1329, - 0.1006 ),\n\tvec3( - 0.0728, - 0.0083, 1.1187 )\n);\nconst mat3 LINEAR_SRGB_TO_LINEAR_REC2020 = mat3(\n\tvec3( 0.6274, 0.0691, 0.0164 ),\n\tvec3( 0.3293, 0.9195, 0.0880 ),\n\tvec3( 0.0433, 0.0113, 0.8956 )\n);\nvec3 agxDefaultContrastApprox( vec3 x ) {\n\tvec3 x2 = x * x;\n\tvec3 x4 = x2 * x2;\n\treturn + 15.5 * x4 * x2\n\t\t- 40.14 * x4 * x\n\t\t+ 31.96 * x4\n\t\t- 6.868 * x2 * x\n\t\t+ 0.4298 * x2\n\t\t+ 0.1191 * x\n\t\t- 0.00232;\n}\nvec3 AgXToneMapping( vec3 color ) {\n\tconst mat3 AgXInsetMatrix = mat3(\n\t\tvec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ),\n\t\tvec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ),\n\t\tvec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 )\n\t);\n\tconst mat3 AgXOutsetMatrix = mat3(\n\t\tvec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ),\n\t\tvec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ),\n\t\tvec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 )\n\t);\n\tconst float AgxMinEv = - 12.47393;\tconst float AgxMaxEv = 4.026069;\n\tcolor *= toneMappingExposure;\n\tcolor = LINEAR_SRGB_TO_LINEAR_REC2020 * color;\n\tcolor = AgXInsetMatrix * color;\n\tcolor = max( color, 1e-10 );\tcolor = log2( color );\n\tcolor = ( color - AgxMinEv ) / ( AgxMaxEv - AgxMinEv );\n\tcolor = clamp( color, 0.0, 1.0 );\n\tcolor = agxDefaultContrastApprox( color );\n\tcolor = AgXOutsetMatrix * color;\n\tcolor = pow( max( vec3( 0.0 ), color ), vec3( 2.2 ) );\n\tcolor = LINEAR_REC2020_TO_LINEAR_SRGB * color;\n\tcolor = clamp( color, 0.0, 1.0 );\n\treturn color;\n}\nvec3 NeutralToneMapping( vec3 color ) {\n\tconst float StartCompression = 0.8 - 0.04;\n\tconst float Desaturation = 0.15;\n\tcolor *= toneMappingExposure;\n\tfloat x = min( color.r, min( color.g, color.b ) );\n\tfloat offset = x < 0.08 ? x - 6.25 * x * x : 0.04;\n\tcolor -= offset;\n\tfloat peak = max( color.r, max( color.g, color.b ) );\n\tif ( peak < StartCompression ) return color;\n\tfloat d = 1. - StartCompression;\n\tfloat newPeak = 1. - d * d / ( peak + d - StartCompression );\n\tcolor *= newPeak / peak;\n\tfloat g = 1. - 1. / ( Desaturation * ( peak - newPeak ) + 1. );\n\treturn mix( color, vec3( newPeak ), g );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }",transmission_fragment:"#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.dispersion, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );\n#endif",transmission_pars_fragment:"#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float dispersion, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec4 transmittedLight;\n\t\tvec3 transmittance;\n\t\t#ifdef USE_DISPERSION\n\t\t\tfloat halfSpread = ( ior - 1.0 ) * 0.025 * dispersion;\n\t\t\tvec3 iors = vec3( ior - halfSpread, ior, ior + halfSpread );\n\t\t\tfor ( int i = 0; i < 3; i ++ ) {\n\t\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, iors[ i ], modelMatrix );\n\t\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\t\trefractionCoords += 1.0;\n\t\t\t\trefractionCoords /= 2.0;\n\t\t\t\tvec4 transmissionSample = getTransmissionSample( refractionCoords, roughness, iors[ i ] );\n\t\t\t\ttransmittedLight[ i ] = transmissionSample[ i ];\n\t\t\t\ttransmittedLight.a += transmissionSample.a;\n\t\t\t\ttransmittance[ i ] = diffuseColor[ i ] * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance )[ i ];\n\t\t\t}\n\t\t\ttransmittedLight.a /= 3.0;\n\t\t#else\n\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\trefractionCoords += 1.0;\n\t\t\trefractionCoords /= 2.0;\n\t\t\ttransmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\t\ttransmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\t#endif\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\t}\n#endif",uv_pars_fragment:"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif",uv_pars_vertex:"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif",uv_vertex:"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_BATCHING\n\t\tworldPosition = batchingMatrix * worldPosition;\n\t#endif\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif",background_vert:"varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}",background_frag:"uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\ttexColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}",backgroundCube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",backgroundCube_frag:"#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float flipEnvMap;\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nuniform mat3 backgroundRotation;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, backgroundRotation * vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, backgroundRotation * vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}",cube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldDirection;\nvoid main() {\n\tvec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );\n\tgl_FragColor = texColor;\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvHighPrecisionZW = gl_Position.zw;\n}",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#elif DEPTH_PACKING == 3202\n\t\tgl_FragColor = vec4( packDepthToRGB( fragCoordZ ), 1.0 );\n\t#elif DEPTH_PACKING == 3203\n\t\tgl_FragColor = vec4( packDepthToRG( fragCoordZ ), 0.0, 1.0 );\n\t#endif\n}",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}",distanceRGBA_frag:"#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}",equirect_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include \n\t#include \n}",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",linedashed_frag:"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_vert:"#define LAMBERT\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_frag:"#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_vert:"#define MATCAP\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}",meshmatcap_frag:"#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshnormal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}",meshnormal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( 0.0, 0.0, 0.0, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), diffuseColor.a );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}",meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphong_frag:"#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_vert:"#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}",meshphysical_frag:"#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define USE_SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_DISPERSION\n\tuniform float dispersion;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecularDirect + sheenSpecularIndirect;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshtoon_vert:"#define TOON\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}",meshtoon_frag:"#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}",points_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}",sprite_vert:"uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix[ 3 ];\n\tvec2 scale = vec2( length( modelMatrix[ 0 ].xyz ), length( modelMatrix[ 1 ].xyz ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}",sprite_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n}"},Dn={common:{diffuse:{value:new e(16777215)},opacity:{value:1},map:{value:null},mapTransform:{value:new t},alphaMap:{value:null},alphaMapTransform:{value:new t},alphaTest:{value:0}},specularmap:{specularMap:{value:null},specularMapTransform:{value:new t}},envmap:{envMap:{value:null},envMapRotation:{value:new t},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1},aoMapTransform:{value:new t}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1},lightMapTransform:{value:new t}},bumpmap:{bumpMap:{value:null},bumpMapTransform:{value:new t},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalMapTransform:{value:new t},normalScale:{value:new n(1,1)}},displacementmap:{displacementMap:{value:null},displacementMapTransform:{value:new t},displacementScale:{value:1},displacementBias:{value:0}},emissivemap:{emissiveMap:{value:null},emissiveMapTransform:{value:new t}},metalnessmap:{metalnessMap:{value:null},metalnessMapTransform:{value:new t}},roughnessmap:{roughnessMap:{value:null},roughnessMapTransform:{value:new t}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new e(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotLightMap:{value:[]},spotShadowMap:{value:[]},spotLightMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMap:{value:[]},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}},ltc_1:{value:null},ltc_2:{value:null}},points:{diffuse:{value:new e(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaMapTransform:{value:new t},alphaTest:{value:0},uvTransform:{value:new t}},sprite:{diffuse:{value:new e(16777215)},opacity:{value:1},center:{value:new n(.5,.5)},rotation:{value:0},map:{value:null},mapTransform:{value:new t},alphaMap:{value:null},alphaMapTransform:{value:new t},alphaTest:{value:0}}},yn={basic:{uniforms:i([Dn.common,Dn.specularmap,Dn.envmap,Dn.aomap,Dn.lightmap,Dn.fog]),vertexShader:wn.meshbasic_vert,fragmentShader:wn.meshbasic_frag},lambert:{uniforms:i([Dn.common,Dn.specularmap,Dn.envmap,Dn.aomap,Dn.lightmap,Dn.emissivemap,Dn.bumpmap,Dn.normalmap,Dn.displacementmap,Dn.fog,Dn.lights,{emissive:{value:new e(0)}}]),vertexShader:wn.meshlambert_vert,fragmentShader:wn.meshlambert_frag},phong:{uniforms:i([Dn.common,Dn.specularmap,Dn.envmap,Dn.aomap,Dn.lightmap,Dn.emissivemap,Dn.bumpmap,Dn.normalmap,Dn.displacementmap,Dn.fog,Dn.lights,{emissive:{value:new e(0)},specular:{value:new e(1118481)},shininess:{value:30}}]),vertexShader:wn.meshphong_vert,fragmentShader:wn.meshphong_frag},standard:{uniforms:i([Dn.common,Dn.envmap,Dn.aomap,Dn.lightmap,Dn.emissivemap,Dn.bumpmap,Dn.normalmap,Dn.displacementmap,Dn.roughnessmap,Dn.metalnessmap,Dn.fog,Dn.lights,{emissive:{value:new e(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:wn.meshphysical_vert,fragmentShader:wn.meshphysical_frag},toon:{uniforms:i([Dn.common,Dn.aomap,Dn.lightmap,Dn.emissivemap,Dn.bumpmap,Dn.normalmap,Dn.displacementmap,Dn.gradientmap,Dn.fog,Dn.lights,{emissive:{value:new e(0)}}]),vertexShader:wn.meshtoon_vert,fragmentShader:wn.meshtoon_frag},matcap:{uniforms:i([Dn.common,Dn.bumpmap,Dn.normalmap,Dn.displacementmap,Dn.fog,{matcap:{value:null}}]),vertexShader:wn.meshmatcap_vert,fragmentShader:wn.meshmatcap_frag},points:{uniforms:i([Dn.points,Dn.fog]),vertexShader:wn.points_vert,fragmentShader:wn.points_frag},dashed:{uniforms:i([Dn.common,Dn.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:wn.linedashed_vert,fragmentShader:wn.linedashed_frag},depth:{uniforms:i([Dn.common,Dn.displacementmap]),vertexShader:wn.depth_vert,fragmentShader:wn.depth_frag},normal:{uniforms:i([Dn.common,Dn.bumpmap,Dn.normalmap,Dn.displacementmap,{opacity:{value:1}}]),vertexShader:wn.meshnormal_vert,fragmentShader:wn.meshnormal_frag},sprite:{uniforms:i([Dn.sprite,Dn.fog]),vertexShader:wn.sprite_vert,fragmentShader:wn.sprite_frag},background:{uniforms:{uvTransform:{value:new t},t2D:{value:null},backgroundIntensity:{value:1}},vertexShader:wn.background_vert,fragmentShader:wn.background_frag},backgroundCube:{uniforms:{envMap:{value:null},flipEnvMap:{value:-1},backgroundBlurriness:{value:0},backgroundIntensity:{value:1},backgroundRotation:{value:new t}},vertexShader:wn.backgroundCube_vert,fragmentShader:wn.backgroundCube_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:wn.cube_vert,fragmentShader:wn.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:wn.equirect_vert,fragmentShader:wn.equirect_frag},distanceRGBA:{uniforms:i([Dn.common,Dn.displacementmap,{referencePosition:{value:new r},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:wn.distanceRGBA_vert,fragmentShader:wn.distanceRGBA_frag},shadow:{uniforms:i([Dn.lights,Dn.fog,{color:{value:new e(0)},opacity:{value:1}}]),vertexShader:wn.shadow_vert,fragmentShader:wn.shadow_frag}};yn.physical={uniforms:i([yn.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatMapTransform:{value:new t},clearcoatNormalMap:{value:null},clearcoatNormalMapTransform:{value:new t},clearcoatNormalScale:{value:new n(1,1)},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatRoughnessMapTransform:{value:new t},dispersion:{value:0},iridescence:{value:0},iridescenceMap:{value:null},iridescenceMapTransform:{value:new t},iridescenceIOR:{value:1.3},iridescenceThicknessMinimum:{value:100},iridescenceThicknessMaximum:{value:400},iridescenceThicknessMap:{value:null},iridescenceThicknessMapTransform:{value:new t},sheen:{value:0},sheenColor:{value:new e(0)},sheenColorMap:{value:null},sheenColorMapTransform:{value:new t},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},sheenRoughnessMapTransform:{value:new t},transmission:{value:0},transmissionMap:{value:null},transmissionMapTransform:{value:new t},transmissionSamplerSize:{value:new n},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},thicknessMapTransform:{value:new t},attenuationDistance:{value:0},attenuationColor:{value:new e(0)},specularColor:{value:new e(1,1,1)},specularColorMap:{value:null},specularColorMapTransform:{value:new t},specularIntensity:{value:1},specularIntensityMap:{value:null},specularIntensityMapTransform:{value:new t},anisotropyVector:{value:new n},anisotropyMap:{value:null},anisotropyMapTransform:{value:new t}}]),vertexShader:wn.meshphysical_vert,fragmentShader:wn.meshphysical_frag};const In={r:0,b:0,g:0},Nn=new _,On=new g;function Fn(t,n,i,r,_,g,v){const E=new e(0);let S,T,M=!0===g?0:1,x=null,R=0,A=null;function b(e){let t=!0===e.isScene?e.background:null;if(t&&t.isTexture){t=(e.backgroundBlurriness>0?i:n).get(t)}return t}function C(e,n){e.getRGB(In,h(t)),r.buffers.color.setClear(In.r,In.g,In.b,n,v)}return{getClearColor:function(){return E},setClearColor:function(e,t=1){E.set(e),M=t,C(E,M)},getClearAlpha:function(){return M},setClearAlpha:function(e){M=e,C(E,M)},render:function(e){let n=!1;const i=b(e);null===i?C(E,M):i&&i.isColor&&(C(i,1),n=!0);const a=t.xr.getEnvironmentBlendMode();"additive"===a?r.buffers.color.setClear(0,0,0,1,v):"alpha-blend"===a&&r.buffers.color.setClear(0,0,0,0,v),(t.autoClear||n)&&(r.buffers.depth.setTest(!0),r.buffers.depth.setMask(!0),r.buffers.color.setMask(!0),t.clear(t.autoClearColor,t.autoClearDepth,t.autoClearStencil))},addToRenderList:function(e,n){const i=b(n);i&&(i.isCubeTexture||i.mapping===a)?(void 0===T&&(T=new o(new s(1,1,1),new l({name:"BackgroundCubeMaterial",uniforms:c(yn.backgroundCube.uniforms),vertexShader:yn.backgroundCube.vertexShader,fragmentShader:yn.backgroundCube.fragmentShader,side:d,depthTest:!1,depthWrite:!1,fog:!1})),T.geometry.deleteAttribute("normal"),T.geometry.deleteAttribute("uv"),T.onBeforeRender=function(e,t,n){this.matrixWorld.copyPosition(n.matrixWorld)},Object.defineProperty(T.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),_.update(T)),Nn.copy(n.backgroundRotation),Nn.x*=-1,Nn.y*=-1,Nn.z*=-1,i.isCubeTexture&&!1===i.isRenderTargetTexture&&(Nn.y*=-1,Nn.z*=-1),T.material.uniforms.envMap.value=i,T.material.uniforms.flipEnvMap.value=i.isCubeTexture&&!1===i.isRenderTargetTexture?-1:1,T.material.uniforms.backgroundBlurriness.value=n.backgroundBlurriness,T.material.uniforms.backgroundIntensity.value=n.backgroundIntensity,T.material.uniforms.backgroundRotation.value.setFromMatrix4(On.makeRotationFromEuler(Nn)),T.material.toneMapped=u.getTransfer(i.colorSpace)!==f,x===i&&R===i.version&&A===t.toneMapping||(T.material.needsUpdate=!0,x=i,R=i.version,A=t.toneMapping),T.layers.enableAll(),e.unshift(T,T.geometry,T.material,0,0,null)):i&&i.isTexture&&(void 0===S&&(S=new o(new p(2,2),new l({name:"BackgroundMaterial",uniforms:c(yn.background.uniforms),vertexShader:yn.background.vertexShader,fragmentShader:yn.background.fragmentShader,side:m,depthTest:!1,depthWrite:!1,fog:!1})),S.geometry.deleteAttribute("normal"),Object.defineProperty(S.material,"map",{get:function(){return this.uniforms.t2D.value}}),_.update(S)),S.material.uniforms.t2D.value=i,S.material.uniforms.backgroundIntensity.value=n.backgroundIntensity,S.material.toneMapped=u.getTransfer(i.colorSpace)!==f,!0===i.matrixAutoUpdate&&i.updateMatrix(),S.material.uniforms.uvTransform.value.copy(i.matrix),x===i&&R===i.version&&A===t.toneMapping||(S.material.needsUpdate=!0,x=i,R=i.version,A=t.toneMapping),S.layers.enableAll(),e.unshift(S,S.geometry,S.material,0,0,null))},dispose:function(){void 0!==T&&(T.geometry.dispose(),T.material.dispose()),void 0!==S&&(S.geometry.dispose(),S.material.dispose())}}}function Bn(e,t){const n=e.getParameter(e.MAX_VERTEX_ATTRIBS),i={},r=c(null);let a=r,o=!1;function s(t){return e.bindVertexArray(t)}function l(t){return e.deleteVertexArray(t)}function c(e){const t=[],i=[],r=[];for(let e=0;e=0){const n=r[t];let i=o[t];if(void 0===i&&("instanceMatrix"===t&&e.instanceMatrix&&(i=e.instanceMatrix),"instanceColor"===t&&e.instanceColor&&(i=e.instanceColor)),void 0===n)return!0;if(n.attribute!==i)return!0;if(i&&n.data!==i.data)return!0;s++}}return a.attributesNum!==s||a.index!==i}(n,h,l,_),g&&function(e,t,n,i){const r={},o=t.attributes;let s=0;const l=n.getAttributes();for(const t in l){if(l[t].location>=0){let n=o[t];void 0===n&&("instanceMatrix"===t&&e.instanceMatrix&&(n=e.instanceMatrix),"instanceColor"===t&&e.instanceColor&&(n=e.instanceColor));const i={};i.attribute=n,n&&n.data&&(i.data=n.data),r[t]=i,s++}}a.attributes=r,a.attributesNum=s,a.index=i}(n,h,l,_),null!==_&&t.update(_,e.ELEMENT_ARRAY_BUFFER),(g||o)&&(o=!1,function(n,i,r,a){d();const o=a.attributes,s=r.getAttributes(),l=i.defaultAttributeValues;for(const i in s){const r=s[i];if(r.location>=0){let s=o[i];if(void 0===s&&("instanceMatrix"===i&&n.instanceMatrix&&(s=n.instanceMatrix),"instanceColor"===i&&n.instanceColor&&(s=n.instanceColor)),void 0!==s){const i=s.normalized,o=s.itemSize,l=t.get(s);if(void 0===l)continue;const c=l.buffer,d=l.type,p=l.bytesPerElement,h=d===e.INT||d===e.UNSIGNED_INT||s.gpuType===v;if(s.isInterleavedBufferAttribute){const t=s.data,l=t.stride,_=s.offset;if(t.isInstancedInterleavedBuffer){for(let e=0;e0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT).precision>0)return"highp";t="mediump"}return"mediump"===t&&e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_FLOAT).precision>0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT).precision>0?"mediump":"lowp"}let o=void 0!==n.precision?n.precision:"highp";const s=a(o);s!==o&&(console.warn("THREE.WebGLRenderer:",o,"not supported, using",s,"instead."),o=s);const l=!0===n.logarithmicDepthBuffer,c=!0===n.reverseDepthBuffer&&t.has("EXT_clip_control"),d=e.getParameter(e.MAX_TEXTURE_IMAGE_UNITS),u=e.getParameter(e.MAX_VERTEX_TEXTURE_IMAGE_UNITS);return{isWebGL2:!0,getMaxAnisotropy:function(){if(void 0!==r)return r;if(!0===t.has("EXT_texture_filter_anisotropic")){const n=t.get("EXT_texture_filter_anisotropic");r=e.getParameter(n.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else r=0;return r},getMaxPrecision:a,textureFormatReadable:function(t){return t===E||i.convert(t)===e.getParameter(e.IMPLEMENTATION_COLOR_READ_FORMAT)},textureTypeReadable:function(n){const r=n===S&&(t.has("EXT_color_buffer_half_float")||t.has("EXT_color_buffer_float"));return!(n!==T&&i.convert(n)!==e.getParameter(e.IMPLEMENTATION_COLOR_READ_TYPE)&&n!==M&&!r)},precision:o,logarithmicDepthBuffer:l,reverseDepthBuffer:c,maxTextures:d,maxVertexTextures:u,maxTextureSize:e.getParameter(e.MAX_TEXTURE_SIZE),maxCubemapSize:e.getParameter(e.MAX_CUBE_MAP_TEXTURE_SIZE),maxAttributes:e.getParameter(e.MAX_VERTEX_ATTRIBS),maxVertexUniforms:e.getParameter(e.MAX_VERTEX_UNIFORM_VECTORS),maxVaryings:e.getParameter(e.MAX_VARYING_VECTORS),maxFragmentUniforms:e.getParameter(e.MAX_FRAGMENT_UNIFORM_VECTORS),vertexTextures:u>0,maxSamples:e.getParameter(e.MAX_SAMPLES)}}function Vn(e){const n=this;let i=null,r=0,a=!1,o=!1;const s=new x,l=new t,c={value:null,needsUpdate:!1};function d(e,t,i,r){const a=null!==e?e.length:0;let o=null;if(0!==a){if(o=c.value,!0!==r||null===o){const n=i+4*a,r=t.matrixWorldInverse;l.getNormalMatrix(r),(null===o||o.length0);n.numPlanes=r,n.numIntersection=0}();else{const e=o?0:r,t=4*e;let n=m.clippingState||null;c.value=n,n=d(u,s,t,l);for(let e=0;e!==t;++e)n[e]=i[e];m.clippingState=n,this.numIntersection=f?this.numPlanes:0,this.numPlanes+=e}}}function zn(e){let t=new WeakMap;function n(e,t){return t===R?e.mapping=C:t===A&&(e.mapping=L),e}function i(e){const n=e.target;n.removeEventListener("dispose",i);const r=t.get(n);void 0!==r&&(t.delete(n),r.dispose())}return{get:function(r){if(r&&r.isTexture){const a=r.mapping;if(a===R||a===A){if(t.has(r)){return n(t.get(r).texture,r.mapping)}{const a=r.image;if(a&&a.height>0){const o=new b(a.height);return o.fromEquirectangularTexture(e,r),t.set(r,o),r.addEventListener("dispose",i),n(o.texture,r.mapping)}return null}}}return r},dispose:function(){t=new WeakMap}}}const kn=[.125,.215,.35,.446,.526,.582],Wn=20,Xn=new O,Yn=new e;let jn=null,Kn=0,qn=0,Zn=!1;const $n=(1+Math.sqrt(5))/2,Qn=1/$n,Jn=[new r(-$n,Qn,0),new r($n,Qn,0),new r(-Qn,0,$n),new r(Qn,0,$n),new r(0,$n,-Qn),new r(0,$n,Qn),new r(-1,1,-1),new r(1,1,-1),new r(-1,1,1),new r(1,1,1)];class ei{constructor(e){this._renderer=e,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._lodPlanes=[],this._sizeLods=[],this._sigmas=[],this._blurMaterial=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._compileMaterial(this._blurMaterial)}fromScene(e,t=0,n=.1,i=100){jn=this._renderer.getRenderTarget(),Kn=this._renderer.getActiveCubeFace(),qn=this._renderer.getActiveMipmapLevel(),Zn=this._renderer.xr.enabled,this._renderer.xr.enabled=!1,this._setSize(256);const r=this._allocateTargets();return r.depthBuffer=!0,this._sceneToCubeUV(e,n,i,r),t>0&&this._blur(r,0,0,t),this._applyPMREM(r),this._cleanup(r),r}fromEquirectangular(e,t=null){return this._fromTexture(e,t)}fromCubemap(e,t=null){return this._fromTexture(e,t)}compileCubemapShader(){null===this._cubemapMaterial&&(this._cubemapMaterial=ri(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){null===this._equirectMaterial&&(this._equirectMaterial=ii(),this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),null!==this._cubemapMaterial&&this._cubemapMaterial.dispose(),null!==this._equirectMaterial&&this._equirectMaterial.dispose()}_setSize(e){this._lodMax=Math.floor(Math.log2(e)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){null!==this._blurMaterial&&this._blurMaterial.dispose(),null!==this._pingPongRenderTarget&&this._pingPongRenderTarget.dispose();for(let e=0;ee-4?s=kn[o-e+4-1]:0===o&&(s=0),i.push(s);const l=1/(a-2),c=-l,d=1+l,u=[c,c,d,c,d,d,c,c,d,d,c,d],f=6,p=6,m=3,h=2,_=1,g=new Float32Array(m*p*f),v=new Float32Array(h*p*f),E=new Float32Array(_*p*f);for(let e=0;e2?0:-1,i=[t,n,0,t+2/3,n,0,t+2/3,n+1,0,t,n,0,t+2/3,n+1,0,t,n+1,0];g.set(i,m*p*e),v.set(u,h*p*e);const r=[e,e,e,e,e,e];E.set(r,_*p*e)}const S=new D;S.setAttribute("position",new y(g,m)),S.setAttribute("uv",new y(v,h)),S.setAttribute("faceIndex",new y(E,_)),t.push(S),r>4&&r--}return{lodPlanes:t,sizeLods:n,sigmas:i}}(i)),this._blurMaterial=function(e,t,n){const i=new Float32Array(Wn),a=new r(0,1,0),o=new l({name:"SphericalGaussianBlur",defines:{n:Wn,CUBEUV_TEXEL_WIDTH:1/t,CUBEUV_TEXEL_HEIGHT:1/n,CUBEUV_MAX_MIP:`${e}.0`},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:i},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:a}},vertexShader:ai(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\t\t\tuniform int samples;\n\t\t\tuniform float weights[ n ];\n\t\t\tuniform bool latitudinal;\n\t\t\tuniform float dTheta;\n\t\t\tuniform float mipInt;\n\t\t\tuniform vec3 poleAxis;\n\n\t\t\t#define ENVMAP_TYPE_CUBE_UV\n\t\t\t#include \n\n\t\t\tvec3 getSample( float theta, vec3 axis ) {\n\n\t\t\t\tfloat cosTheta = cos( theta );\n\t\t\t\t// Rodrigues' axis-angle rotation\n\t\t\t\tvec3 sampleDirection = vOutputDirection * cosTheta\n\t\t\t\t\t+ cross( axis, vOutputDirection ) * sin( theta )\n\t\t\t\t\t+ axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );\n\n\t\t\t\treturn bilinearCubeUV( envMap, sampleDirection, mipInt );\n\n\t\t\t}\n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );\n\n\t\t\t\tif ( all( equal( axis, vec3( 0.0 ) ) ) ) {\n\n\t\t\t\t\taxis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );\n\n\t\t\t\t}\n\n\t\t\t\taxis = normalize( axis );\n\n\t\t\t\tgl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t\t\t\tgl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );\n\n\t\t\t\tfor ( int i = 1; i < n; i++ ) {\n\n\t\t\t\t\tif ( i >= samples ) {\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tfloat theta = dTheta * float( i );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( theta, axis );\n\n\t\t\t\t}\n\n\t\t\t}\n\t\t",blending:N,depthTest:!1,depthWrite:!1});return o}(i,e,t)}return i}_compileMaterial(e){const t=new o(this._lodPlanes[0],e);this._renderer.compile(t,Xn)}_sceneToCubeUV(e,t,n,i){const r=new P(90,1,t,n),a=[1,-1,1,1,1,1],l=[1,1,1,-1,-1,-1],c=this._renderer,u=c.autoClear,f=c.toneMapping;c.getClearColor(Yn),c.toneMapping=U,c.autoClear=!1;const p=new w({name:"PMREM.Background",side:d,depthWrite:!1,depthTest:!1}),m=new o(new s,p);let h=!1;const _=e.background;_?_.isColor&&(p.color.copy(_),e.background=null,h=!0):(p.color.copy(Yn),h=!0);for(let t=0;t<6;t++){const n=t%3;0===n?(r.up.set(0,a[t],0),r.lookAt(l[t],0,0)):1===n?(r.up.set(0,0,a[t]),r.lookAt(0,l[t],0)):(r.up.set(0,a[t],0),r.lookAt(0,0,l[t]));const o=this._cubeSize;ni(i,n*o,t>2?o:0,o,o),c.setRenderTarget(i),h&&c.render(m,r),c.render(e,r)}m.geometry.dispose(),m.material.dispose(),c.toneMapping=f,c.autoClear=u,e.background=_}_textureToCubeUV(e,t){const n=this._renderer,i=e.mapping===C||e.mapping===L;i?(null===this._cubemapMaterial&&(this._cubemapMaterial=ri()),this._cubemapMaterial.uniforms.flipEnvMap.value=!1===e.isRenderTargetTexture?-1:1):null===this._equirectMaterial&&(this._equirectMaterial=ii());const r=i?this._cubemapMaterial:this._equirectMaterial,a=new o(this._lodPlanes[0],r);r.uniforms.envMap.value=e;const s=this._cubeSize;ni(t,0,0,3*s,2*s),n.setRenderTarget(t),n.render(a,Xn)}_applyPMREM(e){const t=this._renderer,n=t.autoClear;t.autoClear=!1;const i=this._lodPlanes.length;for(let t=1;tWn&&console.warn(`sigmaRadians, ${r}, is too large and will clip, as it requested ${h} samples when the maximum is set to 20`);const _=[];let g=0;for(let e=0;ev-4?i-v+4:0),4*(this._cubeSize-E),3*E,2*E),l.setRenderTarget(t),l.render(d,Xn)}}function ti(e,t,n){const i=new I(e,t,n);return i.texture.mapping=a,i.texture.name="PMREM.cubeUv",i.scissorTest=!0,i}function ni(e,t,n,i,r){e.viewport.set(t,n,i,r),e.scissor.set(t,n,i,r)}function ii(){return new l({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null}},vertexShader:ai(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\n\t\t\t#include \n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 outputDirection = normalize( vOutputDirection );\n\t\t\t\tvec2 uv = equirectUv( outputDirection );\n\n\t\t\t\tgl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 );\n\n\t\t\t}\n\t\t",blending:N,depthTest:!1,depthWrite:!1})}function ri(){return new l({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:ai(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tuniform float flipEnvMap;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform samplerCube envMap;\n\n\t\t\tvoid main() {\n\n\t\t\t\tgl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) );\n\n\t\t\t}\n\t\t",blending:N,depthTest:!1,depthWrite:!1})}function ai(){return"\n\n\t\tprecision mediump float;\n\t\tprecision mediump int;\n\n\t\tattribute float faceIndex;\n\n\t\tvarying vec3 vOutputDirection;\n\n\t\t// RH coordinate system; PMREM face-indexing convention\n\t\tvec3 getDirection( vec2 uv, float face ) {\n\n\t\t\tuv = 2.0 * uv - 1.0;\n\n\t\t\tvec3 direction = vec3( uv, 1.0 );\n\n\t\t\tif ( face == 0.0 ) {\n\n\t\t\t\tdirection = direction.zyx; // ( 1, v, u ) pos x\n\n\t\t\t} else if ( face == 1.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xz *= -1.0; // ( -u, 1, -v ) pos y\n\n\t\t\t} else if ( face == 2.0 ) {\n\n\t\t\t\tdirection.x *= -1.0; // ( -u, v, 1 ) pos z\n\n\t\t\t} else if ( face == 3.0 ) {\n\n\t\t\t\tdirection = direction.zyx;\n\t\t\t\tdirection.xz *= -1.0; // ( -1, v, -u ) neg x\n\n\t\t\t} else if ( face == 4.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xy *= -1.0; // ( -u, -1, v ) neg y\n\n\t\t\t} else if ( face == 5.0 ) {\n\n\t\t\t\tdirection.z *= -1.0; // ( u, v, -1 ) neg z\n\n\t\t\t}\n\n\t\t\treturn direction;\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tvOutputDirection = getDirection( uv, faceIndex );\n\t\t\tgl_Position = vec4( position, 1.0 );\n\n\t\t}\n\t"}function oi(e){let t=new WeakMap,n=null;function i(e){const n=e.target;n.removeEventListener("dispose",i);const r=t.get(n);void 0!==r&&(t.delete(n),r.dispose())}return{get:function(r){if(r&&r.isTexture){const a=r.mapping,o=a===R||a===A,s=a===C||a===L;if(o||s){let a=t.get(r);const l=void 0!==a?a.texture.pmremVersion:0;if(r.isRenderTargetTexture&&r.pmremVersion!==l)return null===n&&(n=new ei(e)),a=o?n.fromEquirectangular(r,a):n.fromCubemap(r,a),a.texture.pmremVersion=r.pmremVersion,t.set(r,a),a.texture;if(void 0!==a)return a.texture;{const l=r.image;return o&&l&&l.height>0||s&&l&&function(e){let t=0;const n=6;for(let i=0;it.maxTextureSize&&(T=Math.ceil(S/t.maxTextureSize),S=t.maxTextureSize);const x=new Float32Array(S*T*4*u),R=new W(x,S,T,u);R.type=M,R.needsUpdate=!0;const A=4*E;for(let C=0;C0)return e;const r=t*n;let a=vi[r];if(void 0===a&&(a=new Float32Array(r),vi[r]=a),0!==t){i.toArray(a,0);for(let i=1,r=0;i!==t;++i)r+=n,e[i].toArray(a,r)}return a}function Ri(e,t){if(e.length!==t.length)return!1;for(let n=0,i=e.length;n":" "} ${r}: ${n[e]}`)}return i.join("\n")}(e.getShaderSource(t),i)}return r}function Mr(e,t){const n=function(e){u._getMatrix(Sr,u.workingColorSpace,e);const t=`mat3( ${Sr.elements.map((e=>e.toFixed(4)))} )`;switch(u.getTransfer(e)){case se:return[t,"LinearTransferOETF"];case f:return[t,"sRGBTransferOETF"];default:return console.warn("THREE.WebGLProgram: Unsupported color space: ",e),[t,"LinearTransferOETF"]}}(t);return[`vec4 ${e}( vec4 value ) {`,`\treturn ${n[1]}( vec4( value.rgb * ${n[0]}, value.a ) );`,"}"].join("\n")}function xr(e,t){let n;switch(t){case ie:n="Linear";break;case ne:n="Reinhard";break;case te:n="Cineon";break;case ee:n="ACESFilmic";break;case J:n="AgX";break;case Q:n="Neutral";break;case $:n="Custom";break;default:console.warn("THREE.WebGLProgram: Unsupported toneMapping:",t),n="Linear"}return"vec3 "+e+"( vec3 color ) { return "+n+"ToneMapping( color ); }"}const Rr=new r;function Ar(){u.getLuminanceCoefficients(Rr);return["float luminance( const in vec3 rgb ) {",`\tconst vec3 weights = vec3( ${Rr.x.toFixed(4)}, ${Rr.y.toFixed(4)}, ${Rr.z.toFixed(4)} );`,"\treturn dot( weights, rgb );","}"].join("\n")}function br(e){return""!==e}function Cr(e,t){const n=t.numSpotLightShadows+t.numSpotLightMaps-t.numSpotLightShadowsWithMaps;return e.replace(/NUM_DIR_LIGHTS/g,t.numDirLights).replace(/NUM_SPOT_LIGHTS/g,t.numSpotLights).replace(/NUM_SPOT_LIGHT_MAPS/g,t.numSpotLightMaps).replace(/NUM_SPOT_LIGHT_COORDS/g,n).replace(/NUM_RECT_AREA_LIGHTS/g,t.numRectAreaLights).replace(/NUM_POINT_LIGHTS/g,t.numPointLights).replace(/NUM_HEMI_LIGHTS/g,t.numHemiLights).replace(/NUM_DIR_LIGHT_SHADOWS/g,t.numDirLightShadows).replace(/NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g,t.numSpotLightShadowsWithMaps).replace(/NUM_SPOT_LIGHT_SHADOWS/g,t.numSpotLightShadows).replace(/NUM_POINT_LIGHT_SHADOWS/g,t.numPointLightShadows)}function Lr(e,t){return e.replace(/NUM_CLIPPING_PLANES/g,t.numClippingPlanes).replace(/UNION_CLIPPING_PLANES/g,t.numClippingPlanes-t.numClipIntersection)}const Pr=/^[ \t]*#include +<([\w\d./]+)>/gm;function Ur(e){return e.replace(Pr,Dr)}const wr=new Map;function Dr(e,t){let n=wn[t];if(void 0===n){const e=wr.get(t);if(void 0===e)throw new Error("Can not resolve #include <"+t+">");n=wn[e],console.warn('THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.',t,e)}return Ur(n)}const yr=/#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;function Ir(e){return e.replace(yr,Nr)}function Nr(e,t,n,i){let r="";for(let e=parseInt(t);e0&&(g+="\n"),v=["#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,h].filter(br).join("\n"),v.length>0&&(v+="\n")):(g=[Or(n),"#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,h,n.extensionClipCullDistance?"#define USE_CLIP_DISTANCE":"",n.batching?"#define USE_BATCHING":"",n.batchingColor?"#define USE_BATCHING_COLOR":"",n.instancing?"#define USE_INSTANCING":"",n.instancingColor?"#define USE_INSTANCING_COLOR":"",n.instancingMorph?"#define USE_INSTANCING_MORPH":"",n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.map?"#define USE_MAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+u:"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",n.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",n.displacementMap?"#define USE_DISPLACEMENTMAP":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.anisotropy?"#define USE_ANISOTROPY":"",n.anisotropyMap?"#define USE_ANISOTROPYMAP":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",n.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",n.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.alphaHash?"#define USE_ALPHAHASH":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",n.mapUv?"#define MAP_UV "+n.mapUv:"",n.alphaMapUv?"#define ALPHAMAP_UV "+n.alphaMapUv:"",n.lightMapUv?"#define LIGHTMAP_UV "+n.lightMapUv:"",n.aoMapUv?"#define AOMAP_UV "+n.aoMapUv:"",n.emissiveMapUv?"#define EMISSIVEMAP_UV "+n.emissiveMapUv:"",n.bumpMapUv?"#define BUMPMAP_UV "+n.bumpMapUv:"",n.normalMapUv?"#define NORMALMAP_UV "+n.normalMapUv:"",n.displacementMapUv?"#define DISPLACEMENTMAP_UV "+n.displacementMapUv:"",n.metalnessMapUv?"#define METALNESSMAP_UV "+n.metalnessMapUv:"",n.roughnessMapUv?"#define ROUGHNESSMAP_UV "+n.roughnessMapUv:"",n.anisotropyMapUv?"#define ANISOTROPYMAP_UV "+n.anisotropyMapUv:"",n.clearcoatMapUv?"#define CLEARCOATMAP_UV "+n.clearcoatMapUv:"",n.clearcoatNormalMapUv?"#define CLEARCOAT_NORMALMAP_UV "+n.clearcoatNormalMapUv:"",n.clearcoatRoughnessMapUv?"#define CLEARCOAT_ROUGHNESSMAP_UV "+n.clearcoatRoughnessMapUv:"",n.iridescenceMapUv?"#define IRIDESCENCEMAP_UV "+n.iridescenceMapUv:"",n.iridescenceThicknessMapUv?"#define IRIDESCENCE_THICKNESSMAP_UV "+n.iridescenceThicknessMapUv:"",n.sheenColorMapUv?"#define SHEEN_COLORMAP_UV "+n.sheenColorMapUv:"",n.sheenRoughnessMapUv?"#define SHEEN_ROUGHNESSMAP_UV "+n.sheenRoughnessMapUv:"",n.specularMapUv?"#define SPECULARMAP_UV "+n.specularMapUv:"",n.specularColorMapUv?"#define SPECULAR_COLORMAP_UV "+n.specularColorMapUv:"",n.specularIntensityMapUv?"#define SPECULAR_INTENSITYMAP_UV "+n.specularIntensityMapUv:"",n.transmissionMapUv?"#define TRANSMISSIONMAP_UV "+n.transmissionMapUv:"",n.thicknessMapUv?"#define THICKNESSMAP_UV "+n.thicknessMapUv:"",n.vertexTangents&&!1===n.flatShading?"#define USE_TANGENT":"",n.vertexColors?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUv1s?"#define USE_UV1":"",n.vertexUv2s?"#define USE_UV2":"",n.vertexUv3s?"#define USE_UV3":"",n.pointsUvs?"#define USE_POINTS_UV":"",n.flatShading?"#define FLAT_SHADED":"",n.skinning?"#define USE_SKINNING":"",n.morphTargets?"#define USE_MORPHTARGETS":"",n.morphNormals&&!1===n.flatShading?"#define USE_MORPHNORMALS":"",n.morphColors?"#define USE_MORPHCOLORS":"",n.morphTargetsCount>0?"#define MORPHTARGETS_TEXTURE_STRIDE "+n.morphTextureStride:"",n.morphTargetsCount>0?"#define MORPHTARGETS_COUNT "+n.morphTargetsCount:"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+c:"",n.sizeAttenuation?"#define USE_SIZEATTENUATION":"",n.numLightProbes>0?"#define USE_LIGHT_PROBES":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",n.reverseDepthBuffer?"#define USE_REVERSEDEPTHBUF":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;","#ifdef USE_INSTANCING","\tattribute mat4 instanceMatrix;","#endif","#ifdef USE_INSTANCING_COLOR","\tattribute vec3 instanceColor;","#endif","#ifdef USE_INSTANCING_MORPH","\tuniform sampler2D morphTexture;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_UV1","\tattribute vec2 uv1;","#endif","#ifdef USE_UV2","\tattribute vec2 uv2;","#endif","#ifdef USE_UV3","\tattribute vec2 uv3;","#endif","#ifdef USE_TANGENT","\tattribute vec4 tangent;","#endif","#if defined( USE_COLOR_ALPHA )","\tattribute vec4 color;","#elif defined( USE_COLOR )","\tattribute vec3 color;","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(br).join("\n"),v=[Or(n),"#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,h,n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.alphaToCoverage?"#define ALPHA_TO_COVERAGE":"",n.map?"#define USE_MAP":"",n.matcap?"#define USE_MATCAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+d:"",n.envMap?"#define "+u:"",n.envMap?"#define "+f:"",p?"#define CUBEUV_TEXEL_WIDTH "+p.texelWidth:"",p?"#define CUBEUV_TEXEL_HEIGHT "+p.texelHeight:"",p?"#define CUBEUV_MAX_MIP "+p.maxMip+".0":"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",n.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.anisotropy?"#define USE_ANISOTROPY":"",n.anisotropyMap?"#define USE_ANISOTROPYMAP":"",n.clearcoat?"#define USE_CLEARCOAT":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.dispersion?"#define USE_DISPERSION":"",n.iridescence?"#define USE_IRIDESCENCE":"",n.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",n.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",n.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.alphaTest?"#define USE_ALPHATEST":"",n.alphaHash?"#define USE_ALPHAHASH":"",n.sheen?"#define USE_SHEEN":"",n.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.vertexTangents&&!1===n.flatShading?"#define USE_TANGENT":"",n.vertexColors||n.instancingColor||n.batchingColor?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUv1s?"#define USE_UV1":"",n.vertexUv2s?"#define USE_UV2":"",n.vertexUv3s?"#define USE_UV3":"",n.pointsUvs?"#define USE_POINTS_UV":"",n.gradientMap?"#define USE_GRADIENTMAP":"",n.flatShading?"#define FLAT_SHADED":"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+c:"",n.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",n.numLightProbes>0?"#define USE_LIGHT_PROBES":"",n.decodeVideoTexture?"#define DECODE_VIDEO_TEXTURE":"",n.decodeVideoTextureEmissive?"#define DECODE_VIDEO_TEXTURE_EMISSIVE":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",n.reverseDepthBuffer?"#define USE_REVERSEDEPTHBUF":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",n.toneMapping!==U?"#define TONE_MAPPING":"",n.toneMapping!==U?wn.tonemapping_pars_fragment:"",n.toneMapping!==U?xr("toneMapping",n.toneMapping):"",n.dithering?"#define DITHERING":"",n.opaque?"#define OPAQUE":"",wn.colorspace_pars_fragment,Mr("linearToOutputTexel",n.outputColorSpace),Ar(),n.useDepthPacking?"#define DEPTH_PACKING "+n.depthPacking:"","\n"].filter(br).join("\n")),s=Ur(s),s=Cr(s,n),s=Lr(s,n),l=Ur(l),l=Cr(l,n),l=Lr(l,n),s=Ir(s),l=Ir(l),!0!==n.isRawShaderMaterial&&(E="#version 300 es\n",g=[m,"#define attribute in","#define varying out","#define texture2D texture"].join("\n")+"\n"+g,v=["#define varying in",n.glslVersion===Z?"":"layout(location = 0) out highp vec4 pc_fragColor;",n.glslVersion===Z?"":"#define gl_FragColor pc_fragColor","#define gl_FragDepthEXT gl_FragDepth","#define texture2D texture","#define textureCube texture","#define texture2DProj textureProj","#define texture2DLodEXT textureLod","#define texture2DProjLodEXT textureProjLod","#define textureCubeLodEXT textureLod","#define texture2DGradEXT textureGrad","#define texture2DProjGradEXT textureProjGrad","#define textureCubeGradEXT textureGrad"].join("\n")+"\n"+v);const S=E+g+s,T=E+v+l,M=vr(r,r.VERTEX_SHADER,S),x=vr(r,r.FRAGMENT_SHADER,T);function R(t){if(e.debug.checkShaderErrors){const n=r.getProgramInfoLog(_).trim(),i=r.getShaderInfoLog(M).trim(),a=r.getShaderInfoLog(x).trim();let o=!0,s=!0;if(!1===r.getProgramParameter(_,r.LINK_STATUS))if(o=!1,"function"==typeof e.debug.onShaderError)e.debug.onShaderError(r,_,M,x);else{const e=Tr(r,M,"vertex"),i=Tr(r,x,"fragment");console.error("THREE.WebGLProgram: Shader Error "+r.getError()+" - VALIDATE_STATUS "+r.getProgramParameter(_,r.VALIDATE_STATUS)+"\n\nMaterial Name: "+t.name+"\nMaterial Type: "+t.type+"\n\nProgram Info Log: "+n+"\n"+e+"\n"+i)}else""!==n?console.warn("THREE.WebGLProgram: Program Info Log:",n):""!==i&&""!==a||(s=!1);s&&(t.diagnostics={runnable:o,programLog:n,vertexShader:{log:i,prefix:g},fragmentShader:{log:a,prefix:v}})}r.deleteShader(M),r.deleteShader(x),A=new gr(r,_),b=function(e,t){const n={},i=e.getProgramParameter(t,e.ACTIVE_ATTRIBUTES);for(let r=0;r0,J=o.clearcoat>0,ee=o.dispersion>0,te=o.iridescence>0,ne=o.sheen>0,ie=o.transmission>0,re=Q&&!!o.anisotropyMap,ae=J&&!!o.clearcoatMap,oe=J&&!!o.clearcoatNormalMap,se=J&&!!o.clearcoatRoughnessMap,le=te&&!!o.iridescenceMap,ce=te&&!!o.iridescenceThicknessMap,de=ne&&!!o.sheenColorMap,he=ne&&!!o.sheenRoughnessMap,_e=!!o.specularMap,ge=!!o.specularColorMap,ve=!!o.specularIntensityMap,Ee=ie&&!!o.transmissionMap,Se=ie&&!!o.thicknessMap,Te=!!o.gradientMap,Me=!!o.alphaMap,xe=o.alphaTest>0,Re=!!o.alphaHash,Ae=!!o.extensions;let be=U;o.toneMapped&&(null!==O&&!0!==O.isXRRenderTarget||(be=e.toneMapping));const Ce={shaderID:C,shaderType:o.type,shaderName:o.name,vertexShader:w,fragmentShader:D,defines:o.defines,customVertexShaderID:y,customFragmentShaderID:I,isRawShaderMaterial:!0===o.isRawShaderMaterial,glslVersion:o.glslVersion,precision:g,batching:G,batchingColor:G&&null!==T._colorsTexture,instancing:H,instancingColor:H&&null!==T.instanceColor,instancingMorph:H&&null!==T.morphTexture,supportsVertexTextures:_,outputColorSpace:null===O?e.outputColorSpace:!0===O.isXRRenderTarget?O.texture.colorSpace:B,alphaToCoverage:!!o.alphaToCoverage,map:V,matcap:z,envMap:k,envMapMode:k&&A.mapping,envMapCubeUVHeight:b,aoMap:W,lightMap:X,bumpMap:Y,normalMap:j,displacementMap:_&&K,emissiveMap:q,normalMapObjectSpace:j&&o.normalMapType===ue,normalMapTangentSpace:j&&o.normalMapType===fe,metalnessMap:Z,roughnessMap:$,anisotropy:Q,anisotropyMap:re,clearcoat:J,clearcoatMap:ae,clearcoatNormalMap:oe,clearcoatRoughnessMap:se,dispersion:ee,iridescence:te,iridescenceMap:le,iridescenceThicknessMap:ce,sheen:ne,sheenColorMap:de,sheenRoughnessMap:he,specularMap:_e,specularColorMap:ge,specularIntensityMap:ve,transmission:ie,transmissionMap:Ee,thicknessMap:Se,gradientMap:Te,opaque:!1===o.transparent&&o.blending===pe&&!1===o.alphaToCoverage,alphaMap:Me,alphaTest:xe,alphaHash:Re,combine:o.combine,mapUv:V&&E(o.map.channel),aoMapUv:W&&E(o.aoMap.channel),lightMapUv:X&&E(o.lightMap.channel),bumpMapUv:Y&&E(o.bumpMap.channel),normalMapUv:j&&E(o.normalMap.channel),displacementMapUv:K&&E(o.displacementMap.channel),emissiveMapUv:q&&E(o.emissiveMap.channel),metalnessMapUv:Z&&E(o.metalnessMap.channel),roughnessMapUv:$&&E(o.roughnessMap.channel),anisotropyMapUv:re&&E(o.anisotropyMap.channel),clearcoatMapUv:ae&&E(o.clearcoatMap.channel),clearcoatNormalMapUv:oe&&E(o.clearcoatNormalMap.channel),clearcoatRoughnessMapUv:se&&E(o.clearcoatRoughnessMap.channel),iridescenceMapUv:le&&E(o.iridescenceMap.channel),iridescenceThicknessMapUv:ce&&E(o.iridescenceThicknessMap.channel),sheenColorMapUv:de&&E(o.sheenColorMap.channel),sheenRoughnessMapUv:he&&E(o.sheenRoughnessMap.channel),specularMapUv:_e&&E(o.specularMap.channel),specularColorMapUv:ge&&E(o.specularColorMap.channel),specularIntensityMapUv:ve&&E(o.specularIntensityMap.channel),transmissionMapUv:Ee&&E(o.transmissionMap.channel),thicknessMapUv:Se&&E(o.thicknessMap.channel),alphaMapUv:Me&&E(o.alphaMap.channel),vertexTangents:!!x.attributes.tangent&&(j||Q),vertexColors:o.vertexColors,vertexAlphas:!0===o.vertexColors&&!!x.attributes.color&&4===x.attributes.color.itemSize,pointsUvs:!0===T.isPoints&&!!x.attributes.uv&&(V||Me),fog:!!M,useFog:!0===o.fog,fogExp2:!!M&&M.isFogExp2,flatShading:!0===o.flatShading,sizeAttenuation:!0===o.sizeAttenuation,logarithmicDepthBuffer:h,reverseDepthBuffer:F,skinning:!0===T.isSkinnedMesh,morphTargets:void 0!==x.morphAttributes.position,morphNormals:void 0!==x.morphAttributes.normal,morphColors:void 0!==x.morphAttributes.color,morphTargetsCount:P,morphTextureStride:N,numDirLights:l.directional.length,numPointLights:l.point.length,numSpotLights:l.spot.length,numSpotLightMaps:l.spotLightMap.length,numRectAreaLights:l.rectArea.length,numHemiLights:l.hemi.length,numDirLightShadows:l.directionalShadowMap.length,numPointLightShadows:l.pointShadowMap.length,numSpotLightShadows:l.spotShadowMap.length,numSpotLightShadowsWithMaps:l.numSpotLightShadowsWithMaps,numLightProbes:l.numLightProbes,numClippingPlanes:s.numPlanes,numClipIntersection:s.numIntersection,dithering:o.dithering,shadowMapEnabled:e.shadowMap.enabled&&m.length>0,shadowMapType:e.shadowMap.type,toneMapping:be,decodeVideoTexture:V&&!0===o.map.isVideoTexture&&u.getTransfer(o.map.colorSpace)===f,decodeVideoTextureEmissive:q&&!0===o.emissiveMap.isVideoTexture&&u.getTransfer(o.emissiveMap.colorSpace)===f,premultipliedAlpha:o.premultipliedAlpha,doubleSided:o.side===me,flipSided:o.side===d,useDepthPacking:o.depthPacking>=0,depthPacking:o.depthPacking||0,index0AttributeName:o.index0AttributeName,extensionClipCullDistance:Ae&&!0===o.extensions.clipCullDistance&&i.has("WEBGL_clip_cull_distance"),extensionMultiDraw:(Ae&&!0===o.extensions.multiDraw||G)&&i.has("WEBGL_multi_draw"),rendererExtensionParallelShaderCompile:i.has("KHR_parallel_shader_compile"),customProgramCacheKey:o.customProgramCacheKey()};return Ce.vertexUv1s=p.has(1),Ce.vertexUv2s=p.has(2),Ce.vertexUv3s=p.has(3),p.clear(),Ce},getProgramCacheKey:function(t){const n=[];if(t.shaderID?n.push(t.shaderID):(n.push(t.customVertexShaderID),n.push(t.customFragmentShaderID)),void 0!==t.defines)for(const e in t.defines)n.push(e),n.push(t.defines[e]);return!1===t.isRawShaderMaterial&&(!function(e,t){e.push(t.precision),e.push(t.outputColorSpace),e.push(t.envMapMode),e.push(t.envMapCubeUVHeight),e.push(t.mapUv),e.push(t.alphaMapUv),e.push(t.lightMapUv),e.push(t.aoMapUv),e.push(t.bumpMapUv),e.push(t.normalMapUv),e.push(t.displacementMapUv),e.push(t.emissiveMapUv),e.push(t.metalnessMapUv),e.push(t.roughnessMapUv),e.push(t.anisotropyMapUv),e.push(t.clearcoatMapUv),e.push(t.clearcoatNormalMapUv),e.push(t.clearcoatRoughnessMapUv),e.push(t.iridescenceMapUv),e.push(t.iridescenceThicknessMapUv),e.push(t.sheenColorMapUv),e.push(t.sheenRoughnessMapUv),e.push(t.specularMapUv),e.push(t.specularColorMapUv),e.push(t.specularIntensityMapUv),e.push(t.transmissionMapUv),e.push(t.thicknessMapUv),e.push(t.combine),e.push(t.fogExp2),e.push(t.sizeAttenuation),e.push(t.morphTargetsCount),e.push(t.morphAttributeCount),e.push(t.numDirLights),e.push(t.numPointLights),e.push(t.numSpotLights),e.push(t.numSpotLightMaps),e.push(t.numHemiLights),e.push(t.numRectAreaLights),e.push(t.numDirLightShadows),e.push(t.numPointLightShadows),e.push(t.numSpotLightShadows),e.push(t.numSpotLightShadowsWithMaps),e.push(t.numLightProbes),e.push(t.shadowMapType),e.push(t.toneMapping),e.push(t.numClippingPlanes),e.push(t.numClipIntersection),e.push(t.depthPacking)}(n,t),function(e,t){l.disableAll(),t.supportsVertexTextures&&l.enable(0);t.instancing&&l.enable(1);t.instancingColor&&l.enable(2);t.instancingMorph&&l.enable(3);t.matcap&&l.enable(4);t.envMap&&l.enable(5);t.normalMapObjectSpace&&l.enable(6);t.normalMapTangentSpace&&l.enable(7);t.clearcoat&&l.enable(8);t.iridescence&&l.enable(9);t.alphaTest&&l.enable(10);t.vertexColors&&l.enable(11);t.vertexAlphas&&l.enable(12);t.vertexUv1s&&l.enable(13);t.vertexUv2s&&l.enable(14);t.vertexUv3s&&l.enable(15);t.vertexTangents&&l.enable(16);t.anisotropy&&l.enable(17);t.alphaHash&&l.enable(18);t.batching&&l.enable(19);t.dispersion&&l.enable(20);t.batchingColor&&l.enable(21);e.push(l.mask),l.disableAll(),t.fog&&l.enable(0);t.useFog&&l.enable(1);t.flatShading&&l.enable(2);t.logarithmicDepthBuffer&&l.enable(3);t.reverseDepthBuffer&&l.enable(4);t.skinning&&l.enable(5);t.morphTargets&&l.enable(6);t.morphNormals&&l.enable(7);t.morphColors&&l.enable(8);t.premultipliedAlpha&&l.enable(9);t.shadowMapEnabled&&l.enable(10);t.doubleSided&&l.enable(11);t.flipSided&&l.enable(12);t.useDepthPacking&&l.enable(13);t.dithering&&l.enable(14);t.transmission&&l.enable(15);t.sheen&&l.enable(16);t.opaque&&l.enable(17);t.pointsUvs&&l.enable(18);t.decodeVideoTexture&&l.enable(19);t.decodeVideoTextureEmissive&&l.enable(20);t.alphaToCoverage&&l.enable(21);e.push(l.mask)}(n,t),n.push(e.outputColorSpace)),n.push(t.customProgramCacheKey),n.join()},getUniforms:function(e){const t=v[e.type];let n;if(t){const e=yn[t];n=he.clone(e.uniforms)}else n=e.uniforms;return n},acquireProgram:function(t,n){let i;for(let e=0,t=m.length;e0?i.push(d):!0===o.transparent?r.push(d):n.push(d)},unshift:function(e,t,o,s,l,c){const d=a(e,t,o,s,l,c);o.transmission>0?i.unshift(d):!0===o.transparent?r.unshift(d):n.unshift(d)},finish:function(){for(let n=t,i=e.length;n1&&n.sort(e||kr),i.length>1&&i.sort(t||Wr),r.length>1&&r.sort(t||Wr)}}}function Yr(){let e=new WeakMap;return{get:function(t,n){const i=e.get(t);let r;return void 0===i?(r=new Xr,e.set(t,[r])):n>=i.length?(r=new Xr,i.push(r)):r=i[n],r},dispose:function(){e=new WeakMap}}}function jr(){const t={};return{get:function(n){if(void 0!==t[n.id])return t[n.id];let i;switch(n.type){case"DirectionalLight":i={direction:new r,color:new e};break;case"SpotLight":i={position:new r,direction:new r,color:new e,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":i={position:new r,color:new e,distance:0,decay:0};break;case"HemisphereLight":i={direction:new r,skyColor:new e,groundColor:new e};break;case"RectAreaLight":i={color:new e,position:new r,halfWidth:new r,halfHeight:new r}}return t[n.id]=i,i}}}let Kr=0;function qr(e,t){return(t.castShadow?2:0)-(e.castShadow?2:0)+(t.map?1:0)-(e.map?1:0)}function Zr(e){const t=new jr,i=function(){const e={};return{get:function(t){if(void 0!==e[t.id])return e[t.id];let i;switch(t.type){case"DirectionalLight":case"SpotLight":i={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new n};break;case"PointLight":i={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new n,shadowCameraNear:1,shadowCameraFar:1e3}}return e[t.id]=i,i}}}(),a={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1,numSpotMaps:-1,numLightProbes:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotLightMap:[],spotShadow:[],spotShadowMap:[],spotLightMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[],numSpotLightShadowsWithMaps:0,numLightProbes:0};for(let e=0;e<9;e++)a.probe.push(new r);const o=new r,s=new g,l=new g;return{setup:function(n){let r=0,o=0,s=0;for(let e=0;e<9;e++)a.probe[e].set(0,0,0);let l=0,c=0,d=0,u=0,f=0,p=0,m=0,h=0,_=0,g=0,v=0;n.sort(qr);for(let e=0,E=n.length;e0&&(!0===e.has("OES_texture_float_linear")?(a.rectAreaLTC1=Dn.LTC_FLOAT_1,a.rectAreaLTC2=Dn.LTC_FLOAT_2):(a.rectAreaLTC1=Dn.LTC_HALF_1,a.rectAreaLTC2=Dn.LTC_HALF_2)),a.ambient[0]=r,a.ambient[1]=o,a.ambient[2]=s;const E=a.hash;E.directionalLength===l&&E.pointLength===c&&E.spotLength===d&&E.rectAreaLength===u&&E.hemiLength===f&&E.numDirectionalShadows===p&&E.numPointShadows===m&&E.numSpotShadows===h&&E.numSpotMaps===_&&E.numLightProbes===v||(a.directional.length=l,a.spot.length=d,a.rectArea.length=u,a.point.length=c,a.hemi.length=f,a.directionalShadow.length=p,a.directionalShadowMap.length=p,a.pointShadow.length=m,a.pointShadowMap.length=m,a.spotShadow.length=h,a.spotShadowMap.length=h,a.directionalShadowMatrix.length=p,a.pointShadowMatrix.length=m,a.spotLightMatrix.length=h+_-g,a.spotLightMap.length=_,a.numSpotLightShadowsWithMaps=g,a.numLightProbes=v,E.directionalLength=l,E.pointLength=c,E.spotLength=d,E.rectAreaLength=u,E.hemiLength=f,E.numDirectionalShadows=p,E.numPointShadows=m,E.numSpotShadows=h,E.numSpotMaps=_,E.numLightProbes=v,a.version=Kr++)},setupView:function(e,t){let n=0,i=0,r=0,c=0,d=0;const u=t.matrixWorldInverse;for(let t=0,f=e.length;t=r.length?(a=new $r(e),r.push(a)):a=r[i],a},dispose:function(){t=new WeakMap}}}function Jr(e,t,i){let r=new ge;const a=new n,s=new n,c=new k,u=new ve({depthPacking:Ee}),f=new Se,p={},h=i.maxTextureSize,_={[m]:d,[d]:m,[me]:me},g=new l({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new n},radius:{value:4}},vertexShader:"void main() {\n\tgl_Position = vec4( position, 1.0 );\n}",fragmentShader:"uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include \nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"}),v=g.clone();v.defines.HORIZONTAL_PASS=1;const E=new D;E.setAttribute("position",new y(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const S=new o(E,g),T=this;this.enabled=!1,this.autoUpdate=!0,this.needsUpdate=!1,this.type=re;let M=this.type;function x(n,i){const r=t.update(S);g.defines.VSM_SAMPLES!==n.blurSamples&&(g.defines.VSM_SAMPLES=n.blurSamples,v.defines.VSM_SAMPLES=n.blurSamples,g.needsUpdate=!0,v.needsUpdate=!0),null===n.mapPass&&(n.mapPass=new I(a.x,a.y)),g.uniforms.shadow_pass.value=n.map.texture,g.uniforms.resolution.value=n.mapSize,g.uniforms.radius.value=n.radius,e.setRenderTarget(n.mapPass),e.clear(),e.renderBufferDirect(i,null,r,g,S,null),v.uniforms.shadow_pass.value=n.mapPass.texture,v.uniforms.resolution.value=n.mapSize,v.uniforms.radius.value=n.radius,e.setRenderTarget(n.map),e.clear(),e.renderBufferDirect(i,null,r,v,S,null)}function R(t,n,i,r){let a=null;const o=!0===i.isPointLight?t.customDistanceMaterial:t.customDepthMaterial;if(void 0!==o)a=o;else if(a=!0===i.isPointLight?f:u,e.localClippingEnabled&&!0===n.clipShadows&&Array.isArray(n.clippingPlanes)&&0!==n.clippingPlanes.length||n.displacementMap&&0!==n.displacementScale||n.alphaMap&&n.alphaTest>0||n.map&&n.alphaTest>0){const e=a.uuid,t=n.uuid;let i=p[e];void 0===i&&(i={},p[e]=i);let r=i[t];void 0===r&&(r=a.clone(),i[t]=r,n.addEventListener("dispose",b)),a=r}if(a.visible=n.visible,a.wireframe=n.wireframe,a.side=r===oe?null!==n.shadowSide?n.shadowSide:n.side:null!==n.shadowSide?n.shadowSide:_[n.side],a.alphaMap=n.alphaMap,a.alphaTest=n.alphaTest,a.map=n.map,a.clipShadows=n.clipShadows,a.clippingPlanes=n.clippingPlanes,a.clipIntersection=n.clipIntersection,a.displacementMap=n.displacementMap,a.displacementScale=n.displacementScale,a.displacementBias=n.displacementBias,a.wireframeLinewidth=n.wireframeLinewidth,a.linewidth=n.linewidth,!0===i.isPointLight&&!0===a.isMeshDistanceMaterial){e.properties.get(a).light=i}return a}function A(n,i,a,o,s){if(!1===n.visible)return;if(n.layers.test(i.layers)&&(n.isMesh||n.isLine||n.isPoints)&&(n.castShadow||n.receiveShadow&&s===oe)&&(!n.frustumCulled||r.intersectsObject(n))){n.modelViewMatrix.multiplyMatrices(a.matrixWorldInverse,n.matrixWorld);const r=t.update(n),l=n.material;if(Array.isArray(l)){const t=r.groups;for(let c=0,d=t.length;ch||a.y>h)&&(a.x>h&&(s.x=Math.floor(h/m.x),a.x=s.x*m.x,d.mapSize.x=s.x),a.y>h&&(s.y=Math.floor(h/m.y),a.y=s.y*m.y,d.mapSize.y=s.y)),null===d.map||!0===f||!0===p){const e=this.type!==oe?{minFilter:Te,magFilter:Te}:{};null!==d.map&&d.map.dispose(),d.map=new I(a.x,a.y,e),d.map.texture.name=l.name+".shadowMap",d.camera.updateProjectionMatrix()}e.setRenderTarget(d.map),e.clear();const _=d.getViewportCount();for(let e=0;e<_;e++){const t=d.getViewport(e);c.set(s.x*t.x,s.y*t.y,s.x*t.z,s.y*t.w),u.viewport(c),d.updateMatrices(l,e),r=d.getFrustum(),A(n,i,d.camera,l,this.type)}!0!==d.isPointLightShadow&&this.type===oe&&x(d,i),d.needsUpdate=!1}M=this.type,T.needsUpdate=!1,e.setRenderTarget(o,l,d)}}const ea={[et]:Je,[Qe]:qe,[$e]:Ke,[Me]:Ze,[Je]:et,[qe]:Qe,[Ke]:$e,[Ze]:Me};function ta(t,n){const i=new function(){let e=!1;const n=new k;let i=null;const r=new k(0,0,0,0);return{setMask:function(n){i===n||e||(t.colorMask(n,n,n,n),i=n)},setLocked:function(t){e=t},setClear:function(e,i,a,o,s){!0===s&&(e*=o,i*=o,a*=o),n.set(e,i,a,o),!1===r.equals(n)&&(t.clearColor(e,i,a,o),r.copy(n))},reset:function(){e=!1,i=null,r.set(-1,0,0,0)}}},r=new function(){let e=!1,i=!1,r=null,a=null,o=null;return{setReversed:function(e){if(i!==e){const e=n.get("EXT_clip_control");i?e.clipControlEXT(e.LOWER_LEFT_EXT,e.ZERO_TO_ONE_EXT):e.clipControlEXT(e.LOWER_LEFT_EXT,e.NEGATIVE_ONE_TO_ONE_EXT);const t=o;o=null,this.setClear(t)}i=e},getReversed:function(){return i},setTest:function(e){e?W(t.DEPTH_TEST):X(t.DEPTH_TEST)},setMask:function(n){r===n||e||(t.depthMask(n),r=n)},setFunc:function(e){if(i&&(e=ea[e]),a!==e){switch(e){case et:t.depthFunc(t.NEVER);break;case Je:t.depthFunc(t.ALWAYS);break;case Qe:t.depthFunc(t.LESS);break;case Me:t.depthFunc(t.LEQUAL);break;case $e:t.depthFunc(t.EQUAL);break;case Ze:t.depthFunc(t.GEQUAL);break;case qe:t.depthFunc(t.GREATER);break;case Ke:t.depthFunc(t.NOTEQUAL);break;default:t.depthFunc(t.LEQUAL)}a=e}},setLocked:function(t){e=t},setClear:function(e){o!==e&&(i&&(e=1-e),t.clearDepth(e),o=e)},reset:function(){e=!1,r=null,a=null,o=null,i=!1}}},a=new function(){let e=!1,n=null,i=null,r=null,a=null,o=null,s=null,l=null,c=null;return{setTest:function(n){e||(n?W(t.STENCIL_TEST):X(t.STENCIL_TEST))},setMask:function(i){n===i||e||(t.stencilMask(i),n=i)},setFunc:function(e,n,o){i===e&&r===n&&a===o||(t.stencilFunc(e,n,o),i=e,r=n,a=o)},setOp:function(e,n,i){o===e&&s===n&&l===i||(t.stencilOp(e,n,i),o=e,s=n,l=i)},setLocked:function(t){e=t},setClear:function(e){c!==e&&(t.clearStencil(e),c=e)},reset:function(){e=!1,n=null,i=null,r=null,a=null,o=null,s=null,l=null,c=null}}},o=new WeakMap,s=new WeakMap;let l={},c={},u=new WeakMap,f=[],p=null,m=!1,h=null,_=null,g=null,v=null,E=null,S=null,T=null,M=new e(0,0,0),x=0,R=!1,A=null,b=null,C=null,L=null,P=null;const U=t.getParameter(t.MAX_COMBINED_TEXTURE_IMAGE_UNITS);let w=!1,D=0;const y=t.getParameter(t.VERSION);-1!==y.indexOf("WebGL")?(D=parseFloat(/^WebGL (\d)/.exec(y)[1]),w=D>=1):-1!==y.indexOf("OpenGL ES")&&(D=parseFloat(/^OpenGL ES (\d)/.exec(y)[1]),w=D>=2);let I=null,O={};const F=t.getParameter(t.SCISSOR_BOX),B=t.getParameter(t.VIEWPORT),H=(new k).fromArray(F),G=(new k).fromArray(B);function V(e,n,i,r){const a=new Uint8Array(4),o=t.createTexture();t.bindTexture(e,o),t.texParameteri(e,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(e,t.TEXTURE_MAG_FILTER,t.NEAREST);for(let o=0;on||r.height>n)&&(i=n/Math.max(r.width,r.height)),i<1){if("undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&e instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap||"undefined"!=typeof VideoFrame&&e instanceof VideoFrame){const n=Math.floor(i*r.width),a=Math.floor(i*r.height);void 0===m&&(m=g(n,a));const o=t?g(n,a):m;o.width=n,o.height=a;return o.getContext("2d").drawImage(e,0,0,n,a),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+r.width+"x"+r.height+") to ("+n+"x"+a+")."),o}return"data"in e&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+r.width+"x"+r.height+")."),e}return e}function S(e){return e.generateMipmaps}function x(t){e.generateMipmap(t)}function R(t){return t.isWebGLCubeRenderTarget?e.TEXTURE_CUBE_MAP:t.isWebGL3DRenderTarget?e.TEXTURE_3D:t.isWebGLArrayRenderTarget||t.isCompressedArrayTexture?e.TEXTURE_2D_ARRAY:e.TEXTURE_2D}function A(n,i,r,a,o=!1){if(null!==n){if(void 0!==e[n])return e[n];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+n+"'")}let s=i;if(i===e.RED&&(r===e.FLOAT&&(s=e.R32F),r===e.HALF_FLOAT&&(s=e.R16F),r===e.UNSIGNED_BYTE&&(s=e.R8)),i===e.RED_INTEGER&&(r===e.UNSIGNED_BYTE&&(s=e.R8UI),r===e.UNSIGNED_SHORT&&(s=e.R16UI),r===e.UNSIGNED_INT&&(s=e.R32UI),r===e.BYTE&&(s=e.R8I),r===e.SHORT&&(s=e.R16I),r===e.INT&&(s=e.R32I)),i===e.RG&&(r===e.FLOAT&&(s=e.RG32F),r===e.HALF_FLOAT&&(s=e.RG16F),r===e.UNSIGNED_BYTE&&(s=e.RG8)),i===e.RG_INTEGER&&(r===e.UNSIGNED_BYTE&&(s=e.RG8UI),r===e.UNSIGNED_SHORT&&(s=e.RG16UI),r===e.UNSIGNED_INT&&(s=e.RG32UI),r===e.BYTE&&(s=e.RG8I),r===e.SHORT&&(s=e.RG16I),r===e.INT&&(s=e.RG32I)),i===e.RGB_INTEGER&&(r===e.UNSIGNED_BYTE&&(s=e.RGB8UI),r===e.UNSIGNED_SHORT&&(s=e.RGB16UI),r===e.UNSIGNED_INT&&(s=e.RGB32UI),r===e.BYTE&&(s=e.RGB8I),r===e.SHORT&&(s=e.RGB16I),r===e.INT&&(s=e.RGB32I)),i===e.RGBA_INTEGER&&(r===e.UNSIGNED_BYTE&&(s=e.RGBA8UI),r===e.UNSIGNED_SHORT&&(s=e.RGBA16UI),r===e.UNSIGNED_INT&&(s=e.RGBA32UI),r===e.BYTE&&(s=e.RGBA8I),r===e.SHORT&&(s=e.RGBA16I),r===e.INT&&(s=e.RGBA32I)),i===e.RGB&&r===e.UNSIGNED_INT_5_9_9_9_REV&&(s=e.RGB9_E5),i===e.RGBA){const t=o?se:u.getTransfer(a);r===e.FLOAT&&(s=e.RGBA32F),r===e.HALF_FLOAT&&(s=e.RGBA16F),r===e.UNSIGNED_BYTE&&(s=t===f?e.SRGB8_ALPHA8:e.RGBA8),r===e.UNSIGNED_SHORT_4_4_4_4&&(s=e.RGBA4),r===e.UNSIGNED_SHORT_5_5_5_1&&(s=e.RGB5_A1)}return s!==e.R16F&&s!==e.R32F&&s!==e.RG16F&&s!==e.RG32F&&s!==e.RGBA16F&&s!==e.RGBA32F||t.get("EXT_color_buffer_float"),s}function b(t,n){let i;return t?null===n||n===St||n===Tt?i=e.DEPTH24_STENCIL8:n===M?i=e.DEPTH32F_STENCIL8:n===Mt&&(i=e.DEPTH24_STENCIL8,console.warn("DepthTexture: 16 bit depth attachment is not supported with stencil. Using 24-bit attachment.")):null===n||n===St||n===Tt?i=e.DEPTH_COMPONENT24:n===M?i=e.DEPTH_COMPONENT32F:n===Mt&&(i=e.DEPTH_COMPONENT16),i}function C(e,t){return!0===S(e)||e.isFramebufferTexture&&e.minFilter!==Te&&e.minFilter!==F?Math.log2(Math.max(t.width,t.height))+1:void 0!==e.mipmaps&&e.mipmaps.length>0?e.mipmaps.length:e.isCompressedTexture&&Array.isArray(e.image)?t.mipmaps.length:1}function L(e){const t=e.target;t.removeEventListener("dispose",L),function(e){const t=r.get(e);if(void 0===t.__webglInit)return;const n=e.source,i=h.get(n);if(i){const r=i[t.__cacheKey];r.usedTimes--,0===r.usedTimes&&U(e),0===Object.keys(i).length&&h.delete(n)}r.remove(e)}(t),t.isVideoTexture&&p.delete(t)}function P(t){const n=t.target;n.removeEventListener("dispose",P),function(t){const n=r.get(t);t.depthTexture&&(t.depthTexture.dispose(),r.remove(t.depthTexture));if(t.isWebGLCubeRenderTarget)for(let t=0;t<6;t++){if(Array.isArray(n.__webglFramebuffer[t]))for(let i=0;i0&&a.__version!==t.version){const e=t.image;if(null===e)console.warn("THREE.WebGLRenderer: Texture marked for update but no image data found.");else{if(!1!==e.complete)return void G(a,t,n);console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete")}}i.bindTexture(e.TEXTURE_2D,a.__webglTexture,e.TEXTURE0+n)}const y={[it]:e.REPEAT,[rt]:e.CLAMP_TO_EDGE,[at]:e.MIRRORED_REPEAT},I={[Te]:e.NEAREST,[ot]:e.NEAREST_MIPMAP_NEAREST,[st]:e.NEAREST_MIPMAP_LINEAR,[F]:e.LINEAR,[lt]:e.LINEAR_MIPMAP_NEAREST,[ct]:e.LINEAR_MIPMAP_LINEAR},N={[dt]:e.NEVER,[ut]:e.ALWAYS,[ft]:e.LESS,[X]:e.LEQUAL,[pt]:e.EQUAL,[mt]:e.GEQUAL,[ht]:e.GREATER,[_t]:e.NOTEQUAL};function O(n,i){if(i.type!==M||!1!==t.has("OES_texture_float_linear")||i.magFilter!==F&&i.magFilter!==lt&&i.magFilter!==st&&i.magFilter!==ct&&i.minFilter!==F&&i.minFilter!==lt&&i.minFilter!==st&&i.minFilter!==ct||console.warn("THREE.WebGLRenderer: Unable to use linear filtering with floating point textures. OES_texture_float_linear not supported on this device."),e.texParameteri(n,e.TEXTURE_WRAP_S,y[i.wrapS]),e.texParameteri(n,e.TEXTURE_WRAP_T,y[i.wrapT]),n!==e.TEXTURE_3D&&n!==e.TEXTURE_2D_ARRAY||e.texParameteri(n,e.TEXTURE_WRAP_R,y[i.wrapR]),e.texParameteri(n,e.TEXTURE_MAG_FILTER,I[i.magFilter]),e.texParameteri(n,e.TEXTURE_MIN_FILTER,I[i.minFilter]),i.compareFunction&&(e.texParameteri(n,e.TEXTURE_COMPARE_MODE,e.COMPARE_REF_TO_TEXTURE),e.texParameteri(n,e.TEXTURE_COMPARE_FUNC,N[i.compareFunction])),!0===t.has("EXT_texture_filter_anisotropic")){if(i.magFilter===Te)return;if(i.minFilter!==st&&i.minFilter!==ct)return;if(i.type===M&&!1===t.has("OES_texture_float_linear"))return;if(i.anisotropy>1||r.get(i).__currentAnisotropy){const o=t.get("EXT_texture_filter_anisotropic");e.texParameterf(n,o.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(i.anisotropy,a.getMaxAnisotropy())),r.get(i).__currentAnisotropy=i.anisotropy}}}function H(t,n){let i=!1;void 0===t.__webglInit&&(t.__webglInit=!0,n.addEventListener("dispose",L));const r=n.source;let a=h.get(r);void 0===a&&(a={},h.set(r,a));const o=function(e){const t=[];return t.push(e.wrapS),t.push(e.wrapT),t.push(e.wrapR||0),t.push(e.magFilter),t.push(e.minFilter),t.push(e.anisotropy),t.push(e.internalFormat),t.push(e.format),t.push(e.type),t.push(e.generateMipmaps),t.push(e.premultiplyAlpha),t.push(e.flipY),t.push(e.unpackAlignment),t.push(e.colorSpace),t.join()}(n);if(o!==t.__cacheKey){void 0===a[o]&&(a[o]={texture:e.createTexture(),usedTimes:0},s.memory.textures++,i=!0),a[o].usedTimes++;const r=a[t.__cacheKey];void 0!==r&&(a[t.__cacheKey].usedTimes--,0===r.usedTimes&&U(n)),t.__cacheKey=o,t.__webglTexture=a[o].texture}return i}function G(t,n,s){let l=e.TEXTURE_2D;(n.isDataArrayTexture||n.isCompressedArrayTexture)&&(l=e.TEXTURE_2D_ARRAY),n.isData3DTexture&&(l=e.TEXTURE_3D);const c=H(t,n),d=n.source;i.bindTexture(l,t.__webglTexture,e.TEXTURE0+s);const f=r.get(d);if(d.version!==f.__version||!0===c){i.activeTexture(e.TEXTURE0+s);const t=u.getPrimaries(u.workingColorSpace),r=n.colorSpace===gt?null:u.getPrimaries(n.colorSpace),p=n.colorSpace===gt||t===r?e.NONE:e.BROWSER_DEFAULT_WEBGL;e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,n.flipY),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,n.premultiplyAlpha),e.pixelStorei(e.UNPACK_ALIGNMENT,n.unpackAlignment),e.pixelStorei(e.UNPACK_COLORSPACE_CONVERSION_WEBGL,p);let m=v(n.image,!1,a.maxTextureSize);m=q(n,m);const h=o.convert(n.format,n.colorSpace),_=o.convert(n.type);let g,T=A(n.internalFormat,h,_,n.colorSpace,n.isVideoTexture);O(l,n);const M=n.mipmaps,R=!0!==n.isVideoTexture,L=void 0===f.__version||!0===c,P=d.dataReady,U=C(n,m);if(n.isDepthTexture)T=b(n.format===vt,n.type),L&&(R?i.texStorage2D(e.TEXTURE_2D,1,T,m.width,m.height):i.texImage2D(e.TEXTURE_2D,0,T,m.width,m.height,0,h,_,null));else if(n.isDataTexture)if(M.length>0){R&&L&&i.texStorage2D(e.TEXTURE_2D,U,T,M[0].width,M[0].height);for(let t=0,n=M.length;t0){const r=Et(g.width,g.height,n.format,n.type);for(const a of n.layerUpdates){const n=g.data.subarray(a*r/g.data.BYTES_PER_ELEMENT,(a+1)*r/g.data.BYTES_PER_ELEMENT);i.compressedTexSubImage3D(e.TEXTURE_2D_ARRAY,t,0,0,a,g.width,g.height,1,h,n)}n.clearLayerUpdates()}else i.compressedTexSubImage3D(e.TEXTURE_2D_ARRAY,t,0,0,0,g.width,g.height,m.depth,h,g.data)}else i.compressedTexImage3D(e.TEXTURE_2D_ARRAY,t,T,g.width,g.height,m.depth,0,g.data,0,0);else console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()");else R?P&&i.texSubImage3D(e.TEXTURE_2D_ARRAY,t,0,0,0,g.width,g.height,m.depth,h,_,g.data):i.texImage3D(e.TEXTURE_2D_ARRAY,t,T,g.width,g.height,m.depth,0,h,_,g.data)}else{R&&L&&i.texStorage2D(e.TEXTURE_2D,U,T,M[0].width,M[0].height);for(let t=0,r=M.length;t0){const t=Et(m.width,m.height,n.format,n.type);for(const r of n.layerUpdates){const n=m.data.subarray(r*t/m.data.BYTES_PER_ELEMENT,(r+1)*t/m.data.BYTES_PER_ELEMENT);i.texSubImage3D(e.TEXTURE_2D_ARRAY,0,0,0,r,m.width,m.height,1,h,_,n)}n.clearLayerUpdates()}else i.texSubImage3D(e.TEXTURE_2D_ARRAY,0,0,0,0,m.width,m.height,m.depth,h,_,m.data)}else i.texImage3D(e.TEXTURE_2D_ARRAY,0,T,m.width,m.height,m.depth,0,h,_,m.data);else if(n.isData3DTexture)R?(L&&i.texStorage3D(e.TEXTURE_3D,U,T,m.width,m.height,m.depth),P&&i.texSubImage3D(e.TEXTURE_3D,0,0,0,0,m.width,m.height,m.depth,h,_,m.data)):i.texImage3D(e.TEXTURE_3D,0,T,m.width,m.height,m.depth,0,h,_,m.data);else if(n.isFramebufferTexture){if(L)if(R)i.texStorage2D(e.TEXTURE_2D,U,T,m.width,m.height);else{let t=m.width,n=m.height;for(let r=0;r>=1,n>>=1}}else if(M.length>0){if(R&&L){const t=Z(M[0]);i.texStorage2D(e.TEXTURE_2D,U,T,t.width,t.height)}for(let t=0,n=M.length;t>d),r=Math.max(1,n.height>>d);c===e.TEXTURE_3D||c===e.TEXTURE_2D_ARRAY?i.texImage3D(c,d,p,t,r,n.depth,0,u,f,null):i.texImage2D(c,d,p,t,r,0,u,f,null)}i.bindFramebuffer(e.FRAMEBUFFER,t),K(n)?l.framebufferTexture2DMultisampleEXT(e.FRAMEBUFFER,s,c,h.__webglTexture,0,j(n)):(c===e.TEXTURE_2D||c>=e.TEXTURE_CUBE_MAP_POSITIVE_X&&c<=e.TEXTURE_CUBE_MAP_NEGATIVE_Z)&&e.framebufferTexture2D(e.FRAMEBUFFER,s,c,h.__webglTexture,d),i.bindFramebuffer(e.FRAMEBUFFER,null)}function z(t,n,i){if(e.bindRenderbuffer(e.RENDERBUFFER,t),n.depthBuffer){const r=n.depthTexture,a=r&&r.isDepthTexture?r.type:null,o=b(n.stencilBuffer,a),s=n.stencilBuffer?e.DEPTH_STENCIL_ATTACHMENT:e.DEPTH_ATTACHMENT,c=j(n);K(n)?l.renderbufferStorageMultisampleEXT(e.RENDERBUFFER,c,o,n.width,n.height):i?e.renderbufferStorageMultisample(e.RENDERBUFFER,c,o,n.width,n.height):e.renderbufferStorage(e.RENDERBUFFER,o,n.width,n.height),e.framebufferRenderbuffer(e.FRAMEBUFFER,s,e.RENDERBUFFER,t)}else{const t=n.textures;for(let r=0;r{delete n.__boundDepthTexture,delete n.__depthDisposeCallback,e.removeEventListener("dispose",t)};e.addEventListener("dispose",t),n.__depthDisposeCallback=t}n.__boundDepthTexture=e}if(t.depthTexture&&!n.__autoAllocateDepthBuffer){if(a)throw new Error("target.depthTexture not supported in Cube render targets");!function(t,n){if(n&&n.isWebGLCubeRenderTarget)throw new Error("Depth Texture with cube render targets is not supported");if(i.bindFramebuffer(e.FRAMEBUFFER,t),!n.depthTexture||!n.depthTexture.isDepthTexture)throw new Error("renderTarget.depthTexture must be an instance of THREE.DepthTexture");const a=r.get(n.depthTexture);a.__renderTarget=n,a.__webglTexture&&n.depthTexture.image.width===n.width&&n.depthTexture.image.height===n.height||(n.depthTexture.image.width=n.width,n.depthTexture.image.height=n.height,n.depthTexture.needsUpdate=!0),D(n.depthTexture,0);const o=a.__webglTexture,s=j(n);if(n.depthTexture.format===xt)K(n)?l.framebufferTexture2DMultisampleEXT(e.FRAMEBUFFER,e.DEPTH_ATTACHMENT,e.TEXTURE_2D,o,0,s):e.framebufferTexture2D(e.FRAMEBUFFER,e.DEPTH_ATTACHMENT,e.TEXTURE_2D,o,0);else{if(n.depthTexture.format!==vt)throw new Error("Unknown depthTexture format");K(n)?l.framebufferTexture2DMultisampleEXT(e.FRAMEBUFFER,e.DEPTH_STENCIL_ATTACHMENT,e.TEXTURE_2D,o,0,s):e.framebufferTexture2D(e.FRAMEBUFFER,e.DEPTH_STENCIL_ATTACHMENT,e.TEXTURE_2D,o,0)}}(n.__webglFramebuffer,t)}else if(a){n.__webglDepthbuffer=[];for(let r=0;r<6;r++)if(i.bindFramebuffer(e.FRAMEBUFFER,n.__webglFramebuffer[r]),void 0===n.__webglDepthbuffer[r])n.__webglDepthbuffer[r]=e.createRenderbuffer(),z(n.__webglDepthbuffer[r],t,!1);else{const i=t.stencilBuffer?e.DEPTH_STENCIL_ATTACHMENT:e.DEPTH_ATTACHMENT,a=n.__webglDepthbuffer[r];e.bindRenderbuffer(e.RENDERBUFFER,a),e.framebufferRenderbuffer(e.FRAMEBUFFER,i,e.RENDERBUFFER,a)}}else if(i.bindFramebuffer(e.FRAMEBUFFER,n.__webglFramebuffer),void 0===n.__webglDepthbuffer)n.__webglDepthbuffer=e.createRenderbuffer(),z(n.__webglDepthbuffer,t,!1);else{const i=t.stencilBuffer?e.DEPTH_STENCIL_ATTACHMENT:e.DEPTH_ATTACHMENT,r=n.__webglDepthbuffer;e.bindRenderbuffer(e.RENDERBUFFER,r),e.framebufferRenderbuffer(e.FRAMEBUFFER,i,e.RENDERBUFFER,r)}i.bindFramebuffer(e.FRAMEBUFFER,null)}const W=[],Y=[];function j(e){return Math.min(a.maxSamples,e.samples)}function K(e){const n=r.get(e);return e.samples>0&&!0===t.has("WEBGL_multisampled_render_to_texture")&&!1!==n.__useRenderToTexture}function q(e,t){const n=e.colorSpace,i=e.format,r=e.type;return!0===e.isCompressedTexture||!0===e.isVideoTexture||n!==B&&n!==gt&&(u.getTransfer(n)===f?i===E&&r===T||console.warn("THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType."):console.error("THREE.WebGLTextures: Unsupported texture color space:",n)),t}function Z(e){return"undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement?(d.width=e.naturalWidth||e.width,d.height=e.naturalHeight||e.height):"undefined"!=typeof VideoFrame&&e instanceof VideoFrame?(d.width=e.displayWidth,d.height=e.displayHeight):(d.width=e.width,d.height=e.height),d}this.allocateTextureUnit=function(){const e=w;return e>=a.maxTextures&&console.warn("THREE.WebGLTextures: Trying to use "+e+" texture units while this GPU supports only "+a.maxTextures),w+=1,e},this.resetTextureUnits=function(){w=0},this.setTexture2D=D,this.setTexture2DArray=function(t,n){const a=r.get(t);t.version>0&&a.__version!==t.version?G(a,t,n):i.bindTexture(e.TEXTURE_2D_ARRAY,a.__webglTexture,e.TEXTURE0+n)},this.setTexture3D=function(t,n){const a=r.get(t);t.version>0&&a.__version!==t.version?G(a,t,n):i.bindTexture(e.TEXTURE_3D,a.__webglTexture,e.TEXTURE0+n)},this.setTextureCube=function(t,n){const s=r.get(t);t.version>0&&s.__version!==t.version?function(t,n,s){if(6!==n.image.length)return;const l=H(t,n),c=n.source;i.bindTexture(e.TEXTURE_CUBE_MAP,t.__webglTexture,e.TEXTURE0+s);const d=r.get(c);if(c.version!==d.__version||!0===l){i.activeTexture(e.TEXTURE0+s);const t=u.getPrimaries(u.workingColorSpace),r=n.colorSpace===gt?null:u.getPrimaries(n.colorSpace),f=n.colorSpace===gt||t===r?e.NONE:e.BROWSER_DEFAULT_WEBGL;e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,n.flipY),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,n.premultiplyAlpha),e.pixelStorei(e.UNPACK_ALIGNMENT,n.unpackAlignment),e.pixelStorei(e.UNPACK_COLORSPACE_CONVERSION_WEBGL,f);const p=n.isCompressedTexture||n.image[0].isCompressedTexture,m=n.image[0]&&n.image[0].isDataTexture,h=[];for(let e=0;e<6;e++)h[e]=p||m?m?n.image[e].image:n.image[e]:v(n.image[e],!0,a.maxCubemapSize),h[e]=q(n,h[e]);const _=h[0],g=o.convert(n.format,n.colorSpace),T=o.convert(n.type),M=A(n.internalFormat,g,T,n.colorSpace),R=!0!==n.isVideoTexture,b=void 0===d.__version||!0===l,L=c.dataReady;let P,U=C(n,_);if(O(e.TEXTURE_CUBE_MAP,n),p){R&&b&&i.texStorage2D(e.TEXTURE_CUBE_MAP,U,M,_.width,_.height);for(let t=0;t<6;t++){P=h[t].mipmaps;for(let r=0;r0&&U++;const t=Z(h[0]);i.texStorage2D(e.TEXTURE_CUBE_MAP,U,M,t.width,t.height)}for(let t=0;t<6;t++)if(m){R?L&&i.texSubImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+t,0,0,0,h[t].width,h[t].height,g,T,h[t].data):i.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+t,0,M,h[t].width,h[t].height,0,g,T,h[t].data);for(let n=0;n1;if(u||(void 0===l.__webglTexture&&(l.__webglTexture=e.createTexture()),l.__version=n.version,s.memory.textures++),d){a.__webglFramebuffer=[];for(let t=0;t<6;t++)if(n.mipmaps&&n.mipmaps.length>0){a.__webglFramebuffer[t]=[];for(let i=0;i0){a.__webglFramebuffer=[];for(let t=0;t0&&!1===K(t)){a.__webglMultisampledFramebuffer=e.createFramebuffer(),a.__webglColorRenderbuffer=[],i.bindFramebuffer(e.FRAMEBUFFER,a.__webglMultisampledFramebuffer);for(let n=0;n0)for(let r=0;r0)for(let i=0;i0)if(!1===K(t)){const n=t.textures,a=t.width,o=t.height;let s=e.COLOR_BUFFER_BIT;const l=t.stencilBuffer?e.DEPTH_STENCIL_ATTACHMENT:e.DEPTH_ATTACHMENT,d=r.get(t),u=n.length>1;if(u)for(let t=0;ts+c?(l.inputState.pinching=!1,this.dispatchEvent({type:"pinchend",handedness:e.handedness,target:this})):!l.inputState.pinching&&o<=s-c&&(l.inputState.pinching=!0,this.dispatchEvent({type:"pinchstart",handedness:e.handedness,target:this}))}else null!==s&&e.gripSpace&&(r=t.getPose(e.gripSpace,n),null!==r&&(s.matrix.fromArray(r.transform.matrix),s.matrix.decompose(s.position,s.rotation,s.scale),s.matrixWorldNeedsUpdate=!0,r.linearVelocity?(s.hasLinearVelocity=!0,s.linearVelocity.copy(r.linearVelocity)):s.hasLinearVelocity=!1,r.angularVelocity?(s.hasAngularVelocity=!0,s.angularVelocity.copy(r.angularVelocity)):s.hasAngularVelocity=!1));null!==o&&(i=t.getPose(e.targetRaySpace,n),null===i&&null!==r&&(i=r),null!==i&&(o.matrix.fromArray(i.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),o.matrixWorldNeedsUpdate=!0,i.linearVelocity?(o.hasLinearVelocity=!0,o.linearVelocity.copy(i.linearVelocity)):o.hasLinearVelocity=!1,i.angularVelocity?(o.hasAngularVelocity=!0,o.angularVelocity.copy(i.angularVelocity)):o.hasAngularVelocity=!1,this.dispatchEvent(ra)))}return null!==o&&(o.visible=null!==i),null!==s&&(s.visible=null!==r),null!==l&&(l.visible=null!==a),this}_getHandJoint(e,t){if(void 0===e.joints[t.jointName]){const n=new vn;n.matrixAutoUpdate=!1,n.visible=!1,e.joints[t.jointName]=n,e.add(n)}return e.joints[t.jointName]}}class oa{constructor(){this.texture=null,this.mesh=null,this.depthNear=0,this.depthFar=0}init(e,t,n){if(null===this.texture){const i=new Y;e.properties.get(i).__webglTexture=t.texture,t.depthNear===n.depthNear&&t.depthFar===n.depthFar||(this.depthNear=t.depthNear,this.depthFar=t.depthFar),this.texture=i}}getMesh(e){if(null!==this.texture&&null===this.mesh){const t=e.cameras[0].viewport,n=new l({vertexShader:"\nvoid main() {\n\n\tgl_Position = vec4( position, 1.0 );\n\n}",fragmentShader:"\nuniform sampler2DArray depthColor;\nuniform float depthWidth;\nuniform float depthHeight;\n\nvoid main() {\n\n\tvec2 coord = vec2( gl_FragCoord.x / depthWidth, gl_FragCoord.y / depthHeight );\n\n\tif ( coord.x >= 1.0 ) {\n\n\t\tgl_FragDepth = texture( depthColor, vec3( coord.x - 1.0, coord.y, 1 ) ).r;\n\n\t} else {\n\n\t\tgl_FragDepth = texture( depthColor, vec3( coord.x, coord.y, 0 ) ).r;\n\n\t}\n\n}",uniforms:{depthColor:{value:this.texture},depthWidth:{value:t.z},depthHeight:{value:t.w}}});this.mesh=new o(new p(20,20),n)}return this.mesh}reset(){this.texture=null,this.mesh=null}getDepthTexture(){return this.texture}}class sa extends En{constructor(e,t){super();const i=this;let a=null,o=1,s=null,l="local-floor",c=1,d=null,u=null,f=null,p=null,m=null,h=null;const _=new oa,g=t.getContextAttributes();let v=null,S=null;const M=[],x=[],R=new n;let A=null;const b=new P;b.viewport=new k;const C=new P;C.viewport=new k;const L=[b,C],U=new Sn;let w=null,D=null;function y(e){const t=x.indexOf(e.inputSource);if(-1===t)return;const n=M[t];void 0!==n&&(n.update(e.inputSource,e.frame,d||s),n.dispatchEvent({type:e.type,data:e.inputSource}))}function N(){a.removeEventListener("select",y),a.removeEventListener("selectstart",y),a.removeEventListener("selectend",y),a.removeEventListener("squeeze",y),a.removeEventListener("squeezestart",y),a.removeEventListener("squeezeend",y),a.removeEventListener("end",N),a.removeEventListener("inputsourceschange",O);for(let e=0;e=0&&(x[i]=null,M[i].disconnect(n))}for(let t=0;t=x.length){x.push(n),i=e;break}if(null===x[e]){x[e]=n,i=e;break}}if(-1===i)break}const r=M[i];r&&r.connect(n)}}this.cameraAutoUpdate=!0,this.enabled=!1,this.isPresenting=!1,this.getController=function(e){let t=M[e];return void 0===t&&(t=new aa,M[e]=t),t.getTargetRaySpace()},this.getControllerGrip=function(e){let t=M[e];return void 0===t&&(t=new aa,M[e]=t),t.getGripSpace()},this.getHand=function(e){let t=M[e];return void 0===t&&(t=new aa,M[e]=t),t.getHandSpace()},this.setFramebufferScaleFactor=function(e){o=e,!0===i.isPresenting&&console.warn("THREE.WebXRManager: Cannot change framebuffer scale while presenting.")},this.setReferenceSpaceType=function(e){l=e,!0===i.isPresenting&&console.warn("THREE.WebXRManager: Cannot change reference space type while presenting.")},this.getReferenceSpace=function(){return d||s},this.setReferenceSpace=function(e){d=e},this.getBaseLayer=function(){return null!==p?p:m},this.getBinding=function(){return f},this.getFrame=function(){return h},this.getSession=function(){return a},this.setSession=async function(n){if(a=n,null!==a){v=e.getRenderTarget(),a.addEventListener("select",y),a.addEventListener("selectstart",y),a.addEventListener("selectend",y),a.addEventListener("squeeze",y),a.addEventListener("squeezestart",y),a.addEventListener("squeezeend",y),a.addEventListener("end",N),a.addEventListener("inputsourceschange",O),!0!==g.xrCompatible&&await t.makeXRCompatible(),A=e.getPixelRatio(),e.getSize(R);if(void 0!==a.enabledFeatures&&a.enabledFeatures.includes("layers")){let n=null,i=null,r=null;g.depth&&(r=g.stencil?t.DEPTH24_STENCIL8:t.DEPTH_COMPONENT24,n=g.stencil?vt:xt,i=g.stencil?Tt:St);const s={colorFormat:t.RGBA8,depthFormat:r,scaleFactor:o};f=new XRWebGLBinding(a,t),p=f.createProjectionLayer(s),a.updateRenderState({layers:[p]}),e.setPixelRatio(1),e.setSize(p.textureWidth,p.textureHeight,!1),S=new I(p.textureWidth,p.textureHeight,{format:E,type:T,depthTexture:new j(p.textureWidth,p.textureHeight,i,void 0,void 0,void 0,void 0,void 0,void 0,n),stencilBuffer:g.stencil,colorSpace:e.outputColorSpace,samples:g.antialias?4:0,resolveDepthBuffer:!1===p.ignoreDepthValues})}else{const n={antialias:g.antialias,alpha:!0,depth:g.depth,stencil:g.stencil,framebufferScaleFactor:o};m=new XRWebGLLayer(a,t,n),a.updateRenderState({baseLayer:m}),e.setPixelRatio(1),e.setSize(m.framebufferWidth,m.framebufferHeight,!1),S=new I(m.framebufferWidth,m.framebufferHeight,{format:E,type:T,colorSpace:e.outputColorSpace,stencilBuffer:g.stencil})}S.isXRRenderTarget=!0,this.setFoveation(c),d=null,s=await a.requestReferenceSpace(l),V.setContext(a),V.start(),i.isPresenting=!0,i.dispatchEvent({type:"sessionstart"})}},this.getEnvironmentBlendMode=function(){if(null!==a)return a.environmentBlendMode},this.getDepthTexture=function(){return _.getDepthTexture()};const F=new r,B=new r;function H(e,t){null===t?e.matrixWorld.copy(e.matrix):e.matrixWorld.multiplyMatrices(t.matrixWorld,e.matrix),e.matrixWorldInverse.copy(e.matrixWorld).invert()}this.updateCamera=function(e){if(null===a)return;let t=e.near,n=e.far;null!==_.texture&&(_.depthNear>0&&(t=_.depthNear),_.depthFar>0&&(n=_.depthFar)),U.near=C.near=b.near=t,U.far=C.far=b.far=n,w===U.near&&D===U.far||(a.updateRenderState({depthNear:U.near,depthFar:U.far}),w=U.near,D=U.far),b.layers.mask=2|e.layers.mask,C.layers.mask=4|e.layers.mask,U.layers.mask=b.layers.mask|C.layers.mask;const i=e.parent,r=U.cameras;H(U,i);for(let e=0;e0&&(e.alphaTest.value=i.alphaTest);const r=t.get(i),a=r.envMap,o=r.envMapRotation;a&&(e.envMap.value=a,la.copy(o),la.x*=-1,la.y*=-1,la.z*=-1,a.isCubeTexture&&!1===a.isRenderTargetTexture&&(la.y*=-1,la.z*=-1),e.envMapRotation.value.setFromMatrix4(ca.makeRotationFromEuler(la)),e.flipEnvMap.value=a.isCubeTexture&&!1===a.isRenderTargetTexture?-1:1,e.reflectivity.value=i.reflectivity,e.ior.value=i.ior,e.refractionRatio.value=i.refractionRatio),i.lightMap&&(e.lightMap.value=i.lightMap,e.lightMapIntensity.value=i.lightMapIntensity,n(i.lightMap,e.lightMapTransform)),i.aoMap&&(e.aoMap.value=i.aoMap,e.aoMapIntensity.value=i.aoMapIntensity,n(i.aoMap,e.aoMapTransform))}return{refreshFogUniforms:function(t,n){n.color.getRGB(t.fogColor.value,h(e)),n.isFog?(t.fogNear.value=n.near,t.fogFar.value=n.far):n.isFogExp2&&(t.fogDensity.value=n.density)},refreshMaterialUniforms:function(e,r,a,o,s){r.isMeshBasicMaterial||r.isMeshLambertMaterial?i(e,r):r.isMeshToonMaterial?(i(e,r),function(e,t){t.gradientMap&&(e.gradientMap.value=t.gradientMap)}(e,r)):r.isMeshPhongMaterial?(i(e,r),function(e,t){e.specular.value.copy(t.specular),e.shininess.value=Math.max(t.shininess,1e-4)}(e,r)):r.isMeshStandardMaterial?(i(e,r),function(e,t){e.metalness.value=t.metalness,t.metalnessMap&&(e.metalnessMap.value=t.metalnessMap,n(t.metalnessMap,e.metalnessMapTransform));e.roughness.value=t.roughness,t.roughnessMap&&(e.roughnessMap.value=t.roughnessMap,n(t.roughnessMap,e.roughnessMapTransform));t.envMap&&(e.envMapIntensity.value=t.envMapIntensity)}(e,r),r.isMeshPhysicalMaterial&&function(e,t,i){e.ior.value=t.ior,t.sheen>0&&(e.sheenColor.value.copy(t.sheenColor).multiplyScalar(t.sheen),e.sheenRoughness.value=t.sheenRoughness,t.sheenColorMap&&(e.sheenColorMap.value=t.sheenColorMap,n(t.sheenColorMap,e.sheenColorMapTransform)),t.sheenRoughnessMap&&(e.sheenRoughnessMap.value=t.sheenRoughnessMap,n(t.sheenRoughnessMap,e.sheenRoughnessMapTransform)));t.clearcoat>0&&(e.clearcoat.value=t.clearcoat,e.clearcoatRoughness.value=t.clearcoatRoughness,t.clearcoatMap&&(e.clearcoatMap.value=t.clearcoatMap,n(t.clearcoatMap,e.clearcoatMapTransform)),t.clearcoatRoughnessMap&&(e.clearcoatRoughnessMap.value=t.clearcoatRoughnessMap,n(t.clearcoatRoughnessMap,e.clearcoatRoughnessMapTransform)),t.clearcoatNormalMap&&(e.clearcoatNormalMap.value=t.clearcoatNormalMap,n(t.clearcoatNormalMap,e.clearcoatNormalMapTransform),e.clearcoatNormalScale.value.copy(t.clearcoatNormalScale),t.side===d&&e.clearcoatNormalScale.value.negate()));t.dispersion>0&&(e.dispersion.value=t.dispersion);t.iridescence>0&&(e.iridescence.value=t.iridescence,e.iridescenceIOR.value=t.iridescenceIOR,e.iridescenceThicknessMinimum.value=t.iridescenceThicknessRange[0],e.iridescenceThicknessMaximum.value=t.iridescenceThicknessRange[1],t.iridescenceMap&&(e.iridescenceMap.value=t.iridescenceMap,n(t.iridescenceMap,e.iridescenceMapTransform)),t.iridescenceThicknessMap&&(e.iridescenceThicknessMap.value=t.iridescenceThicknessMap,n(t.iridescenceThicknessMap,e.iridescenceThicknessMapTransform)));t.transmission>0&&(e.transmission.value=t.transmission,e.transmissionSamplerMap.value=i.texture,e.transmissionSamplerSize.value.set(i.width,i.height),t.transmissionMap&&(e.transmissionMap.value=t.transmissionMap,n(t.transmissionMap,e.transmissionMapTransform)),e.thickness.value=t.thickness,t.thicknessMap&&(e.thicknessMap.value=t.thicknessMap,n(t.thicknessMap,e.thicknessMapTransform)),e.attenuationDistance.value=t.attenuationDistance,e.attenuationColor.value.copy(t.attenuationColor));t.anisotropy>0&&(e.anisotropyVector.value.set(t.anisotropy*Math.cos(t.anisotropyRotation),t.anisotropy*Math.sin(t.anisotropyRotation)),t.anisotropyMap&&(e.anisotropyMap.value=t.anisotropyMap,n(t.anisotropyMap,e.anisotropyMapTransform)));e.specularIntensity.value=t.specularIntensity,e.specularColor.value.copy(t.specularColor),t.specularColorMap&&(e.specularColorMap.value=t.specularColorMap,n(t.specularColorMap,e.specularColorMapTransform));t.specularIntensityMap&&(e.specularIntensityMap.value=t.specularIntensityMap,n(t.specularIntensityMap,e.specularIntensityMapTransform))}(e,r,s)):r.isMeshMatcapMaterial?(i(e,r),function(e,t){t.matcap&&(e.matcap.value=t.matcap)}(e,r)):r.isMeshDepthMaterial?i(e,r):r.isMeshDistanceMaterial?(i(e,r),function(e,n){const i=t.get(n).light;e.referencePosition.value.setFromMatrixPosition(i.matrixWorld),e.nearDistance.value=i.shadow.camera.near,e.farDistance.value=i.shadow.camera.far}(e,r)):r.isMeshNormalMaterial?i(e,r):r.isLineBasicMaterial?(function(e,t){e.diffuse.value.copy(t.color),e.opacity.value=t.opacity,t.map&&(e.map.value=t.map,n(t.map,e.mapTransform))}(e,r),r.isLineDashedMaterial&&function(e,t){e.dashSize.value=t.dashSize,e.totalSize.value=t.dashSize+t.gapSize,e.scale.value=t.scale}(e,r)):r.isPointsMaterial?function(e,t,i,r){e.diffuse.value.copy(t.color),e.opacity.value=t.opacity,e.size.value=t.size*i,e.scale.value=.5*r,t.map&&(e.map.value=t.map,n(t.map,e.uvTransform));t.alphaMap&&(e.alphaMap.value=t.alphaMap,n(t.alphaMap,e.alphaMapTransform));t.alphaTest>0&&(e.alphaTest.value=t.alphaTest)}(e,r,a,o):r.isSpriteMaterial?function(e,t){e.diffuse.value.copy(t.color),e.opacity.value=t.opacity,e.rotation.value=t.rotation,t.map&&(e.map.value=t.map,n(t.map,e.mapTransform));t.alphaMap&&(e.alphaMap.value=t.alphaMap,n(t.alphaMap,e.alphaMapTransform));t.alphaTest>0&&(e.alphaTest.value=t.alphaTest)}(e,r):r.isShadowMaterial?(e.color.value.copy(r.color),e.opacity.value=r.opacity):r.isShaderMaterial&&(r.uniformsNeedUpdate=!1)}}}function ua(e,t,n,i){let r={},a={},o=[];const s=e.getParameter(e.MAX_UNIFORM_BUFFER_BINDINGS);function l(e,t,n,i){const r=e.value,a=t+"_"+n;if(void 0===i[a])return i[a]="number"==typeof r||"boolean"==typeof r?r:r.clone(),!0;{const e=i[a];if("number"==typeof r||"boolean"==typeof r){if(e!==r)return i[a]=r,!0}else if(!1===e.equals(r))return e.copy(r),!0}return!1}function c(e){const t={boundary:0,storage:0};return"number"==typeof e||"boolean"==typeof e?(t.boundary=4,t.storage=4):e.isVector2?(t.boundary=8,t.storage=8):e.isVector3||e.isColor?(t.boundary=16,t.storage=12):e.isVector4?(t.boundary=16,t.storage=16):e.isMatrix3?(t.boundary=48,t.storage=48):e.isMatrix4?(t.boundary=64,t.storage=64):e.isTexture?console.warn("THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group."):console.warn("THREE.WebGLRenderer: Unsupported uniform value type.",e),t}function d(t){const n=t.target;n.removeEventListener("dispose",d);const i=o.indexOf(n.__bindingPointIndex);o.splice(i,1),e.deleteBuffer(r[n.id]),delete r[n.id],delete a[n.id]}return{bind:function(e,t){const n=t.program;i.uniformBlockBinding(e,n)},update:function(n,u){let f=r[n.id];void 0===f&&(!function(e){const t=e.uniforms;let n=0;const i=16;for(let e=0,r=t.length;e0&&(n+=i-r);e.__size=n,e.__cache={}}(n),f=function(t){const n=function(){for(let e=0;e0),u=!!n.morphAttributes.position,f=!!n.morphAttributes.normal,p=!!n.morphAttributes.color;let m=U;i.toneMapped&&(null!==D&&!0!==D.isXRRenderTarget||(m=C.toneMapping));const h=n.morphAttributes.position||n.morphAttributes.normal||n.morphAttributes.color,_=void 0!==h?h.length:0,g=fe.get(i),v=R.state.lights;if(!0===J&&(!0===ee||e!==N)){const t=e===N&&i.id===y;Ae.setState(i,e,t)}let E=!1;i.version===g.__version?g.needsLights&&g.lightsStateVersion!==v.state.version||g.outputColorSpace!==s||r.isBatchedMesh&&!1===g.batching?E=!0:r.isBatchedMesh||!0!==g.batching?r.isBatchedMesh&&!0===g.batchingColor&&null===r.colorTexture||r.isBatchedMesh&&!1===g.batchingColor&&null!==r.colorTexture||r.isInstancedMesh&&!1===g.instancing?E=!0:r.isInstancedMesh||!0!==g.instancing?r.isSkinnedMesh&&!1===g.skinning?E=!0:r.isSkinnedMesh||!0!==g.skinning?r.isInstancedMesh&&!0===g.instancingColor&&null===r.instanceColor||r.isInstancedMesh&&!1===g.instancingColor&&null!==r.instanceColor||r.isInstancedMesh&&!0===g.instancingMorph&&null===r.morphTexture||r.isInstancedMesh&&!1===g.instancingMorph&&null!==r.morphTexture||g.envMap!==l||!0===i.fog&&g.fog!==a?E=!0:void 0===g.numClippingPlanes||g.numClippingPlanes===Ae.numPlanes&&g.numIntersection===Ae.numIntersection?(g.vertexAlphas!==c||g.vertexTangents!==d||g.morphTargets!==u||g.morphNormals!==f||g.morphColors!==p||g.toneMapping!==m||g.morphTargetsCount!==_)&&(E=!0):E=!0:E=!0:E=!0:E=!0:(E=!0,g.__version=i.version);let S=g.currentProgram;!0===E&&(S=Qe(i,t,r));let T=!1,M=!1,x=!1;const A=S.getUniforms(),b=g.uniforms;de.useProgram(S.program)&&(T=!0,M=!0,x=!0);i.id!==y&&(y=i.id,M=!0);if(T||N!==e){de.buffers.depth.getReversed()?(te.copy(e.projectionMatrix),An(te),bn(te),A.setValue(Ie,"projectionMatrix",te)):A.setValue(Ie,"projectionMatrix",e.projectionMatrix),A.setValue(Ie,"viewMatrix",e.matrixWorldInverse);const t=A.map.cameraPosition;void 0!==t&&t.setValue(Ie,ie.setFromMatrixPosition(e.matrixWorld)),ce.logarithmicDepthBuffer&&A.setValue(Ie,"logDepthBufFC",2/(Math.log(e.far+1)/Math.LN2)),(i.isMeshPhongMaterial||i.isMeshToonMaterial||i.isMeshLambertMaterial||i.isMeshBasicMaterial||i.isMeshStandardMaterial||i.isShaderMaterial)&&A.setValue(Ie,"isOrthographic",!0===e.isOrthographicCamera),N!==e&&(N=e,M=!0,x=!0)}if(r.isSkinnedMesh){A.setOptional(Ie,r,"bindMatrix"),A.setOptional(Ie,r,"bindMatrixInverse");const e=r.skeleton;e&&(null===e.boneTexture&&e.computeBoneTexture(),A.setValue(Ie,"boneTexture",e.boneTexture,pe))}r.isBatchedMesh&&(A.setOptional(Ie,r,"batchingTexture"),A.setValue(Ie,"batchingTexture",r._matricesTexture,pe),A.setOptional(Ie,r,"batchingIdTexture"),A.setValue(Ie,"batchingIdTexture",r._indirectTexture,pe),A.setOptional(Ie,r,"batchingColorTexture"),null!==r._colorsTexture&&A.setValue(Ie,"batchingColorTexture",r._colorsTexture,pe));const L=n.morphAttributes;void 0===L.position&&void 0===L.normal&&void 0===L.color||Le.update(r,n,S);(M||g.receiveShadow!==r.receiveShadow)&&(g.receiveShadow=r.receiveShadow,A.setValue(Ie,"receiveShadow",r.receiveShadow));i.isMeshGouraudMaterial&&null!==i.envMap&&(b.envMap.value=l,b.flipEnvMap.value=l.isCubeTexture&&!1===l.isRenderTargetTexture?-1:1);i.isMeshStandardMaterial&&null===i.envMap&&null!==t.environment&&(b.envMapIntensity.value=t.environmentIntensity);M&&(A.setValue(Ie,"toneMappingExposure",C.toneMappingExposure),g.needsLights&&(w=x,(P=b).ambientLightColor.needsUpdate=w,P.lightProbe.needsUpdate=w,P.directionalLights.needsUpdate=w,P.directionalLightShadows.needsUpdate=w,P.pointLights.needsUpdate=w,P.pointLightShadows.needsUpdate=w,P.spotLights.needsUpdate=w,P.spotLightShadows.needsUpdate=w,P.rectAreaLights.needsUpdate=w,P.hemisphereLights.needsUpdate=w),a&&!0===i.fog&&Me.refreshFogUniforms(b,a),Me.refreshMaterialUniforms(b,i,Y,X,R.state.transmissionRenderTarget[e.id]),gr.upload(Ie,Je(g),b,pe));var P,w;i.isShaderMaterial&&!0===i.uniformsNeedUpdate&&(gr.upload(Ie,Je(g),b,pe),i.uniformsNeedUpdate=!1);i.isSpriteMaterial&&A.setValue(Ie,"center",r.center);if(A.setValue(Ie,"modelViewMatrix",r.modelViewMatrix),A.setValue(Ie,"normalMatrix",r.normalMatrix),A.setValue(Ie,"modelMatrix",r.matrixWorld),i.isShaderMaterial||i.isRawShaderMaterial){const e=i.uniformsGroups;for(let t=0,n=e.length;t{function n(){i.forEach((function(e){fe.get(e).currentProgram.isReady()&&i.delete(e)})),0!==i.size?setTimeout(n,10):t(e)}null!==le.get("KHR_parallel_shader_compile")?n():setTimeout(n,10)}))};let ke=null;function We(){Ye.stop()}function Xe(){Ye.start()}const Ye=new Pn;function je(e,t,n,i){if(!1===e.visible)return;if(e.layers.test(t.layers))if(e.isGroup)n=e.renderOrder;else if(e.isLOD)!0===e.autoUpdate&&e.update(t);else if(e.isLight)R.pushLight(e),e.castShadow&&R.pushShadow(e);else if(e.isSprite){if(!e.frustumCulled||Q.intersectsSprite(e)){i&&re.setFromMatrixPosition(e.matrixWorld).applyMatrix4(ne);const t=Se.update(e),r=e.material;r.visible&&x.push(e,t,r,n,re.z,null)}}else if((e.isMesh||e.isLine||e.isPoints)&&(!e.frustumCulled||Q.intersectsObject(e))){const t=Se.update(e),r=e.material;if(i&&(void 0!==e.boundingSphere?(null===e.boundingSphere&&e.computeBoundingSphere(),re.copy(e.boundingSphere.center)):(null===t.boundingSphere&&t.computeBoundingSphere(),re.copy(t.boundingSphere.center)),re.applyMatrix4(e.matrixWorld).applyMatrix4(ne)),Array.isArray(r)){const i=t.groups;for(let a=0,o=i.length;a0&&Ze(r,t,n),a.length>0&&Ze(a,t,n),o.length>0&&Ze(o,t,n),de.buffers.depth.setTest(!0),de.buffers.depth.setMask(!0),de.buffers.color.setMask(!0),de.setPolygonOffset(!1)}function qe(e,t,n,i){if(null!==(!0===n.isScene?n.overrideMaterial:null))return;void 0===R.state.transmissionRenderTarget[i.id]&&(R.state.transmissionRenderTarget[i.id]=new I(1,1,{generateMipmaps:!0,type:le.has("EXT_color_buffer_half_float")||le.has("EXT_color_buffer_float")?S:T,minFilter:ct,samples:4,stencilBuffer:o,resolveDepthBuffer:!1,resolveStencilBuffer:!1,colorSpace:u.workingColorSpace}));const r=R.state.transmissionRenderTarget[i.id],a=i.viewport||O;r.setSize(a.z*C.transmissionResolutionScale,a.w*C.transmissionResolutionScale);const s=C.getRenderTarget();C.setRenderTarget(r),C.getClearColor(V),z=C.getClearAlpha(),z<1&&C.setClearColor(16777215,.5),C.clear(),oe&&Ce.render(n);const l=C.toneMapping;C.toneMapping=U;const c=i.viewport;if(void 0!==i.viewport&&(i.viewport=void 0),R.setupLightsView(i),!0===J&&Ae.setGlobalState(C.clippingPlanes,i),Ze(e,n,i),pe.updateMultisampleRenderTarget(r),pe.updateRenderTargetMipmap(r),!1===le.has("WEBGL_multisampled_render_to_texture")){let e=!1;for(let r=0,a=t.length;r0)for(let t=0,a=n.length;t0&&qe(i,r,e,t),oe&&Ce.render(e),Ke(x,e,t);null!==D&&(pe.updateMultisampleRenderTarget(D),pe.updateRenderTargetMipmap(D)),!0===e.isScene&&e.onAfterRender(C,e,t),De.resetDefaultState(),y=-1,N=null,b.pop(),b.length>0?(R=b[b.length-1],!0===J&&Ae.setGlobalState(C.clippingPlanes,R.state.camera)):R=null,A.pop(),x=A.length>0?A[A.length-1]:null},this.getActiveCubeFace=function(){return P},this.getActiveMipmapLevel=function(){return w},this.getRenderTarget=function(){return D},this.setRenderTargetTextures=function(e,t,n){fe.get(e.texture).__webglTexture=t,fe.get(e.depthTexture).__webglTexture=n;const i=fe.get(e);i.__hasExternalTextures=!0,i.__autoAllocateDepthBuffer=void 0===n,i.__autoAllocateDepthBuffer||!0===le.has("WEBGL_multisampled_render_to_texture")&&(console.warn("THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided"),i.__useRenderToTexture=!1)},this.setRenderTargetFramebuffer=function(e,t){const n=fe.get(e);n.__webglFramebuffer=t,n.__useDefaultFramebuffer=void 0===t},this.setRenderTarget=function(e,t=0,n=0){D=e,P=t,w=n;let i=!0,r=null,a=!1,o=!1;if(e){const s=fe.get(e);if(void 0!==s.__useDefaultFramebuffer)de.bindFramebuffer(Ie.FRAMEBUFFER,null),i=!1;else if(void 0===s.__webglFramebuffer)pe.setupRenderTarget(e);else if(s.__hasExternalTextures)pe.rebindTextures(e,fe.get(e.texture).__webglTexture,fe.get(e.depthTexture).__webglTexture);else if(e.depthBuffer){const t=e.depthTexture;if(s.__boundDepthTexture!==t){if(null!==t&&fe.has(t)&&(e.width!==t.image.width||e.height!==t.image.height))throw new Error("WebGLRenderTarget: Attached DepthTexture is initialized to the incorrect size.");pe.setupDepthRenderbuffer(e)}}const l=e.texture;(l.isData3DTexture||l.isDataArrayTexture||l.isCompressedArrayTexture)&&(o=!0);const c=fe.get(e).__webglFramebuffer;e.isWebGLCubeRenderTarget?(r=Array.isArray(c[t])?c[t][n]:c[t],a=!0):r=e.samples>0&&!1===pe.useMultisampledRTT(e)?fe.get(e).__webglMultisampledFramebuffer:Array.isArray(c)?c[n]:c,O.copy(e.viewport),F.copy(e.scissor),G=e.scissorTest}else O.copy(q).multiplyScalar(Y).floor(),F.copy(Z).multiplyScalar(Y).floor(),G=$;if(de.bindFramebuffer(Ie.FRAMEBUFFER,r)&&i&&de.drawBuffers(e,r),de.viewport(O),de.scissor(F),de.setScissorTest(G),a){const i=fe.get(e.texture);Ie.framebufferTexture2D(Ie.FRAMEBUFFER,Ie.COLOR_ATTACHMENT0,Ie.TEXTURE_CUBE_MAP_POSITIVE_X+t,i.__webglTexture,n)}else if(o){const i=fe.get(e.texture),r=t||0;Ie.framebufferTextureLayer(Ie.FRAMEBUFFER,Ie.COLOR_ATTACHMENT0,i.__webglTexture,n||0,r)}y=-1},this.readRenderTargetPixels=function(e,t,n,i,r,a,o){if(!e||!e.isWebGLRenderTarget)return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let s=fe.get(e).__webglFramebuffer;if(e.isWebGLCubeRenderTarget&&void 0!==o&&(s=s[o]),s){de.bindFramebuffer(Ie.FRAMEBUFFER,s);try{const o=e.texture,s=o.format,l=o.type;if(!ce.textureFormatReadable(s))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");if(!ce.textureTypeReadable(l))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");t>=0&&t<=e.width-i&&n>=0&&n<=e.height-r&&Ie.readPixels(t,n,i,r,we.convert(s),we.convert(l),a)}finally{const e=null!==D?fe.get(D).__webglFramebuffer:null;de.bindFramebuffer(Ie.FRAMEBUFFER,e)}}},this.readRenderTargetPixelsAsync=async function(e,t,n,i,r,a,o){if(!e||!e.isWebGLRenderTarget)throw new Error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let s=fe.get(e).__webglFramebuffer;if(e.isWebGLCubeRenderTarget&&void 0!==o&&(s=s[o]),s){const o=e.texture,l=o.format,c=o.type;if(!ce.textureFormatReadable(l))throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.");if(!ce.textureTypeReadable(c))throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in UnsignedByteType or implementation defined type.");if(t>=0&&t<=e.width-i&&n>=0&&n<=e.height-r){de.bindFramebuffer(Ie.FRAMEBUFFER,s);const e=Ie.createBuffer();Ie.bindBuffer(Ie.PIXEL_PACK_BUFFER,e),Ie.bufferData(Ie.PIXEL_PACK_BUFFER,a.byteLength,Ie.STREAM_READ),Ie.readPixels(t,n,i,r,we.convert(l),we.convert(c),0);const o=null!==D?fe.get(D).__webglFramebuffer:null;de.bindFramebuffer(Ie.FRAMEBUFFER,o);const d=Ie.fenceSync(Ie.SYNC_GPU_COMMANDS_COMPLETE,0);return Ie.flush(),await Cn(Ie,d,4),Ie.bindBuffer(Ie.PIXEL_PACK_BUFFER,e),Ie.getBufferSubData(Ie.PIXEL_PACK_BUFFER,0,a),Ie.deleteBuffer(e),Ie.deleteSync(d),a}throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: requested read bounds are out of range.")}},this.copyFramebufferToTexture=function(e,t=null,n=0){!0!==e.isTexture&&(H("WebGLRenderer: copyFramebufferToTexture function signature has changed."),t=arguments[0]||null,e=arguments[1]);const i=Math.pow(2,-n),r=Math.floor(e.image.width*i),a=Math.floor(e.image.height*i),o=null!==t?t.x:0,s=null!==t?t.y:0;pe.setTexture2D(e,0),Ie.copyTexSubImage2D(Ie.TEXTURE_2D,n,0,0,o,s,r,a),de.unbindTexture()};const tt=Ie.createFramebuffer(),nt=Ie.createFramebuffer();this.copyTextureToTexture=function(e,t,n=null,i=null,r=0,a=null){let o,s,l,c,d,u,f,p,m;!0!==e.isTexture&&(H("WebGLRenderer: copyTextureToTexture function signature has changed."),i=arguments[0]||null,e=arguments[1],t=arguments[2],a=arguments[3]||0,n=null),null===a&&(0!==r?(H("WebGLRenderer: copyTextureToTexture function signature has changed to support src and dst mipmap levels."),a=r,r=0):a=0);const h=e.isCompressedTexture?e.mipmaps[a]:e.image;if(null!==n)o=n.max.x-n.min.x,s=n.max.y-n.min.y,l=n.isBox3?n.max.z-n.min.z:1,c=n.min.x,d=n.min.y,u=n.isBox3?n.min.z:0;else{const t=Math.pow(2,-r);o=Math.floor(h.width*t),s=Math.floor(h.height*t),l=e.isDataArrayTexture?h.depth:e.isData3DTexture?Math.floor(h.depth*t):1,c=0,d=0,u=0}null!==i?(f=i.x,p=i.y,m=i.z):(f=0,p=0,m=0);const _=we.convert(t.format),g=we.convert(t.type);let v;t.isData3DTexture?(pe.setTexture3D(t,0),v=Ie.TEXTURE_3D):t.isDataArrayTexture||t.isCompressedArrayTexture?(pe.setTexture2DArray(t,0),v=Ie.TEXTURE_2D_ARRAY):(pe.setTexture2D(t,0),v=Ie.TEXTURE_2D),Ie.pixelStorei(Ie.UNPACK_FLIP_Y_WEBGL,t.flipY),Ie.pixelStorei(Ie.UNPACK_PREMULTIPLY_ALPHA_WEBGL,t.premultiplyAlpha),Ie.pixelStorei(Ie.UNPACK_ALIGNMENT,t.unpackAlignment);const E=Ie.getParameter(Ie.UNPACK_ROW_LENGTH),S=Ie.getParameter(Ie.UNPACK_IMAGE_HEIGHT),T=Ie.getParameter(Ie.UNPACK_SKIP_PIXELS),M=Ie.getParameter(Ie.UNPACK_SKIP_ROWS),x=Ie.getParameter(Ie.UNPACK_SKIP_IMAGES);Ie.pixelStorei(Ie.UNPACK_ROW_LENGTH,h.width),Ie.pixelStorei(Ie.UNPACK_IMAGE_HEIGHT,h.height),Ie.pixelStorei(Ie.UNPACK_SKIP_PIXELS,c),Ie.pixelStorei(Ie.UNPACK_SKIP_ROWS,d),Ie.pixelStorei(Ie.UNPACK_SKIP_IMAGES,u);const R=e.isDataArrayTexture||e.isData3DTexture,A=t.isDataArrayTexture||t.isData3DTexture;if(e.isDepthTexture){const n=fe.get(e),i=fe.get(t),h=fe.get(n.__renderTarget),_=fe.get(i.__renderTarget);de.bindFramebuffer(Ie.READ_FRAMEBUFFER,h.__webglFramebuffer),de.bindFramebuffer(Ie.DRAW_FRAMEBUFFER,_.__webglFramebuffer);for(let n=0;ne.start-t.start));let t=0;for(let e=1;e 0\n\tvec4 plane;\n\t#ifdef ALPHA_TO_COVERAGE\n\t\tfloat distanceToPlane, distanceGradient;\n\t\tfloat clipOpacity = 1.0;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\tclipOpacity *= smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\tif ( clipOpacity == 0.0 ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tfloat unionClipOpacity = 1.0;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\t\tunionClipOpacity *= 1.0 - smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tclipOpacity *= 1.0 - unionClipOpacity;\n\t\t#endif\n\t\tdiffuseColor.a *= clipOpacity;\n\t\tif ( diffuseColor.a == 0.0 ) discard;\n\t#else\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tbool clipped = true;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tif ( clipped ) discard;\n\t\t#endif\n\t#endif\n#endif",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif",color_fragment:"#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif",color_pars_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )\n\tvarying vec3 vColor;\n#endif",color_vertex:"#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif\n#ifdef USE_BATCHING_COLOR\n\tvec3 batchingColor = getBatchingColor( getIndirectIndex( gl_DrawID ) );\n\tvColor.xyz *= batchingColor.xyz;\n#endif",common:"#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\n#ifdef USE_ALPHAHASH\n\tvarying vec3 vPosition;\n#endif\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}\nvec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n} // validated",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\thighp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif",defaultnormal_vertex:"vec3 transformedNormal = objectNormal;\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = objectTangent;\n#endif\n#ifdef USE_BATCHING\n\tmat3 bm = mat3( batchingMatrix );\n\ttransformedNormal /= vec3( dot( bm[ 0 ], bm[ 0 ] ), dot( bm[ 1 ], bm[ 1 ] ), dot( bm[ 2 ], bm[ 2 ] ) );\n\ttransformedNormal = bm * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = bm * transformedTangent;\n\t#endif\n#endif\n#ifdef USE_INSTANCING\n\tmat3 im = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( im[ 0 ], im[ 0 ] ), dot( im[ 1 ], im[ 1 ] ), dot( im[ 2 ], im[ 2 ] ) );\n\ttransformedNormal = im * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = im * transformedTangent;\n\t#endif\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\ttransformedTangent = ( modelViewMatrix * vec4( transformedTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\t#ifdef DECODE_VIDEO_TEXTURE_EMISSIVE\n\t\temissiveColor = sRGBTransferEOTF( emissiveColor );\n\t#endif\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif",colorspace_fragment:"gl_FragColor = linearToOutputTexel( gl_FragColor );",colorspace_pars_fragment:"vec4 LinearTransferOETF( in vec4 value ) {\n\treturn value;\n}\nvec4 sRGBTransferEOTF( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.a );\n}\nvec4 sRGBTransferOETF( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}",envmap_fragment:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, envMapRotation * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif",envmap_common_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\tuniform mat3 envMapRotation;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif",envmap_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif",envmap_physical_pars_fragment:"#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n#endif",envmap_vertex:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif",fog_vertex:"#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif",gradientmap_pars_fragment:"#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\tvec2 fw = fwidth( coord ) * 0.5;\n\t\treturn mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );\n\t#endif\n}",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_fragment:"LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;",lights_lambert_pars_fragment:"varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert",lights_pars_begin:"uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\n#if defined( USE_LIGHT_PROBES )\n\tuniform vec3 lightProbe[ 9 ];\n#endif\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\tif ( cutoffDistance > 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif",lights_toon_fragment:"ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;",lights_toon_pars_fragment:"varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometryNormal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;",lights_phong_pars_fragment:"varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_DISPERSION\n\tmaterial.dispersion = dispersion;\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tif( material.anisotropy == 0.0 ) {\n\t\tanisotropyV = vec2( 1.0, 0.0 );\n\t} else {\n\t\tanisotropyV /= material.anisotropy;\n\t\tmaterial.anisotropy = saturate( material.anisotropy );\n\t}\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;\n#endif",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\tfloat dispersion;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecularDirect = vec3( 0.0 );\nvec3 clearcoatSpecularIndirect = vec3( 0.0 );\nvec3 sheenSpecularDirect = vec3( 0.0 );\nvec3 sheenSpecularIndirect = vec3(0.0 );\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}",lights_fragment_begin:"\nvec3 geometryPosition = - vViewPosition;\nvec3 geometryNormal = normal;\nvec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\nvec3 geometryClearcoatNormal = vec3( 0.0 );\n#ifdef USE_CLEARCOAT\n\tgeometryClearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometryViewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometryPosition, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowIntensity, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometryPosition, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowIntensity, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowIntensity, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#if defined( USE_LIGHT_PROBES )\n\t\tirradiance += getLightProbeIrradiance( lightProbe, geometryNormal );\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometryNormal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif",lights_fragment_maps:"#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometryNormal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometryViewDir, geometryNormal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif",lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF )\n\tgl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#if defined( USE_LOGDEPTHBUF )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\tvFragDepth = 1.0 + gl_Position.w;\n\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n#endif",map_fragment:"#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vMapUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = sRGBTransferEOTF( sampledDiffuseColor );\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif",map_particle_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t#if defined( USE_POINTS_UV )\n\t\tvec2 uv = vUv;\n\t#else\n\t\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif",map_particle_pars_fragment:"#if defined( USE_POINTS_UV )\n\tvarying vec2 vUv;\n#else\n\t#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t\tuniform mat3 uvTransform;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphinstance_vertex:"#ifdef USE_INSTANCING_MORPH\n\tfloat morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\tfloat morphTargetBaseInfluence = texelFetch( morphTexture, ivec2( 0, gl_InstanceID ), 0 ).r;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tmorphTargetInfluences[i] = texelFetch( morphTexture, ivec2( i + 1, gl_InstanceID ), 0 ).r;\n\t}\n#endif",morphcolor_vertex:"#if defined( USE_MORPHCOLORS )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t}\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\t#ifndef USE_INSTANCING_MORPH\n\t\tuniform float morphTargetBaseInfluence;\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t#endif\n\tuniform sampler2DArray morphTargetsTexture;\n\tuniform ivec2 morphTargetsTextureSize;\n\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t}\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t}\n#endif",normal_fragment_begin:"float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal *= faceDirection;\n\t#endif\n#endif\n#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY )\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn = getTangentFrame( - vViewPosition, normal,\n\t\t#if defined( USE_NORMALMAP )\n\t\t\tvNormalMapUv\n\t\t#elif defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tvClearcoatNormalMapUv\n\t\t#else\n\t\t\tvUv\n\t\t#endif\n\t\t);\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn[0] *= faceDirection;\n\t\ttbn[1] *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn2[0] *= faceDirection;\n\t\ttbn2[1] *= faceDirection;\n\t#endif\n#endif\nvec3 nonPerturbedNormal = normal;",normal_fragment_maps:"#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif",normal_pars_fragment:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_pars_vertex:"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif",normal_vertex:"#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef USE_NORMALMAP_OBJECTSPACE\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) )\n\tmat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( uv.st );\n\t\tvec2 st1 = dFdy( uv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det );\n\t\treturn mat3( T * scale, B * scale, N );\n\t}\n#endif",clearcoat_normal_fragment_begin:"#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = nonPerturbedNormal;\n#endif",clearcoat_normal_fragment_maps:"#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\tclearcoatNormal = normalize( tbn2 * clearcoatMapN );\n#endif",clearcoat_pars_fragment:"#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif",iridescence_pars_fragment:"#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif",opaque_fragment:"#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;const float ShiftRight8 = 1. / 256.;\nconst float Inv255 = 1. / 255.;\nconst vec4 PackFactors = vec4( 1.0, 256.0, 256.0 * 256.0, 256.0 * 256.0 * 256.0 );\nconst vec2 UnpackFactors2 = vec2( UnpackDownscale, 1.0 / PackFactors.g );\nconst vec3 UnpackFactors3 = vec3( UnpackDownscale / PackFactors.rg, 1.0 / PackFactors.b );\nconst vec4 UnpackFactors4 = vec4( UnpackDownscale / PackFactors.rgb, 1.0 / PackFactors.a );\nvec4 packDepthToRGBA( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec4( 0., 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec4( 1., 1., 1., 1. );\n\tfloat vuf;\n\tfloat af = modf( v * PackFactors.a, vuf );\n\tfloat bf = modf( vuf * ShiftRight8, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec4( vuf * Inv255, gf * PackUpscale, bf * PackUpscale, af );\n}\nvec3 packDepthToRGB( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec3( 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec3( 1., 1., 1. );\n\tfloat vuf;\n\tfloat bf = modf( v * PackFactors.b, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec3( vuf * Inv255, gf * PackUpscale, bf );\n}\nvec2 packDepthToRG( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec2( 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec2( 1., 1. );\n\tfloat vuf;\n\tfloat gf = modf( v * 256., vuf );\n\treturn vec2( vuf * Inv255, gf );\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors4 );\n}\nfloat unpackRGBToDepth( const in vec3 v ) {\n\treturn dot( v, UnpackFactors3 );\n}\nfloat unpackRGToDepth( const in vec2 v ) {\n\treturn v.r * UnpackFactors2.r + v.g * UnpackFactors2.g;\n}\nvec4 pack2HalfToRGBA( const in vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( const in vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn depth * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * depth - far );\n}",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif",project_vertex:"vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_BATCHING\n\tmvPosition = batchingMatrix * mvPosition;\n#endif\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;",dithering_fragment:"#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif",dithering_pars_fragment:"#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tfloat shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\t\n\t\tfloat lightToPositionLength = length( lightToPosition );\n\t\tif ( lightToPositionLength - shadowCameraFar <= 0.0 && lightToPositionLength - shadowCameraNear >= 0.0 ) {\n\t\t\tfloat dp = ( lightToPositionLength - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\t\tdp += shadowBias;\n\t\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\t\tshadow = (\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t\t) * ( 1.0 / 9.0 );\n\t\t\t#else\n\t\t\t\tshadow = texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t\t#endif\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\n\t}\n#endif",shadowmap_pars_vertex:"#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowIntensity;\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif",shadowmap_vertex:"#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowIntensity, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowIntensity, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowIntensity, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tint size = textureSize( boneTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( boneTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( boneTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( boneTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( boneTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\n\t}\n#endif",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vSpecularMapUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif",tonemapping_pars_fragment:"#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn saturate( toneMappingExposure * color );\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 CineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nconst mat3 LINEAR_REC2020_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.6605, - 0.1246, - 0.0182 ),\n\tvec3( - 0.5876, 1.1329, - 0.1006 ),\n\tvec3( - 0.0728, - 0.0083, 1.1187 )\n);\nconst mat3 LINEAR_SRGB_TO_LINEAR_REC2020 = mat3(\n\tvec3( 0.6274, 0.0691, 0.0164 ),\n\tvec3( 0.3293, 0.9195, 0.0880 ),\n\tvec3( 0.0433, 0.0113, 0.8956 )\n);\nvec3 agxDefaultContrastApprox( vec3 x ) {\n\tvec3 x2 = x * x;\n\tvec3 x4 = x2 * x2;\n\treturn + 15.5 * x4 * x2\n\t\t- 40.14 * x4 * x\n\t\t+ 31.96 * x4\n\t\t- 6.868 * x2 * x\n\t\t+ 0.4298 * x2\n\t\t+ 0.1191 * x\n\t\t- 0.00232;\n}\nvec3 AgXToneMapping( vec3 color ) {\n\tconst mat3 AgXInsetMatrix = mat3(\n\t\tvec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ),\n\t\tvec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ),\n\t\tvec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 )\n\t);\n\tconst mat3 AgXOutsetMatrix = mat3(\n\t\tvec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ),\n\t\tvec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ),\n\t\tvec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 )\n\t);\n\tconst float AgxMinEv = - 12.47393;\tconst float AgxMaxEv = 4.026069;\n\tcolor *= toneMappingExposure;\n\tcolor = LINEAR_SRGB_TO_LINEAR_REC2020 * color;\n\tcolor = AgXInsetMatrix * color;\n\tcolor = max( color, 1e-10 );\tcolor = log2( color );\n\tcolor = ( color - AgxMinEv ) / ( AgxMaxEv - AgxMinEv );\n\tcolor = clamp( color, 0.0, 1.0 );\n\tcolor = agxDefaultContrastApprox( color );\n\tcolor = AgXOutsetMatrix * color;\n\tcolor = pow( max( vec3( 0.0 ), color ), vec3( 2.2 ) );\n\tcolor = LINEAR_REC2020_TO_LINEAR_SRGB * color;\n\tcolor = clamp( color, 0.0, 1.0 );\n\treturn color;\n}\nvec3 NeutralToneMapping( vec3 color ) {\n\tconst float StartCompression = 0.8 - 0.04;\n\tconst float Desaturation = 0.15;\n\tcolor *= toneMappingExposure;\n\tfloat x = min( color.r, min( color.g, color.b ) );\n\tfloat offset = x < 0.08 ? x - 6.25 * x * x : 0.04;\n\tcolor -= offset;\n\tfloat peak = max( color.r, max( color.g, color.b ) );\n\tif ( peak < StartCompression ) return color;\n\tfloat d = 1. - StartCompression;\n\tfloat newPeak = 1. - d * d / ( peak + d - StartCompression );\n\tcolor *= newPeak / peak;\n\tfloat g = 1. - 1. / ( Desaturation * ( peak - newPeak ) + 1. );\n\treturn mix( color, vec3( newPeak ), g );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }",transmission_fragment:"#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.dispersion, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );\n#endif",transmission_pars_fragment:"#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float dispersion, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec4 transmittedLight;\n\t\tvec3 transmittance;\n\t\t#ifdef USE_DISPERSION\n\t\t\tfloat halfSpread = ( ior - 1.0 ) * 0.025 * dispersion;\n\t\t\tvec3 iors = vec3( ior - halfSpread, ior, ior + halfSpread );\n\t\t\tfor ( int i = 0; i < 3; i ++ ) {\n\t\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, iors[ i ], modelMatrix );\n\t\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\t\trefractionCoords += 1.0;\n\t\t\t\trefractionCoords /= 2.0;\n\t\t\t\tvec4 transmissionSample = getTransmissionSample( refractionCoords, roughness, iors[ i ] );\n\t\t\t\ttransmittedLight[ i ] = transmissionSample[ i ];\n\t\t\t\ttransmittedLight.a += transmissionSample.a;\n\t\t\t\ttransmittance[ i ] = diffuseColor[ i ] * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance )[ i ];\n\t\t\t}\n\t\t\ttransmittedLight.a /= 3.0;\n\t\t#else\n\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\trefractionCoords += 1.0;\n\t\t\trefractionCoords /= 2.0;\n\t\t\ttransmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\t\ttransmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\t#endif\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\t}\n#endif",uv_pars_fragment:"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif",uv_pars_vertex:"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif",uv_vertex:"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_BATCHING\n\t\tworldPosition = batchingMatrix * worldPosition;\n\t#endif\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif",background_vert:"varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}",background_frag:"uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\ttexColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}",backgroundCube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",backgroundCube_frag:"#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float flipEnvMap;\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nuniform mat3 backgroundRotation;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, backgroundRotation * vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, backgroundRotation * vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include \n\t#include \n}",cube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldDirection;\nvoid main() {\n\tvec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );\n\tgl_FragColor = texColor;\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvHighPrecisionZW = gl_Position.zw;\n}",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#elif DEPTH_PACKING == 3202\n\t\tgl_FragColor = vec4( packDepthToRGB( fragCoordZ ), 1.0 );\n\t#elif DEPTH_PACKING == 3203\n\t\tgl_FragColor = vec4( packDepthToRG( fragCoordZ ), 0.0, 1.0 );\n\t#endif\n}",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}",distanceRGBA_frag:"#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}",equirect_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include \n\t#include \n}",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",linedashed_frag:"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_vert:"#define LAMBERT\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_frag:"#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_vert:"#define MATCAP\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}",meshmatcap_frag:"#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshnormal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}",meshnormal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( 0.0, 0.0, 0.0, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), diffuseColor.a );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}",meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphong_frag:"#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_vert:"#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}",meshphysical_frag:"#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define USE_SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_DISPERSION\n\tuniform float dispersion;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include \n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecularDirect + sheenSpecularIndirect;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * material.clearcoat;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshtoon_vert:"#define TOON\nvarying vec3 vViewPosition;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}",meshtoon_frag:"#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}",points_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}",sprite_vert:"uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix[ 3 ];\n\tvec2 scale = vec2( length( modelMatrix[ 0 ].xyz ), length( modelMatrix[ 1 ].xyz ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}",sprite_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\t#include \n\t#include \n\t#include \n\t#include \n}"},Dn={common:{diffuse:{value:new e(16777215)},opacity:{value:1},map:{value:null},mapTransform:{value:new t},alphaMap:{value:null},alphaMapTransform:{value:new t},alphaTest:{value:0}},specularmap:{specularMap:{value:null},specularMapTransform:{value:new t}},envmap:{envMap:{value:null},envMapRotation:{value:new t},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1},aoMapTransform:{value:new t}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1},lightMapTransform:{value:new t}},bumpmap:{bumpMap:{value:null},bumpMapTransform:{value:new t},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalMapTransform:{value:new t},normalScale:{value:new n(1,1)}},displacementmap:{displacementMap:{value:null},displacementMapTransform:{value:new t},displacementScale:{value:1},displacementBias:{value:0}},emissivemap:{emissiveMap:{value:null},emissiveMapTransform:{value:new t}},metalnessmap:{metalnessMap:{value:null},metalnessMapTransform:{value:new t}},roughnessmap:{roughnessMap:{value:null},roughnessMapTransform:{value:new t}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new e(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotLightMap:{value:[]},spotShadowMap:{value:[]},spotLightMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMap:{value:[]},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}},ltc_1:{value:null},ltc_2:{value:null}},points:{diffuse:{value:new e(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaMapTransform:{value:new t},alphaTest:{value:0},uvTransform:{value:new t}},sprite:{diffuse:{value:new e(16777215)},opacity:{value:1},center:{value:new n(.5,.5)},rotation:{value:0},map:{value:null},mapTransform:{value:new t},alphaMap:{value:null},alphaMapTransform:{value:new t},alphaTest:{value:0}}},yn={basic:{uniforms:i([Dn.common,Dn.specularmap,Dn.envmap,Dn.aomap,Dn.lightmap,Dn.fog]),vertexShader:wn.meshbasic_vert,fragmentShader:wn.meshbasic_frag},lambert:{uniforms:i([Dn.common,Dn.specularmap,Dn.envmap,Dn.aomap,Dn.lightmap,Dn.emissivemap,Dn.bumpmap,Dn.normalmap,Dn.displacementmap,Dn.fog,Dn.lights,{emissive:{value:new e(0)}}]),vertexShader:wn.meshlambert_vert,fragmentShader:wn.meshlambert_frag},phong:{uniforms:i([Dn.common,Dn.specularmap,Dn.envmap,Dn.aomap,Dn.lightmap,Dn.emissivemap,Dn.bumpmap,Dn.normalmap,Dn.displacementmap,Dn.fog,Dn.lights,{emissive:{value:new e(0)},specular:{value:new e(1118481)},shininess:{value:30}}]),vertexShader:wn.meshphong_vert,fragmentShader:wn.meshphong_frag},standard:{uniforms:i([Dn.common,Dn.envmap,Dn.aomap,Dn.lightmap,Dn.emissivemap,Dn.bumpmap,Dn.normalmap,Dn.displacementmap,Dn.roughnessmap,Dn.metalnessmap,Dn.fog,Dn.lights,{emissive:{value:new e(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:wn.meshphysical_vert,fragmentShader:wn.meshphysical_frag},toon:{uniforms:i([Dn.common,Dn.aomap,Dn.lightmap,Dn.emissivemap,Dn.bumpmap,Dn.normalmap,Dn.displacementmap,Dn.gradientmap,Dn.fog,Dn.lights,{emissive:{value:new e(0)}}]),vertexShader:wn.meshtoon_vert,fragmentShader:wn.meshtoon_frag},matcap:{uniforms:i([Dn.common,Dn.bumpmap,Dn.normalmap,Dn.displacementmap,Dn.fog,{matcap:{value:null}}]),vertexShader:wn.meshmatcap_vert,fragmentShader:wn.meshmatcap_frag},points:{uniforms:i([Dn.points,Dn.fog]),vertexShader:wn.points_vert,fragmentShader:wn.points_frag},dashed:{uniforms:i([Dn.common,Dn.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:wn.linedashed_vert,fragmentShader:wn.linedashed_frag},depth:{uniforms:i([Dn.common,Dn.displacementmap]),vertexShader:wn.depth_vert,fragmentShader:wn.depth_frag},normal:{uniforms:i([Dn.common,Dn.bumpmap,Dn.normalmap,Dn.displacementmap,{opacity:{value:1}}]),vertexShader:wn.meshnormal_vert,fragmentShader:wn.meshnormal_frag},sprite:{uniforms:i([Dn.sprite,Dn.fog]),vertexShader:wn.sprite_vert,fragmentShader:wn.sprite_frag},background:{uniforms:{uvTransform:{value:new t},t2D:{value:null},backgroundIntensity:{value:1}},vertexShader:wn.background_vert,fragmentShader:wn.background_frag},backgroundCube:{uniforms:{envMap:{value:null},flipEnvMap:{value:-1},backgroundBlurriness:{value:0},backgroundIntensity:{value:1},backgroundRotation:{value:new t}},vertexShader:wn.backgroundCube_vert,fragmentShader:wn.backgroundCube_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:wn.cube_vert,fragmentShader:wn.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:wn.equirect_vert,fragmentShader:wn.equirect_frag},distanceRGBA:{uniforms:i([Dn.common,Dn.displacementmap,{referencePosition:{value:new r},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:wn.distanceRGBA_vert,fragmentShader:wn.distanceRGBA_frag},shadow:{uniforms:i([Dn.lights,Dn.fog,{color:{value:new e(0)},opacity:{value:1}}]),vertexShader:wn.shadow_vert,fragmentShader:wn.shadow_frag}};yn.physical={uniforms:i([yn.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatMapTransform:{value:new t},clearcoatNormalMap:{value:null},clearcoatNormalMapTransform:{value:new t},clearcoatNormalScale:{value:new n(1,1)},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatRoughnessMapTransform:{value:new t},dispersion:{value:0},iridescence:{value:0},iridescenceMap:{value:null},iridescenceMapTransform:{value:new t},iridescenceIOR:{value:1.3},iridescenceThicknessMinimum:{value:100},iridescenceThicknessMaximum:{value:400},iridescenceThicknessMap:{value:null},iridescenceThicknessMapTransform:{value:new t},sheen:{value:0},sheenColor:{value:new e(0)},sheenColorMap:{value:null},sheenColorMapTransform:{value:new t},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},sheenRoughnessMapTransform:{value:new t},transmission:{value:0},transmissionMap:{value:null},transmissionMapTransform:{value:new t},transmissionSamplerSize:{value:new n},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},thicknessMapTransform:{value:new t},attenuationDistance:{value:0},attenuationColor:{value:new e(0)},specularColor:{value:new e(1,1,1)},specularColorMap:{value:null},specularColorMapTransform:{value:new t},specularIntensity:{value:1},specularIntensityMap:{value:null},specularIntensityMapTransform:{value:new t},anisotropyVector:{value:new n},anisotropyMap:{value:null},anisotropyMapTransform:{value:new t}}]),vertexShader:wn.meshphysical_vert,fragmentShader:wn.meshphysical_frag};const In={r:0,b:0,g:0},Nn=new _,On=new g;function Fn(t,n,i,r,_,g,v){const E=new e(0);let S,T,M=!0===g?0:1,x=null,R=0,A=null;function b(e){let t=!0===e.isScene?e.background:null;if(t&&t.isTexture){t=(e.backgroundBlurriness>0?i:n).get(t)}return t}function C(e,n){e.getRGB(In,h(t)),r.buffers.color.setClear(In.r,In.g,In.b,n,v)}return{getClearColor:function(){return E},setClearColor:function(e,t=1){E.set(e),M=t,C(E,M)},getClearAlpha:function(){return M},setClearAlpha:function(e){M=e,C(E,M)},render:function(e){let n=!1;const i=b(e);null===i?C(E,M):i&&i.isColor&&(C(i,1),n=!0);const a=t.xr.getEnvironmentBlendMode();"additive"===a?r.buffers.color.setClear(0,0,0,1,v):"alpha-blend"===a&&r.buffers.color.setClear(0,0,0,0,v),(t.autoClear||n)&&(r.buffers.depth.setTest(!0),r.buffers.depth.setMask(!0),r.buffers.color.setMask(!0),t.clear(t.autoClearColor,t.autoClearDepth,t.autoClearStencil))},addToRenderList:function(e,n){const i=b(n);i&&(i.isCubeTexture||i.mapping===a)?(void 0===T&&(T=new o(new s(1,1,1),new l({name:"BackgroundCubeMaterial",uniforms:c(yn.backgroundCube.uniforms),vertexShader:yn.backgroundCube.vertexShader,fragmentShader:yn.backgroundCube.fragmentShader,side:d,depthTest:!1,depthWrite:!1,fog:!1})),T.geometry.deleteAttribute("normal"),T.geometry.deleteAttribute("uv"),T.onBeforeRender=function(e,t,n){this.matrixWorld.copyPosition(n.matrixWorld)},Object.defineProperty(T.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),_.update(T)),Nn.copy(n.backgroundRotation),Nn.x*=-1,Nn.y*=-1,Nn.z*=-1,i.isCubeTexture&&!1===i.isRenderTargetTexture&&(Nn.y*=-1,Nn.z*=-1),T.material.uniforms.envMap.value=i,T.material.uniforms.flipEnvMap.value=i.isCubeTexture&&!1===i.isRenderTargetTexture?-1:1,T.material.uniforms.backgroundBlurriness.value=n.backgroundBlurriness,T.material.uniforms.backgroundIntensity.value=n.backgroundIntensity,T.material.uniforms.backgroundRotation.value.setFromMatrix4(On.makeRotationFromEuler(Nn)),T.material.toneMapped=u.getTransfer(i.colorSpace)!==f,x===i&&R===i.version&&A===t.toneMapping||(T.material.needsUpdate=!0,x=i,R=i.version,A=t.toneMapping),T.layers.enableAll(),e.unshift(T,T.geometry,T.material,0,0,null)):i&&i.isTexture&&(void 0===S&&(S=new o(new p(2,2),new l({name:"BackgroundMaterial",uniforms:c(yn.background.uniforms),vertexShader:yn.background.vertexShader,fragmentShader:yn.background.fragmentShader,side:m,depthTest:!1,depthWrite:!1,fog:!1})),S.geometry.deleteAttribute("normal"),Object.defineProperty(S.material,"map",{get:function(){return this.uniforms.t2D.value}}),_.update(S)),S.material.uniforms.t2D.value=i,S.material.uniforms.backgroundIntensity.value=n.backgroundIntensity,S.material.toneMapped=u.getTransfer(i.colorSpace)!==f,!0===i.matrixAutoUpdate&&i.updateMatrix(),S.material.uniforms.uvTransform.value.copy(i.matrix),x===i&&R===i.version&&A===t.toneMapping||(S.material.needsUpdate=!0,x=i,R=i.version,A=t.toneMapping),S.layers.enableAll(),e.unshift(S,S.geometry,S.material,0,0,null))},dispose:function(){void 0!==T&&(T.geometry.dispose(),T.material.dispose(),T=void 0),void 0!==S&&(S.geometry.dispose(),S.material.dispose(),S=void 0)}}}function Bn(e,t){const n=e.getParameter(e.MAX_VERTEX_ATTRIBS),i={},r=c(null);let a=r,o=!1;function s(t){return e.bindVertexArray(t)}function l(t){return e.deleteVertexArray(t)}function c(e){const t=[],i=[],r=[];for(let e=0;e=0){const n=r[t];let i=o[t];if(void 0===i&&("instanceMatrix"===t&&e.instanceMatrix&&(i=e.instanceMatrix),"instanceColor"===t&&e.instanceColor&&(i=e.instanceColor)),void 0===n)return!0;if(n.attribute!==i)return!0;if(i&&n.data!==i.data)return!0;s++}}return a.attributesNum!==s||a.index!==i}(n,h,l,_),g&&function(e,t,n,i){const r={},o=t.attributes;let s=0;const l=n.getAttributes();for(const t in l){if(l[t].location>=0){let n=o[t];void 0===n&&("instanceMatrix"===t&&e.instanceMatrix&&(n=e.instanceMatrix),"instanceColor"===t&&e.instanceColor&&(n=e.instanceColor));const i={};i.attribute=n,n&&n.data&&(i.data=n.data),r[t]=i,s++}}a.attributes=r,a.attributesNum=s,a.index=i}(n,h,l,_),null!==_&&t.update(_,e.ELEMENT_ARRAY_BUFFER),(g||o)&&(o=!1,function(n,i,r,a){d();const o=a.attributes,s=r.getAttributes(),l=i.defaultAttributeValues;for(const i in s){const r=s[i];if(r.location>=0){let s=o[i];if(void 0===s&&("instanceMatrix"===i&&n.instanceMatrix&&(s=n.instanceMatrix),"instanceColor"===i&&n.instanceColor&&(s=n.instanceColor)),void 0!==s){const i=s.normalized,o=s.itemSize,l=t.get(s);if(void 0===l)continue;const c=l.buffer,d=l.type,p=l.bytesPerElement,h=d===e.INT||d===e.UNSIGNED_INT||s.gpuType===v;if(s.isInterleavedBufferAttribute){const t=s.data,l=t.stride,_=s.offset;if(t.isInstancedInterleavedBuffer){for(let e=0;e0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT).precision>0)return"highp";t="mediump"}return"mediump"===t&&e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_FLOAT).precision>0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT).precision>0?"mediump":"lowp"}let o=void 0!==n.precision?n.precision:"highp";const s=a(o);s!==o&&(console.warn("THREE.WebGLRenderer:",o,"not supported, using",s,"instead."),o=s);const l=!0===n.logarithmicDepthBuffer,c=!0===n.reverseDepthBuffer&&t.has("EXT_clip_control"),d=e.getParameter(e.MAX_TEXTURE_IMAGE_UNITS),u=e.getParameter(e.MAX_VERTEX_TEXTURE_IMAGE_UNITS);return{isWebGL2:!0,getMaxAnisotropy:function(){if(void 0!==r)return r;if(!0===t.has("EXT_texture_filter_anisotropic")){const n=t.get("EXT_texture_filter_anisotropic");r=e.getParameter(n.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else r=0;return r},getMaxPrecision:a,textureFormatReadable:function(t){return t===E||i.convert(t)===e.getParameter(e.IMPLEMENTATION_COLOR_READ_FORMAT)},textureTypeReadable:function(n){const r=n===S&&(t.has("EXT_color_buffer_half_float")||t.has("EXT_color_buffer_float"));return!(n!==T&&i.convert(n)!==e.getParameter(e.IMPLEMENTATION_COLOR_READ_TYPE)&&n!==M&&!r)},precision:o,logarithmicDepthBuffer:l,reverseDepthBuffer:c,maxTextures:d,maxVertexTextures:u,maxTextureSize:e.getParameter(e.MAX_TEXTURE_SIZE),maxCubemapSize:e.getParameter(e.MAX_CUBE_MAP_TEXTURE_SIZE),maxAttributes:e.getParameter(e.MAX_VERTEX_ATTRIBS),maxVertexUniforms:e.getParameter(e.MAX_VERTEX_UNIFORM_VECTORS),maxVaryings:e.getParameter(e.MAX_VARYING_VECTORS),maxFragmentUniforms:e.getParameter(e.MAX_FRAGMENT_UNIFORM_VECTORS),vertexTextures:u>0,maxSamples:e.getParameter(e.MAX_SAMPLES)}}function Vn(e){const n=this;let i=null,r=0,a=!1,o=!1;const s=new x,l=new t,c={value:null,needsUpdate:!1};function d(e,t,i,r){const a=null!==e?e.length:0;let o=null;if(0!==a){if(o=c.value,!0!==r||null===o){const n=i+4*a,r=t.matrixWorldInverse;l.getNormalMatrix(r),(null===o||o.length0);n.numPlanes=r,n.numIntersection=0}();else{const e=o?0:r,t=4*e;let n=m.clippingState||null;c.value=n,n=d(u,s,t,l);for(let e=0;e!==t;++e)n[e]=i[e];m.clippingState=n,this.numIntersection=f?this.numPlanes:0,this.numPlanes+=e}}}function zn(e){let t=new WeakMap;function n(e,t){return t===R?e.mapping=C:t===A&&(e.mapping=L),e}function i(e){const n=e.target;n.removeEventListener("dispose",i);const r=t.get(n);void 0!==r&&(t.delete(n),r.dispose())}return{get:function(r){if(r&&r.isTexture){const a=r.mapping;if(a===R||a===A){if(t.has(r)){return n(t.get(r).texture,r.mapping)}{const a=r.image;if(a&&a.height>0){const o=new b(a.height);return o.fromEquirectangularTexture(e,r),t.set(r,o),r.addEventListener("dispose",i),n(o.texture,r.mapping)}return null}}}return r},dispose:function(){t=new WeakMap}}}const kn=[.125,.215,.35,.446,.526,.582],Wn=20,Xn=new O,Yn=new e;let jn=null,Kn=0,qn=0,Zn=!1;const $n=(1+Math.sqrt(5))/2,Qn=1/$n,Jn=[new r(-$n,Qn,0),new r($n,Qn,0),new r(-Qn,0,$n),new r(Qn,0,$n),new r(0,$n,-Qn),new r(0,$n,Qn),new r(-1,1,-1),new r(1,1,-1),new r(-1,1,1),new r(1,1,1)];class ei{constructor(e){this._renderer=e,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._lodPlanes=[],this._sizeLods=[],this._sigmas=[],this._blurMaterial=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._compileMaterial(this._blurMaterial)}fromScene(e,t=0,n=.1,i=100){jn=this._renderer.getRenderTarget(),Kn=this._renderer.getActiveCubeFace(),qn=this._renderer.getActiveMipmapLevel(),Zn=this._renderer.xr.enabled,this._renderer.xr.enabled=!1,this._setSize(256);const r=this._allocateTargets();return r.depthBuffer=!0,this._sceneToCubeUV(e,n,i,r),t>0&&this._blur(r,0,0,t),this._applyPMREM(r),this._cleanup(r),r}fromEquirectangular(e,t=null){return this._fromTexture(e,t)}fromCubemap(e,t=null){return this._fromTexture(e,t)}compileCubemapShader(){null===this._cubemapMaterial&&(this._cubemapMaterial=ri(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){null===this._equirectMaterial&&(this._equirectMaterial=ii(),this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),null!==this._cubemapMaterial&&this._cubemapMaterial.dispose(),null!==this._equirectMaterial&&this._equirectMaterial.dispose()}_setSize(e){this._lodMax=Math.floor(Math.log2(e)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){null!==this._blurMaterial&&this._blurMaterial.dispose(),null!==this._pingPongRenderTarget&&this._pingPongRenderTarget.dispose();for(let e=0;ee-4?s=kn[o-e+4-1]:0===o&&(s=0),i.push(s);const l=1/(a-2),c=-l,d=1+l,u=[c,c,d,c,d,d,c,c,d,d,c,d],f=6,p=6,m=3,h=2,_=1,g=new Float32Array(m*p*f),v=new Float32Array(h*p*f),E=new Float32Array(_*p*f);for(let e=0;e2?0:-1,i=[t,n,0,t+2/3,n,0,t+2/3,n+1,0,t,n,0,t+2/3,n+1,0,t,n+1,0];g.set(i,m*p*e),v.set(u,h*p*e);const r=[e,e,e,e,e,e];E.set(r,_*p*e)}const S=new D;S.setAttribute("position",new y(g,m)),S.setAttribute("uv",new y(v,h)),S.setAttribute("faceIndex",new y(E,_)),t.push(S),r>4&&r--}return{lodPlanes:t,sizeLods:n,sigmas:i}}(i)),this._blurMaterial=function(e,t,n){const i=new Float32Array(Wn),a=new r(0,1,0),o=new l({name:"SphericalGaussianBlur",defines:{n:Wn,CUBEUV_TEXEL_WIDTH:1/t,CUBEUV_TEXEL_HEIGHT:1/n,CUBEUV_MAX_MIP:`${e}.0`},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:i},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:a}},vertexShader:ai(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\t\t\tuniform int samples;\n\t\t\tuniform float weights[ n ];\n\t\t\tuniform bool latitudinal;\n\t\t\tuniform float dTheta;\n\t\t\tuniform float mipInt;\n\t\t\tuniform vec3 poleAxis;\n\n\t\t\t#define ENVMAP_TYPE_CUBE_UV\n\t\t\t#include \n\n\t\t\tvec3 getSample( float theta, vec3 axis ) {\n\n\t\t\t\tfloat cosTheta = cos( theta );\n\t\t\t\t// Rodrigues' axis-angle rotation\n\t\t\t\tvec3 sampleDirection = vOutputDirection * cosTheta\n\t\t\t\t\t+ cross( axis, vOutputDirection ) * sin( theta )\n\t\t\t\t\t+ axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );\n\n\t\t\t\treturn bilinearCubeUV( envMap, sampleDirection, mipInt );\n\n\t\t\t}\n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );\n\n\t\t\t\tif ( all( equal( axis, vec3( 0.0 ) ) ) ) {\n\n\t\t\t\t\taxis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );\n\n\t\t\t\t}\n\n\t\t\t\taxis = normalize( axis );\n\n\t\t\t\tgl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t\t\t\tgl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );\n\n\t\t\t\tfor ( int i = 1; i < n; i++ ) {\n\n\t\t\t\t\tif ( i >= samples ) {\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tfloat theta = dTheta * float( i );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );\n\t\t\t\t\tgl_FragColor.rgb += weights[ i ] * getSample( theta, axis );\n\n\t\t\t\t}\n\n\t\t\t}\n\t\t",blending:N,depthTest:!1,depthWrite:!1});return o}(i,e,t)}return i}_compileMaterial(e){const t=new o(this._lodPlanes[0],e);this._renderer.compile(t,Xn)}_sceneToCubeUV(e,t,n,i){const r=new P(90,1,t,n),a=[1,-1,1,1,1,1],l=[1,1,1,-1,-1,-1],c=this._renderer,u=c.autoClear,f=c.toneMapping;c.getClearColor(Yn),c.toneMapping=U,c.autoClear=!1;const p=new w({name:"PMREM.Background",side:d,depthWrite:!1,depthTest:!1}),m=new o(new s,p);let h=!1;const _=e.background;_?_.isColor&&(p.color.copy(_),e.background=null,h=!0):(p.color.copy(Yn),h=!0);for(let t=0;t<6;t++){const n=t%3;0===n?(r.up.set(0,a[t],0),r.lookAt(l[t],0,0)):1===n?(r.up.set(0,0,a[t]),r.lookAt(0,l[t],0)):(r.up.set(0,a[t],0),r.lookAt(0,0,l[t]));const o=this._cubeSize;ni(i,n*o,t>2?o:0,o,o),c.setRenderTarget(i),h&&c.render(m,r),c.render(e,r)}m.geometry.dispose(),m.material.dispose(),c.toneMapping=f,c.autoClear=u,e.background=_}_textureToCubeUV(e,t){const n=this._renderer,i=e.mapping===C||e.mapping===L;i?(null===this._cubemapMaterial&&(this._cubemapMaterial=ri()),this._cubemapMaterial.uniforms.flipEnvMap.value=!1===e.isRenderTargetTexture?-1:1):null===this._equirectMaterial&&(this._equirectMaterial=ii());const r=i?this._cubemapMaterial:this._equirectMaterial,a=new o(this._lodPlanes[0],r);r.uniforms.envMap.value=e;const s=this._cubeSize;ni(t,0,0,3*s,2*s),n.setRenderTarget(t),n.render(a,Xn)}_applyPMREM(e){const t=this._renderer,n=t.autoClear;t.autoClear=!1;const i=this._lodPlanes.length;for(let t=1;tWn&&console.warn(`sigmaRadians, ${r}, is too large and will clip, as it requested ${h} samples when the maximum is set to 20`);const _=[];let g=0;for(let e=0;ev-4?i-v+4:0),4*(this._cubeSize-E),3*E,2*E),l.setRenderTarget(t),l.render(d,Xn)}}function ti(e,t,n){const i=new I(e,t,n);return i.texture.mapping=a,i.texture.name="PMREM.cubeUv",i.scissorTest=!0,i}function ni(e,t,n,i,r){e.viewport.set(t,n,i,r),e.scissor.set(t,n,i,r)}function ii(){return new l({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null}},vertexShader:ai(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform sampler2D envMap;\n\n\t\t\t#include \n\n\t\t\tvoid main() {\n\n\t\t\t\tvec3 outputDirection = normalize( vOutputDirection );\n\t\t\t\tvec2 uv = equirectUv( outputDirection );\n\n\t\t\t\tgl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 );\n\n\t\t\t}\n\t\t",blending:N,depthTest:!1,depthWrite:!1})}function ri(){return new l({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:ai(),fragmentShader:"\n\n\t\t\tprecision mediump float;\n\t\t\tprecision mediump int;\n\n\t\t\tuniform float flipEnvMap;\n\n\t\t\tvarying vec3 vOutputDirection;\n\n\t\t\tuniform samplerCube envMap;\n\n\t\t\tvoid main() {\n\n\t\t\t\tgl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) );\n\n\t\t\t}\n\t\t",blending:N,depthTest:!1,depthWrite:!1})}function ai(){return"\n\n\t\tprecision mediump float;\n\t\tprecision mediump int;\n\n\t\tattribute float faceIndex;\n\n\t\tvarying vec3 vOutputDirection;\n\n\t\t// RH coordinate system; PMREM face-indexing convention\n\t\tvec3 getDirection( vec2 uv, float face ) {\n\n\t\t\tuv = 2.0 * uv - 1.0;\n\n\t\t\tvec3 direction = vec3( uv, 1.0 );\n\n\t\t\tif ( face == 0.0 ) {\n\n\t\t\t\tdirection = direction.zyx; // ( 1, v, u ) pos x\n\n\t\t\t} else if ( face == 1.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xz *= -1.0; // ( -u, 1, -v ) pos y\n\n\t\t\t} else if ( face == 2.0 ) {\n\n\t\t\t\tdirection.x *= -1.0; // ( -u, v, 1 ) pos z\n\n\t\t\t} else if ( face == 3.0 ) {\n\n\t\t\t\tdirection = direction.zyx;\n\t\t\t\tdirection.xz *= -1.0; // ( -1, v, -u ) neg x\n\n\t\t\t} else if ( face == 4.0 ) {\n\n\t\t\t\tdirection = direction.xzy;\n\t\t\t\tdirection.xy *= -1.0; // ( -u, -1, v ) neg y\n\n\t\t\t} else if ( face == 5.0 ) {\n\n\t\t\t\tdirection.z *= -1.0; // ( u, v, -1 ) neg z\n\n\t\t\t}\n\n\t\t\treturn direction;\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tvOutputDirection = getDirection( uv, faceIndex );\n\t\t\tgl_Position = vec4( position, 1.0 );\n\n\t\t}\n\t"}function oi(e){let t=new WeakMap,n=null;function i(e){const n=e.target;n.removeEventListener("dispose",i);const r=t.get(n);void 0!==r&&(t.delete(n),r.dispose())}return{get:function(r){if(r&&r.isTexture){const a=r.mapping,o=a===R||a===A,s=a===C||a===L;if(o||s){let a=t.get(r);const l=void 0!==a?a.texture.pmremVersion:0;if(r.isRenderTargetTexture&&r.pmremVersion!==l)return null===n&&(n=new ei(e)),a=o?n.fromEquirectangular(r,a):n.fromCubemap(r,a),a.texture.pmremVersion=r.pmremVersion,t.set(r,a),a.texture;if(void 0!==a)return a.texture;{const l=r.image;return o&&l&&l.height>0||s&&l&&function(e){let t=0;const n=6;for(let i=0;it.maxTextureSize&&(T=Math.ceil(S/t.maxTextureSize),S=t.maxTextureSize);const x=new Float32Array(S*T*4*u),R=new W(x,S,T,u);R.type=M,R.needsUpdate=!0;const A=4*E;for(let C=0;C0)return e;const r=t*n;let a=vi[r];if(void 0===a&&(a=new Float32Array(r),vi[r]=a),0!==t){i.toArray(a,0);for(let i=1,r=0;i!==t;++i)r+=n,e[i].toArray(a,r)}return a}function Ri(e,t){if(e.length!==t.length)return!1;for(let n=0,i=e.length;n":" "} ${r}: ${n[e]}`)}return i.join("\n")}(e.getShaderSource(t),i)}return r}function Mr(e,t){const n=function(e){u._getMatrix(Sr,u.workingColorSpace,e);const t=`mat3( ${Sr.elements.map((e=>e.toFixed(4)))} )`;switch(u.getTransfer(e)){case se:return[t,"LinearTransferOETF"];case f:return[t,"sRGBTransferOETF"];default:return console.warn("THREE.WebGLProgram: Unsupported color space: ",e),[t,"LinearTransferOETF"]}}(t);return[`vec4 ${e}( vec4 value ) {`,`\treturn ${n[1]}( vec4( value.rgb * ${n[0]}, value.a ) );`,"}"].join("\n")}function xr(e,t){let n;switch(t){case ie:n="Linear";break;case ne:n="Reinhard";break;case te:n="Cineon";break;case ee:n="ACESFilmic";break;case J:n="AgX";break;case Q:n="Neutral";break;case $:n="Custom";break;default:console.warn("THREE.WebGLProgram: Unsupported toneMapping:",t),n="Linear"}return"vec3 "+e+"( vec3 color ) { return "+n+"ToneMapping( color ); }"}const Rr=new r;function Ar(){u.getLuminanceCoefficients(Rr);return["float luminance( const in vec3 rgb ) {",`\tconst vec3 weights = vec3( ${Rr.x.toFixed(4)}, ${Rr.y.toFixed(4)}, ${Rr.z.toFixed(4)} );`,"\treturn dot( weights, rgb );","}"].join("\n")}function br(e){return""!==e}function Cr(e,t){const n=t.numSpotLightShadows+t.numSpotLightMaps-t.numSpotLightShadowsWithMaps;return e.replace(/NUM_DIR_LIGHTS/g,t.numDirLights).replace(/NUM_SPOT_LIGHTS/g,t.numSpotLights).replace(/NUM_SPOT_LIGHT_MAPS/g,t.numSpotLightMaps).replace(/NUM_SPOT_LIGHT_COORDS/g,n).replace(/NUM_RECT_AREA_LIGHTS/g,t.numRectAreaLights).replace(/NUM_POINT_LIGHTS/g,t.numPointLights).replace(/NUM_HEMI_LIGHTS/g,t.numHemiLights).replace(/NUM_DIR_LIGHT_SHADOWS/g,t.numDirLightShadows).replace(/NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g,t.numSpotLightShadowsWithMaps).replace(/NUM_SPOT_LIGHT_SHADOWS/g,t.numSpotLightShadows).replace(/NUM_POINT_LIGHT_SHADOWS/g,t.numPointLightShadows)}function Lr(e,t){return e.replace(/NUM_CLIPPING_PLANES/g,t.numClippingPlanes).replace(/UNION_CLIPPING_PLANES/g,t.numClippingPlanes-t.numClipIntersection)}const Pr=/^[ \t]*#include +<([\w\d./]+)>/gm;function Ur(e){return e.replace(Pr,Dr)}const wr=new Map;function Dr(e,t){let n=wn[t];if(void 0===n){const e=wr.get(t);if(void 0===e)throw new Error("Can not resolve #include <"+t+">");n=wn[e],console.warn('THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.',t,e)}return Ur(n)}const yr=/#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;function Ir(e){return e.replace(yr,Nr)}function Nr(e,t,n,i){let r="";for(let e=parseInt(t);e0&&(g+="\n"),v=["#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,h].filter(br).join("\n"),v.length>0&&(v+="\n")):(g=[Or(n),"#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,h,n.extensionClipCullDistance?"#define USE_CLIP_DISTANCE":"",n.batching?"#define USE_BATCHING":"",n.batchingColor?"#define USE_BATCHING_COLOR":"",n.instancing?"#define USE_INSTANCING":"",n.instancingColor?"#define USE_INSTANCING_COLOR":"",n.instancingMorph?"#define USE_INSTANCING_MORPH":"",n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.map?"#define USE_MAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+u:"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",n.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",n.displacementMap?"#define USE_DISPLACEMENTMAP":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.anisotropy?"#define USE_ANISOTROPY":"",n.anisotropyMap?"#define USE_ANISOTROPYMAP":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",n.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",n.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.alphaHash?"#define USE_ALPHAHASH":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",n.mapUv?"#define MAP_UV "+n.mapUv:"",n.alphaMapUv?"#define ALPHAMAP_UV "+n.alphaMapUv:"",n.lightMapUv?"#define LIGHTMAP_UV "+n.lightMapUv:"",n.aoMapUv?"#define AOMAP_UV "+n.aoMapUv:"",n.emissiveMapUv?"#define EMISSIVEMAP_UV "+n.emissiveMapUv:"",n.bumpMapUv?"#define BUMPMAP_UV "+n.bumpMapUv:"",n.normalMapUv?"#define NORMALMAP_UV "+n.normalMapUv:"",n.displacementMapUv?"#define DISPLACEMENTMAP_UV "+n.displacementMapUv:"",n.metalnessMapUv?"#define METALNESSMAP_UV "+n.metalnessMapUv:"",n.roughnessMapUv?"#define ROUGHNESSMAP_UV "+n.roughnessMapUv:"",n.anisotropyMapUv?"#define ANISOTROPYMAP_UV "+n.anisotropyMapUv:"",n.clearcoatMapUv?"#define CLEARCOATMAP_UV "+n.clearcoatMapUv:"",n.clearcoatNormalMapUv?"#define CLEARCOAT_NORMALMAP_UV "+n.clearcoatNormalMapUv:"",n.clearcoatRoughnessMapUv?"#define CLEARCOAT_ROUGHNESSMAP_UV "+n.clearcoatRoughnessMapUv:"",n.iridescenceMapUv?"#define IRIDESCENCEMAP_UV "+n.iridescenceMapUv:"",n.iridescenceThicknessMapUv?"#define IRIDESCENCE_THICKNESSMAP_UV "+n.iridescenceThicknessMapUv:"",n.sheenColorMapUv?"#define SHEEN_COLORMAP_UV "+n.sheenColorMapUv:"",n.sheenRoughnessMapUv?"#define SHEEN_ROUGHNESSMAP_UV "+n.sheenRoughnessMapUv:"",n.specularMapUv?"#define SPECULARMAP_UV "+n.specularMapUv:"",n.specularColorMapUv?"#define SPECULAR_COLORMAP_UV "+n.specularColorMapUv:"",n.specularIntensityMapUv?"#define SPECULAR_INTENSITYMAP_UV "+n.specularIntensityMapUv:"",n.transmissionMapUv?"#define TRANSMISSIONMAP_UV "+n.transmissionMapUv:"",n.thicknessMapUv?"#define THICKNESSMAP_UV "+n.thicknessMapUv:"",n.vertexTangents&&!1===n.flatShading?"#define USE_TANGENT":"",n.vertexColors?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUv1s?"#define USE_UV1":"",n.vertexUv2s?"#define USE_UV2":"",n.vertexUv3s?"#define USE_UV3":"",n.pointsUvs?"#define USE_POINTS_UV":"",n.flatShading?"#define FLAT_SHADED":"",n.skinning?"#define USE_SKINNING":"",n.morphTargets?"#define USE_MORPHTARGETS":"",n.morphNormals&&!1===n.flatShading?"#define USE_MORPHNORMALS":"",n.morphColors?"#define USE_MORPHCOLORS":"",n.morphTargetsCount>0?"#define MORPHTARGETS_TEXTURE_STRIDE "+n.morphTextureStride:"",n.morphTargetsCount>0?"#define MORPHTARGETS_COUNT "+n.morphTargetsCount:"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+c:"",n.sizeAttenuation?"#define USE_SIZEATTENUATION":"",n.numLightProbes>0?"#define USE_LIGHT_PROBES":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",n.reverseDepthBuffer?"#define USE_REVERSEDEPTHBUF":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;","#ifdef USE_INSTANCING","\tattribute mat4 instanceMatrix;","#endif","#ifdef USE_INSTANCING_COLOR","\tattribute vec3 instanceColor;","#endif","#ifdef USE_INSTANCING_MORPH","\tuniform sampler2D morphTexture;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_UV1","\tattribute vec2 uv1;","#endif","#ifdef USE_UV2","\tattribute vec2 uv2;","#endif","#ifdef USE_UV3","\tattribute vec2 uv3;","#endif","#ifdef USE_TANGENT","\tattribute vec4 tangent;","#endif","#if defined( USE_COLOR_ALPHA )","\tattribute vec4 color;","#elif defined( USE_COLOR )","\tattribute vec3 color;","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(br).join("\n"),v=[Or(n),"#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,h,n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.alphaToCoverage?"#define ALPHA_TO_COVERAGE":"",n.map?"#define USE_MAP":"",n.matcap?"#define USE_MATCAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+d:"",n.envMap?"#define "+u:"",n.envMap?"#define "+f:"",p?"#define CUBEUV_TEXEL_WIDTH "+p.texelWidth:"",p?"#define CUBEUV_TEXEL_HEIGHT "+p.texelHeight:"",p?"#define CUBEUV_MAX_MIP "+p.maxMip+".0":"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",n.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.anisotropy?"#define USE_ANISOTROPY":"",n.anisotropyMap?"#define USE_ANISOTROPYMAP":"",n.clearcoat?"#define USE_CLEARCOAT":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.dispersion?"#define USE_DISPERSION":"",n.iridescence?"#define USE_IRIDESCENCE":"",n.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",n.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",n.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.alphaTest?"#define USE_ALPHATEST":"",n.alphaHash?"#define USE_ALPHAHASH":"",n.sheen?"#define USE_SHEEN":"",n.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.vertexTangents&&!1===n.flatShading?"#define USE_TANGENT":"",n.vertexColors||n.instancingColor||n.batchingColor?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUv1s?"#define USE_UV1":"",n.vertexUv2s?"#define USE_UV2":"",n.vertexUv3s?"#define USE_UV3":"",n.pointsUvs?"#define USE_POINTS_UV":"",n.gradientMap?"#define USE_GRADIENTMAP":"",n.flatShading?"#define FLAT_SHADED":"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+c:"",n.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",n.numLightProbes>0?"#define USE_LIGHT_PROBES":"",n.decodeVideoTexture?"#define DECODE_VIDEO_TEXTURE":"",n.decodeVideoTextureEmissive?"#define DECODE_VIDEO_TEXTURE_EMISSIVE":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",n.reverseDepthBuffer?"#define USE_REVERSEDEPTHBUF":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",n.toneMapping!==U?"#define TONE_MAPPING":"",n.toneMapping!==U?wn.tonemapping_pars_fragment:"",n.toneMapping!==U?xr("toneMapping",n.toneMapping):"",n.dithering?"#define DITHERING":"",n.opaque?"#define OPAQUE":"",wn.colorspace_pars_fragment,Mr("linearToOutputTexel",n.outputColorSpace),Ar(),n.useDepthPacking?"#define DEPTH_PACKING "+n.depthPacking:"","\n"].filter(br).join("\n")),s=Ur(s),s=Cr(s,n),s=Lr(s,n),l=Ur(l),l=Cr(l,n),l=Lr(l,n),s=Ir(s),l=Ir(l),!0!==n.isRawShaderMaterial&&(E="#version 300 es\n",g=[m,"#define attribute in","#define varying out","#define texture2D texture"].join("\n")+"\n"+g,v=["#define varying in",n.glslVersion===Z?"":"layout(location = 0) out highp vec4 pc_fragColor;",n.glslVersion===Z?"":"#define gl_FragColor pc_fragColor","#define gl_FragDepthEXT gl_FragDepth","#define texture2D texture","#define textureCube texture","#define texture2DProj textureProj","#define texture2DLodEXT textureLod","#define texture2DProjLodEXT textureProjLod","#define textureCubeLodEXT textureLod","#define texture2DGradEXT textureGrad","#define texture2DProjGradEXT textureProjGrad","#define textureCubeGradEXT textureGrad"].join("\n")+"\n"+v);const S=E+g+s,T=E+v+l,M=vr(r,r.VERTEX_SHADER,S),x=vr(r,r.FRAGMENT_SHADER,T);function R(t){if(e.debug.checkShaderErrors){const n=r.getProgramInfoLog(_).trim(),i=r.getShaderInfoLog(M).trim(),a=r.getShaderInfoLog(x).trim();let o=!0,s=!0;if(!1===r.getProgramParameter(_,r.LINK_STATUS))if(o=!1,"function"==typeof e.debug.onShaderError)e.debug.onShaderError(r,_,M,x);else{const e=Tr(r,M,"vertex"),i=Tr(r,x,"fragment");console.error("THREE.WebGLProgram: Shader Error "+r.getError()+" - VALIDATE_STATUS "+r.getProgramParameter(_,r.VALIDATE_STATUS)+"\n\nMaterial Name: "+t.name+"\nMaterial Type: "+t.type+"\n\nProgram Info Log: "+n+"\n"+e+"\n"+i)}else""!==n?console.warn("THREE.WebGLProgram: Program Info Log:",n):""!==i&&""!==a||(s=!1);s&&(t.diagnostics={runnable:o,programLog:n,vertexShader:{log:i,prefix:g},fragmentShader:{log:a,prefix:v}})}r.deleteShader(M),r.deleteShader(x),A=new gr(r,_),b=function(e,t){const n={},i=e.getProgramParameter(t,e.ACTIVE_ATTRIBUTES);for(let r=0;r0,J=o.clearcoat>0,ee=o.dispersion>0,te=o.iridescence>0,ne=o.sheen>0,ie=o.transmission>0,re=Q&&!!o.anisotropyMap,ae=J&&!!o.clearcoatMap,oe=J&&!!o.clearcoatNormalMap,se=J&&!!o.clearcoatRoughnessMap,le=te&&!!o.iridescenceMap,ce=te&&!!o.iridescenceThicknessMap,de=ne&&!!o.sheenColorMap,he=ne&&!!o.sheenRoughnessMap,_e=!!o.specularMap,ge=!!o.specularColorMap,ve=!!o.specularIntensityMap,Ee=ie&&!!o.transmissionMap,Se=ie&&!!o.thicknessMap,Te=!!o.gradientMap,Me=!!o.alphaMap,xe=o.alphaTest>0,Re=!!o.alphaHash,Ae=!!o.extensions;let be=U;o.toneMapped&&(null!==O&&!0!==O.isXRRenderTarget||(be=e.toneMapping));const Ce={shaderID:C,shaderType:o.type,shaderName:o.name,vertexShader:w,fragmentShader:D,defines:o.defines,customVertexShaderID:y,customFragmentShaderID:I,isRawShaderMaterial:!0===o.isRawShaderMaterial,glslVersion:o.glslVersion,precision:g,batching:G,batchingColor:G&&null!==T._colorsTexture,instancing:H,instancingColor:H&&null!==T.instanceColor,instancingMorph:H&&null!==T.morphTexture,supportsVertexTextures:_,outputColorSpace:null===O?e.outputColorSpace:!0===O.isXRRenderTarget?O.texture.colorSpace:B,alphaToCoverage:!!o.alphaToCoverage,map:V,matcap:z,envMap:k,envMapMode:k&&A.mapping,envMapCubeUVHeight:b,aoMap:W,lightMap:X,bumpMap:Y,normalMap:j,displacementMap:_&&K,emissiveMap:q,normalMapObjectSpace:j&&o.normalMapType===ue,normalMapTangentSpace:j&&o.normalMapType===fe,metalnessMap:Z,roughnessMap:$,anisotropy:Q,anisotropyMap:re,clearcoat:J,clearcoatMap:ae,clearcoatNormalMap:oe,clearcoatRoughnessMap:se,dispersion:ee,iridescence:te,iridescenceMap:le,iridescenceThicknessMap:ce,sheen:ne,sheenColorMap:de,sheenRoughnessMap:he,specularMap:_e,specularColorMap:ge,specularIntensityMap:ve,transmission:ie,transmissionMap:Ee,thicknessMap:Se,gradientMap:Te,opaque:!1===o.transparent&&o.blending===pe&&!1===o.alphaToCoverage,alphaMap:Me,alphaTest:xe,alphaHash:Re,combine:o.combine,mapUv:V&&E(o.map.channel),aoMapUv:W&&E(o.aoMap.channel),lightMapUv:X&&E(o.lightMap.channel),bumpMapUv:Y&&E(o.bumpMap.channel),normalMapUv:j&&E(o.normalMap.channel),displacementMapUv:K&&E(o.displacementMap.channel),emissiveMapUv:q&&E(o.emissiveMap.channel),metalnessMapUv:Z&&E(o.metalnessMap.channel),roughnessMapUv:$&&E(o.roughnessMap.channel),anisotropyMapUv:re&&E(o.anisotropyMap.channel),clearcoatMapUv:ae&&E(o.clearcoatMap.channel),clearcoatNormalMapUv:oe&&E(o.clearcoatNormalMap.channel),clearcoatRoughnessMapUv:se&&E(o.clearcoatRoughnessMap.channel),iridescenceMapUv:le&&E(o.iridescenceMap.channel),iridescenceThicknessMapUv:ce&&E(o.iridescenceThicknessMap.channel),sheenColorMapUv:de&&E(o.sheenColorMap.channel),sheenRoughnessMapUv:he&&E(o.sheenRoughnessMap.channel),specularMapUv:_e&&E(o.specularMap.channel),specularColorMapUv:ge&&E(o.specularColorMap.channel),specularIntensityMapUv:ve&&E(o.specularIntensityMap.channel),transmissionMapUv:Ee&&E(o.transmissionMap.channel),thicknessMapUv:Se&&E(o.thicknessMap.channel),alphaMapUv:Me&&E(o.alphaMap.channel),vertexTangents:!!x.attributes.tangent&&(j||Q),vertexColors:o.vertexColors,vertexAlphas:!0===o.vertexColors&&!!x.attributes.color&&4===x.attributes.color.itemSize,pointsUvs:!0===T.isPoints&&!!x.attributes.uv&&(V||Me),fog:!!M,useFog:!0===o.fog,fogExp2:!!M&&M.isFogExp2,flatShading:!0===o.flatShading,sizeAttenuation:!0===o.sizeAttenuation,logarithmicDepthBuffer:h,reverseDepthBuffer:F,skinning:!0===T.isSkinnedMesh,morphTargets:void 0!==x.morphAttributes.position,morphNormals:void 0!==x.morphAttributes.normal,morphColors:void 0!==x.morphAttributes.color,morphTargetsCount:P,morphTextureStride:N,numDirLights:l.directional.length,numPointLights:l.point.length,numSpotLights:l.spot.length,numSpotLightMaps:l.spotLightMap.length,numRectAreaLights:l.rectArea.length,numHemiLights:l.hemi.length,numDirLightShadows:l.directionalShadowMap.length,numPointLightShadows:l.pointShadowMap.length,numSpotLightShadows:l.spotShadowMap.length,numSpotLightShadowsWithMaps:l.numSpotLightShadowsWithMaps,numLightProbes:l.numLightProbes,numClippingPlanes:s.numPlanes,numClipIntersection:s.numIntersection,dithering:o.dithering,shadowMapEnabled:e.shadowMap.enabled&&m.length>0,shadowMapType:e.shadowMap.type,toneMapping:be,decodeVideoTexture:V&&!0===o.map.isVideoTexture&&u.getTransfer(o.map.colorSpace)===f,decodeVideoTextureEmissive:q&&!0===o.emissiveMap.isVideoTexture&&u.getTransfer(o.emissiveMap.colorSpace)===f,premultipliedAlpha:o.premultipliedAlpha,doubleSided:o.side===me,flipSided:o.side===d,useDepthPacking:o.depthPacking>=0,depthPacking:o.depthPacking||0,index0AttributeName:o.index0AttributeName,extensionClipCullDistance:Ae&&!0===o.extensions.clipCullDistance&&i.has("WEBGL_clip_cull_distance"),extensionMultiDraw:(Ae&&!0===o.extensions.multiDraw||G)&&i.has("WEBGL_multi_draw"),rendererExtensionParallelShaderCompile:i.has("KHR_parallel_shader_compile"),customProgramCacheKey:o.customProgramCacheKey()};return Ce.vertexUv1s=p.has(1),Ce.vertexUv2s=p.has(2),Ce.vertexUv3s=p.has(3),p.clear(),Ce},getProgramCacheKey:function(t){const n=[];if(t.shaderID?n.push(t.shaderID):(n.push(t.customVertexShaderID),n.push(t.customFragmentShaderID)),void 0!==t.defines)for(const e in t.defines)n.push(e),n.push(t.defines[e]);return!1===t.isRawShaderMaterial&&(!function(e,t){e.push(t.precision),e.push(t.outputColorSpace),e.push(t.envMapMode),e.push(t.envMapCubeUVHeight),e.push(t.mapUv),e.push(t.alphaMapUv),e.push(t.lightMapUv),e.push(t.aoMapUv),e.push(t.bumpMapUv),e.push(t.normalMapUv),e.push(t.displacementMapUv),e.push(t.emissiveMapUv),e.push(t.metalnessMapUv),e.push(t.roughnessMapUv),e.push(t.anisotropyMapUv),e.push(t.clearcoatMapUv),e.push(t.clearcoatNormalMapUv),e.push(t.clearcoatRoughnessMapUv),e.push(t.iridescenceMapUv),e.push(t.iridescenceThicknessMapUv),e.push(t.sheenColorMapUv),e.push(t.sheenRoughnessMapUv),e.push(t.specularMapUv),e.push(t.specularColorMapUv),e.push(t.specularIntensityMapUv),e.push(t.transmissionMapUv),e.push(t.thicknessMapUv),e.push(t.combine),e.push(t.fogExp2),e.push(t.sizeAttenuation),e.push(t.morphTargetsCount),e.push(t.morphAttributeCount),e.push(t.numDirLights),e.push(t.numPointLights),e.push(t.numSpotLights),e.push(t.numSpotLightMaps),e.push(t.numHemiLights),e.push(t.numRectAreaLights),e.push(t.numDirLightShadows),e.push(t.numPointLightShadows),e.push(t.numSpotLightShadows),e.push(t.numSpotLightShadowsWithMaps),e.push(t.numLightProbes),e.push(t.shadowMapType),e.push(t.toneMapping),e.push(t.numClippingPlanes),e.push(t.numClipIntersection),e.push(t.depthPacking)}(n,t),function(e,t){l.disableAll(),t.supportsVertexTextures&&l.enable(0);t.instancing&&l.enable(1);t.instancingColor&&l.enable(2);t.instancingMorph&&l.enable(3);t.matcap&&l.enable(4);t.envMap&&l.enable(5);t.normalMapObjectSpace&&l.enable(6);t.normalMapTangentSpace&&l.enable(7);t.clearcoat&&l.enable(8);t.iridescence&&l.enable(9);t.alphaTest&&l.enable(10);t.vertexColors&&l.enable(11);t.vertexAlphas&&l.enable(12);t.vertexUv1s&&l.enable(13);t.vertexUv2s&&l.enable(14);t.vertexUv3s&&l.enable(15);t.vertexTangents&&l.enable(16);t.anisotropy&&l.enable(17);t.alphaHash&&l.enable(18);t.batching&&l.enable(19);t.dispersion&&l.enable(20);t.batchingColor&&l.enable(21);e.push(l.mask),l.disableAll(),t.fog&&l.enable(0);t.useFog&&l.enable(1);t.flatShading&&l.enable(2);t.logarithmicDepthBuffer&&l.enable(3);t.reverseDepthBuffer&&l.enable(4);t.skinning&&l.enable(5);t.morphTargets&&l.enable(6);t.morphNormals&&l.enable(7);t.morphColors&&l.enable(8);t.premultipliedAlpha&&l.enable(9);t.shadowMapEnabled&&l.enable(10);t.doubleSided&&l.enable(11);t.flipSided&&l.enable(12);t.useDepthPacking&&l.enable(13);t.dithering&&l.enable(14);t.transmission&&l.enable(15);t.sheen&&l.enable(16);t.opaque&&l.enable(17);t.pointsUvs&&l.enable(18);t.decodeVideoTexture&&l.enable(19);t.decodeVideoTextureEmissive&&l.enable(20);t.alphaToCoverage&&l.enable(21);e.push(l.mask)}(n,t),n.push(e.outputColorSpace)),n.push(t.customProgramCacheKey),n.join()},getUniforms:function(e){const t=v[e.type];let n;if(t){const e=yn[t];n=he.clone(e.uniforms)}else n=e.uniforms;return n},acquireProgram:function(t,n){let i;for(let e=0,t=m.length;e0?i.push(d):!0===o.transparent?r.push(d):n.push(d)},unshift:function(e,t,o,s,l,c){const d=a(e,t,o,s,l,c);o.transmission>0?i.unshift(d):!0===o.transparent?r.unshift(d):n.unshift(d)},finish:function(){for(let n=t,i=e.length;n1&&n.sort(e||kr),i.length>1&&i.sort(t||Wr),r.length>1&&r.sort(t||Wr)}}}function Yr(){let e=new WeakMap;return{get:function(t,n){const i=e.get(t);let r;return void 0===i?(r=new Xr,e.set(t,[r])):n>=i.length?(r=new Xr,i.push(r)):r=i[n],r},dispose:function(){e=new WeakMap}}}function jr(){const t={};return{get:function(n){if(void 0!==t[n.id])return t[n.id];let i;switch(n.type){case"DirectionalLight":i={direction:new r,color:new e};break;case"SpotLight":i={position:new r,direction:new r,color:new e,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":i={position:new r,color:new e,distance:0,decay:0};break;case"HemisphereLight":i={direction:new r,skyColor:new e,groundColor:new e};break;case"RectAreaLight":i={color:new e,position:new r,halfWidth:new r,halfHeight:new r}}return t[n.id]=i,i}}}let Kr=0;function qr(e,t){return(t.castShadow?2:0)-(e.castShadow?2:0)+(t.map?1:0)-(e.map?1:0)}function Zr(e){const t=new jr,i=function(){const e={};return{get:function(t){if(void 0!==e[t.id])return e[t.id];let i;switch(t.type){case"DirectionalLight":case"SpotLight":i={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new n};break;case"PointLight":i={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new n,shadowCameraNear:1,shadowCameraFar:1e3}}return e[t.id]=i,i}}}(),a={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1,numSpotMaps:-1,numLightProbes:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotLightMap:[],spotShadow:[],spotShadowMap:[],spotLightMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[],numSpotLightShadowsWithMaps:0,numLightProbes:0};for(let e=0;e<9;e++)a.probe.push(new r);const o=new r,s=new g,l=new g;return{setup:function(n){let r=0,o=0,s=0;for(let e=0;e<9;e++)a.probe[e].set(0,0,0);let l=0,c=0,d=0,u=0,f=0,p=0,m=0,h=0,_=0,g=0,v=0;n.sort(qr);for(let e=0,E=n.length;e0&&(!0===e.has("OES_texture_float_linear")?(a.rectAreaLTC1=Dn.LTC_FLOAT_1,a.rectAreaLTC2=Dn.LTC_FLOAT_2):(a.rectAreaLTC1=Dn.LTC_HALF_1,a.rectAreaLTC2=Dn.LTC_HALF_2)),a.ambient[0]=r,a.ambient[1]=o,a.ambient[2]=s;const E=a.hash;E.directionalLength===l&&E.pointLength===c&&E.spotLength===d&&E.rectAreaLength===u&&E.hemiLength===f&&E.numDirectionalShadows===p&&E.numPointShadows===m&&E.numSpotShadows===h&&E.numSpotMaps===_&&E.numLightProbes===v||(a.directional.length=l,a.spot.length=d,a.rectArea.length=u,a.point.length=c,a.hemi.length=f,a.directionalShadow.length=p,a.directionalShadowMap.length=p,a.pointShadow.length=m,a.pointShadowMap.length=m,a.spotShadow.length=h,a.spotShadowMap.length=h,a.directionalShadowMatrix.length=p,a.pointShadowMatrix.length=m,a.spotLightMatrix.length=h+_-g,a.spotLightMap.length=_,a.numSpotLightShadowsWithMaps=g,a.numLightProbes=v,E.directionalLength=l,E.pointLength=c,E.spotLength=d,E.rectAreaLength=u,E.hemiLength=f,E.numDirectionalShadows=p,E.numPointShadows=m,E.numSpotShadows=h,E.numSpotMaps=_,E.numLightProbes=v,a.version=Kr++)},setupView:function(e,t){let n=0,i=0,r=0,c=0,d=0;const u=t.matrixWorldInverse;for(let t=0,f=e.length;t=r.length?(a=new $r(e),r.push(a)):a=r[i],a},dispose:function(){t=new WeakMap}}}function Jr(e,t,i){let r=new ge;const a=new n,s=new n,c=new k,u=new ve({depthPacking:Ee}),f=new Se,p={},h=i.maxTextureSize,_={[m]:d,[d]:m,[me]:me},g=new l({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new n},radius:{value:4}},vertexShader:"void main() {\n\tgl_Position = vec4( position, 1.0 );\n}",fragmentShader:"uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include \nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"}),v=g.clone();v.defines.HORIZONTAL_PASS=1;const E=new D;E.setAttribute("position",new y(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const S=new o(E,g),T=this;this.enabled=!1,this.autoUpdate=!0,this.needsUpdate=!1,this.type=re;let M=this.type;function x(n,i){const r=t.update(S);g.defines.VSM_SAMPLES!==n.blurSamples&&(g.defines.VSM_SAMPLES=n.blurSamples,v.defines.VSM_SAMPLES=n.blurSamples,g.needsUpdate=!0,v.needsUpdate=!0),null===n.mapPass&&(n.mapPass=new I(a.x,a.y)),g.uniforms.shadow_pass.value=n.map.texture,g.uniforms.resolution.value=n.mapSize,g.uniforms.radius.value=n.radius,e.setRenderTarget(n.mapPass),e.clear(),e.renderBufferDirect(i,null,r,g,S,null),v.uniforms.shadow_pass.value=n.mapPass.texture,v.uniforms.resolution.value=n.mapSize,v.uniforms.radius.value=n.radius,e.setRenderTarget(n.map),e.clear(),e.renderBufferDirect(i,null,r,v,S,null)}function R(t,n,i,r){let a=null;const o=!0===i.isPointLight?t.customDistanceMaterial:t.customDepthMaterial;if(void 0!==o)a=o;else if(a=!0===i.isPointLight?f:u,e.localClippingEnabled&&!0===n.clipShadows&&Array.isArray(n.clippingPlanes)&&0!==n.clippingPlanes.length||n.displacementMap&&0!==n.displacementScale||n.alphaMap&&n.alphaTest>0||n.map&&n.alphaTest>0){const e=a.uuid,t=n.uuid;let i=p[e];void 0===i&&(i={},p[e]=i);let r=i[t];void 0===r&&(r=a.clone(),i[t]=r,n.addEventListener("dispose",b)),a=r}if(a.visible=n.visible,a.wireframe=n.wireframe,a.side=r===oe?null!==n.shadowSide?n.shadowSide:n.side:null!==n.shadowSide?n.shadowSide:_[n.side],a.alphaMap=n.alphaMap,a.alphaTest=n.alphaTest,a.map=n.map,a.clipShadows=n.clipShadows,a.clippingPlanes=n.clippingPlanes,a.clipIntersection=n.clipIntersection,a.displacementMap=n.displacementMap,a.displacementScale=n.displacementScale,a.displacementBias=n.displacementBias,a.wireframeLinewidth=n.wireframeLinewidth,a.linewidth=n.linewidth,!0===i.isPointLight&&!0===a.isMeshDistanceMaterial){e.properties.get(a).light=i}return a}function A(n,i,a,o,s){if(!1===n.visible)return;if(n.layers.test(i.layers)&&(n.isMesh||n.isLine||n.isPoints)&&(n.castShadow||n.receiveShadow&&s===oe)&&(!n.frustumCulled||r.intersectsObject(n))){n.modelViewMatrix.multiplyMatrices(a.matrixWorldInverse,n.matrixWorld);const r=t.update(n),l=n.material;if(Array.isArray(l)){const t=r.groups;for(let c=0,d=t.length;ch||a.y>h)&&(a.x>h&&(s.x=Math.floor(h/m.x),a.x=s.x*m.x,d.mapSize.x=s.x),a.y>h&&(s.y=Math.floor(h/m.y),a.y=s.y*m.y,d.mapSize.y=s.y)),null===d.map||!0===f||!0===p){const e=this.type!==oe?{minFilter:Te,magFilter:Te}:{};null!==d.map&&d.map.dispose(),d.map=new I(a.x,a.y,e),d.map.texture.name=l.name+".shadowMap",d.camera.updateProjectionMatrix()}e.setRenderTarget(d.map),e.clear();const _=d.getViewportCount();for(let e=0;e<_;e++){const t=d.getViewport(e);c.set(s.x*t.x,s.y*t.y,s.x*t.z,s.y*t.w),u.viewport(c),d.updateMatrices(l,e),r=d.getFrustum(),A(n,i,d.camera,l,this.type)}!0!==d.isPointLightShadow&&this.type===oe&&x(d,i),d.needsUpdate=!1}M=this.type,T.needsUpdate=!1,e.setRenderTarget(o,l,d)}}const ea={[et]:Je,[Qe]:qe,[$e]:Ke,[Me]:Ze,[Je]:et,[qe]:Qe,[Ke]:$e,[Ze]:Me};function ta(t,n){const i=new function(){let e=!1;const n=new k;let i=null;const r=new k(0,0,0,0);return{setMask:function(n){i===n||e||(t.colorMask(n,n,n,n),i=n)},setLocked:function(t){e=t},setClear:function(e,i,a,o,s){!0===s&&(e*=o,i*=o,a*=o),n.set(e,i,a,o),!1===r.equals(n)&&(t.clearColor(e,i,a,o),r.copy(n))},reset:function(){e=!1,i=null,r.set(-1,0,0,0)}}},r=new function(){let e=!1,i=!1,r=null,a=null,o=null;return{setReversed:function(e){if(i!==e){const e=n.get("EXT_clip_control");i?e.clipControlEXT(e.LOWER_LEFT_EXT,e.ZERO_TO_ONE_EXT):e.clipControlEXT(e.LOWER_LEFT_EXT,e.NEGATIVE_ONE_TO_ONE_EXT);const t=o;o=null,this.setClear(t)}i=e},getReversed:function(){return i},setTest:function(e){e?W(t.DEPTH_TEST):X(t.DEPTH_TEST)},setMask:function(n){r===n||e||(t.depthMask(n),r=n)},setFunc:function(e){if(i&&(e=ea[e]),a!==e){switch(e){case et:t.depthFunc(t.NEVER);break;case Je:t.depthFunc(t.ALWAYS);break;case Qe:t.depthFunc(t.LESS);break;case Me:t.depthFunc(t.LEQUAL);break;case $e:t.depthFunc(t.EQUAL);break;case Ze:t.depthFunc(t.GEQUAL);break;case qe:t.depthFunc(t.GREATER);break;case Ke:t.depthFunc(t.NOTEQUAL);break;default:t.depthFunc(t.LEQUAL)}a=e}},setLocked:function(t){e=t},setClear:function(e){o!==e&&(i&&(e=1-e),t.clearDepth(e),o=e)},reset:function(){e=!1,r=null,a=null,o=null,i=!1}}},a=new function(){let e=!1,n=null,i=null,r=null,a=null,o=null,s=null,l=null,c=null;return{setTest:function(n){e||(n?W(t.STENCIL_TEST):X(t.STENCIL_TEST))},setMask:function(i){n===i||e||(t.stencilMask(i),n=i)},setFunc:function(e,n,o){i===e&&r===n&&a===o||(t.stencilFunc(e,n,o),i=e,r=n,a=o)},setOp:function(e,n,i){o===e&&s===n&&l===i||(t.stencilOp(e,n,i),o=e,s=n,l=i)},setLocked:function(t){e=t},setClear:function(e){c!==e&&(t.clearStencil(e),c=e)},reset:function(){e=!1,n=null,i=null,r=null,a=null,o=null,s=null,l=null,c=null}}},o=new WeakMap,s=new WeakMap;let l={},c={},u=new WeakMap,f=[],p=null,m=!1,h=null,_=null,g=null,v=null,E=null,S=null,T=null,M=new e(0,0,0),x=0,R=!1,A=null,b=null,C=null,L=null,P=null;const U=t.getParameter(t.MAX_COMBINED_TEXTURE_IMAGE_UNITS);let w=!1,D=0;const y=t.getParameter(t.VERSION);-1!==y.indexOf("WebGL")?(D=parseFloat(/^WebGL (\d)/.exec(y)[1]),w=D>=1):-1!==y.indexOf("OpenGL ES")&&(D=parseFloat(/^OpenGL ES (\d)/.exec(y)[1]),w=D>=2);let I=null,O={};const F=t.getParameter(t.SCISSOR_BOX),B=t.getParameter(t.VIEWPORT),H=(new k).fromArray(F),G=(new k).fromArray(B);function V(e,n,i,r){const a=new Uint8Array(4),o=t.createTexture();t.bindTexture(e,o),t.texParameteri(e,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(e,t.TEXTURE_MAG_FILTER,t.NEAREST);for(let o=0;on||r.height>n)&&(i=n/Math.max(r.width,r.height)),i<1){if("undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&e instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap||"undefined"!=typeof VideoFrame&&e instanceof VideoFrame){const n=Math.floor(i*r.width),a=Math.floor(i*r.height);void 0===m&&(m=g(n,a));const o=t?g(n,a):m;o.width=n,o.height=a;return o.getContext("2d").drawImage(e,0,0,n,a),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+r.width+"x"+r.height+") to ("+n+"x"+a+")."),o}return"data"in e&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+r.width+"x"+r.height+")."),e}return e}function S(e){return e.generateMipmaps}function x(t){e.generateMipmap(t)}function R(t){return t.isWebGLCubeRenderTarget?e.TEXTURE_CUBE_MAP:t.isWebGL3DRenderTarget?e.TEXTURE_3D:t.isWebGLArrayRenderTarget||t.isCompressedArrayTexture?e.TEXTURE_2D_ARRAY:e.TEXTURE_2D}function A(n,i,r,a,o=!1){if(null!==n){if(void 0!==e[n])return e[n];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+n+"'")}let s=i;if(i===e.RED&&(r===e.FLOAT&&(s=e.R32F),r===e.HALF_FLOAT&&(s=e.R16F),r===e.UNSIGNED_BYTE&&(s=e.R8)),i===e.RED_INTEGER&&(r===e.UNSIGNED_BYTE&&(s=e.R8UI),r===e.UNSIGNED_SHORT&&(s=e.R16UI),r===e.UNSIGNED_INT&&(s=e.R32UI),r===e.BYTE&&(s=e.R8I),r===e.SHORT&&(s=e.R16I),r===e.INT&&(s=e.R32I)),i===e.RG&&(r===e.FLOAT&&(s=e.RG32F),r===e.HALF_FLOAT&&(s=e.RG16F),r===e.UNSIGNED_BYTE&&(s=e.RG8)),i===e.RG_INTEGER&&(r===e.UNSIGNED_BYTE&&(s=e.RG8UI),r===e.UNSIGNED_SHORT&&(s=e.RG16UI),r===e.UNSIGNED_INT&&(s=e.RG32UI),r===e.BYTE&&(s=e.RG8I),r===e.SHORT&&(s=e.RG16I),r===e.INT&&(s=e.RG32I)),i===e.RGB_INTEGER&&(r===e.UNSIGNED_BYTE&&(s=e.RGB8UI),r===e.UNSIGNED_SHORT&&(s=e.RGB16UI),r===e.UNSIGNED_INT&&(s=e.RGB32UI),r===e.BYTE&&(s=e.RGB8I),r===e.SHORT&&(s=e.RGB16I),r===e.INT&&(s=e.RGB32I)),i===e.RGBA_INTEGER&&(r===e.UNSIGNED_BYTE&&(s=e.RGBA8UI),r===e.UNSIGNED_SHORT&&(s=e.RGBA16UI),r===e.UNSIGNED_INT&&(s=e.RGBA32UI),r===e.BYTE&&(s=e.RGBA8I),r===e.SHORT&&(s=e.RGBA16I),r===e.INT&&(s=e.RGBA32I)),i===e.RGB&&r===e.UNSIGNED_INT_5_9_9_9_REV&&(s=e.RGB9_E5),i===e.RGBA){const t=o?se:u.getTransfer(a);r===e.FLOAT&&(s=e.RGBA32F),r===e.HALF_FLOAT&&(s=e.RGBA16F),r===e.UNSIGNED_BYTE&&(s=t===f?e.SRGB8_ALPHA8:e.RGBA8),r===e.UNSIGNED_SHORT_4_4_4_4&&(s=e.RGBA4),r===e.UNSIGNED_SHORT_5_5_5_1&&(s=e.RGB5_A1)}return s!==e.R16F&&s!==e.R32F&&s!==e.RG16F&&s!==e.RG32F&&s!==e.RGBA16F&&s!==e.RGBA32F||t.get("EXT_color_buffer_float"),s}function b(t,n){let i;return t?null===n||n===St||n===Tt?i=e.DEPTH24_STENCIL8:n===M?i=e.DEPTH32F_STENCIL8:n===Mt&&(i=e.DEPTH24_STENCIL8,console.warn("DepthTexture: 16 bit depth attachment is not supported with stencil. Using 24-bit attachment.")):null===n||n===St||n===Tt?i=e.DEPTH_COMPONENT24:n===M?i=e.DEPTH_COMPONENT32F:n===Mt&&(i=e.DEPTH_COMPONENT16),i}function C(e,t){return!0===S(e)||e.isFramebufferTexture&&e.minFilter!==Te&&e.minFilter!==F?Math.log2(Math.max(t.width,t.height))+1:void 0!==e.mipmaps&&e.mipmaps.length>0?e.mipmaps.length:e.isCompressedTexture&&Array.isArray(e.image)?t.mipmaps.length:1}function L(e){const t=e.target;t.removeEventListener("dispose",L),function(e){const t=r.get(e);if(void 0===t.__webglInit)return;const n=e.source,i=h.get(n);if(i){const r=i[t.__cacheKey];r.usedTimes--,0===r.usedTimes&&U(e),0===Object.keys(i).length&&h.delete(n)}r.remove(e)}(t),t.isVideoTexture&&p.delete(t)}function P(t){const n=t.target;n.removeEventListener("dispose",P),function(t){const n=r.get(t);t.depthTexture&&(t.depthTexture.dispose(),r.remove(t.depthTexture));if(t.isWebGLCubeRenderTarget)for(let t=0;t<6;t++){if(Array.isArray(n.__webglFramebuffer[t]))for(let i=0;i0&&a.__version!==t.version){const e=t.image;if(null===e)console.warn("THREE.WebGLRenderer: Texture marked for update but no image data found.");else{if(!1!==e.complete)return void G(a,t,n);console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete")}}i.bindTexture(e.TEXTURE_2D,a.__webglTexture,e.TEXTURE0+n)}const y={[it]:e.REPEAT,[rt]:e.CLAMP_TO_EDGE,[at]:e.MIRRORED_REPEAT},I={[Te]:e.NEAREST,[ot]:e.NEAREST_MIPMAP_NEAREST,[st]:e.NEAREST_MIPMAP_LINEAR,[F]:e.LINEAR,[lt]:e.LINEAR_MIPMAP_NEAREST,[ct]:e.LINEAR_MIPMAP_LINEAR},N={[dt]:e.NEVER,[ut]:e.ALWAYS,[ft]:e.LESS,[X]:e.LEQUAL,[pt]:e.EQUAL,[mt]:e.GEQUAL,[ht]:e.GREATER,[_t]:e.NOTEQUAL};function O(n,i){if(i.type!==M||!1!==t.has("OES_texture_float_linear")||i.magFilter!==F&&i.magFilter!==lt&&i.magFilter!==st&&i.magFilter!==ct&&i.minFilter!==F&&i.minFilter!==lt&&i.minFilter!==st&&i.minFilter!==ct||console.warn("THREE.WebGLRenderer: Unable to use linear filtering with floating point textures. OES_texture_float_linear not supported on this device."),e.texParameteri(n,e.TEXTURE_WRAP_S,y[i.wrapS]),e.texParameteri(n,e.TEXTURE_WRAP_T,y[i.wrapT]),n!==e.TEXTURE_3D&&n!==e.TEXTURE_2D_ARRAY||e.texParameteri(n,e.TEXTURE_WRAP_R,y[i.wrapR]),e.texParameteri(n,e.TEXTURE_MAG_FILTER,I[i.magFilter]),e.texParameteri(n,e.TEXTURE_MIN_FILTER,I[i.minFilter]),i.compareFunction&&(e.texParameteri(n,e.TEXTURE_COMPARE_MODE,e.COMPARE_REF_TO_TEXTURE),e.texParameteri(n,e.TEXTURE_COMPARE_FUNC,N[i.compareFunction])),!0===t.has("EXT_texture_filter_anisotropic")){if(i.magFilter===Te)return;if(i.minFilter!==st&&i.minFilter!==ct)return;if(i.type===M&&!1===t.has("OES_texture_float_linear"))return;if(i.anisotropy>1||r.get(i).__currentAnisotropy){const o=t.get("EXT_texture_filter_anisotropic");e.texParameterf(n,o.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(i.anisotropy,a.getMaxAnisotropy())),r.get(i).__currentAnisotropy=i.anisotropy}}}function H(t,n){let i=!1;void 0===t.__webglInit&&(t.__webglInit=!0,n.addEventListener("dispose",L));const r=n.source;let a=h.get(r);void 0===a&&(a={},h.set(r,a));const o=function(e){const t=[];return t.push(e.wrapS),t.push(e.wrapT),t.push(e.wrapR||0),t.push(e.magFilter),t.push(e.minFilter),t.push(e.anisotropy),t.push(e.internalFormat),t.push(e.format),t.push(e.type),t.push(e.generateMipmaps),t.push(e.premultiplyAlpha),t.push(e.flipY),t.push(e.unpackAlignment),t.push(e.colorSpace),t.join()}(n);if(o!==t.__cacheKey){void 0===a[o]&&(a[o]={texture:e.createTexture(),usedTimes:0},s.memory.textures++,i=!0),a[o].usedTimes++;const r=a[t.__cacheKey];void 0!==r&&(a[t.__cacheKey].usedTimes--,0===r.usedTimes&&U(n)),t.__cacheKey=o,t.__webglTexture=a[o].texture}return i}function G(t,n,s){let l=e.TEXTURE_2D;(n.isDataArrayTexture||n.isCompressedArrayTexture)&&(l=e.TEXTURE_2D_ARRAY),n.isData3DTexture&&(l=e.TEXTURE_3D);const c=H(t,n),d=n.source;i.bindTexture(l,t.__webglTexture,e.TEXTURE0+s);const f=r.get(d);if(d.version!==f.__version||!0===c){i.activeTexture(e.TEXTURE0+s);const t=u.getPrimaries(u.workingColorSpace),r=n.colorSpace===gt?null:u.getPrimaries(n.colorSpace),p=n.colorSpace===gt||t===r?e.NONE:e.BROWSER_DEFAULT_WEBGL;e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,n.flipY),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,n.premultiplyAlpha),e.pixelStorei(e.UNPACK_ALIGNMENT,n.unpackAlignment),e.pixelStorei(e.UNPACK_COLORSPACE_CONVERSION_WEBGL,p);let m=v(n.image,!1,a.maxTextureSize);m=q(n,m);const h=o.convert(n.format,n.colorSpace),_=o.convert(n.type);let g,T=A(n.internalFormat,h,_,n.colorSpace,n.isVideoTexture);O(l,n);const M=n.mipmaps,R=!0!==n.isVideoTexture,L=void 0===f.__version||!0===c,P=d.dataReady,U=C(n,m);if(n.isDepthTexture)T=b(n.format===vt,n.type),L&&(R?i.texStorage2D(e.TEXTURE_2D,1,T,m.width,m.height):i.texImage2D(e.TEXTURE_2D,0,T,m.width,m.height,0,h,_,null));else if(n.isDataTexture)if(M.length>0){R&&L&&i.texStorage2D(e.TEXTURE_2D,U,T,M[0].width,M[0].height);for(let t=0,n=M.length;t0){const r=Et(g.width,g.height,n.format,n.type);for(const a of n.layerUpdates){const n=g.data.subarray(a*r/g.data.BYTES_PER_ELEMENT,(a+1)*r/g.data.BYTES_PER_ELEMENT);i.compressedTexSubImage3D(e.TEXTURE_2D_ARRAY,t,0,0,a,g.width,g.height,1,h,n)}n.clearLayerUpdates()}else i.compressedTexSubImage3D(e.TEXTURE_2D_ARRAY,t,0,0,0,g.width,g.height,m.depth,h,g.data)}else i.compressedTexImage3D(e.TEXTURE_2D_ARRAY,t,T,g.width,g.height,m.depth,0,g.data,0,0);else console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()");else R?P&&i.texSubImage3D(e.TEXTURE_2D_ARRAY,t,0,0,0,g.width,g.height,m.depth,h,_,g.data):i.texImage3D(e.TEXTURE_2D_ARRAY,t,T,g.width,g.height,m.depth,0,h,_,g.data)}else{R&&L&&i.texStorage2D(e.TEXTURE_2D,U,T,M[0].width,M[0].height);for(let t=0,r=M.length;t0){const t=Et(m.width,m.height,n.format,n.type);for(const r of n.layerUpdates){const n=m.data.subarray(r*t/m.data.BYTES_PER_ELEMENT,(r+1)*t/m.data.BYTES_PER_ELEMENT);i.texSubImage3D(e.TEXTURE_2D_ARRAY,0,0,0,r,m.width,m.height,1,h,_,n)}n.clearLayerUpdates()}else i.texSubImage3D(e.TEXTURE_2D_ARRAY,0,0,0,0,m.width,m.height,m.depth,h,_,m.data)}else i.texImage3D(e.TEXTURE_2D_ARRAY,0,T,m.width,m.height,m.depth,0,h,_,m.data);else if(n.isData3DTexture)R?(L&&i.texStorage3D(e.TEXTURE_3D,U,T,m.width,m.height,m.depth),P&&i.texSubImage3D(e.TEXTURE_3D,0,0,0,0,m.width,m.height,m.depth,h,_,m.data)):i.texImage3D(e.TEXTURE_3D,0,T,m.width,m.height,m.depth,0,h,_,m.data);else if(n.isFramebufferTexture){if(L)if(R)i.texStorage2D(e.TEXTURE_2D,U,T,m.width,m.height);else{let t=m.width,n=m.height;for(let r=0;r>=1,n>>=1}}else if(M.length>0){if(R&&L){const t=Z(M[0]);i.texStorage2D(e.TEXTURE_2D,U,T,t.width,t.height)}for(let t=0,n=M.length;t>d),r=Math.max(1,n.height>>d);c===e.TEXTURE_3D||c===e.TEXTURE_2D_ARRAY?i.texImage3D(c,d,p,t,r,n.depth,0,u,f,null):i.texImage2D(c,d,p,t,r,0,u,f,null)}i.bindFramebuffer(e.FRAMEBUFFER,t),K(n)?l.framebufferTexture2DMultisampleEXT(e.FRAMEBUFFER,s,c,h.__webglTexture,0,j(n)):(c===e.TEXTURE_2D||c>=e.TEXTURE_CUBE_MAP_POSITIVE_X&&c<=e.TEXTURE_CUBE_MAP_NEGATIVE_Z)&&e.framebufferTexture2D(e.FRAMEBUFFER,s,c,h.__webglTexture,d),i.bindFramebuffer(e.FRAMEBUFFER,null)}function z(t,n,i){if(e.bindRenderbuffer(e.RENDERBUFFER,t),n.depthBuffer){const r=n.depthTexture,a=r&&r.isDepthTexture?r.type:null,o=b(n.stencilBuffer,a),s=n.stencilBuffer?e.DEPTH_STENCIL_ATTACHMENT:e.DEPTH_ATTACHMENT,c=j(n);K(n)?l.renderbufferStorageMultisampleEXT(e.RENDERBUFFER,c,o,n.width,n.height):i?e.renderbufferStorageMultisample(e.RENDERBUFFER,c,o,n.width,n.height):e.renderbufferStorage(e.RENDERBUFFER,o,n.width,n.height),e.framebufferRenderbuffer(e.FRAMEBUFFER,s,e.RENDERBUFFER,t)}else{const t=n.textures;for(let r=0;r{delete n.__boundDepthTexture,delete n.__depthDisposeCallback,e.removeEventListener("dispose",t)};e.addEventListener("dispose",t),n.__depthDisposeCallback=t}n.__boundDepthTexture=e}if(t.depthTexture&&!n.__autoAllocateDepthBuffer){if(a)throw new Error("target.depthTexture not supported in Cube render targets");!function(t,n){if(n&&n.isWebGLCubeRenderTarget)throw new Error("Depth Texture with cube render targets is not supported");if(i.bindFramebuffer(e.FRAMEBUFFER,t),!n.depthTexture||!n.depthTexture.isDepthTexture)throw new Error("renderTarget.depthTexture must be an instance of THREE.DepthTexture");const a=r.get(n.depthTexture);a.__renderTarget=n,a.__webglTexture&&n.depthTexture.image.width===n.width&&n.depthTexture.image.height===n.height||(n.depthTexture.image.width=n.width,n.depthTexture.image.height=n.height,n.depthTexture.needsUpdate=!0),D(n.depthTexture,0);const o=a.__webglTexture,s=j(n);if(n.depthTexture.format===xt)K(n)?l.framebufferTexture2DMultisampleEXT(e.FRAMEBUFFER,e.DEPTH_ATTACHMENT,e.TEXTURE_2D,o,0,s):e.framebufferTexture2D(e.FRAMEBUFFER,e.DEPTH_ATTACHMENT,e.TEXTURE_2D,o,0);else{if(n.depthTexture.format!==vt)throw new Error("Unknown depthTexture format");K(n)?l.framebufferTexture2DMultisampleEXT(e.FRAMEBUFFER,e.DEPTH_STENCIL_ATTACHMENT,e.TEXTURE_2D,o,0,s):e.framebufferTexture2D(e.FRAMEBUFFER,e.DEPTH_STENCIL_ATTACHMENT,e.TEXTURE_2D,o,0)}}(n.__webglFramebuffer,t)}else if(a){n.__webglDepthbuffer=[];for(let r=0;r<6;r++)if(i.bindFramebuffer(e.FRAMEBUFFER,n.__webglFramebuffer[r]),void 0===n.__webglDepthbuffer[r])n.__webglDepthbuffer[r]=e.createRenderbuffer(),z(n.__webglDepthbuffer[r],t,!1);else{const i=t.stencilBuffer?e.DEPTH_STENCIL_ATTACHMENT:e.DEPTH_ATTACHMENT,a=n.__webglDepthbuffer[r];e.bindRenderbuffer(e.RENDERBUFFER,a),e.framebufferRenderbuffer(e.FRAMEBUFFER,i,e.RENDERBUFFER,a)}}else if(i.bindFramebuffer(e.FRAMEBUFFER,n.__webglFramebuffer),void 0===n.__webglDepthbuffer)n.__webglDepthbuffer=e.createRenderbuffer(),z(n.__webglDepthbuffer,t,!1);else{const i=t.stencilBuffer?e.DEPTH_STENCIL_ATTACHMENT:e.DEPTH_ATTACHMENT,r=n.__webglDepthbuffer;e.bindRenderbuffer(e.RENDERBUFFER,r),e.framebufferRenderbuffer(e.FRAMEBUFFER,i,e.RENDERBUFFER,r)}i.bindFramebuffer(e.FRAMEBUFFER,null)}const W=[],Y=[];function j(e){return Math.min(a.maxSamples,e.samples)}function K(e){const n=r.get(e);return e.samples>0&&!0===t.has("WEBGL_multisampled_render_to_texture")&&!1!==n.__useRenderToTexture}function q(e,t){const n=e.colorSpace,i=e.format,r=e.type;return!0===e.isCompressedTexture||!0===e.isVideoTexture||n!==B&&n!==gt&&(u.getTransfer(n)===f?i===E&&r===T||console.warn("THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType."):console.error("THREE.WebGLTextures: Unsupported texture color space:",n)),t}function Z(e){return"undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement?(d.width=e.naturalWidth||e.width,d.height=e.naturalHeight||e.height):"undefined"!=typeof VideoFrame&&e instanceof VideoFrame?(d.width=e.displayWidth,d.height=e.displayHeight):(d.width=e.width,d.height=e.height),d}this.allocateTextureUnit=function(){const e=w;return e>=a.maxTextures&&console.warn("THREE.WebGLTextures: Trying to use "+e+" texture units while this GPU supports only "+a.maxTextures),w+=1,e},this.resetTextureUnits=function(){w=0},this.setTexture2D=D,this.setTexture2DArray=function(t,n){const a=r.get(t);t.version>0&&a.__version!==t.version?G(a,t,n):i.bindTexture(e.TEXTURE_2D_ARRAY,a.__webglTexture,e.TEXTURE0+n)},this.setTexture3D=function(t,n){const a=r.get(t);t.version>0&&a.__version!==t.version?G(a,t,n):i.bindTexture(e.TEXTURE_3D,a.__webglTexture,e.TEXTURE0+n)},this.setTextureCube=function(t,n){const s=r.get(t);t.version>0&&s.__version!==t.version?function(t,n,s){if(6!==n.image.length)return;const l=H(t,n),c=n.source;i.bindTexture(e.TEXTURE_CUBE_MAP,t.__webglTexture,e.TEXTURE0+s);const d=r.get(c);if(c.version!==d.__version||!0===l){i.activeTexture(e.TEXTURE0+s);const t=u.getPrimaries(u.workingColorSpace),r=n.colorSpace===gt?null:u.getPrimaries(n.colorSpace),f=n.colorSpace===gt||t===r?e.NONE:e.BROWSER_DEFAULT_WEBGL;e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,n.flipY),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,n.premultiplyAlpha),e.pixelStorei(e.UNPACK_ALIGNMENT,n.unpackAlignment),e.pixelStorei(e.UNPACK_COLORSPACE_CONVERSION_WEBGL,f);const p=n.isCompressedTexture||n.image[0].isCompressedTexture,m=n.image[0]&&n.image[0].isDataTexture,h=[];for(let e=0;e<6;e++)h[e]=p||m?m?n.image[e].image:n.image[e]:v(n.image[e],!0,a.maxCubemapSize),h[e]=q(n,h[e]);const _=h[0],g=o.convert(n.format,n.colorSpace),T=o.convert(n.type),M=A(n.internalFormat,g,T,n.colorSpace),R=!0!==n.isVideoTexture,b=void 0===d.__version||!0===l,L=c.dataReady;let P,U=C(n,_);if(O(e.TEXTURE_CUBE_MAP,n),p){R&&b&&i.texStorage2D(e.TEXTURE_CUBE_MAP,U,M,_.width,_.height);for(let t=0;t<6;t++){P=h[t].mipmaps;for(let r=0;r0&&U++;const t=Z(h[0]);i.texStorage2D(e.TEXTURE_CUBE_MAP,U,M,t.width,t.height)}for(let t=0;t<6;t++)if(m){R?L&&i.texSubImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+t,0,0,0,h[t].width,h[t].height,g,T,h[t].data):i.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+t,0,M,h[t].width,h[t].height,0,g,T,h[t].data);for(let n=0;n1;if(u||(void 0===l.__webglTexture&&(l.__webglTexture=e.createTexture()),l.__version=n.version,s.memory.textures++),d){a.__webglFramebuffer=[];for(let t=0;t<6;t++)if(n.mipmaps&&n.mipmaps.length>0){a.__webglFramebuffer[t]=[];for(let i=0;i0){a.__webglFramebuffer=[];for(let t=0;t0&&!1===K(t)){a.__webglMultisampledFramebuffer=e.createFramebuffer(),a.__webglColorRenderbuffer=[],i.bindFramebuffer(e.FRAMEBUFFER,a.__webglMultisampledFramebuffer);for(let n=0;n0)for(let r=0;r0)for(let i=0;i0)if(!1===K(t)){const n=t.textures,a=t.width,o=t.height;let s=e.COLOR_BUFFER_BIT;const l=t.stencilBuffer?e.DEPTH_STENCIL_ATTACHMENT:e.DEPTH_ATTACHMENT,d=r.get(t),u=n.length>1;if(u)for(let t=0;ts+c?(l.inputState.pinching=!1,this.dispatchEvent({type:"pinchend",handedness:e.handedness,target:this})):!l.inputState.pinching&&o<=s-c&&(l.inputState.pinching=!0,this.dispatchEvent({type:"pinchstart",handedness:e.handedness,target:this}))}else null!==s&&e.gripSpace&&(r=t.getPose(e.gripSpace,n),null!==r&&(s.matrix.fromArray(r.transform.matrix),s.matrix.decompose(s.position,s.rotation,s.scale),s.matrixWorldNeedsUpdate=!0,r.linearVelocity?(s.hasLinearVelocity=!0,s.linearVelocity.copy(r.linearVelocity)):s.hasLinearVelocity=!1,r.angularVelocity?(s.hasAngularVelocity=!0,s.angularVelocity.copy(r.angularVelocity)):s.hasAngularVelocity=!1));null!==o&&(i=t.getPose(e.targetRaySpace,n),null===i&&null!==r&&(i=r),null!==i&&(o.matrix.fromArray(i.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),o.matrixWorldNeedsUpdate=!0,i.linearVelocity?(o.hasLinearVelocity=!0,o.linearVelocity.copy(i.linearVelocity)):o.hasLinearVelocity=!1,i.angularVelocity?(o.hasAngularVelocity=!0,o.angularVelocity.copy(i.angularVelocity)):o.hasAngularVelocity=!1,this.dispatchEvent(ra)))}return null!==o&&(o.visible=null!==i),null!==s&&(s.visible=null!==r),null!==l&&(l.visible=null!==a),this}_getHandJoint(e,t){if(void 0===e.joints[t.jointName]){const n=new vn;n.matrixAutoUpdate=!1,n.visible=!1,e.joints[t.jointName]=n,e.add(n)}return e.joints[t.jointName]}}class oa{constructor(){this.texture=null,this.mesh=null,this.depthNear=0,this.depthFar=0}init(e,t,n){if(null===this.texture){const i=new Y;e.properties.get(i).__webglTexture=t.texture,t.depthNear===n.depthNear&&t.depthFar===n.depthFar||(this.depthNear=t.depthNear,this.depthFar=t.depthFar),this.texture=i}}getMesh(e){if(null!==this.texture&&null===this.mesh){const t=e.cameras[0].viewport,n=new l({vertexShader:"\nvoid main() {\n\n\tgl_Position = vec4( position, 1.0 );\n\n}",fragmentShader:"\nuniform sampler2DArray depthColor;\nuniform float depthWidth;\nuniform float depthHeight;\n\nvoid main() {\n\n\tvec2 coord = vec2( gl_FragCoord.x / depthWidth, gl_FragCoord.y / depthHeight );\n\n\tif ( coord.x >= 1.0 ) {\n\n\t\tgl_FragDepth = texture( depthColor, vec3( coord.x - 1.0, coord.y, 1 ) ).r;\n\n\t} else {\n\n\t\tgl_FragDepth = texture( depthColor, vec3( coord.x, coord.y, 0 ) ).r;\n\n\t}\n\n}",uniforms:{depthColor:{value:this.texture},depthWidth:{value:t.z},depthHeight:{value:t.w}}});this.mesh=new o(new p(20,20),n)}return this.mesh}reset(){this.texture=null,this.mesh=null}getDepthTexture(){return this.texture}}class sa extends En{constructor(e,t){super();const i=this;let a=null,o=1,s=null,l="local-floor",c=1,d=null,u=null,f=null,p=null,m=null,h=null;const _=new oa,g=t.getContextAttributes();let v=null,S=null;const M=[],x=[],R=new n;let A=null;const b=new P;b.viewport=new k;const C=new P;C.viewport=new k;const L=[b,C],U=new Sn;let w=null,D=null;function y(e){const t=x.indexOf(e.inputSource);if(-1===t)return;const n=M[t];void 0!==n&&(n.update(e.inputSource,e.frame,d||s),n.dispatchEvent({type:e.type,data:e.inputSource}))}function N(){a.removeEventListener("select",y),a.removeEventListener("selectstart",y),a.removeEventListener("selectend",y),a.removeEventListener("squeeze",y),a.removeEventListener("squeezestart",y),a.removeEventListener("squeezeend",y),a.removeEventListener("end",N),a.removeEventListener("inputsourceschange",O);for(let e=0;e=0&&(x[i]=null,M[i].disconnect(n))}for(let t=0;t=x.length){x.push(n),i=e;break}if(null===x[e]){x[e]=n,i=e;break}}if(-1===i)break}const r=M[i];r&&r.connect(n)}}this.cameraAutoUpdate=!0,this.enabled=!1,this.isPresenting=!1,this.getController=function(e){let t=M[e];return void 0===t&&(t=new aa,M[e]=t),t.getTargetRaySpace()},this.getControllerGrip=function(e){let t=M[e];return void 0===t&&(t=new aa,M[e]=t),t.getGripSpace()},this.getHand=function(e){let t=M[e];return void 0===t&&(t=new aa,M[e]=t),t.getHandSpace()},this.setFramebufferScaleFactor=function(e){o=e,!0===i.isPresenting&&console.warn("THREE.WebXRManager: Cannot change framebuffer scale while presenting.")},this.setReferenceSpaceType=function(e){l=e,!0===i.isPresenting&&console.warn("THREE.WebXRManager: Cannot change reference space type while presenting.")},this.getReferenceSpace=function(){return d||s},this.setReferenceSpace=function(e){d=e},this.getBaseLayer=function(){return null!==p?p:m},this.getBinding=function(){return f},this.getFrame=function(){return h},this.getSession=function(){return a},this.setSession=async function(n){if(a=n,null!==a){v=e.getRenderTarget(),a.addEventListener("select",y),a.addEventListener("selectstart",y),a.addEventListener("selectend",y),a.addEventListener("squeeze",y),a.addEventListener("squeezestart",y),a.addEventListener("squeezeend",y),a.addEventListener("end",N),a.addEventListener("inputsourceschange",O),!0!==g.xrCompatible&&await t.makeXRCompatible(),A=e.getPixelRatio(),e.getSize(R);if(void 0!==a.enabledFeatures&&a.enabledFeatures.includes("layers")){let n=null,i=null,r=null;g.depth&&(r=g.stencil?t.DEPTH24_STENCIL8:t.DEPTH_COMPONENT24,n=g.stencil?vt:xt,i=g.stencil?Tt:St);const s={colorFormat:t.RGBA8,depthFormat:r,scaleFactor:o};f=new XRWebGLBinding(a,t),p=f.createProjectionLayer(s),a.updateRenderState({layers:[p]}),e.setPixelRatio(1),e.setSize(p.textureWidth,p.textureHeight,!1),S=new I(p.textureWidth,p.textureHeight,{format:E,type:T,depthTexture:new j(p.textureWidth,p.textureHeight,i,void 0,void 0,void 0,void 0,void 0,void 0,n),stencilBuffer:g.stencil,colorSpace:e.outputColorSpace,samples:g.antialias?4:0,resolveDepthBuffer:!1===p.ignoreDepthValues})}else{const n={antialias:g.antialias,alpha:!0,depth:g.depth,stencil:g.stencil,framebufferScaleFactor:o};m=new XRWebGLLayer(a,t,n),a.updateRenderState({baseLayer:m}),e.setPixelRatio(1),e.setSize(m.framebufferWidth,m.framebufferHeight,!1),S=new I(m.framebufferWidth,m.framebufferHeight,{format:E,type:T,colorSpace:e.outputColorSpace,stencilBuffer:g.stencil})}S.isXRRenderTarget=!0,this.setFoveation(c),d=null,s=await a.requestReferenceSpace(l),V.setContext(a),V.start(),i.isPresenting=!0,i.dispatchEvent({type:"sessionstart"})}},this.getEnvironmentBlendMode=function(){if(null!==a)return a.environmentBlendMode},this.getDepthTexture=function(){return _.getDepthTexture()};const F=new r,B=new r;function H(e,t){null===t?e.matrixWorld.copy(e.matrix):e.matrixWorld.multiplyMatrices(t.matrixWorld,e.matrix),e.matrixWorldInverse.copy(e.matrixWorld).invert()}this.updateCamera=function(e){if(null===a)return;let t=e.near,n=e.far;null!==_.texture&&(_.depthNear>0&&(t=_.depthNear),_.depthFar>0&&(n=_.depthFar)),U.near=C.near=b.near=t,U.far=C.far=b.far=n,w===U.near&&D===U.far||(a.updateRenderState({depthNear:U.near,depthFar:U.far}),w=U.near,D=U.far),b.layers.mask=2|e.layers.mask,C.layers.mask=4|e.layers.mask,U.layers.mask=b.layers.mask|C.layers.mask;const i=e.parent,r=U.cameras;H(U,i);for(let e=0;e0&&(e.alphaTest.value=i.alphaTest);const r=t.get(i),a=r.envMap,o=r.envMapRotation;a&&(e.envMap.value=a,la.copy(o),la.x*=-1,la.y*=-1,la.z*=-1,a.isCubeTexture&&!1===a.isRenderTargetTexture&&(la.y*=-1,la.z*=-1),e.envMapRotation.value.setFromMatrix4(ca.makeRotationFromEuler(la)),e.flipEnvMap.value=a.isCubeTexture&&!1===a.isRenderTargetTexture?-1:1,e.reflectivity.value=i.reflectivity,e.ior.value=i.ior,e.refractionRatio.value=i.refractionRatio),i.lightMap&&(e.lightMap.value=i.lightMap,e.lightMapIntensity.value=i.lightMapIntensity,n(i.lightMap,e.lightMapTransform)),i.aoMap&&(e.aoMap.value=i.aoMap,e.aoMapIntensity.value=i.aoMapIntensity,n(i.aoMap,e.aoMapTransform))}return{refreshFogUniforms:function(t,n){n.color.getRGB(t.fogColor.value,h(e)),n.isFog?(t.fogNear.value=n.near,t.fogFar.value=n.far):n.isFogExp2&&(t.fogDensity.value=n.density)},refreshMaterialUniforms:function(e,r,a,o,s){r.isMeshBasicMaterial||r.isMeshLambertMaterial?i(e,r):r.isMeshToonMaterial?(i(e,r),function(e,t){t.gradientMap&&(e.gradientMap.value=t.gradientMap)}(e,r)):r.isMeshPhongMaterial?(i(e,r),function(e,t){e.specular.value.copy(t.specular),e.shininess.value=Math.max(t.shininess,1e-4)}(e,r)):r.isMeshStandardMaterial?(i(e,r),function(e,t){e.metalness.value=t.metalness,t.metalnessMap&&(e.metalnessMap.value=t.metalnessMap,n(t.metalnessMap,e.metalnessMapTransform));e.roughness.value=t.roughness,t.roughnessMap&&(e.roughnessMap.value=t.roughnessMap,n(t.roughnessMap,e.roughnessMapTransform));t.envMap&&(e.envMapIntensity.value=t.envMapIntensity)}(e,r),r.isMeshPhysicalMaterial&&function(e,t,i){e.ior.value=t.ior,t.sheen>0&&(e.sheenColor.value.copy(t.sheenColor).multiplyScalar(t.sheen),e.sheenRoughness.value=t.sheenRoughness,t.sheenColorMap&&(e.sheenColorMap.value=t.sheenColorMap,n(t.sheenColorMap,e.sheenColorMapTransform)),t.sheenRoughnessMap&&(e.sheenRoughnessMap.value=t.sheenRoughnessMap,n(t.sheenRoughnessMap,e.sheenRoughnessMapTransform)));t.clearcoat>0&&(e.clearcoat.value=t.clearcoat,e.clearcoatRoughness.value=t.clearcoatRoughness,t.clearcoatMap&&(e.clearcoatMap.value=t.clearcoatMap,n(t.clearcoatMap,e.clearcoatMapTransform)),t.clearcoatRoughnessMap&&(e.clearcoatRoughnessMap.value=t.clearcoatRoughnessMap,n(t.clearcoatRoughnessMap,e.clearcoatRoughnessMapTransform)),t.clearcoatNormalMap&&(e.clearcoatNormalMap.value=t.clearcoatNormalMap,n(t.clearcoatNormalMap,e.clearcoatNormalMapTransform),e.clearcoatNormalScale.value.copy(t.clearcoatNormalScale),t.side===d&&e.clearcoatNormalScale.value.negate()));t.dispersion>0&&(e.dispersion.value=t.dispersion);t.iridescence>0&&(e.iridescence.value=t.iridescence,e.iridescenceIOR.value=t.iridescenceIOR,e.iridescenceThicknessMinimum.value=t.iridescenceThicknessRange[0],e.iridescenceThicknessMaximum.value=t.iridescenceThicknessRange[1],t.iridescenceMap&&(e.iridescenceMap.value=t.iridescenceMap,n(t.iridescenceMap,e.iridescenceMapTransform)),t.iridescenceThicknessMap&&(e.iridescenceThicknessMap.value=t.iridescenceThicknessMap,n(t.iridescenceThicknessMap,e.iridescenceThicknessMapTransform)));t.transmission>0&&(e.transmission.value=t.transmission,e.transmissionSamplerMap.value=i.texture,e.transmissionSamplerSize.value.set(i.width,i.height),t.transmissionMap&&(e.transmissionMap.value=t.transmissionMap,n(t.transmissionMap,e.transmissionMapTransform)),e.thickness.value=t.thickness,t.thicknessMap&&(e.thicknessMap.value=t.thicknessMap,n(t.thicknessMap,e.thicknessMapTransform)),e.attenuationDistance.value=t.attenuationDistance,e.attenuationColor.value.copy(t.attenuationColor));t.anisotropy>0&&(e.anisotropyVector.value.set(t.anisotropy*Math.cos(t.anisotropyRotation),t.anisotropy*Math.sin(t.anisotropyRotation)),t.anisotropyMap&&(e.anisotropyMap.value=t.anisotropyMap,n(t.anisotropyMap,e.anisotropyMapTransform)));e.specularIntensity.value=t.specularIntensity,e.specularColor.value.copy(t.specularColor),t.specularColorMap&&(e.specularColorMap.value=t.specularColorMap,n(t.specularColorMap,e.specularColorMapTransform));t.specularIntensityMap&&(e.specularIntensityMap.value=t.specularIntensityMap,n(t.specularIntensityMap,e.specularIntensityMapTransform))}(e,r,s)):r.isMeshMatcapMaterial?(i(e,r),function(e,t){t.matcap&&(e.matcap.value=t.matcap)}(e,r)):r.isMeshDepthMaterial?i(e,r):r.isMeshDistanceMaterial?(i(e,r),function(e,n){const i=t.get(n).light;e.referencePosition.value.setFromMatrixPosition(i.matrixWorld),e.nearDistance.value=i.shadow.camera.near,e.farDistance.value=i.shadow.camera.far}(e,r)):r.isMeshNormalMaterial?i(e,r):r.isLineBasicMaterial?(function(e,t){e.diffuse.value.copy(t.color),e.opacity.value=t.opacity,t.map&&(e.map.value=t.map,n(t.map,e.mapTransform))}(e,r),r.isLineDashedMaterial&&function(e,t){e.dashSize.value=t.dashSize,e.totalSize.value=t.dashSize+t.gapSize,e.scale.value=t.scale}(e,r)):r.isPointsMaterial?function(e,t,i,r){e.diffuse.value.copy(t.color),e.opacity.value=t.opacity,e.size.value=t.size*i,e.scale.value=.5*r,t.map&&(e.map.value=t.map,n(t.map,e.uvTransform));t.alphaMap&&(e.alphaMap.value=t.alphaMap,n(t.alphaMap,e.alphaMapTransform));t.alphaTest>0&&(e.alphaTest.value=t.alphaTest)}(e,r,a,o):r.isSpriteMaterial?function(e,t){e.diffuse.value.copy(t.color),e.opacity.value=t.opacity,e.rotation.value=t.rotation,t.map&&(e.map.value=t.map,n(t.map,e.mapTransform));t.alphaMap&&(e.alphaMap.value=t.alphaMap,n(t.alphaMap,e.alphaMapTransform));t.alphaTest>0&&(e.alphaTest.value=t.alphaTest)}(e,r):r.isShadowMaterial?(e.color.value.copy(r.color),e.opacity.value=r.opacity):r.isShaderMaterial&&(r.uniformsNeedUpdate=!1)}}}function ua(e,t,n,i){let r={},a={},o=[];const s=e.getParameter(e.MAX_UNIFORM_BUFFER_BINDINGS);function l(e,t,n,i){const r=e.value,a=t+"_"+n;if(void 0===i[a])return i[a]="number"==typeof r||"boolean"==typeof r?r:r.clone(),!0;{const e=i[a];if("number"==typeof r||"boolean"==typeof r){if(e!==r)return i[a]=r,!0}else if(!1===e.equals(r))return e.copy(r),!0}return!1}function c(e){const t={boundary:0,storage:0};return"number"==typeof e||"boolean"==typeof e?(t.boundary=4,t.storage=4):e.isVector2?(t.boundary=8,t.storage=8):e.isVector3||e.isColor?(t.boundary=16,t.storage=12):e.isVector4?(t.boundary=16,t.storage=16):e.isMatrix3?(t.boundary=48,t.storage=48):e.isMatrix4?(t.boundary=64,t.storage=64):e.isTexture?console.warn("THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group."):console.warn("THREE.WebGLRenderer: Unsupported uniform value type.",e),t}function d(t){const n=t.target;n.removeEventListener("dispose",d);const i=o.indexOf(n.__bindingPointIndex);o.splice(i,1),e.deleteBuffer(r[n.id]),delete r[n.id],delete a[n.id]}return{bind:function(e,t){const n=t.program;i.uniformBlockBinding(e,n)},update:function(n,u){let f=r[n.id];void 0===f&&(!function(e){const t=e.uniforms;let n=0;const i=16;for(let e=0,r=t.length;e0&&(n+=i-r);e.__size=n,e.__cache={}}(n),f=function(t){const n=function(){for(let e=0;e0),u=!!n.morphAttributes.position,f=!!n.morphAttributes.normal,p=!!n.morphAttributes.color;let m=U;i.toneMapped&&(null!==D&&!0!==D.isXRRenderTarget||(m=C.toneMapping));const h=n.morphAttributes.position||n.morphAttributes.normal||n.morphAttributes.color,_=void 0!==h?h.length:0,g=fe.get(i),v=R.state.lights;if(!0===J&&(!0===ee||e!==N)){const t=e===N&&i.id===y;Ae.setState(i,e,t)}let E=!1;i.version===g.__version?g.needsLights&&g.lightsStateVersion!==v.state.version||g.outputColorSpace!==s||r.isBatchedMesh&&!1===g.batching?E=!0:r.isBatchedMesh||!0!==g.batching?r.isBatchedMesh&&!0===g.batchingColor&&null===r.colorTexture||r.isBatchedMesh&&!1===g.batchingColor&&null!==r.colorTexture||r.isInstancedMesh&&!1===g.instancing?E=!0:r.isInstancedMesh||!0!==g.instancing?r.isSkinnedMesh&&!1===g.skinning?E=!0:r.isSkinnedMesh||!0!==g.skinning?r.isInstancedMesh&&!0===g.instancingColor&&null===r.instanceColor||r.isInstancedMesh&&!1===g.instancingColor&&null!==r.instanceColor||r.isInstancedMesh&&!0===g.instancingMorph&&null===r.morphTexture||r.isInstancedMesh&&!1===g.instancingMorph&&null!==r.morphTexture||g.envMap!==l||!0===i.fog&&g.fog!==a?E=!0:void 0===g.numClippingPlanes||g.numClippingPlanes===Ae.numPlanes&&g.numIntersection===Ae.numIntersection?(g.vertexAlphas!==c||g.vertexTangents!==d||g.morphTargets!==u||g.morphNormals!==f||g.morphColors!==p||g.toneMapping!==m||g.morphTargetsCount!==_)&&(E=!0):E=!0:E=!0:E=!0:E=!0:(E=!0,g.__version=i.version);let S=g.currentProgram;!0===E&&(S=Qe(i,t,r));let T=!1,M=!1,x=!1;const A=S.getUniforms(),b=g.uniforms;de.useProgram(S.program)&&(T=!0,M=!0,x=!0);i.id!==y&&(y=i.id,M=!0);if(T||N!==e){de.buffers.depth.getReversed()?(te.copy(e.projectionMatrix),An(te),bn(te),A.setValue(Ie,"projectionMatrix",te)):A.setValue(Ie,"projectionMatrix",e.projectionMatrix),A.setValue(Ie,"viewMatrix",e.matrixWorldInverse);const t=A.map.cameraPosition;void 0!==t&&t.setValue(Ie,ie.setFromMatrixPosition(e.matrixWorld)),ce.logarithmicDepthBuffer&&A.setValue(Ie,"logDepthBufFC",2/(Math.log(e.far+1)/Math.LN2)),(i.isMeshPhongMaterial||i.isMeshToonMaterial||i.isMeshLambertMaterial||i.isMeshBasicMaterial||i.isMeshStandardMaterial||i.isShaderMaterial)&&A.setValue(Ie,"isOrthographic",!0===e.isOrthographicCamera),N!==e&&(N=e,M=!0,x=!0)}if(r.isSkinnedMesh){A.setOptional(Ie,r,"bindMatrix"),A.setOptional(Ie,r,"bindMatrixInverse");const e=r.skeleton;e&&(null===e.boneTexture&&e.computeBoneTexture(),A.setValue(Ie,"boneTexture",e.boneTexture,pe))}r.isBatchedMesh&&(A.setOptional(Ie,r,"batchingTexture"),A.setValue(Ie,"batchingTexture",r._matricesTexture,pe),A.setOptional(Ie,r,"batchingIdTexture"),A.setValue(Ie,"batchingIdTexture",r._indirectTexture,pe),A.setOptional(Ie,r,"batchingColorTexture"),null!==r._colorsTexture&&A.setValue(Ie,"batchingColorTexture",r._colorsTexture,pe));const L=n.morphAttributes;void 0===L.position&&void 0===L.normal&&void 0===L.color||Le.update(r,n,S);(M||g.receiveShadow!==r.receiveShadow)&&(g.receiveShadow=r.receiveShadow,A.setValue(Ie,"receiveShadow",r.receiveShadow));i.isMeshGouraudMaterial&&null!==i.envMap&&(b.envMap.value=l,b.flipEnvMap.value=l.isCubeTexture&&!1===l.isRenderTargetTexture?-1:1);i.isMeshStandardMaterial&&null===i.envMap&&null!==t.environment&&(b.envMapIntensity.value=t.environmentIntensity);M&&(A.setValue(Ie,"toneMappingExposure",C.toneMappingExposure),g.needsLights&&(w=x,(P=b).ambientLightColor.needsUpdate=w,P.lightProbe.needsUpdate=w,P.directionalLights.needsUpdate=w,P.directionalLightShadows.needsUpdate=w,P.pointLights.needsUpdate=w,P.pointLightShadows.needsUpdate=w,P.spotLights.needsUpdate=w,P.spotLightShadows.needsUpdate=w,P.rectAreaLights.needsUpdate=w,P.hemisphereLights.needsUpdate=w),a&&!0===i.fog&&Me.refreshFogUniforms(b,a),Me.refreshMaterialUniforms(b,i,Y,X,R.state.transmissionRenderTarget[e.id]),gr.upload(Ie,Je(g),b,pe));var P,w;i.isShaderMaterial&&!0===i.uniformsNeedUpdate&&(gr.upload(Ie,Je(g),b,pe),i.uniformsNeedUpdate=!1);i.isSpriteMaterial&&A.setValue(Ie,"center",r.center);if(A.setValue(Ie,"modelViewMatrix",r.modelViewMatrix),A.setValue(Ie,"normalMatrix",r.normalMatrix),A.setValue(Ie,"modelMatrix",r.matrixWorld),i.isShaderMaterial||i.isRawShaderMaterial){const e=i.uniformsGroups;for(let t=0,n=e.length;t{function n(){i.forEach((function(e){fe.get(e).currentProgram.isReady()&&i.delete(e)})),0!==i.size?setTimeout(n,10):t(e)}null!==le.get("KHR_parallel_shader_compile")?n():setTimeout(n,10)}))};let ke=null;function We(){Ye.stop()}function Xe(){Ye.start()}const Ye=new Pn;function je(e,t,n,i){if(!1===e.visible)return;if(e.layers.test(t.layers))if(e.isGroup)n=e.renderOrder;else if(e.isLOD)!0===e.autoUpdate&&e.update(t);else if(e.isLight)R.pushLight(e),e.castShadow&&R.pushShadow(e);else if(e.isSprite){if(!e.frustumCulled||Q.intersectsSprite(e)){i&&re.setFromMatrixPosition(e.matrixWorld).applyMatrix4(ne);const t=Se.update(e),r=e.material;r.visible&&x.push(e,t,r,n,re.z,null)}}else if((e.isMesh||e.isLine||e.isPoints)&&(!e.frustumCulled||Q.intersectsObject(e))){const t=Se.update(e),r=e.material;if(i&&(void 0!==e.boundingSphere?(null===e.boundingSphere&&e.computeBoundingSphere(),re.copy(e.boundingSphere.center)):(null===t.boundingSphere&&t.computeBoundingSphere(),re.copy(t.boundingSphere.center)),re.applyMatrix4(e.matrixWorld).applyMatrix4(ne)),Array.isArray(r)){const i=t.groups;for(let a=0,o=i.length;a0&&Ze(r,t,n),a.length>0&&Ze(a,t,n),o.length>0&&Ze(o,t,n),de.buffers.depth.setTest(!0),de.buffers.depth.setMask(!0),de.buffers.color.setMask(!0),de.setPolygonOffset(!1)}function qe(e,t,n,i){if(null!==(!0===n.isScene?n.overrideMaterial:null))return;void 0===R.state.transmissionRenderTarget[i.id]&&(R.state.transmissionRenderTarget[i.id]=new I(1,1,{generateMipmaps:!0,type:le.has("EXT_color_buffer_half_float")||le.has("EXT_color_buffer_float")?S:T,minFilter:ct,samples:4,stencilBuffer:o,resolveDepthBuffer:!1,resolveStencilBuffer:!1,colorSpace:u.workingColorSpace}));const r=R.state.transmissionRenderTarget[i.id],a=i.viewport||O;r.setSize(a.z*C.transmissionResolutionScale,a.w*C.transmissionResolutionScale);const s=C.getRenderTarget();C.setRenderTarget(r),C.getClearColor(V),z=C.getClearAlpha(),z<1&&C.setClearColor(16777215,.5),C.clear(),oe&&Ce.render(n);const l=C.toneMapping;C.toneMapping=U;const c=i.viewport;if(void 0!==i.viewport&&(i.viewport=void 0),R.setupLightsView(i),!0===J&&Ae.setGlobalState(C.clippingPlanes,i),Ze(e,n,i),pe.updateMultisampleRenderTarget(r),pe.updateRenderTargetMipmap(r),!1===le.has("WEBGL_multisampled_render_to_texture")){let e=!1;for(let r=0,a=t.length;r0)for(let t=0,a=n.length;t0&&qe(i,r,e,t),oe&&Ce.render(e),Ke(x,e,t);null!==D&&0===w&&(pe.updateMultisampleRenderTarget(D),pe.updateRenderTargetMipmap(D)),!0===e.isScene&&e.onAfterRender(C,e,t),De.resetDefaultState(),y=-1,N=null,b.pop(),b.length>0?(R=b[b.length-1],!0===J&&Ae.setGlobalState(C.clippingPlanes,R.state.camera)):R=null,A.pop(),x=A.length>0?A[A.length-1]:null},this.getActiveCubeFace=function(){return P},this.getActiveMipmapLevel=function(){return w},this.getRenderTarget=function(){return D},this.setRenderTargetTextures=function(e,t,n){fe.get(e.texture).__webglTexture=t,fe.get(e.depthTexture).__webglTexture=n;const i=fe.get(e);i.__hasExternalTextures=!0,i.__autoAllocateDepthBuffer=void 0===n,i.__autoAllocateDepthBuffer||!0===le.has("WEBGL_multisampled_render_to_texture")&&(console.warn("THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided"),i.__useRenderToTexture=!1)},this.setRenderTargetFramebuffer=function(e,t){const n=fe.get(e);n.__webglFramebuffer=t,n.__useDefaultFramebuffer=void 0===t};const tt=Ie.createFramebuffer();this.setRenderTarget=function(e,t=0,n=0){D=e,P=t,w=n;let i=!0,r=null,a=!1,o=!1;if(e){const s=fe.get(e);if(void 0!==s.__useDefaultFramebuffer)de.bindFramebuffer(Ie.FRAMEBUFFER,null),i=!1;else if(void 0===s.__webglFramebuffer)pe.setupRenderTarget(e);else if(s.__hasExternalTextures)pe.rebindTextures(e,fe.get(e.texture).__webglTexture,fe.get(e.depthTexture).__webglTexture);else if(e.depthBuffer){const t=e.depthTexture;if(s.__boundDepthTexture!==t){if(null!==t&&fe.has(t)&&(e.width!==t.image.width||e.height!==t.image.height))throw new Error("WebGLRenderTarget: Attached DepthTexture is initialized to the incorrect size.");pe.setupDepthRenderbuffer(e)}}const l=e.texture;(l.isData3DTexture||l.isDataArrayTexture||l.isCompressedArrayTexture)&&(o=!0);const c=fe.get(e).__webglFramebuffer;e.isWebGLCubeRenderTarget?(r=Array.isArray(c[t])?c[t][n]:c[t],a=!0):r=e.samples>0&&!1===pe.useMultisampledRTT(e)?fe.get(e).__webglMultisampledFramebuffer:Array.isArray(c)?c[n]:c,O.copy(e.viewport),F.copy(e.scissor),G=e.scissorTest}else O.copy(q).multiplyScalar(Y).floor(),F.copy(Z).multiplyScalar(Y).floor(),G=$;0!==n&&(r=tt);if(de.bindFramebuffer(Ie.FRAMEBUFFER,r)&&i&&de.drawBuffers(e,r),de.viewport(O),de.scissor(F),de.setScissorTest(G),a){const i=fe.get(e.texture);Ie.framebufferTexture2D(Ie.FRAMEBUFFER,Ie.COLOR_ATTACHMENT0,Ie.TEXTURE_CUBE_MAP_POSITIVE_X+t,i.__webglTexture,n)}else if(o){const i=fe.get(e.texture),r=t;Ie.framebufferTextureLayer(Ie.FRAMEBUFFER,Ie.COLOR_ATTACHMENT0,i.__webglTexture,n,r)}else if(null!==e&&0!==n){const t=fe.get(e.texture);Ie.framebufferTexture2D(Ie.FRAMEBUFFER,Ie.COLOR_ATTACHMENT0,Ie.TEXTURE_2D,t.__webglTexture,n)}y=-1},this.readRenderTargetPixels=function(e,t,n,i,r,a,o){if(!e||!e.isWebGLRenderTarget)return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let s=fe.get(e).__webglFramebuffer;if(e.isWebGLCubeRenderTarget&&void 0!==o&&(s=s[o]),s){de.bindFramebuffer(Ie.FRAMEBUFFER,s);try{const o=e.texture,s=o.format,l=o.type;if(!ce.textureFormatReadable(s))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");if(!ce.textureTypeReadable(l))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");t>=0&&t<=e.width-i&&n>=0&&n<=e.height-r&&Ie.readPixels(t,n,i,r,we.convert(s),we.convert(l),a)}finally{const e=null!==D?fe.get(D).__webglFramebuffer:null;de.bindFramebuffer(Ie.FRAMEBUFFER,e)}}},this.readRenderTargetPixelsAsync=async function(e,t,n,i,r,a,o){if(!e||!e.isWebGLRenderTarget)throw new Error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let s=fe.get(e).__webglFramebuffer;if(e.isWebGLCubeRenderTarget&&void 0!==o&&(s=s[o]),s){const o=e.texture,l=o.format,c=o.type;if(!ce.textureFormatReadable(l))throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.");if(!ce.textureTypeReadable(c))throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in UnsignedByteType or implementation defined type.");if(t>=0&&t<=e.width-i&&n>=0&&n<=e.height-r){de.bindFramebuffer(Ie.FRAMEBUFFER,s);const e=Ie.createBuffer();Ie.bindBuffer(Ie.PIXEL_PACK_BUFFER,e),Ie.bufferData(Ie.PIXEL_PACK_BUFFER,a.byteLength,Ie.STREAM_READ),Ie.readPixels(t,n,i,r,we.convert(l),we.convert(c),0);const o=null!==D?fe.get(D).__webglFramebuffer:null;de.bindFramebuffer(Ie.FRAMEBUFFER,o);const d=Ie.fenceSync(Ie.SYNC_GPU_COMMANDS_COMPLETE,0);return Ie.flush(),await Cn(Ie,d,4),Ie.bindBuffer(Ie.PIXEL_PACK_BUFFER,e),Ie.getBufferSubData(Ie.PIXEL_PACK_BUFFER,0,a),Ie.deleteBuffer(e),Ie.deleteSync(d),a}throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: requested read bounds are out of range.")}},this.copyFramebufferToTexture=function(e,t=null,n=0){!0!==e.isTexture&&(H("WebGLRenderer: copyFramebufferToTexture function signature has changed."),t=arguments[0]||null,e=arguments[1]);const i=Math.pow(2,-n),r=Math.floor(e.image.width*i),a=Math.floor(e.image.height*i),o=null!==t?t.x:0,s=null!==t?t.y:0;pe.setTexture2D(e,0),Ie.copyTexSubImage2D(Ie.TEXTURE_2D,n,0,0,o,s,r,a),de.unbindTexture()};const nt=Ie.createFramebuffer(),it=Ie.createFramebuffer();this.copyTextureToTexture=function(e,t,n=null,i=null,r=0,a=null){let o,s,l,c,d,u,f,p,m;!0!==e.isTexture&&(H("WebGLRenderer: copyTextureToTexture function signature has changed."),i=arguments[0]||null,e=arguments[1],t=arguments[2],a=arguments[3]||0,n=null),null===a&&(0!==r?(H("WebGLRenderer: copyTextureToTexture function signature has changed to support src and dst mipmap levels."),a=r,r=0):a=0);const h=e.isCompressedTexture?e.mipmaps[a]:e.image;if(null!==n)o=n.max.x-n.min.x,s=n.max.y-n.min.y,l=n.isBox3?n.max.z-n.min.z:1,c=n.min.x,d=n.min.y,u=n.isBox3?n.min.z:0;else{const t=Math.pow(2,-r);o=Math.floor(h.width*t),s=Math.floor(h.height*t),l=e.isDataArrayTexture?h.depth:e.isData3DTexture?Math.floor(h.depth*t):1,c=0,d=0,u=0}null!==i?(f=i.x,p=i.y,m=i.z):(f=0,p=0,m=0);const _=we.convert(t.format),g=we.convert(t.type);let v;t.isData3DTexture?(pe.setTexture3D(t,0),v=Ie.TEXTURE_3D):t.isDataArrayTexture||t.isCompressedArrayTexture?(pe.setTexture2DArray(t,0),v=Ie.TEXTURE_2D_ARRAY):(pe.setTexture2D(t,0),v=Ie.TEXTURE_2D),Ie.pixelStorei(Ie.UNPACK_FLIP_Y_WEBGL,t.flipY),Ie.pixelStorei(Ie.UNPACK_PREMULTIPLY_ALPHA_WEBGL,t.premultiplyAlpha),Ie.pixelStorei(Ie.UNPACK_ALIGNMENT,t.unpackAlignment);const E=Ie.getParameter(Ie.UNPACK_ROW_LENGTH),S=Ie.getParameter(Ie.UNPACK_IMAGE_HEIGHT),T=Ie.getParameter(Ie.UNPACK_SKIP_PIXELS),M=Ie.getParameter(Ie.UNPACK_SKIP_ROWS),x=Ie.getParameter(Ie.UNPACK_SKIP_IMAGES);Ie.pixelStorei(Ie.UNPACK_ROW_LENGTH,h.width),Ie.pixelStorei(Ie.UNPACK_IMAGE_HEIGHT,h.height),Ie.pixelStorei(Ie.UNPACK_SKIP_PIXELS,c),Ie.pixelStorei(Ie.UNPACK_SKIP_ROWS,d),Ie.pixelStorei(Ie.UNPACK_SKIP_IMAGES,u);const R=e.isDataArrayTexture||e.isData3DTexture,A=t.isDataArrayTexture||t.isData3DTexture;if(e.isDepthTexture){const n=fe.get(e),i=fe.get(t),h=fe.get(n.__renderTarget),_=fe.get(i.__renderTarget);de.bindFramebuffer(Ie.READ_FRAMEBUFFER,h.__webglFramebuffer),de.bindFramebuffer(Ie.DRAW_FRAMEBUFFER,_.__webglFramebuffer);for(let n=0;n} + */ this.renderObjects = new WeakMap(); + + /** + * Whether the material uses node objects or not. + * + * @type {Boolean} + */ this.hasNode = this.containsNode( builder ); + + /** + * Whether the node builder's 3D object is animated or not. + * + * @type {Boolean} + */ this.hasAnimation = builder.object.isSkinnedMesh === true; + + /** + * A list of all possible material uniforms + * + * @type {Array} + */ this.refreshUniforms = refreshUniforms; + + /** + * Holds the current render ID from the node frame. + * + * @type {Number} + * @default 0 + */ this.renderId = 0; } + /** + * Returns `true` if the given render object is verified for the first time of this observer. + * + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether the given render object is verified for the first time of this observer. + */ firstInitialization( renderObject ) { const hasInitialized = this.renderObjects.has( renderObject ); @@ -87,6 +134,12 @@ class NodeMaterialObserver { } + /** + * Returns monitoring data for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @return {Object} The monitoring data. + */ getRenderObjectData( renderObject ) { let data = this.renderObjects.get( renderObject ); @@ -140,6 +193,13 @@ class NodeMaterialObserver { } + /** + * Returns an attribute data structure holding the attributes versions for + * monitoring. + * + * @param {Object} attributes - The geometry attributes. + * @return {Object} An object for monitoring the versions of attributes. + */ getAttributesData( attributes ) { const attributesData = {}; @@ -158,6 +218,13 @@ class NodeMaterialObserver { } + /** + * Returns `true` if the node builder's material uses + * node properties. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Boolean} Whether the node builder's material uses node properties or not. + */ containsNode( builder ) { const material = builder.material; @@ -176,6 +243,13 @@ class NodeMaterialObserver { } + /** + * Returns a material data structure holding the material property values for + * monitoring. + * + * @param {Material} material - The material. + * @return {Object} An object for monitoring material properties. + */ getMaterialData( material ) { const data = {}; @@ -210,6 +284,12 @@ class NodeMaterialObserver { } + /** + * Returns `true` if the given render object has not changed its state. + * + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether the given render object has changed its state or not. + */ equals( renderObject ) { const { object, material, geometry } = renderObject; @@ -390,6 +470,13 @@ class NodeMaterialObserver { } + /** + * Checks if the given render object requires a refresh. + * + * @param {RenderObject} renderObject - The render object. + * @param {NodeFrame} nodeFrame - The current node frame. + * @return {Boolean} Whether the given render object requires a refresh or not. + */ needsRefresh( renderObject, nodeFrame ) { if ( this.hasNode || this.hasAnimation || this.firstInitialization( renderObject ) ) @@ -582,6 +669,8 @@ const typeFromLength = /*@__PURE__*/ new Map( [ [ 16, 'mat4' ] ] ); +const dataFromObject = /*@__PURE__*/ new WeakMap(); + /** * Returns the data type for the given the length. * @@ -595,6 +684,39 @@ function getTypeFromLength( length ) { } +/** + * Returns the typed array for the given data type. + * + * @method + * @param {String} type - The data type. + * @return {TypedArray} The typed array. + */ +function getTypedArrayFromType( type ) { + + // Handle component type for vectors and matrices + if ( /[iu]?vec\d/.test( type ) ) { + + // Handle int vectors + if ( type.startsWith( 'ivec' ) ) return Int32Array; + // Handle uint vectors + if ( type.startsWith( 'uvec' ) ) return Uint32Array; + // Default to float vectors + return Float32Array; + + } + + // Handle matrices (always float) + if ( /mat\d/.test( type ) ) return Float32Array; + + // Basic types + if ( /float/.test( type ) ) return Float32Array; + if ( /uint/.test( type ) ) return Uint32Array; + if ( /int/.test( type ) ) return Int32Array; + + throw new Error( `THREE.NodeUtils: Unsupported type: ${type}` ); + +} + /** * Returns the length for the given data type. * @@ -748,6 +870,27 @@ function getValueFromType( type, ...params ) { } +/** + * Gets the object data that can be shared between different rendering steps. + * + * @param {Object} object - The object to get the data for. + * @return {Object} The object data. + */ +function getDataFromObject( object ) { + + let data = dataFromObject.get( object ); + + if ( data === undefined ) { + + data = {}; + dataFromObject.set( object, data ); + + } + + return data; + +} + /** * Converts the given array buffer to a Base64 string. * @@ -789,9 +932,11 @@ var NodeUtils = /*#__PURE__*/Object.freeze({ arrayBufferToBase64: arrayBufferToBase64, base64ToArrayBuffer: base64ToArrayBuffer, getCacheKey: getCacheKey$1, + getDataFromObject: getDataFromObject, getLengthFromType: getLengthFromType, getNodeChildren: getNodeChildren, getTypeFromLength: getTypeFromLength, + getTypedArrayFromType: getTypedArrayFromType, getValueFromType: getValueFromType, getValueType: getValueType, hash: hash$1, @@ -1340,8 +1485,9 @@ class Node extends EventDispatcher { } - // return a outputNode if exists - return null; + // return a outputNode if exists or null + + return nodeProperties.outputNode || null; } @@ -1475,12 +1621,19 @@ class Node extends EventDispatcher { if ( properties.initialized !== true ) { - const stackNodesBeforeSetup = builder.stack.nodes.length; + //const stackNodesBeforeSetup = builder.stack.nodes.length; properties.initialized = true; - properties.outputNode = this.setup( builder ); - if ( properties.outputNode !== null && builder.stack.nodes.length !== stackNodesBeforeSetup ) ; + const outputNode = this.setup( builder ); // return a node or null + const isNodeOutput = outputNode && outputNode.isNode === true; + + /*if ( isNodeOutput && builder.stack.nodes.length !== stackNodesBeforeSetup ) { + + // !! no outputNode !! + //outputNode = builder.stack; + + }*/ for ( const childNode of Object.values( properties ) ) { @@ -1492,6 +1645,14 @@ class Node extends EventDispatcher { } + if ( isNodeOutput ) { + + outputNode.build( builder ); + + } + + properties.outputNode = outputNode; + } } else if ( buildStage === 'analyze' ) { @@ -3569,8 +3730,10 @@ const uniform = ( arg1, arg2 ) => { }; +/** @module PropertyNode **/ + /** - * This class represents a shader property. It can be used on + * This class represents a shader property. It can be used * to explicitly define a property and assign a value to it. * * ```js @@ -3667,36 +3830,220 @@ class PropertyNode extends Node { } +/** + * TSL function for creating a property node. + * + * @function + * @param {String} type - The type of the node. + * @param {String?} [name=null] - The name of the property in the shader. + * @returns {PropertyNode} + */ const property = ( type, name ) => nodeObject( new PropertyNode( type, name ) ); + +/** + * TSL function for creating a varying property node. + * + * @function + * @param {String} type - The type of the node. + * @param {String?} [name=null] - The name of the varying in the shader. + * @returns {PropertyNode} + */ const varyingProperty = ( type, name ) => nodeObject( new PropertyNode( type, name, true ) ); +/** + * TSL object that represents the shader variable `DiffuseColor`. + * + * @type {PropertyNode} + */ const diffuseColor = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec4', 'DiffuseColor' ); + +/** + * TSL object that represents the shader variable `EmissiveColor`. + * + * @type {PropertyNode} + */ const emissive = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'EmissiveColor' ); + +/** + * TSL object that represents the shader variable `Roughness`. + * + * @type {PropertyNode} + */ const roughness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Roughness' ); + +/** + * TSL object that represents the shader variable `Metalness`. + * + * @type {PropertyNode} + */ const metalness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Metalness' ); + +/** + * TSL object that represents the shader variable `Clearcoat`. + * + * @type {PropertyNode} + */ const clearcoat = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Clearcoat' ); + +/** + * TSL object that represents the shader variable `ClearcoatRoughness`. + * + * @type {PropertyNode} + */ const clearcoatRoughness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'ClearcoatRoughness' ); + +/** + * TSL object that represents the shader variable `Sheen`. + * + * @type {PropertyNode} + */ const sheen = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'Sheen' ); + +/** + * TSL object that represents the shader variable `SheenRoughness`. + * + * @type {PropertyNode} + */ const sheenRoughness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'SheenRoughness' ); + +/** + * TSL object that represents the shader variable `Iridescence`. + * + * @type {PropertyNode} + */ const iridescence = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Iridescence' ); + +/** + * TSL object that represents the shader variable `IridescenceIOR`. + * + * @type {PropertyNode} + */ const iridescenceIOR = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'IridescenceIOR' ); + +/** + * TSL object that represents the shader variable `IridescenceThickness`. + * + * @type {PropertyNode} + */ const iridescenceThickness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'IridescenceThickness' ); + +/** + * TSL object that represents the shader variable `AlphaT`. + * + * @type {PropertyNode} + */ const alphaT = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'AlphaT' ); + +/** + * TSL object that represents the shader variable `Anisotropy`. + * + * @type {PropertyNode} + */ const anisotropy = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Anisotropy' ); + +/** + * TSL object that represents the shader variable `AnisotropyT`. + * + * @type {PropertyNode} + */ const anisotropyT = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'AnisotropyT' ); + +/** + * TSL object that represents the shader variable `AnisotropyB`. + * + * @type {PropertyNode} + */ const anisotropyB = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'AnisotropyB' ); + +/** + * TSL object that represents the shader variable `SpecularColor`. + * + * @type {PropertyNode} + */ const specularColor = /*@__PURE__*/ nodeImmutable( PropertyNode, 'color', 'SpecularColor' ); + +/** + * TSL object that represents the shader variable `SpecularF90`. + * + * @type {PropertyNode} + */ const specularF90 = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'SpecularF90' ); + +/** + * TSL object that represents the shader variable `Shininess`. + * + * @type {PropertyNode} + */ const shininess = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Shininess' ); + +/** + * TSL object that represents the shader variable `Output`. + * + * @type {PropertyNode} + */ const output = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec4', 'Output' ); + +/** + * TSL object that represents the shader variable `dashSize`. + * + * @type {PropertyNode} + */ const dashSize = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'dashSize' ); + +/** + * TSL object that represents the shader variable `gapSize`. + * + * @type {PropertyNode} + */ const gapSize = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'gapSize' ); + +/** + * TSL object that represents the shader variable `pointWidth`. + * + * @type {PropertyNode} + */ const pointWidth = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'pointWidth' ); + +/** + * TSL object that represents the shader variable `IOR`. + * + * @type {PropertyNode} + */ const ior = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'IOR' ); + +/** + * TSL object that represents the shader variable `Transmission`. + * + * @type {PropertyNode} + */ const transmission = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Transmission' ); + +/** + * TSL object that represents the shader variable `Thickness`. + * + * @type {PropertyNode} + */ const thickness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Thickness' ); + +/** + * TSL object that represents the shader variable `AttenuationDistance`. + * + * @type {PropertyNode} + */ const attenuationDistance = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'AttenuationDistance' ); + +/** + * TSL object that represents the shader variable `AttenuationColor`. + * + * @type {PropertyNode} + */ const attenuationColor = /*@__PURE__*/ nodeImmutable( PropertyNode, 'color', 'AttenuationColor' ); + +/** + * TSL object that represents the shader variable `Dispersion`. + * + * @type {PropertyNode} + */ const dispersion = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Dispersion' ); /** @module AssignNode **/ @@ -5500,6 +5847,13 @@ const atan2 = ( y, x ) => { // @deprecated, r172 }; +// GLSL alias function + +const faceforward = faceForward; +const inversesqrt = inverseSqrt; + +// Method chaining + addMethodChaining( 'all', all ); addMethodChaining( 'any', any ); addMethodChaining( 'equals', equals ); @@ -5626,11 +5980,23 @@ class ConditionalNode extends Node { */ getNodeType( builder ) { - const ifType = this.ifNode.getNodeType( builder ); + const { ifNode, elseNode } = builder.getNodeProperties( this ); + + if ( ifNode === undefined ) { + + // fallback setup + + this.setup( builder ); + + return this.getNodeType( builder ); + + } + + const ifType = ifNode.getNodeType( builder ); - if ( this.elseNode !== null ) { + if ( elseNode !== null ) { - const elseType = this.elseNode.getNodeType( builder ); + const elseType = elseNode.getNodeType( builder ); if ( builder.getTypeLength( elseType ) > builder.getTypeLength( ifType ) ) { @@ -6194,7 +6560,17 @@ class VaryingNode extends Node { */ const varying = /*@__PURE__*/ nodeProxy( VaryingNode ); +/** + * Computes a node in the vertex stage. + * + * @function + * @param {Node} node - The node which should be executed in the vertex stage. + * @returns {VaryingNode} + */ +const vertexStage = ( node ) => varying( node ); + addMethodChaining( 'varying', varying ); +addMethodChaining( 'vertexStage', vertexStage ); /** @module ColorSpaceFunctions **/ @@ -6967,7 +7343,7 @@ addMethodChaining( 'toneMapping', ( color, mapping, exposure ) => toneMapping( m * material.colorNode = bufferAttribute( new THREE.Float32BufferAttribute( colors, 3 ) ); * ``` * This new approach is especially interesting when geometry data are generated via - * compute shaders. The below line converts a storage buffer into an attribute. + * compute shaders. The below line converts a storage buffer into an attribute node. * ```js * material.positionNode = positionBuffer.toAttribute(); * ``` @@ -7349,6 +7725,14 @@ class ComputeNode extends Node { */ this.version = 1; + /** + * The name or label of the uniform. + * + * @type {String} + * @default '' + */ + this.name = ''; + /** * The `updateBeforeType` is set to `NodeUpdateType.OBJECT` since {@link ComputeNode#updateBefore} * is executed once per object by default. @@ -7378,6 +7762,20 @@ class ComputeNode extends Node { } + /** + * Sets the {@link ComputeNode#name} property. + * + * @param {String} name - The name of the uniform. + * @return {ComputeNode} A reference to this node. + */ + label( name ) { + + this.name = name; + + return this; + + } + /** * TODO */ @@ -7507,7 +7905,16 @@ class CacheNode extends Node { getNodeType( builder ) { - return this.node.getNodeType( builder ); + const previousCache = builder.getCache(); + const cache = builder.getCacheFromNode( this, this.parent ); + + builder.setCache( cache ); + + const nodeType = this.node.getNodeType( builder ); + + builder.setCache( previousCache ); + + return nodeType; } @@ -8572,7 +8979,7 @@ class TextureNode extends UniformNode { setUpdateMatrix( value ) { this.updateMatrix = value; - this.updateType = value ? NodeUpdateType.FRAME : NodeUpdateType.NONE; + this.updateType = value ? NodeUpdateType.RENDER : NodeUpdateType.NONE; return this; @@ -8620,6 +9027,16 @@ class TextureNode extends UniformNode { // + const texture = this.value; + + if ( ! texture || texture.isTexture !== true ) { + + throw new Error( 'THREE.TSL: `texture( value )` function expects a valid instance of THREE.Texture().' ); + + } + + // + let uvNode = this.uvNode; if ( ( uvNode === null || builder.context.forceUVContext === true ) && builder.context.getUV ) { @@ -8730,16 +9147,9 @@ class TextureNode extends UniformNode { */ generate( builder, output ) { - const properties = builder.getNodeProperties( this ); - const texture = this.value; - if ( ! texture || texture.isTexture !== true ) { - - throw new Error( 'TextureNode: Need a three.js texture.' ); - - } - + const properties = builder.getNodeProperties( this ); const textureProperty = super.generate( builder, 'property' ); if ( output === 'sampler' ) { @@ -9688,7 +10098,9 @@ const normalWorld = /*@__PURE__*/ varying( normalView.transformDirection( camera */ const transformedNormalView = /*@__PURE__*/ ( Fn( ( builder ) => { - return builder.context.setupNormal(); + // Use getUV context to avoid side effects from nodes overwriting getUV in the context (e.g. EnvironmentNode) + + return builder.context.setupNormal().context( { getUV: null } ); }, 'vec3' ).once() )().mul( faceDirection ).toVar( 'transformedNormalView' ); @@ -9706,7 +10118,9 @@ const transformedNormalWorld = /*@__PURE__*/ transformedNormalView.transformDire */ const transformedClearcoatNormalView = /*@__PURE__*/ ( Fn( ( builder ) => { - return builder.context.setupClearcoatNormal(); + // Use getUV context to avoid side effects from nodes overwriting getUV in the context (e.g. EnvironmentNode) + + return builder.context.setupClearcoatNormal().context( { getUV: null } ); }, 'vec3' ).once() )().mul( faceDirection ).toVar( 'transformedClearcoatNormalView' ); @@ -11052,8 +11466,8 @@ class NormalMapNode extends TempNode { /** * Constructs a new normal map node. * - * @param {Node} node - Represents the normal map data. - * @param {Node?} [scaleNode=null] - Controls the intensity of the effect. + * @param {Node} node - Represents the normal map data. + * @param {Node?} [scaleNode=null] - Controls the intensity of the effect. */ constructor( node, scaleNode = null ) { @@ -11062,14 +11476,14 @@ class NormalMapNode extends TempNode { /** * Represents the normal map data. * - * @type {Node} + * @type {Node} */ this.node = node; /** * Controls the intensity of the effect. * - * @type {Node?} + * @type {Node?} * @default null */ this.scaleNode = scaleNode; @@ -11133,8 +11547,8 @@ class NormalMapNode extends TempNode { * TSL function for creating a normal map node. * * @function - * @param {Node} node - Represents the normal map data. - * @param {Node?} [scaleNode=null] - Controls the intensity of the effect. + * @param {Node} node - Represents the normal map data. + * @param {Node?} [scaleNode=null] - Controls the intensity of the effect. * @returns {NormalMapNode} */ const normalMap = /*@__PURE__*/ nodeProxy( NormalMapNode ); @@ -11200,8 +11614,8 @@ class BumpMapNode extends TempNode { /** * Constructs a new bump map node. * - * @param {Node} textureNode - Represents the bump map data. - * @param {Node?} [scaleNode=null] - Controls the intensity of the bump effect. + * @param {Node} textureNode - Represents the bump map data. + * @param {Node?} [scaleNode=null] - Controls the intensity of the bump effect. */ constructor( textureNode, scaleNode = null ) { @@ -11210,14 +11624,14 @@ class BumpMapNode extends TempNode { /** * Represents the bump map data. * - * @type {Node} + * @type {Node} */ this.textureNode = textureNode; /** * Controls the intensity of the bump effect. * - * @type {Node?} + * @type {Node?} * @default null */ this.scaleNode = scaleNode; @@ -11243,8 +11657,8 @@ class BumpMapNode extends TempNode { * TSL function for creating a bump map node. * * @function - * @param {Node} textureNode - Represents the bump map data. - * @param {Node?} [scaleNode=null] - Controls the intensity of the bump effect. + * @param {Node} textureNode - Represents the bump map data. + * @param {Node?} [scaleNode=null] - Controls the intensity of the bump effect. * @returns {BumpMapNode} */ const bumpMap = /*@__PURE__*/ nodeProxy( BumpMapNode ); @@ -11402,15 +11816,15 @@ class MaterialNode extends Node { } else if ( scope === MaterialNode.SPECULAR_INTENSITY ) { - const specularIntensity = this.getFloat( scope ); + const specularIntensityNode = this.getFloat( scope ); - if ( material.specularMap ) { + if ( material.specularIntensityMap && material.specularIntensityMap.isTexture === true ) { - node = specularIntensity.mul( this.getTexture( scope ).a ); + node = specularIntensityNode.mul( this.getTexture( scope ).a ); } else { - node = specularIntensity; + node = specularIntensityNode; } @@ -11625,7 +12039,7 @@ class MaterialNode extends Node { node = this.getTexture( scope ).rgb.mul( this.getFloat( 'lightMapIntensity' ) ); - } else if ( scope === MaterialNode.AO_MAP ) { + } else if ( scope === MaterialNode.AO ) { node = this.getTexture( scope ).r.sub( 1.0 ).mul( this.getFloat( 'aoMapIntensity' ) ).add( 1.0 ); @@ -11679,7 +12093,7 @@ MaterialNode.LINE_DASH_OFFSET = 'dashOffset'; MaterialNode.POINT_WIDTH = 'pointWidth'; MaterialNode.DISPERSION = 'dispersion'; MaterialNode.LIGHT_MAP = 'light'; -MaterialNode.AO_MAP = 'ao'; +MaterialNode.AO = 'ao'; /** * TSL object that represents alpha test of the current material. @@ -11738,7 +12152,7 @@ const materialSpecularIntensity = /*@__PURE__*/ nodeImmutable( MaterialNode, Mat * TSL object that represents the specular color of the current material. * The value is composed via `specularColor` * `specularMap.rgb`. * - * @type {Node} + * @type {Node} */ const materialSpecularColor = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SPECULAR_COLOR ); @@ -11759,7 +12173,7 @@ const materialReflectivity = /*@__PURE__*/ nodeImmutable( MaterialNode, Material /** * TSL object that represents the roughness of the current material. - * The value is composed via `roughness` * `roughnessMap.g` + * The value is composed via `roughness` * `roughnessMap.g`. * * @type {Node} */ @@ -11767,7 +12181,7 @@ const materialRoughness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNod /** * TSL object that represents the metalness of the current material. - * The value is composed via `metalness` * `metalnessMap.b` + * The value is composed via `metalness` * `metalnessMap.b`. * * @type {Node} */ @@ -11775,15 +12189,15 @@ const materialMetalness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNod /** * TSL object that represents the normal of the current material. - * The value will be either `normalMap`, `bumpMap` or `normalView`. + * The value will be either `normalMap` * `normalScale`, `bumpMap` * `bumpScale` or `normalView`. * * @type {Node} */ -const materialNormal = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.NORMAL ).context( { getUV: null } ); +const materialNormal = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.NORMAL ); /** * TSL object that represents the clearcoat of the current material. - * The value is composed via `clearcoat` * `clearcoat.r` + * The value is composed via `clearcoat` * `clearcoatMap.r` * * @type {Node} */ @@ -11791,7 +12205,7 @@ const materialClearcoat = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNod /** * TSL object that represents the clearcoat roughness of the current material. - * The value is composed via `clearcoatRoughness` * `clearcoatRoughnessMap.r` + * The value is composed via `clearcoatRoughness` * `clearcoatRoughnessMap.r`. * * @type {Node} */ @@ -11803,7 +12217,7 @@ const materialClearcoatRoughness = /*@__PURE__*/ nodeImmutable( MaterialNode, Ma * * @type {Node} */ -const materialClearcoatNormal = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.CLEARCOAT_NORMAL ).context( { getUV: null } ); +const materialClearcoatNormal = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.CLEARCOAT_NORMAL ); /** * TSL object that represents the rotation of the current sprite material. @@ -11822,7 +12236,7 @@ const materialSheen = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SH /** * TSL object that represents the sheen roughness of the current material. - * The value is composed via `sheenRoughness` * `sheenRoughnessMap.a` . + * The value is composed via `sheenRoughness` * `sheenRoughnessMap.a`. * * @type {Node} */ @@ -11956,7 +12370,7 @@ const materialLightMap = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode * * @type {Node} */ -const materialAOMap = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.AO_MAP ); +const materialAO = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.AO ); /** * TSL object that represents the anisotropy vector of the current material. @@ -12759,7 +13173,7 @@ class SkinningNode extends Node { const mrt = builder.renderer.getMRT(); - return mrt && mrt.has( 'velocity' ); + return ( mrt && mrt.has( 'velocity' ) ) || getDataFromObject( builder.object ).useVelocity === true; } @@ -14733,6 +15147,11 @@ const getAlphaHashThreshold = /*@__PURE__*/ Fn( ( [ position ] ) => { ] } ); +/** + * Base class for all node materials. + * + * @augments Material + */ class NodeMaterial extends Material { static get type() { @@ -14741,6 +15160,11 @@ class NodeMaterial extends Material { } + /** + * Represents the type of the node material. + * + * @type {String} + */ get type() { return this.constructor.type; @@ -14749,63 +15173,359 @@ class NodeMaterial extends Material { set type( _value ) { /* */ } + /** + * Constructs a new node material. + */ constructor() { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isNodeMaterial = true; - this.forceSinglePass = false; - + /** + * Whether this material is affected by fog or not. + * + * @type {Boolean} + * @default true + */ this.fog = true; + + /** + * Whether this material is affected by lights or not. + * + * @type {Boolean} + * @default false + */ this.lights = false; + + /** + * Whether this material uses hardware clipping or not. + * This property is managed by the engine and should not be + * modified by apps. + * + * @type {Boolean} + * @default false + */ this.hardwareClipping = false; + /** + * Node materials which set their `lights` property to `true` + * are affected by all lights of the scene. Sometimes selective + * lighting is wanted which means only _some_ lights in the scene + * affect a material. This can be achieved by creating an instance + * of {@link module:LightsNode~LightsNode} with a list of selective + * lights and assign the node to this property. + * + * ```js + * const customLightsNode = lights( [ light1, light2 ] ); + * material.lightsNode = customLightsNode; + * ``` + * + * @type {LightsNode?} + * @default null + */ this.lightsNode = null; + + /** + * The environment of node materials can be defined by an environment + * map assigned to the `envMap` property or by `Scene.environment` + * if the node material is a PBR material. This node property allows to overwrite + * the default behavior and define the environment with a custom node. + * + * ```js + * material.envNode = pmremTexture( renderTarget.texture ); + * ``` + * + * @type {Node?} + * @default null + */ this.envNode = null; + + /** + * The lighting of node materials might be influenced by ambient occlusion. + * The default AO is inferred from an ambient occlusion map assigned to `aoMap` + * and the respective `aoMapIntensity`. This node property allows to overwrite + * the default and define the ambient occlusion with a custom node instead. + * + * If you don't want to overwrite the diffuse color but modify the existing + * values instead, use {@link module:MaterialNode.materialAO}. + * + * @type {Node?} + * @default null + */ this.aoNode = null; + /** + * The diffuse color of node materials is by default inferred from the + * `color` and `map` properties. This node property allows to overwrite the default + * and define the diffuse color with a node instead. + * + * ```js + * material.colorNode = color( 0xff0000 ); // define red color + * ``` + * + * If you don't want to overwrite the diffuse color but modify the existing + * values instead, use {@link module:MaterialNode.materialColor}. + * + * ```js + * material.colorNode = materialColor.mul( color( 0xff0000 ) ); // give diffuse colors a red tint + * ``` + * + * @type {Node?} + * @default null + */ this.colorNode = null; + + /** + * The normals of node materials are by default inferred from the `normalMap`/`normalScale` + * or `bumpMap`/`bumpScale` properties. This node property allows to overwrite the default + * and define the normals with a node instead. + * + * If you don't want to overwrite the normals but modify the existing values instead, + * use {@link module:MaterialNode.materialNormal}. + * + * @type {Node?} + * @default null + */ this.normalNode = null; + + /** + * The opacity of node materials is by default inferred from the `opacity` + * and `alphaMap` properties. This node property allows to overwrite the default + * and define the opacity with a node instead. + * + * If you don't want to overwrite the normals but modify the existing + * value instead, use {@link module:MaterialNode.materialOpacity}. + * + * @type {Node?} + * @default null + */ this.opacityNode = null; + + /** + * This node can be used to to implement a variety of filter-like effects. The idea is + * to store the current rendering into a texture e.g. via `viewportSharedTexture()`, use it + * to create an arbitrary effect and then assign the node composition to this property. + * Everything behind the object using this material will now be affected by a filter. + * + * ```js + * const material = new NodeMaterial() + * material.transparent = true; + * + * // everything behind the object will be monochromatic + * material.backdropNode = viewportSharedTexture().rgb.saturation( 0 ); + * ``` + * + * Backdrop computations are part of the lighting so only lit materials can use this property. + * + * @type {Node?} + * @default null + */ this.backdropNode = null; + + /** + * This node allows to modulate the influence of `backdropNode` to the outgoing light. + * + * @type {Node?} + * @default null + */ this.backdropAlphaNode = null; + + /** + * The alpha test of node materials is by default inferred from the `alphaTest` + * property. This node property allows to overwrite the default and define the + * alpha test with a node instead. + * + * If you don't want to overwrite the alpha test but modify the existing + * value instead, use {@link module:MaterialNode.materialAlphaTest}. + * + * @type {Node?} + * @default null + */ this.alphaTestNode = null; + /** + * The local vertex positions are computed based on multiple factors like the + * attribute data, morphing or skinning. This node property allows to overwrite + * the default and define local vertex positions with nodes instead. + * + * If you don't want to overwrite the vertex positions but modify the existing + * values instead, use {@link module:Position.positionLocal}. + * + *```js + * material.positionNode = positionLocal.add( displace ); + * ``` + * + * @type {Node?} + * @default null + */ this.positionNode = null; + + /** + * This node property is intended for logic which modifies geometry data once or per animation step. + * Apps usually place such logic randomly in initialization routines or in the animation loop. + * `geometryNode` is intended as a dedicated API so there is an intended spot where geometry modifications + * can be implemented. + * + * The idea is to assign a `Fn` definition that holds the geometry modification logic. A typical example + * would be a GPU based particle system that provides a node material for usage on app level. The particle + * simulation would be implemented as compute shaders and managed inside a `Fn` function. This function is + * eventually assigned to `geometryNode`. + * + * @type {Function} + * @default null + */ this.geometryNode = null; + /** + * Allows to overwrite depth values in the fragment shader. + * + * @type {Node?} + * @default null + */ this.depthNode = null; + + /** + * Allows to overwrite the position used for shadow map rendering which + * is by default {@link module:Position.positionWorld}, the vertex position + * in world space. + * + * @type {Node?} + * @default null + */ this.shadowPositionNode = null; + + /** + * This node can be used to influence how an object using this node material + * receive shadows. + * + * ```js + * const totalShadows = float( 1 ).toVar(); + * material.receivedShadowNode = Fn( ( [ shadow ] ) => { + * totalShadows.mulAssign( shadow ); + * //return float( 1 ); // bypass received shadows + * return shadow.mix( color( 0xff0000 ), 1 ); // modify shadow color + * } ); + * + * @type {Node?} + * @default null + */ this.receivedShadowNode = null; + + /** + * This node can be used to influence how an object using this node material + * casts shadows. To apply a color to shadows, you can simply do: + * + * ```js + * material.castShadowNode = vec4( 1, 0, 0, 1 ); + * ``` + * + * Which can be nice to fake colored shadows of semi-transparent objects. It + * is also common to use the property with `Fn` function so checks are performed + * per fragment. + * + * ```js + * materialCustomShadow.castShadowNode = Fn( () => { + * hash( vertexIndex ).greaterThan( 0.5 ).discard(); + * return materialColor; + * } )(); + * ``` + * + * @type {Node?} + * @default null + */ this.castShadowNode = null; + /** + * This node can be used to define the final output of the material. + * + * TODO: Explain the differences to `fragmentNode`. + * + * @type {Node?} + * @default null + */ this.outputNode = null; + + /** + * MRT configuration is done on renderer or pass level. This node allows to + * overwrite what values are written into MRT targets on material level. This + * can be useful for implementing selective FX features that should only affect + * specific objects. + * + * @type {MRTNode?} + * @default null + */ this.mrtNode = null; + /** + * This node property can be used if you need complete freedom in implementing + * the fragment shader. Assigning a node will replace the built-in material + * logic used in the fragment stage. + * + * @type {Node?} + * @default null + */ this.fragmentNode = null; + + /** + * This node property can be used if you need complete freedom in implementing + * the vertex shader. Assigning a node will replace the built-in material logic + * used in the vertex stage. + * + * @type {Node?} + * @default null + */ this.vertexNode = null; } + /** + * Allows to define a custom cache key that influence the material key computation + * for render objects. + * + * @return {String} The custom cache key. + */ customProgramCacheKey() { return this.type + getCacheKey$1( this ); } + /** + * Builds this material with the given node builder. + * + * @param {NodeBuilder} builder - The current node builder. + */ build( builder ) { this.setup( builder ); } + /** + * Setups a node material observer with the given builder. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {NodeMaterialObserver} The node material observer. + */ setupObserver( builder ) { return new NodeMaterialObserver( builder ); } + /** + * Setups the vertex and fragment stage of this node material. + * + * @param {NodeBuilder} builder - The current node builder. + */ setup( builder ) { builder.context.setupNormal = () => this.setupNormal( builder ); @@ -14841,7 +15561,7 @@ class NodeMaterial extends Material { const clippingNode = this.setupClipping( builder ); - if ( this.depthWrite === true ) { + if ( this.depthWrite === true || this.depthTest === true ) { // only write depth if depth buffer is configured @@ -14929,6 +15649,12 @@ class NodeMaterial extends Material { } + /** + * Setups the clipping node. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {ClippingNode} The clipping node. + */ setupClipping( builder ) { if ( builder.clippingContext === null ) return null; @@ -14958,6 +15684,11 @@ class NodeMaterial extends Material { } + /** + * Setups the hardware clipping if available on the current device. + * + * @param {NodeBuilder} builder - The current node builder. + */ setupHardwareClipping( builder ) { this.hardwareClipping = false; @@ -14980,6 +15711,11 @@ class NodeMaterial extends Material { } + /** + * Setups the depth of this material. + * + * @param {NodeBuilder} builder - The current node builder. + */ setupDepth( builder ) { const { renderer, camera } = builder; @@ -15020,18 +15756,37 @@ class NodeMaterial extends Material { } - setupPositionView() { + /** + * Setups the position node in view space. This method exists + * so derived node materials can modify the implementation e.g. sprite materials. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Node} The position in view space. + */ + setupPositionView( /*builder*/ ) { return modelViewMatrix.mul( positionLocal ).xyz; } - setupModelViewProjection() { + /** + * Setups the position in clip space. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Node} The position in view space. + */ + setupModelViewProjection( /*builder*/ ) { return cameraProjectionMatrix.mul( positionView ); } + /** + * Setups the logic for the vertex stage. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Node} The position in clip space. + */ setupVertex( builder ) { builder.addStack(); @@ -15044,6 +15799,12 @@ class NodeMaterial extends Material { } + /** + * Setups the computation of the position in local space. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Node} The position in local space. + */ setupPosition( builder ) { const { object, geometry } = builder; @@ -15092,6 +15853,12 @@ class NodeMaterial extends Material { } + /** + * Setups the computation of the material's diffuse color. + * + * @param {NodeBuilder} builder - The current node builder. + * @param {BufferGeometry} geometry - The geometry. + */ setupDiffuseColor( { object, geometry } ) { let colorNode = this.colorNode ? vec4( this.colorNode ) : materialColor; @@ -15158,24 +15925,47 @@ class NodeMaterial extends Material { } + /** + * Abstract interface method that can be implemented by derived materials + * to setup material-specific node variables. + * + * @abstract + * @param {NodeBuilder} builder - The current node builder. + */ setupVariants( /*builder*/ ) { // Interface function. } + /** + * Setups the outgoing light node variable + * + * @return {Node} The outgoing light node. + */ setupOutgoingLight() { return ( this.lights === true ) ? vec3( 0 ) : diffuseColor.rgb; } + /** + * Setups the normal node from the material. + * + * @return {Node} The normal node. + */ setupNormal() { return this.normalNode ? vec3( this.normalNode ) : materialNormal; } + /** + * Setups the environment node from the material. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Node} The environment node. + */ setupEnvironment( /*builder*/ ) { let node = null; @@ -15194,6 +15984,12 @@ class NodeMaterial extends Material { } + /** + * Setups the light map node from the material. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Node} The light map node. + */ setupLightMap( builder ) { let node = null; @@ -15208,6 +16004,12 @@ class NodeMaterial extends Material { } + /** + * Setups the lights node based on the scene, environment and material. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {LightsNode} The lights node. + */ setupLights( builder ) { const materialLightsNode = []; @@ -15232,7 +16034,7 @@ class NodeMaterial extends Material { if ( this.aoNode !== null || builder.material.aoMap ) { - const aoNode = this.aoNode !== null ? this.aoNode : materialAOMap; + const aoNode = this.aoNode !== null ? this.aoNode : materialAO; materialLightsNode.push( new AONode( aoNode ) ); @@ -15250,12 +16052,26 @@ class NodeMaterial extends Material { } + /** + * This method should be implemented by most derived materials + * since it defines the material's lighting model. + * + * @abstract + * @param {NodeBuilder} builder - The current node builder. + * @return {LightingModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { // Interface function. } + /** + * Setups the outgoing light node. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Node} The outgoing light node. + */ setupLighting( builder ) { const { material } = builder; @@ -15295,6 +16111,13 @@ class NodeMaterial extends Material { } + /** + * Setups the output node. + * + * @param {NodeBuilder} builder - The current node builder. + * @param {Node} outputNode - The existing output node. + * @return {Node} The output node. + */ setupOutput( builder, outputNode ) { // FOG @@ -15317,6 +16140,13 @@ class NodeMaterial extends Material { } + /** + * Most classic material types have a node pendant e.g. for `MeshBasicMaterial` + * there is `MeshBasicNodeMaterial`. This utility method is intended for + * defining all material properties of the classic type in the node type. + * + * @param {Material} material - The material to copy properties with their values to this node material. + */ setDefaultValues( material ) { // This approach is to reuse the native refreshUniforms* @@ -15351,6 +16181,12 @@ class NodeMaterial extends Material { } + /** + * Serializes this material to JSON. + * + * @param {(Object|String)?} meta - The meta information for serialization. + * @return {Object} The serialized node. + */ toJSON( meta ) { const isRoot = ( meta === undefined || typeof meta === 'string' ); @@ -15410,6 +16246,12 @@ class NodeMaterial extends Material { } + /** + * Copies the properties of the given node material to this instance. + * + * @param {NodeMaterial} source - The material to copy. + * @return {NodeMaterial} A reference to this node material. + */ copy( source ) { this.lightsNode = source.lightsNode; @@ -15444,6 +16286,15 @@ class NodeMaterial extends Material { const _defaultValues$e = /*@__PURE__*/ new PointsMaterial(); +/** + * Unlike WebGL, WebGPU can render point primitives only with a size + * of one pixel. This type node material can be used to mimic the WebGL + * points rendering by rendering small planes via instancing. + * + * This material should be used with {@link InstancedPointsGeometry}. + * + * @augments NodeMaterial + */ class InstancedPointsNodeMaterial extends NodeMaterial { static get type() { @@ -15452,39 +16303,75 @@ class InstancedPointsNodeMaterial extends NodeMaterial { } - constructor( params = {} ) { + /** + * Constructs a new instanced points node material. + * + * @param {Object?} parameters - The configuration parameter. + */ + constructor( parameters = {} ) { super(); - this.lights = false; - - this.useAlphaToCoverage = true; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ + this.isInstancedPointsNodeMaterial = true; - this.useColor = params.vertexColors; + /** + * Whether vertex colors should be used or not. If set to `true`, + * each point instance can receive a custom color value. + * + * @type {Boolean} + * @default false + */ + this.useColor = parameters.vertexColors; + /** + * The points width in pixels. + * + * @type {Number} + * @default 1 + */ this.pointWidth = 1; + /** + * This node can be used to define the colors for each instance. + * + * @type {Node?} + * @default null + */ this.pointColorNode = null; + /** + * This node can be used to define the width for each point instance. + * + * @type {Node?} + * @default null + */ this.pointWidthNode = null; + this._useAlphaToCoverage = true; + this.setDefaultValues( _defaultValues$e ); - this.setValues( params ); + this.setValues( parameters ); } + /** + * Setups the vertex and fragment stage of this node material. + * + * @param {NodeBuilder} builder - The current node builder. + */ setup( builder ) { - this.setupShaders( builder ); - - super.setup( builder ); - - } - - setupShaders( { renderer } ) { + const { renderer } = builder; - const useAlphaToCoverage = this.alphaToCoverage; + const useAlphaToCoverage = this._useAlphaToCoverage; const useColor = this.useColor; this.vertexNode = Fn( () => { @@ -15563,19 +16450,27 @@ class InstancedPointsNodeMaterial extends NodeMaterial { } )(); + super.setup( builder ); + } + /** + * Whether alpha to coverage should be used or not. + * + * @type {Boolean} + * @default true + */ get alphaToCoverage() { - return this.useAlphaToCoverage; + return this._useAlphaToCoverage; } set alphaToCoverage( value ) { - if ( this.useAlphaToCoverage !== value ) { + if ( this._useAlphaToCoverage !== value ) { - this.useAlphaToCoverage = value; + this._useAlphaToCoverage = value; this.needsUpdate = true; } @@ -15586,6 +16481,11 @@ class InstancedPointsNodeMaterial extends NodeMaterial { const _defaultValues$d = /*@__PURE__*/ new LineBasicMaterial(); +/** + * Node material version of `LineBasicMaterial`. + * + * @augments NodeMaterial + */ class LineBasicNodeMaterial extends NodeMaterial { static get type() { @@ -15594,14 +16494,24 @@ class LineBasicNodeMaterial extends NodeMaterial { } + /** + * Constructs a new line basic node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isLineBasicNodeMaterial = true; - this.lights = false; - this.setDefaultValues( _defaultValues$d ); this.setValues( parameters ); @@ -15612,6 +16522,11 @@ class LineBasicNodeMaterial extends NodeMaterial { const _defaultValues$c = /*@__PURE__*/ new LineDashedMaterial(); +/** + * Node material version of `LineDashedMaterial`. + * + * @augments NodeMaterial + */ class LineDashedNodeMaterial extends NodeMaterial { static get type() { @@ -15620,33 +16535,101 @@ class LineDashedNodeMaterial extends NodeMaterial { } + /** + * Constructs a new line dashed node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isLineDashedNodeMaterial = true; - this.lights = false; - this.setDefaultValues( _defaultValues$c ); + /** + * The dash offset. + * + * @type {Number} + * @default 0 + */ this.dashOffset = 0; + /** + * The offset of dash materials is by default inferred from the `dashOffset` + * property. This node property allows to overwrite the default + * and define the offset with a node instead. + * + * If you don't want to overwrite the offset but modify the existing + * value instead, use {@link module:MaterialNode.materialLineDashOffset}. + * + * @type {Node?} + * @default null + */ this.offsetNode = null; + + /** + * The scale of dash materials is by default inferred from the `scale` + * property. This node property allows to overwrite the default + * and define the scale with a node instead. + * + * If you don't want to overwrite the scale but modify the existing + * value instead, use {@link module:MaterialNode.materialLineScale}. + * + * @type {Node?} + * @default null + */ this.dashScaleNode = null; + + /** + * The dash size of dash materials is by default inferred from the `dashSize` + * property. This node property allows to overwrite the default + * and define the dash size with a node instead. + * + * If you don't want to overwrite the dash size but modify the existing + * value instead, use {@link module:MaterialNode.materialLineDashSize}. + * + * @type {Node?} + * @default null + */ this.dashSizeNode = null; + + /** + * The gap size of dash materials is by default inferred from the `gapSize` + * property. This node property allows to overwrite the default + * and define the gap size with a node instead. + * + * If you don't want to overwrite the gap size but modify the existing + * value instead, use {@link module:MaterialNode.materialLineGapSize}. + * + * @type {Node?} + * @default null + */ this.gapSizeNode = null; this.setValues( parameters ); } - setupVariants() { + /** + * Setups the dash specific node variables. + * + * @param {NodeBuilder} builder - The current node builder. + */ + setupVariants( /* builder */ ) { - const offsetNode = this.offsetNode ? float( this.offsetNodeNode ) : materialLineDashOffset; + const offsetNode = this.offsetNode ? float( this.offsetNode ) : materialLineDashOffset; const dashScaleNode = this.dashScaleNode ? float( this.dashScaleNode ) : materialLineScale; const dashSizeNode = this.dashSizeNode ? float( this.dashSizeNode ) : materialLineDashSize; - const gapSizeNode = this.dashSizeNode ? float( this.dashGapNode ) : materialLineGapSize; + const gapSizeNode = this.gapSizeNode ? float( this.gapSizeNode ) : materialLineGapSize; dashSize.assign( dashSizeNode ); gapSize.assign( gapSizeNode ); @@ -15717,6 +16700,12 @@ const viewportSharedTexture = /*@__PURE__*/ nodeProxy( ViewportSharedTextureNode const _defaultValues$b = /*@__PURE__*/ new LineDashedMaterial(); +/** + * This node material can be used to render lines with a size larger than one + * by representing them as instanced meshes. + * + * @augments NodeMaterial + */ class Line2NodeMaterial extends NodeMaterial { static get type() { @@ -15725,49 +16714,120 @@ class Line2NodeMaterial extends NodeMaterial { } - constructor( params = {} ) { + /** + * Constructs a new node material for wide line rendering. + * + * @param {Object?} parameters - The configuration parameter. + */ + constructor( parameters = {} ) { super(); - this.lights = false; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ + this.isLine2NodeMaterial = true; this.setDefaultValues( _defaultValues$b ); - this.useAlphaToCoverage = true; - this.useColor = params.vertexColors; - this.useDash = params.dashed; - this.useWorldUnits = false; + /** + * Whether vertex colors should be used or not. + * + * @type {Boolean} + * @default false + */ + this.useColor = parameters.vertexColors; + /** + * The dash offset. + * + * @type {Number} + * @default 0 + */ this.dashOffset = 0; + + /** + * The line width. + * + * @type {Number} + * @default 0 + */ this.lineWidth = 1; + /** + * Defines the lines color. + * + * @type {Node?} + * @default null + */ this.lineColorNode = null; + /** + * Defines the offset. + * + * @type {Node?} + * @default null + */ this.offsetNode = null; + + /** + * Defines the dash scale. + * + * @type {Node?} + * @default null + */ this.dashScaleNode = null; + + /** + * Defines the dash size. + * + * @type {Node?} + * @default null + */ this.dashSizeNode = null; + + /** + * Defines the gap size. + * + * @type {Node?} + * @default null + */ this.gapSizeNode = null; + /** + * Blending is set to `NoBlending` since transparency + * is not supported, yet. + * + * @type {Number} + * @default 0 + */ this.blending = NoBlending; - this.setValues( params ); + this._useDash = parameters.dashed; + this._useAlphaToCoverage = true; + this._useWorldUnits = false; + + this.setValues( parameters ); } + /** + * Setups the vertex and fragment stage of this node material. + * + * @param {NodeBuilder} builder - The current node builder. + */ setup( builder ) { - this.setupShaders( builder ); - - super.setup( builder ); - - } - - setupShaders( { renderer } ) { + const { renderer } = builder; - const useAlphaToCoverage = this.alphaToCoverage; + const useAlphaToCoverage = this._useAlphaToCoverage; const useColor = this.useColor; - const useDash = this.dashed; - const useWorldUnits = this.worldUnits; + const useDash = this._useDash; + const useWorldUnits = this._useWorldUnits; const trimSegment = Fn( ( { start, end } ) => { @@ -16095,56 +17155,74 @@ class Line2NodeMaterial extends NodeMaterial { } - } + super.setup( builder ); + } + /** + * Whether the lines should sized in world units or not. + * When set to `false` the unit is pixel. + * + * @type {Boolean} + * @default false + */ get worldUnits() { - return this.useWorldUnits; + return this._useWorldUnits; } set worldUnits( value ) { - if ( this.useWorldUnits !== value ) { + if ( this._useWorldUnits !== value ) { - this.useWorldUnits = value; + this._useWorldUnits = value; this.needsUpdate = true; } } - + /** + * Whether the lines should be dashed or not. + * + * @type {Boolean} + * @default false + */ get dashed() { - return this.useDash; + return this._useDash; } set dashed( value ) { - if ( this.useDash !== value ) { + if ( this._useDash !== value ) { - this.useDash = value; + this._useDash = value; this.needsUpdate = true; } } - + /** + * Whether alpha to coverage should be used or not. + * + * @type {Boolean} + * @default true + */ get alphaToCoverage() { - return this.useAlphaToCoverage; + return this._useAlphaToCoverage; } set alphaToCoverage( value ) { - if ( this.useAlphaToCoverage !== value ) { + if ( this._useAlphaToCoverage !== value ) { - this.useAlphaToCoverage = value; + this._useAlphaToCoverage = value; this.needsUpdate = true; } @@ -16175,6 +17253,11 @@ const colorToDirection = ( node ) => nodeObject( node ).mul( 2.0 ).sub( 1 ); const _defaultValues$a = /*@__PURE__*/ new MeshNormalMaterial(); +/** + * Node material version of `MeshNormalMaterial`. + * + * @augments NodeMaterial + */ class MeshNormalNodeMaterial extends NodeMaterial { static get type() { @@ -16183,12 +17266,22 @@ class MeshNormalNodeMaterial extends NodeMaterial { } + /** + * Constructs a new mesh normal node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); - this.lights = false; - + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshNormalNodeMaterial = true; this.setDefaultValues( _defaultValues$a ); @@ -16197,6 +17290,10 @@ class MeshNormalNodeMaterial extends NodeMaterial { } + /** + * Overwrites the default implementation by computing the diffuse color + * based on the normal data. + */ setupDiffuseColor() { const opacityNode = this.opacityNode ? float( this.opacityNode ) : materialOpacity; @@ -16270,6 +17367,12 @@ const equirectUV = /*@__PURE__*/ nodeProxy( EquirectUVNode ); // @TODO: Consider rename WebGLCubeRenderTarget to just CubeRenderTarget +/** + * This class represents a cube render target. It is a special version + * of `WebGLCubeRenderTarget` which is compatible with `WebGPURenderer`. + * + * @augments WebGLCubeRenderTarget + */ class CubeRenderTarget extends WebGLCubeRenderTarget { constructor( size = 1, options = {} ) { @@ -16280,6 +17383,13 @@ class CubeRenderTarget extends WebGLCubeRenderTarget { } + /** + * Converts the given equirectangular texture to a cube map. + * + * @param {Renderer} renderer - The renderer. + * @param {Texture} texture - The equirectangular texture. + * @return {CubeRenderTarget} A reference to this cube render target. + */ fromEquirectangularTexture( renderer, texture$1 ) { const currentMinFilter = texture$1.minFilter; @@ -16823,6 +17933,11 @@ class BasicLightingModel extends LightingModel { const _defaultValues$9 = /*@__PURE__*/ new MeshBasicMaterial(); +/** + * Node material version of `MeshBasicMaterial`. + * + * @augments NodeMaterial + */ class MeshBasicNodeMaterial extends NodeMaterial { static get type() { @@ -16831,12 +17946,32 @@ class MeshBasicNodeMaterial extends NodeMaterial { } + /** + * Constructs a new mesh basic node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshBasicNodeMaterial = true; + /** + * Although the basic material is by definition unlit, we set + * this property to `true` since we use a lighting model to compute + * the outgoing light of the fragment shader. + * + * @type {Boolean} + * @default true + */ this.lights = true; this.setDefaultValues( _defaultValues$9 ); @@ -16845,12 +17980,25 @@ class MeshBasicNodeMaterial extends NodeMaterial { } + /** + * Basic materials are not affected by normal and bump maps so we + * return by default {@link module:Normal.normalView}. + * + * @return {Node} The normal node. + */ setupNormal() { return normalView; // see #28839 } + /** + * Overwritten since this type of material uses {@link BasicEnvironmentNode} + * to implement the default environment mapping. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {BasicEnvironmentNode?} The environment node. + */ setupEnvironment( builder ) { const envNode = super.setupEnvironment( builder ); @@ -16859,6 +18007,13 @@ class MeshBasicNodeMaterial extends NodeMaterial { } + /** + * This method must be overwritten since light maps are evaluated + * with a special scaling factor for basic materials. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {BasicLightMapNode?} The light map node. + */ setupLightMap( builder ) { let node = null; @@ -16873,12 +18028,23 @@ class MeshBasicNodeMaterial extends NodeMaterial { } + /** + * The material overwrites this method because `lights` is set to `true` but + * we still want to return the diffuse color as the outgoing light. + * + * @return {Node} The outgoing light node. + */ setupOutgoingLight() { return diffuseColor.rgb; } + /** + * Setups the lighting model. + * + * @return {BasicLightingModel} The lighting model. + */ setupLightingModel() { return new BasicLightingModel(); @@ -16999,6 +18165,11 @@ class PhongLightingModel extends BasicLightingModel { const _defaultValues$8 = /*@__PURE__*/ new MeshLambertMaterial(); +/** + * Node material version of `MeshLambertMaterial`. + * + * @augments NodeMaterial + */ class MeshLambertNodeMaterial extends NodeMaterial { static get type() { @@ -17007,12 +18178,30 @@ class MeshLambertNodeMaterial extends NodeMaterial { } + /** + * Constructs a new mesh lambert node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshLambertNodeMaterial = true; + /** + * Set to `true` because lambert materials react on lights. + * + * @type {Boolean} + * @default true + */ this.lights = true; this.setDefaultValues( _defaultValues$8 ); @@ -17021,6 +18210,13 @@ class MeshLambertNodeMaterial extends NodeMaterial { } + /** + * Overwritten since this type of material uses {@link BasicEnvironmentNode} + * to implement the default environment mapping. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {BasicEnvironmentNode?} The environment node. + */ setupEnvironment( builder ) { const envNode = super.setupEnvironment( builder ); @@ -17029,6 +18225,11 @@ class MeshLambertNodeMaterial extends NodeMaterial { } + /** + * Setups the lighting model. + * + * @return {PhongLightingModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { return new PhongLightingModel( false ); // ( specular ) -> force lambert @@ -17039,6 +18240,11 @@ class MeshLambertNodeMaterial extends NodeMaterial { const _defaultValues$7 = /*@__PURE__*/ new MeshPhongMaterial(); +/** + * Node material version of `MeshPhongMaterial`. + * + * @augments NodeMaterial + */ class MeshPhongNodeMaterial extends NodeMaterial { static get type() { @@ -17047,15 +18253,56 @@ class MeshPhongNodeMaterial extends NodeMaterial { } + /** + * Constructs a new mesh lambert node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshPhongNodeMaterial = true; + /** + * Set to `true` because phong materials react on lights. + * + * @type {Boolean} + * @default true + */ this.lights = true; + /** + * The shininess of phong materials is by default inferred from the `shininess` + * property. This node property allows to overwrite the default + * and define the shininess with a node instead. + * + * If you don't want to overwrite the shininess but modify the existing + * value instead, use {@link module:MaterialNode.materialShininess}. + * + * @type {Node?} + * @default null + */ this.shininessNode = null; + + /** + * The specular color of phong materials is by default inferred from the + * `specular` property. This node property allows to overwrite the default + * and define the specular color with a node instead. + * + * If you don't want to overwrite the specular color but modify the existing + * value instead, use {@link module:MaterialNode.materialSpecular}. + * + * @type {Node?} + * @default null + */ this.specularNode = null; this.setDefaultValues( _defaultValues$7 ); @@ -17064,6 +18311,13 @@ class MeshPhongNodeMaterial extends NodeMaterial { } + /** + * Overwritten since this type of material uses {@link BasicEnvironmentNode} + * to implement the default environment mapping. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {BasicEnvironmentNode?} The environment node. + */ setupEnvironment( builder ) { const envNode = super.setupEnvironment( builder ); @@ -17072,13 +18326,23 @@ class MeshPhongNodeMaterial extends NodeMaterial { } + /** + * Setups the lighting model. + * + * @return {PhongLightingModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { return new PhongLightingModel(); } - setupVariants() { + /** + * Setups the phong specific node variables. + * + * @param {NodeBuilder} builder - The current node builder. + */ + setupVariants( /*builder*/ ) { // SHININESS @@ -19140,6 +20404,11 @@ const createIrradianceContext = ( normalWorldNode ) => { const _defaultValues$6 = /*@__PURE__*/ new MeshStandardMaterial(); +/** + * Node material version of `MeshStandardMaterial`. + * + * @augments NodeMaterial + */ class MeshStandardNodeMaterial extends NodeMaterial { static get type() { @@ -19148,17 +20417,69 @@ class MeshStandardNodeMaterial extends NodeMaterial { } + /** + * Constructs a new mesh standard node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshStandardNodeMaterial = true; + /** + * Set to `true` because standard materials react on lights. + * + * @type {Boolean} + * @default true + */ this.lights = true; + /** + * The emissive color of standard materials is by default inferred from the `emissive`, + * `emissiveIntensity` and `emissiveMap` properties. This node property allows to + * overwrite the default and define the emissive color with a node instead. + * + * If you don't want to overwrite the emissive color but modify the existing + * value instead, use {@link module:MaterialNode.materialEmissive}. + * + * @type {Node?} + * @default null + */ this.emissiveNode = null; + /** + * The metalness of standard materials is by default inferred from the `metalness`, + * and `metalnessMap` properties. This node property allows to + * overwrite the default and define the metalness with a node instead. + * + * If you don't want to overwrite the metalness but modify the existing + * value instead, use {@link module:MaterialNode.materialMetalness}. + * + * @type {Node?} + * @default null + */ this.metalnessNode = null; + + /** + * The roughness of standard materials is by default inferred from the `roughness`, + * and `roughnessMap` properties. This node property allows to + * overwrite the default and define the roughness with a node instead. + * + * If you don't want to overwrite the roughness but modify the existing + * value instead, use {@link module:MaterialNode.materialRoughness}. + * + * @type {Node?} + * @default null + */ this.roughnessNode = null; this.setDefaultValues( _defaultValues$6 ); @@ -19167,6 +20488,14 @@ class MeshStandardNodeMaterial extends NodeMaterial { } + /** + * Overwritten since this type of material uses {@link EnvironmentNode} + * to implement the PBR (PMREM based) environment mapping. Besides, the + * method honors `Scene.environment`. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {EnvironmentNode?} The environment node. + */ setupEnvironment( builder ) { let envNode = super.setupEnvironment( builder ); @@ -19181,12 +20510,20 @@ class MeshStandardNodeMaterial extends NodeMaterial { } + /** + * Setups the lighting model. + * + * @return {PhysicalLightingModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { return new PhysicalLightingModel(); } + /** + * Setups the specular related node variables. + */ setupSpecular() { const specularColorNode = mix( vec3( 0.04 ), diffuseColor.rgb, metalness ); @@ -19196,6 +20533,11 @@ class MeshStandardNodeMaterial extends NodeMaterial { } + /** + * Setups the standard specific node variables. + * + * @param {NodeBuilder} builder - The current node builder. + */ setupVariants() { // METALNESS @@ -19236,6 +20578,11 @@ class MeshStandardNodeMaterial extends NodeMaterial { const _defaultValues$5 = /*@__PURE__*/ new MeshPhysicalMaterial(); +/** + * Node material version of `MeshPhysicalMaterial`. + * + * @augments MeshStandardNodeMaterial + */ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial { static get type() { @@ -19244,33 +20591,243 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial { } + /** + * Constructs a new mesh physical node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshPhysicalNodeMaterial = true; + /** + * The clearcoat of physical materials is by default inferred from the `clearcoat` + * and `clearcoatMap` properties. This node property allows to overwrite the default + * and define the clearcoat with a node instead. + * + * If you don't want to overwrite the clearcoat but modify the existing + * value instead, use {@link module:MaterialNode.materialClearcoat}. + * + * @type {Node?} + * @default null + */ this.clearcoatNode = null; + + /** + * The clearcoat roughness of physical materials is by default inferred from the `clearcoatRoughness` + * and `clearcoatRoughnessMap` properties. This node property allows to overwrite the default + * and define the clearcoat roughness with a node instead. + * + * If you don't want to overwrite the clearcoat roughness but modify the existing + * value instead, use {@link module:MaterialNode.materialClearcoatRoughness}. + * + * @type {Node?} + * @default null + */ this.clearcoatRoughnessNode = null; + + /** + * The clearcoat normal of physical materials is by default inferred from the `clearcoatNormalMap` + * property. This node property allows to overwrite the default + * and define the clearcoat normal with a node instead. + * + * If you don't want to overwrite the clearcoat normal but modify the existing + * value instead, use {@link module:MaterialNode.materialClearcoatNormal}. + * + * @type {Node?} + * @default null + */ this.clearcoatNormalNode = null; + /** + * The sheen of physical materials is by default inferred from the `sheen`, `sheenColor` + * and `sheenColorMap` properties. This node property allows to overwrite the default + * and define the sheen with a node instead. + * + * If you don't want to overwrite the sheen but modify the existing + * value instead, use {@link module:MaterialNode.materialSheen}. + * + * @type {Node?} + * @default null + */ this.sheenNode = null; + + /** + * The sheen roughness of physical materials is by default inferred from the `sheenRoughness` and + * `sheenRoughnessMap` properties. This node property allows to overwrite the default + * and define the sheen roughness with a node instead. + * + * If you don't want to overwrite the sheen roughness but modify the existing + * value instead, use {@link module:MaterialNode.materialSheenRoughness}. + * + * @type {Node?} + * @default null + */ this.sheenRoughnessNode = null; + /** + * The iridescence of physical materials is by default inferred from the `iridescence` + * property. This node property allows to overwrite the default + * and define the iridescence with a node instead. + * + * If you don't want to overwrite the iridescence but modify the existing + * value instead, use {@link module:MaterialNode.materialIridescence}. + * + * @type {Node?} + * @default null + */ this.iridescenceNode = null; + + /** + * The iridescence IOR of physical materials is by default inferred from the `iridescenceIOR` + * property. This node property allows to overwrite the default + * and define the iridescence IOR with a node instead. + * + * If you don't want to overwrite the iridescence IOR but modify the existing + * value instead, use {@link module:MaterialNode.materialIridescenceIOR}. + * + * @type {Node?} + * @default null + */ this.iridescenceIORNode = null; + + /** + * The iridescence thickness of physical materials is by default inferred from the `iridescenceThicknessRange` + * and `iridescenceThicknessMap` properties. This node property allows to overwrite the default + * and define the iridescence thickness with a node instead. + * + * If you don't want to overwrite the iridescence thickness but modify the existing + * value instead, use {@link module:MaterialNode.materialIridescenceThickness}. + * + * @type {Node?} + * @default null + */ this.iridescenceThicknessNode = null; + /** + * The specular intensity of physical materials is by default inferred from the `specularIntensity` + * and `specularIntensityMap` properties. This node property allows to overwrite the default + * and define the specular intensity with a node instead. + * + * If you don't want to overwrite the specular intensity but modify the existing + * value instead, use {@link module:MaterialNode.materialSpecularIntensity}. + * + * @type {Node?} + * @default null + */ this.specularIntensityNode = null; + + /** + * The specular color of physical materials is by default inferred from the `specularColor` + * and `specularColorMap` properties. This node property allows to overwrite the default + * and define the specular color with a node instead. + * + * If you don't want to overwrite the specular color but modify the existing + * value instead, use {@link module:MaterialNode.materialSpecularColor}. + * + * @type {Node?} + * @default null + */ this.specularColorNode = null; + /** + * The ior of physical materials is by default inferred from the `ior` + * property. This node property allows to overwrite the default + * and define the ior with a node instead. + * + * If you don't want to overwrite the ior but modify the existing + * value instead, use {@link module:MaterialNode.materialIOR}. + * + * @type {Node?} + * @default null + */ this.iorNode = null; + + /** + * The transmission of physical materials is by default inferred from the `transmission` and + * `transmissionMap` properties. This node property allows to overwrite the default + * and define the transmission with a node instead. + * + * If you don't want to overwrite the transmission but modify the existing + * value instead, use {@link module:MaterialNode.materialTransmission}. + * + * @type {Node?} + * @default null + */ this.transmissionNode = null; + + /** + * The thickness of physical materials is by default inferred from the `thickness` and + * `thicknessMap` properties. This node property allows to overwrite the default + * and define the thickness with a node instead. + * + * If you don't want to overwrite the thickness but modify the existing + * value instead, use {@link module:MaterialNode.materialThickness}. + * + * @type {Node?} + * @default null + */ this.thicknessNode = null; + + /** + * The attenuation distance of physical materials is by default inferred from the + * `attenuationDistance` property. This node property allows to overwrite the default + * and define the attenuation distance with a node instead. + * + * If you don't want to overwrite the attenuation distance but modify the existing + * value instead, use {@link module:MaterialNode.materialAttenuationDistance}. + * + * @type {Node?} + * @default null + */ this.attenuationDistanceNode = null; + + /** + * The attenuation color of physical materials is by default inferred from the + * `attenuationColor` property. This node property allows to overwrite the default + * and define the attenuation color with a node instead. + * + * If you don't want to overwrite the attenuation color but modify the existing + * value instead, use {@link module:MaterialNode.materialAttenuationColor}. + * + * @type {Node?} + * @default null + */ this.attenuationColorNode = null; + + /** + * The dispersion of physical materials is by default inferred from the + * `dispersion` property. This node property allows to overwrite the default + * and define the dispersion with a node instead. + * + * If you don't want to overwrite the dispersion but modify the existing + * value instead, use {@link module:MaterialNode.materialDispersion}. + * + * @type {Node?} + * @default null + */ this.dispersionNode = null; + /** + * The anisotropy of physical materials is by default inferred from the + * `anisotropy` property. This node property allows to overwrite the default + * and define the anisotropy with a node instead. + * + * If you don't want to overwrite the anisotropy but modify the existing + * value instead, use {@link module:MaterialNode.materialAnisotropy}. + * + * @type {Node?} + * @default null + */ this.anisotropyNode = null; this.setDefaultValues( _defaultValues$5 ); @@ -19279,42 +20836,81 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial { } + /** + * Whether the lighting model should use clearcoat or not. + * + * @type {Boolean} + * @default true + */ get useClearcoat() { return this.clearcoat > 0 || this.clearcoatNode !== null; } + /** + * Whether the lighting model should use iridescence or not. + * + * @type {Boolean} + * @default true + */ get useIridescence() { return this.iridescence > 0 || this.iridescenceNode !== null; } + /** + * Whether the lighting model should use sheen or not. + * + * @type {Boolean} + * @default true + */ get useSheen() { return this.sheen > 0 || this.sheenNode !== null; } + /** + * Whether the lighting model should use anisotropy or not. + * + * @type {Boolean} + * @default true + */ get useAnisotropy() { return this.anisotropy > 0 || this.anisotropyNode !== null; } + /** + * Whether the lighting model should use transmission or not. + * + * @type {Boolean} + * @default true + */ get useTransmission() { return this.transmission > 0 || this.transmissionNode !== null; } + /** + * Whether the lighting model should use dispersion or not. + * + * @type {Boolean} + * @default true + */ get useDispersion() { return this.dispersion > 0 || this.dispersionNode !== null; } + /** + * Setups the specular related node variables. + */ setupSpecular() { const iorNode = this.iorNode ? float( this.iorNode ) : materialIOR; @@ -19325,12 +20921,22 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial { } + /** + * Setups the lighting model. + * + * @return {PhysicalLightingModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { return new PhysicalLightingModel( this.useClearcoat, this.useSheen, this.useIridescence, this.useAnisotropy, this.useTransmission, this.useDispersion ); } + /** + * Setups the physical specific node variables. + * + * @param {NodeBuilder} builder - The current node builder. + */ setupVariants( builder ) { super.setupVariants( builder ); @@ -19426,6 +21032,11 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial { } + /** + * Setups the clearcoat normal node. + * + * @return {Node} The clearcoat normal. + */ setupClearcoatNormal() { return this.clearcoatNormalNode ? vec3( this.clearcoatNormalNode ) : materialClearcoatNormal; @@ -19470,16 +21081,49 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial { } +/** @module MeshSSSNodeMaterial **/ + +/** + * Represents the lighting model for {@link MeshSSSNodeMaterial}. + * + * @augments PhysicalLightingModel + */ class SSSLightingModel extends PhysicalLightingModel { - constructor( useClearcoat, useSheen, useIridescence, useSSS ) { + /** + * Constructs a new physical lighting model. + * + * @param {Boolean} [clearcoat=false] - Whether clearcoat is supported or not. + * @param {Boolean} [sheen=false] - Whether sheen is supported or not. + * @param {Boolean} [iridescence=false] - Whether iridescence is supported or not. + * @param {Boolean} [anisotropy=false] - Whether anisotropy is supported or not. + * @param {Boolean} [transmission=false] - Whether transmission is supported or not. + * @param {Boolean} [dispersion=false] - Whether dispersion is supported or not. + * @param {Boolean} [sss=false] - Whether SSS is supported or not. + */ + constructor( clearcoat = false, sheen = false, iridescence = false, anisotropy = false, transmission = false, dispersion = false, sss = false ) { - super( useClearcoat, useSheen, useIridescence ); + super( clearcoat, sheen, iridescence, anisotropy, transmission, dispersion ); - this.useSSS = useSSS; + /** + * Whether the lighting model should use SSS or not. + * + * @type {Boolean} + * @default false + */ + this.useSSS = sss; } + /** + * Extends the default implementation with a SSS term. + * + * Reference: [Approximating Translucency for a Fast, Cheap and Convincing Subsurface Scattering Look]{@link https://colinbarrebrisebois.com/2011/03/07/gdc-2011-approximating-translucency-for-a-fast-cheap-and-convincing-subsurface-scattering-look/} + * + * @param {Object} input - The input data. + * @param {StackNode} stack - The current stack. + * @param {NodeBuilder} builder - The current node builder. + */ direct( { lightDirection, lightColor, reflectedLight }, stack, builder ) { if ( this.useSSS === true ) { @@ -19502,6 +21146,12 @@ class SSSLightingModel extends PhysicalLightingModel { } +/** + * This node material is an experimental extension of {@link MeshPhysicalNodeMaterial} + * that implements a Subsurface scattering (SSS) term. + * + * @augments MeshPhysicalNodeMaterial + */ class MeshSSSNodeMaterial extends MeshPhysicalNodeMaterial { static get type() { @@ -19510,28 +21160,80 @@ class MeshSSSNodeMaterial extends MeshPhysicalNodeMaterial { } + /** + * Constructs a new mesh SSS node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super( parameters ); + /** + * Represents the thickness color. + * + * @type {Node?} + * @default null + */ this.thicknessColorNode = null; + + /** + * Represents the distortion factor. + * + * @type {Node?} + */ this.thicknessDistortionNode = float( 0.1 ); + + /** + * Represents the thickness ambient factor. + * + * @type {Node?} + */ this.thicknessAmbientNode = float( 0.0 ); + + /** + * Represents the thickness attenuation. + * + * @type {Node?} + */ this.thicknessAttenuationNode = float( .1 ); + + /** + * Represents the thickness power. + * + * @type {Node?} + */ this.thicknessPowerNode = float( 2.0 ); + + /** + * Represents the thickness scale. + * + * @type {Node?} + */ this.thicknessScaleNode = float( 10.0 ); } + /** + * Whether the lighting model should use SSS or not. + * + * @type {Boolean} + * @default true + */ get useSSS() { return this.thicknessColorNode !== null; } + /** + * Setups the lighting model. + * + * @return {SSSLightingModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { - return new SSSLightingModel( this.useClearcoat, this.useSheen, this.useIridescence, this.useSSS ); + return new SSSLightingModel( this.useClearcoat, this.useSheen, this.useIridescence, this.useAnisotropy, this.useTransmission, this.useDispersion, this.useSSS ); } @@ -19614,6 +21316,11 @@ class ToonLightingModel extends LightingModel { const _defaultValues$4 = /*@__PURE__*/ new MeshToonMaterial(); +/** + * Node material version of `MeshToonMaterial`. + * + * @augments NodeMaterial + */ class MeshToonNodeMaterial extends NodeMaterial { static get type() { @@ -19622,12 +21329,30 @@ class MeshToonNodeMaterial extends NodeMaterial { } + /** + * Constructs a new mesh toon node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshToonNodeMaterial = true; + /** + * Set to `true` because toon materials react on lights. + * + * @type {Boolean} + * @default true + */ this.lights = true; this.setDefaultValues( _defaultValues$4 ); @@ -19636,6 +21361,11 @@ class MeshToonNodeMaterial extends NodeMaterial { } + /** + * Setups the lighting model. + * + * @return {ToonLightingModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { return new ToonLightingModel(); @@ -19690,6 +21420,11 @@ const matcapUV = /*@__PURE__*/ nodeImmutable( MatcapUVNode ); const _defaultValues$3 = /*@__PURE__*/ new MeshMatcapMaterial(); +/** + * Node material version of `MeshMatcapMaterial`. + * + * @augments NodeMaterial + */ class MeshMatcapNodeMaterial extends NodeMaterial { static get type() { @@ -19698,12 +21433,22 @@ class MeshMatcapNodeMaterial extends NodeMaterial { } + /** + * Constructs a new mesh normal node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); - this.lights = false; - + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshMatcapNodeMaterial = true; this.setDefaultValues( _defaultValues$3 ); @@ -19712,6 +21457,11 @@ class MeshMatcapNodeMaterial extends NodeMaterial { } + /** + * Setups the matcap specific node variables. + * + * @param {NodeBuilder} builder - The current node builder. + */ setupVariants( builder ) { const uv = matcapUV; @@ -19736,6 +21486,16 @@ class MeshMatcapNodeMaterial extends NodeMaterial { const _defaultValues$2 = /*@__PURE__*/ new PointsMaterial(); +/** + * Node material version of `PointsMaterial`. + * + * Since WebGPU can render point primitives only with a size of one pixel, + * this material type does not evaluate the `size` and `sizeAttenuation` + * property of `PointsMaterial`. Use {@link InstancedPointsNodeMaterial} + * instead if you need points with a size larger than one pixel. + * + * @augments NodeMaterial + */ class PointsNodeMaterial extends NodeMaterial { static get type() { @@ -19744,31 +21504,30 @@ class PointsNodeMaterial extends NodeMaterial { } + /** + * Constructs a new points node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isPointsNodeMaterial = true; - this.lights = false; - this.transparent = true; - - this.sizeNode = null; - this.setDefaultValues( _defaultValues$2 ); this.setValues( parameters ); } - copy( source ) { - - this.sizeNode = source.sizeNode; - - return super.copy( source ); - - } - } /** @module RotateNode **/ @@ -19872,6 +21631,11 @@ const rotate = /*@__PURE__*/ nodeProxy( RotateNode ); const _defaultValues$1 = /*@__PURE__*/ new SpriteMaterial(); +/** + * Node material version of `SpriteMaterial`. + * + * @augments NodeMaterial + */ class SpriteNodeMaterial extends NodeMaterial { static get type() { @@ -19880,17 +21644,66 @@ class SpriteNodeMaterial extends NodeMaterial { } + /** + * Constructs a new sprite node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isSpriteNodeMaterial = true; - this.lights = false; this._useSizeAttenuation = true; + /** + * This property makes it possible to define the position of the sprite with a + * node. That can be useful when the material is used with instanced rendering + * and node data are defined with an instanced attribute node: + * ```js + * const positionAttribute = new InstancedBufferAttribute( new Float32Array( positions ), 3 ); + * material.positionNode = instancedBufferAttribute( positionAttribute ); + * ``` + * Another possibility is to compute the instanced data with a compute shader: + * ```js + * const positionBuffer = instancedArray( particleCount, 'vec3' ); + * particleMaterial.positionNode = positionBuffer.toAttribute(); + * ``` + * + * @type {Node?} + * @default null + */ this.positionNode = null; + + /** + * The rotation of sprite materials is by default inferred from the `rotation`, + * property. This node property allows to overwrite the default and define + * the rotation with a node instead. + * + * If you don't want to overwrite the rotation but modify the existing + * value instead, use {@link module:MaterialNode.materialRotation}. + * + * @type {Node?} + * @default null + */ this.rotationNode = null; + + /** + * This node property provides an additional way to scale sprites next to + * `Object3D.scale`. The scale transformation based in `Object3D.scale` + * is multiplied with the scale value of this node in the vertex shader. + * + * @type {Node?} + * @default null + */ this.scaleNode = null; this.setDefaultValues( _defaultValues$1 ); @@ -19899,14 +21712,19 @@ class SpriteNodeMaterial extends NodeMaterial { } + /** + * Setups the position node in view space. This method implements + * the sprite specific vertex shader. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Node} The position in view space. + */ setupPositionView( builder ) { const { object, camera } = builder; const sizeAttenuation = this.sizeAttenuation; - // < VERTEX STAGE > - const { positionNode, rotationNode, scaleNode } = this; const mvPosition = modelViewMatrix.mul( vec3( positionNode || 0 ) ); @@ -19919,7 +21737,7 @@ class SpriteNodeMaterial extends NodeMaterial { } - if ( ! sizeAttenuation ) { + if ( sizeAttenuation === false ) { if ( camera.isPerspectiveCamera ) { @@ -19938,7 +21756,7 @@ class SpriteNodeMaterial extends NodeMaterial { if ( object.center && object.center.isVector2 === true ) { - const center = reference$1( 'center', 'vec2' ); + const center = reference$1( 'center', 'vec2', object ); alignedPosition = alignedPosition.sub( center.sub( 0.5 ) ); @@ -19964,6 +21782,12 @@ class SpriteNodeMaterial extends NodeMaterial { } + /** + * Whether to use size attenuation or not. + * + * @type {Boolean} + * @default true + */ get sizeAttenuation() { return this._useSizeAttenuation; @@ -20034,6 +21858,11 @@ class ShadowMaskModel extends LightingModel { const _defaultValues = /*@__PURE__*/ new ShadowMaterial(); +/** + * Node material version of `ShadowMaterial`. + * + * @augments NodeMaterial + */ class ShadowNodeMaterial extends NodeMaterial { static get type() { @@ -20042,12 +21871,31 @@ class ShadowNodeMaterial extends NodeMaterial { } + /** + * Constructs a new shadow node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isShadowNodeMaterial = true; + /** + * Set to `true` because so it's possible to implement + * the shadow mask effect. + * + * @type {Boolean} + * @default true + */ this.lights = true; this.setDefaultValues( _defaultValues ); @@ -20056,6 +21904,11 @@ class ShadowNodeMaterial extends NodeMaterial { } + /** + * Setups the lighting model. + * + * @return {ShadowMaskModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { return new ShadowMaskModel(); @@ -20188,6 +22041,22 @@ class Texture3DNode extends TextureNode { */ setupUV( builder, uvNode ) { + const texture = this.value; + + if ( builder.isFlipY() && ( texture.isRenderTargetTexture === true || texture.isFramebufferTexture === true ) ) { + + if ( this.sampler ) { + + uvNode = uvNode.flipY(); + + } else { + + uvNode = uvNode.setY( int( textureSize( this, this.levelNode ).y ).sub( uvNode.y ).sub( 1 ) ); + + } + + } + return uvNode; } @@ -20230,6 +22099,14 @@ class Texture3DNode extends TextureNode { */ const texture3D = /*@__PURE__*/ nodeProxy( Texture3DNode ); +/** @module VolumeNodeMaterial **/ + +/** + * Node material intended for volume rendering. The volumetric data are + * defined with an instance of {@link Data3DTexture}. + * + * @augments NodeMaterial + */ class VolumeNodeMaterial extends NodeMaterial { static get type() { @@ -20238,18 +22115,85 @@ class VolumeNodeMaterial extends NodeMaterial { } - constructor( params = {} ) { + /** + * Constructs a new volume node material. + * + * @param {Object?} parameters - The configuration parameter. + */ + constructor( parameters ) { super(); - this.lights = false; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isVolumeNodeMaterial = true; + + /** + * The base color of the volume. + * + * @type {Color} + * @default 100 + */ + this.base = new Color( 0xffffff ); + + /** + * A 3D data texture holding the volumetric data. + * + * @type {Data3DTexture?} + * @default null + */ + this.map = null; + + /** + * This number of samples for each ray that hits the mesh's surface + * and travels through the volume. + * + * @type {Number} + * @default 100 + */ + this.steps = 100; + + /** + * Callback for {@link VolumeNodeMaterial#testNode}. + * + * @callback testNodeCallback + * @param {Data3DTexture} map - The 3D texture. + * @param {Node} mapValue - The sampled value inside the volume. + * @param {Node} probe - The probe which is the entry point of the ray on the mesh's surface. + * @param {Node} finalColor - The final color. + */ + + /** + * The volume rendering of this material works by shooting rays + * from the camera position through each fragment of the mesh's + * surface and sample the inner volume in a raymarching fashion + * multiple times. + * + * This node can be used to assign a callback function of type `Fn` + * that will be executed per sample. The callback receives the + * texture, the sampled texture value as well as position on the surface + * where the rays enters the volume. The last parameter is a color + * that allows the callback to determine the final color. + * + * @type {testNodeCallback?} + * @default null + */ this.testNode = null; - this.setValues( params ); + this.setValues( parameters ); } + /** + * Setups the vertex and fragment stage of this node material. + * + * @param {NodeBuilder} builder - The current node builder. + */ setup( builder ) { const map = texture3D( this.map, null, 0 ); @@ -20326,19 +22270,65 @@ class VolumeNodeMaterial extends NodeMaterial { } +/** + * This module manages the internal animation loop of the renderer. + * + * @private + */ class Animation { + /** + * Constructs a new animation loop management component. + * + * @param {Nodes} nodes - Renderer component for managing nodes related logic. + * @param {Info} info - Renderer component for managing metrics and monitoring data. + */ constructor( nodes, info ) { + /** + * Renderer component for managing nodes related logic. + * + * @type {Nodes} + */ this.nodes = nodes; + + /** + * Renderer component for managing metrics and monitoring data. + * + * @type {Info} + */ this.info = info; + /** + * A reference to the context from `requestAnimationFrame()` can + * be called (usually `window`). + * + * @type {Window|XRSession} + */ this._context = self; + + /** + * The user-defined animation loop. + * + * @type {Function?} + * @default null + */ this._animationLoop = null; + + /** + * The requestId which is returned from the `requestAnimationFrame()` call. + * Can be used to cancel the stop the animation loop. + * + * @type {Number?} + * @default null + */ this._requestId = null; } + /** + * Starts the internal animation loop. + */ start() { const update = ( time, frame ) => { @@ -20359,6 +22349,9 @@ class Animation { } + /** + * Stops the internal animation loop. + */ stop() { this._context.cancelAnimationFrame( this._requestId ); @@ -20367,18 +22360,31 @@ class Animation { } + /** + * Defines the user-level animation loop. + * + * @param {Function} callback - The animation loop. + */ setAnimationLoop( callback ) { this._animationLoop = callback; } + /** + * Defines the context in which `requestAnimationFrame()` is executed. + * + * @param {Window|XRSession} context - The context to set. + */ setContext( context ) { this._context = context; } + /** + * Frees all internal resources and stops the animation loop. + */ dispose() { this.stop(); @@ -20387,19 +22393,41 @@ class Animation { } +/** + * Data structure for the renderer. It allows defining values + * with chained, hierarchical keys. Keys are meant to be + * objects since the module internally works with Weak Maps + * for performance reasons. + * + * @private + */ class ChainMap { + /** + * Constructs a new Chain Map. + */ constructor() { + /** + * The root Weak Map. + * + * @type {WeakMap} + */ this.weakMap = new WeakMap(); } + /** + * Returns the value for the given array of keys. + * + * @param {Array} keys - List of keys. + * @return {Any} The value. Returns `undefined` if no value was found. + */ get( keys ) { let map = this.weakMap; - for ( let i = 0; i < keys.length; i ++ ) { + for ( let i = 0; i < keys.length - 1; i ++ ) { map = map.get( keys[ i ] ); @@ -20411,11 +22439,18 @@ class ChainMap { } + /** + * Sets the value for the given keys. + * + * @param {Array} keys - List of keys. + * @param {Any} value - The value to set. + * @return {ChainMap} A reference to this Chain Map. + */ set( keys, value ) { let map = this.weakMap; - for ( let i = 0; i < keys.length; i ++ ) { + for ( let i = 0; i < keys.length - 1; i ++ ) { const key = keys[ i ]; @@ -20425,15 +22460,23 @@ class ChainMap { } - return map.set( keys[ keys.length - 1 ], value ); + map.set( keys[ keys.length - 1 ], value ); + + return this; } + /** + * Deletes a value for the given keys. + * + * @param {Array} keys - The keys. + * @return {Boolean} Returns `true` if the value has been removed successfully and `false` if the value has not be found. + */ delete( keys ) { let map = this.weakMap; - for ( let i = 0; i < keys.length; i ++ ) { + for ( let i = 0; i < keys.length - 1; i ++ ) { map = map.get( keys[ i ] ); @@ -20447,7 +22490,7 @@ class ChainMap { } -let _id$8 = 0; +let _id$9 = 0; function getKeys( obj ) { @@ -20483,49 +22526,254 @@ function getKeys( obj ) { } +/** + * A render object is the renderer's representation of single entity that gets drawn + * with a draw command. There is no unique mapping of render objects to 3D objects in the + * scene since render objects also depend from the used material, the current render context + * and the current scene's lighting. + * + * In general, the basic process of the renderer is: + * + * - Analyze the 3D objects in the scene and generate render lists containing render items. + * - Process the render lists by calling one or more render commands for each render item. + * - For each render command, request a render object and perform the draw. + * + * The module provides an interface to get data required for the draw command like the actual + * draw parameters or vertex buffers. It also holds a series of caching related methods since + * creating render objects should only be done when necessary. + * + * @private + */ class RenderObject { + /** + * Constructs a new render object. + * + * @param {Nodes} nodes - Renderer component for managing nodes related logic. + * @param {Geometries} geometries - Renderer component for managing geometries. + * @param {Renderer} renderer - The renderer. + * @param {Object3D} object - The 3D object. + * @param {Material} material - The 3D object's material. + * @param {Scene} scene - The scene the 3D object belongs to. + * @param {Camera} camera - The camera the object should be rendered with. + * @param {LightsNode} lightsNode - The lights node. + * @param {RenderContext} renderContext - The render context. + * @param {ClippingContext} clippingContext - The clipping context. + */ constructor( nodes, geometries, renderer, object, material, scene, camera, lightsNode, renderContext, clippingContext ) { + this.id = _id$9 ++; + + /** + * Renderer component for managing nodes related logic. + * + * @type {Nodes} + * @private + */ this._nodes = nodes; - this._geometries = geometries; - this.id = _id$8 ++; + /** + * Renderer component for managing geometries. + * + * @type {Geometries} + * @private + */ + this._geometries = geometries; + /** + * The renderer. + * + * @type {Renderer} + */ this.renderer = renderer; + + /** + * The 3D object. + * + * @type {Object3D} + */ this.object = object; + + /** + * The 3D object's material. + * + * @type {Material} + */ this.material = material; + + /** + * The scene the 3D object belongs to. + * + * @type {Scene} + */ this.scene = scene; + + /** + * The camera the 3D object should be rendered with. + * + * @type {Camera} + */ this.camera = camera; + + /** + * The lights node. + * + * @type {LightsNode} + */ this.lightsNode = lightsNode; + + /** + * The render context. + * + * @type {RenderContext} + */ this.context = renderContext; + /** + * The 3D object's geometry. + * + * @type {BufferGeometry} + */ this.geometry = object.geometry; + + /** + * The render object's version. + * + * @type {Number} + */ this.version = material.version; + /** + * The draw range of the geometry. + * + * @type {Object?} + * @default null + */ this.drawRange = null; + /** + * An array holding the buffer attributes + * of the render object. This entails attribute + * definitions on geometry and node level. + * + * @type {Array?} + * @default null + */ this.attributes = null; + + /** + * A reference to a render pipeline the render + * object is processed with. + * + * @type {RenderPipeline} + * @default null + */ this.pipeline = null; + + /** + * An array holding the vertex buffers which can + * be buffer attributes but also interleaved buffers. + * + * @type {Array?} + * @default null + */ this.vertexBuffers = null; + + /** + * The parameters for the draw command. + * + * @type {Object?} + * @default null + */ this.drawParams = null; + /** + * If this render object is used inside a render bundle, + * this property points to the respective bundle group. + * + * @type {BundleGroup?} + * @default null + */ this.bundle = null; + /** + * The clipping context. + * + * @type {ClippingContext} + */ this.clippingContext = clippingContext; + + /** + * The clipping context's cache key. + * + * @type {String} + */ this.clippingContextCacheKey = clippingContext !== null ? clippingContext.cacheKey : ''; + /** + * The initial node cache key. + * + * @type {Number} + */ this.initialNodesCacheKey = this.getDynamicCacheKey(); + + /** + * The initial cache key. + * + * @type {Number} + */ this.initialCacheKey = this.getCacheKey(); + /** + * The node builder state. + * + * @type {NodeBuilderState?} + * @private + * @default null + */ this._nodeBuilderState = null; + + /** + * An array of bindings. + * + * @type {Array?} + * @private + * @default null + */ this._bindings = null; + + /** + * Reference to the node material observer. + * + * @type {NodeMaterialObserver?} + * @private + * @default null + */ this._monitor = null; + /** + * An event listener which is defined by `RenderObjects`. It performs + * clean up tasks when `dispose()` on this render object. + * + * @method + */ this.onDispose = null; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isRenderObject = true; + /** + * An event listener which is executed when `dispose()` is called on + * the render object's material. + * + * @method + */ this.onMaterialDispose = () => { this.dispose(); @@ -20536,12 +22784,23 @@ class RenderObject { } - updateClipping( parent ) { + /** + * Updates the clipping context. + * + * @param {ClippingContext} context - The clipping context to set. + */ + updateClipping( context ) { - this.clippingContext = parent; + this.clippingContext = context; } + /** + * Whether the clipping requires an update or not. + * + * @type {Boolean} + * @readonly + */ get clippingNeedsUpdate() { if ( this.clippingContext === null || this.clippingContext.cacheKey === this.clippingContextCacheKey ) return false; @@ -20552,48 +22811,90 @@ class RenderObject { } + /** + * The number of clipping planes defined in context of hardware clipping. + * + * @type {Number} + * @readonly + */ get hardwareClippingPlanes() { return this.material.hardwareClipping === true ? this.clippingContext.unionClippingCount : 0; } + /** + * Returns the node builder state of this render object. + * + * @return {NodeBuilderState} The node builder state. + */ getNodeBuilderState() { return this._nodeBuilderState || ( this._nodeBuilderState = this._nodes.getForRender( this ) ); } + /** + * Returns the node material observer of this render object. + * + * @return {NodeMaterialObserver} The node material observer. + */ getMonitor() { return this._monitor || ( this._monitor = this.getNodeBuilderState().monitor ); } + /** + * Returns an array of bind groups of this render object. + * + * @return {Array} The bindings. + */ getBindings() { return this._bindings || ( this._bindings = this.getNodeBuilderState().createBindings() ); } + /** + * Returns the index of the render object's geometry. + * + * @return {BufferAttribute?} The index. Returns `null` for non-indexed geometries. + */ getIndex() { return this._geometries.getIndex( this ); } + /** + * Returns the indirect buffer attribute. + * + * @return {BufferAttribute?} The indirect attribute. `null` if no indirect drawing is used. + */ getIndirect() { return this._geometries.getIndirect( this ); } + /** + * Returns an array that acts as a key for identifying the render object in a chain map. + * + * @return {Array} An array with object references. + */ getChainArray() { return [ this.object, this.material, this.context, this.lightsNode ]; } + /** + * This method is used when the geometry of a 3D object has been exchanged and the + * respective render object now requires an update. + * + * @param {BufferGeometry} geometry - The geometry to set. + */ setGeometry( geometry ) { this.geometry = geometry; @@ -20601,6 +22902,12 @@ class RenderObject { } + /** + * Returns the buffer attributes of the render object. The returned array holds + * attribute definitions on geometry and node level. + * + * @return {Array} An array with buffer attributes. + */ getAttributes() { if ( this.attributes !== null ) return this.attributes; @@ -20631,6 +22938,11 @@ class RenderObject { } + /** + * Returns the vertex buffers of the render object. + * + * @return {Array} An array with buffer attribute or interleaved buffers. + */ getVertexBuffers() { if ( this.vertexBuffers === null ) this.getAttributes(); @@ -20639,6 +22951,11 @@ class RenderObject { } + /** + * Returns the draw parameters for the render object. + * + * @return {{vertexCount: Number, firstVertex: Number, instanceCount: Number, firstInstance: Number}} The draw parameters. + */ getDrawParameters() { const { object, material, geometry, group, drawRange } = this; @@ -20705,6 +23022,13 @@ class RenderObject { } + /** + * Returns the render object's geometry cache key. + * + * The geometry cache key is part of the material cache key. + * + * @return {String} The geometry cache key. + */ getGeometryCacheKey() { const { geometry } = this; @@ -20734,6 +23058,13 @@ class RenderObject { } + /** + * Returns the render object's material cache key. + * + * The material cache key is part of the render object cache key. + * + * @return {String} The material cache key. + */ getMaterialCacheKey() { const { object, material } = this; @@ -20832,18 +23163,46 @@ class RenderObject { } + /** + * Whether the geometry requires an update or not. + * + * @type {Boolean} + * @readonly + */ get needsGeometryUpdate() { return this.geometry.id !== this.object.geometry.id; } + /** + * Whether the render object requires an update or not. + * + * Note: There are two distinct places where render objects are checked for an update. + * + * 1. In `RenderObjects.get()` which is executed when the render object is request. This + * method checks the `needsUpdate` flag and recreates the render object if necessary. + * 2. In `Renderer._renderObjectDirect()` right after getting the render object via + * `RenderObjects.get()`. The render object's NodeMaterialObserver is then used to detect + * a need for a refresh due to material, geometry or object related value changes. + * + * TODO: Investigate if it's possible to merge both steps so there is only a single place + * that performs the 'needsUpdate' check. + * + * @type {Boolean} + * @readonly + */ get needsUpdate() { return /*this.object.static !== true &&*/ ( this.initialNodesCacheKey !== this.getDynamicCacheKey() || this.clippingNeedsUpdate ); } + /** + * Returns the dynamic cache key which represents a key that is computed per draw command. + * + * @return {String} The cache key. + */ getDynamicCacheKey() { // Environment Nodes Cache Key @@ -20860,12 +23219,20 @@ class RenderObject { } + /** + * Returns the render object's cache key. + * + * @return {String} The cache key. + */ getCacheKey() { return this.getMaterialCacheKey() + this.getDynamicCacheKey(); } + /** + * Frees internal resources. + */ dispose() { this.material.removeEventListener( 'dispose', this.onMaterialDispose ); @@ -20876,40 +23243,109 @@ class RenderObject { } -const chainArray = []; +const _chainKeys$5 = []; +/** + * This module manages the render objects of the renderer. + * + * @private + */ class RenderObjects { + /** + * Constructs a new render object management component. + * + * @param {Renderer} renderer - The renderer. + * @param {Nodes} nodes - Renderer component for managing nodes related logic. + * @param {Geometries} geometries - Renderer component for managing geometries. + * @param {Pipelines} pipelines - Renderer component for managing pipelines. + * @param {Bindings} bindings - Renderer component for managing bindings. + * @param {Info} info - Renderer component for managing metrics and monitoring data. + */ constructor( renderer, nodes, geometries, pipelines, bindings, info ) { + /** + * The renderer. + * + * @type {Renderer} + */ this.renderer = renderer; + + /** + * Renderer component for managing nodes related logic. + * + * @type {Nodes} + */ this.nodes = nodes; + + /** + * Renderer component for managing geometries. + * + * @type {Geometries} + */ this.geometries = geometries; + + /** + * Renderer component for managing pipelines. + * + * @type {Pipelines} + */ this.pipelines = pipelines; + + /** + * Renderer component for managing bindings. + * + * @type {Bindings} + */ this.bindings = bindings; + + /** + * Renderer component for managing metrics and monitoring data. + * + * @type {Info} + */ this.info = info; + /** + * A dictionary that manages render contexts in chain maps + * for each pass ID. + * + * @type {Object} + */ this.chainMaps = {}; } + /** + * Returns a render object for the given object and state data. + * + * @param {Object3D} object - The 3D object. + * @param {Material} material - The 3D object's material. + * @param {Scene} scene - The scene the 3D object belongs to. + * @param {Camera} camera - The camera the 3D object should be rendered with. + * @param {LightsNode} lightsNode - The lights node. + * @param {RenderContext} renderContext - The render context. + * @param {ClippingContext} clippingContext - The clipping context. + * @param {String?} passId - An optional ID for identifying the pass. + * @return {RenderObject} The render object. + */ get( object, material, scene, camera, lightsNode, renderContext, clippingContext, passId ) { const chainMap = this.getChainMap( passId ); // reuse chainArray - chainArray[ 0 ] = object; - chainArray[ 1 ] = material; - chainArray[ 2 ] = renderContext; - chainArray[ 3 ] = lightsNode; + _chainKeys$5[ 0 ] = object; + _chainKeys$5[ 1 ] = material; + _chainKeys$5[ 2 ] = renderContext; + _chainKeys$5[ 3 ] = lightsNode; - let renderObject = chainMap.get( chainArray ); + let renderObject = chainMap.get( _chainKeys$5 ); if ( renderObject === undefined ) { renderObject = this.createRenderObject( this.nodes, this.geometries, this.renderer, object, material, scene, camera, lightsNode, renderContext, clippingContext, passId ); - chainMap.set( chainArray, renderObject ); + chainMap.set( _chainKeys$5, renderObject ); } else { @@ -20939,22 +23375,49 @@ class RenderObjects { } + _chainKeys$5.length = 0; + return renderObject; } + /** + * Returns a chain map for the given pass ID. + * + * @param {String} [passId='default'] - The pass ID. + * @return {ChainMap} The chain map. + */ getChainMap( passId = 'default' ) { return this.chainMaps[ passId ] || ( this.chainMaps[ passId ] = new ChainMap() ); } + /** + * Frees internal resources. + */ dispose() { this.chainMaps = {}; } + /** + * Factory method for creating render objects with the given list of parameters. + * + * @param {Nodes} nodes - Renderer component for managing nodes related logic. + * @param {Geometries} geometries - Renderer component for managing geometries. + * @param {Renderer} renderer - The renderer. + * @param {Object3D} object - The 3D object. + * @param {Material} material - The object's material. + * @param {Scene} scene - The scene the 3D object belongs to. + * @param {Camera} camera - The camera the object should be rendered with. + * @param {LightsNode} lightsNode - The lights node. + * @param {RenderContext} renderContext - The render context. + * @param {ClippingContext} clippingContext - The clipping context. + * @param {String?} passId - An optional ID for identifying the pass. + * @return {RenderObject} The render object. + */ createRenderObject( nodes, geometries, renderer, object, material, scene, camera, lightsNode, renderContext, clippingContext, passId ) { const chainMap = this.getChainMap( passId ); @@ -20978,14 +23441,35 @@ class RenderObjects { } +/** + * Data structure for the renderer. It is intended to manage + * data of objects in dictionaries. + * + * @private + */ class DataMap { + /** + * Constructs a new data map. + */ constructor() { + /** + * `DataMap` internally uses a weak map + * to manage its data. + * + * @type {WeakMap} + */ this.data = new WeakMap(); } + /** + * Returns the dictionary for the given object. + * + * @param {Object} object - The object. + * @return {Object} The dictionary. + */ get( object ) { let map = this.data.get( object ); @@ -21001,9 +23485,15 @@ class DataMap { } + /** + * Deletes the dictionary for the given object. + * + * @param {Object} object - The object. + * @return {Object?} The deleted dictionary. + */ delete( object ) { - let map; + let map = null; if ( this.data.has( object ) ) { @@ -21017,12 +23507,21 @@ class DataMap { } + /** + * Returns `true` if the given object has a dictionary defined. + * + * @param {Object} object - The object to test. + * @return {Boolean} Whether a dictionary is defined or not. + */ has( object ) { return this.data.has( object ); } + /** + * Frees internal resources. + */ dispose() { this.data = new WeakMap(); @@ -21047,16 +23546,38 @@ const GPU_CHUNK_BYTES = 16; const BlendColorFactor = 211; const OneMinusBlendColorFactor = 212; +/** + * This renderer module manages geometry attributes. + * + * @private + * @augments DataMap + */ class Attributes extends DataMap { + /** + * Constructs a new attribute management component. + * + * @param {Backend} backend - The renderer's backend. + */ constructor( backend ) { super(); + /** + * The renderer's backend. + * + * @type {Backend} + */ this.backend = backend; } + /** + * Deletes the data for the given attribute. + * + * @param {BufferAttribute} attribute - The attribute. + * @return {Object} The deleted attribute data. + */ delete( attribute ) { const attributeData = super.delete( attribute ); @@ -21071,6 +23592,13 @@ class Attributes extends DataMap { } + /** + * Updates the given attribute. This method creates attribute buffers + * for new attributes and updates data for existing ones. + * + * @param {BufferAttribute} attribute - The attribute to update. + * @param {Number} type - The attribute type. + */ update( attribute, type ) { const data = this.get( attribute ); @@ -21113,6 +23641,13 @@ class Attributes extends DataMap { } + /** + * Utility method for handling interleaved buffer attributes correctly. + * To process them, their `InterleavedBuffer` is returned. + * + * @param {BufferAttribute} attribute - The attribute. + * @return {BufferAttribute|InterleavedBuffer} + */ _getBufferAttribute( attribute ) { if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; @@ -21123,6 +23658,14 @@ class Attributes extends DataMap { } +/** + * Returns `true` if the given array has values that require an Uint32 array type. + * + * @private + * @function + * @param {Array} array - The array to test. + * @return {Boolean} Whether the given array has values that require an Uint32 array type or not. + */ function arrayNeedsUint32( array ) { // assumes larger values usually on last @@ -21137,12 +23680,28 @@ function arrayNeedsUint32( array ) { } +/** + * Returns the wireframe version for the given geometry. + * + * @private + * @function + * @param {BufferGeometry} geometry - The geometry. + * @return {Number} The version. + */ function getWireframeVersion( geometry ) { return ( geometry.index !== null ) ? geometry.index.version : geometry.attributes.position.version; } +/** + * Returns a wireframe index attribute for the given geometry. + * + * @private + * @function + * @param {BufferGeometry} geometry - The geometry. + * @return {BufferAttribute} The wireframe index attribute. + */ function getWireframeIndex( geometry ) { const indices = []; @@ -21187,21 +23746,61 @@ function getWireframeIndex( geometry ) { } +/** + * This renderer module manages geometries. + * + * @private + * @augments DataMap + */ class Geometries extends DataMap { + /** + * Constructs a new geometry management component. + * + * @param {Attributes} attributes - Renderer component for managing attributes. + * @param {Info} info - Renderer component for managing metrics and monitoring data. + */ constructor( attributes, info ) { super(); + /** + * Renderer component for managing attributes. + * + * @type {Attributes} + */ this.attributes = attributes; + + /** + * Renderer component for managing metrics and monitoring data. + * + * @type {Info} + */ this.info = info; + /** + * Weak Map for managing attributes for wireframe rendering. + * + * @type {WeakMap} + */ this.wireframes = new WeakMap(); + /** + * This Weak Map is used to make sure buffer attributes are + * updated only once per render call. + * + * @type {WeakMap} + */ this.attributeCall = new WeakMap(); } + /** + * Returns `true` if the given render object has an initialized geometry. + * + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether if the given render object has an initialized geometry or not. + */ has( renderObject ) { const geometry = renderObject.geometry; @@ -21210,6 +23809,11 @@ class Geometries extends DataMap { } + /** + * Prepares the geometry of the given render object for rendering. + * + * @param {RenderObject} renderObject - The render object. + */ updateForRender( renderObject ) { if ( this.has( renderObject ) === false ) this.initGeometry( renderObject ); @@ -21218,6 +23822,11 @@ class Geometries extends DataMap { } + /** + * Initializes the geometry of the given render object. + * + * @param {RenderObject} renderObject - The render object. + */ initGeometry( renderObject ) { const geometry = renderObject.geometry; @@ -21262,6 +23871,11 @@ class Geometries extends DataMap { } + /** + * Updates the geometry attributes of the given render object. + * + * @param {RenderObject} renderObject - The render object. + */ updateAttributes( renderObject ) { // attributes @@ -21304,6 +23918,12 @@ class Geometries extends DataMap { } + /** + * Updates the given attribute. + * + * @param {BufferAttribute} attribute - The attribute to update. + * @param {Number} type - The attribute type. + */ updateAttribute( attribute, type ) { const callId = this.info.render.calls; @@ -21340,12 +23960,25 @@ class Geometries extends DataMap { } + /** + * Returns the indirect buffer attribute of the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @return {BufferAttribute?} The indirect attribute. `null` if no indirect drawing is used. + */ getIndirect( renderObject ) { return renderObject.geometry.indirect; } + /** + * Returns the index of the given render object's geometry. This is implemented + * in a method to return a wireframe index if necessary. + * + * @param {RenderObject} renderObject - The render object. + * @return {BufferAttribute?} The index. Returns `null` for non-indexed geometries. + */ getIndex( renderObject ) { const { geometry, material } = renderObject; @@ -21384,15 +24017,64 @@ class Geometries extends DataMap { } +/** + * This renderer module provides a series of statistical information + * about the GPU memory and the rendering process. Useful for debugging + * and monitoring. + */ class Info { + /** + * Constructs a new info component. + */ constructor() { + /** + * Whether frame related metrics should automatically + * be resetted or not. This property should be set to `false` + * by apps which manage their own animation loop. They must + * then call `renderer.info.reset()` once per frame manually. + * + * @type {Boolean} + * @default true + */ this.autoReset = true; + /** + * The current frame ID. This ID is managed + * by `NodeFrame`. + * + * @type {Number} + * @readonly + * @default 0 + */ this.frame = 0; + + /** + * The number of render calls since the + * app has been started. + * + * @type {Number} + * @readonly + * @default 0 + */ this.calls = 0; + /** + * Render related metrics. + * + * @type {Object} + * @readonly + * @property {Number} calls - The number of render calls since the app has been started. + * @property {Number} frameCalls - The number of render calls of the current frame. + * @property {Number} drawCalls - The number of draw calls of the current frame. + * @property {Number} triangles - The number of rendered triangle primitives of the current frame. + * @property {Number} points - The number of rendered point primitives of the current frame. + * @property {Number} lines - The number of rendered line primitives of the current frame. + * @property {Number} previousFrameCalls - The number of render calls of the previous frame. + * @property {Number} timestamp - The timestamp of the frame when using `renderer.renderAsync()`. + * @property {Number} timestampCalls - The number of render calls using `renderer.renderAsync()`. + */ this.render = { calls: 0, frameCalls: 0, @@ -21405,6 +24087,17 @@ class Info { timestampCalls: 0 }; + /** + * Compute related metrics. + * + * @type {Object} + * @readonly + * @property {Number} calls - The number of compute calls since the app has been started. + * @property {Number} frameCalls - The number of compute calls of the current frame. + * @property {Number} previousFrameCalls - The number of compute calls of the previous frame. + * @property {Number} timestamp - The timestamp of the frame when using `renderer.computeAsync()`. + * @property {Number} timestampCalls - The number of render calls using `renderer.computeAsync()`. + */ this.compute = { calls: 0, frameCalls: 0, @@ -21413,6 +24106,14 @@ class Info { timestampCalls: 0 }; + /** + * Memory related metrics. + * + * @type {Object} + * @readonly + * @property {Number} geometries - The number of active geometries. + * @property {Number} frameCalls - The number of active textures. + */ this.memory = { geometries: 0, textures: 0 @@ -21420,6 +24121,13 @@ class Info { } + /** + * This method should be executed per draw call and updates the corresponding metrics. + * + * @param {Object3D} object - The 3D object that is going to be rendered. + * @param {Number} count - The vertex or index count. + * @param {Number} instanceCount - The instance count. + */ update( object, count, instanceCount ) { this.render.drawCalls ++; @@ -21448,6 +24156,12 @@ class Info { } + /** + * Used by async render methods to updated timestamp metrics. + * + * @param {('render'|'compute')} type - The type of render call. + * @param {Number} time - The duration of the compute/render call in milliseconds. + */ updateTimestamp( type, time ) { if ( this[ type ].timestampCalls === 0 ) { @@ -21471,6 +24185,9 @@ class Info { } + /** + * Resets frame related metrics. + */ reset() { const previousRenderFrameCalls = this.render.frameCalls; @@ -21491,6 +24208,9 @@ class Info { } + /** + * Performs a complete reset of the object. + */ dispose() { this.reset(); @@ -21509,76 +24229,249 @@ class Info { } +/** + * Abstract class for representing pipelines. + * + * @private + * @abstract + */ class Pipeline { + /** + * Constructs a new pipeline. + * + * @param {String} cacheKey - The pipeline's cache key. + */ constructor( cacheKey ) { + /** + * The pipeline's cache key. + * + * @type {String} + */ this.cacheKey = cacheKey; + /** + * How often the pipeline is currently in use. + * + * @type {Number} + * @default 0 + */ this.usedTimes = 0; } } +/** + * Class for representing render pipelines. + * + * @private + * @augments Pipeline + */ class RenderPipeline extends Pipeline { + /** + * Constructs a new render pipeline. + * + * @param {String} cacheKey - The pipeline's cache key. + * @param {ProgrammableStage} vertexProgram - The pipeline's vertex shader. + * @param {ProgrammableStage} fragmentProgram - The pipeline's fragment shader. + */ constructor( cacheKey, vertexProgram, fragmentProgram ) { super( cacheKey ); + /** + * The pipeline's vertex shader. + * + * @type {ProgrammableStage} + */ this.vertexProgram = vertexProgram; + + /** + * The pipeline's fragment shader. + * + * @type {ProgrammableStage} + */ this.fragmentProgram = fragmentProgram; } } +/** + * Class for representing compute pipelines. + * + * @private + * @augments Pipeline + */ class ComputePipeline extends Pipeline { + /** + * Constructs a new render pipeline. + * + * @param {String} cacheKey - The pipeline's cache key. + * @param {ProgrammableStage} computeProgram - The pipeline's compute shader. + */ constructor( cacheKey, computeProgram ) { super( cacheKey ); + /** + * The pipeline's compute shader. + * + * @type {ProgrammableStage} + */ this.computeProgram = computeProgram; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isComputePipeline = true; } } -let _id$7 = 0; +let _id$8 = 0; +/** + * Class for representing programmable stages which are vertex, + * fragment or compute shaders. Unlike fixed-function states (like blending), + * they represent the programmable part of a pipeline. + * + * @private + */ class ProgrammableStage { - constructor( code, type, transforms = null, attributes = null ) { + /** + * Constructs a new programmable stage. + * + * @param {String} code - The shader code. + * @param {('vertex'|'fragment'|'compute')} stage - The type of stage. + * @param {String} name - The name of the shader. + * @param {Array?} [transforms=null] - The transforms (only relevant for compute stages with WebGL 2 which uses Transform Feedback). + * @param {Array?} [attributes=null] - The attributes (only relevant for compute stages with WebGL 2 which uses Transform Feedback). + */ + constructor( code, stage, name, transforms = null, attributes = null ) { - this.id = _id$7 ++; + /** + * The id of the programmable stage. + * + * @type {Number} + */ + this.id = _id$8 ++; + /** + * The shader code. + * + * @type {String} + */ this.code = code; - this.stage = type; + + /** + * The type of stage. + * + * @type {String} + */ + this.stage = stage; + + /** + * The name of the stage. + * This is used for debugging purposes. + * + * @type {String} + */ + this.name = name; + + /** + * The transforms (only relevant for compute stages with WebGL 2 which uses Transform Feedback). + * + * @type {Array?} + */ this.transforms = transforms; + + /** + * The attributes (only relevant for compute stages with WebGL 2 which uses Transform Feedback). + * + * @type {Array?} + */ this.attributes = attributes; + /** + * How often the programmable stage is currently in use. + * + * @type {Number} + * @default 0 + */ this.usedTimes = 0; } } +/** + * This renderer module manages the pipelines of the renderer. + * + * @private + * @augments DataMap + */ class Pipelines extends DataMap { + /** + * Constructs a new pipeline management component. + * + * @param {Backend} backend - The renderer's backend. + * @param {Nodes} nodes - Renderer component for managing nodes related logic. + */ constructor( backend, nodes ) { super(); + /** + * The renderer's backend. + * + * @type {Backend} + */ this.backend = backend; + + /** + * Renderer component for managing nodes related logic. + * + * @type {Nodes} + */ this.nodes = nodes; - this.bindings = null; // set by the bindings + /** + * A references to the bindings management component. + * This reference will be set inside the `Bindings` + * constructor. + * + * @type {Bindings?} + * @default null + */ + this.bindings = null; + /** + * Internal cache for maintaining pipelines. + * The key of the map is a cache key, the value the pipeline. + * + * @type {Map} + */ this.caches = new Map(); + + /** + * This dictionary maintains for each shader stage type (vertex, + * fragment and compute) the programmable stage objects which + * represent the actual shader code. + * + * @type {Object} + */ this.programs = { vertex: new Map(), fragment: new Map(), @@ -21587,6 +24480,13 @@ class Pipelines extends DataMap { } + /** + * Returns a compute pipeline for the given compute node. + * + * @param {Node} computeNode - The compute node. + * @param {Array} bindings - The bindings. + * @return {ComputePipeline} The compute pipeline. + */ getForCompute( computeNode, bindings ) { const { backend } = this; @@ -21616,7 +24516,7 @@ class Pipelines extends DataMap { if ( previousPipeline && previousPipeline.computeProgram.usedTimes === 0 ) this._releaseProgram( previousPipeline.computeProgram ); - stageCompute = new ProgrammableStage( nodeBuilderState.computeShader, 'compute', nodeBuilderState.transforms, nodeBuilderState.nodeAttributes ); + stageCompute = new ProgrammableStage( nodeBuilderState.computeShader, 'compute', computeNode.name, nodeBuilderState.transforms, nodeBuilderState.nodeAttributes ); this.programs.compute.set( nodeBuilderState.computeShader, stageCompute ); backend.createProgram( stageCompute ); @@ -21653,6 +24553,13 @@ class Pipelines extends DataMap { } + /** + * Returns a render pipeline for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @param {Array?} [promises=null] - An array of compilation promises which is only relevant in context of `Renderer.compileAsync()`. + * @return {RenderPipeline} The render pipeline. + */ getForRender( renderObject, promises = null ) { const { backend } = this; @@ -21675,6 +24582,8 @@ class Pipelines extends DataMap { const nodeBuilderState = renderObject.getNodeBuilderState(); + const name = renderObject.material ? renderObject.material.name : ''; + // programmable stages let stageVertex = this.programs.vertex.get( nodeBuilderState.vertexShader ); @@ -21683,7 +24592,7 @@ class Pipelines extends DataMap { if ( previousPipeline && previousPipeline.vertexProgram.usedTimes === 0 ) this._releaseProgram( previousPipeline.vertexProgram ); - stageVertex = new ProgrammableStage( nodeBuilderState.vertexShader, 'vertex' ); + stageVertex = new ProgrammableStage( nodeBuilderState.vertexShader, 'vertex', name ); this.programs.vertex.set( nodeBuilderState.vertexShader, stageVertex ); backend.createProgram( stageVertex ); @@ -21696,7 +24605,7 @@ class Pipelines extends DataMap { if ( previousPipeline && previousPipeline.fragmentProgram.usedTimes === 0 ) this._releaseProgram( previousPipeline.fragmentProgram ); - stageFragment = new ProgrammableStage( nodeBuilderState.fragmentShader, 'fragment' ); + stageFragment = new ProgrammableStage( nodeBuilderState.fragmentShader, 'fragment', name ); this.programs.fragment.set( nodeBuilderState.fragmentShader, stageFragment ); backend.createProgram( stageFragment ); @@ -21737,6 +24646,12 @@ class Pipelines extends DataMap { } + /** + * Deletes the pipeline for the given render object. + * + * @param {RenderObject} object - The render object. + * @return {Object?} The deleted dictionary. + */ delete( object ) { const pipeline = this.get( object ).pipeline; @@ -21773,6 +24688,9 @@ class Pipelines extends DataMap { } + /** + * Frees internal resources. + */ dispose() { super.dispose(); @@ -21786,12 +24704,27 @@ class Pipelines extends DataMap { } + /** + * Updates the pipeline for the given render object. + * + * @param {RenderObject} renderObject - The render object. + */ updateForRender( renderObject ) { this.getForRender( renderObject ); } + /** + * Returns a compute pipeline for the given parameters. + * + * @private + * @param {Node} computeNode - The compute node. + * @param {ProgrammableStage} stageCompute - The programmable stage representing the compute shader. + * @param {String} cacheKey - The cache key. + * @param {Array} bindings - The bindings. + * @return {ComputePipeline} The compute pipeline. + */ _getComputePipeline( computeNode, stageCompute, cacheKey, bindings ) { // check for existing pipeline @@ -21814,6 +24747,17 @@ class Pipelines extends DataMap { } + /** + * Returns a render pipeline for the given parameters. + * + * @private + * @param {RenderObject} renderObject - The render object. + * @param {ProgrammableStage} stageVertex - The programmable stage representing the vertex shader. + * @param {ProgrammableStage} stageFragment - The programmable stage representing the fragment shader. + * @param {String} cacheKey - The cache key. + * @param {Array} promises - An array of compilation promises which is only relevant in context of `Renderer.compileAsync()`. + * @return {ComputePipeline} The compute pipeline. + */ _getRenderPipeline( renderObject, stageVertex, stageFragment, cacheKey, promises ) { // check for existing pipeline @@ -21830,6 +24774,10 @@ class Pipelines extends DataMap { renderObject.pipeline = pipeline; + // The `promises` array is `null` by default and only set to an empty array when + // `Renderer.compileAsync()` is used. The next call actually fills the array with + // pending promises that resolve when the render pipelines are ready for rendering. + this.backend.createRenderPipeline( renderObject, promises ); } @@ -21838,24 +24786,53 @@ class Pipelines extends DataMap { } + /** + * Computes a cache key representing a compute pipeline. + * + * @private + * @param {Node} computeNode - The compute node. + * @param {ProgrammableStage} stageCompute - The programmable stage representing the compute shader. + * @return {String} The cache key. + */ _getComputeCacheKey( computeNode, stageCompute ) { return computeNode.id + ',' + stageCompute.id; } + /** + * Computes a cache key representing a render pipeline. + * + * @private + * @param {RenderObject} renderObject - The render object. + * @param {ProgrammableStage} stageVertex - The programmable stage representing the vertex shader. + * @param {ProgrammableStage} stageFragment - The programmable stage representing the fragment shader. + * @return {String} The cache key. + */ _getRenderCacheKey( renderObject, stageVertex, stageFragment ) { return stageVertex.id + ',' + stageFragment.id + ',' + this.backend.getRenderCacheKey( renderObject ); } + /** + * Releases the given pipeline. + * + * @private + * @param {Pipeline} pipeline - The pipeline to release. + */ _releasePipeline( pipeline ) { this.caches.delete( pipeline.cacheKey ); } + /** + * Releases the shader program. + * + * @private + * @param {Object} program - The shader program to release. + */ _releaseProgram( program ) { const code = program.code; @@ -21865,6 +24842,13 @@ class Pipelines extends DataMap { } + /** + * Returns `true` if the compute pipeline for the given compute node requires an update. + * + * @private + * @param {Node} computeNode - The compute node. + * @return {Boolean} Whether the compute pipeline for the given compute node requires an update or not. + */ _needsComputeUpdate( computeNode ) { const data = this.get( computeNode ); @@ -21873,6 +24857,13 @@ class Pipelines extends DataMap { } + /** + * Returns `true` if the render pipeline for the given render object requires an update. + * + * @private + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether the render object for the given render object requires an update or not. + */ _needsRenderUpdate( renderObject ) { const data = this.get( renderObject ); @@ -21883,23 +24874,80 @@ class Pipelines extends DataMap { } +/** + * This renderer module manages the bindings of the renderer. + * + * @private + * @augments DataMap + */ class Bindings extends DataMap { + /** + * Constructs a new bindings management component. + * + * @param {Backend} backend - The renderer's backend. + * @param {Nodes} nodes - Renderer component for managing nodes related logic. + * @param {Textures} textures - Renderer component for managing textures. + * @param {Attributes} attributes - Renderer component for managing attributes. + * @param {Pipelines} pipelines - Renderer component for managing pipelines. + * @param {Info} info - Renderer component for managing metrics and monitoring data. + */ constructor( backend, nodes, textures, attributes, pipelines, info ) { super(); + /** + * The renderer's backend. + * + * @type {Backend} + */ this.backend = backend; + + /** + * Renderer component for managing textures. + * + * @type {Textures} + */ this.textures = textures; + + /** + * Renderer component for managing pipelines. + * + * @type {Pipelines} + */ this.pipelines = pipelines; + + /** + * Renderer component for managing attributes. + * + * @type {Attributes} + */ this.attributes = attributes; + + /** + * Renderer component for managing nodes related logic. + * + * @type {Nodes} + */ this.nodes = nodes; + + /** + * Renderer component for managing metrics and monitoring data. + * + * @type {Info} + */ this.info = info; this.pipelines.bindings = this; // assign bindings to pipelines } + /** + * Returns the bind groups for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @return {Array} The bind groups. + */ getForRender( renderObject ) { const bindings = renderObject.getBindings(); @@ -21926,6 +24974,12 @@ class Bindings extends DataMap { } + /** + * Returns the bind groups for the given compute node. + * + * @param {Node} computeNode - The compute node. + * @return {Array} The bind groups. + */ getForCompute( computeNode ) { const bindings = this.nodes.getForCompute( computeNode ).bindings; @@ -21950,18 +25004,33 @@ class Bindings extends DataMap { } + /** + * Updates the bindings for the given compute node. + * + * @param {Node} computeNode - The compute node. + */ updateForCompute( computeNode ) { this._updateBindings( this.getForCompute( computeNode ) ); } + /** + * Updates the bindings for the given render object. + * + * @param {RenderObject} renderObject - The render object. + */ updateForRender( renderObject ) { this._updateBindings( this.getForRender( renderObject ) ); } + /** + * Updates the given array of bindings. + * + * @param {Array} bindings - The bind groups. + */ _updateBindings( bindings ) { for ( const bindGroup of bindings ) { @@ -21972,6 +25041,11 @@ class Bindings extends DataMap { } + /** + * Initializes the given bind group. + * + * @param {BindGroup} bindGroup - The bind group to initialize. + */ _init( bindGroup ) { for ( const binding of bindGroup.bindings ) { @@ -21993,6 +25067,12 @@ class Bindings extends DataMap { } + /** + * Updates the given bind group. + * + * @param {BindGroup} bindGroup - The bind group to update. + * @param {Array} bindings - The bind groups. + */ _update( bindGroup, bindings ) { const { backend } = this; @@ -22010,7 +25090,10 @@ class Bindings extends DataMap { const updated = this.nodes.updateGroup( binding ); - if ( ! updated ) continue; + // every uniforms group is a uniform buffer. So if no update is required, + // we move one with the next binding. Otherwise the next if block will update the group. + + if ( updated === false ) continue; } @@ -22099,6 +25182,15 @@ class Bindings extends DataMap { } +/** + * Default sorting function for opaque render items. + * + * @private + * @function + * @param {Object} a - The first render item. + * @param {Object} b - The second render item. + * @return {Number} A numeric value which defines the sort order. + */ function painterSortStable( a, b ) { if ( a.groupOrder !== b.groupOrder ) { @@ -22125,6 +25217,15 @@ function painterSortStable( a, b ) { } +/** + * Default sorting function for transparent render items. + * + * @private + * @function + * @param {Object} a - The first render item. + * @param {Object} b - The second render item. + * @return {Number} A numeric value which defines the sort order. + */ function reversePainterSortStable( a, b ) { if ( a.groupOrder !== b.groupOrder ) { @@ -22147,6 +25248,14 @@ function reversePainterSortStable( a, b ) { } +/** + * Returns `true` if the given transparent material requires a double pass. + * + * @private + * @function + * @param {Material} material - The transparent material. + * @return {Boolean} Whether the given material requires a double pass or not. + */ function needsDoublePass( material ) { const hasTransmission = material.transmission > 0 || material.transmissionNode; @@ -22155,28 +25264,120 @@ function needsDoublePass( material ) { } +/** + * When the renderer analyzes the scene at the beginning of a render call, + * it stores 3D object for further processing in render lists. Depending on the + * properties of a 3D objects (like their transformation or material state), the + * objects are maintained in ordered lists for the actual rendering. + * + * Render lists are unique per scene and camera combination. + * + * @private + * @augments Pipeline + */ class RenderList { + /** + * Constructs a render list. + * + * @param {Lighting} lighting - The lighting management component. + * @param {Scene} scene - The scene. + * @param {Camera} camera - The camera the scene is rendered with. + */ constructor( lighting, scene, camera ) { + /** + * 3D objects are transformed into render items and stored in this array. + * + * @type {Array} + */ this.renderItems = []; + + /** + * The current render items index. + * + * @type {Number} + * @default 0 + */ this.renderItemsIndex = 0; + /** + * A list with opaque render items. + * + * @type {Array} + */ this.opaque = []; + + /** + * A list with transparent render items which require + * double pass rendering (e.g. transmissive objects). + * + * @type {Array} + */ this.transparentDoublePass = []; + + /** + * A list with transparent render items. + * + * @type {Array} + */ this.transparent = []; + + /** + * A list with transparent render bundle data. + * + * @type {Array} + */ this.bundles = []; + /** + * The render list's lights node. This node is later + * relevant for the actual analytical light nodes which + * compute the scene's lighting in the shader. + * + * @type {LightsNode} + */ this.lightsNode = lighting.getNode( scene, camera ); + + /** + * The scene's lights stored in an array. This array + * is used to setup the lights node. + * + * @type {Array} + */ this.lightsArray = []; + /** + * The scene. + * + * @type {Scene} + */ this.scene = scene; + + /** + * The camera the scene is rendered with. + * + * @type {Camera} + */ this.camera = camera; + /** + * How many objects perform occlusion query tests. + * + * @type {Number} + * @default 0 + */ this.occlusionQueryCount = 0; } + /** + * This method is called right at the beginning of a render call + * before the scene is analyzed. It prepares the internal data + * structures for the upcoming render lists generation. + * + * @return {RenderList} A reference to this render list. + */ begin() { this.renderItemsIndex = 0; @@ -22194,6 +25395,22 @@ class RenderList { } + /** + * Returns a render item for the giving render item state. The state is defined + * by a series of object-related parameters. + * + * The method avoids object creation by holding render items and reusing them in + * subsequent render calls (just with different property values). + * + * @param {Object3D} object - The 3D object. + * @param {BufferGeometry} geometry - The 3D object's geometry. + * @param {Material} material - The 3D object's material. + * @param {Number} groupOrder - The current group order. + * @param {Number} z - Th 3D object's depth value (z value in clip space). + * @param {Number?} group - {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`. + * @param {ClippingContext} clippingContext - The current clipping context. + * @return {Object} The render item. + */ getNextRenderItem( object, geometry, material, groupOrder, z, group, clippingContext ) { let renderItem = this.renderItems[ this.renderItemsIndex ]; @@ -22234,6 +25451,18 @@ class RenderList { } + /** + * Pushes the given object as a render item to the internal render lists. + * The selected lists depend on the object properties. + * + * @param {Object3D} object - The 3D object. + * @param {BufferGeometry} geometry - The 3D object's geometry. + * @param {Material} material - The 3D object's material. + * @param {Number} groupOrder - The current group order. + * @param {Number} z - Th 3D object's depth value (z value in clip space). + * @param {Number?} group - {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`. + * @param {ClippingContext} clippingContext - The current clipping context. + */ push( object, geometry, material, groupOrder, z, group, clippingContext ) { const renderItem = this.getNextRenderItem( object, geometry, material, groupOrder, z, group, clippingContext ); @@ -22254,6 +25483,18 @@ class RenderList { } + /** + * Inserts the given object as a render item at the start of the internal render lists. + * The selected lists depend on the object properties. + * + * @param {Object3D} object - The 3D object. + * @param {BufferGeometry} geometry - The 3D object's geometry. + * @param {Material} material - The 3D object's material. + * @param {Number} groupOrder - The current group order. + * @param {Number} z - Th 3D object's depth value (z value in clip space). + * @param {Number?} group - {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`. + * @param {ClippingContext} clippingContext - The current clipping context. + */ unshift( object, geometry, material, groupOrder, z, group, clippingContext ) { const renderItem = this.getNextRenderItem( object, geometry, material, groupOrder, z, group, clippingContext ); @@ -22272,18 +25513,34 @@ class RenderList { } + /** + * Pushes render bundle group data into the render list. + * + * @param {Object} group - Bundle group data. + */ pushBundle( group ) { this.bundles.push( group ); } + /** + * Pushes a light into the render list. + * + * @param {Light} light - The light. + */ pushLight( light ) { this.lightsArray.push( light ); } + /** + * Sorts the internal render lists. + * + * @param {Function} customOpaqueSort - A custom sort function for opaque objects. + * @param {Function} customTransparentSort - A custom sort function for transparent objects. + */ sort( customOpaqueSort, customTransparentSort ) { if ( this.opaque.length > 1 ) this.opaque.sort( customOpaqueSort || painterSortStable ); @@ -22292,6 +25549,10 @@ class RenderList { } + /** + * This method performs finalizing tasks right after the render lists + * have been generated. + */ finish() { // update lights @@ -22322,34 +25583,71 @@ class RenderList { } +const _chainKeys$4 = []; + +/** + * This renderer module manages the render lists which are unique + * per scene and camera combination. + * + * @private + */ class RenderLists { + /** + * Constructs a render lists management component. + * + * @param {Lighting} lighting - The lighting management component. + */ constructor( lighting ) { + /** + * The lighting management component. + * + * @type {Lighting} + */ this.lighting = lighting; + /** + * The internal chain map which holds the render lists. + * + * @type {ChainMap} + */ this.lists = new ChainMap(); } + /** + * Returns a render list for the given scene and camera. + * + * @param {Scene} scene - The scene. + * @param {Camera} camera - The camera. + * @return {RenderList} The render list. + */ get( scene, camera ) { const lists = this.lists; - const keys = [ scene, camera ]; - let list = lists.get( keys ); + _chainKeys$4[ 0 ] = scene; + _chainKeys$4[ 1 ] = camera; + + let list = lists.get( _chainKeys$4 ); if ( list === undefined ) { list = new RenderList( this.lighting, scene, camera ); - lists.set( keys, list ); + lists.set( _chainKeys$4, list ); } + _chainKeys$4.length = 0; + return list; } + /** + * Frees all internal resources. + */ dispose() { this.lists = new ChainMap(); @@ -22358,44 +25656,203 @@ class RenderLists { } -let id = 0; +let _id$7 = 0; +/** + * Any render or compute command is executed in a specific context that defines + * the state of the renderer and its backend. Typical examples for such context + * data are the current clear values or data from the active framebuffer. This + * module is used to represent these contexts as objects. + * + * @private + */ class RenderContext { + /** + * Constructs a new render context. + */ constructor() { - this.id = id ++; + /** + * The context's ID. + * + * @type {Number} + */ + this.id = _id$7 ++; + /** + * Whether the current active framebuffer has a color attachment. + * + * @type {Boolean} + * @default true + */ this.color = true; + + /** + * Whether the color attachment should be cleared or not. + * + * @type {Boolean} + * @default true + */ this.clearColor = true; + + /** + * The clear color value. + * + * @type {Object} + * @default true + */ this.clearColorValue = { r: 0, g: 0, b: 0, a: 1 }; + /** + * Whether the current active framebuffer has a depth attachment. + * + * @type {Boolean} + * @default true + */ this.depth = true; + + /** + * Whether the depth attachment should be cleared or not. + * + * @type {Boolean} + * @default true + */ this.clearDepth = true; + + /** + * The clear depth value. + * + * @type {Number} + * @default 1 + */ this.clearDepthValue = 1; + /** + * Whether the current active framebuffer has a stencil attachment. + * + * @type {Boolean} + * @default false + */ this.stencil = false; + + /** + * Whether the stencil attachment should be cleared or not. + * + * @type {Boolean} + * @default true + */ this.clearStencil = true; + + /** + * The clear stencil value. + * + * @type {Number} + * @default 1 + */ this.clearStencilValue = 1; + /** + * By default the viewport encloses the entire framebuffer If a smaller + * viewport is manually defined, this property is to `true` by the renderer. + * + * @type {Boolean} + * @default false + */ this.viewport = false; + + /** + * The viewport value. This value is in physical pixels meaning it incorporates + * the renderer's pixel ratio. The viewport property of render targets or + * the renderer is in logical pixels. + * + * @type {Vector4} + */ this.viewportValue = new Vector4(); + /** + * When the scissor test is active and scissor rectangle smaller than the + * framebuffers dimensions, this property is to `true` by the renderer. + * + * @type {Boolean} + * @default false + */ this.scissor = false; + + /** + * The scissor rectangle. + * + * @type {Vector4} + */ this.scissorValue = new Vector4(); + /** + * The textures of the active render target. + * `null` when no render target is set. + * + * @type {Array?} + * @default null + */ this.textures = null; + + /** + * The depth texture of the active render target. + * `null` when no render target is set. + * + * @type {DepthTexture?} + * @default null + */ this.depthTexture = null; + + /** + * The active cube face. + * + * @type {Number} + * @default 0 + */ this.activeCubeFace = 0; + + /** + * The number of MSAA samples. This value is always `1` when + * MSAA isn't used. + * + * @type {Number} + * @default 1 + */ this.sampleCount = 1; + /** + * The framebuffers width in physical pixels. + * + * @type {Number} + * @default 0 + */ this.width = 0; + + /** + * The framebuffers height in physical pixels. + * + * @type {Number} + * @default 0 + */ this.height = 0; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isRenderContext = true; } + /** + * Returns the cache key of this render context. + * + * @return {Number} The cache key. + */ getCacheKey() { return getCacheKey( this ); @@ -22404,6 +25861,12 @@ class RenderContext { } +/** + * Computes a cache key for the given render context. + * + * @param {RenderContext} renderContext - The render context. + * @return {Number} The cache key. + */ function getCacheKey( renderContext ) { const { textures, activeCubeFace } = renderContext; @@ -22420,17 +25883,44 @@ function getCacheKey( renderContext ) { } +const _chainKeys$3 = []; +const _defaultScene = /*@__PURE__*/ new Scene(); +const _defaultCamera = /*@__PURE__*/ new Camera(); + +/** + * This module manages the render contexts of the renderer. + * + * @private + */ class RenderContexts { + /** + * Constructs a new render context management component. + */ constructor() { + /** + * A dictionary that manages render contexts in chain maps + * for each attachment state. + * + * @type {Object} + */ this.chainMaps = {}; } + /** + * Returns a render context for the given scene, camera and render target. + * + * @param {Scene} scene - The scene. + * @param {Camera} camera - The camera that is used to render the scene. + * @param {RenderTarget?} [renderTarget=null] - The active render target. + * @return {RenderContext} The render context. + */ get( scene, camera, renderTarget = null ) { - const chainKey = [ scene, camera ]; + _chainKeys$3[ 0 ] = scene; + _chainKeys$3[ 1 ] = camera; let attachmentState; @@ -22447,30 +25937,54 @@ class RenderContexts { } - const chainMap = this.getChainMap( attachmentState ); + const chainMap = this._getChainMap( attachmentState ); - let renderState = chainMap.get( chainKey ); + let renderState = chainMap.get( _chainKeys$3 ); if ( renderState === undefined ) { renderState = new RenderContext(); - chainMap.set( chainKey, renderState ); + chainMap.set( _chainKeys$3, renderState ); } + _chainKeys$3.length = 0; + if ( renderTarget !== null ) renderState.sampleCount = renderTarget.samples === 0 ? 1 : renderTarget.samples; return renderState; } - getChainMap( attachmentState ) { + /** + * Returns a render context intended for clear operations. + * + * @param {RenderTarget?} [renderTarget=null] - The active render target. + * @return {RenderContext} The render context. + */ + getForClear( renderTarget = null ) { + + return this.get( _defaultScene, _defaultCamera, renderTarget ); + + } + + /** + * Returns a chain map for the given attachment state. + * + * @private + * @param {String} attachmentState - The attachment state. + * @return {ChainMap} The chain map. + */ + _getChainMap( attachmentState ) { return this.chainMaps[ attachmentState ] || ( this.chainMaps[ attachmentState ] = new ChainMap() ); } + /** + * Frees internal resources. + */ dispose() { this.chainMaps = {}; @@ -22481,18 +25995,55 @@ class RenderContexts { const _size$3 = /*@__PURE__*/ new Vector3(); +/** + * This module manages the textures of the renderer. + * + * @private + * @augments DataMap + */ class Textures extends DataMap { + /** + * Constructs a new texture management component. + * + * @param {Renderer} renderer - The renderer. + * @param {Backend} backend - The renderer's backend. + * @param {Info} info - Renderer component for managing metrics and monitoring data. + */ constructor( renderer, backend, info ) { super(); + /** + * The renderer. + * + * @type {Renderer} + */ this.renderer = renderer; + + /** + * The backend. + * + * @type {Backend} + */ this.backend = backend; + + /** + * Renderer component for managing metrics and monitoring data. + * + * @type {Info} + */ this.info = info; } + /** + * Updates the given render target. Based on the given render target configuration, + * it updates the texture states representing the attachments of the framebuffer. + * + * @param {RenderTarget} renderTarget - The render target to update. + * @param {Number} [activeMipmapLevel=0] - The active mipmap level. + */ updateRenderTarget( renderTarget, activeMipmapLevel = 0 ) { const renderTargetData = this.get( renderTarget ); @@ -22614,6 +26165,14 @@ class Textures extends DataMap { } + /** + * Updates the given texture. Depending on the texture state, this method + * triggers the upload of texture data to the GPU memory. If the texture data are + * not yet ready for the upload, it uses default texture data for as a placeholder. + * + * @param {Texture} texture - The texture to update. + * @param {Object} [options={}] - The options. + */ updateTexture( texture, options = {} ) { const textureData = this.get( texture ); @@ -22767,6 +26326,18 @@ class Textures extends DataMap { } + /** + * Computes the size of the given texture and writes the result + * into the target vector. This vector is also returned by the + * method. + * + * If no texture data are available for the compute yet, the method + * returns default size values. + * + * @param {Texture} texture - The texture to compute the size for. + * @param {Vector3} target - The target vector. + * @return {Vector3} The target vector. + */ getSize( texture, target = _size$3 ) { let image = texture.images ? texture.images[ 0 ] : texture.image; @@ -22789,6 +26360,14 @@ class Textures extends DataMap { } + /** + * Computes the number of mipmap levels for the given texture. + * + * @param {Texture} texture - The texture. + * @param {Number} width - The texture's width. + * @param {Number} height - The texture's height. + * @return {Number} The number of mipmap levels. + */ getMipLevels( texture, width, height ) { let mipLevelCount; @@ -22815,12 +26394,24 @@ class Textures extends DataMap { } + /** + * Returns `true` if the given texture requires mipmaps. + * + * @param {Texture} texture - The texture. + * @return {Boolean} Whether mipmaps are required or not. + */ needsMipmaps( texture ) { return this.isEnvironmentTexture( texture ) || texture.isCompressedTexture === true || texture.generateMipmaps; } + /** + * Returns `true` if the given texture is an environment map. + * + * @param {Texture} texture - The texture. + * @return {Boolean} Whether the given texture is an environment map or not. + */ isEnvironmentTexture( texture ) { const mapping = texture.mapping; @@ -22829,6 +26420,12 @@ class Textures extends DataMap { } + /** + * Frees internal resource when the given texture isn't + * required anymore. + * + * @param {Texture} texture - The texture to destroy. + */ _destroyTexture( texture ) { this.backend.destroySampler( texture ); @@ -22840,8 +26437,24 @@ class Textures extends DataMap { } +/** + * A four-component version of {@link Color} which is internally + * used by the renderer to represents clear color with alpha as + * one object. + * + * @private + * @augments Color + */ class Color4 extends Color { + /** + * Constructs a new four-component color. + * + * @param {Number|String} r - The red value. + * @param {Number} g - The green value. + * @param {Number} b - The blue value. + * @param {Number} [a=1] - The alpha value. + */ constructor( r, g, b, a = 1 ) { super( r, g, b ); @@ -22850,6 +26463,15 @@ class Color4 extends Color { } + /** + * Overwrites the default to honor alpha. + * + * @param {Number|String} r - The red value. + * @param {Number} g - The green value. + * @param {Number} b - The blue value. + * @param {Number} [a=1] - The alpha value. + * @return {Color4} A reference to this object. + */ set( r, g, b, a = 1 ) { this.a = a; @@ -22858,6 +26480,12 @@ class Color4 extends Color { } + /** + * Overwrites the default to honor alpha. + * + * @param {Color4} color - The color to copy. + * @return {Color4} A reference to this object. + */ copy( color ) { if ( color.a !== undefined ) this.a = color.a; @@ -22866,6 +26494,11 @@ class Color4 extends Color { } + /** + * Overwrites the default to honor alpha. + * + * @return {Color4} The cloned color. + */ clone() { return new this.constructor( this.r, this.g, this.b, this.a ); @@ -24423,7 +28056,7 @@ class ReflectorBaseNode extends Node { updateBefore( frame ) { - if ( this.bounces === false && _inReflector ) return; + if ( this.bounces === false && _inReflector ) return false; _inReflector = true; @@ -24520,14 +28153,17 @@ class ReflectorBaseNode extends Node { const currentRenderTarget = renderer.getRenderTarget(); const currentMRT = renderer.getMRT(); + const currentAutoClear = renderer.autoClear; renderer.setMRT( null ); renderer.setRenderTarget( renderTarget ); + renderer.autoClear = true; renderer.render( scene, virtualCamera ); renderer.setMRT( currentMRT ); renderer.setRenderTarget( currentRenderTarget ); + renderer.autoClear = currentAutoClear; material.visible = true; @@ -24553,14 +28189,23 @@ class ReflectorBaseNode extends Node { */ const reflector = ( parameters ) => nodeObject( new ReflectorNode( parameters ) ); -// Helper for passes that need to fill the viewport with a single quad. - const _camera = /*@__PURE__*/ new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); -// https://github.com/mrdoob/three.js/pull/21358 - +/** + * The purpose of this special geometry is to fill the entire viewport with a single triangle. + * + * Reference: {@link https://github.com/mrdoob/three.js/pull/21358} + * + * @private + * @augments BufferGeometry + */ class QuadGeometry extends BufferGeometry { + /** + * Constructs a new quad geometry. + * + * @param {Boolean} [flipY=false] - Whether the uv coordinates should be flipped along the vertical axis or not. + */ constructor( flipY = false ) { super(); @@ -24576,24 +28221,64 @@ class QuadGeometry extends BufferGeometry { const _geometry = /*@__PURE__*/ new QuadGeometry(); + +/** + * This module is a helper for passes which need to render a full + * screen effect which is quite common in context of post processing. + * + * The intended usage is to reuse a single quad mesh for rendering + * subsequent passes by just reassigning the `material` reference. + * + * @augments BufferGeometry + */ class QuadMesh extends Mesh { + /** + * Constructs a new quad mesh. + * + * @param {Material?} [material=null] - The material to render the quad mesh with. + */ constructor( material = null ) { super( _geometry, material ); + /** + * The camera to render the quad mesh with. + * + * @type {OrthographicCamera} + * @readonly + */ this.camera = _camera; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isQuadMesh = true; } - renderAsync( renderer ) { + /** + * Async version of `render()`. + * + * @async + * @param {Renderer} renderer - The renderer. + * @return {Promise} A Promise that resolves when the render has been finished. + */ + async renderAsync( renderer ) { return renderer.renderAsync( this, _camera ); } + /** + * Renders the quad mesh + * + * @param {Renderer} renderer - The renderer. + */ render( renderer ) { renderer.render( this, _camera ); @@ -24942,28 +28627,86 @@ const getNormalFromDepth = /*@__PURE__*/ Fn( ( [ uv, depthTexture, projectionMat } ); +/** + * This special type of instanced buffer attribute is intended for compute shaders. + * In earlier three.js versions it was only possible to update attribute data + * on the CPU via JavaScript and then upload the data to the GPU. With the + * new material system and renderer it is now possible to use compute shaders + * to compute the data for an attribute more efficiently on the GPU. + * + * The idea is to create an instance of this class and provide it as an input + * to {@link module:StorageBufferNode}. + * + * Note: This type of buffer attribute can only be used with `WebGPURenderer`. + * + * @augments InstancedBufferAttribute + */ class StorageInstancedBufferAttribute extends InstancedBufferAttribute { - constructor( array, itemSize, typeClass = Float32Array ) { + /** + * Constructs a new storage instanced buffer attribute. + * + * @param {Number|TypedArray} count - The item count. It is also valid to pass a typed array as an argument. + * The subsequent parameters are then obsolete. + * @param {Number} itemSize - The item size. + * @param {TypedArray.constructor} [typeClass=Float32Array] - A typed array constructor. + */ + constructor( count, itemSize, typeClass = Float32Array ) { - if ( ArrayBuffer.isView( array ) === false ) array = new typeClass( array * itemSize ); + const array = ArrayBuffer.isView( count ) ? count : new typeClass( count * itemSize ); super( array, itemSize ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isStorageInstancedBufferAttribute = true; } } +/** + * This special type of buffer attribute is intended for compute shaders. + * In earlier three.js versions it was only possible to update attribute data + * on the CPU via JavaScript and then upload the data to the GPU. With the + * new material system and renderer it is now possible to use compute shaders + * to compute the data for an attribute more efficiently on the GPU. + * + * The idea is to create an instance of this class and provide it as an input + * to {@link module:StorageBufferNode}. + * + * Note: This type of buffer attribute can only be used with `WebGPURenderer`. + * + * @augments BufferAttribute + */ class StorageBufferAttribute extends BufferAttribute { - constructor( array, itemSize, typeClass = Float32Array ) { + /** + * Constructs a new storage buffer attribute. + * + * @param {Number|TypedArray} count - The item count. It is also valid to pass a typed array as an argument. + * The subsequent parameters are then obsolete. + * @param {Number} itemSize - The item size. + * @param {TypedArray.constructor} [typeClass=Float32Array] - A typed array constructor. + */ + constructor( count, itemSize, typeClass = Float32Array ) { - if ( ArrayBuffer.isView( array ) === false ) array = new typeClass( array * itemSize ); + const array = ArrayBuffer.isView( count ) ? count : new typeClass( count * itemSize ); super( array, itemSize ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isStorageBufferAttribute = true; } @@ -25103,7 +28846,7 @@ const storageElement = /*@__PURE__*/ nodeProxy( StorageArrayElementNode ); * storage buffer for data. A typical workflow is to create instances of * this node with the convenience functions `attributeArray()` or `instancedArray()`, * setup up a compute shader that writes into the buffers and then convert - * the storage buffers to attributes for rendering. + * the storage buffers to attribute nodes for rendering. * * ```js * const positionBuffer = instancedArray( particleCount, 'vec3' ); // the storage buffer node @@ -25140,7 +28883,7 @@ class StorageBufferNode extends BufferNode { /** * Constructs a new storage buffer node. * - * @param {StorageBufferAttribute|StorageInstancedBufferAttribute} value - The buffer data. + * @param {StorageBufferAttribute|StorageInstancedBufferAttribute|BufferAttribute} value - The buffer data. * @param {String?} [bufferType=null] - The buffer type (e.g. `'vec3'`). * @param {Number} [bufferCount=0] - The buffer count. */ @@ -25426,7 +29169,7 @@ class StorageBufferNode extends BufferNode { * TSL function for creating a storage buffer node. * * @function - * @param {StorageBufferAttribute|StorageInstancedBufferAttribute} value - The buffer data. + * @param {StorageBufferAttribute|StorageInstancedBufferAttribute|BufferAttribute} value - The buffer data. * @param {String?} [type=null] - The buffer type (e.g. `'vec3'`). * @param {Number} [count=0] - The buffer count. * @returns {StorageBufferNode} @@ -25454,8 +29197,9 @@ const storageObject = ( value, type, count ) => { // @deprecated, r171 const attributeArray = ( count, type = 'float' ) => { const itemSize = getLengthFromType( type ); + const typedArray = getTypedArrayFromType( type ); - const buffer = new StorageBufferAttribute( count, itemSize ); + const buffer = new StorageBufferAttribute( count, itemSize, typedArray ); const node = storage( buffer, type, count ); return node; @@ -25473,8 +29217,9 @@ const attributeArray = ( count, type = 'float' ) => { const instancedArray = ( count, type = 'float' ) => { const itemSize = getLengthFromType( type ); + const typedArray = getTypedArrayFromType( type ); - const buffer = new StorageInstancedBufferAttribute( count, itemSize ); + const buffer = new StorageInstancedBufferAttribute( count, itemSize, typedArray ); const node = storage( buffer, type, count ); return node; @@ -27976,6 +31721,8 @@ const nativeFn = ( code, includes = [], language = '' ) => { const glslFn = ( code, includes ) => nativeFn( code, includes, 'glsl' ); const wgslFn = ( code, includes ) => nativeFn( code, includes, 'wgsl' ); +/** @module ScriptableValueNode **/ + /** * `ScriptableNode` uses this class to manage script inputs and outputs. * @@ -28221,6 +31968,8 @@ class ScriptableValueNode extends Node { */ const scriptableValue = /*@__PURE__*/ nodeProxy( ScriptableValueNode ); +/** @module ScriptableNode **/ + /** * A Map-like data structure for managing resources of scriptable nodes. * @@ -28282,7 +32031,7 @@ class Parameters { } /** - * Defines the resouces (e.g. namespaces) of scriptable nodes. + * Defines the resources (e.g. namespaces) of scriptable nodes. * * @type {Resources} */ @@ -28494,7 +32243,7 @@ class ScriptableNode extends Node { * Returns a script output for the given name. * * @param {String} name - The name of the output. - * @return {Node} The node value. + * @return {ScriptableValueNode} The node value. */ getOutput( name ) { @@ -28503,7 +32252,7 @@ class ScriptableNode extends Node { } /** - * Returns a paramater for the given name + * Returns a parameter for the given name * * @param {String} name - The name of the parameter. * @return {ScriptableValueNode} The node value. @@ -28662,7 +32411,7 @@ class ScriptableNode extends Node { /** * Refreshes the script node. * - * @param {String?} [output=null] - An optinal output. + * @param {String?} [output=null] - An optional output. */ refresh( output = null ) { @@ -28698,7 +32447,7 @@ class ScriptableNode extends Node { const THREE = ScriptableNodeResources.get( 'THREE' ); const TSL = ScriptableNodeResources.get( 'TSL' ); - const method = this.getMethod( this.codeNode ); + const method = this.getMethod(); const params = [ parameters, this._local, ScriptableNodeResources, refresh, setOutput, THREE, TSL ]; this._object = method( ...params ); @@ -28972,6 +32721,7 @@ function getViewZNode( builder ) { /** * Constructs a new range factor node. * + * @function * @param {Node} near - Defines the near value. * @param {Node} far - Defines the far value. */ @@ -28988,6 +32738,7 @@ const rangeFogFactor = Fn( ( [ near, far ], builder ) => { * a clear view near the camera and a faster than exponentially * densening fog farther from the camera. * + * @function * @param {Node} density - Defines the fog density. */ const densityFogFactor = Fn( ( [ density ], builder ) => { @@ -29002,6 +32753,7 @@ const densityFogFactor = Fn( ( [ density ], builder ) => { * This class can be used to configure a fog for the scene. * Nodes of this type are assigned to `Scene.fogNode`. * + * @function * @param {Node} color - Defines the color of the fog. * @param {Node} factor - Defines how the fog is factored in the scene. */ @@ -29191,7 +32943,10 @@ const range = /*@__PURE__*/ nodeProxy( RangeNode ); /** @module ComputeBuiltinNode **/ /** - * TODO + * `ComputeBuiltinNode` represents a compute-scope builtin value that expose information + * about the currently running dispatch and/or the device it is running on. + * + * This node can only be used with a WebGPU backend. * * @augments Node */ @@ -29334,6 +33089,24 @@ const computeBuiltin = ( name, nodeType ) => nodeObject( new ComputeBuiltinNode( /** * TSL function for creating a `numWorkgroups` builtin node. + * Represents the number of workgroups dispatched by the compute shader. + * ```js + * // Run 512 invocations/threads with a workgroup size of 128. + * const computeFn = Fn(() => { + * + * // numWorkgroups.x = 4 + * storageBuffer.element(0).assign(numWorkgroups.x) + * + * })().compute(512, [128]); + * + * // Run 512 invocations/threads with the default workgroup size of 64. + * const computeFn = Fn(() => { + * + * // numWorkgroups.x = 8 + * storageBuffer.element(0).assign(numWorkgroups.x) + * + * })().compute(512); + * ``` * * @function * @returns {ComputeBuiltinNode} @@ -29342,6 +33115,26 @@ const numWorkgroups = /*@__PURE__*/ computeBuiltin( 'numWorkgroups', 'uvec3' ); /** * TSL function for creating a `workgroupId` builtin node. + * Represents the 3-dimensional index of the workgroup the current compute invocation belongs to. + * ```js + * // Execute 12 compute threads with a workgroup size of 3. + * const computeFn = Fn( () => { + * + * If( workgroupId.x.modInt( 2 ).equal( 0 ), () => { + * + * storageBuffer.element( instanceIndex ).assign( instanceIndex ); + * + * } ).Else( () => { + * + * storageBuffer.element( instanceIndex ).assign( 0 ); + * + * } ); + * + * } )().compute( 12, [ 3 ] ); + * + * // workgroupId.x = [0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3]; + * // Buffer Output = [0, 1, 2, 0, 0, 0, 6, 7, 8, 0, 0, 0]; + * ``` * * @function * @returns {ComputeBuiltinNode} @@ -29349,7 +33142,8 @@ const numWorkgroups = /*@__PURE__*/ computeBuiltin( 'numWorkgroups', 'uvec3' ); const workgroupId = /*@__PURE__*/ computeBuiltin( 'workgroupId', 'uvec3' ); /** - * TSL function for creating a `localId` builtin node. + * TSL function for creating a `localId` builtin node. A non-linearized 3-dimensional + * representation of the current invocation's position within a 3D workgroup grid. * * @function * @returns {ComputeBuiltinNode} @@ -29357,7 +33151,8 @@ const workgroupId = /*@__PURE__*/ computeBuiltin( 'workgroupId', 'uvec3' ); const localId = /*@__PURE__*/ computeBuiltin( 'localId', 'uvec3' ); /** - * TSL function for creating a `subgroupSize` builtin node. + * TSL function for creating a `subgroupSize` builtin node. A device dependent variable + * that exposes the size of the current invocation's subgroup. * * @function * @returns {ComputeBuiltinNode} @@ -29367,7 +33162,9 @@ const subgroupSize = /*@__PURE__*/ computeBuiltin( 'subgroupSize', 'uint' ); /** @module BarrierNode **/ /** - * TODO + * Represents a GPU control barrier that synchronizes compute operations within a given scope. + * + * This node can only be used with a WebGPU backend. * * @augments Node */ @@ -29415,7 +33212,9 @@ class BarrierNode extends Node { const barrier = nodeProxy( BarrierNode ); /** - * TSL function for creating a workgroup barrier. + * TSL function for creating a workgroup barrier. All compute shader + * invocations must wait for each invocation within a workgroup to + * complete before the barrier can be surpassed. * * @function * @returns {BarrierNode} @@ -29423,7 +33222,9 @@ const barrier = nodeProxy( BarrierNode ); const workgroupBarrier = () => barrier( 'workgroup' ).append(); /** - * TSL function for creating a storage barrier. + * TSL function for creating a storage barrier. All invocations must + * wait for each access to variables within the 'storage' address space + * to complete before the barrier can be passed. * * @function * @returns {BarrierNode} @@ -29431,7 +33232,9 @@ const workgroupBarrier = () => barrier( 'workgroup' ).append(); const storageBarrier = () => barrier( 'storage' ).append(); /** - * TSL function for creating a texture barrier. + * TSL function for creating a texture barrier. All invocations must + * wait for each access to variables within the 'texture' address space + * to complete before the barrier can be passed. * * @function * @returns {BarrierNode} @@ -29441,7 +33244,7 @@ const textureBarrier = () => barrier( 'texture' ).append(); /** @module WorkgroupInfoNode **/ /** - * TODO + * Represents an element of a 'workgroup' scoped buffer. * * @augments ArrayElementNode */ @@ -29492,18 +33295,25 @@ class WorkgroupInfoElementNode extends ArrayElementNode { } /** - * TODO + * A node allowing the user to create a 'workgroup' scoped buffer within the + * context of a compute shader. Typically, workgroup scoped buffers are + * created to hold data that is transferred from a global storage scope into + * a local workgroup scope. For invocations within a workgroup, data + * access speeds on 'workgroup' scoped buffers can be significantly faster + * than similar access operations on globally accessible storage buffers. + * + * This node can only be used with a WebGPU backend. * * @augments Node */ class WorkgroupInfoNode extends Node { /** - * Constructs a new workgroup info node. + * Constructs a new buffer scoped to type scope. * * @param {String} scope - TODO. - * @param {String} bufferType - The buffer type. - * @param {Number} [bufferCount=0] - The buffer count. + * @param {String} bufferType - The data type of a 'workgroup' scoped buffer element. + * @param {Number} [bufferCount=0] - The number of elements in the buffer. */ constructor( scope, bufferType, bufferCount = 0 ) { @@ -29533,6 +33343,13 @@ class WorkgroupInfoNode extends Node { */ this.isWorkgroupInfoNode = true; + /** + * The data type of the array buffer. + * + * @type {String} + */ + this.elementType = bufferType; + /** * TODO. * @@ -29570,6 +33387,18 @@ class WorkgroupInfoNode extends Node { } + + /** + * The data type of the array buffer. + * + * @return {String} The element type. + */ + getElementType() { + + return this.elementType; + + } + /** * Overwrites the default implementation since the input type * is inferred from the scope. @@ -29605,10 +33434,11 @@ class WorkgroupInfoNode extends Node { /** * TSL function for creating a workgroup info node. + * Creates a new 'workgroup' scoped array buffer. * * @function - * @param {String} type - The buffer type. - * @param {Number} [count=0] - The buffer count. + * @param {String} type - The data type of a 'workgroup' scoped buffer element. + * @param {Number} [count=0] - The number of elements in the buffer. * @returns {WorkgroupInfoNode} */ const workgroupArray = ( type, count ) => nodeObject( new WorkgroupInfoNode( 'Workgroup', type, count ) ); @@ -29616,7 +33446,13 @@ const workgroupArray = ( type, count ) => nodeObject( new WorkgroupInfoNode( 'Wo /** @module AtomicFunctionNode **/ /** - * TODO + * `AtomicFunctionNode` represents any function that can operate on atomic variable types + * within a shader. In an atomic function, any modification to an atomic variable will + * occur as an indivisible step with a defined order relative to other modifications. + * Accordingly, even if multiple atomic functions are modifying an atomic variable at once + * atomic operations will not interfere with each other. + * + * This node can only be used with a WebGPU backend. * * @augments TempNode */ @@ -29631,38 +33467,38 @@ class AtomicFunctionNode extends TempNode { /** * Constructs a new atomic function node. * - * @param {String} method - TODO. - * @param {Node} pointerNode - TODO. - * @param {Node} valueNode - TODO. - * @param {Node?} [storeNode=null] - TODO. + * @param {String} method - The signature of the atomic function to construct. + * @param {Node} pointerNode - An atomic variable or element of an atomic buffer. + * @param {Node} valueNode - The value that mutates the atomic variable. + * @param {Node?} [storeNode=null] - A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. */ constructor( method, pointerNode, valueNode, storeNode = null ) { super( 'uint' ); /** - * TODO + * The signature of the atomic function to construct. * * @type {String} */ this.method = method; /** - * TODO + * An atomic variable or element of an atomic buffer. * * @type {Node} */ this.pointerNode = pointerNode; /** - * TODO + * A value that modifies the atomic variable. * * @type {Node} */ this.valueNode = valueNode; /** - * TODO + * A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. * * @type {Node?} * @default null @@ -29743,22 +33579,22 @@ AtomicFunctionNode.ATOMIC_XOR = 'atomicXor'; * TSL function for creating an atomic function node. * * @function - * @param {String} method - TODO. - * @param {Node} pointerNode - TODO. - * @param {Node} valueNode - TODO. - * @param {Node?} [storeNode=null] - TODO. + * @param {String} method - The signature of the atomic function to construct. + * @param {Node} pointerNode - An atomic variable or element of an atomic buffer. + * @param {Node} valueNode - The value that mutates the atomic variable. + * @param {Node?} [storeNode=null] - A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. * @returns {AtomicFunctionNode} */ const atomicNode = nodeProxy( AtomicFunctionNode ); /** - * TODO + * TSL function for appending an atomic function call into the programmatic flow of a compute shader. * * @function - * @param {String} method - TODO. - * @param {Node} pointerNode - TODO. - * @param {Node} valueNode - TODO. - * @param {Node?} [storeNode=null] - TODO. + * @param {String} method - The signature of the atomic function to construct. + * @param {Node} pointerNode - An atomic variable or element of an atomic buffer. + * @param {Node} valueNode - The value that mutates the atomic variable. + * @param {Node?} [storeNode=null] - A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. * @returns {AtomicFunctionNode} */ const atomicFunc = ( method, pointerNode, valueNode, storeNode = null ) => { @@ -29771,89 +33607,89 @@ const atomicFunc = ( method, pointerNode, valueNode, storeNode = null ) => { }; /** - * TODO + * Stores a value in the atomic variable. * * @function - * @param {Node} pointerNode - TODO. - * @param {Node} valueNode - TODO. - * @param {Node?} [storeNode=null] - TODO. + * @param {Node} pointerNode - An atomic variable or element of an atomic buffer. + * @param {Node} valueNode - The value that mutates the atomic variable. + * @param {Node?} [storeNode=null] - A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. * @returns {AtomicFunctionNode} */ const atomicStore = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_STORE, pointerNode, valueNode, storeNode ); /** - * TODO + * Increments the value stored in the atomic variable. * * @function - * @param {Node} pointerNode - TODO. - * @param {Node} valueNode - TODO. - * @param {Node?} [storeNode=null] - TODO. + * @param {Node} pointerNode - An atomic variable or element of an atomic buffer. + * @param {Node} valueNode - The value that mutates the atomic variable. + * @param {Node?} [storeNode=null] - A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. * @returns {AtomicFunctionNode} */ const atomicAdd = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_ADD, pointerNode, valueNode, storeNode ); /** - * TODO + * Decrements the value stored in the atomic variable. * * @function - * @param {Node} pointerNode - TODO. - * @param {Node} valueNode - TODO. - * @param {Node?} [storeNode=null] - TODO. + * @param {Node} pointerNode - An atomic variable or element of an atomic buffer. + * @param {Node} valueNode - The value that mutates the atomic variable. + * @param {Node?} [storeNode=null] - A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. * @returns {AtomicFunctionNode} */ const atomicSub = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_SUB, pointerNode, valueNode, storeNode ); /** - * TODO + * Stores in an atomic variable the maximum between its current value and a parameter. * * @function - * @param {Node} pointerNode - TODO. - * @param {Node} valueNode - TODO. - * @param {Node?} [storeNode=null] - TODO. + * @param {Node} pointerNode - An atomic variable or element of an atomic buffer. + * @param {Node} valueNode - The value that mutates the atomic variable. + * @param {Node?} [storeNode=null] - A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. * @returns {AtomicFunctionNode} */ const atomicMax = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_MAX, pointerNode, valueNode, storeNode ); /** - * TODO + * Stores in an atomic variable the minimum between its current value and a parameter. * * @function - * @param {Node} pointerNode - TODO. - * @param {Node} valueNode - TODO. - * @param {Node?} [storeNode=null] - TODO. + * @param {Node} pointerNode - An atomic variable or element of an atomic buffer. + * @param {Node} valueNode - The value that mutates the atomic variable. + * @param {Node?} [storeNode=null] - A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. * @returns {AtomicFunctionNode} */ const atomicMin = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_MIN, pointerNode, valueNode, storeNode ); /** - * TODO + * Stores in an atomic variable the bitwise AND of its value with a parameter. * * @function - * @param {Node} pointerNode - TODO. - * @param {Node} valueNode - TODO. - * @param {Node?} [storeNode=null] - TODO. + * @param {Node} pointerNode - An atomic variable or element of an atomic buffer. + * @param {Node} valueNode - The value that mutates the atomic variable. + * @param {Node?} [storeNode=null] - A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. * @returns {AtomicFunctionNode} */ const atomicAnd = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_AND, pointerNode, valueNode, storeNode ); /** - * TODO + * Stores in an atomic variable the bitwise OR of its value with a parameter. * * @function - * @param {Node} pointerNode - TODO. - * @param {Node} valueNode - TODO. - * @param {Node?} [storeNode=null] - TODO. + * @param {Node} pointerNode - An atomic variable or element of an atomic buffer. + * @param {Node} valueNode - The value that mutates the atomic variable. + * @param {Node?} [storeNode=null] - A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. * @returns {AtomicFunctionNode} */ const atomicOr = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_OR, pointerNode, valueNode, storeNode ); /** - * TODO + * Stores in an atomic variable the bitwise XOR of its value with a parameter. * * @function - * @param {Node} pointerNode - TODO. - * @param {Node} valueNode - TODO. - * @param {Node?} [storeNode=null] - TODO. + * @param {Node} pointerNode - An atomic variable or element of an atomic buffer. + * @param {Node} valueNode - The value that mutates the atomic variable. + * @param {Node?} [storeNode=null] - A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. * @returns {AtomicFunctionNode} */ const atomicXor = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_XOR, pointerNode, valueNode, storeNode ); @@ -30428,7 +34264,7 @@ class ShadowBaseNode extends Node { } /** - * Setups the shadow position node which is by default the predefined TSL node object `shadowWorldPosition`. + * Setups the shadow position node which is by default the predefined TSL node object `shadowPositionWorld`. * * @param {(NodeBuilder|{Material})} object - A configuration object that must at least hold a material reference. */ @@ -30436,7 +34272,7 @@ class ShadowBaseNode extends Node { // Use assign inside an Fn() - shadowWorldPosition.assign( material.shadowPositionNode || positionWorld ); + shadowPositionWorld.assign( material.shadowPositionNode || positionWorld ); } @@ -30458,7 +34294,212 @@ class ShadowBaseNode extends Node { * * @type {Node} */ -const shadowWorldPosition = /*@__PURE__*/ vec3().toVar( 'shadowWorldPosition' ); +const shadowPositionWorld = /*@__PURE__*/ vec3().toVar( 'shadowPositionWorld' ); + +/** @module RendererUtils **/ + +/** + * Saves the state of the given renderer and stores it into the given state object. + * + * If not state object is provided, the function creates one. + * + * @function + * @param {Renderer} renderer - The renderer. + * @param {Object} [state={}] - The state. + * @return {Object} The state. + */ +function saveRendererState( renderer, state = {} ) { + + state.toneMapping = renderer.toneMapping; + state.toneMappingExposure = renderer.toneMappingExposure; + state.outputColorSpace = renderer.outputColorSpace; + state.renderTarget = renderer.getRenderTarget(); + state.activeCubeFace = renderer.getActiveCubeFace(); + state.activeMipmapLevel = renderer.getActiveMipmapLevel(); + state.renderObjectFunction = renderer.getRenderObjectFunction(); + state.pixelRatio = renderer.getPixelRatio(); + state.mrt = renderer.getMRT(); + state.clearColor = renderer.getClearColor( state.clearColor || new Color() ); + state.clearAlpha = renderer.getClearAlpha(); + state.autoClear = renderer.autoClear; + state.scissorTest = renderer.getScissorTest(); + + return state; + +} + +/** + * Saves the state of the given renderer and stores it into the given state object. + * Besides, the function also resets the state of the renderer to its default values. + * + * If not state object is provided, the function creates one. + * + * @function + * @param {Renderer} renderer - The renderer. + * @param {Object} [state={}] - The state. + * @return {Object} The state. + */ +function resetRendererState( renderer, state ) { + + state = saveRendererState( renderer, state ); + + renderer.setMRT( null ); + renderer.setRenderObjectFunction( null ); + renderer.setClearColor( 0x000000, 1 ); + renderer.autoClear = true; + + return state; + +} + +/** + * Restores the state of the given renderer from the given state object. + * + * @function + * @param {Renderer} renderer - The renderer. + * @param {Object} state - The state to restore. + */ +function restoreRendererState( renderer, state ) { + + renderer.toneMapping = state.toneMapping; + renderer.toneMappingExposure = state.toneMappingExposure; + renderer.outputColorSpace = state.outputColorSpace; + renderer.setRenderTarget( state.renderTarget, state.activeCubeFace, state.activeMipmapLevel ); + renderer.setRenderObjectFunction( state.renderObjectFunction ); + renderer.setPixelRatio( state.pixelRatio ); + renderer.setMRT( state.mrt ); + renderer.setClearColor( state.clearColor, state.clearAlpha ); + renderer.autoClear = state.autoClear; + renderer.setScissorTest( state.scissorTest ); + +} + +/** + * Saves the state of the given scene and stores it into the given state object. + * + * If not state object is provided, the function creates one. + * + * @function + * @param {Scene} scene - The scene. + * @param {Object} [state={}] - The state. + * @return {Object} The state. + */ +function saveSceneState( scene, state = {} ) { + + state.background = scene.background; + state.backgroundNode = scene.backgroundNode; + state.overrideMaterial = scene.overrideMaterial; + + return state; + +} + +/** + * Saves the state of the given scene and stores it into the given state object. + * Besides, the function also resets the state of the scene to its default values. + * + * If not state object is provided, the function creates one. + * + * @function + * @param {Scene} scene - The scene. + * @param {Object} [state={}] - The state. + * @return {Object} The state. + */ +function resetSceneState( scene, state ) { + + state = saveSceneState( scene, state ); + + scene.background = null; + scene.backgroundNode = null; + scene.overrideMaterial = null; + + return state; + +} + +/** + * Restores the state of the given scene from the given state object. + * + * @function + * @param {Scene} scene - The scene. + * @param {Object} state - The state to restore. + */ +function restoreSceneState( scene, state ) { + + scene.background = state.background; + scene.backgroundNode = state.backgroundNode; + scene.overrideMaterial = state.overrideMaterial; + +} + +/** + * Saves the state of the given renderer and scene and stores it into the given state object. + * + * If not state object is provided, the function creates one. + * + * @function + * @param {Renderer} renderer - The renderer. + * @param {Scene} scene - The scene. + * @param {Object} [state={}] - The state. + * @return {Object} The state. + */ +function saveRendererAndSceneState( renderer, scene, state = {} ) { + + state = saveRendererState( renderer, state ); + state = saveSceneState( scene, state ); + + return state; + +} + +/** + * Saves the state of the given renderer and scene and stores it into the given state object. + * Besides, the function also resets the state of the renderer and scene to its default values. + * + * If not state object is provided, the function creates one. + * + * @function + * @param {Renderer} renderer - The renderer. + * @param {Scene} scene - The scene. + * @param {Object} [state={}] - The state. + * @return {Object} The state. + */ +function resetRendererAndSceneState( renderer, scene, state ) { + + state = resetRendererState( renderer, state ); + state = resetSceneState( scene, state ); + + return state; + +} + +/** + * Restores the state of the given renderer and scene from the given state object. + * + * @function + * @param {Renderer} renderer - The renderer. + * @param {Scene} scene - The scene. + * @param {Object} state - The state to restore. + */ +function restoreRendererAndSceneState( renderer, scene, state ) { + + restoreRendererState( renderer, state ); + restoreSceneState( scene, state ); + +} + +var RendererUtils = /*#__PURE__*/Object.freeze({ + __proto__: null, + resetRendererAndSceneState: resetRendererAndSceneState, + resetRendererState: resetRendererState, + resetSceneState: resetSceneState, + restoreRendererAndSceneState: restoreRendererAndSceneState, + restoreRendererState: restoreRendererState, + restoreSceneState: restoreSceneState, + saveRendererAndSceneState: saveRendererAndSceneState, + saveRendererState: saveRendererState, + saveSceneState: saveSceneState +}); /** @module ShadowNode **/ @@ -30499,6 +34540,7 @@ const getShadowMaterial = ( light ) => { material.depthNode = depthNode; material.isShadowNodeMaterial = true; // Use to avoid other overrideMaterial override material.colorNode unintentionally when using material.shadowNode material.name = 'ShadowMaterial'; + material.fog = false; shadowMaterialLib.set( light, material ); @@ -30748,7 +34790,8 @@ const _shadowFilterLib = [ BasicShadowFilter, PCFShadowFilter, PCFSoftShadowFilt // -const _quadMesh$1 = /*@__PURE__*/ new QuadMesh(); +let _rendererState; +const _quadMesh = /*@__PURE__*/ new QuadMesh(); /** * Represents the default shadow implementation for lighting nodes. @@ -30991,7 +35034,7 @@ class ShadowNode extends ShadowBaseNode { const shadowIntensity = reference( 'intensity', 'float', shadow ).setGroup( renderGroup ); const normalBias = reference( 'normalBias', 'float', shadow ).setGroup( renderGroup ); - const shadowPosition = lightShadowMatrix( light ).mul( shadowWorldPosition.add( transformedNormalWorld.mul( normalBias ) ) ); + const shadowPosition = lightShadowMatrix( light ).mul( shadowPositionWorld.add( transformedNormalWorld.mul( normalBias ) ) ); const shadowCoord = this.setupShadowCoord( builder, shadowPosition ); // @@ -31095,22 +35138,27 @@ class ShadowNode extends ShadowBaseNode { const depthVersion = shadowMap.depthTexture.version; this._depthVersionCached = depthVersion; - const currentOverrideMaterial = scene.overrideMaterial; - - scene.overrideMaterial = getShadowMaterial( light ); - shadow.camera.layers.mask = camera.layers.mask; - const currentRenderTarget = renderer.getRenderTarget(); const currentRenderObjectFunction = renderer.getRenderObjectFunction(); + const currentMRT = renderer.getMRT(); + const useVelocity = currentMRT ? currentMRT.has( 'velocity' ) : false; - renderer.setMRT( null ); + _rendererState = resetRendererAndSceneState( renderer, scene, _rendererState ); + + scene.overrideMaterial = getShadowMaterial( light ); renderer.setRenderObjectFunction( ( object, scene, _camera, geometry, material, group, ...params ) => { if ( object.castShadow === true || ( object.receiveShadow && shadowType === VSMShadowMap ) ) { + if ( useVelocity ) { + + getDataFromObject( object ).useVelocity = true; + + } + object.onBeforeShadow( renderer, object, camera, shadow.camera, geometry, scene.overrideMaterial, group ); renderer.renderObject( object, scene, _camera, geometry, material, group, ...params ); @@ -31135,11 +35183,7 @@ class ShadowNode extends ShadowBaseNode { } - renderer.setRenderTarget( currentRenderTarget ); - - renderer.setMRT( currentMRT ); - - scene.overrideMaterial = currentOverrideMaterial; + restoreRendererAndSceneState( renderer, scene, _rendererState ); } @@ -31156,12 +35200,12 @@ class ShadowNode extends ShadowBaseNode { this.vsmShadowMapHorizontal.setSize( shadow.mapSize.width, shadow.mapSize.height ); renderer.setRenderTarget( this.vsmShadowMapVertical ); - _quadMesh$1.material = this.vsmMaterialVertical; - _quadMesh$1.render( renderer ); + _quadMesh.material = this.vsmMaterialVertical; + _quadMesh.render( renderer ); renderer.setRenderTarget( this.vsmShadowMapHorizontal ); - _quadMesh$1.material = this.vsmMaterialHorizontal; - _quadMesh$1.render( renderer ); + _quadMesh.material = this.vsmMaterialHorizontal; + _quadMesh.render( renderer ); } @@ -33634,6 +37678,7 @@ var TSL = /*#__PURE__*/Object.freeze({ expression: expression, faceDirection: faceDirection, faceForward: faceForward, + faceforward: faceforward, float: float, floor: floor, fog: fog, @@ -33673,6 +37718,7 @@ var TSL = /*#__PURE__*/Object.freeze({ instancedMesh: instancedMesh, int: int, inverseSqrt: inverseSqrt, + inversesqrt: inversesqrt, invocationLocalIndex: invocationLocalIndex, invocationSubgroupIndex: invocationSubgroupIndex, ior: ior, @@ -33708,7 +37754,7 @@ var TSL = /*#__PURE__*/Object.freeze({ mat3: mat3, mat4: mat4, matcapUV: matcapUV, - materialAOMap: materialAOMap, + materialAO: materialAO, materialAlphaTest: materialAlphaTest, materialAnisotropy: materialAnisotropy, materialAnisotropyVector: materialAnisotropyVector, @@ -33891,7 +37937,7 @@ var TSL = /*#__PURE__*/Object.freeze({ setCurrentStack: setCurrentStack, shaderStages: shaderStages, shadow: shadow, - shadowWorldPosition: shadowWorldPosition, + shadowPositionWorld: shadowPositionWorld, sharedUniformGroup: sharedUniformGroup, sheen: sheen, sheenRoughness: sheenRoughness, @@ -33982,6 +38028,7 @@ var TSL = /*#__PURE__*/Object.freeze({ velocity: velocity, vertexColor: vertexColor, vertexIndex: vertexIndex, + vertexStage: vertexStage, vibrance: vibrance, viewZToLogarithmicDepth: viewZToLogarithmicDepth, viewZToOrthographicDepth: viewZToOrthographicDepth, @@ -34010,17 +38057,50 @@ var TSL = /*#__PURE__*/Object.freeze({ const _clearColor$1 = /*@__PURE__*/ new Color4(); +/** + * This renderer module manages the background. + * + * @private + * @augments DataMap + */ class Background extends DataMap { + /** + * Constructs a new background management component. + * + * @param {Renderer} renderer - The renderer. + * @param {Nodes} nodes - Renderer component for managing nodes related logic. + */ constructor( renderer, nodes ) { super(); + /** + * The renderer. + * + * @type {Renderer} + */ this.renderer = renderer; + + /** + * Renderer component for managing nodes related logic. + * + * @type {Nodes} + */ this.nodes = nodes; } + /** + * Updates the background for the given scene. Depending on how `Scene.background` + * or `Scene.backgroundNode` are configured, this method might configure a simple clear + * or add a mesh to the render list for rendering the background as a textured plane + * or skybox. + * + * @param {Scene} scene - The scene. + * @param {RenderList} renderList - The current render list. + * @param {RenderContext} renderContext - The current render context. + */ update( scene, renderList, renderContext ) { const renderer = this.renderer; @@ -34152,50 +38232,187 @@ class Background extends DataMap { let _id$6 = 0; +/** + * A bind group represents a collection of bindings and thus a collection + * or resources. Bind groups are assigned to pipelines to provide them + * with the required resources (like uniform buffers or textures). + * + * @private + */ class BindGroup { + /** + * Constructs a new bind group. + * + * @param {String} name - The bind group's name. + * @param {Array} bindings - An array of bindings. + * @param {Number} index - The group index. + * @param {Array} bindingsReference - An array of reference bindings. + */ constructor( name = '', bindings = [], index = 0, bindingsReference = [] ) { + /** + * The bind group's name. + * + * @type {String} + */ this.name = name; + + /** + * An array of bindings. + * + * @type {Array} + */ this.bindings = bindings; + + /** + * The group index. + * + * @type {Number} + */ this.index = index; + + /** + * An array of reference bindings. + * + * @type {Array} + */ this.bindingsReference = bindingsReference; + /** + * The group's ID. + * + * @type {Number} + */ this.id = _id$6 ++; } } +/** + * This module represents the state of a node builder after it was + * used to build the nodes for a render object. The state holds the + * results of the build for further processing in the renderer. + * + * Render objects with identical cache keys share the same node builder state. + * + * @private + */ class NodeBuilderState { + /** + * Constructs a new node builder state. + * + * @param {String?} vertexShader - The native vertex shader code. + * @param {String?} fragmentShader - The native fragment shader code. + * @param {String?} computeShader - The native compute shader code. + * @param {Array} nodeAttributes - An array of node attributes. + * @param {Array} bindings - An array of bind groups. + * @param {Array} updateNodes - An array of nodes that implement their `update()` method. + * @param {Array} updateBeforeNodes - An array of nodes that implement their `updateBefore()` method. + * @param {Array} updateAfterNodes - An array of nodes that implement their `updateAfter()` method. + * @param {NodeMaterialObserver} monitor - A node material observer. + * @param {Array} transforms - An array with transform attribute objects. Only relevant when using compute shaders with WebGL 2. + */ constructor( vertexShader, fragmentShader, computeShader, nodeAttributes, bindings, updateNodes, updateBeforeNodes, updateAfterNodes, monitor, transforms = [] ) { + /** + * The native vertex shader code. + * + * @type {String} + */ this.vertexShader = vertexShader; + + /** + * The native fragment shader code. + * + * @type {String} + */ this.fragmentShader = fragmentShader; + + /** + * The native compute shader code. + * + * @type {String} + */ this.computeShader = computeShader; + + /** + * An array with transform attribute objects. + * Only relevant when using compute shaders with WebGL 2. + * + * @type {Array} + */ this.transforms = transforms; + /** + * An array of node attributes representing + * the attributes of the shaders. + * + * @type {Array} + */ this.nodeAttributes = nodeAttributes; + + /** + * An array of bind groups representing the uniform or storage + * buffers, texture or samplers of the shader. + * + * @type {Array} + */ this.bindings = bindings; + /** + * An array of nodes that implement their `update()` method. + * + * @type {Array} + */ this.updateNodes = updateNodes; + + /** + * An array of nodes that implement their `updateBefore()` method. + * + * @type {Array} + */ this.updateBeforeNodes = updateBeforeNodes; + + /** + * An array of nodes that implement their `updateAfter()` method. + * + * @type {Array} + */ this.updateAfterNodes = updateAfterNodes; + /** + * A node material observer. + * + * @type {NodeMaterialObserver} + */ this.monitor = monitor; + /** + * How often this state is used by render objects. + * + * @type {Number} + */ this.usedTimes = 0; } + /** + * This method is used to create a array of bind groups based + * on the existing bind groups of this state. Shared groups are + * not cloned. + * + * @return {Array} A array of bind groups. + */ createBindings() { const bindings = []; for ( const instanceGroup of this.bindings ) { - const shared = instanceGroup.bindings[ 0 ].groupNode.shared; + const shared = instanceGroup.bindings[ 0 ].groupNode.shared; // TODO: Is it safe to always check the first binding in the group? if ( shared !== true ) { @@ -34631,26 +38848,79 @@ class StructTypeNode extends Node { } +/** + * Abstract base class for uniforms. + * + * @abstract + * @private + */ class Uniform { + /** + * Constructs a new uniform. + * + * @param {String} name - The uniform's name. + * @param {Any} value - The uniform's value. + */ constructor( name, value ) { + /** + * The uniform's name. + * + * @type {String} + */ this.name = name; + + /** + * The uniform's value. + * + * @type {Any} + */ this.value = value; - this.boundary = 0; // used to build the uniform buffer according to the STD140 layout + /** + * Used to build the uniform buffer according to the STD140 layout. + * Derived uniforms will set this property to a data type specific + * value. + * + * @type {Number} + */ + this.boundary = 0; + + /** + * The item size. Derived uniforms will set this property to a data + * type specific value. + * + * @type {Number} + */ this.itemSize = 0; - this.offset = 0; // this property is set by WebGPUUniformsGroup and marks the start position in the uniform buffer + /** + * This property is set by {@link UniformsGroup} and marks + * the start position in the uniform buffer. + * + * @type {Number} + */ + this.offset = 0; } + /** + * Sets the uniform's value. + * + * @param {Any} value - The value to set. + */ setValue( value ) { this.value = value; } + /** + * Returns the uniform's value. + * + * @return {Any} The value. + */ getValue() { return this.value; @@ -34659,12 +38929,31 @@ class Uniform { } +/** + * Represents a Number uniform. + * + * @private + * @augments Uniform + */ class NumberUniform extends Uniform { + /** + * Constructs a new Number uniform. + * + * @param {String} name - The uniform's name. + * @param {Number} value - The uniform's value. + */ constructor( name, value = 0 ) { super( name, value ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isNumberUniform = true; this.boundary = 4; @@ -34674,12 +38963,31 @@ class NumberUniform extends Uniform { } +/** + * Represents a Vector2 uniform. + * + * @private + * @augments Uniform + */ class Vector2Uniform extends Uniform { + /** + * Constructs a new Number uniform. + * + * @param {String} name - The uniform's name. + * @param {Vector2} value - The uniform's value. + */ constructor( name, value = new Vector2() ) { super( name, value ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isVector2Uniform = true; this.boundary = 8; @@ -34689,12 +38997,31 @@ class Vector2Uniform extends Uniform { } +/** + * Represents a Vector3 uniform. + * + * @private + * @augments Uniform + */ class Vector3Uniform extends Uniform { + /** + * Constructs a new Number uniform. + * + * @param {String} name - The uniform's name. + * @param {Vector3} value - The uniform's value. + */ constructor( name, value = new Vector3() ) { super( name, value ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isVector3Uniform = true; this.boundary = 16; @@ -34704,12 +39031,31 @@ class Vector3Uniform extends Uniform { } +/** + * Represents a Vector4 uniform. + * + * @private + * @augments Uniform + */ class Vector4Uniform extends Uniform { + /** + * Constructs a new Number uniform. + * + * @param {String} name - The uniform's name. + * @param {Vector4} value - The uniform's value. + */ constructor( name, value = new Vector4() ) { super( name, value ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isVector4Uniform = true; this.boundary = 16; @@ -34719,12 +39065,31 @@ class Vector4Uniform extends Uniform { } +/** + * Represents a Color uniform. + * + * @private + * @augments Uniform + */ class ColorUniform extends Uniform { + /** + * Constructs a new Number uniform. + * + * @param {String} name - The uniform's name. + * @param {Color} value - The uniform's value. + */ constructor( name, value = new Color() ) { super( name, value ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isColorUniform = true; this.boundary = 16; @@ -34734,12 +39099,31 @@ class ColorUniform extends Uniform { } +/** + * Represents a Matrix3 uniform. + * + * @private + * @augments Uniform + */ class Matrix3Uniform extends Uniform { + /** + * Constructs a new Number uniform. + * + * @param {String} name - The uniform's name. + * @param {Matrix3} value - The uniform's value. + */ constructor( name, value = new Matrix3() ) { super( name, value ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMatrix3Uniform = true; this.boundary = 48; @@ -34749,12 +39133,31 @@ class Matrix3Uniform extends Uniform { } +/** + * Represents a Matrix4 uniform. + * + * @private + * @augments Uniform + */ class Matrix4Uniform extends Uniform { + /** + * Constructs a new Number uniform. + * + * @param {String} name - The uniform's name. + * @param {Matrix4} value - The uniform's value. + */ constructor( name, value = new Matrix4() ) { super( name, value ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMatrix4Uniform = true; this.boundary = 64; @@ -34764,22 +39167,49 @@ class Matrix4Uniform extends Uniform { } +/** + * A special form of Number uniform binding type. + * It's value is managed by a node object. + * + * @private + * @augments NumberUniform + */ class NumberNodeUniform extends NumberUniform { + /** + * Constructs a new node-based Number uniform. + * + * @param {NodeUniform} nodeUniform - The node uniform. + */ constructor( nodeUniform ) { super( nodeUniform.name, nodeUniform.value ); + /** + * The node uniform. + * + * @type {NodeUniform} + */ this.nodeUniform = nodeUniform; } + /** + * Overwritten to return the value of the node uniform. + * + * @return {Number} The value. + */ getValue() { return this.nodeUniform.value; } + /** + * Returns the node uniform data type. + * + * @return {String} The data type. + */ getType() { return this.nodeUniform.type; @@ -34788,22 +39218,49 @@ class NumberNodeUniform extends NumberUniform { } +/** + * A special form of Vector2 uniform binding type. + * It's value is managed by a node object. + * + * @private + * @augments Vector2Uniform + */ class Vector2NodeUniform extends Vector2Uniform { + /** + * Constructs a new node-based Vector2 uniform. + * + * @param {NodeUniform} nodeUniform - The node uniform. + */ constructor( nodeUniform ) { super( nodeUniform.name, nodeUniform.value ); + /** + * The node uniform. + * + * @type {NodeUniform} + */ this.nodeUniform = nodeUniform; } + /** + * Overwritten to return the value of the node uniform. + * + * @return {Vector2} The value. + */ getValue() { return this.nodeUniform.value; } + /** + * Returns the node uniform data type. + * + * @return {String} The data type. + */ getType() { return this.nodeUniform.type; @@ -34812,22 +39269,49 @@ class Vector2NodeUniform extends Vector2Uniform { } +/** + * A special form of Vector3 uniform binding type. + * It's value is managed by a node object. + * + * @private + * @augments Vector3Uniform + */ class Vector3NodeUniform extends Vector3Uniform { + /** + * Constructs a new node-based Vector3 uniform. + * + * @param {NodeUniform} nodeUniform - The node uniform. + */ constructor( nodeUniform ) { super( nodeUniform.name, nodeUniform.value ); + /** + * The node uniform. + * + * @type {NodeUniform} + */ this.nodeUniform = nodeUniform; } + /** + * Overwritten to return the value of the node uniform. + * + * @return {Vector3} The value. + */ getValue() { return this.nodeUniform.value; } + /** + * Returns the node uniform data type. + * + * @return {String} The data type. + */ getType() { return this.nodeUniform.type; @@ -34836,22 +39320,49 @@ class Vector3NodeUniform extends Vector3Uniform { } +/** + * A special form of Vector4 uniform binding type. + * It's value is managed by a node object. + * + * @private + * @augments Vector4Uniform + */ class Vector4NodeUniform extends Vector4Uniform { + /** + * Constructs a new node-based Vector4 uniform. + * + * @param {NodeUniform} nodeUniform - The node uniform. + */ constructor( nodeUniform ) { super( nodeUniform.name, nodeUniform.value ); + /** + * The node uniform. + * + * @type {NodeUniform} + */ this.nodeUniform = nodeUniform; } + /** + * Overwritten to return the value of the node uniform. + * + * @return {Vector4} The value. + */ getValue() { return this.nodeUniform.value; } + /** + * Returns the node uniform data type. + * + * @return {String} The data type. + */ getType() { return this.nodeUniform.type; @@ -34860,22 +39371,49 @@ class Vector4NodeUniform extends Vector4Uniform { } +/** + * A special form of Color uniform binding type. + * It's value is managed by a node object. + * + * @private + * @augments ColorUniform + */ class ColorNodeUniform extends ColorUniform { + /** + * Constructs a new node-based Color uniform. + * + * @param {NodeUniform} nodeUniform - The node uniform. + */ constructor( nodeUniform ) { super( nodeUniform.name, nodeUniform.value ); + /** + * The node uniform. + * + * @type {NodeUniform} + */ this.nodeUniform = nodeUniform; } + /** + * Overwritten to return the value of the node uniform. + * + * @return {Color} The value. + */ getValue() { return this.nodeUniform.value; } + /** + * Returns the node uniform data type. + * + * @return {String} The data type. + */ getType() { return this.nodeUniform.type; @@ -34884,22 +39422,49 @@ class ColorNodeUniform extends ColorUniform { } +/** + * A special form of Matrix3 uniform binding type. + * It's value is managed by a node object. + * + * @private + * @augments Matrix3Uniform + */ class Matrix3NodeUniform extends Matrix3Uniform { + /** + * Constructs a new node-based Matrix3 uniform. + * + * @param {NodeUniform} nodeUniform - The node uniform. + */ constructor( nodeUniform ) { super( nodeUniform.name, nodeUniform.value ); + /** + * The node uniform. + * + * @type {NodeUniform} + */ this.nodeUniform = nodeUniform; } + /** + * Overwritten to return the value of the node uniform. + * + * @return {Matrix3} The value. + */ getValue() { return this.nodeUniform.value; } + /** + * Returns the node uniform data type. + * + * @return {String} The data type. + */ getType() { return this.nodeUniform.type; @@ -34908,22 +39473,49 @@ class Matrix3NodeUniform extends Matrix3Uniform { } +/** + * A special form of Matrix4 uniform binding type. + * It's value is managed by a node object. + * + * @private + * @augments Matrix4Uniform + */ class Matrix4NodeUniform extends Matrix4Uniform { + /** + * Constructs a new node-based Matrix4 uniform. + * + * @param {NodeUniform} nodeUniform - The node uniform. + */ constructor( nodeUniform ) { super( nodeUniform.name, nodeUniform.value ); + /** + * The node uniform. + * + * @type {NodeUniform} + */ this.nodeUniform = nodeUniform; } + /** + * Overwritten to return the value of the node uniform. + * + * @return {Matrix4} The value. + */ getValue() { return this.nodeUniform.value; } + /** + * Returns the node uniform data type. + * + * @return {String} The data type. + */ getType() { return this.nodeUniform.type; @@ -36229,6 +40821,15 @@ class NodeBuilder { } + /** + * Returns the output struct name which is required by + * {@link module:OutputStructNode}. + * + * @abstract + * @return {String} The name of the output struct. + */ + getOutputStructName() {} + /** * Returns a bind group for the given group name and binding. * @@ -36410,6 +41011,7 @@ class NodeBuilder { /** * It is used to add Nodes that will be used as FRAME and RENDER events, * and need to follow a certain sequence in the calls to work correctly. + * This function should be called after 'setup()' in the 'build()' process to ensure that the child nodes are processed first. * * @param {Node} node - The node to add. */ @@ -36763,10 +41365,11 @@ class NodeBuilder { * @param {Texture} texture - The texture. * @param {String} textureProperty - The texture property name. * @param {String} uvSnippet - Snippet defining the texture coordinates. + * @param {String?} depthSnippet - Snippet defining the 0-based texture array index to sample. * @param {String} levelSnippet - Snippet defining the mip level. * @return {String} The generated shader string. */ - generateTextureLod( /* texture, textureProperty, uvSnippet, levelSnippet */ ) { + generateTextureLod( /* texture, textureProperty, uvSnippet, depthSnippet, levelSnippet */ ) { console.warn( 'Abstract function.' ); @@ -36940,11 +41543,11 @@ class NodeBuilder { } /** - * Whether the given texture needs a conversion to working color space. + * Checks if the given texture requires a manual conversion to the working color space. * * @abstract * @param {Texture} texture - The texture to check. - * @return {Boolean} Whether a color space conversion is required or not. + * @return {Boolean} Whether the given texture requires a conversion to working color space or not. */ needsToWorkingColorSpace( /*texture*/ ) { @@ -39309,29 +43912,93 @@ class GLSLNodeParser extends NodeParser { } -const outputNodeMap = new WeakMap(); +const _outputNodeMap = new WeakMap(); +const _chainKeys$2 = []; +const _cacheKeyValues = []; +/** + * This renderer module manages node-related objects and is the + * primary interface between the renderer and the node system. + * + * @private + * @augments DataMap + */ class Nodes extends DataMap { + /** + * Constructs a new nodes management component. + * + * @param {Renderer} renderer - The renderer. + * @param {Backend} backend - The renderer's backend. + */ constructor( renderer, backend ) { super(); + /** + * The renderer. + * + * @type {Renderer} + */ this.renderer = renderer; + + /** + * The renderer's backend. + * + * @type {Backend} + */ this.backend = backend; + + /** + * The node frame. + * + * @type {Renderer} + */ this.nodeFrame = new NodeFrame(); + + /** + * A cache for managing node builder states. + * + * @type {Map} + */ this.nodeBuilderCache = new Map(); + + /** + * A cache for managing data cache key data. + * + * @type {ChainMap} + */ this.callHashCache = new ChainMap(); + + /** + * A cache for managing node uniforms group data. + * + * @type {ChainMap} + */ this.groupsData = new ChainMap(); + /** + * A cache for managing node objects of + * scene properties like fog or environments. + * + * @type {Object} + */ + this.cacheLib = {}; + } + /** + * Returns `true` if the given node uniforms group must be updated or not. + * + * @param {NodeUniformsGroup} nodeUniformsGroup - The node uniforms group. + * @return {Boolean} Whether the node uniforms group requires an update or not. + */ updateGroup( nodeUniformsGroup ) { const groupNode = nodeUniformsGroup.groupNode; const name = groupNode.name; - // objectGroup is every updated + // objectGroup is always updated if ( name === objectGroup.name ) return true; @@ -39375,10 +44042,13 @@ class Nodes extends DataMap { // other groups are updated just when groupNode.needsUpdate is true - const groupChain = [ groupNode, nodeUniformsGroup ]; + _chainKeys$2[ 0 ] = groupNode; + _chainKeys$2[ 1 ] = nodeUniformsGroup; + + let groupData = this.groupsData.get( _chainKeys$2 ); + if ( groupData === undefined ) this.groupsData.set( _chainKeys$2, groupData = {} ); - let groupData = this.groupsData.get( groupChain ); - if ( groupData === undefined ) this.groupsData.set( groupChain, groupData = {} ); + _chainKeys$2.length = 0; if ( groupData.version !== groupNode.version ) { @@ -39392,12 +44062,24 @@ class Nodes extends DataMap { } + /** + * Returns the cache key for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @return {Number} The cache key. + */ getForRenderCacheKey( renderObject ) { return renderObject.initialCacheKey; } + /** + * Returns a node builder state for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @return {NodeBuilderState} The node builder state. + */ getForRender( renderObject ) { const renderObjectData = this.get( renderObject ); @@ -39441,6 +44123,12 @@ class Nodes extends DataMap { } + /** + * Deletes the given object from the internal data map + * + * @param {Any} object - The object to delete. + * @return {Object?} The deleted dictionary. + */ delete( object ) { if ( object.isRenderObject ) { @@ -39460,6 +44148,12 @@ class Nodes extends DataMap { } + /** + * Returns a node builder state for the given compute node. + * + * @param {Node} computeNode - The compute node. + * @return {NodeBuilderState} The node builder state. + */ getForCompute( computeNode ) { const computeData = this.get( computeNode ); @@ -39481,6 +44175,13 @@ class Nodes extends DataMap { } + /** + * Creates a node builder state for the given node builder. + * + * @private + * @param {NodeBuilder} nodeBuilder - The node builder. + * @return {NodeBuilderState} The node builder state. + */ _createNodeBuilderState( nodeBuilder ) { return new NodeBuilderState( @@ -39498,71 +44199,149 @@ class Nodes extends DataMap { } + /** + * Returns an environment node for the current configured + * scene environment. + * + * @param {Scene} scene - The scene. + * @return {Node} A node representing the current scene environment. + */ getEnvironmentNode( scene ) { - return scene.environmentNode || this.get( scene ).environmentNode || null; + this.updateEnvironment( scene ); + + let environmentNode = null; + + if ( scene.environmentNode && scene.environmentNode.isNode ) { + + environmentNode = scene.environmentNode; + + } else { + + const sceneData = this.get( scene ); + + if ( sceneData.environmentNode ) { + + environmentNode = sceneData.environmentNode; + + } + + } + + return environmentNode; } + /** + * Returns a background node for the current configured + * scene background. + * + * @param {Scene} scene - The scene. + * @return {Node} A node representing the current scene background. + */ getBackgroundNode( scene ) { - return scene.backgroundNode || this.get( scene ).backgroundNode || null; + this.updateBackground( scene ); + + let backgroundNode = null; + + if ( scene.backgroundNode && scene.backgroundNode.isNode ) { + + backgroundNode = scene.backgroundNode; + + } else { + + const sceneData = this.get( scene ); + + if ( sceneData.backgroundNode ) { + + backgroundNode = sceneData.backgroundNode; + + } + + } + + return backgroundNode; } + /** + * Returns a fog node for the current configured scene fog. + * + * @param {Scene} scene - The scene. + * @return {Node} A node representing the current scene fog. + */ getFogNode( scene ) { + this.updateFog( scene ); + return scene.fogNode || this.get( scene ).fogNode || null; } + /** + * Returns a cache key for the given scene and lights node. + * This key is used by `RenderObject` as a part of the dynamic + * cache key (a key that must be checked every time the render + * objects is drawn). + * + * @param {Scene} scene - The scene. + * @param {LightsNode} lightsNode - The lights node. + * @return {Number} The cache key. + */ getCacheKey( scene, lightsNode ) { - const chain = [ scene, lightsNode ]; + _chainKeys$2[ 0 ] = scene; + _chainKeys$2[ 1 ] = lightsNode; + const callId = this.renderer.info.calls; - let cacheKeyData = this.callHashCache.get( chain ); + const cacheKeyData = this.callHashCache.get( _chainKeys$2 ) || {}; - if ( cacheKeyData === undefined || cacheKeyData.callId !== callId ) { + if ( cacheKeyData.callId !== callId ) { const environmentNode = this.getEnvironmentNode( scene ); const fogNode = this.getFogNode( scene ); - const values = []; + if ( lightsNode ) _cacheKeyValues.push( lightsNode.getCacheKey( true ) ); + if ( environmentNode ) _cacheKeyValues.push( environmentNode.getCacheKey() ); + if ( fogNode ) _cacheKeyValues.push( fogNode.getCacheKey() ); - if ( lightsNode ) values.push( lightsNode.getCacheKey( true ) ); - if ( environmentNode ) values.push( environmentNode.getCacheKey() ); - if ( fogNode ) values.push( fogNode.getCacheKey() ); + _cacheKeyValues.push( this.renderer.shadowMap.enabled ? 1 : 0 ); - values.push( this.renderer.shadowMap.enabled ? 1 : 0 ); + cacheKeyData.callId = callId; + cacheKeyData.cacheKey = hashArray( _cacheKeyValues ); - cacheKeyData = { - callId, - cacheKey: hashArray( values ) - }; + this.callHashCache.set( _chainKeys$2, cacheKeyData ); - this.callHashCache.set( chain, cacheKeyData ); + _cacheKeyValues.length = 0; } - return cacheKeyData.cacheKey; - - } - - updateScene( scene ) { + _chainKeys$2.length = 0; - this.updateEnvironment( scene ); - this.updateFog( scene ); - this.updateBackground( scene ); + return cacheKeyData.cacheKey; } + /** + * A boolean that indicates whether tone mapping should be enabled + * or not. + * + * @type {Boolean} + */ get isToneMappingState() { return this.renderer.getRenderTarget() ? false : true; } + /** + * If a scene background is configured, this method makes sure to + * represent the background with a corresponding node-based implementation. + * + * @param {Scene} scene - The scene. + */ updateBackground( scene ) { const sceneData = this.get( scene ); @@ -39574,41 +44353,43 @@ class Nodes extends DataMap { if ( sceneData.background !== background || forceUpdate ) { - let backgroundNode = null; + const backgroundNode = this.getCacheNode( 'background', background, () => { - if ( background.isCubeTexture === true || ( background.mapping === EquirectangularReflectionMapping || background.mapping === EquirectangularRefractionMapping || background.mapping === CubeUVReflectionMapping ) ) { + if ( background.isCubeTexture === true || ( background.mapping === EquirectangularReflectionMapping || background.mapping === EquirectangularRefractionMapping || background.mapping === CubeUVReflectionMapping ) ) { - if ( scene.backgroundBlurriness > 0 || background.mapping === CubeUVReflectionMapping ) { + if ( scene.backgroundBlurriness > 0 || background.mapping === CubeUVReflectionMapping ) { - backgroundNode = pmremTexture( background ); + return pmremTexture( background ); - } else { + } else { - let envMap; + let envMap; - if ( background.isCubeTexture === true ) { + if ( background.isCubeTexture === true ) { - envMap = cubeTexture( background ); + envMap = cubeTexture( background ); - } else { + } else { - envMap = texture( background ); + envMap = texture( background ); - } + } - backgroundNode = cubeMapNode( envMap ); + return cubeMapNode( envMap ); - } + } - } else if ( background.isTexture === true ) { + } else if ( background.isTexture === true ) { - backgroundNode = texture( background, screenUV.flipY() ).setUpdateMatrix( true ); + return texture( background, screenUV.flipY() ).setUpdateMatrix( true ); - } else if ( background.isColor !== true ) { + } else if ( background.isColor !== true ) { - console.error( 'WebGPUNodes: Unsupported background configuration.', background ); + console.error( 'WebGPUNodes: Unsupported background configuration.', background ); - } + } + + }, forceUpdate ); sceneData.backgroundNode = backgroundNode; sceneData.background = background; @@ -39625,6 +44406,39 @@ class Nodes extends DataMap { } + /** + * This method is part of the caching of nodes which are used to represents the + * scene's background, fog or environment. + * + * @param {String} type - The type of object to cache. + * @param {Object} object - The object. + * @param {Function} callback - A callback that produces a node representation for the given object. + * @param {Boolean} [forceUpdate=false] - Whether an update should be enforced or not. + * @return {Node} The node representation. + */ + getCacheNode( type, object, callback, forceUpdate = false ) { + + const nodeCache = this.cacheLib[ type ] || ( this.cacheLib[ type ] = new WeakMap() ); + + let node = nodeCache.get( object ); + + if ( node === undefined || forceUpdate ) { + + node = callback(); + nodeCache.set( object, node ); + + } + + return node; + + } + + /** + * If a scene fog is configured, this method makes sure to + * represent the fog with a corresponding node-based implementation. + * + * @param {Scene} scene - The scene. + */ updateFog( scene ) { const sceneData = this.get( scene ); @@ -39634,28 +44448,30 @@ class Nodes extends DataMap { if ( sceneData.fog !== sceneFog ) { - let fogNode = null; + const fogNode = this.getCacheNode( 'fog', sceneFog, () => { - if ( sceneFog.isFogExp2 ) { + if ( sceneFog.isFogExp2 ) { - const color = reference( 'color', 'color', sceneFog ).setGroup( renderGroup ); - const density = reference( 'density', 'float', sceneFog ).setGroup( renderGroup ); + const color = reference( 'color', 'color', sceneFog ).setGroup( renderGroup ); + const density = reference( 'density', 'float', sceneFog ).setGroup( renderGroup ); - fogNode = fog( color, densityFogFactor( density ) ); + return fog( color, densityFogFactor( density ) ); - } else if ( sceneFog.isFog ) { + } else if ( sceneFog.isFog ) { - const color = reference( 'color', 'color', sceneFog ).setGroup( renderGroup ); - const near = reference( 'near', 'float', sceneFog ).setGroup( renderGroup ); - const far = reference( 'far', 'float', sceneFog ).setGroup( renderGroup ); + const color = reference( 'color', 'color', sceneFog ).setGroup( renderGroup ); + const near = reference( 'near', 'float', sceneFog ).setGroup( renderGroup ); + const far = reference( 'far', 'float', sceneFog ).setGroup( renderGroup ); - fogNode = fog( color, rangeFogFactor( near, far ) ); + return fog( color, rangeFogFactor( near, far ) ); - } else { + } else { - console.error( 'WebGPUNodes: Unsupported fog configuration.', sceneFog ); + console.error( 'THREE.Renderer: Unsupported fog configuration.', sceneFog ); - } + } + + } ); sceneData.fogNode = fogNode; sceneData.fog = sceneFog; @@ -39671,6 +44487,12 @@ class Nodes extends DataMap { } + /** + * If a scene environment is configured, this method makes sure to + * represent the environment with a corresponding node-based implementation. + * + * @param {Scene} scene - The scene. + */ updateEnvironment( scene ) { const sceneData = this.get( scene ); @@ -39680,21 +44502,23 @@ class Nodes extends DataMap { if ( sceneData.environment !== environment ) { - let environmentNode = null; + const environmentNode = this.getCacheNode( 'environment', environment, () => { - if ( environment.isCubeTexture === true ) { + if ( environment.isCubeTexture === true ) { - environmentNode = cubeTexture( environment ); + return cubeTexture( environment ); - } else if ( environment.isTexture === true ) { + } else if ( environment.isTexture === true ) { - environmentNode = texture( environment ); + return texture( environment ); - } else { + } else { - console.error( 'Nodes: Unsupported environment configuration.', environment ); + console.error( 'Nodes: Unsupported environment configuration.', environment ); - } + } + + } ); sceneData.environmentNode = environmentNode; sceneData.environment = environment; @@ -39729,6 +44553,11 @@ class Nodes extends DataMap { } + /** + * Returns the current output cache key. + * + * @return {String} The output cache key. + */ getOutputCacheKey() { const renderer = this.renderer; @@ -39737,27 +44566,47 @@ class Nodes extends DataMap { } + /** + * Checks if the output configuration (tone mapping and color space) for + * the given target has changed. + * + * @param {Texture} outputTarget - The output target. + * @return {Boolean} Whether the output configuration has changed or not. + */ hasOutputChange( outputTarget ) { - const cacheKey = outputNodeMap.get( outputTarget ); + const cacheKey = _outputNodeMap.get( outputTarget ); return cacheKey !== this.getOutputCacheKey(); } - getOutputNode( outputTexture ) { + /** + * Returns a node that represents the output configuration (tone mapping and + * color space) for the current target. + * + * @param {Texture} outputTarget - The output target. + * @return {Node} The output node. + */ + getOutputNode( outputTarget ) { const renderer = this.renderer; const cacheKey = this.getOutputCacheKey(); - const output = texture( outputTexture, screenUV ).renderOutput( renderer.toneMapping, renderer.currentColorSpace ); + const output = texture( outputTarget, screenUV ).renderOutput( renderer.toneMapping, renderer.currentColorSpace ); - outputNodeMap.set( outputTexture, cacheKey ); + _outputNodeMap.set( outputTarget, cacheKey ); return output; } + /** + * Triggers the call of `updateBefore()` methods + * for all nodes of the given render object. + * + * @param {RenderObject} renderObject - The render object. + */ updateBefore( renderObject ) { const nodeBuilder = renderObject.getNodeBuilderState(); @@ -39772,6 +44621,12 @@ class Nodes extends DataMap { } + /** + * Triggers the call of `updateAfter()` methods + * for all nodes of the given render object. + * + * @param {RenderObject} renderObject - The render object. + */ updateAfter( renderObject ) { const nodeBuilder = renderObject.getNodeBuilderState(); @@ -39786,6 +44641,12 @@ class Nodes extends DataMap { } + /** + * Triggers the call of `update()` methods + * for all nodes of the given compute node. + * + * @param {Node} computeNode - The compute node. + */ updateForCompute( computeNode ) { const nodeFrame = this.getNodeFrame(); @@ -39799,6 +44660,12 @@ class Nodes extends DataMap { } + /** + * Triggers the call of `update()` methods + * for all nodes of the given compute node. + * + * @param {RenderObject} renderObject - The render object. + */ updateForRender( renderObject ) { const nodeFrame = this.getNodeFrameForRender( renderObject ); @@ -39812,6 +44679,12 @@ class Nodes extends DataMap { } + /** + * Returns `true` if the given render object requires a refresh. + * + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether the given render object requires a refresh or not. + */ needsRefresh( renderObject ) { const nodeFrame = this.getNodeFrameForRender( renderObject ); @@ -39821,12 +44694,16 @@ class Nodes extends DataMap { } + /** + * Frees the internal resources. + */ dispose() { super.dispose(); this.nodeFrame = new NodeFrame(); this.nodeBuilderCache = new Map(); + this.cacheLib = {}; } @@ -39834,41 +44711,110 @@ class Nodes extends DataMap { const _plane = /*@__PURE__*/ new Plane(); +/** + * Represents the state that is used to perform clipping via clipping planes. + * There is a default clipping context for each render context. When the + * scene holds instances of `ClippingGroup`, there will be a context for each + * group. + * + * @private + */ class ClippingContext { + /** + * Constructs a new clipping context. + * + * @param {ClippingContext?} [parentContext=null] - A reference to the parent clipping context. + */ constructor( parentContext = null ) { + /** + * The clipping context's version. + * + * @type {Number} + * @readonly + */ this.version = 0; + /** + * Whether the intersection of the clipping planes is used to clip objects, rather than their union. + * + * @type {Boolean?} + * @default null + */ this.clipIntersection = null; + + /** + * The clipping context's cache key. + * + * @type {String} + */ this.cacheKey = ''; + /** + * Whether the shadow pass is active or not. + * + * @type {Boolean} + * @default false + */ + this.shadowPass = false; - if ( parentContext === null ) { + /** + * The view normal matrix. + * + * @type {Matrix3} + */ + this.viewNormalMatrix = new Matrix3(); - this.intersectionPlanes = []; - this.unionPlanes = []; + /** + * Internal cache for maintaining clipping contexts. + * + * @type {WeakMap} + */ + this.clippingGroupContexts = new WeakMap(); - this.viewNormalMatrix = new Matrix3(); - this.clippingGroupContexts = new WeakMap(); + /** + * The intersection planes. + * + * @type {Array} + */ + this.intersectionPlanes = []; - this.shadowPass = false; + /** + * The intersection planes. + * + * @type {Array} + */ + this.unionPlanes = []; - } else { + /** + * The version of the clipping context's parent context. + * + * @type {Number?} + * @readonly + */ + this.parentVersion = null; + + if ( parentContext !== null ) { this.viewNormalMatrix = parentContext.viewNormalMatrix; this.clippingGroupContexts = parentContext.clippingGroupContexts; this.shadowPass = parentContext.shadowPass; - this.viewMatrix = parentContext.viewMatrix; } - this.parentVersion = null; - } + /** + * Projects the given source clipping planes and writes the result into the + * destination array. + * + * @param {Array} source - The source clipping planes. + * @param {Array} destination - The destination. + * @param {Number} offset - The offset. + */ projectPlanes( source, destination, offset ) { const l = source.length; @@ -39889,6 +44835,12 @@ class ClippingContext { } + /** + * Updates the root clipping context of a scene. + * + * @param {Scene} scene - The scene. + * @param {Camera} camera - The camera that is used to render the scene. + */ updateGlobal( scene, camera ) { this.shadowPass = ( scene.overrideMaterial !== null && scene.overrideMaterial.isShadowNodeMaterial ); @@ -39898,6 +44850,12 @@ class ClippingContext { } + /** + * Updates the clipping context. + * + * @param {ClippingContext} parentContext - The parent context. + * @param {ClippingGroup} clippingGroup - The clipping group this context belongs to. + */ update( parentContext, clippingGroup ) { let update = false; @@ -39969,6 +44927,12 @@ class ClippingContext { } + /** + * Returns a clipping context for the given clipping group. + * + * @param {ClippingGroup} clippingGroup - The clipping group. + * @return {ClippingContext} The clipping context. + */ getGroupContext( clippingGroup ) { if ( this.shadowPass && ! clippingGroup.clipShadows ) return this; @@ -39988,6 +44952,12 @@ class ClippingContext { } + /** + * The count of union clipping planes. + * + * @type {Number} + * @readonly + */ get unionClippingCount() { return this.unionPlanes.length; @@ -39996,67 +44966,141 @@ class ClippingContext { } +/** + * This module is used to represent render bundles inside the renderer + * for further processing. + * + * @private + */ class RenderBundle { - constructor( scene, camera ) { + /** + * Constructs a new bundle group. + * + * @param {BundleGroup} bundleGroup - The bundle group. + * @param {Camera} camera - The camera the bundle group is rendered with. + */ + constructor( bundleGroup, camera ) { - this.scene = scene; + this.bundleGroup = bundleGroup; this.camera = camera; } - clone() { - - return Object.assign( new this.constructor(), this ); - - } - } +const _chainKeys$1 = []; + +/** + * This renderer module manages render bundles. + * + * @private + */ class RenderBundles { + /** + * Constructs a new render bundle management component. + */ constructor() { - this.lists = new ChainMap(); + /** + * A chain map for maintaining the render bundles. + * + * @type {ChainMap} + */ + this.bundles = new ChainMap(); } - get( scene, camera ) { + /** + * Returns a render bundle for the given bundle group and camera. + * + * @param {BundleGroup} bundleGroup - The bundle group. + * @param {Camera} camera - The camera the bundle group is rendered with. + * @return {RenderBundle} The render bundle. + */ + get( bundleGroup, camera ) { - const lists = this.lists; - const keys = [ scene, camera ]; + const bundles = this.bundles; - let list = lists.get( keys ); + _chainKeys$1[ 0 ] = bundleGroup; + _chainKeys$1[ 1 ] = camera; - if ( list === undefined ) { + let bundle = bundles.get( _chainKeys$1 ); + + if ( bundle === undefined ) { - list = new RenderBundle( scene, camera ); - lists.set( keys, list ); + bundle = new RenderBundle( bundleGroup, camera ); + bundles.set( _chainKeys$1, bundle ); } - return list; + _chainKeys$1.length = 0; + + return bundle; } + /** + * Frees all internal resources. + */ dispose() { - this.lists = new ChainMap(); + this.bundles = new ChainMap(); } } +/** + * The purpose of a node library is to assign node implementations + * to existing library features. In `WebGPURenderer` lights, materials + * which are not based on `NodeMaterial` as well as tone mapping techniques + * are implemented with node-based modules. + * + * @private + */ class NodeLibrary { + /** + * Constructs a new node library. + */ constructor() { + /** + * A weak map that maps lights to light nodes. + * + * @type {WeakMap} + */ this.lightNodes = new WeakMap(); + + /** + * A map that maps materials to node materials. + * + * @type {WeakMap} + */ this.materialNodes = new Map(); + + /** + * A map that maps tone mapping techniques (constants) + * to tone mapping node functions. + * + * @type {WeakMap} + */ this.toneMappingNodes = new Map(); } + /** + * Returns a matching node material instance for the given material object. + * + * This method also assigns/copies the properties of the given material object + * to the node material. This is done to make sure the current material + * configuration carries over to the node version. + * + * @param {Material} material - A material. + * @return {NodeMaterial} The corresponding node material. + */ fromMaterial( material ) { if ( material.isNodeMaterial ) return material; @@ -40081,42 +45125,85 @@ class NodeLibrary { } + /** + * Adds a tone mapping node function for a tone mapping technique (constant). + * + * @param {Function} toneMappingNode - The tone mapping node function. + * @param {Number} toneMapping - The tone mapping. + */ addToneMapping( toneMappingNode, toneMapping ) { this.addType( toneMappingNode, toneMapping, this.toneMappingNodes ); } + /** + * Returns a tone mapping node function for a tone mapping technique (constant). + * + * @param {Number} toneMapping - The tone mapping. + * @return {Function?} The tone mapping node function. Returns `null` if no node function is found. + */ getToneMappingFunction( toneMapping ) { return this.toneMappingNodes.get( toneMapping ) || null; } + /** + * Returns a node material class definition for a material type. + * + * @param {String} materialType - The material type. + * @return {NodeMaterial.constructor?} The node material class definition. Returns `null` if no node material is found. + */ getMaterialNodeClass( materialType ) { return this.materialNodes.get( materialType ) || null; } + /** + * Adds a node material class definition for a given material type. + * + * @param {NodeMaterial.constructor} materialNodeClass - The node material class definition. + * @param {String} materialClassType - The material type. + */ addMaterial( materialNodeClass, materialClassType ) { this.addType( materialNodeClass, materialClassType, this.materialNodes ); } + /** + * Returns a light node class definition for a light class definition. + * + * @param {Light.constructor} light - The light class definition. + * @return {AnalyticLightNode.constructor?} The light node class definition. Returns `null` if no light node is found. + */ getLightNodeClass( light ) { return this.lightNodes.get( light ) || null; } + /** + * Adds a light node class definition for a given light class definition. + * + * @param {AnalyticLightNode.constructor} lightNodeClass - The light node class definition. + * @param {Light.constructor} lightClass - The light class definition. + */ addLight( lightNodeClass, lightClass ) { this.addClass( lightNodeClass, lightClass, this.lightNodes ); } + /** + * Adds a node class definition for the given type to the provided type library. + * + * @param {Any} nodeClass - The node class definition. + * @param {String} type - The object type. + * @param {Map} library - The type library. + */ addType( nodeClass, type, library ) { if ( library.has( type ) ) { @@ -40133,6 +45220,13 @@ class NodeLibrary { } + /** + * Adds a node class definition for the given class definition to the provided type library. + * + * @param {Any} nodeClass - The node class definition. + * @param {Any} baseClass - The class definition. + * @param {WeakMap} library - The type library. + */ addClass( nodeClass, baseClass, library ) { if ( library.has( baseClass ) ) { @@ -40152,46 +45246,76 @@ class NodeLibrary { } const _defaultLights = /*@__PURE__*/ new LightsNode(); +const _chainKeys = []; +/** + * This renderer module manages the lights nodes which are unique + * per scene and camera combination. + * + * The lights node itself is later configured in the render list + * with the actual lights from the scene. + * + * @private + * @augments ChainMap + */ class Lighting extends ChainMap { + /** + * Constructs a lighting management component. + */ constructor() { super(); } + /** + * Creates a new lights node for the given array of lights. + * + * @param {Array} lights - The render object. + * @return {Boolean} Whether if the given render object has an initialized geometry or not. + */ createNode( lights = [] ) { return new LightsNode().setLights( lights ); } + /** + * Returns a lights node for the given scene and camera. + * + * @param {Scene} scene - The scene. + * @param {Camera} camera - The camera. + * @return {LightsNode} The lights node. + */ getNode( scene, camera ) { // ignore post-processing if ( scene.isQuadMesh ) return _defaultLights; - // tiled lighting + _chainKeys[ 0 ] = scene; + _chainKeys[ 1 ] = camera; - const keys = [ scene, camera ]; - - let node = this.get( keys ); + let node = this.get( _chainKeys ); if ( node === undefined ) { node = this.createNode(); - this.set( keys, node ); + this.set( _chainKeys, node ); } + _chainKeys.length = 0; + return node; } } +/** @module Renderer **/ + const _scene = /*@__PURE__*/ new Scene(); const _drawingBufferSize = /*@__PURE__*/ new Vector2(); const _screen = /*@__PURE__*/ new Vector4(); @@ -40199,10 +45323,34 @@ const _frustum = /*@__PURE__*/ new Frustum(); const _projScreenMatrix = /*@__PURE__*/ new Matrix4(); const _vector4 = /*@__PURE__*/ new Vector4(); +/** + * Base class for renderers. + */ class Renderer { + /** + * Constructs a new renderer. + * + * @param {Backend} backend - The backend the renderer is targeting (e.g. WebGPU or WebGL 2). + * @param {Object} parameters - The configuration parameter. + * @param {Boolean} [parameters.logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not. + * @param {Boolean} [parameters.alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque. + * @param {Boolean} [parameters.depth=true] - Whether the default framebuffer should have a depth buffer or not. + * @param {Boolean} [parameters.stencil=false] - Whether the default framebuffer should have a stencil buffer or not. + * @param {Boolean} [parameters.antialias=false] - Whether MSAA as the default anti-aliasing should be enabled or not. + * @param {Number} [parameters.samples=0] - When `antialias` is `true`, `4` samples are used by default. This parameter can set to any other integer value than 0 + * to overwrite the default. + * @param {Function?} [parameters.getFallback=null] - This callback function can be used to provide a fallback backend, if the primary backend can't be targeted. + */ constructor( backend, parameters = {} ) { + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isRenderer = true; // @@ -40217,32 +45365,142 @@ class Renderer { getFallback = null } = parameters; - // public + /** + * A reference to the canvas element the renderer is drawing to. + * This value of this property will automatically be created by + * the renderer. + * + * @type {HTMLCanvasElement|OffscreenCanvas} + */ this.domElement = backend.getDomElement(); + /** + * A reference to the current backend. + * + * @type {Backend} + */ this.backend = backend; + /** + * The number of MSAA samples. + * + * @type {Number} + * @default 0 + */ this.samples = samples || ( antialias === true ) ? 4 : 0; + /** + * Whether the renderer should automatically clear the current rendering target + * before execute a `render()` call. The target can be the canvas (default framebuffer) + * or the current bound render target (custom framebuffer). + * + * @type {Boolean} + * @default true + */ this.autoClear = true; + + /** + * When `autoClear` is set to `true`, this property defines whether the renderer + * should clear the color buffer. + * + * @type {Boolean} + * @default true + */ this.autoClearColor = true; + + /** + * When `autoClear` is set to `true`, this property defines whether the renderer + * should clear the depth buffer. + * + * @type {Boolean} + * @default true + */ this.autoClearDepth = true; + + /** + * When `autoClear` is set to `true`, this property defines whether the renderer + * should clear the stencil buffer. + * + * @type {Boolean} + * @default true + */ this.autoClearStencil = true; + /** + * Whether the default framebuffer should be transparent or opaque. + * + * @type {Boolean} + * @default true + */ this.alpha = alpha; + /** + * Whether logarithmic depth buffer is enabled or not. + * + * @type {Boolean} + * @default false + */ this.logarithmicDepthBuffer = logarithmicDepthBuffer; + /** + * Defines the output color space of the renderer. + * + * @type {String} + * @default SRGBColorSpace + */ this.outputColorSpace = SRGBColorSpace; + /** + * Defines the tone mapping of the renderer. + * + * @type {Number} + * @default NoToneMapping + */ this.toneMapping = NoToneMapping; + + /** + * Defines the tone mapping exposure. + * + * @type {Number} + * @default 1 + */ this.toneMappingExposure = 1.0; + /** + * Whether the renderer should sort its render lists or not. + * + * Note: Sorting is used to attempt to properly render objects that have some degree of transparency. + * By definition, sorting objects may not work in all cases. Depending on the needs of application, + * it may be necessary to turn off sorting and use other methods to deal with transparency rendering + * e.g. manually determining each object's rendering order. + * + * @type {Boolean} + * @default true + */ this.sortObjects = true; + /** + * Whether the default framebuffer should have a depth buffer or not. + * + * @type {Boolean} + * @default true + */ this.depth = depth; + + /** + * Whether the default framebuffer should have a stencil buffer or not. + * + * @type {Boolean} + * @default false + */ this.stencil = stencil; + /** + * Holds a series of statistical information about the GPU memory + * and the rendering process. Useful for debugging and monitoring. + * + * @type {Boolean} + */ this.info = new Info(); this.nodes = { @@ -40250,82 +45508,449 @@ class Renderer { modelNormalViewMatrix: null }; + /** + * The node library defines how certain library objects like materials, lights + * or tone mapping functions are mapped to node types. This is required since + * although instances of classes like `MeshBasicMaterial` or `PointLight` can + * be part of the scene graph, they are internally represented as nodes for + * further processing. + * + * @type {NodeLibrary} + */ this.library = new NodeLibrary(); + + /** + * A map-like data structure for managing lights. + * + * @type {Lighting} + */ this.lighting = new Lighting(); // internals + /** + * This callback function can be used to provide a fallback backend, if the primary backend can't be targeted. + * + * @private + * @type {Function} + */ this._getFallback = getFallback; + /** + * The renderer's pixel ration. + * + * @private + * @type {Number} + * @default 1 + */ this._pixelRatio = 1; + + /** + * The width of the renderer's default framebuffer in logical pixel unit. + * + * @private + * @type {Number} + */ this._width = this.domElement.width; + + /** + * The height of the renderer's default framebuffer in logical pixel unit. + * + * @private + * @type {Number} + */ this._height = this.domElement.height; + /** + * The viewport of the renderer in logical pixel unit. + * + * @private + * @type {Vector4} + */ this._viewport = new Vector4( 0, 0, this._width, this._height ); + + /** + * The scissor rectangle of the renderer in logical pixel unit. + * + * @private + * @type {Vector4} + */ this._scissor = new Vector4( 0, 0, this._width, this._height ); + + /** + * Whether the scissor test should be enabled or not. + * + * @private + * @type {Vector4} + */ this._scissorTest = false; + /** + * A reference to a renderer module for managing shader attributes. + * + * @private + * @type {Attributes?} + * @default null + */ this._attributes = null; + + /** + * A reference to a renderer module for managing geometries. + * + * @private + * @type {Geometries?} + * @default null + */ this._geometries = null; + + /** + * A reference to a renderer module for managing node related logic. + * + * @private + * @type {Nodes?} + * @default null + */ this._nodes = null; + + /** + * A reference to a renderer module for managing the internal animation loop. + * + * @private + * @type {Animation?} + * @default null + */ this._animation = null; + + /** + * A reference to a renderer module for managing shader program bindings. + * + * @private + * @type {Bindings?} + * @default null + */ this._bindings = null; + + /** + * A reference to a renderer module for managing render objects. + * + * @private + * @type {RenderObjects?} + * @default null + */ this._objects = null; + + /** + * A reference to a renderer module for managing render and compute pipelines. + * + * @private + * @type {Pipelines?} + * @default null + */ this._pipelines = null; + + /** + * A reference to a renderer module for managing render bundles. + * + * @private + * @type {RenderBundles?} + * @default null + */ this._bundles = null; + + /** + * A reference to a renderer module for managing render lists. + * + * @private + * @type {RenderLists?} + * @default null + */ this._renderLists = null; + + /** + * A reference to a renderer module for managing render contexts. + * + * @private + * @type {RenderContexts?} + * @default null + */ this._renderContexts = null; + + /** + * A reference to a renderer module for managing textures. + * + * @private + * @type {Textures?} + * @default null + */ this._textures = null; + + /** + * A reference to a renderer module for backgrounds. + * + * @private + * @type {Background?} + * @default null + */ this._background = null; + /** + * This fullscreen quad is used for internal render passes + * like the tone mapping and color space output pass. + * + * @private + * @type {QuadMesh} + */ this._quad = new QuadMesh( new NodeMaterial() ); - this._quad.material.type = 'Renderer_output'; + this._quad.material.name = 'Renderer_output'; + /** + * A reference to the current render context. + * + * @private + * @type {RenderContext?} + * @default null + */ this._currentRenderContext = null; + /** + * A custom sort function for the opaque render list. + * + * @private + * @type {Function?} + * @default null + */ this._opaqueSort = null; + + /** + * A custom sort function for the transparent render list. + * + * @private + * @type {Function?} + * @default null + */ this._transparentSort = null; + /** + * The framebuffer target. + * + * @private + * @type {RenderTarget?} + * @default null + */ this._frameBufferTarget = null; const alphaClear = this.alpha === true ? 0 : 1; + /** + * The clear color value. + * + * @private + * @type {Color4} + */ this._clearColor = new Color4( 0, 0, 0, alphaClear ); + + /** + * The clear depth value. + * + * @private + * @type {Number} + * @default 1 + */ this._clearDepth = 1; + + /** + * The clear stencil value. + * + * @private + * @type {Number} + * @default 0 + */ this._clearStencil = 0; + /** + * The current render target. + * + * @private + * @type {RenderTarget?} + * @default null + */ this._renderTarget = null; + + /** + * The active cube face. + * + * @private + * @type {Number} + * @default 0 + */ this._activeCubeFace = 0; + + /** + * The active mipmap level. + * + * @private + * @type {Number} + * @default 0 + */ this._activeMipmapLevel = 0; + /** + * The MRT setting. + * + * @private + * @type {MRTNode?} + * @default null + */ this._mrt = null; + /** + * This function defines how a render object is going + * to be rendered. + * + * @private + * @type {Function?} + * @default null + */ this._renderObjectFunction = null; + + /** + * Used to keep track of the current render object function. + * + * @private + * @type {Function?} + * @default null + */ this._currentRenderObjectFunction = null; + + /** + * Used to keep track of the current render bundle. + * + * @private + * @type {RenderBundle?} + * @default null + */ this._currentRenderBundle = null; + /** + * Next to `_renderObjectFunction()`, this function provides another hook + * for influencing the render process of a render object. It is meant for internal + * use and only relevant for `compileAsync()` right now. Instead of using + * the default logic of `_renderObjectDirect()` which actually draws the render object, + * a different function might be used which performs no draw but just the node + * and pipeline updates. + * + * @private + * @type {Function?} + * @default null + */ this._handleObjectFunction = this._renderObjectDirect; + /** + * Indicates whether the device has been lost or not. In WebGL terms, the device + * lost is considered as a context lost. When this is set to `true`, rendering + * isn't possible anymore. + * + * @private + * @type {Boolean} + * @default false + */ this._isDeviceLost = false; + + /** + * A callback function that defines what should happen when a device/context lost occurs. + * + * @type {Function} + */ this.onDeviceLost = this._onDeviceLost; + /** + * Whether the renderer has been initialized or not. + * + * @private + * @type {Boolean} + * @default false + */ this._initialized = false; + + /** + * A reference to the promise which initializes the renderer. + * + * @private + * @type {Promise?} + * @default null + */ this._initPromise = null; + /** + * An array of compilation promises which are used in `compileAsync()`. + * + * @private + * @type {Array?} + * @default null + */ this._compilationPromises = null; + /** + * Whether the renderer should render transparent render objects or not. + * + * @type {Boolean} + * @default true + */ this.transparent = true; + + /** + * Whether the renderer should render opaque render objects or not. + * + * @type {Boolean} + * @default true + */ this.opaque = true; + /** + * Shadow map configuration + * @typedef {Object} ShadowMapConfig + * @property {Boolean} enabled - Whether to globally enable shadows or not. + * @property {Number} type - The shadow map type. + */ + + /** + * The renderer's shadow configuration. + * + * @type {module:Renderer~ShadowMapConfig} + */ this.shadowMap = { enabled: false, type: PCFShadowMap }; + /** + * XR configuration. + * @typedef {Object} XRConfig + * @property {Boolean} enabled - Whether to globally enable XR or not. + */ + + /** + * The renderer's XR configuration. + * + * @type {module:Renderer~XRConfig} + */ this.xr = { enabled: false }; + /** + * Debug configuration. + * @typedef {Object} DebugConfig + * @property {Boolean} checkShaderErrors - Whether shader errors should be checked or not. + * @property {Function} onShaderError - A callback function that is executed when a shader error happens. Only supported with WebGL 2 right now. + * @property {Function} getShaderAsync - Allows the get the raw shader code for the given scene, camera and 3D object. + */ + + /** + * The renderer's debug configuration. + * + * @type {module:Renderer~DebugConfig} + */ this.debug = { checkShaderErrors: true, onShaderError: null, @@ -40349,6 +45974,12 @@ class Renderer { } + /** + * Initializes the renderer so it is ready for usage. + * + * @async + * @return {Promise} A Promise that resolves when the renderer has been initialized. + */ async init() { if ( this._initialized ) { @@ -40424,12 +46055,35 @@ class Renderer { } + /** + * The coordinate system of the renderer. The value of this property + * depends on the selected backend. Either `THREE.WebGLCoordinateSystem` or + * `THREE.WebGPUCoordinateSystem`. + * + * @readonly + * @type {Number} + */ get coordinateSystem() { return this.backend.coordinateSystem; } + /** + * Compiles all materials in the given scene. This can be useful to avoid a + * phenomenon which is called "shader compilation stutter", which occurs when + * rendering an object with a new shader for the first time. + * + * If you want to add a 3D object to an existing scene, use the third optional + * parameter for applying the target scene. Note that the (target) scene's lighting + * and environment must be configured before calling this method. + * + * @async + * @param {Object3D} scene - The scene or 3D object to precompile. + * @param {Camera} camera - The camera that is used to render the scene. + * @param {Scene} targetScene - If the first argument is a 3D object, this parameter must represent the scene the 3D object is going to be added. + * @return {Promise} A Promise that resolves when the compile has been finished. + */ async compileAsync( scene, camera, targetScene = null ) { if ( this._isDeviceLost === true ) return; @@ -40526,10 +46180,6 @@ class Renderer { // - this._nodes.updateScene( sceneRef ); - - // - this._background.update( sceneRef, renderList, renderContext ); // process render lists @@ -40558,6 +46208,14 @@ class Renderer { } + /** + * Renders the scene in an async fashion. + * + * @async + * @param {Object3D} scene - The scene or 3D object to render. + * @param {Camera} camera - The camera. + * @return {Promise} A Promise that resolves when the render has been finished. + */ async renderAsync( scene, camera ) { if ( this._initialized === false ) await this.init(); @@ -40568,12 +46226,25 @@ class Renderer { } + /** + * Can be used to synchronize CPU operations with GPU tasks. So when this method is called, + * the CPU waits for the GPU to complete its operation (e.g. a compute task). + * + * @async + * @return {Promise} A Promise that resolves when synchronization has been finished. + */ async waitForGPU() { await this.backend.waitForGPU(); } + /** + * Sets the given MRT configuration. + * + * @param {MRTNode} mrt - The MRT node to set. + * @return {Renderer} A reference to this renderer. + */ setMRT( mrt ) { this._mrt = mrt; @@ -40582,12 +46253,23 @@ class Renderer { } + /** + * Returns the MRT configuration. + * + * @return {MRTNode} The MRT configuration. + */ getMRT() { return this._mrt; } + /** + * Default implementation of the device lost callback. + * + * @private + * @param {Object} info - Information about the context lost. + */ _onDeviceLost( info ) { let errorMessage = `THREE.WebGPURenderer: ${info.api} Device Lost:\n\nMessage: ${info.message}`; @@ -40604,7 +46286,14 @@ class Renderer { } - + /** + * Renders the given render bundle. + * + * @private + * @param {Object} bundle - Render bundle data. + * @param {Scene} sceneRef - The scene the render bundle belongs to. + * @param {LightsNode} lightsNode - The current lights node. + */ _renderBundle( bundle, sceneRef, lightsNode ) { const { bundleGroup, camera, renderList } = bundle; @@ -40676,6 +46365,18 @@ class Renderer { } + /** + * Renders the scene or 3D object with the given camera. This method can only be called + * if the renderer has been initialized. + * + * The target of the method is the default framebuffer (meaning the canvas) + * or alternatively a render target when specified via `setRenderTarget()`. + * + * @param {Object3D} scene - The scene or 3D object to render. + * @param {Camera} camera - The camera to render the scene with. + * @return {Promise?} A Promise that resolve when the scene has been rendered. + * Only returned when the renderer has not been initialized. + */ render( scene, camera ) { if ( this._initialized === false ) { @@ -40690,6 +46391,14 @@ class Renderer { } + /** + * Returns an internal render target which is used when computing the output tone mapping + * and color space conversion. Unlike in `WebGLRenderer`, this is done in a separate render + * pass and not inline to achieve more correct results. + * + * @private + * @return {RenderTarget?} The render target. The method returns `null` if no output conversion should be applied. + */ _getFrameBufferTarget() { const { currentToneMapping, currentColorSpace } = this; @@ -40737,6 +46446,15 @@ class Renderer { } + /** + * Renders the scene or 3D object with the given camera. + * + * @private + * @param {Object3D} scene - The scene or 3D object to render. + * @param {Camera} camera - The camera to render the scene with. + * @param {Boolean} [useFrameBufferTarget=true] - Whether to use a framebuffer target or not. + * @return {RenderContext} The current render context. + */ _renderScene( scene, camera, useFrameBufferTarget = true ) { if ( this._isDeviceLost === true ) return; @@ -40902,10 +46620,6 @@ class Renderer { // - this._nodes.updateScene( sceneRef ); - - // - this._background.update( sceneRef, renderList, renderContext ); // @@ -40966,24 +46680,48 @@ class Renderer { } + /** + * Returns the maximum available anisotropy for texture filtering. + * + * @return {Number} The maximum available anisotropy. + */ getMaxAnisotropy() { return this.backend.getMaxAnisotropy(); } + /** + * Returns the active cube face. + * + * @return {Number} The active cube face. + */ getActiveCubeFace() { return this._activeCubeFace; } + /** + * Returns the active mipmap level. + * + * @return {Number} The active mipmap level. + */ getActiveMipmapLevel() { return this._activeMipmapLevel; } + /** + * Applications are advised to always define the animation loop + * with this method and not manually with `requestAnimationFrame()` + * for best compatibility. + * + * @async + * @param {Function} callback - The application's animation loop. + * @return {Promise} A Promise that resolves when the set has been executed. + */ async setAnimationLoop( callback ) { if ( this._initialized === false ) await this.init(); @@ -40992,36 +46730,71 @@ class Renderer { } + /** + * Can be used to transfer buffer data from a storage buffer attribute + * from the GPU to the CPU in context of compute shaders. + * + * @async + * @param {StorageBufferAttribute} attribute - The storage buffer attribute. + * @return {Promise} A promise that resolves with the buffer data when the data are ready. + */ async getArrayBufferAsync( attribute ) { return await this.backend.getArrayBufferAsync( attribute ); } + /** + * Returns the rendering context. + * + * @return {GPUCanvasContext|WebGL2RenderingContext} The rendering context. + */ getContext() { return this.backend.getContext(); } + /** + * Returns the pixel ratio. + * + * @return {Number} The pixel ratio. + */ getPixelRatio() { return this._pixelRatio; } + /** + * Returns the drawing buffer size in physical pixels. This method honors the pixel ratio. + * + * @param {Vector2} target - The method writes the result in this target object. + * @return {Vector2} The drawing buffer size. + */ getDrawingBufferSize( target ) { return target.set( this._width * this._pixelRatio, this._height * this._pixelRatio ).floor(); } + /** + * Returns the renderer's size in logical pixels. This method does not honor the pixel ratio. + * + * @param {Vector2} target - The method writes the result in this target object. + * @return {Vector2} The drawing buffer size. + */ getSize( target ) { return target.set( this._width, this._height ); } + /** + * Sets the given pixel ration and resizes the canvas if necessary. + * + * @param {Number} [value=1] - The pixel ratio. + */ setPixelRatio( value = 1 ) { if ( this._pixelRatio === value ) return; @@ -41032,6 +46805,19 @@ class Renderer { } + /** + * This method allows to define the drawing buffer size by specifying + * width, height and pixel ratio all at once. The size of the drawing + * buffer is computed with this formula: + * ```` + * size.x = width * pixelRatio; + * size.y = height * pixelRatio; + *``` + * + * @param {Number} width - The width in logical pixels. + * @param {Number} height - The height in logical pixels. + * @param {Number} pixelRatio - The pixel ratio. + */ setDrawingBufferSize( width, height, pixelRatio ) { this._width = width; @@ -41048,6 +46834,13 @@ class Renderer { } + /** + * Sets the size of the renderer. + * + * @param {Number} width - The width in logical pixels. + * @param {Number} height - The height in logical pixels. + * @param {Boolean} [updateStyle=true] - Whether to update the `style` attribute of the canvas or not. + */ setSize( width, height, updateStyle = true ) { this._width = width; @@ -41069,18 +46862,36 @@ class Renderer { } + /** + * Defines a manual sort function for the opaque render list. + * Pass `null` to use the default sort. + * + * @param {Function} method - The sort function. + */ setOpaqueSort( method ) { this._opaqueSort = method; } + /** + * Defines a manual sort function for the transparent render list. + * Pass `null` to use the default sort. + * + * @param {Function} method - The sort function. + */ setTransparentSort( method ) { this._transparentSort = method; } + /** + * Returns the scissor rectangle. + * + * @param {Vector4} target - The method writes the result in this target object. + * @return {Vector4} The scissor rectangle. + */ getScissor( target ) { const scissor = this._scissor; @@ -41094,6 +46905,15 @@ class Renderer { } + /** + * Defines the scissor rectangle. + * + * @param {Number | Vector4} x - The horizontal coordinate for the lower left corner of the box in logical pixel unit. + * Instead of passing four arguments, the method also works with a single four-dimensional vector. + * @param {Number} y - The vertical coordinate for the lower left corner of the box in logical pixel unit. + * @param {Number} width - The width of the scissor box in logical pixel unit. + * @param {Number} height - The height of the scissor box in logical pixel unit. + */ setScissor( x, y, width, height ) { const scissor = this._scissor; @@ -41110,12 +46930,22 @@ class Renderer { } + /** + * Returns the scissor test value. + * + * @return {Boolean} Whether the scissor test should be enabled or not. + */ getScissorTest() { return this._scissorTest; } + /** + * Defines the scissor test. + * + * @param {Boolean} boolean - Whether the scissor test should be enabled or not. + */ setScissorTest( boolean ) { this._scissorTest = boolean; @@ -41124,12 +46954,28 @@ class Renderer { } + /** + * Returns the viewport definition. + * + * @param {Vector4} target - The method writes the result in this target object. + * @return {Vector4} The viewport definition. + */ getViewport( target ) { return target.copy( this._viewport ); } + /** + * Defines the viewport. + * + * @param {Number | Vector4} x - The horizontal coordinate for the lower left corner of the viewport origin in logical pixel unit. + * @param {Number} y - The vertical coordinate for the lower left corner of the viewport origin in logical pixel unit. + * @param {Number} width - The width of the viewport in logical pixel unit. + * @param {Number} height - The height of the viewport in logical pixel unit. + * @param {Number} minDepth - The minimum depth value of the viewport. WebGPU only. + * @param {Number} maxDepth - The maximum depth value of the viewport. WebGPU only. + */ setViewport( x, y, width, height, minDepth = 0, maxDepth = 1 ) { const viewport = this._viewport; @@ -41149,12 +46995,24 @@ class Renderer { } + /** + * Returns the clear color. + * + * @param {Color} target - The method writes the result in this target object. + * @return {Color} The clear color. + */ getClearColor( target ) { return target.copy( this._clearColor ); } + /** + * Defines the clear color and optionally the clear alpha. + * + * @param {Color} color - The clear color. + * @param {Number} [alpha=1] - The clear alpha. + */ setClearColor( color, alpha = 1 ) { this._clearColor.set( color ); @@ -41162,42 +47020,80 @@ class Renderer { } + /** + * Returns the clear alpha. + * + * @return {Number} The clear alpha. + */ getClearAlpha() { return this._clearColor.a; } + /** + * Defines the clear alpha. + * + * @param {Number} alpha - The clear alpha. + */ setClearAlpha( alpha ) { this._clearColor.a = alpha; } + /** + * Returns the clear depth. + * + * @return {Number} The clear depth. + */ getClearDepth() { return this._clearDepth; } + /** + * Defines the clear depth. + * + * @param {Number} depth - The clear depth. + */ setClearDepth( depth ) { this._clearDepth = depth; } + /** + * Returns the clear stencil. + * + * @return {Number} The clear stencil. + */ getClearStencil() { return this._clearStencil; } + /** + * Defines the clear stencil. + * + * @param {Number} stencil - The clear stencil. + */ setClearStencil( stencil ) { this._clearStencil = stencil; } + /** + * This method performs an occlusion query for the given 3D object. + * It returns `true` if the given 3D object is fully occluded by other + * 3D objects in the scene. + * + * @param {Object3D} object - The 3D object to test. + * @return {Boolean} Whether the 3D object is fully occluded or not. + */ isOccluded( object ) { const renderContext = this._currentRenderContext; @@ -41206,6 +47102,15 @@ class Renderer { } + /** + * Performs a manual clear operation. This method ignores `autoClear` properties. + * + * @param {Boolean} [color=true] - Whether the color buffer should be cleared or not. + * @param {Boolean} [depth=true] - Whether the depth buffer should be cleared or not. + * @param {Boolean} [stencil=true] - Whether the stencil buffer should be cleared or not. + * @return {Promise} A Promise that resolves when the clear operation has been executed. + * Only returned when the renderer has not been initialized. + */ clear( color = true, depth = true, stencil = true ) { if ( this._initialized === false ) { @@ -41218,17 +47123,26 @@ class Renderer { const renderTarget = this._renderTarget || this._getFrameBufferTarget(); - let renderTargetData = null; + let renderContext = null; if ( renderTarget !== null ) { this._textures.updateRenderTarget( renderTarget ); - renderTargetData = this._textures.get( renderTarget ); + const renderTargetData = this._textures.get( renderTarget ); + + renderContext = this._renderContexts.getForClear( renderTarget ); + renderContext.textures = renderTargetData.textures; + renderContext.depthTexture = renderTargetData.depthTexture; + renderContext.width = renderTargetData.width; + renderContext.height = renderTargetData.height; + renderContext.renderTarget = renderTarget; + renderContext.depth = renderTarget.depthBuffer; + renderContext.stencil = renderTarget.stencilBuffer; } - this.backend.clear( color, depth, stencil, renderTargetData ); + this.backend.clear( color, depth, stencil, renderContext ); if ( renderTarget !== null && this._renderTarget === null ) { @@ -41250,24 +47164,51 @@ class Renderer { } + /** + * Performs a manual clear operation of the color buffer. This method ignores `autoClear` properties. + * + * @return {Promise} A Promise that resolves when the clear operation has been executed. + * Only returned when the renderer has not been initialized. + */ clearColor() { return this.clear( true, false, false ); } + /** + * Performs a manual clear operation of the depth buffer. This method ignores `autoClear` properties. + * + * @return {Promise} A Promise that resolves when the clear operation has been executed. + * Only returned when the renderer has not been initialized. + */ clearDepth() { return this.clear( false, true, false ); } + /** + * Performs a manual clear operation of the stencil buffer. This method ignores `autoClear` properties. + * + * @return {Promise} A Promise that resolves when the clear operation has been executed. + * Only returned when the renderer has not been initialized. + */ clearStencil() { return this.clear( false, false, true ); } + /** + * Async version of {@link module:Renderer~Renderer#clear}. + * + * @async + * @param {Boolean} [color=true] - Whether the color buffer should be cleared or not. + * @param {Boolean} [depth=true] - Whether the depth buffer should be cleared or not. + * @param {Boolean} [stencil=true] - Whether the stencil buffer should be cleared or not. + * @return {Promise} A Promise that resolves when the clear operation has been executed. + */ async clearAsync( color = true, depth = true, stencil = true ) { if ( this._initialized === false ) await this.init(); @@ -41276,36 +47217,70 @@ class Renderer { } - clearColorAsync() { + /** + * Async version of {@link module:Renderer~Renderer#clearColor}. + * + * @async + * @return {Promise} A Promise that resolves when the clear operation has been executed. + */ + async clearColorAsync() { - return this.clearAsync( true, false, false ); + this.clearAsync( true, false, false ); } - clearDepthAsync() { + /** + * Async version of {@link module:Renderer~Renderer#clearDepth}. + * + * @async + * @return {Promise} A Promise that resolves when the clear operation has been executed. + */ + async clearDepthAsync() { - return this.clearAsync( false, true, false ); + this.clearAsync( false, true, false ); } - clearStencilAsync() { + /** + * Async version of {@link module:Renderer~Renderer#clearStencil}. + * + * @async + * @return {Promise} A Promise that resolves when the clear operation has been executed. + */ + async clearStencilAsync() { - return this.clearAsync( false, false, true ); + this.clearAsync( false, false, true ); } + /** + * The current output tone mapping of the renderer. When a render target is set, + * the output tone mapping is always `NoToneMapping`. + * + * @type {Number} + */ get currentToneMapping() { return this._renderTarget !== null ? NoToneMapping : this.toneMapping; } + /** + * The current output color space of the renderer. When a render target is set, + * the output color space is always `LinearSRGBColorSpace`. + * + * @type {String} + */ get currentColorSpace() { return this._renderTarget !== null ? LinearSRGBColorSpace : this.outputColorSpace; } + /** + * Frees all internal resources of the renderer. Call this method if the renderer + * is no longer in use by your app. + */ dispose() { this.info.dispose(); @@ -41325,6 +47300,15 @@ class Renderer { } + /** + * Sets the given render target. Calling this method means the renderer does not + * target the default framebuffer (meaning the canvas) anymore but a custom framebuffer. + * Use `null` as the first argument to reset the state. + * + * @param {RenderTarget?} renderTarget - The render target to set. + * @param {Number} [activeCubeFace=0] - The active cube face. + * @param {Number} [activeMipmapLevel=0] - The active mipmap level. + */ setRenderTarget( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) { this._renderTarget = renderTarget; @@ -41333,24 +47317,67 @@ class Renderer { } + /** + * Returns the current render target. + * + * @return {RenderTarget?} The render target. Returns `null` if no render target is set. + */ getRenderTarget() { return this._renderTarget; } + /** + * Callback for {@link module:Renderer~Renderer#setRenderObjectFunction}. + * + * @callback renderObjectFunction + * @param {Object3D} object - The 3D object. + * @param {Scene} scene - The scene the 3D object belongs to. + * @param {Camera} camera - The camera the object should be rendered with. + * @param {BufferGeometry} geometry - The object's geometry. + * @param {Material} material - The object's material. + * @param {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`. + * @param {LightsNode} lightsNode - The current lights node. + * @param {ClippingContext} clippingContext - The clipping context. + * @param {String?} [passId=null] - An optional ID for identifying the pass. + */ + + /** + * Sets the given render object function. Calling this method overwrites the default implementation + * which is {@link module:Renderer~Renderer#renderObject}. Defining a custom function can be useful + * if you want to modify the way objects are rendered. For example you can define things like "every + * object that has material of a certain type should perform a pre-pass with a special overwrite material". + * The custom function must always call `renderObject()` in its implementation. + * + * Use `null` as the first argument to reset the state. + * + * @param {module:Renderer~renderObjectFunction?} renderObjectFunction - The render object function. + */ setRenderObjectFunction( renderObjectFunction ) { this._renderObjectFunction = renderObjectFunction; } + /** + * Returns the current render object function. + * + * @return {Function?} The current render object function. Returns `null` if no function is set. + */ getRenderObjectFunction() { return this._renderObjectFunction; } + /** + * Execute a single or an array of compute nodes. This method can only be called + * if the renderer has been initialized. + * + * @param {Node|Array} computeNodes - The compute node(s). + * @return {Promise?} A Promise that resolve when the compute has finished. Only returned when the renderer has not been initialized. + */ compute( computeNodes ) { if ( this.isDeviceLost === true ) return; @@ -41442,6 +47469,13 @@ class Renderer { } + /** + * Execute a single or an array of compute nodes. + * + * @async + * @param {Node|Array} computeNodes - The compute node(s). + * @return {Promise?} A Promise that resolve when the compute has finished. + */ async computeAsync( computeNodes ) { if ( this._initialized === false ) await this.init(); @@ -41452,6 +47486,13 @@ class Renderer { } + /** + * Checks if the given feature is supported by the selected backend. + * + * @async + * @param {String} name - The feature's name. + * @return {Promise} A Promise that resolves with a bool that indicates whether the feature is supported or not. + */ async hasFeatureAsync( name ) { if ( this._initialized === false ) await this.init(); @@ -41460,6 +47501,13 @@ class Renderer { } + /** + * Checks if the given feature is supported by the selected backend. If the + * renderer has not been initialized, this method always returns `false`. + * + * @param {String} name - The feature's name. + * @return {Boolean} Whether the feature is supported or not. + */ hasFeature( name ) { if ( this._initialized === false ) { @@ -41474,12 +47522,25 @@ class Renderer { } + /** + * Returns `true` when the renderer has been initialized. + * + * @return {Boolean} Whether the renderer has been initialized or not. + */ hasInitialized() { return this._initialized; } + /** + * Initializes the given textures. Useful for preloading a texture rather than waiting until first render + * (which can cause noticeable lags due to decode and GPU upload overhead). + * + * @async + * @param {Texture} texture - The texture. + * @return {Promise} A Promise that resolves when the texture has been initialized. + */ async initTextureAsync( texture ) { if ( this._initialized === false ) await this.init(); @@ -41488,20 +47549,32 @@ class Renderer { } + /** + * Initializes the given textures. Useful for preloading a texture rather than waiting until first render + * (which can cause noticeable lags due to decode and GPU upload overhead). + * + * This method can only be used if the renderer has been initialized. + * + * @param {Texture} texture - The texture. + */ initTexture( texture ) { if ( this._initialized === false ) { console.warn( 'THREE.Renderer: .initTexture() called before the backend is initialized. Try using .initTextureAsync() instead.' ); - return false; - } this._textures.updateTexture( texture ); } + /** + * Copies the current bound framebuffer into the given texture. + * + * @param {FramebufferTexture} framebufferTexture - The texture. + * @param {Vector2|Vector4} rectangle - A two or four dimensional vector that defines the rectangular portion of the framebuffer that should be copied. + */ copyFramebufferToTexture( framebufferTexture, rectangle = null ) { if ( rectangle !== null ) { @@ -41559,6 +47632,15 @@ class Renderer { } + /** + * Copies data of source texture into a destination texture. + * + * @param {Texture} srcTexture - The source texture. + * @param {Texture} dstTexture - The destination texture. + * @param {Box2|Box3} [srcRegion=null] - A bounding box which describes the source region. Can be two or three-dimensional. + * @param {Vector2|Vector3} [dstPosition=null] - A vector that represents the origin of the destination region. Can be two or three-dimensional. + * @param {Number} level - The mipmap level to copy. + */ copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { this._textures.updateTexture( srcTexture ); @@ -41568,12 +47650,35 @@ class Renderer { } - readRenderTargetPixelsAsync( renderTarget, x, y, width, height, index = 0, faceIndex = 0 ) { + /** + * Reads pixel data from the given render target. + * + * @async + * @param {RenderTarget} renderTarget - The render target to read from. + * @param {Number} x - The `x` coordinate of the copy region's origin. + * @param {Number} y - The `y` coordinate of the copy region's origin. + * @param {Number} width - The width of the copy region. + * @param {Number} height - The height of the copy region. + * @param {Number} [textureIndex=0] - The texture index of a MRT render target. + * @param {Number} [faceIndex=0] - The active cube face index. + * @return {Promise} A Promise that resolves when the read has been finished. The resolve provides the read data as a typed array. + */ + async readRenderTargetPixelsAsync( renderTarget, x, y, width, height, textureIndex = 0, faceIndex = 0 ) { - return this.backend.copyTextureToBuffer( renderTarget.textures[ index ], x, y, width, height, faceIndex ); + return this.backend.copyTextureToBuffer( renderTarget.textures[ textureIndex ], x, y, width, height, faceIndex ); } + /** + * Analyzes the given 3D object's hierarchy and builds render lists from the + * processed hierarchy. + * + * @param {Object3D} object - The 3D object to process (usually a scene). + * @param {Camera} camera - The camera the object is rendered with. + * @param {Number} groupOrder - The group order is derived from the `renderOrder` of groups and is used to group 3D objects within groups. + * @param {RenderList} renderList - The current render list. + * @param {ClippingContext} clippingContext - The current clipping context. + */ _projectObject( object, camera, groupOrder, renderList, clippingContext ) { if ( object.visible === false ) return; @@ -41695,6 +47800,14 @@ class Renderer { } + /** + * Renders the given render bundles. + * + * @private + * @param {Array} bundles - Array with render bundle data. + * @param {Scene} sceneRef - The scene the render bundles belong to. + * @param {LightsNode} lightsNode - The current lights node. + */ _renderBundles( bundles, sceneRef, lightsNode ) { for ( const bundle of bundles ) { @@ -41705,6 +47818,16 @@ class Renderer { } + /** + * Renders the transparent objects from the given render lists. + * + * @private + * @param {Array} renderList - The transparent render list. + * @param {Array} doublePassList - The list of transparent objects which require a double pass (e.g. because of transmission). + * @param {Camera} camera - The camera the render list should be rendered with. + * @param {Scene} scene - The scene the render list belongs to. + * @param {LightsNode} lightsNode - The current lights node. + */ _renderTransparents( renderList, doublePassList, camera, scene, lightsNode ) { if ( doublePassList.length > 0 ) { @@ -41745,6 +47868,16 @@ class Renderer { } + /** + * Renders the objects from the given render list. + * + * @private + * @param {Array} renderList - The render list. + * @param {Camera} camera - The camera the render list should be rendered with. + * @param {Scene} scene - The scene the render list belongs to. + * @param {LightsNode} lightsNode - The current lights node. + * @param {String?} [passId=null] - An optional ID for identifying the pass. + */ _renderObjects( renderList, camera, scene, lightsNode, passId = null ) { // process renderable objects @@ -41795,6 +47928,20 @@ class Renderer { } + /** + * This method represents the default render object function that manages the render lifecycle + * of the object. + * + * @param {Object3D} object - The 3D object. + * @param {Scene} scene - The scene the 3D object belongs to. + * @param {Camera} camera - The camera the object should be rendered with. + * @param {BufferGeometry} geometry - The object's geometry. + * @param {Material} material - The object's material. + * @param {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`. + * @param {LightsNode} lightsNode - The current lights node. + * @param {ClippingContext} clippingContext - The clipping context. + * @param {String?} [passId=null] - An optional ID for identifying the pass. + */ renderObject( object, scene, camera, geometry, material, group, lightsNode, clippingContext = null, passId = null ) { let overridePositionNode; @@ -41890,6 +48037,20 @@ class Renderer { } + /** + * This method represents the default `_handleObjectFunction` implementation which creates + * a render object from the given data and performs the draw command with the selected backend. + * + * @private + * @param {Object3D} object - The 3D object. + * @param {Material} material - The object's material. + * @param {Scene} scene - The scene the 3D object belongs to. + * @param {Camera} camera - The camera the object should be rendered with. + * @param {LightsNode} lightsNode - The current lights node. + * @param {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`. + * @param {ClippingContext} clippingContext - The clipping context. + * @param {String?} [passId=null] - An optional ID for identifying the pass. + */ _renderObjectDirect( object, material, scene, camera, lightsNode, group, clippingContext, passId ) { const renderObject = this._objects.get( object, material, scene, camera, lightsNode, this._currentRenderContext, clippingContext, passId ); @@ -41921,7 +48082,7 @@ class Renderer { renderBundleData.renderObjects.push( renderObject ); - renderObject.bundle = this._currentRenderBundle.scene; + renderObject.bundle = this._currentRenderBundle.bundleGroup; } @@ -41931,6 +48092,20 @@ class Renderer { } + /** + * A different implementation for `_handleObjectFunction` which only makes sure the object is ready for rendering. + * Used in `compileAsync()`. + * + * @private + * @param {Object3D} object - The 3D object. + * @param {Material} material - The object's material. + * @param {Scene} scene - The scene the 3D object belongs to. + * @param {Camera} camera - The camera the object should be rendered with. + * @param {LightsNode} lightsNode - The current lights node. + * @param {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`. + * @param {ClippingContext} clippingContext - The clipping context. + * @param {String?} [passId=null] - An optional ID for identifying the pass. + */ _createObjectPipeline( object, material, scene, camera, lightsNode, group, clippingContext, passId ) { const renderObject = this._objects.get( object, material, scene, camera, lightsNode, this._currentRenderContext, clippingContext, passId ); @@ -41952,6 +48127,15 @@ class Renderer { } + /** + * Alias for `compileAsync()`. + * + * @method + * @param {Object3D} scene - The scene or 3D object to precompile. + * @param {Camera} camera - The camera that is used to render the scene. + * @param {Scene} targetScene - If the first argument is a 3D object, this parameter must represent the scene the 3D object is going to be added. + * @return {Promise} A Promise that resolves when the compile has been finished. + */ get compile() { return this.compileAsync; @@ -41960,22 +48144,57 @@ class Renderer { } +/** + * A binding represents the connection between a resource (like a texture, sampler + * or uniform buffer) and the resource definition in a shader stage. + * + * This module is an abstract base class for all concrete bindings types. + * + * @abstract + * @private + */ class Binding { + /** + * Constructs a new binding. + * + * @param {String} [name=''] - The binding's name. + */ constructor( name = '' ) { + /** + * The binding's name. + * + * @type {String} + */ this.name = name; + /** + * A bitmask that defines in what shader stages the + * binding's resource is accessible. + * + * @type {String} + */ this.visibility = 0; } + /** + * Makes sure binding's resource is visible for the given shader stage. + * + * @param {Number} visibility - The shader stage. + */ setVisibility( visibility ) { this.visibility |= visibility; } + /** + * Clones the binding. + * + * @return {Binding} The cloned binding. + */ clone() { return Object.assign( new this.constructor(), this ); @@ -41984,6 +48203,16 @@ class Binding { } +/** @module BufferUtils **/ + +/** + * This function is usually called with the length in bytes of an array buffer. + * It returns an padded value which ensure chunk size alignment according to STD140 layout. + * + * @function + * @param {Number} floatLength - The buffer length. + * @return {Number} The padded length. + */ function getFloatLength( floatLength ) { // ensure chunk size alignment (STD140 layout) @@ -41992,32 +48221,81 @@ function getFloatLength( floatLength ) { } +/** + * Represents a buffer binding type. + * + * @private + * @abstract + * @augments Binding + */ class Buffer extends Binding { + /** + * Constructs a new buffer. + * + * @param {String} name - The buffer's name. + * @param {TypedArray} [buffer=null] - The buffer. + */ constructor( name, buffer = null ) { super( name ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isBuffer = true; + /** + * The bytes per element. + * + * @type {Number} + */ this.bytesPerElement = Float32Array.BYTES_PER_ELEMENT; + /** + * A reference to the internal buffer. + * + * @private + * @type {TypedArray} + */ this._buffer = buffer; } + /** + * The buffer's byte length. + * + * @type {Number} + * @readonly + */ get byteLength() { return getFloatLength( this._buffer.byteLength ); } + /** + * A reference to the internal buffer. + * + * @type {Float32Array} + * @readonly + */ get buffer() { return this._buffer; } + /** + * Updates the binding. + * + * @return {Boolean} Whether the buffer has been updated and must be + * uploaded to the GPU. + */ update() { return true; @@ -42026,12 +48304,31 @@ class Buffer extends Binding { } +/** + * Represents a uniform buffer binding type. + * + * @private + * @augments Buffer + */ class UniformBuffer extends Buffer { + /** + * Constructs a new uniform buffer. + * + * @param {String} name - The buffer's name. + * @param {TypedArray} [buffer=null] - The buffer. + */ constructor( name, buffer = null ) { super( name, buffer ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isUniformBuffer = true; } @@ -42040,17 +48337,46 @@ class UniformBuffer extends Buffer { let _id$4 = 0; +/** + * A special form of uniform buffer binding type. + * It's buffer value is managed by a node object. + * + * @private + * @augments UniformBuffer + */ class NodeUniformBuffer extends UniformBuffer { + /** + * Constructs a new node-based uniform buffer. + * + * @param {BufferNode} nodeUniform - The uniform buffer node. + * @param {UniformGroupNode} groupNode - The uniform group node. + */ constructor( nodeUniform, groupNode ) { super( 'UniformBuffer_' + _id$4 ++, nodeUniform ? nodeUniform.value : null ); + /** + * The uniform buffer node. + * + * @type {BufferNode} + */ this.nodeUniform = nodeUniform; + + /** + * The uniform group node. + * + * @type {UniformGroupNode} + */ this.groupNode = groupNode; } + /** + * The uniform buffer. + * + * @type {Float32Array} + */ get buffer() { return this.nodeUniform.value; @@ -42059,22 +48385,59 @@ class NodeUniformBuffer extends UniformBuffer { } +/** + * This class represents a uniform buffer binding but with + * an API that allows to maintain individual uniform objects. + * + * @private + * @augments UniformBuffer + */ class UniformsGroup extends UniformBuffer { + /** + * Constructs a new uniforms group. + * + * @param {String} name - The group's name. + */ constructor( name ) { super( name ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isUniformsGroup = true; + /** + * An array with the raw uniform values. + * + * @private + * @type {Array?} + * @default null + */ this._values = null; - // the order of uniforms in this array must match the order of uniforms in the shader - + /** + * An array of uniform objects. + * + * The order of uniforms in this array must match the order of uniforms in the shader. + * + * @type {Array} + */ this.uniforms = []; } + /** + * Adds a uniform to this group. + * + * @param {Uniform} uniform - The uniform to add. + * @return {UniformsGroup} A reference to this group. + */ addUniform( uniform ) { this.uniforms.push( uniform ); @@ -42083,6 +48446,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Removes a uniform from this group. + * + * @param {Uniform} uniform - The uniform to remove. + * @return {UniformsGroup} A reference to this group. + */ removeUniform( uniform ) { const index = this.uniforms.indexOf( uniform ); @@ -42097,6 +48466,11 @@ class UniformsGroup extends UniformBuffer { } + /** + * An array with the raw uniform values. + * + * @type {Array} + */ get values() { if ( this._values === null ) { @@ -42109,6 +48483,11 @@ class UniformsGroup extends UniformBuffer { } + /** + * A Float32 array buffer with the uniform values. + * + * @type {Float32Array} + */ get buffer() { let buffer = this._buffer; @@ -42127,6 +48506,11 @@ class UniformsGroup extends UniformBuffer { } + /** + * The byte length of the buffer with correct buffer alignment. + * + * @type {Number} + */ get byteLength() { let offset = 0; // global buffer offset in bytes @@ -42168,6 +48552,15 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates this group by updating each uniform object of + * the internal uniform list. The uniform objects check if their + * values has actually changed so this method only returns + * `true` if there is a real value change. + * + * @return {Boolean} Whether the uniforms have been updated and + * must be uploaded to the GPU. + */ update() { let updated = false; @@ -42186,6 +48579,13 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given uniform by calling an update method matching + * the uniforms type. + * + * @param {Uniform} uniform - The uniform to update. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateByType( uniform ) { if ( uniform.isNumberUniform ) return this.updateNumber( uniform ); @@ -42200,6 +48600,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given Number uniform. + * + * @param {NumberUniform} uniform - The Number uniform. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateNumber( uniform ) { let updated = false; @@ -42222,6 +48628,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given Vector2 uniform. + * + * @param {Vector2Uniform} uniform - The Vector2 uniform. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateVector2( uniform ) { let updated = false; @@ -42246,6 +48658,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given Vector3 uniform. + * + * @param {Vector3Uniform} uniform - The Vector3 uniform. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateVector3( uniform ) { let updated = false; @@ -42271,6 +48689,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given Vector4 uniform. + * + * @param {Vector4Uniform} uniform - The Vector4 uniform. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateVector4( uniform ) { let updated = false; @@ -42297,6 +48721,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given Color uniform. + * + * @param {ColorUniform} uniform - The Color uniform. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateColor( uniform ) { let updated = false; @@ -42321,6 +48751,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given Matrix3 uniform. + * + * @param {Matrix3Uniform} uniform - The Matrix3 uniform. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateMatrix3( uniform ) { let updated = false; @@ -42353,6 +48789,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given Matrix4 uniform. + * + * @param {Matrix4Uniform} uniform - The Matrix4 uniform. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateMatrix4( uniform ) { let updated = false; @@ -42374,6 +48816,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Returns a typed array that matches the given data type. + * + * @param {String} type - The data type. + * @return {TypedArray} The typed array. + */ _getBufferForType( type ) { if ( type === 'int' || type === 'ivec2' || type === 'ivec3' || type === 'ivec4' ) return new Int32Array( this.buffer.buffer ); @@ -42384,6 +48832,14 @@ class UniformsGroup extends UniformBuffer { } +/** + * Sets the values of the second array to the first array. + * + * @private + * @param {TypedArray} a - The first array. + * @param {TypedArray} b - The second array. + * @param {Number} offset - An index offset for the first array. + */ function setArray( a, b, offset ) { for ( let i = 0, l = b.length; i < l; i ++ ) { @@ -42394,6 +48850,15 @@ function setArray( a, b, offset ) { } +/** + * Returns `true` if the given arrays are equal. + * + * @private + * @param {TypedArray} a - The first array. + * @param {TypedArray} b - The second array. + * @param {Number} offset - An index offset for the first array. + * @return {Boolean} Whether the given arrays are equal or not. + */ function arraysEqual( a, b, offset ) { for ( let i = 0, l = b.length; i < l; i ++ ) { @@ -42408,58 +48873,128 @@ function arraysEqual( a, b, offset ) { let _id$3 = 0; +/** + * A special form of uniforms group that represents + * the individual uniforms as node-based uniforms. + * + * @private + * @augments UniformsGroup + */ class NodeUniformsGroup extends UniformsGroup { + /** + * Constructs a new node-based uniforms group. + * + * @param {String} name - The group's name. + * @param {UniformGroupNode} groupNode - The uniform group node. + */ constructor( name, groupNode ) { super( name ); + /** + * The group's ID. + * + * @type {Number} + */ this.id = _id$3 ++; + + /** + * The uniform group node. + * + * @type {UniformGroupNode} + */ this.groupNode = groupNode; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isNodeUniformsGroup = true; } - getNodes() { - - const nodes = []; - - for ( const uniform of this.uniforms ) { - - const node = uniform.nodeUniform.node; - - if ( ! node ) throw new Error( 'NodeUniformsGroup: Uniform has no node.' ); - - nodes.push( node ); - - } - - return nodes; - - } - } let _id$2 = 0; +/** + * Represents a sampled texture binding type. + * + * @private + * @augments Binding + */ class SampledTexture extends Binding { + /** + * Constructs a new sampled texture. + * + * @param {String} name - The sampled texture's name. + * @param {Texture?} texture - The texture this binding is referring to. + */ constructor( name, texture ) { super( name ); + /** + * This identifier. + * + * @type {Number} + */ this.id = _id$2 ++; + /** + * The texture this binding is referring to. + * + * @type {Texture?} + */ this.texture = texture; + + /** + * The binding's version. + * + * @type {Number} + */ this.version = texture ? texture.version : 0; + + /** + * Whether the texture is a storage texture or not. + * + * @type {Boolean} + * @default false + */ this.store = false; + + /** + * The binding's generation which is an additional version + * qualifier. + * + * @type {Number?} + * @default null + */ this.generation = null; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isSampledTexture = true; } + /** + * Returns `true` whether this binding requires an update for the + * given generation. + * + * @param {Number} generation - The generation. + * @return {Boolean} Whether an update is required or not. + */ needsBindingsUpdate( generation ) { const { texture } = this; @@ -42476,6 +49011,13 @@ class SampledTexture extends Binding { } + /** + * Updates the binding. + * + * @param {Number} generation - The generation. + * @return {Boolean} Whether the texture has been updated and must be + * uploaded to the GPU. + */ update() { const { texture, version } = this; @@ -42494,25 +49036,70 @@ class SampledTexture extends Binding { } +/** + * A special form of sampled texture binding type. + * It's texture value is managed by a node object. + * + * @private + * @augments SampledTexture + */ class NodeSampledTexture extends SampledTexture { + /** + * Constructs a new node-based sampled texture. + * + * @param {String} name - The textures's name. + * @param {TextureNode} textureNode - The texture node. + * @param {UniformGroupNode} groupNode - The uniform group node. + * @param {String?} [access=null] - The access type. + */ constructor( name, textureNode, groupNode, access = null ) { super( name, textureNode ? textureNode.value : null ); + /** + * The texture node. + * + * @type {TextureNode} + */ this.textureNode = textureNode; + + /** + * The uniform group node. + * + * @type {UniformGroupNode} + */ this.groupNode = groupNode; + /** + * The access type. + * + * @type {String?} + * @default null + */ this.access = access; } + /** + * Overwrites the default to additionally check if the node value has changed. + * + * @param {Number} generation - The generation. + * @return {Boolean} Whether an update is required or not. + */ needsBindingsUpdate( generation ) { return this.textureNode.value !== this.texture || super.needsBindingsUpdate( generation ); } + /** + * Updates the binding. + * + * @param {Number} generation - The generation. + * @return {Boolean} Whether the texture has been updated and must be + * uploaded to the GPU. + */ update() { const { textureNode } = this; @@ -42531,24 +49118,68 @@ class NodeSampledTexture extends SampledTexture { } +/** + * A special form of sampled cube texture binding type. + * It's texture value is managed by a node object. + * + * @private + * @augments NodeSampledTexture + */ class NodeSampledCubeTexture extends NodeSampledTexture { - constructor( name, textureNode, groupNode, access ) { + /** + * Constructs a new node-based sampled cube texture. + * + * @param {String} name - The textures's name. + * @param {TextureNode} textureNode - The texture node. + * @param {UniformGroupNode} groupNode - The uniform group node. + * @param {String?} [access=null] - The access type. + */ + constructor( name, textureNode, groupNode, access = null ) { super( name, textureNode, groupNode, access ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isSampledCubeTexture = true; } } +/** + * A special form of sampled 3D texture binding type. + * It's texture value is managed by a node object. + * + * @private + * @augments NodeSampledTexture + */ class NodeSampledTexture3D extends NodeSampledTexture { - constructor( name, textureNode, groupNode, access ) { + /** + * Constructs a new node-based sampled 3D texture. + * + * @param {String} name - The textures's name. + * @param {TextureNode} textureNode - The texture node. + * @param {UniformGroupNode} groupNode - The uniform group node. + * @param {String?} [access=null] - The access type. + */ + constructor( name, textureNode, groupNode, access = null ) { super( name, textureNode, groupNode, access ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isSampledTexture3D = true; } @@ -42592,39 +49223,109 @@ precision highp isampler2DArray; precision lowp sampler2DShadow; `; +/** + * A node builder targeting GLSL. + * + * This module generates GLSL shader code from node materials and also + * generates the respective bindings and vertex buffer definitions. These + * data are later used by the renderer to create render and compute pipelines + * for render objects. + * + * @augments NodeBuilder + */ class GLSLNodeBuilder extends NodeBuilder { + /** + * Constructs a new GLSL node builder renderer. + * + * @param {Object3D} object - The 3D object. + * @param {Renderer} renderer - The renderer. + */ constructor( object, renderer ) { super( object, renderer, new GLSLNodeParser() ); + /** + * A dictionary holds for each shader stage ('vertex', 'fragment', 'compute') + * another dictionary which manages UBOs per group ('render','frame','object'). + * + * @type {Object>} + */ this.uniformGroups = {}; + + /** + * An array that holds objects defining the varying and attribute data in + * context of Transform Feedback. + * + * @type {Object>} + */ this.transforms = []; + + /** + * A dictionary that holds for each shader stage a Map of used extensions. + * + * @type {Object>} + */ this.extensions = {}; + + /** + * A dictionary that holds for each shader stage an Array of used builtins. + * + * @type {Object>} + */ this.builtins = { vertex: [], fragment: [], compute: [] }; + /** + * Whether comparison in shader code are generated with methods or not. + * + * @type {Boolean} + * @default true + */ this.useComparisonMethod = true; } + /** + * Checks if the given texture requires a manual conversion to the working color space. + * + * @param {Texture} texture - The texture to check. + * @return {Boolean} Whether the given texture requires a conversion to working color space or not. + */ needsToWorkingColorSpace( texture ) { return texture.isVideoTexture === true && texture.colorSpace !== NoColorSpace; } + /** + * Returns the native shader method name for a given generic name. + * + * @param {String} method - The method name to resolve. + * @return {String} The resolved GLSL method name. + */ getMethod( method ) { return glslMethods[ method ] || method; } + /** + * Returns the output struct name. Not relevant for GLSL. + * + * @return {String} + */ getOutputStructName() { return ''; } + /** + * Builds the given shader node. + * + * @param {ShaderNodeInternal} shaderNode - The shader node. + * @return {String} The GLSL function code. + */ buildFunctionCode( shaderNode ) { const layout = shaderNode.layout; @@ -42655,6 +49356,12 @@ ${ flowData.code } } + /** + * Setups the Pixel Buffer Object (PBO) for the given storage + * buffer node. + * + * @param {StorageBufferNode} storageBufferNode - The storage buffer node. + */ setupPBO( storageBufferNode ) { const attribute = storageBufferNode.value; @@ -42723,6 +49430,13 @@ ${ flowData.code } } + /** + * Returns a GLSL snippet that represents the property name of the given node. + * + * @param {Node} node - The node. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The property name. + */ getPropertyName( node, shaderStage = this.shaderStage ) { if ( node.isNodeUniform && node.node.isTextureNode !== true && node.node.isBufferNode !== true ) { @@ -42735,6 +49449,13 @@ ${ flowData.code } } + /** + * Setups the Pixel Buffer Object (PBO) for the given storage + * buffer node. + * + * @param {StorageArrayElementNode} storageArrayElementNode - The storage array element node. + * @return {String} The property name. + */ generatePBO( storageArrayElementNode ) { const { node, indexNode } = storageArrayElementNode; @@ -42817,6 +49538,16 @@ ${ flowData.code } } + /** + * Generates the GLSL snippet that reads a single texel from a texture without sampling or filtering. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvIndexSnippet - A GLSL snippet that represents texture coordinates used for sampling. + * @param {String?} depthSnippet - A GLSL snippet that represents the 0-based texture array index to sample. + * @param {String} [levelSnippet='0u'] - A GLSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @return {String} The GLSL snippet. + */ generateTextureLoad( texture, textureProperty, uvIndexSnippet, depthSnippet, levelSnippet = '0' ) { if ( depthSnippet ) { @@ -42831,6 +49562,15 @@ ${ flowData.code } } + /** + * Generates the GLSL snippet for sampling/loading the given texture. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A GLSL snippet that represents texture coordinates used for sampling. + * @param {String?} depthSnippet - A GLSL snippet that represents the 0-based texture array index to sample. + * @return {String} The GLSL snippet. + */ generateTexture( texture, textureProperty, uvSnippet, depthSnippet ) { if ( texture.isDepthTexture ) { @@ -42847,24 +49587,63 @@ ${ flowData.code } } + /** + * Generates the GLSL snippet when sampling textures with explicit mip level. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A GLSL snippet that represents texture coordinates used for sampling. + * @param {String} levelSnippet - A GLSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @return {String} The GLSL snippet. + */ generateTextureLevel( texture, textureProperty, uvSnippet, levelSnippet ) { return `textureLod( ${ textureProperty }, ${ uvSnippet }, ${ levelSnippet } )`; } + /** + * Generates the GLSL snippet when sampling textures with a bias to the mip level. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A GLSL snippet that represents texture coordinates used for sampling. + * @param {String} biasSnippet - A GLSL snippet that represents the bias to apply to the mip level before sampling. + * @return {String} The GLSL snippet. + */ generateTextureBias( texture, textureProperty, uvSnippet, biasSnippet ) { return `texture( ${ textureProperty }, ${ uvSnippet }, ${ biasSnippet } )`; } + /** + * Generates the GLSL snippet for sampling/loading the given texture using explicit gradients. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A GLSL snippet that represents texture coordinates used for sampling. + * @param {Array} gradSnippet - An array holding both gradient GLSL snippets. + * @return {String} The GLSL snippet. + */ generateTextureGrad( texture, textureProperty, uvSnippet, gradSnippet ) { return `textureGrad( ${ textureProperty }, ${ uvSnippet }, ${ gradSnippet[ 0 ] }, ${ gradSnippet[ 1 ] } )`; } + /** + * Generates the GLSL snippet for sampling a depth texture and comparing the sampled depth values + * against a reference value. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A GLSL snippet that represents texture coordinates used for sampling. + * @param {String} compareSnippet - A GLSL snippet that represents the reference value. + * @param {String?} depthSnippet - A GLSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The GLSL snippet. + */ generateTextureCompare( texture, textureProperty, uvSnippet, compareSnippet, depthSnippet, shaderStage = this.shaderStage ) { if ( shaderStage === 'fragment' ) { @@ -42879,6 +49658,12 @@ ${ flowData.code } } + /** + * Returns the variables of the given shader stage as a GLSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The GLSL snippet that defines the variables. + */ getVars( shaderStage ) { const snippets = []; @@ -42899,6 +49684,12 @@ ${ flowData.code } } + /** + * Returns the uniforms of the given shader stage as a GLSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The GLSL snippet that defines the uniforms. + */ getUniforms( shaderStage ) { const uniforms = this.uniforms[ shaderStage ]; @@ -43016,6 +49807,12 @@ ${ flowData.code } } + /** + * Returns the type for a given buffer attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + * @return {String} The type. + */ getTypeFromAttribute( attribute ) { let nodeType = super.getTypeFromAttribute( attribute ); @@ -43040,6 +49837,12 @@ ${ flowData.code } } + /** + * Returns the shader attributes of the given shader stage as a GLSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The GLSL snippet that defines the shader attributes. + */ getAttributes( shaderStage ) { let snippet = ''; @@ -43062,6 +49865,12 @@ ${ flowData.code } } + /** + * Returns the members of the given struct type node as a GLSL string. + * + * @param {StructTypeNode} struct - The struct type node. + * @return {String} The GLSL snippet that defines the struct members. + */ getStructMembers( struct ) { const snippets = []; @@ -43078,6 +49887,12 @@ ${ flowData.code } } + /** + * Returns the structs of the given shader stage as a GLSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The GLSL snippet that defines the structs. + */ getStructs( shaderStage ) { const snippets = []; @@ -43105,6 +49920,12 @@ ${ flowData.code } } + /** + * Returns the varyings of the given shader stage as a GLSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The GLSL snippet that defines the varyings. + */ getVaryings( shaderStage ) { let snippet = ''; @@ -43150,18 +49971,33 @@ ${ flowData.code } } + /** + * Returns the vertex index builtin. + * + * @return {String} The vertex index. + */ getVertexIndex() { return 'uint( gl_VertexID )'; } + /** + * Returns the instance index builtin. + * + * @return {String} The instance index. + */ getInstanceIndex() { return 'uint( gl_InstanceID )'; } + /** + * Returns the invocation local index builtin. + * + * @return {String} The invocation local index. + */ getInvocationLocalIndex() { const workgroupSize = this.object.workgroupSize; @@ -43172,6 +50008,11 @@ ${ flowData.code } } + /** + * Returns the draw index builtin. + * + * @return {String?} The drawIndex shader string. Returns `null` if `WEBGL_multi_draw` isn't supported by the device. + */ getDrawIndex() { const extensions = this.renderer.backend.extensions; @@ -43186,24 +50027,46 @@ ${ flowData.code } } + /** + * Returns the front facing builtin. + * + * @return {String} The front facing builtin. + */ getFrontFacing() { return 'gl_FrontFacing'; } + /** + * Returns the frag coord builtin. + * + * @return {String} The frag coord builtin. + */ getFragCoord() { return 'gl_FragCoord.xy'; } + /** + * Returns the frag depth builtin. + * + * @return {String} The frag depth builtin. + */ getFragDepth() { return 'gl_FragDepth'; } + /** + * Enables the given extension. + * + * @param {String} name - The extension name. + * @param {String} behavior - The extension behavior. + * @param {String} [shaderStage=this.shaderStage] - The shader stage. + */ enableExtension( name, behavior, shaderStage = this.shaderStage ) { const map = this.extensions[ shaderStage ] || ( this.extensions[ shaderStage ] = new Map() ); @@ -43219,6 +50082,12 @@ ${ flowData.code } } + /** + * Returns the enabled extensions of the given shader stage as a GLSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The GLSL snippet that defines the enabled extensions. + */ getExtensions( shaderStage ) { const snippets = []; @@ -43252,12 +50121,23 @@ ${ flowData.code } } + /** + * Returns the clip distances builtin. + * + * @return {String} The clip distances builtin. + */ getClipDistance() { return 'gl_ClipDistance'; } + /** + * Whether the requested feature is available or not. + * + * @param {String} name - The requested feature. + * @return {Boolean} Whether the requested feature is supported or not. + */ isAvailable( name ) { let result = supports$1[ name ]; @@ -43301,12 +50181,22 @@ ${ flowData.code } } + /** + * Whether to flip texture data along its vertical axis or not. + * + * @return {Boolean} Returns always `true` in context of GLSL. + */ isFlipY() { return true; } + /** + * Enables hardware clipping. + * + * @param {String} planeCount - The clipping plane count. + */ enableHardwareClipping( planeCount ) { this.enableExtension( 'GL_ANGLE_clip_cull_distance', 'require' ); @@ -43315,12 +50205,24 @@ ${ flowData.code } } + /** + * Registers a transform in context of Transform Feedback. + * + * @param {String} varyingName - The varying name. + * @param {AttributeNode} attributeNode - The attribute node. + */ registerTransform( varyingName, attributeNode ) { this.transforms.push( { varyingName, attributeNode } ); } + /** + * Returns the transforms of the given shader stage as a GLSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The GLSL snippet that defines the transforms. + */ getTransforms( /* shaderStage */ ) { const transforms = this.transforms; @@ -43341,6 +50243,14 @@ ${ flowData.code } } + /** + * Returns a GLSL struct based on the given name and variables. + * + * @private + * @param {String} name - The struct name. + * @param {String} vars - The struct variables. + * @return {String} The GLSL snippet representing a struct. + */ _getGLSLUniformStruct( name, vars ) { return ` @@ -43350,6 +50260,13 @@ ${vars} } + /** + * Returns a GLSL vertex shader based on the given shader data. + * + * @private + * @param {Object} shaderData - The shader data. + * @return {String} The vertex shader. + */ _getGLSLVertexCode( shaderData ) { return `#version 300 es @@ -43392,6 +50309,13 @@ void main() { } + /** + * Returns a GLSL fragment shader based on the given shader data. + * + * @private + * @param {Object} shaderData - The shader data. + * @return {String} The vertex shader. + */ _getGLSLFragmentCode( shaderData ) { return `#version 300 es @@ -43425,6 +50349,9 @@ void main() { } + /** + * Controls the code build of the shader stages. + */ buildCode() { const shadersData = this.material !== null ? { fragment: {}, vertex: {} } : { compute: {} }; @@ -43505,6 +50432,19 @@ void main() { } + /** + * This method is one of the more important ones since it's responsible + * for generating a matching binding instance for the given uniform node. + * + * These bindings are later used in the renderer to create bind groups + * and layouts. + * + * @param {UniformNode} node - The uniform node. + * @param {String} type - The node data type. + * @param {String} shaderStage - The shader stage. + * @param {String?} [name=null] - An optional uniform name. + * @return {NodeUniform} The node uniform object. + */ getUniformFromNode( node, type, shaderStage, name = null ) { const uniformNode = super.getUniformFromNode( node, type, shaderStage, name ); @@ -43579,141 +50519,540 @@ void main() { } -let vector2 = null; -let vector4 = null; -let color4 = null; +let _vector2 = null; +let _color4 = null; +/** + * Most of the rendering related logic is implemented in the + * {@link module:Renderer} module and related management components. + * Sometimes it is required though to execute commands which are + * specific to the current 3D backend (which is WebGPU or WebGL 2). + * This abstract base class defines an interface that encapsulates + * all backend-related logic. Derived classes for each backend must + * implement the interface. + * + * @abstract + * @private + */ class Backend { + /** + * Constructs a new backend. + * + * @param {Object} parameters - An object holding parameters for the backend. + */ constructor( parameters = {} ) { + /** + * The parameters of the backend. + * + * @type {Object} + */ this.parameters = Object.assign( {}, parameters ); + + /** + * This weak map holds backend-specific data of objects + * like textures, attributes or render targets. + * + * @type {WeakMap} + */ this.data = new WeakMap(); + + /** + * A reference to the renderer. + * + * @type {Renderer?} + * @default null + */ this.renderer = null; + + /** + * A reference to the canvas element the renderer is drawing to. + * + * @type {(HTMLCanvasElement|OffscreenCanvas)?} + * @default null + */ this.domElement = null; } + /** + * Initializes the backend so it is ready for usage. Concrete backends + * are supposed to implement their rendering context creation and related + * operations in this method. + * + * @async + * @param {Renderer} renderer - The renderer. + * @return {Promise} A Promise that resolves when the backend has been initialized. + */ async init( renderer ) { this.renderer = renderer; } + /** + * The coordinate system of the backend. + * + * @abstract + * @type {Number} + * @readonly + */ + get coordinateSystem() {} + // render context - begin( /*renderContext*/ ) { } + /** + * This method is executed at the beginning of a render call and + * can be used by the backend to prepare the state for upcoming + * draw calls. + * + * @abstract + * @param {RenderContext} renderContext - The render context. + */ + beginRender( /*renderContext*/ ) {} - finish( /*renderContext*/ ) { } + /** + * This method is executed at the end of a render call and + * can be used by the backend to finalize work after draw + * calls. + * + * @abstract + * @param {RenderContext} renderContext - The render context. + */ + finishRender( /*renderContext*/ ) {} + + /** + * This method is executed at the beginning of a compute call and + * can be used by the backend to prepare the state for upcoming + * compute tasks. + * + * @abstract + * @param {Node|Array} computeGroup - The compute node(s). + */ + beginCompute( /*computeGroup*/ ) {} + + /** + * This method is executed at the end of a compute call and + * can be used by the backend to finalize work after compute + * tasks. + * + * @abstract + * @param {Node|Array} computeGroup - The compute node(s). + */ + finishCompute( /*computeGroup*/ ) {} // render object + /** + * Executes a draw command for the given render object. + * + * @abstract + * @param {RenderObject} renderObject - The render object to draw. + * @param {Info} info - Holds a series of statistical information about the GPU memory and the rendering process. + */ draw( /*renderObject, info*/ ) { } + // compute node + + /** + * Executes a compute command for the given compute node. + * + * @abstract + * @param {Node|Array} computeGroup - The group of compute nodes of a compute call. Can be a single compute node. + * @param {Node} computeNode - The compute node. + * @param {Array} bindings - The bindings. + * @param {ComputePipeline} computePipeline - The compute pipeline. + */ + compute( /*computeGroup, computeNode, computeBindings, computePipeline*/ ) { } + // program + /** + * Creates a shader program from the given programmable stage. + * + * @abstract + * @param {ProgrammableStage} program - The programmable stage. + */ createProgram( /*program*/ ) { } + /** + * Destroys the shader program of the given programmable stage. + * + * @abstract + * @param {ProgrammableStage} program - The programmable stage. + */ destroyProgram( /*program*/ ) { } // bindings - createBindings( /*bingGroup, bindings*/ ) { } + /** + * Creates bindings from the given bind group definition. + * + * @abstract + * @param {BindGroup} bindGroup - The bind group. + * @param {Array} bindings - Array of bind groups. + * @param {Number} cacheIndex - The cache index. + * @param {Number} version - The version. + */ + createBindings( /*bindGroup, bindings, cacheIndex, version*/ ) { } - updateBindings( /*bingGroup, bindings*/ ) { } + /** + * Updates the given bind group definition. + * + * @abstract + * @param {BindGroup} bindGroup - The bind group. + * @param {Array} bindings - Array of bind groups. + * @param {Number} cacheIndex - The cache index. + * @param {Number} version - The version. + */ + updateBindings( /*bindGroup, bindings, cacheIndex, version*/ ) { } - // pipeline + /** + * Updates a buffer binding. + * + * @abstract + * @param {Buffer} binding - The buffer binding to update. + */ + updateBinding( /*binding*/ ) { } - createRenderPipeline( /*renderObject*/ ) { } + // pipeline - createComputePipeline( /*computeNode, pipeline*/ ) { } + /** + * Creates a render pipeline for the given render object. + * + * @abstract + * @param {RenderObject} renderObject - The render object. + * @param {Array} promises - An array of compilation promises which are used in `compileAsync()`. + */ + createRenderPipeline( /*renderObject, promises*/ ) { } - destroyPipeline( /*pipeline*/ ) { } + /** + * Creates a compute pipeline for the given compute node. + * + * @abstract + * @param {ComputePipeline} computePipeline - The compute pipeline. + * @param {Array} bindings - The bindings. + */ + createComputePipeline( /*computePipeline, bindings*/ ) { } // cache key - needsRenderUpdate( /*renderObject*/ ) { } // return Boolean ( fast test ) + /** + * Returns `true` if the render pipeline requires an update. + * + * @abstract + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether the render pipeline requires an update or not. + */ + needsRenderUpdate( /*renderObject*/ ) { } - getRenderCacheKey( /*renderObject*/ ) { } // return String + /** + * Returns a cache key that is used to identify render pipelines. + * + * @abstract + * @param {RenderObject} renderObject - The render object. + * @return {String} The cache key. + */ + getRenderCacheKey( /*renderObject*/ ) { } // node builder - createNodeBuilder( /*renderObject*/ ) { } // return NodeBuilder (ADD IT) + /** + * Returns a node builder for the given render object. + * + * @abstract + * @param {RenderObject} renderObject - The render object. + * @param {Renderer} renderer - The renderer. + * @return {NodeBuilder} The node builder. + */ + createNodeBuilder( /*renderObject, renderer*/ ) { } // textures + /** + * Creates a GPU sampler for the given texture. + * + * @abstract + * @param {Texture} texture - The texture to create the sampler for. + */ createSampler( /*texture*/ ) { } + /** + * Destroys the GPU sampler for the given texture. + * + * @abstract + * @param {Texture} texture - The texture to destroy the sampler for. + */ + destroySampler( /*texture*/ ) {} + + /** + * Creates a default texture for the given texture that can be used + * as a placeholder until the actual texture is ready for usage. + * + * @abstract + * @param {Texture} texture - The texture to create a default texture for. + */ createDefaultTexture( /*texture*/ ) { } - createTexture( /*texture*/ ) { } + /** + * Defines a texture on the GPU for the given texture object. + * + * @abstract + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ + createTexture( /*texture, options={}*/ ) { } + + /** + * Uploads the updated texture data to the GPU. + * + * @abstract + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ + updateTexture( /*texture, options = {}*/ ) { } - copyTextureToBuffer( /*texture, x, y, width, height*/ ) {} + /** + * Generates mipmaps for the given texture. + * + * @abstract + * @param {Texture} texture - The texture. + */ + generateMipmaps( /*texture*/ ) { } + + /** + * Destroys the GPU data for the given texture object. + * + * @abstract + * @param {Texture} texture - The texture. + */ + destroyTexture( /*texture*/ ) { } + + /** + * Returns texture data as a typed array. + * + * @abstract + * @async + * @param {Texture} texture - The texture to copy. + * @param {Number} x - The x coordinate of the copy origin. + * @param {Number} y - The y coordinate of the copy origin. + * @param {Number} width - The width of the copy. + * @param {Number} height - The height of the copy. + * @param {Number} faceIndex - The face index. + * @return {Promise} A Promise that resolves with a typed array when the copy operation has finished. + */ + async copyTextureToBuffer( /*texture, x, y, width, height, faceIndex*/ ) {} + + /** + * Copies data of the given source texture to the given destination texture. + * + * @abstract + * @param {Texture} srcTexture - The source texture. + * @param {Texture} dstTexture - The destination texture. + * @param {Vector4?} [srcRegion=null] - The region of the source texture to copy. + * @param {(Vector2|Vector3)?} [dstPosition=null] - The destination position of the copy. + * @param {Number} [level=0] - The mip level to copy. + */ + copyTextureToTexture( /*srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0*/ ) {} + + /** + * Copies the current bound framebuffer to the given texture. + * + * @abstract + * @param {Texture} texture - The destination texture. + * @param {RenderContext} renderContext - The render context. + * @param {Vector4} rectangle - A four dimensional vector defining the origin and dimension of the copy. + */ + copyFramebufferToTexture( /*texture, renderContext, rectangle*/ ) {} // attributes + /** + * Creates the GPU buffer of a shader attribute. + * + * @abstract + * @param {BufferAttribute} attribute - The buffer attribute. + */ createAttribute( /*attribute*/ ) { } + /** + * Creates the GPU buffer of an indexed shader attribute. + * + * @abstract + * @param {BufferAttribute} attribute - The indexed buffer attribute. + */ createIndexAttribute( /*attribute*/ ) { } + /** + * Creates the GPU buffer of a storage attribute. + * + * @abstract + * @param {BufferAttribute} attribute - The buffer attribute. + */ + createStorageAttribute( /*attribute*/ ) { } + + /** + * Updates the GPU buffer of a shader attribute. + * + * @abstract + * @param {BufferAttribute} attribute - The buffer attribute to update. + */ updateAttribute( /*attribute*/ ) { } + /** + * Destroys the GPU buffer of a shader attribute. + * + * @abstract + * @param {BufferAttribute} attribute - The buffer attribute to destroy. + */ destroyAttribute( /*attribute*/ ) { } // canvas + /** + * Returns the backend's rendering context. + * + * @abstract + * @return {Object} The rendering context. + */ getContext() { } + /** + * Backends can use this method if they have to run + * logic when the renderer gets resized. + * + * @abstract + */ updateSize() { } + /** + * Updates the viewport with the values from the given render context. + * + * @abstract + * @param {RenderContext} renderContext - The render context. + */ + updateViewport( /*renderContext*/ ) {} + // utils - resolveTimestampAsync( /*renderContext, type*/ ) { } + /** + * Returns `true` if the given 3D object is fully occluded by other + * 3D objects in the scene. Backends must implement this method by using + * a Occlusion Query API. + * + * @abstract + * @param {RenderContext} renderContext - The render context. + * @param {Object3D} object - The 3D object to test. + * @return {Boolean} Whether the 3D object is fully occluded or not. + */ + isOccluded( /*renderContext, object*/ ) {} - hasFeatureAsync( /*name*/ ) { } // return Boolean + /** + * Resolves the time stamp for the given render context and type. + * + * @async + * @abstract + * @param {RenderContext} renderContext - The render context. + * @param {String} type - The render context. + * @return {Promise} A Promise that resolves when the time stamp has been computed. + */ + async resolveTimestampAsync( /*renderContext, type*/ ) { } - hasFeature( /*name*/ ) { } // return Boolean + /** + * Can be used to synchronize CPU operations with GPU tasks. So when this method is called, + * the CPU waits for the GPU to complete its operation (e.g. a compute task). + * + * @async + * @abstract + * @return {Promise} A Promise that resolves when synchronization has been finished. + */ + async waitForGPU() {} - getInstanceCount( renderObject ) { + /** + * This method performs a readback operation by moving buffer data from + * a storage buffer attribute from the GPU to the CPU. + * + * @async + * @param {StorageBufferAttribute} attribute - The storage buffer attribute. + * @return {Promise} A promise that resolves with the buffer data when the data are ready. + */ + async getArrayBufferAsync( /* attribute */ ) {} - const { object, geometry } = renderObject; + /** + * Checks if the given feature is supported by the backend. + * + * @async + * @abstract + * @param {String} name - The feature's name. + * @return {Promise} A Promise that resolves with a bool that indicates whether the feature is supported or not. + */ + async hasFeatureAsync( /*name*/ ) { } - return geometry.isInstancedBufferGeometry ? geometry.instanceCount : ( object.count > 1 ? object.count : 1 ); + /** + * Checks if the given feature is supported by the backend. + * + * @abstract + * @param {String} name - The feature's name. + * @return {Boolean} Whether the feature is supported or not. + */ + hasFeature( /*name*/ ) {} - } + /** + * Returns the maximum anisotropy texture filtering value. + * + * @abstract + * @return {Number} The maximum anisotropy texture filtering value. + */ + getMaxAnisotropy() {} + /** + * Returns the drawing buffer size. + * + * @return {Vector2} The drawing buffer size. + */ getDrawingBufferSize() { - vector2 = vector2 || new Vector2(); + _vector2 = _vector2 || new Vector2(); - return this.renderer.getDrawingBufferSize( vector2 ); - - } - - getScissor() { - - vector4 = vector4 || new Vector4(); - - return this.renderer.getScissor( vector4 ); + return this.renderer.getDrawingBufferSize( _vector2 ); } + /** + * Defines the scissor test. + * + * @abstract + * @param {Boolean} boolean - Whether the scissor test should be enabled or not. + */ setScissorTest( /*boolean*/ ) { } + /** + * Returns the clear color and alpha into a single + * color object. + * + * @return {Color4} The clear color. + */ getClearColor() { const renderer = this.renderer; - color4 = color4 || new Color4(); + _color4 = _color4 || new Color4(); - renderer.getClearColor( color4 ); + renderer.getClearColor( _color4 ); - color4.getRGB( color4, this.renderer.currentColorSpace ); + _color4.getRGB( _color4, this.renderer.currentColorSpace ); - return color4; + return _color4; } + /** + * Returns the DOM element. If no DOM element exists, the backend + * creates a new one. + * + * @return {HTMLCanvasElement} The DOM element. + */ getDomElement() { let domElement = this.domElement; @@ -43733,14 +51072,25 @@ class Backend { } - // resource properties - + /** + * Sets a dictionary for the given object into the + * internal data structure. + * + * @param {Object} object - The object. + * @param {Object} value - The dictionary to set. + */ set( object, value ) { this.data.set( object, value ); } + /** + * Returns the dictionary for the given object. + * + * @param {Object} object - The object. + * @return {Object} The object's dictionary. + */ get( object ) { let map = this.data.get( object ); @@ -43756,24 +51106,49 @@ class Backend { } + /** + * Checks if the given object has a dictionary + * with data defined. + * + * @param {Object} object - The object. + * @return {Boolean} Whether a dictionary for the given object as been defined or not. + */ has( object ) { return this.data.has( object ); } + /** + * Deletes an object from the internal data structure. + * + * @param {Object} object - The object to delete. + */ delete( object ) { this.data.delete( object ); } + /** + * Frees internal resources. + * + * @abstract + */ dispose() { } } let _id$1 = 0; +/** + * This module is internally used in context of compute shaders. + * This type of shader is not natively supported in WebGL 2 and + * thus implemented via Transform Feedback. `DualAttributeData` + * manages the related data. + * + * @private + */ class DualAttributeData { constructor( attributeData, dualBuffer ) { @@ -43818,14 +51193,35 @@ class DualAttributeData { } +/** + * A WebGL 2 backend utility module for managing shader attributes. + * + * @private + */ class WebGLAttributeUtils { + /** + * Constructs a new utility object. + * + * @param {WebGLBackend} backend - The WebGL 2 backend. + */ constructor( backend ) { + /** + * A reference to the WebGL 2 backend. + * + * @type {WebGLBackend} + */ this.backend = backend; } + /** + * Creates the GPU buffer for the given buffer attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + * @param {GLenum } bufferType - A flag that indicates the buffer type and thus binding point target. + */ createAttribute( attribute, bufferType ) { const backend = this.backend; @@ -43923,6 +51319,11 @@ class WebGLAttributeUtils { } + /** + * Updates the GPU buffer of the given buffer attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ updateAttribute( attribute ) { const backend = this.backend; @@ -43962,6 +51363,11 @@ class WebGLAttributeUtils { } + /** + * Destroys the GPU buffer of the given buffer attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ destroyAttribute( attribute ) { const backend = this.backend; @@ -43981,6 +51387,14 @@ class WebGLAttributeUtils { } + /** + * This method performs a readback operation by moving buffer data from + * a storage buffer attribute from the GPU to the CPU. + * + * @async + * @param {StorageBufferAttribute} attribute - The storage buffer attribute. + * @return {Promise} A promise that resolves with the buffer data when the data are ready. + */ async getArrayBufferAsync( attribute ) { const backend = this.backend; @@ -44019,6 +51433,16 @@ class WebGLAttributeUtils { } + /** + * Creates a WebGL buffer with the given data. + * + * @private + * @param {WebGL2RenderingContext} gl - The rendering context. + * @param {GLenum } bufferType - A flag that indicates the buffer type and thus binding point target. + * @param {TypedArray} array - The array of the buffer attribute. + * @param {GLenum} usage - The usage. + * @return {WebGLBuffer} The WebGL buffer. + */ _createBuffer( gl, bufferType, array, usage ) { const bufferGPU = gl.createBuffer(); @@ -44035,14 +51459,43 @@ class WebGLAttributeUtils { let initialized$1 = false, equationToGL, factorToGL; +/** + * A WebGL 2 backend utility module for managing the WebGL state. + * + * The major goal of this module is to reduce the number of state changes + * by caching the WEbGL state with a series of variables. In this way, the + * renderer only executes state change commands when necessary which + * improves the overall performance. + * + * @private + */ class WebGLState { + /** + * Constructs a new utility object. + * + * @param {WebGLBackend} backend - The WebGL 2 backend. + */ constructor( backend ) { + /** + * A reference to the WebGL 2 backend. + * + * @type {WebGLBackend} + */ this.backend = backend; + /** + * A reference to the rendering context. + * + * @type {WebGL2RenderingContext} + */ this.gl = this.backend.gl; + // Below properties are intended to cache + // the WebGL state and are not explicitly + // documented for convenience reasons. + this.enabled = {}; this.currentFlipSided = null; this.currentCullFace = null; @@ -44079,7 +51532,7 @@ class WebGLState { if ( initialized$1 === false ) { - this._init( this.gl ); + this._init(); initialized$1 = true; @@ -44087,7 +51540,14 @@ class WebGLState { } - _init( gl ) { + /** + * Inits the state of the utility. + * + * @private + */ + _init() { + + const gl = this.gl; // Store only WebGL constants here. @@ -44113,6 +51573,14 @@ class WebGLState { } + /** + * Enables the given WebGL capability. + * + * This method caches the capability state so + * `gl.enable()` is only called when necessary. + * + * @param {GLenum} id - The capability to enable. + */ enable( id ) { const { enabled } = this; @@ -44126,6 +51594,14 @@ class WebGLState { } + /** + * Disables the given WebGL capability. + * + * This method caches the capability state so + * `gl.disable()` is only called when necessary. + * + * @param {GLenum} id - The capability to enable. + */ disable( id ) { const { enabled } = this; @@ -44139,6 +51615,15 @@ class WebGLState { } + /** + * Specifies whether polygons are front- or back-facing + * by setting the winding orientation. + * + * This method caches the state so `gl.frontFace()` is only + * called when necessary. + * + * @param {Boolean} flipSided - Whether triangles flipped their sides or not. + */ setFlipSided( flipSided ) { if ( this.currentFlipSided !== flipSided ) { @@ -44161,6 +51646,15 @@ class WebGLState { } + /** + * Specifies whether or not front- and/or back-facing + * polygons can be culled. + * + * This method caches the state so `gl.cullFace()` is only + * called when necessary. + * + * @param {Number} cullFace - Defines which polygons are candidates for culling. + */ setCullFace( cullFace ) { const { gl } = this; @@ -44197,6 +51691,14 @@ class WebGLState { } + /** + * Specifies the width of line primitives. + * + * This method caches the state so `gl.lineWidth()` is only + * called when necessary. + * + * @param {Number} width - The line width. + */ setLineWidth( width ) { const { currentLineWidth, gl } = this; @@ -44211,7 +51713,21 @@ class WebGLState { } - + /** + * Defines the blending. + * + * This method caches the state so `gl.blendEquation()`, `gl.blendEquationSeparate()`, + * `gl.blendFunc()` and `gl.blendFuncSeparate()` are only called when necessary. + * + * @param {Number} blending - The blending type. + * @param {Number} blendEquation - The blending equation. + * @param {Number} blendSrc - Only relevant for custom blending. The RGB source blending factor. + * @param {Number} blendDst - Only relevant for custom blending. The RGB destination blending factor. + * @param {Number} blendEquationAlpha - Only relevant for custom blending. The blending equation for alpha. + * @param {Number} blendSrcAlpha - Only relevant for custom blending. The alpha source blending factor. + * @param {Number} blendDstAlpha - Only relevant for custom blending. The alpha destination blending factor. + * @param {Boolean} premultipliedAlpha - Whether premultiplied alpha is enabled or not. + */ setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) { const { gl } = this; @@ -44348,6 +51864,15 @@ class WebGLState { } + /** + * Specifies whether colors can be written when rendering + * into a framebuffer or not. + * + * This method caches the state so `gl.colorMask()` is only + * called when necessary. + * + * @param {Boolean} colorMask - The color mask. + */ setColorMask( colorMask ) { if ( this.currentColorMask !== colorMask ) { @@ -44359,6 +51884,11 @@ class WebGLState { } + /** + * Specifies whether the depth test is enabled or not. + * + * @param {Boolean} depthTest - Whether the depth test is enabled or not. + */ setDepthTest( depthTest ) { const { gl } = this; @@ -44375,6 +51905,15 @@ class WebGLState { } + /** + * Specifies whether depth values can be written when rendering + * into a framebuffer or not. + * + * This method caches the state so `gl.depthMask()` is only + * called when necessary. + * + * @param {Boolean} depthMask - The depth mask. + */ setDepthMask( depthMask ) { if ( this.currentDepthMask !== depthMask ) { @@ -44386,6 +51925,14 @@ class WebGLState { } + /** + * Specifies the depth compare function. + * + * This method caches the state so `gl.depthFunc()` is only + * called when necessary. + * + * @param {Number} depthFunc - The depth compare function. + */ setDepthFunc( depthFunc ) { if ( this.currentDepthFunc !== depthFunc ) { @@ -44446,6 +51993,11 @@ class WebGLState { } + /** + * Specifies whether the stencil test is enabled or not. + * + * @param {Boolean} stencilTest - Whether the stencil test is enabled or not. + */ setStencilTest( stencilTest ) { const { gl } = this; @@ -44462,6 +52014,15 @@ class WebGLState { } + /** + * Specifies whether stencil values can be written when rendering + * into a framebuffer or not. + * + * This method caches the state so `gl.stencilMask()` is only + * called when necessary. + * + * @param {Boolean} stencilMask - The stencil mask. + */ setStencilMask( stencilMask ) { if ( this.currentStencilMask !== stencilMask ) { @@ -44473,6 +52034,16 @@ class WebGLState { } + /** + * Specifies whether the stencil test functions. + * + * This method caches the state so `gl.stencilFunc()` is only + * called when necessary. + * + * @param {Number} stencilFunc - The stencil compare function. + * @param {Number} stencilRef - The reference value for the stencil test. + * @param {Number} stencilMask - A bit-wise mask that is used to AND the reference value and the stored stencil value when the test is done. + */ setStencilFunc( stencilFunc, stencilRef, stencilMask ) { if ( this.currentStencilFunc !== stencilFunc || @@ -44489,6 +52060,17 @@ class WebGLState { } + /** + * Specifies whether the stencil test operation. + * + * This method caches the state so `gl.stencilOp()` is only + * called when necessary. + * + * @param {Number} stencilFail - The function to use when the stencil test fails. + * @param {Number} stencilZFail - The function to use when the stencil test passes, but the depth test fail. + * @param {Number} stencilZPass - The function to use when both the stencil test and the depth test pass, + * or when the stencil test passes and there is no depth buffer or depth testing is disabled. + */ setStencilOp( stencilFail, stencilZFail, stencilZPass ) { if ( this.currentStencilFail !== stencilFail || @@ -44505,6 +52087,13 @@ class WebGLState { } + /** + * Configures the WebGL state for the given material. + * + * @param {Material} material - The material to configure the state for. + * @param {Number} frontFaceCW - Whether the front faces are counter-clockwise or not. + * @param {Number} hardwareClippingPlanes - The number of hardware clipping planes. + */ setMaterial( material, frontFaceCW, hardwareClippingPlanes ) { const { gl } = this; @@ -44569,6 +52158,16 @@ class WebGLState { } + /** + * Specifies the polygon offset. + * + * This method caches the state so `gl.polygonOffset()` is only + * called when necessary. + * + * @param {Boolean} polygonOffset - Whether polygon offset is enabled or not. + * @param {Number} factor - The scale factor for the variable depth offset for each polygon. + * @param {Number} units - The multiplier by which an implementation-specific value is multiplied with to create a constant depth offset. + */ setPolygonOffset( polygonOffset, factor, units ) { const { gl } = this; @@ -44594,6 +52193,15 @@ class WebGLState { } + /** + * Defines the usage of the given WebGL program. + * + * This method caches the state so `gl.useProgram()` is only + * called when necessary. + * + * @param {WebGLProgram} program - The WebGL program to use. + * @return {Boolean} Whether a program change has been executed or not. + */ useProgram( program ) { if ( this.currentProgram !== program ) { @@ -44613,6 +52221,16 @@ class WebGLState { // framebuffer + /** + * Binds the given framebuffer. + * + * This method caches the state so `gl.bindFramebuffer()` is only + * called when necessary. + * + * @param {Number} target - The binding point (target). + * @param {WebGLFramebuffer} framebuffer - The WebGL framebuffer to bind. + * @return {Boolean} Whether a bind has been executed or not. + */ bindFramebuffer( target, framebuffer ) { const { gl, currentBoundFramebuffers } = this; @@ -44645,6 +52263,16 @@ class WebGLState { } + /** + * Defines draw buffers to which fragment colors are written into. + * Configures the MRT setup of custom framebuffers. + * + * This method caches the state so `gl.drawBuffers()` is only + * called when necessary. + * + * @param {RenderContext} renderContext - The render context. + * @param {WebGLFramebuffer} framebuffer - The WebGL framebuffer. + */ drawBuffers( renderContext, framebuffer ) { const { gl } = this; @@ -44705,6 +52333,14 @@ class WebGLState { // texture + /** + * Makes the given texture unit active. + * + * This method caches the state so `gl.activeTexture()` is only + * called when necessary. + * + * @param {Number} webglSlot - The texture unit to make active. + */ activeTexture( webglSlot ) { const { gl, currentTextureSlot, maxTextures } = this; @@ -44720,6 +52356,16 @@ class WebGLState { } + /** + * Binds the given WebGL texture to a target. + * + * This method caches the state so `gl.bindTexture()` is only + * called when necessary. + * + * @param {Number} webglType - The binding point (target). + * @param {WebGLTexture} webglTexture - The WebGL texture to bind. + * @param {Number} webglSlot - The texture. + */ bindTexture( webglType, webglTexture, webglSlot ) { const { gl, currentTextureSlot, currentBoundTextures, maxTextures } = this; @@ -44765,6 +52411,17 @@ class WebGLState { } + /** + * Binds a given WebGL buffer to a given binding point (target) at a given index. + * + * This method caches the state so `gl.bindBufferBase()` is only + * called when necessary. + * + * @param {Number} target - The target for the bind operation. + * @param {Number} index - The index of the target. + * @param {WebGLBuffer} buffer - The WebGL buffer. + * @return {Boolean} Whether a bind has been executed or not. + */ bindBufferBase( target, index, buffer ) { const { gl } = this; @@ -44785,6 +52442,12 @@ class WebGLState { } + /** + * Unbinds the current bound texture. + * + * This method caches the state so `gl.bindTexture()` is only + * called when necessary. + */ unbindTexture() { const { gl, currentTextureSlot, currentBoundTextures } = this; @@ -44804,17 +52467,53 @@ class WebGLState { } +/** + * A WebGL 2 backend utility module with common helpers. + * + * @private + */ class WebGLUtils { + /** + * Constructs a new utility object. + * + * @param {WebGLBackend} backend - The WebGL 2 backend. + */ constructor( backend ) { + /** + * A reference to the WebGL 2 backend. + * + * @type {WebGLBackend} + */ this.backend = backend; + /** + * A reference to the rendering context. + * + * @type {WebGL2RenderingContext} + */ this.gl = this.backend.gl; + + /** + * A reference to a backend module holding extension-related + * utility functions. + * + * @type {WebGLExtensions} + */ this.extensions = backend.extensions; } + /** + * Converts the given three.js constant into a WebGL constant. + * The method currently supports the conversion of texture formats + * and types. + * + * @param {Number} p - The three.js constant. + * @param {String} [colorSpace=NoColorSpace] - The color space. + * @return {Number} The corresponding WebGL constant. + */ convert( p, colorSpace = NoColorSpace ) { const { gl, extensions } = this; @@ -45025,6 +52724,13 @@ class WebGLUtils { } + /** + * This method can be used to synchronize the CPU with the GPU by waiting until + * ongoing GPU commands have been completed. + * + * @private + * @return {Promise} A promise that resolves when all ongoing GPU commands have been completed. + */ _clientWaitAsync() { const { gl } = this; @@ -45071,19 +52777,53 @@ class WebGLUtils { let initialized = false, wrappingToGL, filterToGL, compareToGL; +/** + * A WebGL 2 backend utility module for managing textures. + * + * @private + */ class WebGLTextureUtils { + /** + * Constructs a new utility object. + * + * @param {WebGLBackend} backend - The WebGL 2 backend. + */ constructor( backend ) { + /** + * A reference to the WebGL 2 backend. + * + * @type {WebGLBackend} + */ this.backend = backend; + /** + * A reference to the rendering context. + * + * @type {WebGL2RenderingContext} + */ this.gl = backend.gl; + + /** + * A reference to a backend module holding extension-related + * utility functions. + * + * @type {WebGLExtensions} + */ this.extensions = backend.extensions; + + /** + * A dictionary for managing default textures. The key + * is the binding point (target), the value the WEbGL texture object. + * + * @type {Object} + */ this.defaultTextures = {}; if ( initialized === false ) { - this._init( this.gl ); + this._init(); initialized = true; @@ -45091,7 +52831,14 @@ class WebGLTextureUtils { } - _init( gl ) { + /** + * Inits the state of the utility. + * + * @private + */ + _init() { + + const gl = this.gl; // Store only WebGL constants here. @@ -45124,20 +52871,12 @@ class WebGLTextureUtils { } - filterFallback( f ) { - - const { gl } = this; - - if ( f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter ) { - - return gl.NEAREST; - - } - - return gl.LINEAR; - - } - + /** + * Returns the native texture type for the given texture. + * + * @param {Texture} texture - The texture. + * @return {GLenum} The native texture type. + */ getGLTextureType( texture ) { const { gl } = this; @@ -45167,6 +52906,16 @@ class WebGLTextureUtils { } + /** + * Returns the native texture type for the given texture. + * + * @param {String?} internalFormatName - The internal format name. When `null`, the internal format is derived from the subsequent parameters. + * @param {GLenum} glFormat - The WebGL format. + * @param {GLenum} glType - The WebGL type. + * @param {String} colorSpace - The texture's color space. + * @param {Boolean} [forceLinearTransfer=false] - Whether to force a linear transfer or not. + * @return {GLenum} The internal format. + */ getInternalFormat( internalFormatName, glFormat, glType, colorSpace, forceLinearTransfer = false ) { const { gl, extensions } = this; @@ -45310,6 +53059,12 @@ class WebGLTextureUtils { } + /** + * Sets the texture parameters for the given texture. + * + * @param {GLenum} textureType - The texture type. + * @param {Texture} texture - The texture. + */ setTextureParameters( textureType, texture ) { const { gl, extensions, backend } = this; @@ -45363,6 +53118,12 @@ class WebGLTextureUtils { } + /** + * Creates a default texture for the given texture that can be used + * as a placeholder until the actual texture is ready for usage. + * + * @param {Texture} texture - The texture to create a default texture for. + */ createDefaultTexture( texture ) { const { gl, backend, defaultTextures } = this; @@ -45394,6 +53155,13 @@ class WebGLTextureUtils { } + /** + * Defines a texture on the GPU for the given texture object. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + * @return {undefined} + */ createTexture( texture, options ) { const { gl, backend } = this; @@ -45434,6 +53202,12 @@ class WebGLTextureUtils { } + /** + * Uploads texture buffer data to the GPU memory. + * + * @param {WebGLBuffer} buffer - The buffer data. + * @param {Texture} texture - The texture, + */ copyBufferToTexture( buffer, texture ) { const { gl, backend } = this; @@ -45469,6 +53243,12 @@ class WebGLTextureUtils { } + /** + * Uploads the updated texture data to the GPU. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ updateTexture( texture, options ) { const { gl } = this; @@ -45589,6 +53369,11 @@ class WebGLTextureUtils { } + /** + * Generates mipmaps for the given texture. + * + * @param {Texture} texture - The texture. + */ generateMipmaps( texture ) { const { gl, backend } = this; @@ -45599,6 +53384,11 @@ class WebGLTextureUtils { } + /** + * Deallocates the render buffers of the given render target. + * + * @param {RenderTarget} renderTarget - The render target. + */ deallocateRenderBuffers( renderTarget ) { const { gl, backend } = this; @@ -45659,6 +53449,11 @@ class WebGLTextureUtils { } + /** + * Destroys the GPU data for the given texture object. + * + * @param {Texture} texture - The texture. + */ destroyTexture( texture ) { const { gl, backend } = this; @@ -45671,6 +53466,15 @@ class WebGLTextureUtils { } + /** + * Copies data of the given source texture to the given destination texture. + * + * @param {Texture} srcTexture - The source texture. + * @param {Texture} dstTexture - The destination texture. + * @param {Vector4?} [srcRegion=null] - The region of the source texture to copy. + * @param {(Vector2|Vector3)?} [dstPosition=null] - The destination position of the copy. + * @param {Number} [level=0] - The mip level to copy. + */ copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { const { gl, backend } = this; @@ -45789,6 +53593,13 @@ class WebGLTextureUtils { } + /** + * Copies the current bound framebuffer to the given texture. + * + * @param {Texture} texture - The destination texture. + * @param {RenderContext} renderContext - The render context. + * @param {Vector4} rectangle - A four dimensional vector defining the origin and dimension of the copy. + */ copyFramebufferToTexture( texture, renderContext, rectangle ) { const { gl } = this; @@ -45800,7 +53611,7 @@ class WebGLTextureUtils { const requireDrawFrameBuffer = texture.isDepthTexture === true || ( renderContext.renderTarget && renderContext.renderTarget.samples > 0 ); - const srcHeight = renderContext.renderTarget ? renderContext.renderTarget.height : this.backend.gerDrawingBufferSize().y; + const srcHeight = renderContext.renderTarget ? renderContext.renderTarget.height : this.backend.getDrawingBufferSize().y; if ( requireDrawFrameBuffer ) { @@ -45876,7 +53687,12 @@ class WebGLTextureUtils { } - // Setup storage for internal depth/stencil buffers and bind to correct framebuffer + /** + * SetupS storage for internal depth/stencil buffers and bind to correct framebuffer. + * + * @param {WebGLRenderbuffer} renderbuffer - The render buffer. + * @param {RenderContext} renderContext - The render context. + */ setupRenderBufferStorage( renderbuffer, renderContext ) { const { gl } = this; @@ -45931,6 +53747,18 @@ class WebGLTextureUtils { } + /** + * Returns texture data as a typed array. + * + * @async + * @param {Texture} texture - The texture to copy. + * @param {Number} x - The x coordinate of the copy origin. + * @param {Number} y - The y coordinate of the copy origin. + * @param {Number} width - The width of the copy. + * @param {Number} height - The height of the copy. + * @param {Number} faceIndex - The face index. + * @return {Promise} A Promise that resolves with a typed array when the copy operation has finished. + */ async copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { const { backend, gl } = this; @@ -45972,6 +53800,13 @@ class WebGLTextureUtils { } + /** + * Returns the corresponding typed array type for the given WebGL data type. + * + * @private + * @param {GLenum} glType - The WebGL data type. + * @return {TypedArray.constructor} The typed array type. + */ _getTypedArrayType( glType ) { const { gl } = this; @@ -45991,6 +53826,14 @@ class WebGLTextureUtils { } + /** + * Returns the bytes-per-texel value for the given WebGL data type and texture format. + * + * @private + * @param {GLenum} glType - The WebGL data type. + * @param {GLenum} glFormat - The WebGL texture format. + * @return {Number} The bytes-per-texel. + */ _getBytesPerTexel( glType, glFormat ) { const { gl } = this; @@ -46016,19 +53859,58 @@ class WebGLTextureUtils { } +/** + * A WebGL 2 backend utility module for managing extensions. + * + * @private + */ class WebGLExtensions { + /** + * Constructs a new utility object. + * + * @param {WebGLBackend} backend - The WebGL 2 backend. + */ constructor( backend ) { + /** + * A reference to the WebGL 2 backend. + * + * @type {WebGLBackend} + */ this.backend = backend; + /** + * A reference to the rendering context. + * + * @type {WebGL2RenderingContext} + */ this.gl = this.backend.gl; + + /** + * A list with all the supported WebGL extensions. + * + * @type {Array} + */ this.availableExtensions = this.gl.getSupportedExtensions(); + /** + * A dictionary with requested WebGL extensions. + * The key is the name of the extension, the value + * the requested extension object. + * + * @type {Object} + */ this.extensions = {}; } + /** + * Returns the extension object for the given extension name. + * + * @param {String} name - The extension name. + * @return {Object} The extension object. + */ get( name ) { let extension = this.extensions[ name ]; @@ -46045,6 +53927,12 @@ class WebGLExtensions { } + /** + * Returns `true` if the requested extension is available. + * + * @param {String} name - The extension name. + * @return {Boolean} Whether the given extension is available or not. + */ has( name ) { return this.availableExtensions.includes( name ); @@ -46053,16 +53941,44 @@ class WebGLExtensions { } +/** + * A WebGL 2 backend utility module for managing the device's capabilities. + * + * @private + */ class WebGLCapabilities { + /** + * Constructs a new utility object. + * + * @param {WebGLBackend} backend - The WebGL 2 backend. + */ constructor( backend ) { + /** + * A reference to the WebGL 2 backend. + * + * @type {WebGLBackend} + */ this.backend = backend; + /** + * This value holds the cached max anisotropy value. + * + * @type {Number?} + * @default null + */ this.maxAnisotropy = null; } + /** + * Returns the maximum anisotropy texture filtering value. This value + * depends on the device and is reported by the `EXT_texture_filter_anisotropic` + * WebGL extension. + * + * @return {Number} The maximum anisotropy texture filtering value. + */ getMaxAnisotropy() { if ( this.maxAnisotropy !== null ) return this.maxAnisotropy; @@ -46240,18 +54156,184 @@ class WebGLBufferRenderer { } -// - +/** + * A backend implementation targeting WebGL 2. + * + * @private + * @augments Backend + */ class WebGLBackend extends Backend { + /** + * Constructs a new WebGPU backend. + * + * @param {Object} parameters - The configuration parameter. + * @param {Boolean} [parameters.logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not. + * @param {Boolean} [parameters.alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque. + * @param {Boolean} [parameters.depth=true] - Whether the default framebuffer should have a depth buffer or not. + * @param {Boolean} [parameters.stencil=false] - Whether the default framebuffer should have a stencil buffer or not. + * @param {Boolean} [parameters.antialias=false] - Whether MSAA as the default anti-aliasing should be enabled or not. + * @param {Number} [parameters.samples=0] - When `antialias` is `true`, `4` samples are used by default. Set this parameter to any other integer value than 0 to overwrite the default. + * @param {Boolean} [parameters.forceWebGL=false] - If set to `true`, the renderer uses a WebGL 2 backend no matter if WebGPU is supported or not. + * @param {WebGL2RenderingContext} [parameters.context=undefined] - A WebGL 2 rendering context. + */ constructor( parameters = {} ) { super( parameters ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isWebGLBackend = true; + /** + * A reference to a backend module holding shader attribute-related + * utility functions. + * + * @type {WebGLAttributeUtils?} + * @default null + */ + this.attributeUtils = null; + + /** + * A reference to a backend module holding extension-related + * utility functions. + * + * @type {WebGLExtensions?} + * @default null + */ + this.extensions = null; + + /** + * A reference to a backend module holding capability-related + * utility functions. + * + * @type {WebGLCapabilities?} + * @default null + */ + this.capabilities = null; + + /** + * A reference to a backend module holding texture-related + * utility functions. + * + * @type {WebGLTextureUtils?} + * @default null + */ + this.textureUtils = null; + + /** + * A reference to a backend module holding renderer-related + * utility functions. + * + * @type {WebGLBufferRenderer?} + * @default null + */ + this.bufferRenderer = null; + + /** + * A reference to the rendering context. + * + * @type {WebGL2RenderingContext?} + * @default null + */ + this.gl = null; + + /** + * A reference to a backend module holding state-related + * utility functions. + * + * @type {WebGLState?} + * @default null + */ + this.state = null; + + /** + * A reference to a backend module holding common + * utility functions. + * + * @type {WebGLUtils?} + * @default null + */ + this.utils = null; + + /** + * Dictionary for caching VAOs. + * + * @type {Object} + */ + this.vaoCache = {}; + + /** + * Dictionary for caching transform feedback objects. + * + * @type {Object} + */ + this.transformFeedbackCache = {}; + + /** + * Controls if `gl.RASTERIZER_DISCARD` should be enabled or not. + * Only relevant when using compute shaders. + * + * @type {Boolean} + * @default false + */ + this.discard = false; + + /** + * A reference to the `EXT_disjoint_timer_query_webgl2` extension. `null` if the + * device does not support the extension. + * + * @type {EXTDisjointTimerQueryWebGL2?} + * @default null + */ + this.disjoint = null; + + /** + * A reference to the `KHR_parallel_shader_compile` extension. `null` if the + * device does not support the extension. + * + * @type {KHRParallelShaderCompile?} + * @default null + */ + this.parallel = null; + + /** + * Whether to track timestamps with a Timestamp Query API or not. + * + * @type {Boolean} + * @default false + */ + this.trackTimestamp = ( parameters.trackTimestamp === true ); + + /** + * A reference to the current render context. + * + * @private + * @type {RenderContext} + * @default null + */ + this._currentContext = null; + + /** + * A unique collection of bindings. + * + * @private + * @type {WeakSet} + */ + this._knownBindings = new WeakSet(); + } + /** + * Initializes the backend so it is ready for usage. + * + * @param {Renderer} renderer - The renderer. + */ init( renderer ) { super.init( renderer ); @@ -46292,11 +54374,6 @@ class WebGLBackend extends Backend { this.state = new WebGLState( this ); this.utils = new WebGLUtils( this ); - this.vaoCache = {}; - this.transformFeedbackCache = {}; - this.discard = false; - this.trackTimestamp = ( parameters.trackTimestamp === true ); - this.extensions.get( 'EXT_color_buffer_float' ); this.extensions.get( 'WEBGL_clip_cull_distance' ); this.extensions.get( 'OES_texture_float_linear' ); @@ -46308,30 +54385,52 @@ class WebGLBackend extends Backend { this.disjoint = this.extensions.get( 'EXT_disjoint_timer_query_webgl2' ); this.parallel = this.extensions.get( 'KHR_parallel_shader_compile' ); - this._knownBindings = new WeakSet(); - - this._currentContext = null; - } + /** + * The coordinate system of the backend. + * + * @type {Number} + * @readonly + */ get coordinateSystem() { return WebGLCoordinateSystem; } + /** + * This method performs a readback operation by moving buffer data from + * a storage buffer attribute from the GPU to the CPU. + * + * @async + * @param {StorageBufferAttribute} attribute - The storage buffer attribute. + * @return {Promise} A promise that resolves with the buffer data when the data are ready. + */ async getArrayBufferAsync( attribute ) { return await this.attributeUtils.getArrayBufferAsync( attribute ); } + /** + * Can be used to synchronize CPU operations with GPU tasks. So when this method is called, + * the CPU waits for the GPU to complete its operation (e.g. a compute task). + * + * @async + * @return {Promise} A Promise that resolves when synchronization has been finished. + */ async waitForGPU() { await this.utils._clientWaitAsync(); } + /** + * Inits a time stamp query for the given render context. + * + * @param {RenderContext} renderContext - The render context. + */ initTimestampQuery( renderContext ) { if ( ! this.disjoint || ! this.trackTimestamp ) return; @@ -46366,6 +54465,11 @@ class WebGLBackend extends Backend { // timestamp utils + /** + * Prepares the timestamp buffer. + * + * @param {RenderContext} renderContext - The render context. + */ prepareTimestampBuffer( renderContext ) { if ( ! this.disjoint || ! this.trackTimestamp ) return; @@ -46392,6 +54496,14 @@ class WebGLBackend extends Backend { } + /** + * Resolves the time stamp for the given render context and type. + * + * @async + * @param {RenderContext} renderContext - The render context. + * @param {String} type - The render context. + * @return {Promise} A Promise that resolves when the time stamp has been computed. + */ async resolveTimestampAsync( renderContext, type = 'render' ) { if ( ! this.disjoint || ! this.trackTimestamp ) return; @@ -46421,12 +54533,23 @@ class WebGLBackend extends Backend { } + /** + * Returns the backend's rendering context. + * + * @return {WebGL2RenderingContext} The rendering context. + */ getContext() { return this.gl; } + /** + * This method is executed at the beginning of a render call and prepares + * the WebGL state for upcoming render calls + * + * @param {RenderContext} renderContext - The render context. + */ beginRender( renderContext ) { const { gl } = this; @@ -46482,6 +54605,12 @@ class WebGLBackend extends Backend { } + /** + * This method is executed at the end of a render call and finalizes work + * after draw calls. + * + * @param {RenderContext} renderContext - The render context. + */ finishRender( renderContext ) { const { gl, state } = this; @@ -46588,6 +54717,13 @@ class WebGLBackend extends Backend { } + /** + * This method processes the result of occlusion queries and writes it + * into render context data. + * + * @async + * @param {RenderContext} renderContext - The render context. + */ resolveOccludedAsync( renderContext ) { const renderContextData = this.get( renderContext ); @@ -46646,6 +54782,14 @@ class WebGLBackend extends Backend { } + /** + * Returns `true` if the given 3D object is fully occluded by other + * 3D objects in the scene. + * + * @param {RenderContext} renderContext - The render context. + * @param {Object3D} object - The 3D object to test. + * @return {Boolean} Whether the 3D object is fully occluded or not. + */ isOccluded( renderContext, object ) { const renderContextData = this.get( renderContext ); @@ -46654,6 +54798,11 @@ class WebGLBackend extends Backend { } + /** + * Updates the viewport with the values from the given render context. + * + * @param {RenderContext} renderContext - The render context. + */ updateViewport( renderContext ) { const gl = this.gl; @@ -46663,6 +54812,11 @@ class WebGLBackend extends Backend { } + /** + * Defines the scissor test. + * + * @param {Boolean} boolean - Whether the scissor test should be enabled or not. + */ setScissorTest( boolean ) { const gl = this.gl; @@ -46679,6 +54833,15 @@ class WebGLBackend extends Backend { } + /** + * Performs a clear operation. + * + * @param {Boolean} color - Whether the color buffer should be cleared or not. + * @param {Boolean} depth - Whether the depth buffer should be cleared or not. + * @param {Boolean} stencil - Whether the stencil buffer should be cleared or not. + * @param {Object?} [descriptor=null] - The render context of the current set render target. + * @param {Boolean} [setFrameBuffer=true] - TODO. + */ clear( color, depth, stencil, descriptor = null, setFrameBuffer = true ) { const { gl } = this; @@ -46769,6 +54932,12 @@ class WebGLBackend extends Backend { } + /** + * This method is executed at the beginning of a compute call and + * prepares the state for upcoming compute tasks. + * + * @param {Node|Array} computeGroup - The compute node(s). + */ beginCompute( computeGroup ) { const { state, gl } = this; @@ -46778,11 +54947,19 @@ class WebGLBackend extends Backend { } + /** + * Executes a compute command for the given compute node. + * + * @param {Node|Array} computeGroup - The group of compute nodes of a compute call. Can be a single compute node. + * @param {Node} computeNode - The compute node. + * @param {Array} bindings - The bindings. + * @param {ComputePipeline} pipeline - The compute pipeline. + */ compute( computeGroup, computeNode, bindings, pipeline ) { const { state, gl } = this; - if ( ! this.discard ) { + if ( this.discard === false ) { // required here to handle async behaviour of render.compute() gl.enable( gl.RASTERIZER_DISCARD ); @@ -46847,6 +55024,12 @@ class WebGLBackend extends Backend { } + /** + * This method is executed at the end of a compute call and + * finalizes work after compute tasks. + * + * @param {Node|Array} computeGroup - The compute node(s). + */ finishCompute( computeGroup ) { const gl = this.gl; @@ -46865,6 +55048,12 @@ class WebGLBackend extends Backend { } + /** + * Executes a draw command for the given render object. + * + * @param {RenderObject} renderObject - The render object to draw. + * @param {Info} info - Holds a series of statistical information about the GPU memory and the rendering process. + */ draw( renderObject/*, info*/ ) { const { object, pipeline, material, context, hardwareClippingPlanes } = renderObject; @@ -47027,12 +55216,24 @@ class WebGLBackend extends Backend { } + /** + * Explain why always null is returned. + * + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether the render pipeline requires an update or not. + */ needsRenderUpdate( /*renderObject*/ ) { return false; } + /** + * Explain why no cache key is computed. + * + * @param {RenderObject} renderObject - The render object. + * @return {String} The cache key. + */ getRenderCacheKey( /*renderObject*/ ) { return ''; @@ -47041,53 +55242,109 @@ class WebGLBackend extends Backend { // textures + /** + * Creates a default texture for the given texture that can be used + * as a placeholder until the actual texture is ready for usage. + * + * @param {Texture} texture - The texture to create a default texture for. + */ createDefaultTexture( texture ) { this.textureUtils.createDefaultTexture( texture ); } + /** + * Defines a texture on the GPU for the given texture object. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ createTexture( texture, options ) { this.textureUtils.createTexture( texture, options ); } + /** + * Uploads the updated texture data to the GPU. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ updateTexture( texture, options ) { this.textureUtils.updateTexture( texture, options ); } + /** + * Generates mipmaps for the given texture. + * + * @param {Texture} texture - The texture. + */ generateMipmaps( texture ) { this.textureUtils.generateMipmaps( texture ); } - + /** + * Destroys the GPU data for the given texture object. + * + * @param {Texture} texture - The texture. + */ destroyTexture( texture ) { this.textureUtils.destroyTexture( texture ); } - copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { + /** + * Returns texture data as a typed array. + * + * @async + * @param {Texture} texture - The texture to copy. + * @param {Number} x - The x coordinate of the copy origin. + * @param {Number} y - The y coordinate of the copy origin. + * @param {Number} width - The width of the copy. + * @param {Number} height - The height of the copy. + * @param {Number} faceIndex - The face index. + * @return {Promise} A Promise that resolves with a typed array when the copy operation has finished. + */ + async copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { return this.textureUtils.copyTextureToBuffer( texture, x, y, width, height, faceIndex ); } + /** + * This method does nothing since WebGL 2 has no concept of samplers. + * + * @param {Texture} texture - The texture to create the sampler for. + */ createSampler( /*texture*/ ) { //console.warn( 'Abstract class.' ); } - destroySampler() {} + /** + * This method does nothing since WebGL 2 has no concept of samplers. + * + * @param {Texture} texture - The texture to destroy the sampler for. + */ + destroySampler( /*texture*/ ) {} // node builder + /** + * Returns a node builder for the given render object. + * + * @param {RenderObject} object - The render object. + * @param {Renderer} renderer - The renderer. + * @return {GLSLNodeBuilder} The node builder. + */ createNodeBuilder( object, renderer ) { return new GLSLNodeBuilder( object, renderer ); @@ -47096,6 +55353,11 @@ class WebGLBackend extends Backend { // program + /** + * Creates a shader program from the given programmable stage. + * + * @param {ProgrammableStage} program - The programmable stage. + */ createProgram( program ) { const gl = this.gl; @@ -47112,12 +55374,23 @@ class WebGLBackend extends Backend { } - destroyProgram( /*program*/ ) { + /** + * Destroys the shader program of the given programmable stage. + * + * @param {ProgrammableStage} program - The programmable stage. + */ + destroyProgram( program ) { - console.warn( 'Abstract class.' ); + this.delete( program ); } + /** + * Creates a render pipeline for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @param {Array} promises - An array of compilation promises which are used in `compileAsync()`. + */ createRenderPipeline( renderObject, promises ) { const gl = this.gl; @@ -47176,6 +55449,14 @@ class WebGLBackend extends Backend { } + /** + * Formats the source code of error messages. + * + * @private + * @param {String} string - The code. + * @param {Number} errorLine - The error line. + * @return {String} The formatted code. + */ _handleSource( string, errorLine ) { const lines = string.split( '\n' ); @@ -47195,6 +55476,15 @@ class WebGLBackend extends Backend { } + /** + * Gets the shader compilation errors from the info log. + * + * @private + * @param {WebGL2RenderingContext} gl - The rendering context. + * @param {WebGLShader} shader - The WebGL shader object. + * @param {String} type - The shader type. + * @return {String} The shader errors. + */ _getShaderErrors( gl, shader, type ) { const status = gl.getShaderParameter( shader, gl.COMPILE_STATUS ); @@ -47216,6 +55506,14 @@ class WebGLBackend extends Backend { } + /** + * Logs shader compilation errors. + * + * @private + * @param {WebGLProgram} programGPU - The WebGL program. + * @param {WebGLShader} glFragmentShader - The fragment shader as a native WebGL shader object. + * @param {WebGLShader} glVertexShader - The vertex shader as a native WebGL shader object. + */ _logProgramError( programGPU, glFragmentShader, glVertexShader ) { if ( this.renderer.debug.checkShaderErrors ) { @@ -47258,6 +55556,13 @@ class WebGLBackend extends Backend { } + /** + * Completes the shader program setup for the given render object. + * + * @private + * @param {RenderObject} renderObject - The render object. + * @param {RenderPipeline} pipeline - The render pipeline. + */ _completeCompile( renderObject, pipeline ) { const { state, gl } = this; @@ -47286,6 +55591,12 @@ class WebGLBackend extends Backend { } + /** + * Creates a compute pipeline for the given compute node. + * + * @param {ComputePipeline} computePipeline - The compute pipeline. + * @param {Array} bindings - The bindings. + */ createComputePipeline( computePipeline, bindings ) { const { state, gl } = this; @@ -47380,7 +55691,15 @@ class WebGLBackend extends Backend { } - createBindings( bindGroup, bindings ) { + /** + * Creates bindings from the given bind group definition. + * + * @param {BindGroup} bindGroup - The bind group. + * @param {Array} bindings - Array of bind groups. + * @param {Number} cacheIndex - The cache index. + * @param {Number} version - The version. + */ + createBindings( bindGroup, bindings /*, cacheIndex, version*/ ) { if ( this._knownBindings.has( bindings ) === false ) { @@ -47411,7 +55730,15 @@ class WebGLBackend extends Backend { } - updateBindings( bindGroup /*, bindings*/ ) { + /** + * Updates the given bind group definition. + * + * @param {BindGroup} bindGroup - The bind group. + * @param {Array} bindings - Array of bind groups. + * @param {Number} cacheIndex - The cache index. + * @param {Number} version - The version. + */ + updateBindings( bindGroup /*, bindings, cacheIndex, version*/ ) { const { gl } = this; @@ -47451,6 +55778,11 @@ class WebGLBackend extends Backend { } + /** + * Updates a buffer binding. + * + * @param {Buffer} binding - The buffer binding to update. + */ updateBinding( binding ) { const gl = this.gl; @@ -47470,6 +55802,11 @@ class WebGLBackend extends Backend { // attributes + /** + * Creates the GPU buffer of an indexed shader attribute. + * + * @param {BufferAttribute} attribute - The indexed buffer attribute. + */ createIndexAttribute( attribute ) { const gl = this.gl; @@ -47478,6 +55815,11 @@ class WebGLBackend extends Backend { } + /** + * Creates the GPU buffer of a shader attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ createAttribute( attribute ) { if ( this.has( attribute ) ) return; @@ -47488,6 +55830,11 @@ class WebGLBackend extends Backend { } + /** + * Creates the GPU buffer of a storage attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ createStorageAttribute( attribute ) { if ( this.has( attribute ) ) return; @@ -47498,24 +55845,34 @@ class WebGLBackend extends Backend { } + /** + * Updates the GPU buffer of a shader attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute to update. + */ updateAttribute( attribute ) { this.attributeUtils.updateAttribute( attribute ); } + /** + * Destroys the GPU buffer of a shader attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute to destroy. + */ destroyAttribute( attribute ) { this.attributeUtils.destroyAttribute( attribute ); } - updateSize() { - - //console.warn( 'Abstract class.' ); - - } - + /** + * Checks if the given feature is supported by the backend. + * + * @param {String} name - The feature's name. + * @return {Boolean} Whether the feature is supported or not. + */ hasFeature( name ) { const keysMatching = Object.keys( GLFeatureName ).filter( key => GLFeatureName[ key ] === name ); @@ -47532,24 +55889,51 @@ class WebGLBackend extends Backend { } + /** + * Returns the maximum anisotropy texture filtering value. + * + * @return {Number} The maximum anisotropy texture filtering value. + */ getMaxAnisotropy() { return this.capabilities.getMaxAnisotropy(); } - copyTextureToTexture( srcTexture, dstTexture, srcRegion, dstPosition, level ) { + /** + * Copies data of the given source texture to the given destination texture. + * + * @param {Texture} srcTexture - The source texture. + * @param {Texture} dstTexture - The destination texture. + * @param {Vector4?} [srcRegion=null] - The region of the source texture to copy. + * @param {(Vector2|Vector3)?} [dstPosition=null] - The destination position of the copy. + * @param {Number} [level=0] - The mip level to copy. + */ + copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { this.textureUtils.copyTextureToTexture( srcTexture, dstTexture, srcRegion, dstPosition, level ); } + /** + * Copies the current bound framebuffer to the given texture. + * + * @param {Texture} texture - The destination texture. + * @param {RenderContext} renderContext - The render context. + * @param {Vector4} rectangle - A four dimensional vector defining the origin and dimension of the copy. + */ copyFramebufferToTexture( texture, renderContext, rectangle ) { this.textureUtils.copyFramebufferToTexture( texture, renderContext, rectangle ); } + /** + * Configures the active framebuffer from the given render context. + * + * @private + * @param {RenderContext} descriptor - The render context. + */ _setFramebuffer( descriptor ) { const { gl, state } = this; @@ -47563,6 +55947,8 @@ class WebGLBackend extends Backend { const { samples, depthBuffer, stencilBuffer } = renderTarget; const isCube = renderTarget.isWebGLCubeRenderTarget === true; + const isRenderTarget3D = renderTarget.isRenderTarget3D === true; + const isRenderTargetArray = renderTarget.isRenderTargetArray === true; let msaaFb = renderTargetContextData.msaaFrameBuffer; let depthRenderbuffer = renderTargetContextData.depthRenderbuffer; @@ -47616,7 +56002,19 @@ class WebGLBackend extends Backend { const attachment = gl.COLOR_ATTACHMENT0 + i; - gl.framebufferTexture2D( gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureData.textureGPU, 0 ); + if ( isRenderTarget3D || isRenderTargetArray ) { + + const layer = this.renderer._activeCubeFace; + + gl.framebufferTextureLayer( gl.FRAMEBUFFER, attachment, textureData.textureGPU, 0, layer ); + + } else { + + gl.framebufferTexture2D( gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureData.textureGPU, 0 ); + + } + + } @@ -47708,10 +56106,17 @@ class WebGLBackend extends Backend { } - + /** + * Computes the VAO key for the given index and attributes. + * + * @private + * @param {BufferAttribute?} index - The index. `null` for non-indexed geometries. + * @param {Array} attributes - An array of buffer attributes. + * @return {String} The VAO key. + */ _getVaoKey( index, attributes ) { - let key = []; + let key = ''; if ( index !== null ) { @@ -47733,6 +56138,14 @@ class WebGLBackend extends Backend { } + /** + * Creates a VAO from the index and attributes. + * + * @private + * @param {BufferAttribute?} index - The index. `null` for non-indexed geometries. + * @param {Array} attributes - An array of buffer attributes. + * @return {Object} The VAO data. + */ _createVao( index, attributes ) { const { gl } = this; @@ -47810,6 +56223,13 @@ class WebGLBackend extends Backend { } + /** + * Creates a transform feedback from the given transform buffers. + * + * @private + * @param {Array} transformBuffers - The transform buffers. + * @return {WebGLTransformFeedback} The transform feedback. + */ _getTransformFeedback( transformBuffers ) { let key = ''; @@ -47850,7 +56270,13 @@ class WebGLBackend extends Backend { } - + /** + * Setups the given bindings. + * + * @private + * @param {Array} bindings - The bindings. + * @param {WebGLProgram} programGPU - The WebGL program. + */ _setupBindings( bindings, programGPU ) { const gl = this.gl; @@ -47880,6 +56306,12 @@ class WebGLBackend extends Backend { } + /** + * Binds the given uniforms. + * + * @private + * @param {Array} bindings - The bindings. + */ _bindUniforms( bindings ) { const { gl, state } = this; @@ -47908,6 +56340,9 @@ class WebGLBackend extends Backend { } + /** + * Frees internal resources. + */ dispose() { this.renderer.domElement.removeEventListener( 'webglcontextlost', this._onContextLost ); @@ -48211,32 +56646,90 @@ const GPUFeatureName = { Subgroups: 'subgroups' }; +/** + * Represents a sampler binding type. + * + * @private + * @augments Binding + */ class Sampler extends Binding { + /** + * Constructs a new sampler. + * + * @param {String} name - The samplers's name. + * @param {Texture?} texture - The texture this binding is referring to. + */ constructor( name, texture ) { super( name ); + /** + * The texture the sampler is referring to. + * + * @type {Texture?} + */ this.texture = texture; + + /** + * The binding's version. + * + * @type {Number} + */ this.version = texture ? texture.version : 0; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isSampler = true; } } +/** + * A special form of sampler binding type. + * It's texture value is managed by a node object. + * + * @private + * @augments Sampler + */ class NodeSampler extends Sampler { + /** + * Constructs a new node-based sampler. + * + * @param {String} name - The samplers's name. + * @param {TextureNode} textureNode - The texture node. + * @param {UniformGroupNode} groupNode - The uniform group node. + */ constructor( name, textureNode, groupNode ) { super( name, textureNode ? textureNode.value : null ); + /** + * The texture node. + * + * @type {TextureNode} + */ this.textureNode = textureNode; + + /** + * The uniform group node. + * + * @type {UniformGroupNode} + */ this.groupNode = groupNode; } + /** + * Updates the texture value of this sampler. + */ update() { this.texture = this.textureNode.value; @@ -48245,14 +56738,38 @@ class NodeSampler extends Sampler { } +/** + * Represents a storage buffer binding type. + * + * @private + * @augments Buffer + */ class StorageBuffer extends Buffer { + /** + * Constructs a new uniform buffer. + * + * @param {String} name - The buffer's name. + * @param {BufferAttribute} attribute - The buffer attribute. + */ constructor( name, attribute ) { super( name, attribute ? attribute.array : null ); + /** + * This flag can be used for type testing. + * + * @type {BufferAttribute} + */ this.attribute = attribute; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isStorageBuffer = true; } @@ -48261,18 +56778,53 @@ class StorageBuffer extends Buffer { let _id = 0; +/** + * A special form of storage buffer binding type. + * It's buffer value is managed by a node object. + * + * @private + * @augments StorageBuffer + */ class NodeStorageBuffer extends StorageBuffer { + /** + * Constructs a new node-based storage buffer. + * + * @param {StorageBufferNode} nodeUniform - The storage buffer node. + * @param {UniformGroupNode} groupNode - The uniform group node. + */ constructor( nodeUniform, groupNode ) { super( 'StorageBuffer_' + _id ++, nodeUniform ? nodeUniform.value : null ); + /** + * The node uniform. + * + * @type {StorageBufferNode} + */ this.nodeUniform = nodeUniform; + + /** + * The access type. + * + * @type {String} + */ this.access = nodeUniform ? nodeUniform.access : NodeAccess.READ_WRITE; + + /** + * The uniform group node. + * + * @type {UniformGroupNode} + */ this.groupNode = groupNode; } + /** + * The storage buffer. + * + * @type {BufferAttribute} + */ get buffer() { return this.nodeUniform.value; @@ -48281,12 +56833,27 @@ class NodeStorageBuffer extends StorageBuffer { } +/** + * A WebGPU backend utility module used by {@link WebGPUTextureUtils}. + * + * @private + */ class WebGPUTexturePassUtils extends DataMap { + /** + * Constructs a new utility object. + * + * @param {GPUDevice} device - The WebGPU device. + */ constructor( device ) { super(); + /** + * The WebGPU device. + * + * @type {GPUDevice} + */ this.device = device; const mipmapVertexSource = ` @@ -48351,23 +56918,62 @@ fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { } `; + + /** + * The mipmap GPU sampler. + * + * @type {GPUSampler} + */ this.mipmapSampler = device.createSampler( { minFilter: GPUFilterMode.Linear } ); + + /** + * The flipY GPU sampler. + * + * @type {GPUSampler} + */ this.flipYSampler = device.createSampler( { minFilter: GPUFilterMode.Nearest } ); //@TODO?: Consider using textureLoad() - // We'll need a new pipeline for every texture format used. + /** + * A cache for GPU render pipelines used for copy/transfer passes. + * Every texture format requires a unique pipeline. + * + * @type {Object} + */ this.transferPipelines = {}; + + /** + * A cache for GPU render pipelines used for flipY passes. + * Every texture format requires a unique pipeline. + * + * @type {Object} + */ this.flipYPipelines = {}; + /** + * The mipmap vertex shader module. + * + * @type {GPUShaderModule} + */ this.mipmapVertexShaderModule = device.createShaderModule( { label: 'mipmapVertex', code: mipmapVertexSource } ); + /** + * The mipmap fragment shader module. + * + * @type {GPUShaderModule} + */ this.mipmapFragmentShaderModule = device.createShaderModule( { label: 'mipmapFragment', code: mipmapFragmentSource } ); + /** + * The flipY fragment shader module. + * + * @type {GPUShaderModule} + */ this.flipYFragmentShaderModule = device.createShaderModule( { label: 'flipYFragment', code: flipYFragmentSource @@ -48375,6 +56981,13 @@ fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { } + /** + * Returns a render pipeline for the internal copy render pass. The pass + * requires a unique render pipeline for each texture format. + * + * @param {String} format - The GPU texture format + * @return {GPURenderPipeline} The GPU render pipeline. + */ getTransferPipeline( format ) { let pipeline = this.transferPipelines[ format ]; @@ -48407,6 +57020,13 @@ fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { } + /** + * Returns a render pipeline for the flipY render pass. The pass + * requires a unique render pipeline for each texture format. + * + * @param {String} format - The GPU texture format + * @return {GPURenderPipeline} The GPU render pipeline. + */ getFlipYPipeline( format ) { let pipeline = this.flipYPipelines[ format ]; @@ -48439,6 +57059,13 @@ fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { } + /** + * Flip the contents of the given GPU texture along its vertical axis. + * + * @param {GPUTexture} textureGPU - The GPU texture object. + * @param {Object} textureGPUDescriptor - The texture descriptor. + * @param {Number} [baseArrayLayer=0] - The index of the first array layer accessible to the texture view. + */ flipY( textureGPU, textureGPUDescriptor, baseArrayLayer = 0 ) { const format = textureGPUDescriptor.format; @@ -48509,6 +57136,13 @@ fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { } + /** + * Generates mipmaps for the given GPU texture. + * + * @param {GPUTexture} textureGPU - The GPU texture object. + * @param {Object} textureGPUDescriptor - The texture descriptor. + * @param {Number} [baseArrayLayer=0] - The index of the first array layer accessible to the texture view. + */ generateMipmaps( textureGPU, textureGPUDescriptor, baseArrayLayer = 0 ) { const textureData = this.get( textureGPU ); @@ -48534,6 +57168,15 @@ fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { } + /** + * Since multiple copy render passes are required to generate mipmaps, the passes + * are managed as render bundles to improve performance. + * + * @param {GPUTexture} textureGPU - The GPU texture object. + * @param {Object} textureGPUDescriptor - The texture descriptor. + * @param {Number} baseArrayLayer - The index of the first array layer accessible to the texture view. + * @return {Array} An array of render bundles. + */ _mipmapCreateBundles( textureGPU, textureGPUDescriptor, baseArrayLayer ) { const pipeline = this.getTransferPipeline( textureGPUDescriptor.format ); @@ -48599,6 +57242,12 @@ fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { } + /** + * Executes the render bundles. + * + * @param {GPUCommandEncoder} commandEncoder - The GPU command encoder. + * @param {Array} passes - An array of render bundles. + */ _mipmapRunBundles( commandEncoder, passes ) { const levels = passes.length; @@ -48632,25 +57281,82 @@ const _compareToWebGPU = { const _flipMap = [ 0, 1, 3, 2, 4, 5 ]; +/** + * A WebGPU backend utility module for managing textures. + * + * @private + */ class WebGPUTextureUtils { + /** + * Constructs a new utility object. + * + * @param {WebGPUBackend} backend - The WebGPU backend. + */ constructor( backend ) { + /** + * A reference to the WebGPU backend. + * + * @type {WebGPUBackend} + */ this.backend = backend; + /** + * A reference to the pass utils. + * + * @type {WebGPUTexturePassUtils?} + * @default null + */ this._passUtils = null; + /** + * A dictionary for managing default textures. The key + * is the texture format, the value the texture object. + * + * @type {Object} + */ this.defaultTexture = {}; + + /** + * A dictionary for managing default cube textures. The key + * is the texture format, the value the texture object. + * + * @type {Object} + */ this.defaultCubeTexture = {}; + + /** + * A default video frame. + * + * @type {VideoFrame?} + * @default null + */ this.defaultVideoFrame = null; + /** + * Represents the color attachment of the default framebuffer. + * + * @type {GPUTexture?} + * @default null + */ this.colorBuffer = null; + /** + * Represents the depth attachment of the default framebuffer. + * + * @type {DepthTexture} + */ this.depthTexture = new DepthTexture(); this.depthTexture.name = 'depthBuffer'; } + /** + * Creates a GPU sampler for the given texture. + * + * @param {Texture} texture - The texture to create the sampler for. + */ createSampler( texture ) { const backend = this.backend; @@ -48686,6 +57392,12 @@ class WebGPUTextureUtils { } + /** + * Creates a default texture for the given texture that can be used + * as a placeholder until the actual texture is ready for usage. + * + * @param {Texture} texture - The texture to create a default texture for. + */ createDefaultTexture( texture ) { let textureGPU; @@ -48710,6 +57422,13 @@ class WebGPUTextureUtils { } + /** + * Defines a texture on the GPU for the given texture object. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + * @return {undefined} + */ createTexture( texture, options = {} ) { const backend = this.backend; @@ -48821,6 +57540,11 @@ class WebGPUTextureUtils { } + /** + * Destroys the GPU data for the given texture object. + * + * @param {Texture} texture - The texture. + */ destroyTexture( texture ) { const backend = this.backend; @@ -48834,6 +57558,11 @@ class WebGPUTextureUtils { } + /** + * Destroys the GPU sampler for the given texture. + * + * @param {Texture} texture - The texture to destroy the sampler for. + */ destroySampler( texture ) { const backend = this.backend; @@ -48843,6 +57572,11 @@ class WebGPUTextureUtils { } + /** + * Generates mipmaps for the given texture. + * + * @param {Texture} texture - The texture. + */ generateMipmaps( texture ) { const textureData = this.backend.get( texture ); @@ -48869,6 +57603,12 @@ class WebGPUTextureUtils { } + /** + * Returns the color buffer representing the color + * attachment of the default framebuffer. + * + * @return {GPUTexture} The color buffer. + */ getColorBuffer() { if ( this.colorBuffer ) this.colorBuffer.destroy(); @@ -48892,6 +57632,14 @@ class WebGPUTextureUtils { } + /** + * Returns the depth buffer representing the depth + * attachment of the default framebuffer. + * + * @param {Boolean} [depth=true] - Whether depth is enabled or not. + * @param {Boolean} [stencil=false] - Whether stencil is enabled or not. + * @return {GPUTexture} The depth buffer. + */ getDepthBuffer( depth = true, stencil = false ) { const backend = this.backend; @@ -48938,6 +57686,12 @@ class WebGPUTextureUtils { } + /** + * Uploads the updated texture data to the GPU. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ updateTexture( texture, options ) { const textureData = this.backend.get( texture ); @@ -48989,6 +57743,18 @@ class WebGPUTextureUtils { } + /** + * Returns texture data as a typed array. + * + * @async + * @param {Texture} texture - The texture to copy. + * @param {Number} x - The x coordinate of the copy origin. + * @param {Number} y - The y coordinate of the copy origin. + * @param {Number} width - The width of the copy. + * @param {Number} height - The height of the copy. + * @param {Number} faceIndex - The face index. + * @return {Promise} A Promise that resolves with a typed array when the copy operation has finished. + */ async copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { const device = this.backend.device; @@ -49038,6 +57804,13 @@ class WebGPUTextureUtils { } + /** + * Returns `true` if the given texture is an environment map. + * + * @private + * @param {Texture} texture - The texture. + * @return {Boolean} Whether the given texture is an environment map or not. + */ _isEnvironmentTexture( texture ) { const mapping = texture.mapping; @@ -49046,6 +57819,13 @@ class WebGPUTextureUtils { } + /** + * Returns the default GPU texture for the given format. + * + * @private + * @param {String} format - The GPU format. + * @return {GPUTexture} The GPU texture. + */ _getDefaultTextureGPU( format ) { let defaultTexture = this.defaultTexture[ format ]; @@ -49066,6 +57846,13 @@ class WebGPUTextureUtils { } + /** + * Returns the default GPU cube texture for the given format. + * + * @private + * @param {String} format - The GPU format. + * @return {GPUTexture} The GPU texture. + */ _getDefaultCubeTextureGPU( format ) { let defaultCubeTexture = this.defaultTexture[ format ]; @@ -49086,6 +57873,12 @@ class WebGPUTextureUtils { } + /** + * Returns the default video frame used as default data in context of video textures. + * + * @private + * @return {VideoFrame} The video frame. + */ _getDefaultVideoFrame() { let defaultVideoFrame = this.defaultVideoFrame; @@ -49107,6 +57900,15 @@ class WebGPUTextureUtils { } + /** + * Uploads cube texture image data to the GPU memory. + * + * @private + * @param {Array} images - The cube image data. + * @param {GPUTexture} textureGPU - The GPU texture. + * @param {Object} textureDescriptorGPU - The GPU texture descriptor. + * @param {Boolean} flipY - Whether to flip texture data along their vertical axis or not. + */ _copyCubeMapToTexture( images, textureGPU, textureDescriptorGPU, flipY ) { for ( let i = 0; i < 6; i ++ ) { @@ -49129,13 +57931,24 @@ class WebGPUTextureUtils { } + /** + * Uploads texture image data to the GPU memory. + * + * @private + * @param {HTMLImageElement|ImageBitmap|HTMLCanvasElement} image - The image data. + * @param {GPUTexture} textureGPU - The GPU texture. + * @param {Object} textureDescriptorGPU - The GPU texture descriptor. + * @param {Number} originDepth - The origin depth. + * @param {Boolean} flipY - Whether to flip texture data along their vertical axis or not. + */ _copyImageToTexture( image, textureGPU, textureDescriptorGPU, originDepth, flipY ) { const device = this.backend.device; device.queue.copyExternalImageToTexture( { - source: image + source: image, + flipY: flipY }, { texture: textureGPU, mipLevel: 0, @@ -49147,14 +57960,14 @@ class WebGPUTextureUtils { } ); - if ( flipY === true ) { - - this._flipY( textureGPU, textureDescriptorGPU, originDepth ); - - } - } + /** + * Returns the pass utils singleton. + * + * @private + * @return {WebGPUTexturePassUtils} The utils instance. + */ _getPassUtils() { let passUtils = this._passUtils; @@ -49169,18 +57982,45 @@ class WebGPUTextureUtils { } + /** + * Generates mipmaps for the given GPU texture. + * + * @private + * @param {GPUTexture} textureGPU - The GPU texture object. + * @param {Object} textureDescriptorGPU - The texture descriptor. + * @param {Number} [baseArrayLayer=0] - The index of the first array layer accessible to the texture view. + */ _generateMipmaps( textureGPU, textureDescriptorGPU, baseArrayLayer = 0 ) { this._getPassUtils().generateMipmaps( textureGPU, textureDescriptorGPU, baseArrayLayer ); } + /** + * Flip the contents of the given GPU texture along its vertical axis. + * + * @private + * @param {GPUTexture} textureGPU - The GPU texture object. + * @param {Object} textureDescriptorGPU - The texture descriptor. + * @param {Number} [originDepth=0] - The origin depth. + */ _flipY( textureGPU, textureDescriptorGPU, originDepth = 0 ) { this._getPassUtils().flipY( textureGPU, textureDescriptorGPU, originDepth ); } + /** + * Uploads texture buffer data to the GPU memory. + * + * @private + * @param {Object} image - An object defining the image buffer data. + * @param {GPUTexture} textureGPU - The GPU texture. + * @param {Object} textureDescriptorGPU - The GPU texture descriptor. + * @param {Number} originDepth - The origin depth. + * @param {Boolean} flipY - Whether to flip texture data along their vertical axis or not. + * @param {Number} [depth=0] - TODO. + */ _copyBufferToTexture( image, textureGPU, textureDescriptorGPU, originDepth, flipY, depth = 0 ) { // @TODO: Consider to use GPUCommandEncoder.copyBufferToTexture() @@ -49218,6 +58058,14 @@ class WebGPUTextureUtils { } + /** + * Uploads compressed texture data to the GPU memory. + * + * @private + * @param {Array} mipmaps - An array with mipmap data. + * @param {GPUTexture} textureGPU - The GPU texture. + * @param {Object} textureDescriptorGPU - The GPU texture descriptor. + */ _copyCompressedBufferToTexture( mipmaps, textureGPU, textureDescriptorGPU ) { // @TODO: Consider to use GPUCommandEncoder.copyBufferToTexture() @@ -49265,10 +58113,16 @@ class WebGPUTextureUtils { } + /** + * This method is only relevant for compressed texture formats. It returns a block + * data descriptor for the given GPU compressed texture format. + * + * @private + * @param {String} format - The GPU compressed texture format. + * @return {Object} The block data descriptor. + */ _getBlockData( format ) { - // this method is only relevant for compressed texture formats - if ( format === GPUTextureFormat.BC1RGBAUnorm || format === GPUTextureFormat.BC1RGBAUnormSRGB ) return { byteLength: 8, width: 4, height: 4 }; // DXT1 if ( format === GPUTextureFormat.BC2RGBAUnorm || format === GPUTextureFormat.BC2RGBAUnormSRGB ) return { byteLength: 16, width: 4, height: 4 }; // DXT3 if ( format === GPUTextureFormat.BC3RGBAUnorm || format === GPUTextureFormat.BC3RGBAUnormSRGB ) return { byteLength: 16, width: 4, height: 4 }; // DXT5 @@ -49302,6 +58156,13 @@ class WebGPUTextureUtils { } + /** + * Converts the three.js uv wrapping constants to GPU address mode constants. + * + * @private + * @param {Number} value - The three.js constant defining a uv wrapping mode. + * @return {String} The GPU address mode. + */ _convertAddressMode( value ) { let addressMode = GPUAddressMode.ClampToEdge; @@ -49320,6 +58181,13 @@ class WebGPUTextureUtils { } + /** + * Converts the three.js filter constants to GPU filter constants. + * + * @private + * @param {Number} value - The three.js constant defining a filter mode. + * @return {String} The GPU filter mode. + */ _convertFilterMode( value ) { let filterMode = GPUFilterMode.Linear; @@ -49334,6 +58202,13 @@ class WebGPUTextureUtils { } + /** + * Returns the bytes-per-texel value for the given GPU texture format. + * + * @private + * @param {String} format - The GPU texture format. + * @return {Number} The bytes-per-texel. + */ _getBytesPerTexel( format ) { // 8-bit formats @@ -49390,6 +58265,13 @@ class WebGPUTextureUtils { } + /** + * Returns the corresponding typed array type for the given GPU texture format. + * + * @private + * @param {String} format - The GPU texture format. + * @return {TypedArray.constructor} The typed array type. + */ _getTypedArrayType( format ) { if ( format === GPUTextureFormat.R8Uint ) return Uint8Array; @@ -49440,6 +58322,13 @@ class WebGPUTextureUtils { } + /** + * Returns the GPU dimensions for the given texture. + * + * @private + * @param {Texture} texture - The texture. + * @return {String} The GPU dimension. + */ _getDimension( texture ) { let dimension; @@ -49460,6 +58349,14 @@ class WebGPUTextureUtils { } +/** + * Returns the GPU format for the given texture. + * + * @param {Texture} texture - The texture. + * @param {GPUDevice?} [device=null] - The GPU device which is used for feature detection. + * It is not necessary to apply the device for most formats. + * @return {String} The GPU format. + */ function getFormat( texture, device = null ) { const format = texture.format; @@ -50162,30 +59059,83 @@ if ( ( typeof navigator !== 'undefined' && /Firefox|Deno/g.test( navigator.userA } -// - +/** + * A node builder targeting WGSL. + * + * This module generates WGSL shader code from node materials and also + * generates the respective bindings and vertex buffer definitions. These + * data are later used by the renderer to create render and compute pipelines + * for render objects. + * + * @augments NodeBuilder + */ class WGSLNodeBuilder extends NodeBuilder { + /** + * Constructs a new WGSL node builder renderer. + * + * @param {Object3D} object - The 3D object. + * @param {Renderer} renderer - The renderer. + */ constructor( object, renderer ) { super( object, renderer, new WGSLNodeParser() ); + /** + * A dictionary that holds for each shader stage ('vertex', 'fragment', 'compute') + * another dictionary which manages UBOs per group ('render','frame','object'). + * + * @type {Object>} + */ this.uniformGroups = {}; + /** + * A dictionary that holds for each shader stage a Map of builtins. + * + * @type {Object>} + */ this.builtins = {}; + /** + * A dictionary that holds for each shader stage a Set of directives. + * + * @type {Object>} + */ this.directives = {}; + /** + * A map for managing scope arrays. Only relevant for when using + * {@link module:WorkgroupInfoNode} in context of compute shaders. + * + * @type {Map} + */ this.scopedArrays = new Map(); } + /** + * Checks if the given texture requires a manual conversion to the working color space. + * + * @param {Texture} texture - The texture to check. + * @return {Boolean} Whether the given texture requires a conversion to working color space or not. + */ needsToWorkingColorSpace( texture ) { return texture.isVideoTexture === true && texture.colorSpace !== NoColorSpace; } + /** + * Generates the WGSL snippet for sampled textures. + * + * @private + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ _generateTextureSample( texture, textureProperty, uvSnippet, depthSnippet, shaderStage = this.shaderStage ) { if ( shaderStage === 'fragment' ) { @@ -50212,6 +59162,15 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet when sampling video textures. + * + * @private + * @param {String} textureProperty - The name of the video texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ _generateVideoSample( textureProperty, uvSnippet, shaderStage = this.shaderStage ) { if ( shaderStage === 'fragment' ) { @@ -50226,6 +59185,18 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet when sampling textures with explicit mip level. + * + * @private + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String} levelSnippet - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ _generateTextureSampleLevel( texture, textureProperty, uvSnippet, levelSnippet, depthSnippet, shaderStage = this.shaderStage ) { if ( ( shaderStage === 'fragment' || shaderStage === 'compute' ) && this.isUnfilterable( texture ) === false ) { @@ -50244,9 +59215,15 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates a wrap function used in context of textures. + * + * @param {Texture} texture - The texture to generate the function for. + * @return {String} The name of the generated function. + */ generateWrapFunction( texture ) { - const functionName = `tsl_coord_${ wrapNames[ texture.wrapS ] }S_${ wrapNames[ texture.wrapT ] }T`; + const functionName = `tsl_coord_${ wrapNames[ texture.wrapS ] }S_${ wrapNames[ texture.wrapT ] }_${texture.isData3DTexture ? '3d' : '2d'}T`; let nodeCode = wgslCodeCache[ functionName ]; @@ -50254,7 +59231,9 @@ class WGSLNodeBuilder extends NodeBuilder { const includes = []; - let code = `fn ${ functionName }( coord : vec2f ) -> vec2f {\n\n\treturn vec2f(\n`; + // For 3D textures, use vec3f; for texture arrays, keep vec2f since array index is separate + const coordType = texture.isData3DTexture ? 'vec3f' : 'vec2f'; + let code = `fn ${functionName}( coord : ${coordType} ) -> ${coordType} {\n\n\treturn ${coordType}(\n`; const addWrapSnippet = ( wrap, axis ) => { @@ -50292,6 +59271,13 @@ class WGSLNodeBuilder extends NodeBuilder { addWrapSnippet( texture.wrapT, 'y' ); + if ( texture.isData3DTexture ) { + + code += ',\n'; + addWrapSnippet( texture.wrapR, 'z' ); + + } + code += '\n\t);\n\n}\n'; wgslCodeCache[ functionName ] = nodeCode = new CodeNode( code, includes ); @@ -50304,6 +59290,16 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates a WGSL variable that holds the texture dimension of the given texture. + * It also returns information about the the number of layers (elements) of an arrayed + * texture as well as the cube face count of cube textures. + * + * @param {Texture} texture - The texture to generate the function for. + * @param {String} textureProperty - The name of the video texture uniform in the shader. + * @param {String} levelSnippet - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @return {String} The name of the dimension variable. + */ generateTextureDimension( texture, textureProperty, levelSnippet ) { const textureData = this.getDataFromNode( texture, this.shaderStage, this.globalCache ); @@ -50315,29 +59311,72 @@ class WGSLNodeBuilder extends NodeBuilder { if ( textureData.dimensionsSnippet[ levelSnippet ] === undefined ) { let textureDimensionsParams; + let dimensionType; const { primarySamples } = this.renderer.backend.utils.getTextureSampleData( texture ); + const isMultisampled = primarySamples > 1; + + if ( texture.isData3DTexture ) { + + dimensionType = 'vec3'; + + } else { + + // Regular 2D textures, depth textures, etc. + dimensionType = 'vec2'; + + } - if ( primarySamples > 1 ) { + // Build parameters string based on texture type and multisampling + if ( isMultisampled || texture.isVideoTexture || texture.isStorageTexture ) { textureDimensionsParams = textureProperty; } else { - textureDimensionsParams = `${ textureProperty }, u32( ${ levelSnippet } )`; + textureDimensionsParams = `${textureProperty}${levelSnippet ? `, u32( ${ levelSnippet } )` : ''}`; } - textureDimensionNode = new VarNode( new ExpressionNode( `textureDimensions( ${ textureDimensionsParams } )`, 'uvec2' ) ); + textureDimensionNode = new VarNode( new ExpressionNode( `textureDimensions( ${ textureDimensionsParams } )`, dimensionType ) ); textureData.dimensionsSnippet[ levelSnippet ] = textureDimensionNode; + if ( texture.isDataArrayTexture || texture.isData3DTexture ) { + + textureData.arrayLayerCount = new VarNode( + new ExpressionNode( + `textureNumLayers(${textureProperty})`, + 'u32' + ) + ); + + } + + // For cube textures, we know it's always 6 faces + if ( texture.isTextureCube ) { + + textureData.cubeFaceCount = new VarNode( + new ExpressionNode( '6u', 'u32' ) + ); + + } + } return textureDimensionNode.build( this ); } + /** + * Generates the WGSL snippet for a manual filtered texture. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String} levelSnippet - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @return {String} The WGSL snippet. + */ generateFilteredTexture( texture, textureProperty, uvSnippet, levelSnippet = '0u' ) { this._include( 'biquadraticTexture' ); @@ -50349,17 +59388,39 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet for a texture lookup with explicit level-of-detail. + * Since it's a lookup, no sampling or filtering is applied. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [levelSnippet='0u'] - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @return {String} The WGSL snippet. + */ generateTextureLod( texture, textureProperty, uvSnippet, depthSnippet, levelSnippet = '0u' ) { const wrapFunction = this.generateWrapFunction( texture ); const textureDimension = this.generateTextureDimension( texture, textureProperty, levelSnippet ); - const coordSnippet = `vec2u( ${ wrapFunction }( ${ uvSnippet } ) * vec2f( ${ textureDimension } ) )`; + const vecType = texture.isData3DTexture ? 'vec3' : 'vec2'; + const coordSnippet = `${vecType}(${wrapFunction}(${uvSnippet}) * ${vecType}(${textureDimension}))`; return this.generateTextureLoad( texture, textureProperty, coordSnippet, depthSnippet, levelSnippet ); } + /** + * Generates the WGSL snippet that reads a single texel from a texture without sampling or filtering. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvIndexSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [levelSnippet='0u'] - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @return {String} The WGSL snippet. + */ generateTextureLoad( texture, textureProperty, uvIndexSnippet, depthSnippet, levelSnippet = '0u' ) { if ( texture.isVideoTexture === true || texture.isStorageTexture === true ) { @@ -50378,18 +59439,39 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet that writes a single texel to a texture. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvIndexSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String} valueSnippet - A WGSL snippet that represent the new texel value. + * @return {String} The WGSL snippet. + */ generateTextureStore( texture, textureProperty, uvIndexSnippet, valueSnippet ) { return `textureStore( ${ textureProperty }, ${ uvIndexSnippet }, ${ valueSnippet } )`; } + /** + * Returns `true` if the sampled values of the given texture should be compared against a reference value. + * + * @param {Texture} texture - The texture. + * @return {Boolean} Whether the sampled values of the given texture should be compared against a reference value or not. + */ isSampleCompare( texture ) { return texture.isDepthTexture === true && texture.compareFunction !== null; } + /** + * Returns `true` if the given texture is unfilterable. + * + * @param {Texture} texture - The texture. + * @return {Boolean} Whether the given texture is unfilterable or not. + */ isUnfilterable( texture ) { return this.getComponentTypeFromTexture( texture ) !== 'float' || @@ -50399,6 +59481,16 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet for sampling/loading the given texture. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ generateTexture( texture, textureProperty, uvSnippet, depthSnippet, shaderStage = this.shaderStage ) { let snippet = null; @@ -50421,6 +59513,17 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet for sampling/loading the given texture using explicit gradients. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {Array} gradSnippet - An array holding both gradient WGSL snippets. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ generateTextureGrad( texture, textureProperty, uvSnippet, gradSnippet, depthSnippet, shaderStage = this.shaderStage ) { if ( shaderStage === 'fragment' ) { @@ -50436,6 +59539,18 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet for sampling a depth texture and comparing the sampled depth values + * against a reference value. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String} compareSnippet - A WGSL snippet that represents the reference value. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ generateTextureCompare( texture, textureProperty, uvSnippet, compareSnippet, depthSnippet, shaderStage = this.shaderStage ) { if ( shaderStage === 'fragment' ) { @@ -50450,6 +59565,17 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet when sampling textures with explicit mip level. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String} levelSnippet - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ generateTextureLevel( texture, textureProperty, uvSnippet, levelSnippet, depthSnippet, shaderStage = this.shaderStage ) { let snippet = null; @@ -50468,6 +59594,17 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet when sampling textures with a bias to the mip level. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String} biasSnippet - A WGSL snippet that represents the bias to apply to the mip level before sampling. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ generateTextureBias( texture, textureProperty, uvSnippet, biasSnippet, depthSnippet, shaderStage = this.shaderStage ) { if ( shaderStage === 'fragment' ) { @@ -50482,6 +59619,13 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Returns a WGSL snippet that represents the property name of the given node. + * + * @param {Node} node - The node. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The property name. + */ getPropertyName( node, shaderStage = this.shaderStage ) { if ( node.isNodeVarying === true && node.needsInterpolation === true ) { @@ -50517,18 +59661,36 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Returns the output struct name. + * + * @return {String} The name of the output struct. + */ getOutputStructName() { return 'output'; } + /** + * Returns uniforms group count for the given shader stage. + * + * @private + * @param {String} shaderStage - The shader stage. + * @return {Number} The uniforms group count for the given shader stage. + */ _getUniformGroupCount( shaderStage ) { return Object.keys( this.uniforms[ shaderStage ] ).length; } + /** + * Returns the native shader operator name for a given generic name. + * + * @param {String} op - The operator name to resolve. + * @return {String} The resolved operator name. + */ getFunctionOperator( op ) { const fnOp = wgslFnOpLib[ op ]; @@ -50545,6 +59707,13 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Returns the node access for the given node and shader stage. + * + * @param {StorageTextureNode|StorageBufferNode} node - The storage node. + * @param {String} shaderStage - The shader stage. + * @return {String} The node access. + */ getNodeAccess( node, shaderStage ) { if ( shaderStage !== 'compute' ) @@ -50554,12 +59723,32 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Returns A WGSL snippet representing the storage access. + * + * @param {StorageTextureNode|StorageBufferNode} node - The storage node. + * @param {String} shaderStage - The shader stage. + * @return {String} The WGSL snippet representing the storage access. + */ getStorageAccess( node, shaderStage ) { return accessNames[ this.getNodeAccess( node, shaderStage ) ]; } + /** + * This method is one of the more important ones since it's responsible + * for generating a matching binding instance for the given uniform node. + * + * These bindings are later used in the renderer to create bind groups + * and layouts. + * + * @param {UniformNode} node - The uniform node. + * @param {String} type - The node data type. + * @param {String} shaderStage - The shader stage. + * @param {String?} [name=null] - An optional uniform name. + * @return {NodeUniform} The node uniform object. + */ getUniformFromNode( node, type, shaderStage, name = null ) { const uniformNode = super.getUniformFromNode( node, type, shaderStage, name ); @@ -50656,6 +59845,17 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * This method should be used whenever builtins are required in nodes. + * The internal builtins data structure will make sure builtins are + * defined in the WGSL source. + * + * @param {String} name - The builtin name. + * @param {String} property - The property name. + * @param {String} type - The node data type. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The property name. + */ getBuiltin( name, property, type, shaderStage = this.shaderStage ) { const map = this.builtins[ shaderStage ] || ( this.builtins[ shaderStage ] = new Map() ); @@ -50674,12 +59874,24 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Returns `true` if the given builtin is defined in the given shader stage. + * + * @param {String} name - The builtin name. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} Whether the given builtin is defined in the given shader stage or not. + */ hasBuiltin( name, shaderStage = this.shaderStage ) { return ( this.builtins[ shaderStage ] !== undefined && this.builtins[ shaderStage ].has( name ) ); } + /** + * Returns the vertex index builtin. + * + * @return {String} The vertex index. + */ getVertexIndex() { if ( this.shaderStage === 'vertex' ) { @@ -50692,6 +59904,12 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Builds the given shader node. + * + * @param {ShaderNodeInternal} shaderNode - The shader node. + * @return {String} The WGSL function code. + */ buildFunctionCode( shaderNode ) { const layout = shaderNode.layout; @@ -50726,6 +59944,11 @@ ${ flowData.code } } + /** + * Returns the instance index builtin. + * + * @return {String} The instance index. + */ getInstanceIndex() { if ( this.shaderStage === 'vertex' ) { @@ -50738,12 +59961,22 @@ ${ flowData.code } } + /** + * Returns the invocation local index builtin. + * + * @return {String} The invocation local index. + */ getInvocationLocalIndex() { return this.getBuiltin( 'local_invocation_index', 'invocationLocalIndex', 'u32', 'attribute' ); } + /** + * Returns the subgroup size builtin. + * + * @return {String} The subgroup size. + */ getSubgroupSize() { this.enableSubGroups(); @@ -50752,6 +59985,11 @@ ${ flowData.code } } + /** + * Returns the invocation subgroup index builtin. + * + * @return {String} The invocation subgroup index. + */ getInvocationSubgroupIndex() { this.enableSubGroups(); @@ -50760,6 +59998,11 @@ ${ flowData.code } } + /** + * Returns the subgroup index builtin. + * + * @return {String} The subgroup index. + */ getSubgroupIndex() { this.enableSubGroups(); @@ -50768,42 +60011,78 @@ ${ flowData.code } } + /** + * Overwritten as a NOP since this method is intended for the WebGL 2 backend. + * + * @return {null} Null. + */ getDrawIndex() { return null; } + /** + * Returns the front facing builtin. + * + * @return {String} The front facing builtin. + */ getFrontFacing() { return this.getBuiltin( 'front_facing', 'isFront', 'bool' ); } + /** + * Returns the frag coord builtin. + * + * @return {String} The frag coord builtin. + */ getFragCoord() { return this.getBuiltin( 'position', 'fragCoord', 'vec4' ) + '.xy'; } + /** + * Returns the frag depth builtin. + * + * @return {String} The frag depth builtin. + */ getFragDepth() { return 'output.' + this.getBuiltin( 'frag_depth', 'depth', 'f32', 'output' ); } + /** + * Returns the clip distances builtin. + * + * @return {String} The clip distances builtin. + */ getClipDistance() { return 'varyings.hw_clip_distances'; } + /** + * Whether to flip texture data along its vertical axis or not. + * + * @return {Boolean} Returns always `false` in context of WGSL. + */ isFlipY() { return false; } + /** + * Enables the given directive for the given shader stage. + * + * @param {String} name - The directive name. + * @param {String} [shaderStage=this.shaderStage] - The shader stage to enable the directive for. + */ enableDirective( name, shaderStage = this.shaderStage ) { const stage = this.directives[ shaderStage ] || ( this.directives[ shaderStage ] = new Set() ); @@ -50811,6 +60090,12 @@ ${ flowData.code } } + /** + * Returns the directives of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} A WGSL snippet that enables the directives of the given stage. + */ getDirectives( shaderStage ) { const snippets = []; @@ -50830,36 +60115,56 @@ ${ flowData.code } } + /** + * Enables the 'subgroups' directive. + */ enableSubGroups() { this.enableDirective( 'subgroups' ); } + /** + * Enables the 'subgroups-f16' directive. + */ enableSubgroupsF16() { this.enableDirective( 'subgroups-f16' ); } + /** + * Enables the 'clip_distances' directive. + */ enableClipDistances() { this.enableDirective( 'clip_distances' ); } + /** + * Enables the 'f16' directive. + */ enableShaderF16() { this.enableDirective( 'f16' ); } + /** + * Enables the 'dual_source_blending' directive. + */ enableDualSourceBlending() { this.enableDirective( 'dual_source_blending' ); } + /** + * Enables hardware clipping. + * + * @param {String} planeCount - The clipping plane count. + */ enableHardwareClipping( planeCount ) { this.enableClipDistances(); @@ -50867,6 +60172,12 @@ ${ flowData.code } } + /** + * Returns the builtins of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} A WGSL snippet that represents the builtins of the given stage. + */ getBuiltins( shaderStage ) { const snippets = []; @@ -50886,6 +60197,17 @@ ${ flowData.code } } + /** + * This method should be used when a new scoped buffer is used in context of + * compute shaders. It adds the array to the internal data structure which is + * later used to generate the respective WGSL. + * + * @param {String} name - The array name. + * @param {String} scope - The scope. + * @param {String} bufferType - The buffer type. + * @param {String} bufferCount - The buffer count. + * @return {String} The array name. + */ getScopedArray( name, scope, bufferType, bufferCount ) { if ( this.scopedArrays.has( name ) === false ) { @@ -50903,6 +60225,13 @@ ${ flowData.code } } + /** + * Returns the scoped arrays of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String|undefined} The WGSL snippet that defines the scoped arrays. + * Returns `undefined` when used in the vertex or fragment stage. + */ getScopedArrays( shaderStage ) { if ( shaderStage !== 'compute' ) { @@ -50925,6 +60254,12 @@ ${ flowData.code } } + /** + * Returns the shader attributes of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The WGSL snippet that defines the shader attributes. + */ getAttributes( shaderStage ) { const snippets = []; @@ -50969,6 +60304,12 @@ ${ flowData.code } } + /** + * Returns the members of the given struct type node as a WGSL string. + * + * @param {StructTypeNode} struct - The struct type node. + * @return {String} The WGSL snippet that defines the struct members. + */ getStructMembers( struct ) { const snippets = []; @@ -50989,6 +60330,12 @@ ${ flowData.code } } + /** + * Returns the structs of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The WGSL snippet that defines the structs. + */ getStructs( shaderStage ) { const snippets = []; @@ -51014,12 +60361,25 @@ ${ flowData.code } } + /** + * Returns a WGSL string representing a variable. + * + * @param {String} type - The variable's type. + * @param {String} name - The variable's name. + * @return {String} The WGSL snippet that defines a variable. + */ getVar( type, name ) { return `var ${ name } : ${ this.getType( type ) }`; } + /** + * Returns the variables of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The WGSL snippet that defines the variables. + */ getVars( shaderStage ) { const snippets = []; @@ -51039,6 +60399,12 @@ ${ flowData.code } } + /** + * Returns the varyings of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The WGSL snippet that defines the varyings. + */ getVaryings( shaderStage ) { const snippets = []; @@ -51091,6 +60457,12 @@ ${ flowData.code } } + /** + * Returns the uniforms of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The WGSL snippet that defines the uniforms. + */ getUniforms( shaderStage ) { const uniforms = this.uniforms[ shaderStage ]; @@ -51218,6 +60590,9 @@ ${ flowData.code } } + /** + * Controls the code build of the shader stages. + */ buildCode() { const shadersData = this.material !== null ? { fragment: {}, vertex: {} } : { compute: {} }; @@ -51318,6 +60693,13 @@ ${ flowData.code } } + /** + * Returns the native shader method name for a given generic name. + * + * @param {String} method - The method name to resolve. + * @param {String} [output=null] - An optional output. + * @return {String} The resolved WGSL method name. + */ getMethod( method, output = null ) { let wgslMethod; @@ -51338,12 +60720,24 @@ ${ flowData.code } } + /** + * Returns the WGSL type of the given node data type. + * + * @param {String} type - The node data type. + * @return {String} The WGSL type. + */ getType( type ) { return wgslTypeLib[ type ] || type; } + /** + * Whether the requested feature is available or not. + * + * @param {String} name - The requested feature. + * @return {Boolean} Whether the requested feature is supported or not. + */ isAvailable( name ) { let result = supports[ name ]; @@ -51368,6 +60762,13 @@ ${ flowData.code } } + /** + * Returns the native shader method name for a given generic name. + * + * @private + * @param {String} method - The method name to resolve. + * @return {String} The resolved WGSL method name. + */ _getWGSLMethod( method ) { if ( wgslPolyfill[ method ] !== undefined ) { @@ -51380,6 +60781,14 @@ ${ flowData.code } } + /** + * Includes the given method name into the current + * function node. + * + * @private + * @param {String} name - The method name to include. + * @return {CodeNode} The respective code node. + */ _include( name ) { const codeNode = wgslPolyfill[ name ]; @@ -51395,6 +60804,13 @@ ${ flowData.code } } + /** + * Returns a WGSL vertex shader based on the given shader data. + * + * @private + * @param {Object} shaderData - The shader data. + * @return {String} The vertex shader. + */ _getWGSLVertexCode( shaderData ) { return `${ this.getSignature() } @@ -51427,6 +60843,13 @@ fn main( ${shaderData.attributes} ) -> VaryingsStruct { } + /** + * Returns a WGSL fragment shader based on the given shader data. + * + * @private + * @param {Object} shaderData - The shader data. + * @return {String} The vertex shader. + */ _getWGSLFragmentCode( shaderData ) { return `${ this.getSignature() } @@ -51456,6 +60879,14 @@ fn main( ${shaderData.varyings} ) -> ${shaderData.returnType} { } + /** + * Returns a WGSL compute shader based on the given shader data. + * + * @private + * @param {Object} shaderData - The shader data. + * @param {String} workgroupSize - The workgroup size. + * @return {String} The vertex shader. + */ _getWGSLComputeCode( shaderData, workgroupSize ) { return `${ this.getSignature() } @@ -51491,6 +60922,14 @@ fn main( ${shaderData.attributes} ) { } + /** + * Returns a WGSL struct based on the given name and variables. + * + * @private + * @param {String} name - The struct name. + * @param {String} vars - The struct variables. + * @return {String} The WGSL snippet representing a struct. + */ _getWGSLStruct( name, vars ) { return ` @@ -51500,6 +60939,17 @@ ${vars} } + /** + * Returns a WGSL struct binding. + * + * @private + * @param {String} name - The struct name. + * @param {String} vars - The struct variables. + * @param {String} access - The access. + * @param {Number} [binding=0] - The binding index. + * @param {Number} [group=0] - The group index. + * @return {String} The WGSL snippet representing a struct binding. + */ _getWGSLStructBinding( name, vars, access, binding = 0, group = 0 ) { const structName = name + 'Struct'; @@ -51513,14 +60963,35 @@ var<${access}> ${name} : ${structName};`; } +/** + * A WebGPU backend utility module with common helpers. + * + * @private + */ class WebGPUUtils { + /** + * Constructs a new utility object. + * + * @param {WebGPUBackend} backend - The WebGPU backend. + */ constructor( backend ) { + /** + * A reference to the WebGPU backend. + * + * @type {WebGPUBackend} + */ this.backend = backend; } + /** + * Returns the depth/stencil GPU format for the given render context. + * + * @param {RenderContext} renderContext - The render context. + * @return {String} The depth/stencil GPU texture format. + */ getCurrentDepthStencilFormat( renderContext ) { let format; @@ -51543,12 +61014,24 @@ class WebGPUUtils { } + /** + * Returns the GPU format for the given texture. + * + * @param {Texture} texture - The texture. + * @return {String} The GPU texture format. + */ getTextureFormatGPU( texture ) { return this.backend.get( texture ).format; } + /** + * Returns an object that defines the multi-sampling state of the given texture. + * + * @param {Texture} texture - The texture. + * @return {Object} The multi-sampling state. + */ getTextureSampleData( texture ) { let samples; @@ -51579,6 +61062,12 @@ class WebGPUUtils { } + /** + * Returns the default color attachment's GPU format of the current render context. + * + * @param {RenderContext} renderContext - The render context. + * @return {String} The GPU texture format of the default color attachment. + */ getCurrentColorFormat( renderContext ) { let format; @@ -51597,6 +61086,12 @@ class WebGPUUtils { } + /** + * Returns the output color space of the current render context. + * + * @param {RenderContext} renderContext - The render context. + * @return {String} The output color space. + */ getCurrentColorSpace( renderContext ) { if ( renderContext.textures !== null ) { @@ -51609,6 +61104,13 @@ class WebGPUUtils { } + /** + * Returns GPU primitive topology for the given object and material. + * + * @param {Object3D} object - The 3D object. + * @param {Material} material - The material. + * @return {String} The GPU primitive topology. + */ getPrimitiveTopology( object, material ) { if ( object.isPoints ) return GPUPrimitiveTopology.PointList; @@ -51618,6 +61120,14 @@ class WebGPUUtils { } + /** + * Returns a modified sample count from the given sample count value. + * + * That is required since WebGPU does not support arbitrary sample counts. + * + * @param {Number} sampleCount - The input sample count. + * @return {Number} The (potentially updated) output sample count. + */ getSampleCount( sampleCount ) { let count = 1; @@ -51639,6 +61149,12 @@ class WebGPUUtils { } + /** + * Returns the sample count of the given render context. + * + * @param {RenderContext} renderContext - The render context. + * @return {Number} The sample count. + */ getSampleCountRenderContext( renderContext ) { if ( renderContext.textures !== null ) { @@ -51651,6 +61167,14 @@ class WebGPUUtils { } + /** + * Returns the preferred canvas format. + * + * There is a separate method for this so it's possible to + * honor edge cases for specific devices. + * + * @return {String} The GPU texture format of the canvas. + */ getPreferredCanvasFormat() { // TODO: Remove this check when Quest 34.5 is out @@ -51692,14 +61216,35 @@ const typeArraysToVertexFormatPrefixForItemSize1 = new Map( [ [ Float32Array, 'float32' ] ] ); +/** + * A WebGPU backend utility module for managing shader attributes. + * + * @private + */ class WebGPUAttributeUtils { + /** + * Constructs a new utility object. + * + * @param {WebGPUBackend} backend - The WebGPU backend. + */ constructor( backend ) { + /** + * A reference to the WebGPU backend. + * + * @type {WebGPUBackend} + */ this.backend = backend; } + /** + * Creates the GPU buffer for the given buffer attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + * @param {GPUBufferUsage} usage - A flag that indicates how the buffer may be used after its creation. + */ createAttribute( attribute, usage ) { const bufferAttribute = this._getBufferAttribute( attribute ); @@ -51716,16 +61261,27 @@ class WebGPUAttributeUtils { let array = bufferAttribute.array; // patch for INT16 and UINT16 - if ( attribute.normalized === false && ( array.constructor === Int16Array || array.constructor === Uint16Array ) ) { + if ( attribute.normalized === false ) { - const tempArray = new Uint32Array( array.length ); - for ( let i = 0; i < array.length; i ++ ) { + if ( array.constructor === Int16Array ) { - tempArray[ i ] = array[ i ]; + array = new Int32Array( array ); - } + } else if ( array.constructor === Uint16Array ) { + + array = new Uint32Array( array ); - array = tempArray; + if ( usage & GPUBufferUsage.INDEX ) { + + for ( let i = 0; i < array.length; i ++ ) { + + if ( array[ i ] === 0xffff ) array[ i ] = 0xffffffff; // use correct primitive restart index + + } + + } + + } } @@ -51766,6 +61322,11 @@ class WebGPUAttributeUtils { } + /** + * Updates the GPU buffer of the given buffer attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ updateAttribute( attribute ) { const bufferAttribute = this._getBufferAttribute( attribute ); @@ -51817,6 +61378,13 @@ class WebGPUAttributeUtils { } + /** + * This method creates the vertex buffer layout data which are + * require when creating a render pipeline for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @return {Array} An array holding objects which describe the vertex buffer layout. + */ createShaderVertexBuffers( renderObject ) { const attributes = renderObject.getAttributes(); @@ -51878,6 +61446,11 @@ class WebGPUAttributeUtils { } + /** + * Destroys the GPU buffer of the given buffer attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ destroyAttribute( attribute ) { const backend = this.backend; @@ -51889,6 +61462,14 @@ class WebGPUAttributeUtils { } + /** + * This method performs a readback operation by moving buffer data from + * a storage buffer attribute from the GPU to the CPU. + * + * @async + * @param {StorageBufferAttribute} attribute - The storage buffer attribute. + * @return {Promise} A promise that resolves with the buffer data when the data are ready. + */ async getArrayBufferAsync( attribute ) { const backend = this.backend; @@ -51931,6 +61512,13 @@ class WebGPUAttributeUtils { } + /** + * Returns the vertex format of the given buffer attribute. + * + * @private + * @param {BufferAttribute} geometryAttribute - The buffer attribute. + * @return {String} The vertex format (e.g. 'float32x3'). + */ _getVertexFormat( geometryAttribute ) { const { itemSize, normalized } = geometryAttribute; @@ -51976,12 +61564,27 @@ class WebGPUAttributeUtils { } + /** + * Returns `true` if the given array is a typed array. + * + * @private + * @param {Any} array - The array. + * @return {Boolean} Whether the given array is a typed array or not. + */ _isTypedArray( array ) { return ArrayBuffer.isView( array ) && ! ( array instanceof DataView ); } + /** + * Utility method for handling interleaved buffer attributes correctly. + * To process them, their `InterleavedBuffer` is returned. + * + * @private + * @param {BufferAttribute} attribute - The attribute. + * @return {BufferAttribute|InterleavedBuffer} + */ _getBufferAttribute( attribute ) { if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; @@ -51992,15 +61595,47 @@ class WebGPUAttributeUtils { } +/** + * A WebGPU backend utility module for managing bindings. + * + * When reading the documentation it's helpful to keep in mind that + * all class definitions starting with 'GPU*' are modules from the + * WebGPU API. So for example `BindGroup` is a class from the engine + * whereas `GPUBindGroup` is a class from WebGPU. + * + * @private + */ class WebGPUBindingUtils { + /** + * Constructs a new utility object. + * + * @param {WebGPUBackend} backend - The WebGPU backend. + */ constructor( backend ) { + /** + * A reference to the WebGPU backend. + * + * @type {WebGPUBackend} + */ this.backend = backend; + + /** + * A cache for managing bind group layouts. + * + * @type {WeakMap,GPUBindGroupLayout>} + */ this.bindGroupLayoutCache = new WeakMap(); } + /** + * Creates a GPU bind group layout for the given bind group. + * + * @param {BindGroup} bindGroup - The bind group. + * @return {GPUBindGroupLayout} The GPU bind group layout. + */ createBindingsLayout( bindGroup ) { const backend = this.backend; @@ -52170,6 +61805,14 @@ class WebGPUBindingUtils { } + /** + * Creates bindings from the given bind group definition. + * + * @param {BindGroup} bindGroup - The bind group. + * @param {Array} bindings - Array of bind groups. + * @param {Number} cacheIndex - The cache index. + * @param {Number} version - The version. + */ createBindings( bindGroup, bindings, cacheIndex, version = 0 ) { const { backend, bindGroupLayoutCache } = this; @@ -52223,6 +61866,11 @@ class WebGPUBindingUtils { } + /** + * Updates a buffer binding. + * + * @param {Buffer} binding - The buffer binding to update. + */ updateBinding( binding ) { const backend = this.backend; @@ -52235,6 +61883,13 @@ class WebGPUBindingUtils { } + /** + * Creates a GPU bind group for the given bind group and GPU layout. + * + * @param {BindGroup} bindGroup - The bind group. + * @param {GPUBindGroupLayout} layoutGPU - The GPU bind group layout. + * @return {GPUBindGroup} The GPU bind group. + */ createBindGroup( bindGroup, layoutGPU ) { const backend = this.backend; @@ -52355,20 +62010,48 @@ class WebGPUBindingUtils { } +/** + * A WebGPU backend utility module for managing pipelines. + * + * @private + */ class WebGPUPipelineUtils { + /** + * Constructs a new utility object. + * + * @param {WebGPUBackend} backend - The WebGPU backend. + */ constructor( backend ) { + /** + * A reference to the WebGPU backend. + * + * @type {WebGPUBackend} + */ this.backend = backend; } - _getSampleCount( renderObjectContext ) { + /** + * Returns the sample count derived from the given render context. + * + * @private + * @param {RenderContext} renderContext - The render context. + * @return {Number} The sample count. + */ + _getSampleCount( renderContext ) { - return this.backend.utils.getSampleCountRenderContext( renderObjectContext ); + return this.backend.utils.getSampleCountRenderContext( renderContext ); } + /** + * Creates a render pipeline for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @param {Array} promises - An array of compilation promises which are used in `compileAsync()`. + */ createRenderPipeline( renderObject, promises ) { const { object, material, geometry, pipeline } = renderObject; @@ -52528,6 +62211,12 @@ class WebGPUPipelineUtils { } + /** + * Creates GPU render bundle encoder for the given render context. + * + * @param {RenderContext} renderContext - The render context. + * @return {GPURenderBundleEncoder} The GPU render bundle encoder. + */ createBundleEncoder( renderContext ) { const backend = this.backend; @@ -52548,6 +62237,12 @@ class WebGPUPipelineUtils { } + /** + * Creates a compute pipeline for the given compute node. + * + * @param {ComputePipeline} pipeline - The compute pipeline. + * @param {Array} bindings - The bindings. + */ createComputePipeline( pipeline, bindings ) { const backend = this.backend; @@ -52578,6 +62273,14 @@ class WebGPUPipelineUtils { } + /** + * Returns the blending state as a descriptor object required + * for the pipeline creation. + * + * @private + * @param {Material} material - The material. + * @return {Object} The blending state. + */ _getBlending( material ) { let color, alpha; @@ -52685,7 +62388,13 @@ class WebGPUPipelineUtils { } } - + /** + * Returns the GPU blend factor which is required for the pipeline creation. + * + * @private + * @param {Number} blend - The blend factor as a three.js constant. + * @return {String} The GPU blend factor. + */ _getBlendFactor( blend ) { let blendFactor; @@ -52753,6 +62462,13 @@ class WebGPUPipelineUtils { } + /** + * Returns the GPU stencil compare function which is required for the pipeline creation. + * + * @private + * @param {Material} material - The material. + * @return {String} The GPU stencil compare function. + */ _getStencilCompare( material ) { let stencilCompare; @@ -52802,6 +62518,13 @@ class WebGPUPipelineUtils { } + /** + * Returns the GPU stencil operation which is required for the pipeline creation. + * + * @private + * @param {Number} op - A three.js constant defining the stencil operation. + * @return {String} The GPU stencil operation. + */ _getStencilOperation( op ) { let stencilOperation; @@ -52849,6 +62572,13 @@ class WebGPUPipelineUtils { } + /** + * Returns the GPU blend operation which is required for the pipeline creation. + * + * @private + * @param {Number} blendEquation - A three.js constant defining the blend equation. + * @return {String} The GPU blend operation. + */ _getBlendOperation( blendEquation ) { let blendOperation; @@ -52884,6 +62614,16 @@ class WebGPUPipelineUtils { } + /** + * Returns the primitive state as a descriptor object required + * for the pipeline creation. + * + * @private + * @param {Object3D} object - The 3D object. + * @param {BufferGeometry} geometry - The geometry. + * @param {Material} material - The material. + * @return {Object} The primitive state. + */ _getPrimitiveState( object, geometry, material ) { const descriptor = {}; @@ -52924,12 +62664,26 @@ class WebGPUPipelineUtils { } + /** + * Returns the GPU color write mask which is required for the pipeline creation. + * + * @private + * @param {Material} material - The material. + * @return {String} The GPU color write mask. + */ _getColorWriteMask( material ) { return ( material.colorWrite === true ) ? GPUColorWriteFlags.All : GPUColorWriteFlags.None; } + /** + * Returns the GPU depth compare function which is required for the pipeline creation. + * + * @private + * @param {Material} material - The material. + * @return {String} The GPU depth compare function. + */ _getDepthCompare( material ) { let depthCompare; @@ -52994,14 +62748,41 @@ import 'https://greggman.github.io/webgpu-avoid-redundant-state-setting/webgpu-c //*/ -// - +/** + * A backend implementation targeting WebGPU. + * + * @private + * @augments Backend + */ class WebGPUBackend extends Backend { + /** + * Constructs a new WebGPU backend. + * + * @param {Object} parameters - The configuration parameter. + * @param {Boolean} [parameters.logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not. + * @param {Boolean} [parameters.alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque. + * @param {Boolean} [parameters.depth=true] - Whether the default framebuffer should have a depth buffer or not. + * @param {Boolean} [parameters.stencil=false] - Whether the default framebuffer should have a stencil buffer or not. + * @param {Boolean} [parameters.antialias=false] - Whether MSAA as the default anti-aliasing should be enabled or not. + * @param {Number} [parameters.samples=0] - When `antialias` is `true`, `4` samples are used by default. Set this parameter to any other integer value than 0 to overwrite the default. + * @param {Boolean} [parameters.forceWebGL=false] - If set to `true`, the renderer uses a WebGL 2 backend no matter if WebGPU is supported or not. + * @param {Boolean} [parameters.trackTimestamp=false] - Whether to track timestamps with a Timestamp Query API or not. + * @param {String} [parameters.powerPreference=undefined] - The power preference. + * @param {Object} [parameters.requiredLimits=undefined] - Specifies the limits that are required by the device request. The request will fail if the adapter cannot provide these limits. + * @param {GPUDevice} [parameters.device=undefined] - If there is an existing GPU device on app level, it can be passed to the renderer as a parameter. + */ constructor( parameters = {} ) { super( parameters ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isWebGPUBackend = true; // some parameters require default values other than "undefined" @@ -53009,22 +62790,101 @@ class WebGPUBackend extends Backend { this.parameters.requiredLimits = ( parameters.requiredLimits === undefined ) ? {} : parameters.requiredLimits; + /** + * Whether to track timestamps with a Timestamp Query API or not. + * + * @type {Boolean} + * @default false + */ this.trackTimestamp = ( parameters.trackTimestamp === true ); + /** + * A reference to the device. + * + * @type {GPUDevice?} + * @default null + */ this.device = null; + + /** + * A reference to the context. + * + * @type {GPUCanvasContext?} + * @default null + */ this.context = null; + + /** + * A reference to the color attachment of the default framebuffer. + * + * @type {GPUTexture?} + * @default null + */ this.colorBuffer = null; + + /** + * A reference to the default render pass descriptor. + * + * @type {Object?} + * @default null + */ this.defaultRenderPassdescriptor = null; + /** + * A reference to a backend module holding common utility functions. + * + * @type {WebGPUUtils} + */ this.utils = new WebGPUUtils( this ); + + /** + * A reference to a backend module holding shader attribute-related + * utility functions. + * + * @type {WebGPUAttributeUtils} + */ this.attributeUtils = new WebGPUAttributeUtils( this ); + + /** + * A reference to a backend module holding shader binding-related + * utility functions. + * + * @type {WebGPUBindingUtils} + */ this.bindingUtils = new WebGPUBindingUtils( this ); + + /** + * A reference to a backend module holding shader pipeline-related + * utility functions. + * + * @type {WebGPUPipelineUtils} + */ this.pipelineUtils = new WebGPUPipelineUtils( this ); + + /** + * A reference to a backend module holding shader texture-related + * utility functions. + * + * @type {WebGPUTextureUtils} + */ this.textureUtils = new WebGPUTextureUtils( this ); + + /** + * A map that manages the resolve buffers for occlusion queries. + * + * @type {Map} + */ this.occludedResolveCache = new Map(); } + /** + * Initializes the backend so it is ready for usage. + * + * @async + * @param {Renderer} renderer - The renderer. + * @return {Promise} A Promise that resolves when the backend has been initialized. + */ async init( renderer ) { await super.init( renderer ); @@ -53113,24 +62973,53 @@ class WebGPUBackend extends Backend { } + /** + * The coordinate system of the backend. + * + * @type {Number} + * @readonly + */ get coordinateSystem() { return WebGPUCoordinateSystem; } + /** + * This method performs a readback operation by moving buffer data from + * a storage buffer attribute from the GPU to the CPU. + * + * @async + * @param {StorageBufferAttribute} attribute - The storage buffer attribute. + * @return {Promise} A promise that resolves with the buffer data when the data are ready. + */ async getArrayBufferAsync( attribute ) { return await this.attributeUtils.getArrayBufferAsync( attribute ); } + /** + * Returns the backend's rendering context. + * + * @return {GPUCanvasContext} The rendering context. + */ getContext() { return this.context; } + /** + * Returns the default render pass descriptor. + * + * In WebGPU, the default framebuffer must be configured + * like custom framebuffers so the backend needs a render + * pass descriptor even when rendering directly to screen. + * + * @private + * @return {Object} The render pass descriptor. + */ _getDefaultRenderPassDescriptor() { let descriptor = this.defaultRenderPassdescriptor; @@ -53185,7 +63074,15 @@ class WebGPUBackend extends Backend { } - _getRenderPassDescriptor( renderContext ) { + /** + * Returns the render pass descriptor for the given render context. + * + * @private + * @param {RenderContext} renderContext - The render context. + * @param {Object} colorAttachmentsConfig - Configuration object for the color attachments. + * @return {Object} The render pass descriptor. + */ + _getRenderPassDescriptor( renderContext, colorAttachmentsConfig = {} ) { const renderTarget = renderContext.renderTarget; const renderTargetData = this.get( renderTarget ); @@ -53195,8 +63092,11 @@ class WebGPUBackend extends Backend { if ( descriptors === undefined || renderTargetData.width !== renderTarget.width || renderTargetData.height !== renderTarget.height || + renderTargetData.dimensions !== renderTarget.dimensions || renderTargetData.activeMipmapLevel !== renderTarget.activeMipmapLevel || - renderTargetData.samples !== renderTarget.samples + renderTargetData.activeCubeFace !== renderContext.activeCubeFace || + renderTargetData.samples !== renderTarget.samples || + renderTargetData.loadOp !== colorAttachmentsConfig.loadOp ) { descriptors = {}; @@ -53226,16 +63126,37 @@ class WebGPUBackend extends Backend { const textures = renderContext.textures; const colorAttachments = []; + let sliceIndex; + for ( let i = 0; i < textures.length; i ++ ) { const textureData = this.get( textures[ i ] ); - const textureView = textureData.texture.createView( { + const viewDescriptor = { + label: `colorAttachment_${ i }`, baseMipLevel: renderContext.activeMipmapLevel, mipLevelCount: 1, baseArrayLayer: renderContext.activeCubeFace, + arrayLayerCount: 1, dimension: GPUTextureViewDimension.TwoD - } ); + }; + + if ( renderTarget.isRenderTarget3D ) { + + sliceIndex = renderContext.activeCubeFace; + + viewDescriptor.baseArrayLayer = 0; + viewDescriptor.dimension = GPUTextureViewDimension.ThreeD; + viewDescriptor.depthOrArrayLayers = textures[ i ].image.depth; + + } else if ( renderTarget.isRenderTargetArray ) { + + viewDescriptor.dimension = GPUTextureViewDimension.TwoDArray; + viewDescriptor.depthOrArrayLayers = textures[ i ].image.depth; + + } + + const textureView = textureData.texture.createView( viewDescriptor ); let view, resolveTarget; @@ -53253,9 +63174,11 @@ class WebGPUBackend extends Backend { colorAttachments.push( { view, + depthSlice: sliceIndex, resolveTarget, loadOp: GPULoadOp.Load, - storeOp: GPUStoreOp.Store + storeOp: GPUStoreOp.Store, + ...colorAttachmentsConfig } ); } @@ -53281,7 +63204,11 @@ class WebGPUBackend extends Backend { renderTargetData.width = renderTarget.width; renderTargetData.height = renderTarget.height; renderTargetData.samples = renderTarget.samples; - renderTargetData.activeMipmapLevel = renderTarget.activeMipmapLevel; + renderTargetData.activeMipmapLevel = renderContext.activeMipmapLevel; + renderTargetData.activeCubeFace = renderContext.activeCubeFace; + renderTargetData.dimensions = renderTarget.dimensions; + renderTargetData.depthSlice = sliceIndex; + renderTargetData.loadOp = colorAttachments[ 0 ].loadOp; } @@ -53289,6 +63216,12 @@ class WebGPUBackend extends Backend { } + /** + * This method is executed at the beginning of a render call and prepares + * the WebGPU state for upcoming render calls + * + * @param {RenderContext} renderContext - The render context. + */ beginRender( renderContext ) { const renderContextData = this.get( renderContext ); @@ -53329,7 +63262,7 @@ class WebGPUBackend extends Backend { } else { - descriptor = this._getRenderPassDescriptor( renderContext ); + descriptor = this._getRenderPassDescriptor( renderContext, { loadOp: GPULoadOp.Load } ); } @@ -53448,6 +63381,12 @@ class WebGPUBackend extends Backend { } + /** + * This method is executed at the end of a render call and finalizes work + * after draw calls. + * + * @param {RenderContext} renderContext - The render context. + */ finishRender( renderContext ) { const renderContextData = this.get( renderContext ); @@ -53536,6 +63475,14 @@ class WebGPUBackend extends Backend { } + /** + * Returns `true` if the given 3D object is fully occluded by other + * 3D objects in the scene. + * + * @param {RenderContext} renderContext - The render context. + * @param {Object3D} object - The 3D object to test. + * @return {Boolean} Whether the 3D object is fully occluded or not. + */ isOccluded( renderContext, object ) { const renderContextData = this.get( renderContext ); @@ -53544,6 +63491,13 @@ class WebGPUBackend extends Backend { } + /** + * This method processes the result of occlusion queries and writes it + * into render context data. + * + * @async + * @param {RenderContext} renderContext - The render context. + */ async resolveOccludedAsync( renderContext ) { const renderContextData = this.get( renderContext ); @@ -53582,6 +63536,11 @@ class WebGPUBackend extends Backend { } + /** + * Updates the viewport with the values from the given render context. + * + * @param {RenderContext} renderContext - The render context. + */ updateViewport( renderContext ) { const { currentPass } = this.get( renderContext ); @@ -53591,7 +63550,15 @@ class WebGPUBackend extends Backend { } - clear( color, depth, stencil, renderTargetData = null ) { + /** + * Performs a clear operation. + * + * @param {Boolean} color - Whether the color buffer should be cleared or not. + * @param {Boolean} depth - Whether the depth buffer should be cleared or not. + * @param {Boolean} stencil - Whether the stencil buffer should be cleared or not. + * @param {RenderContext?} [renderTargetContext=null] - The render context of the current set render target. + */ + clear( color, depth, stencil, renderTargetContext = null ) { const device = this.device; const renderer = this.renderer; @@ -53624,7 +63591,7 @@ class WebGPUBackend extends Backend { } - if ( renderTargetData === null ) { + if ( renderTargetContext === null ) { supportsDepth = renderer.depth; supportsStencil = renderer.stencil; @@ -53651,45 +63618,20 @@ class WebGPUBackend extends Backend { } else { - supportsDepth = renderTargetData.depth; - supportsStencil = renderTargetData.stencil; + supportsDepth = renderTargetContext.depth; + supportsStencil = renderTargetContext.stencil; if ( color ) { - for ( const texture of renderTargetData.textures ) { - - const textureData = this.get( texture ); - const textureView = textureData.texture.createView(); - - let view, resolveTarget; + const descriptor = this._getRenderPassDescriptor( renderTargetContext, { loadOp: GPULoadOp.Clear } ); - if ( textureData.msaaTexture !== undefined ) { - - view = textureData.msaaTexture.createView(); - resolveTarget = textureView; - - } else { - - view = textureView; - resolveTarget = undefined; - - } - - colorAttachments.push( { - view, - resolveTarget, - clearValue, - loadOp: GPULoadOp.Clear, - storeOp: GPUStoreOp.Store - } ); - - } + colorAttachments = descriptor.colorAttachments; } if ( supportsDepth || supportsStencil ) { - const depthTextureData = this.get( renderTargetData.depthTexture ); + const depthTextureData = this.get( renderTargetContext.depthTexture ); depthStencilAttachment = { view: depthTextureData.texture.createView() @@ -53753,6 +63695,12 @@ class WebGPUBackend extends Backend { // compute + /** + * This method is executed at the beginning of a compute call and + * prepares the state for upcoming compute tasks. + * + * @param {Node|Array} computeGroup - The compute node(s). + */ beginCompute( computeGroup ) { const groupGPU = this.get( computeGroup ); @@ -53768,6 +63716,14 @@ class WebGPUBackend extends Backend { } + /** + * Executes a compute command for the given compute node. + * + * @param {Node|Array} computeGroup - The group of compute nodes of a compute call. Can be a single compute node. + * @param {Node} computeNode - The compute node. + * @param {Array} bindings - The bindings. + * @param {ComputePipeline} pipeline - The compute pipeline. + */ compute( computeGroup, computeNode, bindings, pipeline ) { const { passEncoderGPU } = this.get( computeGroup ); @@ -53815,6 +63771,12 @@ class WebGPUBackend extends Backend { } + /** + * This method is executed at the end of a compute call and + * finalizes work after compute tasks. + * + * @param {Node|Array} computeGroup - The compute node(s). + */ finishCompute( computeGroup ) { const groupData = this.get( computeGroup ); @@ -53827,6 +63789,13 @@ class WebGPUBackend extends Backend { } + /** + * Can be used to synchronize CPU operations with GPU tasks. So when this method is called, + * the CPU waits for the GPU to complete its operation (e.g. a compute task). + * + * @async + * @return {Promise} A Promise that resolves when synchronization has been finished. + */ async waitForGPU() { await this.device.queue.onSubmittedWorkDone(); @@ -53835,6 +63804,12 @@ class WebGPUBackend extends Backend { // render object + /** + * Executes a draw command for the given render object. + * + * @param {RenderObject} renderObject - The render object to draw. + * @param {Info} info - Holds a series of statistical information about the GPU memory and the rendering process. + */ draw( renderObject, info ) { const { object, context, pipeline } = renderObject; @@ -54018,6 +63993,12 @@ class WebGPUBackend extends Backend { // cache key + /** + * Returns `true` if the render pipeline requires an update. + * + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether the render pipeline requires an update or not. + */ needsRenderUpdate( renderObject ) { const data = this.get( renderObject ); @@ -54074,6 +64055,12 @@ class WebGPUBackend extends Backend { } + /** + * Returns a cache key that is used to identify render pipelines. + * + * @param {RenderObject} renderObject - The render object. + * @return {String} The cache key. + */ getRenderCacheKey( renderObject ) { const { object, material } = renderObject; @@ -54102,55 +64089,110 @@ class WebGPUBackend extends Backend { // textures + /** + * Creates a GPU sampler for the given texture. + * + * @param {Texture} texture - The texture to create the sampler for. + */ createSampler( texture ) { this.textureUtils.createSampler( texture ); } + /** + * Destroys the GPU sampler for the given texture. + * + * @param {Texture} texture - The texture to destroy the sampler for. + */ destroySampler( texture ) { this.textureUtils.destroySampler( texture ); } + /** + * Creates a default texture for the given texture that can be used + * as a placeholder until the actual texture is ready for usage. + * + * @param {Texture} texture - The texture to create a default texture for. + */ createDefaultTexture( texture ) { this.textureUtils.createDefaultTexture( texture ); } + /** + * Defines a texture on the GPU for the given texture object. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ createTexture( texture, options ) { this.textureUtils.createTexture( texture, options ); } + /** + * Uploads the updated texture data to the GPU. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ updateTexture( texture, options ) { this.textureUtils.updateTexture( texture, options ); } + /** + * Generates mipmaps for the given texture. + * + * @param {Texture} texture - The texture. + */ generateMipmaps( texture ) { this.textureUtils.generateMipmaps( texture ); } + /** + * Destroys the GPU data for the given texture object. + * + * @param {Texture} texture - The texture. + */ destroyTexture( texture ) { this.textureUtils.destroyTexture( texture ); } - copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { + /** + * Returns texture data as a typed array. + * + * @async + * @param {Texture} texture - The texture to copy. + * @param {Number} x - The x coordinate of the copy origin. + * @param {Number} y - The y coordinate of the copy origin. + * @param {Number} width - The width of the copy. + * @param {Number} height - The height of the copy. + * @param {Number} faceIndex - The face index. + * @return {Promise} A Promise that resolves with a typed array when the copy operation has finished. + */ + async copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { return this.textureUtils.copyTextureToBuffer( texture, x, y, width, height, faceIndex ); } - + /** + * Inits a time stamp query for the given render context. + * + * @param {RenderContext} renderContext - The render context. + * @param {Object} descriptor - The query descriptor. + */ initTimestampQuery( renderContext, descriptor ) { if ( ! this.trackTimestamp ) return; @@ -54177,8 +64219,12 @@ class WebGPUBackend extends Backend { } - // timestamp utils - + /** + * Prepares the timestamp buffer. + * + * @param {RenderContext} renderContext - The render context. + * @param {GPUCommandEncoder} encoder - The command encoder. + */ prepareTimestampBuffer( renderContext, encoder ) { if ( ! this.trackTimestamp ) return; @@ -54218,6 +64264,14 @@ class WebGPUBackend extends Backend { } + /** + * Resolves the time stamp for the given render context and type. + * + * @async + * @param {RenderContext} renderContext - The render context. + * @param {String} type - The render context. + * @return {Promise} A Promise that resolves when the time stamp has been computed. + */ async resolveTimestampAsync( renderContext, type = 'render' ) { if ( ! this.trackTimestamp ) return; @@ -54249,6 +64303,13 @@ class WebGPUBackend extends Backend { // node builder + /** + * Returns a node builder for the given render object. + * + * @param {RenderObject} object - The render object. + * @param {Renderer} renderer - The renderer. + * @return {WGSLNodeBuilder} The node builder. + */ createNodeBuilder( object, renderer ) { return new WGSLNodeBuilder( object, renderer ); @@ -54257,17 +64318,27 @@ class WebGPUBackend extends Backend { // program + /** + * Creates a shader program from the given programmable stage. + * + * @param {ProgrammableStage} program - The programmable stage. + */ createProgram( program ) { const programGPU = this.get( program ); programGPU.module = { - module: this.device.createShaderModule( { code: program.code, label: program.stage } ), + module: this.device.createShaderModule( { code: program.code, label: program.stage + ( program.name !== '' ? `_${ program.name }` : '' ) } ), entryPoint: 'main' }; } + /** + * Destroys the shader program of the given programmable stage. + * + * @param {ProgrammableStage} program - The programmable stage. + */ destroyProgram( program ) { this.delete( program ); @@ -54276,18 +64347,35 @@ class WebGPUBackend extends Backend { // pipelines + /** + * Creates a render pipeline for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @param {Array} promises - An array of compilation promises which are used in `compileAsync()`. + */ createRenderPipeline( renderObject, promises ) { this.pipelineUtils.createRenderPipeline( renderObject, promises ); } + /** + * Creates a compute pipeline for the given compute node. + * + * @param {ComputePipeline} computePipeline - The compute pipeline. + * @param {Array} bindings - The bindings. + */ createComputePipeline( computePipeline, bindings ) { this.pipelineUtils.createComputePipeline( computePipeline, bindings ); } + /** + * Prepares the state for encoding render bundles. + * + * @param {RenderContext} renderContext - The render context. + */ beginBundle( renderContext ) { const renderContextData = this.get( renderContext ); @@ -54300,6 +64388,12 @@ class WebGPUBackend extends Backend { } + /** + * After processing render bundles this method finalizes related work. + * + * @param {RenderContext} renderContext - The render context. + * @param {RenderBundle} bundle - The render bundle. + */ finishBundle( renderContext, bundle ) { const renderContextData = this.get( renderContext ); @@ -54316,6 +64410,12 @@ class WebGPUBackend extends Backend { } + /** + * Adds a render bundle to the render context data. + * + * @param {RenderContext} renderContext - The render context. + * @param {RenderBundle} bundle - The render bundle to add. + */ addBundle( renderContext, bundle ) { const renderContextData = this.get( renderContext ); @@ -54326,18 +64426,39 @@ class WebGPUBackend extends Backend { // bindings + /** + * Creates bindings from the given bind group definition. + * + * @param {BindGroup} bindGroup - The bind group. + * @param {Array} bindings - Array of bind groups. + * @param {Number} cacheIndex - The cache index. + * @param {Number} version - The version. + */ createBindings( bindGroup, bindings, cacheIndex, version ) { this.bindingUtils.createBindings( bindGroup, bindings, cacheIndex, version ); } + /** + * Updates the given bind group definition. + * + * @param {BindGroup} bindGroup - The bind group. + * @param {Array} bindings - Array of bind groups. + * @param {Number} cacheIndex - The cache index. + * @param {Number} version - The version. + */ updateBindings( bindGroup, bindings, cacheIndex, version ) { this.bindingUtils.createBindings( bindGroup, bindings, cacheIndex, version ); } + /** + * Updates a buffer binding. + * + * @param {Buffer} binding - The buffer binding to update. + */ updateBinding( binding ) { this.bindingUtils.updateBinding( binding ); @@ -54346,36 +64467,66 @@ class WebGPUBackend extends Backend { // attributes + /** + * Creates the buffer of an indexed shader attribute. + * + * @param {BufferAttribute} attribute - The indexed buffer attribute. + */ createIndexAttribute( attribute ) { this.attributeUtils.createAttribute( attribute, GPUBufferUsage.INDEX | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST ); } + /** + * Creates the GPU buffer of a shader attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ createAttribute( attribute ) { this.attributeUtils.createAttribute( attribute, GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST ); } + /** + * Creates the GPU buffer of a storage attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ createStorageAttribute( attribute ) { this.attributeUtils.createAttribute( attribute, GPUBufferUsage.STORAGE | GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST ); } + /** + * Creates the GPU buffer of an indirect storage attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ createIndirectStorageAttribute( attribute ) { this.attributeUtils.createAttribute( attribute, GPUBufferUsage.STORAGE | GPUBufferUsage.INDIRECT | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST ); } + /** + * Updates the GPU buffer of a shader attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute to update. + */ updateAttribute( attribute ) { this.attributeUtils.updateAttribute( attribute ); } + /** + * Destroys the GPU buffer of a shader attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute to destroy. + */ destroyAttribute( attribute ) { this.attributeUtils.destroyAttribute( attribute ); @@ -54384,6 +64535,9 @@ class WebGPUBackend extends Backend { // canvas + /** + * Triggers an update of the default render pass descriptor. + */ updateSize() { this.colorBuffer = this.textureUtils.getColorBuffer(); @@ -54393,18 +64547,38 @@ class WebGPUBackend extends Backend { // utils public + /** + * Returns the maximum anisotropy texture filtering value. + * + * @return {Number} The maximum anisotropy texture filtering value. + */ getMaxAnisotropy() { return 16; } + /** + * Checks if the given feature is supported by the backend. + * + * @param {String} name - The feature's name. + * @return {Boolean} Whether the feature is supported or not. + */ hasFeature( name ) { return this.device.features.has( name ); } + /** + * Copies data of the given source texture to the given destination texture. + * + * @param {Texture} srcTexture - The source texture. + * @param {Texture} dstTexture - The destination texture. + * @param {Vector4?} [srcRegion=null] - The region of the source texture to copy. + * @param {(Vector2|Vector3)?} [dstPosition=null] - The destination position of the copy. + * @param {Number} [level=0] - The mip level to copy. + */ copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { let dstX = 0; @@ -54463,6 +64637,13 @@ class WebGPUBackend extends Backend { } + /** + * Copies the current bound framebuffer to the given texture. + * + * @param {Texture} texture - The destination texture. + * @param {RenderContext} renderContext - The render context. + * @param {Vector4} rectangle - A four dimensional vector defining the origin and dimension of the copy. + */ copyFramebufferToTexture( texture, renderContext, rectangle ) { const renderContextData = this.get( renderContext ); @@ -54597,8 +64778,19 @@ class IESSpotLight extends SpotLight { } +/** + * This version of a node library represents the standard version + * used in {@link WebGPURenderer}. It maps lights, tone mapping + * techniques and materials to node-based implementations. + * + * @private + * @augments NodeLibrary + */ class StandardNodeLibrary extends NodeLibrary { + /** + * Constructs a new standard node library. + */ constructor() { super(); @@ -54651,8 +64843,28 @@ const debugHandler = { }; */ + +/** + * This renderer is the new alternative of `WebGLRenderer`. `WebGPURenderer` has the ability + * to target different backends. By default, the renderer tries to use a WebGPU backend if the + * browser supports WebGPU. If not, `WebGPURenderer` falls backs to a WebGL 2 backend. + * + * @augments module:Renderer~Renderer + */ class WebGPURenderer extends Renderer { + /** + * Constructs a new WebGPU renderer. + * + * @param {Object} parameters - The configuration parameter. + * @param {Boolean} [parameters.logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not. + * @param {Boolean} [parameters.alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque. + * @param {Boolean} [parameters.depth=true] - Whether the default framebuffer should have a depth buffer or not. + * @param {Boolean} [parameters.stencil=false] - Whether the default framebuffer should have a stencil buffer or not. + * @param {Boolean} [parameters.antialias=false] - Whether MSAA as the default anti-aliasing should be enabled or not. + * @param {Number} [parameters.samples=0] - When `antialias` is `true`, `4` samples are used by default. Set this parameter to any other integer value than 0 to overwrite the default. + * @param {Boolean} [parameters.forceWebGL=false] - If set to `true`, the renderer uses a WebGL 2 backend no matter if WebGPU is supported or not. + */ constructor( parameters = {} ) { let BackendClass; @@ -54680,29 +64892,99 @@ class WebGPURenderer extends Renderer { //super( new Proxy( backend, debugHandler ) ); super( backend, parameters ); + /** + * The generic default value is overwritten with the + * standard node library for type mapping. + * + * @type {StandardNodeLibrary} + */ this.library = new StandardNodeLibrary(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isWebGPURenderer = true; } } +/** + * A specialized group which enables applications access to the + * Render Bundle API of WebGPU. The group with all its descendant nodes + * are considered as one render bundle and processed as such by + * the renderer. + * + * This module is only fully supported by `WebGPURenderer` with a WebGPU backend. + * With a WebGL backend, the group can technically be rendered but without + * any performance improvements. + * + * @augments Group + */ class BundleGroup extends Group { + /** + * Constructs a new bundle group. + */ constructor() { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isBundleGroup = true; + /** + * This property is only relevant for detecting types + * during serialization/deserialization. It should always + * match the class name. + * + * @type {String} + * @readonly + * @default 'BundleGroup' + */ this.type = 'BundleGroup'; + /** + * Whether the bundle is static or not. When set to `true`, the structure + * is assumed to be static and does not change. E.g. no new objects are + * added to the group + * + * If a change is required, an update can still be forced by setting the + * `needsUpdate` flag to `true`. + * + * @type {Boolean} + * @default true + */ this.static = true; + + /** + * The bundle group's version. + * + * @type {Number} + * @readonly + * @default 0 + */ this.version = 0; } + /** + * Set this property to `true` when the bundle group has changed. + * + * @type {Boolean} + * @default false + * @param {Boolean} value + */ set needsUpdate( value ) { if ( value === true ) this.version ++; @@ -54711,27 +64993,93 @@ class BundleGroup extends Group { } -const _material = /*@__PURE__*/ new NodeMaterial(); -const _quadMesh = /*@__PURE__*/ new QuadMesh( _material ); - +/** + * This module is responsible to manage the post processing setups in apps. + * You usually create a single instance of this class and use it to define + * the output of your post processing effect chain. + * ```js + * const postProcessing = new PostProcessing( renderer ); + * + * const scenePass = pass( scene, camera ); + * + * postProcessing.outputNode = scenePass; + * ``` + */ class PostProcessing { + /** + * Constructs a new post processing management module. + * + * @param {Renderer} renderer - A reference to the renderer. + * @param {Node} outputNode - An optional output node. + */ constructor( renderer, outputNode = vec4( 0, 0, 1, 1 ) ) { + /** + * A reference to the renderer. + * + * @type {Renderer} + */ this.renderer = renderer; + + /** + * A node which defines the final output of the post + * processing. This is usually the last node in a chain + * of effect nodes. + * + * @type {Node} + */ this.outputNode = outputNode; + /** + * Whether the default output tone mapping and color + * space transformation should be enabled or not. + * + * It is enabled by default by it must be disabled when + * effects must be executed after tone mapping and color + * space conversion. A typical example is FXAA which + * requires sRGB input. + * + * When set to `false`, the app must control the output + * transformation with `RenderOutputNode`. + * + * ```js + * const outputPass = renderOutput( scenePass ); + * ``` + * + * @type {Boolean} + */ this.outputColorTransform = true; + /** + * Must be set to `true` when the output node changes. + * + * @type {Node} + */ this.needsUpdate = true; - _material.name = 'PostProcessing'; + const material = new NodeMaterial(); + material.name = 'PostProcessing'; + + /** + * The full screen quad that is used to render + * the effects. + * + * @private + * @type {QuadMesh} + */ + this._quadMesh = new QuadMesh( material ); } + /** + * When `PostProcessing` is used to apply post processing effects, + * the application must use this version of `render()` inside + * its animation loop (not the one from the renderer). + */ render() { - this.update(); + this._update(); const renderer = this.renderer; @@ -54743,7 +65091,7 @@ class PostProcessing { // - _quadMesh.render( renderer ); + this._quadMesh.render( renderer ); // @@ -54752,7 +65100,21 @@ class PostProcessing { } - update() { + /** + * Frees internal resources. + */ + dispose() { + + this._quadMesh.material.dispose(); + + } + + /** + * Updates the state of the module. + * + * @private + */ + _update() { if ( this.needsUpdate === true ) { @@ -54761,8 +65123,8 @@ class PostProcessing { const toneMapping = renderer.toneMapping; const outputColorSpace = renderer.outputColorSpace; - _quadMesh.material.fragmentNode = this.outputColorTransform === true ? renderOutput( this.outputNode, toneMapping, outputColorSpace ) : this.outputNode.context( { toneMapping, outputColorSpace } ); - _quadMesh.material.needsUpdate = true; + this._quadMesh.material.fragmentNode = this.outputColorTransform === true ? renderOutput( this.outputNode, toneMapping, outputColorSpace ) : this.outputNode.context( { toneMapping, outputColorSpace } ); + this._quadMesh.material.needsUpdate = true; this.needsUpdate = false; @@ -54770,9 +65132,17 @@ class PostProcessing { } + /** + * When `PostProcessing` is used to apply post processing effects, + * the application must use this version of `renderAsync()` inside + * its animation loop (not the one from the renderer). + * + * @async + * @return {Promise} A Promise that resolves when the render has been finished. + */ async renderAsync() { - this.update(); + this._update(); const renderer = this.renderer; @@ -54784,7 +65154,7 @@ class PostProcessing { // - await _quadMesh.renderAsync( renderer ); + await this._quadMesh.renderAsync( renderer ); // @@ -54795,124 +65165,90 @@ class PostProcessing { } -// renderer state - -function saveRendererState( renderer, state = {} ) { - - state.toneMapping = renderer.toneMapping; - state.toneMappingExposure = renderer.toneMappingExposure; - state.outputColorSpace = renderer.outputColorSpace; - state.renderTarget = renderer.getRenderTarget(); - state.activeCubeFace = renderer.getActiveCubeFace(); - state.activeMipmapLevel = renderer.getActiveMipmapLevel(); - state.renderObjectFunction = renderer.getRenderObjectFunction(); - state.pixelRatio = renderer.getPixelRatio(); - state.mrt = renderer.getMRT(); - state.clearColor = renderer.getClearColor( state.clearColor || new Color() ); - state.clearAlpha = renderer.getClearAlpha(); - state.autoClear = renderer.autoClear; - state.scissorTest = renderer.getScissorTest(); - - return state; - -} - -function resetRendererState( renderer, state ) { - - state = saveRendererState( renderer, state ); - - renderer.setMRT( null ); - renderer.setRenderObjectFunction( null ); - renderer.setClearColor( 0x000000, 1 ); - renderer.autoClear = true; - - return state; - -} - -function restoreRendererState( renderer, state ) { - - renderer.toneMapping = state.toneMapping; - renderer.toneMappingExposure = state.toneMappingExposure; - renderer.outputColorSpace = state.outputColorSpace; - renderer.setRenderTarget( state.renderTarget, state.activeCubeFace, state.activeMipmapLevel ); - renderer.setRenderObjectFunction( state.renderObjectFunction ); - renderer.setPixelRatio( state.pixelRatio ); - renderer.setMRT( state.mrt ); - renderer.setClearColor( state.clearColor, state.clearAlpha ); - renderer.autoClear = state.autoClear; - renderer.setScissorTest( state.scissorTest ); - -} - -// renderer and scene state - -function saveRendererAndSceneState( renderer, scene, state = {} ) { - - state = saveRendererState( renderer, state ); - state.background = scene.background; - state.backgroundNode = scene.backgroundNode; - state.overrideMaterial = scene.overrideMaterial; - - return state; - -} - -function resetRendererAndSceneState( renderer, scene, state ) { - - state = saveRendererAndSceneState( renderer, scene, state ); - - scene.background = null; - scene.backgroundNode = null; - scene.overrideMaterial = null; - - return state; - -} - -function restoreRendererAndSceneState( renderer, scene, state ) { - - restoreRendererState( renderer, state ); - - scene.background = state.background; - scene.backgroundNode = state.backgroundNode; - scene.overrideMaterial = state.overrideMaterial; - -} - -var PostProcessingUtils = /*#__PURE__*/Object.freeze({ - __proto__: null, - resetRendererAndSceneState: resetRendererAndSceneState, - resetRendererState: resetRendererState, - restoreRendererAndSceneState: restoreRendererAndSceneState, - restoreRendererState: restoreRendererState, - saveRendererAndSceneState: saveRendererAndSceneState, - saveRendererState: saveRendererState -}); - +/** + * This special type of texture is intended for compute shaders. + * It can be used to compute the data of a texture with a compute shader. + * + * Note: This type of texture can only be used with `WebGPURenderer` + * and a WebGPU backend. + * + * @augments Texture + */ class StorageTexture extends Texture { + /** + * Constructs a new storage texture. + * + * @param {Number} [width=1] - The storage texture's width. + * @param {Number} [height=1] - The storage texture's height. + */ constructor( width = 1, height = 1 ) { super(); + /** + * The image object which just represents the texture's dimension. + * + * @type {{width: Number, height:Number}} + */ this.image = { width, height }; + /** + * The default `magFilter` for storage textures is `THREE.LinearFilter`. + * + * @type {Number} + */ this.magFilter = LinearFilter; + + /** + * The default `minFilter` for storage textures is `THREE.LinearFilter`. + * + * @type {Number} + */ this.minFilter = LinearFilter; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isStorageTexture = true; } } +/** + * This special type of buffer attribute is intended for compute shaders. + * It can be used to encode draw parameters for indirect draw calls. + * + * Note: This type of buffer attribute can only be used with `WebGPURenderer` + * and a WebGPU backend. + * + * @augments StorageBufferAttribute + */ class IndirectStorageBufferAttribute extends StorageBufferAttribute { - constructor( array, itemSize ) { + /** + * Constructs a new storage buffer attribute. + * + * @param {Number|Uint32Array} count - The item count. It is also valid to pass a `Uint32Array` as an argument. + * The subsequent parameter is then obsolete. + * @param {Number} itemSize - The item size. + */ + constructor( count, itemSize ) { - super( array, itemSize, Uint32Array ); + super( count, itemSize, Uint32Array ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isIndirectStorageBufferAttribute = true; } @@ -55239,7 +65575,7 @@ class NodeObjectLoader extends ObjectLoader { this.nodeMaterials = {}; /** - * A reference for holdng the `nodes` JSON property. + * A reference to hold the `nodes` JSON property. * * @private * @type {Object?} @@ -55352,20 +65688,69 @@ class NodeObjectLoader extends ObjectLoader { } +/** + * In earlier three.js versions, clipping was defined globally + * on the renderer or on material level. This special version of + * `THREE.Group` allows to encode the clipping state into the scene + * graph. Meaning if you create an instance of this group, all + * descendant 3D objects will be affected by the respective clipping + * planes. + * + * Note: `ClippingGroup` can only be used with `WebGPURenderer`. + * + * @augments Group + */ class ClippingGroup extends Group { + /** + * Constructs a new clipping group. + */ constructor() { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isClippingGroup = true; + + /** + * An array with clipping planes. + * + * @type {Array} + */ this.clippingPlanes = []; + + /** + * Whether clipping should be enabled or not. + * + * @type {Boolean} + * @default true + */ this.enabled = true; + + /** + * Whether the intersection of the clipping planes is used to clip objects, rather than their union. + * + * @type {Boolean} + * @default false + */ this.clipIntersection = false; + + /** + * Whether shadows should be clipped or not. + * + * @type {Boolean} + * @default false + */ this.clipShadows = false; } } -export { ACESFilmicToneMapping, AONode, AddEquation, AddOperation, AdditiveBlending, AgXToneMapping, AlphaFormat, AlwaysCompare, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AmbientLightNode, AnalyticLightNode, ArrayElementNode, AssignNode, AttributeNode, BackSide, BasicEnvironmentNode, BasicShadowMap, BatchNode, BoxGeometry, BufferAttribute, BufferAttributeNode, BufferGeometry, BufferNode, BumpMapNode, BundleGroup, BypassNode, ByteType, CacheNode, CineonToneMapping, ClampToEdgeWrapping, ClippingGroup, CodeNode, Color, ColorManagement, ColorSpaceNode, ComputeNode, ConstNode, ContextNode, ConvertNode, CubeCamera, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureNode, CubeUVReflectionMapping, CullFaceBack, CullFaceFront, CullFaceNone, CustomBlending, DataArrayTexture, DataTexture, DecrementStencilOp, DecrementWrapStencilOp, DepthFormat, DepthStencilFormat, DepthTexture, DirectionalLight, DirectionalLightNode, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicDrawUsage, EnvironmentNode, EqualCompare, EqualDepth, EqualStencilFunc, EquirectUVNode, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExpressionNode, FileLoader, Float16BufferAttribute, Float32BufferAttribute, FloatType, FramebufferTexture, FrontFacingNode, FrontSide, Frustum, FunctionCallNode, FunctionNode, FunctionOverloadingNode, GLSLNodeParser, GreaterCompare, GreaterDepth, GreaterEqualCompare, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, Group, HalfFloatType, HemisphereLight, HemisphereLightNode, IESSpotLight, IESSpotLightNode, IncrementStencilOp, IncrementWrapStencilOp, IndexNode, IndirectStorageBufferAttribute, InstanceNode, InstancedBufferAttribute, InstancedInterleavedBuffer, InstancedMeshNode, InstancedPointsNodeMaterial, IntType, InterleavedBuffer, InterleavedBufferAttribute, InvertStencilOp, IrradianceNode, JoinNode, KeepStencilOp, LessCompare, LessDepth, LessEqualCompare, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, LightProbe, LightProbeNode, Lighting, LightingContextNode, LightingModel, LightingNode, LightsNode, Line2NodeMaterial, LineBasicMaterial, LineBasicNodeMaterial, LineDashedMaterial, LineDashedNodeMaterial, LinearFilter, LinearMipMapLinearFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearSRGBColorSpace, LinearToneMapping, Loader, LoopNode, LuminanceAlphaFormat, LuminanceFormat, MRTNode, MatcapUVNode, Material, MaterialLoader, MaterialNode, MaterialReferenceNode, MathUtils, Matrix3, Matrix4, MaxEquation, MaxMipLevelNode, Mesh, MeshBasicMaterial, MeshBasicNodeMaterial, MeshLambertMaterial, MeshLambertNodeMaterial, MeshMatcapMaterial, MeshMatcapNodeMaterial, MeshNormalMaterial, MeshNormalNodeMaterial, MeshPhongMaterial, MeshPhongNodeMaterial, MeshPhysicalMaterial, MeshPhysicalNodeMaterial, MeshSSSNodeMaterial, MeshStandardMaterial, MeshStandardNodeMaterial, MeshToonMaterial, MeshToonNodeMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, ModelNode, MorphNode, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeutralToneMapping, NeverCompare, NeverDepth, NeverStencilFunc, NoBlending, NoColorSpace, NoToneMapping, Node, NodeAccess, NodeAttribute, NodeBuilder, NodeCache, NodeCode, NodeFrame, NodeFunctionInput, NodeLoader, NodeMaterial, NodeMaterialLoader, NodeMaterialObserver, NodeObjectLoader, NodeShaderStage, NodeType, NodeUniform, NodeUpdateType, NodeUtils, NodeVar, NodeVarying, NormalBlending, NormalMapNode, NotEqualCompare, NotEqualDepth, NotEqualStencilFunc, Object3D, Object3DNode, ObjectLoader, ObjectSpaceNormalMap, OneFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, OutputStructNode, PCFShadowMap, PMREMGenerator, PMREMNode, ParameterNode, PassNode, PerspectiveCamera, PhongLightingModel, PhysicalLightingModel, Plane, PointLight, PointLightNode, PointUVNode, PointsMaterial, PointsNodeMaterial, PostProcessing, PostProcessingUtils, PosterizeNode, PropertyNode, QuadMesh, RED_GREEN_RGTC2_Format, RED_RGTC1_Format, REVISION, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBFormat, RGBIntegerFormat, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, RTTNode, RangeNode, RectAreaLight, RectAreaLightNode, RedFormat, RedIntegerFormat, ReferenceNode, ReflectorNode, ReinhardToneMapping, RemapNode, RenderOutputNode, RenderTarget, RendererReferenceNode, RepeatWrapping, ReplaceStencilOp, ReverseSubtractEquation, RotateNode, SIGNED_RED_GREEN_RGTC2_Format, SIGNED_RED_RGTC1_Format, SRGBColorSpace, SRGBTransfer, Scene, SceneNode, ScreenNode, ScriptableNode, ScriptableValueNode, SetNode, ShadowBaseNode, ShadowMaterial, ShadowNode, ShadowNodeMaterial, ShortType, SkinningNode, SphereGeometry, SplitNode, SpotLight, SpotLightNode, SpriteMaterial, SpriteNodeMaterial, SpriteSheetUVNode, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StackNode, StaticDrawUsage, StorageArrayElementNode, StorageBufferAttribute, StorageBufferNode, StorageInstancedBufferAttribute, StorageTexture, StorageTextureNode, SubtractEquation, SubtractiveBlending, TSL, TangentSpaceNormalMap, TempNode, Texture, Texture3DNode, TextureNode, TextureSizeNode, ToneMappingNode, ToonOutlinePassNode, TriplanarTexturesNode, UVMapping, Uint16BufferAttribute, Uint32BufferAttribute, UniformArrayNode, UniformGroupNode, UniformNode, UnsignedByteType, UnsignedInt248Type, UnsignedInt5999Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, UserDataNode, VSMShadowMap, VarNode, VaryingNode, Vector2, Vector3, Vector4, VertexColorNode, ViewportDepthNode, ViewportDepthTextureNode, ViewportSharedTextureNode, ViewportTextureNode, VolumeNodeMaterial, WebGLCoordinateSystem, WebGLCubeRenderTarget, WebGPUCoordinateSystem, WebGPURenderer, ZeroFactor, ZeroStencilOp, createCanvasElement, defaultBuildStages, defaultShaderStages, shaderStages, vectorComponents }; +export { ACESFilmicToneMapping, AONode, AddEquation, AddOperation, AdditiveBlending, AgXToneMapping, AlphaFormat, AlwaysCompare, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AmbientLightNode, AnalyticLightNode, ArrayElementNode, AssignNode, AttributeNode, BackSide, BasicEnvironmentNode, BasicShadowMap, BatchNode, BoxGeometry, BufferAttribute, BufferAttributeNode, BufferGeometry, BufferNode, BumpMapNode, BundleGroup, BypassNode, ByteType, CacheNode, Camera, CineonToneMapping, ClampToEdgeWrapping, ClippingGroup, CodeNode, Color, ColorManagement, ColorSpaceNode, ComputeNode, ConstNode, ContextNode, ConvertNode, CubeCamera, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureNode, CubeUVReflectionMapping, CullFaceBack, CullFaceFront, CullFaceNone, CustomBlending, DataArrayTexture, DataTexture, DecrementStencilOp, DecrementWrapStencilOp, DepthFormat, DepthStencilFormat, DepthTexture, DirectionalLight, DirectionalLightNode, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicDrawUsage, EnvironmentNode, EqualCompare, EqualDepth, EqualStencilFunc, EquirectUVNode, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExpressionNode, FileLoader, Float16BufferAttribute, Float32BufferAttribute, FloatType, FramebufferTexture, FrontFacingNode, FrontSide, Frustum, FunctionCallNode, FunctionNode, FunctionOverloadingNode, GLSLNodeParser, GreaterCompare, GreaterDepth, GreaterEqualCompare, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, Group, HalfFloatType, HemisphereLight, HemisphereLightNode, IESSpotLight, IESSpotLightNode, IncrementStencilOp, IncrementWrapStencilOp, IndexNode, IndirectStorageBufferAttribute, InstanceNode, InstancedBufferAttribute, InstancedInterleavedBuffer, InstancedMeshNode, InstancedPointsNodeMaterial, IntType, InterleavedBuffer, InterleavedBufferAttribute, InvertStencilOp, IrradianceNode, JoinNode, KeepStencilOp, LessCompare, LessDepth, LessEqualCompare, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, LightProbe, LightProbeNode, Lighting, LightingContextNode, LightingModel, LightingNode, LightsNode, Line2NodeMaterial, LineBasicMaterial, LineBasicNodeMaterial, LineDashedMaterial, LineDashedNodeMaterial, LinearFilter, LinearMipMapLinearFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearSRGBColorSpace, LinearToneMapping, Loader, LoopNode, LuminanceAlphaFormat, LuminanceFormat, MRTNode, MatcapUVNode, Material, MaterialLoader, MaterialNode, MaterialReferenceNode, MathUtils, Matrix3, Matrix4, MaxEquation, MaxMipLevelNode, Mesh, MeshBasicMaterial, MeshBasicNodeMaterial, MeshLambertMaterial, MeshLambertNodeMaterial, MeshMatcapMaterial, MeshMatcapNodeMaterial, MeshNormalMaterial, MeshNormalNodeMaterial, MeshPhongMaterial, MeshPhongNodeMaterial, MeshPhysicalMaterial, MeshPhysicalNodeMaterial, MeshSSSNodeMaterial, MeshStandardMaterial, MeshStandardNodeMaterial, MeshToonMaterial, MeshToonNodeMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, ModelNode, MorphNode, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeutralToneMapping, NeverCompare, NeverDepth, NeverStencilFunc, NoBlending, NoColorSpace, NoToneMapping, Node, NodeAccess, NodeAttribute, NodeBuilder, NodeCache, NodeCode, NodeFrame, NodeFunctionInput, NodeLoader, NodeMaterial, NodeMaterialLoader, NodeMaterialObserver, NodeObjectLoader, NodeShaderStage, NodeType, NodeUniform, NodeUpdateType, NodeUtils, NodeVar, NodeVarying, NormalBlending, NormalMapNode, NotEqualCompare, NotEqualDepth, NotEqualStencilFunc, Object3D, Object3DNode, ObjectLoader, ObjectSpaceNormalMap, OneFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, OutputStructNode, PCFShadowMap, PMREMGenerator, PMREMNode, ParameterNode, PassNode, PerspectiveCamera, PhongLightingModel, PhysicalLightingModel, Plane, PointLight, PointLightNode, PointUVNode, PointsMaterial, PointsNodeMaterial, PostProcessing, PosterizeNode, PropertyNode, QuadMesh, RED_GREEN_RGTC2_Format, RED_RGTC1_Format, REVISION, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBFormat, RGBIntegerFormat, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, RTTNode, RangeNode, RectAreaLight, RectAreaLightNode, RedFormat, RedIntegerFormat, ReferenceNode, ReflectorNode, ReinhardToneMapping, RemapNode, RenderOutputNode, RenderTarget, RendererReferenceNode, RendererUtils, RepeatWrapping, ReplaceStencilOp, ReverseSubtractEquation, RotateNode, SIGNED_RED_GREEN_RGTC2_Format, SIGNED_RED_RGTC1_Format, SRGBColorSpace, SRGBTransfer, Scene, SceneNode, ScreenNode, ScriptableNode, ScriptableValueNode, SetNode, ShadowBaseNode, ShadowMaterial, ShadowNode, ShadowNodeMaterial, ShortType, SkinningNode, SphereGeometry, SplitNode, SpotLight, SpotLightNode, SpriteMaterial, SpriteNodeMaterial, SpriteSheetUVNode, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StackNode, StaticDrawUsage, StorageArrayElementNode, StorageBufferAttribute, StorageBufferNode, StorageInstancedBufferAttribute, StorageTexture, StorageTextureNode, SubtractEquation, SubtractiveBlending, TSL, TangentSpaceNormalMap, TempNode, Texture, Texture3DNode, TextureNode, TextureSizeNode, ToneMappingNode, ToonOutlinePassNode, TriplanarTexturesNode, UVMapping, Uint16BufferAttribute, Uint32BufferAttribute, UniformArrayNode, UniformGroupNode, UniformNode, UnsignedByteType, UnsignedInt248Type, UnsignedInt5999Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, UserDataNode, VSMShadowMap, VarNode, VaryingNode, Vector2, Vector3, Vector4, VertexColorNode, ViewportDepthNode, ViewportDepthTextureNode, ViewportSharedTextureNode, ViewportTextureNode, VolumeNodeMaterial, WebGLCoordinateSystem, WebGLCubeRenderTarget, WebGPUCoordinateSystem, WebGPURenderer, ZeroFactor, ZeroStencilOp, createCanvasElement, defaultBuildStages, defaultShaderStages, shaderStages, vectorComponents }; diff --git a/build/three.webgpu.min.js b/build/three.webgpu.min.js index 5e31b7fcdc092d..75d4d878fe8b47 100644 --- a/build/three.webgpu.min.js +++ b/build/three.webgpu.min.js @@ -1,6 +1,6 @@ /** * @license - * Copyright 2010-2024 Three.js Authors + * Copyright 2010-2025 Three.js Authors * SPDX-License-Identifier: MIT */ -import{Color as e,Vector2 as t,Vector3 as r,Vector4 as s,Matrix3 as i,Matrix4 as n,EventDispatcher as o,MathUtils as a,WebGLCoordinateSystem as u,WebGPUCoordinateSystem as l,ColorManagement as d,SRGBTransfer as c,NoToneMapping as h,StaticDrawUsage as p,InterleavedBuffer as g,DynamicDrawUsage as m,InterleavedBufferAttribute as f,NoColorSpace as y,UnsignedIntType as x,IntType as b,BackSide as T,CubeReflectionMapping as _,CubeRefractionMapping as v,TangentSpaceNormalMap as N,ObjectSpaceNormalMap as S,InstancedInterleavedBuffer as A,InstancedBufferAttribute as R,DataArrayTexture as C,FloatType as E,FramebufferTexture as w,LinearMipmapLinearFilter as M,DepthTexture as B,Material as U,NormalBlending as F,PointsMaterial as P,LineBasicMaterial as I,LineDashedMaterial as L,NoBlending as V,MeshNormalMaterial as D,WebGLCubeRenderTarget as O,BoxGeometry as G,Mesh as k,Scene as z,LinearFilter as $,CubeCamera as H,CubeTexture as W,EquirectangularReflectionMapping as j,EquirectangularRefractionMapping as q,AddOperation as K,MixOperation as X,MultiplyOperation as Y,MeshBasicMaterial as Q,MeshLambertMaterial as Z,MeshPhongMaterial as J,Texture as ee,MeshStandardMaterial as te,MeshPhysicalMaterial as re,MeshToonMaterial as se,MeshMatcapMaterial as ie,SpriteMaterial as ne,ShadowMaterial as oe,Uint32BufferAttribute as ae,Uint16BufferAttribute as ue,DoubleSide as le,DepthStencilFormat as de,DepthFormat as ce,UnsignedInt248Type as he,UnsignedByteType as pe,RenderTarget as ge,Plane as me,Object3D as fe,HalfFloatType as ye,LinearMipMapLinearFilter as xe,OrthographicCamera as be,BufferGeometry as Te,Float32BufferAttribute as _e,BufferAttribute as ve,UVMapping as Ne,Euler as Se,LinearSRGBColorSpace as Ae,LessCompare as Re,VSMShadowMap as Ce,RGFormat as Ee,BasicShadowMap as we,SphereGeometry as Me,CubeUVReflectionMapping as Be,PerspectiveCamera as Ue,RGBAFormat as Fe,LinearMipmapNearestFilter as Pe,NearestMipmapLinearFilter as Ie,Float16BufferAttribute as Le,REVISION as Ve,SRGBColorSpace as De,PCFShadowMap as Oe,FrontSide as Ge,Frustum as ke,DataTexture as ze,RedIntegerFormat as $e,RedFormat as He,RGIntegerFormat as We,RGBIntegerFormat as je,RGBFormat as qe,RGBAIntegerFormat as Ke,UnsignedShortType as Xe,ByteType as Ye,ShortType as Qe,createCanvasElement as Ze,AddEquation as Je,SubtractEquation as et,ReverseSubtractEquation as tt,ZeroFactor as rt,OneFactor as st,SrcColorFactor as it,SrcAlphaFactor as nt,SrcAlphaSaturateFactor as ot,DstColorFactor as at,DstAlphaFactor as ut,OneMinusSrcColorFactor as lt,OneMinusSrcAlphaFactor as dt,OneMinusDstColorFactor as ct,OneMinusDstAlphaFactor as ht,CullFaceNone as pt,CullFaceBack as gt,CullFaceFront as mt,CustomBlending as ft,MultiplyBlending as yt,SubtractiveBlending as xt,AdditiveBlending as bt,NotEqualDepth as Tt,GreaterDepth as _t,GreaterEqualDepth as vt,EqualDepth as Nt,LessEqualDepth as St,LessDepth as At,AlwaysDepth as Rt,NeverDepth as Ct,UnsignedShort4444Type as Et,UnsignedShort5551Type as wt,UnsignedInt5999Type as Mt,AlphaFormat as Bt,LuminanceFormat as Ut,LuminanceAlphaFormat as Ft,RGB_S3TC_DXT1_Format as Pt,RGBA_S3TC_DXT1_Format as It,RGBA_S3TC_DXT3_Format as Lt,RGBA_S3TC_DXT5_Format as Vt,RGB_PVRTC_4BPPV1_Format as Dt,RGB_PVRTC_2BPPV1_Format as Ot,RGBA_PVRTC_4BPPV1_Format as Gt,RGBA_PVRTC_2BPPV1_Format as kt,RGB_ETC1_Format as zt,RGB_ETC2_Format as $t,RGBA_ETC2_EAC_Format as Ht,RGBA_ASTC_4x4_Format as Wt,RGBA_ASTC_5x4_Format as jt,RGBA_ASTC_5x5_Format as qt,RGBA_ASTC_6x5_Format as Kt,RGBA_ASTC_6x6_Format as Xt,RGBA_ASTC_8x5_Format as Yt,RGBA_ASTC_8x6_Format as Qt,RGBA_ASTC_8x8_Format as Zt,RGBA_ASTC_10x5_Format as Jt,RGBA_ASTC_10x6_Format as er,RGBA_ASTC_10x8_Format as tr,RGBA_ASTC_10x10_Format as rr,RGBA_ASTC_12x10_Format as sr,RGBA_ASTC_12x12_Format as ir,RGBA_BPTC_Format as nr,RED_RGTC1_Format as or,SIGNED_RED_RGTC1_Format as ar,RED_GREEN_RGTC2_Format as ur,SIGNED_RED_GREEN_RGTC2_Format as lr,RepeatWrapping as dr,ClampToEdgeWrapping as cr,MirroredRepeatWrapping as hr,NearestFilter as pr,NearestMipmapNearestFilter as gr,NeverCompare as mr,AlwaysCompare as fr,LessEqualCompare as yr,EqualCompare as xr,GreaterEqualCompare as br,GreaterCompare as Tr,NotEqualCompare as _r,warnOnce as vr,NotEqualStencilFunc as Nr,GreaterStencilFunc as Sr,GreaterEqualStencilFunc as Ar,EqualStencilFunc as Rr,LessEqualStencilFunc as Cr,LessStencilFunc as Er,AlwaysStencilFunc as wr,NeverStencilFunc as Mr,DecrementWrapStencilOp as Br,IncrementWrapStencilOp as Ur,DecrementStencilOp as Fr,IncrementStencilOp as Pr,InvertStencilOp as Ir,ReplaceStencilOp as Lr,ZeroStencilOp as Vr,KeepStencilOp as Dr,MaxEquation as Or,MinEquation as Gr,SpotLight as kr,PointLight as zr,DirectionalLight as $r,RectAreaLight as Hr,AmbientLight as Wr,HemisphereLight as jr,LightProbe as qr,LinearToneMapping as Kr,ReinhardToneMapping as Xr,CineonToneMapping as Yr,ACESFilmicToneMapping as Qr,AgXToneMapping as Zr,NeutralToneMapping as Jr,Group as es,Loader as ts,FileLoader as rs,MaterialLoader as ss,ObjectLoader as is}from"./three.core.min.js";export{AdditiveAnimationBlendMode,AnimationAction,AnimationClip,AnimationLoader,AnimationMixer,AnimationObjectGroup,AnimationUtils,ArcCurve,ArrayCamera,ArrowHelper,AttachedBindMode,Audio,AudioAnalyser,AudioContext,AudioListener,AudioLoader,AxesHelper,BasicDepthPacking,BatchedMesh,Bone,BooleanKeyframeTrack,Box2,Box3,Box3Helper,BoxHelper,BufferGeometryLoader,Cache,Camera,CameraHelper,CanvasTexture,CapsuleGeometry,CatmullRomCurve3,CircleGeometry,Clock,ColorKeyframeTrack,CompressedArrayTexture,CompressedCubeTexture,CompressedTexture,CompressedTextureLoader,ConeGeometry,ConstantAlphaFactor,ConstantColorFactor,Controls,CubeTextureLoader,CubicBezierCurve,CubicBezierCurve3,CubicInterpolant,CullFaceFrontBack,Curve,CurvePath,CustomToneMapping,CylinderGeometry,Cylindrical,Data3DTexture,DataTextureLoader,DataUtils,DefaultLoadingManager,DetachedBindMode,DirectionalLightHelper,DiscreteInterpolant,DodecahedronGeometry,DynamicCopyUsage,DynamicReadUsage,EdgesGeometry,EllipseCurve,ExtrudeGeometry,Fog,FogExp2,GLBufferAttribute,GLSL1,GLSL3,GridHelper,HemisphereLightHelper,IcosahedronGeometry,ImageBitmapLoader,ImageLoader,ImageUtils,InstancedBufferGeometry,InstancedMesh,Int16BufferAttribute,Int32BufferAttribute,Int8BufferAttribute,Interpolant,InterpolateDiscrete,InterpolateLinear,InterpolateSmooth,KeyframeTrack,LOD,LatheGeometry,Layers,Light,Line,Line3,LineCurve,LineCurve3,LineLoop,LineSegments,LinearInterpolant,LinearMipMapNearestFilter,LinearTransfer,LoaderUtils,LoadingManager,LoopOnce,LoopPingPong,LoopRepeat,MOUSE,Matrix2,MeshDepthMaterial,MeshDistanceMaterial,NearestMipMapLinearFilter,NearestMipMapNearestFilter,NormalAnimationBlendMode,NumberKeyframeTrack,OctahedronGeometry,OneMinusConstantAlphaFactor,OneMinusConstantColorFactor,PCFSoftShadowMap,Path,PlaneGeometry,PlaneHelper,PointLightHelper,Points,PolarGridHelper,PolyhedronGeometry,PositionalAudio,PropertyBinding,PropertyMixer,QuadraticBezierCurve,QuadraticBezierCurve3,Quaternion,QuaternionKeyframeTrack,QuaternionLinearInterpolant,RGBADepthPacking,RGBDepthPacking,RGB_BPTC_SIGNED_Format,RGB_BPTC_UNSIGNED_Format,RGDepthPacking,RawShaderMaterial,Ray,Raycaster,RingGeometry,ShaderMaterial,Shape,ShapeGeometry,ShapePath,ShapeUtils,Skeleton,SkeletonHelper,SkinnedMesh,Source,Sphere,Spherical,SphericalHarmonics3,SplineCurve,SpotLightHelper,Sprite,StaticCopyUsage,StaticReadUsage,StereoCamera,StreamCopyUsage,StreamDrawUsage,StreamReadUsage,StringKeyframeTrack,TOUCH,TetrahedronGeometry,TextureLoader,TextureUtils,TorusGeometry,TorusKnotGeometry,Triangle,TriangleFanDrawMode,TriangleStripDrawMode,TrianglesDrawMode,TubeGeometry,Uint8BufferAttribute,Uint8ClampedBufferAttribute,Uniform,UniformsGroup,VectorKeyframeTrack,VideoTexture,WebGL3DRenderTarget,WebGLArrayRenderTarget,WebGLRenderTarget,WireframeGeometry,WrapAroundEnding,ZeroCurvatureEnding,ZeroSlopeEnding}from"./three.core.min.js";const ns=["alphaMap","alphaTest","anisotropy","anisotropyMap","anisotropyRotation","aoMap","attenuationColor","attenuationDistance","bumpMap","clearcoat","clearcoatMap","clearcoatNormalMap","clearcoatNormalScale","clearcoatRoughness","color","dispersion","displacementMap","emissive","emissiveMap","envMap","gradientMap","ior","iridescence","iridescenceIOR","iridescenceMap","iridescenceThicknessMap","lightMap","map","matcap","metalness","metalnessMap","normalMap","normalScale","opacity","roughness","roughnessMap","sheen","sheenColor","sheenColorMap","sheenRoughnessMap","shininess","specular","specularColor","specularColorMap","specularIntensity","specularIntensityMap","specularMap","thickness","transmission","transmissionMap"];class os{constructor(e){this.renderObjects=new WeakMap,this.hasNode=this.containsNode(e),this.hasAnimation=!0===e.object.isSkinnedMesh,this.refreshUniforms=ns,this.renderId=0}firstInitialization(e){return!1===this.renderObjects.has(e)&&(this.getRenderObjectData(e),!0)}getRenderObjectData(e){let t=this.renderObjects.get(e);if(void 0===t){const{geometry:r,material:s,object:i}=e;if(t={material:this.getMaterialData(s),geometry:{attributes:this.getAttributesData(r.attributes),indexVersion:r.index?r.index.version:null,drawRange:{start:r.drawRange.start,count:r.drawRange.count}},worldMatrix:i.matrixWorld.clone()},i.center&&(t.center=i.center.clone()),i.morphTargetInfluences&&(t.morphTargetInfluences=i.morphTargetInfluences.slice()),null!==e.bundle&&(t.version=e.bundle.version),t.material.transmission>0){const{width:r,height:s}=e.context;t.bufferWidth=r,t.bufferHeight=s}this.renderObjects.set(e,t)}return t}getAttributesData(e){const t={};for(const r in e){const s=e[r];t[r]={version:s.version}}return t}containsNode(e){const t=e.material;for(const e in t)if(t[e]&&t[e].isNode)return!0;return null!==e.renderer.nodes.modelViewMatrix||null!==e.renderer.nodes.modelNormalViewMatrix}getMaterialData(e){const t={};for(const r of this.refreshUniforms){const s=e[r];null!=s&&("object"==typeof s&&void 0!==s.clone?!0===s.isTexture?t[r]={id:s.id,version:s.version}:t[r]=s.clone():t[r]=s)}return t}equals(e){const{object:t,material:r,geometry:s}=e,i=this.getRenderObjectData(e);if(!0!==i.worldMatrix.equals(t.matrixWorld))return i.worldMatrix.copy(t.matrixWorld),!1;const n=i.material;for(const e in n){const t=n[e],s=r[e];if(void 0!==t.equals){if(!1===t.equals(s))return t.copy(s),!1}else if(!0===s.isTexture){if(t.id!==s.id||t.version!==s.version)return t.id=s.id,t.version=s.version,!1}else if(t!==s)return n[e]=s,!1}if(n.transmission>0){const{width:t,height:r}=e.context;if(i.bufferWidth!==t||i.bufferHeight!==r)return i.bufferWidth=t,i.bufferHeight=r,!1}const o=i.geometry,a=s.attributes,u=o.attributes,l=Object.keys(u),d=Object.keys(a);if(l.length!==d.length)return i.geometry.attributes=this.getAttributesData(a),!1;for(const e of l){const t=u[e],r=a[e];if(void 0===r)return delete u[e],!1;if(t.version!==r.version)return t.version=r.version,!1}const c=s.index,h=o.indexVersion,p=c?c.version:null;if(h!==p)return o.indexVersion=p,!1;if(o.drawRange.start!==s.drawRange.start||o.drawRange.count!==s.drawRange.count)return o.drawRange.start=s.drawRange.start,o.drawRange.count=s.drawRange.count,!1;if(i.morphTargetInfluences){let e=!1;for(let r=0;r>>16,2246822507),r^=Math.imul(s^s>>>13,3266489909),s=Math.imul(s^s>>>16,2246822507),s^=Math.imul(r^r>>>13,3266489909),4294967296*(2097151&s)+(r>>>0)}const us=e=>as(e),ls=e=>as(e),ds=(...e)=>as(e);function cs(e,t=!1){const r=[];!0===e.isNode&&(r.push(e.id),e=e.getSelf());for(const{property:s,childNode:i}of hs(e))r.push(r,as(s.slice(0,-4)),i.getCacheKey(t));return as(r)}function*hs(e,t=!1){for(const r in e){if(!0===r.startsWith("_"))continue;const s=e[r];if(!0===Array.isArray(s))for(let e=0;ee.charCodeAt(0))).buffer}var Ts=Object.freeze({__proto__:null,arrayBufferToBase64:xs,base64ToArrayBuffer:bs,getCacheKey:cs,getLengthFromType:ms,getNodeChildren:hs,getTypeFromLength:gs,getValueFromType:ys,getValueType:fs,hash:ds,hashArray:ls,hashString:us});const _s={VERTEX:"vertex",FRAGMENT:"fragment"},vs={NONE:"none",FRAME:"frame",RENDER:"render",OBJECT:"object"},Ns={BOOLEAN:"bool",INTEGER:"int",FLOAT:"float",VECTOR2:"vec2",VECTOR3:"vec3",VECTOR4:"vec4",MATRIX2:"mat2",MATRIX3:"mat3",MATRIX4:"mat4"},Ss={READ_ONLY:"readOnly",WRITE_ONLY:"writeOnly",READ_WRITE:"readWrite"},As=["fragment","vertex"],Rs=["setup","analyze","generate"],Cs=[...As,"compute"],Es=["x","y","z","w"];let ws=0;class Ms extends o{static get type(){return"Node"}constructor(e=null){super(),this.nodeType=e,this.updateType=vs.NONE,this.updateBeforeType=vs.NONE,this.updateAfterType=vs.NONE,this.uuid=a.generateUUID(),this.version=0,this.global=!1,this.isNode=!0,this._cacheKey=null,this._cacheKeyVersion=0,Object.defineProperty(this,"id",{value:ws++})}set needsUpdate(e){!0===e&&this.version++}get type(){return this.constructor.type}onUpdate(e,t){return this.updateType=t,this.update=e.bind(this.getSelf()),this}onFrameUpdate(e){return this.onUpdate(e,vs.FRAME)}onRenderUpdate(e){return this.onUpdate(e,vs.RENDER)}onObjectUpdate(e){return this.onUpdate(e,vs.OBJECT)}onReference(e){return this.updateReference=e.bind(this.getSelf()),this}getSelf(){return this.self||this}updateReference(){return this}isGlobal(){return this.global}*getChildren(){for(const{childNode:e}of hs(this))yield e}dispose(){this.dispatchEvent({type:"dispose"})}traverse(e){e(this);for(const t of this.getChildren())t.traverse(e)}getCacheKey(e=!1){return!0!==(e=e||this.version!==this._cacheKeyVersion)&&null!==this._cacheKey||(this._cacheKey=ds(cs(this,e),this.customCacheKey()),this._cacheKeyVersion=this.version),this._cacheKey}customCacheKey(){return 0}getScope(){return this}getHash(){return this.uuid}getUpdateType(){return this.updateType}getUpdateBeforeType(){return this.updateBeforeType}getUpdateAfterType(){return this.updateAfterType}getElementType(e){const t=this.getNodeType(e);return e.getElementType(t)}getNodeType(e){const t=e.getNodeProperties(this);return t.outputNode?t.outputNode.getNodeType(e):this.nodeType}getShared(e){const t=this.getHash(e);return e.getNodeFromHash(t)||this}setup(e){const t=e.getNodeProperties(this);let r=0;for(const e of this.getChildren())t["node"+r++]=e;return null}analyze(e){if(1===e.increaseUsage(this)){const t=e.getNodeProperties(this);for(const r of Object.values(t))r&&!0===r.isNode&&r.build(e)}}generate(e,t){const{outputNode:r}=e.getNodeProperties(this);if(r&&!0===r.isNode)return r.build(e,t)}updateBefore(){console.warn("Abstract function.")}updateAfter(){console.warn("Abstract function.")}update(){console.warn("Abstract function.")}build(e,t=null){const r=this.getShared(e);if(this!==r)return r.build(e,t);e.addNode(this),e.addChain(this);let s=null;const i=e.getBuildStage();if("setup"===i){this.updateReference(e);const t=e.getNodeProperties(this);if(!0!==t.initialized){e.stack.nodes.length;t.initialized=!0,t.outputNode=this.setup(e),null!==t.outputNode&&e.stack.nodes.length;for(const r of Object.values(t))r&&!0===r.isNode&&r.build(e)}}else if("analyze"===i)this.analyze(e);else if("generate"===i){if(1===this.generate.length){const r=this.getNodeType(e),i=e.getDataFromNode(this);s=i.snippet,void 0===s?(s=this.generate(e)||"",i.snippet=s):void 0!==i.flowCodes&&void 0!==e.context.nodeBlock&&e.addFlowCodeHierarchy(this,e.context.nodeBlock),s=e.format(s,r,t)}else s=this.generate(e,t)||""}return e.removeChain(this),e.addSequentialNode(this),s}getSerializeChildren(){return hs(this)}serialize(e){const t=this.getSerializeChildren(),r={};for(const{property:s,index:i,childNode:n}of t)void 0!==i?(void 0===r[s]&&(r[s]=Number.isInteger(i)?[]:{}),r[s][i]=n.toJSON(e.meta).uuid):r[s]=n.toJSON(e.meta).uuid;Object.keys(r).length>0&&(e.inputNodes=r)}deserialize(e){if(void 0!==e.inputNodes){const t=e.meta.nodes;for(const r in e.inputNodes)if(Array.isArray(e.inputNodes[r])){const s=[];for(const i of e.inputNodes[r])s.push(t[i]);this[r]=s}else if("object"==typeof e.inputNodes[r]){const s={};for(const i in e.inputNodes[r]){const n=e.inputNodes[r][i];s[i]=t[n]}this[r]=s}else{const s=e.inputNodes[r];this[r]=t[s]}}}toJSON(e){const{uuid:t,type:r}=this,s=void 0===e||"string"==typeof e;s&&(e={textures:{},images:{},nodes:{}});let i=e.nodes[t];function n(e){const t=[];for(const r in e){const s=e[r];delete s.metadata,t.push(s)}return t}if(void 0===i&&(i={uuid:t,type:r,meta:e,metadata:{version:4.6,type:"Node",generator:"Node.toJSON"}},!0!==s&&(e.nodes[i.uuid]=i),this.serialize(i),delete i.meta),s){const t=n(e.textures),r=n(e.images),s=n(e.nodes);t.length>0&&(i.textures=t),r.length>0&&(i.images=r),s.length>0&&(i.nodes=s)}return i}}class Bs extends Ms{static get type(){return"ArrayElementNode"}constructor(e,t){super(),this.node=e,this.indexNode=t,this.isArrayElementNode=!0}getNodeType(e){return this.node.getElementType(e)}generate(e){return`${this.node.build(e)}[ ${this.indexNode.build(e,"uint")} ]`}}class Us extends Ms{static get type(){return"ConvertNode"}constructor(e,t){super(),this.node=e,this.convertTo=t}getNodeType(e){const t=this.node.getNodeType(e);let r=null;for(const s of this.convertTo.split("|"))null!==r&&e.getTypeLength(t)!==e.getTypeLength(s)||(r=s);return r}serialize(e){super.serialize(e),e.convertTo=this.convertTo}deserialize(e){super.deserialize(e),this.convertTo=e.convertTo}generate(e,t){const r=this.node,s=this.getNodeType(e),i=r.build(e,s);return e.format(i,s,t)}}class Fs extends Ms{static get type(){return"TempNode"}constructor(e=null){super(e),this.isTempNode=!0}hasDependencies(e){return e.getDataFromNode(this).usageCount>1}build(e,t){if("generate"===e.getBuildStage()){const r=e.getVectorType(this.getNodeType(e,t)),s=e.getDataFromNode(this);if(void 0!==s.propertyName)return e.format(s.propertyName,r,t);if("void"!==r&&"void"!==t&&this.hasDependencies(e)){const i=super.build(e,r),n=e.getVarFromNode(this,null,r),o=e.getPropertyName(n);return e.addLineFlowCode(`${o} = ${i}`,this),s.snippet=i,s.propertyName=o,e.format(s.propertyName,r,t)}}return super.build(e,t)}}class Ps extends Fs{static get type(){return"JoinNode"}constructor(e=[],t=null){super(t),this.nodes=e}getNodeType(e){return null!==this.nodeType?e.getVectorType(this.nodeType):e.getTypeFromLength(this.nodes.reduce(((t,r)=>t+e.getTypeLength(r.getNodeType(e))),0))}generate(e,t){const r=this.getNodeType(e),s=this.nodes,i=e.getComponentType(r),n=[];for(const t of s){let r=t.build(e);const s=e.getComponentType(t.getNodeType(e));s!==i&&(r=e.format(r,s,i)),n.push(r)}const o=`${e.getType(r)}( ${n.join(", ")} )`;return e.format(o,r,t)}}const Is=Es.join("");class Ls extends Ms{static get type(){return"SplitNode"}constructor(e,t="x"){super(),this.node=e,this.components=t,this.isSplitNode=!0}getVectorLength(){let e=this.components.length;for(const t of this.components)e=Math.max(Es.indexOf(t)+1,e);return e}getComponentType(e){return e.getComponentType(this.node.getNodeType(e))}getNodeType(e){return e.getTypeFromLength(this.components.length,this.getComponentType(e))}generate(e,t){const r=this.node,s=e.getTypeLength(r.getNodeType(e));let i=null;if(s>1){let n=null;this.getVectorLength()>=s&&(n=e.getTypeFromLength(this.getVectorLength(),this.getComponentType(e)));const o=r.build(e,n);i=this.components.length===s&&this.components===Is.slice(0,this.components.length)?e.format(o,n,t):e.format(`${o}.${this.components}`,this.getNodeType(e),t)}else i=r.build(e,t);return i}serialize(e){super.serialize(e),e.components=this.components}deserialize(e){super.deserialize(e),this.components=e.components}}class Vs extends Fs{static get type(){return"SetNode"}constructor(e,t,r){super(),this.sourceNode=e,this.components=t,this.targetNode=r}getNodeType(e){return this.sourceNode.getNodeType(e)}generate(e){const{sourceNode:t,components:r,targetNode:s}=this,i=this.getNodeType(e),n=e.getComponentType(s.getNodeType(e)),o=e.getTypeFromLength(r.length,n),a=s.build(e,o),u=t.build(e,i),l=e.getTypeLength(i),d=[];for(let e=0;ee.replace(/r|s/g,"x").replace(/g|t/g,"y").replace(/b|p/g,"z").replace(/a|q/g,"w"),Ws=e=>Hs(e).split("").sort().join(""),js={setup(e,t){const r=t.shift();return e(yi(r),...t)},get(e,t,r){if("string"==typeof t&&void 0===e[t]){if(!0!==e.isStackNode&&"assign"===t)return(...e)=>(ks.assign(r,...e),r);if(zs.has(t)){const s=zs.get(t);return e.isStackNode?(...e)=>r.add(s(...e)):(...e)=>s(r,...e)}if("self"===t)return e;if(t.endsWith("Assign")&&zs.has(t.slice(0,t.length-6))){const s=zs.get(t.slice(0,t.length-6));return e.isStackNode?(...e)=>r.assign(e[0],s(...e)):(...e)=>r.assign(s(r,...e))}if(!0===/^[xyzwrgbastpq]{1,4}$/.test(t))return t=Hs(t),fi(new Ls(r,t));if(!0===/^set[XYZWRGBASTPQ]{1,4}$/.test(t))return t=Ws(t.slice(3).toLowerCase()),r=>fi(new Vs(e,t,r));if(!0===/^flip[XYZWRGBASTPQ]{1,4}$/.test(t))return t=Ws(t.slice(4).toLowerCase()),()=>fi(new Ds(fi(e),t));if("width"===t||"height"===t||"depth"===t)return"width"===t?t="x":"height"===t?t="y":"depth"===t&&(t="z"),fi(new Ls(e,t));if(!0===/^\d+$/.test(t))return fi(new Bs(r,new Gs(Number(t),"uint")))}return Reflect.get(e,t,r)},set:(e,t,r,s)=>"string"!=typeof t||void 0!==e[t]||!0!==/^[xyzwrgbastpq]{1,4}$/.test(t)&&"width"!==t&&"height"!==t&&"depth"!==t&&!0!==/^\d+$/.test(t)?Reflect.set(e,t,r,s):(s[t].assign(r),!0)},qs=new WeakMap,Ks=new WeakMap,Xs=function(e,t=null){for(const r in e)e[r]=fi(e[r],t);return e},Ys=function(e,t=null){const r=e.length;for(let s=0;sfi(null!==s?Object.assign(e,s):e);return null===t?(...t)=>i(new e(...xi(t))):null!==r?(r=fi(r),(...s)=>i(new e(t,...xi(s),r))):(...r)=>i(new e(t,...xi(r)))},Zs=function(e,...t){return fi(new e(...xi(t)))};class Js extends Ms{constructor(e,t){super(),this.shaderNode=e,this.inputNodes=t}getNodeType(e){return this.shaderNode.nodeType||this.getOutputNode(e).getNodeType(e)}call(e){const{shaderNode:t,inputNodes:r}=this,s=e.getNodeProperties(t);if(s.onceOutput)return s.onceOutput;let i=null;if(t.layout){let s=Ks.get(e.constructor);void 0===s&&(s=new WeakMap,Ks.set(e.constructor,s));let n=s.get(t);void 0===n&&(n=fi(e.buildFunctionNode(t)),s.set(t,n)),null!==e.currentFunctionNode&&e.currentFunctionNode.includes.push(n),i=fi(n.call(r))}else{const s=t.jsFunc,n=null!==r?s(r,e):s(e);i=fi(n)}return t.once&&(s.onceOutput=i),i}getOutputNode(e){const t=e.getNodeProperties(this);return null===t.outputNode&&(t.outputNode=this.setupOutput(e)),t.outputNode}setup(e){return this.getOutputNode(e)}setupOutput(e){return e.addStack(),e.stack.outputNode=this.call(e),e.removeStack()}generate(e,t){return this.getOutputNode(e).build(e,t)}}class ei extends Ms{constructor(e,t){super(t),this.jsFunc=e,this.layout=null,this.global=!0,this.once=!1}setLayout(e){return this.layout=e,this}call(e=null){return yi(e),fi(new Js(this,e))}setup(){return this.call()}}const ti=[!1,!0],ri=[0,1,2,3],si=[-1,-2],ii=[.5,1.5,1/3,1e-6,1e6,Math.PI,2*Math.PI,1/Math.PI,2/Math.PI,1/(2*Math.PI),Math.PI/2],ni=new Map;for(const e of ti)ni.set(e,new Gs(e));const oi=new Map;for(const e of ri)oi.set(e,new Gs(e,"uint"));const ai=new Map([...oi].map((e=>new Gs(e.value,"int"))));for(const e of si)ai.set(e,new Gs(e,"int"));const ui=new Map([...ai].map((e=>new Gs(e.value))));for(const e of ii)ui.set(e,new Gs(e));for(const e of ii)ui.set(-e,new Gs(-e));const li={bool:ni,uint:oi,ints:ai,float:ui},di=new Map([...ni,...ui]),ci=(e,t)=>di.has(e)?di.get(e):!0===e.isNode?e:new Gs(e,t),hi=function(e,t=null){return(...r)=>{if((0===r.length||!["bool","float","int","uint"].includes(e)&&r.every((e=>"object"!=typeof e)))&&(r=[ys(e,...r)]),1===r.length&&null!==t&&t.has(r[0]))return fi(t.get(r[0]));if(1===r.length){const t=ci(r[0],e);return(e=>{try{return e.getNodeType()}catch(e){return}})(t)===e?fi(t):fi(new Us(t,e))}const s=r.map((e=>ci(e)));return fi(new Ps(s,e))}},pi=e=>"object"==typeof e&&null!==e?e.value:e,gi=e=>null!=e?e.nodeType||e.convertTo||("string"==typeof e?e:null):null;function mi(e,t){return new Proxy(new ei(e,t),js)}const fi=(e,t=null)=>function(e,t=null){const r=fs(e);if("node"===r){let t=qs.get(e);return void 0===t&&(t=new Proxy(e,js),qs.set(e,t),qs.set(t,t)),t}return null===t&&("float"===r||"boolean"===r)||r&&"shader"!==r&&"string"!==r?fi(ci(e,t)):"shader"===r?_i(e):e}(e,t),yi=(e,t=null)=>new Xs(e,t),xi=(e,t=null)=>new Ys(e,t),bi=(...e)=>new Qs(...e),Ti=(...e)=>new Zs(...e),_i=(e,t)=>{const r=new mi(e,t),s=(...e)=>{let t;return yi(e),t=e[0]&&e[0].isNode?[...e]:e[0],r.call(t)};return s.shaderNode=r,s.setLayout=e=>(r.setLayout(e),s),s.once=()=>(r.once=!0,s),s};$s("toGlobal",(e=>(e.global=!0,e)));const vi=e=>{ks=e},Ni=()=>ks,Si=(...e)=>ks.If(...e);function Ai(e){return ks&&ks.add(e),e}$s("append",Ai);const Ri=new hi("color"),Ci=new hi("float",li.float),Ei=new hi("int",li.ints),wi=new hi("uint",li.uint),Mi=new hi("bool",li.bool),Bi=new hi("vec2"),Ui=new hi("ivec2"),Fi=new hi("uvec2"),Pi=new hi("bvec2"),Ii=new hi("vec3"),Li=new hi("ivec3"),Vi=new hi("uvec3"),Di=new hi("bvec3"),Oi=new hi("vec4"),Gi=new hi("ivec4"),ki=new hi("uvec4"),zi=new hi("bvec4"),$i=new hi("mat2"),Hi=new hi("mat3"),Wi=new hi("mat4");$s("toColor",Ri),$s("toFloat",Ci),$s("toInt",Ei),$s("toUint",wi),$s("toBool",Mi),$s("toVec2",Bi),$s("toIVec2",Ui),$s("toUVec2",Fi),$s("toBVec2",Pi),$s("toVec3",Ii),$s("toIVec3",Li),$s("toUVec3",Vi),$s("toBVec3",Di),$s("toVec4",Oi),$s("toIVec4",Gi),$s("toUVec4",ki),$s("toBVec4",zi),$s("toMat2",$i),$s("toMat3",Hi),$s("toMat4",Wi);const ji=bi(Bs),qi=(e,t)=>fi(new Us(fi(e),t));$s("element",ji),$s("convert",qi);class Ki extends Ms{static get type(){return"UniformGroupNode"}constructor(e,t=!1,r=1){super("string"),this.name=e,this.shared=t,this.order=r,this.isUniformGroup=!0}serialize(e){super.serialize(e),e.name=this.name,e.version=this.version,e.shared=this.shared}deserialize(e){super.deserialize(e),this.name=e.name,this.version=e.version,this.shared=e.shared}}const Xi=e=>new Ki(e),Yi=(e,t=0)=>new Ki(e,!0,t),Qi=Yi("frame"),Zi=Yi("render"),Ji=Xi("object");class en extends Os{static get type(){return"UniformNode"}constructor(e,t=null){super(e,t),this.isUniformNode=!0,this.name="",this.groupNode=Ji}label(e){return this.name=e,this}setGroup(e){return this.groupNode=e,this}getGroup(){return this.groupNode}getUniformHash(e){return this.getHash(e)}onUpdate(e,t){const r=this.getSelf();return e=e.bind(r),super.onUpdate((t=>{const s=e(t,r);void 0!==s&&(this.value=s)}),t)}generate(e,t){const r=this.getNodeType(e),s=this.getUniformHash(e);let i=e.getNodeFromHash(s);void 0===i&&(e.setHashNode(this,s),i=this);const n=i.getInputType(e),o=e.getUniformFromNode(i,n,e.shaderStage,this.name||e.context.label),a=e.getPropertyName(o);return void 0!==e.context.label&&delete e.context.label,e.format(a,r,t)}}const tn=(e,t)=>{const r=gi(t||e),s=e&&!0===e.isNode?e.node&&e.node.value||e.value:e;return fi(new en(s,r))};class rn extends Ms{static get type(){return"PropertyNode"}constructor(e,t=null,r=!1){super(e),this.name=t,this.varying=r,this.isPropertyNode=!0}getHash(e){return this.name||super.getHash(e)}isGlobal(){return!0}generate(e){let t;return!0===this.varying?(t=e.getVaryingFromNode(this,this.name),t.needsInterpolation=!0):t=e.getVarFromNode(this,this.name),e.getPropertyName(t)}}const sn=(e,t)=>fi(new rn(e,t)),nn=(e,t)=>fi(new rn(e,t,!0)),on=Ti(rn,"vec4","DiffuseColor"),an=Ti(rn,"vec3","EmissiveColor"),un=Ti(rn,"float","Roughness"),ln=Ti(rn,"float","Metalness"),dn=Ti(rn,"float","Clearcoat"),cn=Ti(rn,"float","ClearcoatRoughness"),hn=Ti(rn,"vec3","Sheen"),pn=Ti(rn,"float","SheenRoughness"),gn=Ti(rn,"float","Iridescence"),mn=Ti(rn,"float","IridescenceIOR"),fn=Ti(rn,"float","IridescenceThickness"),yn=Ti(rn,"float","AlphaT"),xn=Ti(rn,"float","Anisotropy"),bn=Ti(rn,"vec3","AnisotropyT"),Tn=Ti(rn,"vec3","AnisotropyB"),_n=Ti(rn,"color","SpecularColor"),vn=Ti(rn,"float","SpecularF90"),Nn=Ti(rn,"float","Shininess"),Sn=Ti(rn,"vec4","Output"),An=Ti(rn,"float","dashSize"),Rn=Ti(rn,"float","gapSize"),Cn=Ti(rn,"float","pointWidth"),En=Ti(rn,"float","IOR"),wn=Ti(rn,"float","Transmission"),Mn=Ti(rn,"float","Thickness"),Bn=Ti(rn,"float","AttenuationDistance"),Un=Ti(rn,"color","AttenuationColor"),Fn=Ti(rn,"float","Dispersion");class Pn extends Fs{static get type(){return"AssignNode"}constructor(e,t){super(),this.targetNode=e,this.sourceNode=t}hasDependencies(){return!1}getNodeType(e,t){return"void"!==t?this.targetNode.getNodeType(e):"void"}needsSplitAssign(e){const{targetNode:t}=this;if(!1===e.isAvailable("swizzleAssign")&&t.isSplitNode&&t.components.length>1){const r=e.getTypeLength(t.node.getNodeType(e));return Es.join("").slice(0,r)!==t.components}return!1}generate(e,t){const{targetNode:r,sourceNode:s}=this,i=this.needsSplitAssign(e),n=r.getNodeType(e),o=r.context({assign:!0}).build(e),a=s.build(e,n),u=s.getNodeType(e),l=e.getDataFromNode(this);let d;if(!0===l.initialized)"void"!==t&&(d=o);else if(i){const s=e.getVarFromNode(this,null,n),i=e.getPropertyName(s);e.addLineFlowCode(`${i} = ${a}`,this);const u=r.node.context({assign:!0}).build(e);for(let t=0;t{const s=r.type;let i;return i="pointer"===s?"&"+t.build(e):t.build(e,s),i};if(Array.isArray(i))for(let e=0;e(t=t.length>1||t[0]&&!0===t[0].isNode?xi(t):yi(t[0]),fi(new Ln(fi(e),t)));$s("call",Vn);class Dn extends Fs{static get type(){return"OperatorNode"}constructor(e,t,r,...s){if(super(),s.length>0){let i=new Dn(e,t,r);for(let t=0;t>"===r||"<<"===r)return e.getIntegerType(n);if("!"===r||"=="===r||"&&"===r||"||"===r||"^^"===r)return"bool";if("<"===r||">"===r||"<="===r||">="===r){const r=t?e.getTypeLength(t):Math.max(e.getTypeLength(n),e.getTypeLength(o));return r>1?`bvec${r}`:"bool"}return"float"===n&&e.isMatrix(o)?o:e.isMatrix(n)&&e.isVector(o)?e.getVectorFromMatrix(n):e.isVector(n)&&e.isMatrix(o)?e.getVectorFromMatrix(o):e.getTypeLength(o)>e.getTypeLength(n)?o:n}generate(e,t){const r=this.op,s=this.aNode,i=this.bNode,n=this.getNodeType(e,t);let o=null,a=null;"void"!==n?(o=s.getNodeType(e),a=void 0!==i?i.getNodeType(e):null,"<"===r||">"===r||"<="===r||">="===r||"=="===r?e.isVector(o)?a=o:o!==a&&(o=a="float"):">>"===r||"<<"===r?(o=n,a=e.changeComponentType(a,"uint")):e.isMatrix(o)&&e.isVector(a)?a=e.getVectorFromMatrix(o):o=e.isVector(o)&&e.isMatrix(a)?e.getVectorFromMatrix(a):a=n):o=a=n;const u=s.build(e,o),l=void 0!==i?i.build(e,a):null,d=e.getTypeLength(t),c=e.getFunctionOperator(r);return"void"!==t?"<"===r&&d>1?e.useComparisonMethod?e.format(`${e.getMethod("lessThan",t)}( ${u}, ${l} )`,n,t):e.format(`( ${u} < ${l} )`,n,t):"<="===r&&d>1?e.useComparisonMethod?e.format(`${e.getMethod("lessThanEqual",t)}( ${u}, ${l} )`,n,t):e.format(`( ${u} <= ${l} )`,n,t):">"===r&&d>1?e.useComparisonMethod?e.format(`${e.getMethod("greaterThan",t)}( ${u}, ${l} )`,n,t):e.format(`( ${u} > ${l} )`,n,t):">="===r&&d>1?e.useComparisonMethod?e.format(`${e.getMethod("greaterThanEqual",t)}( ${u}, ${l} )`,n,t):e.format(`( ${u} >= ${l} )`,n,t):"!"===r||"~"===r?e.format(`(${r}${u})`,o,t):c?e.format(`${c}( ${u}, ${l} )`,n,t):e.format(`( ${u} ${r} ${l} )`,n,t):"void"!==o?c?e.format(`${c}( ${u}, ${l} )`,n,t):e.format(`${u} ${r} ${l}`,n,t):void 0}serialize(e){super.serialize(e),e.op=this.op}deserialize(e){super.deserialize(e),this.op=e.op}}const On=bi(Dn,"+"),Gn=bi(Dn,"-"),kn=bi(Dn,"*"),zn=bi(Dn,"/"),$n=bi(Dn,"%"),Hn=bi(Dn,"=="),Wn=bi(Dn,"!="),jn=bi(Dn,"<"),qn=bi(Dn,">"),Kn=bi(Dn,"<="),Xn=bi(Dn,">="),Yn=bi(Dn,"&&"),Qn=bi(Dn,"||"),Zn=bi(Dn,"!"),Jn=bi(Dn,"^^"),eo=bi(Dn,"&"),to=bi(Dn,"~"),ro=bi(Dn,"|"),so=bi(Dn,"^"),io=bi(Dn,"<<"),no=bi(Dn,">>");$s("add",On),$s("sub",Gn),$s("mul",kn),$s("div",zn),$s("modInt",$n),$s("equal",Hn),$s("notEqual",Wn),$s("lessThan",jn),$s("greaterThan",qn),$s("lessThanEqual",Kn),$s("greaterThanEqual",Xn),$s("and",Yn),$s("or",Qn),$s("not",Zn),$s("xor",Jn),$s("bitAnd",eo),$s("bitNot",to),$s("bitOr",ro),$s("bitXor",so),$s("shiftLeft",io),$s("shiftRight",no);const oo=(...e)=>(console.warn("TSL.OperatorNode: .remainder() has been renamed to .modInt()."),$n(...e));$s("remainder",oo);class ao extends Fs{static get type(){return"MathNode"}constructor(e,t,r=null,s=null){super(),this.method=e,this.aNode=t,this.bNode=r,this.cNode=s}getInputType(e){const t=this.aNode.getNodeType(e),r=this.bNode?this.bNode.getNodeType(e):null,s=this.cNode?this.cNode.getNodeType(e):null,i=e.isMatrix(t)?0:e.getTypeLength(t),n=e.isMatrix(r)?0:e.getTypeLength(r),o=e.isMatrix(s)?0:e.getTypeLength(s);return i>n&&i>o?t:n>o?r:o>i?s:t}getNodeType(e){const t=this.method;return t===ao.LENGTH||t===ao.DISTANCE||t===ao.DOT?"float":t===ao.CROSS?"vec3":t===ao.ALL?"bool":t===ao.EQUALS?e.changeComponentType(this.aNode.getNodeType(e),"bool"):t===ao.MOD?this.aNode.getNodeType(e):this.getInputType(e)}generate(e,t){let r=this.method;const s=this.getNodeType(e),i=this.getInputType(e),n=this.aNode,o=this.bNode,a=this.cNode,d=e.renderer.coordinateSystem;if(r===ao.TRANSFORM_DIRECTION){let r=n,s=o;e.isMatrix(r.getNodeType(e))?s=Oi(Ii(s),0):r=Oi(Ii(r),0);const i=kn(r,s).xyz;return Ao(i).build(e,t)}if(r===ao.NEGATE)return e.format("( - "+n.build(e,i)+" )",s,t);if(r===ao.ONE_MINUS)return Gn(1,n).build(e,t);if(r===ao.RECIPROCAL)return zn(1,n).build(e,t);if(r===ao.DIFFERENCE)return Fo(Gn(n,o)).build(e,t);{const c=[];return r===ao.CROSS||r===ao.MOD?c.push(n.build(e,s),o.build(e,s)):d===u&&r===ao.STEP?c.push(n.build(e,1===e.getTypeLength(n.getNodeType(e))?"float":i),o.build(e,i)):d===u&&(r===ao.MIN||r===ao.MAX)||r===ao.MOD?c.push(n.build(e,i),o.build(e,1===e.getTypeLength(o.getNodeType(e))?"float":i)):r===ao.REFRACT?c.push(n.build(e,i),o.build(e,i),a.build(e,"float")):r===ao.MIX?c.push(n.build(e,i),o.build(e,i),a.build(e,1===e.getTypeLength(a.getNodeType(e))?"float":i)):(d===l&&r===ao.ATAN&&null!==o&&(r="atan2"),c.push(n.build(e,i)),null!==o&&c.push(o.build(e,i)),null!==a&&c.push(a.build(e,i))),e.format(`${e.getMethod(r,s)}( ${c.join(", ")} )`,s,t)}}serialize(e){super.serialize(e),e.method=this.method}deserialize(e){super.deserialize(e),this.method=e.method}}ao.ALL="all",ao.ANY="any",ao.RADIANS="radians",ao.DEGREES="degrees",ao.EXP="exp",ao.EXP2="exp2",ao.LOG="log",ao.LOG2="log2",ao.SQRT="sqrt",ao.INVERSE_SQRT="inversesqrt",ao.FLOOR="floor",ao.CEIL="ceil",ao.NORMALIZE="normalize",ao.FRACT="fract",ao.SIN="sin",ao.COS="cos",ao.TAN="tan",ao.ASIN="asin",ao.ACOS="acos",ao.ATAN="atan",ao.ABS="abs",ao.SIGN="sign",ao.LENGTH="length",ao.NEGATE="negate",ao.ONE_MINUS="oneMinus",ao.DFDX="dFdx",ao.DFDY="dFdy",ao.ROUND="round",ao.RECIPROCAL="reciprocal",ao.TRUNC="trunc",ao.FWIDTH="fwidth",ao.TRANSPOSE="transpose",ao.BITCAST="bitcast",ao.EQUALS="equals",ao.MIN="min",ao.MAX="max",ao.MOD="mod",ao.STEP="step",ao.REFLECT="reflect",ao.DISTANCE="distance",ao.DIFFERENCE="difference",ao.DOT="dot",ao.CROSS="cross",ao.POW="pow",ao.TRANSFORM_DIRECTION="transformDirection",ao.MIX="mix",ao.CLAMP="clamp",ao.REFRACT="refract",ao.SMOOTHSTEP="smoothstep",ao.FACEFORWARD="faceforward";const uo=Ci(1e-6),lo=Ci(1e6),co=Ci(Math.PI),ho=Ci(2*Math.PI),po=bi(ao,ao.ALL),go=bi(ao,ao.ANY),mo=bi(ao,ao.RADIANS),fo=bi(ao,ao.DEGREES),yo=bi(ao,ao.EXP),xo=bi(ao,ao.EXP2),bo=bi(ao,ao.LOG),To=bi(ao,ao.LOG2),_o=bi(ao,ao.SQRT),vo=bi(ao,ao.INVERSE_SQRT),No=bi(ao,ao.FLOOR),So=bi(ao,ao.CEIL),Ao=bi(ao,ao.NORMALIZE),Ro=bi(ao,ao.FRACT),Co=bi(ao,ao.SIN),Eo=bi(ao,ao.COS),wo=bi(ao,ao.TAN),Mo=bi(ao,ao.ASIN),Bo=bi(ao,ao.ACOS),Uo=bi(ao,ao.ATAN),Fo=bi(ao,ao.ABS),Po=bi(ao,ao.SIGN),Io=bi(ao,ao.LENGTH),Lo=bi(ao,ao.NEGATE),Vo=bi(ao,ao.ONE_MINUS),Do=bi(ao,ao.DFDX),Oo=bi(ao,ao.DFDY),Go=bi(ao,ao.ROUND),ko=bi(ao,ao.RECIPROCAL),zo=bi(ao,ao.TRUNC),$o=bi(ao,ao.FWIDTH),Ho=bi(ao,ao.TRANSPOSE),Wo=bi(ao,ao.BITCAST),jo=bi(ao,ao.EQUALS),qo=bi(ao,ao.MIN),Ko=bi(ao,ao.MAX),Xo=bi(ao,ao.MOD),Yo=bi(ao,ao.STEP),Qo=bi(ao,ao.REFLECT),Zo=bi(ao,ao.DISTANCE),Jo=bi(ao,ao.DIFFERENCE),ea=bi(ao,ao.DOT),ta=bi(ao,ao.CROSS),ra=bi(ao,ao.POW),sa=bi(ao,ao.POW,2),ia=bi(ao,ao.POW,3),na=bi(ao,ao.POW,4),oa=bi(ao,ao.TRANSFORM_DIRECTION),aa=e=>kn(Po(e),ra(Fo(e),1/3)),ua=e=>ea(e,e),la=bi(ao,ao.MIX),da=(e,t=0,r=1)=>fi(new ao(ao.CLAMP,fi(e),fi(t),fi(r))),ca=e=>da(e),ha=bi(ao,ao.REFRACT),pa=bi(ao,ao.SMOOTHSTEP),ga=bi(ao,ao.FACEFORWARD),ma=_i((([e])=>{const t=ea(e.xy,Bi(12.9898,78.233)),r=Xo(t,co);return Ro(Co(r).mul(43758.5453))})),fa=(e,t,r)=>la(t,r,e),ya=(e,t,r)=>pa(t,r,e),xa=(e,t)=>(console.warn('THREE.TSL: "atan2" is overloaded. Use "atan" instead.'),Uo(e,t));$s("all",po),$s("any",go),$s("equals",jo),$s("radians",mo),$s("degrees",fo),$s("exp",yo),$s("exp2",xo),$s("log",bo),$s("log2",To),$s("sqrt",_o),$s("inverseSqrt",vo),$s("floor",No),$s("ceil",So),$s("normalize",Ao),$s("fract",Ro),$s("sin",Co),$s("cos",Eo),$s("tan",wo),$s("asin",Mo),$s("acos",Bo),$s("atan",Uo),$s("abs",Fo),$s("sign",Po),$s("length",Io),$s("lengthSq",ua),$s("negate",Lo),$s("oneMinus",Vo),$s("dFdx",Do),$s("dFdy",Oo),$s("round",Go),$s("reciprocal",ko),$s("trunc",zo),$s("fwidth",$o),$s("atan2",xa),$s("min",qo),$s("max",Ko),$s("mod",Xo),$s("step",Yo),$s("reflect",Qo),$s("distance",Zo),$s("dot",ea),$s("cross",ta),$s("pow",ra),$s("pow2",sa),$s("pow3",ia),$s("pow4",na),$s("transformDirection",oa),$s("mix",fa),$s("clamp",da),$s("refract",ha),$s("smoothstep",ya),$s("faceForward",ga),$s("difference",Jo),$s("saturate",ca),$s("cbrt",aa),$s("transpose",Ho),$s("rand",ma);class ba extends Ms{static get type(){return"ConditionalNode"}constructor(e,t,r=null){super(),this.condNode=e,this.ifNode=t,this.elseNode=r}getNodeType(e){const t=this.ifNode.getNodeType(e);if(null!==this.elseNode){const r=this.elseNode.getNodeType(e);if(e.getTypeLength(r)>e.getTypeLength(t))return r}return t}setup(e){const t=this.condNode.cache(),r=this.ifNode.cache(),s=this.elseNode?this.elseNode.cache():null,i=e.context.nodeBlock;e.getDataFromNode(r).parentNodeBlock=i,null!==s&&(e.getDataFromNode(s).parentNodeBlock=i);const n=e.getNodeProperties(this);n.condNode=t,n.ifNode=r.context({nodeBlock:r}),n.elseNode=s?s.context({nodeBlock:s}):null}generate(e,t){const r=this.getNodeType(e),s=e.getDataFromNode(this);if(void 0!==s.nodeProperty)return s.nodeProperty;const{condNode:i,ifNode:n,elseNode:o}=e.getNodeProperties(this),a="void"!==t,u=a?sn(r).build(e):"";s.nodeProperty=u;const l=i.build(e,"bool");e.addFlowCode(`\n${e.tab}if ( ${l} ) {\n\n`).addFlowTab();let d=n.build(e,r);if(d&&(d=a?u+" = "+d+";":"return "+d+";"),e.removeFlowTab().addFlowCode(e.tab+"\t"+d+"\n\n"+e.tab+"}"),null!==o){e.addFlowCode(" else {\n\n").addFlowTab();let t=o.build(e,r);t&&(t=a?u+" = "+t+";":"return "+t+";"),e.removeFlowTab().addFlowCode(e.tab+"\t"+t+"\n\n"+e.tab+"}\n\n")}else e.addFlowCode("\n\n");return e.format(u,r,t)}}const Ta=bi(ba);$s("select",Ta);const _a=(...e)=>(console.warn("TSL.ConditionalNode: cond() has been renamed to select()."),Ta(...e));$s("cond",_a);class va extends Ms{static get type(){return"ContextNode"}constructor(e,t={}){super(),this.isContextNode=!0,this.node=e,this.value=t}getScope(){return this.node.getScope()}getNodeType(e){return this.node.getNodeType(e)}analyze(e){this.node.build(e)}setup(e){const t=e.getContext();e.setContext({...e.context,...this.value});const r=this.node.build(e);return e.setContext(t),r}generate(e,t){const r=e.getContext();e.setContext({...e.context,...this.value});const s=this.node.build(e,t);return e.setContext(r),s}}const Na=bi(va),Sa=(e,t)=>Na(e,{label:t});$s("context",Na),$s("label",Sa);class Aa extends Ms{static get type(){return"VarNode"}constructor(e,t=null){super(),this.node=e,this.name=t,this.global=!0,this.isVarNode=!0}getHash(e){return this.name||super.getHash(e)}getNodeType(e){return this.node.getNodeType(e)}generate(e){const{node:t,name:r}=this,s=e.getVarFromNode(this,r,e.getVectorType(this.getNodeType(e))),i=e.getPropertyName(s),n=t.build(e,s.type);return e.addLineFlowCode(`${i} = ${n}`,this),i}}const Ra=bi(Aa);$s("toVar",((...e)=>Ra(...e).append()));const Ca=e=>(console.warn('TSL: "temp" is deprecated. Use ".toVar()" instead.'),Ra(e));$s("temp",Ca);class Ea extends Ms{static get type(){return"VaryingNode"}constructor(e,t=null){super(),this.node=e,this.name=t,this.isVaryingNode=!0}isGlobal(){return!0}getHash(e){return this.name||super.getHash(e)}getNodeType(e){return this.node.getNodeType(e)}setupVarying(e){const t=e.getNodeProperties(this);let r=t.varying;if(void 0===r){const s=this.name,i=this.getNodeType(e);t.varying=r=e.getVaryingFromNode(this,s,i),t.node=this.node}return r.needsInterpolation||(r.needsInterpolation="fragment"===e.shaderStage),r}setup(e){this.setupVarying(e)}analyze(e){return this.setupVarying(e),this.node.analyze(e)}generate(e){const t=e.getNodeProperties(this),r=this.setupVarying(e),s="fragment"===e.shaderStage&&!0===t.reassignPosition&&e.context.needsPositionReassign;if(void 0===t.propertyName||s){const i=this.getNodeType(e),n=e.getPropertyName(r,_s.VERTEX);e.flowNodeFromShaderStage(_s.VERTEX,this.node,i,n),t.propertyName=n,s?t.reassignPosition=!1:void 0===t.reassignPosition&&e.context.isPositionNodeInput&&(t.reassignPosition=!0)}return e.getPropertyName(r)}}const wa=bi(Ea);$s("varying",wa);const Ma=_i((([e])=>{const t=e.mul(.9478672986).add(.0521327014).pow(2.4),r=e.mul(.0773993808),s=e.lessThanEqual(.04045);return la(t,r,s)})).setLayout({name:"sRGBTransferEOTF",type:"vec3",inputs:[{name:"color",type:"vec3"}]}),Ba=_i((([e])=>{const t=e.pow(.41666).mul(1.055).sub(.055),r=e.mul(12.92),s=e.lessThanEqual(.0031308);return la(t,r,s)})).setLayout({name:"sRGBTransferOETF",type:"vec3",inputs:[{name:"color",type:"vec3"}]}),Ua="WorkingColorSpace",Fa="OutputColorSpace";class Pa extends Fs{static get type(){return"ColorSpaceNode"}constructor(e,t,r){super("vec4"),this.colorNode=e,this.source=t,this.target=r}resolveColorSpace(e,t){return t===Ua?d.workingColorSpace:t===Fa?e.context.outputColorSpace||e.renderer.outputColorSpace:t}setup(e){const{colorNode:t}=this,r=this.resolveColorSpace(e,this.source),s=this.resolveColorSpace(e,this.target);let n=t;return!1!==d.enabled&&r!==s&&r&&s?(d.getTransfer(r)===c&&(n=Oi(Ma(n.rgb),n.a)),d.getPrimaries(r)!==d.getPrimaries(s)&&(n=Oi(Hi(d._getMatrix(new i,r,s)).mul(n.rgb),n.a)),d.getTransfer(s)===c&&(n=Oi(Ba(n.rgb),n.a)),n):n}}const Ia=e=>fi(new Pa(fi(e),Ua,Fa)),La=e=>fi(new Pa(fi(e),Fa,Ua)),Va=(e,t)=>fi(new Pa(fi(e),Ua,t)),Da=(e,t)=>fi(new Pa(fi(e),t,Ua));$s("toOutputColorSpace",Ia),$s("toWorkingColorSpace",La),$s("workingToColorSpace",Va),$s("colorSpaceToWorking",Da);let Oa=class extends Bs{static get type(){return"ReferenceElementNode"}constructor(e,t){super(e,t),this.referenceNode=e,this.isReferenceElementNode=!0}getNodeType(){return this.referenceNode.uniformType}generate(e){const t=super.generate(e),r=this.referenceNode.getNodeType(),s=this.getNodeType();return e.format(t,r,s)}};class Ga extends Ms{static get type(){return"ReferenceBaseNode"}constructor(e,t,r=null,s=null){super(),this.property=e,this.uniformType=t,this.object=r,this.count=s,this.properties=e.split("."),this.reference=r,this.node=null,this.group=null,this.updateType=vs.OBJECT}setGroup(e){return this.group=e,this}element(e){return fi(new Oa(this,fi(e)))}setNodeType(e){const t=tn(null,e).getSelf();null!==this.group&&t.setGroup(this.group),this.node=t}getNodeType(e){return null===this.node&&(this.updateReference(e),this.updateValue()),this.node.getNodeType(e)}getValueFromReference(e=this.reference){const{properties:t}=this;let r=e[t[0]];for(let e=1;efi(new ka(e,t,r));class $a extends Fs{static get type(){return"ToneMappingNode"}constructor(e,t=Wa,r=null){super("vec3"),this.toneMapping=e,this.exposureNode=t,this.colorNode=r}customCacheKey(){return ds(this.toneMapping)}setup(e){const t=this.colorNode||e.context.color,r=this.toneMapping;if(r===h)return t;let s=null;const i=e.renderer.library.getToneMappingFunction(r);return null!==i?s=Oi(i(t.rgb,this.exposureNode),t.a):(console.error("ToneMappingNode: Unsupported Tone Mapping configuration.",r),s=t),s}}const Ha=(e,t,r)=>fi(new $a(e,fi(t),fi(r))),Wa=za("toneMappingExposure","float");$s("toneMapping",((e,t,r)=>Ha(t,r,e)));class ja extends Os{static get type(){return"BufferAttributeNode"}constructor(e,t=null,r=0,s=0){super(e,t),this.isBufferNode=!0,this.bufferType=t,this.bufferStride=r,this.bufferOffset=s,this.usage=p,this.instanced=!1,this.attribute=null,this.global=!0,e&&!0===e.isBufferAttribute&&(this.attribute=e,this.usage=e.usage,this.instanced=e.isInstancedBufferAttribute)}getHash(e){if(0===this.bufferStride&&0===this.bufferOffset){let t=e.globalCache.getData(this.value);return void 0===t&&(t={node:this},e.globalCache.setData(this.value,t)),t.node.uuid}return this.uuid}getNodeType(e){return null===this.bufferType&&(this.bufferType=e.getTypeFromAttribute(this.attribute)),this.bufferType}setup(e){if(null!==this.attribute)return;const t=this.getNodeType(e),r=this.value,s=e.getTypeLength(t),i=this.bufferStride||s,n=this.bufferOffset,o=!0===r.isInterleavedBuffer?r:new g(r,i),a=new f(o,s,n);o.setUsage(this.usage),this.attribute=a,this.attribute.isInstancedBufferAttribute=this.instanced}generate(e){const t=this.getNodeType(e),r=e.getBufferAttributeFromNode(this,t),s=e.getPropertyName(r);let i=null;if("vertex"===e.shaderStage||"compute"===e.shaderStage)this.name=s,i=s;else{i=wa(this).build(e,t)}return i}getInputType(){return"bufferAttribute"}setUsage(e){return this.usage=e,this.attribute&&!0===this.attribute.isBufferAttribute&&(this.attribute.usage=e),this}setInstanced(e){return this.instanced=e,this}}const qa=(e,t=null,r=0,s=0)=>fi(new ja(e,t,r,s)),Ka=(e,t=null,r=0,s=0)=>qa(e,t,r,s).setUsage(m),Xa=(e,t=null,r=0,s=0)=>qa(e,t,r,s).setInstanced(!0),Ya=(e,t=null,r=0,s=0)=>Ka(e,t,r,s).setInstanced(!0);$s("toAttribute",(e=>qa(e.value)));class Qa extends Ms{static get type(){return"ComputeNode"}constructor(e,t,r=[64]){super("void"),this.isComputeNode=!0,this.computeNode=e,this.count=t,this.workgroupSize=r,this.dispatchCount=0,this.version=1,this.updateBeforeType=vs.OBJECT,this.onInitFunction=null,this.updateDispatchCount()}dispose(){this.dispatchEvent({type:"dispose"})}updateDispatchCount(){const{count:e,workgroupSize:t}=this;let r=t[0];for(let e=1;efi(new Qa(fi(e),t,r));$s("compute",Za);class Ja extends Ms{static get type(){return"CacheNode"}constructor(e,t=!0){super(),this.node=e,this.parent=t,this.isCacheNode=!0}getNodeType(e){return this.node.getNodeType(e)}build(e,...t){const r=e.getCache(),s=e.getCacheFromNode(this,this.parent);e.setCache(s);const i=this.node.build(e,...t);return e.setCache(r),i}}const eu=(e,t)=>fi(new Ja(fi(e),t));$s("cache",eu);class tu extends Ms{static get type(){return"BypassNode"}constructor(e,t){super(),this.isBypassNode=!0,this.outputNode=e,this.callNode=t}getNodeType(e){return this.outputNode.getNodeType(e)}generate(e){const t=this.callNode.build(e,"void");return""!==t&&e.addLineFlowCode(t,this),this.outputNode.build(e)}}const ru=bi(tu);$s("bypass",ru);class su extends Ms{static get type(){return"RemapNode"}constructor(e,t,r,s=Ci(0),i=Ci(1)){super(),this.node=e,this.inLowNode=t,this.inHighNode=r,this.outLowNode=s,this.outHighNode=i,this.doClamp=!0}setup(){const{node:e,inLowNode:t,inHighNode:r,outLowNode:s,outHighNode:i,doClamp:n}=this;let o=e.sub(t).div(r.sub(t));return!0===n&&(o=o.clamp()),o.mul(i.sub(s)).add(s)}}const iu=bi(su,null,null,{doClamp:!1}),nu=bi(su);$s("remap",iu),$s("remapClamp",nu);class ou extends Ms{static get type(){return"ExpressionNode"}constructor(e="",t="void"){super(t),this.snippet=e}generate(e,t){const r=this.getNodeType(e),s=this.snippet;if("void"!==r)return e.format(`( ${s} )`,r,t);e.addLineFlowCode(s,this)}}const au=bi(ou),uu=e=>(e?Ta(e,au("discard")):au("discard")).append();$s("discard",uu);class lu extends Fs{static get type(){return"RenderOutputNode"}constructor(e,t,r){super("vec4"),this.colorNode=e,this.toneMapping=t,this.outputColorSpace=r,this.isRenderOutputNode=!0}setup({context:e}){let t=this.colorNode||e.color;const r=(null!==this.toneMapping?this.toneMapping:e.toneMapping)||h,s=(null!==this.outputColorSpace?this.outputColorSpace:e.outputColorSpace)||y;return r!==h&&(t=t.toneMapping(r)),s!==y&&s!==d.workingColorSpace&&(t=t.workingToColorSpace(s)),t}}const du=(e,t=null,r=null)=>fi(new lu(fi(e),t,r));$s("renderOutput",du);class cu extends Ms{static get type(){return"AttributeNode"}constructor(e,t=null){super(t),this.global=!0,this._attributeName=e}getHash(e){return this.getAttributeName(e)}getNodeType(e){let t=this.nodeType;if(null===t){const r=this.getAttributeName(e);if(e.hasGeometryAttribute(r)){const s=e.geometry.getAttribute(r);t=e.getTypeFromAttribute(s)}else t="float"}return t}setAttributeName(e){return this._attributeName=e,this}getAttributeName(){return this._attributeName}generate(e){const t=this.getAttributeName(e),r=this.getNodeType(e);if(!0===e.hasGeometryAttribute(t)){const s=e.geometry.getAttribute(t),i=e.getTypeFromAttribute(s),n=e.getAttribute(t,i);if("vertex"===e.shaderStage)return e.format(n.name,i,r);return wa(this).build(e,r)}return console.warn(`AttributeNode: Vertex attribute "${t}" not found on geometry.`),e.generateConst(r)}serialize(e){super.serialize(e),e.global=this.global,e._attributeName=this._attributeName}deserialize(e){super.deserialize(e),this.global=e.global,this._attributeName=e._attributeName}}const hu=(e,t)=>fi(new cu(e,t)),pu=(e=0)=>hu("uv"+(e>0?e:""),"vec2");class gu extends Ms{static get type(){return"TextureSizeNode"}constructor(e,t=null){super("uvec2"),this.isTextureSizeNode=!0,this.textureNode=e,this.levelNode=t}generate(e,t){const r=this.textureNode.build(e,"property"),s=null===this.levelNode?"0":this.levelNode.build(e,"int");return e.format(`${e.getMethod("textureDimensions")}( ${r}, ${s} )`,this.getNodeType(e),t)}}const mu=bi(gu);class fu extends en{static get type(){return"MaxMipLevelNode"}constructor(e){super(0),this._textureNode=e,this.updateType=vs.FRAME}get textureNode(){return this._textureNode}get texture(){return this._textureNode.value}update(){const e=this.texture,t=e.images,r=t&&t.length>0?t[0]&&t[0].image||t[0]:e.image;if(r&&void 0!==r.width){const{width:e,height:t}=r;this.value=Math.log2(Math.max(e,t))}}}const yu=bi(fu);class xu extends en{static get type(){return"TextureNode"}constructor(e,t=null,r=null,s=null){super(e),this.isTextureNode=!0,this.uvNode=t,this.levelNode=r,this.biasNode=s,this.compareNode=null,this.depthNode=null,this.gradNode=null,this.sampler=!0,this.updateMatrix=!1,this.updateType=vs.NONE,this.referenceNode=null,this._value=e,this._matrixUniform=null,this.setUpdateMatrix(null===t)}set value(e){this.referenceNode?this.referenceNode.value=e:this._value=e}get value(){return this.referenceNode?this.referenceNode.value:this._value}getUniformHash(){return this.value.uuid}getNodeType(){return!0===this.value.isDepthTexture?"float":this.value.type===x?"uvec4":this.value.type===b?"ivec4":"vec4"}getInputType(){return"texture"}getDefaultUV(){return pu(this.value.channel)}updateReference(){return this.value}getTransformedUV(e){return null===this._matrixUniform&&(this._matrixUniform=tn(this.value.matrix)),this._matrixUniform.mul(Ii(e,1)).xy}setUpdateMatrix(e){return this.updateMatrix=e,this.updateType=e?vs.FRAME:vs.NONE,this}setupUV(e,t){const r=this.value;return e.isFlipY()&&(r.image instanceof ImageBitmap&&!0===r.flipY||!0===r.isRenderTargetTexture||!0===r.isFramebufferTexture||!0===r.isDepthTexture)&&(t=this.sampler?t.flipY():t.setY(Ei(mu(this,this.levelNode).y).sub(t.y).sub(1))),t}setup(e){const t=e.getNodeProperties(this);t.referenceNode=this.referenceNode;let r=this.uvNode;null!==r&&!0!==e.context.forceUVContext||!e.context.getUV||(r=e.context.getUV(this)),r||(r=this.getDefaultUV()),!0===this.updateMatrix&&(r=this.getTransformedUV(r)),r=this.setupUV(e,r);let s=this.levelNode;null===s&&e.context.getTextureLevel&&(s=e.context.getTextureLevel(this)),t.uvNode=r,t.levelNode=s,t.biasNode=this.biasNode,t.compareNode=this.compareNode,t.gradNode=this.gradNode,t.depthNode=this.depthNode}generateUV(e,t){return t.build(e,!0===this.sampler?"vec2":"ivec2")}generateSnippet(e,t,r,s,i,n,o,a){const u=this.value;let l;return l=s?e.generateTextureLevel(u,t,r,s,n):i?e.generateTextureBias(u,t,r,i,n):a?e.generateTextureGrad(u,t,r,a,n):o?e.generateTextureCompare(u,t,r,o,n):!1===this.sampler?e.generateTextureLoad(u,t,r,n):e.generateTexture(u,t,r,n),l}generate(e,t){const r=e.getNodeProperties(this),s=this.value;if(!s||!0!==s.isTexture)throw new Error("TextureNode: Need a three.js texture.");const i=super.generate(e,"property");if("sampler"===t)return i+"_sampler";if(e.isReference(t))return i;{const n=e.getDataFromNode(this);let o=n.propertyName;if(void 0===o){const{uvNode:t,levelNode:s,biasNode:a,compareNode:u,depthNode:l,gradNode:d}=r,c=this.generateUV(e,t),h=s?s.build(e,"float"):null,p=a?a.build(e,"float"):null,g=l?l.build(e,"int"):null,m=u?u.build(e,"float"):null,f=d?[d[0].build(e,"vec2"),d[1].build(e,"vec2")]:null,y=e.getVarFromNode(this);o=e.getPropertyName(y);const x=this.generateSnippet(e,i,c,h,p,g,m,f);e.addLineFlowCode(`${o} = ${x}`,this),n.snippet=x,n.propertyName=o}let a=o;const u=this.getNodeType(e);return e.needsToWorkingColorSpace(s)&&(a=Da(au(a,u),s.colorSpace).setup(e).build(e,u)),e.format(a,u,t)}}setSampler(e){return this.sampler=e,this}getSampler(){return this.sampler}uv(e){return console.warn("THREE.TextureNode: .uv() has been renamed. Use .sample() instead."),this.sample(e)}sample(e){const t=this.clone();return t.uvNode=fi(e),t.referenceNode=this.getSelf(),fi(t)}blur(e){const t=this.clone();return t.biasNode=fi(e).mul(yu(t)),t.referenceNode=this.getSelf(),fi(t)}level(e){const t=this.clone();return t.levelNode=fi(e),t.referenceNode=this.getSelf(),fi(t)}size(e){return mu(this,e)}bias(e){const t=this.clone();return t.biasNode=fi(e),t.referenceNode=this.getSelf(),fi(t)}compare(e){const t=this.clone();return t.compareNode=fi(e),t.referenceNode=this.getSelf(),fi(t)}grad(e,t){const r=this.clone();return r.gradNode=[fi(e),fi(t)],r.referenceNode=this.getSelf(),fi(r)}depth(e){const t=this.clone();return t.depthNode=fi(e),t.referenceNode=this.getSelf(),fi(t)}serialize(e){super.serialize(e),e.value=this.value.toJSON(e.meta).uuid,e.sampler=this.sampler,e.updateMatrix=this.updateMatrix,e.updateType=this.updateType}deserialize(e){super.deserialize(e),this.value=e.meta.textures[e.value],this.sampler=e.sampler,this.updateMatrix=e.updateMatrix,this.updateType=e.updateType}update(){const e=this.value,t=this._matrixUniform;null!==t&&(t.value=e.matrix),!0===e.matrixAutoUpdate&&e.updateMatrix()}clone(){const e=new this.constructor(this.value,this.uvNode,this.levelNode,this.biasNode);return e.sampler=this.sampler,e}}const bu=bi(xu),Tu=(...e)=>bu(...e).setSampler(!1),_u=tn("float").label("cameraNear").setGroup(Zi).onRenderUpdate((({camera:e})=>e.near)),vu=tn("float").label("cameraFar").setGroup(Zi).onRenderUpdate((({camera:e})=>e.far)),Nu=tn("mat4").label("cameraProjectionMatrix").setGroup(Zi).onRenderUpdate((({camera:e})=>e.projectionMatrix)),Su=tn("mat4").label("cameraProjectionMatrixInverse").setGroup(Zi).onRenderUpdate((({camera:e})=>e.projectionMatrixInverse)),Au=tn("mat4").label("cameraViewMatrix").setGroup(Zi).onRenderUpdate((({camera:e})=>e.matrixWorldInverse)),Ru=tn("mat4").label("cameraWorldMatrix").setGroup(Zi).onRenderUpdate((({camera:e})=>e.matrixWorld)),Cu=tn("mat3").label("cameraNormalMatrix").setGroup(Zi).onRenderUpdate((({camera:e})=>e.normalMatrix)),Eu=tn(new r).label("cameraPosition").setGroup(Zi).onRenderUpdate((({camera:e},t)=>t.value.setFromMatrixPosition(e.matrixWorld)));class wu extends Ms{static get type(){return"Object3DNode"}constructor(e,t=null){super(),this.scope=e,this.object3d=t,this.updateType=vs.OBJECT,this._uniformNode=new en(null)}getNodeType(){const e=this.scope;return e===wu.WORLD_MATRIX?"mat4":e===wu.POSITION||e===wu.VIEW_POSITION||e===wu.DIRECTION||e===wu.SCALE?"vec3":void 0}update(e){const t=this.object3d,s=this._uniformNode,i=this.scope;if(i===wu.WORLD_MATRIX)s.value=t.matrixWorld;else if(i===wu.POSITION)s.value=s.value||new r,s.value.setFromMatrixPosition(t.matrixWorld);else if(i===wu.SCALE)s.value=s.value||new r,s.value.setFromMatrixScale(t.matrixWorld);else if(i===wu.DIRECTION)s.value=s.value||new r,t.getWorldDirection(s.value);else if(i===wu.VIEW_POSITION){const i=e.camera;s.value=s.value||new r,s.value.setFromMatrixPosition(t.matrixWorld),s.value.applyMatrix4(i.matrixWorldInverse)}}generate(e){const t=this.scope;return t===wu.WORLD_MATRIX?this._uniformNode.nodeType="mat4":t!==wu.POSITION&&t!==wu.VIEW_POSITION&&t!==wu.DIRECTION&&t!==wu.SCALE||(this._uniformNode.nodeType="vec3"),this._uniformNode.build(e)}serialize(e){super.serialize(e),e.scope=this.scope}deserialize(e){super.deserialize(e),this.scope=e.scope}}wu.WORLD_MATRIX="worldMatrix",wu.POSITION="position",wu.SCALE="scale",wu.VIEW_POSITION="viewPosition",wu.DIRECTION="direction";const Mu=bi(wu,wu.DIRECTION),Bu=bi(wu,wu.WORLD_MATRIX),Uu=bi(wu,wu.POSITION),Fu=bi(wu,wu.SCALE),Pu=bi(wu,wu.VIEW_POSITION);class Iu extends wu{static get type(){return"ModelNode"}constructor(e){super(e)}update(e){this.object3d=e.object,super.update(e)}}const Lu=Ti(Iu,Iu.DIRECTION),Vu=Ti(Iu,Iu.WORLD_MATRIX),Du=Ti(Iu,Iu.POSITION),Ou=Ti(Iu,Iu.SCALE),Gu=Ti(Iu,Iu.VIEW_POSITION),ku=tn(new i).onObjectUpdate((({object:e},t)=>t.value.getNormalMatrix(e.matrixWorld))),zu=tn(new n).onObjectUpdate((({object:e},t)=>t.value.copy(e.matrixWorld).invert())),$u=_i((e=>e.renderer.nodes.modelViewMatrix||Hu)).once()().toVar("modelViewMatrix"),Hu=Au.mul(Vu),Wu=_i((e=>(e.context.isHighPrecisionModelViewMatrix=!0,tn("mat4").onObjectUpdate((({object:e,camera:t})=>e.modelViewMatrix.multiplyMatrices(t.matrixWorldInverse,e.matrixWorld)))))).once()().toVar("highpModelViewMatrix"),ju=_i((e=>{const t=e.context.isHighPrecisionModelViewMatrix;return tn("mat3").onObjectUpdate((({object:e,camera:r})=>(!0!==t&&e.modelViewMatrix.multiplyMatrices(r.matrixWorldInverse,e.matrixWorld),e.normalMatrix.getNormalMatrix(e.modelViewMatrix))))})).once()().toVar("highpModelNormalViewMatrix"),qu=hu("position","vec3"),Ku=qu.varying("positionLocal"),Xu=qu.varying("positionPrevious"),Yu=Vu.mul(Ku).xyz.varying("v_positionWorld").context({needsPositionReassign:!0}),Qu=Ku.transformDirection(Vu).varying("v_positionWorldDirection").normalize().toVar("positionWorldDirection").context({needsPositionReassign:!0}),Zu=_i((e=>e.context.setupPositionView()),"vec3").once()().varying("v_positionView").context({needsPositionReassign:!0}),Ju=Zu.negate().varying("v_positionViewDirection").normalize().toVar("positionViewDirection");class el extends Ms{static get type(){return"FrontFacingNode"}constructor(){super("bool"),this.isFrontFacingNode=!0}generate(e){const{renderer:t,material:r}=e;return t.coordinateSystem===u&&r.side===T?"false":e.getFrontFacing()}}const tl=Ti(el),rl=Ci(tl).mul(2).sub(1),sl=hu("normal","vec3"),il=_i((e=>!1===e.geometry.hasAttribute("normal")?(console.warn('TSL.NormalNode: Vertex attribute "normal" not found on geometry.'),Ii(0,1,0)):sl),"vec3").once()().toVar("normalLocal"),nl=Zu.dFdx().cross(Zu.dFdy()).normalize().toVar("normalFlat"),ol=_i((e=>{let t;return t=!0===e.material.flatShading?nl:wa(hl(il),"v_normalView").normalize(),t}),"vec3").once()().toVar("normalView"),al=wa(ol.transformDirection(Au),"v_normalWorld").normalize().toVar("normalWorld"),ul=_i((e=>e.context.setupNormal()),"vec3").once()().mul(rl).toVar("transformedNormalView"),ll=ul.transformDirection(Au).toVar("transformedNormalWorld"),dl=_i((e=>e.context.setupClearcoatNormal()),"vec3").once()().mul(rl).toVar("transformedClearcoatNormalView"),cl=_i((([e,t=Vu])=>{const r=Hi(t),s=e.div(Ii(r[0].dot(r[0]),r[1].dot(r[1]),r[2].dot(r[2])));return r.mul(s).xyz})),hl=_i((([e],t)=>{const r=t.renderer.nodes.modelNormalViewMatrix;if(null!==r)return r.transformDirection(e);const s=ku.mul(e);return Au.transformDirection(s)})),pl=tn(0).onReference((({material:e})=>e)).onRenderUpdate((({material:e})=>e.refractionRatio)),gl=Ju.negate().reflect(ul),ml=Ju.negate().refract(ul,pl),fl=gl.transformDirection(Au).toVar("reflectVector"),yl=ml.transformDirection(Au).toVar("reflectVector");class xl extends xu{static get type(){return"CubeTextureNode"}constructor(e,t=null,r=null,s=null){super(e,t,r,s),this.isCubeTextureNode=!0}getInputType(){return"cubeTexture"}getDefaultUV(){const e=this.value;return e.mapping===_?fl:e.mapping===v?yl:(console.error('THREE.CubeTextureNode: Mapping "%s" not supported.',e.mapping),Ii(0,0,0))}setUpdateMatrix(){}setupUV(e,t){const r=this.value;return e.renderer.coordinateSystem!==l&&r.isRenderTargetTexture?t:Ii(t.x.negate(),t.yz)}generateUV(e,t){return t.build(e,"vec3")}}const bl=bi(xl);class Tl extends en{static get type(){return"BufferNode"}constructor(e,t,r=0){super(e,t),this.isBufferNode=!0,this.bufferType=t,this.bufferCount=r}getElementType(e){return this.getNodeType(e)}getInputType(){return"buffer"}}const _l=(e,t,r)=>fi(new Tl(e,t,r));class vl extends Bs{static get type(){return"UniformArrayElementNode"}constructor(e,t){super(e,t),this.isArrayBufferElementNode=!0}generate(e){const t=super.generate(e),r=this.getNodeType(),s=this.node.getPaddedType();return e.format(t,s,r)}}class Nl extends Tl{static get type(){return"UniformArrayNode"}constructor(e,t=null){super(null),this.array=e,this.elementType=null===t?fs(e[0]):t,this.paddedType=this.getPaddedType(),this.updateType=vs.RENDER,this.isArrayBufferNode=!0}getNodeType(){return this.paddedType}getElementType(){return this.elementType}getPaddedType(){const e=this.elementType;let t="vec4";return"mat2"===e?t="mat2":!0===/mat/.test(e)?t="mat4":"i"===e.charAt(0)?t="ivec4":"u"===e.charAt(0)&&(t="uvec4"),t}update(){const{array:e,value:t}=this,r=this.elementType;if("float"===r||"int"===r||"uint"===r)for(let r=0;rfi(new Nl(e,t));class Al extends Bs{static get type(){return"ReferenceElementNode"}constructor(e,t){super(e,t),this.referenceNode=e,this.isReferenceElementNode=!0}getNodeType(){return this.referenceNode.uniformType}generate(e){const t=super.generate(e),r=this.referenceNode.getNodeType(),s=this.getNodeType();return e.format(t,r,s)}}class Rl extends Ms{static get type(){return"ReferenceNode"}constructor(e,t,r=null,s=null){super(),this.property=e,this.uniformType=t,this.object=r,this.count=s,this.properties=e.split("."),this.reference=r,this.node=null,this.group=null,this.name=null,this.updateType=vs.OBJECT}element(e){return fi(new Al(this,fi(e)))}setGroup(e){return this.group=e,this}label(e){return this.name=e,this}setNodeType(e){let t=null;t=null!==this.count?_l(null,e,this.count):Array.isArray(this.getValueFromReference())?Sl(null,e):"texture"===e?bu(null):"cubeTexture"===e?bl(null):tn(null,e),null!==this.group&&t.setGroup(this.group),null!==this.name&&t.label(this.name),this.node=t.getSelf()}getNodeType(e){return null===this.node&&(this.updateReference(e),this.updateValue()),this.node.getNodeType(e)}getValueFromReference(e=this.reference){const{properties:t}=this;let r=e[t[0]];for(let e=1;efi(new Rl(e,t,r)),El=(e,t,r,s)=>fi(new Rl(e,t,s,r));class wl extends Rl{static get type(){return"MaterialReferenceNode"}constructor(e,t,r=null){super(e,t,r),this.material=r,this.isMaterialReferenceNode=!0}updateReference(e){return this.reference=null!==this.material?this.material:e.material,this.reference}}const Ml=(e,t,r=null)=>fi(new wl(e,t,r)),Bl=_i((e=>(!1===e.geometry.hasAttribute("tangent")&&e.geometry.computeTangents(),hu("tangent","vec4"))))(),Ul=Bl.xyz.toVar("tangentLocal"),Fl=$u.mul(Oi(Ul,0)).xyz.varying("v_tangentView").normalize().toVar("tangentView"),Pl=Fl.transformDirection(Au).varying("v_tangentWorld").normalize().toVar("tangentWorld"),Il=Fl.toVar("transformedTangentView"),Ll=Il.transformDirection(Au).normalize().toVar("transformedTangentWorld"),Vl=e=>e.mul(Bl.w).xyz,Dl=wa(Vl(sl.cross(Bl)),"v_bitangentGeometry").normalize().toVar("bitangentGeometry"),Ol=wa(Vl(il.cross(Ul)),"v_bitangentLocal").normalize().toVar("bitangentLocal"),Gl=wa(Vl(ol.cross(Fl)),"v_bitangentView").normalize().toVar("bitangentView"),kl=wa(Vl(al.cross(Pl)),"v_bitangentWorld").normalize().toVar("bitangentWorld"),zl=Vl(ul.cross(Il)).normalize().toVar("transformedBitangentView"),$l=zl.transformDirection(Au).normalize().toVar("transformedBitangentWorld"),Hl=Hi(Fl,Gl,ol),Wl=Ju.mul(Hl),jl=(()=>{let e=Tn.cross(Ju);return e=e.cross(Tn).normalize(),e=la(e,ul,xn.mul(un.oneMinus()).oneMinus().pow2().pow2()).normalize(),e})(),ql=_i((e=>{const{eye_pos:t,surf_norm:r,mapN:s,uv:i}=e,n=t.dFdx(),o=t.dFdy(),a=i.dFdx(),u=i.dFdy(),l=r,d=o.cross(l),c=l.cross(n),h=d.mul(a.x).add(c.mul(u.x)),p=d.mul(a.y).add(c.mul(u.y)),g=h.dot(h).max(p.dot(p)),m=rl.mul(g.inverseSqrt());return On(h.mul(s.x,m),p.mul(s.y,m),l.mul(s.z)).normalize()}));class Kl extends Fs{static get type(){return"NormalMapNode"}constructor(e,t=null){super("vec3"),this.node=e,this.scaleNode=t,this.normalMapType=N}setup(e){const{normalMapType:t,scaleNode:r}=this;let s=this.node.mul(2).sub(1);null!==r&&(s=Ii(s.xy.mul(r),s.z));let i=null;if(t===S)i=hl(s);else if(t===N){i=!0===e.hasGeometryAttribute("tangent")?Hl.mul(s).normalize():ql({eye_pos:Zu,surf_norm:ol,mapN:s,uv:pu()})}return i}}const Xl=bi(Kl),Yl=_i((({textureNode:e,bumpScale:t})=>{const r=t=>e.cache().context({getUV:e=>t(e.uvNode||pu()),forceUVContext:!0}),s=Ci(r((e=>e)));return Bi(Ci(r((e=>e.add(e.dFdx())))).sub(s),Ci(r((e=>e.add(e.dFdy())))).sub(s)).mul(t)})),Ql=_i((e=>{const{surf_pos:t,surf_norm:r,dHdxy:s}=e,i=t.dFdx().normalize(),n=r,o=t.dFdy().normalize().cross(n),a=n.cross(i),u=i.dot(o).mul(rl),l=u.sign().mul(s.x.mul(o).add(s.y.mul(a)));return u.abs().mul(r).sub(l).normalize()}));class Zl extends Fs{static get type(){return"BumpMapNode"}constructor(e,t=null){super("vec3"),this.textureNode=e,this.scaleNode=t}setup(){const e=null!==this.scaleNode?this.scaleNode:1,t=Yl({textureNode:this.textureNode,bumpScale:e});return Ql({surf_pos:Zu,surf_norm:ol,dHdxy:t})}}const Jl=bi(Zl),ed=new Map;class td extends Ms{static get type(){return"MaterialNode"}constructor(e){super(),this.scope=e}getCache(e,t){let r=ed.get(e);return void 0===r&&(r=Ml(e,t),ed.set(e,r)),r}getFloat(e){return this.getCache(e,"float")}getColor(e){return this.getCache(e,"color")}getTexture(e){return this.getCache("map"===e?"map":e+"Map","texture")}setup(e){const t=e.context.material,r=this.scope;let s=null;if(r===td.COLOR){const e=void 0!==t.color?this.getColor(r):Ii();s=t.map&&!0===t.map.isTexture?e.mul(this.getTexture("map")):e}else if(r===td.OPACITY){const e=this.getFloat(r);s=t.alphaMap&&!0===t.alphaMap.isTexture?e.mul(this.getTexture("alpha")):e}else if(r===td.SPECULAR_STRENGTH)s=t.specularMap&&!0===t.specularMap.isTexture?this.getTexture("specular").r:Ci(1);else if(r===td.SPECULAR_INTENSITY){const e=this.getFloat(r);s=t.specularMap?e.mul(this.getTexture(r).a):e}else if(r===td.SPECULAR_COLOR){const e=this.getColor(r);s=t.specularColorMap&&!0===t.specularColorMap.isTexture?e.mul(this.getTexture(r).rgb):e}else if(r===td.ROUGHNESS){const e=this.getFloat(r);s=t.roughnessMap&&!0===t.roughnessMap.isTexture?e.mul(this.getTexture(r).g):e}else if(r===td.METALNESS){const e=this.getFloat(r);s=t.metalnessMap&&!0===t.metalnessMap.isTexture?e.mul(this.getTexture(r).b):e}else if(r===td.EMISSIVE){const e=this.getFloat("emissiveIntensity"),i=this.getColor(r).mul(e);s=t.emissiveMap&&!0===t.emissiveMap.isTexture?i.mul(this.getTexture(r)):i}else if(r===td.NORMAL)t.normalMap?(s=Xl(this.getTexture("normal"),this.getCache("normalScale","vec2")),s.normalMapType=t.normalMapType):s=t.bumpMap?Jl(this.getTexture("bump").r,this.getFloat("bumpScale")):ol;else if(r===td.CLEARCOAT){const e=this.getFloat(r);s=t.clearcoatMap&&!0===t.clearcoatMap.isTexture?e.mul(this.getTexture(r).r):e}else if(r===td.CLEARCOAT_ROUGHNESS){const e=this.getFloat(r);s=t.clearcoatRoughnessMap&&!0===t.clearcoatRoughnessMap.isTexture?e.mul(this.getTexture(r).r):e}else if(r===td.CLEARCOAT_NORMAL)s=t.clearcoatNormalMap?Xl(this.getTexture(r),this.getCache(r+"Scale","vec2")):ol;else if(r===td.SHEEN){const e=this.getColor("sheenColor").mul(this.getFloat("sheen"));s=t.sheenColorMap&&!0===t.sheenColorMap.isTexture?e.mul(this.getTexture("sheenColor").rgb):e}else if(r===td.SHEEN_ROUGHNESS){const e=this.getFloat(r);s=t.sheenRoughnessMap&&!0===t.sheenRoughnessMap.isTexture?e.mul(this.getTexture(r).a):e,s=s.clamp(.07,1)}else if(r===td.ANISOTROPY)if(t.anisotropyMap&&!0===t.anisotropyMap.isTexture){const e=this.getTexture(r);s=$i(Od.x,Od.y,Od.y.negate(),Od.x).mul(e.rg.mul(2).sub(Bi(1)).normalize().mul(e.b))}else s=Od;else if(r===td.IRIDESCENCE_THICKNESS){const e=Cl("1","float",t.iridescenceThicknessRange);if(t.iridescenceThicknessMap){const i=Cl("0","float",t.iridescenceThicknessRange);s=e.sub(i).mul(this.getTexture(r).g).add(i)}else s=e}else if(r===td.TRANSMISSION){const e=this.getFloat(r);s=t.transmissionMap?e.mul(this.getTexture(r).r):e}else if(r===td.THICKNESS){const e=this.getFloat(r);s=t.thicknessMap?e.mul(this.getTexture(r).g):e}else if(r===td.IOR)s=this.getFloat(r);else if(r===td.LIGHT_MAP)s=this.getTexture(r).rgb.mul(this.getFloat("lightMapIntensity"));else if(r===td.AO_MAP)s=this.getTexture(r).r.sub(1).mul(this.getFloat("aoMapIntensity")).add(1);else{const t=this.getNodeType(e);s=this.getCache(r,t)}return s}}td.ALPHA_TEST="alphaTest",td.COLOR="color",td.OPACITY="opacity",td.SHININESS="shininess",td.SPECULAR="specular",td.SPECULAR_STRENGTH="specularStrength",td.SPECULAR_INTENSITY="specularIntensity",td.SPECULAR_COLOR="specularColor",td.REFLECTIVITY="reflectivity",td.ROUGHNESS="roughness",td.METALNESS="metalness",td.NORMAL="normal",td.CLEARCOAT="clearcoat",td.CLEARCOAT_ROUGHNESS="clearcoatRoughness",td.CLEARCOAT_NORMAL="clearcoatNormal",td.EMISSIVE="emissive",td.ROTATION="rotation",td.SHEEN="sheen",td.SHEEN_ROUGHNESS="sheenRoughness",td.ANISOTROPY="anisotropy",td.IRIDESCENCE="iridescence",td.IRIDESCENCE_IOR="iridescenceIOR",td.IRIDESCENCE_THICKNESS="iridescenceThickness",td.IOR="ior",td.TRANSMISSION="transmission",td.THICKNESS="thickness",td.ATTENUATION_DISTANCE="attenuationDistance",td.ATTENUATION_COLOR="attenuationColor",td.LINE_SCALE="scale",td.LINE_DASH_SIZE="dashSize",td.LINE_GAP_SIZE="gapSize",td.LINE_WIDTH="linewidth",td.LINE_DASH_OFFSET="dashOffset",td.POINT_WIDTH="pointWidth",td.DISPERSION="dispersion",td.LIGHT_MAP="light",td.AO_MAP="ao";const rd=Ti(td,td.ALPHA_TEST),sd=Ti(td,td.COLOR),id=Ti(td,td.SHININESS),nd=Ti(td,td.EMISSIVE),od=Ti(td,td.OPACITY),ad=Ti(td,td.SPECULAR),ud=Ti(td,td.SPECULAR_INTENSITY),ld=Ti(td,td.SPECULAR_COLOR),dd=Ti(td,td.SPECULAR_STRENGTH),cd=Ti(td,td.REFLECTIVITY),hd=Ti(td,td.ROUGHNESS),pd=Ti(td,td.METALNESS),gd=Ti(td,td.NORMAL).context({getUV:null}),md=Ti(td,td.CLEARCOAT),fd=Ti(td,td.CLEARCOAT_ROUGHNESS),yd=Ti(td,td.CLEARCOAT_NORMAL).context({getUV:null}),xd=Ti(td,td.ROTATION),bd=Ti(td,td.SHEEN),Td=Ti(td,td.SHEEN_ROUGHNESS),_d=Ti(td,td.ANISOTROPY),vd=Ti(td,td.IRIDESCENCE),Nd=Ti(td,td.IRIDESCENCE_IOR),Sd=Ti(td,td.IRIDESCENCE_THICKNESS),Ad=Ti(td,td.TRANSMISSION),Rd=Ti(td,td.THICKNESS),Cd=Ti(td,td.IOR),Ed=Ti(td,td.ATTENUATION_DISTANCE),wd=Ti(td,td.ATTENUATION_COLOR),Md=Ti(td,td.LINE_SCALE),Bd=Ti(td,td.LINE_DASH_SIZE),Ud=Ti(td,td.LINE_GAP_SIZE),Fd=Ti(td,td.LINE_WIDTH),Pd=Ti(td,td.LINE_DASH_OFFSET),Id=Ti(td,td.POINT_WIDTH),Ld=Ti(td,td.DISPERSION),Vd=Ti(td,td.LIGHT_MAP),Dd=Ti(td,td.AO_MAP),Od=tn(new t).onReference((function(e){return e.material})).onRenderUpdate((function({material:e}){this.value.set(e.anisotropy*Math.cos(e.anisotropyRotation),e.anisotropy*Math.sin(e.anisotropyRotation))})),Gd=_i((e=>e.context.setupModelViewProjection()),"vec4").once()().varying("v_modelViewProjection");class kd extends Ms{static get type(){return"IndexNode"}constructor(e){super("uint"),this.scope=e,this.isIndexNode=!0}generate(e){const t=this.getNodeType(e),r=this.scope;let s,i;if(r===kd.VERTEX)s=e.getVertexIndex();else if(r===kd.INSTANCE)s=e.getInstanceIndex();else if(r===kd.DRAW)s=e.getDrawIndex();else if(r===kd.INVOCATION_LOCAL)s=e.getInvocationLocalIndex();else if(r===kd.INVOCATION_SUBGROUP)s=e.getInvocationSubgroupIndex();else{if(r!==kd.SUBGROUP)throw new Error("THREE.IndexNode: Unknown scope: "+r);s=e.getSubgroupIndex()}if("vertex"===e.shaderStage||"compute"===e.shaderStage)i=s;else{i=wa(this).build(e,t)}return i}}kd.VERTEX="vertex",kd.INSTANCE="instance",kd.SUBGROUP="subgroup",kd.INVOCATION_LOCAL="invocationLocal",kd.INVOCATION_SUBGROUP="invocationSubgroup",kd.DRAW="draw";const zd=Ti(kd,kd.VERTEX),$d=Ti(kd,kd.INSTANCE),Hd=Ti(kd,kd.SUBGROUP),Wd=Ti(kd,kd.INVOCATION_SUBGROUP),jd=Ti(kd,kd.INVOCATION_LOCAL),qd=Ti(kd,kd.DRAW);class Kd extends Ms{static get type(){return"InstanceNode"}constructor(e,t,r){super("void"),this.count=e,this.instanceMatrix=t,this.instanceColor=r,this.instanceMatrixNode=null,this.instanceColorNode=null,this.updateType=vs.FRAME,this.buffer=null,this.bufferColor=null}setup(e){const{count:t,instanceMatrix:r,instanceColor:s}=this;let{instanceMatrixNode:i,instanceColorNode:n}=this;if(null===i){if(t<=1e3)i=_l(r.array,"mat4",Math.max(t,1)).element($d);else{const e=new A(r.array,16,1);this.buffer=e;const t=r.usage===m?Ya:Xa,s=[t(e,"vec4",16,0),t(e,"vec4",16,4),t(e,"vec4",16,8),t(e,"vec4",16,12)];i=Wi(...s)}this.instanceMatrixNode=i}if(s&&null===n){const e=new R(s.array,3),t=s.usage===m?Ya:Xa;this.bufferColor=e,n=Ii(t(e,"vec3",3,0)),this.instanceColorNode=n}const o=i.mul(Ku).xyz;if(Ku.assign(o),e.hasGeometryAttribute("normal")){const e=cl(il,i);il.assign(e)}null!==this.instanceColorNode&&nn("vec3","vInstanceColor").assign(this.instanceColorNode)}update(){this.instanceMatrix.usage!==m&&null!==this.buffer&&this.instanceMatrix.version!==this.buffer.version&&(this.buffer.version=this.instanceMatrix.version),this.instanceColor&&this.instanceColor.usage!==m&&null!==this.bufferColor&&this.instanceColor.version!==this.bufferColor.version&&(this.bufferColor.version=this.instanceColor.version)}}const Xd=bi(Kd);class Yd extends Kd{static get type(){return"InstancedMeshNode"}constructor(e){const{count:t,instanceMatrix:r,instanceColor:s}=e;super(t,r,s),this.instancedMesh=e}}const Qd=bi(Yd);class Zd extends Ms{static get type(){return"BatchNode"}constructor(e){super("void"),this.batchMesh=e,this.batchingIdNode=null}setup(e){null===this.batchingIdNode&&(null===e.getDrawIndex()?this.batchingIdNode=$d:this.batchingIdNode=qd);const t=_i((([e])=>{const t=mu(Tu(this.batchMesh._indirectTexture),0),r=Ei(e).modInt(Ei(t)),s=Ei(e).div(Ei(t));return Tu(this.batchMesh._indirectTexture,Ui(r,s)).x})).setLayout({name:"getIndirectIndex",type:"uint",inputs:[{name:"id",type:"int"}]}),r=t(Ei(this.batchingIdNode)),s=this.batchMesh._matricesTexture,i=mu(Tu(s),0),n=Ci(r).mul(4).toInt().toVar(),o=n.modInt(i),a=n.div(Ei(i)),u=Wi(Tu(s,Ui(o,a)),Tu(s,Ui(o.add(1),a)),Tu(s,Ui(o.add(2),a)),Tu(s,Ui(o.add(3),a))),l=this.batchMesh._colorsTexture;if(null!==l){const e=_i((([e])=>{const t=mu(Tu(l),0).x,r=e,s=r.modInt(t),i=r.div(t);return Tu(l,Ui(s,i)).rgb})).setLayout({name:"getBatchingColor",type:"vec3",inputs:[{name:"id",type:"int"}]}),t=e(r);nn("vec3","vBatchColor").assign(t)}const d=Hi(u);Ku.assign(u.mul(Ku));const c=il.div(Ii(d[0].dot(d[0]),d[1].dot(d[1]),d[2].dot(d[2]))),h=d.mul(c).xyz;il.assign(h),e.hasGeometryAttribute("tangent")&&Ul.mulAssign(d)}}const Jd=bi(Zd),ec=new WeakMap;class tc extends Ms{static get type(){return"SkinningNode"}constructor(e,t=!1){let r,s,i;super("void"),this.skinnedMesh=e,this.useReference=t,this.updateType=vs.OBJECT,this.skinIndexNode=hu("skinIndex","uvec4"),this.skinWeightNode=hu("skinWeight","vec4"),t?(r=Cl("bindMatrix","mat4"),s=Cl("bindMatrixInverse","mat4"),i=El("skeleton.boneMatrices","mat4",e.skeleton.bones.length)):(r=tn(e.bindMatrix,"mat4"),s=tn(e.bindMatrixInverse,"mat4"),i=_l(e.skeleton.boneMatrices,"mat4",e.skeleton.bones.length)),this.bindMatrixNode=r,this.bindMatrixInverseNode=s,this.boneMatricesNode=i,this.previousBoneMatricesNode=null}getSkinnedPosition(e=this.boneMatricesNode,t=Ku){const{skinIndexNode:r,skinWeightNode:s,bindMatrixNode:i,bindMatrixInverseNode:n}=this,o=e.element(r.x),a=e.element(r.y),u=e.element(r.z),l=e.element(r.w),d=i.mul(t),c=On(o.mul(s.x).mul(d),a.mul(s.y).mul(d),u.mul(s.z).mul(d),l.mul(s.w).mul(d));return n.mul(c).xyz}getSkinnedNormal(e=this.boneMatricesNode,t=il){const{skinIndexNode:r,skinWeightNode:s,bindMatrixNode:i,bindMatrixInverseNode:n}=this,o=e.element(r.x),a=e.element(r.y),u=e.element(r.z),l=e.element(r.w);let d=On(s.x.mul(o),s.y.mul(a),s.z.mul(u),s.w.mul(l));return d=n.mul(d).mul(i),d.transformDirection(t).xyz}getPreviousSkinnedPosition(e){const t=e.object;return null===this.previousBoneMatricesNode&&(t.skeleton.previousBoneMatrices=new Float32Array(t.skeleton.boneMatrices),this.previousBoneMatricesNode=El("skeleton.previousBoneMatrices","mat4",t.skeleton.bones.length)),this.getSkinnedPosition(this.previousBoneMatricesNode,Xu)}needsPreviousBoneMatrices(e){const t=e.renderer.getMRT();return t&&t.has("velocity")}setup(e){this.needsPreviousBoneMatrices(e)&&Xu.assign(this.getPreviousSkinnedPosition(e));const t=this.getSkinnedPosition();if(Ku.assign(t),e.hasGeometryAttribute("normal")){const t=this.getSkinnedNormal();il.assign(t),e.hasGeometryAttribute("tangent")&&Ul.assign(t)}}generate(e,t){if("void"!==t)return Ku.build(e,t)}update(e){const t=(this.useReference?e.object:this.skinnedMesh).skeleton;ec.get(t)!==e.frameId&&(ec.set(t,e.frameId),null!==this.previousBoneMatricesNode&&t.previousBoneMatrices.set(t.boneMatrices),t.update())}}const rc=e=>fi(new tc(e,!0));class sc extends Ms{static get type(){return"LoopNode"}constructor(e=[]){super(),this.params=e}getVarName(e){return String.fromCharCode("i".charCodeAt(0)+e)}getProperties(e){const t=e.getNodeProperties(this);if(void 0!==t.stackNode)return t;const r={};for(let e=0,t=this.params.length-1;eNumber(n)?">=":"<"));const d={start:i,end:n,condition:u},c=d.start,h=d.end;let p="",g="",m="";l||(l="int"===a||"uint"===a?u.includes("<")?"++":"--":u.includes("<")?"+= 1.":"-= 1."),p+=e.getVar(a,o)+" = "+c,g+=o+" "+u+" "+h,m+=o+" "+l;const f=`for ( ${p}; ${g}; ${m} )`;e.addFlowCode((0===t?"\n":"")+e.tab+f+" {\n\n").addFlowTab()}const i=s.build(e,"void"),n=t.returnsNode?t.returnsNode.build(e):"";e.removeFlowTab().addFlowCode("\n"+e.tab+i);for(let t=0,r=this.params.length-1;tfi(new sc(xi(e,"int"))).append(),nc=()=>au("break").append(),oc=new WeakMap,ac=new s,uc=_i((({bufferMap:e,influence:t,stride:r,width:s,depth:i,offset:n})=>{const o=Ei(zd).mul(r).add(n),a=o.div(s),u=o.sub(a.mul(s));return Tu(e,Ui(u,a)).depth(i).mul(t)}));class lc extends Ms{static get type(){return"MorphNode"}constructor(e){super("void"),this.mesh=e,this.morphBaseInfluence=tn(1),this.updateType=vs.OBJECT}setup(e){const{geometry:r}=e,s=void 0!==r.morphAttributes.position,i=r.hasAttribute("normal")&&void 0!==r.morphAttributes.normal,n=r.morphAttributes.position||r.morphAttributes.normal||r.morphAttributes.color,o=void 0!==n?n.length:0,{texture:a,stride:u,size:l}=function(e){const r=void 0!==e.morphAttributes.position,s=void 0!==e.morphAttributes.normal,i=void 0!==e.morphAttributes.color,n=e.morphAttributes.position||e.morphAttributes.normal||e.morphAttributes.color,o=void 0!==n?n.length:0;let a=oc.get(e);if(void 0===a||a.count!==o){void 0!==a&&a.texture.dispose();const u=e.morphAttributes.position||[],l=e.morphAttributes.normal||[],d=e.morphAttributes.color||[];let c=0;!0===r&&(c=1),!0===s&&(c=2),!0===i&&(c=3);let h=e.attributes.position.count*c,p=1;const g=4096;h>g&&(p=Math.ceil(h/g),h=g);const m=new Float32Array(h*p*4*o),f=new C(m,h,p,o);f.type=E,f.needsUpdate=!0;const y=4*c;for(let b=0;b{const t=Ci(0).toVar();this.mesh.count>1&&null!==this.mesh.morphTexture&&void 0!==this.mesh.morphTexture?t.assign(Tu(this.mesh.morphTexture,Ui(Ei(e).add(1),Ei($d))).r):t.assign(Cl("morphTargetInfluences","float").element(e).toVar()),!0===s&&Ku.addAssign(uc({bufferMap:a,influence:t,stride:u,width:d,depth:e,offset:Ei(0)})),!0===i&&il.addAssign(uc({bufferMap:a,influence:t,stride:u,width:d,depth:e,offset:Ei(1)}))}))}update(){const e=this.morphBaseInfluence;this.mesh.geometry.morphTargetsRelative?e.value=1:e.value=1-this.mesh.morphTargetInfluences.reduce(((e,t)=>e+t),0)}}const dc=bi(lc);class cc extends Ms{static get type(){return"LightingNode"}constructor(){super("vec3"),this.isLightingNode=!0}}class hc extends cc{static get type(){return"AONode"}constructor(e=null){super(),this.aoNode=e}setup(e){e.context.ambientOcclusion.mulAssign(this.aoNode)}}class pc extends va{static get type(){return"LightingContextNode"}constructor(e,t=null,r=null,s=null){super(e),this.lightingModel=t,this.backdropNode=r,this.backdropAlphaNode=s,this._value=null}getContext(){const{backdropNode:e,backdropAlphaNode:t}=this,r={directDiffuse:Ii().toVar("directDiffuse"),directSpecular:Ii().toVar("directSpecular"),indirectDiffuse:Ii().toVar("indirectDiffuse"),indirectSpecular:Ii().toVar("indirectSpecular")};return{radiance:Ii().toVar("radiance"),irradiance:Ii().toVar("irradiance"),iblIrradiance:Ii().toVar("iblIrradiance"),ambientOcclusion:Ci(1).toVar("ambientOcclusion"),reflectedLight:r,backdrop:e,backdropAlpha:t}}setup(e){return this.value=this._value||(this._value=this.getContext()),this.value.lightingModel=this.lightingModel||e.context.lightingModel,super.setup(e)}}const gc=bi(pc);class mc extends cc{static get type(){return"IrradianceNode"}constructor(e){super(),this.node=e}setup(e){e.context.irradiance.addAssign(this.node)}}let fc,yc;class xc extends Ms{static get type(){return"ScreenNode"}constructor(e){super(),this.scope=e,this.isViewportNode=!0}getNodeType(){return this.scope===xc.VIEWPORT?"vec4":"vec2"}getUpdateType(){let e=vs.NONE;return this.scope!==xc.SIZE&&this.scope!==xc.VIEWPORT||(e=vs.RENDER),this.updateType=e,e}update({renderer:e}){const t=e.getRenderTarget();this.scope===xc.VIEWPORT?null!==t?yc.copy(t.viewport):(e.getViewport(yc),yc.multiplyScalar(e.getPixelRatio())):null!==t?(fc.width=t.width,fc.height=t.height):e.getDrawingBufferSize(fc)}setup(){const e=this.scope;let r=null;return r=e===xc.SIZE?tn(fc||(fc=new t)):e===xc.VIEWPORT?tn(yc||(yc=new s)):Bi(_c.div(Tc)),r}generate(e){if(this.scope===xc.COORDINATE){let t=e.getFragCoord();if(e.isFlipY()){const r=e.getNodeProperties(Tc).outputNode.build(e);t=`${e.getType("vec2")}( ${t}.x, ${r}.y - ${t}.y )`}return t}return super.generate(e)}}xc.COORDINATE="coordinate",xc.VIEWPORT="viewport",xc.SIZE="size",xc.UV="uv";const bc=Ti(xc,xc.UV),Tc=Ti(xc,xc.SIZE),_c=Ti(xc,xc.COORDINATE),vc=Ti(xc,xc.VIEWPORT),Nc=vc.zw,Sc=_c.sub(vc.xy),Ac=Sc.div(Nc),Rc=_i((()=>(console.warn('TSL.ViewportNode: "viewportResolution" is deprecated. Use "screenSize" instead.'),Tc)),"vec2").once()(),Cc=_i((()=>(console.warn('TSL.ViewportNode: "viewportTopLeft" is deprecated. Use "screenUV" instead.'),bc)),"vec2").once()(),Ec=_i((()=>(console.warn('TSL.ViewportNode: "viewportBottomLeft" is deprecated. Use "screenUV.flipY()" instead.'),bc.flipY())),"vec2").once()(),wc=new t;class Mc extends xu{static get type(){return"ViewportTextureNode"}constructor(e=bc,t=null,r=null){null===r&&((r=new w).minFilter=M),super(r,e,t),this.generateMipmaps=!1,this.isOutputTextureNode=!0,this.updateBeforeType=vs.FRAME}updateBefore(e){const t=e.renderer;t.getDrawingBufferSize(wc);const r=this.value;r.image.width===wc.width&&r.image.height===wc.height||(r.image.width=wc.width,r.image.height=wc.height,r.needsUpdate=!0);const s=r.generateMipmaps;r.generateMipmaps=this.generateMipmaps,t.copyFramebufferToTexture(r),r.generateMipmaps=s}clone(){const e=new this.constructor(this.uvNode,this.levelNode,this.value);return e.generateMipmaps=this.generateMipmaps,e}}const Bc=bi(Mc),Uc=bi(Mc,null,null,{generateMipmaps:!0});let Fc=null;class Pc extends Mc{static get type(){return"ViewportDepthTextureNode"}constructor(e=bc,t=null){null===Fc&&(Fc=new B),super(e,t,Fc)}}const Ic=bi(Pc);class Lc extends Ms{static get type(){return"ViewportDepthNode"}constructor(e,t=null){super("float"),this.scope=e,this.valueNode=t,this.isViewportDepthNode=!0}generate(e){const{scope:t}=this;return t===Lc.DEPTH_BASE?e.getFragDepth():super.generate(e)}setup({camera:e}){const{scope:t}=this,r=this.valueNode;let s=null;if(t===Lc.DEPTH_BASE)null!==r&&(s=kc().assign(r));else if(t===Lc.DEPTH)s=e.isPerspectiveCamera?Dc(Zu.z,_u,vu):Vc(Zu.z,_u,vu);else if(t===Lc.LINEAR_DEPTH)if(null!==r)if(e.isPerspectiveCamera){const e=Oc(r,_u,vu);s=Vc(e,_u,vu)}else s=r;else s=Vc(Zu.z,_u,vu);return s}}Lc.DEPTH_BASE="depthBase",Lc.DEPTH="depth",Lc.LINEAR_DEPTH="linearDepth";const Vc=(e,t,r)=>e.add(t).div(t.sub(r)),Dc=(e,t,r)=>t.add(e).mul(r).div(r.sub(t).mul(e)),Oc=(e,t,r)=>t.mul(r).div(r.sub(t).mul(e).sub(r)),Gc=(e,t,r)=>{t=t.max(1e-6).toVar();const s=To(e.negate().div(t)),i=To(r.div(t));return s.div(i)},kc=bi(Lc,Lc.DEPTH_BASE),zc=Ti(Lc,Lc.DEPTH),$c=bi(Lc,Lc.LINEAR_DEPTH),Hc=$c(Ic());zc.assign=e=>kc(e);const Wc=bi(class extends Ms{constructor(e){super("float"),this.name=e,this.isBuiltinNode=!0}generate(){return this.name}});class jc extends Ms{static get type(){return"ClippingNode"}constructor(e=jc.DEFAULT){super(),this.scope=e}setup(e){super.setup(e);const t=e.clippingContext,{intersectionPlanes:r,unionPlanes:s}=t;return this.hardwareClipping=e.material.hardwareClipping,this.scope===jc.ALPHA_TO_COVERAGE?this.setupAlphaToCoverage(r,s):this.scope===jc.HARDWARE?this.setupHardwareClipping(s,e):this.setupDefault(r,s)}setupAlphaToCoverage(e,t){return _i((()=>{const r=Ci().toVar("distanceToPlane"),s=Ci().toVar("distanceToGradient"),i=Ci(1).toVar("clipOpacity"),n=t.length;if(!1===this.hardwareClipping&&n>0){const e=Sl(t);ic(n,(({i:t})=>{const n=e.element(t);r.assign(Zu.dot(n.xyz).negate().add(n.w)),s.assign(r.fwidth().div(2)),i.mulAssign(pa(s.negate(),s,r))}))}const o=e.length;if(o>0){const t=Sl(e),n=Ci(1).toVar("intersectionClipOpacity");ic(o,(({i:e})=>{const i=t.element(e);r.assign(Zu.dot(i.xyz).negate().add(i.w)),s.assign(r.fwidth().div(2)),n.mulAssign(pa(s.negate(),s,r).oneMinus())})),i.mulAssign(n.oneMinus())}on.a.mulAssign(i),on.a.equal(0).discard()}))()}setupDefault(e,t){return _i((()=>{const r=t.length;if(!1===this.hardwareClipping&&r>0){const e=Sl(t);ic(r,(({i:t})=>{const r=e.element(t);Zu.dot(r.xyz).greaterThan(r.w).discard()}))}const s=e.length;if(s>0){const t=Sl(e),r=Mi(!0).toVar("clipped");ic(s,(({i:e})=>{const s=t.element(e);r.assign(Zu.dot(s.xyz).greaterThan(s.w).and(r))})),r.discard()}}))()}setupHardwareClipping(e,t){const r=e.length;return t.enableHardwareClipping(r),_i((()=>{const s=Sl(e),i=Wc(t.getClipDistance());ic(r,(({i:e})=>{const t=s.element(e),r=Zu.dot(t.xyz).sub(t.w).negate();i.element(e).assign(r)}))}))()}}jc.ALPHA_TO_COVERAGE="alphaToCoverage",jc.DEFAULT="default",jc.HARDWARE="hardware";const qc=_i((([e])=>Ro(kn(1e4,Co(kn(17,e.x).add(kn(.1,e.y)))).mul(On(.1,Fo(Co(kn(13,e.y).add(e.x)))))))),Kc=_i((([e])=>qc(Bi(qc(e.xy),e.z)))),Xc=_i((([e])=>{const t=Ko(Io(Do(e.xyz)),Io(Oo(e.xyz))),r=Ci(1).div(Ci(.05).mul(t)).toVar("pixScale"),s=Bi(xo(No(To(r))),xo(So(To(r)))),i=Bi(Kc(No(s.x.mul(e.xyz))),Kc(No(s.y.mul(e.xyz)))),n=Ro(To(r)),o=On(kn(n.oneMinus(),i.x),kn(n,i.y)),a=qo(n,n.oneMinus()),u=Ii(o.mul(o).div(kn(2,a).mul(Gn(1,a))),o.sub(kn(.5,a)).div(Gn(1,a)),Gn(1,Gn(1,o).mul(Gn(1,o)).div(kn(2,a).mul(Gn(1,a))))),l=o.lessThan(a.oneMinus()).select(o.lessThan(a).select(u.x,u.y),u.z);return da(l,1e-6,1)})).setLayout({name:"getAlphaHashThreshold",type:"float",inputs:[{name:"position",type:"vec3"}]});class Yc extends U{static get type(){return"NodeMaterial"}get type(){return this.constructor.type}set type(e){}constructor(){super(),this.isNodeMaterial=!0,this.forceSinglePass=!1,this.fog=!0,this.lights=!1,this.hardwareClipping=!1,this.lightsNode=null,this.envNode=null,this.aoNode=null,this.colorNode=null,this.normalNode=null,this.opacityNode=null,this.backdropNode=null,this.backdropAlphaNode=null,this.alphaTestNode=null,this.positionNode=null,this.geometryNode=null,this.depthNode=null,this.shadowPositionNode=null,this.receivedShadowNode=null,this.castShadowNode=null,this.outputNode=null,this.mrtNode=null,this.fragmentNode=null,this.vertexNode=null}customProgramCacheKey(){return this.type+cs(this)}build(e){this.setup(e)}setupObserver(e){return new os(e)}setup(e){e.context.setupNormal=()=>this.setupNormal(e),e.context.setupPositionView=()=>this.setupPositionView(e),e.context.setupModelViewProjection=()=>this.setupModelViewProjection(e);const t=e.renderer,r=t.getRenderTarget();e.addStack();const s=this.vertexNode||this.setupVertex(e);let i;e.stack.outputNode=s,this.setupHardwareClipping(e),null!==this.geometryNode&&(e.stack.outputNode=e.stack.outputNode.bypass(this.geometryNode)),e.addFlow("vertex",e.removeStack()),e.addStack();const n=this.setupClipping(e);if(!0===this.depthWrite&&(null!==r?!0===r.depthBuffer&&this.setupDepth(e):!0===t.depth&&this.setupDepth(e)),null===this.fragmentNode){this.setupDiffuseColor(e),this.setupVariants(e);const s=this.setupLighting(e);null!==n&&e.stack.add(n);const o=Oi(s,on.a).max(0);if(i=this.setupOutput(e,o),Sn.assign(i),null!==this.outputNode&&(i=this.outputNode),null!==r){const e=t.getMRT(),r=this.mrtNode;null!==e?(i=e,null!==r&&(i=e.merge(r))):null!==r&&(i=r)}}else{let t=this.fragmentNode;!0!==t.isOutputStructNode&&(t=Oi(t)),i=this.setupOutput(e,t)}e.stack.outputNode=i,e.addFlow("fragment",e.removeStack()),e.monitor=this.setupObserver(e)}setupClipping(e){if(null===e.clippingContext)return null;const{unionPlanes:t,intersectionPlanes:r}=e.clippingContext;let s=null;if(t.length>0||r.length>0){const t=e.renderer.samples;this.alphaToCoverage&&t>1?s=fi(new jc(jc.ALPHA_TO_COVERAGE)):e.stack.add(fi(new jc))}return s}setupHardwareClipping(e){if(this.hardwareClipping=!1,null===e.clippingContext)return;const t=e.clippingContext.unionPlanes.length;t>0&&t<=8&&e.isAvailable("clipDistance")&&(e.stack.add(fi(new jc(jc.HARDWARE))),this.hardwareClipping=!0)}setupDepth(e){const{renderer:t,camera:r}=e;let s=this.depthNode;if(null===s){const e=t.getMRT();e&&e.has("depth")?s=e.get("depth"):!0===t.logarithmicDepthBuffer&&(s=r.isPerspectiveCamera?Gc(Zu.z,_u,vu):Vc(Zu.z,_u,vu))}null!==s&&zc.assign(s).append()}setupPositionView(){return $u.mul(Ku).xyz}setupModelViewProjection(){return Nu.mul(Zu)}setupVertex(e){return e.addStack(),this.setupPosition(e),e.context.vertex=e.removeStack(),Gd}setupPosition(e){const{object:t,geometry:r}=e;if((r.morphAttributes.position||r.morphAttributes.normal||r.morphAttributes.color)&&dc(t).append(),!0===t.isSkinnedMesh&&rc(t).append(),this.displacementMap){const e=Ml("displacementMap","texture"),t=Ml("displacementScale","float"),r=Ml("displacementBias","float");Ku.addAssign(il.normalize().mul(e.x.mul(t).add(r)))}return t.isBatchedMesh&&Jd(t).append(),t.isInstancedMesh&&t.instanceMatrix&&!0===t.instanceMatrix.isInstancedBufferAttribute&&Qd(t).append(),null!==this.positionNode&&Ku.assign(this.positionNode.context({isPositionNodeInput:!0})),Ku}setupDiffuseColor({object:e,geometry:t}){let r=this.colorNode?Oi(this.colorNode):sd;if(!0===this.vertexColors&&t.hasAttribute("color")&&(r=Oi(r.xyz.mul(hu("color","vec3")),r.a)),e.instanceColor){r=nn("vec3","vInstanceColor").mul(r)}if(e.isBatchedMesh&&e._colorsTexture){r=nn("vec3","vBatchColor").mul(r)}on.assign(r);const s=this.opacityNode?Ci(this.opacityNode):od;if(on.a.assign(on.a.mul(s)),null!==this.alphaTestNode||this.alphaTest>0){const e=null!==this.alphaTestNode?Ci(this.alphaTestNode):rd;on.a.lessThanEqual(e).discard()}!0===this.alphaHash&&on.a.lessThan(Xc(Ku)).discard(),!1===this.transparent&&this.blending===F&&!1===this.alphaToCoverage&&on.a.assign(1)}setupVariants(){}setupOutgoingLight(){return!0===this.lights?Ii(0):on.rgb}setupNormal(){return this.normalNode?Ii(this.normalNode):gd}setupEnvironment(){let e=null;return this.envNode?e=this.envNode:this.envMap&&(e=this.envMap.isCubeTexture?Ml("envMap","cubeTexture"):Ml("envMap","texture")),e}setupLightMap(e){let t=null;return e.material.lightMap&&(t=new mc(Vd)),t}setupLights(e){const t=[],r=this.setupEnvironment(e);r&&r.isLightingNode&&t.push(r);const s=this.setupLightMap(e);if(s&&s.isLightingNode&&t.push(s),null!==this.aoNode||e.material.aoMap){const e=null!==this.aoNode?this.aoNode:Dd;t.push(new hc(e))}let i=this.lightsNode||e.lightsNode;return t.length>0&&(i=e.renderer.lighting.createNode([...i.getLights(),...t])),i}setupLightingModel(){}setupLighting(e){const{material:t}=e,{backdropNode:r,backdropAlphaNode:s,emissiveNode:i}=this,n=!0===this.lights||null!==this.lightsNode?this.setupLights(e):null;let o=this.setupOutgoingLight(e);if(n&&n.getScope().hasLights){const t=this.setupLightingModel(e);o=gc(n,t,r,s)}else null!==r&&(o=Ii(null!==s?la(o,r,s):r));return(i&&!0===i.isNode||t.emissive&&!0===t.emissive.isColor)&&(an.assign(Ii(i||nd)),o=o.add(an)),o}setupOutput(e,t){if(!0===this.fog){const r=e.fogNode;r&&(Sn.assign(t),t=Oi(r))}return t}setDefaultValues(e){for(const t in e){const r=e[t];void 0===this[t]&&(this[t]=r,r&&r.clone&&(this[t]=r.clone()))}const t=Object.getOwnPropertyDescriptors(e.constructor.prototype);for(const e in t)void 0===Object.getOwnPropertyDescriptor(this.constructor.prototype,e)&&void 0!==t[e].get&&Object.defineProperty(this.constructor.prototype,e,t[e])}toJSON(e){const t=void 0===e||"string"==typeof e;t&&(e={textures:{},images:{},nodes:{}});const r=U.prototype.toJSON.call(this,e),s=hs(this);r.inputNodes={};for(const{property:t,childNode:i}of s)r.inputNodes[t]=i.toJSON(e).uuid;function i(e){const t=[];for(const r in e){const s=e[r];delete s.metadata,t.push(s)}return t}if(t){const t=i(e.textures),s=i(e.images),n=i(e.nodes);t.length>0&&(r.textures=t),s.length>0&&(r.images=s),n.length>0&&(r.nodes=n)}return r}copy(e){return this.lightsNode=e.lightsNode,this.envNode=e.envNode,this.colorNode=e.colorNode,this.normalNode=e.normalNode,this.opacityNode=e.opacityNode,this.backdropNode=e.backdropNode,this.backdropAlphaNode=e.backdropAlphaNode,this.alphaTestNode=e.alphaTestNode,this.positionNode=e.positionNode,this.geometryNode=e.geometryNode,this.depthNode=e.depthNode,this.shadowPositionNode=e.shadowPositionNode,this.receivedShadowNode=e.receivedShadowNode,this.castShadowNode=e.castShadowNode,this.outputNode=e.outputNode,this.mrtNode=e.mrtNode,this.fragmentNode=e.fragmentNode,this.vertexNode=e.vertexNode,super.copy(e)}}const Qc=new P;class Zc extends Yc{static get type(){return"InstancedPointsNodeMaterial"}constructor(e={}){super(),this.lights=!1,this.useAlphaToCoverage=!0,this.useColor=e.vertexColors,this.pointWidth=1,this.pointColorNode=null,this.pointWidthNode=null,this.setDefaultValues(Qc),this.setValues(e)}setup(e){this.setupShaders(e),super.setup(e)}setupShaders({renderer:e}){const t=this.alphaToCoverage,r=this.useColor;this.vertexNode=_i((()=>{const e=hu("instancePosition").xyz,t=Oi($u.mul(Oi(e,1))),r=vc.z.div(vc.w),s=Nu.mul(t),i=qu.xy.toVar();return i.mulAssign(this.pointWidthNode?this.pointWidthNode:Id),i.assign(i.div(vc.z)),i.y.assign(i.y.mul(r)),i.assign(i.mul(s.w)),s.addAssign(Oi(i,0,0)),s}))(),this.fragmentNode=_i((()=>{const s=Ci(1).toVar(),i=ua(pu().mul(2).sub(1));if(t&&e.samples>1){const e=Ci(i.fwidth()).toVar();s.assign(pa(e.oneMinus(),e.add(1),i).oneMinus())}else i.greaterThan(1).discard();let n;if(this.pointColorNode)n=this.pointColorNode;else if(r){n=hu("instanceColor").mul(sd)}else n=sd;return s.mulAssign(od),Oi(n,s)}))()}get alphaToCoverage(){return this.useAlphaToCoverage}set alphaToCoverage(e){this.useAlphaToCoverage!==e&&(this.useAlphaToCoverage=e,this.needsUpdate=!0)}}const Jc=new I;class eh extends Yc{static get type(){return"LineBasicNodeMaterial"}constructor(e){super(),this.isLineBasicNodeMaterial=!0,this.lights=!1,this.setDefaultValues(Jc),this.setValues(e)}}const th=new L;class rh extends Yc{static get type(){return"LineDashedNodeMaterial"}constructor(e){super(),this.isLineDashedNodeMaterial=!0,this.lights=!1,this.setDefaultValues(th),this.dashOffset=0,this.offsetNode=null,this.dashScaleNode=null,this.dashSizeNode=null,this.gapSizeNode=null,this.setValues(e)}setupVariants(){const e=this.offsetNode?Ci(this.offsetNodeNode):Pd,t=this.dashScaleNode?Ci(this.dashScaleNode):Md,r=this.dashSizeNode?Ci(this.dashSizeNode):Bd,s=this.dashSizeNode?Ci(this.dashGapNode):Ud;An.assign(r),Rn.assign(s);const i=wa(hu("lineDistance").mul(t));(e?i.add(e):i).mod(An.add(Rn)).greaterThan(An).discard()}}let sh=null;class ih extends Mc{static get type(){return"ViewportSharedTextureNode"}constructor(e=bc,t=null){null===sh&&(sh=new w),super(e,t,sh)}updateReference(){return this}}const nh=bi(ih),oh=new L;class ah extends Yc{static get type(){return"Line2NodeMaterial"}constructor(e={}){super(),this.lights=!1,this.setDefaultValues(oh),this.useAlphaToCoverage=!0,this.useColor=e.vertexColors,this.useDash=e.dashed,this.useWorldUnits=!1,this.dashOffset=0,this.lineWidth=1,this.lineColorNode=null,this.offsetNode=null,this.dashScaleNode=null,this.dashSizeNode=null,this.gapSizeNode=null,this.blending=V,this.setValues(e)}setup(e){this.setupShaders(e),super.setup(e)}setupShaders({renderer:e}){const t=this.alphaToCoverage,r=this.useColor,s=this.dashed,i=this.worldUnits,n=_i((({start:e,end:t})=>{const r=Nu.element(2).element(2),s=Nu.element(3).element(2).mul(-.5).div(r).sub(e.z).div(t.z.sub(e.z));return Oi(la(e.xyz,t.xyz,s),t.w)})).setLayout({name:"trimSegment",type:"vec4",inputs:[{name:"start",type:"vec4"},{name:"end",type:"vec4"}]});this.vertexNode=_i((()=>{const e=hu("instanceStart"),t=hu("instanceEnd"),r=Oi($u.mul(Oi(e,1))).toVar("start"),o=Oi($u.mul(Oi(t,1))).toVar("end");if(s){const e=this.dashScaleNode?Ci(this.dashScaleNode):Md,t=this.offsetNode?Ci(this.offsetNode):Pd,r=hu("instanceDistanceStart"),s=hu("instanceDistanceEnd");let i=qu.y.lessThan(.5).select(e.mul(r),e.mul(s));i=i.add(t),nn("float","lineDistance").assign(i)}i&&(nn("vec3","worldStart").assign(r.xyz),nn("vec3","worldEnd").assign(o.xyz));const a=vc.z.div(vc.w),u=Nu.element(2).element(3).equal(-1);Si(u,(()=>{Si(r.z.lessThan(0).and(o.z.greaterThan(0)),(()=>{o.assign(n({start:r,end:o}))})).ElseIf(o.z.lessThan(0).and(r.z.greaterThanEqual(0)),(()=>{r.assign(n({start:o,end:r}))}))}));const l=Nu.mul(r),d=Nu.mul(o),c=l.xyz.div(l.w),h=d.xyz.div(d.w),p=h.xy.sub(c.xy).toVar();p.x.assign(p.x.mul(a)),p.assign(p.normalize());const g=Oi().toVar();if(i){const e=o.xyz.sub(r.xyz).normalize(),t=la(r.xyz,o.xyz,.5).normalize(),i=e.cross(t).normalize(),n=e.cross(i),a=nn("vec4","worldPos");a.assign(qu.y.lessThan(.5).select(r,o));const u=Fd.mul(.5);a.addAssign(Oi(qu.x.lessThan(0).select(i.mul(u),i.mul(u).negate()),0)),s||(a.addAssign(Oi(qu.y.lessThan(.5).select(e.mul(u).negate(),e.mul(u)),0)),a.addAssign(Oi(n.mul(u),0)),Si(qu.y.greaterThan(1).or(qu.y.lessThan(0)),(()=>{a.subAssign(Oi(n.mul(2).mul(u),0))}))),g.assign(Nu.mul(a));const l=Ii().toVar();l.assign(qu.y.lessThan(.5).select(c,h)),g.z.assign(l.z.mul(g.w))}else{const e=Bi(p.y,p.x.negate()).toVar("offset");p.x.assign(p.x.div(a)),e.x.assign(e.x.div(a)),e.assign(qu.x.lessThan(0).select(e.negate(),e)),Si(qu.y.lessThan(0),(()=>{e.assign(e.sub(p))})).ElseIf(qu.y.greaterThan(1),(()=>{e.assign(e.add(p))})),e.assign(e.mul(Fd)),e.assign(e.div(vc.w)),g.assign(qu.y.lessThan(.5).select(l,d)),e.assign(e.mul(g.w)),g.assign(g.add(Oi(e,0,0)))}return g}))();const o=_i((({p1:e,p2:t,p3:r,p4:s})=>{const i=e.sub(r),n=s.sub(r),o=t.sub(e),a=i.dot(n),u=n.dot(o),l=i.dot(o),d=n.dot(n),c=o.dot(o).mul(d).sub(u.mul(u)),h=a.mul(u).sub(l.mul(d)).div(c).clamp(),p=a.add(u.mul(h)).div(d).clamp();return Bi(h,p)}));if(this.colorNode=_i((()=>{const n=pu();if(s){const e=this.dashSizeNode?Ci(this.dashSizeNode):Bd,t=this.gapSizeNode?Ci(this.gapSizeNode):Ud;An.assign(e),Rn.assign(t);const r=nn("float","lineDistance");n.y.lessThan(-1).or(n.y.greaterThan(1)).discard(),r.mod(An.add(Rn)).greaterThan(An).discard()}const a=Ci(1).toVar("alpha");if(i){const r=nn("vec3","worldStart"),i=nn("vec3","worldEnd"),n=nn("vec4","worldPos").xyz.normalize().mul(1e5),u=i.sub(r),l=o({p1:r,p2:i,p3:Ii(0,0,0),p4:n}),d=r.add(u.mul(l.x)),c=n.mul(l.y),h=d.sub(c).length().div(Fd);if(!s)if(t&&e.samples>1){const e=h.fwidth();a.assign(pa(e.negate().add(.5),e.add(.5),h).oneMinus())}else h.greaterThan(.5).discard()}else if(t&&e.samples>1){const e=n.x,t=n.y.greaterThan(0).select(n.y.sub(1),n.y.add(1)),r=e.mul(e).add(t.mul(t)),s=Ci(r.fwidth()).toVar("dlen");Si(n.y.abs().greaterThan(1),(()=>{a.assign(pa(s.oneMinus(),s.add(1),r).oneMinus())}))}else Si(n.y.abs().greaterThan(1),(()=>{const e=n.x,t=n.y.greaterThan(0).select(n.y.sub(1),n.y.add(1));e.mul(e).add(t.mul(t)).greaterThan(1).discard()}));let u;if(this.lineColorNode)u=this.lineColorNode;else if(r){const e=hu("instanceColorStart"),t=hu("instanceColorEnd");u=qu.y.lessThan(.5).select(e,t).mul(sd)}else u=sd;return Oi(u,a)}))(),this.transparent){const e=this.opacityNode?Ci(this.opacityNode):od;this.outputNode=Oi(this.colorNode.rgb.mul(e).add(nh().rgb.mul(e.oneMinus())),this.colorNode.a)}}get worldUnits(){return this.useWorldUnits}set worldUnits(e){this.useWorldUnits!==e&&(this.useWorldUnits=e,this.needsUpdate=!0)}get dashed(){return this.useDash}set dashed(e){this.useDash!==e&&(this.useDash=e,this.needsUpdate=!0)}get alphaToCoverage(){return this.useAlphaToCoverage}set alphaToCoverage(e){this.useAlphaToCoverage!==e&&(this.useAlphaToCoverage=e,this.needsUpdate=!0)}}const uh=e=>fi(e).mul(.5).add(.5),lh=new D;class dh extends Yc{static get type(){return"MeshNormalNodeMaterial"}constructor(e){super(),this.lights=!1,this.isMeshNormalNodeMaterial=!0,this.setDefaultValues(lh),this.setValues(e)}setupDiffuseColor(){const e=this.opacityNode?Ci(this.opacityNode):od;on.assign(Oi(uh(ul),e))}}class ch extends Fs{static get type(){return"EquirectUVNode"}constructor(e=Qu){super("vec2"),this.dirNode=e}setup(){const e=this.dirNode,t=e.z.atan(e.x).mul(1/(2*Math.PI)).add(.5),r=e.y.clamp(-1,1).asin().mul(1/Math.PI).add(.5);return Bi(t,r)}}const hh=bi(ch);class ph extends O{constructor(e=1,t={}){super(e,t),this.isCubeRenderTarget=!0}fromEquirectangularTexture(e,t){const r=t.minFilter,s=t.generateMipmaps;t.generateMipmaps=!0,this.texture.type=t.type,this.texture.colorSpace=t.colorSpace,this.texture.generateMipmaps=t.generateMipmaps,this.texture.minFilter=t.minFilter,this.texture.magFilter=t.magFilter;const i=new G(5,5,5),n=hh(Qu),o=new Yc;o.colorNode=bu(t,n,0),o.side=T,o.blending=V;const a=new k(i,o),u=new z;u.add(a),t.minFilter===M&&(t.minFilter=$);const l=new H(1,10,this),d=e.getMRT();return e.setMRT(null),l.update(e,u),e.setMRT(d),t.minFilter=r,t.currentGenerateMipmaps=s,a.geometry.dispose(),a.material.dispose(),this}}const gh=new WeakMap;class mh extends Fs{static get type(){return"CubeMapNode"}constructor(e){super("vec3"),this.envNode=e,this._cubeTexture=null,this._cubeTextureNode=bl();const t=new W;t.isRenderTargetTexture=!0,this._defaultTexture=t,this.updateBeforeType=vs.RENDER}updateBefore(e){const{renderer:t,material:r}=e,s=this.envNode;if(s.isTextureNode||s.isMaterialReferenceNode){const e=s.isTextureNode?s.value:r[s.property];if(e&&e.isTexture){const r=e.mapping;if(r===j||r===q){if(gh.has(e)){const t=gh.get(e);yh(t,e.mapping),this._cubeTexture=t}else{const r=e.image;if(function(e){return null!=e&&e.height>0}(r)){const s=new ph(r.height);s.fromEquirectangularTexture(t,e),yh(s.texture,e.mapping),this._cubeTexture=s.texture,gh.set(e,s.texture),e.addEventListener("dispose",fh)}else this._cubeTexture=this._defaultTexture}this._cubeTextureNode.value=this._cubeTexture}else this._cubeTextureNode=this.envNode}}}setup(e){return this.updateBefore(e),this._cubeTextureNode}}function fh(e){const t=e.target;t.removeEventListener("dispose",fh);const r=gh.get(t);void 0!==r&&(gh.delete(t),r.dispose())}function yh(e,t){t===j?e.mapping=_:t===q&&(e.mapping=v)}const xh=bi(mh);class bh extends cc{static get type(){return"BasicEnvironmentNode"}constructor(e=null){super(),this.envNode=e}setup(e){e.context.environment=xh(this.envNode)}}class Th extends cc{static get type(){return"BasicLightMapNode"}constructor(e=null){super(),this.lightMapNode=e}setup(e){const t=Ci(1/Math.PI);e.context.irradianceLightMap=this.lightMapNode.mul(t)}}class _h{start(){}finish(){}direct(){}directRectArea(){}indirect(){}ambientOcclusion(){}}class vh extends _h{constructor(){super()}indirect(e,t,r){const s=e.ambientOcclusion,i=e.reflectedLight,n=r.context.irradianceLightMap;i.indirectDiffuse.assign(Oi(0)),n?i.indirectDiffuse.addAssign(n):i.indirectDiffuse.addAssign(Oi(1,1,1,0)),i.indirectDiffuse.mulAssign(s),i.indirectDiffuse.mulAssign(on.rgb)}finish(e,t,r){const s=r.material,i=e.outgoingLight,n=r.context.environment;if(n)switch(s.combine){case Y:i.rgb.assign(la(i.rgb,i.rgb.mul(n.rgb),dd.mul(cd)));break;case X:i.rgb.assign(la(i.rgb,n.rgb,dd.mul(cd)));break;case K:i.rgb.addAssign(n.rgb.mul(dd.mul(cd)));break;default:console.warn("THREE.BasicLightingModel: Unsupported .combine value:",s.combine)}}}const Nh=new Q;class Sh extends Yc{static get type(){return"MeshBasicNodeMaterial"}constructor(e){super(),this.isMeshBasicNodeMaterial=!0,this.lights=!0,this.setDefaultValues(Nh),this.setValues(e)}setupNormal(){return ol}setupEnvironment(e){const t=super.setupEnvironment(e);return t?new bh(t):null}setupLightMap(e){let t=null;return e.material.lightMap&&(t=new Th(Vd)),t}setupOutgoingLight(){return on.rgb}setupLightingModel(){return new vh}}const Ah=_i((({f0:e,f90:t,dotVH:r})=>{const s=r.mul(-5.55473).sub(6.98316).mul(r).exp2();return e.mul(s.oneMinus()).add(t.mul(s))})),Rh=_i((e=>e.diffuseColor.mul(1/Math.PI))),Ch=_i((({dotNH:e})=>Nn.mul(Ci(.5)).add(1).mul(Ci(1/Math.PI)).mul(e.pow(Nn)))),Eh=_i((({lightDirection:e})=>{const t=e.add(Ju).normalize(),r=ul.dot(t).clamp(),s=Ju.dot(t).clamp(),i=Ah({f0:_n,f90:1,dotVH:s}),n=Ci(.25),o=Ch({dotNH:r});return i.mul(n).mul(o)}));class wh extends vh{constructor(e=!0){super(),this.specular=e}direct({lightDirection:e,lightColor:t,reflectedLight:r}){const s=ul.dot(e).clamp().mul(t);r.directDiffuse.addAssign(s.mul(Rh({diffuseColor:on.rgb}))),!0===this.specular&&r.directSpecular.addAssign(s.mul(Eh({lightDirection:e})).mul(dd))}indirect({ambientOcclusion:e,irradiance:t,reflectedLight:r}){r.indirectDiffuse.addAssign(t.mul(Rh({diffuseColor:on}))),r.indirectDiffuse.mulAssign(e)}}const Mh=new Z;class Bh extends Yc{static get type(){return"MeshLambertNodeMaterial"}constructor(e){super(),this.isMeshLambertNodeMaterial=!0,this.lights=!0,this.setDefaultValues(Mh),this.setValues(e)}setupEnvironment(e){const t=super.setupEnvironment(e);return t?new bh(t):null}setupLightingModel(){return new wh(!1)}}const Uh=new J;class Fh extends Yc{static get type(){return"MeshPhongNodeMaterial"}constructor(e){super(),this.isMeshPhongNodeMaterial=!0,this.lights=!0,this.shininessNode=null,this.specularNode=null,this.setDefaultValues(Uh),this.setValues(e)}setupEnvironment(e){const t=super.setupEnvironment(e);return t?new bh(t):null}setupLightingModel(){return new wh}setupVariants(){const e=(this.shininessNode?Ci(this.shininessNode):id).max(1e-4);Nn.assign(e);const t=this.specularNode||ad;_n.assign(t)}copy(e){return this.shininessNode=e.shininessNode,this.specularNode=e.specularNode,super.copy(e)}}const Ph=_i((e=>{if(!1===e.geometry.hasAttribute("normal"))return Ci(0);const t=ol.dFdx().abs().max(ol.dFdy().abs());return t.x.max(t.y).max(t.z)})),Ih=_i((e=>{const{roughness:t}=e,r=Ph();let s=t.max(.0525);return s=s.add(r),s=s.min(1),s})),Lh=_i((({alpha:e,dotNL:t,dotNV:r})=>{const s=e.pow2(),i=t.mul(s.add(s.oneMinus().mul(r.pow2())).sqrt()),n=r.mul(s.add(s.oneMinus().mul(t.pow2())).sqrt());return zn(.5,i.add(n).max(uo))})).setLayout({name:"V_GGX_SmithCorrelated",type:"float",inputs:[{name:"alpha",type:"float"},{name:"dotNL",type:"float"},{name:"dotNV",type:"float"}]}),Vh=_i((({alphaT:e,alphaB:t,dotTV:r,dotBV:s,dotTL:i,dotBL:n,dotNV:o,dotNL:a})=>{const u=a.mul(Ii(e.mul(r),t.mul(s),o).length()),l=o.mul(Ii(e.mul(i),t.mul(n),a).length());return zn(.5,u.add(l)).saturate()})).setLayout({name:"V_GGX_SmithCorrelated_Anisotropic",type:"float",inputs:[{name:"alphaT",type:"float",qualifier:"in"},{name:"alphaB",type:"float",qualifier:"in"},{name:"dotTV",type:"float",qualifier:"in"},{name:"dotBV",type:"float",qualifier:"in"},{name:"dotTL",type:"float",qualifier:"in"},{name:"dotBL",type:"float",qualifier:"in"},{name:"dotNV",type:"float",qualifier:"in"},{name:"dotNL",type:"float",qualifier:"in"}]}),Dh=_i((({alpha:e,dotNH:t})=>{const r=e.pow2(),s=t.pow2().mul(r.oneMinus()).oneMinus();return r.div(s.pow2()).mul(1/Math.PI)})).setLayout({name:"D_GGX",type:"float",inputs:[{name:"alpha",type:"float"},{name:"dotNH",type:"float"}]}),Oh=Ci(1/Math.PI),Gh=_i((({alphaT:e,alphaB:t,dotNH:r,dotTH:s,dotBH:i})=>{const n=e.mul(t),o=Ii(t.mul(s),e.mul(i),n.mul(r)),a=o.dot(o),u=n.div(a);return Oh.mul(n.mul(u.pow2()))})).setLayout({name:"D_GGX_Anisotropic",type:"float",inputs:[{name:"alphaT",type:"float",qualifier:"in"},{name:"alphaB",type:"float",qualifier:"in"},{name:"dotNH",type:"float",qualifier:"in"},{name:"dotTH",type:"float",qualifier:"in"},{name:"dotBH",type:"float",qualifier:"in"}]}),kh=_i((e=>{const{lightDirection:t,f0:r,f90:s,roughness:i,f:n,USE_IRIDESCENCE:o,USE_ANISOTROPY:a}=e,u=e.normalView||ul,l=i.pow2(),d=t.add(Ju).normalize(),c=u.dot(t).clamp(),h=u.dot(Ju).clamp(),p=u.dot(d).clamp(),g=Ju.dot(d).clamp();let m,f,y=Ah({f0:r,f90:s,dotVH:g});if(pi(o)&&(y=gn.mix(y,n)),pi(a)){const e=bn.dot(t),r=bn.dot(Ju),s=bn.dot(d),i=Tn.dot(t),n=Tn.dot(Ju),o=Tn.dot(d);m=Vh({alphaT:yn,alphaB:l,dotTV:r,dotBV:n,dotTL:e,dotBL:i,dotNV:h,dotNL:c}),f=Gh({alphaT:yn,alphaB:l,dotNH:p,dotTH:s,dotBH:o})}else m=Lh({alpha:l,dotNL:c,dotNV:h}),f=Dh({alpha:l,dotNH:p});return y.mul(m).mul(f)})),zh=_i((({roughness:e,dotNV:t})=>{const r=Oi(-1,-.0275,-.572,.022),s=Oi(1,.0425,1.04,-.04),i=e.mul(r).add(s),n=i.x.mul(i.x).min(t.mul(-9.28).exp2()).mul(i.x).add(i.y);return Bi(-1.04,1.04).mul(n).add(i.zw)})).setLayout({name:"DFGApprox",type:"vec2",inputs:[{name:"roughness",type:"float"},{name:"dotNV",type:"vec3"}]}),$h=_i((e=>{const{dotNV:t,specularColor:r,specularF90:s,roughness:i}=e,n=zh({dotNV:t,roughness:i});return r.mul(n.x).add(s.mul(n.y))})),Hh=_i((({f:e,f90:t,dotVH:r})=>{const s=r.oneMinus().saturate(),i=s.mul(s),n=s.mul(i,i).clamp(0,.9999);return e.sub(Ii(t).mul(n)).div(n.oneMinus())})).setLayout({name:"Schlick_to_F0",type:"vec3",inputs:[{name:"f",type:"vec3"},{name:"f90",type:"float"},{name:"dotVH",type:"float"}]}),Wh=_i((({roughness:e,dotNH:t})=>{const r=e.pow2(),s=Ci(1).div(r),i=t.pow2().oneMinus().max(.0078125);return Ci(2).add(s).mul(i.pow(s.mul(.5))).div(2*Math.PI)})).setLayout({name:"D_Charlie",type:"float",inputs:[{name:"roughness",type:"float"},{name:"dotNH",type:"float"}]}),jh=_i((({dotNV:e,dotNL:t})=>Ci(1).div(Ci(4).mul(t.add(e).sub(t.mul(e)))))).setLayout({name:"V_Neubelt",type:"float",inputs:[{name:"dotNV",type:"float"},{name:"dotNL",type:"float"}]}),qh=_i((({lightDirection:e})=>{const t=e.add(Ju).normalize(),r=ul.dot(e).clamp(),s=ul.dot(Ju).clamp(),i=ul.dot(t).clamp(),n=Wh({roughness:pn,dotNH:i}),o=jh({dotNV:s,dotNL:r});return hn.mul(n).mul(o)})),Kh=_i((({N:e,V:t,roughness:r})=>{const s=e.dot(t).saturate(),i=Bi(r,s.oneMinus().sqrt());return i.assign(i.mul(.984375).add(.0078125)),i})).setLayout({name:"LTC_Uv",type:"vec2",inputs:[{name:"N",type:"vec3"},{name:"V",type:"vec3"},{name:"roughness",type:"float"}]}),Xh=_i((({f:e})=>{const t=e.length();return Ko(t.mul(t).add(e.z).div(t.add(1)),0)})).setLayout({name:"LTC_ClippedSphereFormFactor",type:"float",inputs:[{name:"f",type:"vec3"}]}),Yh=_i((({v1:e,v2:t})=>{const r=e.dot(t),s=r.abs().toVar(),i=s.mul(.0145206).add(.4965155).mul(s).add(.8543985).toVar(),n=s.add(4.1616724).mul(s).add(3.417594).toVar(),o=i.div(n),a=r.greaterThan(0).select(o,Ko(r.mul(r).oneMinus(),1e-7).inverseSqrt().mul(.5).sub(o));return e.cross(t).mul(a)})).setLayout({name:"LTC_EdgeVectorFormFactor",type:"vec3",inputs:[{name:"v1",type:"vec3"},{name:"v2",type:"vec3"}]}),Qh=_i((({N:e,V:t,P:r,mInv:s,p0:i,p1:n,p2:o,p3:a})=>{const u=n.sub(i).toVar(),l=a.sub(i).toVar(),d=u.cross(l),c=Ii().toVar();return Si(d.dot(r.sub(i)).greaterThanEqual(0),(()=>{const u=t.sub(e.mul(t.dot(e))).normalize(),l=e.cross(u).negate(),d=s.mul(Hi(u,l,e).transpose()).toVar(),h=d.mul(i.sub(r)).normalize().toVar(),p=d.mul(n.sub(r)).normalize().toVar(),g=d.mul(o.sub(r)).normalize().toVar(),m=d.mul(a.sub(r)).normalize().toVar(),f=Ii(0).toVar();f.addAssign(Yh({v1:h,v2:p})),f.addAssign(Yh({v1:p,v2:g})),f.addAssign(Yh({v1:g,v2:m})),f.addAssign(Yh({v1:m,v2:h})),c.assign(Ii(Xh({f:f})))})),c})).setLayout({name:"LTC_Evaluate",type:"vec3",inputs:[{name:"N",type:"vec3"},{name:"V",type:"vec3"},{name:"P",type:"vec3"},{name:"mInv",type:"mat3"},{name:"p0",type:"vec3"},{name:"p1",type:"vec3"},{name:"p2",type:"vec3"},{name:"p3",type:"vec3"}]}),Zh=1/6,Jh=e=>kn(Zh,kn(e,kn(e,e.negate().add(3)).sub(3)).add(1)),ep=e=>kn(Zh,kn(e,kn(e,kn(3,e).sub(6))).add(4)),tp=e=>kn(Zh,kn(e,kn(e,kn(-3,e).add(3)).add(3)).add(1)),rp=e=>kn(Zh,ra(e,3)),sp=e=>Jh(e).add(ep(e)),ip=e=>tp(e).add(rp(e)),np=e=>On(-1,ep(e).div(Jh(e).add(ep(e)))),op=e=>On(1,rp(e).div(tp(e).add(rp(e)))),ap=(e,t,r)=>{const s=e.uvNode,i=kn(s,t.zw).add(.5),n=No(i),o=Ro(i),a=sp(o.x),u=ip(o.x),l=np(o.x),d=op(o.x),c=np(o.y),h=op(o.y),p=Bi(n.x.add(l),n.y.add(c)).sub(.5).mul(t.xy),g=Bi(n.x.add(d),n.y.add(c)).sub(.5).mul(t.xy),m=Bi(n.x.add(l),n.y.add(h)).sub(.5).mul(t.xy),f=Bi(n.x.add(d),n.y.add(h)).sub(.5).mul(t.xy),y=sp(o.y).mul(On(a.mul(e.sample(p).level(r)),u.mul(e.sample(g).level(r)))),x=ip(o.y).mul(On(a.mul(e.sample(m).level(r)),u.mul(e.sample(f).level(r))));return y.add(x)},up=_i((([e,t=Ci(3)])=>{const r=Bi(e.size(Ei(t))),s=Bi(e.size(Ei(t.add(1)))),i=zn(1,r),n=zn(1,s),o=ap(e,Oi(i,r),No(t)),a=ap(e,Oi(n,s),So(t));return Ro(t).mix(o,a)})),lp=_i((([e,t,r,s,i])=>{const n=Ii(ha(t.negate(),Ao(e),zn(1,s))),o=Ii(Io(i[0].xyz),Io(i[1].xyz),Io(i[2].xyz));return Ao(n).mul(r.mul(o))})).setLayout({name:"getVolumeTransmissionRay",type:"vec3",inputs:[{name:"n",type:"vec3"},{name:"v",type:"vec3"},{name:"thickness",type:"float"},{name:"ior",type:"float"},{name:"modelMatrix",type:"mat4"}]}),dp=_i((([e,t])=>e.mul(da(t.mul(2).sub(2),0,1)))).setLayout({name:"applyIorToRoughness",type:"float",inputs:[{name:"roughness",type:"float"},{name:"ior",type:"float"}]}),cp=Uc(),hp=Uc(),pp=_i((([e,t,r],{material:s})=>{const i=(s.side===T?cp:hp).sample(e),n=To(Tc.x).mul(dp(t,r));return up(i,n)})),gp=_i((([e,t,r])=>(Si(r.notEqual(0),(()=>{const s=bo(t).negate().div(r);return yo(s.negate().mul(e))})),Ii(1)))).setLayout({name:"volumeAttenuation",type:"vec3",inputs:[{name:"transmissionDistance",type:"float"},{name:"attenuationColor",type:"vec3"},{name:"attenuationDistance",type:"float"}]}),mp=_i((([e,t,r,s,i,n,o,a,u,l,d,c,h,p,g])=>{let m,f;if(g){m=Oi().toVar(),f=Ii().toVar();const i=d.sub(1).mul(g.mul(.025)),n=Ii(d.sub(i),d,d.add(i));ic({start:0,end:3},(({i:i})=>{const d=n.element(i),g=lp(e,t,c,d,a),y=o.add(g),x=l.mul(u.mul(Oi(y,1))),b=Bi(x.xy.div(x.w)).toVar();b.addAssign(1),b.divAssign(2),b.assign(Bi(b.x,b.y.oneMinus()));const T=pp(b,r,d);m.element(i).assign(T.element(i)),m.a.addAssign(T.a),f.element(i).assign(s.element(i).mul(gp(Io(g),h,p).element(i)))})),m.a.divAssign(3)}else{const i=lp(e,t,c,d,a),n=o.add(i),g=l.mul(u.mul(Oi(n,1))),y=Bi(g.xy.div(g.w)).toVar();y.addAssign(1),y.divAssign(2),y.assign(Bi(y.x,y.y.oneMinus())),m=pp(y,r,d),f=s.mul(gp(Io(i),h,p))}const y=f.rgb.mul(m.rgb),x=e.dot(t).clamp(),b=Ii($h({dotNV:x,specularColor:i,specularF90:n,roughness:r})),T=f.r.add(f.g,f.b).div(3);return Oi(b.oneMinus().mul(y),m.a.oneMinus().mul(T).oneMinus())})),fp=Hi(3.2404542,-.969266,.0556434,-1.5371385,1.8760108,-.2040259,-.4985314,.041556,1.0572252),yp=(e,t)=>e.sub(t).div(e.add(t)).pow2(),xp=_i((({outsideIOR:e,eta2:t,cosTheta1:r,thinFilmThickness:s,baseF0:i})=>{const n=la(e,t,pa(0,.03,s)),o=e.div(n).pow2().mul(r.pow2().oneMinus()).oneMinus();Si(o.lessThan(0),(()=>Ii(1)));const a=o.sqrt(),u=yp(n,e),l=Ah({f0:u,f90:1,dotVH:r}),d=l.oneMinus(),c=n.lessThan(e).select(Math.PI,0),h=Ci(Math.PI).sub(c),p=(e=>{const t=e.sqrt();return Ii(1).add(t).div(Ii(1).sub(t))})(i.clamp(0,.9999)),g=yp(p,n.toVec3()),m=Ah({f0:g,f90:1,dotVH:a}),f=Ii(p.x.lessThan(n).select(Math.PI,0),p.y.lessThan(n).select(Math.PI,0),p.z.lessThan(n).select(Math.PI,0)),y=n.mul(s,a,2),x=Ii(h).add(f),b=l.mul(m).clamp(1e-5,.9999),T=b.sqrt(),_=d.pow2().mul(m).div(Ii(1).sub(b)),v=l.add(_).toVar(),N=_.sub(d).toVar();return ic({start:1,end:2,condition:"<=",name:"m"},(({m:e})=>{N.mulAssign(T);const t=((e,t)=>{const r=e.mul(2*Math.PI*1e-9),s=Ii(54856e-17,44201e-17,52481e-17),i=Ii(1681e3,1795300,2208400),n=Ii(43278e5,93046e5,66121e5),o=Ci(9747e-17*Math.sqrt(2*Math.PI*45282e5)).mul(r.mul(2239900).add(t.x).cos()).mul(r.pow2().mul(-45282e5).exp());let a=s.mul(n.mul(2*Math.PI).sqrt()).mul(i.mul(r).add(t).cos()).mul(r.pow2().negate().mul(n).exp());return a=Ii(a.x.add(o),a.y,a.z).div(1.0685e-7),fp.mul(a)})(Ci(e).mul(y),Ci(e).mul(x)).mul(2);v.addAssign(N.mul(t))})),v.max(Ii(0))})).setLayout({name:"evalIridescence",type:"vec3",inputs:[{name:"outsideIOR",type:"float"},{name:"eta2",type:"float"},{name:"cosTheta1",type:"float"},{name:"thinFilmThickness",type:"float"},{name:"baseF0",type:"vec3"}]}),bp=_i((({normal:e,viewDir:t,roughness:r})=>{const s=e.dot(t).saturate(),i=r.pow2(),n=Ta(r.lessThan(.25),Ci(-339.2).mul(i).add(Ci(161.4).mul(r)).sub(25.9),Ci(-8.48).mul(i).add(Ci(14.3).mul(r)).sub(9.95)),o=Ta(r.lessThan(.25),Ci(44).mul(i).sub(Ci(23.7).mul(r)).add(3.26),Ci(1.97).mul(i).sub(Ci(3.27).mul(r)).add(.72));return Ta(r.lessThan(.25),0,Ci(.1).mul(r).sub(.025)).add(n.mul(s).add(o).exp()).mul(1/Math.PI).saturate()})),Tp=Ii(.04),_p=Ci(1);class vp extends _h{constructor(e=!1,t=!1,r=!1,s=!1,i=!1,n=!1){super(),this.clearcoat=e,this.sheen=t,this.iridescence=r,this.anisotropy=s,this.transmission=i,this.dispersion=n,this.clearcoatRadiance=null,this.clearcoatSpecularDirect=null,this.clearcoatSpecularIndirect=null,this.sheenSpecularDirect=null,this.sheenSpecularIndirect=null,this.iridescenceFresnel=null,this.iridescenceF0=null}start(e){if(!0===this.clearcoat&&(this.clearcoatRadiance=Ii().toVar("clearcoatRadiance"),this.clearcoatSpecularDirect=Ii().toVar("clearcoatSpecularDirect"),this.clearcoatSpecularIndirect=Ii().toVar("clearcoatSpecularIndirect")),!0===this.sheen&&(this.sheenSpecularDirect=Ii().toVar("sheenSpecularDirect"),this.sheenSpecularIndirect=Ii().toVar("sheenSpecularIndirect")),!0===this.iridescence){const e=ul.dot(Ju).clamp();this.iridescenceFresnel=xp({outsideIOR:Ci(1),eta2:mn,cosTheta1:e,thinFilmThickness:fn,baseF0:_n}),this.iridescenceF0=Hh({f:this.iridescenceFresnel,f90:1,dotVH:e})}if(!0===this.transmission){const t=Yu,r=Eu.sub(Yu).normalize(),s=ll;e.backdrop=mp(s,r,un,on,_n,vn,t,Vu,Au,Nu,En,Mn,Un,Bn,this.dispersion?Fn:null),e.backdropAlpha=wn,on.a.mulAssign(la(1,e.backdrop.a,wn))}}computeMultiscattering(e,t,r){const s=ul.dot(Ju).clamp(),i=zh({roughness:un,dotNV:s}),n=(this.iridescenceF0?gn.mix(_n,this.iridescenceF0):_n).mul(i.x).add(r.mul(i.y)),o=i.x.add(i.y).oneMinus(),a=_n.add(_n.oneMinus().mul(.047619)),u=n.mul(a).div(o.mul(a).oneMinus());e.addAssign(n),t.addAssign(u.mul(o))}direct({lightDirection:e,lightColor:t,reflectedLight:r}){const s=ul.dot(e).clamp().mul(t);if(!0===this.sheen&&this.sheenSpecularDirect.addAssign(s.mul(qh({lightDirection:e}))),!0===this.clearcoat){const r=dl.dot(e).clamp().mul(t);this.clearcoatSpecularDirect.addAssign(r.mul(kh({lightDirection:e,f0:Tp,f90:_p,roughness:cn,normalView:dl})))}r.directDiffuse.addAssign(s.mul(Rh({diffuseColor:on.rgb}))),r.directSpecular.addAssign(s.mul(kh({lightDirection:e,f0:_n,f90:1,roughness:un,iridescence:this.iridescence,f:this.iridescenceFresnel,USE_IRIDESCENCE:this.iridescence,USE_ANISOTROPY:this.anisotropy})))}directRectArea({lightColor:e,lightPosition:t,halfWidth:r,halfHeight:s,reflectedLight:i,ltc_1:n,ltc_2:o}){const a=t.add(r).sub(s),u=t.sub(r).sub(s),l=t.sub(r).add(s),d=t.add(r).add(s),c=ul,h=Ju,p=Zu.toVar(),g=Kh({N:c,V:h,roughness:un}),m=n.sample(g).toVar(),f=o.sample(g).toVar(),y=Hi(Ii(m.x,0,m.y),Ii(0,1,0),Ii(m.z,0,m.w)).toVar(),x=_n.mul(f.x).add(_n.oneMinus().mul(f.y)).toVar();i.directSpecular.addAssign(e.mul(x).mul(Qh({N:c,V:h,P:p,mInv:y,p0:a,p1:u,p2:l,p3:d}))),i.directDiffuse.addAssign(e.mul(on).mul(Qh({N:c,V:h,P:p,mInv:Hi(1,0,0,0,1,0,0,0,1),p0:a,p1:u,p2:l,p3:d})))}indirect(e,t,r){this.indirectDiffuse(e,t,r),this.indirectSpecular(e,t,r),this.ambientOcclusion(e,t,r)}indirectDiffuse({irradiance:e,reflectedLight:t}){t.indirectDiffuse.addAssign(e.mul(Rh({diffuseColor:on})))}indirectSpecular({radiance:e,iblIrradiance:t,reflectedLight:r}){if(!0===this.sheen&&this.sheenSpecularIndirect.addAssign(t.mul(hn,bp({normal:ul,viewDir:Ju,roughness:pn}))),!0===this.clearcoat){const e=dl.dot(Ju).clamp(),t=$h({dotNV:e,specularColor:Tp,specularF90:_p,roughness:cn});this.clearcoatSpecularIndirect.addAssign(this.clearcoatRadiance.mul(t))}const s=Ii().toVar("singleScattering"),i=Ii().toVar("multiScattering"),n=t.mul(1/Math.PI);this.computeMultiscattering(s,i,vn);const o=s.add(i),a=on.mul(o.r.max(o.g).max(o.b).oneMinus());r.indirectSpecular.addAssign(e.mul(s)),r.indirectSpecular.addAssign(i.mul(n)),r.indirectDiffuse.addAssign(a.mul(n))}ambientOcclusion({ambientOcclusion:e,reflectedLight:t}){const r=ul.dot(Ju).clamp().add(e),s=un.mul(-16).oneMinus().negate().exp2(),i=e.sub(r.pow(s).oneMinus()).clamp();!0===this.clearcoat&&this.clearcoatSpecularIndirect.mulAssign(e),!0===this.sheen&&this.sheenSpecularIndirect.mulAssign(e),t.indirectDiffuse.mulAssign(e),t.indirectSpecular.mulAssign(i)}finish(e){const{outgoingLight:t}=e;if(!0===this.clearcoat){const e=dl.dot(Ju).clamp(),r=Ah({dotVH:e,f0:Tp,f90:_p}),s=t.mul(dn.mul(r).oneMinus()).add(this.clearcoatSpecularDirect.add(this.clearcoatSpecularIndirect).mul(dn));t.assign(s)}if(!0===this.sheen){const e=hn.r.max(hn.g).max(hn.b).mul(.157).oneMinus(),r=t.mul(e).add(this.sheenSpecularDirect,this.sheenSpecularIndirect);t.assign(r)}}}const Np=Ci(1),Sp=Ci(-2),Ap=Ci(.8),Rp=Ci(-1),Cp=Ci(.4),Ep=Ci(2),wp=Ci(.305),Mp=Ci(3),Bp=Ci(.21),Up=Ci(4),Fp=Ci(4),Pp=Ci(16),Ip=_i((([e])=>{const t=Ii(Fo(e)).toVar(),r=Ci(-1).toVar();return Si(t.x.greaterThan(t.z),(()=>{Si(t.x.greaterThan(t.y),(()=>{r.assign(Ta(e.x.greaterThan(0),0,3))})).Else((()=>{r.assign(Ta(e.y.greaterThan(0),1,4))}))})).Else((()=>{Si(t.z.greaterThan(t.y),(()=>{r.assign(Ta(e.z.greaterThan(0),2,5))})).Else((()=>{r.assign(Ta(e.y.greaterThan(0),1,4))}))})),r})).setLayout({name:"getFace",type:"float",inputs:[{name:"direction",type:"vec3"}]}),Lp=_i((([e,t])=>{const r=Bi().toVar();return Si(t.equal(0),(()=>{r.assign(Bi(e.z,e.y).div(Fo(e.x)))})).ElseIf(t.equal(1),(()=>{r.assign(Bi(e.x.negate(),e.z.negate()).div(Fo(e.y)))})).ElseIf(t.equal(2),(()=>{r.assign(Bi(e.x.negate(),e.y).div(Fo(e.z)))})).ElseIf(t.equal(3),(()=>{r.assign(Bi(e.z.negate(),e.y).div(Fo(e.x)))})).ElseIf(t.equal(4),(()=>{r.assign(Bi(e.x.negate(),e.z).div(Fo(e.y)))})).Else((()=>{r.assign(Bi(e.x,e.y).div(Fo(e.z)))})),kn(.5,r.add(1))})).setLayout({name:"getUV",type:"vec2",inputs:[{name:"direction",type:"vec3"},{name:"face",type:"float"}]}),Vp=_i((([e])=>{const t=Ci(0).toVar();return Si(e.greaterThanEqual(Ap),(()=>{t.assign(Np.sub(e).mul(Rp.sub(Sp)).div(Np.sub(Ap)).add(Sp))})).ElseIf(e.greaterThanEqual(Cp),(()=>{t.assign(Ap.sub(e).mul(Ep.sub(Rp)).div(Ap.sub(Cp)).add(Rp))})).ElseIf(e.greaterThanEqual(wp),(()=>{t.assign(Cp.sub(e).mul(Mp.sub(Ep)).div(Cp.sub(wp)).add(Ep))})).ElseIf(e.greaterThanEqual(Bp),(()=>{t.assign(wp.sub(e).mul(Up.sub(Mp)).div(wp.sub(Bp)).add(Mp))})).Else((()=>{t.assign(Ci(-2).mul(To(kn(1.16,e))))})),t})).setLayout({name:"roughnessToMip",type:"float",inputs:[{name:"roughness",type:"float"}]}),Dp=_i((([e,t])=>{const r=e.toVar();r.assign(kn(2,r).sub(1));const s=Ii(r,1).toVar();return Si(t.equal(0),(()=>{s.assign(s.zyx)})).ElseIf(t.equal(1),(()=>{s.assign(s.xzy),s.xz.mulAssign(-1)})).ElseIf(t.equal(2),(()=>{s.x.mulAssign(-1)})).ElseIf(t.equal(3),(()=>{s.assign(s.zyx),s.xz.mulAssign(-1)})).ElseIf(t.equal(4),(()=>{s.assign(s.xzy),s.xy.mulAssign(-1)})).ElseIf(t.equal(5),(()=>{s.z.mulAssign(-1)})),s})).setLayout({name:"getDirection",type:"vec3",inputs:[{name:"uv",type:"vec2"},{name:"face",type:"float"}]}),Op=_i((([e,t,r,s,i,n])=>{const o=Ci(r),a=Ii(t),u=da(Vp(o),Sp,n),l=Ro(u),d=No(u),c=Ii(Gp(e,a,d,s,i,n)).toVar();return Si(l.notEqual(0),(()=>{const t=Ii(Gp(e,a,d.add(1),s,i,n)).toVar();c.assign(la(c,t,l))})),c})),Gp=_i((([e,t,r,s,i,n])=>{const o=Ci(r).toVar(),a=Ii(t),u=Ci(Ip(a)).toVar(),l=Ci(Ko(Fp.sub(o),0)).toVar();o.assign(Ko(o,Fp));const d=Ci(xo(o)).toVar(),c=Bi(Lp(a,u).mul(d.sub(2)).add(1)).toVar();return Si(u.greaterThan(2),(()=>{c.y.addAssign(d),u.subAssign(3)})),c.x.addAssign(u.mul(d)),c.x.addAssign(l.mul(kn(3,Pp))),c.y.addAssign(kn(4,xo(n).sub(d))),c.x.mulAssign(s),c.y.mulAssign(i),e.sample(c).grad(Bi(),Bi())})),kp=_i((({envMap:e,mipInt:t,outputDirection:r,theta:s,axis:i,CUBEUV_TEXEL_WIDTH:n,CUBEUV_TEXEL_HEIGHT:o,CUBEUV_MAX_MIP:a})=>{const u=Eo(s),l=r.mul(u).add(i.cross(r).mul(Co(s))).add(i.mul(i.dot(r).mul(u.oneMinus())));return Gp(e,l,t,n,o,a)})),zp=_i((({n:e,latitudinal:t,poleAxis:r,outputDirection:s,weights:i,samples:n,dTheta:o,mipInt:a,envMap:u,CUBEUV_TEXEL_WIDTH:l,CUBEUV_TEXEL_HEIGHT:d,CUBEUV_MAX_MIP:c})=>{const h=Ii(Ta(t,r,ta(r,s))).toVar();Si(po(h.equals(Ii(0))),(()=>{h.assign(Ii(s.z,0,s.x.negate()))})),h.assign(Ao(h));const p=Ii().toVar();return p.addAssign(i.element(Ei(0)).mul(kp({theta:0,axis:h,outputDirection:s,mipInt:a,envMap:u,CUBEUV_TEXEL_WIDTH:l,CUBEUV_TEXEL_HEIGHT:d,CUBEUV_MAX_MIP:c}))),ic({start:Ei(1),end:e},(({i:e})=>{Si(e.greaterThanEqual(n),(()=>{nc()}));const t=Ci(o.mul(Ci(e))).toVar();p.addAssign(i.element(e).mul(kp({theta:t.mul(-1),axis:h,outputDirection:s,mipInt:a,envMap:u,CUBEUV_TEXEL_WIDTH:l,CUBEUV_TEXEL_HEIGHT:d,CUBEUV_MAX_MIP:c}))),p.addAssign(i.element(e).mul(kp({theta:t,axis:h,outputDirection:s,mipInt:a,envMap:u,CUBEUV_TEXEL_WIDTH:l,CUBEUV_TEXEL_HEIGHT:d,CUBEUV_MAX_MIP:c})))})),Oi(p,1)}));let $p=null;const Hp=new WeakMap;function Wp(e){let t=Hp.get(e);if((void 0!==t?t.pmremVersion:-1)!==e.pmremVersion){const r=e.image;if(e.isCubeTexture){if(!function(e){if(null==e)return!1;let t=0;const r=6;for(let s=0;s0}(r))return null;t=$p.fromEquirectangular(e,t)}t.pmremVersion=e.pmremVersion,Hp.set(e,t)}return t.texture}class jp extends Fs{static get type(){return"PMREMNode"}constructor(e,t=null,r=null){super("vec3"),this._value=e,this._pmrem=null,this.uvNode=t,this.levelNode=r,this._generator=null;const s=new ee;s.isRenderTargetTexture=!0,this._texture=bu(s),this._width=tn(0),this._height=tn(0),this._maxMip=tn(0),this.updateBeforeType=vs.RENDER}set value(e){this._value=e,this._pmrem=null}get value(){return this._value}updateFromTexture(e){const t=function(e){const t=Math.log2(e)-2,r=1/e;return{texelWidth:1/(3*Math.max(Math.pow(2,t),112)),texelHeight:r,maxMip:t}}(e.image.height);this._texture.value=e,this._width.value=t.texelWidth,this._height.value=t.texelHeight,this._maxMip.value=t.maxMip}updateBefore(){let e=this._pmrem;const t=e?e.pmremVersion:-1,r=this._value;t!==r.pmremVersion&&(e=!0===r.isPMREMTexture?r:Wp(r),null!==e&&(this._pmrem=e,this.updateFromTexture(e)))}setup(e){null===$p&&($p=e.createPMREMGenerator()),this.updateBefore(e);let t=this.uvNode;null===t&&e.context.getUV&&(t=e.context.getUV(this));const r=this.value;e.renderer.coordinateSystem===u&&!0!==r.isPMREMTexture&&!0===r.isRenderTargetTexture&&(t=Ii(t.x.negate(),t.yz)),t=Ii(t.x,t.y.negate(),t.z);let s=this.levelNode;return null===s&&e.context.getTextureLevel&&(s=e.context.getTextureLevel(this)),Op(this._texture,t,s,this._width,this._height,this._maxMip)}}const qp=bi(jp),Kp=new WeakMap;class Xp extends cc{static get type(){return"EnvironmentNode"}constructor(e=null){super(),this.envNode=e}setup(e){const{material:t}=e;let r=this.envNode;if(r.isTextureNode||r.isMaterialReferenceNode){const e=r.isTextureNode?r.value:t[r.property];let s=Kp.get(e);void 0===s&&(s=qp(e),Kp.set(e,s)),r=s}const s=t.envMap?Cl("envMapIntensity","float",e.material):Cl("environmentIntensity","float",e.scene),i=!0===t.useAnisotropy||t.anisotropy>0?jl:ul,n=r.context(Yp(un,i)).mul(s),o=r.context(Qp(ll)).mul(Math.PI).mul(s),a=eu(n),u=eu(o);e.context.radiance.addAssign(a),e.context.iblIrradiance.addAssign(u);const l=e.context.lightingModel.clearcoatRadiance;if(l){const e=r.context(Yp(cn,dl)).mul(s),t=eu(e);l.addAssign(t)}}}const Yp=(e,t)=>{let r=null;return{getUV:()=>(null===r&&(r=Ju.negate().reflect(t),r=e.mul(e).mix(r,t).normalize(),r=r.transformDirection(Au)),r),getTextureLevel:()=>e}},Qp=e=>({getUV:()=>e,getTextureLevel:()=>Ci(1)}),Zp=new te;class Jp extends Yc{static get type(){return"MeshStandardNodeMaterial"}constructor(e){super(),this.isMeshStandardNodeMaterial=!0,this.lights=!0,this.emissiveNode=null,this.metalnessNode=null,this.roughnessNode=null,this.setDefaultValues(Zp),this.setValues(e)}setupEnvironment(e){let t=super.setupEnvironment(e);return null===t&&e.environmentNode&&(t=e.environmentNode),t?new Xp(t):null}setupLightingModel(){return new vp}setupSpecular(){const e=la(Ii(.04),on.rgb,ln);_n.assign(e),vn.assign(1)}setupVariants(){const e=this.metalnessNode?Ci(this.metalnessNode):pd;ln.assign(e);let t=this.roughnessNode?Ci(this.roughnessNode):hd;t=Ih({roughness:t}),un.assign(t),this.setupSpecular(),on.assign(Oi(on.rgb.mul(e.oneMinus()),on.a))}copy(e){return this.emissiveNode=e.emissiveNode,this.metalnessNode=e.metalnessNode,this.roughnessNode=e.roughnessNode,super.copy(e)}}const eg=new re;class tg extends Jp{static get type(){return"MeshPhysicalNodeMaterial"}constructor(e){super(),this.isMeshPhysicalNodeMaterial=!0,this.clearcoatNode=null,this.clearcoatRoughnessNode=null,this.clearcoatNormalNode=null,this.sheenNode=null,this.sheenRoughnessNode=null,this.iridescenceNode=null,this.iridescenceIORNode=null,this.iridescenceThicknessNode=null,this.specularIntensityNode=null,this.specularColorNode=null,this.iorNode=null,this.transmissionNode=null,this.thicknessNode=null,this.attenuationDistanceNode=null,this.attenuationColorNode=null,this.dispersionNode=null,this.anisotropyNode=null,this.setDefaultValues(eg),this.setValues(e)}get useClearcoat(){return this.clearcoat>0||null!==this.clearcoatNode}get useIridescence(){return this.iridescence>0||null!==this.iridescenceNode}get useSheen(){return this.sheen>0||null!==this.sheenNode}get useAnisotropy(){return this.anisotropy>0||null!==this.anisotropyNode}get useTransmission(){return this.transmission>0||null!==this.transmissionNode}get useDispersion(){return this.dispersion>0||null!==this.dispersionNode}setupSpecular(){const e=this.iorNode?Ci(this.iorNode):Cd;En.assign(e),_n.assign(la(qo(sa(En.sub(1).div(En.add(1))).mul(ld),Ii(1)).mul(ud),on.rgb,ln)),vn.assign(la(ud,1,ln))}setupLightingModel(){return new vp(this.useClearcoat,this.useSheen,this.useIridescence,this.useAnisotropy,this.useTransmission,this.useDispersion)}setupVariants(e){if(super.setupVariants(e),this.useClearcoat){const e=this.clearcoatNode?Ci(this.clearcoatNode):md,t=this.clearcoatRoughnessNode?Ci(this.clearcoatRoughnessNode):fd;dn.assign(e),cn.assign(Ih({roughness:t}))}if(this.useSheen){const e=this.sheenNode?Ii(this.sheenNode):bd,t=this.sheenRoughnessNode?Ci(this.sheenRoughnessNode):Td;hn.assign(e),pn.assign(t)}if(this.useIridescence){const e=this.iridescenceNode?Ci(this.iridescenceNode):vd,t=this.iridescenceIORNode?Ci(this.iridescenceIORNode):Nd,r=this.iridescenceThicknessNode?Ci(this.iridescenceThicknessNode):Sd;gn.assign(e),mn.assign(t),fn.assign(r)}if(this.useAnisotropy){const e=(this.anisotropyNode?Bi(this.anisotropyNode):_d).toVar();xn.assign(e.length()),Si(xn.equal(0),(()=>{e.assign(Bi(1,0))})).Else((()=>{e.divAssign(Bi(xn)),xn.assign(xn.saturate())})),yn.assign(xn.pow2().mix(un.pow2(),1)),bn.assign(Hl[0].mul(e.x).add(Hl[1].mul(e.y))),Tn.assign(Hl[1].mul(e.x).sub(Hl[0].mul(e.y)))}if(this.useTransmission){const e=this.transmissionNode?Ci(this.transmissionNode):Ad,t=this.thicknessNode?Ci(this.thicknessNode):Rd,r=this.attenuationDistanceNode?Ci(this.attenuationDistanceNode):Ed,s=this.attenuationColorNode?Ii(this.attenuationColorNode):wd;if(wn.assign(e),Mn.assign(t),Bn.assign(r),Un.assign(s),this.useDispersion){const e=this.dispersionNode?Ci(this.dispersionNode):Ld;Fn.assign(e)}}}setupClearcoatNormal(){return this.clearcoatNormalNode?Ii(this.clearcoatNormalNode):yd}setup(e){e.context.setupClearcoatNormal=()=>this.setupClearcoatNormal(e),super.setup(e)}copy(e){return this.clearcoatNode=e.clearcoatNode,this.clearcoatRoughnessNode=e.clearcoatRoughnessNode,this.clearcoatNormalNode=e.clearcoatNormalNode,this.sheenNode=e.sheenNode,this.sheenRoughnessNode=e.sheenRoughnessNode,this.iridescenceNode=e.iridescenceNode,this.iridescenceIORNode=e.iridescenceIORNode,this.iridescenceThicknessNode=e.iridescenceThicknessNode,this.specularIntensityNode=e.specularIntensityNode,this.specularColorNode=e.specularColorNode,this.transmissionNode=e.transmissionNode,this.thicknessNode=e.thicknessNode,this.attenuationDistanceNode=e.attenuationDistanceNode,this.attenuationColorNode=e.attenuationColorNode,this.dispersionNode=e.dispersionNode,this.anisotropyNode=e.anisotropyNode,super.copy(e)}}class rg extends vp{constructor(e,t,r,s){super(e,t,r),this.useSSS=s}direct({lightDirection:e,lightColor:t,reflectedLight:r},s,i){if(!0===this.useSSS){const s=i.material,{thicknessColorNode:n,thicknessDistortionNode:o,thicknessAmbientNode:a,thicknessAttenuationNode:u,thicknessPowerNode:l,thicknessScaleNode:d}=s,c=e.add(ul.mul(o)).normalize(),h=Ci(Ju.dot(c.negate()).saturate().pow(l).mul(d)),p=Ii(h.add(a).mul(n));r.directDiffuse.addAssign(p.mul(u.mul(t)))}super.direct({lightDirection:e,lightColor:t,reflectedLight:r},s,i)}}class sg extends tg{static get type(){return"MeshSSSNodeMaterial"}constructor(e){super(e),this.thicknessColorNode=null,this.thicknessDistortionNode=Ci(.1),this.thicknessAmbientNode=Ci(0),this.thicknessAttenuationNode=Ci(.1),this.thicknessPowerNode=Ci(2),this.thicknessScaleNode=Ci(10)}get useSSS(){return null!==this.thicknessColorNode}setupLightingModel(){return new rg(this.useClearcoat,this.useSheen,this.useIridescence,this.useSSS)}copy(e){return this.thicknessColorNode=e.thicknessColorNode,this.thicknessDistortionNode=e.thicknessDistortionNode,this.thicknessAmbientNode=e.thicknessAmbientNode,this.thicknessAttenuationNode=e.thicknessAttenuationNode,this.thicknessPowerNode=e.thicknessPowerNode,this.thicknessScaleNode=e.thicknessScaleNode,super.copy(e)}}const ig=_i((({normal:e,lightDirection:t,builder:r})=>{const s=e.dot(t),i=Bi(s.mul(.5).add(.5),0);if(r.material.gradientMap){const e=Ml("gradientMap","texture").context({getUV:()=>i});return Ii(e.r)}{const e=i.fwidth().mul(.5);return la(Ii(.7),Ii(1),pa(Ci(.7).sub(e.x),Ci(.7).add(e.x),i.x))}}));class ng extends _h{direct({lightDirection:e,lightColor:t,reflectedLight:r},s,i){const n=ig({normal:sl,lightDirection:e,builder:i}).mul(t);r.directDiffuse.addAssign(n.mul(Rh({diffuseColor:on.rgb})))}indirect({ambientOcclusion:e,irradiance:t,reflectedLight:r}){r.indirectDiffuse.addAssign(t.mul(Rh({diffuseColor:on}))),r.indirectDiffuse.mulAssign(e)}}const og=new se;class ag extends Yc{static get type(){return"MeshToonNodeMaterial"}constructor(e){super(),this.isMeshToonNodeMaterial=!0,this.lights=!0,this.setDefaultValues(og),this.setValues(e)}setupLightingModel(){return new ng}}class ug extends Fs{static get type(){return"MatcapUVNode"}constructor(){super("vec2")}setup(){const e=Ii(Ju.z,0,Ju.x.negate()).normalize(),t=Ju.cross(e);return Bi(e.dot(ul),t.dot(ul)).mul(.495).add(.5)}}const lg=Ti(ug),dg=new ie;class cg extends Yc{static get type(){return"MeshMatcapNodeMaterial"}constructor(e){super(),this.lights=!1,this.isMeshMatcapNodeMaterial=!0,this.setDefaultValues(dg),this.setValues(e)}setupVariants(e){const t=lg;let r;r=e.material.matcap?Ml("matcap","texture").context({getUV:()=>t}):Ii(la(.2,.8,t.y)),on.rgb.mulAssign(r.rgb)}}const hg=new P;class pg extends Yc{static get type(){return"PointsNodeMaterial"}constructor(e){super(),this.isPointsNodeMaterial=!0,this.lights=!1,this.transparent=!0,this.sizeNode=null,this.setDefaultValues(hg),this.setValues(e)}copy(e){return this.sizeNode=e.sizeNode,super.copy(e)}}class gg extends Fs{static get type(){return"RotateNode"}constructor(e,t){super(),this.positionNode=e,this.rotationNode=t}getNodeType(e){return this.positionNode.getNodeType(e)}setup(e){const{rotationNode:t,positionNode:r}=this;if("vec2"===this.getNodeType(e)){const e=t.cos(),s=t.sin();return $i(e,s,s.negate(),e).mul(r)}{const e=t,s=Wi(Oi(1,0,0,0),Oi(0,Eo(e.x),Co(e.x).negate(),0),Oi(0,Co(e.x),Eo(e.x),0),Oi(0,0,0,1)),i=Wi(Oi(Eo(e.y),0,Co(e.y),0),Oi(0,1,0,0),Oi(Co(e.y).negate(),0,Eo(e.y),0),Oi(0,0,0,1)),n=Wi(Oi(Eo(e.z),Co(e.z).negate(),0,0),Oi(Co(e.z),Eo(e.z),0,0),Oi(0,0,1,0),Oi(0,0,0,1));return s.mul(i).mul(n).mul(Oi(r,1)).xyz}}}const mg=bi(gg),fg=new ne;class yg extends Yc{static get type(){return"SpriteNodeMaterial"}constructor(e){super(),this.isSpriteNodeMaterial=!0,this.lights=!1,this._useSizeAttenuation=!0,this.positionNode=null,this.rotationNode=null,this.scaleNode=null,this.setDefaultValues(fg),this.setValues(e)}setupPositionView(e){const{object:t,camera:r}=e,s=this.sizeAttenuation,{positionNode:i,rotationNode:n,scaleNode:o}=this,a=$u.mul(Ii(i||0));let u=Bi(Vu[0].xyz.length(),Vu[1].xyz.length());if(null!==o&&(u=u.mul(o)),!s)if(r.isPerspectiveCamera)u=u.mul(a.z.negate());else{const e=Ci(2).div(Nu.element(1).element(1));u=u.mul(e.mul(2))}let l=qu.xy;if(t.center&&!0===t.center.isVector2){const e=((e,t,r)=>fi(new Ga(e,t,r)))("center","vec2");l=l.sub(e.sub(.5))}l=l.mul(u);const d=Ci(n||xd),c=mg(l,d);return Oi(a.xy.add(c),a.zw)}copy(e){return this.positionNode=e.positionNode,this.rotationNode=e.rotationNode,this.scaleNode=e.scaleNode,super.copy(e)}get sizeAttenuation(){return this._useSizeAttenuation}set sizeAttenuation(e){this._useSizeAttenuation!==e&&(this._useSizeAttenuation=e,this.needsUpdate=!0)}}class xg extends _h{constructor(){super(),this.shadowNode=Ci(1).toVar("shadowMask")}direct({shadowMask:e}){this.shadowNode.mulAssign(e)}finish(e){on.a.mulAssign(this.shadowNode.oneMinus()),e.outgoingLight.rgb.assign(on.rgb)}}const bg=new oe;class Tg extends Yc{static get type(){return"ShadowNodeMaterial"}constructor(e){super(),this.isShadowNodeMaterial=!0,this.lights=!0,this.setDefaultValues(bg),this.setValues(e)}setupLightingModel(){return new xg}}const _g=_i((({texture:e,uv:t})=>{const r=1e-4,s=Ii().toVar();return Si(t.x.lessThan(r),(()=>{s.assign(Ii(1,0,0))})).ElseIf(t.y.lessThan(r),(()=>{s.assign(Ii(0,1,0))})).ElseIf(t.z.lessThan(r),(()=>{s.assign(Ii(0,0,1))})).ElseIf(t.x.greaterThan(.9999),(()=>{s.assign(Ii(-1,0,0))})).ElseIf(t.y.greaterThan(.9999),(()=>{s.assign(Ii(0,-1,0))})).ElseIf(t.z.greaterThan(.9999),(()=>{s.assign(Ii(0,0,-1))})).Else((()=>{const r=.01,i=e.sample(t.add(Ii(-.01,0,0))).r.sub(e.sample(t.add(Ii(r,0,0))).r),n=e.sample(t.add(Ii(0,-.01,0))).r.sub(e.sample(t.add(Ii(0,r,0))).r),o=e.sample(t.add(Ii(0,0,-.01))).r.sub(e.sample(t.add(Ii(0,0,r))).r);s.assign(Ii(i,n,o))})),s.normalize()}));class vg extends xu{static get type(){return"Texture3DNode"}constructor(e,t=null,r=null){super(e,t,r),this.isTexture3DNode=!0}getInputType(){return"texture3D"}getDefaultUV(){return Ii(.5,.5,.5)}setUpdateMatrix(){}setupUV(e,t){return t}generateUV(e,t){return t.build(e,"vec3")}normal(e){return _g({texture:this,uv:e})}}const Ng=bi(vg);class Sg extends Yc{static get type(){return"VolumeNodeMaterial"}constructor(e={}){super(),this.lights=!1,this.isVolumeNodeMaterial=!0,this.testNode=null,this.setValues(e)}setup(e){const t=Ng(this.map,null,0),r=_i((({orig:e,dir:t})=>{const r=Ii(-.5),s=Ii(.5),i=t.reciprocal(),n=r.sub(e).mul(i),o=s.sub(e).mul(i),a=qo(n,o),u=Ko(n,o),l=Ko(a.x,Ko(a.y,a.z)),d=qo(u.x,qo(u.y,u.z));return Bi(l,d)}));this.fragmentNode=_i((()=>{const e=wa(Ii(zu.mul(Oi(Eu,1)))),s=wa(qu.sub(e)).normalize(),i=Bi(r({orig:e,dir:s})).toVar();i.x.greaterThan(i.y).discard(),i.assign(Bi(Ko(i.x,0),i.y));const n=Ii(e.add(i.x.mul(s))).toVar(),o=Ii(s.abs().reciprocal()).toVar(),a=Ci(qo(o.x,qo(o.y,o.z))).toVar("delta");a.divAssign(Ml("steps","float"));const u=Oi(Ml("base","color"),0).toVar();return ic({type:"float",start:i.x,end:i.y,update:"+= delta"},(()=>{const e=sn("float","d").assign(t.sample(n.add(.5)).r);null!==this.testNode?this.testNode({map:t,mapValue:e,probe:n,finalColor:u}).append():(u.a.assign(1),nc()),n.addAssign(s.mul(a))})),u.a.equal(0).discard(),Oi(u)}))(),super.setup(e)}}class Ag{constructor(e,t){this.nodes=e,this.info=t,this._context=self,this._animationLoop=null,this._requestId=null}start(){const e=(t,r)=>{this._requestId=this._context.requestAnimationFrame(e),!0===this.info.autoReset&&this.info.reset(),this.nodes.nodeFrame.update(),this.info.frame=this.nodes.nodeFrame.frameId,null!==this._animationLoop&&this._animationLoop(t,r)};e()}stop(){this._context.cancelAnimationFrame(this._requestId),this._requestId=null}setAnimationLoop(e){this._animationLoop=e}setContext(e){this._context=e}dispose(){this.stop()}}class Rg{constructor(){this.weakMap=new WeakMap}get(e){let t=this.weakMap;for(let r=0;r{this.dispose()},this.material.addEventListener("dispose",this.onMaterialDispose)}updateClipping(e){this.clippingContext=e}get clippingNeedsUpdate(){return null!==this.clippingContext&&this.clippingContext.cacheKey!==this.clippingContextCacheKey&&(this.clippingContextCacheKey=this.clippingContext.cacheKey,!0)}get hardwareClippingPlanes(){return!0===this.material.hardwareClipping?this.clippingContext.unionClippingCount:0}getNodeBuilderState(){return this._nodeBuilderState||(this._nodeBuilderState=this._nodes.getForRender(this))}getMonitor(){return this._monitor||(this._monitor=this.getNodeBuilderState().monitor)}getBindings(){return this._bindings||(this._bindings=this.getNodeBuilderState().createBindings())}getIndex(){return this._geometries.getIndex(this)}getIndirect(){return this._geometries.getIndirect(this)}getChainArray(){return[this.object,this.material,this.context,this.lightsNode]}setGeometry(e){this.geometry=e,this.attributes=null}getAttributes(){if(null!==this.attributes)return this.attributes;const e=this.getNodeBuilderState().nodeAttributes,t=this.geometry,r=[],s=new Set;for(const i of e){const e=i.node&&i.node.attribute?i.node.attribute:t.getAttribute(i.name);if(void 0===e)continue;r.push(e);const n=e.isInterleavedBufferAttribute?e.data:e;s.add(n)}return this.attributes=r,this.vertexBuffers=Array.from(s.values()),r}getVertexBuffers(){return null===this.vertexBuffers&&this.getAttributes(),this.vertexBuffers}getDrawParameters(){const{object:e,material:t,geometry:r,group:s,drawRange:i}=this,n=this.drawParams||(this.drawParams={vertexCount:0,firstVertex:0,instanceCount:0,firstInstance:0}),o=this.getIndex(),a=null!==o,u=r.isInstancedBufferGeometry?r.instanceCount:e.count>1?e.count:1;if(0===u)return null;if(n.instanceCount=u,!0===e.isBatchedMesh)return n;let l=1;!0!==t.wireframe||e.isPoints||e.isLineSegments||e.isLine||e.isLineLoop||(l=2);let d=i.start*l,c=(i.start+i.count)*l;null!==s&&(d=Math.max(d,s.start*l),c=Math.min(c,(s.start+s.count)*l));const h=r.attributes.position;let p=1/0;a?p=o.count:null!=h&&(p=h.count),d=Math.max(d,0),c=Math.min(c,p);const g=c-d;return g<0||g===1/0?null:(n.vertexCount=g,n.firstVertex=d,n)}getGeometryCacheKey(){const{geometry:e}=this;let t="";for(const r of Object.keys(e.attributes).sort()){const s=e.attributes[r];t+=r+",",s.data&&(t+=s.data.stride+","),s.offset&&(t+=s.offset+","),s.itemSize&&(t+=s.itemSize+","),s.normalized&&(t+="n,")}return e.index&&(t+="index,"),t}getMaterialCacheKey(){const{object:e,material:t}=this;let r=t.customProgramCacheKey();for(const e of function(e){const t=Object.keys(e);let r=Object.getPrototypeOf(e);for(;r;){const e=Object.getOwnPropertyDescriptors(r);for(const r in e)if(void 0!==e[r]){const s=e[r];s&&"function"==typeof s.get&&t.push(r)}r=Object.getPrototypeOf(r)}return t}(t)){if(/^(is[A-Z]|_)|^(visible|version|uuid|name|opacity|userData)$/.test(e))continue;const s=t[e];let i;if(null!==s){const e=typeof s;"number"===e?i=0!==s?"1":"0":"object"===e?(i="{",s.isTexture&&(i+=s.mapping),i+="}"):i=String(s)}else i=String(s);r+=i+","}return r+=this.clippingContextCacheKey+",",e.geometry&&(r+=this.getGeometryCacheKey()),e.skeleton&&(r+=e.skeleton.bones.length+","),e.morphTargetInfluences&&(r+=e.morphTargetInfluences.length+","),e.isBatchedMesh&&(r+=e._matricesTexture.uuid+",",null!==e._colorsTexture&&(r+=e._colorsTexture.uuid+",")),e.count>1&&(r+=e.uuid+","),r+=e.receiveShadow+",",us(r)}get needsGeometryUpdate(){return this.geometry.id!==this.object.geometry.id}get needsUpdate(){return this.initialNodesCacheKey!==this.getDynamicCacheKey()||this.clippingNeedsUpdate}getDynamicCacheKey(){let e=this._nodes.getCacheKey(this.scene,this.lightsNode);return this.object.receiveShadow&&(e+=1),e}getCacheKey(){return this.getMaterialCacheKey()+this.getDynamicCacheKey()}dispose(){this.material.removeEventListener("dispose",this.onMaterialDispose),this.onDispose()}}const wg=[];class Mg{constructor(e,t,r,s,i,n){this.renderer=e,this.nodes=t,this.geometries=r,this.pipelines=s,this.bindings=i,this.info=n,this.chainMaps={}}get(e,t,r,s,i,n,o,a){const u=this.getChainMap(a);wg[0]=e,wg[1]=t,wg[2]=n,wg[3]=i;let l=u.get(wg);return void 0===l?(l=this.createRenderObject(this.nodes,this.geometries,this.renderer,e,t,r,s,i,n,o,a),u.set(wg,l)):(l.updateClipping(o),l.needsGeometryUpdate&&l.setGeometry(e.geometry),(l.version!==t.version||l.needsUpdate)&&(l.initialCacheKey!==l.getCacheKey()?(l.dispose(),l=this.get(e,t,r,s,i,n,o,a)):l.version=t.version)),l}getChainMap(e="default"){return this.chainMaps[e]||(this.chainMaps[e]=new Rg)}dispose(){this.chainMaps={}}createRenderObject(e,t,r,s,i,n,o,a,u,l,d){const c=this.getChainMap(d),h=new Eg(e,t,r,s,i,n,o,a,u,l);return h.onDispose=()=>{this.pipelines.delete(h),this.bindings.delete(h),this.nodes.delete(h),c.delete(h.getChainArray())},h}}class Bg{constructor(){this.data=new WeakMap}get(e){let t=this.data.get(e);return void 0===t&&(t={},this.data.set(e,t)),t}delete(e){let t;return this.data.has(e)&&(t=this.data.get(e),this.data.delete(e)),t}has(e){return this.data.has(e)}dispose(){this.data=new WeakMap}}const Ug=1,Fg=2,Pg=3,Ig=4,Lg=16;class Vg extends Bg{constructor(e){super(),this.backend=e}delete(e){const t=super.delete(e);return void 0!==t&&this.backend.destroyAttribute(e),t}update(e,t){const r=this.get(e);if(void 0===r.version)t===Ug?this.backend.createAttribute(e):t===Fg?this.backend.createIndexAttribute(e):t===Pg?this.backend.createStorageAttribute(e):t===Ig&&this.backend.createIndirectStorageAttribute(e),r.version=this._getBufferAttribute(e).version;else{const t=this._getBufferAttribute(e);(r.version=0;--t)if(e[t]>=65535)return!0;return!1}(t)?ae:ue)(t,1);return i.version=Dg(e),i}class Gg extends Bg{constructor(e,t){super(),this.attributes=e,this.info=t,this.wireframes=new WeakMap,this.attributeCall=new WeakMap}has(e){const t=e.geometry;return super.has(t)&&!0===this.get(t).initialized}updateForRender(e){!1===this.has(e)&&this.initGeometry(e),this.updateAttributes(e)}initGeometry(e){const t=e.geometry;this.get(t).initialized=!0,this.info.memory.geometries++;const r=()=>{this.info.memory.geometries--;const s=t.index,i=e.getAttributes();null!==s&&this.attributes.delete(s);for(const e of i)this.attributes.delete(e);const n=this.wireframes.get(t);void 0!==n&&this.attributes.delete(n),t.removeEventListener("dispose",r)};t.addEventListener("dispose",r)}updateAttributes(e){const t=e.getAttributes();for(const e of t)e.isStorageBufferAttribute||e.isStorageInstancedBufferAttribute?this.updateAttribute(e,Pg):this.updateAttribute(e,Ug);const r=this.getIndex(e);null!==r&&this.updateAttribute(r,Fg);const s=e.geometry.indirect;null!==s&&this.updateAttribute(s,Ig)}updateAttribute(e,t){const r=this.info.render.calls;e.isInterleavedBufferAttribute?void 0===this.attributeCall.get(e)?(this.attributes.update(e,t),this.attributeCall.set(e,r)):this.attributeCall.get(e.data)!==r&&(this.attributes.update(e,t),this.attributeCall.set(e.data,r),this.attributeCall.set(e,r)):this.attributeCall.get(e)!==r&&(this.attributes.update(e,t),this.attributeCall.set(e,r))}getIndirect(e){return e.geometry.indirect}getIndex(e){const{geometry:t,material:r}=e;let s=t.index;if(!0===r.wireframe){const e=this.wireframes;let r=e.get(t);void 0===r?(r=Og(t),e.set(t,r)):r.version!==Dg(t)&&(this.attributes.delete(r),r=Og(t),e.set(t,r)),s=r}return s}}class kg{constructor(){this.autoReset=!0,this.frame=0,this.calls=0,this.render={calls:0,frameCalls:0,drawCalls:0,triangles:0,points:0,lines:0,timestamp:0,previousFrameCalls:0,timestampCalls:0},this.compute={calls:0,frameCalls:0,timestamp:0,previousFrameCalls:0,timestampCalls:0},this.memory={geometries:0,textures:0}}update(e,t,r){this.render.drawCalls++,e.isMesh||e.isSprite?this.render.triangles+=r*(t/3):e.isPoints?this.render.points+=r*t:e.isLineSegments?this.render.lines+=r*(t/2):e.isLine?this.render.lines+=r*(t-1):console.error("THREE.WebGPUInfo: Unknown object type.")}updateTimestamp(e,t){0===this[e].timestampCalls&&(this[e].timestamp=0),this[e].timestamp+=t,this[e].timestampCalls++,this[e].timestampCalls>=this[e].previousFrameCalls&&(this[e].timestampCalls=0)}reset(){const e=this.render.frameCalls;this.render.previousFrameCalls=e;const t=this.compute.frameCalls;this.compute.previousFrameCalls=t,this.render.drawCalls=0,this.render.frameCalls=0,this.compute.frameCalls=0,this.render.triangles=0,this.render.points=0,this.render.lines=0}dispose(){this.reset(),this.calls=0,this.render.calls=0,this.compute.calls=0,this.render.timestamp=0,this.compute.timestamp=0,this.memory.geometries=0,this.memory.textures=0}}class zg{constructor(e){this.cacheKey=e,this.usedTimes=0}}class $g extends zg{constructor(e,t,r){super(e),this.vertexProgram=t,this.fragmentProgram=r}}class Hg extends zg{constructor(e,t){super(e),this.computeProgram=t,this.isComputePipeline=!0}}let Wg=0;class jg{constructor(e,t,r=null,s=null){this.id=Wg++,this.code=e,this.stage=t,this.transforms=r,this.attributes=s,this.usedTimes=0}}class qg extends Bg{constructor(e,t){super(),this.backend=e,this.nodes=t,this.bindings=null,this.caches=new Map,this.programs={vertex:new Map,fragment:new Map,compute:new Map}}getForCompute(e,t){const{backend:r}=this,s=this.get(e);if(this._needsComputeUpdate(e)){const i=s.pipeline;i&&(i.usedTimes--,i.computeProgram.usedTimes--);const n=this.nodes.getForCompute(e);let o=this.programs.compute.get(n.computeShader);void 0===o&&(i&&0===i.computeProgram.usedTimes&&this._releaseProgram(i.computeProgram),o=new jg(n.computeShader,"compute",n.transforms,n.nodeAttributes),this.programs.compute.set(n.computeShader,o),r.createProgram(o));const a=this._getComputeCacheKey(e,o);let u=this.caches.get(a);void 0===u&&(i&&0===i.usedTimes&&this._releasePipeline(i),u=this._getComputePipeline(e,o,a,t)),u.usedTimes++,o.usedTimes++,s.version=e.version,s.pipeline=u}return s.pipeline}getForRender(e,t=null){const{backend:r}=this,s=this.get(e);if(this._needsRenderUpdate(e)){const i=s.pipeline;i&&(i.usedTimes--,i.vertexProgram.usedTimes--,i.fragmentProgram.usedTimes--);const n=e.getNodeBuilderState();let o=this.programs.vertex.get(n.vertexShader);void 0===o&&(i&&0===i.vertexProgram.usedTimes&&this._releaseProgram(i.vertexProgram),o=new jg(n.vertexShader,"vertex"),this.programs.vertex.set(n.vertexShader,o),r.createProgram(o));let a=this.programs.fragment.get(n.fragmentShader);void 0===a&&(i&&0===i.fragmentProgram.usedTimes&&this._releaseProgram(i.fragmentProgram),a=new jg(n.fragmentShader,"fragment"),this.programs.fragment.set(n.fragmentShader,a),r.createProgram(a));const u=this._getRenderCacheKey(e,o,a);let l=this.caches.get(u);void 0===l?(i&&0===i.usedTimes&&this._releasePipeline(i),l=this._getRenderPipeline(e,o,a,u,t)):e.pipeline=l,l.usedTimes++,o.usedTimes++,a.usedTimes++,s.pipeline=l}return s.pipeline}delete(e){const t=this.get(e).pipeline;return t&&(t.usedTimes--,0===t.usedTimes&&this._releasePipeline(t),t.isComputePipeline?(t.computeProgram.usedTimes--,0===t.computeProgram.usedTimes&&this._releaseProgram(t.computeProgram)):(t.fragmentProgram.usedTimes--,t.vertexProgram.usedTimes--,0===t.vertexProgram.usedTimes&&this._releaseProgram(t.vertexProgram),0===t.fragmentProgram.usedTimes&&this._releaseProgram(t.fragmentProgram))),super.delete(e)}dispose(){super.dispose(),this.caches=new Map,this.programs={vertex:new Map,fragment:new Map,compute:new Map}}updateForRender(e){this.getForRender(e)}_getComputePipeline(e,t,r,s){r=r||this._getComputeCacheKey(e,t);let i=this.caches.get(r);return void 0===i&&(i=new Hg(r,t),this.caches.set(r,i),this.backend.createComputePipeline(i,s)),i}_getRenderPipeline(e,t,r,s,i){s=s||this._getRenderCacheKey(e,t,r);let n=this.caches.get(s);return void 0===n&&(n=new $g(s,t,r),this.caches.set(s,n),e.pipeline=n,this.backend.createRenderPipeline(e,i)),n}_getComputeCacheKey(e,t){return e.id+","+t.id}_getRenderCacheKey(e,t,r){return t.id+","+r.id+","+this.backend.getRenderCacheKey(e)}_releasePipeline(e){this.caches.delete(e.cacheKey)}_releaseProgram(e){const t=e.code,r=e.stage;this.programs[r].delete(t)}_needsComputeUpdate(e){const t=this.get(e);return void 0===t.pipeline||t.version!==e.version}_needsRenderUpdate(e){return void 0===this.get(e).pipeline||this.backend.needsRenderUpdate(e)}}class Kg extends Bg{constructor(e,t,r,s,i,n){super(),this.backend=e,this.textures=r,this.pipelines=i,this.attributes=s,this.nodes=t,this.info=n,this.pipelines.bindings=this}getForRender(e){const t=e.getBindings();for(const e of t){const r=this.get(e);void 0===r.bindGroup&&(this._init(e),this.backend.createBindings(e,t,0),r.bindGroup=e)}return t}getForCompute(e){const t=this.nodes.getForCompute(e).bindings;for(const e of t){const r=this.get(e);void 0===r.bindGroup&&(this._init(e),this.backend.createBindings(e,t,0),r.bindGroup=e)}return t}updateForCompute(e){this._updateBindings(this.getForCompute(e))}updateForRender(e){this._updateBindings(this.getForRender(e))}_updateBindings(e){for(const t of e)this._update(t,e)}_init(e){for(const t of e.bindings)if(t.isSampledTexture)this.textures.updateTexture(t.texture);else if(t.isStorageBuffer){const e=t.attribute,r=e.isIndirectStorageBufferAttribute?Ig:Pg;this.attributes.update(e,r)}}_update(e,t){const{backend:r}=this;let s=!1,i=!0,n=0,o=0;for(const t of e.bindings){if(t.isNodeUniformsGroup){if(!this.nodes.updateGroup(t))continue}if(t.isUniformBuffer){t.update()&&r.updateBinding(t)}else if(t.isSampler)t.update();else if(t.isSampledTexture){const e=this.textures.get(t.texture);t.needsBindingsUpdate(e.generation)&&(s=!0);const a=t.update(),u=t.texture;a&&this.textures.updateTexture(u);const l=r.get(u);if(void 0!==l.externalTexture||e.isDefaultTexture?i=!1:(n=10*n+u.id,o+=u.version),!0===r.isWebGPUBackend&&void 0===l.texture&&void 0===l.externalTexture&&(console.error("Bindings._update: binding should be available:",t,a,u,t.textureNode.value,s),this.textures.updateTexture(u),s=!0),!0===u.isStorageTexture){const e=this.get(u);!0===t.store?e.needsMipmap=!0:this.textures.needsMipmaps(u)&&!0===e.needsMipmap&&(this.backend.generateMipmaps(u),e.needsMipmap=!1)}}}!0===s&&this.backend.updateBindings(e,t,i?n:0,o)}}function Xg(e,t){return e.groupOrder!==t.groupOrder?e.groupOrder-t.groupOrder:e.renderOrder!==t.renderOrder?e.renderOrder-t.renderOrder:e.material.id!==t.material.id?e.material.id-t.material.id:e.z!==t.z?e.z-t.z:e.id-t.id}function Yg(e,t){return e.groupOrder!==t.groupOrder?e.groupOrder-t.groupOrder:e.renderOrder!==t.renderOrder?e.renderOrder-t.renderOrder:e.z!==t.z?t.z-e.z:e.id-t.id}function Qg(e){return(e.transmission>0||e.transmissionNode)&&e.side===le&&!1===e.forceSinglePass}class Zg{constructor(e,t,r){this.renderItems=[],this.renderItemsIndex=0,this.opaque=[],this.transparentDoublePass=[],this.transparent=[],this.bundles=[],this.lightsNode=e.getNode(t,r),this.lightsArray=[],this.scene=t,this.camera=r,this.occlusionQueryCount=0}begin(){return this.renderItemsIndex=0,this.opaque.length=0,this.transparentDoublePass.length=0,this.transparent.length=0,this.bundles.length=0,this.lightsArray.length=0,this.occlusionQueryCount=0,this}getNextRenderItem(e,t,r,s,i,n,o){let a=this.renderItems[this.renderItemsIndex];return void 0===a?(a={id:e.id,object:e,geometry:t,material:r,groupOrder:s,renderOrder:e.renderOrder,z:i,group:n,clippingContext:o},this.renderItems[this.renderItemsIndex]=a):(a.id=e.id,a.object=e,a.geometry=t,a.material=r,a.groupOrder=s,a.renderOrder=e.renderOrder,a.z=i,a.group=n,a.clippingContext=o),this.renderItemsIndex++,a}push(e,t,r,s,i,n,o){const a=this.getNextRenderItem(e,t,r,s,i,n,o);!0===e.occlusionTest&&this.occlusionQueryCount++,!0===r.transparent||r.transmission>0?(Qg(r)&&this.transparentDoublePass.push(a),this.transparent.push(a)):this.opaque.push(a)}unshift(e,t,r,s,i,n,o){const a=this.getNextRenderItem(e,t,r,s,i,n,o);!0===r.transparent||r.transmission>0?(Qg(r)&&this.transparentDoublePass.unshift(a),this.transparent.unshift(a)):this.opaque.unshift(a)}pushBundle(e){this.bundles.push(e)}pushLight(e){this.lightsArray.push(e)}sort(e,t){this.opaque.length>1&&this.opaque.sort(e||Xg),this.transparentDoublePass.length>1&&this.transparentDoublePass.sort(t||Yg),this.transparent.length>1&&this.transparent.sort(t||Yg)}finish(){this.lightsNode.setLights(this.lightsArray);for(let e=this.renderItemsIndex,t=this.renderItems.length;e>t,u=o.height>>t;let l=e.depthTexture||i[t];const d=!0===e.depthBuffer||!0===e.stencilBuffer;let c=!1;void 0===l&&d&&(l=new B,l.format=e.stencilBuffer?de:ce,l.type=e.stencilBuffer?he:x,l.image.width=a,l.image.height=u,i[t]=l),r.width===o.width&&o.height===r.height||(c=!0,l&&(l.needsUpdate=!0,l.image.width=a,l.image.height=u)),r.width=o.width,r.height=o.height,r.textures=n,r.depthTexture=l||null,r.depth=e.depthBuffer,r.stencil=e.stencilBuffer,r.renderTarget=e,r.sampleCount!==s&&(c=!0,l&&(l.needsUpdate=!0),r.sampleCount=s);const h={sampleCount:s};for(let e=0;e{e.removeEventListener("dispose",t);for(let e=0;e0){const s=e.image;if(void 0===s)console.warn("THREE.Renderer: Texture marked for update but image is undefined.");else if(!1===s.complete)console.warn("THREE.Renderer: Texture marked for update but image is incomplete.");else{if(e.images){const r=[];for(const t of e.images)r.push(t);t.images=r}else t.image=s;void 0!==r.isDefaultTexture&&!0!==r.isDefaultTexture||(i.createTexture(e,t),r.isDefaultTexture=!1,r.generation=e.version),!0===e.source.dataReady&&i.updateTexture(e,t),t.needsMipmaps&&0===e.mipmaps.length&&i.generateMipmaps(e)}}else i.createDefaultTexture(e),r.isDefaultTexture=!0,r.generation=e.version}if(!0!==r.initialized){r.initialized=!0,r.generation=e.version,this.info.memory.textures++;const t=()=>{e.removeEventListener("dispose",t),this._destroyTexture(e),this.info.memory.textures--};e.addEventListener("dispose",t)}r.version=e.version}getSize(e,t=im){let r=e.images?e.images[0]:e.image;return r?(void 0!==r.image&&(r=r.image),t.width=r.width||1,t.height=r.height||1,t.depth=e.isCubeTexture?6:r.depth||1):t.width=t.height=t.depth=1,t}getMipLevels(e,t,r){let s;return s=e.isCompressedTexture?e.mipmaps?e.mipmaps.length:1:Math.floor(Math.log2(Math.max(t,r)))+1,s}needsMipmaps(e){return this.isEnvironmentTexture(e)||!0===e.isCompressedTexture||e.generateMipmaps}isEnvironmentTexture(e){const t=e.mapping;return t===j||t===q||t===_||t===v}_destroyTexture(e){this.backend.destroySampler(e),this.backend.destroyTexture(e),this.delete(e)}}class om extends e{constructor(e,t,r,s=1){super(e,t,r),this.a=s}set(e,t,r,s=1){return this.a=s,super.set(e,t,r)}copy(e){return void 0!==e.a&&(this.a=e.a),super.copy(e)}clone(){return new this.constructor(this.r,this.g,this.b,this.a)}}class am extends rn{static get type(){return"ParameterNode"}constructor(e,t=null){super(e,t),this.isParameterNode=!0}getHash(){return this.uuid}generate(){return this.name}}class um extends Ms{static get type(){return"StackNode"}constructor(e=null){super(),this.nodes=[],this.outputNode=null,this.parent=e,this._currentCond=null,this.isStackNode=!0}getNodeType(e){return this.outputNode?this.outputNode.getNodeType(e):"void"}add(e){return this.nodes.push(e),this}If(e,t){const r=new mi(t);return this._currentCond=Ta(e,r),this.add(this._currentCond)}ElseIf(e,t){const r=new mi(t),s=Ta(e,r);return this._currentCond.elseNode=s,this._currentCond=s,this}Else(e){return this._currentCond.elseNode=new mi(e),this}build(e,...t){const r=Ni();vi(this);for(const t of this.nodes)t.build(e,"void");return vi(r),this.outputNode?this.outputNode.build(e,...t):super.build(e,...t)}else(...e){return console.warn("TSL.StackNode: .else() has been renamed to .Else()."),this.Else(...e)}elseif(...e){return console.warn("TSL.StackNode: .elseif() has been renamed to .ElseIf()."),this.ElseIf(...e)}}const lm=bi(um);class dm extends Ms{static get type(){return"OutputStructNode"}constructor(...e){super(),this.members=e,this.isOutputStructNode=!0}setup(e){super.setup(e);const t=this.members,r=[];for(let s=0;s{const t=e.toUint().mul(747796405).add(2891336453),r=t.shiftRight(t.shiftRight(28).add(4)).bitXor(t).mul(277803737);return r.shiftRight(22).bitXor(r).toFloat().mul(1/2**32)})),fm=(e,t)=>ra(kn(4,e.mul(Gn(1,e))),t),ym=_i((([e])=>e.fract().sub(.5).abs())).setLayout({name:"tri",type:"float",inputs:[{name:"x",type:"float"}]}),xm=_i((([e])=>Ii(ym(e.z.add(ym(e.y.mul(1)))),ym(e.z.add(ym(e.x.mul(1)))),ym(e.y.add(ym(e.x.mul(1))))))).setLayout({name:"tri3",type:"vec3",inputs:[{name:"p",type:"vec3"}]}),bm=_i((([e,t,r])=>{const s=Ii(e).toVar(),i=Ci(1.4).toVar(),n=Ci(0).toVar(),o=Ii(s).toVar();return ic({start:Ci(0),end:Ci(3),type:"float",condition:"<="},(()=>{const e=Ii(xm(o.mul(2))).toVar();s.addAssign(e.add(r.mul(Ci(.1).mul(t)))),o.mulAssign(1.8),i.mulAssign(1.5),s.mulAssign(1.2);const a=Ci(ym(s.z.add(ym(s.x.add(ym(s.y)))))).toVar();n.addAssign(a.div(i)),o.addAssign(.14)})),n})).setLayout({name:"triNoise3D",type:"float",inputs:[{name:"position",type:"vec3"},{name:"speed",type:"float"},{name:"time",type:"float"}]});class Tm extends Ms{static get type(){return"FunctionOverloadingNode"}constructor(e=[],...t){super(),this.functionNodes=e,this.parametersNodes=t,this._candidateFnCall=null,this.global=!0}getNodeType(){return this.functionNodes[0].shaderNode.layout.type}setup(e){const t=this.parametersNodes;let r=this._candidateFnCall;if(null===r){let s=null,i=-1;for(const r of this.functionNodes){const n=r.shaderNode.layout;if(null===n)throw new Error("FunctionOverloadingNode: FunctionNode must be a layout.");const o=n.inputs;if(t.length===o.length){let n=0;for(let r=0;ri&&(s=r,i=n)}}this._candidateFnCall=r=s(...t)}return r}}const _m=bi(Tm),vm=e=>(...t)=>_m(e,...t),Nm=tn(0).setGroup(Zi).onRenderUpdate((e=>e.time)),Sm=tn(0).setGroup(Zi).onRenderUpdate((e=>e.deltaTime)),Am=tn(0,"uint").setGroup(Zi).onRenderUpdate((e=>e.frameId)),Rm=_i((([e,t,r=Bi(.5)])=>mg(e.sub(r),t).add(r))),Cm=_i((([e,t,r=Bi(.5)])=>{const s=e.sub(r),i=s.dot(s),n=i.mul(i).mul(t);return e.add(s.mul(n))})),Em=_i((({position:e=null,horizontal:t=!0,vertical:r=!1})=>{let s;null!==e?(s=Vu.toVar(),s[3][0]=e.x,s[3][1]=e.y,s[3][2]=e.z):s=Vu;const i=Au.mul(s);return pi(t)&&(i[0][0]=Vu[0].length(),i[0][1]=0,i[0][2]=0),pi(r)&&(i[1][0]=0,i[1][1]=Vu[1].length(),i[1][2]=0),i[2][0]=0,i[2][1]=0,i[2][2]=1,Nu.mul(i).mul(Ku)})),wm=_i((([e=null])=>{const t=$c();return $c(Ic(e)).sub(t).lessThan(0).select(bc,e)}));class Mm extends Ms{static get type(){return"SpriteSheetUVNode"}constructor(e,t=pu(),r=Ci(0)){super("vec2"),this.countNode=e,this.uvNode=t,this.frameNode=r}setup(){const{frameNode:e,uvNode:t,countNode:r}=this,{width:s,height:i}=r,n=e.mod(s.mul(i)).floor(),o=n.mod(s),a=i.sub(n.add(1).div(s).ceil()),u=r.reciprocal(),l=Bi(o,a);return t.add(l).mul(u)}}const Bm=bi(Mm);class Um extends Ms{static get type(){return"TriplanarTexturesNode"}constructor(e,t=null,r=null,s=Ci(1),i=Ku,n=il){super("vec4"),this.textureXNode=e,this.textureYNode=t,this.textureZNode=r,this.scaleNode=s,this.positionNode=i,this.normalNode=n}setup(){const{textureXNode:e,textureYNode:t,textureZNode:r,scaleNode:s,positionNode:i,normalNode:n}=this;let o=n.abs().normalize();o=o.div(o.dot(Ii(1)));const a=i.yz.mul(s),u=i.zx.mul(s),l=i.xy.mul(s),d=e.value,c=null!==t?t.value:d,h=null!==r?r.value:d,p=bu(d,a).mul(o.x),g=bu(c,u).mul(o.y),m=bu(h,l).mul(o.z);return On(p,g,m)}}const Fm=bi(Um),Pm=new me,Im=new r,Lm=new r,Vm=new r,Dm=new n,Om=new r(0,0,-1),Gm=new s,km=new r,zm=new r,$m=new s,Hm=new t,Wm=new ge,jm=bc.flipX();Wm.depthTexture=new B(1,1);let qm=!1;class Km extends xu{static get type(){return"ReflectorNode"}constructor(e={}){super(e.defaultTexture||Wm.texture,jm),this._reflectorBaseNode=e.reflector||new Xm(this,e),this._depthNode=null,this.setUpdateMatrix(!1)}get reflector(){return this._reflectorBaseNode}get target(){return this._reflectorBaseNode.target}getDepthNode(){if(null===this._depthNode){if(!0!==this._reflectorBaseNode.depth)throw new Error("THREE.ReflectorNode: Depth node can only be requested when the reflector is created with { depth: true }. ");this._depthNode=fi(new Km({defaultTexture:Wm.depthTexture,reflector:this._reflectorBaseNode}))}return this._depthNode}setup(e){return e.object.isQuadMesh||this._reflectorBaseNode.build(e),super.setup(e)}clone(){const e=new this.constructor(this.reflectorNode);return e._reflectorBaseNode=this._reflectorBaseNode,e}}class Xm extends Ms{static get type(){return"ReflectorBaseNode"}constructor(e,t={}){super();const{target:r=new fe,resolution:s=1,generateMipmaps:i=!1,bounces:n=!0,depth:o=!1}=t;this.textureNode=e,this.target=r,this.resolution=s,this.generateMipmaps=i,this.bounces=n,this.depth=o,this.updateBeforeType=n?vs.RENDER:vs.FRAME,this.virtualCameras=new WeakMap,this.renderTargets=new WeakMap}_updateResolution(e,t){const r=this.resolution;t.getDrawingBufferSize(Hm),e.setSize(Math.round(Hm.width*r),Math.round(Hm.height*r))}setup(e){return this._updateResolution(Wm,e.renderer),super.setup(e)}getVirtualCamera(e){let t=this.virtualCameras.get(e);return void 0===t&&(t=e.clone(),this.virtualCameras.set(e,t)),t}getRenderTarget(e){let t=this.renderTargets.get(e);return void 0===t&&(t=new ge(0,0,{type:ye}),!0===this.generateMipmaps&&(t.texture.minFilter=xe,t.texture.generateMipmaps=!0),!0===this.depth&&(t.depthTexture=new B),this.renderTargets.set(e,t)),t}updateBefore(e){if(!1===this.bounces&&qm)return;qm=!0;const{scene:t,camera:r,renderer:s,material:i}=e,{target:n}=this,o=this.getVirtualCamera(r),a=this.getRenderTarget(o);if(s.getDrawingBufferSize(Hm),this._updateResolution(a,s),Lm.setFromMatrixPosition(n.matrixWorld),Vm.setFromMatrixPosition(r.matrixWorld),Dm.extractRotation(n.matrixWorld),Im.set(0,0,1),Im.applyMatrix4(Dm),km.subVectors(Lm,Vm),km.dot(Im)>0)return;km.reflect(Im).negate(),km.add(Lm),Dm.extractRotation(r.matrixWorld),Om.set(0,0,-1),Om.applyMatrix4(Dm),Om.add(Vm),zm.subVectors(Lm,Om),zm.reflect(Im).negate(),zm.add(Lm),o.coordinateSystem=r.coordinateSystem,o.position.copy(km),o.up.set(0,1,0),o.up.applyMatrix4(Dm),o.up.reflect(Im),o.lookAt(zm),o.near=r.near,o.far=r.far,o.updateMatrixWorld(),o.projectionMatrix.copy(r.projectionMatrix),Pm.setFromNormalAndCoplanarPoint(Im,Lm),Pm.applyMatrix4(o.matrixWorldInverse),Gm.set(Pm.normal.x,Pm.normal.y,Pm.normal.z,Pm.constant);const u=o.projectionMatrix;$m.x=(Math.sign(Gm.x)+u.elements[8])/u.elements[0],$m.y=(Math.sign(Gm.y)+u.elements[9])/u.elements[5],$m.z=-1,$m.w=(1+u.elements[10])/u.elements[14],Gm.multiplyScalar(1/Gm.dot($m));u.elements[2]=Gm.x,u.elements[6]=Gm.y,u.elements[10]=s.coordinateSystem===l?Gm.z-0:Gm.z+1-0,u.elements[14]=Gm.w,this.textureNode.value=a.texture,!0===this.depth&&(this.textureNode.getDepthNode().value=a.depthTexture),i.visible=!1;const d=s.getRenderTarget(),c=s.getMRT();s.setMRT(null),s.setRenderTarget(a),s.render(t,o),s.setMRT(c),s.setRenderTarget(d),i.visible=!0,qm=!1}}const Ym=new be(-1,1,1,-1,0,1);class Qm extends Te{constructor(e=!1){super();const t=!1===e?[0,-1,0,1,2,1]:[0,2,0,0,2,0];this.setAttribute("position",new _e([-1,3,0,-1,-1,0,3,-1,0],3)),this.setAttribute("uv",new _e(t,2))}}const Zm=new Qm;class Jm extends k{constructor(e=null){super(Zm,e),this.camera=Ym,this.isQuadMesh=!0}renderAsync(e){return e.renderAsync(this,Ym)}render(e){e.render(this,Ym)}}const ef=new t;class tf extends xu{static get type(){return"RTTNode"}constructor(e,t=null,r=null,s={type:ye}){const i=new ge(t,r,s);super(i.texture,pu()),this.node=e,this.width=t,this.height=r,this.pixelRatio=1,this.renderTarget=i,this.textureNeedsUpdate=!0,this.autoUpdate=!0,this._rttNode=null,this._quadMesh=new Jm(new Yc),this.updateBeforeType=vs.RENDER}get autoSize(){return null===this.width}setup(e){return this._rttNode=this.node.context(e.getSharedContext()),this._quadMesh.material.name="RTT",this._quadMesh.material.needsUpdate=!0,super.setup(e)}setSize(e,t){this.width=e,this.height=t;const r=e*this.pixelRatio,s=t*this.pixelRatio;this.renderTarget.setSize(r,s),this.textureNeedsUpdate=!0}setPixelRatio(e){this.pixelRatio=e,this.setSize(this.width,this.height)}updateBefore({renderer:e}){if(!1===this.textureNeedsUpdate&&!1===this.autoUpdate)return;if(this.textureNeedsUpdate=!1,!0===this.autoSize){this.pixelRatio=e.getPixelRatio();const t=e.getSize(ef);this.setSize(t.width,t.height)}this._quadMesh.material.fragmentNode=this._rttNode;const t=e.getRenderTarget();e.setRenderTarget(this.renderTarget),this._quadMesh.render(e),e.setRenderTarget(t)}clone(){const e=new xu(this.value,this.uvNode,this.levelNode);return e.sampler=this.sampler,e.referenceNode=this,e}}const rf=(e,...t)=>fi(new tf(fi(e),...t)),sf=_i((([e,t,r],s)=>{let i;s.renderer.coordinateSystem===l?(e=Bi(e.x,e.y.oneMinus()).mul(2).sub(1),i=Oi(Ii(e,t),1)):i=Oi(Ii(e.x,e.y.oneMinus(),t).mul(2).sub(1),1);const n=Oi(r.mul(i));return n.xyz.div(n.w)})),nf=_i((([e,t])=>{const r=t.mul(Oi(e,1)),s=r.xy.div(r.w).mul(.5).add(.5).toVar();return Bi(s.x,s.y.oneMinus())})),of=_i((([e,t,r])=>{const s=mu(Tu(t)),i=Ui(e.mul(s)).toVar(),n=Tu(t,i).toVar(),o=Tu(t,i.sub(Ui(2,0))).toVar(),a=Tu(t,i.sub(Ui(1,0))).toVar(),u=Tu(t,i.add(Ui(1,0))).toVar(),l=Tu(t,i.add(Ui(2,0))).toVar(),d=Tu(t,i.add(Ui(0,2))).toVar(),c=Tu(t,i.add(Ui(0,1))).toVar(),h=Tu(t,i.sub(Ui(0,1))).toVar(),p=Tu(t,i.sub(Ui(0,2))).toVar(),g=Fo(Gn(Ci(2).mul(a).sub(o),n)).toVar(),m=Fo(Gn(Ci(2).mul(u).sub(l),n)).toVar(),f=Fo(Gn(Ci(2).mul(c).sub(d),n)).toVar(),y=Fo(Gn(Ci(2).mul(h).sub(p),n)).toVar(),x=sf(e,n,r).toVar(),b=g.lessThan(m).select(x.sub(sf(e.sub(Bi(Ci(1).div(s.x),0)),a,r)),x.negate().add(sf(e.add(Bi(Ci(1).div(s.x),0)),u,r))),T=f.lessThan(y).select(x.sub(sf(e.add(Bi(0,Ci(1).div(s.y))),c,r)),x.negate().add(sf(e.sub(Bi(0,Ci(1).div(s.y))),h,r)));return Ao(ta(b,T))}));class af extends R{constructor(e,t,r=Float32Array){!1===ArrayBuffer.isView(e)&&(e=new r(e*t)),super(e,t),this.isStorageInstancedBufferAttribute=!0}}class uf extends ve{constructor(e,t,r=Float32Array){!1===ArrayBuffer.isView(e)&&(e=new r(e*t)),super(e,t),this.isStorageBufferAttribute=!0}}class lf extends Bs{static get type(){return"StorageArrayElementNode"}constructor(e,t){super(e,t),this.isStorageArrayElementNode=!0}set storageBufferNode(e){this.node=e}get storageBufferNode(){return this.node}setup(e){return!1===e.isAvailable("storageBuffer")&&!0===this.node.isPBO&&e.setupPBO(this.node),super.setup(e)}generate(e,t){let r;const s=e.context.assign;if(r=!1===e.isAvailable("storageBuffer")?!0!==this.node.isPBO||!0===s||!this.node.value.isInstancedBufferAttribute&&"compute"===e.shaderStage?this.node.build(e):e.generatePBO(this):super.generate(e),!0!==s){const s=this.getNodeType(e);r=e.format(r,s,t)}return r}}const df=bi(lf);class cf extends Tl{static get type(){return"StorageBufferNode"}constructor(e,t=null,r=0){null===t&&(e.isStorageBufferAttribute||e.isStorageInstancedBufferAttribute)&&(t=gs(e.itemSize),r=e.count),super(e,t,r),this.isStorageBufferNode=!0,this.access=Ss.READ_WRITE,this.isAtomic=!1,this.isPBO=!1,this._attribute=null,this._varying=null,this.global=!0,!0!==e.isStorageBufferAttribute&&!0!==e.isStorageInstancedBufferAttribute&&(e.isInstancedBufferAttribute?e.isStorageInstancedBufferAttribute=!0:e.isStorageBufferAttribute=!0)}getHash(e){if(0===this.bufferCount){let t=e.globalCache.getData(this.value);return void 0===t&&(t={node:this},e.globalCache.setData(this.value,t)),t.node.uuid}return this.uuid}getInputType(){return this.value.isIndirectStorageBufferAttribute?"indirectStorageBuffer":"storageBuffer"}element(e){return df(this,e)}setPBO(e){return this.isPBO=e,this}getPBO(){return this.isPBO}setAccess(e){return this.access=e,this}toReadOnly(){return this.setAccess(Ss.READ_ONLY)}setAtomic(e){return this.isAtomic=e,this}toAtomic(){return this.setAtomic(!0)}getAttributeData(){return null===this._attribute&&(this._attribute=qa(this.value),this._varying=wa(this._attribute)),{attribute:this._attribute,varying:this._varying}}getNodeType(e){if(e.isAvailable("storageBuffer")||e.isAvailable("indirectStorageBuffer"))return super.getNodeType(e);const{attribute:t}=this.getAttributeData();return t.getNodeType(e)}generate(e){if(e.isAvailable("storageBuffer")||e.isAvailable("indirectStorageBuffer"))return super.generate(e);const{attribute:t,varying:r}=this.getAttributeData(),s=r.build(e);return e.registerTransform(s,t),s}}const hf=(e,t=null,r=0)=>fi(new cf(e,t,r));class pf extends cu{static get type(){return"VertexColorNode"}constructor(e=0){super(null,"vec4"),this.isVertexColorNode=!0,this.index=e}getAttributeName(){const e=this.index;return"color"+(e>0?e:"")}generate(e){const t=this.getAttributeName(e);let r;return r=!0===e.hasGeometryAttribute(t)?super.generate(e):e.generateConst(this.nodeType,new s(1,1,1,1)),r}serialize(e){super.serialize(e),e.index=this.index}deserialize(e){super.deserialize(e),this.index=e.index}}class gf extends Ms{static get type(){return"PointUVNode"}constructor(){super("vec2"),this.isPointUVNode=!0}generate(){return"vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y )"}}const mf=Ti(gf),ff=new Se,yf=new n;class xf extends Ms{static get type(){return"SceneNode"}constructor(e=xf.BACKGROUND_BLURRINESS,t=null){super(),this.scope=e,this.scene=t}setup(e){const t=this.scope,r=null!==this.scene?this.scene:e.scene;let s;return t===xf.BACKGROUND_BLURRINESS?s=Cl("backgroundBlurriness","float",r):t===xf.BACKGROUND_INTENSITY?s=Cl("backgroundIntensity","float",r):t===xf.BACKGROUND_ROTATION?s=tn("mat4").label("backgroundRotation").setGroup(Zi).onRenderUpdate((()=>{const e=r.background;return null!==e&&e.isTexture&&e.mapping!==Ne?(ff.copy(r.backgroundRotation),ff.x*=-1,ff.y*=-1,ff.z*=-1,yf.makeRotationFromEuler(ff)):yf.identity(),yf})):console.error("THREE.SceneNode: Unknown scope:",t),s}}xf.BACKGROUND_BLURRINESS="backgroundBlurriness",xf.BACKGROUND_INTENSITY="backgroundIntensity",xf.BACKGROUND_ROTATION="backgroundRotation";const bf=Ti(xf,xf.BACKGROUND_BLURRINESS),Tf=Ti(xf,xf.BACKGROUND_INTENSITY),_f=Ti(xf,xf.BACKGROUND_ROTATION);class vf extends xu{static get type(){return"StorageTextureNode"}constructor(e,t,r=null){super(e,t),this.storeNode=r,this.isStorageTextureNode=!0,this.access=Ss.WRITE_ONLY}getInputType(){return"storageTexture"}setup(e){super.setup(e);e.getNodeProperties(this).storeNode=this.storeNode}setAccess(e){return this.access=e,this}generate(e,t){let r;return r=null!==this.storeNode?this.generateStore(e):super.generate(e,t),r}toReadWrite(){return this.setAccess(Ss.READ_WRITE)}toReadOnly(){return this.setAccess(Ss.READ_ONLY)}toWriteOnly(){return this.setAccess(Ss.WRITE_ONLY)}generateStore(e){const t=e.getNodeProperties(this),{uvNode:r,storeNode:s}=t,i=super.generate(e,"property"),n=r.build(e,"uvec2"),o=s.build(e,"vec4"),a=e.generateTextureStore(e,i,n,o);e.addLineFlowCode(a,this)}}const Nf=bi(vf);class Sf extends Rl{static get type(){return"UserDataNode"}constructor(e,t,r=null){super(e,t,r),this.userData=r}updateReference(e){return this.reference=null!==this.userData?this.userData:e.object.userData,this.reference}}const Af=new WeakMap;class Rf extends Fs{static get type(){return"VelocityNode"}constructor(){super("vec2"),this.projectionMatrix=null,this.updateType=vs.OBJECT,this.updateAfterType=vs.OBJECT,this.previousModelWorldMatrix=tn(new n),this.previousProjectionMatrix=tn(new n).setGroup(Zi),this.previousCameraViewMatrix=tn(new n)}setProjectionMatrix(e){this.projectionMatrix=e}update({frameId:e,camera:t,object:r}){const s=Ef(r);this.previousModelWorldMatrix.value.copy(s);const i=Cf(t);i.frameId!==e&&(i.frameId=e,void 0===i.previousProjectionMatrix?(i.previousProjectionMatrix=new n,i.previousCameraViewMatrix=new n,i.currentProjectionMatrix=new n,i.currentCameraViewMatrix=new n,i.previousProjectionMatrix.copy(this.projectionMatrix||t.projectionMatrix),i.previousCameraViewMatrix.copy(t.matrixWorldInverse)):(i.previousProjectionMatrix.copy(i.currentProjectionMatrix),i.previousCameraViewMatrix.copy(i.currentCameraViewMatrix)),i.currentProjectionMatrix.copy(this.projectionMatrix||t.projectionMatrix),i.currentCameraViewMatrix.copy(t.matrixWorldInverse),this.previousProjectionMatrix.value.copy(i.previousProjectionMatrix),this.previousCameraViewMatrix.value.copy(i.previousCameraViewMatrix))}updateAfter({object:e}){Ef(e).copy(e.matrixWorld)}setup(){const e=null===this.projectionMatrix?Nu:tn(this.projectionMatrix),t=this.previousCameraViewMatrix.mul(this.previousModelWorldMatrix),r=e.mul($u).mul(Ku),s=this.previousProjectionMatrix.mul(t).mul(Xu),i=r.xy.div(r.w),n=s.xy.div(s.w);return Gn(i,n)}}function Cf(e){let t=Af.get(e);return void 0===t&&(t={},Af.set(e,t)),t}function Ef(e,t=0){const r=Cf(e);let s=r[t];return void 0===s&&(r[t]=s=new n),s}const wf=Ti(Rf),Mf=_i((([e,t])=>qo(1,e.oneMinus().div(t)).oneMinus())).setLayout({name:"blendBurn",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),Bf=_i((([e,t])=>qo(e.div(t.oneMinus()),1))).setLayout({name:"blendDodge",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),Uf=_i((([e,t])=>e.oneMinus().mul(t.oneMinus()).oneMinus())).setLayout({name:"blendScreen",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),Ff=_i((([e,t])=>la(e.mul(2).mul(t),e.oneMinus().mul(2).mul(t.oneMinus()).oneMinus(),Yo(.5,e)))).setLayout({name:"blendOverlay",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),Pf=_i((([e,t])=>{const r=t.a.add(e.a.mul(t.a.oneMinus()));return Oi(t.rgb.mul(t.a).add(e.rgb.mul(e.a).mul(t.a.oneMinus())).div(r),r)})).setLayout({name:"blendColor",type:"vec4",inputs:[{name:"base",type:"vec4"},{name:"blend",type:"vec4"}]}),If=_i((([e])=>Of(e.rgb))),Lf=_i((([e,t=Ci(1)])=>t.mix(Of(e.rgb),e.rgb))),Vf=_i((([e,t=Ci(1)])=>{const r=On(e.r,e.g,e.b).div(3),s=e.r.max(e.g.max(e.b)),i=s.sub(r).mul(t).mul(-3);return la(e.rgb,s,i)})),Df=_i((([e,t=Ci(1)])=>{const r=Ii(.57735,.57735,.57735),s=t.cos();return Ii(e.rgb.mul(s).add(r.cross(e.rgb).mul(t.sin()).add(r.mul(ea(r,e.rgb).mul(s.oneMinus())))))})),Of=(e,t=Ii(d.getLuminanceCoefficients(new r)))=>ea(e,t),Gf=_i((([e,t=Ii(1),s=Ii(0),i=Ii(1),n=Ci(1),o=Ii(d.getLuminanceCoefficients(new r,Ae))])=>{const a=e.rgb.dot(Ii(o)),u=Ko(e.rgb.mul(t).add(s),0).toVar(),l=u.pow(i).toVar();return Si(u.r.greaterThan(0),(()=>{u.r.assign(l.r)})),Si(u.g.greaterThan(0),(()=>{u.g.assign(l.g)})),Si(u.b.greaterThan(0),(()=>{u.b.assign(l.b)})),u.assign(a.add(u.sub(a).mul(n))),Oi(u.rgb,e.a)}));class kf extends Fs{static get type(){return"PosterizeNode"}constructor(e,t){super(),this.sourceNode=e,this.stepsNode=t}setup(){const{sourceNode:e,stepsNode:t}=this;return e.mul(t).floor().div(t)}}const zf=bi(kf),$f=new t;class Hf extends xu{static get type(){return"PassTextureNode"}constructor(e,t){super(t),this.passNode=e,this.setUpdateMatrix(!1)}setup(e){return e.object.isQuadMesh&&this.passNode.build(e),super.setup(e)}clone(){return new this.constructor(this.passNode,this.value)}}class Wf extends Hf{static get type(){return"PassMultipleTextureNode"}constructor(e,t,r=!1){super(e,null),this.textureName=t,this.previousTexture=r}updateTexture(){this.value=this.previousTexture?this.passNode.getPreviousTexture(this.textureName):this.passNode.getTexture(this.textureName)}setup(e){return this.updateTexture(),super.setup(e)}clone(){return new this.constructor(this.passNode,this.textureName,this.previousTexture)}}class jf extends Fs{static get type(){return"PassNode"}constructor(e,t,r,s={}){super("vec4"),this.scope=e,this.scene=t,this.camera=r,this.options=s,this._pixelRatio=1,this._width=1,this._height=1;const i=new B;i.isRenderTargetTexture=!0,i.name="depth";const n=new ge(this._width*this._pixelRatio,this._height*this._pixelRatio,{type:ye,...s});n.texture.name="output",n.depthTexture=i,this.renderTarget=n,this._textures={output:n.texture,depth:i},this._textureNodes={},this._linearDepthNodes={},this._viewZNodes={},this._previousTextures={},this._previousTextureNodes={},this._cameraNear=tn(0),this._cameraFar=tn(0),this._mrt=null,this.isPassNode=!0,this.updateBeforeType=vs.FRAME}setMRT(e){return this._mrt=e,this}getMRT(){return this._mrt}isGlobal(){return!0}getTexture(e){let t=this._textures[e];if(void 0===t){t=this.renderTarget.texture.clone(),t.name=e,this._textures[e]=t,this.renderTarget.textures.push(t)}return t}getPreviousTexture(e){let t=this._previousTextures[e];return void 0===t&&(t=this.getTexture(e).clone(),this._previousTextures[e]=t),t}toggleTexture(e){const t=this._previousTextures[e];if(void 0!==t){const r=this._textures[e],s=this.renderTarget.textures.indexOf(r);this.renderTarget.textures[s]=t,this._textures[e]=t,this._previousTextures[e]=r,this._textureNodes[e].updateTexture(),this._previousTextureNodes[e].updateTexture()}}getTextureNode(e="output"){let t=this._textureNodes[e];return void 0===t&&(t=fi(new Wf(this,e)),t.updateTexture(),this._textureNodes[e]=t),t}getPreviousTextureNode(e="output"){let t=this._previousTextureNodes[e];return void 0===t&&(void 0===this._textureNodes[e]&&this.getTextureNode(e),t=fi(new Wf(this,e,!0)),t.updateTexture(),this._previousTextureNodes[e]=t),t}getViewZNode(e="depth"){let t=this._viewZNodes[e];if(void 0===t){const r=this._cameraNear,s=this._cameraFar;this._viewZNodes[e]=t=Oc(this.getTextureNode(e),r,s)}return t}getLinearDepthNode(e="depth"){let t=this._linearDepthNodes[e];if(void 0===t){const r=this._cameraNear,s=this._cameraFar,i=this.getViewZNode(e);this._linearDepthNodes[e]=t=Vc(i,r,s)}return t}setup({renderer:e}){return this.renderTarget.samples=void 0===this.options.samples?e.samples:this.options.samples,!0===e.backend.isWebGLBackend&&(this.renderTarget.samples=0),this.scope===jf.COLOR?this.getTextureNode():this.getLinearDepthNode()}updateBefore(e){const{renderer:t}=e,{scene:r,camera:s}=this;this._pixelRatio=t.getPixelRatio();const i=t.getSize($f);this.setSize(i.width,i.height);const n=t.getRenderTarget(),o=t.getMRT();this._cameraNear.value=s.near,this._cameraFar.value=s.far;for(const e in this._previousTextures)this.toggleTexture(e);t.setRenderTarget(this.renderTarget),t.setMRT(this._mrt),t.render(r,s),t.setRenderTarget(n),t.setMRT(o)}setSize(e,t){this._width=e,this._height=t;const r=this._width*this._pixelRatio,s=this._height*this._pixelRatio;this.renderTarget.setSize(r,s)}setPixelRatio(e){this._pixelRatio=e,this.setSize(this._width,this._height)}dispose(){this.renderTarget.dispose()}}jf.COLOR="color",jf.DEPTH="depth";class qf extends jf{static get type(){return"ToonOutlinePassNode"}constructor(e,t,r,s,i){super(jf.COLOR,e,t),this.colorNode=r,this.thicknessNode=s,this.alphaNode=i,this._materialCache=new WeakMap}updateBefore(e){const{renderer:t}=e,r=t.getRenderObjectFunction();t.setRenderObjectFunction(((e,r,s,i,n,o,a,u)=>{if((n.isMeshToonMaterial||n.isMeshToonNodeMaterial)&&!1===n.wireframe){const l=this._getOutlineMaterial(n);t.renderObject(e,r,s,i,l,o,a,u)}t.renderObject(e,r,s,i,n,o,a,u)})),super.updateBefore(e),t.setRenderObjectFunction(r)}_createMaterial(){const e=new Yc;e.isMeshToonOutlineMaterial=!0,e.name="Toon_Outline",e.side=T;const t=il.negate(),r=Nu.mul($u),s=Ci(1),i=r.mul(Oi(Ku,1)),n=r.mul(Oi(Ku.add(t),1)),o=Ao(i.sub(n));return e.vertexNode=i.add(o.mul(this.thicknessNode).mul(i.w).mul(s)),e.colorNode=Oi(this.colorNode,this.alphaNode),e}_getOutlineMaterial(e){let t=this._materialCache.get(e);return void 0===t&&(t=this._createMaterial(),this._materialCache.set(e,t)),t}}const Kf=_i((([e,t])=>e.mul(t).clamp())).setLayout({name:"linearToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),Xf=_i((([e,t])=>(e=e.mul(t)).div(e.add(1)).clamp())).setLayout({name:"reinhardToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),Yf=_i((([e,t])=>{const r=(e=(e=e.mul(t)).sub(.004).max(0)).mul(e.mul(6.2).add(.5)),s=e.mul(e.mul(6.2).add(1.7)).add(.06);return r.div(s).pow(2.2)})).setLayout({name:"cineonToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),Qf=_i((([e])=>{const t=e.mul(e.add(.0245786)).sub(90537e-9),r=e.mul(e.add(.432951).mul(.983729)).add(.238081);return t.div(r)})),Zf=_i((([e,t])=>{const r=Hi(.59719,.35458,.04823,.076,.90834,.01566,.0284,.13383,.83777),s=Hi(1.60475,-.53108,-.07367,-.10208,1.10813,-.00605,-.00327,-.07276,1.07602);return e=e.mul(t).div(.6),e=r.mul(e),e=Qf(e),(e=s.mul(e)).clamp()})).setLayout({name:"acesFilmicToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),Jf=Hi(Ii(1.6605,-.1246,-.0182),Ii(-.5876,1.1329,-.1006),Ii(-.0728,-.0083,1.1187)),ey=Hi(Ii(.6274,.0691,.0164),Ii(.3293,.9195,.088),Ii(.0433,.0113,.8956)),ty=_i((([e])=>{const t=Ii(e).toVar(),r=Ii(t.mul(t)).toVar(),s=Ii(r.mul(r)).toVar();return Ci(15.5).mul(s.mul(r)).sub(kn(40.14,s.mul(t))).add(kn(31.96,s).sub(kn(6.868,r.mul(t))).add(kn(.4298,r).add(kn(.1191,t).sub(.00232))))})),ry=_i((([e,t])=>{const r=Ii(e).toVar(),s=Hi(Ii(.856627153315983,.137318972929847,.11189821299995),Ii(.0951212405381588,.761241990602591,.0767994186031903),Ii(.0482516061458583,.101439036467562,.811302368396859)),i=Hi(Ii(1.1271005818144368,-.1413297634984383,-.14132976349843826),Ii(-.11060664309660323,1.157823702216272,-.11060664309660294),Ii(-.016493938717834573,-.016493938717834257,1.2519364065950405)),n=Ci(-12.47393),o=Ci(4.026069);return r.mulAssign(t),r.assign(ey.mul(r)),r.assign(s.mul(r)),r.assign(Ko(r,1e-10)),r.assign(To(r)),r.assign(r.sub(n).div(o.sub(n))),r.assign(da(r,0,1)),r.assign(ty(r)),r.assign(i.mul(r)),r.assign(ra(Ko(Ii(0),r),Ii(2.2))),r.assign(Jf.mul(r)),r.assign(da(r,0,1)),r})).setLayout({name:"agxToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),sy=_i((([e,t])=>{const r=Ci(.76),s=Ci(.15);e=e.mul(t);const i=qo(e.r,qo(e.g,e.b)),n=Ta(i.lessThan(.08),i.sub(kn(6.25,i.mul(i))),.04);e.subAssign(n);const o=Ko(e.r,Ko(e.g,e.b));Si(o.lessThan(r),(()=>e));const a=Gn(1,r),u=Gn(1,a.mul(a).div(o.add(a.sub(r))));e.mulAssign(u.div(o));const l=Gn(1,zn(1,s.mul(o.sub(u)).add(1)));return la(e,Ii(u),l)})).setLayout({name:"neutralToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]});class iy extends Ms{static get type(){return"CodeNode"}constructor(e="",t=[],r=""){super("code"),this.isCodeNode=!0,this.code=e,this.includes=t,this.language=r}isGlobal(){return!0}setIncludes(e){return this.includes=e,this}getIncludes(){return this.includes}generate(e){const t=this.getIncludes(e);for(const r of t)r.build(e);const r=e.getCodeFromNode(this,this.getNodeType(e));return r.code=this.code,r.code}serialize(e){super.serialize(e),e.code=this.code,e.language=this.language}deserialize(e){super.deserialize(e),this.code=e.code,this.language=e.language}}const ny=bi(iy);class oy extends iy{static get type(){return"FunctionNode"}constructor(e="",t=[],r=""){super(e,t,r)}getNodeType(e){return this.getNodeFunction(e).type}getInputs(e){return this.getNodeFunction(e).inputs}getNodeFunction(e){const t=e.getDataFromNode(this);let r=t.nodeFunction;return void 0===r&&(r=e.parser.parseFunction(this.code),t.nodeFunction=r),r}generate(e,t){super.generate(e);const r=this.getNodeFunction(e),s=r.name,i=r.type,n=e.getCodeFromNode(this,i);""!==s&&(n.name=s);const o=e.getPropertyName(n),a=this.getNodeFunction(e).getCode(o);return n.code=a+"\n","property"===t?o:e.format(`${o}()`,i,t)}}const ay=(e,t=[],r="")=>{for(let e=0;es.call(...e);return i.functionNode=s,i};class uy extends Ms{static get type(){return"ScriptableValueNode"}constructor(e=null){super(),this._value=e,this._cache=null,this.inputType=null,this.outputType=null,this.events=new o,this.isScriptableValueNode=!0}get isScriptableOutputNode(){return null!==this.outputType}set value(e){this._value!==e&&(this._cache&&"URL"===this.inputType&&this.value.value instanceof ArrayBuffer&&(URL.revokeObjectURL(this._cache),this._cache=null),this._value=e,this.events.dispatchEvent({type:"change"}),this.refresh())}get value(){return this._value}refresh(){this.events.dispatchEvent({type:"refresh"})}getValue(){const e=this.value;if(e&&null===this._cache&&"URL"===this.inputType&&e.value instanceof ArrayBuffer)this._cache=URL.createObjectURL(new Blob([e.value]));else if(e&&null!==e.value&&void 0!==e.value&&(("URL"===this.inputType||"String"===this.inputType)&&"string"==typeof e.value||"Number"===this.inputType&&"number"==typeof e.value||"Vector2"===this.inputType&&e.value.isVector2||"Vector3"===this.inputType&&e.value.isVector3||"Vector4"===this.inputType&&e.value.isVector4||"Color"===this.inputType&&e.value.isColor||"Matrix3"===this.inputType&&e.value.isMatrix3||"Matrix4"===this.inputType&&e.value.isMatrix4))return e.value;return this._cache||e}getNodeType(e){return this.value&&this.value.isNode?this.value.getNodeType(e):"float"}setup(){return this.value&&this.value.isNode?this.value:Ci()}serialize(e){super.serialize(e),null!==this.value?"ArrayBuffer"===this.inputType?e.value=xs(this.value):e.value=this.value?this.value.toJSON(e.meta).uuid:null:e.value=null,e.inputType=this.inputType,e.outputType=this.outputType}deserialize(e){super.deserialize(e);let t=null;null!==e.value&&(t="ArrayBuffer"===e.inputType?bs(e.value):"Texture"===e.inputType?e.meta.textures[e.value]:e.meta.nodes[e.value]||null),this.value=t,this.inputType=e.inputType,this.outputType=e.outputType}}const ly=bi(uy);class dy extends Map{get(e,t=null,...r){if(this.has(e))return super.get(e);if(null!==t){const s=t(...r);return this.set(e,s),s}}}class cy{constructor(e){this.scriptableNode=e}get parameters(){return this.scriptableNode.parameters}get layout(){return this.scriptableNode.getLayout()}getInputLayout(e){return this.scriptableNode.getInputLayout(e)}get(e){const t=this.parameters[e];return t?t.getValue():null}}const hy=new dy;class py extends Ms{static get type(){return"ScriptableNode"}constructor(e=null,t={}){super(),this.codeNode=e,this.parameters=t,this._local=new dy,this._output=ly(),this._outputs={},this._source=this.source,this._method=null,this._object=null,this._value=null,this._needsOutputUpdate=!0,this.onRefresh=this.onRefresh.bind(this),this.isScriptableNode=!0}get source(){return this.codeNode?this.codeNode.code:""}setLocal(e,t){return this._local.set(e,t)}getLocal(e){return this._local.get(e)}onRefresh(){this._refresh()}getInputLayout(e){for(const t of this.getLayout())if(t.inputType&&(t.id===e||t.name===e))return t}getOutputLayout(e){for(const t of this.getLayout())if(t.outputType&&(t.id===e||t.name===e))return t}setOutput(e,t){const r=this._outputs;return void 0===r[e]?r[e]=ly(t):r[e].value=t,this}getOutput(e){return this._outputs[e]}getParameter(e){return this.parameters[e]}setParameter(e,t){const r=this.parameters;return t&&t.isScriptableNode?(this.deleteParameter(e),r[e]=t,r[e].getDefaultOutput().events.addEventListener("refresh",this.onRefresh)):t&&t.isScriptableValueNode?(this.deleteParameter(e),r[e]=t,r[e].events.addEventListener("refresh",this.onRefresh)):void 0===r[e]?(r[e]=ly(t),r[e].events.addEventListener("refresh",this.onRefresh)):r[e].value=t,this}getValue(){return this.getDefaultOutput().getValue()}deleteParameter(e){let t=this.parameters[e];return t&&(t.isScriptableNode&&(t=t.getDefaultOutput()),t.events.removeEventListener("refresh",this.onRefresh)),this}clearParameters(){for(const e of Object.keys(this.parameters))this.deleteParameter(e);return this.needsUpdate=!0,this}call(e,...t){const r=this.getObject()[e];if("function"==typeof r)return r(...t)}async callAsync(e,...t){const r=this.getObject()[e];if("function"==typeof r)return"AsyncFunction"===r.constructor.name?await r(...t):r(...t)}getNodeType(e){return this.getDefaultOutputNode().getNodeType(e)}refresh(e=null){null!==e?this.getOutput(e).refresh():this._refresh()}getObject(){if(this.needsUpdate&&this.dispose(),null!==this._object)return this._object;const e=new cy(this),t=hy.get("THREE"),r=hy.get("TSL"),s=this.getMethod(this.codeNode),i=[e,this._local,hy,()=>this.refresh(),(e,t)=>this.setOutput(e,t),t,r];this._object=s(...i);const n=this._object.layout;if(n&&(!1===n.cache&&this._local.clear(),this._output.outputType=n.outputType||null,Array.isArray(n.elements)))for(const e of n.elements){const t=e.id||e.name;e.inputType&&(void 0===this.getParameter(t)&&this.setParameter(t,null),this.getParameter(t).inputType=e.inputType),e.outputType&&(void 0===this.getOutput(t)&&this.setOutput(t,null),this.getOutput(t).outputType=e.outputType)}return this._object}deserialize(e){super.deserialize(e);for(const e in this.parameters){let t=this.parameters[e];t.isScriptableNode&&(t=t.getDefaultOutput()),t.events.addEventListener("refresh",this.onRefresh)}}getLayout(){return this.getObject().layout}getDefaultOutputNode(){const e=this.getDefaultOutput().value;return e&&e.isNode?e:Ci()}getDefaultOutput(){return this._exec()._output}getMethod(){if(this.needsUpdate&&this.dispose(),null!==this._method)return this._method;const e=["layout","init","main","dispose"].join(", "),t="\nreturn { ...output, "+e+" };",r="var "+e+"; var output = {};\n"+this.codeNode.code+t;return this._method=new Function(...["parameters","local","global","refresh","setOutput","THREE","TSL"],r),this._method}dispose(){null!==this._method&&(this._object&&"function"==typeof this._object.dispose&&this._object.dispose(),this._method=null,this._object=null,this._source=null,this._value=null,this._needsOutputUpdate=!0,this._output.value=null,this._outputs={})}setup(){return this.getDefaultOutputNode()}getCacheKey(e){const t=[us(this.source),this.getDefaultOutputNode().getCacheKey(e)];for(const r in this.parameters)t.push(this.parameters[r].getCacheKey(e));return ls(t)}set needsUpdate(e){!0===e&&this.dispose()}get needsUpdate(){return this.source!==this._source}_exec(){return null===this.codeNode||(!0===this._needsOutputUpdate&&(this._value=this.call("main"),this._needsOutputUpdate=!1),this._output.value=this._value),this}_refresh(){this.needsUpdate=!0,this._exec(),this._output.refresh()}}const gy=bi(py);function my(e){let t;const r=e.context.getViewZ;return void 0!==r&&(t=r(this)),(t||Zu.z).negate()}const fy=_i((([e,t],r)=>{const s=my(r);return pa(e,t,s)})),yy=_i((([e],t)=>{const r=my(t);return e.mul(e,r,r).negate().exp().oneMinus()})),xy=_i((([e,t])=>Oi(t.toFloat().mix(Sn.rgb,e.toVec3()),Sn.a)));let by=null,Ty=null;class _y extends Ms{static get type(){return"RangeNode"}constructor(e=Ci(),t=Ci()){super(),this.minNode=e,this.maxNode=t}getVectorLength(e){const t=e.getTypeLength(fs(this.minNode.value)),r=e.getTypeLength(fs(this.maxNode.value));return t>r?t:r}getNodeType(e){return e.object.count>1?e.getTypeFromLength(this.getVectorLength(e)):"float"}setup(e){const t=e.object;let r=null;if(t.count>1){const i=this.minNode.value,n=this.maxNode.value,o=e.getTypeLength(fs(i)),u=e.getTypeLength(fs(n));by=by||new s,Ty=Ty||new s,by.setScalar(0),Ty.setScalar(0),1===o?by.setScalar(i):i.isColor?by.set(i.r,i.g,i.b,1):by.set(i.x,i.y,i.z||0,i.w||0),1===u?Ty.setScalar(n):n.isColor?Ty.set(n.r,n.g,n.b,1):Ty.set(n.x,n.y,n.z||0,n.w||0);const l=4,d=l*t.count,c=new Float32Array(d);for(let e=0;efi(new Ny(e,t)),Ay=Sy("numWorkgroups","uvec3"),Ry=Sy("workgroupId","uvec3"),Cy=Sy("localId","uvec3"),Ey=Sy("subgroupSize","uint");const wy=bi(class extends Ms{constructor(e){super(),this.scope=e}generate(e){const{scope:t}=this,{renderer:r}=e;!0===r.backend.isWebGLBackend?e.addFlowCode(`\t// ${t}Barrier \n`):e.addLineFlowCode(`${t}Barrier()`,this)}});class My extends Bs{constructor(e,t){super(e,t),this.isWorkgroupInfoElementNode=!0}generate(e,t){let r;const s=e.context.assign;if(r=super.generate(e),!0!==s){const s=this.getNodeType(e);r=e.format(r,s,t)}return r}}class By extends Ms{constructor(e,t,r=0){super(t),this.bufferType=t,this.bufferCount=r,this.isWorkgroupInfoNode=!0,this.scope=e}label(e){return this.name=e,this}setScope(e){return this.scope=e,this}getInputType(){return`${this.scope}Array`}element(e){return fi(new My(this,e))}generate(e){return e.getScopedArray(this.name||`${this.scope}Array_${this.id}`,this.scope.toLowerCase(),this.bufferType,this.bufferCount)}}class Uy extends Fs{static get type(){return"AtomicFunctionNode"}constructor(e,t,r,s=null){super("uint"),this.method=e,this.pointerNode=t,this.valueNode=r,this.storeNode=s}getInputType(e){return this.pointerNode.getNodeType(e)}getNodeType(e){return this.getInputType(e)}generate(e){const t=this.method,r=this.getNodeType(e),s=this.getInputType(e),i=this.pointerNode,n=this.valueNode,o=[];o.push(`&${i.build(e,s)}`),o.push(n.build(e,s));const a=`${e.getMethod(t,r)}( ${o.join(", ")} )`;if(null!==this.storeNode){const t=this.storeNode.build(e,s);e.addLineFlowCode(`${t} = ${a}`,this)}else e.addLineFlowCode(a,this)}}Uy.ATOMIC_LOAD="atomicLoad",Uy.ATOMIC_STORE="atomicStore",Uy.ATOMIC_ADD="atomicAdd",Uy.ATOMIC_SUB="atomicSub",Uy.ATOMIC_MAX="atomicMax",Uy.ATOMIC_MIN="atomicMin",Uy.ATOMIC_AND="atomicAnd",Uy.ATOMIC_OR="atomicOr",Uy.ATOMIC_XOR="atomicXor";const Fy=bi(Uy),Py=(e,t,r,s=null)=>{const i=Fy(e,t,r,s);return i.append(),i};let Iy;function Ly(e){Iy=Iy||new WeakMap;let t=Iy.get(e);return void 0===t&&Iy.set(e,t={}),t}function Vy(e){const t=Ly(e);return t.shadowMatrix||(t.shadowMatrix=tn("mat4").setGroup(Zi).onRenderUpdate((()=>(!0!==e.castShadow&&e.shadow.updateMatrices(e),e.shadow.matrix))))}function Dy(e){const t=Ly(e);if(void 0===t.projectionUV){const r=Vy(e).mul(Yu);t.projectionUV=r.xyz.div(r.w)}return t.projectionUV}function Oy(e){const t=Ly(e);return t.position||(t.position=tn(new r).setGroup(Zi).onRenderUpdate(((t,r)=>r.value.setFromMatrixPosition(e.matrixWorld))))}function Gy(e){const t=Ly(e);return t.targetPosition||(t.targetPosition=tn(new r).setGroup(Zi).onRenderUpdate(((t,r)=>r.value.setFromMatrixPosition(e.target.matrixWorld))))}function ky(e){const t=Ly(e);return t.viewPosition||(t.viewPosition=tn(new r).setGroup(Zi).onRenderUpdate((({camera:t},s)=>{s.value=s.value||new r,s.value.setFromMatrixPosition(e.matrixWorld),s.value.applyMatrix4(t.matrixWorldInverse)})))}const zy=e=>Au.transformDirection(Oy(e).sub(Gy(e))),$y=(e,t)=>{for(const r of t)if(r.isAnalyticLightNode&&r.light.id===e)return r;return null},Hy=new WeakMap;class Wy extends Ms{static get type(){return"LightsNode"}constructor(){super("vec3"),this.totalDiffuseNode=Ii().toVar("totalDiffuse"),this.totalSpecularNode=Ii().toVar("totalSpecular"),this.outgoingLightNode=Ii().toVar("outgoingLight"),this._lights=[],this._lightNodes=null,this._lightNodesHash=null,this.global=!0}customCacheKey(){const e=[],t=this._lights;for(let r=0;re.sort(((e,t)=>e.id-t.id)))(this._lights),i=e.renderer.library;for(const e of s)if(e.isNode)t.push(fi(e));else{let s=null;if(null!==r&&(s=$y(e.id,r)),null===s){const r=i.getLightNodeClass(e.constructor);if(null===r){console.warn(`LightsNode.setupNodeLights: Light node not found for ${e.constructor.name}`);continue}let s=null;Hy.has(e)?s=Hy.get(e):(s=fi(new r(e)),Hy.set(e,s)),t.push(s)}}this._lightNodes=t}setupLights(e,t){for(const r of t)r.build(e)}setup(e){null===this._lightNodes&&this.setupLightsNode(e);const t=e.context,r=t.lightingModel;let s=this.outgoingLightNode;if(r){const{_lightNodes:i,totalDiffuseNode:n,totalSpecularNode:o}=this;t.outgoingLight=s;const a=e.addStack();e.getDataFromNode(this).nodes=a.nodes,r.start(t,a,e),this.setupLights(e,i),r.indirect(t,a,e);const{backdrop:u,backdropAlpha:l}=t,{directDiffuse:d,directSpecular:c,indirectDiffuse:h,indirectSpecular:p}=t.reflectedLight;let g=d.add(h);null!==u&&(g=Ii(null!==l?l.mix(g,u):u),t.material.transparent=!0),n.assign(g),o.assign(c.add(p)),s.assign(n.add(o)),r.finish(t,a,e),s=s.bypass(e.removeStack())}return s}setLights(e){return this._lights=e,this._lightNodes=null,this._lightNodesHash=null,this}getLights(){return this._lights}get hasLights(){return this._lights.length>0}}class jy extends Ms{static get type(){return"ShadowBaseNode"}constructor(e){super(),this.light=e,this.updateBeforeType=vs.RENDER,this.isShadowBaseNode=!0}setupShadowPosition({material:e}){qy.assign(e.shadowPositionNode||Yu)}dispose(){this.updateBeforeType=vs.NONE}}const qy=Ii().toVar("shadowWorldPosition"),Ky=new WeakMap,Xy=_i((([e,t,r])=>{let s=Yu.sub(e).length();return s=s.sub(t).div(r.sub(t)),s=s.saturate(),s})),Yy=e=>{let t=Ky.get(e);if(void 0===t){const r=e.isPointLight?(e=>{const t=e.shadow.camera,r=Cl("near","float",t).setGroup(Zi),s=Cl("far","float",t).setGroup(Zi),i=Uu(e);return Xy(i,r,s)})(e):null;t=new Yc,t.colorNode=Oi(0,0,0,1),t.depthNode=r,t.isShadowNodeMaterial=!0,t.name="ShadowMaterial",Ky.set(e,t)}return t},Qy=_i((({depthTexture:e,shadowCoord:t})=>bu(e,t.xy).compare(t.z))),Zy=_i((({depthTexture:e,shadowCoord:t,shadow:r})=>{const s=(t,r)=>bu(e,t).compare(r),i=Cl("mapSize","vec2",r).setGroup(Zi),n=Cl("radius","float",r).setGroup(Zi),o=Bi(1).div(i),a=o.x.negate().mul(n),u=o.y.negate().mul(n),l=o.x.mul(n),d=o.y.mul(n),c=a.div(2),h=u.div(2),p=l.div(2),g=d.div(2);return On(s(t.xy.add(Bi(a,u)),t.z),s(t.xy.add(Bi(0,u)),t.z),s(t.xy.add(Bi(l,u)),t.z),s(t.xy.add(Bi(c,h)),t.z),s(t.xy.add(Bi(0,h)),t.z),s(t.xy.add(Bi(p,h)),t.z),s(t.xy.add(Bi(a,0)),t.z),s(t.xy.add(Bi(c,0)),t.z),s(t.xy,t.z),s(t.xy.add(Bi(p,0)),t.z),s(t.xy.add(Bi(l,0)),t.z),s(t.xy.add(Bi(c,g)),t.z),s(t.xy.add(Bi(0,g)),t.z),s(t.xy.add(Bi(p,g)),t.z),s(t.xy.add(Bi(a,d)),t.z),s(t.xy.add(Bi(0,d)),t.z),s(t.xy.add(Bi(l,d)),t.z)).mul(1/17)})),Jy=_i((({depthTexture:e,shadowCoord:t,shadow:r})=>{const s=(t,r)=>bu(e,t).compare(r),i=Cl("mapSize","vec2",r).setGroup(Zi),n=Bi(1).div(i),o=n.x,a=n.y,u=t.xy,l=Ro(u.mul(i).add(.5));return u.subAssign(l.mul(n)),On(s(u,t.z),s(u.add(Bi(o,0)),t.z),s(u.add(Bi(0,a)),t.z),s(u.add(n),t.z),la(s(u.add(Bi(o.negate(),0)),t.z),s(u.add(Bi(o.mul(2),0)),t.z),l.x),la(s(u.add(Bi(o.negate(),a)),t.z),s(u.add(Bi(o.mul(2),a)),t.z),l.x),la(s(u.add(Bi(0,a.negate())),t.z),s(u.add(Bi(0,a.mul(2))),t.z),l.y),la(s(u.add(Bi(o,a.negate())),t.z),s(u.add(Bi(o,a.mul(2))),t.z),l.y),la(la(s(u.add(Bi(o.negate(),a.negate())),t.z),s(u.add(Bi(o.mul(2),a.negate())),t.z),l.x),la(s(u.add(Bi(o.negate(),a.mul(2))),t.z),s(u.add(Bi(o.mul(2),a.mul(2))),t.z),l.x),l.y)).mul(1/9)})),ex=_i((({depthTexture:e,shadowCoord:t})=>{const r=Ci(1).toVar(),s=bu(e).sample(t.xy).rg,i=Yo(t.z,s.x);return Si(i.notEqual(Ci(1)),(()=>{const e=t.z.sub(s.x),n=Ko(0,s.y.mul(s.y));let o=n.div(n.add(e.mul(e)));o=da(Gn(o,.3).div(.95-.3)),r.assign(da(Ko(i,o)))})),r})),tx=_i((({samples:e,radius:t,size:r,shadowPass:s})=>{const i=Ci(0).toVar(),n=Ci(0).toVar(),o=e.lessThanEqual(Ci(1)).select(Ci(0),Ci(2).div(e.sub(1))),a=e.lessThanEqual(Ci(1)).select(Ci(0),Ci(-1));ic({start:Ei(0),end:Ei(e),type:"int",condition:"<"},(({i:e})=>{const u=a.add(Ci(e).mul(o)),l=s.sample(On(_c.xy,Bi(0,u).mul(t)).div(r)).x;i.addAssign(l),n.addAssign(l.mul(l))})),i.divAssign(e),n.divAssign(e);const u=_o(n.sub(i.mul(i)));return Bi(i,u)})),rx=_i((({samples:e,radius:t,size:r,shadowPass:s})=>{const i=Ci(0).toVar(),n=Ci(0).toVar(),o=e.lessThanEqual(Ci(1)).select(Ci(0),Ci(2).div(e.sub(1))),a=e.lessThanEqual(Ci(1)).select(Ci(0),Ci(-1));ic({start:Ei(0),end:Ei(e),type:"int",condition:"<"},(({i:e})=>{const u=a.add(Ci(e).mul(o)),l=s.sample(On(_c.xy,Bi(u,0).mul(t)).div(r));i.addAssign(l.x),n.addAssign(On(l.y.mul(l.y),l.x.mul(l.x)))})),i.divAssign(e),n.divAssign(e);const u=_o(n.sub(i.mul(i)));return Bi(i,u)})),sx=[Qy,Zy,Jy,ex],ix=new Jm;class nx extends jy{static get type(){return"ShadowNode"}constructor(e,t=null){super(e),this.shadow=t||e.shadow,this.shadowMap=null,this.vsmShadowMapVertical=null,this.vsmShadowMapHorizontal=null,this.vsmMaterialVertical=null,this.vsmMaterialHorizontal=null,this._node=null,this.isShadowNode=!0}setupShadowFilter(e,{filterFn:t,depthTexture:r,shadowCoord:s,shadow:i}){const n=s.x.greaterThanEqual(0).and(s.x.lessThanEqual(1)).and(s.y.greaterThanEqual(0)).and(s.y.lessThanEqual(1)).and(s.z.lessThanEqual(1)),o=t({depthTexture:r,shadowCoord:s,shadow:i});return n.select(o,Ci(1))}setupShadowCoord(e,t){const{shadow:r}=this,{renderer:s}=e,i=Cl("bias","float",r).setGroup(Zi);let n,o=t;if(r.camera.isOrthographicCamera||!0!==s.logarithmicDepthBuffer)o=o.xyz.div(o.w),n=o.z,s.coordinateSystem===l&&(n=n.mul(2).sub(1));else{const e=o.w;o=o.xy.div(e);const t=Cl("near","float",r.camera).setGroup(Zi),s=Cl("far","float",r.camera).setGroup(Zi);n=Gc(e.negate(),t,s)}return o=Ii(o.x,o.y.oneMinus(),n.add(i)),o}getShadowFilterFn(e){return sx[e]}setupShadow(e){const{renderer:t}=e,{light:r,shadow:s}=this,i=t.shadowMap.type,n=new B(s.mapSize.width,s.mapSize.height);n.compareFunction=Re;const o=e.createRenderTarget(s.mapSize.width,s.mapSize.height);if(o.depthTexture=n,s.camera.updateProjectionMatrix(),i===Ce){n.compareFunction=null,this.vsmShadowMapVertical=e.createRenderTarget(s.mapSize.width,s.mapSize.height,{format:Ee,type:ye}),this.vsmShadowMapHorizontal=e.createRenderTarget(s.mapSize.width,s.mapSize.height,{format:Ee,type:ye});const t=bu(n),r=bu(this.vsmShadowMapVertical.texture),i=Cl("blurSamples","float",s).setGroup(Zi),o=Cl("radius","float",s).setGroup(Zi),a=Cl("mapSize","vec2",s).setGroup(Zi);let u=this.vsmMaterialVertical||(this.vsmMaterialVertical=new Yc);u.fragmentNode=tx({samples:i,radius:o,size:a,shadowPass:t}).context(e.getSharedContext()),u.name="VSMVertical",u=this.vsmMaterialHorizontal||(this.vsmMaterialHorizontal=new Yc),u.fragmentNode=rx({samples:i,radius:o,size:a,shadowPass:r}).context(e.getSharedContext()),u.name="VSMHorizontal"}const a=Cl("intensity","float",s).setGroup(Zi),u=Cl("normalBias","float",s).setGroup(Zi),l=Vy(r).mul(qy.add(ll.mul(u))),d=this.setupShadowCoord(e,l),c=s.filterNode||this.getShadowFilterFn(t.shadowMap.type)||null;if(null===c)throw new Error("THREE.WebGPURenderer: Shadow map type not supported yet.");const h=i===Ce?this.vsmShadowMapHorizontal.texture:n,p=this.setupShadowFilter(e,{filterFn:c,shadowTexture:o.texture,depthTexture:h,shadowCoord:d,shadow:s}),g=bu(o.texture,d),m=la(1,p.rgb.mix(g,1),a.mul(g.a)).toVar();return this.shadowMap=o,this.shadow.map=o,m}setup(e){if(!1!==e.renderer.shadowMap.enabled)return _i((()=>{let t=this._node;return this.setupShadowPosition(e),null===t&&(this._node=t=this.setupShadow(e)),e.material.shadowNode&&console.warn('THREE.NodeMaterial: ".shadowNode" is deprecated. Use ".castShadowNode" instead.'),e.material.receivedShadowNode&&(t=e.material.receivedShadowNode(t)),t}))()}renderShadow(e){const{shadow:t,shadowMap:r,light:s}=this,{renderer:i,scene:n}=e;t.updateMatrices(s),r.setSize(t.mapSize.width,t.mapSize.height),i.render(n,t.camera)}updateShadow(e){const{shadowMap:t,light:r,shadow:s}=this,{renderer:i,scene:n,camera:o}=e,a=i.shadowMap.type,u=t.depthTexture.version;this._depthVersionCached=u;const l=n.overrideMaterial;n.overrideMaterial=Yy(r),s.camera.layers.mask=o.layers.mask;const d=i.getRenderTarget(),c=i.getRenderObjectFunction(),h=i.getMRT();i.setMRT(null),i.setRenderObjectFunction(((e,t,r,n,u,l,...d)=>{(!0===e.castShadow||e.receiveShadow&&a===Ce)&&(e.onBeforeShadow(i,e,o,s.camera,n,t.overrideMaterial,l),i.renderObject(e,t,r,n,u,l,...d),e.onAfterShadow(i,e,o,s.camera,n,t.overrideMaterial,l))})),i.setRenderTarget(t),this.renderShadow(e),i.setRenderObjectFunction(c),!0!==r.isPointLight&&a===Ce&&this.vsmPass(i),i.setRenderTarget(d),i.setMRT(h),n.overrideMaterial=l}vsmPass(e){const{shadow:t}=this;this.vsmShadowMapVertical.setSize(t.mapSize.width,t.mapSize.height),this.vsmShadowMapHorizontal.setSize(t.mapSize.width,t.mapSize.height),e.setRenderTarget(this.vsmShadowMapVertical),ix.material=this.vsmMaterialVertical,ix.render(e),e.setRenderTarget(this.vsmShadowMapHorizontal),ix.material=this.vsmMaterialHorizontal,ix.render(e)}dispose(){this.shadowMap.dispose(),this.shadowMap=null,null!==this.vsmShadowMapVertical&&(this.vsmShadowMapVertical.dispose(),this.vsmShadowMapVertical=null,this.vsmMaterialVertical.dispose(),this.vsmMaterialVertical=null),null!==this.vsmShadowMapHorizontal&&(this.vsmShadowMapHorizontal.dispose(),this.vsmShadowMapHorizontal=null,this.vsmMaterialHorizontal.dispose(),this.vsmMaterialHorizontal=null),super.dispose()}updateBefore(e){const{shadow:t}=this;(t.needsUpdate||t.autoUpdate)&&(this.updateShadow(e),this.shadowMap.depthTexture.version===this._depthVersionCached&&(t.needsUpdate=!1))}}const ox=(e,t)=>fi(new nx(e,t));class ax extends cc{static get type(){return"AnalyticLightNode"}constructor(t=null){super(),this.light=t,this.color=new e,this.colorNode=t&&t.colorNode||tn(this.color).setGroup(Zi),this.baseColorNode=null,this.shadowNode=null,this.shadowColorNode=null,this.isAnalyticLightNode=!0,this.updateType=vs.FRAME}customCacheKey(){return ds(this.light.id,this.light.castShadow?1:0)}getHash(){return this.light.uuid}setupShadowNode(){return ox(this.light)}setupShadow(e){const{renderer:t}=e;if(!1===t.shadowMap.enabled)return;let r=this.shadowColorNode;if(null===r){const t=this.light.shadow.shadowNode;let s;s=void 0!==t?fi(t):this.setupShadowNode(e),this.shadowNode=s,this.shadowColorNode=r=this.colorNode.mul(s),this.baseColorNode=this.colorNode}this.colorNode=r}setup(e){this.colorNode=this.baseColorNode||this.colorNode,this.light.castShadow?e.object.receiveShadow&&this.setupShadow(e):null!==this.shadowNode&&(this.shadowNode.dispose(),this.shadowNode=null,this.shadowColorNode=null)}update(){const{light:e}=this;this.color.copy(e.color).multiplyScalar(e.intensity)}}const ux=_i((e=>{const{lightDistance:t,cutoffDistance:r,decayExponent:s}=e,i=t.pow(s).max(.01).reciprocal();return r.greaterThan(0).select(i.mul(t.div(r).pow4().oneMinus().clamp().pow2()),i)})),lx=new e,dx=_i((([e,t])=>{const r=e.toVar(),s=Fo(r),i=zn(1,Ko(s.x,Ko(s.y,s.z)));s.mulAssign(i),r.mulAssign(i.mul(t.mul(2).oneMinus()));const n=Bi(r.xy).toVar(),o=t.mul(1.5).oneMinus();return Si(s.z.greaterThanEqual(o),(()=>{Si(r.z.greaterThan(0),(()=>{n.x.assign(Gn(4,r.x))}))})).ElseIf(s.x.greaterThanEqual(o),(()=>{const e=Po(r.x);n.x.assign(r.z.mul(e).add(e.mul(2)))})).ElseIf(s.y.greaterThanEqual(o),(()=>{const e=Po(r.y);n.x.assign(r.x.add(e.mul(2)).add(2)),n.y.assign(r.z.mul(e).sub(2))})),Bi(.125,.25).mul(n).add(Bi(.375,.75)).flipY()})).setLayout({name:"cubeToUV",type:"vec2",inputs:[{name:"pos",type:"vec3"},{name:"texelSizeY",type:"float"}]}),cx=_i((({depthTexture:e,bd3D:t,dp:r,texelSize:s})=>bu(e,dx(t,s.y)).compare(r))),hx=_i((({depthTexture:e,bd3D:t,dp:r,texelSize:s,shadow:i})=>{const n=Cl("radius","float",i).setGroup(Zi),o=Bi(-1,1).mul(n).mul(s.y);return bu(e,dx(t.add(o.xyy),s.y)).compare(r).add(bu(e,dx(t.add(o.yyy),s.y)).compare(r)).add(bu(e,dx(t.add(o.xyx),s.y)).compare(r)).add(bu(e,dx(t.add(o.yyx),s.y)).compare(r)).add(bu(e,dx(t,s.y)).compare(r)).add(bu(e,dx(t.add(o.xxy),s.y)).compare(r)).add(bu(e,dx(t.add(o.yxy),s.y)).compare(r)).add(bu(e,dx(t.add(o.xxx),s.y)).compare(r)).add(bu(e,dx(t.add(o.yxx),s.y)).compare(r)).mul(1/9)})),px=_i((({filterFn:e,depthTexture:t,shadowCoord:r,shadow:s})=>{const i=r.xyz.toVar(),n=i.length(),o=tn("float").setGroup(Zi).onRenderUpdate((()=>s.camera.near)),a=tn("float").setGroup(Zi).onRenderUpdate((()=>s.camera.far)),u=Cl("bias","float",s).setGroup(Zi),l=tn(s.mapSize).setGroup(Zi),d=Ci(1).toVar();return Si(n.sub(a).lessThanEqual(0).and(n.sub(o).greaterThanEqual(0)),(()=>{const r=n.sub(o).div(a.sub(o)).toVar();r.addAssign(u);const c=i.normalize(),h=Bi(1).div(l.mul(Bi(4,2)));d.assign(e({depthTexture:t,bd3D:c,dp:r,texelSize:h,shadow:s}))})),d})),gx=new s,mx=new t,fx=new t;class yx extends nx{static get type(){return"PointShadowNode"}constructor(e,t=null){super(e,t)}getShadowFilterFn(e){return e===we?cx:hx}setupShadowCoord(e,t){return t}setupShadowFilter(e,{filterFn:t,shadowTexture:r,depthTexture:s,shadowCoord:i,shadow:n}){return px({filterFn:t,shadowTexture:r,depthTexture:s,shadowCoord:i,shadow:n})}renderShadow(e){const{shadow:t,shadowMap:r,light:s}=this,{renderer:i,scene:n}=e,o=t.getFrameExtents();fx.copy(t.mapSize),fx.multiply(o),r.setSize(fx.width,fx.height),mx.copy(t.mapSize);const a=i.autoClear,u=i.getClearColor(lx),l=i.getClearAlpha();i.autoClear=!1,i.setClearColor(t.clearColor,t.clearAlpha),i.clear();const d=t.getViewportCount();for(let e=0;e{const n=i.context.lightingModel,o=t.sub(Zu),a=o.normalize(),u=o.length(),l=ux({lightDistance:u,cutoffDistance:r,decayExponent:s}),d=e.mul(l),c=i.context.reflectedLight;n.direct({lightDirection:a,lightColor:d,reflectedLight:c},i.stack,i)}));class bx extends ax{static get type(){return"PointLightNode"}constructor(e=null){super(e),this.cutoffDistanceNode=tn(0).setGroup(Zi),this.decayExponentNode=tn(2).setGroup(Zi)}update(e){const{light:t}=this;super.update(e),this.cutoffDistanceNode.value=t.distance,this.decayExponentNode.value=t.decay}setupShadowNode(){return((e,t)=>fi(new yx(e,t)))(this.light)}setup(e){super.setup(e),xx({color:this.colorNode,lightViewPosition:ky(this.light),cutoffDistance:this.cutoffDistanceNode,decayExponent:this.decayExponentNode}).append()}}const Tx=_i((([e=t()])=>{const t=e.mul(2),r=t.x.floor(),s=t.y.floor();return r.add(s).mod(2).sign()})),_x=_i((([e,t,r])=>{const s=Ci(r).toVar(),i=Ci(t).toVar(),n=Mi(e).toVar();return Ta(n,i,s)})).setLayout({name:"mx_select",type:"float",inputs:[{name:"b",type:"bool"},{name:"t",type:"float"},{name:"f",type:"float"}]}),vx=_i((([e,t])=>{const r=Mi(t).toVar(),s=Ci(e).toVar();return Ta(r,s.negate(),s)})).setLayout({name:"mx_negate_if",type:"float",inputs:[{name:"val",type:"float"},{name:"b",type:"bool"}]}),Nx=_i((([e])=>{const t=Ci(e).toVar();return Ei(No(t))})).setLayout({name:"mx_floor",type:"int",inputs:[{name:"x",type:"float"}]}),Sx=_i((([e,t])=>{const r=Ci(e).toVar();return t.assign(Nx(r)),r.sub(Ci(t))})),Ax=vm([_i((([e,t,r,s,i,n])=>{const o=Ci(n).toVar(),a=Ci(i).toVar(),u=Ci(s).toVar(),l=Ci(r).toVar(),d=Ci(t).toVar(),c=Ci(e).toVar(),h=Ci(Gn(1,a)).toVar();return Gn(1,o).mul(c.mul(h).add(d.mul(a))).add(o.mul(l.mul(h).add(u.mul(a))))})).setLayout({name:"mx_bilerp_0",type:"float",inputs:[{name:"v0",type:"float"},{name:"v1",type:"float"},{name:"v2",type:"float"},{name:"v3",type:"float"},{name:"s",type:"float"},{name:"t",type:"float"}]}),_i((([e,t,r,s,i,n])=>{const o=Ci(n).toVar(),a=Ci(i).toVar(),u=Ii(s).toVar(),l=Ii(r).toVar(),d=Ii(t).toVar(),c=Ii(e).toVar(),h=Ci(Gn(1,a)).toVar();return Gn(1,o).mul(c.mul(h).add(d.mul(a))).add(o.mul(l.mul(h).add(u.mul(a))))})).setLayout({name:"mx_bilerp_1",type:"vec3",inputs:[{name:"v0",type:"vec3"},{name:"v1",type:"vec3"},{name:"v2",type:"vec3"},{name:"v3",type:"vec3"},{name:"s",type:"float"},{name:"t",type:"float"}]})]),Rx=vm([_i((([e,t,r,s,i,n,o,a,u,l,d])=>{const c=Ci(d).toVar(),h=Ci(l).toVar(),p=Ci(u).toVar(),g=Ci(a).toVar(),m=Ci(o).toVar(),f=Ci(n).toVar(),y=Ci(i).toVar(),x=Ci(s).toVar(),b=Ci(r).toVar(),T=Ci(t).toVar(),_=Ci(e).toVar(),v=Ci(Gn(1,p)).toVar(),N=Ci(Gn(1,h)).toVar();return Ci(Gn(1,c)).toVar().mul(N.mul(_.mul(v).add(T.mul(p))).add(h.mul(b.mul(v).add(x.mul(p))))).add(c.mul(N.mul(y.mul(v).add(f.mul(p))).add(h.mul(m.mul(v).add(g.mul(p))))))})).setLayout({name:"mx_trilerp_0",type:"float",inputs:[{name:"v0",type:"float"},{name:"v1",type:"float"},{name:"v2",type:"float"},{name:"v3",type:"float"},{name:"v4",type:"float"},{name:"v5",type:"float"},{name:"v6",type:"float"},{name:"v7",type:"float"},{name:"s",type:"float"},{name:"t",type:"float"},{name:"r",type:"float"}]}),_i((([e,t,r,s,i,n,o,a,u,l,d])=>{const c=Ci(d).toVar(),h=Ci(l).toVar(),p=Ci(u).toVar(),g=Ii(a).toVar(),m=Ii(o).toVar(),f=Ii(n).toVar(),y=Ii(i).toVar(),x=Ii(s).toVar(),b=Ii(r).toVar(),T=Ii(t).toVar(),_=Ii(e).toVar(),v=Ci(Gn(1,p)).toVar(),N=Ci(Gn(1,h)).toVar();return Ci(Gn(1,c)).toVar().mul(N.mul(_.mul(v).add(T.mul(p))).add(h.mul(b.mul(v).add(x.mul(p))))).add(c.mul(N.mul(y.mul(v).add(f.mul(p))).add(h.mul(m.mul(v).add(g.mul(p))))))})).setLayout({name:"mx_trilerp_1",type:"vec3",inputs:[{name:"v0",type:"vec3"},{name:"v1",type:"vec3"},{name:"v2",type:"vec3"},{name:"v3",type:"vec3"},{name:"v4",type:"vec3"},{name:"v5",type:"vec3"},{name:"v6",type:"vec3"},{name:"v7",type:"vec3"},{name:"s",type:"float"},{name:"t",type:"float"},{name:"r",type:"float"}]})]),Cx=_i((([e,t,r])=>{const s=Ci(r).toVar(),i=Ci(t).toVar(),n=wi(e).toVar(),o=wi(n.bitAnd(wi(7))).toVar(),a=Ci(_x(o.lessThan(wi(4)),i,s)).toVar(),u=Ci(kn(2,_x(o.lessThan(wi(4)),s,i))).toVar();return vx(a,Mi(o.bitAnd(wi(1)))).add(vx(u,Mi(o.bitAnd(wi(2)))))})).setLayout({name:"mx_gradient_float_0",type:"float",inputs:[{name:"hash",type:"uint"},{name:"x",type:"float"},{name:"y",type:"float"}]}),Ex=_i((([e,t,r,s])=>{const i=Ci(s).toVar(),n=Ci(r).toVar(),o=Ci(t).toVar(),a=wi(e).toVar(),u=wi(a.bitAnd(wi(15))).toVar(),l=Ci(_x(u.lessThan(wi(8)),o,n)).toVar(),d=Ci(_x(u.lessThan(wi(4)),n,_x(u.equal(wi(12)).or(u.equal(wi(14))),o,i))).toVar();return vx(l,Mi(u.bitAnd(wi(1)))).add(vx(d,Mi(u.bitAnd(wi(2)))))})).setLayout({name:"mx_gradient_float_1",type:"float",inputs:[{name:"hash",type:"uint"},{name:"x",type:"float"},{name:"y",type:"float"},{name:"z",type:"float"}]}),wx=vm([Cx,Ex]),Mx=_i((([e,t,r])=>{const s=Ci(r).toVar(),i=Ci(t).toVar(),n=Vi(e).toVar();return Ii(wx(n.x,i,s),wx(n.y,i,s),wx(n.z,i,s))})).setLayout({name:"mx_gradient_vec3_0",type:"vec3",inputs:[{name:"hash",type:"uvec3"},{name:"x",type:"float"},{name:"y",type:"float"}]}),Bx=_i((([e,t,r,s])=>{const i=Ci(s).toVar(),n=Ci(r).toVar(),o=Ci(t).toVar(),a=Vi(e).toVar();return Ii(wx(a.x,o,n,i),wx(a.y,o,n,i),wx(a.z,o,n,i))})).setLayout({name:"mx_gradient_vec3_1",type:"vec3",inputs:[{name:"hash",type:"uvec3"},{name:"x",type:"float"},{name:"y",type:"float"},{name:"z",type:"float"}]}),Ux=vm([Mx,Bx]),Fx=_i((([e])=>{const t=Ci(e).toVar();return kn(.6616,t)})).setLayout({name:"mx_gradient_scale2d_0",type:"float",inputs:[{name:"v",type:"float"}]}),Px=_i((([e])=>{const t=Ci(e).toVar();return kn(.982,t)})).setLayout({name:"mx_gradient_scale3d_0",type:"float",inputs:[{name:"v",type:"float"}]}),Ix=vm([Fx,_i((([e])=>{const t=Ii(e).toVar();return kn(.6616,t)})).setLayout({name:"mx_gradient_scale2d_1",type:"vec3",inputs:[{name:"v",type:"vec3"}]})]),Lx=vm([Px,_i((([e])=>{const t=Ii(e).toVar();return kn(.982,t)})).setLayout({name:"mx_gradient_scale3d_1",type:"vec3",inputs:[{name:"v",type:"vec3"}]})]),Vx=_i((([e,t])=>{const r=Ei(t).toVar(),s=wi(e).toVar();return s.shiftLeft(r).bitOr(s.shiftRight(Ei(32).sub(r)))})).setLayout({name:"mx_rotl32",type:"uint",inputs:[{name:"x",type:"uint"},{name:"k",type:"int"}]}),Dx=_i((([e,t,r])=>{e.subAssign(r),e.bitXorAssign(Vx(r,Ei(4))),r.addAssign(t),t.subAssign(e),t.bitXorAssign(Vx(e,Ei(6))),e.addAssign(r),r.subAssign(t),r.bitXorAssign(Vx(t,Ei(8))),t.addAssign(e),e.subAssign(r),e.bitXorAssign(Vx(r,Ei(16))),r.addAssign(t),t.subAssign(e),t.bitXorAssign(Vx(e,Ei(19))),e.addAssign(r),r.subAssign(t),r.bitXorAssign(Vx(t,Ei(4))),t.addAssign(e)})),Ox=_i((([e,t,r])=>{const s=wi(r).toVar(),i=wi(t).toVar(),n=wi(e).toVar();return s.bitXorAssign(i),s.subAssign(Vx(i,Ei(14))),n.bitXorAssign(s),n.subAssign(Vx(s,Ei(11))),i.bitXorAssign(n),i.subAssign(Vx(n,Ei(25))),s.bitXorAssign(i),s.subAssign(Vx(i,Ei(16))),n.bitXorAssign(s),n.subAssign(Vx(s,Ei(4))),i.bitXorAssign(n),i.subAssign(Vx(n,Ei(14))),s.bitXorAssign(i),s.subAssign(Vx(i,Ei(24))),s})).setLayout({name:"mx_bjfinal",type:"uint",inputs:[{name:"a",type:"uint"},{name:"b",type:"uint"},{name:"c",type:"uint"}]}),Gx=_i((([e])=>{const t=wi(e).toVar();return Ci(t).div(Ci(wi(Ei(4294967295))))})).setLayout({name:"mx_bits_to_01",type:"float",inputs:[{name:"bits",type:"uint"}]}),kx=_i((([e])=>{const t=Ci(e).toVar();return t.mul(t).mul(t).mul(t.mul(t.mul(6).sub(15)).add(10))})).setLayout({name:"mx_fade",type:"float",inputs:[{name:"t",type:"float"}]}),zx=vm([_i((([e])=>{const t=Ei(e).toVar(),r=wi(wi(1)).toVar(),s=wi(wi(Ei(3735928559)).add(r.shiftLeft(wi(2))).add(wi(13))).toVar();return Ox(s.add(wi(t)),s,s)})).setLayout({name:"mx_hash_int_0",type:"uint",inputs:[{name:"x",type:"int"}]}),_i((([e,t])=>{const r=Ei(t).toVar(),s=Ei(e).toVar(),i=wi(wi(2)).toVar(),n=wi().toVar(),o=wi().toVar(),a=wi().toVar();return n.assign(o.assign(a.assign(wi(Ei(3735928559)).add(i.shiftLeft(wi(2))).add(wi(13))))),n.addAssign(wi(s)),o.addAssign(wi(r)),Ox(n,o,a)})).setLayout({name:"mx_hash_int_1",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"}]}),_i((([e,t,r])=>{const s=Ei(r).toVar(),i=Ei(t).toVar(),n=Ei(e).toVar(),o=wi(wi(3)).toVar(),a=wi().toVar(),u=wi().toVar(),l=wi().toVar();return a.assign(u.assign(l.assign(wi(Ei(3735928559)).add(o.shiftLeft(wi(2))).add(wi(13))))),a.addAssign(wi(n)),u.addAssign(wi(i)),l.addAssign(wi(s)),Ox(a,u,l)})).setLayout({name:"mx_hash_int_2",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"}]}),_i((([e,t,r,s])=>{const i=Ei(s).toVar(),n=Ei(r).toVar(),o=Ei(t).toVar(),a=Ei(e).toVar(),u=wi(wi(4)).toVar(),l=wi().toVar(),d=wi().toVar(),c=wi().toVar();return l.assign(d.assign(c.assign(wi(Ei(3735928559)).add(u.shiftLeft(wi(2))).add(wi(13))))),l.addAssign(wi(a)),d.addAssign(wi(o)),c.addAssign(wi(n)),Dx(l,d,c),l.addAssign(wi(i)),Ox(l,d,c)})).setLayout({name:"mx_hash_int_3",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"},{name:"xx",type:"int"}]}),_i((([e,t,r,s,i])=>{const n=Ei(i).toVar(),o=Ei(s).toVar(),a=Ei(r).toVar(),u=Ei(t).toVar(),l=Ei(e).toVar(),d=wi(wi(5)).toVar(),c=wi().toVar(),h=wi().toVar(),p=wi().toVar();return c.assign(h.assign(p.assign(wi(Ei(3735928559)).add(d.shiftLeft(wi(2))).add(wi(13))))),c.addAssign(wi(l)),h.addAssign(wi(u)),p.addAssign(wi(a)),Dx(c,h,p),c.addAssign(wi(o)),h.addAssign(wi(n)),Ox(c,h,p)})).setLayout({name:"mx_hash_int_4",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"},{name:"xx",type:"int"},{name:"yy",type:"int"}]})]),$x=vm([_i((([e,t])=>{const r=Ei(t).toVar(),s=Ei(e).toVar(),i=wi(zx(s,r)).toVar(),n=Vi().toVar();return n.x.assign(i.bitAnd(Ei(255))),n.y.assign(i.shiftRight(Ei(8)).bitAnd(Ei(255))),n.z.assign(i.shiftRight(Ei(16)).bitAnd(Ei(255))),n})).setLayout({name:"mx_hash_vec3_0",type:"uvec3",inputs:[{name:"x",type:"int"},{name:"y",type:"int"}]}),_i((([e,t,r])=>{const s=Ei(r).toVar(),i=Ei(t).toVar(),n=Ei(e).toVar(),o=wi(zx(n,i,s)).toVar(),a=Vi().toVar();return a.x.assign(o.bitAnd(Ei(255))),a.y.assign(o.shiftRight(Ei(8)).bitAnd(Ei(255))),a.z.assign(o.shiftRight(Ei(16)).bitAnd(Ei(255))),a})).setLayout({name:"mx_hash_vec3_1",type:"uvec3",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"}]})]),Hx=vm([_i((([e])=>{const t=Bi(e).toVar(),r=Ei().toVar(),s=Ei().toVar(),i=Ci(Sx(t.x,r)).toVar(),n=Ci(Sx(t.y,s)).toVar(),o=Ci(kx(i)).toVar(),a=Ci(kx(n)).toVar(),u=Ci(Ax(wx(zx(r,s),i,n),wx(zx(r.add(Ei(1)),s),i.sub(1),n),wx(zx(r,s.add(Ei(1))),i,n.sub(1)),wx(zx(r.add(Ei(1)),s.add(Ei(1))),i.sub(1),n.sub(1)),o,a)).toVar();return Ix(u)})).setLayout({name:"mx_perlin_noise_float_0",type:"float",inputs:[{name:"p",type:"vec2"}]}),_i((([e])=>{const t=Ii(e).toVar(),r=Ei().toVar(),s=Ei().toVar(),i=Ei().toVar(),n=Ci(Sx(t.x,r)).toVar(),o=Ci(Sx(t.y,s)).toVar(),a=Ci(Sx(t.z,i)).toVar(),u=Ci(kx(n)).toVar(),l=Ci(kx(o)).toVar(),d=Ci(kx(a)).toVar(),c=Ci(Rx(wx(zx(r,s,i),n,o,a),wx(zx(r.add(Ei(1)),s,i),n.sub(1),o,a),wx(zx(r,s.add(Ei(1)),i),n,o.sub(1),a),wx(zx(r.add(Ei(1)),s.add(Ei(1)),i),n.sub(1),o.sub(1),a),wx(zx(r,s,i.add(Ei(1))),n,o,a.sub(1)),wx(zx(r.add(Ei(1)),s,i.add(Ei(1))),n.sub(1),o,a.sub(1)),wx(zx(r,s.add(Ei(1)),i.add(Ei(1))),n,o.sub(1),a.sub(1)),wx(zx(r.add(Ei(1)),s.add(Ei(1)),i.add(Ei(1))),n.sub(1),o.sub(1),a.sub(1)),u,l,d)).toVar();return Lx(c)})).setLayout({name:"mx_perlin_noise_float_1",type:"float",inputs:[{name:"p",type:"vec3"}]})]),Wx=vm([_i((([e])=>{const t=Bi(e).toVar(),r=Ei().toVar(),s=Ei().toVar(),i=Ci(Sx(t.x,r)).toVar(),n=Ci(Sx(t.y,s)).toVar(),o=Ci(kx(i)).toVar(),a=Ci(kx(n)).toVar(),u=Ii(Ax(Ux($x(r,s),i,n),Ux($x(r.add(Ei(1)),s),i.sub(1),n),Ux($x(r,s.add(Ei(1))),i,n.sub(1)),Ux($x(r.add(Ei(1)),s.add(Ei(1))),i.sub(1),n.sub(1)),o,a)).toVar();return Ix(u)})).setLayout({name:"mx_perlin_noise_vec3_0",type:"vec3",inputs:[{name:"p",type:"vec2"}]}),_i((([e])=>{const t=Ii(e).toVar(),r=Ei().toVar(),s=Ei().toVar(),i=Ei().toVar(),n=Ci(Sx(t.x,r)).toVar(),o=Ci(Sx(t.y,s)).toVar(),a=Ci(Sx(t.z,i)).toVar(),u=Ci(kx(n)).toVar(),l=Ci(kx(o)).toVar(),d=Ci(kx(a)).toVar(),c=Ii(Rx(Ux($x(r,s,i),n,o,a),Ux($x(r.add(Ei(1)),s,i),n.sub(1),o,a),Ux($x(r,s.add(Ei(1)),i),n,o.sub(1),a),Ux($x(r.add(Ei(1)),s.add(Ei(1)),i),n.sub(1),o.sub(1),a),Ux($x(r,s,i.add(Ei(1))),n,o,a.sub(1)),Ux($x(r.add(Ei(1)),s,i.add(Ei(1))),n.sub(1),o,a.sub(1)),Ux($x(r,s.add(Ei(1)),i.add(Ei(1))),n,o.sub(1),a.sub(1)),Ux($x(r.add(Ei(1)),s.add(Ei(1)),i.add(Ei(1))),n.sub(1),o.sub(1),a.sub(1)),u,l,d)).toVar();return Lx(c)})).setLayout({name:"mx_perlin_noise_vec3_1",type:"vec3",inputs:[{name:"p",type:"vec3"}]})]),jx=vm([_i((([e])=>{const t=Ci(e).toVar(),r=Ei(Nx(t)).toVar();return Gx(zx(r))})).setLayout({name:"mx_cell_noise_float_0",type:"float",inputs:[{name:"p",type:"float"}]}),_i((([e])=>{const t=Bi(e).toVar(),r=Ei(Nx(t.x)).toVar(),s=Ei(Nx(t.y)).toVar();return Gx(zx(r,s))})).setLayout({name:"mx_cell_noise_float_1",type:"float",inputs:[{name:"p",type:"vec2"}]}),_i((([e])=>{const t=Ii(e).toVar(),r=Ei(Nx(t.x)).toVar(),s=Ei(Nx(t.y)).toVar(),i=Ei(Nx(t.z)).toVar();return Gx(zx(r,s,i))})).setLayout({name:"mx_cell_noise_float_2",type:"float",inputs:[{name:"p",type:"vec3"}]}),_i((([e])=>{const t=Oi(e).toVar(),r=Ei(Nx(t.x)).toVar(),s=Ei(Nx(t.y)).toVar(),i=Ei(Nx(t.z)).toVar(),n=Ei(Nx(t.w)).toVar();return Gx(zx(r,s,i,n))})).setLayout({name:"mx_cell_noise_float_3",type:"float",inputs:[{name:"p",type:"vec4"}]})]),qx=vm([_i((([e])=>{const t=Ci(e).toVar(),r=Ei(Nx(t)).toVar();return Ii(Gx(zx(r,Ei(0))),Gx(zx(r,Ei(1))),Gx(zx(r,Ei(2))))})).setLayout({name:"mx_cell_noise_vec3_0",type:"vec3",inputs:[{name:"p",type:"float"}]}),_i((([e])=>{const t=Bi(e).toVar(),r=Ei(Nx(t.x)).toVar(),s=Ei(Nx(t.y)).toVar();return Ii(Gx(zx(r,s,Ei(0))),Gx(zx(r,s,Ei(1))),Gx(zx(r,s,Ei(2))))})).setLayout({name:"mx_cell_noise_vec3_1",type:"vec3",inputs:[{name:"p",type:"vec2"}]}),_i((([e])=>{const t=Ii(e).toVar(),r=Ei(Nx(t.x)).toVar(),s=Ei(Nx(t.y)).toVar(),i=Ei(Nx(t.z)).toVar();return Ii(Gx(zx(r,s,i,Ei(0))),Gx(zx(r,s,i,Ei(1))),Gx(zx(r,s,i,Ei(2))))})).setLayout({name:"mx_cell_noise_vec3_2",type:"vec3",inputs:[{name:"p",type:"vec3"}]}),_i((([e])=>{const t=Oi(e).toVar(),r=Ei(Nx(t.x)).toVar(),s=Ei(Nx(t.y)).toVar(),i=Ei(Nx(t.z)).toVar(),n=Ei(Nx(t.w)).toVar();return Ii(Gx(zx(r,s,i,n,Ei(0))),Gx(zx(r,s,i,n,Ei(1))),Gx(zx(r,s,i,n,Ei(2))))})).setLayout({name:"mx_cell_noise_vec3_3",type:"vec3",inputs:[{name:"p",type:"vec4"}]})]),Kx=_i((([e,t,r,s])=>{const i=Ci(s).toVar(),n=Ci(r).toVar(),o=Ei(t).toVar(),a=Ii(e).toVar(),u=Ci(0).toVar(),l=Ci(1).toVar();return ic(o,(()=>{u.addAssign(l.mul(Hx(a))),l.mulAssign(i),a.mulAssign(n)})),u})).setLayout({name:"mx_fractal_noise_float",type:"float",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),Xx=_i((([e,t,r,s])=>{const i=Ci(s).toVar(),n=Ci(r).toVar(),o=Ei(t).toVar(),a=Ii(e).toVar(),u=Ii(0).toVar(),l=Ci(1).toVar();return ic(o,(()=>{u.addAssign(l.mul(Wx(a))),l.mulAssign(i),a.mulAssign(n)})),u})).setLayout({name:"mx_fractal_noise_vec3",type:"vec3",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),Yx=_i((([e,t,r,s])=>{const i=Ci(s).toVar(),n=Ci(r).toVar(),o=Ei(t).toVar(),a=Ii(e).toVar();return Bi(Kx(a,o,n,i),Kx(a.add(Ii(Ei(19),Ei(193),Ei(17))),o,n,i))})).setLayout({name:"mx_fractal_noise_vec2",type:"vec2",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),Qx=_i((([e,t,r,s])=>{const i=Ci(s).toVar(),n=Ci(r).toVar(),o=Ei(t).toVar(),a=Ii(e).toVar(),u=Ii(Xx(a,o,n,i)).toVar(),l=Ci(Kx(a.add(Ii(Ei(19),Ei(193),Ei(17))),o,n,i)).toVar();return Oi(u,l)})).setLayout({name:"mx_fractal_noise_vec4",type:"vec4",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),Zx=vm([_i((([e,t,r,s,i,n,o])=>{const a=Ei(o).toVar(),u=Ci(n).toVar(),l=Ei(i).toVar(),d=Ei(s).toVar(),c=Ei(r).toVar(),h=Ei(t).toVar(),p=Bi(e).toVar(),g=Ii(qx(Bi(h.add(d),c.add(l)))).toVar(),m=Bi(g.x,g.y).toVar();m.subAssign(.5),m.mulAssign(u),m.addAssign(.5);const f=Bi(Bi(Ci(h),Ci(c)).add(m)).toVar(),y=Bi(f.sub(p)).toVar();return Si(a.equal(Ei(2)),(()=>Fo(y.x).add(Fo(y.y)))),Si(a.equal(Ei(3)),(()=>Ko(Fo(y.x),Fo(y.y)))),ea(y,y)})).setLayout({name:"mx_worley_distance_0",type:"float",inputs:[{name:"p",type:"vec2"},{name:"x",type:"int"},{name:"y",type:"int"},{name:"xoff",type:"int"},{name:"yoff",type:"int"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),_i((([e,t,r,s,i,n,o,a,u])=>{const l=Ei(u).toVar(),d=Ci(a).toVar(),c=Ei(o).toVar(),h=Ei(n).toVar(),p=Ei(i).toVar(),g=Ei(s).toVar(),m=Ei(r).toVar(),f=Ei(t).toVar(),y=Ii(e).toVar(),x=Ii(qx(Ii(f.add(p),m.add(h),g.add(c)))).toVar();x.subAssign(.5),x.mulAssign(d),x.addAssign(.5);const b=Ii(Ii(Ci(f),Ci(m),Ci(g)).add(x)).toVar(),T=Ii(b.sub(y)).toVar();return Si(l.equal(Ei(2)),(()=>Fo(T.x).add(Fo(T.y)).add(Fo(T.z)))),Si(l.equal(Ei(3)),(()=>Ko(Ko(Fo(T.x),Fo(T.y)),Fo(T.z)))),ea(T,T)})).setLayout({name:"mx_worley_distance_1",type:"float",inputs:[{name:"p",type:"vec3"},{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"},{name:"xoff",type:"int"},{name:"yoff",type:"int"},{name:"zoff",type:"int"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),Jx=_i((([e,t,r])=>{const s=Ei(r).toVar(),i=Ci(t).toVar(),n=Bi(e).toVar(),o=Ei().toVar(),a=Ei().toVar(),u=Bi(Sx(n.x,o),Sx(n.y,a)).toVar(),l=Ci(1e6).toVar();return ic({start:-1,end:Ei(1),name:"x",condition:"<="},(({x:e})=>{ic({start:-1,end:Ei(1),name:"y",condition:"<="},(({y:t})=>{const r=Ci(Zx(u,e,t,o,a,i,s)).toVar();l.assign(qo(l,r))}))})),Si(s.equal(Ei(0)),(()=>{l.assign(_o(l))})),l})).setLayout({name:"mx_worley_noise_float_0",type:"float",inputs:[{name:"p",type:"vec2"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),eb=_i((([e,t,r])=>{const s=Ei(r).toVar(),i=Ci(t).toVar(),n=Bi(e).toVar(),o=Ei().toVar(),a=Ei().toVar(),u=Bi(Sx(n.x,o),Sx(n.y,a)).toVar(),l=Bi(1e6,1e6).toVar();return ic({start:-1,end:Ei(1),name:"x",condition:"<="},(({x:e})=>{ic({start:-1,end:Ei(1),name:"y",condition:"<="},(({y:t})=>{const r=Ci(Zx(u,e,t,o,a,i,s)).toVar();Si(r.lessThan(l.x),(()=>{l.y.assign(l.x),l.x.assign(r)})).ElseIf(r.lessThan(l.y),(()=>{l.y.assign(r)}))}))})),Si(s.equal(Ei(0)),(()=>{l.assign(_o(l))})),l})).setLayout({name:"mx_worley_noise_vec2_0",type:"vec2",inputs:[{name:"p",type:"vec2"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),tb=_i((([e,t,r])=>{const s=Ei(r).toVar(),i=Ci(t).toVar(),n=Bi(e).toVar(),o=Ei().toVar(),a=Ei().toVar(),u=Bi(Sx(n.x,o),Sx(n.y,a)).toVar(),l=Ii(1e6,1e6,1e6).toVar();return ic({start:-1,end:Ei(1),name:"x",condition:"<="},(({x:e})=>{ic({start:-1,end:Ei(1),name:"y",condition:"<="},(({y:t})=>{const r=Ci(Zx(u,e,t,o,a,i,s)).toVar();Si(r.lessThan(l.x),(()=>{l.z.assign(l.y),l.y.assign(l.x),l.x.assign(r)})).ElseIf(r.lessThan(l.y),(()=>{l.z.assign(l.y),l.y.assign(r)})).ElseIf(r.lessThan(l.z),(()=>{l.z.assign(r)}))}))})),Si(s.equal(Ei(0)),(()=>{l.assign(_o(l))})),l})).setLayout({name:"mx_worley_noise_vec3_0",type:"vec3",inputs:[{name:"p",type:"vec2"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),rb=vm([Jx,_i((([e,t,r])=>{const s=Ei(r).toVar(),i=Ci(t).toVar(),n=Ii(e).toVar(),o=Ei().toVar(),a=Ei().toVar(),u=Ei().toVar(),l=Ii(Sx(n.x,o),Sx(n.y,a),Sx(n.z,u)).toVar(),d=Ci(1e6).toVar();return ic({start:-1,end:Ei(1),name:"x",condition:"<="},(({x:e})=>{ic({start:-1,end:Ei(1),name:"y",condition:"<="},(({y:t})=>{ic({start:-1,end:Ei(1),name:"z",condition:"<="},(({z:r})=>{const n=Ci(Zx(l,e,t,r,o,a,u,i,s)).toVar();d.assign(qo(d,n))}))}))})),Si(s.equal(Ei(0)),(()=>{d.assign(_o(d))})),d})).setLayout({name:"mx_worley_noise_float_1",type:"float",inputs:[{name:"p",type:"vec3"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),sb=vm([eb,_i((([e,t,r])=>{const s=Ei(r).toVar(),i=Ci(t).toVar(),n=Ii(e).toVar(),o=Ei().toVar(),a=Ei().toVar(),u=Ei().toVar(),l=Ii(Sx(n.x,o),Sx(n.y,a),Sx(n.z,u)).toVar(),d=Bi(1e6,1e6).toVar();return ic({start:-1,end:Ei(1),name:"x",condition:"<="},(({x:e})=>{ic({start:-1,end:Ei(1),name:"y",condition:"<="},(({y:t})=>{ic({start:-1,end:Ei(1),name:"z",condition:"<="},(({z:r})=>{const n=Ci(Zx(l,e,t,r,o,a,u,i,s)).toVar();Si(n.lessThan(d.x),(()=>{d.y.assign(d.x),d.x.assign(n)})).ElseIf(n.lessThan(d.y),(()=>{d.y.assign(n)}))}))}))})),Si(s.equal(Ei(0)),(()=>{d.assign(_o(d))})),d})).setLayout({name:"mx_worley_noise_vec2_1",type:"vec2",inputs:[{name:"p",type:"vec3"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),ib=vm([tb,_i((([e,t,r])=>{const s=Ei(r).toVar(),i=Ci(t).toVar(),n=Ii(e).toVar(),o=Ei().toVar(),a=Ei().toVar(),u=Ei().toVar(),l=Ii(Sx(n.x,o),Sx(n.y,a),Sx(n.z,u)).toVar(),d=Ii(1e6,1e6,1e6).toVar();return ic({start:-1,end:Ei(1),name:"x",condition:"<="},(({x:e})=>{ic({start:-1,end:Ei(1),name:"y",condition:"<="},(({y:t})=>{ic({start:-1,end:Ei(1),name:"z",condition:"<="},(({z:r})=>{const n=Ci(Zx(l,e,t,r,o,a,u,i,s)).toVar();Si(n.lessThan(d.x),(()=>{d.z.assign(d.y),d.y.assign(d.x),d.x.assign(n)})).ElseIf(n.lessThan(d.y),(()=>{d.z.assign(d.y),d.y.assign(n)})).ElseIf(n.lessThan(d.z),(()=>{d.z.assign(n)}))}))}))})),Si(s.equal(Ei(0)),(()=>{d.assign(_o(d))})),d})).setLayout({name:"mx_worley_noise_vec3_1",type:"vec3",inputs:[{name:"p",type:"vec3"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),nb=_i((([e])=>{const t=e.y,r=e.z,s=Ii().toVar();return Si(t.lessThan(1e-4),(()=>{s.assign(Ii(r,r,r))})).Else((()=>{let i=e.x;i=i.sub(No(i)).mul(6).toVar();const n=Ei(zo(i)),o=i.sub(Ci(n)),a=r.mul(t.oneMinus()),u=r.mul(t.mul(o).oneMinus()),l=r.mul(t.mul(o.oneMinus()).oneMinus());Si(n.equal(Ei(0)),(()=>{s.assign(Ii(r,l,a))})).ElseIf(n.equal(Ei(1)),(()=>{s.assign(Ii(u,r,a))})).ElseIf(n.equal(Ei(2)),(()=>{s.assign(Ii(a,r,l))})).ElseIf(n.equal(Ei(3)),(()=>{s.assign(Ii(a,u,r))})).ElseIf(n.equal(Ei(4)),(()=>{s.assign(Ii(l,a,r))})).Else((()=>{s.assign(Ii(r,a,u))}))})),s})).setLayout({name:"mx_hsvtorgb",type:"vec3",inputs:[{name:"hsv",type:"vec3"}]}),ob=_i((([e])=>{const t=Ii(e).toVar(),r=Ci(t.x).toVar(),s=Ci(t.y).toVar(),i=Ci(t.z).toVar(),n=Ci(qo(r,qo(s,i))).toVar(),o=Ci(Ko(r,Ko(s,i))).toVar(),a=Ci(o.sub(n)).toVar(),u=Ci().toVar(),l=Ci().toVar(),d=Ci().toVar();return d.assign(o),Si(o.greaterThan(0),(()=>{l.assign(a.div(o))})).Else((()=>{l.assign(0)})),Si(l.lessThanEqual(0),(()=>{u.assign(0)})).Else((()=>{Si(r.greaterThanEqual(o),(()=>{u.assign(s.sub(i).div(a))})).ElseIf(s.greaterThanEqual(o),(()=>{u.assign(On(2,i.sub(r).div(a)))})).Else((()=>{u.assign(On(4,r.sub(s).div(a)))})),u.mulAssign(1/6),Si(u.lessThan(0),(()=>{u.addAssign(1)}))})),Ii(u,l,d)})).setLayout({name:"mx_rgbtohsv",type:"vec3",inputs:[{name:"c",type:"vec3"}]}),ab=_i((([e])=>{const t=Ii(e).toVar(),r=Di(qn(t,Ii(.04045))).toVar(),s=Ii(t.div(12.92)).toVar(),i=Ii(ra(Ko(t.add(Ii(.055)),Ii(0)).div(1.055),Ii(2.4))).toVar();return la(s,i,r)})).setLayout({name:"mx_srgb_texture_to_lin_rec709",type:"vec3",inputs:[{name:"color",type:"vec3"}]}),ub=(e,t)=>{e=Ci(e),t=Ci(t);const r=Bi(t.dFdx(),t.dFdy()).length().mul(.7071067811865476);return pa(e.sub(r),e.add(r),t)},lb=(e,t,r,s)=>la(e,t,r[s].clamp()),db=(e,t,r,s,i)=>la(e,t,ub(r,s[i])),cb=_i((([e,t,r])=>{const s=Ao(e).toVar("nDir"),i=Gn(Ci(.5).mul(t.sub(r)),Yu).div(s).toVar("rbmax"),n=Gn(Ci(-.5).mul(t.sub(r)),Yu).div(s).toVar("rbmin"),o=Ii().toVar("rbminmax");o.x=s.x.greaterThan(Ci(0)).select(i.x,n.x),o.y=s.y.greaterThan(Ci(0)).select(i.y,n.y),o.z=s.z.greaterThan(Ci(0)).select(i.z,n.z);const a=qo(qo(o.x,o.y),o.z).toVar("correction");return Yu.add(s.mul(a)).toVar("boxIntersection").sub(r)})),hb=_i((([e,t])=>{const r=e.x,s=e.y,i=e.z;let n=t.element(0).mul(.886227);return n=n.add(t.element(1).mul(1.023328).mul(s)),n=n.add(t.element(2).mul(1.023328).mul(i)),n=n.add(t.element(3).mul(1.023328).mul(r)),n=n.add(t.element(4).mul(.858086).mul(r).mul(s)),n=n.add(t.element(5).mul(.858086).mul(s).mul(i)),n=n.add(t.element(6).mul(i.mul(i).mul(.743125).sub(.247708))),n=n.add(t.element(7).mul(.858086).mul(r).mul(i)),n=n.add(t.element(8).mul(.429043).mul(kn(r,r).sub(kn(s,s)))),n}));var pb=Object.freeze({__proto__:null,BRDF_GGX:kh,BRDF_Lambert:Rh,BasicShadowFilter:Qy,Break:nc,Continue:()=>au("continue").append(),DFGApprox:zh,D_GGX:Dh,Discard:uu,EPSILON:uo,F_Schlick:Ah,Fn:_i,INFINITY:lo,If:Si,Loop:ic,NodeAccess:Ss,NodeShaderStage:_s,NodeType:Ns,NodeUpdateType:vs,PCFShadowFilter:Zy,PCFSoftShadowFilter:Jy,PI:co,PI2:ho,Return:()=>au("return").append(),Schlick_to_F0:Hh,ScriptableNodeResources:hy,ShaderNode:mi,TBNViewMatrix:Hl,VSMShadowFilter:ex,V_GGX_SmithCorrelated:Lh,abs:Fo,acesFilmicToneMapping:Zf,acos:Bo,add:On,addMethodChaining:$s,addNodeElement:function(e){console.warn("THREE.TSLBase: AddNodeElement has been removed in favor of tree-shaking. Trying add",e)},agxToneMapping:ry,all:po,alphaT:yn,and:Yn,anisotropy:xn,anisotropyB:Tn,anisotropyT:bn,any:go,append:Ai,arrayBuffer:e=>fi(new Gs(e,"ArrayBuffer")),asin:Mo,assign:In,atan:Uo,atan2:xa,atomicAdd:(e,t,r=null)=>Py(Uy.ATOMIC_ADD,e,t,r),atomicAnd:(e,t,r=null)=>Py(Uy.ATOMIC_AND,e,t,r),atomicFunc:Py,atomicMax:(e,t,r=null)=>Py(Uy.ATOMIC_MAX,e,t,r),atomicMin:(e,t,r=null)=>Py(Uy.ATOMIC_MIN,e,t,r),atomicOr:(e,t,r=null)=>Py(Uy.ATOMIC_OR,e,t,r),atomicStore:(e,t,r=null)=>Py(Uy.ATOMIC_STORE,e,t,r),atomicSub:(e,t,r=null)=>Py(Uy.ATOMIC_SUB,e,t,r),atomicXor:(e,t,r=null)=>Py(Uy.ATOMIC_XOR,e,t,r),attenuationColor:Un,attenuationDistance:Bn,attribute:hu,attributeArray:(e,t="float")=>{const r=ms(t),s=new uf(e,r);return hf(s,t,e)},backgroundBlurriness:bf,backgroundIntensity:Tf,backgroundRotation:_f,batch:Jd,billboarding:Em,bitAnd:eo,bitNot:to,bitOr:ro,bitXor:so,bitangentGeometry:Dl,bitangentLocal:Ol,bitangentView:Gl,bitangentWorld:kl,bitcast:Wo,blendBurn:Mf,blendColor:Pf,blendDodge:Bf,blendOverlay:Ff,blendScreen:Uf,blur:zp,bool:Mi,buffer:_l,bufferAttribute:qa,bumpMap:Jl,burn:(...e)=>(console.warn('THREE.TSL: "burn" has been renamed. Use "blendBurn" instead.'),Mf(e)),bvec2:Pi,bvec3:Di,bvec4:zi,bypass:ru,cache:eu,call:Vn,cameraFar:vu,cameraNear:_u,cameraNormalMatrix:Cu,cameraPosition:Eu,cameraProjectionMatrix:Nu,cameraProjectionMatrixInverse:Su,cameraViewMatrix:Au,cameraWorldMatrix:Ru,cbrt:aa,cdl:Gf,ceil:So,checker:Tx,cineonToneMapping:Yf,clamp:da,clearcoat:dn,clearcoatRoughness:cn,code:ny,color:Ri,colorSpaceToWorking:Da,colorToDirection:e=>fi(e).mul(2).sub(1),compute:Za,cond:_a,context:Na,convert:qi,convertColorSpace:(e,t,r)=>fi(new Pa(fi(e),t,r)),convertToTexture:(e,...t)=>e.isTextureNode?e:e.isPassNode?e.getTextureNode():rf(e,...t),cos:Eo,cross:ta,cubeTexture:bl,dFdx:Do,dFdy:Oo,dashSize:An,defaultBuildStages:Rs,defaultShaderStages:As,defined:pi,degrees:fo,deltaTime:Sm,densityFog:function(e,t){return console.warn('THREE.TSL: "densityFog( color, density )" is deprecated. Use "fog( color, densityFogFactor( density ) )" instead.'),xy(e,yy(t))},densityFogFactor:yy,depth:zc,depthPass:(e,t,r)=>fi(new jf(jf.DEPTH,e,t,r)),difference:Jo,diffuseColor:on,directPointLight:xx,directionToColor:uh,dispersion:Fn,distance:Zo,div:zn,dodge:(...e)=>(console.warn('THREE.TSL: "dodge" has been renamed. Use "blendDodge" instead.'),Bf(e)),dot:ea,drawIndex:qd,dynamicBufferAttribute:Ka,element:ji,emissive:an,equal:Hn,equals:jo,equirectUV:hh,exp:yo,exp2:xo,expression:au,faceDirection:rl,faceForward:ga,float:Ci,floor:No,fog:xy,fract:Ro,frameGroup:Qi,frameId:Am,frontFacing:tl,fwidth:$o,gain:(e,t)=>e.lessThan(.5)?fm(e.mul(2),t).div(2):Gn(1,fm(kn(Gn(1,e),2),t).div(2)),gapSize:Rn,getConstNodeType:gi,getCurrentStack:Ni,getDirection:Dp,getDistanceAttenuation:ux,getGeometryRoughness:Ph,getNormalFromDepth:of,getParallaxCorrectNormal:cb,getRoughness:Ih,getScreenPosition:nf,getShIrradianceAt:hb,getTextureIndex:hm,getViewPosition:sf,glsl:(e,t)=>ny(e,t,"glsl"),glslFn:(e,t)=>ay(e,t,"glsl"),grayscale:If,greaterThan:qn,greaterThanEqual:Xn,hash:mm,highpModelNormalViewMatrix:ju,highpModelViewMatrix:Wu,hue:Df,instance:Xd,instanceIndex:$d,instancedArray:(e,t="float")=>{const r=ms(t),s=new af(e,r);return hf(s,t,e)},instancedBufferAttribute:Xa,instancedDynamicBufferAttribute:Ya,instancedMesh:Qd,int:Ei,inverseSqrt:vo,invocationLocalIndex:jd,invocationSubgroupIndex:Wd,ior:En,iridescence:gn,iridescenceIOR:mn,iridescenceThickness:fn,ivec2:Ui,ivec3:Li,ivec4:Gi,js:(e,t)=>ny(e,t,"js"),label:Sa,length:Io,lengthSq:ua,lessThan:jn,lessThanEqual:Kn,lightPosition:Oy,lightProjectionUV:Dy,lightShadowMatrix:Vy,lightTargetDirection:zy,lightTargetPosition:Gy,lightViewPosition:ky,lightingContext:gc,lights:(e=[])=>fi(new Wy).setLights(e),linearDepth:$c,linearToneMapping:Kf,localId:Cy,log:bo,log2:To,logarithmicDepthToViewZ:(e,t,r)=>{const s=e.mul(bo(r.div(t)));return Ci(Math.E).pow(s).mul(t).negate()},loop:(...e)=>(console.warn("TSL.LoopNode: loop() has been renamed to Loop()."),ic(...e)),luminance:Of,mat2:$i,mat3:Hi,mat4:Wi,matcapUV:lg,materialAOMap:Dd,materialAlphaTest:rd,materialAnisotropy:_d,materialAnisotropyVector:Od,materialAttenuationColor:wd,materialAttenuationDistance:Ed,materialClearcoat:md,materialClearcoatNormal:yd,materialClearcoatRoughness:fd,materialColor:sd,materialDispersion:Ld,materialEmissive:nd,materialIOR:Cd,materialIridescence:vd,materialIridescenceIOR:Nd,materialIridescenceThickness:Sd,materialLightMap:Vd,materialLineDashOffset:Pd,materialLineDashSize:Bd,materialLineGapSize:Ud,materialLineScale:Md,materialLineWidth:Fd,materialMetalness:pd,materialNormal:gd,materialOpacity:od,materialPointWidth:Id,materialReference:Ml,materialReflectivity:cd,materialRefractionRatio:pl,materialRotation:xd,materialRoughness:hd,materialSheen:bd,materialSheenRoughness:Td,materialShininess:id,materialSpecular:ad,materialSpecularColor:ld,materialSpecularIntensity:ud,materialSpecularStrength:dd,materialThickness:Rd,materialTransmission:Ad,max:Ko,maxMipLevel:yu,mediumpModelViewMatrix:Hu,metalness:ln,min:qo,mix:la,mixElement:fa,mod:Xo,modInt:$n,modelDirection:Lu,modelNormalMatrix:ku,modelPosition:Du,modelScale:Ou,modelViewMatrix:$u,modelViewPosition:Gu,modelViewProjection:Gd,modelWorldMatrix:Vu,modelWorldMatrixInverse:zu,morphReference:dc,mrt:gm,mul:kn,mx_aastep:ub,mx_cell_noise_float:(e=pu())=>jx(e.convert("vec2|vec3")),mx_contrast:(e,t=1,r=.5)=>Ci(e).sub(r).mul(t).add(r),mx_fractal_noise_float:(e=pu(),t=3,r=2,s=.5,i=1)=>Kx(e,Ei(t),r,s).mul(i),mx_fractal_noise_vec2:(e=pu(),t=3,r=2,s=.5,i=1)=>Yx(e,Ei(t),r,s).mul(i),mx_fractal_noise_vec3:(e=pu(),t=3,r=2,s=.5,i=1)=>Xx(e,Ei(t),r,s).mul(i),mx_fractal_noise_vec4:(e=pu(),t=3,r=2,s=.5,i=1)=>Qx(e,Ei(t),r,s).mul(i),mx_hsvtorgb:nb,mx_noise_float:(e=pu(),t=1,r=0)=>Hx(e.convert("vec2|vec3")).mul(t).add(r),mx_noise_vec3:(e=pu(),t=1,r=0)=>Wx(e.convert("vec2|vec3")).mul(t).add(r),mx_noise_vec4:(e=pu(),t=1,r=0)=>{e=e.convert("vec2|vec3");return Oi(Wx(e),Hx(e.add(Bi(19,73)))).mul(t).add(r)},mx_ramplr:(e,t,r=pu())=>lb(e,t,r,"x"),mx_ramptb:(e,t,r=pu())=>lb(e,t,r,"y"),mx_rgbtohsv:ob,mx_safepower:(e,t=1)=>(e=Ci(e)).abs().pow(t).mul(e.sign()),mx_splitlr:(e,t,r,s=pu())=>db(e,t,r,s,"x"),mx_splittb:(e,t,r,s=pu())=>db(e,t,r,s,"y"),mx_srgb_texture_to_lin_rec709:ab,mx_transform_uv:(e=1,t=0,r=pu())=>r.mul(e).add(t),mx_worley_noise_float:(e=pu(),t=1)=>rb(e.convert("vec2|vec3"),t,Ei(1)),mx_worley_noise_vec2:(e=pu(),t=1)=>sb(e.convert("vec2|vec3"),t,Ei(1)),mx_worley_noise_vec3:(e=pu(),t=1)=>ib(e.convert("vec2|vec3"),t,Ei(1)),negate:Lo,neutralToneMapping:sy,nodeArray:xi,nodeImmutable:Ti,nodeObject:fi,nodeObjects:yi,nodeProxy:bi,normalFlat:nl,normalGeometry:sl,normalLocal:il,normalMap:Xl,normalView:ol,normalWorld:al,normalize:Ao,not:Zn,notEqual:Wn,numWorkgroups:Ay,objectDirection:Mu,objectGroup:Ji,objectPosition:Uu,objectScale:Fu,objectViewPosition:Pu,objectWorldMatrix:Bu,oneMinus:Vo,or:Qn,orthographicDepthToViewZ:(e,t,r)=>t.sub(r).mul(e).sub(t),oscSawtooth:(e=Nm)=>e.fract(),oscSine:(e=Nm)=>e.add(.75).mul(2*Math.PI).sin().mul(.5).add(.5),oscSquare:(e=Nm)=>e.fract().round(),oscTriangle:(e=Nm)=>e.add(.5).fract().mul(2).sub(1).abs(),output:Sn,outputStruct:cm,overlay:(...e)=>(console.warn('THREE.TSL: "overlay" has been renamed. Use "blendOverlay" instead.'),Ff(e)),overloadingFn:vm,parabola:fm,parallaxDirection:Wl,parallaxUV:(e,t)=>e.sub(Wl.mul(t)),parameter:(e,t)=>fi(new am(e,t)),pass:(e,t,r)=>fi(new jf(jf.COLOR,e,t,r)),passTexture:(e,t)=>fi(new Hf(e,t)),pcurve:(e,t,r)=>ra(zn(ra(e,t),On(ra(e,t),ra(Gn(1,e),r))),1/t),perspectiveDepthToViewZ:Oc,pmremTexture:qp,pointUV:mf,pointWidth:Cn,positionGeometry:qu,positionLocal:Ku,positionPrevious:Xu,positionView:Zu,positionViewDirection:Ju,positionWorld:Yu,positionWorldDirection:Qu,posterize:zf,pow:ra,pow2:sa,pow3:ia,pow4:na,property:sn,radians:mo,rand:ma,range:vy,rangeFog:function(e,t,r){return console.warn('THREE.TSL: "rangeFog( color, near, far )" is deprecated. Use "fog( color, rangeFogFactor( near, far ) )" instead.'),xy(e,fy(t,r))},rangeFogFactor:fy,reciprocal:ko,reference:Cl,referenceBuffer:El,reflect:Qo,reflectVector:fl,reflectView:gl,reflector:e=>fi(new Km(e)),refract:ha,refractVector:yl,refractView:ml,reinhardToneMapping:Xf,remainder:oo,remap:iu,remapClamp:nu,renderGroup:Zi,renderOutput:du,rendererReference:za,rotate:mg,rotateUV:Rm,roughness:un,round:Go,rtt:rf,sRGBTransferEOTF:Ma,sRGBTransferOETF:Ba,sampler:e=>(!0===e.isNode?e:bu(e)).convert("sampler"),saturate:ca,saturation:Lf,screen:(...e)=>(console.warn('THREE.TSL: "screen" has been renamed. Use "blendScreen" instead.'),Uf(e)),screenCoordinate:_c,screenSize:Tc,screenUV:bc,scriptable:gy,scriptableValue:ly,select:Ta,setCurrentStack:vi,shaderStages:Cs,shadow:ox,shadowWorldPosition:qy,sharedUniformGroup:Yi,sheen:hn,sheenRoughness:pn,shiftLeft:io,shiftRight:no,shininess:Nn,sign:Po,sin:Co,sinc:(e,t)=>Co(co.mul(t.mul(e).sub(1))).div(co.mul(t.mul(e).sub(1))),skinning:e=>fi(new tc(e)),skinningReference:rc,smoothstep:pa,smoothstepElement:ya,specularColor:_n,specularF90:vn,spherizeUV:Cm,split:(e,t)=>fi(new Ls(fi(e),t)),spritesheetUV:Bm,sqrt:_o,stack:lm,step:Yo,storage:hf,storageBarrier:()=>wy("storage").append(),storageObject:(e,t,r)=>(console.warn('THREE.TSL: "storageObject()" is deprecated. Use "storage().setPBO( true )" instead.'),hf(e,t,r).setPBO(!0)),storageTexture:Nf,string:(e="")=>fi(new Gs(e,"string")),sub:Gn,subgroupIndex:Hd,subgroupSize:Ey,tan:wo,tangentGeometry:Bl,tangentLocal:Ul,tangentView:Fl,tangentWorld:Pl,temp:Ca,texture:bu,texture3D:Ng,textureBarrier:()=>wy("texture").append(),textureBicubic:up,textureCubeUV:Op,textureLoad:Tu,textureSize:mu,textureStore:(e,t,r)=>{const s=Nf(e,t,r);return null!==r&&s.append(),s},thickness:Mn,time:Nm,timerDelta:(e=1)=>(console.warn('TSL: timerDelta() is deprecated. Use "deltaTime" instead.'),Sm.mul(e)),timerGlobal:(e=1)=>(console.warn('TSL: timerGlobal() is deprecated. Use "time" instead.'),Nm.mul(e)),timerLocal:(e=1)=>(console.warn('TSL: timerLocal() is deprecated. Use "time" instead.'),Nm.mul(e)),toOutputColorSpace:Ia,toWorkingColorSpace:La,toneMapping:Ha,toneMappingExposure:Wa,toonOutlinePass:(t,r,s=new e(0,0,0),i=.003,n=1)=>fi(new qf(t,r,fi(s),fi(i),fi(n))),transformDirection:oa,transformNormal:cl,transformNormalToView:hl,transformedBentNormalView:jl,transformedBitangentView:zl,transformedBitangentWorld:$l,transformedClearcoatNormalView:dl,transformedNormalView:ul,transformedNormalWorld:ll,transformedTangentView:Il,transformedTangentWorld:Ll,transmission:wn,transpose:Ho,triNoise3D:bm,triplanarTexture:(...e)=>Fm(...e),triplanarTextures:Fm,trunc:zo,tslFn:(...e)=>(console.warn("TSL.ShaderNode: tslFn() has been renamed to Fn()."),_i(...e)),uint:wi,uniform:tn,uniformArray:Sl,uniformGroup:Xi,uniforms:(e,t)=>(console.warn("TSL.UniformArrayNode: uniforms() has been renamed to uniformArray()."),fi(new Nl(e,t))),userData:(e,t,r)=>fi(new Sf(e,t,r)),uv:pu,uvec2:Fi,uvec3:Vi,uvec4:ki,varying:wa,varyingProperty:nn,vec2:Bi,vec3:Ii,vec4:Oi,vectorComponents:Es,velocity:wf,vertexColor:e=>fi(new pf(e)),vertexIndex:zd,vibrance:Vf,viewZToLogarithmicDepth:Gc,viewZToOrthographicDepth:Vc,viewZToPerspectiveDepth:Dc,viewport:vc,viewportBottomLeft:Ec,viewportCoordinate:Sc,viewportDepthTexture:Ic,viewportLinearDepth:Hc,viewportMipTexture:Uc,viewportResolution:Rc,viewportSafeUV:wm,viewportSharedTexture:nh,viewportSize:Nc,viewportTexture:Bc,viewportTopLeft:Cc,viewportUV:Ac,wgsl:(e,t)=>ny(e,t,"wgsl"),wgslFn:(e,t)=>ay(e,t,"wgsl"),workgroupArray:(e,t)=>fi(new By("Workgroup",e,t)),workgroupBarrier:()=>wy("workgroup").append(),workgroupId:Ry,workingToColorSpace:Va,xor:Jn});const gb=new om;class mb extends Bg{constructor(e,t){super(),this.renderer=e,this.nodes=t}update(e,t,r){const s=this.renderer,i=this.nodes.getBackgroundNode(e)||e.background;let n=!1;if(null===i)s._clearColor.getRGB(gb,Ae),gb.a=s._clearColor.a;else if(!0===i.isColor)i.getRGB(gb,Ae),gb.a=1,n=!0;else if(!0===i.isNode){const r=this.get(e),n=i;gb.copy(s._clearColor);let o=r.backgroundMesh;if(void 0===o){const e=Na(Oi(n).mul(Tf),{getUV:()=>_f.mul(al),getTextureLevel:()=>bf});let t=Gd;t=t.setZ(t.w);const s=new Yc;s.name="Background.material",s.side=T,s.depthTest=!1,s.depthWrite=!1,s.fog=!1,s.lights=!1,s.vertexNode=t,s.colorNode=e,r.backgroundMeshNode=e,r.backgroundMesh=o=new k(new Me(1,32,32),s),o.frustumCulled=!1,o.name="Background.mesh",o.onBeforeRender=function(e,t,r){this.matrixWorld.copyPosition(r.matrixWorld)}}const a=n.getCacheKey();r.backgroundCacheKey!==a&&(r.backgroundMeshNode.node=Oi(n).mul(Tf),r.backgroundMeshNode.needsUpdate=!0,o.material.needsUpdate=!0,r.backgroundCacheKey=a),t.unshift(o,o.geometry,o.material,0,0,null,null)}else console.error("THREE.Renderer: Unsupported background configuration.",i);if(!0===s.autoClear||!0===n){const e=r.clearColorValue;e.r=gb.r,e.g=gb.g,e.b=gb.b,e.a=gb.a,!0!==s.backend.isWebGLBackend&&!0!==s.alpha||(e.r*=e.a,e.g*=e.a,e.b*=e.a),r.depthClearValue=s._clearDepth,r.stencilClearValue=s._clearStencil,r.clearColor=!0===s.autoClearColor,r.clearDepth=!0===s.autoClearDepth,r.clearStencil=!0===s.autoClearStencil}else r.clearColor=!1,r.clearDepth=!1,r.clearStencil=!1}}let fb=0;class yb{constructor(e="",t=[],r=0,s=[]){this.name=e,this.bindings=t,this.index=r,this.bindingsReference=s,this.id=fb++}}class xb{constructor(e,t,r,s,i,n,o,a,u,l=[]){this.vertexShader=e,this.fragmentShader=t,this.computeShader=r,this.transforms=l,this.nodeAttributes=s,this.bindings=i,this.updateNodes=n,this.updateBeforeNodes=o,this.updateAfterNodes=a,this.monitor=u,this.usedTimes=0}createBindings(){const e=[];for(const t of this.bindings){if(!0!==t.bindings[0].groupNode.shared){const r=new yb(t.name,[],t.index,t);e.push(r);for(const e of t.bindings)r.bindings.push(e.clone())}else e.push(t)}return e}}class bb{constructor(e,t,r=null){this.isNodeAttribute=!0,this.name=e,this.type=t,this.node=r}}class Tb{constructor(e,t,r){this.isNodeUniform=!0,this.name=e,this.type=t,this.node=r.getSelf()}get value(){return this.node.value}set value(e){this.node.value=e}get id(){return this.node.id}get groupNode(){return this.node.groupNode}}class _b{constructor(e,t){this.isNodeVar=!0,this.name=e,this.type=t}}class vb extends _b{constructor(e,t){super(e,t),this.needsInterpolation=!1,this.isNodeVarying=!0}}class Nb{constructor(e,t,r=""){this.name=e,this.type=t,this.code=r,Object.defineProperty(this,"isNodeCode",{value:!0})}}let Sb=0;class Ab{constructor(e=null){this.id=Sb++,this.nodesData=new WeakMap,this.parent=e}getData(e){let t=this.nodesData.get(e);return void 0===t&&null!==this.parent&&(t=this.parent.getData(e)),t}setData(e,t){this.nodesData.set(e,t)}}class Rb extends Ms{static get type(){return"StructTypeNode"}constructor(e,t){super(),this.name=e,this.types=t,this.isStructTypeNode=!0}getMemberTypes(){return this.types}}class Cb{constructor(e,t){this.name=e,this.value=t,this.boundary=0,this.itemSize=0,this.offset=0}setValue(e){this.value=e}getValue(){return this.value}}class Eb extends Cb{constructor(e,t=0){super(e,t),this.isNumberUniform=!0,this.boundary=4,this.itemSize=1}}class wb extends Cb{constructor(e,r=new t){super(e,r),this.isVector2Uniform=!0,this.boundary=8,this.itemSize=2}}class Mb extends Cb{constructor(e,t=new r){super(e,t),this.isVector3Uniform=!0,this.boundary=16,this.itemSize=3}}class Bb extends Cb{constructor(e,t=new s){super(e,t),this.isVector4Uniform=!0,this.boundary=16,this.itemSize=4}}class Ub extends Cb{constructor(t,r=new e){super(t,r),this.isColorUniform=!0,this.boundary=16,this.itemSize=3}}class Fb extends Cb{constructor(e,t=new i){super(e,t),this.isMatrix3Uniform=!0,this.boundary=48,this.itemSize=12}}class Pb extends Cb{constructor(e,t=new n){super(e,t),this.isMatrix4Uniform=!0,this.boundary=64,this.itemSize=16}}class Ib extends Eb{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class Lb extends wb{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class Vb extends Mb{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class Db extends Bb{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class Ob extends Ub{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class Gb extends Fb{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class kb extends Pb{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}const zb=[.125,.215,.35,.446,.526,.582],$b=20,Hb=new be(-1,1,1,-1,0,1),Wb=new Ue(90,1),jb=new e;let qb=null,Kb=0,Xb=0;const Yb=(1+Math.sqrt(5))/2,Qb=1/Yb,Zb=[new r(-Yb,Qb,0),new r(Yb,Qb,0),new r(-Qb,0,Yb),new r(Qb,0,Yb),new r(0,Yb,-Qb),new r(0,Yb,Qb),new r(-1,1,-1),new r(1,1,-1),new r(-1,1,1),new r(1,1,1)],Jb=[3,1,5,0,4,2],eT=Dp(pu(),hu("faceIndex")).normalize(),tT=Ii(eT.x,eT.y,eT.z);class rT{constructor(e){this._renderer=e,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._lodPlanes=[],this._sizeLods=[],this._sigmas=[],this._lodMeshes=[],this._blurMaterial=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._backgroundBox=null}get _hasInitialized(){return this._renderer.hasInitialized()}fromScene(e,t=0,r=.1,s=100,i=null){if(this._setSize(256),!1===this._hasInitialized){console.warn("THREE.PMREMGenerator: .fromScene() called before the backend is initialized. Try using .fromSceneAsync() instead.");const n=i||this._allocateTargets();return this.fromSceneAsync(e,t,r,s,n),n}qb=this._renderer.getRenderTarget(),Kb=this._renderer.getActiveCubeFace(),Xb=this._renderer.getActiveMipmapLevel();const n=i||this._allocateTargets();return n.depthBuffer=!0,this._sceneToCubeUV(e,r,s,n),t>0&&this._blur(n,0,0,t),this._applyPMREM(n),this._cleanup(n),n}async fromSceneAsync(e,t=0,r=.1,s=100,i=null){return!1===this._hasInitialized&&await this._renderer.init(),this.fromScene(e,t,r,s,i)}fromEquirectangular(e,t=null){if(!1===this._hasInitialized){console.warn("THREE.PMREMGenerator: .fromEquirectangular() called before the backend is initialized. Try using .fromEquirectangularAsync() instead."),this._setSizeFromTexture(e);const r=t||this._allocateTargets();return this.fromEquirectangularAsync(e,r),r}return this._fromTexture(e,t)}async fromEquirectangularAsync(e,t=null){return!1===this._hasInitialized&&await this._renderer.init(),this._fromTexture(e,t)}fromCubemap(e,t=null){if(!1===this._hasInitialized){console.warn("THREE.PMREMGenerator: .fromCubemap() called before the backend is initialized. Try using .fromCubemapAsync() instead."),this._setSizeFromTexture(e);const r=t||this._allocateTargets();return this.fromCubemapAsync(e,t),r}return this._fromTexture(e,t)}async fromCubemapAsync(e,t=null){return!1===this._hasInitialized&&await this._renderer.init(),this._fromTexture(e,t)}async compileCubemapShader(){null===this._cubemapMaterial&&(this._cubemapMaterial=oT(),await this._compileMaterial(this._cubemapMaterial))}async compileEquirectangularShader(){null===this._equirectMaterial&&(this._equirectMaterial=aT(),await this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),null!==this._cubemapMaterial&&this._cubemapMaterial.dispose(),null!==this._equirectMaterial&&this._equirectMaterial.dispose(),null!==this._backgroundBox&&(this._backgroundBox.geometry.dispose(),this._backgroundBox.material.dispose())}_setSizeFromTexture(e){e.mapping===_||e.mapping===v?this._setSize(0===e.image.length?16:e.image[0].width||e.image[0].image.width):this._setSize(e.image.width/4)}_setSize(e){this._lodMax=Math.floor(Math.log2(e)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){null!==this._blurMaterial&&this._blurMaterial.dispose(),null!==this._pingPongRenderTarget&&this._pingPongRenderTarget.dispose();for(let e=0;ee-4?u=zb[a-e+4-1]:0===a&&(u=0),s.push(u);const l=1/(o-2),d=-l,c=1+l,h=[d,d,c,d,c,c,d,d,c,c,d,c],p=6,g=6,m=3,f=2,y=1,x=new Float32Array(m*g*p),b=new Float32Array(f*g*p),T=new Float32Array(y*g*p);for(let e=0;e2?0:-1,s=[t,r,0,t+2/3,r,0,t+2/3,r+1,0,t,r,0,t+2/3,r+1,0,t,r+1,0],i=Jb[e];x.set(s,m*g*i),b.set(h,f*g*i);const n=[i,i,i,i,i,i];T.set(n,y*g*i)}const _=new Te;_.setAttribute("position",new ve(x,m)),_.setAttribute("uv",new ve(b,f)),_.setAttribute("faceIndex",new ve(T,y)),t.push(_),i.push(new k(_,null)),n>4&&n--}return{lodPlanes:t,sizeLods:r,sigmas:s,lodMeshes:i}}(i)),this._blurMaterial=function(e,t,s){const i=Sl(new Array($b).fill(0)),n=tn(new r(0,1,0)),o=tn(0),a=Ci($b),u=tn(0),l=tn(1),d=bu(null),c=tn(0),h=Ci(1/t),p=Ci(1/s),g=Ci(e),m={n:a,latitudinal:u,weights:i,poleAxis:n,outputDirection:tT,dTheta:o,samples:l,envMap:d,mipInt:c,CUBEUV_TEXEL_WIDTH:h,CUBEUV_TEXEL_HEIGHT:p,CUBEUV_MAX_MIP:g},f=nT("blur");return f.uniforms=m,f.fragmentNode=zp({...m,latitudinal:u.equal(1)}),f}(i,e,t)}return i}async _compileMaterial(e){const t=new k(this._lodPlanes[0],e);await this._renderer.compile(t,Hb)}_sceneToCubeUV(e,t,r,s){const i=Wb;i.near=t,i.far=r;const n=[1,1,1,1,-1,1],o=[1,-1,1,-1,1,-1],a=this._renderer,u=a.autoClear;a.getClearColor(jb),a.autoClear=!1;let l=this._backgroundBox;if(null===l){const e=new Q({name:"PMREM.Background",side:T,depthWrite:!1,depthTest:!1});l=new k(new G,e)}let d=!1;const c=e.background;c?c.isColor&&(l.material.color.copy(c),e.background=null,d=!0):(l.material.color.copy(jb),d=!0),a.setRenderTarget(s),a.clear(),d&&a.render(l,i);for(let t=0;t<6;t++){const r=t%3;0===r?(i.up.set(0,n[t],0),i.lookAt(o[t],0,0)):1===r?(i.up.set(0,0,n[t]),i.lookAt(0,o[t],0)):(i.up.set(0,n[t],0),i.lookAt(0,0,o[t]));const u=this._cubeSize;iT(s,r*u,t>2?u:0,u,u),a.render(e,i)}a.autoClear=u,e.background=c}_textureToCubeUV(e,t){const r=this._renderer,s=e.mapping===_||e.mapping===v;s?null===this._cubemapMaterial&&(this._cubemapMaterial=oT(e)):null===this._equirectMaterial&&(this._equirectMaterial=aT(e));const i=s?this._cubemapMaterial:this._equirectMaterial;i.fragmentNode.value=e;const n=this._lodMeshes[0];n.material=i;const o=this._cubeSize;iT(t,0,0,3*o,2*o),r.setRenderTarget(t),r.render(n,Hb)}_applyPMREM(e){const t=this._renderer,r=t.autoClear;t.autoClear=!1;const s=this._lodPlanes.length;for(let t=1;t$b&&console.warn(`sigmaRadians, ${i}, is too large and will clip, as it requested ${g} samples when the maximum is set to 20`);const m=[];let f=0;for(let e=0;e<$b;++e){const t=e/p,r=Math.exp(-t*t/2);m.push(r),0===e?f+=r:ey-4?s-y+4:0),4*(this._cubeSize-x),3*x,2*x),a.setRenderTarget(t),a.render(l,Hb)}}function sT(e,t,r){const s=new ge(e,t,r);return s.texture.mapping=Be,s.texture.name="PMREM.cubeUv",s.texture.isPMREMTexture=!0,s.scissorTest=!0,s}function iT(e,t,r,s,i){e.viewport.set(t,r,s,i),e.scissor.set(t,r,s,i)}function nT(e){const t=new Yc;return t.depthTest=!1,t.depthWrite=!1,t.blending=V,t.name=`PMREM_${e}`,t}function oT(e){const t=nT("cubemap");return t.fragmentNode=bl(e,tT),t}function aT(e){const t=nT("equirect");return t.fragmentNode=bu(e,hh(tT),0),t}const uT=new WeakMap,lT=new Map([[Int8Array,"int"],[Int16Array,"int"],[Int32Array,"int"],[Uint8Array,"uint"],[Uint16Array,"uint"],[Uint32Array,"uint"],[Float32Array,"float"]]),dT=e=>/e/g.test(e)?String(e).replace(/\+/g,""):(e=Number(e))+(e%1?"":".0");class cT{constructor(e,t,r){this.object=e,this.material=e&&e.material||null,this.geometry=e&&e.geometry||null,this.renderer=t,this.parser=r,this.scene=null,this.camera=null,this.nodes=[],this.sequentialNodes=[],this.updateNodes=[],this.updateBeforeNodes=[],this.updateAfterNodes=[],this.hashNodes={},this.monitor=null,this.lightsNode=null,this.environmentNode=null,this.fogNode=null,this.clippingContext=null,this.vertexShader=null,this.fragmentShader=null,this.computeShader=null,this.flowNodes={vertex:[],fragment:[],compute:[]},this.flowCode={vertex:"",fragment:"",compute:""},this.uniforms={vertex:[],fragment:[],compute:[],index:0},this.structs={vertex:[],fragment:[],compute:[],index:0},this.bindings={vertex:{},fragment:{},compute:{}},this.bindingsIndexes={},this.bindGroups=null,this.attributes=[],this.bufferAttributes=[],this.varyings=[],this.codes={},this.vars={},this.flow={code:""},this.chaining=[],this.stack=lm(),this.stacks=[],this.tab="\t",this.currentFunctionNode=null,this.context={material:this.material},this.cache=new Ab,this.globalCache=this.cache,this.flowsData=new WeakMap,this.shaderStage=null,this.buildStage=null,this.useComparisonMethod=!1}getBindGroupsCache(){let e=uT.get(this.renderer);return void 0===e&&(e=new Rg,uT.set(this.renderer,e)),e}createRenderTarget(e,t,r){return new ge(e,t,r)}createCubeRenderTarget(e,t){return new ph(e,t)}createPMREMGenerator(){return new rT(this.renderer)}includes(e){return this.nodes.includes(e)}_getBindGroup(e,t){const r=this.getBindGroupsCache(),s=[];let i,n=!0;for(const e of t)s.push(e),n=n&&!0!==e.groupNode.shared;return n?(i=r.get(s),void 0===i&&(i=new yb(e,s,this.bindingsIndexes[e].group,s),r.set(s,i))):i=new yb(e,s,this.bindingsIndexes[e].group,s),i}getBindGroupArray(e,t){const r=this.bindings[t];let s=r[e];return void 0===s&&(void 0===this.bindingsIndexes[e]&&(this.bindingsIndexes[e]={binding:0,group:Object.keys(this.bindingsIndexes).length}),r[e]=s=[]),s}getBindings(){let e=this.bindGroups;if(null===e){const t={},r=this.bindings;for(const e of Cs)for(const s in r[e]){const i=r[e][s];(t[s]||(t[s]=[])).push(...i)}e=[];for(const r in t){const s=t[r],i=this._getBindGroup(r,s);e.push(i)}this.bindGroups=e}return e}sortBindingGroups(){const e=this.getBindings();e.sort(((e,t)=>e.bindings[0].groupNode.order-t.bindings[0].groupNode.order));for(let t=0;t=0?`${Math.round(n)}u`:"0u";if("bool"===i)return n?"true":"false";if("color"===i)return`${this.getType("vec3")}( ${dT(n.r)}, ${dT(n.g)}, ${dT(n.b)} )`;const o=this.getTypeLength(i),a=this.getComponentType(i),u=e=>this.generateConst(a,e);if(2===o)return`${this.getType(i)}( ${u(n.x)}, ${u(n.y)} )`;if(3===o)return`${this.getType(i)}( ${u(n.x)}, ${u(n.y)}, ${u(n.z)} )`;if(4===o)return`${this.getType(i)}( ${u(n.x)}, ${u(n.y)}, ${u(n.z)}, ${u(n.w)} )`;if(o>4&&n&&(n.isMatrix3||n.isMatrix4))return`${this.getType(i)}( ${n.elements.map(u).join(", ")} )`;if(o>4)return`${this.getType(i)}()`;throw new Error(`NodeBuilder: Type '${i}' not found in generate constant attempt.`)}getType(e){return"color"===e?"vec3":e}hasGeometryAttribute(e){return this.geometry&&void 0!==this.geometry.getAttribute(e)}getAttribute(e,t){const r=this.attributes;for(const t of r)if(t.name===e)return t;const s=new bb(e,t);return r.push(s),s}getPropertyName(e){return e.name}isVector(e){return/vec\d/.test(e)}isMatrix(e){return/mat\d/.test(e)}isReference(e){return"void"===e||"property"===e||"sampler"===e||"texture"===e||"cubeTexture"===e||"storageTexture"===e||"depthTexture"===e||"texture3D"===e}needsToWorkingColorSpace(){return!1}getComponentTypeFromTexture(e){const t=e.type;if(e.isDataTexture){if(t===b)return"int";if(t===x)return"uint"}return"float"}getElementType(e){return"mat2"===e?"vec2":"mat3"===e?"vec3":"mat4"===e?"vec4":this.getComponentType(e)}getComponentType(e){if("float"===(e=this.getVectorType(e))||"bool"===e||"int"===e||"uint"===e)return e;const t=/(b|i|u|)(vec|mat)([2-4])/.exec(e);return null===t?null:"b"===t[1]?"bool":"i"===t[1]?"int":"u"===t[1]?"uint":"float"}getVectorType(e){return"color"===e?"vec3":"texture"===e||"cubeTexture"===e||"storageTexture"===e||"texture3D"===e?"vec4":e}getTypeFromLength(e,t="float"){if(1===e)return t;const r=gs(e);return("float"===t?"":t[0])+r}getTypeFromArray(e){return lT.get(e.constructor)}getTypeFromAttribute(e){let t=e;e.isInterleavedBufferAttribute&&(t=e.data);const r=t.array,s=e.itemSize,i=e.normalized;let n;return e instanceof Le||!0===i||(n=this.getTypeFromArray(r)),this.getTypeFromLength(s,n)}getTypeLength(e){const t=this.getVectorType(e),r=/vec([2-4])/.exec(t);return null!==r?Number(r[1]):"float"===t||"bool"===t||"int"===t||"uint"===t?1:!0===/mat2/.test(e)?4:!0===/mat3/.test(e)?9:!0===/mat4/.test(e)?16:0}getVectorFromMatrix(e){return e.replace("mat","vec")}changeComponentType(e,t){return this.getTypeFromLength(this.getTypeLength(e),t)}getIntegerType(e){const t=this.getComponentType(e);return"int"===t||"uint"===t?e:this.changeComponentType(e,"int")}addStack(){return this.stack=lm(this.stack),this.stacks.push(Ni()||this.stack),vi(this.stack),this.stack}removeStack(){const e=this.stack;return this.stack=e.parent,vi(this.stacks.pop()),e}getDataFromNode(e,t=this.shaderStage,r=null){let s=(r=null===r?e.isGlobal(this)?this.globalCache:this.cache:r).getData(e);return void 0===s&&(s={},r.setData(e,s)),void 0===s[t]&&(s[t]={}),s[t]}getNodeProperties(e,t="any"){const r=this.getDataFromNode(e,t);return r.properties||(r.properties={outputNode:null})}getBufferAttributeFromNode(e,t){const r=this.getDataFromNode(e);let s=r.bufferAttribute;if(void 0===s){const i=this.uniforms.index++;s=new bb("nodeAttribute"+i,t,e),this.bufferAttributes.push(s),r.bufferAttribute=s}return s}getStructTypeFromNode(e,t,r=this.shaderStage){const s=this.getDataFromNode(e,r);let i=s.structType;if(void 0===i){const e=this.structs.index++;i=new Rb("StructType"+e,t),this.structs[r].push(i),s.structType=i}return i}getUniformFromNode(e,t,r=this.shaderStage,s=null){const i=this.getDataFromNode(e,r,this.globalCache);let n=i.uniform;if(void 0===n){const o=this.uniforms.index++;n=new Tb(s||"nodeUniform"+o,t,e),this.uniforms[r].push(n),i.uniform=n}return n}getVarFromNode(e,t=null,r=e.getNodeType(this),s=this.shaderStage){const i=this.getDataFromNode(e,s);let n=i.variable;if(void 0===n){const e=this.vars[s]||(this.vars[s]=[]);null===t&&(t="nodeVar"+e.length),n=new _b(t,r),e.push(n),i.variable=n}return n}getVaryingFromNode(e,t=null,r=e.getNodeType(this)){const s=this.getDataFromNode(e,"any");let i=s.varying;if(void 0===i){const e=this.varyings,n=e.length;null===t&&(t="nodeVarying"+n),i=new vb(t,r),e.push(i),s.varying=i}return i}getCodeFromNode(e,t,r=this.shaderStage){const s=this.getDataFromNode(e);let i=s.code;if(void 0===i){const e=this.codes[r]||(this.codes[r]=[]),n=e.length;i=new Nb("nodeCode"+n,t),e.push(i),s.code=i}return i}addFlowCodeHierarchy(e,t){const{flowCodes:r,flowCodeBlock:s}=this.getDataFromNode(e);let i=!0,n=t;for(;n;){if(!0===s.get(n)){i=!1;break}n=this.getDataFromNode(n).parentNodeBlock}if(i)for(const e of r)this.addLineFlowCode(e)}addLineFlowCodeBlock(e,t,r){const s=this.getDataFromNode(e),i=s.flowCodes||(s.flowCodes=[]),n=s.flowCodeBlock||(s.flowCodeBlock=new WeakMap);i.push(t),n.set(r,!0)}addLineFlowCode(e,t=null){return""===e||(null!==t&&this.context.nodeBlock&&this.addLineFlowCodeBlock(t,e,this.context.nodeBlock),e=this.tab+e,/;\s*$/.test(e)||(e+=";\n"),this.flow.code+=e),this}addFlowCode(e){return this.flow.code+=e,this}addFlowTab(){return this.tab+="\t",this}removeFlowTab(){return this.tab=this.tab.slice(0,-1),this}getFlowData(e){return this.flowsData.get(e)}flowNode(e){const t=e.getNodeType(this),r=this.flowChildNode(e,t);return this.flowsData.set(e,r),r}buildFunctionNode(e){const t=new oy,r=this.currentFunctionNode;return this.currentFunctionNode=t,t.code=this.buildFunctionCode(e),this.currentFunctionNode=r,t}flowShaderNode(e){const t=e.layout,r={[Symbol.iterator](){let e=0;const t=Object.values(this);return{next:()=>({value:t[e],done:e++>=t.length})}}};for(const e of t.inputs)r[e.name]=new am(e.type,e.name);e.layout=null;const s=e.call(r),i=this.flowStagesNode(s,t.type);return e.layout=t,i}flowStagesNode(e,t=null){const r=this.flow,s=this.vars,i=this.cache,n=this.buildStage,o=this.stack,a={code:""};this.flow=a,this.vars={},this.cache=new Ab,this.stack=lm();for(const r of Rs)this.setBuildStage(r),a.result=e.build(this,t);return a.vars=this.getVars(this.shaderStage),this.flow=r,this.vars=s,this.cache=i,this.stack=o,this.setBuildStage(n),a}getFunctionOperator(){return null}flowChildNode(e,t=null){const r=this.flow,s={code:""};return this.flow=s,s.result=e.build(this,t),this.flow=r,s}flowNodeFromShaderStage(e,t,r=null,s=null){const i=this.shaderStage;this.setShaderStage(e);const n=this.flowChildNode(t,r);return null!==s&&(n.code+=`${this.tab+s} = ${n.result};\n`),this.flowCode[e]=this.flowCode[e]+n.code,this.setShaderStage(i),n}getAttributesArray(){return this.attributes.concat(this.bufferAttributes)}getAttributes(){console.warn("Abstract function.")}getVaryings(){console.warn("Abstract function.")}getVar(e,t){return`${this.getType(e)} ${t}`}getVars(e){let t="";const r=this.vars[e];if(void 0!==r)for(const e of r)t+=`${this.getVar(e.type,e.name)}; `;return t}getUniforms(){console.warn("Abstract function.")}getCodes(e){const t=this.codes[e];let r="";if(void 0!==t)for(const e of t)r+=e.code+"\n";return r}getHash(){return this.vertexShader+this.fragmentShader+this.computeShader}setShaderStage(e){this.shaderStage=e}getShaderStage(){return this.shaderStage}setBuildStage(e){this.buildStage=e}getBuildStage(){return this.buildStage}buildCode(){console.warn("Abstract function.")}build(){const{object:e,material:t,renderer:r}=this;if(null!==t){let e=r.library.fromMaterial(t);null===e&&(console.error(`NodeMaterial: Material "${t.type}" is not compatible.`),e=new Yc),e.build(this)}else this.addFlow("compute",e);for(const e of Rs){this.setBuildStage(e),this.context.vertex&&this.context.vertex.isNode&&this.flowNodeFromShaderStage("vertex",this.context.vertex);for(const t of Cs){this.setShaderStage(t);const r=this.flowNodes[t];for(const t of r)"generate"===e?this.flowNode(t):t.build(this)}}return this.setBuildStage(null),this.setShaderStage(null),this.buildCode(),this.buildUpdateNodes(),this}getNodeUniform(e,t){if("float"===t||"int"===t||"uint"===t)return new Ib(e);if("vec2"===t||"ivec2"===t||"uvec2"===t)return new Lb(e);if("vec3"===t||"ivec3"===t||"uvec3"===t)return new Vb(e);if("vec4"===t||"ivec4"===t||"uvec4"===t)return new Db(e);if("color"===t)return new Ob(e);if("mat3"===t)return new Gb(e);if("mat4"===t)return new kb(e);throw new Error(`Uniform "${t}" not declared.`)}format(e,t,r){if((t=this.getVectorType(t))===(r=this.getVectorType(r))||null===r||this.isReference(r))return e;const s=this.getTypeLength(t),i=this.getTypeLength(r);return 16===s&&9===i?`${this.getType(r)}(${e}[0].xyz, ${e}[1].xyz, ${e}[2].xyz)`:9===s&&4===i?`${this.getType(r)}(${e}[0].xy, ${e}[1].xy)`:s>4||i>4||0===i?e:s===i?`${this.getType(r)}( ${e} )`:s>i?this.format(`${e}.${"xyz".slice(0,i)}`,this.getTypeFromLength(i,this.getComponentType(t)),r):4===i&&s>1?`${this.getType(r)}( ${this.format(e,t,"vec3")}, 1.0 )`:2===s?`${this.getType(r)}( ${this.format(e,t,"vec2")}, 0.0 )`:(1===s&&i>1&&t!==this.getComponentType(r)&&(e=`${this.getType(this.getComponentType(r))}( ${e} )`),`${this.getType(r)}( ${e} )`)}getSignature(){return`// Three.js r${Ve} - Node System\n`}createNodeMaterial(e="NodeMaterial"){throw new Error(`THREE.NodeBuilder: createNodeMaterial() was deprecated. Use new ${e}() instead.`)}}class hT{constructor(){this.time=0,this.deltaTime=0,this.frameId=0,this.renderId=0,this.updateMap=new WeakMap,this.updateBeforeMap=new WeakMap,this.updateAfterMap=new WeakMap,this.renderer=null,this.material=null,this.camera=null,this.object=null,this.scene=null}_getMaps(e,t){let r=e.get(t);return void 0===r&&(r={renderMap:new WeakMap,frameMap:new WeakMap},e.set(t,r)),r}updateBeforeNode(e){const t=e.getUpdateBeforeType(),r=e.updateReference(this);if(t===vs.FRAME){const{frameMap:t}=this._getMaps(this.updateBeforeMap,r);t.get(r)!==this.frameId&&!1!==e.updateBefore(this)&&t.set(r,this.frameId)}else if(t===vs.RENDER){const{renderMap:t}=this._getMaps(this.updateBeforeMap,r);t.get(r)!==this.renderId&&!1!==e.updateBefore(this)&&t.set(r,this.renderId)}else t===vs.OBJECT&&e.updateBefore(this)}updateAfterNode(e){const t=e.getUpdateAfterType(),r=e.updateReference(this);if(t===vs.FRAME){const{frameMap:t}=this._getMaps(this.updateAfterMap,r);t.get(r)!==this.frameId&&!1!==e.updateAfter(this)&&t.set(r,this.frameId)}else if(t===vs.RENDER){const{renderMap:t}=this._getMaps(this.updateAfterMap,r);t.get(r)!==this.renderId&&!1!==e.updateAfter(this)&&t.set(r,this.renderId)}else t===vs.OBJECT&&e.updateAfter(this)}updateNode(e){const t=e.getUpdateType(),r=e.updateReference(this);if(t===vs.FRAME){const{frameMap:t}=this._getMaps(this.updateMap,r);t.get(r)!==this.frameId&&!1!==e.update(this)&&t.set(r,this.frameId)}else if(t===vs.RENDER){const{renderMap:t}=this._getMaps(this.updateMap,r);t.get(r)!==this.renderId&&!1!==e.update(this)&&t.set(r,this.renderId)}else t===vs.OBJECT&&e.update(this)}update(){this.frameId++,void 0===this.lastTime&&(this.lastTime=performance.now()),this.deltaTime=(performance.now()-this.lastTime)/1e3,this.lastTime=performance.now(),this.time+=this.deltaTime}}class pT{constructor(e,t,r=null,s="",i=!1){this.type=e,this.name=t,this.count=r,this.qualifier=s,this.isConst=i}}pT.isNodeFunctionInput=!0;class gT extends ax{static get type(){return"DirectionalLightNode"}constructor(e=null){super(e)}setup(e){super.setup(e);const t=e.context.lightingModel,r=this.colorNode,s=zy(this.light),i=e.context.reflectedLight;t.direct({lightDirection:s,lightColor:r,reflectedLight:i},e.stack,e)}}const mT=new n,fT=new n;let yT=null;class xT extends ax{static get type(){return"RectAreaLightNode"}constructor(e=null){super(e),this.halfHeight=tn(new r).setGroup(Zi),this.halfWidth=tn(new r).setGroup(Zi),this.updateType=vs.RENDER}update(e){super.update(e);const{light:t}=this,r=e.camera.matrixWorldInverse;fT.identity(),mT.copy(t.matrixWorld),mT.premultiply(r),fT.extractRotation(mT),this.halfWidth.value.set(.5*t.width,0,0),this.halfHeight.value.set(0,.5*t.height,0),this.halfWidth.value.applyMatrix4(fT),this.halfHeight.value.applyMatrix4(fT)}setup(e){let t,r;super.setup(e),e.isAvailable("float32Filterable")?(t=bu(yT.LTC_FLOAT_1),r=bu(yT.LTC_FLOAT_2)):(t=bu(yT.LTC_HALF_1),r=bu(yT.LTC_HALF_2));const{colorNode:s,light:i}=this,n=e.context.lightingModel,o=ky(i),a=e.context.reflectedLight;n.directRectArea({lightColor:s,lightPosition:o,halfWidth:this.halfWidth,halfHeight:this.halfHeight,reflectedLight:a,ltc_1:t,ltc_2:r},e.stack,e)}static setLTC(e){yT=e}}class bT extends ax{static get type(){return"SpotLightNode"}constructor(e=null){super(e),this.coneCosNode=tn(0).setGroup(Zi),this.penumbraCosNode=tn(0).setGroup(Zi),this.cutoffDistanceNode=tn(0).setGroup(Zi),this.decayExponentNode=tn(0).setGroup(Zi)}update(e){super.update(e);const{light:t}=this;this.coneCosNode.value=Math.cos(t.angle),this.penumbraCosNode.value=Math.cos(t.angle*(1-t.penumbra)),this.cutoffDistanceNode.value=t.distance,this.decayExponentNode.value=t.decay}getSpotAttenuation(e){const{coneCosNode:t,penumbraCosNode:r}=this;return pa(t,r,e)}setup(e){super.setup(e);const t=e.context.lightingModel,{colorNode:r,cutoffDistanceNode:s,decayExponentNode:i,light:n}=this,o=ky(n).sub(Zu),a=o.normalize(),u=a.dot(zy(n)),l=this.getSpotAttenuation(u),d=o.length(),c=ux({lightDistance:d,cutoffDistance:s,decayExponent:i});let h=r.mul(l).mul(c);if(n.map){const e=Dy(n),t=bu(n.map,e.xy).onRenderUpdate((()=>n.map));h=e.mul(2).sub(1).abs().lessThan(1).all().select(h.mul(t),h)}const p=e.context.reflectedLight;t.direct({lightDirection:a,lightColor:h,reflectedLight:p},e.stack,e)}}class TT extends bT{static get type(){return"IESSpotLightNode"}getSpotAttenuation(e){const t=this.light.iesMap;let r=null;if(t&&!0===t.isTexture){const s=e.acos().mul(1/Math.PI);r=bu(t,Bi(s,0),0).r}else r=super.getSpotAttenuation(e);return r}}class _T extends ax{static get type(){return"AmbientLightNode"}constructor(e=null){super(e)}setup({context:e}){e.irradiance.addAssign(this.colorNode)}}class vT extends ax{static get type(){return"HemisphereLightNode"}constructor(t=null){super(t),this.lightPositionNode=Oy(t),this.lightDirectionNode=this.lightPositionNode.normalize(),this.groundColorNode=tn(new e).setGroup(Zi)}update(e){const{light:t}=this;super.update(e),this.lightPositionNode.object3d=t,this.groundColorNode.value.copy(t.groundColor).multiplyScalar(t.intensity)}setup(e){const{colorNode:t,groundColorNode:r,lightDirectionNode:s}=this,i=ol.dot(s).mul(.5).add(.5),n=la(r,t,i);e.context.irradiance.addAssign(n)}}class NT extends ax{static get type(){return"LightProbeNode"}constructor(e=null){super(e);const t=[];for(let e=0;e<9;e++)t.push(new r);this.lightProbe=Sl(t)}update(e){const{light:t}=this;super.update(e);for(let e=0;e<9;e++)this.lightProbe.array[e].copy(t.sh.coefficients[e]).multiplyScalar(t.intensity)}setup(e){const t=hb(al,this.lightProbe);e.context.irradiance.addAssign(t)}}class ST{parseFunction(){console.warn("Abstract function.")}}class AT{constructor(e,t,r="",s=""){this.type=e,this.inputs=t,this.name=r,this.precision=s}getCode(){console.warn("Abstract function.")}}AT.isNodeFunction=!0;const RT=/^\s*(highp|mediump|lowp)?\s*([a-z_0-9]+)\s*([a-z_0-9]+)?\s*\(([\s\S]*?)\)/i,CT=/[a-z_0-9]+/gi,ET="#pragma main";class wT extends AT{constructor(e){const{type:t,inputs:r,name:s,precision:i,inputsCode:n,blockCode:o,headerCode:a}=(e=>{const t=(e=e.trim()).indexOf(ET),r=-1!==t?e.slice(t+12):e,s=r.match(RT);if(null!==s&&5===s.length){const i=s[4],n=[];let o=null;for(;null!==(o=CT.exec(i));)n.push(o);const a=[];let u=0;for(;u0||e.backgroundBlurriness>0&&0===t.backgroundBlurriness;if(t.background!==r||s){let s=null;if(!0===r.isCubeTexture||r.mapping===j||r.mapping===q||r.mapping===Be)if(e.backgroundBlurriness>0||r.mapping===Be)s=qp(r);else{let e;e=!0===r.isCubeTexture?bl(r):bu(r),s=xh(e)}else!0===r.isTexture?s=bu(r,bc.flipY()).setUpdateMatrix(!0):!0!==r.isColor&&console.error("WebGPUNodes: Unsupported background configuration.",r);t.backgroundNode=s,t.background=r,t.backgroundBlurriness=e.backgroundBlurriness}}else t.backgroundNode&&(delete t.backgroundNode,delete t.background)}updateFog(e){const t=this.get(e),r=e.fog;if(r){if(t.fog!==r){let e=null;if(r.isFogExp2){const t=Cl("color","color",r).setGroup(Zi),s=Cl("density","float",r).setGroup(Zi);e=xy(t,yy(s))}else if(r.isFog){const t=Cl("color","color",r).setGroup(Zi),s=Cl("near","float",r).setGroup(Zi),i=Cl("far","float",r).setGroup(Zi);e=xy(t,fy(s,i))}else console.error("WebGPUNodes: Unsupported fog configuration.",r);t.fogNode=e,t.fog=r}}else delete t.fogNode,delete t.fog}updateEnvironment(e){const t=this.get(e),r=e.environment;if(r){if(t.environment!==r){let e=null;!0===r.isCubeTexture?e=bl(r):!0===r.isTexture?e=bu(r):console.error("Nodes: Unsupported environment configuration.",r),t.environmentNode=e,t.environment=r}}else t.environmentNode&&(delete t.environmentNode,delete t.environment)}getNodeFrame(e=this.renderer,t=null,r=null,s=null,i=null){const n=this.nodeFrame;return n.renderer=e,n.scene=t,n.object=r,n.camera=s,n.material=i,n}getNodeFrameForRender(e){return this.getNodeFrame(e.renderer,e.scene,e.object,e.camera,e.material)}getOutputCacheKey(){const e=this.renderer;return e.toneMapping+","+e.currentColorSpace}hasOutputChange(e){return BT.get(e)!==this.getOutputCacheKey()}getOutputNode(e){const t=this.renderer,r=this.getOutputCacheKey(),s=bu(e,bc).renderOutput(t.toneMapping,t.currentColorSpace);return BT.set(e,r),s}updateBefore(e){const t=e.getNodeBuilderState();for(const r of t.updateBeforeNodes)this.getNodeFrameForRender(e).updateBeforeNode(r)}updateAfter(e){const t=e.getNodeBuilderState();for(const r of t.updateAfterNodes)this.getNodeFrameForRender(e).updateAfterNode(r)}updateForCompute(e){const t=this.getNodeFrame(),r=this.getForCompute(e);for(const e of r.updateNodes)t.updateNode(e)}updateForRender(e){const t=this.getNodeFrameForRender(e),r=e.getNodeBuilderState();for(const e of r.updateNodes)t.updateNode(e)}needsRefresh(e){const t=this.getNodeFrameForRender(e);return e.getMonitor().needsRefresh(e,t)}dispose(){super.dispose(),this.nodeFrame=new hT,this.nodeBuilderCache=new Map}}const FT=new me;class PT{constructor(e=null){this.version=0,this.clipIntersection=null,this.cacheKey="",null===e?(this.intersectionPlanes=[],this.unionPlanes=[],this.viewNormalMatrix=new i,this.clippingGroupContexts=new WeakMap,this.shadowPass=!1):(this.viewNormalMatrix=e.viewNormalMatrix,this.clippingGroupContexts=e.clippingGroupContexts,this.shadowPass=e.shadowPass,this.viewMatrix=e.viewMatrix),this.parentVersion=null}projectPlanes(e,t,r){const s=e.length;for(let i=0;i{await this.compileAsync(e,t);const s=this._renderLists.get(e,t),i=this._renderContexts.get(e,t,this._renderTarget),n=e.overrideMaterial||r.material,o=this._objects.get(r,n,e,t,s.lightsNode,i,i.clippingContext),{fragmentShader:a,vertexShader:u}=o.getNodeBuilderState();return{fragmentShader:a,vertexShader:u}}}}async init(){if(this._initialized)throw new Error("Renderer: Backend has already been initialized.");return null!==this._initPromise||(this._initPromise=new Promise((async(e,t)=>{let r=this.backend;try{await r.init(this)}catch(e){if(null===this._getFallback)return void t(e);try{this.backend=r=this._getFallback(e),await r.init(this)}catch(e){return void t(e)}}this._nodes=new UT(this,r),this._animation=new Ag(this._nodes,this.info),this._attributes=new Vg(r),this._background=new mb(this,this._nodes),this._geometries=new Gg(this._attributes,this.info),this._textures=new nm(this,r,this.info),this._pipelines=new qg(r,this._nodes),this._bindings=new Kg(r,this._nodes,this._textures,this._attributes,this._pipelines,this.info),this._objects=new Mg(this,this._nodes,this._geometries,this._pipelines,this._bindings,this.info),this._renderLists=new Jg(this.lighting),this._bundles=new LT,this._renderContexts=new sm,this._animation.start(),this._initialized=!0,e()}))),this._initPromise}get coordinateSystem(){return this.backend.coordinateSystem}async compileAsync(e,t,r=null){if(!0===this._isDeviceLost)return;!1===this._initialized&&await this.init();const s=this._nodes.nodeFrame,i=s.renderId,n=this._currentRenderContext,o=this._currentRenderObjectFunction,a=this._compilationPromises,u=!0===e.isScene?e:GT;null===r&&(r=e);const l=this._renderTarget,d=this._renderContexts.get(r,t,l),c=this._activeMipmapLevel,h=[];this._currentRenderContext=d,this._currentRenderObjectFunction=this.renderObject,this._handleObjectFunction=this._createObjectPipeline,this._compilationPromises=h,s.renderId++,s.update(),d.depth=this.depth,d.stencil=this.stencil,d.clippingContext||(d.clippingContext=new PT),d.clippingContext.updateGlobal(u,t),u.onBeforeRender(this,e,t,l);const p=this._renderLists.get(e,t);if(p.begin(),this._projectObject(e,t,0,p,d.clippingContext),r!==e&&r.traverseVisible((function(e){e.isLight&&e.layers.test(t.layers)&&p.pushLight(e)})),p.finish(),null!==l){this._textures.updateRenderTarget(l,c);const e=this._textures.get(l);d.textures=e.textures,d.depthTexture=e.depthTexture}else d.textures=null,d.depthTexture=null;this._nodes.updateScene(u),this._background.update(u,p,d);const g=p.opaque,m=p.transparent,f=p.transparentDoublePass,y=p.lightsNode;!0===this.opaque&&g.length>0&&this._renderObjects(g,t,u,y),!0===this.transparent&&m.length>0&&this._renderTransparents(m,f,t,u,y),s.renderId=i,this._currentRenderContext=n,this._currentRenderObjectFunction=o,this._compilationPromises=a,this._handleObjectFunction=this._renderObjectDirect,await Promise.all(h)}async renderAsync(e,t){!1===this._initialized&&await this.init();const r=this._renderScene(e,t);await this.backend.resolveTimestampAsync(r,"render")}async waitForGPU(){await this.backend.waitForGPU()}setMRT(e){return this._mrt=e,this}getMRT(){return this._mrt}_onDeviceLost(e){let t=`THREE.WebGPURenderer: ${e.api} Device Lost:\n\nMessage: ${e.message}`;e.reason&&(t+=`\nReason: ${e.reason}`),console.error(t),this._isDeviceLost=!0}_renderBundle(e,t,r){const{bundleGroup:s,camera:i,renderList:n}=e,o=this._currentRenderContext,a=this._bundles.get(s,i),u=this.backend.get(a);void 0===u.renderContexts&&(u.renderContexts=new Set);const l=s.version!==u.version,d=!1===u.renderContexts.has(o)||l;if(u.renderContexts.add(o),d){this.backend.beginBundle(o),(void 0===u.renderObjects||l)&&(u.renderObjects=[]),this._currentRenderBundle=a;const e=n.opaque;!0===this.opaque&&e.length>0&&this._renderObjects(e,i,t,r),this._currentRenderBundle=null,this.backend.finishBundle(o,a),u.version=s.version}else{const{renderObjects:e}=u;for(let t=0,r=e.length;t>=c,p.viewportValue.height>>=c,p.viewportValue.minDepth=x,p.viewportValue.maxDepth=b,p.viewport=!1===p.viewportValue.equals(zT),p.scissorValue.copy(f).multiplyScalar(y).floor(),p.scissor=this._scissorTest&&!1===p.scissorValue.equals(zT),p.scissorValue.width>>=c,p.scissorValue.height>>=c,p.clippingContext||(p.clippingContext=new PT),p.clippingContext.updateGlobal(u,t),u.onBeforeRender(this,e,t,h),HT.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),$T.setFromProjectionMatrix(HT,g);const T=this._renderLists.get(e,t);if(T.begin(),this._projectObject(e,t,0,T,p.clippingContext),T.finish(),!0===this.sortObjects&&T.sort(this._opaqueSort,this._transparentSort),null!==h){this._textures.updateRenderTarget(h,c);const e=this._textures.get(h);p.textures=e.textures,p.depthTexture=e.depthTexture,p.width=e.width,p.height=e.height,p.renderTarget=h,p.depth=h.depthBuffer,p.stencil=h.stencilBuffer}else p.textures=null,p.depthTexture=null,p.width=this.domElement.width,p.height=this.domElement.height,p.depth=this.depth,p.stencil=this.stencil;p.width>>=c,p.height>>=c,p.activeCubeFace=d,p.activeMipmapLevel=c,p.occlusionQueryCount=T.occlusionQueryCount,this._nodes.updateScene(u),this._background.update(u,T,p),this.backend.beginRender(p);const{bundles:_,lightsNode:v,transparentDoublePass:N,transparent:S,opaque:A}=T;if(_.length>0&&this._renderBundles(_,u,v),!0===this.opaque&&A.length>0&&this._renderObjects(A,t,u,v),!0===this.transparent&&S.length>0&&this._renderTransparents(S,N,t,u,v),this.backend.finishRender(p),i.renderId=n,this._currentRenderContext=o,this._currentRenderObjectFunction=a,null!==s){this.setRenderTarget(l,d,c);const e=this._quad;this._nodes.hasOutputChange(h.texture)&&(e.material.fragmentNode=this._nodes.getOutputNode(h.texture),e.material.needsUpdate=!0),this._renderScene(e,e.camera,!1)}return u.onAfterRender(this,e,t,h),p}getMaxAnisotropy(){return this.backend.getMaxAnisotropy()}getActiveCubeFace(){return this._activeCubeFace}getActiveMipmapLevel(){return this._activeMipmapLevel}async setAnimationLoop(e){!1===this._initialized&&await this.init(),this._animation.setAnimationLoop(e)}async getArrayBufferAsync(e){return await this.backend.getArrayBufferAsync(e)}getContext(){return this.backend.getContext()}getPixelRatio(){return this._pixelRatio}getDrawingBufferSize(e){return e.set(this._width*this._pixelRatio,this._height*this._pixelRatio).floor()}getSize(e){return e.set(this._width,this._height)}setPixelRatio(e=1){this._pixelRatio!==e&&(this._pixelRatio=e,this.setSize(this._width,this._height,!1))}setDrawingBufferSize(e,t,r){this._width=e,this._height=t,this._pixelRatio=r,this.domElement.width=Math.floor(e*r),this.domElement.height=Math.floor(t*r),this.setViewport(0,0,e,t),this._initialized&&this.backend.updateSize()}setSize(e,t,r=!0){this._width=e,this._height=t,this.domElement.width=Math.floor(e*this._pixelRatio),this.domElement.height=Math.floor(t*this._pixelRatio),!0===r&&(this.domElement.style.width=e+"px",this.domElement.style.height=t+"px"),this.setViewport(0,0,e,t),this._initialized&&this.backend.updateSize()}setOpaqueSort(e){this._opaqueSort=e}setTransparentSort(e){this._transparentSort=e}getScissor(e){const t=this._scissor;return e.x=t.x,e.y=t.y,e.width=t.width,e.height=t.height,e}setScissor(e,t,r,s){const i=this._scissor;e.isVector4?i.copy(e):i.set(e,t,r,s)}getScissorTest(){return this._scissorTest}setScissorTest(e){this._scissorTest=e,this.backend.setScissorTest(e)}getViewport(e){return e.copy(this._viewport)}setViewport(e,t,r,s,i=0,n=1){const o=this._viewport;e.isVector4?o.copy(e):o.set(e,t,r,s),o.minDepth=i,o.maxDepth=n}getClearColor(e){return e.copy(this._clearColor)}setClearColor(e,t=1){this._clearColor.set(e),this._clearColor.a=t}getClearAlpha(){return this._clearColor.a}setClearAlpha(e){this._clearColor.a=e}getClearDepth(){return this._clearDepth}setClearDepth(e){this._clearDepth=e}getClearStencil(){return this._clearStencil}setClearStencil(e){this._clearStencil=e}isOccluded(e){const t=this._currentRenderContext;return t&&this.backend.isOccluded(t,e)}clear(e=!0,t=!0,r=!0){if(!1===this._initialized)return console.warn("THREE.Renderer: .clear() called before the backend is initialized. Try using .clearAsync() instead."),this.clearAsync(e,t,r);const s=this._renderTarget||this._getFrameBufferTarget();let i=null;if(null!==s&&(this._textures.updateRenderTarget(s),i=this._textures.get(s)),this.backend.clear(e,t,r,i),null!==s&&null===this._renderTarget){const e=this._quad;this._nodes.hasOutputChange(s.texture)&&(e.material.fragmentNode=this._nodes.getOutputNode(s.texture),e.material.needsUpdate=!0),this._renderScene(e,e.camera,!1)}}clearColor(){return this.clear(!0,!1,!1)}clearDepth(){return this.clear(!1,!0,!1)}clearStencil(){return this.clear(!1,!1,!0)}async clearAsync(e=!0,t=!0,r=!0){!1===this._initialized&&await this.init(),this.clear(e,t,r)}clearColorAsync(){return this.clearAsync(!0,!1,!1)}clearDepthAsync(){return this.clearAsync(!1,!0,!1)}clearStencilAsync(){return this.clearAsync(!1,!1,!0)}get currentToneMapping(){return null!==this._renderTarget?h:this.toneMapping}get currentColorSpace(){return null!==this._renderTarget?Ae:this.outputColorSpace}dispose(){this.info.dispose(),this.backend.dispose(),this._animation.dispose(),this._objects.dispose(),this._pipelines.dispose(),this._nodes.dispose(),this._bindings.dispose(),this._renderLists.dispose(),this._renderContexts.dispose(),this._textures.dispose(),this.setRenderTarget(null),this.setAnimationLoop(null)}setRenderTarget(e,t=0,r=0){this._renderTarget=e,this._activeCubeFace=t,this._activeMipmapLevel=r}getRenderTarget(){return this._renderTarget}setRenderObjectFunction(e){this._renderObjectFunction=e}getRenderObjectFunction(){return this._renderObjectFunction}compute(e){if(!0===this.isDeviceLost)return;if(!1===this._initialized)return console.warn("THREE.Renderer: .compute() called before the backend is initialized. Try using .computeAsync() instead."),this.computeAsync(e);const t=this._nodes.nodeFrame,r=t.renderId;this.info.calls++,this.info.compute.calls++,this.info.compute.frameCalls++,t.renderId=this.info.calls;const s=this.backend,i=this._pipelines,n=this._bindings,o=this._nodes,a=Array.isArray(e)?e:[e];if(void 0===a[0]||!0!==a[0].isComputeNode)throw new Error("THREE.Renderer: .compute() expects a ComputeNode.");s.beginCompute(e);for(const t of a){if(!1===i.has(t)){const e=()=>{t.removeEventListener("dispose",e),i.delete(t),n.delete(t),o.delete(t)};t.addEventListener("dispose",e);const r=t.onInitFunction;null!==r&&r.call(t,{renderer:this})}o.updateForCompute(t),n.updateForCompute(t);const r=n.getForCompute(t),a=i.getForCompute(t,r);s.compute(e,t,r,a)}s.finishCompute(e),t.renderId=r}async computeAsync(e){!1===this._initialized&&await this.init(),this.compute(e),await this.backend.resolveTimestampAsync(e,"compute")}async hasFeatureAsync(e){return!1===this._initialized&&await this.init(),this.backend.hasFeature(e)}hasFeature(e){return!1===this._initialized?(console.warn("THREE.Renderer: .hasFeature() called before the backend is initialized. Try using .hasFeatureAsync() instead."),!1):this.backend.hasFeature(e)}hasInitialized(){return this._initialized}async initTextureAsync(e){!1===this._initialized&&await this.init(),this._textures.updateTexture(e)}initTexture(e){if(!1===this._initialized)return console.warn("THREE.Renderer: .initTexture() called before the backend is initialized. Try using .initTextureAsync() instead."),!1;this._textures.updateTexture(e)}copyFramebufferToTexture(e,t=null){if(null!==t)if(t.isVector2)t=WT.set(t.x,t.y,e.image.width,e.image.height).floor();else{if(!t.isVector4)return void console.error("THREE.Renderer.copyFramebufferToTexture: Invalid rectangle.");t=WT.copy(t).floor()}else t=WT.set(0,0,e.image.width,e.image.height);let r,s=this._currentRenderContext;null!==s?r=s.renderTarget:(r=this._renderTarget||this._getFrameBufferTarget(),null!==r&&(this._textures.updateRenderTarget(r),s=this._textures.get(r))),this._textures.updateTexture(e,{renderTarget:r}),this.backend.copyFramebufferToTexture(e,s,t)}copyTextureToTexture(e,t,r=null,s=null,i=0){this._textures.updateTexture(e),this._textures.updateTexture(t),this.backend.copyTextureToTexture(e,t,r,s,i)}readRenderTargetPixelsAsync(e,t,r,s,i,n=0,o=0){return this.backend.copyTextureToBuffer(e.textures[n],t,r,s,i,o)}_projectObject(e,t,r,s,i){if(!1===e.visible)return;if(e.layers.test(t.layers))if(e.isGroup)r=e.renderOrder,e.isClippingGroup&&e.enabled&&(i=i.getGroupContext(e));else if(e.isLOD)!0===e.autoUpdate&&e.update(t);else if(e.isLight)s.pushLight(e);else if(e.isSprite){if(!e.frustumCulled||$T.intersectsSprite(e)){!0===this.sortObjects&&WT.setFromMatrixPosition(e.matrixWorld).applyMatrix4(HT);const{geometry:t,material:n}=e;n.visible&&s.push(e,t,n,r,WT.z,null,i)}}else if(e.isLineLoop)console.error("THREE.Renderer: Objects of type THREE.LineLoop are not supported. Please use THREE.Line or THREE.LineSegments.");else if((e.isMesh||e.isLine||e.isPoints)&&(!e.frustumCulled||$T.intersectsObject(e))){const{geometry:t,material:n}=e;if(!0===this.sortObjects&&(null===t.boundingSphere&&t.computeBoundingSphere(),WT.copy(t.boundingSphere.center).applyMatrix4(e.matrixWorld).applyMatrix4(HT)),Array.isArray(n)){const o=t.groups;for(let a=0,u=o.length;a0){for(const{material:e}of t)e.side=T;this._renderObjects(t,r,s,i,"backSide");for(const{material:e}of t)e.side=Ge;this._renderObjects(e,r,s,i);for(const{material:e}of t)e.side=le}else this._renderObjects(e,r,s,i)}_renderObjects(e,t,r,s,i=null){for(let n=0,o=e.length;n0,e.isShadowNodeMaterial&&(e.side=null===i.shadowSide?i.side:i.shadowSide,i.depthNode&&i.depthNode.isNode&&(c=e.depthNode,e.depthNode=i.depthNode),i.castShadowNode&&i.castShadowNode.isNode&&(d=e.colorNode,e.colorNode=i.castShadowNode)),i=e}!0===i.transparent&&i.side===le&&!1===i.forceSinglePass?(i.side=T,this._handleObjectFunction(e,i,t,r,o,n,a,"backSide"),i.side=Ge,this._handleObjectFunction(e,i,t,r,o,n,a,u),i.side=le):this._handleObjectFunction(e,i,t,r,o,n,a,u),void 0!==l&&(t.overrideMaterial.positionNode=l),void 0!==c&&(t.overrideMaterial.depthNode=c),void 0!==d&&(t.overrideMaterial.colorNode=d),e.onAfterRender(this,t,r,s,i,n)}_renderObjectDirect(e,t,r,s,i,n,o,a){const u=this._objects.get(e,t,r,s,i,this._currentRenderContext,o,a);u.drawRange=e.geometry.drawRange,u.group=n;const l=this._nodes.needsRefresh(u);if(l&&(this._nodes.updateBefore(u),this._geometries.updateForRender(u),this._nodes.updateForRender(u),this._bindings.updateForRender(u)),this._pipelines.updateForRender(u),null!==this._currentRenderBundle){this.backend.get(this._currentRenderBundle).renderObjects.push(u),u.bundle=this._currentRenderBundle.scene}this.backend.draw(u,this.info),l&&this._nodes.updateAfter(u)}_createObjectPipeline(e,t,r,s,i,n,o,a){const u=this._objects.get(e,t,r,s,i,this._currentRenderContext,o,a);u.drawRange=e.geometry.drawRange,u.group=n,this._nodes.updateBefore(u),this._geometries.updateForRender(u),this._nodes.updateForRender(u),this._bindings.updateForRender(u),this._pipelines.getForRender(u,this._compilationPromises),this._nodes.updateAfter(u)}get compile(){return this.compileAsync}}class qT{constructor(e=""){this.name=e,this.visibility=0}setVisibility(e){this.visibility|=e}clone(){return Object.assign(new this.constructor,this)}}class KT extends qT{constructor(e,t=null){super(e),this.isBuffer=!0,this.bytesPerElement=Float32Array.BYTES_PER_ELEMENT,this._buffer=t}get byteLength(){return(e=this._buffer.byteLength)+(Lg-e%Lg)%Lg;var e}get buffer(){return this._buffer}update(){return!0}}class XT extends KT{constructor(e,t=null){super(e,t),this.isUniformBuffer=!0}}let YT=0;class QT extends XT{constructor(e,t){super("UniformBuffer_"+YT++,e?e.value:null),this.nodeUniform=e,this.groupNode=t}get buffer(){return this.nodeUniform.value}}class ZT extends XT{constructor(e){super(e),this.isUniformsGroup=!0,this._values=null,this.uniforms=[]}addUniform(e){return this.uniforms.push(e),this}removeUniform(e){const t=this.uniforms.indexOf(e);return-1!==t&&this.uniforms.splice(t,1),this}get values(){return null===this._values&&(this._values=Array.from(this.buffer)),this._values}get buffer(){let e=this._buffer;if(null===e){const t=this.byteLength;e=new Float32Array(new ArrayBuffer(t)),this._buffer=e}return e}get byteLength(){let e=0;for(let t=0,r=this.uniforms.length;t0?s:"";t=`${e.name} {\n\t${r} ${i.name}[${n}];\n};\n`}else{t=`${this.getVectorType(i.type)} ${this.getPropertyName(i,e)};`,n=!0}const o=i.node.precision;if(null!==o&&(t=a_[o]+" "+t),n){t="\t"+t;const e=i.groupNode.name;(s[e]||(s[e]=[])).push(t)}else t="uniform "+t,r.push(t)}let i="";for(const t in s){const r=s[t];i+=this._getGLSLUniformStruct(e+"_"+t,r.join("\n"))+"\n"}return i+=r.join("\n"),i}getTypeFromAttribute(e){let t=super.getTypeFromAttribute(e);if(/^[iu]/.test(t)&&e.gpuType!==b){let r=e;e.isInterleavedBufferAttribute&&(r=e.data);const s=r.array;!1==(s instanceof Uint32Array||s instanceof Int32Array)&&(t=t.slice(1))}return t}getAttributes(e){let t="";if("vertex"===e||"compute"===e){const e=this.getAttributesArray();let r=0;for(const s of e)t+=`layout( location = ${r++} ) in ${s.type} ${s.name};\n`}return t}getStructMembers(e){const t=[],r=e.getMemberTypes();for(let e=0;ee*t),1)}u`}getDrawIndex(){return this.renderer.backend.extensions.has("WEBGL_multi_draw")?"uint( gl_DrawID )":null}getFrontFacing(){return"gl_FrontFacing"}getFragCoord(){return"gl_FragCoord.xy"}getFragDepth(){return"gl_FragDepth"}enableExtension(e,t,r=this.shaderStage){const s=this.extensions[r]||(this.extensions[r]=new Map);!1===s.has(e)&&s.set(e,{name:e,behavior:t})}getExtensions(e){const t=[];if("vertex"===e){const t=this.renderer.backend.extensions;this.object.isBatchedMesh&&t.has("WEBGL_multi_draw")&&this.enableExtension("GL_ANGLE_multi_draw","require",e)}const r=this.extensions[e];if(void 0!==r)for(const{name:e,behavior:s}of r.values())t.push(`#extension ${e} : ${s}`);return t.join("\n")}getClipDistance(){return"gl_ClipDistance"}isAvailable(e){let t=u_[e];if(void 0===t){let r;switch(t=!1,e){case"float32Filterable":r="OES_texture_float_linear";break;case"clipDistance":r="WEBGL_clip_cull_distance"}if(void 0!==r){const e=this.renderer.backend.extensions;e.has(r)&&(e.get(r),t=!0)}u_[e]=t}return t}isFlipY(){return!0}enableHardwareClipping(e){this.enableExtension("GL_ANGLE_clip_cull_distance","require"),this.builtins.vertex.push(`out float gl_ClipDistance[ ${e} ]`)}registerTransform(e,t){this.transforms.push({varyingName:e,attributeNode:t})}getTransforms(){const e=this.transforms;let t="";for(let r=0;r0&&(r+="\n"),r+=`\t// flow -> ${n}\n\t`),r+=`${s.code}\n\t`,e===i&&"compute"!==t&&(r+="// result\n\t","vertex"===t?(r+="gl_Position = ",r+=`${s.result};`):"fragment"===t&&(e.outputNode.isOutputStructNode||(r+="fragColor = ",r+=`${s.result};`)))}const n=e[t];n.extensions=this.getExtensions(t),n.uniforms=this.getUniforms(t),n.attributes=this.getAttributes(t),n.varyings=this.getVaryings(t),n.vars=this.getVars(t),n.structs=this.getStructs(t),n.codes=this.getCodes(t),n.transforms=this.getTransforms(t),n.flow=r}null!==this.material?(this.vertexShader=this._getGLSLVertexCode(e.vertex),this.fragmentShader=this._getGLSLFragmentCode(e.fragment)):this.computeShader=this._getGLSLVertexCode(e.compute)}getUniformFromNode(e,t,r,s=null){const i=super.getUniformFromNode(e,t,r,s),n=this.getDataFromNode(e,r,this.globalCache);let o=n.uniformGPU;if(void 0===o){const s=e.groupNode,a=s.name,u=this.getBindGroupArray(a,r);if("texture"===t)o=new s_(i.name,i.node,s),u.push(o);else if("cubeTexture"===t)o=new i_(i.name,i.node,s),u.push(o);else if("texture3D"===t)o=new n_(i.name,i.node,s),u.push(o);else if("buffer"===t){e.name=`NodeBuffer_${e.id}`,i.name=`buffer${e.id}`;const t=new QT(e,s);t.name=e.name,u.push(t),o=t}else{const e=this.uniformGroups[r]||(this.uniformGroups[r]={});let n=e[a];void 0===n&&(n=new e_(r+"_"+a,s),e[a]=n,u.push(n)),o=this.getNodeUniform(i,t),n.addUniform(o)}n.uniformGPU=o}return i}}let c_=null,h_=null,p_=null;class g_{constructor(e={}){this.parameters=Object.assign({},e),this.data=new WeakMap,this.renderer=null,this.domElement=null}async init(e){this.renderer=e}begin(){}finish(){}draw(){}createProgram(){}destroyProgram(){}createBindings(){}updateBindings(){}createRenderPipeline(){}createComputePipeline(){}destroyPipeline(){}needsRenderUpdate(){}getRenderCacheKey(){}createNodeBuilder(){}createSampler(){}createDefaultTexture(){}createTexture(){}copyTextureToBuffer(){}createAttribute(){}createIndexAttribute(){}updateAttribute(){}destroyAttribute(){}getContext(){}updateSize(){}resolveTimestampAsync(){}hasFeatureAsync(){}hasFeature(){}getInstanceCount(e){const{object:t,geometry:r}=e;return r.isInstancedBufferGeometry?r.instanceCount:t.count>1?t.count:1}getDrawingBufferSize(){return c_=c_||new t,this.renderer.getDrawingBufferSize(c_)}getScissor(){return h_=h_||new s,this.renderer.getScissor(h_)}setScissorTest(){}getClearColor(){const e=this.renderer;return p_=p_||new om,e.getClearColor(p_),p_.getRGB(p_,this.renderer.currentColorSpace),p_}getDomElement(){let e=this.domElement;return null===e&&(e=void 0!==this.parameters.canvas?this.parameters.canvas:Ze(),"setAttribute"in e&&e.setAttribute("data-engine",`three.js r${Ve} webgpu`),this.domElement=e),e}set(e,t){this.data.set(e,t)}get(e){let t=this.data.get(e);return void 0===t&&(t={},this.data.set(e,t)),t}has(e){return this.data.has(e)}delete(e){this.data.delete(e)}dispose(){}}let m_=0;class f_{constructor(e,t){this.buffers=[e.bufferGPU,t],this.type=e.type,this.bufferType=e.bufferType,this.pbo=e.pbo,this.byteLength=e.byteLength,this.bytesPerElement=e.BYTES_PER_ELEMENT,this.version=e.version,this.isInteger=e.isInteger,this.activeBufferIndex=0,this.baseId=e.id}get id(){return`${this.baseId}|${this.activeBufferIndex}`}get bufferGPU(){return this.buffers[this.activeBufferIndex]}get transformBuffer(){return this.buffers[1^this.activeBufferIndex]}switchBuffers(){this.activeBufferIndex^=1}}class y_{constructor(e){this.backend=e}createAttribute(e,t){const r=this.backend,{gl:s}=r,i=e.array,n=e.usage||s.STATIC_DRAW,o=e.isInterleavedBufferAttribute?e.data:e,a=r.get(o);let u,l=a.bufferGPU;if(void 0===l&&(l=this._createBuffer(s,t,i,n),a.bufferGPU=l,a.bufferType=t,a.version=o.version),i instanceof Float32Array)u=s.FLOAT;else if(i instanceof Uint16Array)u=e.isFloat16BufferAttribute?s.HALF_FLOAT:s.UNSIGNED_SHORT;else if(i instanceof Int16Array)u=s.SHORT;else if(i instanceof Uint32Array)u=s.UNSIGNED_INT;else if(i instanceof Int32Array)u=s.INT;else if(i instanceof Int8Array)u=s.BYTE;else if(i instanceof Uint8Array)u=s.UNSIGNED_BYTE;else{if(!(i instanceof Uint8ClampedArray))throw new Error("THREE.WebGLBackend: Unsupported buffer data format: "+i);u=s.UNSIGNED_BYTE}let d={bufferGPU:l,bufferType:t,type:u,byteLength:i.byteLength,bytesPerElement:i.BYTES_PER_ELEMENT,version:e.version,pbo:e.pbo,isInteger:u===s.INT||u===s.UNSIGNED_INT||e.gpuType===b,id:m_++};if(e.isStorageBufferAttribute||e.isStorageInstancedBufferAttribute){const e=this._createBuffer(s,t,i,n);d=new f_(d,e)}r.set(e,d)}updateAttribute(e){const t=this.backend,{gl:r}=t,s=e.array,i=e.isInterleavedBufferAttribute?e.data:e,n=t.get(i),o=n.bufferType,a=e.isInterleavedBufferAttribute?e.data.updateRanges:e.updateRanges;if(r.bindBuffer(o,n.bufferGPU),0===a.length)r.bufferSubData(o,0,s);else{for(let e=0,t=a.length;e1?this.enable(s.SAMPLE_ALPHA_TO_COVERAGE):this.disable(s.SAMPLE_ALPHA_TO_COVERAGE),r>0&&this.currentClippingPlanes!==r){const e=12288;for(let t=0;t<8;t++)t{!function i(){const n=e.clientWaitSync(t,e.SYNC_FLUSH_COMMANDS_BIT,0);if(n===e.WAIT_FAILED)return e.deleteSync(t),void s();n!==e.TIMEOUT_EXPIRED?(e.deleteSync(t),r()):requestAnimationFrame(i)}()}))}}let N_,S_,A_,R_=!1;class C_{constructor(e){this.backend=e,this.gl=e.gl,this.extensions=e.extensions,this.defaultTextures={},!1===R_&&(this._init(this.gl),R_=!0)}_init(e){N_={[dr]:e.REPEAT,[cr]:e.CLAMP_TO_EDGE,[hr]:e.MIRRORED_REPEAT},S_={[pr]:e.NEAREST,[gr]:e.NEAREST_MIPMAP_NEAREST,[Ie]:e.NEAREST_MIPMAP_LINEAR,[$]:e.LINEAR,[Pe]:e.LINEAR_MIPMAP_NEAREST,[M]:e.LINEAR_MIPMAP_LINEAR},A_={[mr]:e.NEVER,[fr]:e.ALWAYS,[Re]:e.LESS,[yr]:e.LEQUAL,[xr]:e.EQUAL,[br]:e.GEQUAL,[Tr]:e.GREATER,[_r]:e.NOTEQUAL}}filterFallback(e){const{gl:t}=this;return e===pr||e===gr||e===Ie?t.NEAREST:t.LINEAR}getGLTextureType(e){const{gl:t}=this;let r;return r=!0===e.isCubeTexture?t.TEXTURE_CUBE_MAP:!0===e.isDataArrayTexture||!0===e.isCompressedArrayTexture?t.TEXTURE_2D_ARRAY:!0===e.isData3DTexture?t.TEXTURE_3D:t.TEXTURE_2D,r}getInternalFormat(e,t,r,s,i=!1){const{gl:n,extensions:o}=this;if(null!==e){if(void 0!==n[e])return n[e];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+e+"'")}let a=t;return t===n.RED&&(r===n.FLOAT&&(a=n.R32F),r===n.HALF_FLOAT&&(a=n.R16F),r===n.UNSIGNED_BYTE&&(a=n.R8),r===n.UNSIGNED_SHORT&&(a=n.R16),r===n.UNSIGNED_INT&&(a=n.R32UI),r===n.BYTE&&(a=n.R8I),r===n.SHORT&&(a=n.R16I),r===n.INT&&(a=n.R32I)),t===n.RED_INTEGER&&(r===n.UNSIGNED_BYTE&&(a=n.R8UI),r===n.UNSIGNED_SHORT&&(a=n.R16UI),r===n.UNSIGNED_INT&&(a=n.R32UI),r===n.BYTE&&(a=n.R8I),r===n.SHORT&&(a=n.R16I),r===n.INT&&(a=n.R32I)),t===n.RG&&(r===n.FLOAT&&(a=n.RG32F),r===n.HALF_FLOAT&&(a=n.RG16F),r===n.UNSIGNED_BYTE&&(a=n.RG8),r===n.UNSIGNED_SHORT&&(a=n.RG16),r===n.UNSIGNED_INT&&(a=n.RG32UI),r===n.BYTE&&(a=n.RG8I),r===n.SHORT&&(a=n.RG16I),r===n.INT&&(a=n.RG32I)),t===n.RG_INTEGER&&(r===n.UNSIGNED_BYTE&&(a=n.RG8UI),r===n.UNSIGNED_SHORT&&(a=n.RG16UI),r===n.UNSIGNED_INT&&(a=n.RG32UI),r===n.BYTE&&(a=n.RG8I),r===n.SHORT&&(a=n.RG16I),r===n.INT&&(a=n.RG32I)),t===n.RGB&&(r===n.FLOAT&&(a=n.RGB32F),r===n.HALF_FLOAT&&(a=n.RGB16F),r===n.UNSIGNED_BYTE&&(a=n.RGB8),r===n.UNSIGNED_SHORT&&(a=n.RGB16),r===n.UNSIGNED_INT&&(a=n.RGB32UI),r===n.BYTE&&(a=n.RGB8I),r===n.SHORT&&(a=n.RGB16I),r===n.INT&&(a=n.RGB32I),r===n.UNSIGNED_BYTE&&(a=s===De&&!1===i?n.SRGB8:n.RGB8),r===n.UNSIGNED_SHORT_5_6_5&&(a=n.RGB565),r===n.UNSIGNED_SHORT_5_5_5_1&&(a=n.RGB5_A1),r===n.UNSIGNED_SHORT_4_4_4_4&&(a=n.RGB4),r===n.UNSIGNED_INT_5_9_9_9_REV&&(a=n.RGB9_E5)),t===n.RGB_INTEGER&&(r===n.UNSIGNED_BYTE&&(a=n.RGB8UI),r===n.UNSIGNED_SHORT&&(a=n.RGB16UI),r===n.UNSIGNED_INT&&(a=n.RGB32UI),r===n.BYTE&&(a=n.RGB8I),r===n.SHORT&&(a=n.RGB16I),r===n.INT&&(a=n.RGB32I)),t===n.RGBA&&(r===n.FLOAT&&(a=n.RGBA32F),r===n.HALF_FLOAT&&(a=n.RGBA16F),r===n.UNSIGNED_BYTE&&(a=n.RGBA8),r===n.UNSIGNED_SHORT&&(a=n.RGBA16),r===n.UNSIGNED_INT&&(a=n.RGBA32UI),r===n.BYTE&&(a=n.RGBA8I),r===n.SHORT&&(a=n.RGBA16I),r===n.INT&&(a=n.RGBA32I),r===n.UNSIGNED_BYTE&&(a=s===De&&!1===i?n.SRGB8_ALPHA8:n.RGBA8),r===n.UNSIGNED_SHORT_4_4_4_4&&(a=n.RGBA4),r===n.UNSIGNED_SHORT_5_5_5_1&&(a=n.RGB5_A1)),t===n.RGBA_INTEGER&&(r===n.UNSIGNED_BYTE&&(a=n.RGBA8UI),r===n.UNSIGNED_SHORT&&(a=n.RGBA16UI),r===n.UNSIGNED_INT&&(a=n.RGBA32UI),r===n.BYTE&&(a=n.RGBA8I),r===n.SHORT&&(a=n.RGBA16I),r===n.INT&&(a=n.RGBA32I)),t===n.DEPTH_COMPONENT&&(r===n.UNSIGNED_INT&&(a=n.DEPTH24_STENCIL8),r===n.FLOAT&&(a=n.DEPTH_COMPONENT32F)),t===n.DEPTH_STENCIL&&r===n.UNSIGNED_INT_24_8&&(a=n.DEPTH24_STENCIL8),a!==n.R16F&&a!==n.R32F&&a!==n.RG16F&&a!==n.RG32F&&a!==n.RGBA16F&&a!==n.RGBA32F||o.get("EXT_color_buffer_float"),a}setTextureParameters(e,t){const{gl:r,extensions:s,backend:i}=this;r.pixelStorei(r.UNPACK_FLIP_Y_WEBGL,t.flipY),r.pixelStorei(r.UNPACK_PREMULTIPLY_ALPHA_WEBGL,t.premultiplyAlpha),r.pixelStorei(r.UNPACK_ALIGNMENT,t.unpackAlignment),r.pixelStorei(r.UNPACK_COLORSPACE_CONVERSION_WEBGL,r.NONE),r.texParameteri(e,r.TEXTURE_WRAP_S,N_[t.wrapS]),r.texParameteri(e,r.TEXTURE_WRAP_T,N_[t.wrapT]),e!==r.TEXTURE_3D&&e!==r.TEXTURE_2D_ARRAY||r.texParameteri(e,r.TEXTURE_WRAP_R,N_[t.wrapR]),r.texParameteri(e,r.TEXTURE_MAG_FILTER,S_[t.magFilter]);const n=void 0!==t.mipmaps&&t.mipmaps.length>0,o=t.minFilter===$&&n?M:t.minFilter;if(r.texParameteri(e,r.TEXTURE_MIN_FILTER,S_[o]),t.compareFunction&&(r.texParameteri(e,r.TEXTURE_COMPARE_MODE,r.COMPARE_REF_TO_TEXTURE),r.texParameteri(e,r.TEXTURE_COMPARE_FUNC,A_[t.compareFunction])),!0===s.has("EXT_texture_filter_anisotropic")){if(t.magFilter===pr)return;if(t.minFilter!==Ie&&t.minFilter!==M)return;if(t.type===E&&!1===s.has("OES_texture_float_linear"))return;if(t.anisotropy>1){const n=s.get("EXT_texture_filter_anisotropic");r.texParameterf(e,n.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(t.anisotropy,i.getMaxAnisotropy()))}}}createDefaultTexture(e){const{gl:t,backend:r,defaultTextures:s}=this,i=this.getGLTextureType(e);let n=s[i];void 0===n&&(n=t.createTexture(),r.state.bindTexture(i,n),t.texParameteri(i,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(i,t.TEXTURE_MAG_FILTER,t.NEAREST),s[i]=n),r.set(e,{textureGPU:n,glTextureType:i,isDefault:!0})}createTexture(e,t){const{gl:r,backend:s}=this,{levels:i,width:n,height:o,depth:a}=t,u=s.utils.convert(e.format,e.colorSpace),l=s.utils.convert(e.type),d=this.getInternalFormat(e.internalFormat,u,l,e.colorSpace,e.isVideoTexture),c=r.createTexture(),h=this.getGLTextureType(e);s.state.bindTexture(h,c),this.setTextureParameters(h,e),e.isDataArrayTexture||e.isCompressedArrayTexture?r.texStorage3D(r.TEXTURE_2D_ARRAY,i,d,n,o,a):e.isData3DTexture?r.texStorage3D(r.TEXTURE_3D,i,d,n,o,a):e.isVideoTexture||r.texStorage2D(h,i,d,n,o),s.set(e,{textureGPU:c,glTextureType:h,glFormat:u,glType:l,glInternalFormat:d})}copyBufferToTexture(e,t){const{gl:r,backend:s}=this,{textureGPU:i,glTextureType:n,glFormat:o,glType:a}=s.get(t),{width:u,height:l}=t.source.data;r.bindBuffer(r.PIXEL_UNPACK_BUFFER,e),s.state.bindTexture(n,i),r.pixelStorei(r.UNPACK_FLIP_Y_WEBGL,!1),r.pixelStorei(r.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),r.texSubImage2D(n,0,0,0,u,l,o,a,0),r.bindBuffer(r.PIXEL_UNPACK_BUFFER,null),s.state.unbindTexture()}updateTexture(e,t){const{gl:r}=this,{width:s,height:i}=t,{textureGPU:n,glTextureType:o,glFormat:a,glType:u,glInternalFormat:l}=this.backend.get(e);if(e.isRenderTargetTexture||void 0===n)return;const d=e=>e.isDataTexture?e.image.data:"undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&e instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap||e instanceof OffscreenCanvas?e:e.data;if(this.backend.state.bindTexture(o,n),this.setTextureParameters(o,e),e.isCompressedTexture){const s=e.mipmaps,i=t.image;for(let t=0;t0,c=t.renderTarget?t.renderTarget.height:this.backend.gerDrawingBufferSize().y;if(d){const r=0!==o||0!==a;let d,h;if(!0===e.isDepthTexture?(d=s.DEPTH_BUFFER_BIT,h=s.DEPTH_ATTACHMENT,t.stencil&&(d|=s.STENCIL_BUFFER_BIT)):(d=s.COLOR_BUFFER_BIT,h=s.COLOR_ATTACHMENT0),r){const e=this.backend.get(t.renderTarget),r=e.framebuffers[t.getCacheKey()],h=e.msaaFrameBuffer;i.bindFramebuffer(s.DRAW_FRAMEBUFFER,r),i.bindFramebuffer(s.READ_FRAMEBUFFER,h);const p=c-a-l;s.blitFramebuffer(o,p,o+u,p+l,o,p,o+u,p+l,d,s.NEAREST),i.bindFramebuffer(s.READ_FRAMEBUFFER,r),i.bindTexture(s.TEXTURE_2D,n),s.copyTexSubImage2D(s.TEXTURE_2D,0,0,0,o,p,u,l),i.unbindTexture()}else{const e=s.createFramebuffer();i.bindFramebuffer(s.DRAW_FRAMEBUFFER,e),s.framebufferTexture2D(s.DRAW_FRAMEBUFFER,h,s.TEXTURE_2D,n,0),s.blitFramebuffer(0,0,u,l,0,0,u,l,d,s.NEAREST),s.deleteFramebuffer(e)}}else i.bindTexture(s.TEXTURE_2D,n),s.copyTexSubImage2D(s.TEXTURE_2D,0,0,0,o,c-l-a,u,l),i.unbindTexture();e.generateMipmaps&&this.generateMipmaps(e),this.backend._setFramebuffer(t)}setupRenderBufferStorage(e,t){const{gl:r}=this,s=t.renderTarget,{samples:i,depthTexture:n,depthBuffer:o,stencilBuffer:a,width:u,height:l}=s;if(r.bindRenderbuffer(r.RENDERBUFFER,e),o&&!a){let t=r.DEPTH_COMPONENT24;i>0?(n&&n.isDepthTexture&&n.type===r.FLOAT&&(t=r.DEPTH_COMPONENT32F),r.renderbufferStorageMultisample(r.RENDERBUFFER,i,t,u,l)):r.renderbufferStorage(r.RENDERBUFFER,t,u,l),r.framebufferRenderbuffer(r.FRAMEBUFFER,r.DEPTH_ATTACHMENT,r.RENDERBUFFER,e)}else o&&a&&(i>0?r.renderbufferStorageMultisample(r.RENDERBUFFER,i,r.DEPTH24_STENCIL8,u,l):r.renderbufferStorage(r.RENDERBUFFER,r.DEPTH_STENCIL,u,l),r.framebufferRenderbuffer(r.FRAMEBUFFER,r.DEPTH_STENCIL_ATTACHMENT,r.RENDERBUFFER,e))}async copyTextureToBuffer(e,t,r,s,i,n){const{backend:o,gl:a}=this,{textureGPU:u,glFormat:l,glType:d}=this.backend.get(e),c=a.createFramebuffer();a.bindFramebuffer(a.READ_FRAMEBUFFER,c);const h=e.isCubeTexture?a.TEXTURE_CUBE_MAP_POSITIVE_X+n:a.TEXTURE_2D;a.framebufferTexture2D(a.READ_FRAMEBUFFER,a.COLOR_ATTACHMENT0,h,u,0);const p=this._getTypedArrayType(d),g=s*i*this._getBytesPerTexel(d,l),m=a.createBuffer();a.bindBuffer(a.PIXEL_PACK_BUFFER,m),a.bufferData(a.PIXEL_PACK_BUFFER,g,a.STREAM_READ),a.readPixels(t,r,s,i,l,d,0),a.bindBuffer(a.PIXEL_PACK_BUFFER,null),await o.utils._clientWaitAsync();const f=new p(g/p.BYTES_PER_ELEMENT);return a.bindBuffer(a.PIXEL_PACK_BUFFER,m),a.getBufferSubData(a.PIXEL_PACK_BUFFER,0,f),a.bindBuffer(a.PIXEL_PACK_BUFFER,null),a.deleteFramebuffer(c),f}_getTypedArrayType(e){const{gl:t}=this;if(e===t.UNSIGNED_BYTE)return Uint8Array;if(e===t.UNSIGNED_SHORT_4_4_4_4)return Uint16Array;if(e===t.UNSIGNED_SHORT_5_5_5_1)return Uint16Array;if(e===t.UNSIGNED_SHORT_5_6_5)return Uint16Array;if(e===t.UNSIGNED_SHORT)return Uint16Array;if(e===t.UNSIGNED_INT)return Uint32Array;if(e===t.HALF_FLOAT)return Uint16Array;if(e===t.FLOAT)return Float32Array;throw new Error(`Unsupported WebGL type: ${e}`)}_getBytesPerTexel(e,t){const{gl:r}=this;let s=0;return e===r.UNSIGNED_BYTE&&(s=1),e!==r.UNSIGNED_SHORT_4_4_4_4&&e!==r.UNSIGNED_SHORT_5_5_5_1&&e!==r.UNSIGNED_SHORT_5_6_5&&e!==r.UNSIGNED_SHORT&&e!==r.HALF_FLOAT||(s=2),e!==r.UNSIGNED_INT&&e!==r.FLOAT||(s=4),t===r.RGBA?4*s:t===r.RGB?3*s:t===r.ALPHA?s:void 0}}class E_{constructor(e){this.backend=e,this.gl=this.backend.gl,this.availableExtensions=this.gl.getSupportedExtensions(),this.extensions={}}get(e){let t=this.extensions[e];return void 0===t&&(t=this.gl.getExtension(e),this.extensions[e]=t),t}has(e){return this.availableExtensions.includes(e)}}class w_{constructor(e){this.backend=e,this.maxAnisotropy=null}getMaxAnisotropy(){if(null!==this.maxAnisotropy)return this.maxAnisotropy;const e=this.backend.gl,t=this.backend.extensions;if(!0===t.has("EXT_texture_filter_anisotropic")){const r=t.get("EXT_texture_filter_anisotropic");this.maxAnisotropy=e.getParameter(r.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else this.maxAnisotropy=0;return this.maxAnisotropy}}const M_={WEBGL_multi_draw:"WEBGL_multi_draw",WEBGL_compressed_texture_astc:"texture-compression-astc",WEBGL_compressed_texture_etc:"texture-compression-etc2",WEBGL_compressed_texture_etc1:"texture-compression-etc1",WEBGL_compressed_texture_pvrtc:"texture-compression-pvrtc",WEBKIT_WEBGL_compressed_texture_pvrtc:"texture-compression-pvrtc",WEBGL_compressed_texture_s3tc:"texture-compression-bc",EXT_texture_compression_bptc:"texture-compression-bptc",EXT_disjoint_timer_query_webgl2:"timestamp-query"};class B_{constructor(e){this.gl=e.gl,this.extensions=e.extensions,this.info=e.renderer.info,this.mode=null,this.index=0,this.type=null,this.object=null}render(e,t){const{gl:r,mode:s,object:i,type:n,info:o,index:a}=this;0!==a?r.drawElements(s,t,n,e):r.drawArrays(s,e,t),o.update(i,t,s,1)}renderInstances(e,t,r){const{gl:s,mode:i,type:n,index:o,object:a,info:u}=this;0!==r&&(0!==o?s.drawElementsInstanced(i,t,n,e,r):s.drawArraysInstanced(i,e,t,r),u.update(a,t,i,r))}renderMultiDraw(e,t,r){const{extensions:s,mode:i,object:n,info:o}=this;if(0===r)return;const a=s.get("WEBGL_multi_draw");if(null===a)for(let s=0;s0)){const e=t.queryQueue.shift();this.initTimestampQuery(e)}}async resolveTimestampAsync(e,t="render"){if(!this.disjoint||!this.trackTimestamp)return;const r=this.get(e);r.gpuQueries||(r.gpuQueries=[]);for(let e=0;e0&&(r.currentOcclusionQueries=r.occlusionQueries,r.currentOcclusionQueryObjects=r.occlusionQueryObjects,r.lastOcclusionObject=null,r.occlusionQueries=new Array(s),r.occlusionQueryObjects=new Array(s),r.occlusionQueryIndex=0)}finishRender(e){const{gl:t,state:r}=this,s=this.get(e),i=s.previousContext,n=e.occlusionQueryCount;n>0&&(n>s.occlusionQueryIndex&&t.endQuery(t.ANY_SAMPLES_PASSED),this.resolveOccludedAsync(e));const o=e.textures;if(null!==o)for(let e=0;e0){const i=s.framebuffers[e.getCacheKey()],n=t.COLOR_BUFFER_BIT,o=s.msaaFrameBuffer,a=e.textures;r.bindFramebuffer(t.READ_FRAMEBUFFER,o),r.bindFramebuffer(t.DRAW_FRAMEBUFFER,i);for(let r=0;r{let o=0;for(let t=0;t0&&e.add(s[t]),r[t]=null,i.deleteQuery(n),o++))}o1?f.renderInstances(b,y,x):f.render(b,y),a.bindVertexArray(null)}needsRenderUpdate(){return!1}getRenderCacheKey(){return""}createDefaultTexture(e){this.textureUtils.createDefaultTexture(e)}createTexture(e,t){this.textureUtils.createTexture(e,t)}updateTexture(e,t){this.textureUtils.updateTexture(e,t)}generateMipmaps(e){this.textureUtils.generateMipmaps(e)}destroyTexture(e){this.textureUtils.destroyTexture(e)}copyTextureToBuffer(e,t,r,s,i,n){return this.textureUtils.copyTextureToBuffer(e,t,r,s,i,n)}createSampler(){}destroySampler(){}createNodeBuilder(e,t){return new d_(e,t)}createProgram(e){const t=this.gl,{stage:r,code:s}=e,i="fragment"===r?t.createShader(t.FRAGMENT_SHADER):t.createShader(t.VERTEX_SHADER);t.shaderSource(i,s),t.compileShader(i),this.set(e,{shaderGPU:i})}destroyProgram(){console.warn("Abstract class.")}createRenderPipeline(e,t){const r=this.gl,s=e.pipeline,{fragmentProgram:i,vertexProgram:n}=s,o=r.createProgram(),a=this.get(i).shaderGPU,u=this.get(n).shaderGPU;if(r.attachShader(o,a),r.attachShader(o,u),r.linkProgram(o),this.set(s,{programGPU:o,fragmentShader:a,vertexShader:u}),null!==t&&this.parallel){const i=new Promise((t=>{const i=this.parallel,n=()=>{r.getProgramParameter(o,i.COMPLETION_STATUS_KHR)?(this._completeCompile(e,s),t()):requestAnimationFrame(n)};n()}));t.push(i)}else this._completeCompile(e,s)}_handleSource(e,t){const r=e.split("\n"),s=[],i=Math.max(t-6,0),n=Math.min(t+6,r.length);for(let e=i;e":" "} ${i}: ${r[e]}`)}return s.join("\n")}_getShaderErrors(e,t,r){const s=e.getShaderParameter(t,e.COMPILE_STATUS),i=e.getShaderInfoLog(t).trim();if(s&&""===i)return"";const n=/ERROR: 0:(\d+)/.exec(i);if(n){const s=parseInt(n[1]);return r.toUpperCase()+"\n\n"+i+"\n\n"+this._handleSource(e.getShaderSource(t),s)}return i}_logProgramError(e,t,r){if(this.renderer.debug.checkShaderErrors){const s=this.gl,i=s.getProgramInfoLog(e).trim();if(!1===s.getProgramParameter(e,s.LINK_STATUS))if("function"==typeof this.renderer.debug.onShaderError)this.renderer.debug.onShaderError(s,e,r,t);else{const n=this._getShaderErrors(s,r,"vertex"),o=this._getShaderErrors(s,t,"fragment");console.error("THREE.WebGLProgram: Shader Error "+s.getError()+" - VALIDATE_STATUS "+s.getProgramParameter(e,s.VALIDATE_STATUS)+"\n\nProgram Info Log: "+i+"\n"+n+"\n"+o)}else""!==i&&console.warn("THREE.WebGLProgram: Program Info Log:",i)}}_completeCompile(e,t){const{state:r,gl:s}=this,i=this.get(t),{programGPU:n,fragmentShader:o,vertexShader:a}=i;!1===s.getProgramParameter(n,s.LINK_STATUS)&&this._logProgramError(n,o,a),r.useProgram(n);const u=e.getBindings();this._setupBindings(u,n),this.set(t,{programGPU:n})}createComputePipeline(e,t){const{state:r,gl:s}=this,i={stage:"fragment",code:"#version 300 es\nprecision highp float;\nvoid main() {}"};this.createProgram(i);const{computeProgram:n}=e,o=s.createProgram(),a=this.get(i).shaderGPU,u=this.get(n).shaderGPU,l=n.transforms,d=[],c=[];for(let e=0;eM_[t]===e)),r=this.extensions;for(let e=0;e0){if(void 0===d){const s=[];d=t.createFramebuffer(),r.bindFramebuffer(t.FRAMEBUFFER,d);const i=[],l=e.textures;for(let r=0;r,\n\t@location( 0 ) vTex : vec2\n};\n\n@vertex\nfn main( @builtin( vertex_index ) vertexIndex : u32 ) -> VarysStruct {\n\n\tvar Varys : VarysStruct;\n\n\tvar pos = array< vec2, 4 >(\n\t\tvec2( -1.0, 1.0 ),\n\t\tvec2( 1.0, 1.0 ),\n\t\tvec2( -1.0, -1.0 ),\n\t\tvec2( 1.0, -1.0 )\n\t);\n\n\tvar tex = array< vec2, 4 >(\n\t\tvec2( 0.0, 0.0 ),\n\t\tvec2( 1.0, 0.0 ),\n\t\tvec2( 0.0, 1.0 ),\n\t\tvec2( 1.0, 1.0 )\n\t);\n\n\tVarys.vTex = tex[ vertexIndex ];\n\tVarys.Position = vec4( pos[ vertexIndex ], 0.0, 1.0 );\n\n\treturn Varys;\n\n}\n"}),this.mipmapFragmentShaderModule=e.createShaderModule({label:"mipmapFragment",code:"\n@group( 0 ) @binding( 0 )\nvar imgSampler : sampler;\n\n@group( 0 ) @binding( 1 )\nvar img : texture_2d;\n\n@fragment\nfn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 {\n\n\treturn textureSample( img, imgSampler, vTex );\n\n}\n"}),this.flipYFragmentShaderModule=e.createShaderModule({label:"flipYFragment",code:"\n@group( 0 ) @binding( 0 )\nvar imgSampler : sampler;\n\n@group( 0 ) @binding( 1 )\nvar img : texture_2d;\n\n@fragment\nfn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 {\n\n\treturn textureSample( img, imgSampler, vec2( vTex.x, 1.0 - vTex.y ) );\n\n}\n"})}getTransferPipeline(e){let t=this.transferPipelines[e];return void 0===t&&(t=this.device.createRenderPipeline({label:`mipmap-${e}`,vertex:{module:this.mipmapVertexShaderModule,entryPoint:"main"},fragment:{module:this.mipmapFragmentShaderModule,entryPoint:"main",targets:[{format:e}]},primitive:{topology:V_,stripIndexFormat:ev},layout:"auto"}),this.transferPipelines[e]=t),t}getFlipYPipeline(e){let t=this.flipYPipelines[e];return void 0===t&&(t=this.device.createRenderPipeline({label:`flipY-${e}`,vertex:{module:this.mipmapVertexShaderModule,entryPoint:"main"},fragment:{module:this.flipYFragmentShaderModule,entryPoint:"main",targets:[{format:e}]},primitive:{topology:V_,stripIndexFormat:ev},layout:"auto"}),this.flipYPipelines[e]=t),t}flipY(e,t,r=0){const s=t.format,{width:i,height:n}=t.size,o=this.getTransferPipeline(s),a=this.getFlipYPipeline(s),u=this.device.createTexture({size:{width:i,height:n,depthOrArrayLayers:1},format:s,usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.TEXTURE_BINDING}),l=e.createView({baseMipLevel:0,mipLevelCount:1,dimension:qv,baseArrayLayer:r}),d=u.createView({baseMipLevel:0,mipLevelCount:1,dimension:qv,baseArrayLayer:0}),c=this.device.createCommandEncoder({}),h=(e,t,r)=>{const s=e.getBindGroupLayout(0),i=this.device.createBindGroup({layout:s,entries:[{binding:0,resource:this.flipYSampler},{binding:1,resource:t}]}),n=c.beginRenderPass({colorAttachments:[{view:r,loadOp:K_,storeOp:j_,clearValue:[0,0,0,0]}]});n.setPipeline(e),n.setBindGroup(0,i),n.draw(4,1,0,0),n.end()};h(o,l,d),h(a,d,l),this.device.queue.submit([c.finish()]),u.destroy()}generateMipmaps(e,t,r=0){const s=this.get(e);void 0===s.useCount&&(s.useCount=0,s.layers=[]);const i=s.layers[r]||this._mipmapCreateBundles(e,t,r),n=this.device.createCommandEncoder({});this._mipmapRunBundles(n,i),this.device.queue.submit([n.finish()]),0!==s.useCount&&(s.layers[r]=i),s.useCount++}_mipmapCreateBundles(e,t,r){const s=this.getTransferPipeline(t.format),i=s.getBindGroupLayout(0);let n=e.createView({baseMipLevel:0,mipLevelCount:1,dimension:qv,baseArrayLayer:r});const o=[];for(let a=1;a1;for(let o=0;o]*\s*([a-z_0-9]+(?:<[\s\S]+?>)?)/i,hN=/([a-z_0-9]+)\s*:\s*([a-z_0-9]+(?:<[\s\S]+?>)?)/gi,pN={f32:"float",i32:"int",u32:"uint",bool:"bool","vec2":"vec2","vec2":"ivec2","vec2":"uvec2","vec2":"bvec2",vec2f:"vec2",vec2i:"ivec2",vec2u:"uvec2",vec2b:"bvec2","vec3":"vec3","vec3":"ivec3","vec3":"uvec3","vec3":"bvec3",vec3f:"vec3",vec3i:"ivec3",vec3u:"uvec3",vec3b:"bvec3","vec4":"vec4","vec4":"ivec4","vec4":"uvec4","vec4":"bvec4",vec4f:"vec4",vec4i:"ivec4",vec4u:"uvec4",vec4b:"bvec4","mat2x2":"mat2",mat2x2f:"mat2","mat3x3":"mat3",mat3x3f:"mat3","mat4x4":"mat4",mat4x4f:"mat4",sampler:"sampler",texture_1d:"texture",texture_2d:"texture",texture_2d_array:"texture",texture_multisampled_2d:"cubeTexture",texture_depth_2d:"depthTexture",texture_depth_multisampled_2d:"depthTexture",texture_3d:"texture3D",texture_cube:"cubeTexture",texture_cube_array:"cubeTexture",texture_storage_1d:"storageTexture",texture_storage_2d:"storageTexture",texture_storage_2d_array:"storageTexture",texture_storage_3d:"storageTexture"};class gN extends AT{constructor(e){const{type:t,inputs:r,name:s,inputsCode:i,blockCode:n,outputType:o}=(e=>{const t=(e=e.trim()).match(cN);if(null!==t&&4===t.length){const r=t[2],s=[];let i=null;for(;null!==(i=hN.exec(r));)s.push({name:i[1],type:i[2]});const n=[];for(let e=0;e "+this.outputType:"";return`fn ${e} ( ${this.inputsCode.trim()} ) ${t}`+this.blockCode}}class mN extends ST{parseFunction(e){return new gN(e)}}const fN="undefined"!=typeof self?self.GPUShaderStage:{VERTEX:1,FRAGMENT:2,COMPUTE:4},yN={[Ss.READ_ONLY]:"read",[Ss.WRITE_ONLY]:"write",[Ss.READ_WRITE]:"read_write"},xN={[dr]:"repeat",[cr]:"clamp",[hr]:"mirror"},bN={vertex:fN?fN.VERTEX:1,fragment:fN?fN.FRAGMENT:2,compute:fN?fN.COMPUTE:4},TN={instance:!0,swizzleAssign:!1,storageBuffer:!0},_N={"^^":"tsl_xor"},vN={float:"f32",int:"i32",uint:"u32",bool:"bool",color:"vec3",vec2:"vec2",ivec2:"vec2",uvec2:"vec2",bvec2:"vec2",vec3:"vec3",ivec3:"vec3",uvec3:"vec3",bvec3:"vec3",vec4:"vec4",ivec4:"vec4",uvec4:"vec4",bvec4:"vec4",mat2:"mat2x2",mat3:"mat3x3",mat4:"mat4x4"},NN={},SN={tsl_xor:new iy("fn tsl_xor( a : bool, b : bool ) -> bool { return ( a || b ) && !( a && b ); }"),mod_float:new iy("fn tsl_mod_float( x : f32, y : f32 ) -> f32 { return x - y * floor( x / y ); }"),mod_vec2:new iy("fn tsl_mod_vec2( x : vec2f, y : vec2f ) -> vec2f { return x - y * floor( x / y ); }"),mod_vec3:new iy("fn tsl_mod_vec3( x : vec3f, y : vec3f ) -> vec3f { return x - y * floor( x / y ); }"),mod_vec4:new iy("fn tsl_mod_vec4( x : vec4f, y : vec4f ) -> vec4f { return x - y * floor( x / y ); }"),equals_bool:new iy("fn tsl_equals_bool( a : bool, b : bool ) -> bool { return a == b; }"),equals_bvec2:new iy("fn tsl_equals_bvec2( a : vec2f, b : vec2f ) -> vec2 { return vec2( a.x == b.x, a.y == b.y ); }"),equals_bvec3:new iy("fn tsl_equals_bvec3( a : vec3f, b : vec3f ) -> vec3 { return vec3( a.x == b.x, a.y == b.y, a.z == b.z ); }"),equals_bvec4:new iy("fn tsl_equals_bvec4( a : vec4f, b : vec4f ) -> vec4 { return vec4( a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w ); }"),repeatWrapping_float:new iy("fn tsl_repeatWrapping_float( coord: f32 ) -> f32 { return fract( coord ); }"),mirrorWrapping_float:new iy("fn tsl_mirrorWrapping_float( coord: f32 ) -> f32 { let mirrored = fract( coord * 0.5 ) * 2.0; return 1.0 - abs( 1.0 - mirrored ); }"),clampWrapping_float:new iy("fn tsl_clampWrapping_float( coord: f32 ) -> f32 { return clamp( coord, 0.0, 1.0 ); }"),biquadraticTexture:new iy("\nfn tsl_biquadraticTexture( map : texture_2d, coord : vec2f, iRes : vec2u, level : u32 ) -> vec4f {\n\n\tlet res = vec2f( iRes );\n\n\tlet uvScaled = coord * res;\n\tlet uvWrapping = ( ( uvScaled % res ) + res ) % res;\n\n\t// https://www.shadertoy.com/view/WtyXRy\n\n\tlet uv = uvWrapping - 0.5;\n\tlet iuv = floor( uv );\n\tlet f = fract( uv );\n\n\tlet rg1 = textureLoad( map, vec2u( iuv + vec2( 0.5, 0.5 ) ) % iRes, level );\n\tlet rg2 = textureLoad( map, vec2u( iuv + vec2( 1.5, 0.5 ) ) % iRes, level );\n\tlet rg3 = textureLoad( map, vec2u( iuv + vec2( 0.5, 1.5 ) ) % iRes, level );\n\tlet rg4 = textureLoad( map, vec2u( iuv + vec2( 1.5, 1.5 ) ) % iRes, level );\n\n\treturn mix( mix( rg1, rg2, f.x ), mix( rg3, rg4, f.x ), f.y );\n\n}\n")},AN={dFdx:"dpdx",dFdy:"- dpdy",mod_float:"tsl_mod_float",mod_vec2:"tsl_mod_vec2",mod_vec3:"tsl_mod_vec3",mod_vec4:"tsl_mod_vec4",equals_bool:"tsl_equals_bool",equals_bvec2:"tsl_equals_bvec2",equals_bvec3:"tsl_equals_bvec3",equals_bvec4:"tsl_equals_bvec4",inversesqrt:"inverseSqrt",bitcast:"bitcast"};"undefined"!=typeof navigator&&/Windows/g.test(navigator.userAgent)&&(SN.pow_float=new iy("fn tsl_pow_float( a : f32, b : f32 ) -> f32 { return select( -pow( -a, b ), pow( a, b ), a > 0.0 ); }"),SN.pow_vec2=new iy("fn tsl_pow_vec2( a : vec2f, b : vec2f ) -> vec2f { return vec2f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ) ); }",[SN.pow_float]),SN.pow_vec3=new iy("fn tsl_pow_vec3( a : vec3f, b : vec3f ) -> vec3f { return vec3f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ), tsl_pow_float( a.z, b.z ) ); }",[SN.pow_float]),SN.pow_vec4=new iy("fn tsl_pow_vec4( a : vec4f, b : vec4f ) -> vec4f { return vec4f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ), tsl_pow_float( a.z, b.z ), tsl_pow_float( a.w, b.w ) ); }",[SN.pow_float]),AN.pow_float="tsl_pow_float",AN.pow_vec2="tsl_pow_vec2",AN.pow_vec3="tsl_pow_vec3",AN.pow_vec4="tsl_pow_vec4");let RN="";!0!==("undefined"!=typeof navigator&&/Firefox|Deno/g.test(navigator.userAgent))&&(RN+="diagnostic( off, derivative_uniformity );\n");class CN extends cT{constructor(e,t){super(e,t,new mN),this.uniformGroups={},this.builtins={},this.directives={},this.scopedArrays=new Map}needsToWorkingColorSpace(e){return!0===e.isVideoTexture&&e.colorSpace!==y}_generateTextureSample(e,t,r,s,i=this.shaderStage){return"fragment"===i?s?`textureSample( ${t}, ${t}_sampler, ${r}, ${s} )`:`textureSample( ${t}, ${t}_sampler, ${r} )`:this.isFilteredTexture(e)?this.generateFilteredTexture(e,t,r):this.generateTextureLod(e,t,r,s,"0")}_generateVideoSample(e,t,r=this.shaderStage){if("fragment"===r)return`textureSampleBaseClampToEdge( ${e}, ${e}_sampler, vec2( ${t}.x, 1.0 - ${t}.y ) )`;console.error(`WebGPURenderer: THREE.VideoTexture does not support ${r} shader.`)}_generateTextureSampleLevel(e,t,r,s,i,n=this.shaderStage){return"fragment"!==n&&"compute"!==n||!1!==this.isUnfilterable(e)?this.isFilteredTexture(e)?this.generateFilteredTexture(e,t,r,s):this.generateTextureLod(e,t,r,i,s):`textureSampleLevel( ${t}, ${t}_sampler, ${r}, ${s} )`}generateWrapFunction(e){const t=`tsl_coord_${xN[e.wrapS]}S_${xN[e.wrapT]}T`;let r=NN[t];if(void 0===r){const s=[];let i=`fn ${t}( coord : vec2f ) -> vec2f {\n\n\treturn vec2f(\n`;const n=(e,t)=>{e===dr?(s.push(SN.repeatWrapping_float),i+=`\t\ttsl_repeatWrapping_float( coord.${t} )`):e===cr?(s.push(SN.clampWrapping_float),i+=`\t\ttsl_clampWrapping_float( coord.${t} )`):e===hr?(s.push(SN.mirrorWrapping_float),i+=`\t\ttsl_mirrorWrapping_float( coord.${t} )`):(i+=`\t\tcoord.${t}`,console.warn(`WebGPURenderer: Unsupported texture wrap type "${e}" for vertex shader.`))};n(e.wrapS,"x"),i+=",\n",n(e.wrapT,"y"),i+="\n\t);\n\n}\n",NN[t]=r=new iy(i,s)}return r.build(this),t}generateTextureDimension(e,t,r){const s=this.getDataFromNode(e,this.shaderStage,this.globalCache);void 0===s.dimensionsSnippet&&(s.dimensionsSnippet={});let i=s.dimensionsSnippet[r];if(void 0===s.dimensionsSnippet[r]){let n;const{primarySamples:o}=this.renderer.backend.utils.getTextureSampleData(e);n=o>1?t:`${t}, u32( ${r} )`,i=new Aa(new ou(`textureDimensions( ${n} )`,"uvec2")),s.dimensionsSnippet[r]=i}return i.build(this)}generateFilteredTexture(e,t,r,s="0u"){this._include("biquadraticTexture");return`tsl_biquadraticTexture( ${t}, ${this.generateWrapFunction(e)}( ${r} ), ${this.generateTextureDimension(e,t,s)}, u32( ${s} ) )`}generateTextureLod(e,t,r,s,i="0u"){const n=`vec2u( ${this.generateWrapFunction(e)}( ${r} ) * vec2f( ${this.generateTextureDimension(e,t,i)} ) )`;return this.generateTextureLoad(e,t,n,s,i)}generateTextureLoad(e,t,r,s,i="0u"){return!0===e.isVideoTexture||!0===e.isStorageTexture?`textureLoad( ${t}, ${r} )`:s?`textureLoad( ${t}, ${r}, ${s}, u32( ${i} ) )`:`textureLoad( ${t}, ${r}, u32( ${i} ) )`}generateTextureStore(e,t,r,s){return`textureStore( ${t}, ${r}, ${s} )`}isSampleCompare(e){return!0===e.isDepthTexture&&null!==e.compareFunction}isUnfilterable(e){return"float"!==this.getComponentTypeFromTexture(e)||!this.isAvailable("float32Filterable")&&!0===e.isDataTexture&&e.type===E||!1===this.isSampleCompare(e)&&e.minFilter===pr&&e.magFilter===pr||this.renderer.backend.utils.getTextureSampleData(e).primarySamples>1}generateTexture(e,t,r,s,i=this.shaderStage){let n=null;return n=!0===e.isVideoTexture?this._generateVideoSample(t,r,i):this.isUnfilterable(e)?this.generateTextureLod(e,t,r,s,"0",i):this._generateTextureSample(e,t,r,s,i),n}generateTextureGrad(e,t,r,s,i,n=this.shaderStage){if("fragment"===n)return`textureSampleGrad( ${t}, ${t}_sampler, ${r}, ${s[0]}, ${s[1]} )`;console.error(`WebGPURenderer: THREE.TextureNode.gradient() does not support ${n} shader.`)}generateTextureCompare(e,t,r,s,i,n=this.shaderStage){if("fragment"===n)return`textureSampleCompare( ${t}, ${t}_sampler, ${r}, ${s} )`;console.error(`WebGPURenderer: THREE.DepthTexture.compareFunction() does not support ${n} shader.`)}generateTextureLevel(e,t,r,s,i,n=this.shaderStage){let o=null;return o=!0===e.isVideoTexture?this._generateVideoSample(t,r,n):this._generateTextureSampleLevel(e,t,r,s,i,n),o}generateTextureBias(e,t,r,s,i,n=this.shaderStage){if("fragment"===n)return`textureSampleBias( ${t}, ${t}_sampler, ${r}, ${s} )`;console.error(`WebGPURenderer: THREE.TextureNode.biasNode does not support ${n} shader.`)}getPropertyName(e,t=this.shaderStage){if(!0===e.isNodeVarying&&!0===e.needsInterpolation){if("vertex"===t)return`varyings.${e.name}`}else if(!0===e.isNodeUniform){const t=e.name,r=e.type;return"texture"===r||"cubeTexture"===r||"storageTexture"===r||"texture3D"===r?t:"buffer"===r||"storageBuffer"===r||"indirectStorageBuffer"===r?`NodeBuffer_${e.id}.${t}`:e.groupNode.name+"."+t}return super.getPropertyName(e)}getOutputStructName(){return"output"}_getUniformGroupCount(e){return Object.keys(this.uniforms[e]).length}getFunctionOperator(e){const t=_N[e];return void 0!==t?(this._include(t),t):null}getNodeAccess(e,t){return"compute"!==t?Ss.READ_ONLY:e.access}getStorageAccess(e,t){return yN[this.getNodeAccess(e,t)]}getUniformFromNode(e,t,r,s=null){const i=super.getUniformFromNode(e,t,r,s),n=this.getDataFromNode(e,r,this.globalCache);if(void 0===n.uniformGPU){let s;const o=e.groupNode,a=o.name,u=this.getBindGroupArray(a,r);if("texture"===t||"cubeTexture"===t||"storageTexture"===t||"texture3D"===t){let n=null;const a=this.getNodeAccess(e,r);if("texture"===t||"storageTexture"===t?n=new s_(i.name,i.node,o,a):"cubeTexture"===t?n=new i_(i.name,i.node,o,a):"texture3D"===t&&(n=new n_(i.name,i.node,o,a)),n.store=!0===e.isStorageTextureNode,n.setVisibility(bN[r]),"fragment"!==r&&"compute"!==r||!1!==this.isUnfilterable(e.value)||!1!==n.store)u.push(n),s=[n];else{const e=new rN(`${i.name}_sampler`,i.node,o);e.setVisibility(bN[r]),u.push(e,n),s=[e,n]}}else if("buffer"===t||"storageBuffer"===t||"indirectStorageBuffer"===t){const i=new("buffer"===t?QT:nN)(e,o);i.setVisibility(bN[r]),u.push(i),s=i}else{const e=this.uniformGroups[r]||(this.uniformGroups[r]={});let n=e[a];void 0===n&&(n=new e_(a,o),n.setVisibility(bN[r]),e[a]=n,u.push(n)),s=this.getNodeUniform(i,t),n.addUniform(s)}n.uniformGPU=s}return i}getBuiltin(e,t,r,s=this.shaderStage){const i=this.builtins[s]||(this.builtins[s]=new Map);return!1===i.has(e)&&i.set(e,{name:e,property:t,type:r}),t}hasBuiltin(e,t=this.shaderStage){return void 0!==this.builtins[t]&&this.builtins[t].has(e)}getVertexIndex(){return"vertex"===this.shaderStage?this.getBuiltin("vertex_index","vertexIndex","u32","attribute"):"vertexIndex"}buildFunctionCode(e){const t=e.layout,r=this.flowShaderNode(e),s=[];for(const e of t.inputs)s.push(e.name+" : "+this.getType(e.type));let i=`fn ${t.name}( ${s.join(", ")} ) -> ${this.getType(t.type)} {\n${r.vars}\n${r.code}\n`;return r.result&&(i+=`\treturn ${r.result};\n`),i+="\n}\n",i}getInstanceIndex(){return"vertex"===this.shaderStage?this.getBuiltin("instance_index","instanceIndex","u32","attribute"):"instanceIndex"}getInvocationLocalIndex(){return this.getBuiltin("local_invocation_index","invocationLocalIndex","u32","attribute")}getSubgroupSize(){return this.enableSubGroups(),this.getBuiltin("subgroup_size","subgroupSize","u32","attribute")}getInvocationSubgroupIndex(){return this.enableSubGroups(),this.getBuiltin("subgroup_invocation_id","invocationSubgroupIndex","u32","attribute")}getSubgroupIndex(){return this.enableSubGroups(),this.getBuiltin("subgroup_id","subgroupIndex","u32","attribute")}getDrawIndex(){return null}getFrontFacing(){return this.getBuiltin("front_facing","isFront","bool")}getFragCoord(){return this.getBuiltin("position","fragCoord","vec4")+".xy"}getFragDepth(){return"output."+this.getBuiltin("frag_depth","depth","f32","output")}getClipDistance(){return"varyings.hw_clip_distances"}isFlipY(){return!1}enableDirective(e,t=this.shaderStage){(this.directives[t]||(this.directives[t]=new Set)).add(e)}getDirectives(e){const t=[],r=this.directives[e];if(void 0!==r)for(const e of r)t.push(`enable ${e};`);return t.join("\n")}enableSubGroups(){this.enableDirective("subgroups")}enableSubgroupsF16(){this.enableDirective("subgroups-f16")}enableClipDistances(){this.enableDirective("clip_distances")}enableShaderF16(){this.enableDirective("f16")}enableDualSourceBlending(){this.enableDirective("dual_source_blending")}enableHardwareClipping(e){this.enableClipDistances(),this.getBuiltin("clip_distances","hw_clip_distances",`array`,"vertex")}getBuiltins(e){const t=[],r=this.builtins[e];if(void 0!==r)for(const{name:e,property:s,type:i}of r.values())t.push(`@builtin( ${e} ) ${s} : ${i}`);return t.join(",\n\t")}getScopedArray(e,t,r,s){return!1===this.scopedArrays.has(e)&&this.scopedArrays.set(e,{name:e,scope:t,bufferType:r,bufferCount:s}),e}getScopedArrays(e){if("compute"!==e)return;const t=[];for(const{name:e,scope:r,bufferType:s,bufferCount:i}of this.scopedArrays.values()){const n=this.getType(s);t.push(`var<${r}> ${e}: array< ${n}, ${i} >;`)}return t.join("\n")}getAttributes(e){const t=[];if("compute"===e&&(this.getBuiltin("global_invocation_id","id","vec3","attribute"),this.getBuiltin("workgroup_id","workgroupId","vec3","attribute"),this.getBuiltin("local_invocation_id","localId","vec3","attribute"),this.getBuiltin("num_workgroups","numWorkgroups","vec3","attribute"),this.renderer.hasFeature("subgroups")&&(this.enableDirective("subgroups",e),this.getBuiltin("subgroup_size","subgroupSize","u32","attribute"))),"vertex"===e||"compute"===e){const e=this.getBuiltins("attribute");e&&t.push(e);const r=this.getAttributesArray();for(let e=0,s=r.length;e`)}const s=this.getBuiltins("output");return s&&t.push("\t"+s),t.join(",\n")}getStructs(e){const t=[],r=this.structs[e];for(let e=0,s=r.length;e output : ${i};\n\n`)}return t.join("\n\n")}getVar(e,t){return`var ${t} : ${this.getType(e)}`}getVars(e){const t=[],r=this.vars[e];if(void 0!==r)for(const e of r)t.push(`\t${this.getVar(e.type,e.name)};`);return`\n${t.join("\n")}\n`}getVaryings(e){const t=[];if("vertex"===e&&this.getBuiltin("position","Vertex","vec4","vertex"),"vertex"===e||"fragment"===e){const r=this.varyings,s=this.vars[e];for(let i=0;i1&&(n="_multisampled"),!0===t.isCubeTexture)s="texture_cube";else if(!0===t.isDataArrayTexture||!0===t.isCompressedArrayTexture)s="texture_2d_array";else if(!0===t.isDepthTexture)s=`texture_depth${n}_2d`;else if(!0===t.isVideoTexture)s="texture_external";else if(!0===t.isData3DTexture)s="texture_3d";else if(!0===i.node.isStorageTextureNode){s=`texture_storage_2d<${dN(t)}, ${this.getStorageAccess(i.node,e)}>`}else{s=`texture${n}_2d<${this.getComponentTypeFromTexture(t).charAt(0)}32>`}r.push(`@binding( ${o.binding++} ) @group( ${o.group} ) var ${i.name} : ${s};`)}else if("buffer"===i.type||"storageBuffer"===i.type||"indirectStorageBuffer"===i.type){const t=i.node,r=this.getType(t.bufferType),n=t.bufferCount,a=n>0&&"buffer"===i.type?", "+n:"",u=t.isAtomic?`atomic<${r}>`:`${r}`,l=`\t${i.name} : array< ${u}${a} >\n`,d=t.isStorageBufferNode?`storage, ${this.getStorageAccess(t,e)}`:"uniform";s.push(this._getWGSLStructBinding("NodeBuffer_"+t.id,l,d,o.binding++,o.group))}else{const e=this.getType(this.getVectorType(i.type)),t=i.groupNode.name;(n[t]||(n[t]={index:o.binding++,id:o.group,snippets:[]})).snippets.push(`\t${i.name} : ${e}`)}}for(const e in n){const t=n[e];i.push(this._getWGSLStructBinding(e,t.snippets.join(",\n"),"uniform",t.index,t.id))}let o=r.join("\n");return o+=s.join("\n"),o+=i.join("\n"),o}buildCode(){const e=null!==this.material?{fragment:{},vertex:{}}:{compute:{}};this.sortBindingGroups();for(const t in e){const r=e[t];r.uniforms=this.getUniforms(t),r.attributes=this.getAttributes(t),r.varyings=this.getVaryings(t),r.structs=this.getStructs(t),r.vars=this.getVars(t),r.codes=this.getCodes(t),r.directives=this.getDirectives(t),r.scopedArrays=this.getScopedArrays(t);let s="// code\n\n";s+=this.flowCode[t];const i=this.flowNodes[t],n=i[i.length-1],o=n.outputNode,a=void 0!==o&&!0===o.isOutputStructNode;for(const e of i){const i=this.getFlowData(e),u=e.name;if(u&&(s.length>0&&(s+="\n"),s+=`\t// flow -> ${u}\n\t`),s+=`${i.code}\n\t`,e===n&&"compute"!==t)if(s+="// result\n\n\t","vertex"===t)s+=`varyings.Vertex = ${i.result};`;else if("fragment"===t)if(a)r.returnType=o.nodeType,s+=`return ${i.result};`;else{let e="\t@location(0) color: vec4";const t=this.getBuiltins("output");t&&(e+=",\n\t"+t),r.returnType="OutputStruct",r.structs+=this._getWGSLStruct("OutputStruct",e),r.structs+="\nvar output : OutputStruct;\n\n",s+=`output.color = ${i.result};\n\n\treturn output;`}}r.flow=s}null!==this.material?(this.vertexShader=this._getWGSLVertexCode(e.vertex),this.fragmentShader=this._getWGSLFragmentCode(e.fragment)):this.computeShader=this._getWGSLComputeCode(e.compute,(this.object.workgroupSize||[64]).join(", "))}getMethod(e,t=null){let r;return null!==t&&(r=this._getWGSLMethod(e+"_"+t)),void 0===r&&(r=this._getWGSLMethod(e)),r||e}getType(e){return vN[e]||e}isAvailable(e){let t=TN[e];return void 0===t&&("float32Filterable"===e?t=this.renderer.hasFeature("float32-filterable"):"clipDistance"===e&&(t=this.renderer.hasFeature("clip-distances")),TN[e]=t),t}_getWGSLMethod(e){return void 0!==SN[e]&&this._include(e),AN[e]}_include(e){const t=SN[e];return t.build(this),null!==this.currentFunctionNode&&this.currentFunctionNode.includes.push(t),t}_getWGSLVertexCode(e){return`${this.getSignature()}\n// directives\n${e.directives}\n\n// uniforms\n${e.uniforms}\n\n// varyings\n${e.varyings}\nvar varyings : VaryingsStruct;\n\n// codes\n${e.codes}\n\n@vertex\nfn main( ${e.attributes} ) -> VaryingsStruct {\n\n\t// vars\n\t${e.vars}\n\n\t// flow\n\t${e.flow}\n\n\treturn varyings;\n\n}\n`}_getWGSLFragmentCode(e){return`${this.getSignature()}\n// global\n${RN}\n\n// uniforms\n${e.uniforms}\n\n// structs\n${e.structs}\n\n// codes\n${e.codes}\n\n@fragment\nfn main( ${e.varyings} ) -> ${e.returnType} {\n\n\t// vars\n\t${e.vars}\n\n\t// flow\n\t${e.flow}\n\n}\n`}_getWGSLComputeCode(e,t){return`${this.getSignature()}\n// directives\n${e.directives}\n\n// system\nvar instanceIndex : u32;\n\n// locals\n${e.scopedArrays}\n\n// uniforms\n${e.uniforms}\n\n// codes\n${e.codes}\n\n@compute @workgroup_size( ${t} )\nfn main( ${e.attributes} ) {\n\n\t// system\n\tinstanceIndex = id.x + id.y * numWorkgroups.x * u32(${t}) + id.z * numWorkgroups.x * numWorkgroups.y * u32(${t});\n\n\t// vars\n\t${e.vars}\n\n\t// flow\n\t${e.flow}\n\n}\n`}_getWGSLStruct(e,t){return`\nstruct ${e} {\n${t}\n};`}_getWGSLStructBinding(e,t,r,s=0,i=0){const n=e+"Struct";return`${this._getWGSLStruct(n,t)}\n@binding( ${s} ) @group( ${i} )\nvar<${r}> ${e} : ${n};`}}class EN{constructor(e){this.backend=e}getCurrentDepthStencilFormat(e){let t;return null!==e.depthTexture?t=this.getTextureFormatGPU(e.depthTexture):e.depth&&e.stencil?t=tv.Depth24PlusStencil8:e.depth&&(t=tv.Depth24Plus),t}getTextureFormatGPU(e){return this.backend.get(e).format}getTextureSampleData(e){let t;if(e.isFramebufferTexture)t=1;else if(e.isDepthTexture&&!e.renderTarget){const e=this.backend.renderer,r=e.getRenderTarget();t=r?r.samples:e.samples}else e.renderTarget&&(t=e.renderTarget.samples);t=t||1;const r=t>1&&null!==e.renderTarget&&!0!==e.isDepthTexture&&!0!==e.isFramebufferTexture;return{samples:t,primarySamples:r?1:t,isMSAA:r}}getCurrentColorFormat(e){let t;return t=null!==e.textures?this.getTextureFormatGPU(e.textures[0]):this.getPreferredCanvasFormat(),t}getCurrentColorSpace(e){return null!==e.textures?e.textures[0].colorSpace:this.backend.renderer.outputColorSpace}getPrimitiveTopology(e,t){return e.isPoints?F_:e.isLineSegments||e.isMesh&&!0===t.wireframe?P_:e.isLine?I_:e.isMesh?L_:void 0}getSampleCount(e){let t=1;return e>1&&(t=Math.pow(2,Math.floor(Math.log2(e))),2===t&&(t=4)),t}getSampleCountRenderContext(e){return null!==e.textures?this.getSampleCount(e.sampleCount):this.getSampleCount(this.backend.renderer.samples)}getPreferredCanvasFormat(){return navigator.userAgent.includes("Quest")?tv.BGRA8Unorm:navigator.gpu.getPreferredCanvasFormat()}}const wN=new Map([[Int8Array,["sint8","snorm8"]],[Uint8Array,["uint8","unorm8"]],[Int16Array,["sint16","snorm16"]],[Uint16Array,["uint16","unorm16"]],[Int32Array,["sint32","snorm32"]],[Uint32Array,["uint32","unorm32"]],[Float32Array,["float32"]]]),MN=new Map([[Le,["float16"]]]),BN=new Map([[Int32Array,"sint32"],[Int16Array,"sint32"],[Uint32Array,"uint32"],[Uint16Array,"uint32"],[Float32Array,"float32"]]);class UN{constructor(e){this.backend=e}createAttribute(e,t){const r=this._getBufferAttribute(e),s=this.backend,i=s.get(r);let n=i.buffer;if(void 0===n){const o=s.device;let a=r.array;if(!1===e.normalized&&(a.constructor===Int16Array||a.constructor===Uint16Array)){const e=new Uint32Array(a.length);for(let t=0;t1&&(s.multisampled=!0,r.texture.isDepthTexture||(s.sampleType=kv)),r.texture.isDepthTexture)s.sampleType=zv;else if(r.texture.isDataTexture||r.texture.isDataArrayTexture||r.texture.isData3DTexture){const e=r.texture.type;e===b?s.sampleType=$v:e===x?s.sampleType=Hv:e===E&&(this.backend.hasFeature("float32-filterable")?s.sampleType=Gv:s.sampleType=kv)}r.isSampledCubeTexture?s.viewDimension=Xv:r.texture.isDataArrayTexture||r.texture.isCompressedArrayTexture?s.viewDimension=Kv:r.isSampledTexture3D&&(s.viewDimension=Yv),e.texture=s}else console.error(`WebGPUBindingUtils: Unsupported binding "${r}".`);s.push(e)}return r.createBindGroupLayout({entries:s})}createBindings(e,t,r,s=0){const{backend:i,bindGroupLayoutCache:n}=this,o=i.get(e);let a,u=n.get(e.bindingsReference);void 0===u&&(u=this.createBindingsLayout(e),n.set(e.bindingsReference,u)),r>0&&(void 0===o.groups&&(o.groups=[],o.versions=[]),o.versions[r]===s&&(a=o.groups[r])),void 0===a&&(a=this.createBindGroup(e,u),r>0&&(o.groups[r]=a,o.versions[r]=s)),o.group=a,o.layout=u}updateBinding(e){const t=this.backend,r=t.device,s=e.buffer,i=t.get(e).buffer;r.queue.writeBuffer(i,0,s,0)}createBindGroup(e,t){const r=this.backend,s=r.device;let i=0;const n=[];for(const t of e.bindings){if(t.isUniformBuffer){const e=r.get(t);if(void 0===e.buffer){const r=t.byteLength,i=GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST,n=s.createBuffer({label:"bindingBuffer_"+t.name,size:r,usage:i});e.buffer=n}n.push({binding:i,resource:{buffer:e.buffer}})}else if(t.isStorageBuffer){const e=r.get(t);if(void 0===e.buffer){const s=t.attribute;e.buffer=r.get(s).buffer}n.push({binding:i,resource:{buffer:e.buffer}})}else if(t.isSampler){const e=r.get(t.texture);n.push({binding:i,resource:e.sampler})}else if(t.isSampledTexture){const e=r.get(t.texture);let o;if(void 0!==e.externalTexture)o=s.importExternalTexture({source:e.externalTexture});else{const r=t.store?1:e.texture.mipLevelCount,s=`view-${e.texture.width}-${e.texture.height}-${r}`;if(o=e[s],void 0===o){const i=Qv;let n;n=t.isSampledCubeTexture?Xv:t.isSampledTexture3D?Yv:t.texture.isDataArrayTexture||t.texture.isCompressedArrayTexture?Kv:qv,o=e[s]=e.texture.createView({aspect:i,dimension:n,mipLevelCount:r})}}n.push({binding:i,resource:o})}i++}return s.createBindGroup({label:"bindGroup_"+e.name,layout:t,entries:n})}}class PN{constructor(e){this.backend=e}_getSampleCount(e){return this.backend.utils.getSampleCountRenderContext(e)}createRenderPipeline(e,t){const{object:r,material:s,geometry:i,pipeline:n}=e,{vertexProgram:o,fragmentProgram:a}=n,u=this.backend,l=u.device,d=u.utils,c=u.get(n),h=[];for(const t of e.getBindings()){const e=u.get(t);h.push(e.layout)}const p=u.attributeUtils.createShaderVertexBuffers(e);let g;!0===s.transparent&&s.blending!==V&&(g=this._getBlending(s));let m={};!0===s.stencilWrite&&(m={compare:this._getStencilCompare(s),failOp:this._getStencilOperation(s.stencilFail),depthFailOp:this._getStencilOperation(s.stencilZFail),passOp:this._getStencilOperation(s.stencilZPass)});const f=this._getColorWriteMask(s),y=[];if(null!==e.context.textures){const t=e.context.textures;for(let e=0;e1},layout:l.createPipelineLayout({bindGroupLayouts:h})},A={},R=e.context.depth,C=e.context.stencil;if(!0!==R&&!0!==C||(!0===R&&(A.format=v,A.depthWriteEnabled=s.depthWrite,A.depthCompare=_),!0===C&&(A.stencilFront=m,A.stencilBack={},A.stencilReadMask=s.stencilFuncMask,A.stencilWriteMask=s.stencilWriteMask),S.depthStencil=A),null===t)c.pipeline=l.createRenderPipeline(S);else{const e=new Promise((e=>{l.createRenderPipelineAsync(S).then((t=>{c.pipeline=t,e()}))}));t.push(e)}}createBundleEncoder(e){const t=this.backend,{utils:r,device:s}=t,i=r.getCurrentDepthStencilFormat(e),n={label:"renderBundleEncoder",colorFormats:[r.getCurrentColorFormat(e)],depthStencilFormat:i,sampleCount:this._getSampleCount(e)};return s.createRenderBundleEncoder(n)}createComputePipeline(e,t){const r=this.backend,s=r.device,i=r.get(e.computeProgram).module,n=r.get(e),o=[];for(const e of t){const t=r.get(e);o.push(t.layout)}n.pipeline=s.createComputePipeline({compute:i,layout:s.createPipelineLayout({bindGroupLayouts:o})})}_getBlending(e){let t,r;const s=e.blending,i=e.blendSrc,n=e.blendDst,o=e.blendEquation;if(s===ft){const s=null!==e.blendSrcAlpha?e.blendSrcAlpha:i,a=null!==e.blendDstAlpha?e.blendDstAlpha:n,u=null!==e.blendEquationAlpha?e.blendEquationAlpha:o;t={srcFactor:this._getBlendFactor(i),dstFactor:this._getBlendFactor(n),operation:this._getBlendOperation(o)},r={srcFactor:this._getBlendFactor(s),dstFactor:this._getBlendFactor(a),operation:this._getBlendOperation(u)}}else{const i=(e,s,i,n)=>{t={srcFactor:e,dstFactor:s,operation:Tv},r={srcFactor:i,dstFactor:n,operation:Tv}};if(e.premultipliedAlpha)switch(s){case F:i(uv,hv,uv,hv);break;case bt:i(uv,uv,uv,uv);break;case xt:i(av,dv,av,uv);break;case yt:i(av,lv,av,cv)}else switch(s){case F:i(cv,hv,uv,hv);break;case bt:i(cv,uv,cv,uv);break;case xt:i(av,dv,av,uv);break;case yt:i(av,lv,av,lv)}}if(void 0!==t&&void 0!==r)return{color:t,alpha:r};console.error("THREE.WebGPURenderer: Invalid blending: ",s)}_getBlendFactor(e){let t;switch(e){case rt:t=av;break;case st:t=uv;break;case it:t=lv;break;case lt:t=dv;break;case nt:t=cv;break;case dt:t=hv;break;case at:t=pv;break;case ct:t=gv;break;case ut:t=mv;break;case ht:t=fv;break;case ot:t=yv;break;case 211:t=xv;break;case 212:t=bv;break;default:console.error("THREE.WebGPURenderer: Blend factor not supported.",e)}return t}_getStencilCompare(e){let t;const r=e.stencilFunc;switch(r){case Mr:t=D_;break;case wr:t=W_;break;case Er:t=O_;break;case Cr:t=k_;break;case Rr:t=G_;break;case Ar:t=H_;break;case Sr:t=z_;break;case Nr:t=$_;break;default:console.error("THREE.WebGPURenderer: Invalid stencil function.",r)}return t}_getStencilOperation(e){let t;switch(e){case Dr:t=Cv;break;case Vr:t=Ev;break;case Lr:t=wv;break;case Ir:t=Mv;break;case Pr:t=Bv;break;case Fr:t=Uv;break;case Ur:t=Fv;break;case Br:t=Pv;break;default:console.error("THREE.WebGPURenderer: Invalid stencil operation.",t)}return t}_getBlendOperation(e){let t;switch(e){case Je:t=Tv;break;case et:t=_v;break;case tt:t=vv;break;case Gr:t=Nv;break;case Or:t=Sv;break;default:console.error("THREE.WebGPUPipelineUtils: Blend equation not supported.",e)}return t}_getPrimitiveState(e,t,r){const s={},i=this.backend.utils;switch(s.topology=i.getPrimitiveTopology(e,r),null!==t.index&&!0===e.isLine&&!0!==e.isLineSegments&&(s.stripIndexFormat=t.index.array instanceof Uint16Array?J_:ev),r.side){case Ge:s.frontFace=X_,s.cullMode=Z_;break;case T:s.frontFace=X_,s.cullMode=Q_;break;case le:s.frontFace=X_,s.cullMode=Y_;break;default:console.error("THREE.WebGPUPipelineUtils: Unknown material.side value.",r.side)}return s}_getColorWriteMask(e){return!0===e.colorWrite?Rv:Av}_getDepthCompare(e){let t;if(!1===e.depthTest)t=W_;else{const r=e.depthFunc;switch(r){case Ct:t=D_;break;case Rt:t=W_;break;case At:t=O_;break;case St:t=k_;break;case Nt:t=G_;break;case vt:t=H_;break;case _t:t=z_;break;case Tt:t=$_;break;default:console.error("THREE.WebGPUPipelineUtils: Invalid depth function.",r)}}return t}}class IN extends g_{constructor(e={}){super(e),this.isWebGPUBackend=!0,this.parameters.alpha=void 0===e.alpha||e.alpha,this.parameters.requiredLimits=void 0===e.requiredLimits?{}:e.requiredLimits,this.trackTimestamp=!0===e.trackTimestamp,this.device=null,this.context=null,this.colorBuffer=null,this.defaultRenderPassdescriptor=null,this.utils=new EN(this),this.attributeUtils=new UN(this),this.bindingUtils=new FN(this),this.pipelineUtils=new PN(this),this.textureUtils=new lN(this),this.occludedResolveCache=new Map}async init(e){await super.init(e);const t=this.parameters;let r;if(void 0===t.device){const e={powerPreference:t.powerPreference},s="undefined"!=typeof navigator?await navigator.gpu.requestAdapter(e):null;if(null===s)throw new Error("WebGPUBackend: Unable to create WebGPU adapter.");const i=Object.values(eN),n=[];for(const e of i)s.features.has(e)&&n.push(e);const o={requiredFeatures:n,requiredLimits:t.requiredLimits};r=await s.requestDevice(o)}else r=t.device;r.lost.then((t=>{const r={api:"WebGPU",message:t.message||"Unknown reason",reason:t.reason||null,originalEvent:t};e.onDeviceLost(r)}));const s=void 0!==t.context?t.context:e.domElement.getContext("webgpu");this.device=r,this.context=s;const i=t.alpha?"premultiplied":"opaque";this.trackTimestamp=this.trackTimestamp&&this.hasFeature(eN.TimestampQuery),this.context.configure({device:this.device,format:this.utils.getPreferredCanvasFormat(),usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.COPY_SRC,alphaMode:i}),this.updateSize()}get coordinateSystem(){return l}async getArrayBufferAsync(e){return await this.attributeUtils.getArrayBufferAsync(e)}getContext(){return this.context}_getDefaultRenderPassDescriptor(){let e=this.defaultRenderPassdescriptor;if(null===e){const t=this.renderer;e={colorAttachments:[{view:null}]},!0!==this.renderer.depth&&!0!==this.renderer.stencil||(e.depthStencilAttachment={view:this.textureUtils.getDepthBuffer(t.depth,t.stencil).createView()});const r=e.colorAttachments[0];this.renderer.samples>0?r.view=this.colorBuffer.createView():r.resolveTarget=void 0,this.defaultRenderPassdescriptor=e}const t=e.colorAttachments[0];return this.renderer.samples>0?t.resolveTarget=this.context.getCurrentTexture().createView():t.view=this.context.getCurrentTexture().createView(),e}_getRenderPassDescriptor(e){const t=e.renderTarget,r=this.get(t);let s=r.descriptors;if(void 0===s||r.width!==t.width||r.height!==t.height||r.activeMipmapLevel!==t.activeMipmapLevel||r.samples!==t.samples){s={},r.descriptors=s;const e=()=>{t.removeEventListener("dispose",e),this.delete(t)};t.addEventListener("dispose",e)}const i=e.getCacheKey();let n=s[i];if(void 0===n){const o=e.textures,a=[];for(let t=0;t0&&(t.currentOcclusionQuerySet&&t.currentOcclusionQuerySet.destroy(),t.currentOcclusionQueryBuffer&&t.currentOcclusionQueryBuffer.destroy(),t.currentOcclusionQuerySet=t.occlusionQuerySet,t.currentOcclusionQueryBuffer=t.occlusionQueryBuffer,t.currentOcclusionQueryObjects=t.occlusionQueryObjects,i=r.createQuerySet({type:"occlusion",count:s,label:`occlusionQuerySet_${e.id}`}),t.occlusionQuerySet=i,t.occlusionQueryIndex=0,t.occlusionQueryObjects=new Array(s),t.lastOcclusionObject=null),n=null===e.textures?this._getDefaultRenderPassDescriptor():this._getRenderPassDescriptor(e),this.initTimestampQuery(e,n),n.occlusionQuerySet=i;const o=n.depthStencilAttachment;if(null!==e.textures){const t=n.colorAttachments;for(let r=0;r0&&t.currentPass.executeBundles(t.renderBundles),r>t.occlusionQueryIndex&&t.currentPass.endOcclusionQuery(),t.currentPass.end(),r>0){const s=8*r;let i=this.occludedResolveCache.get(s);void 0===i&&(i=this.device.createBuffer({size:s,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),this.occludedResolveCache.set(s,i));const n=this.device.createBuffer({size:s,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});t.encoder.resolveQuerySet(t.occlusionQuerySet,0,r,i,0),t.encoder.copyBufferToBuffer(i,0,n,0,s),t.occlusionQueryBuffer=n,this.resolveOccludedAsync(e)}if(this.prepareTimestampBuffer(e,t.encoder),this.device.queue.submit([t.encoder.finish()]),null!==e.textures){const t=e.textures;for(let e=0;eo?(u.x=Math.min(t.dispatchCount,o),u.y=Math.ceil(t.dispatchCount/o)):u.x=t.dispatchCount,i.dispatchWorkgroups(u.x,u.y,u.z)}finishCompute(e){const t=this.get(e);t.passEncoderGPU.end(),this.prepareTimestampBuffer(e,t.cmdEncoderGPU),this.device.queue.submit([t.cmdEncoderGPU.finish()])}async waitForGPU(){await this.device.queue.onSubmittedWorkDone()}draw(e,t){const{object:r,context:s,pipeline:i}=e,n=e.getBindings(),o=this.get(s),a=this.get(i).pipeline,u=o.currentSets,l=o.currentPass,d=e.getDrawParameters();if(null===d)return;u.pipeline!==a&&(l.setPipeline(a),u.pipeline=a);const c=u.bindingGroups;for(let e=0,t=n.length;e1?0:r;!0===p?l.drawIndexed(t[r],s,e[r]/h.array.BYTES_PER_ELEMENT,0,n):l.draw(t[r],s,e[r],n)}}else if(!0===p){const{vertexCount:s,instanceCount:i,firstVertex:n}=d,o=e.getIndirect();if(null!==o){const e=this.get(o).buffer;l.drawIndexedIndirect(e,0)}else l.drawIndexed(s,i,n,0,0);t.update(r,s,i)}else{const{vertexCount:s,instanceCount:i,firstVertex:n}=d,o=e.getIndirect();if(null!==o){const e=this.get(o).buffer;l.drawIndirect(e,0)}else l.draw(s,i,n,0);t.update(r,s,i)}}needsRenderUpdate(e){const t=this.get(e),{object:r,material:s}=e,i=this.utils,n=i.getSampleCountRenderContext(e.context),o=i.getCurrentColorSpace(e.context),a=i.getCurrentColorFormat(e.context),u=i.getCurrentDepthStencilFormat(e.context),l=i.getPrimitiveTopology(r,s);let d=!1;return t.material===s&&t.materialVersion===s.version&&t.transparent===s.transparent&&t.blending===s.blending&&t.premultipliedAlpha===s.premultipliedAlpha&&t.blendSrc===s.blendSrc&&t.blendDst===s.blendDst&&t.blendEquation===s.blendEquation&&t.blendSrcAlpha===s.blendSrcAlpha&&t.blendDstAlpha===s.blendDstAlpha&&t.blendEquationAlpha===s.blendEquationAlpha&&t.colorWrite===s.colorWrite&&t.depthWrite===s.depthWrite&&t.depthTest===s.depthTest&&t.depthFunc===s.depthFunc&&t.stencilWrite===s.stencilWrite&&t.stencilFunc===s.stencilFunc&&t.stencilFail===s.stencilFail&&t.stencilZFail===s.stencilZFail&&t.stencilZPass===s.stencilZPass&&t.stencilFuncMask===s.stencilFuncMask&&t.stencilWriteMask===s.stencilWriteMask&&t.side===s.side&&t.alphaToCoverage===s.alphaToCoverage&&t.sampleCount===n&&t.colorSpace===o&&t.colorFormat===a&&t.depthStencilFormat===u&&t.primitiveTopology===l&&t.clippingContextCacheKey===e.clippingContextCacheKey||(t.material=s,t.materialVersion=s.version,t.transparent=s.transparent,t.blending=s.blending,t.premultipliedAlpha=s.premultipliedAlpha,t.blendSrc=s.blendSrc,t.blendDst=s.blendDst,t.blendEquation=s.blendEquation,t.blendSrcAlpha=s.blendSrcAlpha,t.blendDstAlpha=s.blendDstAlpha,t.blendEquationAlpha=s.blendEquationAlpha,t.colorWrite=s.colorWrite,t.depthWrite=s.depthWrite,t.depthTest=s.depthTest,t.depthFunc=s.depthFunc,t.stencilWrite=s.stencilWrite,t.stencilFunc=s.stencilFunc,t.stencilFail=s.stencilFail,t.stencilZFail=s.stencilZFail,t.stencilZPass=s.stencilZPass,t.stencilFuncMask=s.stencilFuncMask,t.stencilWriteMask=s.stencilWriteMask,t.side=s.side,t.alphaToCoverage=s.alphaToCoverage,t.sampleCount=n,t.colorSpace=o,t.colorFormat=a,t.depthStencilFormat=u,t.primitiveTopology=l,t.clippingContextCacheKey=e.clippingContextCacheKey,d=!0),d}getRenderCacheKey(e){const{object:t,material:r}=e,s=this.utils,i=e.context;return[r.transparent,r.blending,r.premultipliedAlpha,r.blendSrc,r.blendDst,r.blendEquation,r.blendSrcAlpha,r.blendDstAlpha,r.blendEquationAlpha,r.colorWrite,r.depthWrite,r.depthTest,r.depthFunc,r.stencilWrite,r.stencilFunc,r.stencilFail,r.stencilZFail,r.stencilZPass,r.stencilFuncMask,r.stencilWriteMask,r.side,s.getSampleCountRenderContext(i),s.getCurrentColorSpace(i),s.getCurrentColorFormat(i),s.getCurrentDepthStencilFormat(i),s.getPrimitiveTopology(t,r),e.getGeometryCacheKey(),e.clippingContextCacheKey].join()}createSampler(e){this.textureUtils.createSampler(e)}destroySampler(e){this.textureUtils.destroySampler(e)}createDefaultTexture(e){this.textureUtils.createDefaultTexture(e)}createTexture(e,t){this.textureUtils.createTexture(e,t)}updateTexture(e,t){this.textureUtils.updateTexture(e,t)}generateMipmaps(e){this.textureUtils.generateMipmaps(e)}destroyTexture(e){this.textureUtils.destroyTexture(e)}copyTextureToBuffer(e,t,r,s,i,n){return this.textureUtils.copyTextureToBuffer(e,t,r,s,i,n)}initTimestampQuery(e,t){if(!this.trackTimestamp)return;const r=this.get(e);if(!r.timeStampQuerySet){const s=e.isComputeNode?"compute":"render",i=this.device.createQuerySet({type:"timestamp",count:2,label:`timestamp_${s}_${e.id}`}),n={querySet:i,beginningOfPassWriteIndex:0,endOfPassWriteIndex:1};Object.assign(t,{timestampWrites:n}),r.timeStampQuerySet=i}}prepareTimestampBuffer(e,t){if(!this.trackTimestamp)return;const r=this.get(e),s=2*BigInt64Array.BYTES_PER_ELEMENT;void 0===r.currentTimestampQueryBuffers&&(r.currentTimestampQueryBuffers={resolveBuffer:this.device.createBuffer({label:"timestamp resolve buffer",size:s,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),resultBuffer:this.device.createBuffer({label:"timestamp result buffer",size:s,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ})});const{resolveBuffer:i,resultBuffer:n}=r.currentTimestampQueryBuffers;t.resolveQuerySet(r.timeStampQuerySet,0,2,i,0),"unmapped"===n.mapState&&t.copyBufferToBuffer(i,0,n,0,s)}async resolveTimestampAsync(e,t="render"){if(!this.trackTimestamp)return;const r=this.get(e);if(void 0===r.currentTimestampQueryBuffers)return;const{resultBuffer:s}=r.currentTimestampQueryBuffers;"unmapped"===s.mapState&&s.mapAsync(GPUMapMode.READ).then((()=>{const e=new BigUint64Array(s.getMappedRange()),r=Number(e[1]-e[0])/1e6;this.renderer.info.updateTimestamp(t,r),s.unmap()}))}createNodeBuilder(e,t){return new CN(e,t)}createProgram(e){this.get(e).module={module:this.device.createShaderModule({code:e.code,label:e.stage}),entryPoint:"main"}}destroyProgram(e){this.delete(e)}createRenderPipeline(e,t){this.pipelineUtils.createRenderPipeline(e,t)}createComputePipeline(e,t){this.pipelineUtils.createComputePipeline(e,t)}beginBundle(e){const t=this.get(e);t._currentPass=t.currentPass,t._currentSets=t.currentSets,t.currentSets={attributes:{},bindingGroups:[],pipeline:null,index:null},t.currentPass=this.pipelineUtils.createBundleEncoder(e)}finishBundle(e,t){const r=this.get(e),s=r.currentPass.finish();this.get(t).bundleGPU=s,r.currentSets=r._currentSets,r.currentPass=r._currentPass}addBundle(e,t){this.get(e).renderBundles.push(this.get(t).bundleGPU)}createBindings(e,t,r,s){this.bindingUtils.createBindings(e,t,r,s)}updateBindings(e,t,r,s){this.bindingUtils.createBindings(e,t,r,s)}updateBinding(e){this.bindingUtils.updateBinding(e)}createIndexAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.INDEX|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}createAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}createStorageAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.STORAGE|GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}createIndirectStorageAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.STORAGE|GPUBufferUsage.INDIRECT|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}updateAttribute(e){this.attributeUtils.updateAttribute(e)}destroyAttribute(e){this.attributeUtils.destroyAttribute(e)}updateSize(){this.colorBuffer=this.textureUtils.getColorBuffer(),this.defaultRenderPassdescriptor=null}getMaxAnisotropy(){return 16}hasFeature(e){return this.device.features.has(e)}copyTextureToTexture(e,t,r=null,s=null,i=0){let n=0,o=0,a=0,u=0,l=0,d=0,c=e.image.width,h=e.image.height;null!==r&&(u=r.x,l=r.y,d=r.z||0,c=r.width,h=r.height),null!==s&&(n=s.x,o=s.y,a=s.z||0);const p=this.device.createCommandEncoder({label:"copyTextureToTexture_"+e.id+"_"+t.id}),g=this.get(e).texture,m=this.get(t).texture;p.copyTextureToTexture({texture:g,mipLevel:i,origin:{x:u,y:l,z:d}},{texture:m,mipLevel:i,origin:{x:n,y:o,z:a}},[c,h,1]),this.device.queue.submit([p.finish()])}copyFramebufferToTexture(e,t,r){const s=this.get(t);let i=null;i=t.renderTarget?e.isDepthTexture?this.get(t.depthTexture).texture:this.get(t.textures[0]).texture:e.isDepthTexture?this.textureUtils.getDepthBuffer(t.depth,t.stencil):this.context.getCurrentTexture();const n=this.get(e).texture;if(i.format!==n.format)return void console.error("WebGPUBackend: copyFramebufferToTexture: Source and destination formats do not match.",i.format,n.format);let o;if(s.currentPass?(s.currentPass.end(),o=s.encoder):o=this.device.createCommandEncoder({label:"copyFramebufferToTexture_"+e.id}),o.copyTextureToTexture({texture:i,origin:[r.x,r.y,0]},{texture:n},[r.z,r.w]),e.generateMipmaps&&this.textureUtils.generateMipmaps(e),s.currentPass){const{descriptor:e}=s;for(let t=0;t(console.warn("THREE.WebGPURenderer: WebGPU is not available, running under WebGL2 backend."),new U_(e)));super(new t(e),e),this.library=new VN,this.isWebGPURenderer=!0}}class ON extends es{constructor(){super(),this.isBundleGroup=!0,this.type="BundleGroup",this.static=!0,this.version=0}set needsUpdate(e){!0===e&&this.version++}}const GN=new Yc,kN=new Jm(GN);class zN{constructor(e,t=Oi(0,0,1,1)){this.renderer=e,this.outputNode=t,this.outputColorTransform=!0,this.needsUpdate=!0,GN.name="PostProcessing"}render(){this.update();const e=this.renderer,t=e.toneMapping,r=e.outputColorSpace;e.toneMapping=h,e.outputColorSpace=Ae,kN.render(e),e.toneMapping=t,e.outputColorSpace=r}update(){if(!0===this.needsUpdate){const e=this.renderer,t=e.toneMapping,r=e.outputColorSpace;kN.material.fragmentNode=!0===this.outputColorTransform?du(this.outputNode,t,r):this.outputNode.context({toneMapping:t,outputColorSpace:r}),kN.material.needsUpdate=!0,this.needsUpdate=!1}}async renderAsync(){this.update();const e=this.renderer,t=e.toneMapping,r=e.outputColorSpace;e.toneMapping=h,e.outputColorSpace=Ae,await kN.renderAsync(e),e.toneMapping=t,e.outputColorSpace=r}}function $N(t,r={}){return r.toneMapping=t.toneMapping,r.toneMappingExposure=t.toneMappingExposure,r.outputColorSpace=t.outputColorSpace,r.renderTarget=t.getRenderTarget(),r.activeCubeFace=t.getActiveCubeFace(),r.activeMipmapLevel=t.getActiveMipmapLevel(),r.renderObjectFunction=t.getRenderObjectFunction(),r.pixelRatio=t.getPixelRatio(),r.mrt=t.getMRT(),r.clearColor=t.getClearColor(r.clearColor||new e),r.clearAlpha=t.getClearAlpha(),r.autoClear=t.autoClear,r.scissorTest=t.getScissorTest(),r}function HN(e,t){e.toneMapping=t.toneMapping,e.toneMappingExposure=t.toneMappingExposure,e.outputColorSpace=t.outputColorSpace,e.setRenderTarget(t.renderTarget,t.activeCubeFace,t.activeMipmapLevel),e.setRenderObjectFunction(t.renderObjectFunction),e.setPixelRatio(t.pixelRatio),e.setMRT(t.mrt),e.setClearColor(t.clearColor,t.clearAlpha),e.autoClear=t.autoClear,e.setScissorTest(t.scissorTest)}function WN(e,t,r={}){return(r=$N(e,r)).background=t.background,r.backgroundNode=t.backgroundNode,r.overrideMaterial=t.overrideMaterial,r}var jN=Object.freeze({__proto__:null,resetRendererAndSceneState:function(e,t,r){return r=WN(e,t,r),t.background=null,t.backgroundNode=null,t.overrideMaterial=null,r},resetRendererState:function(e,t){return t=$N(e,t),e.setMRT(null),e.setRenderObjectFunction(null),e.setClearColor(0,1),e.autoClear=!0,t},restoreRendererAndSceneState:function(e,t,r){HN(e,r),t.background=r.background,t.backgroundNode=r.backgroundNode,t.overrideMaterial=r.overrideMaterial},restoreRendererState:HN,saveRendererAndSceneState:WN,saveRendererState:$N});class qN extends ee{constructor(e=1,t=1){super(),this.image={width:e,height:t},this.magFilter=$,this.minFilter=$,this.isStorageTexture=!0}}class KN extends uf{constructor(e,t){super(e,t,Uint32Array),this.isIndirectStorageBufferAttribute=!0}}class XN extends ts{constructor(e){super(e),this.textures={},this.nodes={}}load(e,t,r,s){const i=new rs(this.manager);i.setPath(this.path),i.setRequestHeader(this.requestHeader),i.setWithCredentials(this.withCredentials),i.load(e,(r=>{try{t(this.parse(JSON.parse(r)))}catch(t){s?s(t):console.error(t),this.manager.itemError(e)}}),r,s)}parseNodes(e){const t={};if(void 0!==e){for(const r of e){const{uuid:e,type:s}=r;t[e]=this.createNodeFromType(s),t[e].uuid=e}const r={nodes:t,textures:this.textures};for(const s of e){s.meta=r;t[s.uuid].deserialize(s),delete s.meta}}return t}parse(e){const t=this.createNodeFromType(e.type);t.uuid=e.uuid;const r={nodes:this.parseNodes(e.nodes),textures:this.textures};return e.meta=r,t.deserialize(e),delete e.meta,t}setTextures(e){return this.textures=e,this}setNodes(e){return this.nodes=e,this}createNodeFromType(e){return void 0===this.nodes[e]?(console.error("THREE.NodeLoader: Node type not found:",e),Ci()):fi(new this.nodes[e])}}class YN extends ss{constructor(e){super(e),this.nodes={},this.nodeMaterials={}}parse(e){const t=super.parse(e),r=this.nodes,s=e.inputNodes;for(const e in s){const i=s[e];t[e]=r[i]}return t}setNodes(e){return this.nodes=e,this}setNodeMaterials(e){return this.nodeMaterials=e,this}createMaterialFromType(e){const t=this.nodeMaterials[e];return void 0!==t?new t:super.createMaterialFromType(e)}}class QN extends is{constructor(e){super(e),this.nodes={},this.nodeMaterials={},this._nodesJSON=null}setNodes(e){return this.nodes=e,this}setNodeMaterials(e){return this.nodeMaterials=e,this}parse(e,t){this._nodesJSON=e.nodes;const r=super.parse(e,t);return this._nodesJSON=null,r}parseNodes(e,t){if(void 0!==e){const r=new XN;return r.setNodes(this.nodes),r.setTextures(t),r.parseNodes(e)}return{}}parseMaterials(e,t){const r={};if(void 0!==e){const s=this.parseNodes(this._nodesJSON,t),i=new YN;i.setTextures(t),i.setNodes(s),i.setNodeMaterials(this.nodeMaterials);for(let t=0,s=e.length;t0){const{width:r,height:s}=e.context;t.bufferWidth=r,t.bufferHeight=s}this.renderObjects.set(e,t)}return t}getAttributesData(e){const t={};for(const r in e){const s=e[r];t[r]={version:s.version}}return t}containsNode(e){const t=e.material;for(const e in t)if(t[e]&&t[e].isNode)return!0;return null!==e.renderer.nodes.modelViewMatrix||null!==e.renderer.nodes.modelNormalViewMatrix}getMaterialData(e){const t={};for(const r of this.refreshUniforms){const s=e[r];null!=s&&("object"==typeof s&&void 0!==s.clone?!0===s.isTexture?t[r]={id:s.id,version:s.version}:t[r]=s.clone():t[r]=s)}return t}equals(e){const{object:t,material:r,geometry:s}=e,i=this.getRenderObjectData(e);if(!0!==i.worldMatrix.equals(t.matrixWorld))return i.worldMatrix.copy(t.matrixWorld),!1;const n=i.material;for(const e in n){const t=n[e],s=r[e];if(void 0!==t.equals){if(!1===t.equals(s))return t.copy(s),!1}else if(!0===s.isTexture){if(t.id!==s.id||t.version!==s.version)return t.id=s.id,t.version=s.version,!1}else if(t!==s)return n[e]=s,!1}if(n.transmission>0){const{width:t,height:r}=e.context;if(i.bufferWidth!==t||i.bufferHeight!==r)return i.bufferWidth=t,i.bufferHeight=r,!1}const o=i.geometry,a=s.attributes,u=o.attributes,l=Object.keys(u),d=Object.keys(a);if(l.length!==d.length)return i.geometry.attributes=this.getAttributesData(a),!1;for(const e of l){const t=u[e],r=a[e];if(void 0===r)return delete u[e],!1;if(t.version!==r.version)return t.version=r.version,!1}const c=s.index,h=o.indexVersion,p=c?c.version:null;if(h!==p)return o.indexVersion=p,!1;if(o.drawRange.start!==s.drawRange.start||o.drawRange.count!==s.drawRange.count)return o.drawRange.start=s.drawRange.start,o.drawRange.count=s.drawRange.count,!1;if(i.morphTargetInfluences){let e=!1;for(let r=0;r>>16,2246822507),r^=Math.imul(s^s>>>13,3266489909),s=Math.imul(s^s>>>16,2246822507),s^=Math.imul(r^r>>>13,3266489909),4294967296*(2097151&s)+(r>>>0)}const ls=e=>us(e),ds=e=>us(e),cs=(...e)=>us(e);function hs(e,t=!1){const r=[];!0===e.isNode&&(r.push(e.id),e=e.getSelf());for(const{property:s,childNode:i}of ps(e))r.push(r,us(s.slice(0,-4)),i.getCacheKey(t));return us(r)}function*ps(e,t=!1){for(const r in e){if(!0===r.startsWith("_"))continue;const s=e[r];if(!0===Array.isArray(s))for(let e=0;ee.charCodeAt(0))).buffer}var Ss=Object.freeze({__proto__:null,arrayBufferToBase64:vs,base64ToArrayBuffer:Ns,getCacheKey:hs,getDataFromObject:_s,getLengthFromType:bs,getNodeChildren:ps,getTypeFromLength:fs,getTypedArrayFromType:ys,getValueFromType:Ts,getValueType:xs,hash:cs,hashArray:ds,hashString:ls});const As={VERTEX:"vertex",FRAGMENT:"fragment"},Rs={NONE:"none",FRAME:"frame",RENDER:"render",OBJECT:"object"},Cs={BOOLEAN:"bool",INTEGER:"int",FLOAT:"float",VECTOR2:"vec2",VECTOR3:"vec3",VECTOR4:"vec4",MATRIX2:"mat2",MATRIX3:"mat3",MATRIX4:"mat4"},Es={READ_ONLY:"readOnly",WRITE_ONLY:"writeOnly",READ_WRITE:"readWrite"},ws=["fragment","vertex"],Ms=["setup","analyze","generate"],Bs=[...ws,"compute"],Fs=["x","y","z","w"];let Us=0;class Ps extends o{static get type(){return"Node"}constructor(e=null){super(),this.nodeType=e,this.updateType=Rs.NONE,this.updateBeforeType=Rs.NONE,this.updateAfterType=Rs.NONE,this.uuid=a.generateUUID(),this.version=0,this.global=!1,this.isNode=!0,this._cacheKey=null,this._cacheKeyVersion=0,Object.defineProperty(this,"id",{value:Us++})}set needsUpdate(e){!0===e&&this.version++}get type(){return this.constructor.type}onUpdate(e,t){return this.updateType=t,this.update=e.bind(this.getSelf()),this}onFrameUpdate(e){return this.onUpdate(e,Rs.FRAME)}onRenderUpdate(e){return this.onUpdate(e,Rs.RENDER)}onObjectUpdate(e){return this.onUpdate(e,Rs.OBJECT)}onReference(e){return this.updateReference=e.bind(this.getSelf()),this}getSelf(){return this.self||this}updateReference(){return this}isGlobal(){return this.global}*getChildren(){for(const{childNode:e}of ps(this))yield e}dispose(){this.dispatchEvent({type:"dispose"})}traverse(e){e(this);for(const t of this.getChildren())t.traverse(e)}getCacheKey(e=!1){return!0!==(e=e||this.version!==this._cacheKeyVersion)&&null!==this._cacheKey||(this._cacheKey=cs(hs(this,e),this.customCacheKey()),this._cacheKeyVersion=this.version),this._cacheKey}customCacheKey(){return 0}getScope(){return this}getHash(){return this.uuid}getUpdateType(){return this.updateType}getUpdateBeforeType(){return this.updateBeforeType}getUpdateAfterType(){return this.updateAfterType}getElementType(e){const t=this.getNodeType(e);return e.getElementType(t)}getNodeType(e){const t=e.getNodeProperties(this);return t.outputNode?t.outputNode.getNodeType(e):this.nodeType}getShared(e){const t=this.getHash(e);return e.getNodeFromHash(t)||this}setup(e){const t=e.getNodeProperties(this);let r=0;for(const e of this.getChildren())t["node"+r++]=e;return t.outputNode||null}analyze(e){if(1===e.increaseUsage(this)){const t=e.getNodeProperties(this);for(const r of Object.values(t))r&&!0===r.isNode&&r.build(e)}}generate(e,t){const{outputNode:r}=e.getNodeProperties(this);if(r&&!0===r.isNode)return r.build(e,t)}updateBefore(){console.warn("Abstract function.")}updateAfter(){console.warn("Abstract function.")}update(){console.warn("Abstract function.")}build(e,t=null){const r=this.getShared(e);if(this!==r)return r.build(e,t);e.addNode(this),e.addChain(this);let s=null;const i=e.getBuildStage();if("setup"===i){this.updateReference(e);const t=e.getNodeProperties(this);if(!0!==t.initialized){t.initialized=!0;const r=this.setup(e),s=r&&!0===r.isNode;for(const r of Object.values(t))r&&!0===r.isNode&&r.build(e);s&&r.build(e),t.outputNode=r}}else if("analyze"===i)this.analyze(e);else if("generate"===i){if(1===this.generate.length){const r=this.getNodeType(e),i=e.getDataFromNode(this);s=i.snippet,void 0===s?(s=this.generate(e)||"",i.snippet=s):void 0!==i.flowCodes&&void 0!==e.context.nodeBlock&&e.addFlowCodeHierarchy(this,e.context.nodeBlock),s=e.format(s,r,t)}else s=this.generate(e,t)||""}return e.removeChain(this),e.addSequentialNode(this),s}getSerializeChildren(){return ps(this)}serialize(e){const t=this.getSerializeChildren(),r={};for(const{property:s,index:i,childNode:n}of t)void 0!==i?(void 0===r[s]&&(r[s]=Number.isInteger(i)?[]:{}),r[s][i]=n.toJSON(e.meta).uuid):r[s]=n.toJSON(e.meta).uuid;Object.keys(r).length>0&&(e.inputNodes=r)}deserialize(e){if(void 0!==e.inputNodes){const t=e.meta.nodes;for(const r in e.inputNodes)if(Array.isArray(e.inputNodes[r])){const s=[];for(const i of e.inputNodes[r])s.push(t[i]);this[r]=s}else if("object"==typeof e.inputNodes[r]){const s={};for(const i in e.inputNodes[r]){const n=e.inputNodes[r][i];s[i]=t[n]}this[r]=s}else{const s=e.inputNodes[r];this[r]=t[s]}}}toJSON(e){const{uuid:t,type:r}=this,s=void 0===e||"string"==typeof e;s&&(e={textures:{},images:{},nodes:{}});let i=e.nodes[t];function n(e){const t=[];for(const r in e){const s=e[r];delete s.metadata,t.push(s)}return t}if(void 0===i&&(i={uuid:t,type:r,meta:e,metadata:{version:4.6,type:"Node",generator:"Node.toJSON"}},!0!==s&&(e.nodes[i.uuid]=i),this.serialize(i),delete i.meta),s){const t=n(e.textures),r=n(e.images),s=n(e.nodes);t.length>0&&(i.textures=t),r.length>0&&(i.images=r),s.length>0&&(i.nodes=s)}return i}}class Is extends Ps{static get type(){return"ArrayElementNode"}constructor(e,t){super(),this.node=e,this.indexNode=t,this.isArrayElementNode=!0}getNodeType(e){return this.node.getElementType(e)}generate(e){return`${this.node.build(e)}[ ${this.indexNode.build(e,"uint")} ]`}}class Ds extends Ps{static get type(){return"ConvertNode"}constructor(e,t){super(),this.node=e,this.convertTo=t}getNodeType(e){const t=this.node.getNodeType(e);let r=null;for(const s of this.convertTo.split("|"))null!==r&&e.getTypeLength(t)!==e.getTypeLength(s)||(r=s);return r}serialize(e){super.serialize(e),e.convertTo=this.convertTo}deserialize(e){super.deserialize(e),this.convertTo=e.convertTo}generate(e,t){const r=this.node,s=this.getNodeType(e),i=r.build(e,s);return e.format(i,s,t)}}class Ls extends Ps{static get type(){return"TempNode"}constructor(e=null){super(e),this.isTempNode=!0}hasDependencies(e){return e.getDataFromNode(this).usageCount>1}build(e,t){if("generate"===e.getBuildStage()){const r=e.getVectorType(this.getNodeType(e,t)),s=e.getDataFromNode(this);if(void 0!==s.propertyName)return e.format(s.propertyName,r,t);if("void"!==r&&"void"!==t&&this.hasDependencies(e)){const i=super.build(e,r),n=e.getVarFromNode(this,null,r),o=e.getPropertyName(n);return e.addLineFlowCode(`${o} = ${i}`,this),s.snippet=i,s.propertyName=o,e.format(s.propertyName,r,t)}}return super.build(e,t)}}class Vs extends Ls{static get type(){return"JoinNode"}constructor(e=[],t=null){super(t),this.nodes=e}getNodeType(e){return null!==this.nodeType?e.getVectorType(this.nodeType):e.getTypeFromLength(this.nodes.reduce(((t,r)=>t+e.getTypeLength(r.getNodeType(e))),0))}generate(e,t){const r=this.getNodeType(e),s=this.nodes,i=e.getComponentType(r),n=[];for(const t of s){let r=t.build(e);const s=e.getComponentType(t.getNodeType(e));s!==i&&(r=e.format(r,s,i)),n.push(r)}const o=`${e.getType(r)}( ${n.join(", ")} )`;return e.format(o,r,t)}}const Os=Fs.join("");class Gs extends Ps{static get type(){return"SplitNode"}constructor(e,t="x"){super(),this.node=e,this.components=t,this.isSplitNode=!0}getVectorLength(){let e=this.components.length;for(const t of this.components)e=Math.max(Fs.indexOf(t)+1,e);return e}getComponentType(e){return e.getComponentType(this.node.getNodeType(e))}getNodeType(e){return e.getTypeFromLength(this.components.length,this.getComponentType(e))}generate(e,t){const r=this.node,s=e.getTypeLength(r.getNodeType(e));let i=null;if(s>1){let n=null;this.getVectorLength()>=s&&(n=e.getTypeFromLength(this.getVectorLength(),this.getComponentType(e)));const o=r.build(e,n);i=this.components.length===s&&this.components===Os.slice(0,this.components.length)?e.format(o,n,t):e.format(`${o}.${this.components}`,this.getNodeType(e),t)}else i=r.build(e,t);return i}serialize(e){super.serialize(e),e.components=this.components}deserialize(e){super.deserialize(e),this.components=e.components}}class ks extends Ls{static get type(){return"SetNode"}constructor(e,t,r){super(),this.sourceNode=e,this.components=t,this.targetNode=r}getNodeType(e){return this.sourceNode.getNodeType(e)}generate(e){const{sourceNode:t,components:r,targetNode:s}=this,i=this.getNodeType(e),n=e.getComponentType(s.getNodeType(e)),o=e.getTypeFromLength(r.length,n),a=s.build(e,o),u=t.build(e,i),l=e.getTypeLength(i),d=[];for(let e=0;ee.replace(/r|s/g,"x").replace(/g|t/g,"y").replace(/b|p/g,"z").replace(/a|q/g,"w"),Xs=e=>Ks(e).split("").sort().join(""),Ys={setup(e,t){const r=t.shift();return e(_i(r),...t)},get(e,t,r){if("string"==typeof t&&void 0===e[t]){if(!0!==e.isStackNode&&"assign"===t)return(...e)=>(Ws.assign(r,...e),r);if(js.has(t)){const s=js.get(t);return e.isStackNode?(...e)=>r.add(s(...e)):(...e)=>s(r,...e)}if("self"===t)return e;if(t.endsWith("Assign")&&js.has(t.slice(0,t.length-6))){const s=js.get(t.slice(0,t.length-6));return e.isStackNode?(...e)=>r.assign(e[0],s(...e)):(...e)=>r.assign(s(r,...e))}if(!0===/^[xyzwrgbastpq]{1,4}$/.test(t))return t=Ks(t),Ti(new Gs(r,t));if(!0===/^set[XYZWRGBASTPQ]{1,4}$/.test(t))return t=Xs(t.slice(3).toLowerCase()),r=>Ti(new ks(e,t,r));if(!0===/^flip[XYZWRGBASTPQ]{1,4}$/.test(t))return t=Xs(t.slice(4).toLowerCase()),()=>Ti(new zs(Ti(e),t));if("width"===t||"height"===t||"depth"===t)return"width"===t?t="x":"height"===t?t="y":"depth"===t&&(t="z"),Ti(new Gs(e,t));if(!0===/^\d+$/.test(t))return Ti(new Is(r,new Hs(Number(t),"uint")))}return Reflect.get(e,t,r)},set:(e,t,r,s)=>"string"!=typeof t||void 0!==e[t]||!0!==/^[xyzwrgbastpq]{1,4}$/.test(t)&&"width"!==t&&"height"!==t&&"depth"!==t&&!0!==/^\d+$/.test(t)?Reflect.set(e,t,r,s):(s[t].assign(r),!0)},Qs=new WeakMap,Zs=new WeakMap,Js=function(e,t=null){for(const r in e)e[r]=Ti(e[r],t);return e},ei=function(e,t=null){const r=e.length;for(let s=0;sTi(null!==s?Object.assign(e,s):e);return null===t?(...t)=>i(new e(...vi(t))):null!==r?(r=Ti(r),(...s)=>i(new e(t,...vi(s),r))):(...r)=>i(new e(t,...vi(r)))},ri=function(e,...t){return Ti(new e(...vi(t)))};class si extends Ps{constructor(e,t){super(),this.shaderNode=e,this.inputNodes=t}getNodeType(e){return this.shaderNode.nodeType||this.getOutputNode(e).getNodeType(e)}call(e){const{shaderNode:t,inputNodes:r}=this,s=e.getNodeProperties(t);if(s.onceOutput)return s.onceOutput;let i=null;if(t.layout){let s=Zs.get(e.constructor);void 0===s&&(s=new WeakMap,Zs.set(e.constructor,s));let n=s.get(t);void 0===n&&(n=Ti(e.buildFunctionNode(t)),s.set(t,n)),null!==e.currentFunctionNode&&e.currentFunctionNode.includes.push(n),i=Ti(n.call(r))}else{const s=t.jsFunc,n=null!==r?s(r,e):s(e);i=Ti(n)}return t.once&&(s.onceOutput=i),i}getOutputNode(e){const t=e.getNodeProperties(this);return null===t.outputNode&&(t.outputNode=this.setupOutput(e)),t.outputNode}setup(e){return this.getOutputNode(e)}setupOutput(e){return e.addStack(),e.stack.outputNode=this.call(e),e.removeStack()}generate(e,t){return this.getOutputNode(e).build(e,t)}}class ii extends Ps{constructor(e,t){super(t),this.jsFunc=e,this.layout=null,this.global=!0,this.once=!1}setLayout(e){return this.layout=e,this}call(e=null){return _i(e),Ti(new si(this,e))}setup(){return this.call()}}const ni=[!1,!0],oi=[0,1,2,3],ai=[-1,-2],ui=[.5,1.5,1/3,1e-6,1e6,Math.PI,2*Math.PI,1/Math.PI,2/Math.PI,1/(2*Math.PI),Math.PI/2],li=new Map;for(const e of ni)li.set(e,new Hs(e));const di=new Map;for(const e of oi)di.set(e,new Hs(e,"uint"));const ci=new Map([...di].map((e=>new Hs(e.value,"int"))));for(const e of ai)ci.set(e,new Hs(e,"int"));const hi=new Map([...ci].map((e=>new Hs(e.value))));for(const e of ui)hi.set(e,new Hs(e));for(const e of ui)hi.set(-e,new Hs(-e));const pi={bool:li,uint:di,ints:ci,float:hi},gi=new Map([...li,...hi]),mi=(e,t)=>gi.has(e)?gi.get(e):!0===e.isNode?e:new Hs(e,t),fi=function(e,t=null){return(...r)=>{if((0===r.length||!["bool","float","int","uint"].includes(e)&&r.every((e=>"object"!=typeof e)))&&(r=[Ts(e,...r)]),1===r.length&&null!==t&&t.has(r[0]))return Ti(t.get(r[0]));if(1===r.length){const t=mi(r[0],e);return(e=>{try{return e.getNodeType()}catch(e){return}})(t)===e?Ti(t):Ti(new Ds(t,e))}const s=r.map((e=>mi(e)));return Ti(new Vs(s,e))}},yi=e=>"object"==typeof e&&null!==e?e.value:e,bi=e=>null!=e?e.nodeType||e.convertTo||("string"==typeof e?e:null):null;function xi(e,t){return new Proxy(new ii(e,t),Ys)}const Ti=(e,t=null)=>function(e,t=null){const r=xs(e);if("node"===r){let t=Qs.get(e);return void 0===t&&(t=new Proxy(e,Ys),Qs.set(e,t),Qs.set(t,t)),t}return null===t&&("float"===r||"boolean"===r)||r&&"shader"!==r&&"string"!==r?Ti(mi(e,t)):"shader"===r?Ai(e):e}(e,t),_i=(e,t=null)=>new Js(e,t),vi=(e,t=null)=>new ei(e,t),Ni=(...e)=>new ti(...e),Si=(...e)=>new ri(...e),Ai=(e,t)=>{const r=new xi(e,t),s=(...e)=>{let t;return _i(e),t=e[0]&&e[0].isNode?[...e]:e[0],r.call(t)};return s.shaderNode=r,s.setLayout=e=>(r.setLayout(e),s),s.once=()=>(r.once=!0,s),s};qs("toGlobal",(e=>(e.global=!0,e)));const Ri=e=>{Ws=e},Ci=()=>Ws,Ei=(...e)=>Ws.If(...e);function wi(e){return Ws&&Ws.add(e),e}qs("append",wi);const Mi=new fi("color"),Bi=new fi("float",pi.float),Fi=new fi("int",pi.ints),Ui=new fi("uint",pi.uint),Pi=new fi("bool",pi.bool),Ii=new fi("vec2"),Di=new fi("ivec2"),Li=new fi("uvec2"),Vi=new fi("bvec2"),Oi=new fi("vec3"),Gi=new fi("ivec3"),ki=new fi("uvec3"),zi=new fi("bvec3"),$i=new fi("vec4"),Hi=new fi("ivec4"),Wi=new fi("uvec4"),ji=new fi("bvec4"),qi=new fi("mat2"),Ki=new fi("mat3"),Xi=new fi("mat4");qs("toColor",Mi),qs("toFloat",Bi),qs("toInt",Fi),qs("toUint",Ui),qs("toBool",Pi),qs("toVec2",Ii),qs("toIVec2",Di),qs("toUVec2",Li),qs("toBVec2",Vi),qs("toVec3",Oi),qs("toIVec3",Gi),qs("toUVec3",ki),qs("toBVec3",zi),qs("toVec4",$i),qs("toIVec4",Hi),qs("toUVec4",Wi),qs("toBVec4",ji),qs("toMat2",qi),qs("toMat3",Ki),qs("toMat4",Xi);const Yi=Ni(Is),Qi=(e,t)=>Ti(new Ds(Ti(e),t));qs("element",Yi),qs("convert",Qi);class Zi extends Ps{static get type(){return"UniformGroupNode"}constructor(e,t=!1,r=1){super("string"),this.name=e,this.shared=t,this.order=r,this.isUniformGroup=!0}serialize(e){super.serialize(e),e.name=this.name,e.version=this.version,e.shared=this.shared}deserialize(e){super.deserialize(e),this.name=e.name,this.version=e.version,this.shared=e.shared}}const Ji=e=>new Zi(e),en=(e,t=0)=>new Zi(e,!0,t),tn=en("frame"),rn=en("render"),sn=Ji("object");class nn extends $s{static get type(){return"UniformNode"}constructor(e,t=null){super(e,t),this.isUniformNode=!0,this.name="",this.groupNode=sn}label(e){return this.name=e,this}setGroup(e){return this.groupNode=e,this}getGroup(){return this.groupNode}getUniformHash(e){return this.getHash(e)}onUpdate(e,t){const r=this.getSelf();return e=e.bind(r),super.onUpdate((t=>{const s=e(t,r);void 0!==s&&(this.value=s)}),t)}generate(e,t){const r=this.getNodeType(e),s=this.getUniformHash(e);let i=e.getNodeFromHash(s);void 0===i&&(e.setHashNode(this,s),i=this);const n=i.getInputType(e),o=e.getUniformFromNode(i,n,e.shaderStage,this.name||e.context.label),a=e.getPropertyName(o);return void 0!==e.context.label&&delete e.context.label,e.format(a,r,t)}}const on=(e,t)=>{const r=bi(t||e),s=e&&!0===e.isNode?e.node&&e.node.value||e.value:e;return Ti(new nn(s,r))};class an extends Ps{static get type(){return"PropertyNode"}constructor(e,t=null,r=!1){super(e),this.name=t,this.varying=r,this.isPropertyNode=!0}getHash(e){return this.name||super.getHash(e)}isGlobal(){return!0}generate(e){let t;return!0===this.varying?(t=e.getVaryingFromNode(this,this.name),t.needsInterpolation=!0):t=e.getVarFromNode(this,this.name),e.getPropertyName(t)}}const un=(e,t)=>Ti(new an(e,t)),ln=(e,t)=>Ti(new an(e,t,!0)),dn=Si(an,"vec4","DiffuseColor"),cn=Si(an,"vec3","EmissiveColor"),hn=Si(an,"float","Roughness"),pn=Si(an,"float","Metalness"),gn=Si(an,"float","Clearcoat"),mn=Si(an,"float","ClearcoatRoughness"),fn=Si(an,"vec3","Sheen"),yn=Si(an,"float","SheenRoughness"),bn=Si(an,"float","Iridescence"),xn=Si(an,"float","IridescenceIOR"),Tn=Si(an,"float","IridescenceThickness"),_n=Si(an,"float","AlphaT"),vn=Si(an,"float","Anisotropy"),Nn=Si(an,"vec3","AnisotropyT"),Sn=Si(an,"vec3","AnisotropyB"),An=Si(an,"color","SpecularColor"),Rn=Si(an,"float","SpecularF90"),Cn=Si(an,"float","Shininess"),En=Si(an,"vec4","Output"),wn=Si(an,"float","dashSize"),Mn=Si(an,"float","gapSize"),Bn=Si(an,"float","pointWidth"),Fn=Si(an,"float","IOR"),Un=Si(an,"float","Transmission"),Pn=Si(an,"float","Thickness"),In=Si(an,"float","AttenuationDistance"),Dn=Si(an,"color","AttenuationColor"),Ln=Si(an,"float","Dispersion");class Vn extends Ls{static get type(){return"AssignNode"}constructor(e,t){super(),this.targetNode=e,this.sourceNode=t}hasDependencies(){return!1}getNodeType(e,t){return"void"!==t?this.targetNode.getNodeType(e):"void"}needsSplitAssign(e){const{targetNode:t}=this;if(!1===e.isAvailable("swizzleAssign")&&t.isSplitNode&&t.components.length>1){const r=e.getTypeLength(t.node.getNodeType(e));return Fs.join("").slice(0,r)!==t.components}return!1}generate(e,t){const{targetNode:r,sourceNode:s}=this,i=this.needsSplitAssign(e),n=r.getNodeType(e),o=r.context({assign:!0}).build(e),a=s.build(e,n),u=s.getNodeType(e),l=e.getDataFromNode(this);let d;if(!0===l.initialized)"void"!==t&&(d=o);else if(i){const s=e.getVarFromNode(this,null,n),i=e.getPropertyName(s);e.addLineFlowCode(`${i} = ${a}`,this);const u=r.node.context({assign:!0}).build(e);for(let t=0;t{const s=r.type;let i;return i="pointer"===s?"&"+t.build(e):t.build(e,s),i};if(Array.isArray(i))for(let e=0;e(t=t.length>1||t[0]&&!0===t[0].isNode?vi(t):_i(t[0]),Ti(new Gn(Ti(e),t)));qs("call",kn);class zn extends Ls{static get type(){return"OperatorNode"}constructor(e,t,r,...s){if(super(),s.length>0){let i=new zn(e,t,r);for(let t=0;t>"===r||"<<"===r)return e.getIntegerType(n);if("!"===r||"=="===r||"&&"===r||"||"===r||"^^"===r)return"bool";if("<"===r||">"===r||"<="===r||">="===r){const r=t?e.getTypeLength(t):Math.max(e.getTypeLength(n),e.getTypeLength(o));return r>1?`bvec${r}`:"bool"}return"float"===n&&e.isMatrix(o)?o:e.isMatrix(n)&&e.isVector(o)?e.getVectorFromMatrix(n):e.isVector(n)&&e.isMatrix(o)?e.getVectorFromMatrix(o):e.getTypeLength(o)>e.getTypeLength(n)?o:n}generate(e,t){const r=this.op,s=this.aNode,i=this.bNode,n=this.getNodeType(e,t);let o=null,a=null;"void"!==n?(o=s.getNodeType(e),a=void 0!==i?i.getNodeType(e):null,"<"===r||">"===r||"<="===r||">="===r||"=="===r?e.isVector(o)?a=o:o!==a&&(o=a="float"):">>"===r||"<<"===r?(o=n,a=e.changeComponentType(a,"uint")):e.isMatrix(o)&&e.isVector(a)?a=e.getVectorFromMatrix(o):o=e.isVector(o)&&e.isMatrix(a)?e.getVectorFromMatrix(a):a=n):o=a=n;const u=s.build(e,o),l=void 0!==i?i.build(e,a):null,d=e.getTypeLength(t),c=e.getFunctionOperator(r);return"void"!==t?"<"===r&&d>1?e.useComparisonMethod?e.format(`${e.getMethod("lessThan",t)}( ${u}, ${l} )`,n,t):e.format(`( ${u} < ${l} )`,n,t):"<="===r&&d>1?e.useComparisonMethod?e.format(`${e.getMethod("lessThanEqual",t)}( ${u}, ${l} )`,n,t):e.format(`( ${u} <= ${l} )`,n,t):">"===r&&d>1?e.useComparisonMethod?e.format(`${e.getMethod("greaterThan",t)}( ${u}, ${l} )`,n,t):e.format(`( ${u} > ${l} )`,n,t):">="===r&&d>1?e.useComparisonMethod?e.format(`${e.getMethod("greaterThanEqual",t)}( ${u}, ${l} )`,n,t):e.format(`( ${u} >= ${l} )`,n,t):"!"===r||"~"===r?e.format(`(${r}${u})`,o,t):c?e.format(`${c}( ${u}, ${l} )`,n,t):e.format(`( ${u} ${r} ${l} )`,n,t):"void"!==o?c?e.format(`${c}( ${u}, ${l} )`,n,t):e.format(`${u} ${r} ${l}`,n,t):void 0}serialize(e){super.serialize(e),e.op=this.op}deserialize(e){super.deserialize(e),this.op=e.op}}const $n=Ni(zn,"+"),Hn=Ni(zn,"-"),Wn=Ni(zn,"*"),jn=Ni(zn,"/"),qn=Ni(zn,"%"),Kn=Ni(zn,"=="),Xn=Ni(zn,"!="),Yn=Ni(zn,"<"),Qn=Ni(zn,">"),Zn=Ni(zn,"<="),Jn=Ni(zn,">="),eo=Ni(zn,"&&"),to=Ni(zn,"||"),ro=Ni(zn,"!"),so=Ni(zn,"^^"),io=Ni(zn,"&"),no=Ni(zn,"~"),oo=Ni(zn,"|"),ao=Ni(zn,"^"),uo=Ni(zn,"<<"),lo=Ni(zn,">>");qs("add",$n),qs("sub",Hn),qs("mul",Wn),qs("div",jn),qs("modInt",qn),qs("equal",Kn),qs("notEqual",Xn),qs("lessThan",Yn),qs("greaterThan",Qn),qs("lessThanEqual",Zn),qs("greaterThanEqual",Jn),qs("and",eo),qs("or",to),qs("not",ro),qs("xor",so),qs("bitAnd",io),qs("bitNot",no),qs("bitOr",oo),qs("bitXor",ao),qs("shiftLeft",uo),qs("shiftRight",lo);const co=(...e)=>(console.warn("TSL.OperatorNode: .remainder() has been renamed to .modInt()."),qn(...e));qs("remainder",co);class ho extends Ls{static get type(){return"MathNode"}constructor(e,t,r=null,s=null){super(),this.method=e,this.aNode=t,this.bNode=r,this.cNode=s}getInputType(e){const t=this.aNode.getNodeType(e),r=this.bNode?this.bNode.getNodeType(e):null,s=this.cNode?this.cNode.getNodeType(e):null,i=e.isMatrix(t)?0:e.getTypeLength(t),n=e.isMatrix(r)?0:e.getTypeLength(r),o=e.isMatrix(s)?0:e.getTypeLength(s);return i>n&&i>o?t:n>o?r:o>i?s:t}getNodeType(e){const t=this.method;return t===ho.LENGTH||t===ho.DISTANCE||t===ho.DOT?"float":t===ho.CROSS?"vec3":t===ho.ALL?"bool":t===ho.EQUALS?e.changeComponentType(this.aNode.getNodeType(e),"bool"):t===ho.MOD?this.aNode.getNodeType(e):this.getInputType(e)}generate(e,t){let r=this.method;const s=this.getNodeType(e),i=this.getInputType(e),n=this.aNode,o=this.bNode,a=this.cNode,d=e.renderer.coordinateSystem;if(r===ho.TRANSFORM_DIRECTION){let r=n,s=o;e.isMatrix(r.getNodeType(e))?s=$i(Oi(s),0):r=$i(Oi(r),0);const i=Wn(r,s).xyz;return wo(i).build(e,t)}if(r===ho.NEGATE)return e.format("( - "+n.build(e,i)+" )",s,t);if(r===ho.ONE_MINUS)return Hn(1,n).build(e,t);if(r===ho.RECIPROCAL)return jn(1,n).build(e,t);if(r===ho.DIFFERENCE)return Lo(Hn(n,o)).build(e,t);{const c=[];return r===ho.CROSS||r===ho.MOD?c.push(n.build(e,s),o.build(e,s)):d===u&&r===ho.STEP?c.push(n.build(e,1===e.getTypeLength(n.getNodeType(e))?"float":i),o.build(e,i)):d===u&&(r===ho.MIN||r===ho.MAX)||r===ho.MOD?c.push(n.build(e,i),o.build(e,1===e.getTypeLength(o.getNodeType(e))?"float":i)):r===ho.REFRACT?c.push(n.build(e,i),o.build(e,i),a.build(e,"float")):r===ho.MIX?c.push(n.build(e,i),o.build(e,i),a.build(e,1===e.getTypeLength(a.getNodeType(e))?"float":i)):(d===l&&r===ho.ATAN&&null!==o&&(r="atan2"),c.push(n.build(e,i)),null!==o&&c.push(o.build(e,i)),null!==a&&c.push(a.build(e,i))),e.format(`${e.getMethod(r,s)}( ${c.join(", ")} )`,s,t)}}serialize(e){super.serialize(e),e.method=this.method}deserialize(e){super.deserialize(e),this.method=e.method}}ho.ALL="all",ho.ANY="any",ho.RADIANS="radians",ho.DEGREES="degrees",ho.EXP="exp",ho.EXP2="exp2",ho.LOG="log",ho.LOG2="log2",ho.SQRT="sqrt",ho.INVERSE_SQRT="inversesqrt",ho.FLOOR="floor",ho.CEIL="ceil",ho.NORMALIZE="normalize",ho.FRACT="fract",ho.SIN="sin",ho.COS="cos",ho.TAN="tan",ho.ASIN="asin",ho.ACOS="acos",ho.ATAN="atan",ho.ABS="abs",ho.SIGN="sign",ho.LENGTH="length",ho.NEGATE="negate",ho.ONE_MINUS="oneMinus",ho.DFDX="dFdx",ho.DFDY="dFdy",ho.ROUND="round",ho.RECIPROCAL="reciprocal",ho.TRUNC="trunc",ho.FWIDTH="fwidth",ho.TRANSPOSE="transpose",ho.BITCAST="bitcast",ho.EQUALS="equals",ho.MIN="min",ho.MAX="max",ho.MOD="mod",ho.STEP="step",ho.REFLECT="reflect",ho.DISTANCE="distance",ho.DIFFERENCE="difference",ho.DOT="dot",ho.CROSS="cross",ho.POW="pow",ho.TRANSFORM_DIRECTION="transformDirection",ho.MIX="mix",ho.CLAMP="clamp",ho.REFRACT="refract",ho.SMOOTHSTEP="smoothstep",ho.FACEFORWARD="faceforward";const po=Bi(1e-6),go=Bi(1e6),mo=Bi(Math.PI),fo=Bi(2*Math.PI),yo=Ni(ho,ho.ALL),bo=Ni(ho,ho.ANY),xo=Ni(ho,ho.RADIANS),To=Ni(ho,ho.DEGREES),_o=Ni(ho,ho.EXP),vo=Ni(ho,ho.EXP2),No=Ni(ho,ho.LOG),So=Ni(ho,ho.LOG2),Ao=Ni(ho,ho.SQRT),Ro=Ni(ho,ho.INVERSE_SQRT),Co=Ni(ho,ho.FLOOR),Eo=Ni(ho,ho.CEIL),wo=Ni(ho,ho.NORMALIZE),Mo=Ni(ho,ho.FRACT),Bo=Ni(ho,ho.SIN),Fo=Ni(ho,ho.COS),Uo=Ni(ho,ho.TAN),Po=Ni(ho,ho.ASIN),Io=Ni(ho,ho.ACOS),Do=Ni(ho,ho.ATAN),Lo=Ni(ho,ho.ABS),Vo=Ni(ho,ho.SIGN),Oo=Ni(ho,ho.LENGTH),Go=Ni(ho,ho.NEGATE),ko=Ni(ho,ho.ONE_MINUS),zo=Ni(ho,ho.DFDX),$o=Ni(ho,ho.DFDY),Ho=Ni(ho,ho.ROUND),Wo=Ni(ho,ho.RECIPROCAL),jo=Ni(ho,ho.TRUNC),qo=Ni(ho,ho.FWIDTH),Ko=Ni(ho,ho.TRANSPOSE),Xo=Ni(ho,ho.BITCAST),Yo=Ni(ho,ho.EQUALS),Qo=Ni(ho,ho.MIN),Zo=Ni(ho,ho.MAX),Jo=Ni(ho,ho.MOD),ea=Ni(ho,ho.STEP),ta=Ni(ho,ho.REFLECT),ra=Ni(ho,ho.DISTANCE),sa=Ni(ho,ho.DIFFERENCE),ia=Ni(ho,ho.DOT),na=Ni(ho,ho.CROSS),oa=Ni(ho,ho.POW),aa=Ni(ho,ho.POW,2),ua=Ni(ho,ho.POW,3),la=Ni(ho,ho.POW,4),da=Ni(ho,ho.TRANSFORM_DIRECTION),ca=e=>Wn(Vo(e),oa(Lo(e),1/3)),ha=e=>ia(e,e),pa=Ni(ho,ho.MIX),ga=(e,t=0,r=1)=>Ti(new ho(ho.CLAMP,Ti(e),Ti(t),Ti(r))),ma=e=>ga(e),fa=Ni(ho,ho.REFRACT),ya=Ni(ho,ho.SMOOTHSTEP),ba=Ni(ho,ho.FACEFORWARD),xa=Ai((([e])=>{const t=ia(e.xy,Ii(12.9898,78.233)),r=Jo(t,mo);return Mo(Bo(r).mul(43758.5453))})),Ta=(e,t,r)=>pa(t,r,e),_a=(e,t,r)=>ya(t,r,e),va=(e,t)=>(console.warn('THREE.TSL: "atan2" is overloaded. Use "atan" instead.'),Do(e,t)),Na=ba,Sa=Ro;qs("all",yo),qs("any",bo),qs("equals",Yo),qs("radians",xo),qs("degrees",To),qs("exp",_o),qs("exp2",vo),qs("log",No),qs("log2",So),qs("sqrt",Ao),qs("inverseSqrt",Ro),qs("floor",Co),qs("ceil",Eo),qs("normalize",wo),qs("fract",Mo),qs("sin",Bo),qs("cos",Fo),qs("tan",Uo),qs("asin",Po),qs("acos",Io),qs("atan",Do),qs("abs",Lo),qs("sign",Vo),qs("length",Oo),qs("lengthSq",ha),qs("negate",Go),qs("oneMinus",ko),qs("dFdx",zo),qs("dFdy",$o),qs("round",Ho),qs("reciprocal",Wo),qs("trunc",jo),qs("fwidth",qo),qs("atan2",va),qs("min",Qo),qs("max",Zo),qs("mod",Jo),qs("step",ea),qs("reflect",ta),qs("distance",ra),qs("dot",ia),qs("cross",na),qs("pow",oa),qs("pow2",aa),qs("pow3",ua),qs("pow4",la),qs("transformDirection",da),qs("mix",Ta),qs("clamp",ga),qs("refract",fa),qs("smoothstep",_a),qs("faceForward",ba),qs("difference",sa),qs("saturate",ma),qs("cbrt",ca),qs("transpose",Ko),qs("rand",xa);class Aa extends Ps{static get type(){return"ConditionalNode"}constructor(e,t,r=null){super(),this.condNode=e,this.ifNode=t,this.elseNode=r}getNodeType(e){const{ifNode:t,elseNode:r}=e.getNodeProperties(this);if(void 0===t)return this.setup(e),this.getNodeType(e);const s=t.getNodeType(e);if(null!==r){const t=r.getNodeType(e);if(e.getTypeLength(t)>e.getTypeLength(s))return t}return s}setup(e){const t=this.condNode.cache(),r=this.ifNode.cache(),s=this.elseNode?this.elseNode.cache():null,i=e.context.nodeBlock;e.getDataFromNode(r).parentNodeBlock=i,null!==s&&(e.getDataFromNode(s).parentNodeBlock=i);const n=e.getNodeProperties(this);n.condNode=t,n.ifNode=r.context({nodeBlock:r}),n.elseNode=s?s.context({nodeBlock:s}):null}generate(e,t){const r=this.getNodeType(e),s=e.getDataFromNode(this);if(void 0!==s.nodeProperty)return s.nodeProperty;const{condNode:i,ifNode:n,elseNode:o}=e.getNodeProperties(this),a="void"!==t,u=a?un(r).build(e):"";s.nodeProperty=u;const l=i.build(e,"bool");e.addFlowCode(`\n${e.tab}if ( ${l} ) {\n\n`).addFlowTab();let d=n.build(e,r);if(d&&(d=a?u+" = "+d+";":"return "+d+";"),e.removeFlowTab().addFlowCode(e.tab+"\t"+d+"\n\n"+e.tab+"}"),null!==o){e.addFlowCode(" else {\n\n").addFlowTab();let t=o.build(e,r);t&&(t=a?u+" = "+t+";":"return "+t+";"),e.removeFlowTab().addFlowCode(e.tab+"\t"+t+"\n\n"+e.tab+"}\n\n")}else e.addFlowCode("\n\n");return e.format(u,r,t)}}const Ra=Ni(Aa);qs("select",Ra);const Ca=(...e)=>(console.warn("TSL.ConditionalNode: cond() has been renamed to select()."),Ra(...e));qs("cond",Ca);class Ea extends Ps{static get type(){return"ContextNode"}constructor(e,t={}){super(),this.isContextNode=!0,this.node=e,this.value=t}getScope(){return this.node.getScope()}getNodeType(e){return this.node.getNodeType(e)}analyze(e){this.node.build(e)}setup(e){const t=e.getContext();e.setContext({...e.context,...this.value});const r=this.node.build(e);return e.setContext(t),r}generate(e,t){const r=e.getContext();e.setContext({...e.context,...this.value});const s=this.node.build(e,t);return e.setContext(r),s}}const wa=Ni(Ea),Ma=(e,t)=>wa(e,{label:t});qs("context",wa),qs("label",Ma);class Ba extends Ps{static get type(){return"VarNode"}constructor(e,t=null){super(),this.node=e,this.name=t,this.global=!0,this.isVarNode=!0}getHash(e){return this.name||super.getHash(e)}getNodeType(e){return this.node.getNodeType(e)}generate(e){const{node:t,name:r}=this,s=e.getVarFromNode(this,r,e.getVectorType(this.getNodeType(e))),i=e.getPropertyName(s),n=t.build(e,s.type);return e.addLineFlowCode(`${i} = ${n}`,this),i}}const Fa=Ni(Ba);qs("toVar",((...e)=>Fa(...e).append()));const Ua=e=>(console.warn('TSL: "temp" is deprecated. Use ".toVar()" instead.'),Fa(e));qs("temp",Ua);class Pa extends Ps{static get type(){return"VaryingNode"}constructor(e,t=null){super(),this.node=e,this.name=t,this.isVaryingNode=!0}isGlobal(){return!0}getHash(e){return this.name||super.getHash(e)}getNodeType(e){return this.node.getNodeType(e)}setupVarying(e){const t=e.getNodeProperties(this);let r=t.varying;if(void 0===r){const s=this.name,i=this.getNodeType(e);t.varying=r=e.getVaryingFromNode(this,s,i),t.node=this.node}return r.needsInterpolation||(r.needsInterpolation="fragment"===e.shaderStage),r}setup(e){this.setupVarying(e)}analyze(e){return this.setupVarying(e),this.node.analyze(e)}generate(e){const t=e.getNodeProperties(this),r=this.setupVarying(e),s="fragment"===e.shaderStage&&!0===t.reassignPosition&&e.context.needsPositionReassign;if(void 0===t.propertyName||s){const i=this.getNodeType(e),n=e.getPropertyName(r,As.VERTEX);e.flowNodeFromShaderStage(As.VERTEX,this.node,i,n),t.propertyName=n,s?t.reassignPosition=!1:void 0===t.reassignPosition&&e.context.isPositionNodeInput&&(t.reassignPosition=!0)}return e.getPropertyName(r)}}const Ia=Ni(Pa),Da=e=>Ia(e);qs("varying",Ia),qs("vertexStage",Da);const La=Ai((([e])=>{const t=e.mul(.9478672986).add(.0521327014).pow(2.4),r=e.mul(.0773993808),s=e.lessThanEqual(.04045);return pa(t,r,s)})).setLayout({name:"sRGBTransferEOTF",type:"vec3",inputs:[{name:"color",type:"vec3"}]}),Va=Ai((([e])=>{const t=e.pow(.41666).mul(1.055).sub(.055),r=e.mul(12.92),s=e.lessThanEqual(.0031308);return pa(t,r,s)})).setLayout({name:"sRGBTransferOETF",type:"vec3",inputs:[{name:"color",type:"vec3"}]}),Oa="WorkingColorSpace",Ga="OutputColorSpace";class ka extends Ls{static get type(){return"ColorSpaceNode"}constructor(e,t,r){super("vec4"),this.colorNode=e,this.source=t,this.target=r}resolveColorSpace(e,t){return t===Oa?d.workingColorSpace:t===Ga?e.context.outputColorSpace||e.renderer.outputColorSpace:t}setup(e){const{colorNode:t}=this,r=this.resolveColorSpace(e,this.source),s=this.resolveColorSpace(e,this.target);let n=t;return!1!==d.enabled&&r!==s&&r&&s?(d.getTransfer(r)===c&&(n=$i(La(n.rgb),n.a)),d.getPrimaries(r)!==d.getPrimaries(s)&&(n=$i(Ki(d._getMatrix(new i,r,s)).mul(n.rgb),n.a)),d.getTransfer(s)===c&&(n=$i(Va(n.rgb),n.a)),n):n}}const za=e=>Ti(new ka(Ti(e),Oa,Ga)),$a=e=>Ti(new ka(Ti(e),Ga,Oa)),Ha=(e,t)=>Ti(new ka(Ti(e),Oa,t)),Wa=(e,t)=>Ti(new ka(Ti(e),t,Oa));qs("toOutputColorSpace",za),qs("toWorkingColorSpace",$a),qs("workingToColorSpace",Ha),qs("colorSpaceToWorking",Wa);let ja=class extends Is{static get type(){return"ReferenceElementNode"}constructor(e,t){super(e,t),this.referenceNode=e,this.isReferenceElementNode=!0}getNodeType(){return this.referenceNode.uniformType}generate(e){const t=super.generate(e),r=this.referenceNode.getNodeType(),s=this.getNodeType();return e.format(t,r,s)}};class qa extends Ps{static get type(){return"ReferenceBaseNode"}constructor(e,t,r=null,s=null){super(),this.property=e,this.uniformType=t,this.object=r,this.count=s,this.properties=e.split("."),this.reference=r,this.node=null,this.group=null,this.updateType=Rs.OBJECT}setGroup(e){return this.group=e,this}element(e){return Ti(new ja(this,Ti(e)))}setNodeType(e){const t=on(null,e).getSelf();null!==this.group&&t.setGroup(this.group),this.node=t}getNodeType(e){return null===this.node&&(this.updateReference(e),this.updateValue()),this.node.getNodeType(e)}getValueFromReference(e=this.reference){const{properties:t}=this;let r=e[t[0]];for(let e=1;eTi(new Ka(e,t,r));class Ya extends Ls{static get type(){return"ToneMappingNode"}constructor(e,t=Za,r=null){super("vec3"),this.toneMapping=e,this.exposureNode=t,this.colorNode=r}customCacheKey(){return cs(this.toneMapping)}setup(e){const t=this.colorNode||e.context.color,r=this.toneMapping;if(r===h)return t;let s=null;const i=e.renderer.library.getToneMappingFunction(r);return null!==i?s=$i(i(t.rgb,this.exposureNode),t.a):(console.error("ToneMappingNode: Unsupported Tone Mapping configuration.",r),s=t),s}}const Qa=(e,t,r)=>Ti(new Ya(e,Ti(t),Ti(r))),Za=Xa("toneMappingExposure","float");qs("toneMapping",((e,t,r)=>Qa(t,r,e)));class Ja extends $s{static get type(){return"BufferAttributeNode"}constructor(e,t=null,r=0,s=0){super(e,t),this.isBufferNode=!0,this.bufferType=t,this.bufferStride=r,this.bufferOffset=s,this.usage=p,this.instanced=!1,this.attribute=null,this.global=!0,e&&!0===e.isBufferAttribute&&(this.attribute=e,this.usage=e.usage,this.instanced=e.isInstancedBufferAttribute)}getHash(e){if(0===this.bufferStride&&0===this.bufferOffset){let t=e.globalCache.getData(this.value);return void 0===t&&(t={node:this},e.globalCache.setData(this.value,t)),t.node.uuid}return this.uuid}getNodeType(e){return null===this.bufferType&&(this.bufferType=e.getTypeFromAttribute(this.attribute)),this.bufferType}setup(e){if(null!==this.attribute)return;const t=this.getNodeType(e),r=this.value,s=e.getTypeLength(t),i=this.bufferStride||s,n=this.bufferOffset,o=!0===r.isInterleavedBuffer?r:new g(r,i),a=new f(o,s,n);o.setUsage(this.usage),this.attribute=a,this.attribute.isInstancedBufferAttribute=this.instanced}generate(e){const t=this.getNodeType(e),r=e.getBufferAttributeFromNode(this,t),s=e.getPropertyName(r);let i=null;if("vertex"===e.shaderStage||"compute"===e.shaderStage)this.name=s,i=s;else{i=Ia(this).build(e,t)}return i}getInputType(){return"bufferAttribute"}setUsage(e){return this.usage=e,this.attribute&&!0===this.attribute.isBufferAttribute&&(this.attribute.usage=e),this}setInstanced(e){return this.instanced=e,this}}const eu=(e,t=null,r=0,s=0)=>Ti(new Ja(e,t,r,s)),tu=(e,t=null,r=0,s=0)=>eu(e,t,r,s).setUsage(m),ru=(e,t=null,r=0,s=0)=>eu(e,t,r,s).setInstanced(!0),su=(e,t=null,r=0,s=0)=>tu(e,t,r,s).setInstanced(!0);qs("toAttribute",(e=>eu(e.value)));class iu extends Ps{static get type(){return"ComputeNode"}constructor(e,t,r=[64]){super("void"),this.isComputeNode=!0,this.computeNode=e,this.count=t,this.workgroupSize=r,this.dispatchCount=0,this.version=1,this.name="",this.updateBeforeType=Rs.OBJECT,this.onInitFunction=null,this.updateDispatchCount()}dispose(){this.dispatchEvent({type:"dispose"})}label(e){return this.name=e,this}updateDispatchCount(){const{count:e,workgroupSize:t}=this;let r=t[0];for(let e=1;eTi(new iu(Ti(e),t,r));qs("compute",nu);class ou extends Ps{static get type(){return"CacheNode"}constructor(e,t=!0){super(),this.node=e,this.parent=t,this.isCacheNode=!0}getNodeType(e){const t=e.getCache(),r=e.getCacheFromNode(this,this.parent);e.setCache(r);const s=this.node.getNodeType(e);return e.setCache(t),s}build(e,...t){const r=e.getCache(),s=e.getCacheFromNode(this,this.parent);e.setCache(s);const i=this.node.build(e,...t);return e.setCache(r),i}}const au=(e,t)=>Ti(new ou(Ti(e),t));qs("cache",au);class uu extends Ps{static get type(){return"BypassNode"}constructor(e,t){super(),this.isBypassNode=!0,this.outputNode=e,this.callNode=t}getNodeType(e){return this.outputNode.getNodeType(e)}generate(e){const t=this.callNode.build(e,"void");return""!==t&&e.addLineFlowCode(t,this),this.outputNode.build(e)}}const lu=Ni(uu);qs("bypass",lu);class du extends Ps{static get type(){return"RemapNode"}constructor(e,t,r,s=Bi(0),i=Bi(1)){super(),this.node=e,this.inLowNode=t,this.inHighNode=r,this.outLowNode=s,this.outHighNode=i,this.doClamp=!0}setup(){const{node:e,inLowNode:t,inHighNode:r,outLowNode:s,outHighNode:i,doClamp:n}=this;let o=e.sub(t).div(r.sub(t));return!0===n&&(o=o.clamp()),o.mul(i.sub(s)).add(s)}}const cu=Ni(du,null,null,{doClamp:!1}),hu=Ni(du);qs("remap",cu),qs("remapClamp",hu);class pu extends Ps{static get type(){return"ExpressionNode"}constructor(e="",t="void"){super(t),this.snippet=e}generate(e,t){const r=this.getNodeType(e),s=this.snippet;if("void"!==r)return e.format(`( ${s} )`,r,t);e.addLineFlowCode(s,this)}}const gu=Ni(pu),mu=e=>(e?Ra(e,gu("discard")):gu("discard")).append();qs("discard",mu);class fu extends Ls{static get type(){return"RenderOutputNode"}constructor(e,t,r){super("vec4"),this.colorNode=e,this.toneMapping=t,this.outputColorSpace=r,this.isRenderOutputNode=!0}setup({context:e}){let t=this.colorNode||e.color;const r=(null!==this.toneMapping?this.toneMapping:e.toneMapping)||h,s=(null!==this.outputColorSpace?this.outputColorSpace:e.outputColorSpace)||y;return r!==h&&(t=t.toneMapping(r)),s!==y&&s!==d.workingColorSpace&&(t=t.workingToColorSpace(s)),t}}const yu=(e,t=null,r=null)=>Ti(new fu(Ti(e),t,r));qs("renderOutput",yu);class bu extends Ps{static get type(){return"AttributeNode"}constructor(e,t=null){super(t),this.global=!0,this._attributeName=e}getHash(e){return this.getAttributeName(e)}getNodeType(e){let t=this.nodeType;if(null===t){const r=this.getAttributeName(e);if(e.hasGeometryAttribute(r)){const s=e.geometry.getAttribute(r);t=e.getTypeFromAttribute(s)}else t="float"}return t}setAttributeName(e){return this._attributeName=e,this}getAttributeName(){return this._attributeName}generate(e){const t=this.getAttributeName(e),r=this.getNodeType(e);if(!0===e.hasGeometryAttribute(t)){const s=e.geometry.getAttribute(t),i=e.getTypeFromAttribute(s),n=e.getAttribute(t,i);if("vertex"===e.shaderStage)return e.format(n.name,i,r);return Ia(this).build(e,r)}return console.warn(`AttributeNode: Vertex attribute "${t}" not found on geometry.`),e.generateConst(r)}serialize(e){super.serialize(e),e.global=this.global,e._attributeName=this._attributeName}deserialize(e){super.deserialize(e),this.global=e.global,this._attributeName=e._attributeName}}const xu=(e,t)=>Ti(new bu(e,t)),Tu=(e=0)=>xu("uv"+(e>0?e:""),"vec2");class _u extends Ps{static get type(){return"TextureSizeNode"}constructor(e,t=null){super("uvec2"),this.isTextureSizeNode=!0,this.textureNode=e,this.levelNode=t}generate(e,t){const r=this.textureNode.build(e,"property"),s=null===this.levelNode?"0":this.levelNode.build(e,"int");return e.format(`${e.getMethod("textureDimensions")}( ${r}, ${s} )`,this.getNodeType(e),t)}}const vu=Ni(_u);class Nu extends nn{static get type(){return"MaxMipLevelNode"}constructor(e){super(0),this._textureNode=e,this.updateType=Rs.FRAME}get textureNode(){return this._textureNode}get texture(){return this._textureNode.value}update(){const e=this.texture,t=e.images,r=t&&t.length>0?t[0]&&t[0].image||t[0]:e.image;if(r&&void 0!==r.width){const{width:e,height:t}=r;this.value=Math.log2(Math.max(e,t))}}}const Su=Ni(Nu);class Au extends nn{static get type(){return"TextureNode"}constructor(e,t=null,r=null,s=null){super(e),this.isTextureNode=!0,this.uvNode=t,this.levelNode=r,this.biasNode=s,this.compareNode=null,this.depthNode=null,this.gradNode=null,this.sampler=!0,this.updateMatrix=!1,this.updateType=Rs.NONE,this.referenceNode=null,this._value=e,this._matrixUniform=null,this.setUpdateMatrix(null===t)}set value(e){this.referenceNode?this.referenceNode.value=e:this._value=e}get value(){return this.referenceNode?this.referenceNode.value:this._value}getUniformHash(){return this.value.uuid}getNodeType(){return!0===this.value.isDepthTexture?"float":this.value.type===b?"uvec4":this.value.type===x?"ivec4":"vec4"}getInputType(){return"texture"}getDefaultUV(){return Tu(this.value.channel)}updateReference(){return this.value}getTransformedUV(e){return null===this._matrixUniform&&(this._matrixUniform=on(this.value.matrix)),this._matrixUniform.mul(Oi(e,1)).xy}setUpdateMatrix(e){return this.updateMatrix=e,this.updateType=e?Rs.RENDER:Rs.NONE,this}setupUV(e,t){const r=this.value;return e.isFlipY()&&(r.image instanceof ImageBitmap&&!0===r.flipY||!0===r.isRenderTargetTexture||!0===r.isFramebufferTexture||!0===r.isDepthTexture)&&(t=this.sampler?t.flipY():t.setY(Fi(vu(this,this.levelNode).y).sub(t.y).sub(1))),t}setup(e){const t=e.getNodeProperties(this);t.referenceNode=this.referenceNode;const r=this.value;if(!r||!0!==r.isTexture)throw new Error("THREE.TSL: `texture( value )` function expects a valid instance of THREE.Texture().");let s=this.uvNode;null!==s&&!0!==e.context.forceUVContext||!e.context.getUV||(s=e.context.getUV(this)),s||(s=this.getDefaultUV()),!0===this.updateMatrix&&(s=this.getTransformedUV(s)),s=this.setupUV(e,s);let i=this.levelNode;null===i&&e.context.getTextureLevel&&(i=e.context.getTextureLevel(this)),t.uvNode=s,t.levelNode=i,t.biasNode=this.biasNode,t.compareNode=this.compareNode,t.gradNode=this.gradNode,t.depthNode=this.depthNode}generateUV(e,t){return t.build(e,!0===this.sampler?"vec2":"ivec2")}generateSnippet(e,t,r,s,i,n,o,a){const u=this.value;let l;return l=s?e.generateTextureLevel(u,t,r,s,n):i?e.generateTextureBias(u,t,r,i,n):a?e.generateTextureGrad(u,t,r,a,n):o?e.generateTextureCompare(u,t,r,o,n):!1===this.sampler?e.generateTextureLoad(u,t,r,n):e.generateTexture(u,t,r,n),l}generate(e,t){const r=this.value,s=e.getNodeProperties(this),i=super.generate(e,"property");if("sampler"===t)return i+"_sampler";if(e.isReference(t))return i;{const n=e.getDataFromNode(this);let o=n.propertyName;if(void 0===o){const{uvNode:t,levelNode:r,biasNode:a,compareNode:u,depthNode:l,gradNode:d}=s,c=this.generateUV(e,t),h=r?r.build(e,"float"):null,p=a?a.build(e,"float"):null,g=l?l.build(e,"int"):null,m=u?u.build(e,"float"):null,f=d?[d[0].build(e,"vec2"),d[1].build(e,"vec2")]:null,y=e.getVarFromNode(this);o=e.getPropertyName(y);const b=this.generateSnippet(e,i,c,h,p,g,m,f);e.addLineFlowCode(`${o} = ${b}`,this),n.snippet=b,n.propertyName=o}let a=o;const u=this.getNodeType(e);return e.needsToWorkingColorSpace(r)&&(a=Wa(gu(a,u),r.colorSpace).setup(e).build(e,u)),e.format(a,u,t)}}setSampler(e){return this.sampler=e,this}getSampler(){return this.sampler}uv(e){return console.warn("THREE.TextureNode: .uv() has been renamed. Use .sample() instead."),this.sample(e)}sample(e){const t=this.clone();return t.uvNode=Ti(e),t.referenceNode=this.getSelf(),Ti(t)}blur(e){const t=this.clone();return t.biasNode=Ti(e).mul(Su(t)),t.referenceNode=this.getSelf(),Ti(t)}level(e){const t=this.clone();return t.levelNode=Ti(e),t.referenceNode=this.getSelf(),Ti(t)}size(e){return vu(this,e)}bias(e){const t=this.clone();return t.biasNode=Ti(e),t.referenceNode=this.getSelf(),Ti(t)}compare(e){const t=this.clone();return t.compareNode=Ti(e),t.referenceNode=this.getSelf(),Ti(t)}grad(e,t){const r=this.clone();return r.gradNode=[Ti(e),Ti(t)],r.referenceNode=this.getSelf(),Ti(r)}depth(e){const t=this.clone();return t.depthNode=Ti(e),t.referenceNode=this.getSelf(),Ti(t)}serialize(e){super.serialize(e),e.value=this.value.toJSON(e.meta).uuid,e.sampler=this.sampler,e.updateMatrix=this.updateMatrix,e.updateType=this.updateType}deserialize(e){super.deserialize(e),this.value=e.meta.textures[e.value],this.sampler=e.sampler,this.updateMatrix=e.updateMatrix,this.updateType=e.updateType}update(){const e=this.value,t=this._matrixUniform;null!==t&&(t.value=e.matrix),!0===e.matrixAutoUpdate&&e.updateMatrix()}clone(){const e=new this.constructor(this.value,this.uvNode,this.levelNode,this.biasNode);return e.sampler=this.sampler,e}}const Ru=Ni(Au),Cu=(...e)=>Ru(...e).setSampler(!1),Eu=on("float").label("cameraNear").setGroup(rn).onRenderUpdate((({camera:e})=>e.near)),wu=on("float").label("cameraFar").setGroup(rn).onRenderUpdate((({camera:e})=>e.far)),Mu=on("mat4").label("cameraProjectionMatrix").setGroup(rn).onRenderUpdate((({camera:e})=>e.projectionMatrix)),Bu=on("mat4").label("cameraProjectionMatrixInverse").setGroup(rn).onRenderUpdate((({camera:e})=>e.projectionMatrixInverse)),Fu=on("mat4").label("cameraViewMatrix").setGroup(rn).onRenderUpdate((({camera:e})=>e.matrixWorldInverse)),Uu=on("mat4").label("cameraWorldMatrix").setGroup(rn).onRenderUpdate((({camera:e})=>e.matrixWorld)),Pu=on("mat3").label("cameraNormalMatrix").setGroup(rn).onRenderUpdate((({camera:e})=>e.normalMatrix)),Iu=on(new r).label("cameraPosition").setGroup(rn).onRenderUpdate((({camera:e},t)=>t.value.setFromMatrixPosition(e.matrixWorld)));class Du extends Ps{static get type(){return"Object3DNode"}constructor(e,t=null){super(),this.scope=e,this.object3d=t,this.updateType=Rs.OBJECT,this._uniformNode=new nn(null)}getNodeType(){const e=this.scope;return e===Du.WORLD_MATRIX?"mat4":e===Du.POSITION||e===Du.VIEW_POSITION||e===Du.DIRECTION||e===Du.SCALE?"vec3":void 0}update(e){const t=this.object3d,s=this._uniformNode,i=this.scope;if(i===Du.WORLD_MATRIX)s.value=t.matrixWorld;else if(i===Du.POSITION)s.value=s.value||new r,s.value.setFromMatrixPosition(t.matrixWorld);else if(i===Du.SCALE)s.value=s.value||new r,s.value.setFromMatrixScale(t.matrixWorld);else if(i===Du.DIRECTION)s.value=s.value||new r,t.getWorldDirection(s.value);else if(i===Du.VIEW_POSITION){const i=e.camera;s.value=s.value||new r,s.value.setFromMatrixPosition(t.matrixWorld),s.value.applyMatrix4(i.matrixWorldInverse)}}generate(e){const t=this.scope;return t===Du.WORLD_MATRIX?this._uniformNode.nodeType="mat4":t!==Du.POSITION&&t!==Du.VIEW_POSITION&&t!==Du.DIRECTION&&t!==Du.SCALE||(this._uniformNode.nodeType="vec3"),this._uniformNode.build(e)}serialize(e){super.serialize(e),e.scope=this.scope}deserialize(e){super.deserialize(e),this.scope=e.scope}}Du.WORLD_MATRIX="worldMatrix",Du.POSITION="position",Du.SCALE="scale",Du.VIEW_POSITION="viewPosition",Du.DIRECTION="direction";const Lu=Ni(Du,Du.DIRECTION),Vu=Ni(Du,Du.WORLD_MATRIX),Ou=Ni(Du,Du.POSITION),Gu=Ni(Du,Du.SCALE),ku=Ni(Du,Du.VIEW_POSITION);class zu extends Du{static get type(){return"ModelNode"}constructor(e){super(e)}update(e){this.object3d=e.object,super.update(e)}}const $u=Si(zu,zu.DIRECTION),Hu=Si(zu,zu.WORLD_MATRIX),Wu=Si(zu,zu.POSITION),ju=Si(zu,zu.SCALE),qu=Si(zu,zu.VIEW_POSITION),Ku=on(new i).onObjectUpdate((({object:e},t)=>t.value.getNormalMatrix(e.matrixWorld))),Xu=on(new n).onObjectUpdate((({object:e},t)=>t.value.copy(e.matrixWorld).invert())),Yu=Ai((e=>e.renderer.nodes.modelViewMatrix||Qu)).once()().toVar("modelViewMatrix"),Qu=Fu.mul(Hu),Zu=Ai((e=>(e.context.isHighPrecisionModelViewMatrix=!0,on("mat4").onObjectUpdate((({object:e,camera:t})=>e.modelViewMatrix.multiplyMatrices(t.matrixWorldInverse,e.matrixWorld)))))).once()().toVar("highpModelViewMatrix"),Ju=Ai((e=>{const t=e.context.isHighPrecisionModelViewMatrix;return on("mat3").onObjectUpdate((({object:e,camera:r})=>(!0!==t&&e.modelViewMatrix.multiplyMatrices(r.matrixWorldInverse,e.matrixWorld),e.normalMatrix.getNormalMatrix(e.modelViewMatrix))))})).once()().toVar("highpModelNormalViewMatrix"),el=xu("position","vec3"),tl=el.varying("positionLocal"),rl=el.varying("positionPrevious"),sl=Hu.mul(tl).xyz.varying("v_positionWorld").context({needsPositionReassign:!0}),il=tl.transformDirection(Hu).varying("v_positionWorldDirection").normalize().toVar("positionWorldDirection").context({needsPositionReassign:!0}),nl=Ai((e=>e.context.setupPositionView()),"vec3").once()().varying("v_positionView").context({needsPositionReassign:!0}),ol=nl.negate().varying("v_positionViewDirection").normalize().toVar("positionViewDirection");class al extends Ps{static get type(){return"FrontFacingNode"}constructor(){super("bool"),this.isFrontFacingNode=!0}generate(e){const{renderer:t,material:r}=e;return t.coordinateSystem===u&&r.side===T?"false":e.getFrontFacing()}}const ul=Si(al),ll=Bi(ul).mul(2).sub(1),dl=xu("normal","vec3"),cl=Ai((e=>!1===e.geometry.hasAttribute("normal")?(console.warn('TSL.NormalNode: Vertex attribute "normal" not found on geometry.'),Oi(0,1,0)):dl),"vec3").once()().toVar("normalLocal"),hl=nl.dFdx().cross(nl.dFdy()).normalize().toVar("normalFlat"),pl=Ai((e=>{let t;return t=!0===e.material.flatShading?hl:Ia(xl(cl),"v_normalView").normalize(),t}),"vec3").once()().toVar("normalView"),gl=Ia(pl.transformDirection(Fu),"v_normalWorld").normalize().toVar("normalWorld"),ml=Ai((e=>e.context.setupNormal().context({getUV:null})),"vec3").once()().mul(ll).toVar("transformedNormalView"),fl=ml.transformDirection(Fu).toVar("transformedNormalWorld"),yl=Ai((e=>e.context.setupClearcoatNormal().context({getUV:null})),"vec3").once()().mul(ll).toVar("transformedClearcoatNormalView"),bl=Ai((([e,t=Hu])=>{const r=Ki(t),s=e.div(Oi(r[0].dot(r[0]),r[1].dot(r[1]),r[2].dot(r[2])));return r.mul(s).xyz})),xl=Ai((([e],t)=>{const r=t.renderer.nodes.modelNormalViewMatrix;if(null!==r)return r.transformDirection(e);const s=Ku.mul(e);return Fu.transformDirection(s)})),Tl=on(0).onReference((({material:e})=>e)).onRenderUpdate((({material:e})=>e.refractionRatio)),_l=ol.negate().reflect(ml),vl=ol.negate().refract(ml,Tl),Nl=_l.transformDirection(Fu).toVar("reflectVector"),Sl=vl.transformDirection(Fu).toVar("reflectVector");class Al extends Au{static get type(){return"CubeTextureNode"}constructor(e,t=null,r=null,s=null){super(e,t,r,s),this.isCubeTextureNode=!0}getInputType(){return"cubeTexture"}getDefaultUV(){const e=this.value;return e.mapping===_?Nl:e.mapping===v?Sl:(console.error('THREE.CubeTextureNode: Mapping "%s" not supported.',e.mapping),Oi(0,0,0))}setUpdateMatrix(){}setupUV(e,t){const r=this.value;return e.renderer.coordinateSystem!==l&&r.isRenderTargetTexture?t:Oi(t.x.negate(),t.yz)}generateUV(e,t){return t.build(e,"vec3")}}const Rl=Ni(Al);class Cl extends nn{static get type(){return"BufferNode"}constructor(e,t,r=0){super(e,t),this.isBufferNode=!0,this.bufferType=t,this.bufferCount=r}getElementType(e){return this.getNodeType(e)}getInputType(){return"buffer"}}const El=(e,t,r)=>Ti(new Cl(e,t,r));class wl extends Is{static get type(){return"UniformArrayElementNode"}constructor(e,t){super(e,t),this.isArrayBufferElementNode=!0}generate(e){const t=super.generate(e),r=this.getNodeType(),s=this.node.getPaddedType();return e.format(t,s,r)}}class Ml extends Cl{static get type(){return"UniformArrayNode"}constructor(e,t=null){super(null),this.array=e,this.elementType=null===t?xs(e[0]):t,this.paddedType=this.getPaddedType(),this.updateType=Rs.RENDER,this.isArrayBufferNode=!0}getNodeType(){return this.paddedType}getElementType(){return this.elementType}getPaddedType(){const e=this.elementType;let t="vec4";return"mat2"===e?t="mat2":!0===/mat/.test(e)?t="mat4":"i"===e.charAt(0)?t="ivec4":"u"===e.charAt(0)&&(t="uvec4"),t}update(){const{array:e,value:t}=this,r=this.elementType;if("float"===r||"int"===r||"uint"===r)for(let r=0;rTi(new Ml(e,t));class Fl extends Is{static get type(){return"ReferenceElementNode"}constructor(e,t){super(e,t),this.referenceNode=e,this.isReferenceElementNode=!0}getNodeType(){return this.referenceNode.uniformType}generate(e){const t=super.generate(e),r=this.referenceNode.getNodeType(),s=this.getNodeType();return e.format(t,r,s)}}class Ul extends Ps{static get type(){return"ReferenceNode"}constructor(e,t,r=null,s=null){super(),this.property=e,this.uniformType=t,this.object=r,this.count=s,this.properties=e.split("."),this.reference=r,this.node=null,this.group=null,this.name=null,this.updateType=Rs.OBJECT}element(e){return Ti(new Fl(this,Ti(e)))}setGroup(e){return this.group=e,this}label(e){return this.name=e,this}setNodeType(e){let t=null;t=null!==this.count?El(null,e,this.count):Array.isArray(this.getValueFromReference())?Bl(null,e):"texture"===e?Ru(null):"cubeTexture"===e?Rl(null):on(null,e),null!==this.group&&t.setGroup(this.group),null!==this.name&&t.label(this.name),this.node=t.getSelf()}getNodeType(e){return null===this.node&&(this.updateReference(e),this.updateValue()),this.node.getNodeType(e)}getValueFromReference(e=this.reference){const{properties:t}=this;let r=e[t[0]];for(let e=1;eTi(new Ul(e,t,r)),Il=(e,t,r,s)=>Ti(new Ul(e,t,s,r));class Dl extends Ul{static get type(){return"MaterialReferenceNode"}constructor(e,t,r=null){super(e,t,r),this.material=r,this.isMaterialReferenceNode=!0}updateReference(e){return this.reference=null!==this.material?this.material:e.material,this.reference}}const Ll=(e,t,r=null)=>Ti(new Dl(e,t,r)),Vl=Ai((e=>(!1===e.geometry.hasAttribute("tangent")&&e.geometry.computeTangents(),xu("tangent","vec4"))))(),Ol=Vl.xyz.toVar("tangentLocal"),Gl=Yu.mul($i(Ol,0)).xyz.varying("v_tangentView").normalize().toVar("tangentView"),kl=Gl.transformDirection(Fu).varying("v_tangentWorld").normalize().toVar("tangentWorld"),zl=Gl.toVar("transformedTangentView"),$l=zl.transformDirection(Fu).normalize().toVar("transformedTangentWorld"),Hl=e=>e.mul(Vl.w).xyz,Wl=Ia(Hl(dl.cross(Vl)),"v_bitangentGeometry").normalize().toVar("bitangentGeometry"),jl=Ia(Hl(cl.cross(Ol)),"v_bitangentLocal").normalize().toVar("bitangentLocal"),ql=Ia(Hl(pl.cross(Gl)),"v_bitangentView").normalize().toVar("bitangentView"),Kl=Ia(Hl(gl.cross(kl)),"v_bitangentWorld").normalize().toVar("bitangentWorld"),Xl=Hl(ml.cross(zl)).normalize().toVar("transformedBitangentView"),Yl=Xl.transformDirection(Fu).normalize().toVar("transformedBitangentWorld"),Ql=Ki(Gl,ql,pl),Zl=ol.mul(Ql),Jl=(()=>{let e=Sn.cross(ol);return e=e.cross(Sn).normalize(),e=pa(e,ml,vn.mul(hn.oneMinus()).oneMinus().pow2().pow2()).normalize(),e})(),ed=Ai((e=>{const{eye_pos:t,surf_norm:r,mapN:s,uv:i}=e,n=t.dFdx(),o=t.dFdy(),a=i.dFdx(),u=i.dFdy(),l=r,d=o.cross(l),c=l.cross(n),h=d.mul(a.x).add(c.mul(u.x)),p=d.mul(a.y).add(c.mul(u.y)),g=h.dot(h).max(p.dot(p)),m=ll.mul(g.inverseSqrt());return $n(h.mul(s.x,m),p.mul(s.y,m),l.mul(s.z)).normalize()}));class td extends Ls{static get type(){return"NormalMapNode"}constructor(e,t=null){super("vec3"),this.node=e,this.scaleNode=t,this.normalMapType=N}setup(e){const{normalMapType:t,scaleNode:r}=this;let s=this.node.mul(2).sub(1);null!==r&&(s=Oi(s.xy.mul(r),s.z));let i=null;if(t===S)i=xl(s);else if(t===N){i=!0===e.hasGeometryAttribute("tangent")?Ql.mul(s).normalize():ed({eye_pos:nl,surf_norm:pl,mapN:s,uv:Tu()})}return i}}const rd=Ni(td),sd=Ai((({textureNode:e,bumpScale:t})=>{const r=t=>e.cache().context({getUV:e=>t(e.uvNode||Tu()),forceUVContext:!0}),s=Bi(r((e=>e)));return Ii(Bi(r((e=>e.add(e.dFdx())))).sub(s),Bi(r((e=>e.add(e.dFdy())))).sub(s)).mul(t)})),id=Ai((e=>{const{surf_pos:t,surf_norm:r,dHdxy:s}=e,i=t.dFdx().normalize(),n=r,o=t.dFdy().normalize().cross(n),a=n.cross(i),u=i.dot(o).mul(ll),l=u.sign().mul(s.x.mul(o).add(s.y.mul(a)));return u.abs().mul(r).sub(l).normalize()}));class nd extends Ls{static get type(){return"BumpMapNode"}constructor(e,t=null){super("vec3"),this.textureNode=e,this.scaleNode=t}setup(){const e=null!==this.scaleNode?this.scaleNode:1,t=sd({textureNode:this.textureNode,bumpScale:e});return id({surf_pos:nl,surf_norm:pl,dHdxy:t})}}const od=Ni(nd),ad=new Map;class ud extends Ps{static get type(){return"MaterialNode"}constructor(e){super(),this.scope=e}getCache(e,t){let r=ad.get(e);return void 0===r&&(r=Ll(e,t),ad.set(e,r)),r}getFloat(e){return this.getCache(e,"float")}getColor(e){return this.getCache(e,"color")}getTexture(e){return this.getCache("map"===e?"map":e+"Map","texture")}setup(e){const t=e.context.material,r=this.scope;let s=null;if(r===ud.COLOR){const e=void 0!==t.color?this.getColor(r):Oi();s=t.map&&!0===t.map.isTexture?e.mul(this.getTexture("map")):e}else if(r===ud.OPACITY){const e=this.getFloat(r);s=t.alphaMap&&!0===t.alphaMap.isTexture?e.mul(this.getTexture("alpha")):e}else if(r===ud.SPECULAR_STRENGTH)s=t.specularMap&&!0===t.specularMap.isTexture?this.getTexture("specular").r:Bi(1);else if(r===ud.SPECULAR_INTENSITY){const e=this.getFloat(r);s=t.specularIntensityMap&&!0===t.specularIntensityMap.isTexture?e.mul(this.getTexture(r).a):e}else if(r===ud.SPECULAR_COLOR){const e=this.getColor(r);s=t.specularColorMap&&!0===t.specularColorMap.isTexture?e.mul(this.getTexture(r).rgb):e}else if(r===ud.ROUGHNESS){const e=this.getFloat(r);s=t.roughnessMap&&!0===t.roughnessMap.isTexture?e.mul(this.getTexture(r).g):e}else if(r===ud.METALNESS){const e=this.getFloat(r);s=t.metalnessMap&&!0===t.metalnessMap.isTexture?e.mul(this.getTexture(r).b):e}else if(r===ud.EMISSIVE){const e=this.getFloat("emissiveIntensity"),i=this.getColor(r).mul(e);s=t.emissiveMap&&!0===t.emissiveMap.isTexture?i.mul(this.getTexture(r)):i}else if(r===ud.NORMAL)t.normalMap?(s=rd(this.getTexture("normal"),this.getCache("normalScale","vec2")),s.normalMapType=t.normalMapType):s=t.bumpMap?od(this.getTexture("bump").r,this.getFloat("bumpScale")):pl;else if(r===ud.CLEARCOAT){const e=this.getFloat(r);s=t.clearcoatMap&&!0===t.clearcoatMap.isTexture?e.mul(this.getTexture(r).r):e}else if(r===ud.CLEARCOAT_ROUGHNESS){const e=this.getFloat(r);s=t.clearcoatRoughnessMap&&!0===t.clearcoatRoughnessMap.isTexture?e.mul(this.getTexture(r).r):e}else if(r===ud.CLEARCOAT_NORMAL)s=t.clearcoatNormalMap?rd(this.getTexture(r),this.getCache(r+"Scale","vec2")):pl;else if(r===ud.SHEEN){const e=this.getColor("sheenColor").mul(this.getFloat("sheen"));s=t.sheenColorMap&&!0===t.sheenColorMap.isTexture?e.mul(this.getTexture("sheenColor").rgb):e}else if(r===ud.SHEEN_ROUGHNESS){const e=this.getFloat(r);s=t.sheenRoughnessMap&&!0===t.sheenRoughnessMap.isTexture?e.mul(this.getTexture(r).a):e,s=s.clamp(.07,1)}else if(r===ud.ANISOTROPY)if(t.anisotropyMap&&!0===t.anisotropyMap.isTexture){const e=this.getTexture(r);s=qi(jd.x,jd.y,jd.y.negate(),jd.x).mul(e.rg.mul(2).sub(Ii(1)).normalize().mul(e.b))}else s=jd;else if(r===ud.IRIDESCENCE_THICKNESS){const e=Pl("1","float",t.iridescenceThicknessRange);if(t.iridescenceThicknessMap){const i=Pl("0","float",t.iridescenceThicknessRange);s=e.sub(i).mul(this.getTexture(r).g).add(i)}else s=e}else if(r===ud.TRANSMISSION){const e=this.getFloat(r);s=t.transmissionMap?e.mul(this.getTexture(r).r):e}else if(r===ud.THICKNESS){const e=this.getFloat(r);s=t.thicknessMap?e.mul(this.getTexture(r).g):e}else if(r===ud.IOR)s=this.getFloat(r);else if(r===ud.LIGHT_MAP)s=this.getTexture(r).rgb.mul(this.getFloat("lightMapIntensity"));else if(r===ud.AO)s=this.getTexture(r).r.sub(1).mul(this.getFloat("aoMapIntensity")).add(1);else{const t=this.getNodeType(e);s=this.getCache(r,t)}return s}}ud.ALPHA_TEST="alphaTest",ud.COLOR="color",ud.OPACITY="opacity",ud.SHININESS="shininess",ud.SPECULAR="specular",ud.SPECULAR_STRENGTH="specularStrength",ud.SPECULAR_INTENSITY="specularIntensity",ud.SPECULAR_COLOR="specularColor",ud.REFLECTIVITY="reflectivity",ud.ROUGHNESS="roughness",ud.METALNESS="metalness",ud.NORMAL="normal",ud.CLEARCOAT="clearcoat",ud.CLEARCOAT_ROUGHNESS="clearcoatRoughness",ud.CLEARCOAT_NORMAL="clearcoatNormal",ud.EMISSIVE="emissive",ud.ROTATION="rotation",ud.SHEEN="sheen",ud.SHEEN_ROUGHNESS="sheenRoughness",ud.ANISOTROPY="anisotropy",ud.IRIDESCENCE="iridescence",ud.IRIDESCENCE_IOR="iridescenceIOR",ud.IRIDESCENCE_THICKNESS="iridescenceThickness",ud.IOR="ior",ud.TRANSMISSION="transmission",ud.THICKNESS="thickness",ud.ATTENUATION_DISTANCE="attenuationDistance",ud.ATTENUATION_COLOR="attenuationColor",ud.LINE_SCALE="scale",ud.LINE_DASH_SIZE="dashSize",ud.LINE_GAP_SIZE="gapSize",ud.LINE_WIDTH="linewidth",ud.LINE_DASH_OFFSET="dashOffset",ud.POINT_WIDTH="pointWidth",ud.DISPERSION="dispersion",ud.LIGHT_MAP="light",ud.AO="ao";const ld=Si(ud,ud.ALPHA_TEST),dd=Si(ud,ud.COLOR),cd=Si(ud,ud.SHININESS),hd=Si(ud,ud.EMISSIVE),pd=Si(ud,ud.OPACITY),gd=Si(ud,ud.SPECULAR),md=Si(ud,ud.SPECULAR_INTENSITY),fd=Si(ud,ud.SPECULAR_COLOR),yd=Si(ud,ud.SPECULAR_STRENGTH),bd=Si(ud,ud.REFLECTIVITY),xd=Si(ud,ud.ROUGHNESS),Td=Si(ud,ud.METALNESS),_d=Si(ud,ud.NORMAL),vd=Si(ud,ud.CLEARCOAT),Nd=Si(ud,ud.CLEARCOAT_ROUGHNESS),Sd=Si(ud,ud.CLEARCOAT_NORMAL),Ad=Si(ud,ud.ROTATION),Rd=Si(ud,ud.SHEEN),Cd=Si(ud,ud.SHEEN_ROUGHNESS),Ed=Si(ud,ud.ANISOTROPY),wd=Si(ud,ud.IRIDESCENCE),Md=Si(ud,ud.IRIDESCENCE_IOR),Bd=Si(ud,ud.IRIDESCENCE_THICKNESS),Fd=Si(ud,ud.TRANSMISSION),Ud=Si(ud,ud.THICKNESS),Pd=Si(ud,ud.IOR),Id=Si(ud,ud.ATTENUATION_DISTANCE),Dd=Si(ud,ud.ATTENUATION_COLOR),Ld=Si(ud,ud.LINE_SCALE),Vd=Si(ud,ud.LINE_DASH_SIZE),Od=Si(ud,ud.LINE_GAP_SIZE),Gd=Si(ud,ud.LINE_WIDTH),kd=Si(ud,ud.LINE_DASH_OFFSET),zd=Si(ud,ud.POINT_WIDTH),$d=Si(ud,ud.DISPERSION),Hd=Si(ud,ud.LIGHT_MAP),Wd=Si(ud,ud.AO),jd=on(new t).onReference((function(e){return e.material})).onRenderUpdate((function({material:e}){this.value.set(e.anisotropy*Math.cos(e.anisotropyRotation),e.anisotropy*Math.sin(e.anisotropyRotation))})),qd=Ai((e=>e.context.setupModelViewProjection()),"vec4").once()().varying("v_modelViewProjection");class Kd extends Ps{static get type(){return"IndexNode"}constructor(e){super("uint"),this.scope=e,this.isIndexNode=!0}generate(e){const t=this.getNodeType(e),r=this.scope;let s,i;if(r===Kd.VERTEX)s=e.getVertexIndex();else if(r===Kd.INSTANCE)s=e.getInstanceIndex();else if(r===Kd.DRAW)s=e.getDrawIndex();else if(r===Kd.INVOCATION_LOCAL)s=e.getInvocationLocalIndex();else if(r===Kd.INVOCATION_SUBGROUP)s=e.getInvocationSubgroupIndex();else{if(r!==Kd.SUBGROUP)throw new Error("THREE.IndexNode: Unknown scope: "+r);s=e.getSubgroupIndex()}if("vertex"===e.shaderStage||"compute"===e.shaderStage)i=s;else{i=Ia(this).build(e,t)}return i}}Kd.VERTEX="vertex",Kd.INSTANCE="instance",Kd.SUBGROUP="subgroup",Kd.INVOCATION_LOCAL="invocationLocal",Kd.INVOCATION_SUBGROUP="invocationSubgroup",Kd.DRAW="draw";const Xd=Si(Kd,Kd.VERTEX),Yd=Si(Kd,Kd.INSTANCE),Qd=Si(Kd,Kd.SUBGROUP),Zd=Si(Kd,Kd.INVOCATION_SUBGROUP),Jd=Si(Kd,Kd.INVOCATION_LOCAL),ec=Si(Kd,Kd.DRAW);class tc extends Ps{static get type(){return"InstanceNode"}constructor(e,t,r){super("void"),this.count=e,this.instanceMatrix=t,this.instanceColor=r,this.instanceMatrixNode=null,this.instanceColorNode=null,this.updateType=Rs.FRAME,this.buffer=null,this.bufferColor=null}setup(e){const{count:t,instanceMatrix:r,instanceColor:s}=this;let{instanceMatrixNode:i,instanceColorNode:n}=this;if(null===i){if(t<=1e3)i=El(r.array,"mat4",Math.max(t,1)).element(Yd);else{const e=new A(r.array,16,1);this.buffer=e;const t=r.usage===m?su:ru,s=[t(e,"vec4",16,0),t(e,"vec4",16,4),t(e,"vec4",16,8),t(e,"vec4",16,12)];i=Xi(...s)}this.instanceMatrixNode=i}if(s&&null===n){const e=new R(s.array,3),t=s.usage===m?su:ru;this.bufferColor=e,n=Oi(t(e,"vec3",3,0)),this.instanceColorNode=n}const o=i.mul(tl).xyz;if(tl.assign(o),e.hasGeometryAttribute("normal")){const e=bl(cl,i);cl.assign(e)}null!==this.instanceColorNode&&ln("vec3","vInstanceColor").assign(this.instanceColorNode)}update(){this.instanceMatrix.usage!==m&&null!==this.buffer&&this.instanceMatrix.version!==this.buffer.version&&(this.buffer.version=this.instanceMatrix.version),this.instanceColor&&this.instanceColor.usage!==m&&null!==this.bufferColor&&this.instanceColor.version!==this.bufferColor.version&&(this.bufferColor.version=this.instanceColor.version)}}const rc=Ni(tc);class sc extends tc{static get type(){return"InstancedMeshNode"}constructor(e){const{count:t,instanceMatrix:r,instanceColor:s}=e;super(t,r,s),this.instancedMesh=e}}const ic=Ni(sc);class nc extends Ps{static get type(){return"BatchNode"}constructor(e){super("void"),this.batchMesh=e,this.batchingIdNode=null}setup(e){null===this.batchingIdNode&&(null===e.getDrawIndex()?this.batchingIdNode=Yd:this.batchingIdNode=ec);const t=Ai((([e])=>{const t=vu(Cu(this.batchMesh._indirectTexture),0),r=Fi(e).modInt(Fi(t)),s=Fi(e).div(Fi(t));return Cu(this.batchMesh._indirectTexture,Di(r,s)).x})).setLayout({name:"getIndirectIndex",type:"uint",inputs:[{name:"id",type:"int"}]}),r=t(Fi(this.batchingIdNode)),s=this.batchMesh._matricesTexture,i=vu(Cu(s),0),n=Bi(r).mul(4).toInt().toVar(),o=n.modInt(i),a=n.div(Fi(i)),u=Xi(Cu(s,Di(o,a)),Cu(s,Di(o.add(1),a)),Cu(s,Di(o.add(2),a)),Cu(s,Di(o.add(3),a))),l=this.batchMesh._colorsTexture;if(null!==l){const e=Ai((([e])=>{const t=vu(Cu(l),0).x,r=e,s=r.modInt(t),i=r.div(t);return Cu(l,Di(s,i)).rgb})).setLayout({name:"getBatchingColor",type:"vec3",inputs:[{name:"id",type:"int"}]}),t=e(r);ln("vec3","vBatchColor").assign(t)}const d=Ki(u);tl.assign(u.mul(tl));const c=cl.div(Oi(d[0].dot(d[0]),d[1].dot(d[1]),d[2].dot(d[2]))),h=d.mul(c).xyz;cl.assign(h),e.hasGeometryAttribute("tangent")&&Ol.mulAssign(d)}}const oc=Ni(nc),ac=new WeakMap;class uc extends Ps{static get type(){return"SkinningNode"}constructor(e,t=!1){let r,s,i;super("void"),this.skinnedMesh=e,this.useReference=t,this.updateType=Rs.OBJECT,this.skinIndexNode=xu("skinIndex","uvec4"),this.skinWeightNode=xu("skinWeight","vec4"),t?(r=Pl("bindMatrix","mat4"),s=Pl("bindMatrixInverse","mat4"),i=Il("skeleton.boneMatrices","mat4",e.skeleton.bones.length)):(r=on(e.bindMatrix,"mat4"),s=on(e.bindMatrixInverse,"mat4"),i=El(e.skeleton.boneMatrices,"mat4",e.skeleton.bones.length)),this.bindMatrixNode=r,this.bindMatrixInverseNode=s,this.boneMatricesNode=i,this.previousBoneMatricesNode=null}getSkinnedPosition(e=this.boneMatricesNode,t=tl){const{skinIndexNode:r,skinWeightNode:s,bindMatrixNode:i,bindMatrixInverseNode:n}=this,o=e.element(r.x),a=e.element(r.y),u=e.element(r.z),l=e.element(r.w),d=i.mul(t),c=$n(o.mul(s.x).mul(d),a.mul(s.y).mul(d),u.mul(s.z).mul(d),l.mul(s.w).mul(d));return n.mul(c).xyz}getSkinnedNormal(e=this.boneMatricesNode,t=cl){const{skinIndexNode:r,skinWeightNode:s,bindMatrixNode:i,bindMatrixInverseNode:n}=this,o=e.element(r.x),a=e.element(r.y),u=e.element(r.z),l=e.element(r.w);let d=$n(s.x.mul(o),s.y.mul(a),s.z.mul(u),s.w.mul(l));return d=n.mul(d).mul(i),d.transformDirection(t).xyz}getPreviousSkinnedPosition(e){const t=e.object;return null===this.previousBoneMatricesNode&&(t.skeleton.previousBoneMatrices=new Float32Array(t.skeleton.boneMatrices),this.previousBoneMatricesNode=Il("skeleton.previousBoneMatrices","mat4",t.skeleton.bones.length)),this.getSkinnedPosition(this.previousBoneMatricesNode,rl)}needsPreviousBoneMatrices(e){const t=e.renderer.getMRT();return t&&t.has("velocity")||!0===_s(e.object).useVelocity}setup(e){this.needsPreviousBoneMatrices(e)&&rl.assign(this.getPreviousSkinnedPosition(e));const t=this.getSkinnedPosition();if(tl.assign(t),e.hasGeometryAttribute("normal")){const t=this.getSkinnedNormal();cl.assign(t),e.hasGeometryAttribute("tangent")&&Ol.assign(t)}}generate(e,t){if("void"!==t)return tl.build(e,t)}update(e){const t=(this.useReference?e.object:this.skinnedMesh).skeleton;ac.get(t)!==e.frameId&&(ac.set(t,e.frameId),null!==this.previousBoneMatricesNode&&t.previousBoneMatrices.set(t.boneMatrices),t.update())}}const lc=e=>Ti(new uc(e,!0));class dc extends Ps{static get type(){return"LoopNode"}constructor(e=[]){super(),this.params=e}getVarName(e){return String.fromCharCode("i".charCodeAt(0)+e)}getProperties(e){const t=e.getNodeProperties(this);if(void 0!==t.stackNode)return t;const r={};for(let e=0,t=this.params.length-1;eNumber(n)?">=":"<"));const d={start:i,end:n,condition:u},c=d.start,h=d.end;let p="",g="",m="";l||(l="int"===a||"uint"===a?u.includes("<")?"++":"--":u.includes("<")?"+= 1.":"-= 1."),p+=e.getVar(a,o)+" = "+c,g+=o+" "+u+" "+h,m+=o+" "+l;const f=`for ( ${p}; ${g}; ${m} )`;e.addFlowCode((0===t?"\n":"")+e.tab+f+" {\n\n").addFlowTab()}const i=s.build(e,"void"),n=t.returnsNode?t.returnsNode.build(e):"";e.removeFlowTab().addFlowCode("\n"+e.tab+i);for(let t=0,r=this.params.length-1;tTi(new dc(vi(e,"int"))).append(),hc=()=>gu("break").append(),pc=new WeakMap,gc=new s,mc=Ai((({bufferMap:e,influence:t,stride:r,width:s,depth:i,offset:n})=>{const o=Fi(Xd).mul(r).add(n),a=o.div(s),u=o.sub(a.mul(s));return Cu(e,Di(u,a)).depth(i).mul(t)}));class fc extends Ps{static get type(){return"MorphNode"}constructor(e){super("void"),this.mesh=e,this.morphBaseInfluence=on(1),this.updateType=Rs.OBJECT}setup(e){const{geometry:r}=e,s=void 0!==r.morphAttributes.position,i=r.hasAttribute("normal")&&void 0!==r.morphAttributes.normal,n=r.morphAttributes.position||r.morphAttributes.normal||r.morphAttributes.color,o=void 0!==n?n.length:0,{texture:a,stride:u,size:l}=function(e){const r=void 0!==e.morphAttributes.position,s=void 0!==e.morphAttributes.normal,i=void 0!==e.morphAttributes.color,n=e.morphAttributes.position||e.morphAttributes.normal||e.morphAttributes.color,o=void 0!==n?n.length:0;let a=pc.get(e);if(void 0===a||a.count!==o){void 0!==a&&a.texture.dispose();const u=e.morphAttributes.position||[],l=e.morphAttributes.normal||[],d=e.morphAttributes.color||[];let c=0;!0===r&&(c=1),!0===s&&(c=2),!0===i&&(c=3);let h=e.attributes.position.count*c,p=1;const g=4096;h>g&&(p=Math.ceil(h/g),h=g);const m=new Float32Array(h*p*4*o),f=new C(m,h,p,o);f.type=E,f.needsUpdate=!0;const y=4*c;for(let x=0;x{const t=Bi(0).toVar();this.mesh.count>1&&null!==this.mesh.morphTexture&&void 0!==this.mesh.morphTexture?t.assign(Cu(this.mesh.morphTexture,Di(Fi(e).add(1),Fi(Yd))).r):t.assign(Pl("morphTargetInfluences","float").element(e).toVar()),!0===s&&tl.addAssign(mc({bufferMap:a,influence:t,stride:u,width:d,depth:e,offset:Fi(0)})),!0===i&&cl.addAssign(mc({bufferMap:a,influence:t,stride:u,width:d,depth:e,offset:Fi(1)}))}))}update(){const e=this.morphBaseInfluence;this.mesh.geometry.morphTargetsRelative?e.value=1:e.value=1-this.mesh.morphTargetInfluences.reduce(((e,t)=>e+t),0)}}const yc=Ni(fc);class bc extends Ps{static get type(){return"LightingNode"}constructor(){super("vec3"),this.isLightingNode=!0}}class xc extends bc{static get type(){return"AONode"}constructor(e=null){super(),this.aoNode=e}setup(e){e.context.ambientOcclusion.mulAssign(this.aoNode)}}class Tc extends Ea{static get type(){return"LightingContextNode"}constructor(e,t=null,r=null,s=null){super(e),this.lightingModel=t,this.backdropNode=r,this.backdropAlphaNode=s,this._value=null}getContext(){const{backdropNode:e,backdropAlphaNode:t}=this,r={directDiffuse:Oi().toVar("directDiffuse"),directSpecular:Oi().toVar("directSpecular"),indirectDiffuse:Oi().toVar("indirectDiffuse"),indirectSpecular:Oi().toVar("indirectSpecular")};return{radiance:Oi().toVar("radiance"),irradiance:Oi().toVar("irradiance"),iblIrradiance:Oi().toVar("iblIrradiance"),ambientOcclusion:Bi(1).toVar("ambientOcclusion"),reflectedLight:r,backdrop:e,backdropAlpha:t}}setup(e){return this.value=this._value||(this._value=this.getContext()),this.value.lightingModel=this.lightingModel||e.context.lightingModel,super.setup(e)}}const _c=Ni(Tc);class vc extends bc{static get type(){return"IrradianceNode"}constructor(e){super(),this.node=e}setup(e){e.context.irradiance.addAssign(this.node)}}let Nc,Sc;class Ac extends Ps{static get type(){return"ScreenNode"}constructor(e){super(),this.scope=e,this.isViewportNode=!0}getNodeType(){return this.scope===Ac.VIEWPORT?"vec4":"vec2"}getUpdateType(){let e=Rs.NONE;return this.scope!==Ac.SIZE&&this.scope!==Ac.VIEWPORT||(e=Rs.RENDER),this.updateType=e,e}update({renderer:e}){const t=e.getRenderTarget();this.scope===Ac.VIEWPORT?null!==t?Sc.copy(t.viewport):(e.getViewport(Sc),Sc.multiplyScalar(e.getPixelRatio())):null!==t?(Nc.width=t.width,Nc.height=t.height):e.getDrawingBufferSize(Nc)}setup(){const e=this.scope;let r=null;return r=e===Ac.SIZE?on(Nc||(Nc=new t)):e===Ac.VIEWPORT?on(Sc||(Sc=new s)):Ii(Ec.div(Cc)),r}generate(e){if(this.scope===Ac.COORDINATE){let t=e.getFragCoord();if(e.isFlipY()){const r=e.getNodeProperties(Cc).outputNode.build(e);t=`${e.getType("vec2")}( ${t}.x, ${r}.y - ${t}.y )`}return t}return super.generate(e)}}Ac.COORDINATE="coordinate",Ac.VIEWPORT="viewport",Ac.SIZE="size",Ac.UV="uv";const Rc=Si(Ac,Ac.UV),Cc=Si(Ac,Ac.SIZE),Ec=Si(Ac,Ac.COORDINATE),wc=Si(Ac,Ac.VIEWPORT),Mc=wc.zw,Bc=Ec.sub(wc.xy),Fc=Bc.div(Mc),Uc=Ai((()=>(console.warn('TSL.ViewportNode: "viewportResolution" is deprecated. Use "screenSize" instead.'),Cc)),"vec2").once()(),Pc=Ai((()=>(console.warn('TSL.ViewportNode: "viewportTopLeft" is deprecated. Use "screenUV" instead.'),Rc)),"vec2").once()(),Ic=Ai((()=>(console.warn('TSL.ViewportNode: "viewportBottomLeft" is deprecated. Use "screenUV.flipY()" instead.'),Rc.flipY())),"vec2").once()(),Dc=new t;class Lc extends Au{static get type(){return"ViewportTextureNode"}constructor(e=Rc,t=null,r=null){null===r&&((r=new w).minFilter=M),super(r,e,t),this.generateMipmaps=!1,this.isOutputTextureNode=!0,this.updateBeforeType=Rs.FRAME}updateBefore(e){const t=e.renderer;t.getDrawingBufferSize(Dc);const r=this.value;r.image.width===Dc.width&&r.image.height===Dc.height||(r.image.width=Dc.width,r.image.height=Dc.height,r.needsUpdate=!0);const s=r.generateMipmaps;r.generateMipmaps=this.generateMipmaps,t.copyFramebufferToTexture(r),r.generateMipmaps=s}clone(){const e=new this.constructor(this.uvNode,this.levelNode,this.value);return e.generateMipmaps=this.generateMipmaps,e}}const Vc=Ni(Lc),Oc=Ni(Lc,null,null,{generateMipmaps:!0});let Gc=null;class kc extends Lc{static get type(){return"ViewportDepthTextureNode"}constructor(e=Rc,t=null){null===Gc&&(Gc=new B),super(e,t,Gc)}}const zc=Ni(kc);class $c extends Ps{static get type(){return"ViewportDepthNode"}constructor(e,t=null){super("float"),this.scope=e,this.valueNode=t,this.isViewportDepthNode=!0}generate(e){const{scope:t}=this;return t===$c.DEPTH_BASE?e.getFragDepth():super.generate(e)}setup({camera:e}){const{scope:t}=this,r=this.valueNode;let s=null;if(t===$c.DEPTH_BASE)null!==r&&(s=Kc().assign(r));else if(t===$c.DEPTH)s=e.isPerspectiveCamera?Wc(nl.z,Eu,wu):Hc(nl.z,Eu,wu);else if(t===$c.LINEAR_DEPTH)if(null!==r)if(e.isPerspectiveCamera){const e=jc(r,Eu,wu);s=Hc(e,Eu,wu)}else s=r;else s=Hc(nl.z,Eu,wu);return s}}$c.DEPTH_BASE="depthBase",$c.DEPTH="depth",$c.LINEAR_DEPTH="linearDepth";const Hc=(e,t,r)=>e.add(t).div(t.sub(r)),Wc=(e,t,r)=>t.add(e).mul(r).div(r.sub(t).mul(e)),jc=(e,t,r)=>t.mul(r).div(r.sub(t).mul(e).sub(r)),qc=(e,t,r)=>{t=t.max(1e-6).toVar();const s=So(e.negate().div(t)),i=So(r.div(t));return s.div(i)},Kc=Ni($c,$c.DEPTH_BASE),Xc=Si($c,$c.DEPTH),Yc=Ni($c,$c.LINEAR_DEPTH),Qc=Yc(zc());Xc.assign=e=>Kc(e);const Zc=Ni(class extends Ps{constructor(e){super("float"),this.name=e,this.isBuiltinNode=!0}generate(){return this.name}});class Jc extends Ps{static get type(){return"ClippingNode"}constructor(e=Jc.DEFAULT){super(),this.scope=e}setup(e){super.setup(e);const t=e.clippingContext,{intersectionPlanes:r,unionPlanes:s}=t;return this.hardwareClipping=e.material.hardwareClipping,this.scope===Jc.ALPHA_TO_COVERAGE?this.setupAlphaToCoverage(r,s):this.scope===Jc.HARDWARE?this.setupHardwareClipping(s,e):this.setupDefault(r,s)}setupAlphaToCoverage(e,t){return Ai((()=>{const r=Bi().toVar("distanceToPlane"),s=Bi().toVar("distanceToGradient"),i=Bi(1).toVar("clipOpacity"),n=t.length;if(!1===this.hardwareClipping&&n>0){const e=Bl(t);cc(n,(({i:t})=>{const n=e.element(t);r.assign(nl.dot(n.xyz).negate().add(n.w)),s.assign(r.fwidth().div(2)),i.mulAssign(ya(s.negate(),s,r))}))}const o=e.length;if(o>0){const t=Bl(e),n=Bi(1).toVar("intersectionClipOpacity");cc(o,(({i:e})=>{const i=t.element(e);r.assign(nl.dot(i.xyz).negate().add(i.w)),s.assign(r.fwidth().div(2)),n.mulAssign(ya(s.negate(),s,r).oneMinus())})),i.mulAssign(n.oneMinus())}dn.a.mulAssign(i),dn.a.equal(0).discard()}))()}setupDefault(e,t){return Ai((()=>{const r=t.length;if(!1===this.hardwareClipping&&r>0){const e=Bl(t);cc(r,(({i:t})=>{const r=e.element(t);nl.dot(r.xyz).greaterThan(r.w).discard()}))}const s=e.length;if(s>0){const t=Bl(e),r=Pi(!0).toVar("clipped");cc(s,(({i:e})=>{const s=t.element(e);r.assign(nl.dot(s.xyz).greaterThan(s.w).and(r))})),r.discard()}}))()}setupHardwareClipping(e,t){const r=e.length;return t.enableHardwareClipping(r),Ai((()=>{const s=Bl(e),i=Zc(t.getClipDistance());cc(r,(({i:e})=>{const t=s.element(e),r=nl.dot(t.xyz).sub(t.w).negate();i.element(e).assign(r)}))}))()}}Jc.ALPHA_TO_COVERAGE="alphaToCoverage",Jc.DEFAULT="default",Jc.HARDWARE="hardware";const eh=Ai((([e])=>Mo(Wn(1e4,Bo(Wn(17,e.x).add(Wn(.1,e.y)))).mul($n(.1,Lo(Bo(Wn(13,e.y).add(e.x)))))))),th=Ai((([e])=>eh(Ii(eh(e.xy),e.z)))),rh=Ai((([e])=>{const t=Zo(Oo(zo(e.xyz)),Oo($o(e.xyz))),r=Bi(1).div(Bi(.05).mul(t)).toVar("pixScale"),s=Ii(vo(Co(So(r))),vo(Eo(So(r)))),i=Ii(th(Co(s.x.mul(e.xyz))),th(Co(s.y.mul(e.xyz)))),n=Mo(So(r)),o=$n(Wn(n.oneMinus(),i.x),Wn(n,i.y)),a=Qo(n,n.oneMinus()),u=Oi(o.mul(o).div(Wn(2,a).mul(Hn(1,a))),o.sub(Wn(.5,a)).div(Hn(1,a)),Hn(1,Hn(1,o).mul(Hn(1,o)).div(Wn(2,a).mul(Hn(1,a))))),l=o.lessThan(a.oneMinus()).select(o.lessThan(a).select(u.x,u.y),u.z);return ga(l,1e-6,1)})).setLayout({name:"getAlphaHashThreshold",type:"float",inputs:[{name:"position",type:"vec3"}]});class sh extends F{static get type(){return"NodeMaterial"}get type(){return this.constructor.type}set type(e){}constructor(){super(),this.isNodeMaterial=!0,this.fog=!0,this.lights=!1,this.hardwareClipping=!1,this.lightsNode=null,this.envNode=null,this.aoNode=null,this.colorNode=null,this.normalNode=null,this.opacityNode=null,this.backdropNode=null,this.backdropAlphaNode=null,this.alphaTestNode=null,this.positionNode=null,this.geometryNode=null,this.depthNode=null,this.shadowPositionNode=null,this.receivedShadowNode=null,this.castShadowNode=null,this.outputNode=null,this.mrtNode=null,this.fragmentNode=null,this.vertexNode=null}customProgramCacheKey(){return this.type+hs(this)}build(e){this.setup(e)}setupObserver(e){return new as(e)}setup(e){e.context.setupNormal=()=>this.setupNormal(e),e.context.setupPositionView=()=>this.setupPositionView(e),e.context.setupModelViewProjection=()=>this.setupModelViewProjection(e);const t=e.renderer,r=t.getRenderTarget();e.addStack();const s=this.vertexNode||this.setupVertex(e);let i;e.stack.outputNode=s,this.setupHardwareClipping(e),null!==this.geometryNode&&(e.stack.outputNode=e.stack.outputNode.bypass(this.geometryNode)),e.addFlow("vertex",e.removeStack()),e.addStack();const n=this.setupClipping(e);if(!0!==this.depthWrite&&!0!==this.depthTest||(null!==r?!0===r.depthBuffer&&this.setupDepth(e):!0===t.depth&&this.setupDepth(e)),null===this.fragmentNode){this.setupDiffuseColor(e),this.setupVariants(e);const s=this.setupLighting(e);null!==n&&e.stack.add(n);const o=$i(s,dn.a).max(0);if(i=this.setupOutput(e,o),En.assign(i),null!==this.outputNode&&(i=this.outputNode),null!==r){const e=t.getMRT(),r=this.mrtNode;null!==e?(i=e,null!==r&&(i=e.merge(r))):null!==r&&(i=r)}}else{let t=this.fragmentNode;!0!==t.isOutputStructNode&&(t=$i(t)),i=this.setupOutput(e,t)}e.stack.outputNode=i,e.addFlow("fragment",e.removeStack()),e.monitor=this.setupObserver(e)}setupClipping(e){if(null===e.clippingContext)return null;const{unionPlanes:t,intersectionPlanes:r}=e.clippingContext;let s=null;if(t.length>0||r.length>0){const t=e.renderer.samples;this.alphaToCoverage&&t>1?s=Ti(new Jc(Jc.ALPHA_TO_COVERAGE)):e.stack.add(Ti(new Jc))}return s}setupHardwareClipping(e){if(this.hardwareClipping=!1,null===e.clippingContext)return;const t=e.clippingContext.unionPlanes.length;t>0&&t<=8&&e.isAvailable("clipDistance")&&(e.stack.add(Ti(new Jc(Jc.HARDWARE))),this.hardwareClipping=!0)}setupDepth(e){const{renderer:t,camera:r}=e;let s=this.depthNode;if(null===s){const e=t.getMRT();e&&e.has("depth")?s=e.get("depth"):!0===t.logarithmicDepthBuffer&&(s=r.isPerspectiveCamera?qc(nl.z,Eu,wu):Hc(nl.z,Eu,wu))}null!==s&&Xc.assign(s).append()}setupPositionView(){return Yu.mul(tl).xyz}setupModelViewProjection(){return Mu.mul(nl)}setupVertex(e){return e.addStack(),this.setupPosition(e),e.context.vertex=e.removeStack(),qd}setupPosition(e){const{object:t,geometry:r}=e;if((r.morphAttributes.position||r.morphAttributes.normal||r.morphAttributes.color)&&yc(t).append(),!0===t.isSkinnedMesh&&lc(t).append(),this.displacementMap){const e=Ll("displacementMap","texture"),t=Ll("displacementScale","float"),r=Ll("displacementBias","float");tl.addAssign(cl.normalize().mul(e.x.mul(t).add(r)))}return t.isBatchedMesh&&oc(t).append(),t.isInstancedMesh&&t.instanceMatrix&&!0===t.instanceMatrix.isInstancedBufferAttribute&&ic(t).append(),null!==this.positionNode&&tl.assign(this.positionNode.context({isPositionNodeInput:!0})),tl}setupDiffuseColor({object:e,geometry:t}){let r=this.colorNode?$i(this.colorNode):dd;if(!0===this.vertexColors&&t.hasAttribute("color")&&(r=$i(r.xyz.mul(xu("color","vec3")),r.a)),e.instanceColor){r=ln("vec3","vInstanceColor").mul(r)}if(e.isBatchedMesh&&e._colorsTexture){r=ln("vec3","vBatchColor").mul(r)}dn.assign(r);const s=this.opacityNode?Bi(this.opacityNode):pd;if(dn.a.assign(dn.a.mul(s)),null!==this.alphaTestNode||this.alphaTest>0){const e=null!==this.alphaTestNode?Bi(this.alphaTestNode):ld;dn.a.lessThanEqual(e).discard()}!0===this.alphaHash&&dn.a.lessThan(rh(tl)).discard(),!1===this.transparent&&this.blending===U&&!1===this.alphaToCoverage&&dn.a.assign(1)}setupVariants(){}setupOutgoingLight(){return!0===this.lights?Oi(0):dn.rgb}setupNormal(){return this.normalNode?Oi(this.normalNode):_d}setupEnvironment(){let e=null;return this.envNode?e=this.envNode:this.envMap&&(e=this.envMap.isCubeTexture?Ll("envMap","cubeTexture"):Ll("envMap","texture")),e}setupLightMap(e){let t=null;return e.material.lightMap&&(t=new vc(Hd)),t}setupLights(e){const t=[],r=this.setupEnvironment(e);r&&r.isLightingNode&&t.push(r);const s=this.setupLightMap(e);if(s&&s.isLightingNode&&t.push(s),null!==this.aoNode||e.material.aoMap){const e=null!==this.aoNode?this.aoNode:Wd;t.push(new xc(e))}let i=this.lightsNode||e.lightsNode;return t.length>0&&(i=e.renderer.lighting.createNode([...i.getLights(),...t])),i}setupLightingModel(){}setupLighting(e){const{material:t}=e,{backdropNode:r,backdropAlphaNode:s,emissiveNode:i}=this,n=!0===this.lights||null!==this.lightsNode?this.setupLights(e):null;let o=this.setupOutgoingLight(e);if(n&&n.getScope().hasLights){const t=this.setupLightingModel(e);o=_c(n,t,r,s)}else null!==r&&(o=Oi(null!==s?pa(o,r,s):r));return(i&&!0===i.isNode||t.emissive&&!0===t.emissive.isColor)&&(cn.assign(Oi(i||hd)),o=o.add(cn)),o}setupOutput(e,t){if(!0===this.fog){const r=e.fogNode;r&&(En.assign(t),t=$i(r))}return t}setDefaultValues(e){for(const t in e){const r=e[t];void 0===this[t]&&(this[t]=r,r&&r.clone&&(this[t]=r.clone()))}const t=Object.getOwnPropertyDescriptors(e.constructor.prototype);for(const e in t)void 0===Object.getOwnPropertyDescriptor(this.constructor.prototype,e)&&void 0!==t[e].get&&Object.defineProperty(this.constructor.prototype,e,t[e])}toJSON(e){const t=void 0===e||"string"==typeof e;t&&(e={textures:{},images:{},nodes:{}});const r=F.prototype.toJSON.call(this,e),s=ps(this);r.inputNodes={};for(const{property:t,childNode:i}of s)r.inputNodes[t]=i.toJSON(e).uuid;function i(e){const t=[];for(const r in e){const s=e[r];delete s.metadata,t.push(s)}return t}if(t){const t=i(e.textures),s=i(e.images),n=i(e.nodes);t.length>0&&(r.textures=t),s.length>0&&(r.images=s),n.length>0&&(r.nodes=n)}return r}copy(e){return this.lightsNode=e.lightsNode,this.envNode=e.envNode,this.colorNode=e.colorNode,this.normalNode=e.normalNode,this.opacityNode=e.opacityNode,this.backdropNode=e.backdropNode,this.backdropAlphaNode=e.backdropAlphaNode,this.alphaTestNode=e.alphaTestNode,this.positionNode=e.positionNode,this.geometryNode=e.geometryNode,this.depthNode=e.depthNode,this.shadowPositionNode=e.shadowPositionNode,this.receivedShadowNode=e.receivedShadowNode,this.castShadowNode=e.castShadowNode,this.outputNode=e.outputNode,this.mrtNode=e.mrtNode,this.fragmentNode=e.fragmentNode,this.vertexNode=e.vertexNode,super.copy(e)}}const ih=new P;class nh extends sh{static get type(){return"InstancedPointsNodeMaterial"}constructor(e={}){super(),this.isInstancedPointsNodeMaterial=!0,this.useColor=e.vertexColors,this.pointWidth=1,this.pointColorNode=null,this.pointWidthNode=null,this._useAlphaToCoverage=!0,this.setDefaultValues(ih),this.setValues(e)}setup(e){const{renderer:t}=e,r=this._useAlphaToCoverage,s=this.useColor;this.vertexNode=Ai((()=>{const e=xu("instancePosition").xyz,t=$i(Yu.mul($i(e,1))),r=wc.z.div(wc.w),s=Mu.mul(t),i=el.xy.toVar();return i.mulAssign(this.pointWidthNode?this.pointWidthNode:zd),i.assign(i.div(wc.z)),i.y.assign(i.y.mul(r)),i.assign(i.mul(s.w)),s.addAssign($i(i,0,0)),s}))(),this.fragmentNode=Ai((()=>{const e=Bi(1).toVar(),i=ha(Tu().mul(2).sub(1));if(r&&t.samples>1){const t=Bi(i.fwidth()).toVar();e.assign(ya(t.oneMinus(),t.add(1),i).oneMinus())}else i.greaterThan(1).discard();let n;if(this.pointColorNode)n=this.pointColorNode;else if(s){n=xu("instanceColor").mul(dd)}else n=dd;return e.mulAssign(pd),$i(n,e)}))(),super.setup(e)}get alphaToCoverage(){return this._useAlphaToCoverage}set alphaToCoverage(e){this._useAlphaToCoverage!==e&&(this._useAlphaToCoverage=e,this.needsUpdate=!0)}}const oh=new I;class ah extends sh{static get type(){return"LineBasicNodeMaterial"}constructor(e){super(),this.isLineBasicNodeMaterial=!0,this.setDefaultValues(oh),this.setValues(e)}}const uh=new D;class lh extends sh{static get type(){return"LineDashedNodeMaterial"}constructor(e){super(),this.isLineDashedNodeMaterial=!0,this.setDefaultValues(uh),this.dashOffset=0,this.offsetNode=null,this.dashScaleNode=null,this.dashSizeNode=null,this.gapSizeNode=null,this.setValues(e)}setupVariants(){const e=this.offsetNode?Bi(this.offsetNode):kd,t=this.dashScaleNode?Bi(this.dashScaleNode):Ld,r=this.dashSizeNode?Bi(this.dashSizeNode):Vd,s=this.gapSizeNode?Bi(this.gapSizeNode):Od;wn.assign(r),Mn.assign(s);const i=Ia(xu("lineDistance").mul(t));(e?i.add(e):i).mod(wn.add(Mn)).greaterThan(wn).discard()}}let dh=null;class ch extends Lc{static get type(){return"ViewportSharedTextureNode"}constructor(e=Rc,t=null){null===dh&&(dh=new w),super(e,t,dh)}updateReference(){return this}}const hh=Ni(ch),ph=new D;class gh extends sh{static get type(){return"Line2NodeMaterial"}constructor(e={}){super(),this.isLine2NodeMaterial=!0,this.setDefaultValues(ph),this.useColor=e.vertexColors,this.dashOffset=0,this.lineWidth=1,this.lineColorNode=null,this.offsetNode=null,this.dashScaleNode=null,this.dashSizeNode=null,this.gapSizeNode=null,this.blending=L,this._useDash=e.dashed,this._useAlphaToCoverage=!0,this._useWorldUnits=!1,this.setValues(e)}setup(e){const{renderer:t}=e,r=this._useAlphaToCoverage,s=this.useColor,i=this._useDash,n=this._useWorldUnits,o=Ai((({start:e,end:t})=>{const r=Mu.element(2).element(2),s=Mu.element(3).element(2).mul(-.5).div(r).sub(e.z).div(t.z.sub(e.z));return $i(pa(e.xyz,t.xyz,s),t.w)})).setLayout({name:"trimSegment",type:"vec4",inputs:[{name:"start",type:"vec4"},{name:"end",type:"vec4"}]});this.vertexNode=Ai((()=>{const e=xu("instanceStart"),t=xu("instanceEnd"),r=$i(Yu.mul($i(e,1))).toVar("start"),s=$i(Yu.mul($i(t,1))).toVar("end");if(i){const e=this.dashScaleNode?Bi(this.dashScaleNode):Ld,t=this.offsetNode?Bi(this.offsetNode):kd,r=xu("instanceDistanceStart"),s=xu("instanceDistanceEnd");let i=el.y.lessThan(.5).select(e.mul(r),e.mul(s));i=i.add(t),ln("float","lineDistance").assign(i)}n&&(ln("vec3","worldStart").assign(r.xyz),ln("vec3","worldEnd").assign(s.xyz));const a=wc.z.div(wc.w),u=Mu.element(2).element(3).equal(-1);Ei(u,(()=>{Ei(r.z.lessThan(0).and(s.z.greaterThan(0)),(()=>{s.assign(o({start:r,end:s}))})).ElseIf(s.z.lessThan(0).and(r.z.greaterThanEqual(0)),(()=>{r.assign(o({start:s,end:r}))}))}));const l=Mu.mul(r),d=Mu.mul(s),c=l.xyz.div(l.w),h=d.xyz.div(d.w),p=h.xy.sub(c.xy).toVar();p.x.assign(p.x.mul(a)),p.assign(p.normalize());const g=$i().toVar();if(n){const e=s.xyz.sub(r.xyz).normalize(),t=pa(r.xyz,s.xyz,.5).normalize(),n=e.cross(t).normalize(),o=e.cross(n),a=ln("vec4","worldPos");a.assign(el.y.lessThan(.5).select(r,s));const u=Gd.mul(.5);a.addAssign($i(el.x.lessThan(0).select(n.mul(u),n.mul(u).negate()),0)),i||(a.addAssign($i(el.y.lessThan(.5).select(e.mul(u).negate(),e.mul(u)),0)),a.addAssign($i(o.mul(u),0)),Ei(el.y.greaterThan(1).or(el.y.lessThan(0)),(()=>{a.subAssign($i(o.mul(2).mul(u),0))}))),g.assign(Mu.mul(a));const l=Oi().toVar();l.assign(el.y.lessThan(.5).select(c,h)),g.z.assign(l.z.mul(g.w))}else{const e=Ii(p.y,p.x.negate()).toVar("offset");p.x.assign(p.x.div(a)),e.x.assign(e.x.div(a)),e.assign(el.x.lessThan(0).select(e.negate(),e)),Ei(el.y.lessThan(0),(()=>{e.assign(e.sub(p))})).ElseIf(el.y.greaterThan(1),(()=>{e.assign(e.add(p))})),e.assign(e.mul(Gd)),e.assign(e.div(wc.w)),g.assign(el.y.lessThan(.5).select(l,d)),e.assign(e.mul(g.w)),g.assign(g.add($i(e,0,0)))}return g}))();const a=Ai((({p1:e,p2:t,p3:r,p4:s})=>{const i=e.sub(r),n=s.sub(r),o=t.sub(e),a=i.dot(n),u=n.dot(o),l=i.dot(o),d=n.dot(n),c=o.dot(o).mul(d).sub(u.mul(u)),h=a.mul(u).sub(l.mul(d)).div(c).clamp(),p=a.add(u.mul(h)).div(d).clamp();return Ii(h,p)}));if(this.colorNode=Ai((()=>{const e=Tu();if(i){const t=this.dashSizeNode?Bi(this.dashSizeNode):Vd,r=this.gapSizeNode?Bi(this.gapSizeNode):Od;wn.assign(t),Mn.assign(r);const s=ln("float","lineDistance");e.y.lessThan(-1).or(e.y.greaterThan(1)).discard(),s.mod(wn.add(Mn)).greaterThan(wn).discard()}const o=Bi(1).toVar("alpha");if(n){const e=ln("vec3","worldStart"),s=ln("vec3","worldEnd"),n=ln("vec4","worldPos").xyz.normalize().mul(1e5),u=s.sub(e),l=a({p1:e,p2:s,p3:Oi(0,0,0),p4:n}),d=e.add(u.mul(l.x)),c=n.mul(l.y),h=d.sub(c).length().div(Gd);if(!i)if(r&&t.samples>1){const e=h.fwidth();o.assign(ya(e.negate().add(.5),e.add(.5),h).oneMinus())}else h.greaterThan(.5).discard()}else if(r&&t.samples>1){const t=e.x,r=e.y.greaterThan(0).select(e.y.sub(1),e.y.add(1)),s=t.mul(t).add(r.mul(r)),i=Bi(s.fwidth()).toVar("dlen");Ei(e.y.abs().greaterThan(1),(()=>{o.assign(ya(i.oneMinus(),i.add(1),s).oneMinus())}))}else Ei(e.y.abs().greaterThan(1),(()=>{const t=e.x,r=e.y.greaterThan(0).select(e.y.sub(1),e.y.add(1));t.mul(t).add(r.mul(r)).greaterThan(1).discard()}));let u;if(this.lineColorNode)u=this.lineColorNode;else if(s){const e=xu("instanceColorStart"),t=xu("instanceColorEnd");u=el.y.lessThan(.5).select(e,t).mul(dd)}else u=dd;return $i(u,o)}))(),this.transparent){const e=this.opacityNode?Bi(this.opacityNode):pd;this.outputNode=$i(this.colorNode.rgb.mul(e).add(hh().rgb.mul(e.oneMinus())),this.colorNode.a)}super.setup(e)}get worldUnits(){return this._useWorldUnits}set worldUnits(e){this._useWorldUnits!==e&&(this._useWorldUnits=e,this.needsUpdate=!0)}get dashed(){return this._useDash}set dashed(e){this._useDash!==e&&(this._useDash=e,this.needsUpdate=!0)}get alphaToCoverage(){return this._useAlphaToCoverage}set alphaToCoverage(e){this._useAlphaToCoverage!==e&&(this._useAlphaToCoverage=e,this.needsUpdate=!0)}}const mh=e=>Ti(e).mul(.5).add(.5),fh=new V;class yh extends sh{static get type(){return"MeshNormalNodeMaterial"}constructor(e){super(),this.isMeshNormalNodeMaterial=!0,this.setDefaultValues(fh),this.setValues(e)}setupDiffuseColor(){const e=this.opacityNode?Bi(this.opacityNode):pd;dn.assign($i(mh(ml),e))}}class bh extends Ls{static get type(){return"EquirectUVNode"}constructor(e=il){super("vec2"),this.dirNode=e}setup(){const e=this.dirNode,t=e.z.atan(e.x).mul(1/(2*Math.PI)).add(.5),r=e.y.clamp(-1,1).asin().mul(1/Math.PI).add(.5);return Ii(t,r)}}const xh=Ni(bh);class Th extends O{constructor(e=1,t={}){super(e,t),this.isCubeRenderTarget=!0}fromEquirectangularTexture(e,t){const r=t.minFilter,s=t.generateMipmaps;t.generateMipmaps=!0,this.texture.type=t.type,this.texture.colorSpace=t.colorSpace,this.texture.generateMipmaps=t.generateMipmaps,this.texture.minFilter=t.minFilter,this.texture.magFilter=t.magFilter;const i=new G(5,5,5),n=xh(il),o=new sh;o.colorNode=Ru(t,n,0),o.side=T,o.blending=L;const a=new k(i,o),u=new z;u.add(a),t.minFilter===M&&(t.minFilter=$);const l=new H(1,10,this),d=e.getMRT();return e.setMRT(null),l.update(e,u),e.setMRT(d),t.minFilter=r,t.currentGenerateMipmaps=s,a.geometry.dispose(),a.material.dispose(),this}}const _h=new WeakMap;class vh extends Ls{static get type(){return"CubeMapNode"}constructor(e){super("vec3"),this.envNode=e,this._cubeTexture=null,this._cubeTextureNode=Rl();const t=new W;t.isRenderTargetTexture=!0,this._defaultTexture=t,this.updateBeforeType=Rs.RENDER}updateBefore(e){const{renderer:t,material:r}=e,s=this.envNode;if(s.isTextureNode||s.isMaterialReferenceNode){const e=s.isTextureNode?s.value:r[s.property];if(e&&e.isTexture){const r=e.mapping;if(r===j||r===q){if(_h.has(e)){const t=_h.get(e);Sh(t,e.mapping),this._cubeTexture=t}else{const r=e.image;if(function(e){return null!=e&&e.height>0}(r)){const s=new Th(r.height);s.fromEquirectangularTexture(t,e),Sh(s.texture,e.mapping),this._cubeTexture=s.texture,_h.set(e,s.texture),e.addEventListener("dispose",Nh)}else this._cubeTexture=this._defaultTexture}this._cubeTextureNode.value=this._cubeTexture}else this._cubeTextureNode=this.envNode}}}setup(e){return this.updateBefore(e),this._cubeTextureNode}}function Nh(e){const t=e.target;t.removeEventListener("dispose",Nh);const r=_h.get(t);void 0!==r&&(_h.delete(t),r.dispose())}function Sh(e,t){t===j?e.mapping=_:t===q&&(e.mapping=v)}const Ah=Ni(vh);class Rh extends bc{static get type(){return"BasicEnvironmentNode"}constructor(e=null){super(),this.envNode=e}setup(e){e.context.environment=Ah(this.envNode)}}class Ch extends bc{static get type(){return"BasicLightMapNode"}constructor(e=null){super(),this.lightMapNode=e}setup(e){const t=Bi(1/Math.PI);e.context.irradianceLightMap=this.lightMapNode.mul(t)}}class Eh{start(){}finish(){}direct(){}directRectArea(){}indirect(){}ambientOcclusion(){}}class wh extends Eh{constructor(){super()}indirect(e,t,r){const s=e.ambientOcclusion,i=e.reflectedLight,n=r.context.irradianceLightMap;i.indirectDiffuse.assign($i(0)),n?i.indirectDiffuse.addAssign(n):i.indirectDiffuse.addAssign($i(1,1,1,0)),i.indirectDiffuse.mulAssign(s),i.indirectDiffuse.mulAssign(dn.rgb)}finish(e,t,r){const s=r.material,i=e.outgoingLight,n=r.context.environment;if(n)switch(s.combine){case Y:i.rgb.assign(pa(i.rgb,i.rgb.mul(n.rgb),yd.mul(bd)));break;case X:i.rgb.assign(pa(i.rgb,n.rgb,yd.mul(bd)));break;case K:i.rgb.addAssign(n.rgb.mul(yd.mul(bd)));break;default:console.warn("THREE.BasicLightingModel: Unsupported .combine value:",s.combine)}}}const Mh=new Q;class Bh extends sh{static get type(){return"MeshBasicNodeMaterial"}constructor(e){super(),this.isMeshBasicNodeMaterial=!0,this.lights=!0,this.setDefaultValues(Mh),this.setValues(e)}setupNormal(){return pl}setupEnvironment(e){const t=super.setupEnvironment(e);return t?new Rh(t):null}setupLightMap(e){let t=null;return e.material.lightMap&&(t=new Ch(Hd)),t}setupOutgoingLight(){return dn.rgb}setupLightingModel(){return new wh}}const Fh=Ai((({f0:e,f90:t,dotVH:r})=>{const s=r.mul(-5.55473).sub(6.98316).mul(r).exp2();return e.mul(s.oneMinus()).add(t.mul(s))})),Uh=Ai((e=>e.diffuseColor.mul(1/Math.PI))),Ph=Ai((({dotNH:e})=>Cn.mul(Bi(.5)).add(1).mul(Bi(1/Math.PI)).mul(e.pow(Cn)))),Ih=Ai((({lightDirection:e})=>{const t=e.add(ol).normalize(),r=ml.dot(t).clamp(),s=ol.dot(t).clamp(),i=Fh({f0:An,f90:1,dotVH:s}),n=Bi(.25),o=Ph({dotNH:r});return i.mul(n).mul(o)}));class Dh extends wh{constructor(e=!0){super(),this.specular=e}direct({lightDirection:e,lightColor:t,reflectedLight:r}){const s=ml.dot(e).clamp().mul(t);r.directDiffuse.addAssign(s.mul(Uh({diffuseColor:dn.rgb}))),!0===this.specular&&r.directSpecular.addAssign(s.mul(Ih({lightDirection:e})).mul(yd))}indirect({ambientOcclusion:e,irradiance:t,reflectedLight:r}){r.indirectDiffuse.addAssign(t.mul(Uh({diffuseColor:dn}))),r.indirectDiffuse.mulAssign(e)}}const Lh=new Z;class Vh extends sh{static get type(){return"MeshLambertNodeMaterial"}constructor(e){super(),this.isMeshLambertNodeMaterial=!0,this.lights=!0,this.setDefaultValues(Lh),this.setValues(e)}setupEnvironment(e){const t=super.setupEnvironment(e);return t?new Rh(t):null}setupLightingModel(){return new Dh(!1)}}const Oh=new J;class Gh extends sh{static get type(){return"MeshPhongNodeMaterial"}constructor(e){super(),this.isMeshPhongNodeMaterial=!0,this.lights=!0,this.shininessNode=null,this.specularNode=null,this.setDefaultValues(Oh),this.setValues(e)}setupEnvironment(e){const t=super.setupEnvironment(e);return t?new Rh(t):null}setupLightingModel(){return new Dh}setupVariants(){const e=(this.shininessNode?Bi(this.shininessNode):cd).max(1e-4);Cn.assign(e);const t=this.specularNode||gd;An.assign(t)}copy(e){return this.shininessNode=e.shininessNode,this.specularNode=e.specularNode,super.copy(e)}}const kh=Ai((e=>{if(!1===e.geometry.hasAttribute("normal"))return Bi(0);const t=pl.dFdx().abs().max(pl.dFdy().abs());return t.x.max(t.y).max(t.z)})),zh=Ai((e=>{const{roughness:t}=e,r=kh();let s=t.max(.0525);return s=s.add(r),s=s.min(1),s})),$h=Ai((({alpha:e,dotNL:t,dotNV:r})=>{const s=e.pow2(),i=t.mul(s.add(s.oneMinus().mul(r.pow2())).sqrt()),n=r.mul(s.add(s.oneMinus().mul(t.pow2())).sqrt());return jn(.5,i.add(n).max(po))})).setLayout({name:"V_GGX_SmithCorrelated",type:"float",inputs:[{name:"alpha",type:"float"},{name:"dotNL",type:"float"},{name:"dotNV",type:"float"}]}),Hh=Ai((({alphaT:e,alphaB:t,dotTV:r,dotBV:s,dotTL:i,dotBL:n,dotNV:o,dotNL:a})=>{const u=a.mul(Oi(e.mul(r),t.mul(s),o).length()),l=o.mul(Oi(e.mul(i),t.mul(n),a).length());return jn(.5,u.add(l)).saturate()})).setLayout({name:"V_GGX_SmithCorrelated_Anisotropic",type:"float",inputs:[{name:"alphaT",type:"float",qualifier:"in"},{name:"alphaB",type:"float",qualifier:"in"},{name:"dotTV",type:"float",qualifier:"in"},{name:"dotBV",type:"float",qualifier:"in"},{name:"dotTL",type:"float",qualifier:"in"},{name:"dotBL",type:"float",qualifier:"in"},{name:"dotNV",type:"float",qualifier:"in"},{name:"dotNL",type:"float",qualifier:"in"}]}),Wh=Ai((({alpha:e,dotNH:t})=>{const r=e.pow2(),s=t.pow2().mul(r.oneMinus()).oneMinus();return r.div(s.pow2()).mul(1/Math.PI)})).setLayout({name:"D_GGX",type:"float",inputs:[{name:"alpha",type:"float"},{name:"dotNH",type:"float"}]}),jh=Bi(1/Math.PI),qh=Ai((({alphaT:e,alphaB:t,dotNH:r,dotTH:s,dotBH:i})=>{const n=e.mul(t),o=Oi(t.mul(s),e.mul(i),n.mul(r)),a=o.dot(o),u=n.div(a);return jh.mul(n.mul(u.pow2()))})).setLayout({name:"D_GGX_Anisotropic",type:"float",inputs:[{name:"alphaT",type:"float",qualifier:"in"},{name:"alphaB",type:"float",qualifier:"in"},{name:"dotNH",type:"float",qualifier:"in"},{name:"dotTH",type:"float",qualifier:"in"},{name:"dotBH",type:"float",qualifier:"in"}]}),Kh=Ai((e=>{const{lightDirection:t,f0:r,f90:s,roughness:i,f:n,USE_IRIDESCENCE:o,USE_ANISOTROPY:a}=e,u=e.normalView||ml,l=i.pow2(),d=t.add(ol).normalize(),c=u.dot(t).clamp(),h=u.dot(ol).clamp(),p=u.dot(d).clamp(),g=ol.dot(d).clamp();let m,f,y=Fh({f0:r,f90:s,dotVH:g});if(yi(o)&&(y=bn.mix(y,n)),yi(a)){const e=Nn.dot(t),r=Nn.dot(ol),s=Nn.dot(d),i=Sn.dot(t),n=Sn.dot(ol),o=Sn.dot(d);m=Hh({alphaT:_n,alphaB:l,dotTV:r,dotBV:n,dotTL:e,dotBL:i,dotNV:h,dotNL:c}),f=qh({alphaT:_n,alphaB:l,dotNH:p,dotTH:s,dotBH:o})}else m=$h({alpha:l,dotNL:c,dotNV:h}),f=Wh({alpha:l,dotNH:p});return y.mul(m).mul(f)})),Xh=Ai((({roughness:e,dotNV:t})=>{const r=$i(-1,-.0275,-.572,.022),s=$i(1,.0425,1.04,-.04),i=e.mul(r).add(s),n=i.x.mul(i.x).min(t.mul(-9.28).exp2()).mul(i.x).add(i.y);return Ii(-1.04,1.04).mul(n).add(i.zw)})).setLayout({name:"DFGApprox",type:"vec2",inputs:[{name:"roughness",type:"float"},{name:"dotNV",type:"vec3"}]}),Yh=Ai((e=>{const{dotNV:t,specularColor:r,specularF90:s,roughness:i}=e,n=Xh({dotNV:t,roughness:i});return r.mul(n.x).add(s.mul(n.y))})),Qh=Ai((({f:e,f90:t,dotVH:r})=>{const s=r.oneMinus().saturate(),i=s.mul(s),n=s.mul(i,i).clamp(0,.9999);return e.sub(Oi(t).mul(n)).div(n.oneMinus())})).setLayout({name:"Schlick_to_F0",type:"vec3",inputs:[{name:"f",type:"vec3"},{name:"f90",type:"float"},{name:"dotVH",type:"float"}]}),Zh=Ai((({roughness:e,dotNH:t})=>{const r=e.pow2(),s=Bi(1).div(r),i=t.pow2().oneMinus().max(.0078125);return Bi(2).add(s).mul(i.pow(s.mul(.5))).div(2*Math.PI)})).setLayout({name:"D_Charlie",type:"float",inputs:[{name:"roughness",type:"float"},{name:"dotNH",type:"float"}]}),Jh=Ai((({dotNV:e,dotNL:t})=>Bi(1).div(Bi(4).mul(t.add(e).sub(t.mul(e)))))).setLayout({name:"V_Neubelt",type:"float",inputs:[{name:"dotNV",type:"float"},{name:"dotNL",type:"float"}]}),ep=Ai((({lightDirection:e})=>{const t=e.add(ol).normalize(),r=ml.dot(e).clamp(),s=ml.dot(ol).clamp(),i=ml.dot(t).clamp(),n=Zh({roughness:yn,dotNH:i}),o=Jh({dotNV:s,dotNL:r});return fn.mul(n).mul(o)})),tp=Ai((({N:e,V:t,roughness:r})=>{const s=e.dot(t).saturate(),i=Ii(r,s.oneMinus().sqrt());return i.assign(i.mul(.984375).add(.0078125)),i})).setLayout({name:"LTC_Uv",type:"vec2",inputs:[{name:"N",type:"vec3"},{name:"V",type:"vec3"},{name:"roughness",type:"float"}]}),rp=Ai((({f:e})=>{const t=e.length();return Zo(t.mul(t).add(e.z).div(t.add(1)),0)})).setLayout({name:"LTC_ClippedSphereFormFactor",type:"float",inputs:[{name:"f",type:"vec3"}]}),sp=Ai((({v1:e,v2:t})=>{const r=e.dot(t),s=r.abs().toVar(),i=s.mul(.0145206).add(.4965155).mul(s).add(.8543985).toVar(),n=s.add(4.1616724).mul(s).add(3.417594).toVar(),o=i.div(n),a=r.greaterThan(0).select(o,Zo(r.mul(r).oneMinus(),1e-7).inverseSqrt().mul(.5).sub(o));return e.cross(t).mul(a)})).setLayout({name:"LTC_EdgeVectorFormFactor",type:"vec3",inputs:[{name:"v1",type:"vec3"},{name:"v2",type:"vec3"}]}),ip=Ai((({N:e,V:t,P:r,mInv:s,p0:i,p1:n,p2:o,p3:a})=>{const u=n.sub(i).toVar(),l=a.sub(i).toVar(),d=u.cross(l),c=Oi().toVar();return Ei(d.dot(r.sub(i)).greaterThanEqual(0),(()=>{const u=t.sub(e.mul(t.dot(e))).normalize(),l=e.cross(u).negate(),d=s.mul(Ki(u,l,e).transpose()).toVar(),h=d.mul(i.sub(r)).normalize().toVar(),p=d.mul(n.sub(r)).normalize().toVar(),g=d.mul(o.sub(r)).normalize().toVar(),m=d.mul(a.sub(r)).normalize().toVar(),f=Oi(0).toVar();f.addAssign(sp({v1:h,v2:p})),f.addAssign(sp({v1:p,v2:g})),f.addAssign(sp({v1:g,v2:m})),f.addAssign(sp({v1:m,v2:h})),c.assign(Oi(rp({f:f})))})),c})).setLayout({name:"LTC_Evaluate",type:"vec3",inputs:[{name:"N",type:"vec3"},{name:"V",type:"vec3"},{name:"P",type:"vec3"},{name:"mInv",type:"mat3"},{name:"p0",type:"vec3"},{name:"p1",type:"vec3"},{name:"p2",type:"vec3"},{name:"p3",type:"vec3"}]}),np=1/6,op=e=>Wn(np,Wn(e,Wn(e,e.negate().add(3)).sub(3)).add(1)),ap=e=>Wn(np,Wn(e,Wn(e,Wn(3,e).sub(6))).add(4)),up=e=>Wn(np,Wn(e,Wn(e,Wn(-3,e).add(3)).add(3)).add(1)),lp=e=>Wn(np,oa(e,3)),dp=e=>op(e).add(ap(e)),cp=e=>up(e).add(lp(e)),hp=e=>$n(-1,ap(e).div(op(e).add(ap(e)))),pp=e=>$n(1,lp(e).div(up(e).add(lp(e)))),gp=(e,t,r)=>{const s=e.uvNode,i=Wn(s,t.zw).add(.5),n=Co(i),o=Mo(i),a=dp(o.x),u=cp(o.x),l=hp(o.x),d=pp(o.x),c=hp(o.y),h=pp(o.y),p=Ii(n.x.add(l),n.y.add(c)).sub(.5).mul(t.xy),g=Ii(n.x.add(d),n.y.add(c)).sub(.5).mul(t.xy),m=Ii(n.x.add(l),n.y.add(h)).sub(.5).mul(t.xy),f=Ii(n.x.add(d),n.y.add(h)).sub(.5).mul(t.xy),y=dp(o.y).mul($n(a.mul(e.sample(p).level(r)),u.mul(e.sample(g).level(r)))),b=cp(o.y).mul($n(a.mul(e.sample(m).level(r)),u.mul(e.sample(f).level(r))));return y.add(b)},mp=Ai((([e,t=Bi(3)])=>{const r=Ii(e.size(Fi(t))),s=Ii(e.size(Fi(t.add(1)))),i=jn(1,r),n=jn(1,s),o=gp(e,$i(i,r),Co(t)),a=gp(e,$i(n,s),Eo(t));return Mo(t).mix(o,a)})),fp=Ai((([e,t,r,s,i])=>{const n=Oi(fa(t.negate(),wo(e),jn(1,s))),o=Oi(Oo(i[0].xyz),Oo(i[1].xyz),Oo(i[2].xyz));return wo(n).mul(r.mul(o))})).setLayout({name:"getVolumeTransmissionRay",type:"vec3",inputs:[{name:"n",type:"vec3"},{name:"v",type:"vec3"},{name:"thickness",type:"float"},{name:"ior",type:"float"},{name:"modelMatrix",type:"mat4"}]}),yp=Ai((([e,t])=>e.mul(ga(t.mul(2).sub(2),0,1)))).setLayout({name:"applyIorToRoughness",type:"float",inputs:[{name:"roughness",type:"float"},{name:"ior",type:"float"}]}),bp=Oc(),xp=Oc(),Tp=Ai((([e,t,r],{material:s})=>{const i=(s.side===T?bp:xp).sample(e),n=So(Cc.x).mul(yp(t,r));return mp(i,n)})),_p=Ai((([e,t,r])=>(Ei(r.notEqual(0),(()=>{const s=No(t).negate().div(r);return _o(s.negate().mul(e))})),Oi(1)))).setLayout({name:"volumeAttenuation",type:"vec3",inputs:[{name:"transmissionDistance",type:"float"},{name:"attenuationColor",type:"vec3"},{name:"attenuationDistance",type:"float"}]}),vp=Ai((([e,t,r,s,i,n,o,a,u,l,d,c,h,p,g])=>{let m,f;if(g){m=$i().toVar(),f=Oi().toVar();const i=d.sub(1).mul(g.mul(.025)),n=Oi(d.sub(i),d,d.add(i));cc({start:0,end:3},(({i:i})=>{const d=n.element(i),g=fp(e,t,c,d,a),y=o.add(g),b=l.mul(u.mul($i(y,1))),x=Ii(b.xy.div(b.w)).toVar();x.addAssign(1),x.divAssign(2),x.assign(Ii(x.x,x.y.oneMinus()));const T=Tp(x,r,d);m.element(i).assign(T.element(i)),m.a.addAssign(T.a),f.element(i).assign(s.element(i).mul(_p(Oo(g),h,p).element(i)))})),m.a.divAssign(3)}else{const i=fp(e,t,c,d,a),n=o.add(i),g=l.mul(u.mul($i(n,1))),y=Ii(g.xy.div(g.w)).toVar();y.addAssign(1),y.divAssign(2),y.assign(Ii(y.x,y.y.oneMinus())),m=Tp(y,r,d),f=s.mul(_p(Oo(i),h,p))}const y=f.rgb.mul(m.rgb),b=e.dot(t).clamp(),x=Oi(Yh({dotNV:b,specularColor:i,specularF90:n,roughness:r})),T=f.r.add(f.g,f.b).div(3);return $i(x.oneMinus().mul(y),m.a.oneMinus().mul(T).oneMinus())})),Np=Ki(3.2404542,-.969266,.0556434,-1.5371385,1.8760108,-.2040259,-.4985314,.041556,1.0572252),Sp=(e,t)=>e.sub(t).div(e.add(t)).pow2(),Ap=Ai((({outsideIOR:e,eta2:t,cosTheta1:r,thinFilmThickness:s,baseF0:i})=>{const n=pa(e,t,ya(0,.03,s)),o=e.div(n).pow2().mul(r.pow2().oneMinus()).oneMinus();Ei(o.lessThan(0),(()=>Oi(1)));const a=o.sqrt(),u=Sp(n,e),l=Fh({f0:u,f90:1,dotVH:r}),d=l.oneMinus(),c=n.lessThan(e).select(Math.PI,0),h=Bi(Math.PI).sub(c),p=(e=>{const t=e.sqrt();return Oi(1).add(t).div(Oi(1).sub(t))})(i.clamp(0,.9999)),g=Sp(p,n.toVec3()),m=Fh({f0:g,f90:1,dotVH:a}),f=Oi(p.x.lessThan(n).select(Math.PI,0),p.y.lessThan(n).select(Math.PI,0),p.z.lessThan(n).select(Math.PI,0)),y=n.mul(s,a,2),b=Oi(h).add(f),x=l.mul(m).clamp(1e-5,.9999),T=x.sqrt(),_=d.pow2().mul(m).div(Oi(1).sub(x)),v=l.add(_).toVar(),N=_.sub(d).toVar();return cc({start:1,end:2,condition:"<=",name:"m"},(({m:e})=>{N.mulAssign(T);const t=((e,t)=>{const r=e.mul(2*Math.PI*1e-9),s=Oi(54856e-17,44201e-17,52481e-17),i=Oi(1681e3,1795300,2208400),n=Oi(43278e5,93046e5,66121e5),o=Bi(9747e-17*Math.sqrt(2*Math.PI*45282e5)).mul(r.mul(2239900).add(t.x).cos()).mul(r.pow2().mul(-45282e5).exp());let a=s.mul(n.mul(2*Math.PI).sqrt()).mul(i.mul(r).add(t).cos()).mul(r.pow2().negate().mul(n).exp());return a=Oi(a.x.add(o),a.y,a.z).div(1.0685e-7),Np.mul(a)})(Bi(e).mul(y),Bi(e).mul(b)).mul(2);v.addAssign(N.mul(t))})),v.max(Oi(0))})).setLayout({name:"evalIridescence",type:"vec3",inputs:[{name:"outsideIOR",type:"float"},{name:"eta2",type:"float"},{name:"cosTheta1",type:"float"},{name:"thinFilmThickness",type:"float"},{name:"baseF0",type:"vec3"}]}),Rp=Ai((({normal:e,viewDir:t,roughness:r})=>{const s=e.dot(t).saturate(),i=r.pow2(),n=Ra(r.lessThan(.25),Bi(-339.2).mul(i).add(Bi(161.4).mul(r)).sub(25.9),Bi(-8.48).mul(i).add(Bi(14.3).mul(r)).sub(9.95)),o=Ra(r.lessThan(.25),Bi(44).mul(i).sub(Bi(23.7).mul(r)).add(3.26),Bi(1.97).mul(i).sub(Bi(3.27).mul(r)).add(.72));return Ra(r.lessThan(.25),0,Bi(.1).mul(r).sub(.025)).add(n.mul(s).add(o).exp()).mul(1/Math.PI).saturate()})),Cp=Oi(.04),Ep=Bi(1);class wp extends Eh{constructor(e=!1,t=!1,r=!1,s=!1,i=!1,n=!1){super(),this.clearcoat=e,this.sheen=t,this.iridescence=r,this.anisotropy=s,this.transmission=i,this.dispersion=n,this.clearcoatRadiance=null,this.clearcoatSpecularDirect=null,this.clearcoatSpecularIndirect=null,this.sheenSpecularDirect=null,this.sheenSpecularIndirect=null,this.iridescenceFresnel=null,this.iridescenceF0=null}start(e){if(!0===this.clearcoat&&(this.clearcoatRadiance=Oi().toVar("clearcoatRadiance"),this.clearcoatSpecularDirect=Oi().toVar("clearcoatSpecularDirect"),this.clearcoatSpecularIndirect=Oi().toVar("clearcoatSpecularIndirect")),!0===this.sheen&&(this.sheenSpecularDirect=Oi().toVar("sheenSpecularDirect"),this.sheenSpecularIndirect=Oi().toVar("sheenSpecularIndirect")),!0===this.iridescence){const e=ml.dot(ol).clamp();this.iridescenceFresnel=Ap({outsideIOR:Bi(1),eta2:xn,cosTheta1:e,thinFilmThickness:Tn,baseF0:An}),this.iridescenceF0=Qh({f:this.iridescenceFresnel,f90:1,dotVH:e})}if(!0===this.transmission){const t=sl,r=Iu.sub(sl).normalize(),s=fl;e.backdrop=vp(s,r,hn,dn,An,Rn,t,Hu,Fu,Mu,Fn,Pn,Dn,In,this.dispersion?Ln:null),e.backdropAlpha=Un,dn.a.mulAssign(pa(1,e.backdrop.a,Un))}}computeMultiscattering(e,t,r){const s=ml.dot(ol).clamp(),i=Xh({roughness:hn,dotNV:s}),n=(this.iridescenceF0?bn.mix(An,this.iridescenceF0):An).mul(i.x).add(r.mul(i.y)),o=i.x.add(i.y).oneMinus(),a=An.add(An.oneMinus().mul(.047619)),u=n.mul(a).div(o.mul(a).oneMinus());e.addAssign(n),t.addAssign(u.mul(o))}direct({lightDirection:e,lightColor:t,reflectedLight:r}){const s=ml.dot(e).clamp().mul(t);if(!0===this.sheen&&this.sheenSpecularDirect.addAssign(s.mul(ep({lightDirection:e}))),!0===this.clearcoat){const r=yl.dot(e).clamp().mul(t);this.clearcoatSpecularDirect.addAssign(r.mul(Kh({lightDirection:e,f0:Cp,f90:Ep,roughness:mn,normalView:yl})))}r.directDiffuse.addAssign(s.mul(Uh({diffuseColor:dn.rgb}))),r.directSpecular.addAssign(s.mul(Kh({lightDirection:e,f0:An,f90:1,roughness:hn,iridescence:this.iridescence,f:this.iridescenceFresnel,USE_IRIDESCENCE:this.iridescence,USE_ANISOTROPY:this.anisotropy})))}directRectArea({lightColor:e,lightPosition:t,halfWidth:r,halfHeight:s,reflectedLight:i,ltc_1:n,ltc_2:o}){const a=t.add(r).sub(s),u=t.sub(r).sub(s),l=t.sub(r).add(s),d=t.add(r).add(s),c=ml,h=ol,p=nl.toVar(),g=tp({N:c,V:h,roughness:hn}),m=n.sample(g).toVar(),f=o.sample(g).toVar(),y=Ki(Oi(m.x,0,m.y),Oi(0,1,0),Oi(m.z,0,m.w)).toVar(),b=An.mul(f.x).add(An.oneMinus().mul(f.y)).toVar();i.directSpecular.addAssign(e.mul(b).mul(ip({N:c,V:h,P:p,mInv:y,p0:a,p1:u,p2:l,p3:d}))),i.directDiffuse.addAssign(e.mul(dn).mul(ip({N:c,V:h,P:p,mInv:Ki(1,0,0,0,1,0,0,0,1),p0:a,p1:u,p2:l,p3:d})))}indirect(e,t,r){this.indirectDiffuse(e,t,r),this.indirectSpecular(e,t,r),this.ambientOcclusion(e,t,r)}indirectDiffuse({irradiance:e,reflectedLight:t}){t.indirectDiffuse.addAssign(e.mul(Uh({diffuseColor:dn})))}indirectSpecular({radiance:e,iblIrradiance:t,reflectedLight:r}){if(!0===this.sheen&&this.sheenSpecularIndirect.addAssign(t.mul(fn,Rp({normal:ml,viewDir:ol,roughness:yn}))),!0===this.clearcoat){const e=yl.dot(ol).clamp(),t=Yh({dotNV:e,specularColor:Cp,specularF90:Ep,roughness:mn});this.clearcoatSpecularIndirect.addAssign(this.clearcoatRadiance.mul(t))}const s=Oi().toVar("singleScattering"),i=Oi().toVar("multiScattering"),n=t.mul(1/Math.PI);this.computeMultiscattering(s,i,Rn);const o=s.add(i),a=dn.mul(o.r.max(o.g).max(o.b).oneMinus());r.indirectSpecular.addAssign(e.mul(s)),r.indirectSpecular.addAssign(i.mul(n)),r.indirectDiffuse.addAssign(a.mul(n))}ambientOcclusion({ambientOcclusion:e,reflectedLight:t}){const r=ml.dot(ol).clamp().add(e),s=hn.mul(-16).oneMinus().negate().exp2(),i=e.sub(r.pow(s).oneMinus()).clamp();!0===this.clearcoat&&this.clearcoatSpecularIndirect.mulAssign(e),!0===this.sheen&&this.sheenSpecularIndirect.mulAssign(e),t.indirectDiffuse.mulAssign(e),t.indirectSpecular.mulAssign(i)}finish(e){const{outgoingLight:t}=e;if(!0===this.clearcoat){const e=yl.dot(ol).clamp(),r=Fh({dotVH:e,f0:Cp,f90:Ep}),s=t.mul(gn.mul(r).oneMinus()).add(this.clearcoatSpecularDirect.add(this.clearcoatSpecularIndirect).mul(gn));t.assign(s)}if(!0===this.sheen){const e=fn.r.max(fn.g).max(fn.b).mul(.157).oneMinus(),r=t.mul(e).add(this.sheenSpecularDirect,this.sheenSpecularIndirect);t.assign(r)}}}const Mp=Bi(1),Bp=Bi(-2),Fp=Bi(.8),Up=Bi(-1),Pp=Bi(.4),Ip=Bi(2),Dp=Bi(.305),Lp=Bi(3),Vp=Bi(.21),Op=Bi(4),Gp=Bi(4),kp=Bi(16),zp=Ai((([e])=>{const t=Oi(Lo(e)).toVar(),r=Bi(-1).toVar();return Ei(t.x.greaterThan(t.z),(()=>{Ei(t.x.greaterThan(t.y),(()=>{r.assign(Ra(e.x.greaterThan(0),0,3))})).Else((()=>{r.assign(Ra(e.y.greaterThan(0),1,4))}))})).Else((()=>{Ei(t.z.greaterThan(t.y),(()=>{r.assign(Ra(e.z.greaterThan(0),2,5))})).Else((()=>{r.assign(Ra(e.y.greaterThan(0),1,4))}))})),r})).setLayout({name:"getFace",type:"float",inputs:[{name:"direction",type:"vec3"}]}),$p=Ai((([e,t])=>{const r=Ii().toVar();return Ei(t.equal(0),(()=>{r.assign(Ii(e.z,e.y).div(Lo(e.x)))})).ElseIf(t.equal(1),(()=>{r.assign(Ii(e.x.negate(),e.z.negate()).div(Lo(e.y)))})).ElseIf(t.equal(2),(()=>{r.assign(Ii(e.x.negate(),e.y).div(Lo(e.z)))})).ElseIf(t.equal(3),(()=>{r.assign(Ii(e.z.negate(),e.y).div(Lo(e.x)))})).ElseIf(t.equal(4),(()=>{r.assign(Ii(e.x.negate(),e.z).div(Lo(e.y)))})).Else((()=>{r.assign(Ii(e.x,e.y).div(Lo(e.z)))})),Wn(.5,r.add(1))})).setLayout({name:"getUV",type:"vec2",inputs:[{name:"direction",type:"vec3"},{name:"face",type:"float"}]}),Hp=Ai((([e])=>{const t=Bi(0).toVar();return Ei(e.greaterThanEqual(Fp),(()=>{t.assign(Mp.sub(e).mul(Up.sub(Bp)).div(Mp.sub(Fp)).add(Bp))})).ElseIf(e.greaterThanEqual(Pp),(()=>{t.assign(Fp.sub(e).mul(Ip.sub(Up)).div(Fp.sub(Pp)).add(Up))})).ElseIf(e.greaterThanEqual(Dp),(()=>{t.assign(Pp.sub(e).mul(Lp.sub(Ip)).div(Pp.sub(Dp)).add(Ip))})).ElseIf(e.greaterThanEqual(Vp),(()=>{t.assign(Dp.sub(e).mul(Op.sub(Lp)).div(Dp.sub(Vp)).add(Lp))})).Else((()=>{t.assign(Bi(-2).mul(So(Wn(1.16,e))))})),t})).setLayout({name:"roughnessToMip",type:"float",inputs:[{name:"roughness",type:"float"}]}),Wp=Ai((([e,t])=>{const r=e.toVar();r.assign(Wn(2,r).sub(1));const s=Oi(r,1).toVar();return Ei(t.equal(0),(()=>{s.assign(s.zyx)})).ElseIf(t.equal(1),(()=>{s.assign(s.xzy),s.xz.mulAssign(-1)})).ElseIf(t.equal(2),(()=>{s.x.mulAssign(-1)})).ElseIf(t.equal(3),(()=>{s.assign(s.zyx),s.xz.mulAssign(-1)})).ElseIf(t.equal(4),(()=>{s.assign(s.xzy),s.xy.mulAssign(-1)})).ElseIf(t.equal(5),(()=>{s.z.mulAssign(-1)})),s})).setLayout({name:"getDirection",type:"vec3",inputs:[{name:"uv",type:"vec2"},{name:"face",type:"float"}]}),jp=Ai((([e,t,r,s,i,n])=>{const o=Bi(r),a=Oi(t),u=ga(Hp(o),Bp,n),l=Mo(u),d=Co(u),c=Oi(qp(e,a,d,s,i,n)).toVar();return Ei(l.notEqual(0),(()=>{const t=Oi(qp(e,a,d.add(1),s,i,n)).toVar();c.assign(pa(c,t,l))})),c})),qp=Ai((([e,t,r,s,i,n])=>{const o=Bi(r).toVar(),a=Oi(t),u=Bi(zp(a)).toVar(),l=Bi(Zo(Gp.sub(o),0)).toVar();o.assign(Zo(o,Gp));const d=Bi(vo(o)).toVar(),c=Ii($p(a,u).mul(d.sub(2)).add(1)).toVar();return Ei(u.greaterThan(2),(()=>{c.y.addAssign(d),u.subAssign(3)})),c.x.addAssign(u.mul(d)),c.x.addAssign(l.mul(Wn(3,kp))),c.y.addAssign(Wn(4,vo(n).sub(d))),c.x.mulAssign(s),c.y.mulAssign(i),e.sample(c).grad(Ii(),Ii())})),Kp=Ai((({envMap:e,mipInt:t,outputDirection:r,theta:s,axis:i,CUBEUV_TEXEL_WIDTH:n,CUBEUV_TEXEL_HEIGHT:o,CUBEUV_MAX_MIP:a})=>{const u=Fo(s),l=r.mul(u).add(i.cross(r).mul(Bo(s))).add(i.mul(i.dot(r).mul(u.oneMinus())));return qp(e,l,t,n,o,a)})),Xp=Ai((({n:e,latitudinal:t,poleAxis:r,outputDirection:s,weights:i,samples:n,dTheta:o,mipInt:a,envMap:u,CUBEUV_TEXEL_WIDTH:l,CUBEUV_TEXEL_HEIGHT:d,CUBEUV_MAX_MIP:c})=>{const h=Oi(Ra(t,r,na(r,s))).toVar();Ei(yo(h.equals(Oi(0))),(()=>{h.assign(Oi(s.z,0,s.x.negate()))})),h.assign(wo(h));const p=Oi().toVar();return p.addAssign(i.element(Fi(0)).mul(Kp({theta:0,axis:h,outputDirection:s,mipInt:a,envMap:u,CUBEUV_TEXEL_WIDTH:l,CUBEUV_TEXEL_HEIGHT:d,CUBEUV_MAX_MIP:c}))),cc({start:Fi(1),end:e},(({i:e})=>{Ei(e.greaterThanEqual(n),(()=>{hc()}));const t=Bi(o.mul(Bi(e))).toVar();p.addAssign(i.element(e).mul(Kp({theta:t.mul(-1),axis:h,outputDirection:s,mipInt:a,envMap:u,CUBEUV_TEXEL_WIDTH:l,CUBEUV_TEXEL_HEIGHT:d,CUBEUV_MAX_MIP:c}))),p.addAssign(i.element(e).mul(Kp({theta:t,axis:h,outputDirection:s,mipInt:a,envMap:u,CUBEUV_TEXEL_WIDTH:l,CUBEUV_TEXEL_HEIGHT:d,CUBEUV_MAX_MIP:c})))})),$i(p,1)}));let Yp=null;const Qp=new WeakMap;function Zp(e){let t=Qp.get(e);if((void 0!==t?t.pmremVersion:-1)!==e.pmremVersion){const r=e.image;if(e.isCubeTexture){if(!function(e){if(null==e)return!1;let t=0;const r=6;for(let s=0;s0}(r))return null;t=Yp.fromEquirectangular(e,t)}t.pmremVersion=e.pmremVersion,Qp.set(e,t)}return t.texture}class Jp extends Ls{static get type(){return"PMREMNode"}constructor(e,t=null,r=null){super("vec3"),this._value=e,this._pmrem=null,this.uvNode=t,this.levelNode=r,this._generator=null;const s=new ee;s.isRenderTargetTexture=!0,this._texture=Ru(s),this._width=on(0),this._height=on(0),this._maxMip=on(0),this.updateBeforeType=Rs.RENDER}set value(e){this._value=e,this._pmrem=null}get value(){return this._value}updateFromTexture(e){const t=function(e){const t=Math.log2(e)-2,r=1/e;return{texelWidth:1/(3*Math.max(Math.pow(2,t),112)),texelHeight:r,maxMip:t}}(e.image.height);this._texture.value=e,this._width.value=t.texelWidth,this._height.value=t.texelHeight,this._maxMip.value=t.maxMip}updateBefore(){let e=this._pmrem;const t=e?e.pmremVersion:-1,r=this._value;t!==r.pmremVersion&&(e=!0===r.isPMREMTexture?r:Zp(r),null!==e&&(this._pmrem=e,this.updateFromTexture(e)))}setup(e){null===Yp&&(Yp=e.createPMREMGenerator()),this.updateBefore(e);let t=this.uvNode;null===t&&e.context.getUV&&(t=e.context.getUV(this));const r=this.value;e.renderer.coordinateSystem===u&&!0!==r.isPMREMTexture&&!0===r.isRenderTargetTexture&&(t=Oi(t.x.negate(),t.yz)),t=Oi(t.x,t.y.negate(),t.z);let s=this.levelNode;return null===s&&e.context.getTextureLevel&&(s=e.context.getTextureLevel(this)),jp(this._texture,t,s,this._width,this._height,this._maxMip)}}const eg=Ni(Jp),tg=new WeakMap;class rg extends bc{static get type(){return"EnvironmentNode"}constructor(e=null){super(),this.envNode=e}setup(e){const{material:t}=e;let r=this.envNode;if(r.isTextureNode||r.isMaterialReferenceNode){const e=r.isTextureNode?r.value:t[r.property];let s=tg.get(e);void 0===s&&(s=eg(e),tg.set(e,s)),r=s}const s=t.envMap?Pl("envMapIntensity","float",e.material):Pl("environmentIntensity","float",e.scene),i=!0===t.useAnisotropy||t.anisotropy>0?Jl:ml,n=r.context(sg(hn,i)).mul(s),o=r.context(ig(fl)).mul(Math.PI).mul(s),a=au(n),u=au(o);e.context.radiance.addAssign(a),e.context.iblIrradiance.addAssign(u);const l=e.context.lightingModel.clearcoatRadiance;if(l){const e=r.context(sg(mn,yl)).mul(s),t=au(e);l.addAssign(t)}}}const sg=(e,t)=>{let r=null;return{getUV:()=>(null===r&&(r=ol.negate().reflect(t),r=e.mul(e).mix(r,t).normalize(),r=r.transformDirection(Fu)),r),getTextureLevel:()=>e}},ig=e=>({getUV:()=>e,getTextureLevel:()=>Bi(1)}),ng=new te;class og extends sh{static get type(){return"MeshStandardNodeMaterial"}constructor(e){super(),this.isMeshStandardNodeMaterial=!0,this.lights=!0,this.emissiveNode=null,this.metalnessNode=null,this.roughnessNode=null,this.setDefaultValues(ng),this.setValues(e)}setupEnvironment(e){let t=super.setupEnvironment(e);return null===t&&e.environmentNode&&(t=e.environmentNode),t?new rg(t):null}setupLightingModel(){return new wp}setupSpecular(){const e=pa(Oi(.04),dn.rgb,pn);An.assign(e),Rn.assign(1)}setupVariants(){const e=this.metalnessNode?Bi(this.metalnessNode):Td;pn.assign(e);let t=this.roughnessNode?Bi(this.roughnessNode):xd;t=zh({roughness:t}),hn.assign(t),this.setupSpecular(),dn.assign($i(dn.rgb.mul(e.oneMinus()),dn.a))}copy(e){return this.emissiveNode=e.emissiveNode,this.metalnessNode=e.metalnessNode,this.roughnessNode=e.roughnessNode,super.copy(e)}}const ag=new re;class ug extends og{static get type(){return"MeshPhysicalNodeMaterial"}constructor(e){super(),this.isMeshPhysicalNodeMaterial=!0,this.clearcoatNode=null,this.clearcoatRoughnessNode=null,this.clearcoatNormalNode=null,this.sheenNode=null,this.sheenRoughnessNode=null,this.iridescenceNode=null,this.iridescenceIORNode=null,this.iridescenceThicknessNode=null,this.specularIntensityNode=null,this.specularColorNode=null,this.iorNode=null,this.transmissionNode=null,this.thicknessNode=null,this.attenuationDistanceNode=null,this.attenuationColorNode=null,this.dispersionNode=null,this.anisotropyNode=null,this.setDefaultValues(ag),this.setValues(e)}get useClearcoat(){return this.clearcoat>0||null!==this.clearcoatNode}get useIridescence(){return this.iridescence>0||null!==this.iridescenceNode}get useSheen(){return this.sheen>0||null!==this.sheenNode}get useAnisotropy(){return this.anisotropy>0||null!==this.anisotropyNode}get useTransmission(){return this.transmission>0||null!==this.transmissionNode}get useDispersion(){return this.dispersion>0||null!==this.dispersionNode}setupSpecular(){const e=this.iorNode?Bi(this.iorNode):Pd;Fn.assign(e),An.assign(pa(Qo(aa(Fn.sub(1).div(Fn.add(1))).mul(fd),Oi(1)).mul(md),dn.rgb,pn)),Rn.assign(pa(md,1,pn))}setupLightingModel(){return new wp(this.useClearcoat,this.useSheen,this.useIridescence,this.useAnisotropy,this.useTransmission,this.useDispersion)}setupVariants(e){if(super.setupVariants(e),this.useClearcoat){const e=this.clearcoatNode?Bi(this.clearcoatNode):vd,t=this.clearcoatRoughnessNode?Bi(this.clearcoatRoughnessNode):Nd;gn.assign(e),mn.assign(zh({roughness:t}))}if(this.useSheen){const e=this.sheenNode?Oi(this.sheenNode):Rd,t=this.sheenRoughnessNode?Bi(this.sheenRoughnessNode):Cd;fn.assign(e),yn.assign(t)}if(this.useIridescence){const e=this.iridescenceNode?Bi(this.iridescenceNode):wd,t=this.iridescenceIORNode?Bi(this.iridescenceIORNode):Md,r=this.iridescenceThicknessNode?Bi(this.iridescenceThicknessNode):Bd;bn.assign(e),xn.assign(t),Tn.assign(r)}if(this.useAnisotropy){const e=(this.anisotropyNode?Ii(this.anisotropyNode):Ed).toVar();vn.assign(e.length()),Ei(vn.equal(0),(()=>{e.assign(Ii(1,0))})).Else((()=>{e.divAssign(Ii(vn)),vn.assign(vn.saturate())})),_n.assign(vn.pow2().mix(hn.pow2(),1)),Nn.assign(Ql[0].mul(e.x).add(Ql[1].mul(e.y))),Sn.assign(Ql[1].mul(e.x).sub(Ql[0].mul(e.y)))}if(this.useTransmission){const e=this.transmissionNode?Bi(this.transmissionNode):Fd,t=this.thicknessNode?Bi(this.thicknessNode):Ud,r=this.attenuationDistanceNode?Bi(this.attenuationDistanceNode):Id,s=this.attenuationColorNode?Oi(this.attenuationColorNode):Dd;if(Un.assign(e),Pn.assign(t),In.assign(r),Dn.assign(s),this.useDispersion){const e=this.dispersionNode?Bi(this.dispersionNode):$d;Ln.assign(e)}}}setupClearcoatNormal(){return this.clearcoatNormalNode?Oi(this.clearcoatNormalNode):Sd}setup(e){e.context.setupClearcoatNormal=()=>this.setupClearcoatNormal(e),super.setup(e)}copy(e){return this.clearcoatNode=e.clearcoatNode,this.clearcoatRoughnessNode=e.clearcoatRoughnessNode,this.clearcoatNormalNode=e.clearcoatNormalNode,this.sheenNode=e.sheenNode,this.sheenRoughnessNode=e.sheenRoughnessNode,this.iridescenceNode=e.iridescenceNode,this.iridescenceIORNode=e.iridescenceIORNode,this.iridescenceThicknessNode=e.iridescenceThicknessNode,this.specularIntensityNode=e.specularIntensityNode,this.specularColorNode=e.specularColorNode,this.transmissionNode=e.transmissionNode,this.thicknessNode=e.thicknessNode,this.attenuationDistanceNode=e.attenuationDistanceNode,this.attenuationColorNode=e.attenuationColorNode,this.dispersionNode=e.dispersionNode,this.anisotropyNode=e.anisotropyNode,super.copy(e)}}class lg extends wp{constructor(e=!1,t=!1,r=!1,s=!1,i=!1,n=!1,o=!1){super(e,t,r,s,i,n),this.useSSS=o}direct({lightDirection:e,lightColor:t,reflectedLight:r},s,i){if(!0===this.useSSS){const s=i.material,{thicknessColorNode:n,thicknessDistortionNode:o,thicknessAmbientNode:a,thicknessAttenuationNode:u,thicknessPowerNode:l,thicknessScaleNode:d}=s,c=e.add(ml.mul(o)).normalize(),h=Bi(ol.dot(c.negate()).saturate().pow(l).mul(d)),p=Oi(h.add(a).mul(n));r.directDiffuse.addAssign(p.mul(u.mul(t)))}super.direct({lightDirection:e,lightColor:t,reflectedLight:r},s,i)}}class dg extends ug{static get type(){return"MeshSSSNodeMaterial"}constructor(e){super(e),this.thicknessColorNode=null,this.thicknessDistortionNode=Bi(.1),this.thicknessAmbientNode=Bi(0),this.thicknessAttenuationNode=Bi(.1),this.thicknessPowerNode=Bi(2),this.thicknessScaleNode=Bi(10)}get useSSS(){return null!==this.thicknessColorNode}setupLightingModel(){return new lg(this.useClearcoat,this.useSheen,this.useIridescence,this.useAnisotropy,this.useTransmission,this.useDispersion,this.useSSS)}copy(e){return this.thicknessColorNode=e.thicknessColorNode,this.thicknessDistortionNode=e.thicknessDistortionNode,this.thicknessAmbientNode=e.thicknessAmbientNode,this.thicknessAttenuationNode=e.thicknessAttenuationNode,this.thicknessPowerNode=e.thicknessPowerNode,this.thicknessScaleNode=e.thicknessScaleNode,super.copy(e)}}const cg=Ai((({normal:e,lightDirection:t,builder:r})=>{const s=e.dot(t),i=Ii(s.mul(.5).add(.5),0);if(r.material.gradientMap){const e=Ll("gradientMap","texture").context({getUV:()=>i});return Oi(e.r)}{const e=i.fwidth().mul(.5);return pa(Oi(.7),Oi(1),ya(Bi(.7).sub(e.x),Bi(.7).add(e.x),i.x))}}));class hg extends Eh{direct({lightDirection:e,lightColor:t,reflectedLight:r},s,i){const n=cg({normal:dl,lightDirection:e,builder:i}).mul(t);r.directDiffuse.addAssign(n.mul(Uh({diffuseColor:dn.rgb})))}indirect({ambientOcclusion:e,irradiance:t,reflectedLight:r}){r.indirectDiffuse.addAssign(t.mul(Uh({diffuseColor:dn}))),r.indirectDiffuse.mulAssign(e)}}const pg=new se;class gg extends sh{static get type(){return"MeshToonNodeMaterial"}constructor(e){super(),this.isMeshToonNodeMaterial=!0,this.lights=!0,this.setDefaultValues(pg),this.setValues(e)}setupLightingModel(){return new hg}}class mg extends Ls{static get type(){return"MatcapUVNode"}constructor(){super("vec2")}setup(){const e=Oi(ol.z,0,ol.x.negate()).normalize(),t=ol.cross(e);return Ii(e.dot(ml),t.dot(ml)).mul(.495).add(.5)}}const fg=Si(mg),yg=new ie;class bg extends sh{static get type(){return"MeshMatcapNodeMaterial"}constructor(e){super(),this.isMeshMatcapNodeMaterial=!0,this.setDefaultValues(yg),this.setValues(e)}setupVariants(e){const t=fg;let r;r=e.material.matcap?Ll("matcap","texture").context({getUV:()=>t}):Oi(pa(.2,.8,t.y)),dn.rgb.mulAssign(r.rgb)}}const xg=new P;class Tg extends sh{static get type(){return"PointsNodeMaterial"}constructor(e){super(),this.isPointsNodeMaterial=!0,this.setDefaultValues(xg),this.setValues(e)}}class _g extends Ls{static get type(){return"RotateNode"}constructor(e,t){super(),this.positionNode=e,this.rotationNode=t}getNodeType(e){return this.positionNode.getNodeType(e)}setup(e){const{rotationNode:t,positionNode:r}=this;if("vec2"===this.getNodeType(e)){const e=t.cos(),s=t.sin();return qi(e,s,s.negate(),e).mul(r)}{const e=t,s=Xi($i(1,0,0,0),$i(0,Fo(e.x),Bo(e.x).negate(),0),$i(0,Bo(e.x),Fo(e.x),0),$i(0,0,0,1)),i=Xi($i(Fo(e.y),0,Bo(e.y),0),$i(0,1,0,0),$i(Bo(e.y).negate(),0,Fo(e.y),0),$i(0,0,0,1)),n=Xi($i(Fo(e.z),Bo(e.z).negate(),0,0),$i(Bo(e.z),Fo(e.z),0,0),$i(0,0,1,0),$i(0,0,0,1));return s.mul(i).mul(n).mul($i(r,1)).xyz}}}const vg=Ni(_g),Ng=new ne;class Sg extends sh{static get type(){return"SpriteNodeMaterial"}constructor(e){super(),this.isSpriteNodeMaterial=!0,this._useSizeAttenuation=!0,this.positionNode=null,this.rotationNode=null,this.scaleNode=null,this.setDefaultValues(Ng),this.setValues(e)}setupPositionView(e){const{object:t,camera:r}=e,s=this.sizeAttenuation,{positionNode:i,rotationNode:n,scaleNode:o}=this,a=Yu.mul(Oi(i||0));let u=Ii(Hu[0].xyz.length(),Hu[1].xyz.length());if(null!==o&&(u=u.mul(o)),!1===s)if(r.isPerspectiveCamera)u=u.mul(a.z.negate());else{const e=Bi(2).div(Mu.element(1).element(1));u=u.mul(e.mul(2))}let l=el.xy;if(t.center&&!0===t.center.isVector2){const e=((e,t,r)=>Ti(new qa(e,t,r)))("center","vec2",t);l=l.sub(e.sub(.5))}l=l.mul(u);const d=Bi(n||Ad),c=vg(l,d);return $i(a.xy.add(c),a.zw)}copy(e){return this.positionNode=e.positionNode,this.rotationNode=e.rotationNode,this.scaleNode=e.scaleNode,super.copy(e)}get sizeAttenuation(){return this._useSizeAttenuation}set sizeAttenuation(e){this._useSizeAttenuation!==e&&(this._useSizeAttenuation=e,this.needsUpdate=!0)}}class Ag extends Eh{constructor(){super(),this.shadowNode=Bi(1).toVar("shadowMask")}direct({shadowMask:e}){this.shadowNode.mulAssign(e)}finish(e){dn.a.mulAssign(this.shadowNode.oneMinus()),e.outgoingLight.rgb.assign(dn.rgb)}}const Rg=new oe;class Cg extends sh{static get type(){return"ShadowNodeMaterial"}constructor(e){super(),this.isShadowNodeMaterial=!0,this.lights=!0,this.setDefaultValues(Rg),this.setValues(e)}setupLightingModel(){return new Ag}}const Eg=Ai((({texture:e,uv:t})=>{const r=1e-4,s=Oi().toVar();return Ei(t.x.lessThan(r),(()=>{s.assign(Oi(1,0,0))})).ElseIf(t.y.lessThan(r),(()=>{s.assign(Oi(0,1,0))})).ElseIf(t.z.lessThan(r),(()=>{s.assign(Oi(0,0,1))})).ElseIf(t.x.greaterThan(.9999),(()=>{s.assign(Oi(-1,0,0))})).ElseIf(t.y.greaterThan(.9999),(()=>{s.assign(Oi(0,-1,0))})).ElseIf(t.z.greaterThan(.9999),(()=>{s.assign(Oi(0,0,-1))})).Else((()=>{const r=.01,i=e.sample(t.add(Oi(-.01,0,0))).r.sub(e.sample(t.add(Oi(r,0,0))).r),n=e.sample(t.add(Oi(0,-.01,0))).r.sub(e.sample(t.add(Oi(0,r,0))).r),o=e.sample(t.add(Oi(0,0,-.01))).r.sub(e.sample(t.add(Oi(0,0,r))).r);s.assign(Oi(i,n,o))})),s.normalize()}));class wg extends Au{static get type(){return"Texture3DNode"}constructor(e,t=null,r=null){super(e,t,r),this.isTexture3DNode=!0}getInputType(){return"texture3D"}getDefaultUV(){return Oi(.5,.5,.5)}setUpdateMatrix(){}setupUV(e,t){const r=this.value;return!e.isFlipY()||!0!==r.isRenderTargetTexture&&!0!==r.isFramebufferTexture||(t=this.sampler?t.flipY():t.setY(Fi(vu(this,this.levelNode).y).sub(t.y).sub(1))),t}generateUV(e,t){return t.build(e,"vec3")}normal(e){return Eg({texture:this,uv:e})}}const Mg=Ni(wg);class Bg extends sh{static get type(){return"VolumeNodeMaterial"}constructor(t){super(),this.isVolumeNodeMaterial=!0,this.base=new e(16777215),this.map=null,this.steps=100,this.testNode=null,this.setValues(t)}setup(e){const t=Mg(this.map,null,0),r=Ai((({orig:e,dir:t})=>{const r=Oi(-.5),s=Oi(.5),i=t.reciprocal(),n=r.sub(e).mul(i),o=s.sub(e).mul(i),a=Qo(n,o),u=Zo(n,o),l=Zo(a.x,Zo(a.y,a.z)),d=Qo(u.x,Qo(u.y,u.z));return Ii(l,d)}));this.fragmentNode=Ai((()=>{const e=Ia(Oi(Xu.mul($i(Iu,1)))),s=Ia(el.sub(e)).normalize(),i=Ii(r({orig:e,dir:s})).toVar();i.x.greaterThan(i.y).discard(),i.assign(Ii(Zo(i.x,0),i.y));const n=Oi(e.add(i.x.mul(s))).toVar(),o=Oi(s.abs().reciprocal()).toVar(),a=Bi(Qo(o.x,Qo(o.y,o.z))).toVar("delta");a.divAssign(Ll("steps","float"));const u=$i(Ll("base","color"),0).toVar();return cc({type:"float",start:i.x,end:i.y,update:"+= delta"},(()=>{const e=un("float","d").assign(t.sample(n.add(.5)).r);null!==this.testNode?this.testNode({map:t,mapValue:e,probe:n,finalColor:u}).append():(u.a.assign(1),hc()),n.addAssign(s.mul(a))})),u.a.equal(0).discard(),$i(u)}))(),super.setup(e)}}class Fg{constructor(e,t){this.nodes=e,this.info=t,this._context=self,this._animationLoop=null,this._requestId=null}start(){const e=(t,r)=>{this._requestId=this._context.requestAnimationFrame(e),!0===this.info.autoReset&&this.info.reset(),this.nodes.nodeFrame.update(),this.info.frame=this.nodes.nodeFrame.frameId,null!==this._animationLoop&&this._animationLoop(t,r)};e()}stop(){this._context.cancelAnimationFrame(this._requestId),this._requestId=null}setAnimationLoop(e){this._animationLoop=e}setContext(e){this._context=e}dispose(){this.stop()}}class Ug{constructor(){this.weakMap=new WeakMap}get(e){let t=this.weakMap;for(let r=0;r{this.dispose()},this.material.addEventListener("dispose",this.onMaterialDispose)}updateClipping(e){this.clippingContext=e}get clippingNeedsUpdate(){return null!==this.clippingContext&&this.clippingContext.cacheKey!==this.clippingContextCacheKey&&(this.clippingContextCacheKey=this.clippingContext.cacheKey,!0)}get hardwareClippingPlanes(){return!0===this.material.hardwareClipping?this.clippingContext.unionClippingCount:0}getNodeBuilderState(){return this._nodeBuilderState||(this._nodeBuilderState=this._nodes.getForRender(this))}getMonitor(){return this._monitor||(this._monitor=this.getNodeBuilderState().monitor)}getBindings(){return this._bindings||(this._bindings=this.getNodeBuilderState().createBindings())}getIndex(){return this._geometries.getIndex(this)}getIndirect(){return this._geometries.getIndirect(this)}getChainArray(){return[this.object,this.material,this.context,this.lightsNode]}setGeometry(e){this.geometry=e,this.attributes=null}getAttributes(){if(null!==this.attributes)return this.attributes;const e=this.getNodeBuilderState().nodeAttributes,t=this.geometry,r=[],s=new Set;for(const i of e){const e=i.node&&i.node.attribute?i.node.attribute:t.getAttribute(i.name);if(void 0===e)continue;r.push(e);const n=e.isInterleavedBufferAttribute?e.data:e;s.add(n)}return this.attributes=r,this.vertexBuffers=Array.from(s.values()),r}getVertexBuffers(){return null===this.vertexBuffers&&this.getAttributes(),this.vertexBuffers}getDrawParameters(){const{object:e,material:t,geometry:r,group:s,drawRange:i}=this,n=this.drawParams||(this.drawParams={vertexCount:0,firstVertex:0,instanceCount:0,firstInstance:0}),o=this.getIndex(),a=null!==o,u=r.isInstancedBufferGeometry?r.instanceCount:e.count>1?e.count:1;if(0===u)return null;if(n.instanceCount=u,!0===e.isBatchedMesh)return n;let l=1;!0!==t.wireframe||e.isPoints||e.isLineSegments||e.isLine||e.isLineLoop||(l=2);let d=i.start*l,c=(i.start+i.count)*l;null!==s&&(d=Math.max(d,s.start*l),c=Math.min(c,(s.start+s.count)*l));const h=r.attributes.position;let p=1/0;a?p=o.count:null!=h&&(p=h.count),d=Math.max(d,0),c=Math.min(c,p);const g=c-d;return g<0||g===1/0?null:(n.vertexCount=g,n.firstVertex=d,n)}getGeometryCacheKey(){const{geometry:e}=this;let t="";for(const r of Object.keys(e.attributes).sort()){const s=e.attributes[r];t+=r+",",s.data&&(t+=s.data.stride+","),s.offset&&(t+=s.offset+","),s.itemSize&&(t+=s.itemSize+","),s.normalized&&(t+="n,")}return e.index&&(t+="index,"),t}getMaterialCacheKey(){const{object:e,material:t}=this;let r=t.customProgramCacheKey();for(const e of function(e){const t=Object.keys(e);let r=Object.getPrototypeOf(e);for(;r;){const e=Object.getOwnPropertyDescriptors(r);for(const r in e)if(void 0!==e[r]){const s=e[r];s&&"function"==typeof s.get&&t.push(r)}r=Object.getPrototypeOf(r)}return t}(t)){if(/^(is[A-Z]|_)|^(visible|version|uuid|name|opacity|userData)$/.test(e))continue;const s=t[e];let i;if(null!==s){const e=typeof s;"number"===e?i=0!==s?"1":"0":"object"===e?(i="{",s.isTexture&&(i+=s.mapping),i+="}"):i=String(s)}else i=String(s);r+=i+","}return r+=this.clippingContextCacheKey+",",e.geometry&&(r+=this.getGeometryCacheKey()),e.skeleton&&(r+=e.skeleton.bones.length+","),e.morphTargetInfluences&&(r+=e.morphTargetInfluences.length+","),e.isBatchedMesh&&(r+=e._matricesTexture.uuid+",",null!==e._colorsTexture&&(r+=e._colorsTexture.uuid+",")),e.count>1&&(r+=e.uuid+","),r+=e.receiveShadow+",",ls(r)}get needsGeometryUpdate(){return this.geometry.id!==this.object.geometry.id}get needsUpdate(){return this.initialNodesCacheKey!==this.getDynamicCacheKey()||this.clippingNeedsUpdate}getDynamicCacheKey(){let e=this._nodes.getCacheKey(this.scene,this.lightsNode);return this.object.receiveShadow&&(e+=1),e}getCacheKey(){return this.getMaterialCacheKey()+this.getDynamicCacheKey()}dispose(){this.material.removeEventListener("dispose",this.onMaterialDispose),this.onDispose()}}const Dg=[];class Lg{constructor(e,t,r,s,i,n){this.renderer=e,this.nodes=t,this.geometries=r,this.pipelines=s,this.bindings=i,this.info=n,this.chainMaps={}}get(e,t,r,s,i,n,o,a){const u=this.getChainMap(a);Dg[0]=e,Dg[1]=t,Dg[2]=n,Dg[3]=i;let l=u.get(Dg);return void 0===l?(l=this.createRenderObject(this.nodes,this.geometries,this.renderer,e,t,r,s,i,n,o,a),u.set(Dg,l)):(l.updateClipping(o),l.needsGeometryUpdate&&l.setGeometry(e.geometry),(l.version!==t.version||l.needsUpdate)&&(l.initialCacheKey!==l.getCacheKey()?(l.dispose(),l=this.get(e,t,r,s,i,n,o,a)):l.version=t.version)),Dg.length=0,l}getChainMap(e="default"){return this.chainMaps[e]||(this.chainMaps[e]=new Ug)}dispose(){this.chainMaps={}}createRenderObject(e,t,r,s,i,n,o,a,u,l,d){const c=this.getChainMap(d),h=new Ig(e,t,r,s,i,n,o,a,u,l);return h.onDispose=()=>{this.pipelines.delete(h),this.bindings.delete(h),this.nodes.delete(h),c.delete(h.getChainArray())},h}}class Vg{constructor(){this.data=new WeakMap}get(e){let t=this.data.get(e);return void 0===t&&(t={},this.data.set(e,t)),t}delete(e){let t=null;return this.data.has(e)&&(t=this.data.get(e),this.data.delete(e)),t}has(e){return this.data.has(e)}dispose(){this.data=new WeakMap}}const Og=1,Gg=2,kg=3,zg=4,$g=16;class Hg extends Vg{constructor(e){super(),this.backend=e}delete(e){const t=super.delete(e);return void 0!==t&&this.backend.destroyAttribute(e),t}update(e,t){const r=this.get(e);if(void 0===r.version)t===Og?this.backend.createAttribute(e):t===Gg?this.backend.createIndexAttribute(e):t===kg?this.backend.createStorageAttribute(e):t===zg&&this.backend.createIndirectStorageAttribute(e),r.version=this._getBufferAttribute(e).version;else{const t=this._getBufferAttribute(e);(r.version=0;--t)if(e[t]>=65535)return!0;return!1}(t)?ae:ue)(t,1);return i.version=Wg(e),i}class qg extends Vg{constructor(e,t){super(),this.attributes=e,this.info=t,this.wireframes=new WeakMap,this.attributeCall=new WeakMap}has(e){const t=e.geometry;return super.has(t)&&!0===this.get(t).initialized}updateForRender(e){!1===this.has(e)&&this.initGeometry(e),this.updateAttributes(e)}initGeometry(e){const t=e.geometry;this.get(t).initialized=!0,this.info.memory.geometries++;const r=()=>{this.info.memory.geometries--;const s=t.index,i=e.getAttributes();null!==s&&this.attributes.delete(s);for(const e of i)this.attributes.delete(e);const n=this.wireframes.get(t);void 0!==n&&this.attributes.delete(n),t.removeEventListener("dispose",r)};t.addEventListener("dispose",r)}updateAttributes(e){const t=e.getAttributes();for(const e of t)e.isStorageBufferAttribute||e.isStorageInstancedBufferAttribute?this.updateAttribute(e,kg):this.updateAttribute(e,Og);const r=this.getIndex(e);null!==r&&this.updateAttribute(r,Gg);const s=e.geometry.indirect;null!==s&&this.updateAttribute(s,zg)}updateAttribute(e,t){const r=this.info.render.calls;e.isInterleavedBufferAttribute?void 0===this.attributeCall.get(e)?(this.attributes.update(e,t),this.attributeCall.set(e,r)):this.attributeCall.get(e.data)!==r&&(this.attributes.update(e,t),this.attributeCall.set(e.data,r),this.attributeCall.set(e,r)):this.attributeCall.get(e)!==r&&(this.attributes.update(e,t),this.attributeCall.set(e,r))}getIndirect(e){return e.geometry.indirect}getIndex(e){const{geometry:t,material:r}=e;let s=t.index;if(!0===r.wireframe){const e=this.wireframes;let r=e.get(t);void 0===r?(r=jg(t),e.set(t,r)):r.version!==Wg(t)&&(this.attributes.delete(r),r=jg(t),e.set(t,r)),s=r}return s}}class Kg{constructor(){this.autoReset=!0,this.frame=0,this.calls=0,this.render={calls:0,frameCalls:0,drawCalls:0,triangles:0,points:0,lines:0,timestamp:0,previousFrameCalls:0,timestampCalls:0},this.compute={calls:0,frameCalls:0,timestamp:0,previousFrameCalls:0,timestampCalls:0},this.memory={geometries:0,textures:0}}update(e,t,r){this.render.drawCalls++,e.isMesh||e.isSprite?this.render.triangles+=r*(t/3):e.isPoints?this.render.points+=r*t:e.isLineSegments?this.render.lines+=r*(t/2):e.isLine?this.render.lines+=r*(t-1):console.error("THREE.WebGPUInfo: Unknown object type.")}updateTimestamp(e,t){0===this[e].timestampCalls&&(this[e].timestamp=0),this[e].timestamp+=t,this[e].timestampCalls++,this[e].timestampCalls>=this[e].previousFrameCalls&&(this[e].timestampCalls=0)}reset(){const e=this.render.frameCalls;this.render.previousFrameCalls=e;const t=this.compute.frameCalls;this.compute.previousFrameCalls=t,this.render.drawCalls=0,this.render.frameCalls=0,this.compute.frameCalls=0,this.render.triangles=0,this.render.points=0,this.render.lines=0}dispose(){this.reset(),this.calls=0,this.render.calls=0,this.compute.calls=0,this.render.timestamp=0,this.compute.timestamp=0,this.memory.geometries=0,this.memory.textures=0}}class Xg{constructor(e){this.cacheKey=e,this.usedTimes=0}}class Yg extends Xg{constructor(e,t,r){super(e),this.vertexProgram=t,this.fragmentProgram=r}}class Qg extends Xg{constructor(e,t){super(e),this.computeProgram=t,this.isComputePipeline=!0}}let Zg=0;class Jg{constructor(e,t,r,s=null,i=null){this.id=Zg++,this.code=e,this.stage=t,this.name=r,this.transforms=s,this.attributes=i,this.usedTimes=0}}class em extends Vg{constructor(e,t){super(),this.backend=e,this.nodes=t,this.bindings=null,this.caches=new Map,this.programs={vertex:new Map,fragment:new Map,compute:new Map}}getForCompute(e,t){const{backend:r}=this,s=this.get(e);if(this._needsComputeUpdate(e)){const i=s.pipeline;i&&(i.usedTimes--,i.computeProgram.usedTimes--);const n=this.nodes.getForCompute(e);let o=this.programs.compute.get(n.computeShader);void 0===o&&(i&&0===i.computeProgram.usedTimes&&this._releaseProgram(i.computeProgram),o=new Jg(n.computeShader,"compute",e.name,n.transforms,n.nodeAttributes),this.programs.compute.set(n.computeShader,o),r.createProgram(o));const a=this._getComputeCacheKey(e,o);let u=this.caches.get(a);void 0===u&&(i&&0===i.usedTimes&&this._releasePipeline(i),u=this._getComputePipeline(e,o,a,t)),u.usedTimes++,o.usedTimes++,s.version=e.version,s.pipeline=u}return s.pipeline}getForRender(e,t=null){const{backend:r}=this,s=this.get(e);if(this._needsRenderUpdate(e)){const i=s.pipeline;i&&(i.usedTimes--,i.vertexProgram.usedTimes--,i.fragmentProgram.usedTimes--);const n=e.getNodeBuilderState(),o=e.material?e.material.name:"";let a=this.programs.vertex.get(n.vertexShader);void 0===a&&(i&&0===i.vertexProgram.usedTimes&&this._releaseProgram(i.vertexProgram),a=new Jg(n.vertexShader,"vertex",o),this.programs.vertex.set(n.vertexShader,a),r.createProgram(a));let u=this.programs.fragment.get(n.fragmentShader);void 0===u&&(i&&0===i.fragmentProgram.usedTimes&&this._releaseProgram(i.fragmentProgram),u=new Jg(n.fragmentShader,"fragment",o),this.programs.fragment.set(n.fragmentShader,u),r.createProgram(u));const l=this._getRenderCacheKey(e,a,u);let d=this.caches.get(l);void 0===d?(i&&0===i.usedTimes&&this._releasePipeline(i),d=this._getRenderPipeline(e,a,u,l,t)):e.pipeline=d,d.usedTimes++,a.usedTimes++,u.usedTimes++,s.pipeline=d}return s.pipeline}delete(e){const t=this.get(e).pipeline;return t&&(t.usedTimes--,0===t.usedTimes&&this._releasePipeline(t),t.isComputePipeline?(t.computeProgram.usedTimes--,0===t.computeProgram.usedTimes&&this._releaseProgram(t.computeProgram)):(t.fragmentProgram.usedTimes--,t.vertexProgram.usedTimes--,0===t.vertexProgram.usedTimes&&this._releaseProgram(t.vertexProgram),0===t.fragmentProgram.usedTimes&&this._releaseProgram(t.fragmentProgram))),super.delete(e)}dispose(){super.dispose(),this.caches=new Map,this.programs={vertex:new Map,fragment:new Map,compute:new Map}}updateForRender(e){this.getForRender(e)}_getComputePipeline(e,t,r,s){r=r||this._getComputeCacheKey(e,t);let i=this.caches.get(r);return void 0===i&&(i=new Qg(r,t),this.caches.set(r,i),this.backend.createComputePipeline(i,s)),i}_getRenderPipeline(e,t,r,s,i){s=s||this._getRenderCacheKey(e,t,r);let n=this.caches.get(s);return void 0===n&&(n=new Yg(s,t,r),this.caches.set(s,n),e.pipeline=n,this.backend.createRenderPipeline(e,i)),n}_getComputeCacheKey(e,t){return e.id+","+t.id}_getRenderCacheKey(e,t,r){return t.id+","+r.id+","+this.backend.getRenderCacheKey(e)}_releasePipeline(e){this.caches.delete(e.cacheKey)}_releaseProgram(e){const t=e.code,r=e.stage;this.programs[r].delete(t)}_needsComputeUpdate(e){const t=this.get(e);return void 0===t.pipeline||t.version!==e.version}_needsRenderUpdate(e){return void 0===this.get(e).pipeline||this.backend.needsRenderUpdate(e)}}class tm extends Vg{constructor(e,t,r,s,i,n){super(),this.backend=e,this.textures=r,this.pipelines=i,this.attributes=s,this.nodes=t,this.info=n,this.pipelines.bindings=this}getForRender(e){const t=e.getBindings();for(const e of t){const r=this.get(e);void 0===r.bindGroup&&(this._init(e),this.backend.createBindings(e,t,0),r.bindGroup=e)}return t}getForCompute(e){const t=this.nodes.getForCompute(e).bindings;for(const e of t){const r=this.get(e);void 0===r.bindGroup&&(this._init(e),this.backend.createBindings(e,t,0),r.bindGroup=e)}return t}updateForCompute(e){this._updateBindings(this.getForCompute(e))}updateForRender(e){this._updateBindings(this.getForRender(e))}_updateBindings(e){for(const t of e)this._update(t,e)}_init(e){for(const t of e.bindings)if(t.isSampledTexture)this.textures.updateTexture(t.texture);else if(t.isStorageBuffer){const e=t.attribute,r=e.isIndirectStorageBufferAttribute?zg:kg;this.attributes.update(e,r)}}_update(e,t){const{backend:r}=this;let s=!1,i=!0,n=0,o=0;for(const t of e.bindings){if(t.isNodeUniformsGroup){if(!1===this.nodes.updateGroup(t))continue}if(t.isUniformBuffer){t.update()&&r.updateBinding(t)}else if(t.isSampler)t.update();else if(t.isSampledTexture){const e=this.textures.get(t.texture);t.needsBindingsUpdate(e.generation)&&(s=!0);const a=t.update(),u=t.texture;a&&this.textures.updateTexture(u);const l=r.get(u);if(void 0!==l.externalTexture||e.isDefaultTexture?i=!1:(n=10*n+u.id,o+=u.version),!0===r.isWebGPUBackend&&void 0===l.texture&&void 0===l.externalTexture&&(console.error("Bindings._update: binding should be available:",t,a,u,t.textureNode.value,s),this.textures.updateTexture(u),s=!0),!0===u.isStorageTexture){const e=this.get(u);!0===t.store?e.needsMipmap=!0:this.textures.needsMipmaps(u)&&!0===e.needsMipmap&&(this.backend.generateMipmaps(u),e.needsMipmap=!1)}}}!0===s&&this.backend.updateBindings(e,t,i?n:0,o)}}function rm(e,t){return e.groupOrder!==t.groupOrder?e.groupOrder-t.groupOrder:e.renderOrder!==t.renderOrder?e.renderOrder-t.renderOrder:e.material.id!==t.material.id?e.material.id-t.material.id:e.z!==t.z?e.z-t.z:e.id-t.id}function sm(e,t){return e.groupOrder!==t.groupOrder?e.groupOrder-t.groupOrder:e.renderOrder!==t.renderOrder?e.renderOrder-t.renderOrder:e.z!==t.z?t.z-e.z:e.id-t.id}function im(e){return(e.transmission>0||e.transmissionNode)&&e.side===le&&!1===e.forceSinglePass}class nm{constructor(e,t,r){this.renderItems=[],this.renderItemsIndex=0,this.opaque=[],this.transparentDoublePass=[],this.transparent=[],this.bundles=[],this.lightsNode=e.getNode(t,r),this.lightsArray=[],this.scene=t,this.camera=r,this.occlusionQueryCount=0}begin(){return this.renderItemsIndex=0,this.opaque.length=0,this.transparentDoublePass.length=0,this.transparent.length=0,this.bundles.length=0,this.lightsArray.length=0,this.occlusionQueryCount=0,this}getNextRenderItem(e,t,r,s,i,n,o){let a=this.renderItems[this.renderItemsIndex];return void 0===a?(a={id:e.id,object:e,geometry:t,material:r,groupOrder:s,renderOrder:e.renderOrder,z:i,group:n,clippingContext:o},this.renderItems[this.renderItemsIndex]=a):(a.id=e.id,a.object=e,a.geometry=t,a.material=r,a.groupOrder=s,a.renderOrder=e.renderOrder,a.z=i,a.group=n,a.clippingContext=o),this.renderItemsIndex++,a}push(e,t,r,s,i,n,o){const a=this.getNextRenderItem(e,t,r,s,i,n,o);!0===e.occlusionTest&&this.occlusionQueryCount++,!0===r.transparent||r.transmission>0?(im(r)&&this.transparentDoublePass.push(a),this.transparent.push(a)):this.opaque.push(a)}unshift(e,t,r,s,i,n,o){const a=this.getNextRenderItem(e,t,r,s,i,n,o);!0===r.transparent||r.transmission>0?(im(r)&&this.transparentDoublePass.unshift(a),this.transparent.unshift(a)):this.opaque.unshift(a)}pushBundle(e){this.bundles.push(e)}pushLight(e){this.lightsArray.push(e)}sort(e,t){this.opaque.length>1&&this.opaque.sort(e||rm),this.transparentDoublePass.length>1&&this.transparentDoublePass.sort(t||sm),this.transparent.length>1&&this.transparent.sort(t||sm)}finish(){this.lightsNode.setLights(this.lightsArray);for(let e=this.renderItemsIndex,t=this.renderItems.length;e>t,u=o.height>>t;let l=e.depthTexture||i[t];const d=!0===e.depthBuffer||!0===e.stencilBuffer;let c=!1;void 0===l&&d&&(l=new B,l.format=e.stencilBuffer?ce:he,l.type=e.stencilBuffer?pe:b,l.image.width=a,l.image.height=u,i[t]=l),r.width===o.width&&o.height===r.height||(c=!0,l&&(l.needsUpdate=!0,l.image.width=a,l.image.height=u)),r.width=o.width,r.height=o.height,r.textures=n,r.depthTexture=l||null,r.depth=e.depthBuffer,r.stencil=e.stencilBuffer,r.renderTarget=e,r.sampleCount!==s&&(c=!0,l&&(l.needsUpdate=!0),r.sampleCount=s);const h={sampleCount:s};for(let e=0;e{e.removeEventListener("dispose",t);for(let e=0;e0){const s=e.image;if(void 0===s)console.warn("THREE.Renderer: Texture marked for update but image is undefined.");else if(!1===s.complete)console.warn("THREE.Renderer: Texture marked for update but image is incomplete.");else{if(e.images){const r=[];for(const t of e.images)r.push(t);t.images=r}else t.image=s;void 0!==r.isDefaultTexture&&!0!==r.isDefaultTexture||(i.createTexture(e,t),r.isDefaultTexture=!1,r.generation=e.version),!0===e.source.dataReady&&i.updateTexture(e,t),t.needsMipmaps&&0===e.mipmaps.length&&i.generateMipmaps(e)}}else i.createDefaultTexture(e),r.isDefaultTexture=!0,r.generation=e.version}if(!0!==r.initialized){r.initialized=!0,r.generation=e.version,this.info.memory.textures++;const t=()=>{e.removeEventListener("dispose",t),this._destroyTexture(e),this.info.memory.textures--};e.addEventListener("dispose",t)}r.version=e.version}getSize(e,t=mm){let r=e.images?e.images[0]:e.image;return r?(void 0!==r.image&&(r=r.image),t.width=r.width||1,t.height=r.height||1,t.depth=e.isCubeTexture?6:r.depth||1):t.width=t.height=t.depth=1,t}getMipLevels(e,t,r){let s;return s=e.isCompressedTexture?e.mipmaps?e.mipmaps.length:1:Math.floor(Math.log2(Math.max(t,r)))+1,s}needsMipmaps(e){return this.isEnvironmentTexture(e)||!0===e.isCompressedTexture||e.generateMipmaps}isEnvironmentTexture(e){const t=e.mapping;return t===j||t===q||t===_||t===v}_destroyTexture(e){this.backend.destroySampler(e),this.backend.destroyTexture(e),this.delete(e)}}class ym extends e{constructor(e,t,r,s=1){super(e,t,r),this.a=s}set(e,t,r,s=1){return this.a=s,super.set(e,t,r)}copy(e){return void 0!==e.a&&(this.a=e.a),super.copy(e)}clone(){return new this.constructor(this.r,this.g,this.b,this.a)}}class bm extends an{static get type(){return"ParameterNode"}constructor(e,t=null){super(e,t),this.isParameterNode=!0}getHash(){return this.uuid}generate(){return this.name}}class xm extends Ps{static get type(){return"StackNode"}constructor(e=null){super(),this.nodes=[],this.outputNode=null,this.parent=e,this._currentCond=null,this.isStackNode=!0}getNodeType(e){return this.outputNode?this.outputNode.getNodeType(e):"void"}add(e){return this.nodes.push(e),this}If(e,t){const r=new xi(t);return this._currentCond=Ra(e,r),this.add(this._currentCond)}ElseIf(e,t){const r=new xi(t),s=Ra(e,r);return this._currentCond.elseNode=s,this._currentCond=s,this}Else(e){return this._currentCond.elseNode=new xi(e),this}build(e,...t){const r=Ci();Ri(this);for(const t of this.nodes)t.build(e,"void");return Ri(r),this.outputNode?this.outputNode.build(e,...t):super.build(e,...t)}else(...e){return console.warn("TSL.StackNode: .else() has been renamed to .Else()."),this.Else(...e)}elseif(...e){return console.warn("TSL.StackNode: .elseif() has been renamed to .ElseIf()."),this.ElseIf(...e)}}const Tm=Ni(xm);class _m extends Ps{static get type(){return"OutputStructNode"}constructor(...e){super(),this.members=e,this.isOutputStructNode=!0}setup(e){super.setup(e);const t=this.members,r=[];for(let s=0;s{const t=e.toUint().mul(747796405).add(2891336453),r=t.shiftRight(t.shiftRight(28).add(4)).bitXor(t).mul(277803737);return r.shiftRight(22).bitXor(r).toFloat().mul(1/2**32)})),Cm=(e,t)=>oa(Wn(4,e.mul(Hn(1,e))),t),Em=Ai((([e])=>e.fract().sub(.5).abs())).setLayout({name:"tri",type:"float",inputs:[{name:"x",type:"float"}]}),wm=Ai((([e])=>Oi(Em(e.z.add(Em(e.y.mul(1)))),Em(e.z.add(Em(e.x.mul(1)))),Em(e.y.add(Em(e.x.mul(1))))))).setLayout({name:"tri3",type:"vec3",inputs:[{name:"p",type:"vec3"}]}),Mm=Ai((([e,t,r])=>{const s=Oi(e).toVar(),i=Bi(1.4).toVar(),n=Bi(0).toVar(),o=Oi(s).toVar();return cc({start:Bi(0),end:Bi(3),type:"float",condition:"<="},(()=>{const e=Oi(wm(o.mul(2))).toVar();s.addAssign(e.add(r.mul(Bi(.1).mul(t)))),o.mulAssign(1.8),i.mulAssign(1.5),s.mulAssign(1.2);const a=Bi(Em(s.z.add(Em(s.x.add(Em(s.y)))))).toVar();n.addAssign(a.div(i)),o.addAssign(.14)})),n})).setLayout({name:"triNoise3D",type:"float",inputs:[{name:"position",type:"vec3"},{name:"speed",type:"float"},{name:"time",type:"float"}]});class Bm extends Ps{static get type(){return"FunctionOverloadingNode"}constructor(e=[],...t){super(),this.functionNodes=e,this.parametersNodes=t,this._candidateFnCall=null,this.global=!0}getNodeType(){return this.functionNodes[0].shaderNode.layout.type}setup(e){const t=this.parametersNodes;let r=this._candidateFnCall;if(null===r){let s=null,i=-1;for(const r of this.functionNodes){const n=r.shaderNode.layout;if(null===n)throw new Error("FunctionOverloadingNode: FunctionNode must be a layout.");const o=n.inputs;if(t.length===o.length){let n=0;for(let r=0;ri&&(s=r,i=n)}}this._candidateFnCall=r=s(...t)}return r}}const Fm=Ni(Bm),Um=e=>(...t)=>Fm(e,...t),Pm=on(0).setGroup(rn).onRenderUpdate((e=>e.time)),Im=on(0).setGroup(rn).onRenderUpdate((e=>e.deltaTime)),Dm=on(0,"uint").setGroup(rn).onRenderUpdate((e=>e.frameId)),Lm=Ai((([e,t,r=Ii(.5)])=>vg(e.sub(r),t).add(r))),Vm=Ai((([e,t,r=Ii(.5)])=>{const s=e.sub(r),i=s.dot(s),n=i.mul(i).mul(t);return e.add(s.mul(n))})),Om=Ai((({position:e=null,horizontal:t=!0,vertical:r=!1})=>{let s;null!==e?(s=Hu.toVar(),s[3][0]=e.x,s[3][1]=e.y,s[3][2]=e.z):s=Hu;const i=Fu.mul(s);return yi(t)&&(i[0][0]=Hu[0].length(),i[0][1]=0,i[0][2]=0),yi(r)&&(i[1][0]=0,i[1][1]=Hu[1].length(),i[1][2]=0),i[2][0]=0,i[2][1]=0,i[2][2]=1,Mu.mul(i).mul(tl)})),Gm=Ai((([e=null])=>{const t=Yc();return Yc(zc(e)).sub(t).lessThan(0).select(Rc,e)}));class km extends Ps{static get type(){return"SpriteSheetUVNode"}constructor(e,t=Tu(),r=Bi(0)){super("vec2"),this.countNode=e,this.uvNode=t,this.frameNode=r}setup(){const{frameNode:e,uvNode:t,countNode:r}=this,{width:s,height:i}=r,n=e.mod(s.mul(i)).floor(),o=n.mod(s),a=i.sub(n.add(1).div(s).ceil()),u=r.reciprocal(),l=Ii(o,a);return t.add(l).mul(u)}}const zm=Ni(km);class $m extends Ps{static get type(){return"TriplanarTexturesNode"}constructor(e,t=null,r=null,s=Bi(1),i=tl,n=cl){super("vec4"),this.textureXNode=e,this.textureYNode=t,this.textureZNode=r,this.scaleNode=s,this.positionNode=i,this.normalNode=n}setup(){const{textureXNode:e,textureYNode:t,textureZNode:r,scaleNode:s,positionNode:i,normalNode:n}=this;let o=n.abs().normalize();o=o.div(o.dot(Oi(1)));const a=i.yz.mul(s),u=i.zx.mul(s),l=i.xy.mul(s),d=e.value,c=null!==t?t.value:d,h=null!==r?r.value:d,p=Ru(d,a).mul(o.x),g=Ru(c,u).mul(o.y),m=Ru(h,l).mul(o.z);return $n(p,g,m)}}const Hm=Ni($m),Wm=new fe,jm=new r,qm=new r,Km=new r,Xm=new n,Ym=new r(0,0,-1),Qm=new s,Zm=new r,Jm=new r,ef=new s,tf=new t,rf=new me,sf=Rc.flipX();rf.depthTexture=new B(1,1);let nf=!1;class of extends Au{static get type(){return"ReflectorNode"}constructor(e={}){super(e.defaultTexture||rf.texture,sf),this._reflectorBaseNode=e.reflector||new af(this,e),this._depthNode=null,this.setUpdateMatrix(!1)}get reflector(){return this._reflectorBaseNode}get target(){return this._reflectorBaseNode.target}getDepthNode(){if(null===this._depthNode){if(!0!==this._reflectorBaseNode.depth)throw new Error("THREE.ReflectorNode: Depth node can only be requested when the reflector is created with { depth: true }. ");this._depthNode=Ti(new of({defaultTexture:rf.depthTexture,reflector:this._reflectorBaseNode}))}return this._depthNode}setup(e){return e.object.isQuadMesh||this._reflectorBaseNode.build(e),super.setup(e)}clone(){const e=new this.constructor(this.reflectorNode);return e._reflectorBaseNode=this._reflectorBaseNode,e}}class af extends Ps{static get type(){return"ReflectorBaseNode"}constructor(e,t={}){super();const{target:r=new ye,resolution:s=1,generateMipmaps:i=!1,bounces:n=!0,depth:o=!1}=t;this.textureNode=e,this.target=r,this.resolution=s,this.generateMipmaps=i,this.bounces=n,this.depth=o,this.updateBeforeType=n?Rs.RENDER:Rs.FRAME,this.virtualCameras=new WeakMap,this.renderTargets=new WeakMap}_updateResolution(e,t){const r=this.resolution;t.getDrawingBufferSize(tf),e.setSize(Math.round(tf.width*r),Math.round(tf.height*r))}setup(e){return this._updateResolution(rf,e.renderer),super.setup(e)}getVirtualCamera(e){let t=this.virtualCameras.get(e);return void 0===t&&(t=e.clone(),this.virtualCameras.set(e,t)),t}getRenderTarget(e){let t=this.renderTargets.get(e);return void 0===t&&(t=new me(0,0,{type:be}),!0===this.generateMipmaps&&(t.texture.minFilter=xe,t.texture.generateMipmaps=!0),!0===this.depth&&(t.depthTexture=new B),this.renderTargets.set(e,t)),t}updateBefore(e){if(!1===this.bounces&&nf)return!1;nf=!0;const{scene:t,camera:r,renderer:s,material:i}=e,{target:n}=this,o=this.getVirtualCamera(r),a=this.getRenderTarget(o);if(s.getDrawingBufferSize(tf),this._updateResolution(a,s),qm.setFromMatrixPosition(n.matrixWorld),Km.setFromMatrixPosition(r.matrixWorld),Xm.extractRotation(n.matrixWorld),jm.set(0,0,1),jm.applyMatrix4(Xm),Zm.subVectors(qm,Km),Zm.dot(jm)>0)return;Zm.reflect(jm).negate(),Zm.add(qm),Xm.extractRotation(r.matrixWorld),Ym.set(0,0,-1),Ym.applyMatrix4(Xm),Ym.add(Km),Jm.subVectors(qm,Ym),Jm.reflect(jm).negate(),Jm.add(qm),o.coordinateSystem=r.coordinateSystem,o.position.copy(Zm),o.up.set(0,1,0),o.up.applyMatrix4(Xm),o.up.reflect(jm),o.lookAt(Jm),o.near=r.near,o.far=r.far,o.updateMatrixWorld(),o.projectionMatrix.copy(r.projectionMatrix),Wm.setFromNormalAndCoplanarPoint(jm,qm),Wm.applyMatrix4(o.matrixWorldInverse),Qm.set(Wm.normal.x,Wm.normal.y,Wm.normal.z,Wm.constant);const u=o.projectionMatrix;ef.x=(Math.sign(Qm.x)+u.elements[8])/u.elements[0],ef.y=(Math.sign(Qm.y)+u.elements[9])/u.elements[5],ef.z=-1,ef.w=(1+u.elements[10])/u.elements[14],Qm.multiplyScalar(1/Qm.dot(ef));u.elements[2]=Qm.x,u.elements[6]=Qm.y,u.elements[10]=s.coordinateSystem===l?Qm.z-0:Qm.z+1-0,u.elements[14]=Qm.w,this.textureNode.value=a.texture,!0===this.depth&&(this.textureNode.getDepthNode().value=a.depthTexture),i.visible=!1;const d=s.getRenderTarget(),c=s.getMRT(),h=s.autoClear;s.setMRT(null),s.setRenderTarget(a),s.autoClear=!0,s.render(t,o),s.setMRT(c),s.setRenderTarget(d),s.autoClear=h,i.visible=!0,nf=!1}}const uf=new Te(-1,1,1,-1,0,1);class lf extends _e{constructor(e=!1){super();const t=!1===e?[0,-1,0,1,2,1]:[0,2,0,0,2,0];this.setAttribute("position",new ve([-1,3,0,-1,-1,0,3,-1,0],3)),this.setAttribute("uv",new ve(t,2))}}const df=new lf;class cf extends k{constructor(e=null){super(df,e),this.camera=uf,this.isQuadMesh=!0}async renderAsync(e){return e.renderAsync(this,uf)}render(e){e.render(this,uf)}}const hf=new t;class pf extends Au{static get type(){return"RTTNode"}constructor(e,t=null,r=null,s={type:be}){const i=new me(t,r,s);super(i.texture,Tu()),this.node=e,this.width=t,this.height=r,this.pixelRatio=1,this.renderTarget=i,this.textureNeedsUpdate=!0,this.autoUpdate=!0,this._rttNode=null,this._quadMesh=new cf(new sh),this.updateBeforeType=Rs.RENDER}get autoSize(){return null===this.width}setup(e){return this._rttNode=this.node.context(e.getSharedContext()),this._quadMesh.material.name="RTT",this._quadMesh.material.needsUpdate=!0,super.setup(e)}setSize(e,t){this.width=e,this.height=t;const r=e*this.pixelRatio,s=t*this.pixelRatio;this.renderTarget.setSize(r,s),this.textureNeedsUpdate=!0}setPixelRatio(e){this.pixelRatio=e,this.setSize(this.width,this.height)}updateBefore({renderer:e}){if(!1===this.textureNeedsUpdate&&!1===this.autoUpdate)return;if(this.textureNeedsUpdate=!1,!0===this.autoSize){this.pixelRatio=e.getPixelRatio();const t=e.getSize(hf);this.setSize(t.width,t.height)}this._quadMesh.material.fragmentNode=this._rttNode;const t=e.getRenderTarget();e.setRenderTarget(this.renderTarget),this._quadMesh.render(e),e.setRenderTarget(t)}clone(){const e=new Au(this.value,this.uvNode,this.levelNode);return e.sampler=this.sampler,e.referenceNode=this,e}}const gf=(e,...t)=>Ti(new pf(Ti(e),...t)),mf=Ai((([e,t,r],s)=>{let i;s.renderer.coordinateSystem===l?(e=Ii(e.x,e.y.oneMinus()).mul(2).sub(1),i=$i(Oi(e,t),1)):i=$i(Oi(e.x,e.y.oneMinus(),t).mul(2).sub(1),1);const n=$i(r.mul(i));return n.xyz.div(n.w)})),ff=Ai((([e,t])=>{const r=t.mul($i(e,1)),s=r.xy.div(r.w).mul(.5).add(.5).toVar();return Ii(s.x,s.y.oneMinus())})),yf=Ai((([e,t,r])=>{const s=vu(Cu(t)),i=Di(e.mul(s)).toVar(),n=Cu(t,i).toVar(),o=Cu(t,i.sub(Di(2,0))).toVar(),a=Cu(t,i.sub(Di(1,0))).toVar(),u=Cu(t,i.add(Di(1,0))).toVar(),l=Cu(t,i.add(Di(2,0))).toVar(),d=Cu(t,i.add(Di(0,2))).toVar(),c=Cu(t,i.add(Di(0,1))).toVar(),h=Cu(t,i.sub(Di(0,1))).toVar(),p=Cu(t,i.sub(Di(0,2))).toVar(),g=Lo(Hn(Bi(2).mul(a).sub(o),n)).toVar(),m=Lo(Hn(Bi(2).mul(u).sub(l),n)).toVar(),f=Lo(Hn(Bi(2).mul(c).sub(d),n)).toVar(),y=Lo(Hn(Bi(2).mul(h).sub(p),n)).toVar(),b=mf(e,n,r).toVar(),x=g.lessThan(m).select(b.sub(mf(e.sub(Ii(Bi(1).div(s.x),0)),a,r)),b.negate().add(mf(e.add(Ii(Bi(1).div(s.x),0)),u,r))),T=f.lessThan(y).select(b.sub(mf(e.add(Ii(0,Bi(1).div(s.y))),c,r)),b.negate().add(mf(e.sub(Ii(0,Bi(1).div(s.y))),h,r)));return wo(na(x,T))}));class bf extends R{constructor(e,t,r=Float32Array){super(ArrayBuffer.isView(e)?e:new r(e*t),t),this.isStorageInstancedBufferAttribute=!0}}class xf extends Ne{constructor(e,t,r=Float32Array){super(ArrayBuffer.isView(e)?e:new r(e*t),t),this.isStorageBufferAttribute=!0}}class Tf extends Is{static get type(){return"StorageArrayElementNode"}constructor(e,t){super(e,t),this.isStorageArrayElementNode=!0}set storageBufferNode(e){this.node=e}get storageBufferNode(){return this.node}setup(e){return!1===e.isAvailable("storageBuffer")&&!0===this.node.isPBO&&e.setupPBO(this.node),super.setup(e)}generate(e,t){let r;const s=e.context.assign;if(r=!1===e.isAvailable("storageBuffer")?!0!==this.node.isPBO||!0===s||!this.node.value.isInstancedBufferAttribute&&"compute"===e.shaderStage?this.node.build(e):e.generatePBO(this):super.generate(e),!0!==s){const s=this.getNodeType(e);r=e.format(r,s,t)}return r}}const _f=Ni(Tf);class vf extends Cl{static get type(){return"StorageBufferNode"}constructor(e,t=null,r=0){null===t&&(e.isStorageBufferAttribute||e.isStorageInstancedBufferAttribute)&&(t=fs(e.itemSize),r=e.count),super(e,t,r),this.isStorageBufferNode=!0,this.access=Es.READ_WRITE,this.isAtomic=!1,this.isPBO=!1,this._attribute=null,this._varying=null,this.global=!0,!0!==e.isStorageBufferAttribute&&!0!==e.isStorageInstancedBufferAttribute&&(e.isInstancedBufferAttribute?e.isStorageInstancedBufferAttribute=!0:e.isStorageBufferAttribute=!0)}getHash(e){if(0===this.bufferCount){let t=e.globalCache.getData(this.value);return void 0===t&&(t={node:this},e.globalCache.setData(this.value,t)),t.node.uuid}return this.uuid}getInputType(){return this.value.isIndirectStorageBufferAttribute?"indirectStorageBuffer":"storageBuffer"}element(e){return _f(this,e)}setPBO(e){return this.isPBO=e,this}getPBO(){return this.isPBO}setAccess(e){return this.access=e,this}toReadOnly(){return this.setAccess(Es.READ_ONLY)}setAtomic(e){return this.isAtomic=e,this}toAtomic(){return this.setAtomic(!0)}getAttributeData(){return null===this._attribute&&(this._attribute=eu(this.value),this._varying=Ia(this._attribute)),{attribute:this._attribute,varying:this._varying}}getNodeType(e){if(e.isAvailable("storageBuffer")||e.isAvailable("indirectStorageBuffer"))return super.getNodeType(e);const{attribute:t}=this.getAttributeData();return t.getNodeType(e)}generate(e){if(e.isAvailable("storageBuffer")||e.isAvailable("indirectStorageBuffer"))return super.generate(e);const{attribute:t,varying:r}=this.getAttributeData(),s=r.build(e);return e.registerTransform(s,t),s}}const Nf=(e,t=null,r=0)=>Ti(new vf(e,t,r));class Sf extends bu{static get type(){return"VertexColorNode"}constructor(e=0){super(null,"vec4"),this.isVertexColorNode=!0,this.index=e}getAttributeName(){const e=this.index;return"color"+(e>0?e:"")}generate(e){const t=this.getAttributeName(e);let r;return r=!0===e.hasGeometryAttribute(t)?super.generate(e):e.generateConst(this.nodeType,new s(1,1,1,1)),r}serialize(e){super.serialize(e),e.index=this.index}deserialize(e){super.deserialize(e),this.index=e.index}}class Af extends Ps{static get type(){return"PointUVNode"}constructor(){super("vec2"),this.isPointUVNode=!0}generate(){return"vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y )"}}const Rf=Si(Af),Cf=new Ae,Ef=new n;class wf extends Ps{static get type(){return"SceneNode"}constructor(e=wf.BACKGROUND_BLURRINESS,t=null){super(),this.scope=e,this.scene=t}setup(e){const t=this.scope,r=null!==this.scene?this.scene:e.scene;let s;return t===wf.BACKGROUND_BLURRINESS?s=Pl("backgroundBlurriness","float",r):t===wf.BACKGROUND_INTENSITY?s=Pl("backgroundIntensity","float",r):t===wf.BACKGROUND_ROTATION?s=on("mat4").label("backgroundRotation").setGroup(rn).onRenderUpdate((()=>{const e=r.background;return null!==e&&e.isTexture&&e.mapping!==Se?(Cf.copy(r.backgroundRotation),Cf.x*=-1,Cf.y*=-1,Cf.z*=-1,Ef.makeRotationFromEuler(Cf)):Ef.identity(),Ef})):console.error("THREE.SceneNode: Unknown scope:",t),s}}wf.BACKGROUND_BLURRINESS="backgroundBlurriness",wf.BACKGROUND_INTENSITY="backgroundIntensity",wf.BACKGROUND_ROTATION="backgroundRotation";const Mf=Si(wf,wf.BACKGROUND_BLURRINESS),Bf=Si(wf,wf.BACKGROUND_INTENSITY),Ff=Si(wf,wf.BACKGROUND_ROTATION);class Uf extends Au{static get type(){return"StorageTextureNode"}constructor(e,t,r=null){super(e,t),this.storeNode=r,this.isStorageTextureNode=!0,this.access=Es.WRITE_ONLY}getInputType(){return"storageTexture"}setup(e){super.setup(e);e.getNodeProperties(this).storeNode=this.storeNode}setAccess(e){return this.access=e,this}generate(e,t){let r;return r=null!==this.storeNode?this.generateStore(e):super.generate(e,t),r}toReadWrite(){return this.setAccess(Es.READ_WRITE)}toReadOnly(){return this.setAccess(Es.READ_ONLY)}toWriteOnly(){return this.setAccess(Es.WRITE_ONLY)}generateStore(e){const t=e.getNodeProperties(this),{uvNode:r,storeNode:s}=t,i=super.generate(e,"property"),n=r.build(e,"uvec2"),o=s.build(e,"vec4"),a=e.generateTextureStore(e,i,n,o);e.addLineFlowCode(a,this)}}const Pf=Ni(Uf);class If extends Ul{static get type(){return"UserDataNode"}constructor(e,t,r=null){super(e,t,r),this.userData=r}updateReference(e){return this.reference=null!==this.userData?this.userData:e.object.userData,this.reference}}const Df=new WeakMap;class Lf extends Ls{static get type(){return"VelocityNode"}constructor(){super("vec2"),this.projectionMatrix=null,this.updateType=Rs.OBJECT,this.updateAfterType=Rs.OBJECT,this.previousModelWorldMatrix=on(new n),this.previousProjectionMatrix=on(new n).setGroup(rn),this.previousCameraViewMatrix=on(new n)}setProjectionMatrix(e){this.projectionMatrix=e}update({frameId:e,camera:t,object:r}){const s=Of(r);this.previousModelWorldMatrix.value.copy(s);const i=Vf(t);i.frameId!==e&&(i.frameId=e,void 0===i.previousProjectionMatrix?(i.previousProjectionMatrix=new n,i.previousCameraViewMatrix=new n,i.currentProjectionMatrix=new n,i.currentCameraViewMatrix=new n,i.previousProjectionMatrix.copy(this.projectionMatrix||t.projectionMatrix),i.previousCameraViewMatrix.copy(t.matrixWorldInverse)):(i.previousProjectionMatrix.copy(i.currentProjectionMatrix),i.previousCameraViewMatrix.copy(i.currentCameraViewMatrix)),i.currentProjectionMatrix.copy(this.projectionMatrix||t.projectionMatrix),i.currentCameraViewMatrix.copy(t.matrixWorldInverse),this.previousProjectionMatrix.value.copy(i.previousProjectionMatrix),this.previousCameraViewMatrix.value.copy(i.previousCameraViewMatrix))}updateAfter({object:e}){Of(e).copy(e.matrixWorld)}setup(){const e=null===this.projectionMatrix?Mu:on(this.projectionMatrix),t=this.previousCameraViewMatrix.mul(this.previousModelWorldMatrix),r=e.mul(Yu).mul(tl),s=this.previousProjectionMatrix.mul(t).mul(rl),i=r.xy.div(r.w),n=s.xy.div(s.w);return Hn(i,n)}}function Vf(e){let t=Df.get(e);return void 0===t&&(t={},Df.set(e,t)),t}function Of(e,t=0){const r=Vf(e);let s=r[t];return void 0===s&&(r[t]=s=new n),s}const Gf=Si(Lf),kf=Ai((([e,t])=>Qo(1,e.oneMinus().div(t)).oneMinus())).setLayout({name:"blendBurn",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),zf=Ai((([e,t])=>Qo(e.div(t.oneMinus()),1))).setLayout({name:"blendDodge",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),$f=Ai((([e,t])=>e.oneMinus().mul(t.oneMinus()).oneMinus())).setLayout({name:"blendScreen",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),Hf=Ai((([e,t])=>pa(e.mul(2).mul(t),e.oneMinus().mul(2).mul(t.oneMinus()).oneMinus(),ea(.5,e)))).setLayout({name:"blendOverlay",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),Wf=Ai((([e,t])=>{const r=t.a.add(e.a.mul(t.a.oneMinus()));return $i(t.rgb.mul(t.a).add(e.rgb.mul(e.a).mul(t.a.oneMinus())).div(r),r)})).setLayout({name:"blendColor",type:"vec4",inputs:[{name:"base",type:"vec4"},{name:"blend",type:"vec4"}]}),jf=Ai((([e])=>Yf(e.rgb))),qf=Ai((([e,t=Bi(1)])=>t.mix(Yf(e.rgb),e.rgb))),Kf=Ai((([e,t=Bi(1)])=>{const r=$n(e.r,e.g,e.b).div(3),s=e.r.max(e.g.max(e.b)),i=s.sub(r).mul(t).mul(-3);return pa(e.rgb,s,i)})),Xf=Ai((([e,t=Bi(1)])=>{const r=Oi(.57735,.57735,.57735),s=t.cos();return Oi(e.rgb.mul(s).add(r.cross(e.rgb).mul(t.sin()).add(r.mul(ia(r,e.rgb).mul(s.oneMinus())))))})),Yf=(e,t=Oi(d.getLuminanceCoefficients(new r)))=>ia(e,t),Qf=Ai((([e,t=Oi(1),s=Oi(0),i=Oi(1),n=Bi(1),o=Oi(d.getLuminanceCoefficients(new r,Re))])=>{const a=e.rgb.dot(Oi(o)),u=Zo(e.rgb.mul(t).add(s),0).toVar(),l=u.pow(i).toVar();return Ei(u.r.greaterThan(0),(()=>{u.r.assign(l.r)})),Ei(u.g.greaterThan(0),(()=>{u.g.assign(l.g)})),Ei(u.b.greaterThan(0),(()=>{u.b.assign(l.b)})),u.assign(a.add(u.sub(a).mul(n))),$i(u.rgb,e.a)}));class Zf extends Ls{static get type(){return"PosterizeNode"}constructor(e,t){super(),this.sourceNode=e,this.stepsNode=t}setup(){const{sourceNode:e,stepsNode:t}=this;return e.mul(t).floor().div(t)}}const Jf=Ni(Zf),ey=new t;class ty extends Au{static get type(){return"PassTextureNode"}constructor(e,t){super(t),this.passNode=e,this.setUpdateMatrix(!1)}setup(e){return e.object.isQuadMesh&&this.passNode.build(e),super.setup(e)}clone(){return new this.constructor(this.passNode,this.value)}}class ry extends ty{static get type(){return"PassMultipleTextureNode"}constructor(e,t,r=!1){super(e,null),this.textureName=t,this.previousTexture=r}updateTexture(){this.value=this.previousTexture?this.passNode.getPreviousTexture(this.textureName):this.passNode.getTexture(this.textureName)}setup(e){return this.updateTexture(),super.setup(e)}clone(){return new this.constructor(this.passNode,this.textureName,this.previousTexture)}}class sy extends Ls{static get type(){return"PassNode"}constructor(e,t,r,s={}){super("vec4"),this.scope=e,this.scene=t,this.camera=r,this.options=s,this._pixelRatio=1,this._width=1,this._height=1;const i=new B;i.isRenderTargetTexture=!0,i.name="depth";const n=new me(this._width*this._pixelRatio,this._height*this._pixelRatio,{type:be,...s});n.texture.name="output",n.depthTexture=i,this.renderTarget=n,this._textures={output:n.texture,depth:i},this._textureNodes={},this._linearDepthNodes={},this._viewZNodes={},this._previousTextures={},this._previousTextureNodes={},this._cameraNear=on(0),this._cameraFar=on(0),this._mrt=null,this.isPassNode=!0,this.updateBeforeType=Rs.FRAME}setMRT(e){return this._mrt=e,this}getMRT(){return this._mrt}isGlobal(){return!0}getTexture(e){let t=this._textures[e];if(void 0===t){t=this.renderTarget.texture.clone(),t.name=e,this._textures[e]=t,this.renderTarget.textures.push(t)}return t}getPreviousTexture(e){let t=this._previousTextures[e];return void 0===t&&(t=this.getTexture(e).clone(),this._previousTextures[e]=t),t}toggleTexture(e){const t=this._previousTextures[e];if(void 0!==t){const r=this._textures[e],s=this.renderTarget.textures.indexOf(r);this.renderTarget.textures[s]=t,this._textures[e]=t,this._previousTextures[e]=r,this._textureNodes[e].updateTexture(),this._previousTextureNodes[e].updateTexture()}}getTextureNode(e="output"){let t=this._textureNodes[e];return void 0===t&&(t=Ti(new ry(this,e)),t.updateTexture(),this._textureNodes[e]=t),t}getPreviousTextureNode(e="output"){let t=this._previousTextureNodes[e];return void 0===t&&(void 0===this._textureNodes[e]&&this.getTextureNode(e),t=Ti(new ry(this,e,!0)),t.updateTexture(),this._previousTextureNodes[e]=t),t}getViewZNode(e="depth"){let t=this._viewZNodes[e];if(void 0===t){const r=this._cameraNear,s=this._cameraFar;this._viewZNodes[e]=t=jc(this.getTextureNode(e),r,s)}return t}getLinearDepthNode(e="depth"){let t=this._linearDepthNodes[e];if(void 0===t){const r=this._cameraNear,s=this._cameraFar,i=this.getViewZNode(e);this._linearDepthNodes[e]=t=Hc(i,r,s)}return t}setup({renderer:e}){return this.renderTarget.samples=void 0===this.options.samples?e.samples:this.options.samples,!0===e.backend.isWebGLBackend&&(this.renderTarget.samples=0),this.scope===sy.COLOR?this.getTextureNode():this.getLinearDepthNode()}updateBefore(e){const{renderer:t}=e,{scene:r,camera:s}=this;this._pixelRatio=t.getPixelRatio();const i=t.getSize(ey);this.setSize(i.width,i.height);const n=t.getRenderTarget(),o=t.getMRT();this._cameraNear.value=s.near,this._cameraFar.value=s.far;for(const e in this._previousTextures)this.toggleTexture(e);t.setRenderTarget(this.renderTarget),t.setMRT(this._mrt),t.render(r,s),t.setRenderTarget(n),t.setMRT(o)}setSize(e,t){this._width=e,this._height=t;const r=this._width*this._pixelRatio,s=this._height*this._pixelRatio;this.renderTarget.setSize(r,s)}setPixelRatio(e){this._pixelRatio=e,this.setSize(this._width,this._height)}dispose(){this.renderTarget.dispose()}}sy.COLOR="color",sy.DEPTH="depth";class iy extends sy{static get type(){return"ToonOutlinePassNode"}constructor(e,t,r,s,i){super(sy.COLOR,e,t),this.colorNode=r,this.thicknessNode=s,this.alphaNode=i,this._materialCache=new WeakMap}updateBefore(e){const{renderer:t}=e,r=t.getRenderObjectFunction();t.setRenderObjectFunction(((e,r,s,i,n,o,a,u)=>{if((n.isMeshToonMaterial||n.isMeshToonNodeMaterial)&&!1===n.wireframe){const l=this._getOutlineMaterial(n);t.renderObject(e,r,s,i,l,o,a,u)}t.renderObject(e,r,s,i,n,o,a,u)})),super.updateBefore(e),t.setRenderObjectFunction(r)}_createMaterial(){const e=new sh;e.isMeshToonOutlineMaterial=!0,e.name="Toon_Outline",e.side=T;const t=cl.negate(),r=Mu.mul(Yu),s=Bi(1),i=r.mul($i(tl,1)),n=r.mul($i(tl.add(t),1)),o=wo(i.sub(n));return e.vertexNode=i.add(o.mul(this.thicknessNode).mul(i.w).mul(s)),e.colorNode=$i(this.colorNode,this.alphaNode),e}_getOutlineMaterial(e){let t=this._materialCache.get(e);return void 0===t&&(t=this._createMaterial(),this._materialCache.set(e,t)),t}}const ny=Ai((([e,t])=>e.mul(t).clamp())).setLayout({name:"linearToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),oy=Ai((([e,t])=>(e=e.mul(t)).div(e.add(1)).clamp())).setLayout({name:"reinhardToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),ay=Ai((([e,t])=>{const r=(e=(e=e.mul(t)).sub(.004).max(0)).mul(e.mul(6.2).add(.5)),s=e.mul(e.mul(6.2).add(1.7)).add(.06);return r.div(s).pow(2.2)})).setLayout({name:"cineonToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),uy=Ai((([e])=>{const t=e.mul(e.add(.0245786)).sub(90537e-9),r=e.mul(e.add(.432951).mul(.983729)).add(.238081);return t.div(r)})),ly=Ai((([e,t])=>{const r=Ki(.59719,.35458,.04823,.076,.90834,.01566,.0284,.13383,.83777),s=Ki(1.60475,-.53108,-.07367,-.10208,1.10813,-.00605,-.00327,-.07276,1.07602);return e=e.mul(t).div(.6),e=r.mul(e),e=uy(e),(e=s.mul(e)).clamp()})).setLayout({name:"acesFilmicToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),dy=Ki(Oi(1.6605,-.1246,-.0182),Oi(-.5876,1.1329,-.1006),Oi(-.0728,-.0083,1.1187)),cy=Ki(Oi(.6274,.0691,.0164),Oi(.3293,.9195,.088),Oi(.0433,.0113,.8956)),hy=Ai((([e])=>{const t=Oi(e).toVar(),r=Oi(t.mul(t)).toVar(),s=Oi(r.mul(r)).toVar();return Bi(15.5).mul(s.mul(r)).sub(Wn(40.14,s.mul(t))).add(Wn(31.96,s).sub(Wn(6.868,r.mul(t))).add(Wn(.4298,r).add(Wn(.1191,t).sub(.00232))))})),py=Ai((([e,t])=>{const r=Oi(e).toVar(),s=Ki(Oi(.856627153315983,.137318972929847,.11189821299995),Oi(.0951212405381588,.761241990602591,.0767994186031903),Oi(.0482516061458583,.101439036467562,.811302368396859)),i=Ki(Oi(1.1271005818144368,-.1413297634984383,-.14132976349843826),Oi(-.11060664309660323,1.157823702216272,-.11060664309660294),Oi(-.016493938717834573,-.016493938717834257,1.2519364065950405)),n=Bi(-12.47393),o=Bi(4.026069);return r.mulAssign(t),r.assign(cy.mul(r)),r.assign(s.mul(r)),r.assign(Zo(r,1e-10)),r.assign(So(r)),r.assign(r.sub(n).div(o.sub(n))),r.assign(ga(r,0,1)),r.assign(hy(r)),r.assign(i.mul(r)),r.assign(oa(Zo(Oi(0),r),Oi(2.2))),r.assign(dy.mul(r)),r.assign(ga(r,0,1)),r})).setLayout({name:"agxToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),gy=Ai((([e,t])=>{const r=Bi(.76),s=Bi(.15);e=e.mul(t);const i=Qo(e.r,Qo(e.g,e.b)),n=Ra(i.lessThan(.08),i.sub(Wn(6.25,i.mul(i))),.04);e.subAssign(n);const o=Zo(e.r,Zo(e.g,e.b));Ei(o.lessThan(r),(()=>e));const a=Hn(1,r),u=Hn(1,a.mul(a).div(o.add(a.sub(r))));e.mulAssign(u.div(o));const l=Hn(1,jn(1,s.mul(o.sub(u)).add(1)));return pa(e,Oi(u),l)})).setLayout({name:"neutralToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]});class my extends Ps{static get type(){return"CodeNode"}constructor(e="",t=[],r=""){super("code"),this.isCodeNode=!0,this.code=e,this.includes=t,this.language=r}isGlobal(){return!0}setIncludes(e){return this.includes=e,this}getIncludes(){return this.includes}generate(e){const t=this.getIncludes(e);for(const r of t)r.build(e);const r=e.getCodeFromNode(this,this.getNodeType(e));return r.code=this.code,r.code}serialize(e){super.serialize(e),e.code=this.code,e.language=this.language}deserialize(e){super.deserialize(e),this.code=e.code,this.language=e.language}}const fy=Ni(my);class yy extends my{static get type(){return"FunctionNode"}constructor(e="",t=[],r=""){super(e,t,r)}getNodeType(e){return this.getNodeFunction(e).type}getInputs(e){return this.getNodeFunction(e).inputs}getNodeFunction(e){const t=e.getDataFromNode(this);let r=t.nodeFunction;return void 0===r&&(r=e.parser.parseFunction(this.code),t.nodeFunction=r),r}generate(e,t){super.generate(e);const r=this.getNodeFunction(e),s=r.name,i=r.type,n=e.getCodeFromNode(this,i);""!==s&&(n.name=s);const o=e.getPropertyName(n),a=this.getNodeFunction(e).getCode(o);return n.code=a+"\n","property"===t?o:e.format(`${o}()`,i,t)}}const by=(e,t=[],r="")=>{for(let e=0;es.call(...e);return i.functionNode=s,i};class xy extends Ps{static get type(){return"ScriptableValueNode"}constructor(e=null){super(),this._value=e,this._cache=null,this.inputType=null,this.outputType=null,this.events=new o,this.isScriptableValueNode=!0}get isScriptableOutputNode(){return null!==this.outputType}set value(e){this._value!==e&&(this._cache&&"URL"===this.inputType&&this.value.value instanceof ArrayBuffer&&(URL.revokeObjectURL(this._cache),this._cache=null),this._value=e,this.events.dispatchEvent({type:"change"}),this.refresh())}get value(){return this._value}refresh(){this.events.dispatchEvent({type:"refresh"})}getValue(){const e=this.value;if(e&&null===this._cache&&"URL"===this.inputType&&e.value instanceof ArrayBuffer)this._cache=URL.createObjectURL(new Blob([e.value]));else if(e&&null!==e.value&&void 0!==e.value&&(("URL"===this.inputType||"String"===this.inputType)&&"string"==typeof e.value||"Number"===this.inputType&&"number"==typeof e.value||"Vector2"===this.inputType&&e.value.isVector2||"Vector3"===this.inputType&&e.value.isVector3||"Vector4"===this.inputType&&e.value.isVector4||"Color"===this.inputType&&e.value.isColor||"Matrix3"===this.inputType&&e.value.isMatrix3||"Matrix4"===this.inputType&&e.value.isMatrix4))return e.value;return this._cache||e}getNodeType(e){return this.value&&this.value.isNode?this.value.getNodeType(e):"float"}setup(){return this.value&&this.value.isNode?this.value:Bi()}serialize(e){super.serialize(e),null!==this.value?"ArrayBuffer"===this.inputType?e.value=vs(this.value):e.value=this.value?this.value.toJSON(e.meta).uuid:null:e.value=null,e.inputType=this.inputType,e.outputType=this.outputType}deserialize(e){super.deserialize(e);let t=null;null!==e.value&&(t="ArrayBuffer"===e.inputType?Ns(e.value):"Texture"===e.inputType?e.meta.textures[e.value]:e.meta.nodes[e.value]||null),this.value=t,this.inputType=e.inputType,this.outputType=e.outputType}}const Ty=Ni(xy);class _y extends Map{get(e,t=null,...r){if(this.has(e))return super.get(e);if(null!==t){const s=t(...r);return this.set(e,s),s}}}class vy{constructor(e){this.scriptableNode=e}get parameters(){return this.scriptableNode.parameters}get layout(){return this.scriptableNode.getLayout()}getInputLayout(e){return this.scriptableNode.getInputLayout(e)}get(e){const t=this.parameters[e];return t?t.getValue():null}}const Ny=new _y;class Sy extends Ps{static get type(){return"ScriptableNode"}constructor(e=null,t={}){super(),this.codeNode=e,this.parameters=t,this._local=new _y,this._output=Ty(),this._outputs={},this._source=this.source,this._method=null,this._object=null,this._value=null,this._needsOutputUpdate=!0,this.onRefresh=this.onRefresh.bind(this),this.isScriptableNode=!0}get source(){return this.codeNode?this.codeNode.code:""}setLocal(e,t){return this._local.set(e,t)}getLocal(e){return this._local.get(e)}onRefresh(){this._refresh()}getInputLayout(e){for(const t of this.getLayout())if(t.inputType&&(t.id===e||t.name===e))return t}getOutputLayout(e){for(const t of this.getLayout())if(t.outputType&&(t.id===e||t.name===e))return t}setOutput(e,t){const r=this._outputs;return void 0===r[e]?r[e]=Ty(t):r[e].value=t,this}getOutput(e){return this._outputs[e]}getParameter(e){return this.parameters[e]}setParameter(e,t){const r=this.parameters;return t&&t.isScriptableNode?(this.deleteParameter(e),r[e]=t,r[e].getDefaultOutput().events.addEventListener("refresh",this.onRefresh)):t&&t.isScriptableValueNode?(this.deleteParameter(e),r[e]=t,r[e].events.addEventListener("refresh",this.onRefresh)):void 0===r[e]?(r[e]=Ty(t),r[e].events.addEventListener("refresh",this.onRefresh)):r[e].value=t,this}getValue(){return this.getDefaultOutput().getValue()}deleteParameter(e){let t=this.parameters[e];return t&&(t.isScriptableNode&&(t=t.getDefaultOutput()),t.events.removeEventListener("refresh",this.onRefresh)),this}clearParameters(){for(const e of Object.keys(this.parameters))this.deleteParameter(e);return this.needsUpdate=!0,this}call(e,...t){const r=this.getObject()[e];if("function"==typeof r)return r(...t)}async callAsync(e,...t){const r=this.getObject()[e];if("function"==typeof r)return"AsyncFunction"===r.constructor.name?await r(...t):r(...t)}getNodeType(e){return this.getDefaultOutputNode().getNodeType(e)}refresh(e=null){null!==e?this.getOutput(e).refresh():this._refresh()}getObject(){if(this.needsUpdate&&this.dispose(),null!==this._object)return this._object;const e=new vy(this),t=Ny.get("THREE"),r=Ny.get("TSL"),s=this.getMethod(),i=[e,this._local,Ny,()=>this.refresh(),(e,t)=>this.setOutput(e,t),t,r];this._object=s(...i);const n=this._object.layout;if(n&&(!1===n.cache&&this._local.clear(),this._output.outputType=n.outputType||null,Array.isArray(n.elements)))for(const e of n.elements){const t=e.id||e.name;e.inputType&&(void 0===this.getParameter(t)&&this.setParameter(t,null),this.getParameter(t).inputType=e.inputType),e.outputType&&(void 0===this.getOutput(t)&&this.setOutput(t,null),this.getOutput(t).outputType=e.outputType)}return this._object}deserialize(e){super.deserialize(e);for(const e in this.parameters){let t=this.parameters[e];t.isScriptableNode&&(t=t.getDefaultOutput()),t.events.addEventListener("refresh",this.onRefresh)}}getLayout(){return this.getObject().layout}getDefaultOutputNode(){const e=this.getDefaultOutput().value;return e&&e.isNode?e:Bi()}getDefaultOutput(){return this._exec()._output}getMethod(){if(this.needsUpdate&&this.dispose(),null!==this._method)return this._method;const e=["layout","init","main","dispose"].join(", "),t="\nreturn { ...output, "+e+" };",r="var "+e+"; var output = {};\n"+this.codeNode.code+t;return this._method=new Function(...["parameters","local","global","refresh","setOutput","THREE","TSL"],r),this._method}dispose(){null!==this._method&&(this._object&&"function"==typeof this._object.dispose&&this._object.dispose(),this._method=null,this._object=null,this._source=null,this._value=null,this._needsOutputUpdate=!0,this._output.value=null,this._outputs={})}setup(){return this.getDefaultOutputNode()}getCacheKey(e){const t=[ls(this.source),this.getDefaultOutputNode().getCacheKey(e)];for(const r in this.parameters)t.push(this.parameters[r].getCacheKey(e));return ds(t)}set needsUpdate(e){!0===e&&this.dispose()}get needsUpdate(){return this.source!==this._source}_exec(){return null===this.codeNode||(!0===this._needsOutputUpdate&&(this._value=this.call("main"),this._needsOutputUpdate=!1),this._output.value=this._value),this}_refresh(){this.needsUpdate=!0,this._exec(),this._output.refresh()}}const Ay=Ni(Sy);function Ry(e){let t;const r=e.context.getViewZ;return void 0!==r&&(t=r(this)),(t||nl.z).negate()}const Cy=Ai((([e,t],r)=>{const s=Ry(r);return ya(e,t,s)})),Ey=Ai((([e],t)=>{const r=Ry(t);return e.mul(e,r,r).negate().exp().oneMinus()})),wy=Ai((([e,t])=>$i(t.toFloat().mix(En.rgb,e.toVec3()),En.a)));let My=null,By=null;class Fy extends Ps{static get type(){return"RangeNode"}constructor(e=Bi(),t=Bi()){super(),this.minNode=e,this.maxNode=t}getVectorLength(e){const t=e.getTypeLength(xs(this.minNode.value)),r=e.getTypeLength(xs(this.maxNode.value));return t>r?t:r}getNodeType(e){return e.object.count>1?e.getTypeFromLength(this.getVectorLength(e)):"float"}setup(e){const t=e.object;let r=null;if(t.count>1){const i=this.minNode.value,n=this.maxNode.value,o=e.getTypeLength(xs(i)),u=e.getTypeLength(xs(n));My=My||new s,By=By||new s,My.setScalar(0),By.setScalar(0),1===o?My.setScalar(i):i.isColor?My.set(i.r,i.g,i.b,1):My.set(i.x,i.y,i.z||0,i.w||0),1===u?By.setScalar(n):n.isColor?By.set(n.r,n.g,n.b,1):By.set(n.x,n.y,n.z||0,n.w||0);const l=4,d=l*t.count,c=new Float32Array(d);for(let e=0;eTi(new Py(e,t)),Dy=Iy("numWorkgroups","uvec3"),Ly=Iy("workgroupId","uvec3"),Vy=Iy("localId","uvec3"),Oy=Iy("subgroupSize","uint");const Gy=Ni(class extends Ps{constructor(e){super(),this.scope=e}generate(e){const{scope:t}=this,{renderer:r}=e;!0===r.backend.isWebGLBackend?e.addFlowCode(`\t// ${t}Barrier \n`):e.addLineFlowCode(`${t}Barrier()`,this)}});class ky extends Is{constructor(e,t){super(e,t),this.isWorkgroupInfoElementNode=!0}generate(e,t){let r;const s=e.context.assign;if(r=super.generate(e),!0!==s){const s=this.getNodeType(e);r=e.format(r,s,t)}return r}}class zy extends Ps{constructor(e,t,r=0){super(t),this.bufferType=t,this.bufferCount=r,this.isWorkgroupInfoNode=!0,this.elementType=t,this.scope=e}label(e){return this.name=e,this}setScope(e){return this.scope=e,this}getElementType(){return this.elementType}getInputType(){return`${this.scope}Array`}element(e){return Ti(new ky(this,e))}generate(e){return e.getScopedArray(this.name||`${this.scope}Array_${this.id}`,this.scope.toLowerCase(),this.bufferType,this.bufferCount)}}class $y extends Ls{static get type(){return"AtomicFunctionNode"}constructor(e,t,r,s=null){super("uint"),this.method=e,this.pointerNode=t,this.valueNode=r,this.storeNode=s}getInputType(e){return this.pointerNode.getNodeType(e)}getNodeType(e){return this.getInputType(e)}generate(e){const t=this.method,r=this.getNodeType(e),s=this.getInputType(e),i=this.pointerNode,n=this.valueNode,o=[];o.push(`&${i.build(e,s)}`),o.push(n.build(e,s));const a=`${e.getMethod(t,r)}( ${o.join(", ")} )`;if(null!==this.storeNode){const t=this.storeNode.build(e,s);e.addLineFlowCode(`${t} = ${a}`,this)}else e.addLineFlowCode(a,this)}}$y.ATOMIC_LOAD="atomicLoad",$y.ATOMIC_STORE="atomicStore",$y.ATOMIC_ADD="atomicAdd",$y.ATOMIC_SUB="atomicSub",$y.ATOMIC_MAX="atomicMax",$y.ATOMIC_MIN="atomicMin",$y.ATOMIC_AND="atomicAnd",$y.ATOMIC_OR="atomicOr",$y.ATOMIC_XOR="atomicXor";const Hy=Ni($y),Wy=(e,t,r,s=null)=>{const i=Hy(e,t,r,s);return i.append(),i};let jy;function qy(e){jy=jy||new WeakMap;let t=jy.get(e);return void 0===t&&jy.set(e,t={}),t}function Ky(e){const t=qy(e);return t.shadowMatrix||(t.shadowMatrix=on("mat4").setGroup(rn).onRenderUpdate((()=>(!0!==e.castShadow&&e.shadow.updateMatrices(e),e.shadow.matrix))))}function Xy(e){const t=qy(e);if(void 0===t.projectionUV){const r=Ky(e).mul(sl);t.projectionUV=r.xyz.div(r.w)}return t.projectionUV}function Yy(e){const t=qy(e);return t.position||(t.position=on(new r).setGroup(rn).onRenderUpdate(((t,r)=>r.value.setFromMatrixPosition(e.matrixWorld))))}function Qy(e){const t=qy(e);return t.targetPosition||(t.targetPosition=on(new r).setGroup(rn).onRenderUpdate(((t,r)=>r.value.setFromMatrixPosition(e.target.matrixWorld))))}function Zy(e){const t=qy(e);return t.viewPosition||(t.viewPosition=on(new r).setGroup(rn).onRenderUpdate((({camera:t},s)=>{s.value=s.value||new r,s.value.setFromMatrixPosition(e.matrixWorld),s.value.applyMatrix4(t.matrixWorldInverse)})))}const Jy=e=>Fu.transformDirection(Yy(e).sub(Qy(e))),eb=(e,t)=>{for(const r of t)if(r.isAnalyticLightNode&&r.light.id===e)return r;return null},tb=new WeakMap;class rb extends Ps{static get type(){return"LightsNode"}constructor(){super("vec3"),this.totalDiffuseNode=Oi().toVar("totalDiffuse"),this.totalSpecularNode=Oi().toVar("totalSpecular"),this.outgoingLightNode=Oi().toVar("outgoingLight"),this._lights=[],this._lightNodes=null,this._lightNodesHash=null,this.global=!0}customCacheKey(){const e=[],t=this._lights;for(let r=0;re.sort(((e,t)=>e.id-t.id)))(this._lights),i=e.renderer.library;for(const e of s)if(e.isNode)t.push(Ti(e));else{let s=null;if(null!==r&&(s=eb(e.id,r)),null===s){const r=i.getLightNodeClass(e.constructor);if(null===r){console.warn(`LightsNode.setupNodeLights: Light node not found for ${e.constructor.name}`);continue}let s=null;tb.has(e)?s=tb.get(e):(s=Ti(new r(e)),tb.set(e,s)),t.push(s)}}this._lightNodes=t}setupLights(e,t){for(const r of t)r.build(e)}setup(e){null===this._lightNodes&&this.setupLightsNode(e);const t=e.context,r=t.lightingModel;let s=this.outgoingLightNode;if(r){const{_lightNodes:i,totalDiffuseNode:n,totalSpecularNode:o}=this;t.outgoingLight=s;const a=e.addStack();e.getDataFromNode(this).nodes=a.nodes,r.start(t,a,e),this.setupLights(e,i),r.indirect(t,a,e);const{backdrop:u,backdropAlpha:l}=t,{directDiffuse:d,directSpecular:c,indirectDiffuse:h,indirectSpecular:p}=t.reflectedLight;let g=d.add(h);null!==u&&(g=Oi(null!==l?l.mix(g,u):u),t.material.transparent=!0),n.assign(g),o.assign(c.add(p)),s.assign(n.add(o)),r.finish(t,a,e),s=s.bypass(e.removeStack())}return s}setLights(e){return this._lights=e,this._lightNodes=null,this._lightNodesHash=null,this}getLights(){return this._lights}get hasLights(){return this._lights.length>0}}class sb extends Ps{static get type(){return"ShadowBaseNode"}constructor(e){super(),this.light=e,this.updateBeforeType=Rs.RENDER,this.isShadowBaseNode=!0}setupShadowPosition({material:e}){ib.assign(e.shadowPositionNode||sl)}dispose(){this.updateBeforeType=Rs.NONE}}const ib=Oi().toVar("shadowPositionWorld");function nb(t,r={}){return r.toneMapping=t.toneMapping,r.toneMappingExposure=t.toneMappingExposure,r.outputColorSpace=t.outputColorSpace,r.renderTarget=t.getRenderTarget(),r.activeCubeFace=t.getActiveCubeFace(),r.activeMipmapLevel=t.getActiveMipmapLevel(),r.renderObjectFunction=t.getRenderObjectFunction(),r.pixelRatio=t.getPixelRatio(),r.mrt=t.getMRT(),r.clearColor=t.getClearColor(r.clearColor||new e),r.clearAlpha=t.getClearAlpha(),r.autoClear=t.autoClear,r.scissorTest=t.getScissorTest(),r}function ob(e,t){return t=nb(e,t),e.setMRT(null),e.setRenderObjectFunction(null),e.setClearColor(0,1),e.autoClear=!0,t}function ab(e,t){e.toneMapping=t.toneMapping,e.toneMappingExposure=t.toneMappingExposure,e.outputColorSpace=t.outputColorSpace,e.setRenderTarget(t.renderTarget,t.activeCubeFace,t.activeMipmapLevel),e.setRenderObjectFunction(t.renderObjectFunction),e.setPixelRatio(t.pixelRatio),e.setMRT(t.mrt),e.setClearColor(t.clearColor,t.clearAlpha),e.autoClear=t.autoClear,e.setScissorTest(t.scissorTest)}function ub(e,t={}){return t.background=e.background,t.backgroundNode=e.backgroundNode,t.overrideMaterial=e.overrideMaterial,t}function lb(e,t){return t=ub(e,t),e.background=null,e.backgroundNode=null,e.overrideMaterial=null,t}function db(e,t){e.background=t.background,e.backgroundNode=t.backgroundNode,e.overrideMaterial=t.overrideMaterial}function cb(e,t,r){return r=lb(t,r=ob(e,r))}function hb(e,t,r){ab(e,r),db(t,r)}var pb=Object.freeze({__proto__:null,resetRendererAndSceneState:cb,resetRendererState:ob,resetSceneState:lb,restoreRendererAndSceneState:hb,restoreRendererState:ab,restoreSceneState:db,saveRendererAndSceneState:function(e,t,r={}){return r=ub(t,r=nb(e,r))},saveRendererState:nb,saveSceneState:ub});const gb=new WeakMap,mb=Ai((([e,t,r])=>{let s=sl.sub(e).length();return s=s.sub(t).div(r.sub(t)),s=s.saturate(),s})),fb=e=>{let t=gb.get(e);if(void 0===t){const r=e.isPointLight?(e=>{const t=e.shadow.camera,r=Pl("near","float",t).setGroup(rn),s=Pl("far","float",t).setGroup(rn),i=Ou(e);return mb(i,r,s)})(e):null;t=new sh,t.colorNode=$i(0,0,0,1),t.depthNode=r,t.isShadowNodeMaterial=!0,t.name="ShadowMaterial",t.fog=!1,gb.set(e,t)}return t},yb=Ai((({depthTexture:e,shadowCoord:t})=>Ru(e,t.xy).compare(t.z))),bb=Ai((({depthTexture:e,shadowCoord:t,shadow:r})=>{const s=(t,r)=>Ru(e,t).compare(r),i=Pl("mapSize","vec2",r).setGroup(rn),n=Pl("radius","float",r).setGroup(rn),o=Ii(1).div(i),a=o.x.negate().mul(n),u=o.y.negate().mul(n),l=o.x.mul(n),d=o.y.mul(n),c=a.div(2),h=u.div(2),p=l.div(2),g=d.div(2);return $n(s(t.xy.add(Ii(a,u)),t.z),s(t.xy.add(Ii(0,u)),t.z),s(t.xy.add(Ii(l,u)),t.z),s(t.xy.add(Ii(c,h)),t.z),s(t.xy.add(Ii(0,h)),t.z),s(t.xy.add(Ii(p,h)),t.z),s(t.xy.add(Ii(a,0)),t.z),s(t.xy.add(Ii(c,0)),t.z),s(t.xy,t.z),s(t.xy.add(Ii(p,0)),t.z),s(t.xy.add(Ii(l,0)),t.z),s(t.xy.add(Ii(c,g)),t.z),s(t.xy.add(Ii(0,g)),t.z),s(t.xy.add(Ii(p,g)),t.z),s(t.xy.add(Ii(a,d)),t.z),s(t.xy.add(Ii(0,d)),t.z),s(t.xy.add(Ii(l,d)),t.z)).mul(1/17)})),xb=Ai((({depthTexture:e,shadowCoord:t,shadow:r})=>{const s=(t,r)=>Ru(e,t).compare(r),i=Pl("mapSize","vec2",r).setGroup(rn),n=Ii(1).div(i),o=n.x,a=n.y,u=t.xy,l=Mo(u.mul(i).add(.5));return u.subAssign(l.mul(n)),$n(s(u,t.z),s(u.add(Ii(o,0)),t.z),s(u.add(Ii(0,a)),t.z),s(u.add(n),t.z),pa(s(u.add(Ii(o.negate(),0)),t.z),s(u.add(Ii(o.mul(2),0)),t.z),l.x),pa(s(u.add(Ii(o.negate(),a)),t.z),s(u.add(Ii(o.mul(2),a)),t.z),l.x),pa(s(u.add(Ii(0,a.negate())),t.z),s(u.add(Ii(0,a.mul(2))),t.z),l.y),pa(s(u.add(Ii(o,a.negate())),t.z),s(u.add(Ii(o,a.mul(2))),t.z),l.y),pa(pa(s(u.add(Ii(o.negate(),a.negate())),t.z),s(u.add(Ii(o.mul(2),a.negate())),t.z),l.x),pa(s(u.add(Ii(o.negate(),a.mul(2))),t.z),s(u.add(Ii(o.mul(2),a.mul(2))),t.z),l.x),l.y)).mul(1/9)})),Tb=Ai((({depthTexture:e,shadowCoord:t})=>{const r=Bi(1).toVar(),s=Ru(e).sample(t.xy).rg,i=ea(t.z,s.x);return Ei(i.notEqual(Bi(1)),(()=>{const e=t.z.sub(s.x),n=Zo(0,s.y.mul(s.y));let o=n.div(n.add(e.mul(e)));o=ga(Hn(o,.3).div(.95-.3)),r.assign(ga(Zo(i,o)))})),r})),_b=Ai((({samples:e,radius:t,size:r,shadowPass:s})=>{const i=Bi(0).toVar(),n=Bi(0).toVar(),o=e.lessThanEqual(Bi(1)).select(Bi(0),Bi(2).div(e.sub(1))),a=e.lessThanEqual(Bi(1)).select(Bi(0),Bi(-1));cc({start:Fi(0),end:Fi(e),type:"int",condition:"<"},(({i:e})=>{const u=a.add(Bi(e).mul(o)),l=s.sample($n(Ec.xy,Ii(0,u).mul(t)).div(r)).x;i.addAssign(l),n.addAssign(l.mul(l))})),i.divAssign(e),n.divAssign(e);const u=Ao(n.sub(i.mul(i)));return Ii(i,u)})),vb=Ai((({samples:e,radius:t,size:r,shadowPass:s})=>{const i=Bi(0).toVar(),n=Bi(0).toVar(),o=e.lessThanEqual(Bi(1)).select(Bi(0),Bi(2).div(e.sub(1))),a=e.lessThanEqual(Bi(1)).select(Bi(0),Bi(-1));cc({start:Fi(0),end:Fi(e),type:"int",condition:"<"},(({i:e})=>{const u=a.add(Bi(e).mul(o)),l=s.sample($n(Ec.xy,Ii(u,0).mul(t)).div(r));i.addAssign(l.x),n.addAssign($n(l.y.mul(l.y),l.x.mul(l.x)))})),i.divAssign(e),n.divAssign(e);const u=Ao(n.sub(i.mul(i)));return Ii(i,u)})),Nb=[yb,bb,xb,Tb];let Sb;const Ab=new cf;class Rb extends sb{static get type(){return"ShadowNode"}constructor(e,t=null){super(e),this.shadow=t||e.shadow,this.shadowMap=null,this.vsmShadowMapVertical=null,this.vsmShadowMapHorizontal=null,this.vsmMaterialVertical=null,this.vsmMaterialHorizontal=null,this._node=null,this.isShadowNode=!0}setupShadowFilter(e,{filterFn:t,depthTexture:r,shadowCoord:s,shadow:i}){const n=s.x.greaterThanEqual(0).and(s.x.lessThanEqual(1)).and(s.y.greaterThanEqual(0)).and(s.y.lessThanEqual(1)).and(s.z.lessThanEqual(1)),o=t({depthTexture:r,shadowCoord:s,shadow:i});return n.select(o,Bi(1))}setupShadowCoord(e,t){const{shadow:r}=this,{renderer:s}=e,i=Pl("bias","float",r).setGroup(rn);let n,o=t;if(r.camera.isOrthographicCamera||!0!==s.logarithmicDepthBuffer)o=o.xyz.div(o.w),n=o.z,s.coordinateSystem===l&&(n=n.mul(2).sub(1));else{const e=o.w;o=o.xy.div(e);const t=Pl("near","float",r.camera).setGroup(rn),s=Pl("far","float",r.camera).setGroup(rn);n=qc(e.negate(),t,s)}return o=Oi(o.x,o.y.oneMinus(),n.add(i)),o}getShadowFilterFn(e){return Nb[e]}setupShadow(e){const{renderer:t}=e,{light:r,shadow:s}=this,i=t.shadowMap.type,n=new B(s.mapSize.width,s.mapSize.height);n.compareFunction=Ce;const o=e.createRenderTarget(s.mapSize.width,s.mapSize.height);if(o.depthTexture=n,s.camera.updateProjectionMatrix(),i===Ee){n.compareFunction=null,this.vsmShadowMapVertical=e.createRenderTarget(s.mapSize.width,s.mapSize.height,{format:we,type:be}),this.vsmShadowMapHorizontal=e.createRenderTarget(s.mapSize.width,s.mapSize.height,{format:we,type:be});const t=Ru(n),r=Ru(this.vsmShadowMapVertical.texture),i=Pl("blurSamples","float",s).setGroup(rn),o=Pl("radius","float",s).setGroup(rn),a=Pl("mapSize","vec2",s).setGroup(rn);let u=this.vsmMaterialVertical||(this.vsmMaterialVertical=new sh);u.fragmentNode=_b({samples:i,radius:o,size:a,shadowPass:t}).context(e.getSharedContext()),u.name="VSMVertical",u=this.vsmMaterialHorizontal||(this.vsmMaterialHorizontal=new sh),u.fragmentNode=vb({samples:i,radius:o,size:a,shadowPass:r}).context(e.getSharedContext()),u.name="VSMHorizontal"}const a=Pl("intensity","float",s).setGroup(rn),u=Pl("normalBias","float",s).setGroup(rn),l=Ky(r).mul(ib.add(fl.mul(u))),d=this.setupShadowCoord(e,l),c=s.filterNode||this.getShadowFilterFn(t.shadowMap.type)||null;if(null===c)throw new Error("THREE.WebGPURenderer: Shadow map type not supported yet.");const h=i===Ee?this.vsmShadowMapHorizontal.texture:n,p=this.setupShadowFilter(e,{filterFn:c,shadowTexture:o.texture,depthTexture:h,shadowCoord:d,shadow:s}),g=Ru(o.texture,d),m=pa(1,p.rgb.mix(g,1),a.mul(g.a)).toVar();return this.shadowMap=o,this.shadow.map=o,m}setup(e){if(!1!==e.renderer.shadowMap.enabled)return Ai((()=>{let t=this._node;return this.setupShadowPosition(e),null===t&&(this._node=t=this.setupShadow(e)),e.material.shadowNode&&console.warn('THREE.NodeMaterial: ".shadowNode" is deprecated. Use ".castShadowNode" instead.'),e.material.receivedShadowNode&&(t=e.material.receivedShadowNode(t)),t}))()}renderShadow(e){const{shadow:t,shadowMap:r,light:s}=this,{renderer:i,scene:n}=e;t.updateMatrices(s),r.setSize(t.mapSize.width,t.mapSize.height),i.render(n,t.camera)}updateShadow(e){const{shadowMap:t,light:r,shadow:s}=this,{renderer:i,scene:n,camera:o}=e,a=i.shadowMap.type,u=t.depthTexture.version;this._depthVersionCached=u,s.camera.layers.mask=o.layers.mask;const l=i.getRenderObjectFunction(),d=i.getMRT(),c=!!d&&d.has("velocity");Sb=cb(i,n,Sb),n.overrideMaterial=fb(r),i.setRenderObjectFunction(((e,t,r,n,u,l,...d)=>{(!0===e.castShadow||e.receiveShadow&&a===Ee)&&(c&&(_s(e).useVelocity=!0),e.onBeforeShadow(i,e,o,s.camera,n,t.overrideMaterial,l),i.renderObject(e,t,r,n,u,l,...d),e.onAfterShadow(i,e,o,s.camera,n,t.overrideMaterial,l))})),i.setRenderTarget(t),this.renderShadow(e),i.setRenderObjectFunction(l),!0!==r.isPointLight&&a===Ee&&this.vsmPass(i),hb(i,n,Sb)}vsmPass(e){const{shadow:t}=this;this.vsmShadowMapVertical.setSize(t.mapSize.width,t.mapSize.height),this.vsmShadowMapHorizontal.setSize(t.mapSize.width,t.mapSize.height),e.setRenderTarget(this.vsmShadowMapVertical),Ab.material=this.vsmMaterialVertical,Ab.render(e),e.setRenderTarget(this.vsmShadowMapHorizontal),Ab.material=this.vsmMaterialHorizontal,Ab.render(e)}dispose(){this.shadowMap.dispose(),this.shadowMap=null,null!==this.vsmShadowMapVertical&&(this.vsmShadowMapVertical.dispose(),this.vsmShadowMapVertical=null,this.vsmMaterialVertical.dispose(),this.vsmMaterialVertical=null),null!==this.vsmShadowMapHorizontal&&(this.vsmShadowMapHorizontal.dispose(),this.vsmShadowMapHorizontal=null,this.vsmMaterialHorizontal.dispose(),this.vsmMaterialHorizontal=null),super.dispose()}updateBefore(e){const{shadow:t}=this;(t.needsUpdate||t.autoUpdate)&&(this.updateShadow(e),this.shadowMap.depthTexture.version===this._depthVersionCached&&(t.needsUpdate=!1))}}const Cb=(e,t)=>Ti(new Rb(e,t));class Eb extends bc{static get type(){return"AnalyticLightNode"}constructor(t=null){super(),this.light=t,this.color=new e,this.colorNode=t&&t.colorNode||on(this.color).setGroup(rn),this.baseColorNode=null,this.shadowNode=null,this.shadowColorNode=null,this.isAnalyticLightNode=!0,this.updateType=Rs.FRAME}customCacheKey(){return cs(this.light.id,this.light.castShadow?1:0)}getHash(){return this.light.uuid}setupShadowNode(){return Cb(this.light)}setupShadow(e){const{renderer:t}=e;if(!1===t.shadowMap.enabled)return;let r=this.shadowColorNode;if(null===r){const t=this.light.shadow.shadowNode;let s;s=void 0!==t?Ti(t):this.setupShadowNode(e),this.shadowNode=s,this.shadowColorNode=r=this.colorNode.mul(s),this.baseColorNode=this.colorNode}this.colorNode=r}setup(e){this.colorNode=this.baseColorNode||this.colorNode,this.light.castShadow?e.object.receiveShadow&&this.setupShadow(e):null!==this.shadowNode&&(this.shadowNode.dispose(),this.shadowNode=null,this.shadowColorNode=null)}update(){const{light:e}=this;this.color.copy(e.color).multiplyScalar(e.intensity)}}const wb=Ai((e=>{const{lightDistance:t,cutoffDistance:r,decayExponent:s}=e,i=t.pow(s).max(.01).reciprocal();return r.greaterThan(0).select(i.mul(t.div(r).pow4().oneMinus().clamp().pow2()),i)})),Mb=new e,Bb=Ai((([e,t])=>{const r=e.toVar(),s=Lo(r),i=jn(1,Zo(s.x,Zo(s.y,s.z)));s.mulAssign(i),r.mulAssign(i.mul(t.mul(2).oneMinus()));const n=Ii(r.xy).toVar(),o=t.mul(1.5).oneMinus();return Ei(s.z.greaterThanEqual(o),(()=>{Ei(r.z.greaterThan(0),(()=>{n.x.assign(Hn(4,r.x))}))})).ElseIf(s.x.greaterThanEqual(o),(()=>{const e=Vo(r.x);n.x.assign(r.z.mul(e).add(e.mul(2)))})).ElseIf(s.y.greaterThanEqual(o),(()=>{const e=Vo(r.y);n.x.assign(r.x.add(e.mul(2)).add(2)),n.y.assign(r.z.mul(e).sub(2))})),Ii(.125,.25).mul(n).add(Ii(.375,.75)).flipY()})).setLayout({name:"cubeToUV",type:"vec2",inputs:[{name:"pos",type:"vec3"},{name:"texelSizeY",type:"float"}]}),Fb=Ai((({depthTexture:e,bd3D:t,dp:r,texelSize:s})=>Ru(e,Bb(t,s.y)).compare(r))),Ub=Ai((({depthTexture:e,bd3D:t,dp:r,texelSize:s,shadow:i})=>{const n=Pl("radius","float",i).setGroup(rn),o=Ii(-1,1).mul(n).mul(s.y);return Ru(e,Bb(t.add(o.xyy),s.y)).compare(r).add(Ru(e,Bb(t.add(o.yyy),s.y)).compare(r)).add(Ru(e,Bb(t.add(o.xyx),s.y)).compare(r)).add(Ru(e,Bb(t.add(o.yyx),s.y)).compare(r)).add(Ru(e,Bb(t,s.y)).compare(r)).add(Ru(e,Bb(t.add(o.xxy),s.y)).compare(r)).add(Ru(e,Bb(t.add(o.yxy),s.y)).compare(r)).add(Ru(e,Bb(t.add(o.xxx),s.y)).compare(r)).add(Ru(e,Bb(t.add(o.yxx),s.y)).compare(r)).mul(1/9)})),Pb=Ai((({filterFn:e,depthTexture:t,shadowCoord:r,shadow:s})=>{const i=r.xyz.toVar(),n=i.length(),o=on("float").setGroup(rn).onRenderUpdate((()=>s.camera.near)),a=on("float").setGroup(rn).onRenderUpdate((()=>s.camera.far)),u=Pl("bias","float",s).setGroup(rn),l=on(s.mapSize).setGroup(rn),d=Bi(1).toVar();return Ei(n.sub(a).lessThanEqual(0).and(n.sub(o).greaterThanEqual(0)),(()=>{const r=n.sub(o).div(a.sub(o)).toVar();r.addAssign(u);const c=i.normalize(),h=Ii(1).div(l.mul(Ii(4,2)));d.assign(e({depthTexture:t,bd3D:c,dp:r,texelSize:h,shadow:s}))})),d})),Ib=new s,Db=new t,Lb=new t;class Vb extends Rb{static get type(){return"PointShadowNode"}constructor(e,t=null){super(e,t)}getShadowFilterFn(e){return e===Me?Fb:Ub}setupShadowCoord(e,t){return t}setupShadowFilter(e,{filterFn:t,shadowTexture:r,depthTexture:s,shadowCoord:i,shadow:n}){return Pb({filterFn:t,shadowTexture:r,depthTexture:s,shadowCoord:i,shadow:n})}renderShadow(e){const{shadow:t,shadowMap:r,light:s}=this,{renderer:i,scene:n}=e,o=t.getFrameExtents();Lb.copy(t.mapSize),Lb.multiply(o),r.setSize(Lb.width,Lb.height),Db.copy(t.mapSize);const a=i.autoClear,u=i.getClearColor(Mb),l=i.getClearAlpha();i.autoClear=!1,i.setClearColor(t.clearColor,t.clearAlpha),i.clear();const d=t.getViewportCount();for(let e=0;e{const n=i.context.lightingModel,o=t.sub(nl),a=o.normalize(),u=o.length(),l=wb({lightDistance:u,cutoffDistance:r,decayExponent:s}),d=e.mul(l),c=i.context.reflectedLight;n.direct({lightDirection:a,lightColor:d,reflectedLight:c},i.stack,i)}));class Gb extends Eb{static get type(){return"PointLightNode"}constructor(e=null){super(e),this.cutoffDistanceNode=on(0).setGroup(rn),this.decayExponentNode=on(2).setGroup(rn)}update(e){const{light:t}=this;super.update(e),this.cutoffDistanceNode.value=t.distance,this.decayExponentNode.value=t.decay}setupShadowNode(){return((e,t)=>Ti(new Vb(e,t)))(this.light)}setup(e){super.setup(e),Ob({color:this.colorNode,lightViewPosition:Zy(this.light),cutoffDistance:this.cutoffDistanceNode,decayExponent:this.decayExponentNode}).append()}}const kb=Ai((([e=t()])=>{const t=e.mul(2),r=t.x.floor(),s=t.y.floor();return r.add(s).mod(2).sign()})),zb=Ai((([e,t,r])=>{const s=Bi(r).toVar(),i=Bi(t).toVar(),n=Pi(e).toVar();return Ra(n,i,s)})).setLayout({name:"mx_select",type:"float",inputs:[{name:"b",type:"bool"},{name:"t",type:"float"},{name:"f",type:"float"}]}),$b=Ai((([e,t])=>{const r=Pi(t).toVar(),s=Bi(e).toVar();return Ra(r,s.negate(),s)})).setLayout({name:"mx_negate_if",type:"float",inputs:[{name:"val",type:"float"},{name:"b",type:"bool"}]}),Hb=Ai((([e])=>{const t=Bi(e).toVar();return Fi(Co(t))})).setLayout({name:"mx_floor",type:"int",inputs:[{name:"x",type:"float"}]}),Wb=Ai((([e,t])=>{const r=Bi(e).toVar();return t.assign(Hb(r)),r.sub(Bi(t))})),jb=Um([Ai((([e,t,r,s,i,n])=>{const o=Bi(n).toVar(),a=Bi(i).toVar(),u=Bi(s).toVar(),l=Bi(r).toVar(),d=Bi(t).toVar(),c=Bi(e).toVar(),h=Bi(Hn(1,a)).toVar();return Hn(1,o).mul(c.mul(h).add(d.mul(a))).add(o.mul(l.mul(h).add(u.mul(a))))})).setLayout({name:"mx_bilerp_0",type:"float",inputs:[{name:"v0",type:"float"},{name:"v1",type:"float"},{name:"v2",type:"float"},{name:"v3",type:"float"},{name:"s",type:"float"},{name:"t",type:"float"}]}),Ai((([e,t,r,s,i,n])=>{const o=Bi(n).toVar(),a=Bi(i).toVar(),u=Oi(s).toVar(),l=Oi(r).toVar(),d=Oi(t).toVar(),c=Oi(e).toVar(),h=Bi(Hn(1,a)).toVar();return Hn(1,o).mul(c.mul(h).add(d.mul(a))).add(o.mul(l.mul(h).add(u.mul(a))))})).setLayout({name:"mx_bilerp_1",type:"vec3",inputs:[{name:"v0",type:"vec3"},{name:"v1",type:"vec3"},{name:"v2",type:"vec3"},{name:"v3",type:"vec3"},{name:"s",type:"float"},{name:"t",type:"float"}]})]),qb=Um([Ai((([e,t,r,s,i,n,o,a,u,l,d])=>{const c=Bi(d).toVar(),h=Bi(l).toVar(),p=Bi(u).toVar(),g=Bi(a).toVar(),m=Bi(o).toVar(),f=Bi(n).toVar(),y=Bi(i).toVar(),b=Bi(s).toVar(),x=Bi(r).toVar(),T=Bi(t).toVar(),_=Bi(e).toVar(),v=Bi(Hn(1,p)).toVar(),N=Bi(Hn(1,h)).toVar();return Bi(Hn(1,c)).toVar().mul(N.mul(_.mul(v).add(T.mul(p))).add(h.mul(x.mul(v).add(b.mul(p))))).add(c.mul(N.mul(y.mul(v).add(f.mul(p))).add(h.mul(m.mul(v).add(g.mul(p))))))})).setLayout({name:"mx_trilerp_0",type:"float",inputs:[{name:"v0",type:"float"},{name:"v1",type:"float"},{name:"v2",type:"float"},{name:"v3",type:"float"},{name:"v4",type:"float"},{name:"v5",type:"float"},{name:"v6",type:"float"},{name:"v7",type:"float"},{name:"s",type:"float"},{name:"t",type:"float"},{name:"r",type:"float"}]}),Ai((([e,t,r,s,i,n,o,a,u,l,d])=>{const c=Bi(d).toVar(),h=Bi(l).toVar(),p=Bi(u).toVar(),g=Oi(a).toVar(),m=Oi(o).toVar(),f=Oi(n).toVar(),y=Oi(i).toVar(),b=Oi(s).toVar(),x=Oi(r).toVar(),T=Oi(t).toVar(),_=Oi(e).toVar(),v=Bi(Hn(1,p)).toVar(),N=Bi(Hn(1,h)).toVar();return Bi(Hn(1,c)).toVar().mul(N.mul(_.mul(v).add(T.mul(p))).add(h.mul(x.mul(v).add(b.mul(p))))).add(c.mul(N.mul(y.mul(v).add(f.mul(p))).add(h.mul(m.mul(v).add(g.mul(p))))))})).setLayout({name:"mx_trilerp_1",type:"vec3",inputs:[{name:"v0",type:"vec3"},{name:"v1",type:"vec3"},{name:"v2",type:"vec3"},{name:"v3",type:"vec3"},{name:"v4",type:"vec3"},{name:"v5",type:"vec3"},{name:"v6",type:"vec3"},{name:"v7",type:"vec3"},{name:"s",type:"float"},{name:"t",type:"float"},{name:"r",type:"float"}]})]),Kb=Ai((([e,t,r])=>{const s=Bi(r).toVar(),i=Bi(t).toVar(),n=Ui(e).toVar(),o=Ui(n.bitAnd(Ui(7))).toVar(),a=Bi(zb(o.lessThan(Ui(4)),i,s)).toVar(),u=Bi(Wn(2,zb(o.lessThan(Ui(4)),s,i))).toVar();return $b(a,Pi(o.bitAnd(Ui(1)))).add($b(u,Pi(o.bitAnd(Ui(2)))))})).setLayout({name:"mx_gradient_float_0",type:"float",inputs:[{name:"hash",type:"uint"},{name:"x",type:"float"},{name:"y",type:"float"}]}),Xb=Ai((([e,t,r,s])=>{const i=Bi(s).toVar(),n=Bi(r).toVar(),o=Bi(t).toVar(),a=Ui(e).toVar(),u=Ui(a.bitAnd(Ui(15))).toVar(),l=Bi(zb(u.lessThan(Ui(8)),o,n)).toVar(),d=Bi(zb(u.lessThan(Ui(4)),n,zb(u.equal(Ui(12)).or(u.equal(Ui(14))),o,i))).toVar();return $b(l,Pi(u.bitAnd(Ui(1)))).add($b(d,Pi(u.bitAnd(Ui(2)))))})).setLayout({name:"mx_gradient_float_1",type:"float",inputs:[{name:"hash",type:"uint"},{name:"x",type:"float"},{name:"y",type:"float"},{name:"z",type:"float"}]}),Yb=Um([Kb,Xb]),Qb=Ai((([e,t,r])=>{const s=Bi(r).toVar(),i=Bi(t).toVar(),n=ki(e).toVar();return Oi(Yb(n.x,i,s),Yb(n.y,i,s),Yb(n.z,i,s))})).setLayout({name:"mx_gradient_vec3_0",type:"vec3",inputs:[{name:"hash",type:"uvec3"},{name:"x",type:"float"},{name:"y",type:"float"}]}),Zb=Ai((([e,t,r,s])=>{const i=Bi(s).toVar(),n=Bi(r).toVar(),o=Bi(t).toVar(),a=ki(e).toVar();return Oi(Yb(a.x,o,n,i),Yb(a.y,o,n,i),Yb(a.z,o,n,i))})).setLayout({name:"mx_gradient_vec3_1",type:"vec3",inputs:[{name:"hash",type:"uvec3"},{name:"x",type:"float"},{name:"y",type:"float"},{name:"z",type:"float"}]}),Jb=Um([Qb,Zb]),ex=Ai((([e])=>{const t=Bi(e).toVar();return Wn(.6616,t)})).setLayout({name:"mx_gradient_scale2d_0",type:"float",inputs:[{name:"v",type:"float"}]}),tx=Ai((([e])=>{const t=Bi(e).toVar();return Wn(.982,t)})).setLayout({name:"mx_gradient_scale3d_0",type:"float",inputs:[{name:"v",type:"float"}]}),rx=Um([ex,Ai((([e])=>{const t=Oi(e).toVar();return Wn(.6616,t)})).setLayout({name:"mx_gradient_scale2d_1",type:"vec3",inputs:[{name:"v",type:"vec3"}]})]),sx=Um([tx,Ai((([e])=>{const t=Oi(e).toVar();return Wn(.982,t)})).setLayout({name:"mx_gradient_scale3d_1",type:"vec3",inputs:[{name:"v",type:"vec3"}]})]),ix=Ai((([e,t])=>{const r=Fi(t).toVar(),s=Ui(e).toVar();return s.shiftLeft(r).bitOr(s.shiftRight(Fi(32).sub(r)))})).setLayout({name:"mx_rotl32",type:"uint",inputs:[{name:"x",type:"uint"},{name:"k",type:"int"}]}),nx=Ai((([e,t,r])=>{e.subAssign(r),e.bitXorAssign(ix(r,Fi(4))),r.addAssign(t),t.subAssign(e),t.bitXorAssign(ix(e,Fi(6))),e.addAssign(r),r.subAssign(t),r.bitXorAssign(ix(t,Fi(8))),t.addAssign(e),e.subAssign(r),e.bitXorAssign(ix(r,Fi(16))),r.addAssign(t),t.subAssign(e),t.bitXorAssign(ix(e,Fi(19))),e.addAssign(r),r.subAssign(t),r.bitXorAssign(ix(t,Fi(4))),t.addAssign(e)})),ox=Ai((([e,t,r])=>{const s=Ui(r).toVar(),i=Ui(t).toVar(),n=Ui(e).toVar();return s.bitXorAssign(i),s.subAssign(ix(i,Fi(14))),n.bitXorAssign(s),n.subAssign(ix(s,Fi(11))),i.bitXorAssign(n),i.subAssign(ix(n,Fi(25))),s.bitXorAssign(i),s.subAssign(ix(i,Fi(16))),n.bitXorAssign(s),n.subAssign(ix(s,Fi(4))),i.bitXorAssign(n),i.subAssign(ix(n,Fi(14))),s.bitXorAssign(i),s.subAssign(ix(i,Fi(24))),s})).setLayout({name:"mx_bjfinal",type:"uint",inputs:[{name:"a",type:"uint"},{name:"b",type:"uint"},{name:"c",type:"uint"}]}),ax=Ai((([e])=>{const t=Ui(e).toVar();return Bi(t).div(Bi(Ui(Fi(4294967295))))})).setLayout({name:"mx_bits_to_01",type:"float",inputs:[{name:"bits",type:"uint"}]}),ux=Ai((([e])=>{const t=Bi(e).toVar();return t.mul(t).mul(t).mul(t.mul(t.mul(6).sub(15)).add(10))})).setLayout({name:"mx_fade",type:"float",inputs:[{name:"t",type:"float"}]}),lx=Um([Ai((([e])=>{const t=Fi(e).toVar(),r=Ui(Ui(1)).toVar(),s=Ui(Ui(Fi(3735928559)).add(r.shiftLeft(Ui(2))).add(Ui(13))).toVar();return ox(s.add(Ui(t)),s,s)})).setLayout({name:"mx_hash_int_0",type:"uint",inputs:[{name:"x",type:"int"}]}),Ai((([e,t])=>{const r=Fi(t).toVar(),s=Fi(e).toVar(),i=Ui(Ui(2)).toVar(),n=Ui().toVar(),o=Ui().toVar(),a=Ui().toVar();return n.assign(o.assign(a.assign(Ui(Fi(3735928559)).add(i.shiftLeft(Ui(2))).add(Ui(13))))),n.addAssign(Ui(s)),o.addAssign(Ui(r)),ox(n,o,a)})).setLayout({name:"mx_hash_int_1",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"}]}),Ai((([e,t,r])=>{const s=Fi(r).toVar(),i=Fi(t).toVar(),n=Fi(e).toVar(),o=Ui(Ui(3)).toVar(),a=Ui().toVar(),u=Ui().toVar(),l=Ui().toVar();return a.assign(u.assign(l.assign(Ui(Fi(3735928559)).add(o.shiftLeft(Ui(2))).add(Ui(13))))),a.addAssign(Ui(n)),u.addAssign(Ui(i)),l.addAssign(Ui(s)),ox(a,u,l)})).setLayout({name:"mx_hash_int_2",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"}]}),Ai((([e,t,r,s])=>{const i=Fi(s).toVar(),n=Fi(r).toVar(),o=Fi(t).toVar(),a=Fi(e).toVar(),u=Ui(Ui(4)).toVar(),l=Ui().toVar(),d=Ui().toVar(),c=Ui().toVar();return l.assign(d.assign(c.assign(Ui(Fi(3735928559)).add(u.shiftLeft(Ui(2))).add(Ui(13))))),l.addAssign(Ui(a)),d.addAssign(Ui(o)),c.addAssign(Ui(n)),nx(l,d,c),l.addAssign(Ui(i)),ox(l,d,c)})).setLayout({name:"mx_hash_int_3",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"},{name:"xx",type:"int"}]}),Ai((([e,t,r,s,i])=>{const n=Fi(i).toVar(),o=Fi(s).toVar(),a=Fi(r).toVar(),u=Fi(t).toVar(),l=Fi(e).toVar(),d=Ui(Ui(5)).toVar(),c=Ui().toVar(),h=Ui().toVar(),p=Ui().toVar();return c.assign(h.assign(p.assign(Ui(Fi(3735928559)).add(d.shiftLeft(Ui(2))).add(Ui(13))))),c.addAssign(Ui(l)),h.addAssign(Ui(u)),p.addAssign(Ui(a)),nx(c,h,p),c.addAssign(Ui(o)),h.addAssign(Ui(n)),ox(c,h,p)})).setLayout({name:"mx_hash_int_4",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"},{name:"xx",type:"int"},{name:"yy",type:"int"}]})]),dx=Um([Ai((([e,t])=>{const r=Fi(t).toVar(),s=Fi(e).toVar(),i=Ui(lx(s,r)).toVar(),n=ki().toVar();return n.x.assign(i.bitAnd(Fi(255))),n.y.assign(i.shiftRight(Fi(8)).bitAnd(Fi(255))),n.z.assign(i.shiftRight(Fi(16)).bitAnd(Fi(255))),n})).setLayout({name:"mx_hash_vec3_0",type:"uvec3",inputs:[{name:"x",type:"int"},{name:"y",type:"int"}]}),Ai((([e,t,r])=>{const s=Fi(r).toVar(),i=Fi(t).toVar(),n=Fi(e).toVar(),o=Ui(lx(n,i,s)).toVar(),a=ki().toVar();return a.x.assign(o.bitAnd(Fi(255))),a.y.assign(o.shiftRight(Fi(8)).bitAnd(Fi(255))),a.z.assign(o.shiftRight(Fi(16)).bitAnd(Fi(255))),a})).setLayout({name:"mx_hash_vec3_1",type:"uvec3",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"}]})]),cx=Um([Ai((([e])=>{const t=Ii(e).toVar(),r=Fi().toVar(),s=Fi().toVar(),i=Bi(Wb(t.x,r)).toVar(),n=Bi(Wb(t.y,s)).toVar(),o=Bi(ux(i)).toVar(),a=Bi(ux(n)).toVar(),u=Bi(jb(Yb(lx(r,s),i,n),Yb(lx(r.add(Fi(1)),s),i.sub(1),n),Yb(lx(r,s.add(Fi(1))),i,n.sub(1)),Yb(lx(r.add(Fi(1)),s.add(Fi(1))),i.sub(1),n.sub(1)),o,a)).toVar();return rx(u)})).setLayout({name:"mx_perlin_noise_float_0",type:"float",inputs:[{name:"p",type:"vec2"}]}),Ai((([e])=>{const t=Oi(e).toVar(),r=Fi().toVar(),s=Fi().toVar(),i=Fi().toVar(),n=Bi(Wb(t.x,r)).toVar(),o=Bi(Wb(t.y,s)).toVar(),a=Bi(Wb(t.z,i)).toVar(),u=Bi(ux(n)).toVar(),l=Bi(ux(o)).toVar(),d=Bi(ux(a)).toVar(),c=Bi(qb(Yb(lx(r,s,i),n,o,a),Yb(lx(r.add(Fi(1)),s,i),n.sub(1),o,a),Yb(lx(r,s.add(Fi(1)),i),n,o.sub(1),a),Yb(lx(r.add(Fi(1)),s.add(Fi(1)),i),n.sub(1),o.sub(1),a),Yb(lx(r,s,i.add(Fi(1))),n,o,a.sub(1)),Yb(lx(r.add(Fi(1)),s,i.add(Fi(1))),n.sub(1),o,a.sub(1)),Yb(lx(r,s.add(Fi(1)),i.add(Fi(1))),n,o.sub(1),a.sub(1)),Yb(lx(r.add(Fi(1)),s.add(Fi(1)),i.add(Fi(1))),n.sub(1),o.sub(1),a.sub(1)),u,l,d)).toVar();return sx(c)})).setLayout({name:"mx_perlin_noise_float_1",type:"float",inputs:[{name:"p",type:"vec3"}]})]),hx=Um([Ai((([e])=>{const t=Ii(e).toVar(),r=Fi().toVar(),s=Fi().toVar(),i=Bi(Wb(t.x,r)).toVar(),n=Bi(Wb(t.y,s)).toVar(),o=Bi(ux(i)).toVar(),a=Bi(ux(n)).toVar(),u=Oi(jb(Jb(dx(r,s),i,n),Jb(dx(r.add(Fi(1)),s),i.sub(1),n),Jb(dx(r,s.add(Fi(1))),i,n.sub(1)),Jb(dx(r.add(Fi(1)),s.add(Fi(1))),i.sub(1),n.sub(1)),o,a)).toVar();return rx(u)})).setLayout({name:"mx_perlin_noise_vec3_0",type:"vec3",inputs:[{name:"p",type:"vec2"}]}),Ai((([e])=>{const t=Oi(e).toVar(),r=Fi().toVar(),s=Fi().toVar(),i=Fi().toVar(),n=Bi(Wb(t.x,r)).toVar(),o=Bi(Wb(t.y,s)).toVar(),a=Bi(Wb(t.z,i)).toVar(),u=Bi(ux(n)).toVar(),l=Bi(ux(o)).toVar(),d=Bi(ux(a)).toVar(),c=Oi(qb(Jb(dx(r,s,i),n,o,a),Jb(dx(r.add(Fi(1)),s,i),n.sub(1),o,a),Jb(dx(r,s.add(Fi(1)),i),n,o.sub(1),a),Jb(dx(r.add(Fi(1)),s.add(Fi(1)),i),n.sub(1),o.sub(1),a),Jb(dx(r,s,i.add(Fi(1))),n,o,a.sub(1)),Jb(dx(r.add(Fi(1)),s,i.add(Fi(1))),n.sub(1),o,a.sub(1)),Jb(dx(r,s.add(Fi(1)),i.add(Fi(1))),n,o.sub(1),a.sub(1)),Jb(dx(r.add(Fi(1)),s.add(Fi(1)),i.add(Fi(1))),n.sub(1),o.sub(1),a.sub(1)),u,l,d)).toVar();return sx(c)})).setLayout({name:"mx_perlin_noise_vec3_1",type:"vec3",inputs:[{name:"p",type:"vec3"}]})]),px=Um([Ai((([e])=>{const t=Bi(e).toVar(),r=Fi(Hb(t)).toVar();return ax(lx(r))})).setLayout({name:"mx_cell_noise_float_0",type:"float",inputs:[{name:"p",type:"float"}]}),Ai((([e])=>{const t=Ii(e).toVar(),r=Fi(Hb(t.x)).toVar(),s=Fi(Hb(t.y)).toVar();return ax(lx(r,s))})).setLayout({name:"mx_cell_noise_float_1",type:"float",inputs:[{name:"p",type:"vec2"}]}),Ai((([e])=>{const t=Oi(e).toVar(),r=Fi(Hb(t.x)).toVar(),s=Fi(Hb(t.y)).toVar(),i=Fi(Hb(t.z)).toVar();return ax(lx(r,s,i))})).setLayout({name:"mx_cell_noise_float_2",type:"float",inputs:[{name:"p",type:"vec3"}]}),Ai((([e])=>{const t=$i(e).toVar(),r=Fi(Hb(t.x)).toVar(),s=Fi(Hb(t.y)).toVar(),i=Fi(Hb(t.z)).toVar(),n=Fi(Hb(t.w)).toVar();return ax(lx(r,s,i,n))})).setLayout({name:"mx_cell_noise_float_3",type:"float",inputs:[{name:"p",type:"vec4"}]})]),gx=Um([Ai((([e])=>{const t=Bi(e).toVar(),r=Fi(Hb(t)).toVar();return Oi(ax(lx(r,Fi(0))),ax(lx(r,Fi(1))),ax(lx(r,Fi(2))))})).setLayout({name:"mx_cell_noise_vec3_0",type:"vec3",inputs:[{name:"p",type:"float"}]}),Ai((([e])=>{const t=Ii(e).toVar(),r=Fi(Hb(t.x)).toVar(),s=Fi(Hb(t.y)).toVar();return Oi(ax(lx(r,s,Fi(0))),ax(lx(r,s,Fi(1))),ax(lx(r,s,Fi(2))))})).setLayout({name:"mx_cell_noise_vec3_1",type:"vec3",inputs:[{name:"p",type:"vec2"}]}),Ai((([e])=>{const t=Oi(e).toVar(),r=Fi(Hb(t.x)).toVar(),s=Fi(Hb(t.y)).toVar(),i=Fi(Hb(t.z)).toVar();return Oi(ax(lx(r,s,i,Fi(0))),ax(lx(r,s,i,Fi(1))),ax(lx(r,s,i,Fi(2))))})).setLayout({name:"mx_cell_noise_vec3_2",type:"vec3",inputs:[{name:"p",type:"vec3"}]}),Ai((([e])=>{const t=$i(e).toVar(),r=Fi(Hb(t.x)).toVar(),s=Fi(Hb(t.y)).toVar(),i=Fi(Hb(t.z)).toVar(),n=Fi(Hb(t.w)).toVar();return Oi(ax(lx(r,s,i,n,Fi(0))),ax(lx(r,s,i,n,Fi(1))),ax(lx(r,s,i,n,Fi(2))))})).setLayout({name:"mx_cell_noise_vec3_3",type:"vec3",inputs:[{name:"p",type:"vec4"}]})]),mx=Ai((([e,t,r,s])=>{const i=Bi(s).toVar(),n=Bi(r).toVar(),o=Fi(t).toVar(),a=Oi(e).toVar(),u=Bi(0).toVar(),l=Bi(1).toVar();return cc(o,(()=>{u.addAssign(l.mul(cx(a))),l.mulAssign(i),a.mulAssign(n)})),u})).setLayout({name:"mx_fractal_noise_float",type:"float",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),fx=Ai((([e,t,r,s])=>{const i=Bi(s).toVar(),n=Bi(r).toVar(),o=Fi(t).toVar(),a=Oi(e).toVar(),u=Oi(0).toVar(),l=Bi(1).toVar();return cc(o,(()=>{u.addAssign(l.mul(hx(a))),l.mulAssign(i),a.mulAssign(n)})),u})).setLayout({name:"mx_fractal_noise_vec3",type:"vec3",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),yx=Ai((([e,t,r,s])=>{const i=Bi(s).toVar(),n=Bi(r).toVar(),o=Fi(t).toVar(),a=Oi(e).toVar();return Ii(mx(a,o,n,i),mx(a.add(Oi(Fi(19),Fi(193),Fi(17))),o,n,i))})).setLayout({name:"mx_fractal_noise_vec2",type:"vec2",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),bx=Ai((([e,t,r,s])=>{const i=Bi(s).toVar(),n=Bi(r).toVar(),o=Fi(t).toVar(),a=Oi(e).toVar(),u=Oi(fx(a,o,n,i)).toVar(),l=Bi(mx(a.add(Oi(Fi(19),Fi(193),Fi(17))),o,n,i)).toVar();return $i(u,l)})).setLayout({name:"mx_fractal_noise_vec4",type:"vec4",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),xx=Um([Ai((([e,t,r,s,i,n,o])=>{const a=Fi(o).toVar(),u=Bi(n).toVar(),l=Fi(i).toVar(),d=Fi(s).toVar(),c=Fi(r).toVar(),h=Fi(t).toVar(),p=Ii(e).toVar(),g=Oi(gx(Ii(h.add(d),c.add(l)))).toVar(),m=Ii(g.x,g.y).toVar();m.subAssign(.5),m.mulAssign(u),m.addAssign(.5);const f=Ii(Ii(Bi(h),Bi(c)).add(m)).toVar(),y=Ii(f.sub(p)).toVar();return Ei(a.equal(Fi(2)),(()=>Lo(y.x).add(Lo(y.y)))),Ei(a.equal(Fi(3)),(()=>Zo(Lo(y.x),Lo(y.y)))),ia(y,y)})).setLayout({name:"mx_worley_distance_0",type:"float",inputs:[{name:"p",type:"vec2"},{name:"x",type:"int"},{name:"y",type:"int"},{name:"xoff",type:"int"},{name:"yoff",type:"int"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),Ai((([e,t,r,s,i,n,o,a,u])=>{const l=Fi(u).toVar(),d=Bi(a).toVar(),c=Fi(o).toVar(),h=Fi(n).toVar(),p=Fi(i).toVar(),g=Fi(s).toVar(),m=Fi(r).toVar(),f=Fi(t).toVar(),y=Oi(e).toVar(),b=Oi(gx(Oi(f.add(p),m.add(h),g.add(c)))).toVar();b.subAssign(.5),b.mulAssign(d),b.addAssign(.5);const x=Oi(Oi(Bi(f),Bi(m),Bi(g)).add(b)).toVar(),T=Oi(x.sub(y)).toVar();return Ei(l.equal(Fi(2)),(()=>Lo(T.x).add(Lo(T.y)).add(Lo(T.z)))),Ei(l.equal(Fi(3)),(()=>Zo(Zo(Lo(T.x),Lo(T.y)),Lo(T.z)))),ia(T,T)})).setLayout({name:"mx_worley_distance_1",type:"float",inputs:[{name:"p",type:"vec3"},{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"},{name:"xoff",type:"int"},{name:"yoff",type:"int"},{name:"zoff",type:"int"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),Tx=Ai((([e,t,r])=>{const s=Fi(r).toVar(),i=Bi(t).toVar(),n=Ii(e).toVar(),o=Fi().toVar(),a=Fi().toVar(),u=Ii(Wb(n.x,o),Wb(n.y,a)).toVar(),l=Bi(1e6).toVar();return cc({start:-1,end:Fi(1),name:"x",condition:"<="},(({x:e})=>{cc({start:-1,end:Fi(1),name:"y",condition:"<="},(({y:t})=>{const r=Bi(xx(u,e,t,o,a,i,s)).toVar();l.assign(Qo(l,r))}))})),Ei(s.equal(Fi(0)),(()=>{l.assign(Ao(l))})),l})).setLayout({name:"mx_worley_noise_float_0",type:"float",inputs:[{name:"p",type:"vec2"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),_x=Ai((([e,t,r])=>{const s=Fi(r).toVar(),i=Bi(t).toVar(),n=Ii(e).toVar(),o=Fi().toVar(),a=Fi().toVar(),u=Ii(Wb(n.x,o),Wb(n.y,a)).toVar(),l=Ii(1e6,1e6).toVar();return cc({start:-1,end:Fi(1),name:"x",condition:"<="},(({x:e})=>{cc({start:-1,end:Fi(1),name:"y",condition:"<="},(({y:t})=>{const r=Bi(xx(u,e,t,o,a,i,s)).toVar();Ei(r.lessThan(l.x),(()=>{l.y.assign(l.x),l.x.assign(r)})).ElseIf(r.lessThan(l.y),(()=>{l.y.assign(r)}))}))})),Ei(s.equal(Fi(0)),(()=>{l.assign(Ao(l))})),l})).setLayout({name:"mx_worley_noise_vec2_0",type:"vec2",inputs:[{name:"p",type:"vec2"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),vx=Ai((([e,t,r])=>{const s=Fi(r).toVar(),i=Bi(t).toVar(),n=Ii(e).toVar(),o=Fi().toVar(),a=Fi().toVar(),u=Ii(Wb(n.x,o),Wb(n.y,a)).toVar(),l=Oi(1e6,1e6,1e6).toVar();return cc({start:-1,end:Fi(1),name:"x",condition:"<="},(({x:e})=>{cc({start:-1,end:Fi(1),name:"y",condition:"<="},(({y:t})=>{const r=Bi(xx(u,e,t,o,a,i,s)).toVar();Ei(r.lessThan(l.x),(()=>{l.z.assign(l.y),l.y.assign(l.x),l.x.assign(r)})).ElseIf(r.lessThan(l.y),(()=>{l.z.assign(l.y),l.y.assign(r)})).ElseIf(r.lessThan(l.z),(()=>{l.z.assign(r)}))}))})),Ei(s.equal(Fi(0)),(()=>{l.assign(Ao(l))})),l})).setLayout({name:"mx_worley_noise_vec3_0",type:"vec3",inputs:[{name:"p",type:"vec2"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),Nx=Um([Tx,Ai((([e,t,r])=>{const s=Fi(r).toVar(),i=Bi(t).toVar(),n=Oi(e).toVar(),o=Fi().toVar(),a=Fi().toVar(),u=Fi().toVar(),l=Oi(Wb(n.x,o),Wb(n.y,a),Wb(n.z,u)).toVar(),d=Bi(1e6).toVar();return cc({start:-1,end:Fi(1),name:"x",condition:"<="},(({x:e})=>{cc({start:-1,end:Fi(1),name:"y",condition:"<="},(({y:t})=>{cc({start:-1,end:Fi(1),name:"z",condition:"<="},(({z:r})=>{const n=Bi(xx(l,e,t,r,o,a,u,i,s)).toVar();d.assign(Qo(d,n))}))}))})),Ei(s.equal(Fi(0)),(()=>{d.assign(Ao(d))})),d})).setLayout({name:"mx_worley_noise_float_1",type:"float",inputs:[{name:"p",type:"vec3"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),Sx=Um([_x,Ai((([e,t,r])=>{const s=Fi(r).toVar(),i=Bi(t).toVar(),n=Oi(e).toVar(),o=Fi().toVar(),a=Fi().toVar(),u=Fi().toVar(),l=Oi(Wb(n.x,o),Wb(n.y,a),Wb(n.z,u)).toVar(),d=Ii(1e6,1e6).toVar();return cc({start:-1,end:Fi(1),name:"x",condition:"<="},(({x:e})=>{cc({start:-1,end:Fi(1),name:"y",condition:"<="},(({y:t})=>{cc({start:-1,end:Fi(1),name:"z",condition:"<="},(({z:r})=>{const n=Bi(xx(l,e,t,r,o,a,u,i,s)).toVar();Ei(n.lessThan(d.x),(()=>{d.y.assign(d.x),d.x.assign(n)})).ElseIf(n.lessThan(d.y),(()=>{d.y.assign(n)}))}))}))})),Ei(s.equal(Fi(0)),(()=>{d.assign(Ao(d))})),d})).setLayout({name:"mx_worley_noise_vec2_1",type:"vec2",inputs:[{name:"p",type:"vec3"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),Ax=Um([vx,Ai((([e,t,r])=>{const s=Fi(r).toVar(),i=Bi(t).toVar(),n=Oi(e).toVar(),o=Fi().toVar(),a=Fi().toVar(),u=Fi().toVar(),l=Oi(Wb(n.x,o),Wb(n.y,a),Wb(n.z,u)).toVar(),d=Oi(1e6,1e6,1e6).toVar();return cc({start:-1,end:Fi(1),name:"x",condition:"<="},(({x:e})=>{cc({start:-1,end:Fi(1),name:"y",condition:"<="},(({y:t})=>{cc({start:-1,end:Fi(1),name:"z",condition:"<="},(({z:r})=>{const n=Bi(xx(l,e,t,r,o,a,u,i,s)).toVar();Ei(n.lessThan(d.x),(()=>{d.z.assign(d.y),d.y.assign(d.x),d.x.assign(n)})).ElseIf(n.lessThan(d.y),(()=>{d.z.assign(d.y),d.y.assign(n)})).ElseIf(n.lessThan(d.z),(()=>{d.z.assign(n)}))}))}))})),Ei(s.equal(Fi(0)),(()=>{d.assign(Ao(d))})),d})).setLayout({name:"mx_worley_noise_vec3_1",type:"vec3",inputs:[{name:"p",type:"vec3"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),Rx=Ai((([e])=>{const t=e.y,r=e.z,s=Oi().toVar();return Ei(t.lessThan(1e-4),(()=>{s.assign(Oi(r,r,r))})).Else((()=>{let i=e.x;i=i.sub(Co(i)).mul(6).toVar();const n=Fi(jo(i)),o=i.sub(Bi(n)),a=r.mul(t.oneMinus()),u=r.mul(t.mul(o).oneMinus()),l=r.mul(t.mul(o.oneMinus()).oneMinus());Ei(n.equal(Fi(0)),(()=>{s.assign(Oi(r,l,a))})).ElseIf(n.equal(Fi(1)),(()=>{s.assign(Oi(u,r,a))})).ElseIf(n.equal(Fi(2)),(()=>{s.assign(Oi(a,r,l))})).ElseIf(n.equal(Fi(3)),(()=>{s.assign(Oi(a,u,r))})).ElseIf(n.equal(Fi(4)),(()=>{s.assign(Oi(l,a,r))})).Else((()=>{s.assign(Oi(r,a,u))}))})),s})).setLayout({name:"mx_hsvtorgb",type:"vec3",inputs:[{name:"hsv",type:"vec3"}]}),Cx=Ai((([e])=>{const t=Oi(e).toVar(),r=Bi(t.x).toVar(),s=Bi(t.y).toVar(),i=Bi(t.z).toVar(),n=Bi(Qo(r,Qo(s,i))).toVar(),o=Bi(Zo(r,Zo(s,i))).toVar(),a=Bi(o.sub(n)).toVar(),u=Bi().toVar(),l=Bi().toVar(),d=Bi().toVar();return d.assign(o),Ei(o.greaterThan(0),(()=>{l.assign(a.div(o))})).Else((()=>{l.assign(0)})),Ei(l.lessThanEqual(0),(()=>{u.assign(0)})).Else((()=>{Ei(r.greaterThanEqual(o),(()=>{u.assign(s.sub(i).div(a))})).ElseIf(s.greaterThanEqual(o),(()=>{u.assign($n(2,i.sub(r).div(a)))})).Else((()=>{u.assign($n(4,r.sub(s).div(a)))})),u.mulAssign(1/6),Ei(u.lessThan(0),(()=>{u.addAssign(1)}))})),Oi(u,l,d)})).setLayout({name:"mx_rgbtohsv",type:"vec3",inputs:[{name:"c",type:"vec3"}]}),Ex=Ai((([e])=>{const t=Oi(e).toVar(),r=zi(Qn(t,Oi(.04045))).toVar(),s=Oi(t.div(12.92)).toVar(),i=Oi(oa(Zo(t.add(Oi(.055)),Oi(0)).div(1.055),Oi(2.4))).toVar();return pa(s,i,r)})).setLayout({name:"mx_srgb_texture_to_lin_rec709",type:"vec3",inputs:[{name:"color",type:"vec3"}]}),wx=(e,t)=>{e=Bi(e),t=Bi(t);const r=Ii(t.dFdx(),t.dFdy()).length().mul(.7071067811865476);return ya(e.sub(r),e.add(r),t)},Mx=(e,t,r,s)=>pa(e,t,r[s].clamp()),Bx=(e,t,r,s,i)=>pa(e,t,wx(r,s[i])),Fx=Ai((([e,t,r])=>{const s=wo(e).toVar("nDir"),i=Hn(Bi(.5).mul(t.sub(r)),sl).div(s).toVar("rbmax"),n=Hn(Bi(-.5).mul(t.sub(r)),sl).div(s).toVar("rbmin"),o=Oi().toVar("rbminmax");o.x=s.x.greaterThan(Bi(0)).select(i.x,n.x),o.y=s.y.greaterThan(Bi(0)).select(i.y,n.y),o.z=s.z.greaterThan(Bi(0)).select(i.z,n.z);const a=Qo(Qo(o.x,o.y),o.z).toVar("correction");return sl.add(s.mul(a)).toVar("boxIntersection").sub(r)})),Ux=Ai((([e,t])=>{const r=e.x,s=e.y,i=e.z;let n=t.element(0).mul(.886227);return n=n.add(t.element(1).mul(1.023328).mul(s)),n=n.add(t.element(2).mul(1.023328).mul(i)),n=n.add(t.element(3).mul(1.023328).mul(r)),n=n.add(t.element(4).mul(.858086).mul(r).mul(s)),n=n.add(t.element(5).mul(.858086).mul(s).mul(i)),n=n.add(t.element(6).mul(i.mul(i).mul(.743125).sub(.247708))),n=n.add(t.element(7).mul(.858086).mul(r).mul(i)),n=n.add(t.element(8).mul(.429043).mul(Wn(r,r).sub(Wn(s,s)))),n}));var Px=Object.freeze({__proto__:null,BRDF_GGX:Kh,BRDF_Lambert:Uh,BasicShadowFilter:yb,Break:hc,Continue:()=>gu("continue").append(),DFGApprox:Xh,D_GGX:Wh,Discard:mu,EPSILON:po,F_Schlick:Fh,Fn:Ai,INFINITY:go,If:Ei,Loop:cc,NodeAccess:Es,NodeShaderStage:As,NodeType:Cs,NodeUpdateType:Rs,PCFShadowFilter:bb,PCFSoftShadowFilter:xb,PI:mo,PI2:fo,Return:()=>gu("return").append(),Schlick_to_F0:Qh,ScriptableNodeResources:Ny,ShaderNode:xi,TBNViewMatrix:Ql,VSMShadowFilter:Tb,V_GGX_SmithCorrelated:$h,abs:Lo,acesFilmicToneMapping:ly,acos:Io,add:$n,addMethodChaining:qs,addNodeElement:function(e){console.warn("THREE.TSLBase: AddNodeElement has been removed in favor of tree-shaking. Trying add",e)},agxToneMapping:py,all:yo,alphaT:_n,and:eo,anisotropy:vn,anisotropyB:Sn,anisotropyT:Nn,any:bo,append:wi,arrayBuffer:e=>Ti(new Hs(e,"ArrayBuffer")),asin:Po,assign:On,atan:Do,atan2:va,atomicAdd:(e,t,r=null)=>Wy($y.ATOMIC_ADD,e,t,r),atomicAnd:(e,t,r=null)=>Wy($y.ATOMIC_AND,e,t,r),atomicFunc:Wy,atomicMax:(e,t,r=null)=>Wy($y.ATOMIC_MAX,e,t,r),atomicMin:(e,t,r=null)=>Wy($y.ATOMIC_MIN,e,t,r),atomicOr:(e,t,r=null)=>Wy($y.ATOMIC_OR,e,t,r),atomicStore:(e,t,r=null)=>Wy($y.ATOMIC_STORE,e,t,r),atomicSub:(e,t,r=null)=>Wy($y.ATOMIC_SUB,e,t,r),atomicXor:(e,t,r=null)=>Wy($y.ATOMIC_XOR,e,t,r),attenuationColor:Dn,attenuationDistance:In,attribute:xu,attributeArray:(e,t="float")=>{const r=bs(t),s=ys(t),i=new xf(e,r,s);return Nf(i,t,e)},backgroundBlurriness:Mf,backgroundIntensity:Bf,backgroundRotation:Ff,batch:oc,billboarding:Om,bitAnd:io,bitNot:no,bitOr:oo,bitXor:ao,bitangentGeometry:Wl,bitangentLocal:jl,bitangentView:ql,bitangentWorld:Kl,bitcast:Xo,blendBurn:kf,blendColor:Wf,blendDodge:zf,blendOverlay:Hf,blendScreen:$f,blur:Xp,bool:Pi,buffer:El,bufferAttribute:eu,bumpMap:od,burn:(...e)=>(console.warn('THREE.TSL: "burn" has been renamed. Use "blendBurn" instead.'),kf(e)),bvec2:Vi,bvec3:zi,bvec4:ji,bypass:lu,cache:au,call:kn,cameraFar:wu,cameraNear:Eu,cameraNormalMatrix:Pu,cameraPosition:Iu,cameraProjectionMatrix:Mu,cameraProjectionMatrixInverse:Bu,cameraViewMatrix:Fu,cameraWorldMatrix:Uu,cbrt:ca,cdl:Qf,ceil:Eo,checker:kb,cineonToneMapping:ay,clamp:ga,clearcoat:gn,clearcoatRoughness:mn,code:fy,color:Mi,colorSpaceToWorking:Wa,colorToDirection:e=>Ti(e).mul(2).sub(1),compute:nu,cond:Ca,context:wa,convert:Qi,convertColorSpace:(e,t,r)=>Ti(new ka(Ti(e),t,r)),convertToTexture:(e,...t)=>e.isTextureNode?e:e.isPassNode?e.getTextureNode():gf(e,...t),cos:Fo,cross:na,cubeTexture:Rl,dFdx:zo,dFdy:$o,dashSize:wn,defaultBuildStages:Ms,defaultShaderStages:ws,defined:yi,degrees:To,deltaTime:Im,densityFog:function(e,t){return console.warn('THREE.TSL: "densityFog( color, density )" is deprecated. Use "fog( color, densityFogFactor( density ) )" instead.'),wy(e,Ey(t))},densityFogFactor:Ey,depth:Xc,depthPass:(e,t,r)=>Ti(new sy(sy.DEPTH,e,t,r)),difference:sa,diffuseColor:dn,directPointLight:Ob,directionToColor:mh,dispersion:Ln,distance:ra,div:jn,dodge:(...e)=>(console.warn('THREE.TSL: "dodge" has been renamed. Use "blendDodge" instead.'),zf(e)),dot:ia,drawIndex:ec,dynamicBufferAttribute:tu,element:Yi,emissive:cn,equal:Kn,equals:Yo,equirectUV:xh,exp:_o,exp2:vo,expression:gu,faceDirection:ll,faceForward:ba,faceforward:Na,float:Bi,floor:Co,fog:wy,fract:Mo,frameGroup:tn,frameId:Dm,frontFacing:ul,fwidth:qo,gain:(e,t)=>e.lessThan(.5)?Cm(e.mul(2),t).div(2):Hn(1,Cm(Wn(Hn(1,e),2),t).div(2)),gapSize:Mn,getConstNodeType:bi,getCurrentStack:Ci,getDirection:Wp,getDistanceAttenuation:wb,getGeometryRoughness:kh,getNormalFromDepth:yf,getParallaxCorrectNormal:Fx,getRoughness:zh,getScreenPosition:ff,getShIrradianceAt:Ux,getTextureIndex:Nm,getViewPosition:mf,glsl:(e,t)=>fy(e,t,"glsl"),glslFn:(e,t)=>by(e,t,"glsl"),grayscale:jf,greaterThan:Qn,greaterThanEqual:Jn,hash:Rm,highpModelNormalViewMatrix:Ju,highpModelViewMatrix:Zu,hue:Xf,instance:rc,instanceIndex:Yd,instancedArray:(e,t="float")=>{const r=bs(t),s=ys(t),i=new bf(e,r,s);return Nf(i,t,e)},instancedBufferAttribute:ru,instancedDynamicBufferAttribute:su,instancedMesh:ic,int:Fi,inverseSqrt:Ro,inversesqrt:Sa,invocationLocalIndex:Jd,invocationSubgroupIndex:Zd,ior:Fn,iridescence:bn,iridescenceIOR:xn,iridescenceThickness:Tn,ivec2:Di,ivec3:Gi,ivec4:Hi,js:(e,t)=>fy(e,t,"js"),label:Ma,length:Oo,lengthSq:ha,lessThan:Yn,lessThanEqual:Zn,lightPosition:Yy,lightProjectionUV:Xy,lightShadowMatrix:Ky,lightTargetDirection:Jy,lightTargetPosition:Qy,lightViewPosition:Zy,lightingContext:_c,lights:(e=[])=>Ti(new rb).setLights(e),linearDepth:Yc,linearToneMapping:ny,localId:Vy,log:No,log2:So,logarithmicDepthToViewZ:(e,t,r)=>{const s=e.mul(No(r.div(t)));return Bi(Math.E).pow(s).mul(t).negate()},loop:(...e)=>(console.warn("TSL.LoopNode: loop() has been renamed to Loop()."),cc(...e)),luminance:Yf,mat2:qi,mat3:Ki,mat4:Xi,matcapUV:fg,materialAO:Wd,materialAlphaTest:ld,materialAnisotropy:Ed,materialAnisotropyVector:jd,materialAttenuationColor:Dd,materialAttenuationDistance:Id,materialClearcoat:vd,materialClearcoatNormal:Sd,materialClearcoatRoughness:Nd,materialColor:dd,materialDispersion:$d,materialEmissive:hd,materialIOR:Pd,materialIridescence:wd,materialIridescenceIOR:Md,materialIridescenceThickness:Bd,materialLightMap:Hd,materialLineDashOffset:kd,materialLineDashSize:Vd,materialLineGapSize:Od,materialLineScale:Ld,materialLineWidth:Gd,materialMetalness:Td,materialNormal:_d,materialOpacity:pd,materialPointWidth:zd,materialReference:Ll,materialReflectivity:bd,materialRefractionRatio:Tl,materialRotation:Ad,materialRoughness:xd,materialSheen:Rd,materialSheenRoughness:Cd,materialShininess:cd,materialSpecular:gd,materialSpecularColor:fd,materialSpecularIntensity:md,materialSpecularStrength:yd,materialThickness:Ud,materialTransmission:Fd,max:Zo,maxMipLevel:Su,mediumpModelViewMatrix:Qu,metalness:pn,min:Qo,mix:pa,mixElement:Ta,mod:Jo,modInt:qn,modelDirection:$u,modelNormalMatrix:Ku,modelPosition:Wu,modelScale:ju,modelViewMatrix:Yu,modelViewPosition:qu,modelViewProjection:qd,modelWorldMatrix:Hu,modelWorldMatrixInverse:Xu,morphReference:yc,mrt:Am,mul:Wn,mx_aastep:wx,mx_cell_noise_float:(e=Tu())=>px(e.convert("vec2|vec3")),mx_contrast:(e,t=1,r=.5)=>Bi(e).sub(r).mul(t).add(r),mx_fractal_noise_float:(e=Tu(),t=3,r=2,s=.5,i=1)=>mx(e,Fi(t),r,s).mul(i),mx_fractal_noise_vec2:(e=Tu(),t=3,r=2,s=.5,i=1)=>yx(e,Fi(t),r,s).mul(i),mx_fractal_noise_vec3:(e=Tu(),t=3,r=2,s=.5,i=1)=>fx(e,Fi(t),r,s).mul(i),mx_fractal_noise_vec4:(e=Tu(),t=3,r=2,s=.5,i=1)=>bx(e,Fi(t),r,s).mul(i),mx_hsvtorgb:Rx,mx_noise_float:(e=Tu(),t=1,r=0)=>cx(e.convert("vec2|vec3")).mul(t).add(r),mx_noise_vec3:(e=Tu(),t=1,r=0)=>hx(e.convert("vec2|vec3")).mul(t).add(r),mx_noise_vec4:(e=Tu(),t=1,r=0)=>{e=e.convert("vec2|vec3");return $i(hx(e),cx(e.add(Ii(19,73)))).mul(t).add(r)},mx_ramplr:(e,t,r=Tu())=>Mx(e,t,r,"x"),mx_ramptb:(e,t,r=Tu())=>Mx(e,t,r,"y"),mx_rgbtohsv:Cx,mx_safepower:(e,t=1)=>(e=Bi(e)).abs().pow(t).mul(e.sign()),mx_splitlr:(e,t,r,s=Tu())=>Bx(e,t,r,s,"x"),mx_splittb:(e,t,r,s=Tu())=>Bx(e,t,r,s,"y"),mx_srgb_texture_to_lin_rec709:Ex,mx_transform_uv:(e=1,t=0,r=Tu())=>r.mul(e).add(t),mx_worley_noise_float:(e=Tu(),t=1)=>Nx(e.convert("vec2|vec3"),t,Fi(1)),mx_worley_noise_vec2:(e=Tu(),t=1)=>Sx(e.convert("vec2|vec3"),t,Fi(1)),mx_worley_noise_vec3:(e=Tu(),t=1)=>Ax(e.convert("vec2|vec3"),t,Fi(1)),negate:Go,neutralToneMapping:gy,nodeArray:vi,nodeImmutable:Si,nodeObject:Ti,nodeObjects:_i,nodeProxy:Ni,normalFlat:hl,normalGeometry:dl,normalLocal:cl,normalMap:rd,normalView:pl,normalWorld:gl,normalize:wo,not:ro,notEqual:Xn,numWorkgroups:Dy,objectDirection:Lu,objectGroup:sn,objectPosition:Ou,objectScale:Gu,objectViewPosition:ku,objectWorldMatrix:Vu,oneMinus:ko,or:to,orthographicDepthToViewZ:(e,t,r)=>t.sub(r).mul(e).sub(t),oscSawtooth:(e=Pm)=>e.fract(),oscSine:(e=Pm)=>e.add(.75).mul(2*Math.PI).sin().mul(.5).add(.5),oscSquare:(e=Pm)=>e.fract().round(),oscTriangle:(e=Pm)=>e.add(.5).fract().mul(2).sub(1).abs(),output:En,outputStruct:vm,overlay:(...e)=>(console.warn('THREE.TSL: "overlay" has been renamed. Use "blendOverlay" instead.'),Hf(e)),overloadingFn:Um,parabola:Cm,parallaxDirection:Zl,parallaxUV:(e,t)=>e.sub(Zl.mul(t)),parameter:(e,t)=>Ti(new bm(e,t)),pass:(e,t,r)=>Ti(new sy(sy.COLOR,e,t,r)),passTexture:(e,t)=>Ti(new ty(e,t)),pcurve:(e,t,r)=>oa(jn(oa(e,t),$n(oa(e,t),oa(Hn(1,e),r))),1/t),perspectiveDepthToViewZ:jc,pmremTexture:eg,pointUV:Rf,pointWidth:Bn,positionGeometry:el,positionLocal:tl,positionPrevious:rl,positionView:nl,positionViewDirection:ol,positionWorld:sl,positionWorldDirection:il,posterize:Jf,pow:oa,pow2:aa,pow3:ua,pow4:la,property:un,radians:xo,rand:xa,range:Uy,rangeFog:function(e,t,r){return console.warn('THREE.TSL: "rangeFog( color, near, far )" is deprecated. Use "fog( color, rangeFogFactor( near, far ) )" instead.'),wy(e,Cy(t,r))},rangeFogFactor:Cy,reciprocal:Wo,reference:Pl,referenceBuffer:Il,reflect:ta,reflectVector:Nl,reflectView:_l,reflector:e=>Ti(new of(e)),refract:fa,refractVector:Sl,refractView:vl,reinhardToneMapping:oy,remainder:co,remap:cu,remapClamp:hu,renderGroup:rn,renderOutput:yu,rendererReference:Xa,rotate:vg,rotateUV:Lm,roughness:hn,round:Ho,rtt:gf,sRGBTransferEOTF:La,sRGBTransferOETF:Va,sampler:e=>(!0===e.isNode?e:Ru(e)).convert("sampler"),saturate:ma,saturation:qf,screen:(...e)=>(console.warn('THREE.TSL: "screen" has been renamed. Use "blendScreen" instead.'),$f(e)),screenCoordinate:Ec,screenSize:Cc,screenUV:Rc,scriptable:Ay,scriptableValue:Ty,select:Ra,setCurrentStack:Ri,shaderStages:Bs,shadow:Cb,shadowPositionWorld:ib,sharedUniformGroup:en,sheen:fn,sheenRoughness:yn,shiftLeft:uo,shiftRight:lo,shininess:Cn,sign:Vo,sin:Bo,sinc:(e,t)=>Bo(mo.mul(t.mul(e).sub(1))).div(mo.mul(t.mul(e).sub(1))),skinning:e=>Ti(new uc(e)),skinningReference:lc,smoothstep:ya,smoothstepElement:_a,specularColor:An,specularF90:Rn,spherizeUV:Vm,split:(e,t)=>Ti(new Gs(Ti(e),t)),spritesheetUV:zm,sqrt:Ao,stack:Tm,step:ea,storage:Nf,storageBarrier:()=>Gy("storage").append(),storageObject:(e,t,r)=>(console.warn('THREE.TSL: "storageObject()" is deprecated. Use "storage().setPBO( true )" instead.'),Nf(e,t,r).setPBO(!0)),storageTexture:Pf,string:(e="")=>Ti(new Hs(e,"string")),sub:Hn,subgroupIndex:Qd,subgroupSize:Oy,tan:Uo,tangentGeometry:Vl,tangentLocal:Ol,tangentView:Gl,tangentWorld:kl,temp:Ua,texture:Ru,texture3D:Mg,textureBarrier:()=>Gy("texture").append(),textureBicubic:mp,textureCubeUV:jp,textureLoad:Cu,textureSize:vu,textureStore:(e,t,r)=>{const s=Pf(e,t,r);return null!==r&&s.append(),s},thickness:Pn,time:Pm,timerDelta:(e=1)=>(console.warn('TSL: timerDelta() is deprecated. Use "deltaTime" instead.'),Im.mul(e)),timerGlobal:(e=1)=>(console.warn('TSL: timerGlobal() is deprecated. Use "time" instead.'),Pm.mul(e)),timerLocal:(e=1)=>(console.warn('TSL: timerLocal() is deprecated. Use "time" instead.'),Pm.mul(e)),toOutputColorSpace:za,toWorkingColorSpace:$a,toneMapping:Qa,toneMappingExposure:Za,toonOutlinePass:(t,r,s=new e(0,0,0),i=.003,n=1)=>Ti(new iy(t,r,Ti(s),Ti(i),Ti(n))),transformDirection:da,transformNormal:bl,transformNormalToView:xl,transformedBentNormalView:Jl,transformedBitangentView:Xl,transformedBitangentWorld:Yl,transformedClearcoatNormalView:yl,transformedNormalView:ml,transformedNormalWorld:fl,transformedTangentView:zl,transformedTangentWorld:$l,transmission:Un,transpose:Ko,triNoise3D:Mm,triplanarTexture:(...e)=>Hm(...e),triplanarTextures:Hm,trunc:jo,tslFn:(...e)=>(console.warn("TSL.ShaderNode: tslFn() has been renamed to Fn()."),Ai(...e)),uint:Ui,uniform:on,uniformArray:Bl,uniformGroup:Ji,uniforms:(e,t)=>(console.warn("TSL.UniformArrayNode: uniforms() has been renamed to uniformArray()."),Ti(new Ml(e,t))),userData:(e,t,r)=>Ti(new If(e,t,r)),uv:Tu,uvec2:Li,uvec3:ki,uvec4:Wi,varying:Ia,varyingProperty:ln,vec2:Ii,vec3:Oi,vec4:$i,vectorComponents:Fs,velocity:Gf,vertexColor:e=>Ti(new Sf(e)),vertexIndex:Xd,vertexStage:Da,vibrance:Kf,viewZToLogarithmicDepth:qc,viewZToOrthographicDepth:Hc,viewZToPerspectiveDepth:Wc,viewport:wc,viewportBottomLeft:Ic,viewportCoordinate:Bc,viewportDepthTexture:zc,viewportLinearDepth:Qc,viewportMipTexture:Oc,viewportResolution:Uc,viewportSafeUV:Gm,viewportSharedTexture:hh,viewportSize:Mc,viewportTexture:Vc,viewportTopLeft:Pc,viewportUV:Fc,wgsl:(e,t)=>fy(e,t,"wgsl"),wgslFn:(e,t)=>by(e,t,"wgsl"),workgroupArray:(e,t)=>Ti(new zy("Workgroup",e,t)),workgroupBarrier:()=>Gy("workgroup").append(),workgroupId:Ly,workingToColorSpace:Ha,xor:so});const Ix=new ym;class Dx extends Vg{constructor(e,t){super(),this.renderer=e,this.nodes=t}update(e,t,r){const s=this.renderer,i=this.nodes.getBackgroundNode(e)||e.background;let n=!1;if(null===i)s._clearColor.getRGB(Ix,Re),Ix.a=s._clearColor.a;else if(!0===i.isColor)i.getRGB(Ix,Re),Ix.a=1,n=!0;else if(!0===i.isNode){const r=this.get(e),n=i;Ix.copy(s._clearColor);let o=r.backgroundMesh;if(void 0===o){const e=wa($i(n).mul(Bf),{getUV:()=>Ff.mul(gl),getTextureLevel:()=>Mf});let t=qd;t=t.setZ(t.w);const s=new sh;s.name="Background.material",s.side=T,s.depthTest=!1,s.depthWrite=!1,s.fog=!1,s.lights=!1,s.vertexNode=t,s.colorNode=e,r.backgroundMeshNode=e,r.backgroundMesh=o=new k(new Be(1,32,32),s),o.frustumCulled=!1,o.name="Background.mesh",o.onBeforeRender=function(e,t,r){this.matrixWorld.copyPosition(r.matrixWorld)}}const a=n.getCacheKey();r.backgroundCacheKey!==a&&(r.backgroundMeshNode.node=$i(n).mul(Bf),r.backgroundMeshNode.needsUpdate=!0,o.material.needsUpdate=!0,r.backgroundCacheKey=a),t.unshift(o,o.geometry,o.material,0,0,null,null)}else console.error("THREE.Renderer: Unsupported background configuration.",i);if(!0===s.autoClear||!0===n){const e=r.clearColorValue;e.r=Ix.r,e.g=Ix.g,e.b=Ix.b,e.a=Ix.a,!0!==s.backend.isWebGLBackend&&!0!==s.alpha||(e.r*=e.a,e.g*=e.a,e.b*=e.a),r.depthClearValue=s._clearDepth,r.stencilClearValue=s._clearStencil,r.clearColor=!0===s.autoClearColor,r.clearDepth=!0===s.autoClearDepth,r.clearStencil=!0===s.autoClearStencil}else r.clearColor=!1,r.clearDepth=!1,r.clearStencil=!1}}let Lx=0;class Vx{constructor(e="",t=[],r=0,s=[]){this.name=e,this.bindings=t,this.index=r,this.bindingsReference=s,this.id=Lx++}}class Ox{constructor(e,t,r,s,i,n,o,a,u,l=[]){this.vertexShader=e,this.fragmentShader=t,this.computeShader=r,this.transforms=l,this.nodeAttributes=s,this.bindings=i,this.updateNodes=n,this.updateBeforeNodes=o,this.updateAfterNodes=a,this.monitor=u,this.usedTimes=0}createBindings(){const e=[];for(const t of this.bindings){if(!0!==t.bindings[0].groupNode.shared){const r=new Vx(t.name,[],t.index,t);e.push(r);for(const e of t.bindings)r.bindings.push(e.clone())}else e.push(t)}return e}}class Gx{constructor(e,t,r=null){this.isNodeAttribute=!0,this.name=e,this.type=t,this.node=r}}class kx{constructor(e,t,r){this.isNodeUniform=!0,this.name=e,this.type=t,this.node=r.getSelf()}get value(){return this.node.value}set value(e){this.node.value=e}get id(){return this.node.id}get groupNode(){return this.node.groupNode}}class zx{constructor(e,t){this.isNodeVar=!0,this.name=e,this.type=t}}class $x extends zx{constructor(e,t){super(e,t),this.needsInterpolation=!1,this.isNodeVarying=!0}}class Hx{constructor(e,t,r=""){this.name=e,this.type=t,this.code=r,Object.defineProperty(this,"isNodeCode",{value:!0})}}let Wx=0;class jx{constructor(e=null){this.id=Wx++,this.nodesData=new WeakMap,this.parent=e}getData(e){let t=this.nodesData.get(e);return void 0===t&&null!==this.parent&&(t=this.parent.getData(e)),t}setData(e,t){this.nodesData.set(e,t)}}class qx extends Ps{static get type(){return"StructTypeNode"}constructor(e,t){super(),this.name=e,this.types=t,this.isStructTypeNode=!0}getMemberTypes(){return this.types}}class Kx{constructor(e,t){this.name=e,this.value=t,this.boundary=0,this.itemSize=0,this.offset=0}setValue(e){this.value=e}getValue(){return this.value}}class Xx extends Kx{constructor(e,t=0){super(e,t),this.isNumberUniform=!0,this.boundary=4,this.itemSize=1}}class Yx extends Kx{constructor(e,r=new t){super(e,r),this.isVector2Uniform=!0,this.boundary=8,this.itemSize=2}}class Qx extends Kx{constructor(e,t=new r){super(e,t),this.isVector3Uniform=!0,this.boundary=16,this.itemSize=3}}class Zx extends Kx{constructor(e,t=new s){super(e,t),this.isVector4Uniform=!0,this.boundary=16,this.itemSize=4}}class Jx extends Kx{constructor(t,r=new e){super(t,r),this.isColorUniform=!0,this.boundary=16,this.itemSize=3}}class eT extends Kx{constructor(e,t=new i){super(e,t),this.isMatrix3Uniform=!0,this.boundary=48,this.itemSize=12}}class tT extends Kx{constructor(e,t=new n){super(e,t),this.isMatrix4Uniform=!0,this.boundary=64,this.itemSize=16}}class rT extends Xx{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class sT extends Yx{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class iT extends Qx{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class nT extends Zx{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class oT extends Jx{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class aT extends eT{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class uT extends tT{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}const lT=[.125,.215,.35,.446,.526,.582],dT=20,cT=new Te(-1,1,1,-1,0,1),hT=new Ue(90,1),pT=new e;let gT=null,mT=0,fT=0;const yT=(1+Math.sqrt(5))/2,bT=1/yT,xT=[new r(-yT,bT,0),new r(yT,bT,0),new r(-bT,0,yT),new r(bT,0,yT),new r(0,yT,-bT),new r(0,yT,bT),new r(-1,1,-1),new r(1,1,-1),new r(-1,1,1),new r(1,1,1)],TT=[3,1,5,0,4,2],_T=Wp(Tu(),xu("faceIndex")).normalize(),vT=Oi(_T.x,_T.y,_T.z);class NT{constructor(e){this._renderer=e,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._lodPlanes=[],this._sizeLods=[],this._sigmas=[],this._lodMeshes=[],this._blurMaterial=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._backgroundBox=null}get _hasInitialized(){return this._renderer.hasInitialized()}fromScene(e,t=0,r=.1,s=100,i=null){if(this._setSize(256),!1===this._hasInitialized){console.warn("THREE.PMREMGenerator: .fromScene() called before the backend is initialized. Try using .fromSceneAsync() instead.");const n=i||this._allocateTargets();return this.fromSceneAsync(e,t,r,s,n),n}gT=this._renderer.getRenderTarget(),mT=this._renderer.getActiveCubeFace(),fT=this._renderer.getActiveMipmapLevel();const n=i||this._allocateTargets();return n.depthBuffer=!0,this._sceneToCubeUV(e,r,s,n),t>0&&this._blur(n,0,0,t),this._applyPMREM(n),this._cleanup(n),n}async fromSceneAsync(e,t=0,r=.1,s=100,i=null){return!1===this._hasInitialized&&await this._renderer.init(),this.fromScene(e,t,r,s,i)}fromEquirectangular(e,t=null){if(!1===this._hasInitialized){console.warn("THREE.PMREMGenerator: .fromEquirectangular() called before the backend is initialized. Try using .fromEquirectangularAsync() instead."),this._setSizeFromTexture(e);const r=t||this._allocateTargets();return this.fromEquirectangularAsync(e,r),r}return this._fromTexture(e,t)}async fromEquirectangularAsync(e,t=null){return!1===this._hasInitialized&&await this._renderer.init(),this._fromTexture(e,t)}fromCubemap(e,t=null){if(!1===this._hasInitialized){console.warn("THREE.PMREMGenerator: .fromCubemap() called before the backend is initialized. Try using .fromCubemapAsync() instead."),this._setSizeFromTexture(e);const r=t||this._allocateTargets();return this.fromCubemapAsync(e,t),r}return this._fromTexture(e,t)}async fromCubemapAsync(e,t=null){return!1===this._hasInitialized&&await this._renderer.init(),this._fromTexture(e,t)}async compileCubemapShader(){null===this._cubemapMaterial&&(this._cubemapMaterial=CT(),await this._compileMaterial(this._cubemapMaterial))}async compileEquirectangularShader(){null===this._equirectMaterial&&(this._equirectMaterial=ET(),await this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),null!==this._cubemapMaterial&&this._cubemapMaterial.dispose(),null!==this._equirectMaterial&&this._equirectMaterial.dispose(),null!==this._backgroundBox&&(this._backgroundBox.geometry.dispose(),this._backgroundBox.material.dispose())}_setSizeFromTexture(e){e.mapping===_||e.mapping===v?this._setSize(0===e.image.length?16:e.image[0].width||e.image[0].image.width):this._setSize(e.image.width/4)}_setSize(e){this._lodMax=Math.floor(Math.log2(e)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){null!==this._blurMaterial&&this._blurMaterial.dispose(),null!==this._pingPongRenderTarget&&this._pingPongRenderTarget.dispose();for(let e=0;ee-4?u=lT[a-e+4-1]:0===a&&(u=0),s.push(u);const l=1/(o-2),d=-l,c=1+l,h=[d,d,c,d,c,c,d,d,c,c,d,c],p=6,g=6,m=3,f=2,y=1,b=new Float32Array(m*g*p),x=new Float32Array(f*g*p),T=new Float32Array(y*g*p);for(let e=0;e2?0:-1,s=[t,r,0,t+2/3,r,0,t+2/3,r+1,0,t,r,0,t+2/3,r+1,0,t,r+1,0],i=TT[e];b.set(s,m*g*i),x.set(h,f*g*i);const n=[i,i,i,i,i,i];T.set(n,y*g*i)}const _=new _e;_.setAttribute("position",new Ne(b,m)),_.setAttribute("uv",new Ne(x,f)),_.setAttribute("faceIndex",new Ne(T,y)),t.push(_),i.push(new k(_,null)),n>4&&n--}return{lodPlanes:t,sizeLods:r,sigmas:s,lodMeshes:i}}(i)),this._blurMaterial=function(e,t,s){const i=Bl(new Array(dT).fill(0)),n=on(new r(0,1,0)),o=on(0),a=Bi(dT),u=on(0),l=on(1),d=Ru(null),c=on(0),h=Bi(1/t),p=Bi(1/s),g=Bi(e),m={n:a,latitudinal:u,weights:i,poleAxis:n,outputDirection:vT,dTheta:o,samples:l,envMap:d,mipInt:c,CUBEUV_TEXEL_WIDTH:h,CUBEUV_TEXEL_HEIGHT:p,CUBEUV_MAX_MIP:g},f=RT("blur");return f.uniforms=m,f.fragmentNode=Xp({...m,latitudinal:u.equal(1)}),f}(i,e,t)}return i}async _compileMaterial(e){const t=new k(this._lodPlanes[0],e);await this._renderer.compile(t,cT)}_sceneToCubeUV(e,t,r,s){const i=hT;i.near=t,i.far=r;const n=[1,1,1,1,-1,1],o=[1,-1,1,-1,1,-1],a=this._renderer,u=a.autoClear;a.getClearColor(pT),a.autoClear=!1;let l=this._backgroundBox;if(null===l){const e=new Q({name:"PMREM.Background",side:T,depthWrite:!1,depthTest:!1});l=new k(new G,e)}let d=!1;const c=e.background;c?c.isColor&&(l.material.color.copy(c),e.background=null,d=!0):(l.material.color.copy(pT),d=!0),a.setRenderTarget(s),a.clear(),d&&a.render(l,i);for(let t=0;t<6;t++){const r=t%3;0===r?(i.up.set(0,n[t],0),i.lookAt(o[t],0,0)):1===r?(i.up.set(0,0,n[t]),i.lookAt(0,o[t],0)):(i.up.set(0,n[t],0),i.lookAt(0,0,o[t]));const u=this._cubeSize;AT(s,r*u,t>2?u:0,u,u),a.render(e,i)}a.autoClear=u,e.background=c}_textureToCubeUV(e,t){const r=this._renderer,s=e.mapping===_||e.mapping===v;s?null===this._cubemapMaterial&&(this._cubemapMaterial=CT(e)):null===this._equirectMaterial&&(this._equirectMaterial=ET(e));const i=s?this._cubemapMaterial:this._equirectMaterial;i.fragmentNode.value=e;const n=this._lodMeshes[0];n.material=i;const o=this._cubeSize;AT(t,0,0,3*o,2*o),r.setRenderTarget(t),r.render(n,cT)}_applyPMREM(e){const t=this._renderer,r=t.autoClear;t.autoClear=!1;const s=this._lodPlanes.length;for(let t=1;tdT&&console.warn(`sigmaRadians, ${i}, is too large and will clip, as it requested ${g} samples when the maximum is set to 20`);const m=[];let f=0;for(let e=0;ey-4?s-y+4:0),4*(this._cubeSize-b),3*b,2*b),a.setRenderTarget(t),a.render(l,cT)}}function ST(e,t,r){const s=new me(e,t,r);return s.texture.mapping=Fe,s.texture.name="PMREM.cubeUv",s.texture.isPMREMTexture=!0,s.scissorTest=!0,s}function AT(e,t,r,s,i){e.viewport.set(t,r,s,i),e.scissor.set(t,r,s,i)}function RT(e){const t=new sh;return t.depthTest=!1,t.depthWrite=!1,t.blending=L,t.name=`PMREM_${e}`,t}function CT(e){const t=RT("cubemap");return t.fragmentNode=Rl(e,vT),t}function ET(e){const t=RT("equirect");return t.fragmentNode=Ru(e,xh(vT),0),t}const wT=new WeakMap,MT=new Map([[Int8Array,"int"],[Int16Array,"int"],[Int32Array,"int"],[Uint8Array,"uint"],[Uint16Array,"uint"],[Uint32Array,"uint"],[Float32Array,"float"]]),BT=e=>/e/g.test(e)?String(e).replace(/\+/g,""):(e=Number(e))+(e%1?"":".0");class FT{constructor(e,t,r){this.object=e,this.material=e&&e.material||null,this.geometry=e&&e.geometry||null,this.renderer=t,this.parser=r,this.scene=null,this.camera=null,this.nodes=[],this.sequentialNodes=[],this.updateNodes=[],this.updateBeforeNodes=[],this.updateAfterNodes=[],this.hashNodes={},this.monitor=null,this.lightsNode=null,this.environmentNode=null,this.fogNode=null,this.clippingContext=null,this.vertexShader=null,this.fragmentShader=null,this.computeShader=null,this.flowNodes={vertex:[],fragment:[],compute:[]},this.flowCode={vertex:"",fragment:"",compute:""},this.uniforms={vertex:[],fragment:[],compute:[],index:0},this.structs={vertex:[],fragment:[],compute:[],index:0},this.bindings={vertex:{},fragment:{},compute:{}},this.bindingsIndexes={},this.bindGroups=null,this.attributes=[],this.bufferAttributes=[],this.varyings=[],this.codes={},this.vars={},this.flow={code:""},this.chaining=[],this.stack=Tm(),this.stacks=[],this.tab="\t",this.currentFunctionNode=null,this.context={material:this.material},this.cache=new jx,this.globalCache=this.cache,this.flowsData=new WeakMap,this.shaderStage=null,this.buildStage=null,this.useComparisonMethod=!1}getBindGroupsCache(){let e=wT.get(this.renderer);return void 0===e&&(e=new Ug,wT.set(this.renderer,e)),e}createRenderTarget(e,t,r){return new me(e,t,r)}createCubeRenderTarget(e,t){return new Th(e,t)}createPMREMGenerator(){return new NT(this.renderer)}includes(e){return this.nodes.includes(e)}getOutputStructName(){}_getBindGroup(e,t){const r=this.getBindGroupsCache(),s=[];let i,n=!0;for(const e of t)s.push(e),n=n&&!0!==e.groupNode.shared;return n?(i=r.get(s),void 0===i&&(i=new Vx(e,s,this.bindingsIndexes[e].group,s),r.set(s,i))):i=new Vx(e,s,this.bindingsIndexes[e].group,s),i}getBindGroupArray(e,t){const r=this.bindings[t];let s=r[e];return void 0===s&&(void 0===this.bindingsIndexes[e]&&(this.bindingsIndexes[e]={binding:0,group:Object.keys(this.bindingsIndexes).length}),r[e]=s=[]),s}getBindings(){let e=this.bindGroups;if(null===e){const t={},r=this.bindings;for(const e of Bs)for(const s in r[e]){const i=r[e][s];(t[s]||(t[s]=[])).push(...i)}e=[];for(const r in t){const s=t[r],i=this._getBindGroup(r,s);e.push(i)}this.bindGroups=e}return e}sortBindingGroups(){const e=this.getBindings();e.sort(((e,t)=>e.bindings[0].groupNode.order-t.bindings[0].groupNode.order));for(let t=0;t=0?`${Math.round(n)}u`:"0u";if("bool"===i)return n?"true":"false";if("color"===i)return`${this.getType("vec3")}( ${BT(n.r)}, ${BT(n.g)}, ${BT(n.b)} )`;const o=this.getTypeLength(i),a=this.getComponentType(i),u=e=>this.generateConst(a,e);if(2===o)return`${this.getType(i)}( ${u(n.x)}, ${u(n.y)} )`;if(3===o)return`${this.getType(i)}( ${u(n.x)}, ${u(n.y)}, ${u(n.z)} )`;if(4===o)return`${this.getType(i)}( ${u(n.x)}, ${u(n.y)}, ${u(n.z)}, ${u(n.w)} )`;if(o>4&&n&&(n.isMatrix3||n.isMatrix4))return`${this.getType(i)}( ${n.elements.map(u).join(", ")} )`;if(o>4)return`${this.getType(i)}()`;throw new Error(`NodeBuilder: Type '${i}' not found in generate constant attempt.`)}getType(e){return"color"===e?"vec3":e}hasGeometryAttribute(e){return this.geometry&&void 0!==this.geometry.getAttribute(e)}getAttribute(e,t){const r=this.attributes;for(const t of r)if(t.name===e)return t;const s=new Gx(e,t);return r.push(s),s}getPropertyName(e){return e.name}isVector(e){return/vec\d/.test(e)}isMatrix(e){return/mat\d/.test(e)}isReference(e){return"void"===e||"property"===e||"sampler"===e||"texture"===e||"cubeTexture"===e||"storageTexture"===e||"depthTexture"===e||"texture3D"===e}needsToWorkingColorSpace(){return!1}getComponentTypeFromTexture(e){const t=e.type;if(e.isDataTexture){if(t===x)return"int";if(t===b)return"uint"}return"float"}getElementType(e){return"mat2"===e?"vec2":"mat3"===e?"vec3":"mat4"===e?"vec4":this.getComponentType(e)}getComponentType(e){if("float"===(e=this.getVectorType(e))||"bool"===e||"int"===e||"uint"===e)return e;const t=/(b|i|u|)(vec|mat)([2-4])/.exec(e);return null===t?null:"b"===t[1]?"bool":"i"===t[1]?"int":"u"===t[1]?"uint":"float"}getVectorType(e){return"color"===e?"vec3":"texture"===e||"cubeTexture"===e||"storageTexture"===e||"texture3D"===e?"vec4":e}getTypeFromLength(e,t="float"){if(1===e)return t;const r=fs(e);return("float"===t?"":t[0])+r}getTypeFromArray(e){return MT.get(e.constructor)}getTypeFromAttribute(e){let t=e;e.isInterleavedBufferAttribute&&(t=e.data);const r=t.array,s=e.itemSize,i=e.normalized;let n;return e instanceof Le||!0===i||(n=this.getTypeFromArray(r)),this.getTypeFromLength(s,n)}getTypeLength(e){const t=this.getVectorType(e),r=/vec([2-4])/.exec(t);return null!==r?Number(r[1]):"float"===t||"bool"===t||"int"===t||"uint"===t?1:!0===/mat2/.test(e)?4:!0===/mat3/.test(e)?9:!0===/mat4/.test(e)?16:0}getVectorFromMatrix(e){return e.replace("mat","vec")}changeComponentType(e,t){return this.getTypeFromLength(this.getTypeLength(e),t)}getIntegerType(e){const t=this.getComponentType(e);return"int"===t||"uint"===t?e:this.changeComponentType(e,"int")}addStack(){return this.stack=Tm(this.stack),this.stacks.push(Ci()||this.stack),Ri(this.stack),this.stack}removeStack(){const e=this.stack;return this.stack=e.parent,Ri(this.stacks.pop()),e}getDataFromNode(e,t=this.shaderStage,r=null){let s=(r=null===r?e.isGlobal(this)?this.globalCache:this.cache:r).getData(e);return void 0===s&&(s={},r.setData(e,s)),void 0===s[t]&&(s[t]={}),s[t]}getNodeProperties(e,t="any"){const r=this.getDataFromNode(e,t);return r.properties||(r.properties={outputNode:null})}getBufferAttributeFromNode(e,t){const r=this.getDataFromNode(e);let s=r.bufferAttribute;if(void 0===s){const i=this.uniforms.index++;s=new Gx("nodeAttribute"+i,t,e),this.bufferAttributes.push(s),r.bufferAttribute=s}return s}getStructTypeFromNode(e,t,r=this.shaderStage){const s=this.getDataFromNode(e,r);let i=s.structType;if(void 0===i){const e=this.structs.index++;i=new qx("StructType"+e,t),this.structs[r].push(i),s.structType=i}return i}getUniformFromNode(e,t,r=this.shaderStage,s=null){const i=this.getDataFromNode(e,r,this.globalCache);let n=i.uniform;if(void 0===n){const o=this.uniforms.index++;n=new kx(s||"nodeUniform"+o,t,e),this.uniforms[r].push(n),i.uniform=n}return n}getVarFromNode(e,t=null,r=e.getNodeType(this),s=this.shaderStage){const i=this.getDataFromNode(e,s);let n=i.variable;if(void 0===n){const e=this.vars[s]||(this.vars[s]=[]);null===t&&(t="nodeVar"+e.length),n=new zx(t,r),e.push(n),i.variable=n}return n}getVaryingFromNode(e,t=null,r=e.getNodeType(this)){const s=this.getDataFromNode(e,"any");let i=s.varying;if(void 0===i){const e=this.varyings,n=e.length;null===t&&(t="nodeVarying"+n),i=new $x(t,r),e.push(i),s.varying=i}return i}getCodeFromNode(e,t,r=this.shaderStage){const s=this.getDataFromNode(e);let i=s.code;if(void 0===i){const e=this.codes[r]||(this.codes[r]=[]),n=e.length;i=new Hx("nodeCode"+n,t),e.push(i),s.code=i}return i}addFlowCodeHierarchy(e,t){const{flowCodes:r,flowCodeBlock:s}=this.getDataFromNode(e);let i=!0,n=t;for(;n;){if(!0===s.get(n)){i=!1;break}n=this.getDataFromNode(n).parentNodeBlock}if(i)for(const e of r)this.addLineFlowCode(e)}addLineFlowCodeBlock(e,t,r){const s=this.getDataFromNode(e),i=s.flowCodes||(s.flowCodes=[]),n=s.flowCodeBlock||(s.flowCodeBlock=new WeakMap);i.push(t),n.set(r,!0)}addLineFlowCode(e,t=null){return""===e||(null!==t&&this.context.nodeBlock&&this.addLineFlowCodeBlock(t,e,this.context.nodeBlock),e=this.tab+e,/;\s*$/.test(e)||(e+=";\n"),this.flow.code+=e),this}addFlowCode(e){return this.flow.code+=e,this}addFlowTab(){return this.tab+="\t",this}removeFlowTab(){return this.tab=this.tab.slice(0,-1),this}getFlowData(e){return this.flowsData.get(e)}flowNode(e){const t=e.getNodeType(this),r=this.flowChildNode(e,t);return this.flowsData.set(e,r),r}buildFunctionNode(e){const t=new yy,r=this.currentFunctionNode;return this.currentFunctionNode=t,t.code=this.buildFunctionCode(e),this.currentFunctionNode=r,t}flowShaderNode(e){const t=e.layout,r={[Symbol.iterator](){let e=0;const t=Object.values(this);return{next:()=>({value:t[e],done:e++>=t.length})}}};for(const e of t.inputs)r[e.name]=new bm(e.type,e.name);e.layout=null;const s=e.call(r),i=this.flowStagesNode(s,t.type);return e.layout=t,i}flowStagesNode(e,t=null){const r=this.flow,s=this.vars,i=this.cache,n=this.buildStage,o=this.stack,a={code:""};this.flow=a,this.vars={},this.cache=new jx,this.stack=Tm();for(const r of Ms)this.setBuildStage(r),a.result=e.build(this,t);return a.vars=this.getVars(this.shaderStage),this.flow=r,this.vars=s,this.cache=i,this.stack=o,this.setBuildStage(n),a}getFunctionOperator(){return null}flowChildNode(e,t=null){const r=this.flow,s={code:""};return this.flow=s,s.result=e.build(this,t),this.flow=r,s}flowNodeFromShaderStage(e,t,r=null,s=null){const i=this.shaderStage;this.setShaderStage(e);const n=this.flowChildNode(t,r);return null!==s&&(n.code+=`${this.tab+s} = ${n.result};\n`),this.flowCode[e]=this.flowCode[e]+n.code,this.setShaderStage(i),n}getAttributesArray(){return this.attributes.concat(this.bufferAttributes)}getAttributes(){console.warn("Abstract function.")}getVaryings(){console.warn("Abstract function.")}getVar(e,t){return`${this.getType(e)} ${t}`}getVars(e){let t="";const r=this.vars[e];if(void 0!==r)for(const e of r)t+=`${this.getVar(e.type,e.name)}; `;return t}getUniforms(){console.warn("Abstract function.")}getCodes(e){const t=this.codes[e];let r="";if(void 0!==t)for(const e of t)r+=e.code+"\n";return r}getHash(){return this.vertexShader+this.fragmentShader+this.computeShader}setShaderStage(e){this.shaderStage=e}getShaderStage(){return this.shaderStage}setBuildStage(e){this.buildStage=e}getBuildStage(){return this.buildStage}buildCode(){console.warn("Abstract function.")}build(){const{object:e,material:t,renderer:r}=this;if(null!==t){let e=r.library.fromMaterial(t);null===e&&(console.error(`NodeMaterial: Material "${t.type}" is not compatible.`),e=new sh),e.build(this)}else this.addFlow("compute",e);for(const e of Ms){this.setBuildStage(e),this.context.vertex&&this.context.vertex.isNode&&this.flowNodeFromShaderStage("vertex",this.context.vertex);for(const t of Bs){this.setShaderStage(t);const r=this.flowNodes[t];for(const t of r)"generate"===e?this.flowNode(t):t.build(this)}}return this.setBuildStage(null),this.setShaderStage(null),this.buildCode(),this.buildUpdateNodes(),this}getNodeUniform(e,t){if("float"===t||"int"===t||"uint"===t)return new rT(e);if("vec2"===t||"ivec2"===t||"uvec2"===t)return new sT(e);if("vec3"===t||"ivec3"===t||"uvec3"===t)return new iT(e);if("vec4"===t||"ivec4"===t||"uvec4"===t)return new nT(e);if("color"===t)return new oT(e);if("mat3"===t)return new aT(e);if("mat4"===t)return new uT(e);throw new Error(`Uniform "${t}" not declared.`)}format(e,t,r){if((t=this.getVectorType(t))===(r=this.getVectorType(r))||null===r||this.isReference(r))return e;const s=this.getTypeLength(t),i=this.getTypeLength(r);return 16===s&&9===i?`${this.getType(r)}(${e}[0].xyz, ${e}[1].xyz, ${e}[2].xyz)`:9===s&&4===i?`${this.getType(r)}(${e}[0].xy, ${e}[1].xy)`:s>4||i>4||0===i?e:s===i?`${this.getType(r)}( ${e} )`:s>i?this.format(`${e}.${"xyz".slice(0,i)}`,this.getTypeFromLength(i,this.getComponentType(t)),r):4===i&&s>1?`${this.getType(r)}( ${this.format(e,t,"vec3")}, 1.0 )`:2===s?`${this.getType(r)}( ${this.format(e,t,"vec2")}, 0.0 )`:(1===s&&i>1&&t!==this.getComponentType(r)&&(e=`${this.getType(this.getComponentType(r))}( ${e} )`),`${this.getType(r)}( ${e} )`)}getSignature(){return`// Three.js r${Ve} - Node System\n`}createNodeMaterial(e="NodeMaterial"){throw new Error(`THREE.NodeBuilder: createNodeMaterial() was deprecated. Use new ${e}() instead.`)}}class UT{constructor(){this.time=0,this.deltaTime=0,this.frameId=0,this.renderId=0,this.updateMap=new WeakMap,this.updateBeforeMap=new WeakMap,this.updateAfterMap=new WeakMap,this.renderer=null,this.material=null,this.camera=null,this.object=null,this.scene=null}_getMaps(e,t){let r=e.get(t);return void 0===r&&(r={renderMap:new WeakMap,frameMap:new WeakMap},e.set(t,r)),r}updateBeforeNode(e){const t=e.getUpdateBeforeType(),r=e.updateReference(this);if(t===Rs.FRAME){const{frameMap:t}=this._getMaps(this.updateBeforeMap,r);t.get(r)!==this.frameId&&!1!==e.updateBefore(this)&&t.set(r,this.frameId)}else if(t===Rs.RENDER){const{renderMap:t}=this._getMaps(this.updateBeforeMap,r);t.get(r)!==this.renderId&&!1!==e.updateBefore(this)&&t.set(r,this.renderId)}else t===Rs.OBJECT&&e.updateBefore(this)}updateAfterNode(e){const t=e.getUpdateAfterType(),r=e.updateReference(this);if(t===Rs.FRAME){const{frameMap:t}=this._getMaps(this.updateAfterMap,r);t.get(r)!==this.frameId&&!1!==e.updateAfter(this)&&t.set(r,this.frameId)}else if(t===Rs.RENDER){const{renderMap:t}=this._getMaps(this.updateAfterMap,r);t.get(r)!==this.renderId&&!1!==e.updateAfter(this)&&t.set(r,this.renderId)}else t===Rs.OBJECT&&e.updateAfter(this)}updateNode(e){const t=e.getUpdateType(),r=e.updateReference(this);if(t===Rs.FRAME){const{frameMap:t}=this._getMaps(this.updateMap,r);t.get(r)!==this.frameId&&!1!==e.update(this)&&t.set(r,this.frameId)}else if(t===Rs.RENDER){const{renderMap:t}=this._getMaps(this.updateMap,r);t.get(r)!==this.renderId&&!1!==e.update(this)&&t.set(r,this.renderId)}else t===Rs.OBJECT&&e.update(this)}update(){this.frameId++,void 0===this.lastTime&&(this.lastTime=performance.now()),this.deltaTime=(performance.now()-this.lastTime)/1e3,this.lastTime=performance.now(),this.time+=this.deltaTime}}class PT{constructor(e,t,r=null,s="",i=!1){this.type=e,this.name=t,this.count=r,this.qualifier=s,this.isConst=i}}PT.isNodeFunctionInput=!0;class IT extends Eb{static get type(){return"DirectionalLightNode"}constructor(e=null){super(e)}setup(e){super.setup(e);const t=e.context.lightingModel,r=this.colorNode,s=Jy(this.light),i=e.context.reflectedLight;t.direct({lightDirection:s,lightColor:r,reflectedLight:i},e.stack,e)}}const DT=new n,LT=new n;let VT=null;class OT extends Eb{static get type(){return"RectAreaLightNode"}constructor(e=null){super(e),this.halfHeight=on(new r).setGroup(rn),this.halfWidth=on(new r).setGroup(rn),this.updateType=Rs.RENDER}update(e){super.update(e);const{light:t}=this,r=e.camera.matrixWorldInverse;LT.identity(),DT.copy(t.matrixWorld),DT.premultiply(r),LT.extractRotation(DT),this.halfWidth.value.set(.5*t.width,0,0),this.halfHeight.value.set(0,.5*t.height,0),this.halfWidth.value.applyMatrix4(LT),this.halfHeight.value.applyMatrix4(LT)}setup(e){let t,r;super.setup(e),e.isAvailable("float32Filterable")?(t=Ru(VT.LTC_FLOAT_1),r=Ru(VT.LTC_FLOAT_2)):(t=Ru(VT.LTC_HALF_1),r=Ru(VT.LTC_HALF_2));const{colorNode:s,light:i}=this,n=e.context.lightingModel,o=Zy(i),a=e.context.reflectedLight;n.directRectArea({lightColor:s,lightPosition:o,halfWidth:this.halfWidth,halfHeight:this.halfHeight,reflectedLight:a,ltc_1:t,ltc_2:r},e.stack,e)}static setLTC(e){VT=e}}class GT extends Eb{static get type(){return"SpotLightNode"}constructor(e=null){super(e),this.coneCosNode=on(0).setGroup(rn),this.penumbraCosNode=on(0).setGroup(rn),this.cutoffDistanceNode=on(0).setGroup(rn),this.decayExponentNode=on(0).setGroup(rn)}update(e){super.update(e);const{light:t}=this;this.coneCosNode.value=Math.cos(t.angle),this.penumbraCosNode.value=Math.cos(t.angle*(1-t.penumbra)),this.cutoffDistanceNode.value=t.distance,this.decayExponentNode.value=t.decay}getSpotAttenuation(e){const{coneCosNode:t,penumbraCosNode:r}=this;return ya(t,r,e)}setup(e){super.setup(e);const t=e.context.lightingModel,{colorNode:r,cutoffDistanceNode:s,decayExponentNode:i,light:n}=this,o=Zy(n).sub(nl),a=o.normalize(),u=a.dot(Jy(n)),l=this.getSpotAttenuation(u),d=o.length(),c=wb({lightDistance:d,cutoffDistance:s,decayExponent:i});let h=r.mul(l).mul(c);if(n.map){const e=Xy(n),t=Ru(n.map,e.xy).onRenderUpdate((()=>n.map));h=e.mul(2).sub(1).abs().lessThan(1).all().select(h.mul(t),h)}const p=e.context.reflectedLight;t.direct({lightDirection:a,lightColor:h,reflectedLight:p},e.stack,e)}}class kT extends GT{static get type(){return"IESSpotLightNode"}getSpotAttenuation(e){const t=this.light.iesMap;let r=null;if(t&&!0===t.isTexture){const s=e.acos().mul(1/Math.PI);r=Ru(t,Ii(s,0),0).r}else r=super.getSpotAttenuation(e);return r}}class zT extends Eb{static get type(){return"AmbientLightNode"}constructor(e=null){super(e)}setup({context:e}){e.irradiance.addAssign(this.colorNode)}}class $T extends Eb{static get type(){return"HemisphereLightNode"}constructor(t=null){super(t),this.lightPositionNode=Yy(t),this.lightDirectionNode=this.lightPositionNode.normalize(),this.groundColorNode=on(new e).setGroup(rn)}update(e){const{light:t}=this;super.update(e),this.lightPositionNode.object3d=t,this.groundColorNode.value.copy(t.groundColor).multiplyScalar(t.intensity)}setup(e){const{colorNode:t,groundColorNode:r,lightDirectionNode:s}=this,i=pl.dot(s).mul(.5).add(.5),n=pa(r,t,i);e.context.irradiance.addAssign(n)}}class HT extends Eb{static get type(){return"LightProbeNode"}constructor(e=null){super(e);const t=[];for(let e=0;e<9;e++)t.push(new r);this.lightProbe=Bl(t)}update(e){const{light:t}=this;super.update(e);for(let e=0;e<9;e++)this.lightProbe.array[e].copy(t.sh.coefficients[e]).multiplyScalar(t.intensity)}setup(e){const t=Ux(gl,this.lightProbe);e.context.irradiance.addAssign(t)}}class WT{parseFunction(){console.warn("Abstract function.")}}class jT{constructor(e,t,r="",s=""){this.type=e,this.inputs=t,this.name=r,this.precision=s}getCode(){console.warn("Abstract function.")}}jT.isNodeFunction=!0;const qT=/^\s*(highp|mediump|lowp)?\s*([a-z_0-9]+)\s*([a-z_0-9]+)?\s*\(([\s\S]*?)\)/i,KT=/[a-z_0-9]+/gi,XT="#pragma main";class YT extends jT{constructor(e){const{type:t,inputs:r,name:s,precision:i,inputsCode:n,blockCode:o,headerCode:a}=(e=>{const t=(e=e.trim()).indexOf(XT),r=-1!==t?e.slice(t+12):e,s=r.match(qT);if(null!==s&&5===s.length){const i=s[4],n=[];let o=null;for(;null!==(o=KT.exec(i));)n.push(o);const a=[];let u=0;for(;u0||e.backgroundBlurriness>0&&0===t.backgroundBlurriness;if(t.background!==r||s){const i=this.getCacheNode("background",r,(()=>{if(!0===r.isCubeTexture||r.mapping===j||r.mapping===q||r.mapping===Fe){if(e.backgroundBlurriness>0||r.mapping===Fe)return eg(r);{let e;return e=!0===r.isCubeTexture?Rl(r):Ru(r),Ah(e)}}if(!0===r.isTexture)return Ru(r,Rc.flipY()).setUpdateMatrix(!0);!0!==r.isColor&&console.error("WebGPUNodes: Unsupported background configuration.",r)}),s);t.backgroundNode=i,t.background=r,t.backgroundBlurriness=e.backgroundBlurriness}}else t.backgroundNode&&(delete t.backgroundNode,delete t.background)}getCacheNode(e,t,r,s=!1){const i=this.cacheLib[e]||(this.cacheLib[e]=new WeakMap);let n=i.get(t);return(void 0===n||s)&&(n=r(),i.set(t,n)),n}updateFog(e){const t=this.get(e),r=e.fog;if(r){if(t.fog!==r){const e=this.getCacheNode("fog",r,(()=>{if(r.isFogExp2){const e=Pl("color","color",r).setGroup(rn),t=Pl("density","float",r).setGroup(rn);return wy(e,Ey(t))}if(r.isFog){const e=Pl("color","color",r).setGroup(rn),t=Pl("near","float",r).setGroup(rn),s=Pl("far","float",r).setGroup(rn);return wy(e,Cy(t,s))}console.error("THREE.Renderer: Unsupported fog configuration.",r)}));t.fogNode=e,t.fog=r}}else delete t.fogNode,delete t.fog}updateEnvironment(e){const t=this.get(e),r=e.environment;if(r){if(t.environment!==r){const e=this.getCacheNode("environment",r,(()=>!0===r.isCubeTexture?Rl(r):!0===r.isTexture?Ru(r):void console.error("Nodes: Unsupported environment configuration.",r)));t.environmentNode=e,t.environment=r}}else t.environmentNode&&(delete t.environmentNode,delete t.environment)}getNodeFrame(e=this.renderer,t=null,r=null,s=null,i=null){const n=this.nodeFrame;return n.renderer=e,n.scene=t,n.object=r,n.camera=s,n.material=i,n}getNodeFrameForRender(e){return this.getNodeFrame(e.renderer,e.scene,e.object,e.camera,e.material)}getOutputCacheKey(){const e=this.renderer;return e.toneMapping+","+e.currentColorSpace}hasOutputChange(e){return ZT.get(e)!==this.getOutputCacheKey()}getOutputNode(e){const t=this.renderer,r=this.getOutputCacheKey(),s=Ru(e,Rc).renderOutput(t.toneMapping,t.currentColorSpace);return ZT.set(e,r),s}updateBefore(e){const t=e.getNodeBuilderState();for(const r of t.updateBeforeNodes)this.getNodeFrameForRender(e).updateBeforeNode(r)}updateAfter(e){const t=e.getNodeBuilderState();for(const r of t.updateAfterNodes)this.getNodeFrameForRender(e).updateAfterNode(r)}updateForCompute(e){const t=this.getNodeFrame(),r=this.getForCompute(e);for(const e of r.updateNodes)t.updateNode(e)}updateForRender(e){const t=this.getNodeFrameForRender(e),r=e.getNodeBuilderState();for(const e of r.updateNodes)t.updateNode(e)}needsRefresh(e){const t=this.getNodeFrameForRender(e);return e.getMonitor().needsRefresh(e,t)}dispose(){super.dispose(),this.nodeFrame=new UT,this.nodeBuilderCache=new Map,this.cacheLib={}}}const r_=new fe;class s_{constructor(e=null){this.version=0,this.clipIntersection=null,this.cacheKey="",this.shadowPass=!1,this.viewNormalMatrix=new i,this.clippingGroupContexts=new WeakMap,this.intersectionPlanes=[],this.unionPlanes=[],this.parentVersion=null,null!==e&&(this.viewNormalMatrix=e.viewNormalMatrix,this.clippingGroupContexts=e.clippingGroupContexts,this.shadowPass=e.shadowPass,this.viewMatrix=e.viewMatrix)}projectPlanes(e,t,r){const s=e.length;for(let i=0;i{await this.compileAsync(e,t);const s=this._renderLists.get(e,t),i=this._renderContexts.get(e,t,this._renderTarget),n=e.overrideMaterial||r.material,o=this._objects.get(r,n,e,t,s.lightsNode,i,i.clippingContext),{fragmentShader:a,vertexShader:u}=o.getNodeBuilderState();return{fragmentShader:a,vertexShader:u}}}}async init(){if(this._initialized)throw new Error("Renderer: Backend has already been initialized.");return null!==this._initPromise||(this._initPromise=new Promise((async(e,t)=>{let r=this.backend;try{await r.init(this)}catch(e){if(null===this._getFallback)return void t(e);try{this.backend=r=this._getFallback(e),await r.init(this)}catch(e){return void t(e)}}this._nodes=new t_(this,r),this._animation=new Fg(this._nodes,this.info),this._attributes=new Hg(r),this._background=new Dx(this,this._nodes),this._geometries=new qg(this._attributes,this.info),this._textures=new fm(this,r,this.info),this._pipelines=new em(r,this._nodes),this._bindings=new tm(r,this._nodes,this._textures,this._attributes,this._pipelines,this.info),this._objects=new Lg(this,this._nodes,this._geometries,this._pipelines,this._bindings,this.info),this._renderLists=new am(this.lighting),this._bundles=new o_,this._renderContexts=new gm,this._animation.start(),this._initialized=!0,e()}))),this._initPromise}get coordinateSystem(){return this.backend.coordinateSystem}async compileAsync(e,t,r=null){if(!0===this._isDeviceLost)return;!1===this._initialized&&await this.init();const s=this._nodes.nodeFrame,i=s.renderId,n=this._currentRenderContext,o=this._currentRenderObjectFunction,a=this._compilationPromises,u=!0===e.isScene?e:c_;null===r&&(r=e);const l=this._renderTarget,d=this._renderContexts.get(r,t,l),c=this._activeMipmapLevel,h=[];this._currentRenderContext=d,this._currentRenderObjectFunction=this.renderObject,this._handleObjectFunction=this._createObjectPipeline,this._compilationPromises=h,s.renderId++,s.update(),d.depth=this.depth,d.stencil=this.stencil,d.clippingContext||(d.clippingContext=new s_),d.clippingContext.updateGlobal(u,t),u.onBeforeRender(this,e,t,l);const p=this._renderLists.get(e,t);if(p.begin(),this._projectObject(e,t,0,p,d.clippingContext),r!==e&&r.traverseVisible((function(e){e.isLight&&e.layers.test(t.layers)&&p.pushLight(e)})),p.finish(),null!==l){this._textures.updateRenderTarget(l,c);const e=this._textures.get(l);d.textures=e.textures,d.depthTexture=e.depthTexture}else d.textures=null,d.depthTexture=null;this._background.update(u,p,d);const g=p.opaque,m=p.transparent,f=p.transparentDoublePass,y=p.lightsNode;!0===this.opaque&&g.length>0&&this._renderObjects(g,t,u,y),!0===this.transparent&&m.length>0&&this._renderTransparents(m,f,t,u,y),s.renderId=i,this._currentRenderContext=n,this._currentRenderObjectFunction=o,this._compilationPromises=a,this._handleObjectFunction=this._renderObjectDirect,await Promise.all(h)}async renderAsync(e,t){!1===this._initialized&&await this.init();const r=this._renderScene(e,t);await this.backend.resolveTimestampAsync(r,"render")}async waitForGPU(){await this.backend.waitForGPU()}setMRT(e){return this._mrt=e,this}getMRT(){return this._mrt}_onDeviceLost(e){let t=`THREE.WebGPURenderer: ${e.api} Device Lost:\n\nMessage: ${e.message}`;e.reason&&(t+=`\nReason: ${e.reason}`),console.error(t),this._isDeviceLost=!0}_renderBundle(e,t,r){const{bundleGroup:s,camera:i,renderList:n}=e,o=this._currentRenderContext,a=this._bundles.get(s,i),u=this.backend.get(a);void 0===u.renderContexts&&(u.renderContexts=new Set);const l=s.version!==u.version,d=!1===u.renderContexts.has(o)||l;if(u.renderContexts.add(o),d){this.backend.beginBundle(o),(void 0===u.renderObjects||l)&&(u.renderObjects=[]),this._currentRenderBundle=a;const e=n.opaque;!0===this.opaque&&e.length>0&&this._renderObjects(e,i,t,r),this._currentRenderBundle=null,this.backend.finishBundle(o,a),u.version=s.version}else{const{renderObjects:e}=u;for(let t=0,r=e.length;t>=c,p.viewportValue.height>>=c,p.viewportValue.minDepth=b,p.viewportValue.maxDepth=x,p.viewport=!1===p.viewportValue.equals(p_),p.scissorValue.copy(f).multiplyScalar(y).floor(),p.scissor=this._scissorTest&&!1===p.scissorValue.equals(p_),p.scissorValue.width>>=c,p.scissorValue.height>>=c,p.clippingContext||(p.clippingContext=new s_),p.clippingContext.updateGlobal(u,t),u.onBeforeRender(this,e,t,h),m_.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),g_.setFromProjectionMatrix(m_,g);const T=this._renderLists.get(e,t);if(T.begin(),this._projectObject(e,t,0,T,p.clippingContext),T.finish(),!0===this.sortObjects&&T.sort(this._opaqueSort,this._transparentSort),null!==h){this._textures.updateRenderTarget(h,c);const e=this._textures.get(h);p.textures=e.textures,p.depthTexture=e.depthTexture,p.width=e.width,p.height=e.height,p.renderTarget=h,p.depth=h.depthBuffer,p.stencil=h.stencilBuffer}else p.textures=null,p.depthTexture=null,p.width=this.domElement.width,p.height=this.domElement.height,p.depth=this.depth,p.stencil=this.stencil;p.width>>=c,p.height>>=c,p.activeCubeFace=d,p.activeMipmapLevel=c,p.occlusionQueryCount=T.occlusionQueryCount,this._background.update(u,T,p),this.backend.beginRender(p);const{bundles:_,lightsNode:v,transparentDoublePass:N,transparent:S,opaque:A}=T;if(_.length>0&&this._renderBundles(_,u,v),!0===this.opaque&&A.length>0&&this._renderObjects(A,t,u,v),!0===this.transparent&&S.length>0&&this._renderTransparents(S,N,t,u,v),this.backend.finishRender(p),i.renderId=n,this._currentRenderContext=o,this._currentRenderObjectFunction=a,null!==s){this.setRenderTarget(l,d,c);const e=this._quad;this._nodes.hasOutputChange(h.texture)&&(e.material.fragmentNode=this._nodes.getOutputNode(h.texture),e.material.needsUpdate=!0),this._renderScene(e,e.camera,!1)}return u.onAfterRender(this,e,t,h),p}getMaxAnisotropy(){return this.backend.getMaxAnisotropy()}getActiveCubeFace(){return this._activeCubeFace}getActiveMipmapLevel(){return this._activeMipmapLevel}async setAnimationLoop(e){!1===this._initialized&&await this.init(),this._animation.setAnimationLoop(e)}async getArrayBufferAsync(e){return await this.backend.getArrayBufferAsync(e)}getContext(){return this.backend.getContext()}getPixelRatio(){return this._pixelRatio}getDrawingBufferSize(e){return e.set(this._width*this._pixelRatio,this._height*this._pixelRatio).floor()}getSize(e){return e.set(this._width,this._height)}setPixelRatio(e=1){this._pixelRatio!==e&&(this._pixelRatio=e,this.setSize(this._width,this._height,!1))}setDrawingBufferSize(e,t,r){this._width=e,this._height=t,this._pixelRatio=r,this.domElement.width=Math.floor(e*r),this.domElement.height=Math.floor(t*r),this.setViewport(0,0,e,t),this._initialized&&this.backend.updateSize()}setSize(e,t,r=!0){this._width=e,this._height=t,this.domElement.width=Math.floor(e*this._pixelRatio),this.domElement.height=Math.floor(t*this._pixelRatio),!0===r&&(this.domElement.style.width=e+"px",this.domElement.style.height=t+"px"),this.setViewport(0,0,e,t),this._initialized&&this.backend.updateSize()}setOpaqueSort(e){this._opaqueSort=e}setTransparentSort(e){this._transparentSort=e}getScissor(e){const t=this._scissor;return e.x=t.x,e.y=t.y,e.width=t.width,e.height=t.height,e}setScissor(e,t,r,s){const i=this._scissor;e.isVector4?i.copy(e):i.set(e,t,r,s)}getScissorTest(){return this._scissorTest}setScissorTest(e){this._scissorTest=e,this.backend.setScissorTest(e)}getViewport(e){return e.copy(this._viewport)}setViewport(e,t,r,s,i=0,n=1){const o=this._viewport;e.isVector4?o.copy(e):o.set(e,t,r,s),o.minDepth=i,o.maxDepth=n}getClearColor(e){return e.copy(this._clearColor)}setClearColor(e,t=1){this._clearColor.set(e),this._clearColor.a=t}getClearAlpha(){return this._clearColor.a}setClearAlpha(e){this._clearColor.a=e}getClearDepth(){return this._clearDepth}setClearDepth(e){this._clearDepth=e}getClearStencil(){return this._clearStencil}setClearStencil(e){this._clearStencil=e}isOccluded(e){const t=this._currentRenderContext;return t&&this.backend.isOccluded(t,e)}clear(e=!0,t=!0,r=!0){if(!1===this._initialized)return console.warn("THREE.Renderer: .clear() called before the backend is initialized. Try using .clearAsync() instead."),this.clearAsync(e,t,r);const s=this._renderTarget||this._getFrameBufferTarget();let i=null;if(null!==s){this._textures.updateRenderTarget(s);const e=this._textures.get(s);i=this._renderContexts.getForClear(s),i.textures=e.textures,i.depthTexture=e.depthTexture,i.width=e.width,i.height=e.height,i.renderTarget=s,i.depth=s.depthBuffer,i.stencil=s.stencilBuffer}if(this.backend.clear(e,t,r,i),null!==s&&null===this._renderTarget){const e=this._quad;this._nodes.hasOutputChange(s.texture)&&(e.material.fragmentNode=this._nodes.getOutputNode(s.texture),e.material.needsUpdate=!0),this._renderScene(e,e.camera,!1)}}clearColor(){return this.clear(!0,!1,!1)}clearDepth(){return this.clear(!1,!0,!1)}clearStencil(){return this.clear(!1,!1,!0)}async clearAsync(e=!0,t=!0,r=!0){!1===this._initialized&&await this.init(),this.clear(e,t,r)}async clearColorAsync(){this.clearAsync(!0,!1,!1)}async clearDepthAsync(){this.clearAsync(!1,!0,!1)}async clearStencilAsync(){this.clearAsync(!1,!1,!0)}get currentToneMapping(){return null!==this._renderTarget?h:this.toneMapping}get currentColorSpace(){return null!==this._renderTarget?Re:this.outputColorSpace}dispose(){this.info.dispose(),this.backend.dispose(),this._animation.dispose(),this._objects.dispose(),this._pipelines.dispose(),this._nodes.dispose(),this._bindings.dispose(),this._renderLists.dispose(),this._renderContexts.dispose(),this._textures.dispose(),this.setRenderTarget(null),this.setAnimationLoop(null)}setRenderTarget(e,t=0,r=0){this._renderTarget=e,this._activeCubeFace=t,this._activeMipmapLevel=r}getRenderTarget(){return this._renderTarget}setRenderObjectFunction(e){this._renderObjectFunction=e}getRenderObjectFunction(){return this._renderObjectFunction}compute(e){if(!0===this.isDeviceLost)return;if(!1===this._initialized)return console.warn("THREE.Renderer: .compute() called before the backend is initialized. Try using .computeAsync() instead."),this.computeAsync(e);const t=this._nodes.nodeFrame,r=t.renderId;this.info.calls++,this.info.compute.calls++,this.info.compute.frameCalls++,t.renderId=this.info.calls;const s=this.backend,i=this._pipelines,n=this._bindings,o=this._nodes,a=Array.isArray(e)?e:[e];if(void 0===a[0]||!0!==a[0].isComputeNode)throw new Error("THREE.Renderer: .compute() expects a ComputeNode.");s.beginCompute(e);for(const t of a){if(!1===i.has(t)){const e=()=>{t.removeEventListener("dispose",e),i.delete(t),n.delete(t),o.delete(t)};t.addEventListener("dispose",e);const r=t.onInitFunction;null!==r&&r.call(t,{renderer:this})}o.updateForCompute(t),n.updateForCompute(t);const r=n.getForCompute(t),a=i.getForCompute(t,r);s.compute(e,t,r,a)}s.finishCompute(e),t.renderId=r}async computeAsync(e){!1===this._initialized&&await this.init(),this.compute(e),await this.backend.resolveTimestampAsync(e,"compute")}async hasFeatureAsync(e){return!1===this._initialized&&await this.init(),this.backend.hasFeature(e)}hasFeature(e){return!1===this._initialized?(console.warn("THREE.Renderer: .hasFeature() called before the backend is initialized. Try using .hasFeatureAsync() instead."),!1):this.backend.hasFeature(e)}hasInitialized(){return this._initialized}async initTextureAsync(e){!1===this._initialized&&await this.init(),this._textures.updateTexture(e)}initTexture(e){!1===this._initialized&&console.warn("THREE.Renderer: .initTexture() called before the backend is initialized. Try using .initTextureAsync() instead."),this._textures.updateTexture(e)}copyFramebufferToTexture(e,t=null){if(null!==t)if(t.isVector2)t=f_.set(t.x,t.y,e.image.width,e.image.height).floor();else{if(!t.isVector4)return void console.error("THREE.Renderer.copyFramebufferToTexture: Invalid rectangle.");t=f_.copy(t).floor()}else t=f_.set(0,0,e.image.width,e.image.height);let r,s=this._currentRenderContext;null!==s?r=s.renderTarget:(r=this._renderTarget||this._getFrameBufferTarget(),null!==r&&(this._textures.updateRenderTarget(r),s=this._textures.get(r))),this._textures.updateTexture(e,{renderTarget:r}),this.backend.copyFramebufferToTexture(e,s,t)}copyTextureToTexture(e,t,r=null,s=null,i=0){this._textures.updateTexture(e),this._textures.updateTexture(t),this.backend.copyTextureToTexture(e,t,r,s,i)}async readRenderTargetPixelsAsync(e,t,r,s,i,n=0,o=0){return this.backend.copyTextureToBuffer(e.textures[n],t,r,s,i,o)}_projectObject(e,t,r,s,i){if(!1===e.visible)return;if(e.layers.test(t.layers))if(e.isGroup)r=e.renderOrder,e.isClippingGroup&&e.enabled&&(i=i.getGroupContext(e));else if(e.isLOD)!0===e.autoUpdate&&e.update(t);else if(e.isLight)s.pushLight(e);else if(e.isSprite){if(!e.frustumCulled||g_.intersectsSprite(e)){!0===this.sortObjects&&f_.setFromMatrixPosition(e.matrixWorld).applyMatrix4(m_);const{geometry:t,material:n}=e;n.visible&&s.push(e,t,n,r,f_.z,null,i)}}else if(e.isLineLoop)console.error("THREE.Renderer: Objects of type THREE.LineLoop are not supported. Please use THREE.Line or THREE.LineSegments.");else if((e.isMesh||e.isLine||e.isPoints)&&(!e.frustumCulled||g_.intersectsObject(e))){const{geometry:t,material:n}=e;if(!0===this.sortObjects&&(null===t.boundingSphere&&t.computeBoundingSphere(),f_.copy(t.boundingSphere.center).applyMatrix4(e.matrixWorld).applyMatrix4(m_)),Array.isArray(n)){const o=t.groups;for(let a=0,u=o.length;a0){for(const{material:e}of t)e.side=T;this._renderObjects(t,r,s,i,"backSide");for(const{material:e}of t)e.side=ke;this._renderObjects(e,r,s,i);for(const{material:e}of t)e.side=le}else this._renderObjects(e,r,s,i)}_renderObjects(e,t,r,s,i=null){for(let n=0,o=e.length;n0,e.isShadowNodeMaterial&&(e.side=null===i.shadowSide?i.side:i.shadowSide,i.depthNode&&i.depthNode.isNode&&(c=e.depthNode,e.depthNode=i.depthNode),i.castShadowNode&&i.castShadowNode.isNode&&(d=e.colorNode,e.colorNode=i.castShadowNode)),i=e}!0===i.transparent&&i.side===le&&!1===i.forceSinglePass?(i.side=T,this._handleObjectFunction(e,i,t,r,o,n,a,"backSide"),i.side=ke,this._handleObjectFunction(e,i,t,r,o,n,a,u),i.side=le):this._handleObjectFunction(e,i,t,r,o,n,a,u),void 0!==l&&(t.overrideMaterial.positionNode=l),void 0!==c&&(t.overrideMaterial.depthNode=c),void 0!==d&&(t.overrideMaterial.colorNode=d),e.onAfterRender(this,t,r,s,i,n)}_renderObjectDirect(e,t,r,s,i,n,o,a){const u=this._objects.get(e,t,r,s,i,this._currentRenderContext,o,a);u.drawRange=e.geometry.drawRange,u.group=n;const l=this._nodes.needsRefresh(u);if(l&&(this._nodes.updateBefore(u),this._geometries.updateForRender(u),this._nodes.updateForRender(u),this._bindings.updateForRender(u)),this._pipelines.updateForRender(u),null!==this._currentRenderBundle){this.backend.get(this._currentRenderBundle).renderObjects.push(u),u.bundle=this._currentRenderBundle.bundleGroup}this.backend.draw(u,this.info),l&&this._nodes.updateAfter(u)}_createObjectPipeline(e,t,r,s,i,n,o,a){const u=this._objects.get(e,t,r,s,i,this._currentRenderContext,o,a);u.drawRange=e.geometry.drawRange,u.group=n,this._nodes.updateBefore(u),this._geometries.updateForRender(u),this._nodes.updateForRender(u),this._bindings.updateForRender(u),this._pipelines.getForRender(u,this._compilationPromises),this._nodes.updateAfter(u)}get compile(){return this.compileAsync}}class b_{constructor(e=""){this.name=e,this.visibility=0}setVisibility(e){this.visibility|=e}clone(){return Object.assign(new this.constructor,this)}}class x_ extends b_{constructor(e,t=null){super(e),this.isBuffer=!0,this.bytesPerElement=Float32Array.BYTES_PER_ELEMENT,this._buffer=t}get byteLength(){return(e=this._buffer.byteLength)+($g-e%$g)%$g;var e}get buffer(){return this._buffer}update(){return!0}}class T_ extends x_{constructor(e,t=null){super(e,t),this.isUniformBuffer=!0}}let __=0;class v_ extends T_{constructor(e,t){super("UniformBuffer_"+__++,e?e.value:null),this.nodeUniform=e,this.groupNode=t}get buffer(){return this.nodeUniform.value}}class N_ extends T_{constructor(e){super(e),this.isUniformsGroup=!0,this._values=null,this.uniforms=[]}addUniform(e){return this.uniforms.push(e),this}removeUniform(e){const t=this.uniforms.indexOf(e);return-1!==t&&this.uniforms.splice(t,1),this}get values(){return null===this._values&&(this._values=Array.from(this.buffer)),this._values}get buffer(){let e=this._buffer;if(null===e){const t=this.byteLength;e=new Float32Array(new ArrayBuffer(t)),this._buffer=e}return e}get byteLength(){let e=0;for(let t=0,r=this.uniforms.length;t0?s:"";t=`${e.name} {\n\t${r} ${i.name}[${n}];\n};\n`}else{t=`${this.getVectorType(i.type)} ${this.getPropertyName(i,e)};`,n=!0}const o=i.node.precision;if(null!==o&&(t=F_[o]+" "+t),n){t="\t"+t;const e=i.groupNode.name;(s[e]||(s[e]=[])).push(t)}else t="uniform "+t,r.push(t)}let i="";for(const t in s){const r=s[t];i+=this._getGLSLUniformStruct(e+"_"+t,r.join("\n"))+"\n"}return i+=r.join("\n"),i}getTypeFromAttribute(e){let t=super.getTypeFromAttribute(e);if(/^[iu]/.test(t)&&e.gpuType!==x){let r=e;e.isInterleavedBufferAttribute&&(r=e.data);const s=r.array;!1==(s instanceof Uint32Array||s instanceof Int32Array)&&(t=t.slice(1))}return t}getAttributes(e){let t="";if("vertex"===e||"compute"===e){const e=this.getAttributesArray();let r=0;for(const s of e)t+=`layout( location = ${r++} ) in ${s.type} ${s.name};\n`}return t}getStructMembers(e){const t=[],r=e.getMemberTypes();for(let e=0;ee*t),1)}u`}getDrawIndex(){return this.renderer.backend.extensions.has("WEBGL_multi_draw")?"uint( gl_DrawID )":null}getFrontFacing(){return"gl_FrontFacing"}getFragCoord(){return"gl_FragCoord.xy"}getFragDepth(){return"gl_FragDepth"}enableExtension(e,t,r=this.shaderStage){const s=this.extensions[r]||(this.extensions[r]=new Map);!1===s.has(e)&&s.set(e,{name:e,behavior:t})}getExtensions(e){const t=[];if("vertex"===e){const t=this.renderer.backend.extensions;this.object.isBatchedMesh&&t.has("WEBGL_multi_draw")&&this.enableExtension("GL_ANGLE_multi_draw","require",e)}const r=this.extensions[e];if(void 0!==r)for(const{name:e,behavior:s}of r.values())t.push(`#extension ${e} : ${s}`);return t.join("\n")}getClipDistance(){return"gl_ClipDistance"}isAvailable(e){let t=U_[e];if(void 0===t){let r;switch(t=!1,e){case"float32Filterable":r="OES_texture_float_linear";break;case"clipDistance":r="WEBGL_clip_cull_distance"}if(void 0!==r){const e=this.renderer.backend.extensions;e.has(r)&&(e.get(r),t=!0)}U_[e]=t}return t}isFlipY(){return!0}enableHardwareClipping(e){this.enableExtension("GL_ANGLE_clip_cull_distance","require"),this.builtins.vertex.push(`out float gl_ClipDistance[ ${e} ]`)}registerTransform(e,t){this.transforms.push({varyingName:e,attributeNode:t})}getTransforms(){const e=this.transforms;let t="";for(let r=0;r0&&(r+="\n"),r+=`\t// flow -> ${n}\n\t`),r+=`${s.code}\n\t`,e===i&&"compute"!==t&&(r+="// result\n\t","vertex"===t?(r+="gl_Position = ",r+=`${s.result};`):"fragment"===t&&(e.outputNode.isOutputStructNode||(r+="fragColor = ",r+=`${s.result};`)))}const n=e[t];n.extensions=this.getExtensions(t),n.uniforms=this.getUniforms(t),n.attributes=this.getAttributes(t),n.varyings=this.getVaryings(t),n.vars=this.getVars(t),n.structs=this.getStructs(t),n.codes=this.getCodes(t),n.transforms=this.getTransforms(t),n.flow=r}null!==this.material?(this.vertexShader=this._getGLSLVertexCode(e.vertex),this.fragmentShader=this._getGLSLFragmentCode(e.fragment)):this.computeShader=this._getGLSLVertexCode(e.compute)}getUniformFromNode(e,t,r,s=null){const i=super.getUniformFromNode(e,t,r,s),n=this.getDataFromNode(e,r,this.globalCache);let o=n.uniformGPU;if(void 0===o){const s=e.groupNode,a=s.name,u=this.getBindGroupArray(a,r);if("texture"===t)o=new E_(i.name,i.node,s),u.push(o);else if("cubeTexture"===t)o=new w_(i.name,i.node,s),u.push(o);else if("texture3D"===t)o=new M_(i.name,i.node,s),u.push(o);else if("buffer"===t){e.name=`NodeBuffer_${e.id}`,i.name=`buffer${e.id}`;const t=new v_(e,s);t.name=e.name,u.push(t),o=t}else{const e=this.uniformGroups[r]||(this.uniformGroups[r]={});let n=e[a];void 0===n&&(n=new A_(r+"_"+a,s),e[a]=n,u.push(n)),o=this.getNodeUniform(i,t),n.addUniform(o)}n.uniformGPU=o}return i}}let D_=null,L_=null;class V_{constructor(e={}){this.parameters=Object.assign({},e),this.data=new WeakMap,this.renderer=null,this.domElement=null}async init(e){this.renderer=e}get coordinateSystem(){}beginRender(){}finishRender(){}beginCompute(){}finishCompute(){}draw(){}compute(){}createProgram(){}destroyProgram(){}createBindings(){}updateBindings(){}updateBinding(){}createRenderPipeline(){}createComputePipeline(){}needsRenderUpdate(){}getRenderCacheKey(){}createNodeBuilder(){}createSampler(){}destroySampler(){}createDefaultTexture(){}createTexture(){}updateTexture(){}generateMipmaps(){}destroyTexture(){}async copyTextureToBuffer(){}copyTextureToTexture(){}copyFramebufferToTexture(){}createAttribute(){}createIndexAttribute(){}createStorageAttribute(){}updateAttribute(){}destroyAttribute(){}getContext(){}updateSize(){}updateViewport(){}isOccluded(){}async resolveTimestampAsync(){}async waitForGPU(){}async getArrayBufferAsync(){}async hasFeatureAsync(){}hasFeature(){}getMaxAnisotropy(){}getDrawingBufferSize(){return D_=D_||new t,this.renderer.getDrawingBufferSize(D_)}setScissorTest(){}getClearColor(){const e=this.renderer;return L_=L_||new ym,e.getClearColor(L_),L_.getRGB(L_,this.renderer.currentColorSpace),L_}getDomElement(){let e=this.domElement;return null===e&&(e=void 0!==this.parameters.canvas?this.parameters.canvas:Je(),"setAttribute"in e&&e.setAttribute("data-engine",`three.js r${Ve} webgpu`),this.domElement=e),e}set(e,t){this.data.set(e,t)}get(e){let t=this.data.get(e);return void 0===t&&(t={},this.data.set(e,t)),t}has(e){return this.data.has(e)}delete(e){this.data.delete(e)}dispose(){}}let O_=0;class G_{constructor(e,t){this.buffers=[e.bufferGPU,t],this.type=e.type,this.bufferType=e.bufferType,this.pbo=e.pbo,this.byteLength=e.byteLength,this.bytesPerElement=e.BYTES_PER_ELEMENT,this.version=e.version,this.isInteger=e.isInteger,this.activeBufferIndex=0,this.baseId=e.id}get id(){return`${this.baseId}|${this.activeBufferIndex}`}get bufferGPU(){return this.buffers[this.activeBufferIndex]}get transformBuffer(){return this.buffers[1^this.activeBufferIndex]}switchBuffers(){this.activeBufferIndex^=1}}class k_{constructor(e){this.backend=e}createAttribute(e,t){const r=this.backend,{gl:s}=r,i=e.array,n=e.usage||s.STATIC_DRAW,o=e.isInterleavedBufferAttribute?e.data:e,a=r.get(o);let u,l=a.bufferGPU;if(void 0===l&&(l=this._createBuffer(s,t,i,n),a.bufferGPU=l,a.bufferType=t,a.version=o.version),i instanceof Float32Array)u=s.FLOAT;else if(i instanceof Uint16Array)u=e.isFloat16BufferAttribute?s.HALF_FLOAT:s.UNSIGNED_SHORT;else if(i instanceof Int16Array)u=s.SHORT;else if(i instanceof Uint32Array)u=s.UNSIGNED_INT;else if(i instanceof Int32Array)u=s.INT;else if(i instanceof Int8Array)u=s.BYTE;else if(i instanceof Uint8Array)u=s.UNSIGNED_BYTE;else{if(!(i instanceof Uint8ClampedArray))throw new Error("THREE.WebGLBackend: Unsupported buffer data format: "+i);u=s.UNSIGNED_BYTE}let d={bufferGPU:l,bufferType:t,type:u,byteLength:i.byteLength,bytesPerElement:i.BYTES_PER_ELEMENT,version:e.version,pbo:e.pbo,isInteger:u===s.INT||u===s.UNSIGNED_INT||e.gpuType===x,id:O_++};if(e.isStorageBufferAttribute||e.isStorageInstancedBufferAttribute){const e=this._createBuffer(s,t,i,n);d=new G_(d,e)}r.set(e,d)}updateAttribute(e){const t=this.backend,{gl:r}=t,s=e.array,i=e.isInterleavedBufferAttribute?e.data:e,n=t.get(i),o=n.bufferType,a=e.isInterleavedBufferAttribute?e.data.updateRanges:e.updateRanges;if(r.bindBuffer(o,n.bufferGPU),0===a.length)r.bufferSubData(o,0,s);else{for(let e=0,t=a.length;e1?this.enable(s.SAMPLE_ALPHA_TO_COVERAGE):this.disable(s.SAMPLE_ALPHA_TO_COVERAGE),r>0&&this.currentClippingPlanes!==r){const e=12288;for(let t=0;t<8;t++)t{!function i(){const n=e.clientWaitSync(t,e.SYNC_FLUSH_COMMANDS_BIT,0);if(n===e.WAIT_FAILED)return e.deleteSync(t),void s();n!==e.TIMEOUT_EXPIRED?(e.deleteSync(t),r()):requestAnimationFrame(i)}()}))}}let q_,K_,X_,Y_=!1;class Q_{constructor(e){this.backend=e,this.gl=e.gl,this.extensions=e.extensions,this.defaultTextures={},!1===Y_&&(this._init(),Y_=!0)}_init(){const e=this.gl;q_={[cr]:e.REPEAT,[hr]:e.CLAMP_TO_EDGE,[pr]:e.MIRRORED_REPEAT},K_={[gr]:e.NEAREST,[mr]:e.NEAREST_MIPMAP_NEAREST,[De]:e.NEAREST_MIPMAP_LINEAR,[$]:e.LINEAR,[Ie]:e.LINEAR_MIPMAP_NEAREST,[M]:e.LINEAR_MIPMAP_LINEAR},X_={[fr]:e.NEVER,[yr]:e.ALWAYS,[Ce]:e.LESS,[br]:e.LEQUAL,[xr]:e.EQUAL,[Tr]:e.GEQUAL,[_r]:e.GREATER,[vr]:e.NOTEQUAL}}getGLTextureType(e){const{gl:t}=this;let r;return r=!0===e.isCubeTexture?t.TEXTURE_CUBE_MAP:!0===e.isDataArrayTexture||!0===e.isCompressedArrayTexture?t.TEXTURE_2D_ARRAY:!0===e.isData3DTexture?t.TEXTURE_3D:t.TEXTURE_2D,r}getInternalFormat(e,t,r,s,i=!1){const{gl:n,extensions:o}=this;if(null!==e){if(void 0!==n[e])return n[e];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+e+"'")}let a=t;return t===n.RED&&(r===n.FLOAT&&(a=n.R32F),r===n.HALF_FLOAT&&(a=n.R16F),r===n.UNSIGNED_BYTE&&(a=n.R8),r===n.UNSIGNED_SHORT&&(a=n.R16),r===n.UNSIGNED_INT&&(a=n.R32UI),r===n.BYTE&&(a=n.R8I),r===n.SHORT&&(a=n.R16I),r===n.INT&&(a=n.R32I)),t===n.RED_INTEGER&&(r===n.UNSIGNED_BYTE&&(a=n.R8UI),r===n.UNSIGNED_SHORT&&(a=n.R16UI),r===n.UNSIGNED_INT&&(a=n.R32UI),r===n.BYTE&&(a=n.R8I),r===n.SHORT&&(a=n.R16I),r===n.INT&&(a=n.R32I)),t===n.RG&&(r===n.FLOAT&&(a=n.RG32F),r===n.HALF_FLOAT&&(a=n.RG16F),r===n.UNSIGNED_BYTE&&(a=n.RG8),r===n.UNSIGNED_SHORT&&(a=n.RG16),r===n.UNSIGNED_INT&&(a=n.RG32UI),r===n.BYTE&&(a=n.RG8I),r===n.SHORT&&(a=n.RG16I),r===n.INT&&(a=n.RG32I)),t===n.RG_INTEGER&&(r===n.UNSIGNED_BYTE&&(a=n.RG8UI),r===n.UNSIGNED_SHORT&&(a=n.RG16UI),r===n.UNSIGNED_INT&&(a=n.RG32UI),r===n.BYTE&&(a=n.RG8I),r===n.SHORT&&(a=n.RG16I),r===n.INT&&(a=n.RG32I)),t===n.RGB&&(r===n.FLOAT&&(a=n.RGB32F),r===n.HALF_FLOAT&&(a=n.RGB16F),r===n.UNSIGNED_BYTE&&(a=n.RGB8),r===n.UNSIGNED_SHORT&&(a=n.RGB16),r===n.UNSIGNED_INT&&(a=n.RGB32UI),r===n.BYTE&&(a=n.RGB8I),r===n.SHORT&&(a=n.RGB16I),r===n.INT&&(a=n.RGB32I),r===n.UNSIGNED_BYTE&&(a=s===Oe&&!1===i?n.SRGB8:n.RGB8),r===n.UNSIGNED_SHORT_5_6_5&&(a=n.RGB565),r===n.UNSIGNED_SHORT_5_5_5_1&&(a=n.RGB5_A1),r===n.UNSIGNED_SHORT_4_4_4_4&&(a=n.RGB4),r===n.UNSIGNED_INT_5_9_9_9_REV&&(a=n.RGB9_E5)),t===n.RGB_INTEGER&&(r===n.UNSIGNED_BYTE&&(a=n.RGB8UI),r===n.UNSIGNED_SHORT&&(a=n.RGB16UI),r===n.UNSIGNED_INT&&(a=n.RGB32UI),r===n.BYTE&&(a=n.RGB8I),r===n.SHORT&&(a=n.RGB16I),r===n.INT&&(a=n.RGB32I)),t===n.RGBA&&(r===n.FLOAT&&(a=n.RGBA32F),r===n.HALF_FLOAT&&(a=n.RGBA16F),r===n.UNSIGNED_BYTE&&(a=n.RGBA8),r===n.UNSIGNED_SHORT&&(a=n.RGBA16),r===n.UNSIGNED_INT&&(a=n.RGBA32UI),r===n.BYTE&&(a=n.RGBA8I),r===n.SHORT&&(a=n.RGBA16I),r===n.INT&&(a=n.RGBA32I),r===n.UNSIGNED_BYTE&&(a=s===Oe&&!1===i?n.SRGB8_ALPHA8:n.RGBA8),r===n.UNSIGNED_SHORT_4_4_4_4&&(a=n.RGBA4),r===n.UNSIGNED_SHORT_5_5_5_1&&(a=n.RGB5_A1)),t===n.RGBA_INTEGER&&(r===n.UNSIGNED_BYTE&&(a=n.RGBA8UI),r===n.UNSIGNED_SHORT&&(a=n.RGBA16UI),r===n.UNSIGNED_INT&&(a=n.RGBA32UI),r===n.BYTE&&(a=n.RGBA8I),r===n.SHORT&&(a=n.RGBA16I),r===n.INT&&(a=n.RGBA32I)),t===n.DEPTH_COMPONENT&&(r===n.UNSIGNED_INT&&(a=n.DEPTH24_STENCIL8),r===n.FLOAT&&(a=n.DEPTH_COMPONENT32F)),t===n.DEPTH_STENCIL&&r===n.UNSIGNED_INT_24_8&&(a=n.DEPTH24_STENCIL8),a!==n.R16F&&a!==n.R32F&&a!==n.RG16F&&a!==n.RG32F&&a!==n.RGBA16F&&a!==n.RGBA32F||o.get("EXT_color_buffer_float"),a}setTextureParameters(e,t){const{gl:r,extensions:s,backend:i}=this;r.pixelStorei(r.UNPACK_FLIP_Y_WEBGL,t.flipY),r.pixelStorei(r.UNPACK_PREMULTIPLY_ALPHA_WEBGL,t.premultiplyAlpha),r.pixelStorei(r.UNPACK_ALIGNMENT,t.unpackAlignment),r.pixelStorei(r.UNPACK_COLORSPACE_CONVERSION_WEBGL,r.NONE),r.texParameteri(e,r.TEXTURE_WRAP_S,q_[t.wrapS]),r.texParameteri(e,r.TEXTURE_WRAP_T,q_[t.wrapT]),e!==r.TEXTURE_3D&&e!==r.TEXTURE_2D_ARRAY||r.texParameteri(e,r.TEXTURE_WRAP_R,q_[t.wrapR]),r.texParameteri(e,r.TEXTURE_MAG_FILTER,K_[t.magFilter]);const n=void 0!==t.mipmaps&&t.mipmaps.length>0,o=t.minFilter===$&&n?M:t.minFilter;if(r.texParameteri(e,r.TEXTURE_MIN_FILTER,K_[o]),t.compareFunction&&(r.texParameteri(e,r.TEXTURE_COMPARE_MODE,r.COMPARE_REF_TO_TEXTURE),r.texParameteri(e,r.TEXTURE_COMPARE_FUNC,X_[t.compareFunction])),!0===s.has("EXT_texture_filter_anisotropic")){if(t.magFilter===gr)return;if(t.minFilter!==De&&t.minFilter!==M)return;if(t.type===E&&!1===s.has("OES_texture_float_linear"))return;if(t.anisotropy>1){const n=s.get("EXT_texture_filter_anisotropic");r.texParameterf(e,n.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(t.anisotropy,i.getMaxAnisotropy()))}}}createDefaultTexture(e){const{gl:t,backend:r,defaultTextures:s}=this,i=this.getGLTextureType(e);let n=s[i];void 0===n&&(n=t.createTexture(),r.state.bindTexture(i,n),t.texParameteri(i,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(i,t.TEXTURE_MAG_FILTER,t.NEAREST),s[i]=n),r.set(e,{textureGPU:n,glTextureType:i,isDefault:!0})}createTexture(e,t){const{gl:r,backend:s}=this,{levels:i,width:n,height:o,depth:a}=t,u=s.utils.convert(e.format,e.colorSpace),l=s.utils.convert(e.type),d=this.getInternalFormat(e.internalFormat,u,l,e.colorSpace,e.isVideoTexture),c=r.createTexture(),h=this.getGLTextureType(e);s.state.bindTexture(h,c),this.setTextureParameters(h,e),e.isDataArrayTexture||e.isCompressedArrayTexture?r.texStorage3D(r.TEXTURE_2D_ARRAY,i,d,n,o,a):e.isData3DTexture?r.texStorage3D(r.TEXTURE_3D,i,d,n,o,a):e.isVideoTexture||r.texStorage2D(h,i,d,n,o),s.set(e,{textureGPU:c,glTextureType:h,glFormat:u,glType:l,glInternalFormat:d})}copyBufferToTexture(e,t){const{gl:r,backend:s}=this,{textureGPU:i,glTextureType:n,glFormat:o,glType:a}=s.get(t),{width:u,height:l}=t.source.data;r.bindBuffer(r.PIXEL_UNPACK_BUFFER,e),s.state.bindTexture(n,i),r.pixelStorei(r.UNPACK_FLIP_Y_WEBGL,!1),r.pixelStorei(r.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),r.texSubImage2D(n,0,0,0,u,l,o,a,0),r.bindBuffer(r.PIXEL_UNPACK_BUFFER,null),s.state.unbindTexture()}updateTexture(e,t){const{gl:r}=this,{width:s,height:i}=t,{textureGPU:n,glTextureType:o,glFormat:a,glType:u,glInternalFormat:l}=this.backend.get(e);if(e.isRenderTargetTexture||void 0===n)return;const d=e=>e.isDataTexture?e.image.data:"undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&e instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap||e instanceof OffscreenCanvas?e:e.data;if(this.backend.state.bindTexture(o,n),this.setTextureParameters(o,e),e.isCompressedTexture){const s=e.mipmaps,i=t.image;for(let t=0;t0,c=t.renderTarget?t.renderTarget.height:this.backend.getDrawingBufferSize().y;if(d){const r=0!==o||0!==a;let d,h;if(!0===e.isDepthTexture?(d=s.DEPTH_BUFFER_BIT,h=s.DEPTH_ATTACHMENT,t.stencil&&(d|=s.STENCIL_BUFFER_BIT)):(d=s.COLOR_BUFFER_BIT,h=s.COLOR_ATTACHMENT0),r){const e=this.backend.get(t.renderTarget),r=e.framebuffers[t.getCacheKey()],h=e.msaaFrameBuffer;i.bindFramebuffer(s.DRAW_FRAMEBUFFER,r),i.bindFramebuffer(s.READ_FRAMEBUFFER,h);const p=c-a-l;s.blitFramebuffer(o,p,o+u,p+l,o,p,o+u,p+l,d,s.NEAREST),i.bindFramebuffer(s.READ_FRAMEBUFFER,r),i.bindTexture(s.TEXTURE_2D,n),s.copyTexSubImage2D(s.TEXTURE_2D,0,0,0,o,p,u,l),i.unbindTexture()}else{const e=s.createFramebuffer();i.bindFramebuffer(s.DRAW_FRAMEBUFFER,e),s.framebufferTexture2D(s.DRAW_FRAMEBUFFER,h,s.TEXTURE_2D,n,0),s.blitFramebuffer(0,0,u,l,0,0,u,l,d,s.NEAREST),s.deleteFramebuffer(e)}}else i.bindTexture(s.TEXTURE_2D,n),s.copyTexSubImage2D(s.TEXTURE_2D,0,0,0,o,c-l-a,u,l),i.unbindTexture();e.generateMipmaps&&this.generateMipmaps(e),this.backend._setFramebuffer(t)}setupRenderBufferStorage(e,t){const{gl:r}=this,s=t.renderTarget,{samples:i,depthTexture:n,depthBuffer:o,stencilBuffer:a,width:u,height:l}=s;if(r.bindRenderbuffer(r.RENDERBUFFER,e),o&&!a){let t=r.DEPTH_COMPONENT24;i>0?(n&&n.isDepthTexture&&n.type===r.FLOAT&&(t=r.DEPTH_COMPONENT32F),r.renderbufferStorageMultisample(r.RENDERBUFFER,i,t,u,l)):r.renderbufferStorage(r.RENDERBUFFER,t,u,l),r.framebufferRenderbuffer(r.FRAMEBUFFER,r.DEPTH_ATTACHMENT,r.RENDERBUFFER,e)}else o&&a&&(i>0?r.renderbufferStorageMultisample(r.RENDERBUFFER,i,r.DEPTH24_STENCIL8,u,l):r.renderbufferStorage(r.RENDERBUFFER,r.DEPTH_STENCIL,u,l),r.framebufferRenderbuffer(r.FRAMEBUFFER,r.DEPTH_STENCIL_ATTACHMENT,r.RENDERBUFFER,e))}async copyTextureToBuffer(e,t,r,s,i,n){const{backend:o,gl:a}=this,{textureGPU:u,glFormat:l,glType:d}=this.backend.get(e),c=a.createFramebuffer();a.bindFramebuffer(a.READ_FRAMEBUFFER,c);const h=e.isCubeTexture?a.TEXTURE_CUBE_MAP_POSITIVE_X+n:a.TEXTURE_2D;a.framebufferTexture2D(a.READ_FRAMEBUFFER,a.COLOR_ATTACHMENT0,h,u,0);const p=this._getTypedArrayType(d),g=s*i*this._getBytesPerTexel(d,l),m=a.createBuffer();a.bindBuffer(a.PIXEL_PACK_BUFFER,m),a.bufferData(a.PIXEL_PACK_BUFFER,g,a.STREAM_READ),a.readPixels(t,r,s,i,l,d,0),a.bindBuffer(a.PIXEL_PACK_BUFFER,null),await o.utils._clientWaitAsync();const f=new p(g/p.BYTES_PER_ELEMENT);return a.bindBuffer(a.PIXEL_PACK_BUFFER,m),a.getBufferSubData(a.PIXEL_PACK_BUFFER,0,f),a.bindBuffer(a.PIXEL_PACK_BUFFER,null),a.deleteFramebuffer(c),f}_getTypedArrayType(e){const{gl:t}=this;if(e===t.UNSIGNED_BYTE)return Uint8Array;if(e===t.UNSIGNED_SHORT_4_4_4_4)return Uint16Array;if(e===t.UNSIGNED_SHORT_5_5_5_1)return Uint16Array;if(e===t.UNSIGNED_SHORT_5_6_5)return Uint16Array;if(e===t.UNSIGNED_SHORT)return Uint16Array;if(e===t.UNSIGNED_INT)return Uint32Array;if(e===t.HALF_FLOAT)return Uint16Array;if(e===t.FLOAT)return Float32Array;throw new Error(`Unsupported WebGL type: ${e}`)}_getBytesPerTexel(e,t){const{gl:r}=this;let s=0;return e===r.UNSIGNED_BYTE&&(s=1),e!==r.UNSIGNED_SHORT_4_4_4_4&&e!==r.UNSIGNED_SHORT_5_5_5_1&&e!==r.UNSIGNED_SHORT_5_6_5&&e!==r.UNSIGNED_SHORT&&e!==r.HALF_FLOAT||(s=2),e!==r.UNSIGNED_INT&&e!==r.FLOAT||(s=4),t===r.RGBA?4*s:t===r.RGB?3*s:t===r.ALPHA?s:void 0}}class Z_{constructor(e){this.backend=e,this.gl=this.backend.gl,this.availableExtensions=this.gl.getSupportedExtensions(),this.extensions={}}get(e){let t=this.extensions[e];return void 0===t&&(t=this.gl.getExtension(e),this.extensions[e]=t),t}has(e){return this.availableExtensions.includes(e)}}class J_{constructor(e){this.backend=e,this.maxAnisotropy=null}getMaxAnisotropy(){if(null!==this.maxAnisotropy)return this.maxAnisotropy;const e=this.backend.gl,t=this.backend.extensions;if(!0===t.has("EXT_texture_filter_anisotropic")){const r=t.get("EXT_texture_filter_anisotropic");this.maxAnisotropy=e.getParameter(r.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else this.maxAnisotropy=0;return this.maxAnisotropy}}const ev={WEBGL_multi_draw:"WEBGL_multi_draw",WEBGL_compressed_texture_astc:"texture-compression-astc",WEBGL_compressed_texture_etc:"texture-compression-etc2",WEBGL_compressed_texture_etc1:"texture-compression-etc1",WEBGL_compressed_texture_pvrtc:"texture-compression-pvrtc",WEBKIT_WEBGL_compressed_texture_pvrtc:"texture-compression-pvrtc",WEBGL_compressed_texture_s3tc:"texture-compression-bc",EXT_texture_compression_bptc:"texture-compression-bptc",EXT_disjoint_timer_query_webgl2:"timestamp-query"};class tv{constructor(e){this.gl=e.gl,this.extensions=e.extensions,this.info=e.renderer.info,this.mode=null,this.index=0,this.type=null,this.object=null}render(e,t){const{gl:r,mode:s,object:i,type:n,info:o,index:a}=this;0!==a?r.drawElements(s,t,n,e):r.drawArrays(s,e,t),o.update(i,t,s,1)}renderInstances(e,t,r){const{gl:s,mode:i,type:n,index:o,object:a,info:u}=this;0!==r&&(0!==o?s.drawElementsInstanced(i,t,n,e,r):s.drawArraysInstanced(i,e,t,r),u.update(a,t,i,r))}renderMultiDraw(e,t,r){const{extensions:s,mode:i,object:n,info:o}=this;if(0===r)return;const a=s.get("WEBGL_multi_draw");if(null===a)for(let s=0;s0)){const e=t.queryQueue.shift();this.initTimestampQuery(e)}}async resolveTimestampAsync(e,t="render"){if(!this.disjoint||!this.trackTimestamp)return;const r=this.get(e);r.gpuQueries||(r.gpuQueries=[]);for(let e=0;e0&&(r.currentOcclusionQueries=r.occlusionQueries,r.currentOcclusionQueryObjects=r.occlusionQueryObjects,r.lastOcclusionObject=null,r.occlusionQueries=new Array(s),r.occlusionQueryObjects=new Array(s),r.occlusionQueryIndex=0)}finishRender(e){const{gl:t,state:r}=this,s=this.get(e),i=s.previousContext,n=e.occlusionQueryCount;n>0&&(n>s.occlusionQueryIndex&&t.endQuery(t.ANY_SAMPLES_PASSED),this.resolveOccludedAsync(e));const o=e.textures;if(null!==o)for(let e=0;e0){const i=s.framebuffers[e.getCacheKey()],n=t.COLOR_BUFFER_BIT,o=s.msaaFrameBuffer,a=e.textures;r.bindFramebuffer(t.READ_FRAMEBUFFER,o),r.bindFramebuffer(t.DRAW_FRAMEBUFFER,i);for(let r=0;r{let o=0;for(let t=0;t0&&e.add(s[t]),r[t]=null,i.deleteQuery(n),o++))}o1?f.renderInstances(x,y,b):f.render(x,y),a.bindVertexArray(null)}needsRenderUpdate(){return!1}getRenderCacheKey(){return""}createDefaultTexture(e){this.textureUtils.createDefaultTexture(e)}createTexture(e,t){this.textureUtils.createTexture(e,t)}updateTexture(e,t){this.textureUtils.updateTexture(e,t)}generateMipmaps(e){this.textureUtils.generateMipmaps(e)}destroyTexture(e){this.textureUtils.destroyTexture(e)}async copyTextureToBuffer(e,t,r,s,i,n){return this.textureUtils.copyTextureToBuffer(e,t,r,s,i,n)}createSampler(){}destroySampler(){}createNodeBuilder(e,t){return new I_(e,t)}createProgram(e){const t=this.gl,{stage:r,code:s}=e,i="fragment"===r?t.createShader(t.FRAGMENT_SHADER):t.createShader(t.VERTEX_SHADER);t.shaderSource(i,s),t.compileShader(i),this.set(e,{shaderGPU:i})}destroyProgram(e){this.delete(e)}createRenderPipeline(e,t){const r=this.gl,s=e.pipeline,{fragmentProgram:i,vertexProgram:n}=s,o=r.createProgram(),a=this.get(i).shaderGPU,u=this.get(n).shaderGPU;if(r.attachShader(o,a),r.attachShader(o,u),r.linkProgram(o),this.set(s,{programGPU:o,fragmentShader:a,vertexShader:u}),null!==t&&this.parallel){const i=new Promise((t=>{const i=this.parallel,n=()=>{r.getProgramParameter(o,i.COMPLETION_STATUS_KHR)?(this._completeCompile(e,s),t()):requestAnimationFrame(n)};n()}));t.push(i)}else this._completeCompile(e,s)}_handleSource(e,t){const r=e.split("\n"),s=[],i=Math.max(t-6,0),n=Math.min(t+6,r.length);for(let e=i;e":" "} ${i}: ${r[e]}`)}return s.join("\n")}_getShaderErrors(e,t,r){const s=e.getShaderParameter(t,e.COMPILE_STATUS),i=e.getShaderInfoLog(t).trim();if(s&&""===i)return"";const n=/ERROR: 0:(\d+)/.exec(i);if(n){const s=parseInt(n[1]);return r.toUpperCase()+"\n\n"+i+"\n\n"+this._handleSource(e.getShaderSource(t),s)}return i}_logProgramError(e,t,r){if(this.renderer.debug.checkShaderErrors){const s=this.gl,i=s.getProgramInfoLog(e).trim();if(!1===s.getProgramParameter(e,s.LINK_STATUS))if("function"==typeof this.renderer.debug.onShaderError)this.renderer.debug.onShaderError(s,e,r,t);else{const n=this._getShaderErrors(s,r,"vertex"),o=this._getShaderErrors(s,t,"fragment");console.error("THREE.WebGLProgram: Shader Error "+s.getError()+" - VALIDATE_STATUS "+s.getProgramParameter(e,s.VALIDATE_STATUS)+"\n\nProgram Info Log: "+i+"\n"+n+"\n"+o)}else""!==i&&console.warn("THREE.WebGLProgram: Program Info Log:",i)}}_completeCompile(e,t){const{state:r,gl:s}=this,i=this.get(t),{programGPU:n,fragmentShader:o,vertexShader:a}=i;!1===s.getProgramParameter(n,s.LINK_STATUS)&&this._logProgramError(n,o,a),r.useProgram(n);const u=e.getBindings();this._setupBindings(u,n),this.set(t,{programGPU:n})}createComputePipeline(e,t){const{state:r,gl:s}=this,i={stage:"fragment",code:"#version 300 es\nprecision highp float;\nvoid main() {}"};this.createProgram(i);const{computeProgram:n}=e,o=s.createProgram(),a=this.get(i).shaderGPU,u=this.get(n).shaderGPU,l=n.transforms,d=[],c=[];for(let e=0;eev[t]===e)),r=this.extensions;for(let e=0;e0){if(void 0===h){const s=[];h=t.createFramebuffer(),r.bindFramebuffer(t.FRAMEBUFFER,h);const i=[],l=e.textures;for(let r=0;r,\n\t@location( 0 ) vTex : vec2\n};\n\n@vertex\nfn main( @builtin( vertex_index ) vertexIndex : u32 ) -> VarysStruct {\n\n\tvar Varys : VarysStruct;\n\n\tvar pos = array< vec2, 4 >(\n\t\tvec2( -1.0, 1.0 ),\n\t\tvec2( 1.0, 1.0 ),\n\t\tvec2( -1.0, -1.0 ),\n\t\tvec2( 1.0, -1.0 )\n\t);\n\n\tvar tex = array< vec2, 4 >(\n\t\tvec2( 0.0, 0.0 ),\n\t\tvec2( 1.0, 0.0 ),\n\t\tvec2( 0.0, 1.0 ),\n\t\tvec2( 1.0, 1.0 )\n\t);\n\n\tVarys.vTex = tex[ vertexIndex ];\n\tVarys.Position = vec4( pos[ vertexIndex ], 0.0, 1.0 );\n\n\treturn Varys;\n\n}\n"}),this.mipmapFragmentShaderModule=e.createShaderModule({label:"mipmapFragment",code:"\n@group( 0 ) @binding( 0 )\nvar imgSampler : sampler;\n\n@group( 0 ) @binding( 1 )\nvar img : texture_2d;\n\n@fragment\nfn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 {\n\n\treturn textureSample( img, imgSampler, vTex );\n\n}\n"}),this.flipYFragmentShaderModule=e.createShaderModule({label:"flipYFragment",code:"\n@group( 0 ) @binding( 0 )\nvar imgSampler : sampler;\n\n@group( 0 ) @binding( 1 )\nvar img : texture_2d;\n\n@fragment\nfn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 {\n\n\treturn textureSample( img, imgSampler, vec2( vTex.x, 1.0 - vTex.y ) );\n\n}\n"})}getTransferPipeline(e){let t=this.transferPipelines[e];return void 0===t&&(t=this.device.createRenderPipeline({label:`mipmap-${e}`,vertex:{module:this.mipmapVertexShaderModule,entryPoint:"main"},fragment:{module:this.mipmapFragmentShaderModule,entryPoint:"main",targets:[{format:e}]},primitive:{topology:av,stripIndexFormat:Sv},layout:"auto"}),this.transferPipelines[e]=t),t}getFlipYPipeline(e){let t=this.flipYPipelines[e];return void 0===t&&(t=this.device.createRenderPipeline({label:`flipY-${e}`,vertex:{module:this.mipmapVertexShaderModule,entryPoint:"main"},fragment:{module:this.flipYFragmentShaderModule,entryPoint:"main",targets:[{format:e}]},primitive:{topology:av,stripIndexFormat:Sv},layout:"auto"}),this.flipYPipelines[e]=t),t}flipY(e,t,r=0){const s=t.format,{width:i,height:n}=t.size,o=this.getTransferPipeline(s),a=this.getFlipYPipeline(s),u=this.device.createTexture({size:{width:i,height:n,depthOrArrayLayers:1},format:s,usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.TEXTURE_BINDING}),l=e.createView({baseMipLevel:0,mipLevelCount:1,dimension:yN,baseArrayLayer:r}),d=u.createView({baseMipLevel:0,mipLevelCount:1,dimension:yN,baseArrayLayer:0}),c=this.device.createCommandEncoder({}),h=(e,t,r)=>{const s=e.getBindGroupLayout(0),i=this.device.createBindGroup({layout:s,entries:[{binding:0,resource:this.flipYSampler},{binding:1,resource:t}]}),n=c.beginRenderPass({colorAttachments:[{view:r,loadOp:bv,storeOp:fv,clearValue:[0,0,0,0]}]});n.setPipeline(e),n.setBindGroup(0,i),n.draw(4,1,0,0),n.end()};h(o,l,d),h(a,d,l),this.device.queue.submit([c.finish()]),u.destroy()}generateMipmaps(e,t,r=0){const s=this.get(e);void 0===s.useCount&&(s.useCount=0,s.layers=[]);const i=s.layers[r]||this._mipmapCreateBundles(e,t,r),n=this.device.createCommandEncoder({});this._mipmapRunBundles(n,i),this.device.queue.submit([n.finish()]),0!==s.useCount&&(s.layers[r]=i),s.useCount++}_mipmapCreateBundles(e,t,r){const s=this.getTransferPipeline(t.format),i=s.getBindGroupLayout(0);let n=e.createView({baseMipLevel:0,mipLevelCount:1,dimension:yN,baseArrayLayer:r});const o=[];for(let a=1;a1;for(let o=0;o]*\s*([a-z_0-9]+(?:<[\s\S]+?>)?)/i,DN=/([a-z_0-9]+)\s*:\s*([a-z_0-9]+(?:<[\s\S]+?>)?)/gi,LN={f32:"float",i32:"int",u32:"uint",bool:"bool","vec2":"vec2","vec2":"ivec2","vec2":"uvec2","vec2":"bvec2",vec2f:"vec2",vec2i:"ivec2",vec2u:"uvec2",vec2b:"bvec2","vec3":"vec3","vec3":"ivec3","vec3":"uvec3","vec3":"bvec3",vec3f:"vec3",vec3i:"ivec3",vec3u:"uvec3",vec3b:"bvec3","vec4":"vec4","vec4":"ivec4","vec4":"uvec4","vec4":"bvec4",vec4f:"vec4",vec4i:"ivec4",vec4u:"uvec4",vec4b:"bvec4","mat2x2":"mat2",mat2x2f:"mat2","mat3x3":"mat3",mat3x3f:"mat3","mat4x4":"mat4",mat4x4f:"mat4",sampler:"sampler",texture_1d:"texture",texture_2d:"texture",texture_2d_array:"texture",texture_multisampled_2d:"cubeTexture",texture_depth_2d:"depthTexture",texture_depth_multisampled_2d:"depthTexture",texture_3d:"texture3D",texture_cube:"cubeTexture",texture_cube_array:"cubeTexture",texture_storage_1d:"storageTexture",texture_storage_2d:"storageTexture",texture_storage_2d_array:"storageTexture",texture_storage_3d:"storageTexture"};class VN extends jT{constructor(e){const{type:t,inputs:r,name:s,inputsCode:i,blockCode:n,outputType:o}=(e=>{const t=(e=e.trim()).match(IN);if(null!==t&&4===t.length){const r=t[2],s=[];let i=null;for(;null!==(i=DN.exec(r));)s.push({name:i[1],type:i[2]});const n=[];for(let e=0;e "+this.outputType:"";return`fn ${e} ( ${this.inputsCode.trim()} ) ${t}`+this.blockCode}}class ON extends WT{parseFunction(e){return new VN(e)}}const GN="undefined"!=typeof self?self.GPUShaderStage:{VERTEX:1,FRAGMENT:2,COMPUTE:4},kN={[Es.READ_ONLY]:"read",[Es.WRITE_ONLY]:"write",[Es.READ_WRITE]:"read_write"},zN={[cr]:"repeat",[hr]:"clamp",[pr]:"mirror"},$N={vertex:GN?GN.VERTEX:1,fragment:GN?GN.FRAGMENT:2,compute:GN?GN.COMPUTE:4},HN={instance:!0,swizzleAssign:!1,storageBuffer:!0},WN={"^^":"tsl_xor"},jN={float:"f32",int:"i32",uint:"u32",bool:"bool",color:"vec3",vec2:"vec2",ivec2:"vec2",uvec2:"vec2",bvec2:"vec2",vec3:"vec3",ivec3:"vec3",uvec3:"vec3",bvec3:"vec3",vec4:"vec4",ivec4:"vec4",uvec4:"vec4",bvec4:"vec4",mat2:"mat2x2",mat3:"mat3x3",mat4:"mat4x4"},qN={},KN={tsl_xor:new my("fn tsl_xor( a : bool, b : bool ) -> bool { return ( a || b ) && !( a && b ); }"),mod_float:new my("fn tsl_mod_float( x : f32, y : f32 ) -> f32 { return x - y * floor( x / y ); }"),mod_vec2:new my("fn tsl_mod_vec2( x : vec2f, y : vec2f ) -> vec2f { return x - y * floor( x / y ); }"),mod_vec3:new my("fn tsl_mod_vec3( x : vec3f, y : vec3f ) -> vec3f { return x - y * floor( x / y ); }"),mod_vec4:new my("fn tsl_mod_vec4( x : vec4f, y : vec4f ) -> vec4f { return x - y * floor( x / y ); }"),equals_bool:new my("fn tsl_equals_bool( a : bool, b : bool ) -> bool { return a == b; }"),equals_bvec2:new my("fn tsl_equals_bvec2( a : vec2f, b : vec2f ) -> vec2 { return vec2( a.x == b.x, a.y == b.y ); }"),equals_bvec3:new my("fn tsl_equals_bvec3( a : vec3f, b : vec3f ) -> vec3 { return vec3( a.x == b.x, a.y == b.y, a.z == b.z ); }"),equals_bvec4:new my("fn tsl_equals_bvec4( a : vec4f, b : vec4f ) -> vec4 { return vec4( a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w ); }"),repeatWrapping_float:new my("fn tsl_repeatWrapping_float( coord: f32 ) -> f32 { return fract( coord ); }"),mirrorWrapping_float:new my("fn tsl_mirrorWrapping_float( coord: f32 ) -> f32 { let mirrored = fract( coord * 0.5 ) * 2.0; return 1.0 - abs( 1.0 - mirrored ); }"),clampWrapping_float:new my("fn tsl_clampWrapping_float( coord: f32 ) -> f32 { return clamp( coord, 0.0, 1.0 ); }"),biquadraticTexture:new my("\nfn tsl_biquadraticTexture( map : texture_2d, coord : vec2f, iRes : vec2u, level : u32 ) -> vec4f {\n\n\tlet res = vec2f( iRes );\n\n\tlet uvScaled = coord * res;\n\tlet uvWrapping = ( ( uvScaled % res ) + res ) % res;\n\n\t// https://www.shadertoy.com/view/WtyXRy\n\n\tlet uv = uvWrapping - 0.5;\n\tlet iuv = floor( uv );\n\tlet f = fract( uv );\n\n\tlet rg1 = textureLoad( map, vec2u( iuv + vec2( 0.5, 0.5 ) ) % iRes, level );\n\tlet rg2 = textureLoad( map, vec2u( iuv + vec2( 1.5, 0.5 ) ) % iRes, level );\n\tlet rg3 = textureLoad( map, vec2u( iuv + vec2( 0.5, 1.5 ) ) % iRes, level );\n\tlet rg4 = textureLoad( map, vec2u( iuv + vec2( 1.5, 1.5 ) ) % iRes, level );\n\n\treturn mix( mix( rg1, rg2, f.x ), mix( rg3, rg4, f.x ), f.y );\n\n}\n")},XN={dFdx:"dpdx",dFdy:"- dpdy",mod_float:"tsl_mod_float",mod_vec2:"tsl_mod_vec2",mod_vec3:"tsl_mod_vec3",mod_vec4:"tsl_mod_vec4",equals_bool:"tsl_equals_bool",equals_bvec2:"tsl_equals_bvec2",equals_bvec3:"tsl_equals_bvec3",equals_bvec4:"tsl_equals_bvec4",inversesqrt:"inverseSqrt",bitcast:"bitcast"};"undefined"!=typeof navigator&&/Windows/g.test(navigator.userAgent)&&(KN.pow_float=new my("fn tsl_pow_float( a : f32, b : f32 ) -> f32 { return select( -pow( -a, b ), pow( a, b ), a > 0.0 ); }"),KN.pow_vec2=new my("fn tsl_pow_vec2( a : vec2f, b : vec2f ) -> vec2f { return vec2f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ) ); }",[KN.pow_float]),KN.pow_vec3=new my("fn tsl_pow_vec3( a : vec3f, b : vec3f ) -> vec3f { return vec3f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ), tsl_pow_float( a.z, b.z ) ); }",[KN.pow_float]),KN.pow_vec4=new my("fn tsl_pow_vec4( a : vec4f, b : vec4f ) -> vec4f { return vec4f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ), tsl_pow_float( a.z, b.z ), tsl_pow_float( a.w, b.w ) ); }",[KN.pow_float]),XN.pow_float="tsl_pow_float",XN.pow_vec2="tsl_pow_vec2",XN.pow_vec3="tsl_pow_vec3",XN.pow_vec4="tsl_pow_vec4");let YN="";!0!==("undefined"!=typeof navigator&&/Firefox|Deno/g.test(navigator.userAgent))&&(YN+="diagnostic( off, derivative_uniformity );\n");class QN extends FT{constructor(e,t){super(e,t,new ON),this.uniformGroups={},this.builtins={},this.directives={},this.scopedArrays=new Map}needsToWorkingColorSpace(e){return!0===e.isVideoTexture&&e.colorSpace!==y}_generateTextureSample(e,t,r,s,i=this.shaderStage){return"fragment"===i?s?`textureSample( ${t}, ${t}_sampler, ${r}, ${s} )`:`textureSample( ${t}, ${t}_sampler, ${r} )`:this.isFilteredTexture(e)?this.generateFilteredTexture(e,t,r):this.generateTextureLod(e,t,r,s,"0")}_generateVideoSample(e,t,r=this.shaderStage){if("fragment"===r)return`textureSampleBaseClampToEdge( ${e}, ${e}_sampler, vec2( ${t}.x, 1.0 - ${t}.y ) )`;console.error(`WebGPURenderer: THREE.VideoTexture does not support ${r} shader.`)}_generateTextureSampleLevel(e,t,r,s,i,n=this.shaderStage){return"fragment"!==n&&"compute"!==n||!1!==this.isUnfilterable(e)?this.isFilteredTexture(e)?this.generateFilteredTexture(e,t,r,s):this.generateTextureLod(e,t,r,i,s):`textureSampleLevel( ${t}, ${t}_sampler, ${r}, ${s} )`}generateWrapFunction(e){const t=`tsl_coord_${zN[e.wrapS]}S_${zN[e.wrapT]}_${e.isData3DTexture?"3d":"2d"}T`;let r=qN[t];if(void 0===r){const s=[],i=e.isData3DTexture?"vec3f":"vec2f";let n=`fn ${t}( coord : ${i} ) -> ${i} {\n\n\treturn ${i}(\n`;const o=(e,t)=>{e===cr?(s.push(KN.repeatWrapping_float),n+=`\t\ttsl_repeatWrapping_float( coord.${t} )`):e===hr?(s.push(KN.clampWrapping_float),n+=`\t\ttsl_clampWrapping_float( coord.${t} )`):e===pr?(s.push(KN.mirrorWrapping_float),n+=`\t\ttsl_mirrorWrapping_float( coord.${t} )`):(n+=`\t\tcoord.${t}`,console.warn(`WebGPURenderer: Unsupported texture wrap type "${e}" for vertex shader.`))};o(e.wrapS,"x"),n+=",\n",o(e.wrapT,"y"),e.isData3DTexture&&(n+=",\n",o(e.wrapR,"z")),n+="\n\t);\n\n}\n",qN[t]=r=new my(n,s)}return r.build(this),t}generateTextureDimension(e,t,r){const s=this.getDataFromNode(e,this.shaderStage,this.globalCache);void 0===s.dimensionsSnippet&&(s.dimensionsSnippet={});let i=s.dimensionsSnippet[r];if(void 0===s.dimensionsSnippet[r]){let n,o;const{primarySamples:a}=this.renderer.backend.utils.getTextureSampleData(e),u=a>1;o=e.isData3DTexture?"vec3":"vec2",n=u||e.isVideoTexture||e.isStorageTexture?t:`${t}${r?`, u32( ${r} )`:""}`,i=new Ba(new pu(`textureDimensions( ${n} )`,o)),s.dimensionsSnippet[r]=i,(e.isDataArrayTexture||e.isData3DTexture)&&(s.arrayLayerCount=new Ba(new pu(`textureNumLayers(${t})`,"u32"))),e.isTextureCube&&(s.cubeFaceCount=new Ba(new pu("6u","u32")))}return i.build(this)}generateFilteredTexture(e,t,r,s="0u"){this._include("biquadraticTexture");return`tsl_biquadraticTexture( ${t}, ${this.generateWrapFunction(e)}( ${r} ), ${this.generateTextureDimension(e,t,s)}, u32( ${s} ) )`}generateTextureLod(e,t,r,s,i="0u"){const n=this.generateWrapFunction(e),o=this.generateTextureDimension(e,t,i),a=e.isData3DTexture?"vec3":"vec2",u=`${a}(${n}(${r}) * ${a}(${o}))`;return this.generateTextureLoad(e,t,u,s,i)}generateTextureLoad(e,t,r,s,i="0u"){return!0===e.isVideoTexture||!0===e.isStorageTexture?`textureLoad( ${t}, ${r} )`:s?`textureLoad( ${t}, ${r}, ${s}, u32( ${i} ) )`:`textureLoad( ${t}, ${r}, u32( ${i} ) )`}generateTextureStore(e,t,r,s){return`textureStore( ${t}, ${r}, ${s} )`}isSampleCompare(e){return!0===e.isDepthTexture&&null!==e.compareFunction}isUnfilterable(e){return"float"!==this.getComponentTypeFromTexture(e)||!this.isAvailable("float32Filterable")&&!0===e.isDataTexture&&e.type===E||!1===this.isSampleCompare(e)&&e.minFilter===gr&&e.magFilter===gr||this.renderer.backend.utils.getTextureSampleData(e).primarySamples>1}generateTexture(e,t,r,s,i=this.shaderStage){let n=null;return n=!0===e.isVideoTexture?this._generateVideoSample(t,r,i):this.isUnfilterable(e)?this.generateTextureLod(e,t,r,s,"0",i):this._generateTextureSample(e,t,r,s,i),n}generateTextureGrad(e,t,r,s,i,n=this.shaderStage){if("fragment"===n)return`textureSampleGrad( ${t}, ${t}_sampler, ${r}, ${s[0]}, ${s[1]} )`;console.error(`WebGPURenderer: THREE.TextureNode.gradient() does not support ${n} shader.`)}generateTextureCompare(e,t,r,s,i,n=this.shaderStage){if("fragment"===n)return`textureSampleCompare( ${t}, ${t}_sampler, ${r}, ${s} )`;console.error(`WebGPURenderer: THREE.DepthTexture.compareFunction() does not support ${n} shader.`)}generateTextureLevel(e,t,r,s,i,n=this.shaderStage){let o=null;return o=!0===e.isVideoTexture?this._generateVideoSample(t,r,n):this._generateTextureSampleLevel(e,t,r,s,i,n),o}generateTextureBias(e,t,r,s,i,n=this.shaderStage){if("fragment"===n)return`textureSampleBias( ${t}, ${t}_sampler, ${r}, ${s} )`;console.error(`WebGPURenderer: THREE.TextureNode.biasNode does not support ${n} shader.`)}getPropertyName(e,t=this.shaderStage){if(!0===e.isNodeVarying&&!0===e.needsInterpolation){if("vertex"===t)return`varyings.${e.name}`}else if(!0===e.isNodeUniform){const t=e.name,r=e.type;return"texture"===r||"cubeTexture"===r||"storageTexture"===r||"texture3D"===r?t:"buffer"===r||"storageBuffer"===r||"indirectStorageBuffer"===r?`NodeBuffer_${e.id}.${t}`:e.groupNode.name+"."+t}return super.getPropertyName(e)}getOutputStructName(){return"output"}_getUniformGroupCount(e){return Object.keys(this.uniforms[e]).length}getFunctionOperator(e){const t=WN[e];return void 0!==t?(this._include(t),t):null}getNodeAccess(e,t){return"compute"!==t?Es.READ_ONLY:e.access}getStorageAccess(e,t){return kN[this.getNodeAccess(e,t)]}getUniformFromNode(e,t,r,s=null){const i=super.getUniformFromNode(e,t,r,s),n=this.getDataFromNode(e,r,this.globalCache);if(void 0===n.uniformGPU){let s;const o=e.groupNode,a=o.name,u=this.getBindGroupArray(a,r);if("texture"===t||"cubeTexture"===t||"storageTexture"===t||"texture3D"===t){let n=null;const a=this.getNodeAccess(e,r);if("texture"===t||"storageTexture"===t?n=new E_(i.name,i.node,o,a):"cubeTexture"===t?n=new w_(i.name,i.node,o,a):"texture3D"===t&&(n=new M_(i.name,i.node,o,a)),n.store=!0===e.isStorageTextureNode,n.setVisibility($N[r]),"fragment"!==r&&"compute"!==r||!1!==this.isUnfilterable(e.value)||!1!==n.store)u.push(n),s=[n];else{const e=new RN(`${i.name}_sampler`,i.node,o);e.setVisibility($N[r]),u.push(e,n),s=[e,n]}}else if("buffer"===t||"storageBuffer"===t||"indirectStorageBuffer"===t){const i=new("buffer"===t?v_:wN)(e,o);i.setVisibility($N[r]),u.push(i),s=i}else{const e=this.uniformGroups[r]||(this.uniformGroups[r]={});let n=e[a];void 0===n&&(n=new A_(a,o),n.setVisibility($N[r]),e[a]=n,u.push(n)),s=this.getNodeUniform(i,t),n.addUniform(s)}n.uniformGPU=s}return i}getBuiltin(e,t,r,s=this.shaderStage){const i=this.builtins[s]||(this.builtins[s]=new Map);return!1===i.has(e)&&i.set(e,{name:e,property:t,type:r}),t}hasBuiltin(e,t=this.shaderStage){return void 0!==this.builtins[t]&&this.builtins[t].has(e)}getVertexIndex(){return"vertex"===this.shaderStage?this.getBuiltin("vertex_index","vertexIndex","u32","attribute"):"vertexIndex"}buildFunctionCode(e){const t=e.layout,r=this.flowShaderNode(e),s=[];for(const e of t.inputs)s.push(e.name+" : "+this.getType(e.type));let i=`fn ${t.name}( ${s.join(", ")} ) -> ${this.getType(t.type)} {\n${r.vars}\n${r.code}\n`;return r.result&&(i+=`\treturn ${r.result};\n`),i+="\n}\n",i}getInstanceIndex(){return"vertex"===this.shaderStage?this.getBuiltin("instance_index","instanceIndex","u32","attribute"):"instanceIndex"}getInvocationLocalIndex(){return this.getBuiltin("local_invocation_index","invocationLocalIndex","u32","attribute")}getSubgroupSize(){return this.enableSubGroups(),this.getBuiltin("subgroup_size","subgroupSize","u32","attribute")}getInvocationSubgroupIndex(){return this.enableSubGroups(),this.getBuiltin("subgroup_invocation_id","invocationSubgroupIndex","u32","attribute")}getSubgroupIndex(){return this.enableSubGroups(),this.getBuiltin("subgroup_id","subgroupIndex","u32","attribute")}getDrawIndex(){return null}getFrontFacing(){return this.getBuiltin("front_facing","isFront","bool")}getFragCoord(){return this.getBuiltin("position","fragCoord","vec4")+".xy"}getFragDepth(){return"output."+this.getBuiltin("frag_depth","depth","f32","output")}getClipDistance(){return"varyings.hw_clip_distances"}isFlipY(){return!1}enableDirective(e,t=this.shaderStage){(this.directives[t]||(this.directives[t]=new Set)).add(e)}getDirectives(e){const t=[],r=this.directives[e];if(void 0!==r)for(const e of r)t.push(`enable ${e};`);return t.join("\n")}enableSubGroups(){this.enableDirective("subgroups")}enableSubgroupsF16(){this.enableDirective("subgroups-f16")}enableClipDistances(){this.enableDirective("clip_distances")}enableShaderF16(){this.enableDirective("f16")}enableDualSourceBlending(){this.enableDirective("dual_source_blending")}enableHardwareClipping(e){this.enableClipDistances(),this.getBuiltin("clip_distances","hw_clip_distances",`array`,"vertex")}getBuiltins(e){const t=[],r=this.builtins[e];if(void 0!==r)for(const{name:e,property:s,type:i}of r.values())t.push(`@builtin( ${e} ) ${s} : ${i}`);return t.join(",\n\t")}getScopedArray(e,t,r,s){return!1===this.scopedArrays.has(e)&&this.scopedArrays.set(e,{name:e,scope:t,bufferType:r,bufferCount:s}),e}getScopedArrays(e){if("compute"!==e)return;const t=[];for(const{name:e,scope:r,bufferType:s,bufferCount:i}of this.scopedArrays.values()){const n=this.getType(s);t.push(`var<${r}> ${e}: array< ${n}, ${i} >;`)}return t.join("\n")}getAttributes(e){const t=[];if("compute"===e&&(this.getBuiltin("global_invocation_id","id","vec3","attribute"),this.getBuiltin("workgroup_id","workgroupId","vec3","attribute"),this.getBuiltin("local_invocation_id","localId","vec3","attribute"),this.getBuiltin("num_workgroups","numWorkgroups","vec3","attribute"),this.renderer.hasFeature("subgroups")&&(this.enableDirective("subgroups",e),this.getBuiltin("subgroup_size","subgroupSize","u32","attribute"))),"vertex"===e||"compute"===e){const e=this.getBuiltins("attribute");e&&t.push(e);const r=this.getAttributesArray();for(let e=0,s=r.length;e`)}const s=this.getBuiltins("output");return s&&t.push("\t"+s),t.join(",\n")}getStructs(e){const t=[],r=this.structs[e];for(let e=0,s=r.length;e output : ${i};\n\n`)}return t.join("\n\n")}getVar(e,t){return`var ${t} : ${this.getType(e)}`}getVars(e){const t=[],r=this.vars[e];if(void 0!==r)for(const e of r)t.push(`\t${this.getVar(e.type,e.name)};`);return`\n${t.join("\n")}\n`}getVaryings(e){const t=[];if("vertex"===e&&this.getBuiltin("position","Vertex","vec4","vertex"),"vertex"===e||"fragment"===e){const r=this.varyings,s=this.vars[e];for(let i=0;i1&&(n="_multisampled"),!0===t.isCubeTexture)s="texture_cube";else if(!0===t.isDataArrayTexture||!0===t.isCompressedArrayTexture)s="texture_2d_array";else if(!0===t.isDepthTexture)s=`texture_depth${n}_2d`;else if(!0===t.isVideoTexture)s="texture_external";else if(!0===t.isData3DTexture)s="texture_3d";else if(!0===i.node.isStorageTextureNode){s=`texture_storage_2d<${PN(t)}, ${this.getStorageAccess(i.node,e)}>`}else{s=`texture${n}_2d<${this.getComponentTypeFromTexture(t).charAt(0)}32>`}r.push(`@binding( ${o.binding++} ) @group( ${o.group} ) var ${i.name} : ${s};`)}else if("buffer"===i.type||"storageBuffer"===i.type||"indirectStorageBuffer"===i.type){const t=i.node,r=this.getType(t.bufferType),n=t.bufferCount,a=n>0&&"buffer"===i.type?", "+n:"",u=t.isAtomic?`atomic<${r}>`:`${r}`,l=`\t${i.name} : array< ${u}${a} >\n`,d=t.isStorageBufferNode?`storage, ${this.getStorageAccess(t,e)}`:"uniform";s.push(this._getWGSLStructBinding("NodeBuffer_"+t.id,l,d,o.binding++,o.group))}else{const e=this.getType(this.getVectorType(i.type)),t=i.groupNode.name;(n[t]||(n[t]={index:o.binding++,id:o.group,snippets:[]})).snippets.push(`\t${i.name} : ${e}`)}}for(const e in n){const t=n[e];i.push(this._getWGSLStructBinding(e,t.snippets.join(",\n"),"uniform",t.index,t.id))}let o=r.join("\n");return o+=s.join("\n"),o+=i.join("\n"),o}buildCode(){const e=null!==this.material?{fragment:{},vertex:{}}:{compute:{}};this.sortBindingGroups();for(const t in e){const r=e[t];r.uniforms=this.getUniforms(t),r.attributes=this.getAttributes(t),r.varyings=this.getVaryings(t),r.structs=this.getStructs(t),r.vars=this.getVars(t),r.codes=this.getCodes(t),r.directives=this.getDirectives(t),r.scopedArrays=this.getScopedArrays(t);let s="// code\n\n";s+=this.flowCode[t];const i=this.flowNodes[t],n=i[i.length-1],o=n.outputNode,a=void 0!==o&&!0===o.isOutputStructNode;for(const e of i){const i=this.getFlowData(e),u=e.name;if(u&&(s.length>0&&(s+="\n"),s+=`\t// flow -> ${u}\n\t`),s+=`${i.code}\n\t`,e===n&&"compute"!==t)if(s+="// result\n\n\t","vertex"===t)s+=`varyings.Vertex = ${i.result};`;else if("fragment"===t)if(a)r.returnType=o.nodeType,s+=`return ${i.result};`;else{let e="\t@location(0) color: vec4";const t=this.getBuiltins("output");t&&(e+=",\n\t"+t),r.returnType="OutputStruct",r.structs+=this._getWGSLStruct("OutputStruct",e),r.structs+="\nvar output : OutputStruct;\n\n",s+=`output.color = ${i.result};\n\n\treturn output;`}}r.flow=s}null!==this.material?(this.vertexShader=this._getWGSLVertexCode(e.vertex),this.fragmentShader=this._getWGSLFragmentCode(e.fragment)):this.computeShader=this._getWGSLComputeCode(e.compute,(this.object.workgroupSize||[64]).join(", "))}getMethod(e,t=null){let r;return null!==t&&(r=this._getWGSLMethod(e+"_"+t)),void 0===r&&(r=this._getWGSLMethod(e)),r||e}getType(e){return jN[e]||e}isAvailable(e){let t=HN[e];return void 0===t&&("float32Filterable"===e?t=this.renderer.hasFeature("float32-filterable"):"clipDistance"===e&&(t=this.renderer.hasFeature("clip-distances")),HN[e]=t),t}_getWGSLMethod(e){return void 0!==KN[e]&&this._include(e),XN[e]}_include(e){const t=KN[e];return t.build(this),null!==this.currentFunctionNode&&this.currentFunctionNode.includes.push(t),t}_getWGSLVertexCode(e){return`${this.getSignature()}\n// directives\n${e.directives}\n\n// uniforms\n${e.uniforms}\n\n// varyings\n${e.varyings}\nvar varyings : VaryingsStruct;\n\n// codes\n${e.codes}\n\n@vertex\nfn main( ${e.attributes} ) -> VaryingsStruct {\n\n\t// vars\n\t${e.vars}\n\n\t// flow\n\t${e.flow}\n\n\treturn varyings;\n\n}\n`}_getWGSLFragmentCode(e){return`${this.getSignature()}\n// global\n${YN}\n\n// uniforms\n${e.uniforms}\n\n// structs\n${e.structs}\n\n// codes\n${e.codes}\n\n@fragment\nfn main( ${e.varyings} ) -> ${e.returnType} {\n\n\t// vars\n\t${e.vars}\n\n\t// flow\n\t${e.flow}\n\n}\n`}_getWGSLComputeCode(e,t){return`${this.getSignature()}\n// directives\n${e.directives}\n\n// system\nvar instanceIndex : u32;\n\n// locals\n${e.scopedArrays}\n\n// uniforms\n${e.uniforms}\n\n// codes\n${e.codes}\n\n@compute @workgroup_size( ${t} )\nfn main( ${e.attributes} ) {\n\n\t// system\n\tinstanceIndex = id.x + id.y * numWorkgroups.x * u32(${t}) + id.z * numWorkgroups.x * numWorkgroups.y * u32(${t});\n\n\t// vars\n\t${e.vars}\n\n\t// flow\n\t${e.flow}\n\n}\n`}_getWGSLStruct(e,t){return`\nstruct ${e} {\n${t}\n};`}_getWGSLStructBinding(e,t,r,s=0,i=0){const n=e+"Struct";return`${this._getWGSLStruct(n,t)}\n@binding( ${s} ) @group( ${i} )\nvar<${r}> ${e} : ${n};`}}class ZN{constructor(e){this.backend=e}getCurrentDepthStencilFormat(e){let t;return null!==e.depthTexture?t=this.getTextureFormatGPU(e.depthTexture):e.depth&&e.stencil?t=Av.Depth24PlusStencil8:e.depth&&(t=Av.Depth24Plus),t}getTextureFormatGPU(e){return this.backend.get(e).format}getTextureSampleData(e){let t;if(e.isFramebufferTexture)t=1;else if(e.isDepthTexture&&!e.renderTarget){const e=this.backend.renderer,r=e.getRenderTarget();t=r?r.samples:e.samples}else e.renderTarget&&(t=e.renderTarget.samples);t=t||1;const r=t>1&&null!==e.renderTarget&&!0!==e.isDepthTexture&&!0!==e.isFramebufferTexture;return{samples:t,primarySamples:r?1:t,isMSAA:r}}getCurrentColorFormat(e){let t;return t=null!==e.textures?this.getTextureFormatGPU(e.textures[0]):this.getPreferredCanvasFormat(),t}getCurrentColorSpace(e){return null!==e.textures?e.textures[0].colorSpace:this.backend.renderer.outputColorSpace}getPrimitiveTopology(e,t){return e.isPoints?sv:e.isLineSegments||e.isMesh&&!0===t.wireframe?iv:e.isLine?nv:e.isMesh?ov:void 0}getSampleCount(e){let t=1;return e>1&&(t=Math.pow(2,Math.floor(Math.log2(e))),2===t&&(t=4)),t}getSampleCountRenderContext(e){return null!==e.textures?this.getSampleCount(e.sampleCount):this.getSampleCount(this.backend.renderer.samples)}getPreferredCanvasFormat(){return navigator.userAgent.includes("Quest")?Av.BGRA8Unorm:navigator.gpu.getPreferredCanvasFormat()}}const JN=new Map([[Int8Array,["sint8","snorm8"]],[Uint8Array,["uint8","unorm8"]],[Int16Array,["sint16","snorm16"]],[Uint16Array,["uint16","unorm16"]],[Int32Array,["sint32","snorm32"]],[Uint32Array,["uint32","unorm32"]],[Float32Array,["float32"]]]),eS=new Map([[Le,["float16"]]]),tS=new Map([[Int32Array,"sint32"],[Int16Array,"sint32"],[Uint32Array,"uint32"],[Uint16Array,"uint32"],[Float32Array,"float32"]]);class rS{constructor(e){this.backend=e}createAttribute(e,t){const r=this._getBufferAttribute(e),s=this.backend,i=s.get(r);let n=i.buffer;if(void 0===n){const o=s.device;let a=r.array;if(!1===e.normalized)if(a.constructor===Int16Array)a=new Int32Array(a);else if(a.constructor===Uint16Array&&(a=new Uint32Array(a),t&GPUBufferUsage.INDEX))for(let e=0;e1&&(s.multisampled=!0,r.texture.isDepthTexture||(s.sampleType=cN)),r.texture.isDepthTexture)s.sampleType=hN;else if(r.texture.isDataTexture||r.texture.isDataArrayTexture||r.texture.isData3DTexture){const e=r.texture.type;e===x?s.sampleType=pN:e===b?s.sampleType=gN:e===E&&(this.backend.hasFeature("float32-filterable")?s.sampleType=dN:s.sampleType=cN)}r.isSampledCubeTexture?s.viewDimension=xN:r.texture.isDataArrayTexture||r.texture.isCompressedArrayTexture?s.viewDimension=bN:r.isSampledTexture3D&&(s.viewDimension=TN),e.texture=s}else console.error(`WebGPUBindingUtils: Unsupported binding "${r}".`);s.push(e)}return r.createBindGroupLayout({entries:s})}createBindings(e,t,r,s=0){const{backend:i,bindGroupLayoutCache:n}=this,o=i.get(e);let a,u=n.get(e.bindingsReference);void 0===u&&(u=this.createBindingsLayout(e),n.set(e.bindingsReference,u)),r>0&&(void 0===o.groups&&(o.groups=[],o.versions=[]),o.versions[r]===s&&(a=o.groups[r])),void 0===a&&(a=this.createBindGroup(e,u),r>0&&(o.groups[r]=a,o.versions[r]=s)),o.group=a,o.layout=u}updateBinding(e){const t=this.backend,r=t.device,s=e.buffer,i=t.get(e).buffer;r.queue.writeBuffer(i,0,s,0)}createBindGroup(e,t){const r=this.backend,s=r.device;let i=0;const n=[];for(const t of e.bindings){if(t.isUniformBuffer){const e=r.get(t);if(void 0===e.buffer){const r=t.byteLength,i=GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST,n=s.createBuffer({label:"bindingBuffer_"+t.name,size:r,usage:i});e.buffer=n}n.push({binding:i,resource:{buffer:e.buffer}})}else if(t.isStorageBuffer){const e=r.get(t);if(void 0===e.buffer){const s=t.attribute;e.buffer=r.get(s).buffer}n.push({binding:i,resource:{buffer:e.buffer}})}else if(t.isSampler){const e=r.get(t.texture);n.push({binding:i,resource:e.sampler})}else if(t.isSampledTexture){const e=r.get(t.texture);let o;if(void 0!==e.externalTexture)o=s.importExternalTexture({source:e.externalTexture});else{const r=t.store?1:e.texture.mipLevelCount,s=`view-${e.texture.width}-${e.texture.height}-${r}`;if(o=e[s],void 0===o){const i=_N;let n;n=t.isSampledCubeTexture?xN:t.isSampledTexture3D?TN:t.texture.isDataArrayTexture||t.texture.isCompressedArrayTexture?bN:yN,o=e[s]=e.texture.createView({aspect:i,dimension:n,mipLevelCount:r})}}n.push({binding:i,resource:o})}i++}return s.createBindGroup({label:"bindGroup_"+e.name,layout:t,entries:n})}}class iS{constructor(e){this.backend=e}_getSampleCount(e){return this.backend.utils.getSampleCountRenderContext(e)}createRenderPipeline(e,t){const{object:r,material:s,geometry:i,pipeline:n}=e,{vertexProgram:o,fragmentProgram:a}=n,u=this.backend,l=u.device,d=u.utils,c=u.get(n),h=[];for(const t of e.getBindings()){const e=u.get(t);h.push(e.layout)}const p=u.attributeUtils.createShaderVertexBuffers(e);let g;!0===s.transparent&&s.blending!==L&&(g=this._getBlending(s));let m={};!0===s.stencilWrite&&(m={compare:this._getStencilCompare(s),failOp:this._getStencilOperation(s.stencilFail),depthFailOp:this._getStencilOperation(s.stencilZFail),passOp:this._getStencilOperation(s.stencilZPass)});const f=this._getColorWriteMask(s),y=[];if(null!==e.context.textures){const t=e.context.textures;for(let e=0;e1},layout:l.createPipelineLayout({bindGroupLayouts:h})},A={},R=e.context.depth,C=e.context.stencil;if(!0!==R&&!0!==C||(!0===R&&(A.format=v,A.depthWriteEnabled=s.depthWrite,A.depthCompare=_),!0===C&&(A.stencilFront=m,A.stencilBack={},A.stencilReadMask=s.stencilFuncMask,A.stencilWriteMask=s.stencilWriteMask),S.depthStencil=A),null===t)c.pipeline=l.createRenderPipeline(S);else{const e=new Promise((e=>{l.createRenderPipelineAsync(S).then((t=>{c.pipeline=t,e()}))}));t.push(e)}}createBundleEncoder(e){const t=this.backend,{utils:r,device:s}=t,i=r.getCurrentDepthStencilFormat(e),n={label:"renderBundleEncoder",colorFormats:[r.getCurrentColorFormat(e)],depthStencilFormat:i,sampleCount:this._getSampleCount(e)};return s.createRenderBundleEncoder(n)}createComputePipeline(e,t){const r=this.backend,s=r.device,i=r.get(e.computeProgram).module,n=r.get(e),o=[];for(const e of t){const t=r.get(e);o.push(t.layout)}n.pipeline=s.createComputePipeline({compute:i,layout:s.createPipelineLayout({bindGroupLayouts:o})})}_getBlending(e){let t,r;const s=e.blending,i=e.blendSrc,n=e.blendDst,o=e.blendEquation;if(s===yt){const s=null!==e.blendSrcAlpha?e.blendSrcAlpha:i,a=null!==e.blendDstAlpha?e.blendDstAlpha:n,u=null!==e.blendEquationAlpha?e.blendEquationAlpha:o;t={srcFactor:this._getBlendFactor(i),dstFactor:this._getBlendFactor(n),operation:this._getBlendOperation(o)},r={srcFactor:this._getBlendFactor(s),dstFactor:this._getBlendFactor(a),operation:this._getBlendOperation(u)}}else{const i=(e,s,i,n)=>{t={srcFactor:e,dstFactor:s,operation:Hv},r={srcFactor:i,dstFactor:n,operation:Hv}};if(e.premultipliedAlpha)switch(s){case U:i(Fv,Dv,Fv,Dv);break;case Tt:i(Fv,Fv,Fv,Fv);break;case xt:i(Bv,Pv,Bv,Fv);break;case bt:i(Bv,Uv,Bv,Iv)}else switch(s){case U:i(Iv,Dv,Fv,Dv);break;case Tt:i(Iv,Fv,Iv,Fv);break;case xt:i(Bv,Pv,Bv,Fv);break;case bt:i(Bv,Uv,Bv,Uv)}}if(void 0!==t&&void 0!==r)return{color:t,alpha:r};console.error("THREE.WebGPURenderer: Invalid blending: ",s)}_getBlendFactor(e){let t;switch(e){case st:t=Bv;break;case it:t=Fv;break;case nt:t=Uv;break;case dt:t=Pv;break;case ot:t=Iv;break;case ct:t=Dv;break;case ut:t=Lv;break;case ht:t=Vv;break;case lt:t=Ov;break;case pt:t=Gv;break;case at:t=kv;break;case 211:t=zv;break;case 212:t=$v;break;default:console.error("THREE.WebGPURenderer: Blend factor not supported.",e)}return t}_getStencilCompare(e){let t;const r=e.stencilFunc;switch(r){case Br:t=uv;break;case Mr:t=mv;break;case wr:t=lv;break;case Er:t=cv;break;case Cr:t=dv;break;case Rr:t=gv;break;case Ar:t=hv;break;case Sr:t=pv;break;default:console.error("THREE.WebGPURenderer: Invalid stencil function.",r)}return t}_getStencilOperation(e){let t;switch(e){case Or:t=Qv;break;case Vr:t=Zv;break;case Lr:t=Jv;break;case Dr:t=eN;break;case Ir:t=tN;break;case Pr:t=rN;break;case Ur:t=sN;break;case Fr:t=iN;break;default:console.error("THREE.WebGPURenderer: Invalid stencil operation.",t)}return t}_getBlendOperation(e){let t;switch(e){case et:t=Hv;break;case tt:t=Wv;break;case rt:t=jv;break;case kr:t=qv;break;case Gr:t=Kv;break;default:console.error("THREE.WebGPUPipelineUtils: Blend equation not supported.",e)}return t}_getPrimitiveState(e,t,r){const s={},i=this.backend.utils;switch(s.topology=i.getPrimitiveTopology(e,r),null!==t.index&&!0===e.isLine&&!0!==e.isLineSegments&&(s.stripIndexFormat=t.index.array instanceof Uint16Array?Nv:Sv),r.side){case ke:s.frontFace=xv,s.cullMode=vv;break;case T:s.frontFace=xv,s.cullMode=_v;break;case le:s.frontFace=xv,s.cullMode=Tv;break;default:console.error("THREE.WebGPUPipelineUtils: Unknown material.side value.",r.side)}return s}_getColorWriteMask(e){return!0===e.colorWrite?Yv:Xv}_getDepthCompare(e){let t;if(!1===e.depthTest)t=mv;else{const r=e.depthFunc;switch(r){case Et:t=uv;break;case Ct:t=mv;break;case Rt:t=lv;break;case At:t=cv;break;case St:t=dv;break;case Nt:t=gv;break;case vt:t=hv;break;case _t:t=pv;break;default:console.error("THREE.WebGPUPipelineUtils: Invalid depth function.",r)}}return t}}class nS extends V_{constructor(e={}){super(e),this.isWebGPUBackend=!0,this.parameters.alpha=void 0===e.alpha||e.alpha,this.parameters.requiredLimits=void 0===e.requiredLimits?{}:e.requiredLimits,this.trackTimestamp=!0===e.trackTimestamp,this.device=null,this.context=null,this.colorBuffer=null,this.defaultRenderPassdescriptor=null,this.utils=new ZN(this),this.attributeUtils=new rS(this),this.bindingUtils=new sS(this),this.pipelineUtils=new iS(this),this.textureUtils=new UN(this),this.occludedResolveCache=new Map}async init(e){await super.init(e);const t=this.parameters;let r;if(void 0===t.device){const e={powerPreference:t.powerPreference},s="undefined"!=typeof navigator?await navigator.gpu.requestAdapter(e):null;if(null===s)throw new Error("WebGPUBackend: Unable to create WebGPU adapter.");const i=Object.values(SN),n=[];for(const e of i)s.features.has(e)&&n.push(e);const o={requiredFeatures:n,requiredLimits:t.requiredLimits};r=await s.requestDevice(o)}else r=t.device;r.lost.then((t=>{const r={api:"WebGPU",message:t.message||"Unknown reason",reason:t.reason||null,originalEvent:t};e.onDeviceLost(r)}));const s=void 0!==t.context?t.context:e.domElement.getContext("webgpu");this.device=r,this.context=s;const i=t.alpha?"premultiplied":"opaque";this.trackTimestamp=this.trackTimestamp&&this.hasFeature(SN.TimestampQuery),this.context.configure({device:this.device,format:this.utils.getPreferredCanvasFormat(),usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.COPY_SRC,alphaMode:i}),this.updateSize()}get coordinateSystem(){return l}async getArrayBufferAsync(e){return await this.attributeUtils.getArrayBufferAsync(e)}getContext(){return this.context}_getDefaultRenderPassDescriptor(){let e=this.defaultRenderPassdescriptor;if(null===e){const t=this.renderer;e={colorAttachments:[{view:null}]},!0!==this.renderer.depth&&!0!==this.renderer.stencil||(e.depthStencilAttachment={view:this.textureUtils.getDepthBuffer(t.depth,t.stencil).createView()});const r=e.colorAttachments[0];this.renderer.samples>0?r.view=this.colorBuffer.createView():r.resolveTarget=void 0,this.defaultRenderPassdescriptor=e}const t=e.colorAttachments[0];return this.renderer.samples>0?t.resolveTarget=this.context.getCurrentTexture().createView():t.view=this.context.getCurrentTexture().createView(),e}_getRenderPassDescriptor(e,t={}){const r=e.renderTarget,s=this.get(r);let i=s.descriptors;if(void 0===i||s.width!==r.width||s.height!==r.height||s.dimensions!==r.dimensions||s.activeMipmapLevel!==r.activeMipmapLevel||s.activeCubeFace!==e.activeCubeFace||s.samples!==r.samples||s.loadOp!==t.loadOp){i={},s.descriptors=i;const e=()=>{r.removeEventListener("dispose",e),this.delete(r)};r.addEventListener("dispose",e)}const n=e.getCacheKey();let o=i[n];if(void 0===o){const a=e.textures,u=[];let l;for(let s=0;s0&&(t.currentOcclusionQuerySet&&t.currentOcclusionQuerySet.destroy(),t.currentOcclusionQueryBuffer&&t.currentOcclusionQueryBuffer.destroy(),t.currentOcclusionQuerySet=t.occlusionQuerySet,t.currentOcclusionQueryBuffer=t.occlusionQueryBuffer,t.currentOcclusionQueryObjects=t.occlusionQueryObjects,i=r.createQuerySet({type:"occlusion",count:s,label:`occlusionQuerySet_${e.id}`}),t.occlusionQuerySet=i,t.occlusionQueryIndex=0,t.occlusionQueryObjects=new Array(s),t.lastOcclusionObject=null),n=null===e.textures?this._getDefaultRenderPassDescriptor():this._getRenderPassDescriptor(e,{loadOp:yv}),this.initTimestampQuery(e,n),n.occlusionQuerySet=i;const o=n.depthStencilAttachment;if(null!==e.textures){const t=n.colorAttachments;for(let r=0;r0&&t.currentPass.executeBundles(t.renderBundles),r>t.occlusionQueryIndex&&t.currentPass.endOcclusionQuery(),t.currentPass.end(),r>0){const s=8*r;let i=this.occludedResolveCache.get(s);void 0===i&&(i=this.device.createBuffer({size:s,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),this.occludedResolveCache.set(s,i));const n=this.device.createBuffer({size:s,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});t.encoder.resolveQuerySet(t.occlusionQuerySet,0,r,i,0),t.encoder.copyBufferToBuffer(i,0,n,0,s),t.occlusionQueryBuffer=n,this.resolveOccludedAsync(e)}if(this.prepareTimestampBuffer(e,t.encoder),this.device.queue.submit([t.encoder.finish()]),null!==e.textures){const t=e.textures;for(let e=0;eo?(u.x=Math.min(t.dispatchCount,o),u.y=Math.ceil(t.dispatchCount/o)):u.x=t.dispatchCount,i.dispatchWorkgroups(u.x,u.y,u.z)}finishCompute(e){const t=this.get(e);t.passEncoderGPU.end(),this.prepareTimestampBuffer(e,t.cmdEncoderGPU),this.device.queue.submit([t.cmdEncoderGPU.finish()])}async waitForGPU(){await this.device.queue.onSubmittedWorkDone()}draw(e,t){const{object:r,context:s,pipeline:i}=e,n=e.getBindings(),o=this.get(s),a=this.get(i).pipeline,u=o.currentSets,l=o.currentPass,d=e.getDrawParameters();if(null===d)return;u.pipeline!==a&&(l.setPipeline(a),u.pipeline=a);const c=u.bindingGroups;for(let e=0,t=n.length;e1?0:r;!0===p?l.drawIndexed(t[r],s,e[r]/h.array.BYTES_PER_ELEMENT,0,n):l.draw(t[r],s,e[r],n)}}else if(!0===p){const{vertexCount:s,instanceCount:i,firstVertex:n}=d,o=e.getIndirect();if(null!==o){const e=this.get(o).buffer;l.drawIndexedIndirect(e,0)}else l.drawIndexed(s,i,n,0,0);t.update(r,s,i)}else{const{vertexCount:s,instanceCount:i,firstVertex:n}=d,o=e.getIndirect();if(null!==o){const e=this.get(o).buffer;l.drawIndirect(e,0)}else l.draw(s,i,n,0);t.update(r,s,i)}}needsRenderUpdate(e){const t=this.get(e),{object:r,material:s}=e,i=this.utils,n=i.getSampleCountRenderContext(e.context),o=i.getCurrentColorSpace(e.context),a=i.getCurrentColorFormat(e.context),u=i.getCurrentDepthStencilFormat(e.context),l=i.getPrimitiveTopology(r,s);let d=!1;return t.material===s&&t.materialVersion===s.version&&t.transparent===s.transparent&&t.blending===s.blending&&t.premultipliedAlpha===s.premultipliedAlpha&&t.blendSrc===s.blendSrc&&t.blendDst===s.blendDst&&t.blendEquation===s.blendEquation&&t.blendSrcAlpha===s.blendSrcAlpha&&t.blendDstAlpha===s.blendDstAlpha&&t.blendEquationAlpha===s.blendEquationAlpha&&t.colorWrite===s.colorWrite&&t.depthWrite===s.depthWrite&&t.depthTest===s.depthTest&&t.depthFunc===s.depthFunc&&t.stencilWrite===s.stencilWrite&&t.stencilFunc===s.stencilFunc&&t.stencilFail===s.stencilFail&&t.stencilZFail===s.stencilZFail&&t.stencilZPass===s.stencilZPass&&t.stencilFuncMask===s.stencilFuncMask&&t.stencilWriteMask===s.stencilWriteMask&&t.side===s.side&&t.alphaToCoverage===s.alphaToCoverage&&t.sampleCount===n&&t.colorSpace===o&&t.colorFormat===a&&t.depthStencilFormat===u&&t.primitiveTopology===l&&t.clippingContextCacheKey===e.clippingContextCacheKey||(t.material=s,t.materialVersion=s.version,t.transparent=s.transparent,t.blending=s.blending,t.premultipliedAlpha=s.premultipliedAlpha,t.blendSrc=s.blendSrc,t.blendDst=s.blendDst,t.blendEquation=s.blendEquation,t.blendSrcAlpha=s.blendSrcAlpha,t.blendDstAlpha=s.blendDstAlpha,t.blendEquationAlpha=s.blendEquationAlpha,t.colorWrite=s.colorWrite,t.depthWrite=s.depthWrite,t.depthTest=s.depthTest,t.depthFunc=s.depthFunc,t.stencilWrite=s.stencilWrite,t.stencilFunc=s.stencilFunc,t.stencilFail=s.stencilFail,t.stencilZFail=s.stencilZFail,t.stencilZPass=s.stencilZPass,t.stencilFuncMask=s.stencilFuncMask,t.stencilWriteMask=s.stencilWriteMask,t.side=s.side,t.alphaToCoverage=s.alphaToCoverage,t.sampleCount=n,t.colorSpace=o,t.colorFormat=a,t.depthStencilFormat=u,t.primitiveTopology=l,t.clippingContextCacheKey=e.clippingContextCacheKey,d=!0),d}getRenderCacheKey(e){const{object:t,material:r}=e,s=this.utils,i=e.context;return[r.transparent,r.blending,r.premultipliedAlpha,r.blendSrc,r.blendDst,r.blendEquation,r.blendSrcAlpha,r.blendDstAlpha,r.blendEquationAlpha,r.colorWrite,r.depthWrite,r.depthTest,r.depthFunc,r.stencilWrite,r.stencilFunc,r.stencilFail,r.stencilZFail,r.stencilZPass,r.stencilFuncMask,r.stencilWriteMask,r.side,s.getSampleCountRenderContext(i),s.getCurrentColorSpace(i),s.getCurrentColorFormat(i),s.getCurrentDepthStencilFormat(i),s.getPrimitiveTopology(t,r),e.getGeometryCacheKey(),e.clippingContextCacheKey].join()}createSampler(e){this.textureUtils.createSampler(e)}destroySampler(e){this.textureUtils.destroySampler(e)}createDefaultTexture(e){this.textureUtils.createDefaultTexture(e)}createTexture(e,t){this.textureUtils.createTexture(e,t)}updateTexture(e,t){this.textureUtils.updateTexture(e,t)}generateMipmaps(e){this.textureUtils.generateMipmaps(e)}destroyTexture(e){this.textureUtils.destroyTexture(e)}async copyTextureToBuffer(e,t,r,s,i,n){return this.textureUtils.copyTextureToBuffer(e,t,r,s,i,n)}initTimestampQuery(e,t){if(!this.trackTimestamp)return;const r=this.get(e);if(!r.timeStampQuerySet){const s=e.isComputeNode?"compute":"render",i=this.device.createQuerySet({type:"timestamp",count:2,label:`timestamp_${s}_${e.id}`}),n={querySet:i,beginningOfPassWriteIndex:0,endOfPassWriteIndex:1};Object.assign(t,{timestampWrites:n}),r.timeStampQuerySet=i}}prepareTimestampBuffer(e,t){if(!this.trackTimestamp)return;const r=this.get(e),s=2*BigInt64Array.BYTES_PER_ELEMENT;void 0===r.currentTimestampQueryBuffers&&(r.currentTimestampQueryBuffers={resolveBuffer:this.device.createBuffer({label:"timestamp resolve buffer",size:s,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),resultBuffer:this.device.createBuffer({label:"timestamp result buffer",size:s,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ})});const{resolveBuffer:i,resultBuffer:n}=r.currentTimestampQueryBuffers;t.resolveQuerySet(r.timeStampQuerySet,0,2,i,0),"unmapped"===n.mapState&&t.copyBufferToBuffer(i,0,n,0,s)}async resolveTimestampAsync(e,t="render"){if(!this.trackTimestamp)return;const r=this.get(e);if(void 0===r.currentTimestampQueryBuffers)return;const{resultBuffer:s}=r.currentTimestampQueryBuffers;"unmapped"===s.mapState&&s.mapAsync(GPUMapMode.READ).then((()=>{const e=new BigUint64Array(s.getMappedRange()),r=Number(e[1]-e[0])/1e6;this.renderer.info.updateTimestamp(t,r),s.unmap()}))}createNodeBuilder(e,t){return new QN(e,t)}createProgram(e){this.get(e).module={module:this.device.createShaderModule({code:e.code,label:e.stage+(""!==e.name?`_${e.name}`:"")}),entryPoint:"main"}}destroyProgram(e){this.delete(e)}createRenderPipeline(e,t){this.pipelineUtils.createRenderPipeline(e,t)}createComputePipeline(e,t){this.pipelineUtils.createComputePipeline(e,t)}beginBundle(e){const t=this.get(e);t._currentPass=t.currentPass,t._currentSets=t.currentSets,t.currentSets={attributes:{},bindingGroups:[],pipeline:null,index:null},t.currentPass=this.pipelineUtils.createBundleEncoder(e)}finishBundle(e,t){const r=this.get(e),s=r.currentPass.finish();this.get(t).bundleGPU=s,r.currentSets=r._currentSets,r.currentPass=r._currentPass}addBundle(e,t){this.get(e).renderBundles.push(this.get(t).bundleGPU)}createBindings(e,t,r,s){this.bindingUtils.createBindings(e,t,r,s)}updateBindings(e,t,r,s){this.bindingUtils.createBindings(e,t,r,s)}updateBinding(e){this.bindingUtils.updateBinding(e)}createIndexAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.INDEX|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}createAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}createStorageAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.STORAGE|GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}createIndirectStorageAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.STORAGE|GPUBufferUsage.INDIRECT|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}updateAttribute(e){this.attributeUtils.updateAttribute(e)}destroyAttribute(e){this.attributeUtils.destroyAttribute(e)}updateSize(){this.colorBuffer=this.textureUtils.getColorBuffer(),this.defaultRenderPassdescriptor=null}getMaxAnisotropy(){return 16}hasFeature(e){return this.device.features.has(e)}copyTextureToTexture(e,t,r=null,s=null,i=0){let n=0,o=0,a=0,u=0,l=0,d=0,c=e.image.width,h=e.image.height;null!==r&&(u=r.x,l=r.y,d=r.z||0,c=r.width,h=r.height),null!==s&&(n=s.x,o=s.y,a=s.z||0);const p=this.device.createCommandEncoder({label:"copyTextureToTexture_"+e.id+"_"+t.id}),g=this.get(e).texture,m=this.get(t).texture;p.copyTextureToTexture({texture:g,mipLevel:i,origin:{x:u,y:l,z:d}},{texture:m,mipLevel:i,origin:{x:n,y:o,z:a}},[c,h,1]),this.device.queue.submit([p.finish()])}copyFramebufferToTexture(e,t,r){const s=this.get(t);let i=null;i=t.renderTarget?e.isDepthTexture?this.get(t.depthTexture).texture:this.get(t.textures[0]).texture:e.isDepthTexture?this.textureUtils.getDepthBuffer(t.depth,t.stencil):this.context.getCurrentTexture();const n=this.get(e).texture;if(i.format!==n.format)return void console.error("WebGPUBackend: copyFramebufferToTexture: Source and destination formats do not match.",i.format,n.format);let o;if(s.currentPass?(s.currentPass.end(),o=s.encoder):o=this.device.createCommandEncoder({label:"copyFramebufferToTexture_"+e.id}),o.copyTextureToTexture({texture:i,origin:[r.x,r.y,0]},{texture:n},[r.z,r.w]),e.generateMipmaps&&this.textureUtils.generateMipmaps(e),s.currentPass){const{descriptor:e}=s;for(let t=0;t(console.warn("THREE.WebGPURenderer: WebGPU is not available, running under WebGL2 backend."),new rv(e)));super(new t(e),e),this.library=new aS,this.isWebGPURenderer=!0}}class lS extends ts{constructor(){super(),this.isBundleGroup=!0,this.type="BundleGroup",this.static=!0,this.version=0}set needsUpdate(e){!0===e&&this.version++}}class dS{constructor(e,t=$i(0,0,1,1)){this.renderer=e,this.outputNode=t,this.outputColorTransform=!0,this.needsUpdate=!0;const r=new sh;r.name="PostProcessing",this._quadMesh=new cf(r)}render(){this._update();const e=this.renderer,t=e.toneMapping,r=e.outputColorSpace;e.toneMapping=h,e.outputColorSpace=Re,this._quadMesh.render(e),e.toneMapping=t,e.outputColorSpace=r}dispose(){this._quadMesh.material.dispose()}_update(){if(!0===this.needsUpdate){const e=this.renderer,t=e.toneMapping,r=e.outputColorSpace;this._quadMesh.material.fragmentNode=!0===this.outputColorTransform?yu(this.outputNode,t,r):this.outputNode.context({toneMapping:t,outputColorSpace:r}),this._quadMesh.material.needsUpdate=!0,this.needsUpdate=!1}}async renderAsync(){this._update();const e=this.renderer,t=e.toneMapping,r=e.outputColorSpace;e.toneMapping=h,e.outputColorSpace=Re,await this._quadMesh.renderAsync(e),e.toneMapping=t,e.outputColorSpace=r}}class cS extends ee{constructor(e=1,t=1){super(),this.image={width:e,height:t},this.magFilter=$,this.minFilter=$,this.isStorageTexture=!0}}class hS extends xf{constructor(e,t){super(e,t,Uint32Array),this.isIndirectStorageBufferAttribute=!0}}class pS extends rs{constructor(e){super(e),this.textures={},this.nodes={}}load(e,t,r,s){const i=new ss(this.manager);i.setPath(this.path),i.setRequestHeader(this.requestHeader),i.setWithCredentials(this.withCredentials),i.load(e,(r=>{try{t(this.parse(JSON.parse(r)))}catch(t){s?s(t):console.error(t),this.manager.itemError(e)}}),r,s)}parseNodes(e){const t={};if(void 0!==e){for(const r of e){const{uuid:e,type:s}=r;t[e]=this.createNodeFromType(s),t[e].uuid=e}const r={nodes:t,textures:this.textures};for(const s of e){s.meta=r;t[s.uuid].deserialize(s),delete s.meta}}return t}parse(e){const t=this.createNodeFromType(e.type);t.uuid=e.uuid;const r={nodes:this.parseNodes(e.nodes),textures:this.textures};return e.meta=r,t.deserialize(e),delete e.meta,t}setTextures(e){return this.textures=e,this}setNodes(e){return this.nodes=e,this}createNodeFromType(e){return void 0===this.nodes[e]?(console.error("THREE.NodeLoader: Node type not found:",e),Bi()):Ti(new this.nodes[e])}}class gS extends is{constructor(e){super(e),this.nodes={},this.nodeMaterials={}}parse(e){const t=super.parse(e),r=this.nodes,s=e.inputNodes;for(const e in s){const i=s[e];t[e]=r[i]}return t}setNodes(e){return this.nodes=e,this}setNodeMaterials(e){return this.nodeMaterials=e,this}createMaterialFromType(e){const t=this.nodeMaterials[e];return void 0!==t?new t:super.createMaterialFromType(e)}}class mS extends ns{constructor(e){super(e),this.nodes={},this.nodeMaterials={},this._nodesJSON=null}setNodes(e){return this.nodes=e,this}setNodeMaterials(e){return this.nodeMaterials=e,this}parse(e,t){this._nodesJSON=e.nodes;const r=super.parse(e,t);return this._nodesJSON=null,r}parseNodes(e,t){if(void 0!==e){const r=new pS;return r.setNodes(this.nodes),r.setTextures(t),r.parseNodes(e)}return{}}parseMaterials(e,t){const r={};if(void 0!==e){const s=this.parseNodes(this._nodesJSON,t),i=new gS;i.setTextures(t),i.setNodes(s),i.setNodeMaterials(this.nodeMaterials);for(let t=0,s=e.length;t} + */ this.renderObjects = new WeakMap(); + + /** + * Whether the material uses node objects or not. + * + * @type {Boolean} + */ this.hasNode = this.containsNode( builder ); + + /** + * Whether the node builder's 3D object is animated or not. + * + * @type {Boolean} + */ this.hasAnimation = builder.object.isSkinnedMesh === true; + + /** + * A list of all possible material uniforms + * + * @type {Array} + */ this.refreshUniforms = refreshUniforms; + + /** + * Holds the current render ID from the node frame. + * + * @type {Number} + * @default 0 + */ this.renderId = 0; } + /** + * Returns `true` if the given render object is verified for the first time of this observer. + * + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether the given render object is verified for the first time of this observer. + */ firstInitialization( renderObject ) { const hasInitialized = this.renderObjects.has( renderObject ); @@ -87,6 +134,12 @@ class NodeMaterialObserver { } + /** + * Returns monitoring data for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @return {Object} The monitoring data. + */ getRenderObjectData( renderObject ) { let data = this.renderObjects.get( renderObject ); @@ -140,6 +193,13 @@ class NodeMaterialObserver { } + /** + * Returns an attribute data structure holding the attributes versions for + * monitoring. + * + * @param {Object} attributes - The geometry attributes. + * @return {Object} An object for monitoring the versions of attributes. + */ getAttributesData( attributes ) { const attributesData = {}; @@ -158,6 +218,13 @@ class NodeMaterialObserver { } + /** + * Returns `true` if the node builder's material uses + * node properties. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Boolean} Whether the node builder's material uses node properties or not. + */ containsNode( builder ) { const material = builder.material; @@ -176,6 +243,13 @@ class NodeMaterialObserver { } + /** + * Returns a material data structure holding the material property values for + * monitoring. + * + * @param {Material} material - The material. + * @return {Object} An object for monitoring material properties. + */ getMaterialData( material ) { const data = {}; @@ -210,6 +284,12 @@ class NodeMaterialObserver { } + /** + * Returns `true` if the given render object has not changed its state. + * + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether the given render object has changed its state or not. + */ equals( renderObject ) { const { object, material, geometry } = renderObject; @@ -390,6 +470,13 @@ class NodeMaterialObserver { } + /** + * Checks if the given render object requires a refresh. + * + * @param {RenderObject} renderObject - The render object. + * @param {NodeFrame} nodeFrame - The current node frame. + * @return {Boolean} Whether the given render object requires a refresh or not. + */ needsRefresh( renderObject, nodeFrame ) { if ( this.hasNode || this.hasAnimation || this.firstInitialization( renderObject ) ) @@ -582,6 +669,8 @@ const typeFromLength = /*@__PURE__*/ new Map( [ [ 16, 'mat4' ] ] ); +const dataFromObject = /*@__PURE__*/ new WeakMap(); + /** * Returns the data type for the given the length. * @@ -595,6 +684,39 @@ function getTypeFromLength( length ) { } +/** + * Returns the typed array for the given data type. + * + * @method + * @param {String} type - The data type. + * @return {TypedArray} The typed array. + */ +function getTypedArrayFromType( type ) { + + // Handle component type for vectors and matrices + if ( /[iu]?vec\d/.test( type ) ) { + + // Handle int vectors + if ( type.startsWith( 'ivec' ) ) return Int32Array; + // Handle uint vectors + if ( type.startsWith( 'uvec' ) ) return Uint32Array; + // Default to float vectors + return Float32Array; + + } + + // Handle matrices (always float) + if ( /mat\d/.test( type ) ) return Float32Array; + + // Basic types + if ( /float/.test( type ) ) return Float32Array; + if ( /uint/.test( type ) ) return Uint32Array; + if ( /int/.test( type ) ) return Int32Array; + + throw new Error( `THREE.NodeUtils: Unsupported type: ${type}` ); + +} + /** * Returns the length for the given data type. * @@ -748,6 +870,27 @@ function getValueFromType( type, ...params ) { } +/** + * Gets the object data that can be shared between different rendering steps. + * + * @param {Object} object - The object to get the data for. + * @return {Object} The object data. + */ +function getDataFromObject( object ) { + + let data = dataFromObject.get( object ); + + if ( data === undefined ) { + + data = {}; + dataFromObject.set( object, data ); + + } + + return data; + +} + /** * Converts the given array buffer to a Base64 string. * @@ -789,9 +932,11 @@ var NodeUtils = /*#__PURE__*/Object.freeze({ arrayBufferToBase64: arrayBufferToBase64, base64ToArrayBuffer: base64ToArrayBuffer, getCacheKey: getCacheKey$1, + getDataFromObject: getDataFromObject, getLengthFromType: getLengthFromType, getNodeChildren: getNodeChildren, getTypeFromLength: getTypeFromLength, + getTypedArrayFromType: getTypedArrayFromType, getValueFromType: getValueFromType, getValueType: getValueType, hash: hash$1, @@ -1340,8 +1485,9 @@ class Node extends EventDispatcher { } - // return a outputNode if exists - return null; + // return a outputNode if exists or null + + return nodeProperties.outputNode || null; } @@ -1475,12 +1621,19 @@ class Node extends EventDispatcher { if ( properties.initialized !== true ) { - const stackNodesBeforeSetup = builder.stack.nodes.length; + //const stackNodesBeforeSetup = builder.stack.nodes.length; properties.initialized = true; - properties.outputNode = this.setup( builder ); - if ( properties.outputNode !== null && builder.stack.nodes.length !== stackNodesBeforeSetup ) ; + const outputNode = this.setup( builder ); // return a node or null + const isNodeOutput = outputNode && outputNode.isNode === true; + + /*if ( isNodeOutput && builder.stack.nodes.length !== stackNodesBeforeSetup ) { + + // !! no outputNode !! + //outputNode = builder.stack; + + }*/ for ( const childNode of Object.values( properties ) ) { @@ -1492,6 +1645,14 @@ class Node extends EventDispatcher { } + if ( isNodeOutput ) { + + outputNode.build( builder ); + + } + + properties.outputNode = outputNode; + } } else if ( buildStage === 'analyze' ) { @@ -3569,8 +3730,10 @@ const uniform = ( arg1, arg2 ) => { }; +/** @module PropertyNode **/ + /** - * This class represents a shader property. It can be used on + * This class represents a shader property. It can be used * to explicitly define a property and assign a value to it. * * ```js @@ -3667,36 +3830,220 @@ class PropertyNode extends Node { } +/** + * TSL function for creating a property node. + * + * @function + * @param {String} type - The type of the node. + * @param {String?} [name=null] - The name of the property in the shader. + * @returns {PropertyNode} + */ const property = ( type, name ) => nodeObject( new PropertyNode( type, name ) ); + +/** + * TSL function for creating a varying property node. + * + * @function + * @param {String} type - The type of the node. + * @param {String?} [name=null] - The name of the varying in the shader. + * @returns {PropertyNode} + */ const varyingProperty = ( type, name ) => nodeObject( new PropertyNode( type, name, true ) ); +/** + * TSL object that represents the shader variable `DiffuseColor`. + * + * @type {PropertyNode} + */ const diffuseColor = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec4', 'DiffuseColor' ); + +/** + * TSL object that represents the shader variable `EmissiveColor`. + * + * @type {PropertyNode} + */ const emissive = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'EmissiveColor' ); + +/** + * TSL object that represents the shader variable `Roughness`. + * + * @type {PropertyNode} + */ const roughness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Roughness' ); + +/** + * TSL object that represents the shader variable `Metalness`. + * + * @type {PropertyNode} + */ const metalness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Metalness' ); + +/** + * TSL object that represents the shader variable `Clearcoat`. + * + * @type {PropertyNode} + */ const clearcoat = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Clearcoat' ); + +/** + * TSL object that represents the shader variable `ClearcoatRoughness`. + * + * @type {PropertyNode} + */ const clearcoatRoughness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'ClearcoatRoughness' ); + +/** + * TSL object that represents the shader variable `Sheen`. + * + * @type {PropertyNode} + */ const sheen = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'Sheen' ); + +/** + * TSL object that represents the shader variable `SheenRoughness`. + * + * @type {PropertyNode} + */ const sheenRoughness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'SheenRoughness' ); + +/** + * TSL object that represents the shader variable `Iridescence`. + * + * @type {PropertyNode} + */ const iridescence = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Iridescence' ); + +/** + * TSL object that represents the shader variable `IridescenceIOR`. + * + * @type {PropertyNode} + */ const iridescenceIOR = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'IridescenceIOR' ); + +/** + * TSL object that represents the shader variable `IridescenceThickness`. + * + * @type {PropertyNode} + */ const iridescenceThickness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'IridescenceThickness' ); + +/** + * TSL object that represents the shader variable `AlphaT`. + * + * @type {PropertyNode} + */ const alphaT = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'AlphaT' ); + +/** + * TSL object that represents the shader variable `Anisotropy`. + * + * @type {PropertyNode} + */ const anisotropy = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Anisotropy' ); + +/** + * TSL object that represents the shader variable `AnisotropyT`. + * + * @type {PropertyNode} + */ const anisotropyT = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'AnisotropyT' ); + +/** + * TSL object that represents the shader variable `AnisotropyB`. + * + * @type {PropertyNode} + */ const anisotropyB = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'AnisotropyB' ); + +/** + * TSL object that represents the shader variable `SpecularColor`. + * + * @type {PropertyNode} + */ const specularColor = /*@__PURE__*/ nodeImmutable( PropertyNode, 'color', 'SpecularColor' ); + +/** + * TSL object that represents the shader variable `SpecularF90`. + * + * @type {PropertyNode} + */ const specularF90 = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'SpecularF90' ); + +/** + * TSL object that represents the shader variable `Shininess`. + * + * @type {PropertyNode} + */ const shininess = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Shininess' ); + +/** + * TSL object that represents the shader variable `Output`. + * + * @type {PropertyNode} + */ const output = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec4', 'Output' ); + +/** + * TSL object that represents the shader variable `dashSize`. + * + * @type {PropertyNode} + */ const dashSize = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'dashSize' ); + +/** + * TSL object that represents the shader variable `gapSize`. + * + * @type {PropertyNode} + */ const gapSize = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'gapSize' ); + +/** + * TSL object that represents the shader variable `pointWidth`. + * + * @type {PropertyNode} + */ const pointWidth = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'pointWidth' ); + +/** + * TSL object that represents the shader variable `IOR`. + * + * @type {PropertyNode} + */ const ior = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'IOR' ); + +/** + * TSL object that represents the shader variable `Transmission`. + * + * @type {PropertyNode} + */ const transmission = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Transmission' ); + +/** + * TSL object that represents the shader variable `Thickness`. + * + * @type {PropertyNode} + */ const thickness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Thickness' ); + +/** + * TSL object that represents the shader variable `AttenuationDistance`. + * + * @type {PropertyNode} + */ const attenuationDistance = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'AttenuationDistance' ); + +/** + * TSL object that represents the shader variable `AttenuationColor`. + * + * @type {PropertyNode} + */ const attenuationColor = /*@__PURE__*/ nodeImmutable( PropertyNode, 'color', 'AttenuationColor' ); + +/** + * TSL object that represents the shader variable `Dispersion`. + * + * @type {PropertyNode} + */ const dispersion = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Dispersion' ); /** @module AssignNode **/ @@ -5500,6 +5847,13 @@ const atan2 = ( y, x ) => { // @deprecated, r172 }; +// GLSL alias function + +const faceforward = faceForward; +const inversesqrt = inverseSqrt; + +// Method chaining + addMethodChaining( 'all', all ); addMethodChaining( 'any', any ); addMethodChaining( 'equals', equals ); @@ -5626,11 +5980,23 @@ class ConditionalNode extends Node { */ getNodeType( builder ) { - const ifType = this.ifNode.getNodeType( builder ); + const { ifNode, elseNode } = builder.getNodeProperties( this ); + + if ( ifNode === undefined ) { + + // fallback setup + + this.setup( builder ); + + return this.getNodeType( builder ); + + } + + const ifType = ifNode.getNodeType( builder ); - if ( this.elseNode !== null ) { + if ( elseNode !== null ) { - const elseType = this.elseNode.getNodeType( builder ); + const elseType = elseNode.getNodeType( builder ); if ( builder.getTypeLength( elseType ) > builder.getTypeLength( ifType ) ) { @@ -6194,7 +6560,17 @@ class VaryingNode extends Node { */ const varying = /*@__PURE__*/ nodeProxy( VaryingNode ); +/** + * Computes a node in the vertex stage. + * + * @function + * @param {Node} node - The node which should be executed in the vertex stage. + * @returns {VaryingNode} + */ +const vertexStage = ( node ) => varying( node ); + addMethodChaining( 'varying', varying ); +addMethodChaining( 'vertexStage', vertexStage ); /** @module ColorSpaceFunctions **/ @@ -6967,7 +7343,7 @@ addMethodChaining( 'toneMapping', ( color, mapping, exposure ) => toneMapping( m * material.colorNode = bufferAttribute( new THREE.Float32BufferAttribute( colors, 3 ) ); * ``` * This new approach is especially interesting when geometry data are generated via - * compute shaders. The below line converts a storage buffer into an attribute. + * compute shaders. The below line converts a storage buffer into an attribute node. * ```js * material.positionNode = positionBuffer.toAttribute(); * ``` @@ -7349,6 +7725,14 @@ class ComputeNode extends Node { */ this.version = 1; + /** + * The name or label of the uniform. + * + * @type {String} + * @default '' + */ + this.name = ''; + /** * The `updateBeforeType` is set to `NodeUpdateType.OBJECT` since {@link ComputeNode#updateBefore} * is executed once per object by default. @@ -7378,6 +7762,20 @@ class ComputeNode extends Node { } + /** + * Sets the {@link ComputeNode#name} property. + * + * @param {String} name - The name of the uniform. + * @return {ComputeNode} A reference to this node. + */ + label( name ) { + + this.name = name; + + return this; + + } + /** * TODO */ @@ -7507,7 +7905,16 @@ class CacheNode extends Node { getNodeType( builder ) { - return this.node.getNodeType( builder ); + const previousCache = builder.getCache(); + const cache = builder.getCacheFromNode( this, this.parent ); + + builder.setCache( cache ); + + const nodeType = this.node.getNodeType( builder ); + + builder.setCache( previousCache ); + + return nodeType; } @@ -8572,7 +8979,7 @@ class TextureNode extends UniformNode { setUpdateMatrix( value ) { this.updateMatrix = value; - this.updateType = value ? NodeUpdateType.FRAME : NodeUpdateType.NONE; + this.updateType = value ? NodeUpdateType.RENDER : NodeUpdateType.NONE; return this; @@ -8620,6 +9027,16 @@ class TextureNode extends UniformNode { // + const texture = this.value; + + if ( ! texture || texture.isTexture !== true ) { + + throw new Error( 'THREE.TSL: `texture( value )` function expects a valid instance of THREE.Texture().' ); + + } + + // + let uvNode = this.uvNode; if ( ( uvNode === null || builder.context.forceUVContext === true ) && builder.context.getUV ) { @@ -8730,16 +9147,9 @@ class TextureNode extends UniformNode { */ generate( builder, output ) { - const properties = builder.getNodeProperties( this ); - const texture = this.value; - if ( ! texture || texture.isTexture !== true ) { - - throw new Error( 'TextureNode: Need a three.js texture.' ); - - } - + const properties = builder.getNodeProperties( this ); const textureProperty = super.generate( builder, 'property' ); if ( output === 'sampler' ) { @@ -9688,7 +10098,9 @@ const normalWorld = /*@__PURE__*/ varying( normalView.transformDirection( camera */ const transformedNormalView = /*@__PURE__*/ ( Fn( ( builder ) => { - return builder.context.setupNormal(); + // Use getUV context to avoid side effects from nodes overwriting getUV in the context (e.g. EnvironmentNode) + + return builder.context.setupNormal().context( { getUV: null } ); }, 'vec3' ).once() )().mul( faceDirection ).toVar( 'transformedNormalView' ); @@ -9706,7 +10118,9 @@ const transformedNormalWorld = /*@__PURE__*/ transformedNormalView.transformDire */ const transformedClearcoatNormalView = /*@__PURE__*/ ( Fn( ( builder ) => { - return builder.context.setupClearcoatNormal(); + // Use getUV context to avoid side effects from nodes overwriting getUV in the context (e.g. EnvironmentNode) + + return builder.context.setupClearcoatNormal().context( { getUV: null } ); }, 'vec3' ).once() )().mul( faceDirection ).toVar( 'transformedClearcoatNormalView' ); @@ -11052,8 +11466,8 @@ class NormalMapNode extends TempNode { /** * Constructs a new normal map node. * - * @param {Node} node - Represents the normal map data. - * @param {Node?} [scaleNode=null] - Controls the intensity of the effect. + * @param {Node} node - Represents the normal map data. + * @param {Node?} [scaleNode=null] - Controls the intensity of the effect. */ constructor( node, scaleNode = null ) { @@ -11062,14 +11476,14 @@ class NormalMapNode extends TempNode { /** * Represents the normal map data. * - * @type {Node} + * @type {Node} */ this.node = node; /** * Controls the intensity of the effect. * - * @type {Node?} + * @type {Node?} * @default null */ this.scaleNode = scaleNode; @@ -11133,8 +11547,8 @@ class NormalMapNode extends TempNode { * TSL function for creating a normal map node. * * @function - * @param {Node} node - Represents the normal map data. - * @param {Node?} [scaleNode=null] - Controls the intensity of the effect. + * @param {Node} node - Represents the normal map data. + * @param {Node?} [scaleNode=null] - Controls the intensity of the effect. * @returns {NormalMapNode} */ const normalMap = /*@__PURE__*/ nodeProxy( NormalMapNode ); @@ -11200,8 +11614,8 @@ class BumpMapNode extends TempNode { /** * Constructs a new bump map node. * - * @param {Node} textureNode - Represents the bump map data. - * @param {Node?} [scaleNode=null] - Controls the intensity of the bump effect. + * @param {Node} textureNode - Represents the bump map data. + * @param {Node?} [scaleNode=null] - Controls the intensity of the bump effect. */ constructor( textureNode, scaleNode = null ) { @@ -11210,14 +11624,14 @@ class BumpMapNode extends TempNode { /** * Represents the bump map data. * - * @type {Node} + * @type {Node} */ this.textureNode = textureNode; /** * Controls the intensity of the bump effect. * - * @type {Node?} + * @type {Node?} * @default null */ this.scaleNode = scaleNode; @@ -11243,8 +11657,8 @@ class BumpMapNode extends TempNode { * TSL function for creating a bump map node. * * @function - * @param {Node} textureNode - Represents the bump map data. - * @param {Node?} [scaleNode=null] - Controls the intensity of the bump effect. + * @param {Node} textureNode - Represents the bump map data. + * @param {Node?} [scaleNode=null] - Controls the intensity of the bump effect. * @returns {BumpMapNode} */ const bumpMap = /*@__PURE__*/ nodeProxy( BumpMapNode ); @@ -11402,15 +11816,15 @@ class MaterialNode extends Node { } else if ( scope === MaterialNode.SPECULAR_INTENSITY ) { - const specularIntensity = this.getFloat( scope ); + const specularIntensityNode = this.getFloat( scope ); - if ( material.specularMap ) { + if ( material.specularIntensityMap && material.specularIntensityMap.isTexture === true ) { - node = specularIntensity.mul( this.getTexture( scope ).a ); + node = specularIntensityNode.mul( this.getTexture( scope ).a ); } else { - node = specularIntensity; + node = specularIntensityNode; } @@ -11625,7 +12039,7 @@ class MaterialNode extends Node { node = this.getTexture( scope ).rgb.mul( this.getFloat( 'lightMapIntensity' ) ); - } else if ( scope === MaterialNode.AO_MAP ) { + } else if ( scope === MaterialNode.AO ) { node = this.getTexture( scope ).r.sub( 1.0 ).mul( this.getFloat( 'aoMapIntensity' ) ).add( 1.0 ); @@ -11679,7 +12093,7 @@ MaterialNode.LINE_DASH_OFFSET = 'dashOffset'; MaterialNode.POINT_WIDTH = 'pointWidth'; MaterialNode.DISPERSION = 'dispersion'; MaterialNode.LIGHT_MAP = 'light'; -MaterialNode.AO_MAP = 'ao'; +MaterialNode.AO = 'ao'; /** * TSL object that represents alpha test of the current material. @@ -11738,7 +12152,7 @@ const materialSpecularIntensity = /*@__PURE__*/ nodeImmutable( MaterialNode, Mat * TSL object that represents the specular color of the current material. * The value is composed via `specularColor` * `specularMap.rgb`. * - * @type {Node} + * @type {Node} */ const materialSpecularColor = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SPECULAR_COLOR ); @@ -11759,7 +12173,7 @@ const materialReflectivity = /*@__PURE__*/ nodeImmutable( MaterialNode, Material /** * TSL object that represents the roughness of the current material. - * The value is composed via `roughness` * `roughnessMap.g` + * The value is composed via `roughness` * `roughnessMap.g`. * * @type {Node} */ @@ -11767,7 +12181,7 @@ const materialRoughness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNod /** * TSL object that represents the metalness of the current material. - * The value is composed via `metalness` * `metalnessMap.b` + * The value is composed via `metalness` * `metalnessMap.b`. * * @type {Node} */ @@ -11775,15 +12189,15 @@ const materialMetalness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNod /** * TSL object that represents the normal of the current material. - * The value will be either `normalMap`, `bumpMap` or `normalView`. + * The value will be either `normalMap` * `normalScale`, `bumpMap` * `bumpScale` or `normalView`. * * @type {Node} */ -const materialNormal = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.NORMAL ).context( { getUV: null } ); +const materialNormal = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.NORMAL ); /** * TSL object that represents the clearcoat of the current material. - * The value is composed via `clearcoat` * `clearcoat.r` + * The value is composed via `clearcoat` * `clearcoatMap.r` * * @type {Node} */ @@ -11791,7 +12205,7 @@ const materialClearcoat = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNod /** * TSL object that represents the clearcoat roughness of the current material. - * The value is composed via `clearcoatRoughness` * `clearcoatRoughnessMap.r` + * The value is composed via `clearcoatRoughness` * `clearcoatRoughnessMap.r`. * * @type {Node} */ @@ -11803,7 +12217,7 @@ const materialClearcoatRoughness = /*@__PURE__*/ nodeImmutable( MaterialNode, Ma * * @type {Node} */ -const materialClearcoatNormal = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.CLEARCOAT_NORMAL ).context( { getUV: null } ); +const materialClearcoatNormal = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.CLEARCOAT_NORMAL ); /** * TSL object that represents the rotation of the current sprite material. @@ -11822,7 +12236,7 @@ const materialSheen = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SH /** * TSL object that represents the sheen roughness of the current material. - * The value is composed via `sheenRoughness` * `sheenRoughnessMap.a` . + * The value is composed via `sheenRoughness` * `sheenRoughnessMap.a`. * * @type {Node} */ @@ -11956,7 +12370,7 @@ const materialLightMap = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode * * @type {Node} */ -const materialAOMap = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.AO_MAP ); +const materialAO = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.AO ); /** * TSL object that represents the anisotropy vector of the current material. @@ -12759,7 +13173,7 @@ class SkinningNode extends Node { const mrt = builder.renderer.getMRT(); - return mrt && mrt.has( 'velocity' ); + return ( mrt && mrt.has( 'velocity' ) ) || getDataFromObject( builder.object ).useVelocity === true; } @@ -14733,6 +15147,11 @@ const getAlphaHashThreshold = /*@__PURE__*/ Fn( ( [ position ] ) => { ] } ); +/** + * Base class for all node materials. + * + * @augments Material + */ class NodeMaterial extends Material { static get type() { @@ -14741,6 +15160,11 @@ class NodeMaterial extends Material { } + /** + * Represents the type of the node material. + * + * @type {String} + */ get type() { return this.constructor.type; @@ -14749,63 +15173,359 @@ class NodeMaterial extends Material { set type( _value ) { /* */ } + /** + * Constructs a new node material. + */ constructor() { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isNodeMaterial = true; - this.forceSinglePass = false; - + /** + * Whether this material is affected by fog or not. + * + * @type {Boolean} + * @default true + */ this.fog = true; + + /** + * Whether this material is affected by lights or not. + * + * @type {Boolean} + * @default false + */ this.lights = false; + + /** + * Whether this material uses hardware clipping or not. + * This property is managed by the engine and should not be + * modified by apps. + * + * @type {Boolean} + * @default false + */ this.hardwareClipping = false; + /** + * Node materials which set their `lights` property to `true` + * are affected by all lights of the scene. Sometimes selective + * lighting is wanted which means only _some_ lights in the scene + * affect a material. This can be achieved by creating an instance + * of {@link module:LightsNode~LightsNode} with a list of selective + * lights and assign the node to this property. + * + * ```js + * const customLightsNode = lights( [ light1, light2 ] ); + * material.lightsNode = customLightsNode; + * ``` + * + * @type {LightsNode?} + * @default null + */ this.lightsNode = null; + + /** + * The environment of node materials can be defined by an environment + * map assigned to the `envMap` property or by `Scene.environment` + * if the node material is a PBR material. This node property allows to overwrite + * the default behavior and define the environment with a custom node. + * + * ```js + * material.envNode = pmremTexture( renderTarget.texture ); + * ``` + * + * @type {Node?} + * @default null + */ this.envNode = null; + + /** + * The lighting of node materials might be influenced by ambient occlusion. + * The default AO is inferred from an ambient occlusion map assigned to `aoMap` + * and the respective `aoMapIntensity`. This node property allows to overwrite + * the default and define the ambient occlusion with a custom node instead. + * + * If you don't want to overwrite the diffuse color but modify the existing + * values instead, use {@link module:MaterialNode.materialAO}. + * + * @type {Node?} + * @default null + */ this.aoNode = null; + /** + * The diffuse color of node materials is by default inferred from the + * `color` and `map` properties. This node property allows to overwrite the default + * and define the diffuse color with a node instead. + * + * ```js + * material.colorNode = color( 0xff0000 ); // define red color + * ``` + * + * If you don't want to overwrite the diffuse color but modify the existing + * values instead, use {@link module:MaterialNode.materialColor}. + * + * ```js + * material.colorNode = materialColor.mul( color( 0xff0000 ) ); // give diffuse colors a red tint + * ``` + * + * @type {Node?} + * @default null + */ this.colorNode = null; + + /** + * The normals of node materials are by default inferred from the `normalMap`/`normalScale` + * or `bumpMap`/`bumpScale` properties. This node property allows to overwrite the default + * and define the normals with a node instead. + * + * If you don't want to overwrite the normals but modify the existing values instead, + * use {@link module:MaterialNode.materialNormal}. + * + * @type {Node?} + * @default null + */ this.normalNode = null; + + /** + * The opacity of node materials is by default inferred from the `opacity` + * and `alphaMap` properties. This node property allows to overwrite the default + * and define the opacity with a node instead. + * + * If you don't want to overwrite the normals but modify the existing + * value instead, use {@link module:MaterialNode.materialOpacity}. + * + * @type {Node?} + * @default null + */ this.opacityNode = null; + + /** + * This node can be used to to implement a variety of filter-like effects. The idea is + * to store the current rendering into a texture e.g. via `viewportSharedTexture()`, use it + * to create an arbitrary effect and then assign the node composition to this property. + * Everything behind the object using this material will now be affected by a filter. + * + * ```js + * const material = new NodeMaterial() + * material.transparent = true; + * + * // everything behind the object will be monochromatic + * material.backdropNode = viewportSharedTexture().rgb.saturation( 0 ); + * ``` + * + * Backdrop computations are part of the lighting so only lit materials can use this property. + * + * @type {Node?} + * @default null + */ this.backdropNode = null; + + /** + * This node allows to modulate the influence of `backdropNode` to the outgoing light. + * + * @type {Node?} + * @default null + */ this.backdropAlphaNode = null; + + /** + * The alpha test of node materials is by default inferred from the `alphaTest` + * property. This node property allows to overwrite the default and define the + * alpha test with a node instead. + * + * If you don't want to overwrite the alpha test but modify the existing + * value instead, use {@link module:MaterialNode.materialAlphaTest}. + * + * @type {Node?} + * @default null + */ this.alphaTestNode = null; + /** + * The local vertex positions are computed based on multiple factors like the + * attribute data, morphing or skinning. This node property allows to overwrite + * the default and define local vertex positions with nodes instead. + * + * If you don't want to overwrite the vertex positions but modify the existing + * values instead, use {@link module:Position.positionLocal}. + * + *```js + * material.positionNode = positionLocal.add( displace ); + * ``` + * + * @type {Node?} + * @default null + */ this.positionNode = null; + + /** + * This node property is intended for logic which modifies geometry data once or per animation step. + * Apps usually place such logic randomly in initialization routines or in the animation loop. + * `geometryNode` is intended as a dedicated API so there is an intended spot where geometry modifications + * can be implemented. + * + * The idea is to assign a `Fn` definition that holds the geometry modification logic. A typical example + * would be a GPU based particle system that provides a node material for usage on app level. The particle + * simulation would be implemented as compute shaders and managed inside a `Fn` function. This function is + * eventually assigned to `geometryNode`. + * + * @type {Function} + * @default null + */ this.geometryNode = null; + /** + * Allows to overwrite depth values in the fragment shader. + * + * @type {Node?} + * @default null + */ this.depthNode = null; + + /** + * Allows to overwrite the position used for shadow map rendering which + * is by default {@link module:Position.positionWorld}, the vertex position + * in world space. + * + * @type {Node?} + * @default null + */ this.shadowPositionNode = null; + + /** + * This node can be used to influence how an object using this node material + * receive shadows. + * + * ```js + * const totalShadows = float( 1 ).toVar(); + * material.receivedShadowNode = Fn( ( [ shadow ] ) => { + * totalShadows.mulAssign( shadow ); + * //return float( 1 ); // bypass received shadows + * return shadow.mix( color( 0xff0000 ), 1 ); // modify shadow color + * } ); + * + * @type {Node?} + * @default null + */ this.receivedShadowNode = null; + + /** + * This node can be used to influence how an object using this node material + * casts shadows. To apply a color to shadows, you can simply do: + * + * ```js + * material.castShadowNode = vec4( 1, 0, 0, 1 ); + * ``` + * + * Which can be nice to fake colored shadows of semi-transparent objects. It + * is also common to use the property with `Fn` function so checks are performed + * per fragment. + * + * ```js + * materialCustomShadow.castShadowNode = Fn( () => { + * hash( vertexIndex ).greaterThan( 0.5 ).discard(); + * return materialColor; + * } )(); + * ``` + * + * @type {Node?} + * @default null + */ this.castShadowNode = null; + /** + * This node can be used to define the final output of the material. + * + * TODO: Explain the differences to `fragmentNode`. + * + * @type {Node?} + * @default null + */ this.outputNode = null; + + /** + * MRT configuration is done on renderer or pass level. This node allows to + * overwrite what values are written into MRT targets on material level. This + * can be useful for implementing selective FX features that should only affect + * specific objects. + * + * @type {MRTNode?} + * @default null + */ this.mrtNode = null; + /** + * This node property can be used if you need complete freedom in implementing + * the fragment shader. Assigning a node will replace the built-in material + * logic used in the fragment stage. + * + * @type {Node?} + * @default null + */ this.fragmentNode = null; + + /** + * This node property can be used if you need complete freedom in implementing + * the vertex shader. Assigning a node will replace the built-in material logic + * used in the vertex stage. + * + * @type {Node?} + * @default null + */ this.vertexNode = null; } + /** + * Allows to define a custom cache key that influence the material key computation + * for render objects. + * + * @return {String} The custom cache key. + */ customProgramCacheKey() { return this.type + getCacheKey$1( this ); } + /** + * Builds this material with the given node builder. + * + * @param {NodeBuilder} builder - The current node builder. + */ build( builder ) { this.setup( builder ); } + /** + * Setups a node material observer with the given builder. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {NodeMaterialObserver} The node material observer. + */ setupObserver( builder ) { return new NodeMaterialObserver( builder ); } + /** + * Setups the vertex and fragment stage of this node material. + * + * @param {NodeBuilder} builder - The current node builder. + */ setup( builder ) { builder.context.setupNormal = () => this.setupNormal( builder ); @@ -14841,7 +15561,7 @@ class NodeMaterial extends Material { const clippingNode = this.setupClipping( builder ); - if ( this.depthWrite === true ) { + if ( this.depthWrite === true || this.depthTest === true ) { // only write depth if depth buffer is configured @@ -14929,6 +15649,12 @@ class NodeMaterial extends Material { } + /** + * Setups the clipping node. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {ClippingNode} The clipping node. + */ setupClipping( builder ) { if ( builder.clippingContext === null ) return null; @@ -14958,6 +15684,11 @@ class NodeMaterial extends Material { } + /** + * Setups the hardware clipping if available on the current device. + * + * @param {NodeBuilder} builder - The current node builder. + */ setupHardwareClipping( builder ) { this.hardwareClipping = false; @@ -14980,6 +15711,11 @@ class NodeMaterial extends Material { } + /** + * Setups the depth of this material. + * + * @param {NodeBuilder} builder - The current node builder. + */ setupDepth( builder ) { const { renderer, camera } = builder; @@ -15020,18 +15756,37 @@ class NodeMaterial extends Material { } - setupPositionView() { + /** + * Setups the position node in view space. This method exists + * so derived node materials can modify the implementation e.g. sprite materials. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Node} The position in view space. + */ + setupPositionView( /*builder*/ ) { return modelViewMatrix.mul( positionLocal ).xyz; } - setupModelViewProjection() { + /** + * Setups the position in clip space. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Node} The position in view space. + */ + setupModelViewProjection( /*builder*/ ) { return cameraProjectionMatrix.mul( positionView ); } + /** + * Setups the logic for the vertex stage. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Node} The position in clip space. + */ setupVertex( builder ) { builder.addStack(); @@ -15044,6 +15799,12 @@ class NodeMaterial extends Material { } + /** + * Setups the computation of the position in local space. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Node} The position in local space. + */ setupPosition( builder ) { const { object, geometry } = builder; @@ -15092,6 +15853,12 @@ class NodeMaterial extends Material { } + /** + * Setups the computation of the material's diffuse color. + * + * @param {NodeBuilder} builder - The current node builder. + * @param {BufferGeometry} geometry - The geometry. + */ setupDiffuseColor( { object, geometry } ) { let colorNode = this.colorNode ? vec4( this.colorNode ) : materialColor; @@ -15158,24 +15925,47 @@ class NodeMaterial extends Material { } + /** + * Abstract interface method that can be implemented by derived materials + * to setup material-specific node variables. + * + * @abstract + * @param {NodeBuilder} builder - The current node builder. + */ setupVariants( /*builder*/ ) { // Interface function. } + /** + * Setups the outgoing light node variable + * + * @return {Node} The outgoing light node. + */ setupOutgoingLight() { return ( this.lights === true ) ? vec3( 0 ) : diffuseColor.rgb; } + /** + * Setups the normal node from the material. + * + * @return {Node} The normal node. + */ setupNormal() { return this.normalNode ? vec3( this.normalNode ) : materialNormal; } + /** + * Setups the environment node from the material. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Node} The environment node. + */ setupEnvironment( /*builder*/ ) { let node = null; @@ -15194,6 +15984,12 @@ class NodeMaterial extends Material { } + /** + * Setups the light map node from the material. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Node} The light map node. + */ setupLightMap( builder ) { let node = null; @@ -15208,6 +16004,12 @@ class NodeMaterial extends Material { } + /** + * Setups the lights node based on the scene, environment and material. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {LightsNode} The lights node. + */ setupLights( builder ) { const materialLightsNode = []; @@ -15232,7 +16034,7 @@ class NodeMaterial extends Material { if ( this.aoNode !== null || builder.material.aoMap ) { - const aoNode = this.aoNode !== null ? this.aoNode : materialAOMap; + const aoNode = this.aoNode !== null ? this.aoNode : materialAO; materialLightsNode.push( new AONode( aoNode ) ); @@ -15250,12 +16052,26 @@ class NodeMaterial extends Material { } + /** + * This method should be implemented by most derived materials + * since it defines the material's lighting model. + * + * @abstract + * @param {NodeBuilder} builder - The current node builder. + * @return {LightingModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { // Interface function. } + /** + * Setups the outgoing light node. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Node} The outgoing light node. + */ setupLighting( builder ) { const { material } = builder; @@ -15295,6 +16111,13 @@ class NodeMaterial extends Material { } + /** + * Setups the output node. + * + * @param {NodeBuilder} builder - The current node builder. + * @param {Node} outputNode - The existing output node. + * @return {Node} The output node. + */ setupOutput( builder, outputNode ) { // FOG @@ -15317,6 +16140,13 @@ class NodeMaterial extends Material { } + /** + * Most classic material types have a node pendant e.g. for `MeshBasicMaterial` + * there is `MeshBasicNodeMaterial`. This utility method is intended for + * defining all material properties of the classic type in the node type. + * + * @param {Material} material - The material to copy properties with their values to this node material. + */ setDefaultValues( material ) { // This approach is to reuse the native refreshUniforms* @@ -15351,6 +16181,12 @@ class NodeMaterial extends Material { } + /** + * Serializes this material to JSON. + * + * @param {(Object|String)?} meta - The meta information for serialization. + * @return {Object} The serialized node. + */ toJSON( meta ) { const isRoot = ( meta === undefined || typeof meta === 'string' ); @@ -15410,6 +16246,12 @@ class NodeMaterial extends Material { } + /** + * Copies the properties of the given node material to this instance. + * + * @param {NodeMaterial} source - The material to copy. + * @return {NodeMaterial} A reference to this node material. + */ copy( source ) { this.lightsNode = source.lightsNode; @@ -15444,6 +16286,15 @@ class NodeMaterial extends Material { const _defaultValues$e = /*@__PURE__*/ new PointsMaterial(); +/** + * Unlike WebGL, WebGPU can render point primitives only with a size + * of one pixel. This type node material can be used to mimic the WebGL + * points rendering by rendering small planes via instancing. + * + * This material should be used with {@link InstancedPointsGeometry}. + * + * @augments NodeMaterial + */ class InstancedPointsNodeMaterial extends NodeMaterial { static get type() { @@ -15452,39 +16303,75 @@ class InstancedPointsNodeMaterial extends NodeMaterial { } - constructor( params = {} ) { + /** + * Constructs a new instanced points node material. + * + * @param {Object?} parameters - The configuration parameter. + */ + constructor( parameters = {} ) { super(); - this.lights = false; - - this.useAlphaToCoverage = true; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ + this.isInstancedPointsNodeMaterial = true; - this.useColor = params.vertexColors; + /** + * Whether vertex colors should be used or not. If set to `true`, + * each point instance can receive a custom color value. + * + * @type {Boolean} + * @default false + */ + this.useColor = parameters.vertexColors; + /** + * The points width in pixels. + * + * @type {Number} + * @default 1 + */ this.pointWidth = 1; + /** + * This node can be used to define the colors for each instance. + * + * @type {Node?} + * @default null + */ this.pointColorNode = null; + /** + * This node can be used to define the width for each point instance. + * + * @type {Node?} + * @default null + */ this.pointWidthNode = null; + this._useAlphaToCoverage = true; + this.setDefaultValues( _defaultValues$e ); - this.setValues( params ); + this.setValues( parameters ); } + /** + * Setups the vertex and fragment stage of this node material. + * + * @param {NodeBuilder} builder - The current node builder. + */ setup( builder ) { - this.setupShaders( builder ); - - super.setup( builder ); - - } - - setupShaders( { renderer } ) { + const { renderer } = builder; - const useAlphaToCoverage = this.alphaToCoverage; + const useAlphaToCoverage = this._useAlphaToCoverage; const useColor = this.useColor; this.vertexNode = Fn( () => { @@ -15563,19 +16450,27 @@ class InstancedPointsNodeMaterial extends NodeMaterial { } )(); + super.setup( builder ); + } + /** + * Whether alpha to coverage should be used or not. + * + * @type {Boolean} + * @default true + */ get alphaToCoverage() { - return this.useAlphaToCoverage; + return this._useAlphaToCoverage; } set alphaToCoverage( value ) { - if ( this.useAlphaToCoverage !== value ) { + if ( this._useAlphaToCoverage !== value ) { - this.useAlphaToCoverage = value; + this._useAlphaToCoverage = value; this.needsUpdate = true; } @@ -15586,6 +16481,11 @@ class InstancedPointsNodeMaterial extends NodeMaterial { const _defaultValues$d = /*@__PURE__*/ new LineBasicMaterial(); +/** + * Node material version of `LineBasicMaterial`. + * + * @augments NodeMaterial + */ class LineBasicNodeMaterial extends NodeMaterial { static get type() { @@ -15594,14 +16494,24 @@ class LineBasicNodeMaterial extends NodeMaterial { } + /** + * Constructs a new line basic node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isLineBasicNodeMaterial = true; - this.lights = false; - this.setDefaultValues( _defaultValues$d ); this.setValues( parameters ); @@ -15612,6 +16522,11 @@ class LineBasicNodeMaterial extends NodeMaterial { const _defaultValues$c = /*@__PURE__*/ new LineDashedMaterial(); +/** + * Node material version of `LineDashedMaterial`. + * + * @augments NodeMaterial + */ class LineDashedNodeMaterial extends NodeMaterial { static get type() { @@ -15620,33 +16535,101 @@ class LineDashedNodeMaterial extends NodeMaterial { } + /** + * Constructs a new line dashed node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isLineDashedNodeMaterial = true; - this.lights = false; - this.setDefaultValues( _defaultValues$c ); + /** + * The dash offset. + * + * @type {Number} + * @default 0 + */ this.dashOffset = 0; + /** + * The offset of dash materials is by default inferred from the `dashOffset` + * property. This node property allows to overwrite the default + * and define the offset with a node instead. + * + * If you don't want to overwrite the offset but modify the existing + * value instead, use {@link module:MaterialNode.materialLineDashOffset}. + * + * @type {Node?} + * @default null + */ this.offsetNode = null; + + /** + * The scale of dash materials is by default inferred from the `scale` + * property. This node property allows to overwrite the default + * and define the scale with a node instead. + * + * If you don't want to overwrite the scale but modify the existing + * value instead, use {@link module:MaterialNode.materialLineScale}. + * + * @type {Node?} + * @default null + */ this.dashScaleNode = null; + + /** + * The dash size of dash materials is by default inferred from the `dashSize` + * property. This node property allows to overwrite the default + * and define the dash size with a node instead. + * + * If you don't want to overwrite the dash size but modify the existing + * value instead, use {@link module:MaterialNode.materialLineDashSize}. + * + * @type {Node?} + * @default null + */ this.dashSizeNode = null; + + /** + * The gap size of dash materials is by default inferred from the `gapSize` + * property. This node property allows to overwrite the default + * and define the gap size with a node instead. + * + * If you don't want to overwrite the gap size but modify the existing + * value instead, use {@link module:MaterialNode.materialLineGapSize}. + * + * @type {Node?} + * @default null + */ this.gapSizeNode = null; this.setValues( parameters ); } - setupVariants() { + /** + * Setups the dash specific node variables. + * + * @param {NodeBuilder} builder - The current node builder. + */ + setupVariants( /* builder */ ) { - const offsetNode = this.offsetNode ? float( this.offsetNodeNode ) : materialLineDashOffset; + const offsetNode = this.offsetNode ? float( this.offsetNode ) : materialLineDashOffset; const dashScaleNode = this.dashScaleNode ? float( this.dashScaleNode ) : materialLineScale; const dashSizeNode = this.dashSizeNode ? float( this.dashSizeNode ) : materialLineDashSize; - const gapSizeNode = this.dashSizeNode ? float( this.dashGapNode ) : materialLineGapSize; + const gapSizeNode = this.gapSizeNode ? float( this.gapSizeNode ) : materialLineGapSize; dashSize.assign( dashSizeNode ); gapSize.assign( gapSizeNode ); @@ -15717,6 +16700,12 @@ const viewportSharedTexture = /*@__PURE__*/ nodeProxy( ViewportSharedTextureNode const _defaultValues$b = /*@__PURE__*/ new LineDashedMaterial(); +/** + * This node material can be used to render lines with a size larger than one + * by representing them as instanced meshes. + * + * @augments NodeMaterial + */ class Line2NodeMaterial extends NodeMaterial { static get type() { @@ -15725,49 +16714,120 @@ class Line2NodeMaterial extends NodeMaterial { } - constructor( params = {} ) { + /** + * Constructs a new node material for wide line rendering. + * + * @param {Object?} parameters - The configuration parameter. + */ + constructor( parameters = {} ) { super(); - this.lights = false; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ + this.isLine2NodeMaterial = true; this.setDefaultValues( _defaultValues$b ); - this.useAlphaToCoverage = true; - this.useColor = params.vertexColors; - this.useDash = params.dashed; - this.useWorldUnits = false; + /** + * Whether vertex colors should be used or not. + * + * @type {Boolean} + * @default false + */ + this.useColor = parameters.vertexColors; + /** + * The dash offset. + * + * @type {Number} + * @default 0 + */ this.dashOffset = 0; + + /** + * The line width. + * + * @type {Number} + * @default 0 + */ this.lineWidth = 1; + /** + * Defines the lines color. + * + * @type {Node?} + * @default null + */ this.lineColorNode = null; + /** + * Defines the offset. + * + * @type {Node?} + * @default null + */ this.offsetNode = null; + + /** + * Defines the dash scale. + * + * @type {Node?} + * @default null + */ this.dashScaleNode = null; + + /** + * Defines the dash size. + * + * @type {Node?} + * @default null + */ this.dashSizeNode = null; + + /** + * Defines the gap size. + * + * @type {Node?} + * @default null + */ this.gapSizeNode = null; + /** + * Blending is set to `NoBlending` since transparency + * is not supported, yet. + * + * @type {Number} + * @default 0 + */ this.blending = NoBlending; - this.setValues( params ); + this._useDash = parameters.dashed; + this._useAlphaToCoverage = true; + this._useWorldUnits = false; + + this.setValues( parameters ); } + /** + * Setups the vertex and fragment stage of this node material. + * + * @param {NodeBuilder} builder - The current node builder. + */ setup( builder ) { - this.setupShaders( builder ); - - super.setup( builder ); - - } - - setupShaders( { renderer } ) { + const { renderer } = builder; - const useAlphaToCoverage = this.alphaToCoverage; + const useAlphaToCoverage = this._useAlphaToCoverage; const useColor = this.useColor; - const useDash = this.dashed; - const useWorldUnits = this.worldUnits; + const useDash = this._useDash; + const useWorldUnits = this._useWorldUnits; const trimSegment = Fn( ( { start, end } ) => { @@ -16095,56 +17155,74 @@ class Line2NodeMaterial extends NodeMaterial { } - } + super.setup( builder ); + } + /** + * Whether the lines should sized in world units or not. + * When set to `false` the unit is pixel. + * + * @type {Boolean} + * @default false + */ get worldUnits() { - return this.useWorldUnits; + return this._useWorldUnits; } set worldUnits( value ) { - if ( this.useWorldUnits !== value ) { + if ( this._useWorldUnits !== value ) { - this.useWorldUnits = value; + this._useWorldUnits = value; this.needsUpdate = true; } } - + /** + * Whether the lines should be dashed or not. + * + * @type {Boolean} + * @default false + */ get dashed() { - return this.useDash; + return this._useDash; } set dashed( value ) { - if ( this.useDash !== value ) { + if ( this._useDash !== value ) { - this.useDash = value; + this._useDash = value; this.needsUpdate = true; } } - + /** + * Whether alpha to coverage should be used or not. + * + * @type {Boolean} + * @default true + */ get alphaToCoverage() { - return this.useAlphaToCoverage; + return this._useAlphaToCoverage; } set alphaToCoverage( value ) { - if ( this.useAlphaToCoverage !== value ) { + if ( this._useAlphaToCoverage !== value ) { - this.useAlphaToCoverage = value; + this._useAlphaToCoverage = value; this.needsUpdate = true; } @@ -16175,6 +17253,11 @@ const colorToDirection = ( node ) => nodeObject( node ).mul( 2.0 ).sub( 1 ); const _defaultValues$a = /*@__PURE__*/ new MeshNormalMaterial(); +/** + * Node material version of `MeshNormalMaterial`. + * + * @augments NodeMaterial + */ class MeshNormalNodeMaterial extends NodeMaterial { static get type() { @@ -16183,12 +17266,22 @@ class MeshNormalNodeMaterial extends NodeMaterial { } + /** + * Constructs a new mesh normal node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); - this.lights = false; - + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshNormalNodeMaterial = true; this.setDefaultValues( _defaultValues$a ); @@ -16197,6 +17290,10 @@ class MeshNormalNodeMaterial extends NodeMaterial { } + /** + * Overwrites the default implementation by computing the diffuse color + * based on the normal data. + */ setupDiffuseColor() { const opacityNode = this.opacityNode ? float( this.opacityNode ) : materialOpacity; @@ -16270,6 +17367,12 @@ const equirectUV = /*@__PURE__*/ nodeProxy( EquirectUVNode ); // @TODO: Consider rename WebGLCubeRenderTarget to just CubeRenderTarget +/** + * This class represents a cube render target. It is a special version + * of `WebGLCubeRenderTarget` which is compatible with `WebGPURenderer`. + * + * @augments WebGLCubeRenderTarget + */ class CubeRenderTarget extends WebGLCubeRenderTarget { constructor( size = 1, options = {} ) { @@ -16280,6 +17383,13 @@ class CubeRenderTarget extends WebGLCubeRenderTarget { } + /** + * Converts the given equirectangular texture to a cube map. + * + * @param {Renderer} renderer - The renderer. + * @param {Texture} texture - The equirectangular texture. + * @return {CubeRenderTarget} A reference to this cube render target. + */ fromEquirectangularTexture( renderer, texture$1 ) { const currentMinFilter = texture$1.minFilter; @@ -16823,6 +17933,11 @@ class BasicLightingModel extends LightingModel { const _defaultValues$9 = /*@__PURE__*/ new MeshBasicMaterial(); +/** + * Node material version of `MeshBasicMaterial`. + * + * @augments NodeMaterial + */ class MeshBasicNodeMaterial extends NodeMaterial { static get type() { @@ -16831,12 +17946,32 @@ class MeshBasicNodeMaterial extends NodeMaterial { } + /** + * Constructs a new mesh basic node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshBasicNodeMaterial = true; + /** + * Although the basic material is by definition unlit, we set + * this property to `true` since we use a lighting model to compute + * the outgoing light of the fragment shader. + * + * @type {Boolean} + * @default true + */ this.lights = true; this.setDefaultValues( _defaultValues$9 ); @@ -16845,12 +17980,25 @@ class MeshBasicNodeMaterial extends NodeMaterial { } + /** + * Basic materials are not affected by normal and bump maps so we + * return by default {@link module:Normal.normalView}. + * + * @return {Node} The normal node. + */ setupNormal() { return normalView; // see #28839 } + /** + * Overwritten since this type of material uses {@link BasicEnvironmentNode} + * to implement the default environment mapping. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {BasicEnvironmentNode?} The environment node. + */ setupEnvironment( builder ) { const envNode = super.setupEnvironment( builder ); @@ -16859,6 +18007,13 @@ class MeshBasicNodeMaterial extends NodeMaterial { } + /** + * This method must be overwritten since light maps are evaluated + * with a special scaling factor for basic materials. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {BasicLightMapNode?} The light map node. + */ setupLightMap( builder ) { let node = null; @@ -16873,12 +18028,23 @@ class MeshBasicNodeMaterial extends NodeMaterial { } + /** + * The material overwrites this method because `lights` is set to `true` but + * we still want to return the diffuse color as the outgoing light. + * + * @return {Node} The outgoing light node. + */ setupOutgoingLight() { return diffuseColor.rgb; } + /** + * Setups the lighting model. + * + * @return {BasicLightingModel} The lighting model. + */ setupLightingModel() { return new BasicLightingModel(); @@ -16999,6 +18165,11 @@ class PhongLightingModel extends BasicLightingModel { const _defaultValues$8 = /*@__PURE__*/ new MeshLambertMaterial(); +/** + * Node material version of `MeshLambertMaterial`. + * + * @augments NodeMaterial + */ class MeshLambertNodeMaterial extends NodeMaterial { static get type() { @@ -17007,12 +18178,30 @@ class MeshLambertNodeMaterial extends NodeMaterial { } + /** + * Constructs a new mesh lambert node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshLambertNodeMaterial = true; + /** + * Set to `true` because lambert materials react on lights. + * + * @type {Boolean} + * @default true + */ this.lights = true; this.setDefaultValues( _defaultValues$8 ); @@ -17021,6 +18210,13 @@ class MeshLambertNodeMaterial extends NodeMaterial { } + /** + * Overwritten since this type of material uses {@link BasicEnvironmentNode} + * to implement the default environment mapping. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {BasicEnvironmentNode?} The environment node. + */ setupEnvironment( builder ) { const envNode = super.setupEnvironment( builder ); @@ -17029,6 +18225,11 @@ class MeshLambertNodeMaterial extends NodeMaterial { } + /** + * Setups the lighting model. + * + * @return {PhongLightingModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { return new PhongLightingModel( false ); // ( specular ) -> force lambert @@ -17039,6 +18240,11 @@ class MeshLambertNodeMaterial extends NodeMaterial { const _defaultValues$7 = /*@__PURE__*/ new MeshPhongMaterial(); +/** + * Node material version of `MeshPhongMaterial`. + * + * @augments NodeMaterial + */ class MeshPhongNodeMaterial extends NodeMaterial { static get type() { @@ -17047,15 +18253,56 @@ class MeshPhongNodeMaterial extends NodeMaterial { } + /** + * Constructs a new mesh lambert node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshPhongNodeMaterial = true; + /** + * Set to `true` because phong materials react on lights. + * + * @type {Boolean} + * @default true + */ this.lights = true; + /** + * The shininess of phong materials is by default inferred from the `shininess` + * property. This node property allows to overwrite the default + * and define the shininess with a node instead. + * + * If you don't want to overwrite the shininess but modify the existing + * value instead, use {@link module:MaterialNode.materialShininess}. + * + * @type {Node?} + * @default null + */ this.shininessNode = null; + + /** + * The specular color of phong materials is by default inferred from the + * `specular` property. This node property allows to overwrite the default + * and define the specular color with a node instead. + * + * If you don't want to overwrite the specular color but modify the existing + * value instead, use {@link module:MaterialNode.materialSpecular}. + * + * @type {Node?} + * @default null + */ this.specularNode = null; this.setDefaultValues( _defaultValues$7 ); @@ -17064,6 +18311,13 @@ class MeshPhongNodeMaterial extends NodeMaterial { } + /** + * Overwritten since this type of material uses {@link BasicEnvironmentNode} + * to implement the default environment mapping. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {BasicEnvironmentNode?} The environment node. + */ setupEnvironment( builder ) { const envNode = super.setupEnvironment( builder ); @@ -17072,13 +18326,23 @@ class MeshPhongNodeMaterial extends NodeMaterial { } + /** + * Setups the lighting model. + * + * @return {PhongLightingModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { return new PhongLightingModel(); } - setupVariants() { + /** + * Setups the phong specific node variables. + * + * @param {NodeBuilder} builder - The current node builder. + */ + setupVariants( /*builder*/ ) { // SHININESS @@ -19140,6 +20404,11 @@ const createIrradianceContext = ( normalWorldNode ) => { const _defaultValues$6 = /*@__PURE__*/ new MeshStandardMaterial(); +/** + * Node material version of `MeshStandardMaterial`. + * + * @augments NodeMaterial + */ class MeshStandardNodeMaterial extends NodeMaterial { static get type() { @@ -19148,17 +20417,69 @@ class MeshStandardNodeMaterial extends NodeMaterial { } + /** + * Constructs a new mesh standard node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshStandardNodeMaterial = true; + /** + * Set to `true` because standard materials react on lights. + * + * @type {Boolean} + * @default true + */ this.lights = true; + /** + * The emissive color of standard materials is by default inferred from the `emissive`, + * `emissiveIntensity` and `emissiveMap` properties. This node property allows to + * overwrite the default and define the emissive color with a node instead. + * + * If you don't want to overwrite the emissive color but modify the existing + * value instead, use {@link module:MaterialNode.materialEmissive}. + * + * @type {Node?} + * @default null + */ this.emissiveNode = null; + /** + * The metalness of standard materials is by default inferred from the `metalness`, + * and `metalnessMap` properties. This node property allows to + * overwrite the default and define the metalness with a node instead. + * + * If you don't want to overwrite the metalness but modify the existing + * value instead, use {@link module:MaterialNode.materialMetalness}. + * + * @type {Node?} + * @default null + */ this.metalnessNode = null; + + /** + * The roughness of standard materials is by default inferred from the `roughness`, + * and `roughnessMap` properties. This node property allows to + * overwrite the default and define the roughness with a node instead. + * + * If you don't want to overwrite the roughness but modify the existing + * value instead, use {@link module:MaterialNode.materialRoughness}. + * + * @type {Node?} + * @default null + */ this.roughnessNode = null; this.setDefaultValues( _defaultValues$6 ); @@ -19167,6 +20488,14 @@ class MeshStandardNodeMaterial extends NodeMaterial { } + /** + * Overwritten since this type of material uses {@link EnvironmentNode} + * to implement the PBR (PMREM based) environment mapping. Besides, the + * method honors `Scene.environment`. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {EnvironmentNode?} The environment node. + */ setupEnvironment( builder ) { let envNode = super.setupEnvironment( builder ); @@ -19181,12 +20510,20 @@ class MeshStandardNodeMaterial extends NodeMaterial { } + /** + * Setups the lighting model. + * + * @return {PhysicalLightingModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { return new PhysicalLightingModel(); } + /** + * Setups the specular related node variables. + */ setupSpecular() { const specularColorNode = mix( vec3( 0.04 ), diffuseColor.rgb, metalness ); @@ -19196,6 +20533,11 @@ class MeshStandardNodeMaterial extends NodeMaterial { } + /** + * Setups the standard specific node variables. + * + * @param {NodeBuilder} builder - The current node builder. + */ setupVariants() { // METALNESS @@ -19236,6 +20578,11 @@ class MeshStandardNodeMaterial extends NodeMaterial { const _defaultValues$5 = /*@__PURE__*/ new MeshPhysicalMaterial(); +/** + * Node material version of `MeshPhysicalMaterial`. + * + * @augments MeshStandardNodeMaterial + */ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial { static get type() { @@ -19244,33 +20591,243 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial { } + /** + * Constructs a new mesh physical node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshPhysicalNodeMaterial = true; + /** + * The clearcoat of physical materials is by default inferred from the `clearcoat` + * and `clearcoatMap` properties. This node property allows to overwrite the default + * and define the clearcoat with a node instead. + * + * If you don't want to overwrite the clearcoat but modify the existing + * value instead, use {@link module:MaterialNode.materialClearcoat}. + * + * @type {Node?} + * @default null + */ this.clearcoatNode = null; + + /** + * The clearcoat roughness of physical materials is by default inferred from the `clearcoatRoughness` + * and `clearcoatRoughnessMap` properties. This node property allows to overwrite the default + * and define the clearcoat roughness with a node instead. + * + * If you don't want to overwrite the clearcoat roughness but modify the existing + * value instead, use {@link module:MaterialNode.materialClearcoatRoughness}. + * + * @type {Node?} + * @default null + */ this.clearcoatRoughnessNode = null; + + /** + * The clearcoat normal of physical materials is by default inferred from the `clearcoatNormalMap` + * property. This node property allows to overwrite the default + * and define the clearcoat normal with a node instead. + * + * If you don't want to overwrite the clearcoat normal but modify the existing + * value instead, use {@link module:MaterialNode.materialClearcoatNormal}. + * + * @type {Node?} + * @default null + */ this.clearcoatNormalNode = null; + /** + * The sheen of physical materials is by default inferred from the `sheen`, `sheenColor` + * and `sheenColorMap` properties. This node property allows to overwrite the default + * and define the sheen with a node instead. + * + * If you don't want to overwrite the sheen but modify the existing + * value instead, use {@link module:MaterialNode.materialSheen}. + * + * @type {Node?} + * @default null + */ this.sheenNode = null; + + /** + * The sheen roughness of physical materials is by default inferred from the `sheenRoughness` and + * `sheenRoughnessMap` properties. This node property allows to overwrite the default + * and define the sheen roughness with a node instead. + * + * If you don't want to overwrite the sheen roughness but modify the existing + * value instead, use {@link module:MaterialNode.materialSheenRoughness}. + * + * @type {Node?} + * @default null + */ this.sheenRoughnessNode = null; + /** + * The iridescence of physical materials is by default inferred from the `iridescence` + * property. This node property allows to overwrite the default + * and define the iridescence with a node instead. + * + * If you don't want to overwrite the iridescence but modify the existing + * value instead, use {@link module:MaterialNode.materialIridescence}. + * + * @type {Node?} + * @default null + */ this.iridescenceNode = null; + + /** + * The iridescence IOR of physical materials is by default inferred from the `iridescenceIOR` + * property. This node property allows to overwrite the default + * and define the iridescence IOR with a node instead. + * + * If you don't want to overwrite the iridescence IOR but modify the existing + * value instead, use {@link module:MaterialNode.materialIridescenceIOR}. + * + * @type {Node?} + * @default null + */ this.iridescenceIORNode = null; + + /** + * The iridescence thickness of physical materials is by default inferred from the `iridescenceThicknessRange` + * and `iridescenceThicknessMap` properties. This node property allows to overwrite the default + * and define the iridescence thickness with a node instead. + * + * If you don't want to overwrite the iridescence thickness but modify the existing + * value instead, use {@link module:MaterialNode.materialIridescenceThickness}. + * + * @type {Node?} + * @default null + */ this.iridescenceThicknessNode = null; + /** + * The specular intensity of physical materials is by default inferred from the `specularIntensity` + * and `specularIntensityMap` properties. This node property allows to overwrite the default + * and define the specular intensity with a node instead. + * + * If you don't want to overwrite the specular intensity but modify the existing + * value instead, use {@link module:MaterialNode.materialSpecularIntensity}. + * + * @type {Node?} + * @default null + */ this.specularIntensityNode = null; + + /** + * The specular color of physical materials is by default inferred from the `specularColor` + * and `specularColorMap` properties. This node property allows to overwrite the default + * and define the specular color with a node instead. + * + * If you don't want to overwrite the specular color but modify the existing + * value instead, use {@link module:MaterialNode.materialSpecularColor}. + * + * @type {Node?} + * @default null + */ this.specularColorNode = null; + /** + * The ior of physical materials is by default inferred from the `ior` + * property. This node property allows to overwrite the default + * and define the ior with a node instead. + * + * If you don't want to overwrite the ior but modify the existing + * value instead, use {@link module:MaterialNode.materialIOR}. + * + * @type {Node?} + * @default null + */ this.iorNode = null; + + /** + * The transmission of physical materials is by default inferred from the `transmission` and + * `transmissionMap` properties. This node property allows to overwrite the default + * and define the transmission with a node instead. + * + * If you don't want to overwrite the transmission but modify the existing + * value instead, use {@link module:MaterialNode.materialTransmission}. + * + * @type {Node?} + * @default null + */ this.transmissionNode = null; + + /** + * The thickness of physical materials is by default inferred from the `thickness` and + * `thicknessMap` properties. This node property allows to overwrite the default + * and define the thickness with a node instead. + * + * If you don't want to overwrite the thickness but modify the existing + * value instead, use {@link module:MaterialNode.materialThickness}. + * + * @type {Node?} + * @default null + */ this.thicknessNode = null; + + /** + * The attenuation distance of physical materials is by default inferred from the + * `attenuationDistance` property. This node property allows to overwrite the default + * and define the attenuation distance with a node instead. + * + * If you don't want to overwrite the attenuation distance but modify the existing + * value instead, use {@link module:MaterialNode.materialAttenuationDistance}. + * + * @type {Node?} + * @default null + */ this.attenuationDistanceNode = null; + + /** + * The attenuation color of physical materials is by default inferred from the + * `attenuationColor` property. This node property allows to overwrite the default + * and define the attenuation color with a node instead. + * + * If you don't want to overwrite the attenuation color but modify the existing + * value instead, use {@link module:MaterialNode.materialAttenuationColor}. + * + * @type {Node?} + * @default null + */ this.attenuationColorNode = null; + + /** + * The dispersion of physical materials is by default inferred from the + * `dispersion` property. This node property allows to overwrite the default + * and define the dispersion with a node instead. + * + * If you don't want to overwrite the dispersion but modify the existing + * value instead, use {@link module:MaterialNode.materialDispersion}. + * + * @type {Node?} + * @default null + */ this.dispersionNode = null; + /** + * The anisotropy of physical materials is by default inferred from the + * `anisotropy` property. This node property allows to overwrite the default + * and define the anisotropy with a node instead. + * + * If you don't want to overwrite the anisotropy but modify the existing + * value instead, use {@link module:MaterialNode.materialAnisotropy}. + * + * @type {Node?} + * @default null + */ this.anisotropyNode = null; this.setDefaultValues( _defaultValues$5 ); @@ -19279,42 +20836,81 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial { } + /** + * Whether the lighting model should use clearcoat or not. + * + * @type {Boolean} + * @default true + */ get useClearcoat() { return this.clearcoat > 0 || this.clearcoatNode !== null; } + /** + * Whether the lighting model should use iridescence or not. + * + * @type {Boolean} + * @default true + */ get useIridescence() { return this.iridescence > 0 || this.iridescenceNode !== null; } + /** + * Whether the lighting model should use sheen or not. + * + * @type {Boolean} + * @default true + */ get useSheen() { return this.sheen > 0 || this.sheenNode !== null; } + /** + * Whether the lighting model should use anisotropy or not. + * + * @type {Boolean} + * @default true + */ get useAnisotropy() { return this.anisotropy > 0 || this.anisotropyNode !== null; } + /** + * Whether the lighting model should use transmission or not. + * + * @type {Boolean} + * @default true + */ get useTransmission() { return this.transmission > 0 || this.transmissionNode !== null; } + /** + * Whether the lighting model should use dispersion or not. + * + * @type {Boolean} + * @default true + */ get useDispersion() { return this.dispersion > 0 || this.dispersionNode !== null; } + /** + * Setups the specular related node variables. + */ setupSpecular() { const iorNode = this.iorNode ? float( this.iorNode ) : materialIOR; @@ -19325,12 +20921,22 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial { } + /** + * Setups the lighting model. + * + * @return {PhysicalLightingModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { return new PhysicalLightingModel( this.useClearcoat, this.useSheen, this.useIridescence, this.useAnisotropy, this.useTransmission, this.useDispersion ); } + /** + * Setups the physical specific node variables. + * + * @param {NodeBuilder} builder - The current node builder. + */ setupVariants( builder ) { super.setupVariants( builder ); @@ -19426,6 +21032,11 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial { } + /** + * Setups the clearcoat normal node. + * + * @return {Node} The clearcoat normal. + */ setupClearcoatNormal() { return this.clearcoatNormalNode ? vec3( this.clearcoatNormalNode ) : materialClearcoatNormal; @@ -19470,16 +21081,49 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial { } +/** @module MeshSSSNodeMaterial **/ + +/** + * Represents the lighting model for {@link MeshSSSNodeMaterial}. + * + * @augments PhysicalLightingModel + */ class SSSLightingModel extends PhysicalLightingModel { - constructor( useClearcoat, useSheen, useIridescence, useSSS ) { + /** + * Constructs a new physical lighting model. + * + * @param {Boolean} [clearcoat=false] - Whether clearcoat is supported or not. + * @param {Boolean} [sheen=false] - Whether sheen is supported or not. + * @param {Boolean} [iridescence=false] - Whether iridescence is supported or not. + * @param {Boolean} [anisotropy=false] - Whether anisotropy is supported or not. + * @param {Boolean} [transmission=false] - Whether transmission is supported or not. + * @param {Boolean} [dispersion=false] - Whether dispersion is supported or not. + * @param {Boolean} [sss=false] - Whether SSS is supported or not. + */ + constructor( clearcoat = false, sheen = false, iridescence = false, anisotropy = false, transmission = false, dispersion = false, sss = false ) { - super( useClearcoat, useSheen, useIridescence ); + super( clearcoat, sheen, iridescence, anisotropy, transmission, dispersion ); - this.useSSS = useSSS; + /** + * Whether the lighting model should use SSS or not. + * + * @type {Boolean} + * @default false + */ + this.useSSS = sss; } + /** + * Extends the default implementation with a SSS term. + * + * Reference: [Approximating Translucency for a Fast, Cheap and Convincing Subsurface Scattering Look]{@link https://colinbarrebrisebois.com/2011/03/07/gdc-2011-approximating-translucency-for-a-fast-cheap-and-convincing-subsurface-scattering-look/} + * + * @param {Object} input - The input data. + * @param {StackNode} stack - The current stack. + * @param {NodeBuilder} builder - The current node builder. + */ direct( { lightDirection, lightColor, reflectedLight }, stack, builder ) { if ( this.useSSS === true ) { @@ -19502,6 +21146,12 @@ class SSSLightingModel extends PhysicalLightingModel { } +/** + * This node material is an experimental extension of {@link MeshPhysicalNodeMaterial} + * that implements a Subsurface scattering (SSS) term. + * + * @augments MeshPhysicalNodeMaterial + */ class MeshSSSNodeMaterial extends MeshPhysicalNodeMaterial { static get type() { @@ -19510,28 +21160,80 @@ class MeshSSSNodeMaterial extends MeshPhysicalNodeMaterial { } + /** + * Constructs a new mesh SSS node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super( parameters ); + /** + * Represents the thickness color. + * + * @type {Node?} + * @default null + */ this.thicknessColorNode = null; + + /** + * Represents the distortion factor. + * + * @type {Node?} + */ this.thicknessDistortionNode = float( 0.1 ); + + /** + * Represents the thickness ambient factor. + * + * @type {Node?} + */ this.thicknessAmbientNode = float( 0.0 ); + + /** + * Represents the thickness attenuation. + * + * @type {Node?} + */ this.thicknessAttenuationNode = float( .1 ); + + /** + * Represents the thickness power. + * + * @type {Node?} + */ this.thicknessPowerNode = float( 2.0 ); + + /** + * Represents the thickness scale. + * + * @type {Node?} + */ this.thicknessScaleNode = float( 10.0 ); } + /** + * Whether the lighting model should use SSS or not. + * + * @type {Boolean} + * @default true + */ get useSSS() { return this.thicknessColorNode !== null; } + /** + * Setups the lighting model. + * + * @return {SSSLightingModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { - return new SSSLightingModel( this.useClearcoat, this.useSheen, this.useIridescence, this.useSSS ); + return new SSSLightingModel( this.useClearcoat, this.useSheen, this.useIridescence, this.useAnisotropy, this.useTransmission, this.useDispersion, this.useSSS ); } @@ -19614,6 +21316,11 @@ class ToonLightingModel extends LightingModel { const _defaultValues$4 = /*@__PURE__*/ new MeshToonMaterial(); +/** + * Node material version of `MeshToonMaterial`. + * + * @augments NodeMaterial + */ class MeshToonNodeMaterial extends NodeMaterial { static get type() { @@ -19622,12 +21329,30 @@ class MeshToonNodeMaterial extends NodeMaterial { } + /** + * Constructs a new mesh toon node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshToonNodeMaterial = true; + /** + * Set to `true` because toon materials react on lights. + * + * @type {Boolean} + * @default true + */ this.lights = true; this.setDefaultValues( _defaultValues$4 ); @@ -19636,6 +21361,11 @@ class MeshToonNodeMaterial extends NodeMaterial { } + /** + * Setups the lighting model. + * + * @return {ToonLightingModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { return new ToonLightingModel(); @@ -19690,6 +21420,11 @@ const matcapUV = /*@__PURE__*/ nodeImmutable( MatcapUVNode ); const _defaultValues$3 = /*@__PURE__*/ new MeshMatcapMaterial(); +/** + * Node material version of `MeshMatcapMaterial`. + * + * @augments NodeMaterial + */ class MeshMatcapNodeMaterial extends NodeMaterial { static get type() { @@ -19698,12 +21433,22 @@ class MeshMatcapNodeMaterial extends NodeMaterial { } + /** + * Constructs a new mesh normal node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); - this.lights = false; - + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshMatcapNodeMaterial = true; this.setDefaultValues( _defaultValues$3 ); @@ -19712,6 +21457,11 @@ class MeshMatcapNodeMaterial extends NodeMaterial { } + /** + * Setups the matcap specific node variables. + * + * @param {NodeBuilder} builder - The current node builder. + */ setupVariants( builder ) { const uv = matcapUV; @@ -19736,6 +21486,16 @@ class MeshMatcapNodeMaterial extends NodeMaterial { const _defaultValues$2 = /*@__PURE__*/ new PointsMaterial(); +/** + * Node material version of `PointsMaterial`. + * + * Since WebGPU can render point primitives only with a size of one pixel, + * this material type does not evaluate the `size` and `sizeAttenuation` + * property of `PointsMaterial`. Use {@link InstancedPointsNodeMaterial} + * instead if you need points with a size larger than one pixel. + * + * @augments NodeMaterial + */ class PointsNodeMaterial extends NodeMaterial { static get type() { @@ -19744,31 +21504,30 @@ class PointsNodeMaterial extends NodeMaterial { } + /** + * Constructs a new points node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isPointsNodeMaterial = true; - this.lights = false; - this.transparent = true; - - this.sizeNode = null; - this.setDefaultValues( _defaultValues$2 ); this.setValues( parameters ); } - copy( source ) { - - this.sizeNode = source.sizeNode; - - return super.copy( source ); - - } - } /** @module RotateNode **/ @@ -19872,6 +21631,11 @@ const rotate = /*@__PURE__*/ nodeProxy( RotateNode ); const _defaultValues$1 = /*@__PURE__*/ new SpriteMaterial(); +/** + * Node material version of `SpriteMaterial`. + * + * @augments NodeMaterial + */ class SpriteNodeMaterial extends NodeMaterial { static get type() { @@ -19880,17 +21644,66 @@ class SpriteNodeMaterial extends NodeMaterial { } + /** + * Constructs a new sprite node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isSpriteNodeMaterial = true; - this.lights = false; this._useSizeAttenuation = true; + /** + * This property makes it possible to define the position of the sprite with a + * node. That can be useful when the material is used with instanced rendering + * and node data are defined with an instanced attribute node: + * ```js + * const positionAttribute = new InstancedBufferAttribute( new Float32Array( positions ), 3 ); + * material.positionNode = instancedBufferAttribute( positionAttribute ); + * ``` + * Another possibility is to compute the instanced data with a compute shader: + * ```js + * const positionBuffer = instancedArray( particleCount, 'vec3' ); + * particleMaterial.positionNode = positionBuffer.toAttribute(); + * ``` + * + * @type {Node?} + * @default null + */ this.positionNode = null; + + /** + * The rotation of sprite materials is by default inferred from the `rotation`, + * property. This node property allows to overwrite the default and define + * the rotation with a node instead. + * + * If you don't want to overwrite the rotation but modify the existing + * value instead, use {@link module:MaterialNode.materialRotation}. + * + * @type {Node?} + * @default null + */ this.rotationNode = null; + + /** + * This node property provides an additional way to scale sprites next to + * `Object3D.scale`. The scale transformation based in `Object3D.scale` + * is multiplied with the scale value of this node in the vertex shader. + * + * @type {Node?} + * @default null + */ this.scaleNode = null; this.setDefaultValues( _defaultValues$1 ); @@ -19899,14 +21712,19 @@ class SpriteNodeMaterial extends NodeMaterial { } + /** + * Setups the position node in view space. This method implements + * the sprite specific vertex shader. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Node} The position in view space. + */ setupPositionView( builder ) { const { object, camera } = builder; const sizeAttenuation = this.sizeAttenuation; - // < VERTEX STAGE > - const { positionNode, rotationNode, scaleNode } = this; const mvPosition = modelViewMatrix.mul( vec3( positionNode || 0 ) ); @@ -19919,7 +21737,7 @@ class SpriteNodeMaterial extends NodeMaterial { } - if ( ! sizeAttenuation ) { + if ( sizeAttenuation === false ) { if ( camera.isPerspectiveCamera ) { @@ -19938,7 +21756,7 @@ class SpriteNodeMaterial extends NodeMaterial { if ( object.center && object.center.isVector2 === true ) { - const center = reference$1( 'center', 'vec2' ); + const center = reference$1( 'center', 'vec2', object ); alignedPosition = alignedPosition.sub( center.sub( 0.5 ) ); @@ -19964,6 +21782,12 @@ class SpriteNodeMaterial extends NodeMaterial { } + /** + * Whether to use size attenuation or not. + * + * @type {Boolean} + * @default true + */ get sizeAttenuation() { return this._useSizeAttenuation; @@ -20034,6 +21858,11 @@ class ShadowMaskModel extends LightingModel { const _defaultValues = /*@__PURE__*/ new ShadowMaterial(); +/** + * Node material version of `ShadowMaterial`. + * + * @augments NodeMaterial + */ class ShadowNodeMaterial extends NodeMaterial { static get type() { @@ -20042,12 +21871,31 @@ class ShadowNodeMaterial extends NodeMaterial { } + /** + * Constructs a new shadow node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isShadowNodeMaterial = true; + /** + * Set to `true` because so it's possible to implement + * the shadow mask effect. + * + * @type {Boolean} + * @default true + */ this.lights = true; this.setDefaultValues( _defaultValues ); @@ -20056,6 +21904,11 @@ class ShadowNodeMaterial extends NodeMaterial { } + /** + * Setups the lighting model. + * + * @return {ShadowMaskModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { return new ShadowMaskModel(); @@ -20188,6 +22041,22 @@ class Texture3DNode extends TextureNode { */ setupUV( builder, uvNode ) { + const texture = this.value; + + if ( builder.isFlipY() && ( texture.isRenderTargetTexture === true || texture.isFramebufferTexture === true ) ) { + + if ( this.sampler ) { + + uvNode = uvNode.flipY(); + + } else { + + uvNode = uvNode.setY( int( textureSize( this, this.levelNode ).y ).sub( uvNode.y ).sub( 1 ) ); + + } + + } + return uvNode; } @@ -20230,6 +22099,14 @@ class Texture3DNode extends TextureNode { */ const texture3D = /*@__PURE__*/ nodeProxy( Texture3DNode ); +/** @module VolumeNodeMaterial **/ + +/** + * Node material intended for volume rendering. The volumetric data are + * defined with an instance of {@link Data3DTexture}. + * + * @augments NodeMaterial + */ class VolumeNodeMaterial extends NodeMaterial { static get type() { @@ -20238,18 +22115,85 @@ class VolumeNodeMaterial extends NodeMaterial { } - constructor( params = {} ) { + /** + * Constructs a new volume node material. + * + * @param {Object?} parameters - The configuration parameter. + */ + constructor( parameters ) { super(); - this.lights = false; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isVolumeNodeMaterial = true; + + /** + * The base color of the volume. + * + * @type {Color} + * @default 100 + */ + this.base = new Color( 0xffffff ); + + /** + * A 3D data texture holding the volumetric data. + * + * @type {Data3DTexture?} + * @default null + */ + this.map = null; + + /** + * This number of samples for each ray that hits the mesh's surface + * and travels through the volume. + * + * @type {Number} + * @default 100 + */ + this.steps = 100; + + /** + * Callback for {@link VolumeNodeMaterial#testNode}. + * + * @callback testNodeCallback + * @param {Data3DTexture} map - The 3D texture. + * @param {Node} mapValue - The sampled value inside the volume. + * @param {Node} probe - The probe which is the entry point of the ray on the mesh's surface. + * @param {Node} finalColor - The final color. + */ + + /** + * The volume rendering of this material works by shooting rays + * from the camera position through each fragment of the mesh's + * surface and sample the inner volume in a raymarching fashion + * multiple times. + * + * This node can be used to assign a callback function of type `Fn` + * that will be executed per sample. The callback receives the + * texture, the sampled texture value as well as position on the surface + * where the rays enters the volume. The last parameter is a color + * that allows the callback to determine the final color. + * + * @type {testNodeCallback?} + * @default null + */ this.testNode = null; - this.setValues( params ); + this.setValues( parameters ); } + /** + * Setups the vertex and fragment stage of this node material. + * + * @param {NodeBuilder} builder - The current node builder. + */ setup( builder ) { const map = texture3D( this.map, null, 0 ); @@ -20326,19 +22270,65 @@ class VolumeNodeMaterial extends NodeMaterial { } +/** + * This module manages the internal animation loop of the renderer. + * + * @private + */ class Animation { + /** + * Constructs a new animation loop management component. + * + * @param {Nodes} nodes - Renderer component for managing nodes related logic. + * @param {Info} info - Renderer component for managing metrics and monitoring data. + */ constructor( nodes, info ) { + /** + * Renderer component for managing nodes related logic. + * + * @type {Nodes} + */ this.nodes = nodes; + + /** + * Renderer component for managing metrics and monitoring data. + * + * @type {Info} + */ this.info = info; + /** + * A reference to the context from `requestAnimationFrame()` can + * be called (usually `window`). + * + * @type {Window|XRSession} + */ this._context = self; + + /** + * The user-defined animation loop. + * + * @type {Function?} + * @default null + */ this._animationLoop = null; + + /** + * The requestId which is returned from the `requestAnimationFrame()` call. + * Can be used to cancel the stop the animation loop. + * + * @type {Number?} + * @default null + */ this._requestId = null; } + /** + * Starts the internal animation loop. + */ start() { const update = ( time, frame ) => { @@ -20359,6 +22349,9 @@ class Animation { } + /** + * Stops the internal animation loop. + */ stop() { this._context.cancelAnimationFrame( this._requestId ); @@ -20367,18 +22360,31 @@ class Animation { } + /** + * Defines the user-level animation loop. + * + * @param {Function} callback - The animation loop. + */ setAnimationLoop( callback ) { this._animationLoop = callback; } + /** + * Defines the context in which `requestAnimationFrame()` is executed. + * + * @param {Window|XRSession} context - The context to set. + */ setContext( context ) { this._context = context; } + /** + * Frees all internal resources and stops the animation loop. + */ dispose() { this.stop(); @@ -20387,19 +22393,41 @@ class Animation { } +/** + * Data structure for the renderer. It allows defining values + * with chained, hierarchical keys. Keys are meant to be + * objects since the module internally works with Weak Maps + * for performance reasons. + * + * @private + */ class ChainMap { + /** + * Constructs a new Chain Map. + */ constructor() { + /** + * The root Weak Map. + * + * @type {WeakMap} + */ this.weakMap = new WeakMap(); } + /** + * Returns the value for the given array of keys. + * + * @param {Array} keys - List of keys. + * @return {Any} The value. Returns `undefined` if no value was found. + */ get( keys ) { let map = this.weakMap; - for ( let i = 0; i < keys.length; i ++ ) { + for ( let i = 0; i < keys.length - 1; i ++ ) { map = map.get( keys[ i ] ); @@ -20411,11 +22439,18 @@ class ChainMap { } + /** + * Sets the value for the given keys. + * + * @param {Array} keys - List of keys. + * @param {Any} value - The value to set. + * @return {ChainMap} A reference to this Chain Map. + */ set( keys, value ) { let map = this.weakMap; - for ( let i = 0; i < keys.length; i ++ ) { + for ( let i = 0; i < keys.length - 1; i ++ ) { const key = keys[ i ]; @@ -20425,15 +22460,23 @@ class ChainMap { } - return map.set( keys[ keys.length - 1 ], value ); + map.set( keys[ keys.length - 1 ], value ); + + return this; } + /** + * Deletes a value for the given keys. + * + * @param {Array} keys - The keys. + * @return {Boolean} Returns `true` if the value has been removed successfully and `false` if the value has not be found. + */ delete( keys ) { let map = this.weakMap; - for ( let i = 0; i < keys.length; i ++ ) { + for ( let i = 0; i < keys.length - 1; i ++ ) { map = map.get( keys[ i ] ); @@ -20447,7 +22490,7 @@ class ChainMap { } -let _id$8 = 0; +let _id$9 = 0; function getKeys( obj ) { @@ -20483,49 +22526,254 @@ function getKeys( obj ) { } +/** + * A render object is the renderer's representation of single entity that gets drawn + * with a draw command. There is no unique mapping of render objects to 3D objects in the + * scene since render objects also depend from the used material, the current render context + * and the current scene's lighting. + * + * In general, the basic process of the renderer is: + * + * - Analyze the 3D objects in the scene and generate render lists containing render items. + * - Process the render lists by calling one or more render commands for each render item. + * - For each render command, request a render object and perform the draw. + * + * The module provides an interface to get data required for the draw command like the actual + * draw parameters or vertex buffers. It also holds a series of caching related methods since + * creating render objects should only be done when necessary. + * + * @private + */ class RenderObject { + /** + * Constructs a new render object. + * + * @param {Nodes} nodes - Renderer component for managing nodes related logic. + * @param {Geometries} geometries - Renderer component for managing geometries. + * @param {Renderer} renderer - The renderer. + * @param {Object3D} object - The 3D object. + * @param {Material} material - The 3D object's material. + * @param {Scene} scene - The scene the 3D object belongs to. + * @param {Camera} camera - The camera the object should be rendered with. + * @param {LightsNode} lightsNode - The lights node. + * @param {RenderContext} renderContext - The render context. + * @param {ClippingContext} clippingContext - The clipping context. + */ constructor( nodes, geometries, renderer, object, material, scene, camera, lightsNode, renderContext, clippingContext ) { + this.id = _id$9 ++; + + /** + * Renderer component for managing nodes related logic. + * + * @type {Nodes} + * @private + */ this._nodes = nodes; - this._geometries = geometries; - this.id = _id$8 ++; + /** + * Renderer component for managing geometries. + * + * @type {Geometries} + * @private + */ + this._geometries = geometries; + /** + * The renderer. + * + * @type {Renderer} + */ this.renderer = renderer; + + /** + * The 3D object. + * + * @type {Object3D} + */ this.object = object; + + /** + * The 3D object's material. + * + * @type {Material} + */ this.material = material; + + /** + * The scene the 3D object belongs to. + * + * @type {Scene} + */ this.scene = scene; + + /** + * The camera the 3D object should be rendered with. + * + * @type {Camera} + */ this.camera = camera; + + /** + * The lights node. + * + * @type {LightsNode} + */ this.lightsNode = lightsNode; + + /** + * The render context. + * + * @type {RenderContext} + */ this.context = renderContext; + /** + * The 3D object's geometry. + * + * @type {BufferGeometry} + */ this.geometry = object.geometry; + + /** + * The render object's version. + * + * @type {Number} + */ this.version = material.version; + /** + * The draw range of the geometry. + * + * @type {Object?} + * @default null + */ this.drawRange = null; + /** + * An array holding the buffer attributes + * of the render object. This entails attribute + * definitions on geometry and node level. + * + * @type {Array?} + * @default null + */ this.attributes = null; + + /** + * A reference to a render pipeline the render + * object is processed with. + * + * @type {RenderPipeline} + * @default null + */ this.pipeline = null; + + /** + * An array holding the vertex buffers which can + * be buffer attributes but also interleaved buffers. + * + * @type {Array?} + * @default null + */ this.vertexBuffers = null; + + /** + * The parameters for the draw command. + * + * @type {Object?} + * @default null + */ this.drawParams = null; + /** + * If this render object is used inside a render bundle, + * this property points to the respective bundle group. + * + * @type {BundleGroup?} + * @default null + */ this.bundle = null; + /** + * The clipping context. + * + * @type {ClippingContext} + */ this.clippingContext = clippingContext; + + /** + * The clipping context's cache key. + * + * @type {String} + */ this.clippingContextCacheKey = clippingContext !== null ? clippingContext.cacheKey : ''; + /** + * The initial node cache key. + * + * @type {Number} + */ this.initialNodesCacheKey = this.getDynamicCacheKey(); + + /** + * The initial cache key. + * + * @type {Number} + */ this.initialCacheKey = this.getCacheKey(); + /** + * The node builder state. + * + * @type {NodeBuilderState?} + * @private + * @default null + */ this._nodeBuilderState = null; + + /** + * An array of bindings. + * + * @type {Array?} + * @private + * @default null + */ this._bindings = null; + + /** + * Reference to the node material observer. + * + * @type {NodeMaterialObserver?} + * @private + * @default null + */ this._monitor = null; + /** + * An event listener which is defined by `RenderObjects`. It performs + * clean up tasks when `dispose()` on this render object. + * + * @method + */ this.onDispose = null; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isRenderObject = true; + /** + * An event listener which is executed when `dispose()` is called on + * the render object's material. + * + * @method + */ this.onMaterialDispose = () => { this.dispose(); @@ -20536,12 +22784,23 @@ class RenderObject { } - updateClipping( parent ) { + /** + * Updates the clipping context. + * + * @param {ClippingContext} context - The clipping context to set. + */ + updateClipping( context ) { - this.clippingContext = parent; + this.clippingContext = context; } + /** + * Whether the clipping requires an update or not. + * + * @type {Boolean} + * @readonly + */ get clippingNeedsUpdate() { if ( this.clippingContext === null || this.clippingContext.cacheKey === this.clippingContextCacheKey ) return false; @@ -20552,48 +22811,90 @@ class RenderObject { } + /** + * The number of clipping planes defined in context of hardware clipping. + * + * @type {Number} + * @readonly + */ get hardwareClippingPlanes() { return this.material.hardwareClipping === true ? this.clippingContext.unionClippingCount : 0; } + /** + * Returns the node builder state of this render object. + * + * @return {NodeBuilderState} The node builder state. + */ getNodeBuilderState() { return this._nodeBuilderState || ( this._nodeBuilderState = this._nodes.getForRender( this ) ); } + /** + * Returns the node material observer of this render object. + * + * @return {NodeMaterialObserver} The node material observer. + */ getMonitor() { return this._monitor || ( this._monitor = this.getNodeBuilderState().monitor ); } + /** + * Returns an array of bind groups of this render object. + * + * @return {Array} The bindings. + */ getBindings() { return this._bindings || ( this._bindings = this.getNodeBuilderState().createBindings() ); } + /** + * Returns the index of the render object's geometry. + * + * @return {BufferAttribute?} The index. Returns `null` for non-indexed geometries. + */ getIndex() { return this._geometries.getIndex( this ); } + /** + * Returns the indirect buffer attribute. + * + * @return {BufferAttribute?} The indirect attribute. `null` if no indirect drawing is used. + */ getIndirect() { return this._geometries.getIndirect( this ); } + /** + * Returns an array that acts as a key for identifying the render object in a chain map. + * + * @return {Array} An array with object references. + */ getChainArray() { return [ this.object, this.material, this.context, this.lightsNode ]; } + /** + * This method is used when the geometry of a 3D object has been exchanged and the + * respective render object now requires an update. + * + * @param {BufferGeometry} geometry - The geometry to set. + */ setGeometry( geometry ) { this.geometry = geometry; @@ -20601,6 +22902,12 @@ class RenderObject { } + /** + * Returns the buffer attributes of the render object. The returned array holds + * attribute definitions on geometry and node level. + * + * @return {Array} An array with buffer attributes. + */ getAttributes() { if ( this.attributes !== null ) return this.attributes; @@ -20631,6 +22938,11 @@ class RenderObject { } + /** + * Returns the vertex buffers of the render object. + * + * @return {Array} An array with buffer attribute or interleaved buffers. + */ getVertexBuffers() { if ( this.vertexBuffers === null ) this.getAttributes(); @@ -20639,6 +22951,11 @@ class RenderObject { } + /** + * Returns the draw parameters for the render object. + * + * @return {{vertexCount: Number, firstVertex: Number, instanceCount: Number, firstInstance: Number}} The draw parameters. + */ getDrawParameters() { const { object, material, geometry, group, drawRange } = this; @@ -20705,6 +23022,13 @@ class RenderObject { } + /** + * Returns the render object's geometry cache key. + * + * The geometry cache key is part of the material cache key. + * + * @return {String} The geometry cache key. + */ getGeometryCacheKey() { const { geometry } = this; @@ -20734,6 +23058,13 @@ class RenderObject { } + /** + * Returns the render object's material cache key. + * + * The material cache key is part of the render object cache key. + * + * @return {String} The material cache key. + */ getMaterialCacheKey() { const { object, material } = this; @@ -20832,18 +23163,46 @@ class RenderObject { } + /** + * Whether the geometry requires an update or not. + * + * @type {Boolean} + * @readonly + */ get needsGeometryUpdate() { return this.geometry.id !== this.object.geometry.id; } + /** + * Whether the render object requires an update or not. + * + * Note: There are two distinct places where render objects are checked for an update. + * + * 1. In `RenderObjects.get()` which is executed when the render object is request. This + * method checks the `needsUpdate` flag and recreates the render object if necessary. + * 2. In `Renderer._renderObjectDirect()` right after getting the render object via + * `RenderObjects.get()`. The render object's NodeMaterialObserver is then used to detect + * a need for a refresh due to material, geometry or object related value changes. + * + * TODO: Investigate if it's possible to merge both steps so there is only a single place + * that performs the 'needsUpdate' check. + * + * @type {Boolean} + * @readonly + */ get needsUpdate() { return /*this.object.static !== true &&*/ ( this.initialNodesCacheKey !== this.getDynamicCacheKey() || this.clippingNeedsUpdate ); } + /** + * Returns the dynamic cache key which represents a key that is computed per draw command. + * + * @return {String} The cache key. + */ getDynamicCacheKey() { // Environment Nodes Cache Key @@ -20860,12 +23219,20 @@ class RenderObject { } + /** + * Returns the render object's cache key. + * + * @return {String} The cache key. + */ getCacheKey() { return this.getMaterialCacheKey() + this.getDynamicCacheKey(); } + /** + * Frees internal resources. + */ dispose() { this.material.removeEventListener( 'dispose', this.onMaterialDispose ); @@ -20876,40 +23243,109 @@ class RenderObject { } -const chainArray = []; +const _chainKeys$5 = []; +/** + * This module manages the render objects of the renderer. + * + * @private + */ class RenderObjects { + /** + * Constructs a new render object management component. + * + * @param {Renderer} renderer - The renderer. + * @param {Nodes} nodes - Renderer component for managing nodes related logic. + * @param {Geometries} geometries - Renderer component for managing geometries. + * @param {Pipelines} pipelines - Renderer component for managing pipelines. + * @param {Bindings} bindings - Renderer component for managing bindings. + * @param {Info} info - Renderer component for managing metrics and monitoring data. + */ constructor( renderer, nodes, geometries, pipelines, bindings, info ) { + /** + * The renderer. + * + * @type {Renderer} + */ this.renderer = renderer; + + /** + * Renderer component for managing nodes related logic. + * + * @type {Nodes} + */ this.nodes = nodes; + + /** + * Renderer component for managing geometries. + * + * @type {Geometries} + */ this.geometries = geometries; + + /** + * Renderer component for managing pipelines. + * + * @type {Pipelines} + */ this.pipelines = pipelines; + + /** + * Renderer component for managing bindings. + * + * @type {Bindings} + */ this.bindings = bindings; + + /** + * Renderer component for managing metrics and monitoring data. + * + * @type {Info} + */ this.info = info; + /** + * A dictionary that manages render contexts in chain maps + * for each pass ID. + * + * @type {Object} + */ this.chainMaps = {}; } + /** + * Returns a render object for the given object and state data. + * + * @param {Object3D} object - The 3D object. + * @param {Material} material - The 3D object's material. + * @param {Scene} scene - The scene the 3D object belongs to. + * @param {Camera} camera - The camera the 3D object should be rendered with. + * @param {LightsNode} lightsNode - The lights node. + * @param {RenderContext} renderContext - The render context. + * @param {ClippingContext} clippingContext - The clipping context. + * @param {String?} passId - An optional ID for identifying the pass. + * @return {RenderObject} The render object. + */ get( object, material, scene, camera, lightsNode, renderContext, clippingContext, passId ) { const chainMap = this.getChainMap( passId ); // reuse chainArray - chainArray[ 0 ] = object; - chainArray[ 1 ] = material; - chainArray[ 2 ] = renderContext; - chainArray[ 3 ] = lightsNode; + _chainKeys$5[ 0 ] = object; + _chainKeys$5[ 1 ] = material; + _chainKeys$5[ 2 ] = renderContext; + _chainKeys$5[ 3 ] = lightsNode; - let renderObject = chainMap.get( chainArray ); + let renderObject = chainMap.get( _chainKeys$5 ); if ( renderObject === undefined ) { renderObject = this.createRenderObject( this.nodes, this.geometries, this.renderer, object, material, scene, camera, lightsNode, renderContext, clippingContext, passId ); - chainMap.set( chainArray, renderObject ); + chainMap.set( _chainKeys$5, renderObject ); } else { @@ -20939,22 +23375,49 @@ class RenderObjects { } + _chainKeys$5.length = 0; + return renderObject; } + /** + * Returns a chain map for the given pass ID. + * + * @param {String} [passId='default'] - The pass ID. + * @return {ChainMap} The chain map. + */ getChainMap( passId = 'default' ) { return this.chainMaps[ passId ] || ( this.chainMaps[ passId ] = new ChainMap() ); } + /** + * Frees internal resources. + */ dispose() { this.chainMaps = {}; } + /** + * Factory method for creating render objects with the given list of parameters. + * + * @param {Nodes} nodes - Renderer component for managing nodes related logic. + * @param {Geometries} geometries - Renderer component for managing geometries. + * @param {Renderer} renderer - The renderer. + * @param {Object3D} object - The 3D object. + * @param {Material} material - The object's material. + * @param {Scene} scene - The scene the 3D object belongs to. + * @param {Camera} camera - The camera the object should be rendered with. + * @param {LightsNode} lightsNode - The lights node. + * @param {RenderContext} renderContext - The render context. + * @param {ClippingContext} clippingContext - The clipping context. + * @param {String?} passId - An optional ID for identifying the pass. + * @return {RenderObject} The render object. + */ createRenderObject( nodes, geometries, renderer, object, material, scene, camera, lightsNode, renderContext, clippingContext, passId ) { const chainMap = this.getChainMap( passId ); @@ -20978,14 +23441,35 @@ class RenderObjects { } +/** + * Data structure for the renderer. It is intended to manage + * data of objects in dictionaries. + * + * @private + */ class DataMap { + /** + * Constructs a new data map. + */ constructor() { + /** + * `DataMap` internally uses a weak map + * to manage its data. + * + * @type {WeakMap} + */ this.data = new WeakMap(); } + /** + * Returns the dictionary for the given object. + * + * @param {Object} object - The object. + * @return {Object} The dictionary. + */ get( object ) { let map = this.data.get( object ); @@ -21001,9 +23485,15 @@ class DataMap { } + /** + * Deletes the dictionary for the given object. + * + * @param {Object} object - The object. + * @return {Object?} The deleted dictionary. + */ delete( object ) { - let map; + let map = null; if ( this.data.has( object ) ) { @@ -21017,12 +23507,21 @@ class DataMap { } + /** + * Returns `true` if the given object has a dictionary defined. + * + * @param {Object} object - The object to test. + * @return {Boolean} Whether a dictionary is defined or not. + */ has( object ) { return this.data.has( object ); } + /** + * Frees internal resources. + */ dispose() { this.data = new WeakMap(); @@ -21047,16 +23546,38 @@ const GPU_CHUNK_BYTES = 16; const BlendColorFactor = 211; const OneMinusBlendColorFactor = 212; +/** + * This renderer module manages geometry attributes. + * + * @private + * @augments DataMap + */ class Attributes extends DataMap { + /** + * Constructs a new attribute management component. + * + * @param {Backend} backend - The renderer's backend. + */ constructor( backend ) { super(); + /** + * The renderer's backend. + * + * @type {Backend} + */ this.backend = backend; } + /** + * Deletes the data for the given attribute. + * + * @param {BufferAttribute} attribute - The attribute. + * @return {Object} The deleted attribute data. + */ delete( attribute ) { const attributeData = super.delete( attribute ); @@ -21071,6 +23592,13 @@ class Attributes extends DataMap { } + /** + * Updates the given attribute. This method creates attribute buffers + * for new attributes and updates data for existing ones. + * + * @param {BufferAttribute} attribute - The attribute to update. + * @param {Number} type - The attribute type. + */ update( attribute, type ) { const data = this.get( attribute ); @@ -21113,6 +23641,13 @@ class Attributes extends DataMap { } + /** + * Utility method for handling interleaved buffer attributes correctly. + * To process them, their `InterleavedBuffer` is returned. + * + * @param {BufferAttribute} attribute - The attribute. + * @return {BufferAttribute|InterleavedBuffer} + */ _getBufferAttribute( attribute ) { if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; @@ -21123,6 +23658,14 @@ class Attributes extends DataMap { } +/** + * Returns `true` if the given array has values that require an Uint32 array type. + * + * @private + * @function + * @param {Array} array - The array to test. + * @return {Boolean} Whether the given array has values that require an Uint32 array type or not. + */ function arrayNeedsUint32( array ) { // assumes larger values usually on last @@ -21137,12 +23680,28 @@ function arrayNeedsUint32( array ) { } +/** + * Returns the wireframe version for the given geometry. + * + * @private + * @function + * @param {BufferGeometry} geometry - The geometry. + * @return {Number} The version. + */ function getWireframeVersion( geometry ) { return ( geometry.index !== null ) ? geometry.index.version : geometry.attributes.position.version; } +/** + * Returns a wireframe index attribute for the given geometry. + * + * @private + * @function + * @param {BufferGeometry} geometry - The geometry. + * @return {BufferAttribute} The wireframe index attribute. + */ function getWireframeIndex( geometry ) { const indices = []; @@ -21187,21 +23746,61 @@ function getWireframeIndex( geometry ) { } +/** + * This renderer module manages geometries. + * + * @private + * @augments DataMap + */ class Geometries extends DataMap { + /** + * Constructs a new geometry management component. + * + * @param {Attributes} attributes - Renderer component for managing attributes. + * @param {Info} info - Renderer component for managing metrics and monitoring data. + */ constructor( attributes, info ) { super(); + /** + * Renderer component for managing attributes. + * + * @type {Attributes} + */ this.attributes = attributes; + + /** + * Renderer component for managing metrics and monitoring data. + * + * @type {Info} + */ this.info = info; + /** + * Weak Map for managing attributes for wireframe rendering. + * + * @type {WeakMap} + */ this.wireframes = new WeakMap(); + /** + * This Weak Map is used to make sure buffer attributes are + * updated only once per render call. + * + * @type {WeakMap} + */ this.attributeCall = new WeakMap(); } + /** + * Returns `true` if the given render object has an initialized geometry. + * + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether if the given render object has an initialized geometry or not. + */ has( renderObject ) { const geometry = renderObject.geometry; @@ -21210,6 +23809,11 @@ class Geometries extends DataMap { } + /** + * Prepares the geometry of the given render object for rendering. + * + * @param {RenderObject} renderObject - The render object. + */ updateForRender( renderObject ) { if ( this.has( renderObject ) === false ) this.initGeometry( renderObject ); @@ -21218,6 +23822,11 @@ class Geometries extends DataMap { } + /** + * Initializes the geometry of the given render object. + * + * @param {RenderObject} renderObject - The render object. + */ initGeometry( renderObject ) { const geometry = renderObject.geometry; @@ -21262,6 +23871,11 @@ class Geometries extends DataMap { } + /** + * Updates the geometry attributes of the given render object. + * + * @param {RenderObject} renderObject - The render object. + */ updateAttributes( renderObject ) { // attributes @@ -21304,6 +23918,12 @@ class Geometries extends DataMap { } + /** + * Updates the given attribute. + * + * @param {BufferAttribute} attribute - The attribute to update. + * @param {Number} type - The attribute type. + */ updateAttribute( attribute, type ) { const callId = this.info.render.calls; @@ -21340,12 +23960,25 @@ class Geometries extends DataMap { } + /** + * Returns the indirect buffer attribute of the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @return {BufferAttribute?} The indirect attribute. `null` if no indirect drawing is used. + */ getIndirect( renderObject ) { return renderObject.geometry.indirect; } + /** + * Returns the index of the given render object's geometry. This is implemented + * in a method to return a wireframe index if necessary. + * + * @param {RenderObject} renderObject - The render object. + * @return {BufferAttribute?} The index. Returns `null` for non-indexed geometries. + */ getIndex( renderObject ) { const { geometry, material } = renderObject; @@ -21384,15 +24017,64 @@ class Geometries extends DataMap { } +/** + * This renderer module provides a series of statistical information + * about the GPU memory and the rendering process. Useful for debugging + * and monitoring. + */ class Info { + /** + * Constructs a new info component. + */ constructor() { + /** + * Whether frame related metrics should automatically + * be resetted or not. This property should be set to `false` + * by apps which manage their own animation loop. They must + * then call `renderer.info.reset()` once per frame manually. + * + * @type {Boolean} + * @default true + */ this.autoReset = true; + /** + * The current frame ID. This ID is managed + * by `NodeFrame`. + * + * @type {Number} + * @readonly + * @default 0 + */ this.frame = 0; + + /** + * The number of render calls since the + * app has been started. + * + * @type {Number} + * @readonly + * @default 0 + */ this.calls = 0; + /** + * Render related metrics. + * + * @type {Object} + * @readonly + * @property {Number} calls - The number of render calls since the app has been started. + * @property {Number} frameCalls - The number of render calls of the current frame. + * @property {Number} drawCalls - The number of draw calls of the current frame. + * @property {Number} triangles - The number of rendered triangle primitives of the current frame. + * @property {Number} points - The number of rendered point primitives of the current frame. + * @property {Number} lines - The number of rendered line primitives of the current frame. + * @property {Number} previousFrameCalls - The number of render calls of the previous frame. + * @property {Number} timestamp - The timestamp of the frame when using `renderer.renderAsync()`. + * @property {Number} timestampCalls - The number of render calls using `renderer.renderAsync()`. + */ this.render = { calls: 0, frameCalls: 0, @@ -21405,6 +24087,17 @@ class Info { timestampCalls: 0 }; + /** + * Compute related metrics. + * + * @type {Object} + * @readonly + * @property {Number} calls - The number of compute calls since the app has been started. + * @property {Number} frameCalls - The number of compute calls of the current frame. + * @property {Number} previousFrameCalls - The number of compute calls of the previous frame. + * @property {Number} timestamp - The timestamp of the frame when using `renderer.computeAsync()`. + * @property {Number} timestampCalls - The number of render calls using `renderer.computeAsync()`. + */ this.compute = { calls: 0, frameCalls: 0, @@ -21413,6 +24106,14 @@ class Info { timestampCalls: 0 }; + /** + * Memory related metrics. + * + * @type {Object} + * @readonly + * @property {Number} geometries - The number of active geometries. + * @property {Number} frameCalls - The number of active textures. + */ this.memory = { geometries: 0, textures: 0 @@ -21420,6 +24121,13 @@ class Info { } + /** + * This method should be executed per draw call and updates the corresponding metrics. + * + * @param {Object3D} object - The 3D object that is going to be rendered. + * @param {Number} count - The vertex or index count. + * @param {Number} instanceCount - The instance count. + */ update( object, count, instanceCount ) { this.render.drawCalls ++; @@ -21448,6 +24156,12 @@ class Info { } + /** + * Used by async render methods to updated timestamp metrics. + * + * @param {('render'|'compute')} type - The type of render call. + * @param {Number} time - The duration of the compute/render call in milliseconds. + */ updateTimestamp( type, time ) { if ( this[ type ].timestampCalls === 0 ) { @@ -21471,6 +24185,9 @@ class Info { } + /** + * Resets frame related metrics. + */ reset() { const previousRenderFrameCalls = this.render.frameCalls; @@ -21491,6 +24208,9 @@ class Info { } + /** + * Performs a complete reset of the object. + */ dispose() { this.reset(); @@ -21509,76 +24229,249 @@ class Info { } +/** + * Abstract class for representing pipelines. + * + * @private + * @abstract + */ class Pipeline { + /** + * Constructs a new pipeline. + * + * @param {String} cacheKey - The pipeline's cache key. + */ constructor( cacheKey ) { + /** + * The pipeline's cache key. + * + * @type {String} + */ this.cacheKey = cacheKey; + /** + * How often the pipeline is currently in use. + * + * @type {Number} + * @default 0 + */ this.usedTimes = 0; } } +/** + * Class for representing render pipelines. + * + * @private + * @augments Pipeline + */ class RenderPipeline extends Pipeline { + /** + * Constructs a new render pipeline. + * + * @param {String} cacheKey - The pipeline's cache key. + * @param {ProgrammableStage} vertexProgram - The pipeline's vertex shader. + * @param {ProgrammableStage} fragmentProgram - The pipeline's fragment shader. + */ constructor( cacheKey, vertexProgram, fragmentProgram ) { super( cacheKey ); + /** + * The pipeline's vertex shader. + * + * @type {ProgrammableStage} + */ this.vertexProgram = vertexProgram; + + /** + * The pipeline's fragment shader. + * + * @type {ProgrammableStage} + */ this.fragmentProgram = fragmentProgram; } } +/** + * Class for representing compute pipelines. + * + * @private + * @augments Pipeline + */ class ComputePipeline extends Pipeline { + /** + * Constructs a new render pipeline. + * + * @param {String} cacheKey - The pipeline's cache key. + * @param {ProgrammableStage} computeProgram - The pipeline's compute shader. + */ constructor( cacheKey, computeProgram ) { super( cacheKey ); + /** + * The pipeline's compute shader. + * + * @type {ProgrammableStage} + */ this.computeProgram = computeProgram; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isComputePipeline = true; } } -let _id$7 = 0; +let _id$8 = 0; +/** + * Class for representing programmable stages which are vertex, + * fragment or compute shaders. Unlike fixed-function states (like blending), + * they represent the programmable part of a pipeline. + * + * @private + */ class ProgrammableStage { - constructor( code, type, transforms = null, attributes = null ) { + /** + * Constructs a new programmable stage. + * + * @param {String} code - The shader code. + * @param {('vertex'|'fragment'|'compute')} stage - The type of stage. + * @param {String} name - The name of the shader. + * @param {Array?} [transforms=null] - The transforms (only relevant for compute stages with WebGL 2 which uses Transform Feedback). + * @param {Array?} [attributes=null] - The attributes (only relevant for compute stages with WebGL 2 which uses Transform Feedback). + */ + constructor( code, stage, name, transforms = null, attributes = null ) { - this.id = _id$7 ++; + /** + * The id of the programmable stage. + * + * @type {Number} + */ + this.id = _id$8 ++; + /** + * The shader code. + * + * @type {String} + */ this.code = code; - this.stage = type; + + /** + * The type of stage. + * + * @type {String} + */ + this.stage = stage; + + /** + * The name of the stage. + * This is used for debugging purposes. + * + * @type {String} + */ + this.name = name; + + /** + * The transforms (only relevant for compute stages with WebGL 2 which uses Transform Feedback). + * + * @type {Array?} + */ this.transforms = transforms; + + /** + * The attributes (only relevant for compute stages with WebGL 2 which uses Transform Feedback). + * + * @type {Array?} + */ this.attributes = attributes; + /** + * How often the programmable stage is currently in use. + * + * @type {Number} + * @default 0 + */ this.usedTimes = 0; } } +/** + * This renderer module manages the pipelines of the renderer. + * + * @private + * @augments DataMap + */ class Pipelines extends DataMap { + /** + * Constructs a new pipeline management component. + * + * @param {Backend} backend - The renderer's backend. + * @param {Nodes} nodes - Renderer component for managing nodes related logic. + */ constructor( backend, nodes ) { super(); + /** + * The renderer's backend. + * + * @type {Backend} + */ this.backend = backend; + + /** + * Renderer component for managing nodes related logic. + * + * @type {Nodes} + */ this.nodes = nodes; - this.bindings = null; // set by the bindings + /** + * A references to the bindings management component. + * This reference will be set inside the `Bindings` + * constructor. + * + * @type {Bindings?} + * @default null + */ + this.bindings = null; + /** + * Internal cache for maintaining pipelines. + * The key of the map is a cache key, the value the pipeline. + * + * @type {Map} + */ this.caches = new Map(); + + /** + * This dictionary maintains for each shader stage type (vertex, + * fragment and compute) the programmable stage objects which + * represent the actual shader code. + * + * @type {Object} + */ this.programs = { vertex: new Map(), fragment: new Map(), @@ -21587,6 +24480,13 @@ class Pipelines extends DataMap { } + /** + * Returns a compute pipeline for the given compute node. + * + * @param {Node} computeNode - The compute node. + * @param {Array} bindings - The bindings. + * @return {ComputePipeline} The compute pipeline. + */ getForCompute( computeNode, bindings ) { const { backend } = this; @@ -21616,7 +24516,7 @@ class Pipelines extends DataMap { if ( previousPipeline && previousPipeline.computeProgram.usedTimes === 0 ) this._releaseProgram( previousPipeline.computeProgram ); - stageCompute = new ProgrammableStage( nodeBuilderState.computeShader, 'compute', nodeBuilderState.transforms, nodeBuilderState.nodeAttributes ); + stageCompute = new ProgrammableStage( nodeBuilderState.computeShader, 'compute', computeNode.name, nodeBuilderState.transforms, nodeBuilderState.nodeAttributes ); this.programs.compute.set( nodeBuilderState.computeShader, stageCompute ); backend.createProgram( stageCompute ); @@ -21653,6 +24553,13 @@ class Pipelines extends DataMap { } + /** + * Returns a render pipeline for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @param {Array?} [promises=null] - An array of compilation promises which is only relevant in context of `Renderer.compileAsync()`. + * @return {RenderPipeline} The render pipeline. + */ getForRender( renderObject, promises = null ) { const { backend } = this; @@ -21675,6 +24582,8 @@ class Pipelines extends DataMap { const nodeBuilderState = renderObject.getNodeBuilderState(); + const name = renderObject.material ? renderObject.material.name : ''; + // programmable stages let stageVertex = this.programs.vertex.get( nodeBuilderState.vertexShader ); @@ -21683,7 +24592,7 @@ class Pipelines extends DataMap { if ( previousPipeline && previousPipeline.vertexProgram.usedTimes === 0 ) this._releaseProgram( previousPipeline.vertexProgram ); - stageVertex = new ProgrammableStage( nodeBuilderState.vertexShader, 'vertex' ); + stageVertex = new ProgrammableStage( nodeBuilderState.vertexShader, 'vertex', name ); this.programs.vertex.set( nodeBuilderState.vertexShader, stageVertex ); backend.createProgram( stageVertex ); @@ -21696,7 +24605,7 @@ class Pipelines extends DataMap { if ( previousPipeline && previousPipeline.fragmentProgram.usedTimes === 0 ) this._releaseProgram( previousPipeline.fragmentProgram ); - stageFragment = new ProgrammableStage( nodeBuilderState.fragmentShader, 'fragment' ); + stageFragment = new ProgrammableStage( nodeBuilderState.fragmentShader, 'fragment', name ); this.programs.fragment.set( nodeBuilderState.fragmentShader, stageFragment ); backend.createProgram( stageFragment ); @@ -21737,6 +24646,12 @@ class Pipelines extends DataMap { } + /** + * Deletes the pipeline for the given render object. + * + * @param {RenderObject} object - The render object. + * @return {Object?} The deleted dictionary. + */ delete( object ) { const pipeline = this.get( object ).pipeline; @@ -21773,6 +24688,9 @@ class Pipelines extends DataMap { } + /** + * Frees internal resources. + */ dispose() { super.dispose(); @@ -21786,12 +24704,27 @@ class Pipelines extends DataMap { } + /** + * Updates the pipeline for the given render object. + * + * @param {RenderObject} renderObject - The render object. + */ updateForRender( renderObject ) { this.getForRender( renderObject ); } + /** + * Returns a compute pipeline for the given parameters. + * + * @private + * @param {Node} computeNode - The compute node. + * @param {ProgrammableStage} stageCompute - The programmable stage representing the compute shader. + * @param {String} cacheKey - The cache key. + * @param {Array} bindings - The bindings. + * @return {ComputePipeline} The compute pipeline. + */ _getComputePipeline( computeNode, stageCompute, cacheKey, bindings ) { // check for existing pipeline @@ -21814,6 +24747,17 @@ class Pipelines extends DataMap { } + /** + * Returns a render pipeline for the given parameters. + * + * @private + * @param {RenderObject} renderObject - The render object. + * @param {ProgrammableStage} stageVertex - The programmable stage representing the vertex shader. + * @param {ProgrammableStage} stageFragment - The programmable stage representing the fragment shader. + * @param {String} cacheKey - The cache key. + * @param {Array} promises - An array of compilation promises which is only relevant in context of `Renderer.compileAsync()`. + * @return {ComputePipeline} The compute pipeline. + */ _getRenderPipeline( renderObject, stageVertex, stageFragment, cacheKey, promises ) { // check for existing pipeline @@ -21830,6 +24774,10 @@ class Pipelines extends DataMap { renderObject.pipeline = pipeline; + // The `promises` array is `null` by default and only set to an empty array when + // `Renderer.compileAsync()` is used. The next call actually fills the array with + // pending promises that resolve when the render pipelines are ready for rendering. + this.backend.createRenderPipeline( renderObject, promises ); } @@ -21838,24 +24786,53 @@ class Pipelines extends DataMap { } + /** + * Computes a cache key representing a compute pipeline. + * + * @private + * @param {Node} computeNode - The compute node. + * @param {ProgrammableStage} stageCompute - The programmable stage representing the compute shader. + * @return {String} The cache key. + */ _getComputeCacheKey( computeNode, stageCompute ) { return computeNode.id + ',' + stageCompute.id; } + /** + * Computes a cache key representing a render pipeline. + * + * @private + * @param {RenderObject} renderObject - The render object. + * @param {ProgrammableStage} stageVertex - The programmable stage representing the vertex shader. + * @param {ProgrammableStage} stageFragment - The programmable stage representing the fragment shader. + * @return {String} The cache key. + */ _getRenderCacheKey( renderObject, stageVertex, stageFragment ) { return stageVertex.id + ',' + stageFragment.id + ',' + this.backend.getRenderCacheKey( renderObject ); } + /** + * Releases the given pipeline. + * + * @private + * @param {Pipeline} pipeline - The pipeline to release. + */ _releasePipeline( pipeline ) { this.caches.delete( pipeline.cacheKey ); } + /** + * Releases the shader program. + * + * @private + * @param {Object} program - The shader program to release. + */ _releaseProgram( program ) { const code = program.code; @@ -21865,6 +24842,13 @@ class Pipelines extends DataMap { } + /** + * Returns `true` if the compute pipeline for the given compute node requires an update. + * + * @private + * @param {Node} computeNode - The compute node. + * @return {Boolean} Whether the compute pipeline for the given compute node requires an update or not. + */ _needsComputeUpdate( computeNode ) { const data = this.get( computeNode ); @@ -21873,6 +24857,13 @@ class Pipelines extends DataMap { } + /** + * Returns `true` if the render pipeline for the given render object requires an update. + * + * @private + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether the render object for the given render object requires an update or not. + */ _needsRenderUpdate( renderObject ) { const data = this.get( renderObject ); @@ -21883,23 +24874,80 @@ class Pipelines extends DataMap { } +/** + * This renderer module manages the bindings of the renderer. + * + * @private + * @augments DataMap + */ class Bindings extends DataMap { + /** + * Constructs a new bindings management component. + * + * @param {Backend} backend - The renderer's backend. + * @param {Nodes} nodes - Renderer component for managing nodes related logic. + * @param {Textures} textures - Renderer component for managing textures. + * @param {Attributes} attributes - Renderer component for managing attributes. + * @param {Pipelines} pipelines - Renderer component for managing pipelines. + * @param {Info} info - Renderer component for managing metrics and monitoring data. + */ constructor( backend, nodes, textures, attributes, pipelines, info ) { super(); + /** + * The renderer's backend. + * + * @type {Backend} + */ this.backend = backend; + + /** + * Renderer component for managing textures. + * + * @type {Textures} + */ this.textures = textures; + + /** + * Renderer component for managing pipelines. + * + * @type {Pipelines} + */ this.pipelines = pipelines; + + /** + * Renderer component for managing attributes. + * + * @type {Attributes} + */ this.attributes = attributes; + + /** + * Renderer component for managing nodes related logic. + * + * @type {Nodes} + */ this.nodes = nodes; + + /** + * Renderer component for managing metrics and monitoring data. + * + * @type {Info} + */ this.info = info; this.pipelines.bindings = this; // assign bindings to pipelines } + /** + * Returns the bind groups for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @return {Array} The bind groups. + */ getForRender( renderObject ) { const bindings = renderObject.getBindings(); @@ -21926,6 +24974,12 @@ class Bindings extends DataMap { } + /** + * Returns the bind groups for the given compute node. + * + * @param {Node} computeNode - The compute node. + * @return {Array} The bind groups. + */ getForCompute( computeNode ) { const bindings = this.nodes.getForCompute( computeNode ).bindings; @@ -21950,18 +25004,33 @@ class Bindings extends DataMap { } + /** + * Updates the bindings for the given compute node. + * + * @param {Node} computeNode - The compute node. + */ updateForCompute( computeNode ) { this._updateBindings( this.getForCompute( computeNode ) ); } + /** + * Updates the bindings for the given render object. + * + * @param {RenderObject} renderObject - The render object. + */ updateForRender( renderObject ) { this._updateBindings( this.getForRender( renderObject ) ); } + /** + * Updates the given array of bindings. + * + * @param {Array} bindings - The bind groups. + */ _updateBindings( bindings ) { for ( const bindGroup of bindings ) { @@ -21972,6 +25041,11 @@ class Bindings extends DataMap { } + /** + * Initializes the given bind group. + * + * @param {BindGroup} bindGroup - The bind group to initialize. + */ _init( bindGroup ) { for ( const binding of bindGroup.bindings ) { @@ -21993,6 +25067,12 @@ class Bindings extends DataMap { } + /** + * Updates the given bind group. + * + * @param {BindGroup} bindGroup - The bind group to update. + * @param {Array} bindings - The bind groups. + */ _update( bindGroup, bindings ) { const { backend } = this; @@ -22010,7 +25090,10 @@ class Bindings extends DataMap { const updated = this.nodes.updateGroup( binding ); - if ( ! updated ) continue; + // every uniforms group is a uniform buffer. So if no update is required, + // we move one with the next binding. Otherwise the next if block will update the group. + + if ( updated === false ) continue; } @@ -22099,6 +25182,15 @@ class Bindings extends DataMap { } +/** + * Default sorting function for opaque render items. + * + * @private + * @function + * @param {Object} a - The first render item. + * @param {Object} b - The second render item. + * @return {Number} A numeric value which defines the sort order. + */ function painterSortStable( a, b ) { if ( a.groupOrder !== b.groupOrder ) { @@ -22125,6 +25217,15 @@ function painterSortStable( a, b ) { } +/** + * Default sorting function for transparent render items. + * + * @private + * @function + * @param {Object} a - The first render item. + * @param {Object} b - The second render item. + * @return {Number} A numeric value which defines the sort order. + */ function reversePainterSortStable( a, b ) { if ( a.groupOrder !== b.groupOrder ) { @@ -22147,6 +25248,14 @@ function reversePainterSortStable( a, b ) { } +/** + * Returns `true` if the given transparent material requires a double pass. + * + * @private + * @function + * @param {Material} material - The transparent material. + * @return {Boolean} Whether the given material requires a double pass or not. + */ function needsDoublePass( material ) { const hasTransmission = material.transmission > 0 || material.transmissionNode; @@ -22155,28 +25264,120 @@ function needsDoublePass( material ) { } +/** + * When the renderer analyzes the scene at the beginning of a render call, + * it stores 3D object for further processing in render lists. Depending on the + * properties of a 3D objects (like their transformation or material state), the + * objects are maintained in ordered lists for the actual rendering. + * + * Render lists are unique per scene and camera combination. + * + * @private + * @augments Pipeline + */ class RenderList { + /** + * Constructs a render list. + * + * @param {Lighting} lighting - The lighting management component. + * @param {Scene} scene - The scene. + * @param {Camera} camera - The camera the scene is rendered with. + */ constructor( lighting, scene, camera ) { + /** + * 3D objects are transformed into render items and stored in this array. + * + * @type {Array} + */ this.renderItems = []; + + /** + * The current render items index. + * + * @type {Number} + * @default 0 + */ this.renderItemsIndex = 0; + /** + * A list with opaque render items. + * + * @type {Array} + */ this.opaque = []; + + /** + * A list with transparent render items which require + * double pass rendering (e.g. transmissive objects). + * + * @type {Array} + */ this.transparentDoublePass = []; + + /** + * A list with transparent render items. + * + * @type {Array} + */ this.transparent = []; + + /** + * A list with transparent render bundle data. + * + * @type {Array} + */ this.bundles = []; + /** + * The render list's lights node. This node is later + * relevant for the actual analytical light nodes which + * compute the scene's lighting in the shader. + * + * @type {LightsNode} + */ this.lightsNode = lighting.getNode( scene, camera ); + + /** + * The scene's lights stored in an array. This array + * is used to setup the lights node. + * + * @type {Array} + */ this.lightsArray = []; + /** + * The scene. + * + * @type {Scene} + */ this.scene = scene; + + /** + * The camera the scene is rendered with. + * + * @type {Camera} + */ this.camera = camera; + /** + * How many objects perform occlusion query tests. + * + * @type {Number} + * @default 0 + */ this.occlusionQueryCount = 0; } + /** + * This method is called right at the beginning of a render call + * before the scene is analyzed. It prepares the internal data + * structures for the upcoming render lists generation. + * + * @return {RenderList} A reference to this render list. + */ begin() { this.renderItemsIndex = 0; @@ -22194,6 +25395,22 @@ class RenderList { } + /** + * Returns a render item for the giving render item state. The state is defined + * by a series of object-related parameters. + * + * The method avoids object creation by holding render items and reusing them in + * subsequent render calls (just with different property values). + * + * @param {Object3D} object - The 3D object. + * @param {BufferGeometry} geometry - The 3D object's geometry. + * @param {Material} material - The 3D object's material. + * @param {Number} groupOrder - The current group order. + * @param {Number} z - Th 3D object's depth value (z value in clip space). + * @param {Number?} group - {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`. + * @param {ClippingContext} clippingContext - The current clipping context. + * @return {Object} The render item. + */ getNextRenderItem( object, geometry, material, groupOrder, z, group, clippingContext ) { let renderItem = this.renderItems[ this.renderItemsIndex ]; @@ -22234,6 +25451,18 @@ class RenderList { } + /** + * Pushes the given object as a render item to the internal render lists. + * The selected lists depend on the object properties. + * + * @param {Object3D} object - The 3D object. + * @param {BufferGeometry} geometry - The 3D object's geometry. + * @param {Material} material - The 3D object's material. + * @param {Number} groupOrder - The current group order. + * @param {Number} z - Th 3D object's depth value (z value in clip space). + * @param {Number?} group - {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`. + * @param {ClippingContext} clippingContext - The current clipping context. + */ push( object, geometry, material, groupOrder, z, group, clippingContext ) { const renderItem = this.getNextRenderItem( object, geometry, material, groupOrder, z, group, clippingContext ); @@ -22254,6 +25483,18 @@ class RenderList { } + /** + * Inserts the given object as a render item at the start of the internal render lists. + * The selected lists depend on the object properties. + * + * @param {Object3D} object - The 3D object. + * @param {BufferGeometry} geometry - The 3D object's geometry. + * @param {Material} material - The 3D object's material. + * @param {Number} groupOrder - The current group order. + * @param {Number} z - Th 3D object's depth value (z value in clip space). + * @param {Number?} group - {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`. + * @param {ClippingContext} clippingContext - The current clipping context. + */ unshift( object, geometry, material, groupOrder, z, group, clippingContext ) { const renderItem = this.getNextRenderItem( object, geometry, material, groupOrder, z, group, clippingContext ); @@ -22272,18 +25513,34 @@ class RenderList { } + /** + * Pushes render bundle group data into the render list. + * + * @param {Object} group - Bundle group data. + */ pushBundle( group ) { this.bundles.push( group ); } + /** + * Pushes a light into the render list. + * + * @param {Light} light - The light. + */ pushLight( light ) { this.lightsArray.push( light ); } + /** + * Sorts the internal render lists. + * + * @param {Function} customOpaqueSort - A custom sort function for opaque objects. + * @param {Function} customTransparentSort - A custom sort function for transparent objects. + */ sort( customOpaqueSort, customTransparentSort ) { if ( this.opaque.length > 1 ) this.opaque.sort( customOpaqueSort || painterSortStable ); @@ -22292,6 +25549,10 @@ class RenderList { } + /** + * This method performs finalizing tasks right after the render lists + * have been generated. + */ finish() { // update lights @@ -22322,34 +25583,71 @@ class RenderList { } +const _chainKeys$4 = []; + +/** + * This renderer module manages the render lists which are unique + * per scene and camera combination. + * + * @private + */ class RenderLists { + /** + * Constructs a render lists management component. + * + * @param {Lighting} lighting - The lighting management component. + */ constructor( lighting ) { + /** + * The lighting management component. + * + * @type {Lighting} + */ this.lighting = lighting; + /** + * The internal chain map which holds the render lists. + * + * @type {ChainMap} + */ this.lists = new ChainMap(); } + /** + * Returns a render list for the given scene and camera. + * + * @param {Scene} scene - The scene. + * @param {Camera} camera - The camera. + * @return {RenderList} The render list. + */ get( scene, camera ) { const lists = this.lists; - const keys = [ scene, camera ]; - let list = lists.get( keys ); + _chainKeys$4[ 0 ] = scene; + _chainKeys$4[ 1 ] = camera; + + let list = lists.get( _chainKeys$4 ); if ( list === undefined ) { list = new RenderList( this.lighting, scene, camera ); - lists.set( keys, list ); + lists.set( _chainKeys$4, list ); } + _chainKeys$4.length = 0; + return list; } + /** + * Frees all internal resources. + */ dispose() { this.lists = new ChainMap(); @@ -22358,44 +25656,203 @@ class RenderLists { } -let id = 0; +let _id$7 = 0; +/** + * Any render or compute command is executed in a specific context that defines + * the state of the renderer and its backend. Typical examples for such context + * data are the current clear values or data from the active framebuffer. This + * module is used to represent these contexts as objects. + * + * @private + */ class RenderContext { + /** + * Constructs a new render context. + */ constructor() { - this.id = id ++; + /** + * The context's ID. + * + * @type {Number} + */ + this.id = _id$7 ++; + /** + * Whether the current active framebuffer has a color attachment. + * + * @type {Boolean} + * @default true + */ this.color = true; + + /** + * Whether the color attachment should be cleared or not. + * + * @type {Boolean} + * @default true + */ this.clearColor = true; + + /** + * The clear color value. + * + * @type {Object} + * @default true + */ this.clearColorValue = { r: 0, g: 0, b: 0, a: 1 }; + /** + * Whether the current active framebuffer has a depth attachment. + * + * @type {Boolean} + * @default true + */ this.depth = true; + + /** + * Whether the depth attachment should be cleared or not. + * + * @type {Boolean} + * @default true + */ this.clearDepth = true; + + /** + * The clear depth value. + * + * @type {Number} + * @default 1 + */ this.clearDepthValue = 1; + /** + * Whether the current active framebuffer has a stencil attachment. + * + * @type {Boolean} + * @default false + */ this.stencil = false; + + /** + * Whether the stencil attachment should be cleared or not. + * + * @type {Boolean} + * @default true + */ this.clearStencil = true; + + /** + * The clear stencil value. + * + * @type {Number} + * @default 1 + */ this.clearStencilValue = 1; + /** + * By default the viewport encloses the entire framebuffer If a smaller + * viewport is manually defined, this property is to `true` by the renderer. + * + * @type {Boolean} + * @default false + */ this.viewport = false; + + /** + * The viewport value. This value is in physical pixels meaning it incorporates + * the renderer's pixel ratio. The viewport property of render targets or + * the renderer is in logical pixels. + * + * @type {Vector4} + */ this.viewportValue = new Vector4(); + /** + * When the scissor test is active and scissor rectangle smaller than the + * framebuffers dimensions, this property is to `true` by the renderer. + * + * @type {Boolean} + * @default false + */ this.scissor = false; + + /** + * The scissor rectangle. + * + * @type {Vector4} + */ this.scissorValue = new Vector4(); + /** + * The textures of the active render target. + * `null` when no render target is set. + * + * @type {Array?} + * @default null + */ this.textures = null; + + /** + * The depth texture of the active render target. + * `null` when no render target is set. + * + * @type {DepthTexture?} + * @default null + */ this.depthTexture = null; + + /** + * The active cube face. + * + * @type {Number} + * @default 0 + */ this.activeCubeFace = 0; + + /** + * The number of MSAA samples. This value is always `1` when + * MSAA isn't used. + * + * @type {Number} + * @default 1 + */ this.sampleCount = 1; + /** + * The framebuffers width in physical pixels. + * + * @type {Number} + * @default 0 + */ this.width = 0; + + /** + * The framebuffers height in physical pixels. + * + * @type {Number} + * @default 0 + */ this.height = 0; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isRenderContext = true; } + /** + * Returns the cache key of this render context. + * + * @return {Number} The cache key. + */ getCacheKey() { return getCacheKey( this ); @@ -22404,6 +25861,12 @@ class RenderContext { } +/** + * Computes a cache key for the given render context. + * + * @param {RenderContext} renderContext - The render context. + * @return {Number} The cache key. + */ function getCacheKey( renderContext ) { const { textures, activeCubeFace } = renderContext; @@ -22420,17 +25883,44 @@ function getCacheKey( renderContext ) { } +const _chainKeys$3 = []; +const _defaultScene = /*@__PURE__*/ new Scene(); +const _defaultCamera = /*@__PURE__*/ new Camera(); + +/** + * This module manages the render contexts of the renderer. + * + * @private + */ class RenderContexts { + /** + * Constructs a new render context management component. + */ constructor() { + /** + * A dictionary that manages render contexts in chain maps + * for each attachment state. + * + * @type {Object} + */ this.chainMaps = {}; } + /** + * Returns a render context for the given scene, camera and render target. + * + * @param {Scene} scene - The scene. + * @param {Camera} camera - The camera that is used to render the scene. + * @param {RenderTarget?} [renderTarget=null] - The active render target. + * @return {RenderContext} The render context. + */ get( scene, camera, renderTarget = null ) { - const chainKey = [ scene, camera ]; + _chainKeys$3[ 0 ] = scene; + _chainKeys$3[ 1 ] = camera; let attachmentState; @@ -22447,30 +25937,54 @@ class RenderContexts { } - const chainMap = this.getChainMap( attachmentState ); + const chainMap = this._getChainMap( attachmentState ); - let renderState = chainMap.get( chainKey ); + let renderState = chainMap.get( _chainKeys$3 ); if ( renderState === undefined ) { renderState = new RenderContext(); - chainMap.set( chainKey, renderState ); + chainMap.set( _chainKeys$3, renderState ); } + _chainKeys$3.length = 0; + if ( renderTarget !== null ) renderState.sampleCount = renderTarget.samples === 0 ? 1 : renderTarget.samples; return renderState; } - getChainMap( attachmentState ) { + /** + * Returns a render context intended for clear operations. + * + * @param {RenderTarget?} [renderTarget=null] - The active render target. + * @return {RenderContext} The render context. + */ + getForClear( renderTarget = null ) { + + return this.get( _defaultScene, _defaultCamera, renderTarget ); + + } + + /** + * Returns a chain map for the given attachment state. + * + * @private + * @param {String} attachmentState - The attachment state. + * @return {ChainMap} The chain map. + */ + _getChainMap( attachmentState ) { return this.chainMaps[ attachmentState ] || ( this.chainMaps[ attachmentState ] = new ChainMap() ); } + /** + * Frees internal resources. + */ dispose() { this.chainMaps = {}; @@ -22481,18 +25995,55 @@ class RenderContexts { const _size$3 = /*@__PURE__*/ new Vector3(); +/** + * This module manages the textures of the renderer. + * + * @private + * @augments DataMap + */ class Textures extends DataMap { + /** + * Constructs a new texture management component. + * + * @param {Renderer} renderer - The renderer. + * @param {Backend} backend - The renderer's backend. + * @param {Info} info - Renderer component for managing metrics and monitoring data. + */ constructor( renderer, backend, info ) { super(); + /** + * The renderer. + * + * @type {Renderer} + */ this.renderer = renderer; + + /** + * The backend. + * + * @type {Backend} + */ this.backend = backend; + + /** + * Renderer component for managing metrics and monitoring data. + * + * @type {Info} + */ this.info = info; } + /** + * Updates the given render target. Based on the given render target configuration, + * it updates the texture states representing the attachments of the framebuffer. + * + * @param {RenderTarget} renderTarget - The render target to update. + * @param {Number} [activeMipmapLevel=0] - The active mipmap level. + */ updateRenderTarget( renderTarget, activeMipmapLevel = 0 ) { const renderTargetData = this.get( renderTarget ); @@ -22614,6 +26165,14 @@ class Textures extends DataMap { } + /** + * Updates the given texture. Depending on the texture state, this method + * triggers the upload of texture data to the GPU memory. If the texture data are + * not yet ready for the upload, it uses default texture data for as a placeholder. + * + * @param {Texture} texture - The texture to update. + * @param {Object} [options={}] - The options. + */ updateTexture( texture, options = {} ) { const textureData = this.get( texture ); @@ -22767,6 +26326,18 @@ class Textures extends DataMap { } + /** + * Computes the size of the given texture and writes the result + * into the target vector. This vector is also returned by the + * method. + * + * If no texture data are available for the compute yet, the method + * returns default size values. + * + * @param {Texture} texture - The texture to compute the size for. + * @param {Vector3} target - The target vector. + * @return {Vector3} The target vector. + */ getSize( texture, target = _size$3 ) { let image = texture.images ? texture.images[ 0 ] : texture.image; @@ -22789,6 +26360,14 @@ class Textures extends DataMap { } + /** + * Computes the number of mipmap levels for the given texture. + * + * @param {Texture} texture - The texture. + * @param {Number} width - The texture's width. + * @param {Number} height - The texture's height. + * @return {Number} The number of mipmap levels. + */ getMipLevels( texture, width, height ) { let mipLevelCount; @@ -22815,12 +26394,24 @@ class Textures extends DataMap { } + /** + * Returns `true` if the given texture requires mipmaps. + * + * @param {Texture} texture - The texture. + * @return {Boolean} Whether mipmaps are required or not. + */ needsMipmaps( texture ) { return this.isEnvironmentTexture( texture ) || texture.isCompressedTexture === true || texture.generateMipmaps; } + /** + * Returns `true` if the given texture is an environment map. + * + * @param {Texture} texture - The texture. + * @return {Boolean} Whether the given texture is an environment map or not. + */ isEnvironmentTexture( texture ) { const mapping = texture.mapping; @@ -22829,6 +26420,12 @@ class Textures extends DataMap { } + /** + * Frees internal resource when the given texture isn't + * required anymore. + * + * @param {Texture} texture - The texture to destroy. + */ _destroyTexture( texture ) { this.backend.destroySampler( texture ); @@ -22840,8 +26437,24 @@ class Textures extends DataMap { } +/** + * A four-component version of {@link Color} which is internally + * used by the renderer to represents clear color with alpha as + * one object. + * + * @private + * @augments Color + */ class Color4 extends Color { + /** + * Constructs a new four-component color. + * + * @param {Number|String} r - The red value. + * @param {Number} g - The green value. + * @param {Number} b - The blue value. + * @param {Number} [a=1] - The alpha value. + */ constructor( r, g, b, a = 1 ) { super( r, g, b ); @@ -22850,6 +26463,15 @@ class Color4 extends Color { } + /** + * Overwrites the default to honor alpha. + * + * @param {Number|String} r - The red value. + * @param {Number} g - The green value. + * @param {Number} b - The blue value. + * @param {Number} [a=1] - The alpha value. + * @return {Color4} A reference to this object. + */ set( r, g, b, a = 1 ) { this.a = a; @@ -22858,6 +26480,12 @@ class Color4 extends Color { } + /** + * Overwrites the default to honor alpha. + * + * @param {Color4} color - The color to copy. + * @return {Color4} A reference to this object. + */ copy( color ) { if ( color.a !== undefined ) this.a = color.a; @@ -22866,6 +26494,11 @@ class Color4 extends Color { } + /** + * Overwrites the default to honor alpha. + * + * @return {Color4} The cloned color. + */ clone() { return new this.constructor( this.r, this.g, this.b, this.a ); @@ -24423,7 +28056,7 @@ class ReflectorBaseNode extends Node { updateBefore( frame ) { - if ( this.bounces === false && _inReflector ) return; + if ( this.bounces === false && _inReflector ) return false; _inReflector = true; @@ -24520,14 +28153,17 @@ class ReflectorBaseNode extends Node { const currentRenderTarget = renderer.getRenderTarget(); const currentMRT = renderer.getMRT(); + const currentAutoClear = renderer.autoClear; renderer.setMRT( null ); renderer.setRenderTarget( renderTarget ); + renderer.autoClear = true; renderer.render( scene, virtualCamera ); renderer.setMRT( currentMRT ); renderer.setRenderTarget( currentRenderTarget ); + renderer.autoClear = currentAutoClear; material.visible = true; @@ -24553,14 +28189,23 @@ class ReflectorBaseNode extends Node { */ const reflector = ( parameters ) => nodeObject( new ReflectorNode( parameters ) ); -// Helper for passes that need to fill the viewport with a single quad. - const _camera = /*@__PURE__*/ new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); -// https://github.com/mrdoob/three.js/pull/21358 - +/** + * The purpose of this special geometry is to fill the entire viewport with a single triangle. + * + * Reference: {@link https://github.com/mrdoob/three.js/pull/21358} + * + * @private + * @augments BufferGeometry + */ class QuadGeometry extends BufferGeometry { + /** + * Constructs a new quad geometry. + * + * @param {Boolean} [flipY=false] - Whether the uv coordinates should be flipped along the vertical axis or not. + */ constructor( flipY = false ) { super(); @@ -24576,24 +28221,64 @@ class QuadGeometry extends BufferGeometry { const _geometry = /*@__PURE__*/ new QuadGeometry(); + +/** + * This module is a helper for passes which need to render a full + * screen effect which is quite common in context of post processing. + * + * The intended usage is to reuse a single quad mesh for rendering + * subsequent passes by just reassigning the `material` reference. + * + * @augments BufferGeometry + */ class QuadMesh extends Mesh { + /** + * Constructs a new quad mesh. + * + * @param {Material?} [material=null] - The material to render the quad mesh with. + */ constructor( material = null ) { super( _geometry, material ); + /** + * The camera to render the quad mesh with. + * + * @type {OrthographicCamera} + * @readonly + */ this.camera = _camera; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isQuadMesh = true; } - renderAsync( renderer ) { + /** + * Async version of `render()`. + * + * @async + * @param {Renderer} renderer - The renderer. + * @return {Promise} A Promise that resolves when the render has been finished. + */ + async renderAsync( renderer ) { return renderer.renderAsync( this, _camera ); } + /** + * Renders the quad mesh + * + * @param {Renderer} renderer - The renderer. + */ render( renderer ) { renderer.render( this, _camera ); @@ -24942,28 +28627,86 @@ const getNormalFromDepth = /*@__PURE__*/ Fn( ( [ uv, depthTexture, projectionMat } ); +/** + * This special type of instanced buffer attribute is intended for compute shaders. + * In earlier three.js versions it was only possible to update attribute data + * on the CPU via JavaScript and then upload the data to the GPU. With the + * new material system and renderer it is now possible to use compute shaders + * to compute the data for an attribute more efficiently on the GPU. + * + * The idea is to create an instance of this class and provide it as an input + * to {@link module:StorageBufferNode}. + * + * Note: This type of buffer attribute can only be used with `WebGPURenderer`. + * + * @augments InstancedBufferAttribute + */ class StorageInstancedBufferAttribute extends InstancedBufferAttribute { - constructor( array, itemSize, typeClass = Float32Array ) { + /** + * Constructs a new storage instanced buffer attribute. + * + * @param {Number|TypedArray} count - The item count. It is also valid to pass a typed array as an argument. + * The subsequent parameters are then obsolete. + * @param {Number} itemSize - The item size. + * @param {TypedArray.constructor} [typeClass=Float32Array] - A typed array constructor. + */ + constructor( count, itemSize, typeClass = Float32Array ) { - if ( ArrayBuffer.isView( array ) === false ) array = new typeClass( array * itemSize ); + const array = ArrayBuffer.isView( count ) ? count : new typeClass( count * itemSize ); super( array, itemSize ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isStorageInstancedBufferAttribute = true; } } +/** + * This special type of buffer attribute is intended for compute shaders. + * In earlier three.js versions it was only possible to update attribute data + * on the CPU via JavaScript and then upload the data to the GPU. With the + * new material system and renderer it is now possible to use compute shaders + * to compute the data for an attribute more efficiently on the GPU. + * + * The idea is to create an instance of this class and provide it as an input + * to {@link module:StorageBufferNode}. + * + * Note: This type of buffer attribute can only be used with `WebGPURenderer`. + * + * @augments BufferAttribute + */ class StorageBufferAttribute extends BufferAttribute { - constructor( array, itemSize, typeClass = Float32Array ) { + /** + * Constructs a new storage buffer attribute. + * + * @param {Number|TypedArray} count - The item count. It is also valid to pass a typed array as an argument. + * The subsequent parameters are then obsolete. + * @param {Number} itemSize - The item size. + * @param {TypedArray.constructor} [typeClass=Float32Array] - A typed array constructor. + */ + constructor( count, itemSize, typeClass = Float32Array ) { - if ( ArrayBuffer.isView( array ) === false ) array = new typeClass( array * itemSize ); + const array = ArrayBuffer.isView( count ) ? count : new typeClass( count * itemSize ); super( array, itemSize ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isStorageBufferAttribute = true; } @@ -25103,7 +28846,7 @@ const storageElement = /*@__PURE__*/ nodeProxy( StorageArrayElementNode ); * storage buffer for data. A typical workflow is to create instances of * this node with the convenience functions `attributeArray()` or `instancedArray()`, * setup up a compute shader that writes into the buffers and then convert - * the storage buffers to attributes for rendering. + * the storage buffers to attribute nodes for rendering. * * ```js * const positionBuffer = instancedArray( particleCount, 'vec3' ); // the storage buffer node @@ -25140,7 +28883,7 @@ class StorageBufferNode extends BufferNode { /** * Constructs a new storage buffer node. * - * @param {StorageBufferAttribute|StorageInstancedBufferAttribute} value - The buffer data. + * @param {StorageBufferAttribute|StorageInstancedBufferAttribute|BufferAttribute} value - The buffer data. * @param {String?} [bufferType=null] - The buffer type (e.g. `'vec3'`). * @param {Number} [bufferCount=0] - The buffer count. */ @@ -25426,7 +29169,7 @@ class StorageBufferNode extends BufferNode { * TSL function for creating a storage buffer node. * * @function - * @param {StorageBufferAttribute|StorageInstancedBufferAttribute} value - The buffer data. + * @param {StorageBufferAttribute|StorageInstancedBufferAttribute|BufferAttribute} value - The buffer data. * @param {String?} [type=null] - The buffer type (e.g. `'vec3'`). * @param {Number} [count=0] - The buffer count. * @returns {StorageBufferNode} @@ -25454,8 +29197,9 @@ const storageObject = ( value, type, count ) => { // @deprecated, r171 const attributeArray = ( count, type = 'float' ) => { const itemSize = getLengthFromType( type ); + const typedArray = getTypedArrayFromType( type ); - const buffer = new StorageBufferAttribute( count, itemSize ); + const buffer = new StorageBufferAttribute( count, itemSize, typedArray ); const node = storage( buffer, type, count ); return node; @@ -25473,8 +29217,9 @@ const attributeArray = ( count, type = 'float' ) => { const instancedArray = ( count, type = 'float' ) => { const itemSize = getLengthFromType( type ); + const typedArray = getTypedArrayFromType( type ); - const buffer = new StorageInstancedBufferAttribute( count, itemSize ); + const buffer = new StorageInstancedBufferAttribute( count, itemSize, typedArray ); const node = storage( buffer, type, count ); return node; @@ -27976,6 +31721,8 @@ const nativeFn = ( code, includes = [], language = '' ) => { const glslFn = ( code, includes ) => nativeFn( code, includes, 'glsl' ); const wgslFn = ( code, includes ) => nativeFn( code, includes, 'wgsl' ); +/** @module ScriptableValueNode **/ + /** * `ScriptableNode` uses this class to manage script inputs and outputs. * @@ -28221,6 +31968,8 @@ class ScriptableValueNode extends Node { */ const scriptableValue = /*@__PURE__*/ nodeProxy( ScriptableValueNode ); +/** @module ScriptableNode **/ + /** * A Map-like data structure for managing resources of scriptable nodes. * @@ -28282,7 +32031,7 @@ class Parameters { } /** - * Defines the resouces (e.g. namespaces) of scriptable nodes. + * Defines the resources (e.g. namespaces) of scriptable nodes. * * @type {Resources} */ @@ -28494,7 +32243,7 @@ class ScriptableNode extends Node { * Returns a script output for the given name. * * @param {String} name - The name of the output. - * @return {Node} The node value. + * @return {ScriptableValueNode} The node value. */ getOutput( name ) { @@ -28503,7 +32252,7 @@ class ScriptableNode extends Node { } /** - * Returns a paramater for the given name + * Returns a parameter for the given name * * @param {String} name - The name of the parameter. * @return {ScriptableValueNode} The node value. @@ -28662,7 +32411,7 @@ class ScriptableNode extends Node { /** * Refreshes the script node. * - * @param {String?} [output=null] - An optinal output. + * @param {String?} [output=null] - An optional output. */ refresh( output = null ) { @@ -28698,7 +32447,7 @@ class ScriptableNode extends Node { const THREE = ScriptableNodeResources.get( 'THREE' ); const TSL = ScriptableNodeResources.get( 'TSL' ); - const method = this.getMethod( this.codeNode ); + const method = this.getMethod(); const params = [ parameters, this._local, ScriptableNodeResources, refresh, setOutput, THREE, TSL ]; this._object = method( ...params ); @@ -28972,6 +32721,7 @@ function getViewZNode( builder ) { /** * Constructs a new range factor node. * + * @function * @param {Node} near - Defines the near value. * @param {Node} far - Defines the far value. */ @@ -28988,6 +32738,7 @@ const rangeFogFactor = Fn( ( [ near, far ], builder ) => { * a clear view near the camera and a faster than exponentially * densening fog farther from the camera. * + * @function * @param {Node} density - Defines the fog density. */ const densityFogFactor = Fn( ( [ density ], builder ) => { @@ -29002,6 +32753,7 @@ const densityFogFactor = Fn( ( [ density ], builder ) => { * This class can be used to configure a fog for the scene. * Nodes of this type are assigned to `Scene.fogNode`. * + * @function * @param {Node} color - Defines the color of the fog. * @param {Node} factor - Defines how the fog is factored in the scene. */ @@ -29191,7 +32943,10 @@ const range = /*@__PURE__*/ nodeProxy( RangeNode ); /** @module ComputeBuiltinNode **/ /** - * TODO + * `ComputeBuiltinNode` represents a compute-scope builtin value that expose information + * about the currently running dispatch and/or the device it is running on. + * + * This node can only be used with a WebGPU backend. * * @augments Node */ @@ -29334,6 +33089,24 @@ const computeBuiltin = ( name, nodeType ) => nodeObject( new ComputeBuiltinNode( /** * TSL function for creating a `numWorkgroups` builtin node. + * Represents the number of workgroups dispatched by the compute shader. + * ```js + * // Run 512 invocations/threads with a workgroup size of 128. + * const computeFn = Fn(() => { + * + * // numWorkgroups.x = 4 + * storageBuffer.element(0).assign(numWorkgroups.x) + * + * })().compute(512, [128]); + * + * // Run 512 invocations/threads with the default workgroup size of 64. + * const computeFn = Fn(() => { + * + * // numWorkgroups.x = 8 + * storageBuffer.element(0).assign(numWorkgroups.x) + * + * })().compute(512); + * ``` * * @function * @returns {ComputeBuiltinNode} @@ -29342,6 +33115,26 @@ const numWorkgroups = /*@__PURE__*/ computeBuiltin( 'numWorkgroups', 'uvec3' ); /** * TSL function for creating a `workgroupId` builtin node. + * Represents the 3-dimensional index of the workgroup the current compute invocation belongs to. + * ```js + * // Execute 12 compute threads with a workgroup size of 3. + * const computeFn = Fn( () => { + * + * If( workgroupId.x.modInt( 2 ).equal( 0 ), () => { + * + * storageBuffer.element( instanceIndex ).assign( instanceIndex ); + * + * } ).Else( () => { + * + * storageBuffer.element( instanceIndex ).assign( 0 ); + * + * } ); + * + * } )().compute( 12, [ 3 ] ); + * + * // workgroupId.x = [0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3]; + * // Buffer Output = [0, 1, 2, 0, 0, 0, 6, 7, 8, 0, 0, 0]; + * ``` * * @function * @returns {ComputeBuiltinNode} @@ -29349,7 +33142,8 @@ const numWorkgroups = /*@__PURE__*/ computeBuiltin( 'numWorkgroups', 'uvec3' ); const workgroupId = /*@__PURE__*/ computeBuiltin( 'workgroupId', 'uvec3' ); /** - * TSL function for creating a `localId` builtin node. + * TSL function for creating a `localId` builtin node. A non-linearized 3-dimensional + * representation of the current invocation's position within a 3D workgroup grid. * * @function * @returns {ComputeBuiltinNode} @@ -29357,7 +33151,8 @@ const workgroupId = /*@__PURE__*/ computeBuiltin( 'workgroupId', 'uvec3' ); const localId = /*@__PURE__*/ computeBuiltin( 'localId', 'uvec3' ); /** - * TSL function for creating a `subgroupSize` builtin node. + * TSL function for creating a `subgroupSize` builtin node. A device dependent variable + * that exposes the size of the current invocation's subgroup. * * @function * @returns {ComputeBuiltinNode} @@ -29367,7 +33162,9 @@ const subgroupSize = /*@__PURE__*/ computeBuiltin( 'subgroupSize', 'uint' ); /** @module BarrierNode **/ /** - * TODO + * Represents a GPU control barrier that synchronizes compute operations within a given scope. + * + * This node can only be used with a WebGPU backend. * * @augments Node */ @@ -29415,7 +33212,9 @@ class BarrierNode extends Node { const barrier = nodeProxy( BarrierNode ); /** - * TSL function for creating a workgroup barrier. + * TSL function for creating a workgroup barrier. All compute shader + * invocations must wait for each invocation within a workgroup to + * complete before the barrier can be surpassed. * * @function * @returns {BarrierNode} @@ -29423,7 +33222,9 @@ const barrier = nodeProxy( BarrierNode ); const workgroupBarrier = () => barrier( 'workgroup' ).append(); /** - * TSL function for creating a storage barrier. + * TSL function for creating a storage barrier. All invocations must + * wait for each access to variables within the 'storage' address space + * to complete before the barrier can be passed. * * @function * @returns {BarrierNode} @@ -29431,7 +33232,9 @@ const workgroupBarrier = () => barrier( 'workgroup' ).append(); const storageBarrier = () => barrier( 'storage' ).append(); /** - * TSL function for creating a texture barrier. + * TSL function for creating a texture barrier. All invocations must + * wait for each access to variables within the 'texture' address space + * to complete before the barrier can be passed. * * @function * @returns {BarrierNode} @@ -29441,7 +33244,7 @@ const textureBarrier = () => barrier( 'texture' ).append(); /** @module WorkgroupInfoNode **/ /** - * TODO + * Represents an element of a 'workgroup' scoped buffer. * * @augments ArrayElementNode */ @@ -29492,18 +33295,25 @@ class WorkgroupInfoElementNode extends ArrayElementNode { } /** - * TODO + * A node allowing the user to create a 'workgroup' scoped buffer within the + * context of a compute shader. Typically, workgroup scoped buffers are + * created to hold data that is transferred from a global storage scope into + * a local workgroup scope. For invocations within a workgroup, data + * access speeds on 'workgroup' scoped buffers can be significantly faster + * than similar access operations on globally accessible storage buffers. + * + * This node can only be used with a WebGPU backend. * * @augments Node */ class WorkgroupInfoNode extends Node { /** - * Constructs a new workgroup info node. + * Constructs a new buffer scoped to type scope. * * @param {String} scope - TODO. - * @param {String} bufferType - The buffer type. - * @param {Number} [bufferCount=0] - The buffer count. + * @param {String} bufferType - The data type of a 'workgroup' scoped buffer element. + * @param {Number} [bufferCount=0] - The number of elements in the buffer. */ constructor( scope, bufferType, bufferCount = 0 ) { @@ -29533,6 +33343,13 @@ class WorkgroupInfoNode extends Node { */ this.isWorkgroupInfoNode = true; + /** + * The data type of the array buffer. + * + * @type {String} + */ + this.elementType = bufferType; + /** * TODO. * @@ -29570,6 +33387,18 @@ class WorkgroupInfoNode extends Node { } + + /** + * The data type of the array buffer. + * + * @return {String} The element type. + */ + getElementType() { + + return this.elementType; + + } + /** * Overwrites the default implementation since the input type * is inferred from the scope. @@ -29605,10 +33434,11 @@ class WorkgroupInfoNode extends Node { /** * TSL function for creating a workgroup info node. + * Creates a new 'workgroup' scoped array buffer. * * @function - * @param {String} type - The buffer type. - * @param {Number} [count=0] - The buffer count. + * @param {String} type - The data type of a 'workgroup' scoped buffer element. + * @param {Number} [count=0] - The number of elements in the buffer. * @returns {WorkgroupInfoNode} */ const workgroupArray = ( type, count ) => nodeObject( new WorkgroupInfoNode( 'Workgroup', type, count ) ); @@ -29616,7 +33446,13 @@ const workgroupArray = ( type, count ) => nodeObject( new WorkgroupInfoNode( 'Wo /** @module AtomicFunctionNode **/ /** - * TODO + * `AtomicFunctionNode` represents any function that can operate on atomic variable types + * within a shader. In an atomic function, any modification to an atomic variable will + * occur as an indivisible step with a defined order relative to other modifications. + * Accordingly, even if multiple atomic functions are modifying an atomic variable at once + * atomic operations will not interfere with each other. + * + * This node can only be used with a WebGPU backend. * * @augments TempNode */ @@ -29631,38 +33467,38 @@ class AtomicFunctionNode extends TempNode { /** * Constructs a new atomic function node. * - * @param {String} method - TODO. - * @param {Node} pointerNode - TODO. - * @param {Node} valueNode - TODO. - * @param {Node?} [storeNode=null] - TODO. + * @param {String} method - The signature of the atomic function to construct. + * @param {Node} pointerNode - An atomic variable or element of an atomic buffer. + * @param {Node} valueNode - The value that mutates the atomic variable. + * @param {Node?} [storeNode=null] - A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. */ constructor( method, pointerNode, valueNode, storeNode = null ) { super( 'uint' ); /** - * TODO + * The signature of the atomic function to construct. * * @type {String} */ this.method = method; /** - * TODO + * An atomic variable or element of an atomic buffer. * * @type {Node} */ this.pointerNode = pointerNode; /** - * TODO + * A value that modifies the atomic variable. * * @type {Node} */ this.valueNode = valueNode; /** - * TODO + * A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. * * @type {Node?} * @default null @@ -29743,22 +33579,22 @@ AtomicFunctionNode.ATOMIC_XOR = 'atomicXor'; * TSL function for creating an atomic function node. * * @function - * @param {String} method - TODO. - * @param {Node} pointerNode - TODO. - * @param {Node} valueNode - TODO. - * @param {Node?} [storeNode=null] - TODO. + * @param {String} method - The signature of the atomic function to construct. + * @param {Node} pointerNode - An atomic variable or element of an atomic buffer. + * @param {Node} valueNode - The value that mutates the atomic variable. + * @param {Node?} [storeNode=null] - A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. * @returns {AtomicFunctionNode} */ const atomicNode = nodeProxy( AtomicFunctionNode ); /** - * TODO + * TSL function for appending an atomic function call into the programmatic flow of a compute shader. * * @function - * @param {String} method - TODO. - * @param {Node} pointerNode - TODO. - * @param {Node} valueNode - TODO. - * @param {Node?} [storeNode=null] - TODO. + * @param {String} method - The signature of the atomic function to construct. + * @param {Node} pointerNode - An atomic variable or element of an atomic buffer. + * @param {Node} valueNode - The value that mutates the atomic variable. + * @param {Node?} [storeNode=null] - A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. * @returns {AtomicFunctionNode} */ const atomicFunc = ( method, pointerNode, valueNode, storeNode = null ) => { @@ -29771,89 +33607,89 @@ const atomicFunc = ( method, pointerNode, valueNode, storeNode = null ) => { }; /** - * TODO + * Stores a value in the atomic variable. * * @function - * @param {Node} pointerNode - TODO. - * @param {Node} valueNode - TODO. - * @param {Node?} [storeNode=null] - TODO. + * @param {Node} pointerNode - An atomic variable or element of an atomic buffer. + * @param {Node} valueNode - The value that mutates the atomic variable. + * @param {Node?} [storeNode=null] - A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. * @returns {AtomicFunctionNode} */ const atomicStore = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_STORE, pointerNode, valueNode, storeNode ); /** - * TODO + * Increments the value stored in the atomic variable. * * @function - * @param {Node} pointerNode - TODO. - * @param {Node} valueNode - TODO. - * @param {Node?} [storeNode=null] - TODO. + * @param {Node} pointerNode - An atomic variable or element of an atomic buffer. + * @param {Node} valueNode - The value that mutates the atomic variable. + * @param {Node?} [storeNode=null] - A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. * @returns {AtomicFunctionNode} */ const atomicAdd = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_ADD, pointerNode, valueNode, storeNode ); /** - * TODO + * Decrements the value stored in the atomic variable. * * @function - * @param {Node} pointerNode - TODO. - * @param {Node} valueNode - TODO. - * @param {Node?} [storeNode=null] - TODO. + * @param {Node} pointerNode - An atomic variable or element of an atomic buffer. + * @param {Node} valueNode - The value that mutates the atomic variable. + * @param {Node?} [storeNode=null] - A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. * @returns {AtomicFunctionNode} */ const atomicSub = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_SUB, pointerNode, valueNode, storeNode ); /** - * TODO + * Stores in an atomic variable the maximum between its current value and a parameter. * * @function - * @param {Node} pointerNode - TODO. - * @param {Node} valueNode - TODO. - * @param {Node?} [storeNode=null] - TODO. + * @param {Node} pointerNode - An atomic variable or element of an atomic buffer. + * @param {Node} valueNode - The value that mutates the atomic variable. + * @param {Node?} [storeNode=null] - A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. * @returns {AtomicFunctionNode} */ const atomicMax = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_MAX, pointerNode, valueNode, storeNode ); /** - * TODO + * Stores in an atomic variable the minimum between its current value and a parameter. * * @function - * @param {Node} pointerNode - TODO. - * @param {Node} valueNode - TODO. - * @param {Node?} [storeNode=null] - TODO. + * @param {Node} pointerNode - An atomic variable or element of an atomic buffer. + * @param {Node} valueNode - The value that mutates the atomic variable. + * @param {Node?} [storeNode=null] - A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. * @returns {AtomicFunctionNode} */ const atomicMin = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_MIN, pointerNode, valueNode, storeNode ); /** - * TODO + * Stores in an atomic variable the bitwise AND of its value with a parameter. * * @function - * @param {Node} pointerNode - TODO. - * @param {Node} valueNode - TODO. - * @param {Node?} [storeNode=null] - TODO. + * @param {Node} pointerNode - An atomic variable or element of an atomic buffer. + * @param {Node} valueNode - The value that mutates the atomic variable. + * @param {Node?} [storeNode=null] - A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. * @returns {AtomicFunctionNode} */ const atomicAnd = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_AND, pointerNode, valueNode, storeNode ); /** - * TODO + * Stores in an atomic variable the bitwise OR of its value with a parameter. * * @function - * @param {Node} pointerNode - TODO. - * @param {Node} valueNode - TODO. - * @param {Node?} [storeNode=null] - TODO. + * @param {Node} pointerNode - An atomic variable or element of an atomic buffer. + * @param {Node} valueNode - The value that mutates the atomic variable. + * @param {Node?} [storeNode=null] - A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. * @returns {AtomicFunctionNode} */ const atomicOr = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_OR, pointerNode, valueNode, storeNode ); /** - * TODO + * Stores in an atomic variable the bitwise XOR of its value with a parameter. * * @function - * @param {Node} pointerNode - TODO. - * @param {Node} valueNode - TODO. - * @param {Node?} [storeNode=null] - TODO. + * @param {Node} pointerNode - An atomic variable or element of an atomic buffer. + * @param {Node} valueNode - The value that mutates the atomic variable. + * @param {Node?} [storeNode=null] - A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation. * @returns {AtomicFunctionNode} */ const atomicXor = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_XOR, pointerNode, valueNode, storeNode ); @@ -30428,7 +34264,7 @@ class ShadowBaseNode extends Node { } /** - * Setups the shadow position node which is by default the predefined TSL node object `shadowWorldPosition`. + * Setups the shadow position node which is by default the predefined TSL node object `shadowPositionWorld`. * * @param {(NodeBuilder|{Material})} object - A configuration object that must at least hold a material reference. */ @@ -30436,7 +34272,7 @@ class ShadowBaseNode extends Node { // Use assign inside an Fn() - shadowWorldPosition.assign( material.shadowPositionNode || positionWorld ); + shadowPositionWorld.assign( material.shadowPositionNode || positionWorld ); } @@ -30458,7 +34294,212 @@ class ShadowBaseNode extends Node { * * @type {Node} */ -const shadowWorldPosition = /*@__PURE__*/ vec3().toVar( 'shadowWorldPosition' ); +const shadowPositionWorld = /*@__PURE__*/ vec3().toVar( 'shadowPositionWorld' ); + +/** @module RendererUtils **/ + +/** + * Saves the state of the given renderer and stores it into the given state object. + * + * If not state object is provided, the function creates one. + * + * @function + * @param {Renderer} renderer - The renderer. + * @param {Object} [state={}] - The state. + * @return {Object} The state. + */ +function saveRendererState( renderer, state = {} ) { + + state.toneMapping = renderer.toneMapping; + state.toneMappingExposure = renderer.toneMappingExposure; + state.outputColorSpace = renderer.outputColorSpace; + state.renderTarget = renderer.getRenderTarget(); + state.activeCubeFace = renderer.getActiveCubeFace(); + state.activeMipmapLevel = renderer.getActiveMipmapLevel(); + state.renderObjectFunction = renderer.getRenderObjectFunction(); + state.pixelRatio = renderer.getPixelRatio(); + state.mrt = renderer.getMRT(); + state.clearColor = renderer.getClearColor( state.clearColor || new Color() ); + state.clearAlpha = renderer.getClearAlpha(); + state.autoClear = renderer.autoClear; + state.scissorTest = renderer.getScissorTest(); + + return state; + +} + +/** + * Saves the state of the given renderer and stores it into the given state object. + * Besides, the function also resets the state of the renderer to its default values. + * + * If not state object is provided, the function creates one. + * + * @function + * @param {Renderer} renderer - The renderer. + * @param {Object} [state={}] - The state. + * @return {Object} The state. + */ +function resetRendererState( renderer, state ) { + + state = saveRendererState( renderer, state ); + + renderer.setMRT( null ); + renderer.setRenderObjectFunction( null ); + renderer.setClearColor( 0x000000, 1 ); + renderer.autoClear = true; + + return state; + +} + +/** + * Restores the state of the given renderer from the given state object. + * + * @function + * @param {Renderer} renderer - The renderer. + * @param {Object} state - The state to restore. + */ +function restoreRendererState( renderer, state ) { + + renderer.toneMapping = state.toneMapping; + renderer.toneMappingExposure = state.toneMappingExposure; + renderer.outputColorSpace = state.outputColorSpace; + renderer.setRenderTarget( state.renderTarget, state.activeCubeFace, state.activeMipmapLevel ); + renderer.setRenderObjectFunction( state.renderObjectFunction ); + renderer.setPixelRatio( state.pixelRatio ); + renderer.setMRT( state.mrt ); + renderer.setClearColor( state.clearColor, state.clearAlpha ); + renderer.autoClear = state.autoClear; + renderer.setScissorTest( state.scissorTest ); + +} + +/** + * Saves the state of the given scene and stores it into the given state object. + * + * If not state object is provided, the function creates one. + * + * @function + * @param {Scene} scene - The scene. + * @param {Object} [state={}] - The state. + * @return {Object} The state. + */ +function saveSceneState( scene, state = {} ) { + + state.background = scene.background; + state.backgroundNode = scene.backgroundNode; + state.overrideMaterial = scene.overrideMaterial; + + return state; + +} + +/** + * Saves the state of the given scene and stores it into the given state object. + * Besides, the function also resets the state of the scene to its default values. + * + * If not state object is provided, the function creates one. + * + * @function + * @param {Scene} scene - The scene. + * @param {Object} [state={}] - The state. + * @return {Object} The state. + */ +function resetSceneState( scene, state ) { + + state = saveSceneState( scene, state ); + + scene.background = null; + scene.backgroundNode = null; + scene.overrideMaterial = null; + + return state; + +} + +/** + * Restores the state of the given scene from the given state object. + * + * @function + * @param {Scene} scene - The scene. + * @param {Object} state - The state to restore. + */ +function restoreSceneState( scene, state ) { + + scene.background = state.background; + scene.backgroundNode = state.backgroundNode; + scene.overrideMaterial = state.overrideMaterial; + +} + +/** + * Saves the state of the given renderer and scene and stores it into the given state object. + * + * If not state object is provided, the function creates one. + * + * @function + * @param {Renderer} renderer - The renderer. + * @param {Scene} scene - The scene. + * @param {Object} [state={}] - The state. + * @return {Object} The state. + */ +function saveRendererAndSceneState( renderer, scene, state = {} ) { + + state = saveRendererState( renderer, state ); + state = saveSceneState( scene, state ); + + return state; + +} + +/** + * Saves the state of the given renderer and scene and stores it into the given state object. + * Besides, the function also resets the state of the renderer and scene to its default values. + * + * If not state object is provided, the function creates one. + * + * @function + * @param {Renderer} renderer - The renderer. + * @param {Scene} scene - The scene. + * @param {Object} [state={}] - The state. + * @return {Object} The state. + */ +function resetRendererAndSceneState( renderer, scene, state ) { + + state = resetRendererState( renderer, state ); + state = resetSceneState( scene, state ); + + return state; + +} + +/** + * Restores the state of the given renderer and scene from the given state object. + * + * @function + * @param {Renderer} renderer - The renderer. + * @param {Scene} scene - The scene. + * @param {Object} state - The state to restore. + */ +function restoreRendererAndSceneState( renderer, scene, state ) { + + restoreRendererState( renderer, state ); + restoreSceneState( scene, state ); + +} + +var RendererUtils = /*#__PURE__*/Object.freeze({ + __proto__: null, + resetRendererAndSceneState: resetRendererAndSceneState, + resetRendererState: resetRendererState, + resetSceneState: resetSceneState, + restoreRendererAndSceneState: restoreRendererAndSceneState, + restoreRendererState: restoreRendererState, + restoreSceneState: restoreSceneState, + saveRendererAndSceneState: saveRendererAndSceneState, + saveRendererState: saveRendererState, + saveSceneState: saveSceneState +}); /** @module ShadowNode **/ @@ -30499,6 +34540,7 @@ const getShadowMaterial = ( light ) => { material.depthNode = depthNode; material.isShadowNodeMaterial = true; // Use to avoid other overrideMaterial override material.colorNode unintentionally when using material.shadowNode material.name = 'ShadowMaterial'; + material.fog = false; shadowMaterialLib.set( light, material ); @@ -30748,7 +34790,8 @@ const _shadowFilterLib = [ BasicShadowFilter, PCFShadowFilter, PCFSoftShadowFilt // -const _quadMesh$1 = /*@__PURE__*/ new QuadMesh(); +let _rendererState; +const _quadMesh = /*@__PURE__*/ new QuadMesh(); /** * Represents the default shadow implementation for lighting nodes. @@ -30991,7 +35034,7 @@ class ShadowNode extends ShadowBaseNode { const shadowIntensity = reference( 'intensity', 'float', shadow ).setGroup( renderGroup ); const normalBias = reference( 'normalBias', 'float', shadow ).setGroup( renderGroup ); - const shadowPosition = lightShadowMatrix( light ).mul( shadowWorldPosition.add( transformedNormalWorld.mul( normalBias ) ) ); + const shadowPosition = lightShadowMatrix( light ).mul( shadowPositionWorld.add( transformedNormalWorld.mul( normalBias ) ) ); const shadowCoord = this.setupShadowCoord( builder, shadowPosition ); // @@ -31095,22 +35138,27 @@ class ShadowNode extends ShadowBaseNode { const depthVersion = shadowMap.depthTexture.version; this._depthVersionCached = depthVersion; - const currentOverrideMaterial = scene.overrideMaterial; - - scene.overrideMaterial = getShadowMaterial( light ); - shadow.camera.layers.mask = camera.layers.mask; - const currentRenderTarget = renderer.getRenderTarget(); const currentRenderObjectFunction = renderer.getRenderObjectFunction(); + const currentMRT = renderer.getMRT(); + const useVelocity = currentMRT ? currentMRT.has( 'velocity' ) : false; - renderer.setMRT( null ); + _rendererState = resetRendererAndSceneState( renderer, scene, _rendererState ); + + scene.overrideMaterial = getShadowMaterial( light ); renderer.setRenderObjectFunction( ( object, scene, _camera, geometry, material, group, ...params ) => { if ( object.castShadow === true || ( object.receiveShadow && shadowType === VSMShadowMap ) ) { + if ( useVelocity ) { + + getDataFromObject( object ).useVelocity = true; + + } + object.onBeforeShadow( renderer, object, camera, shadow.camera, geometry, scene.overrideMaterial, group ); renderer.renderObject( object, scene, _camera, geometry, material, group, ...params ); @@ -31135,11 +35183,7 @@ class ShadowNode extends ShadowBaseNode { } - renderer.setRenderTarget( currentRenderTarget ); - - renderer.setMRT( currentMRT ); - - scene.overrideMaterial = currentOverrideMaterial; + restoreRendererAndSceneState( renderer, scene, _rendererState ); } @@ -31156,12 +35200,12 @@ class ShadowNode extends ShadowBaseNode { this.vsmShadowMapHorizontal.setSize( shadow.mapSize.width, shadow.mapSize.height ); renderer.setRenderTarget( this.vsmShadowMapVertical ); - _quadMesh$1.material = this.vsmMaterialVertical; - _quadMesh$1.render( renderer ); + _quadMesh.material = this.vsmMaterialVertical; + _quadMesh.render( renderer ); renderer.setRenderTarget( this.vsmShadowMapHorizontal ); - _quadMesh$1.material = this.vsmMaterialHorizontal; - _quadMesh$1.render( renderer ); + _quadMesh.material = this.vsmMaterialHorizontal; + _quadMesh.render( renderer ); } @@ -33634,6 +37678,7 @@ var TSL = /*#__PURE__*/Object.freeze({ expression: expression, faceDirection: faceDirection, faceForward: faceForward, + faceforward: faceforward, float: float, floor: floor, fog: fog, @@ -33673,6 +37718,7 @@ var TSL = /*#__PURE__*/Object.freeze({ instancedMesh: instancedMesh, int: int, inverseSqrt: inverseSqrt, + inversesqrt: inversesqrt, invocationLocalIndex: invocationLocalIndex, invocationSubgroupIndex: invocationSubgroupIndex, ior: ior, @@ -33708,7 +37754,7 @@ var TSL = /*#__PURE__*/Object.freeze({ mat3: mat3, mat4: mat4, matcapUV: matcapUV, - materialAOMap: materialAOMap, + materialAO: materialAO, materialAlphaTest: materialAlphaTest, materialAnisotropy: materialAnisotropy, materialAnisotropyVector: materialAnisotropyVector, @@ -33891,7 +37937,7 @@ var TSL = /*#__PURE__*/Object.freeze({ setCurrentStack: setCurrentStack, shaderStages: shaderStages, shadow: shadow, - shadowWorldPosition: shadowWorldPosition, + shadowPositionWorld: shadowPositionWorld, sharedUniformGroup: sharedUniformGroup, sheen: sheen, sheenRoughness: sheenRoughness, @@ -33982,6 +38028,7 @@ var TSL = /*#__PURE__*/Object.freeze({ velocity: velocity, vertexColor: vertexColor, vertexIndex: vertexIndex, + vertexStage: vertexStage, vibrance: vibrance, viewZToLogarithmicDepth: viewZToLogarithmicDepth, viewZToOrthographicDepth: viewZToOrthographicDepth, @@ -34010,17 +38057,50 @@ var TSL = /*#__PURE__*/Object.freeze({ const _clearColor$1 = /*@__PURE__*/ new Color4(); +/** + * This renderer module manages the background. + * + * @private + * @augments DataMap + */ class Background extends DataMap { + /** + * Constructs a new background management component. + * + * @param {Renderer} renderer - The renderer. + * @param {Nodes} nodes - Renderer component for managing nodes related logic. + */ constructor( renderer, nodes ) { super(); + /** + * The renderer. + * + * @type {Renderer} + */ this.renderer = renderer; + + /** + * Renderer component for managing nodes related logic. + * + * @type {Nodes} + */ this.nodes = nodes; } + /** + * Updates the background for the given scene. Depending on how `Scene.background` + * or `Scene.backgroundNode` are configured, this method might configure a simple clear + * or add a mesh to the render list for rendering the background as a textured plane + * or skybox. + * + * @param {Scene} scene - The scene. + * @param {RenderList} renderList - The current render list. + * @param {RenderContext} renderContext - The current render context. + */ update( scene, renderList, renderContext ) { const renderer = this.renderer; @@ -34152,50 +38232,187 @@ class Background extends DataMap { let _id$6 = 0; +/** + * A bind group represents a collection of bindings and thus a collection + * or resources. Bind groups are assigned to pipelines to provide them + * with the required resources (like uniform buffers or textures). + * + * @private + */ class BindGroup { + /** + * Constructs a new bind group. + * + * @param {String} name - The bind group's name. + * @param {Array} bindings - An array of bindings. + * @param {Number} index - The group index. + * @param {Array} bindingsReference - An array of reference bindings. + */ constructor( name = '', bindings = [], index = 0, bindingsReference = [] ) { + /** + * The bind group's name. + * + * @type {String} + */ this.name = name; + + /** + * An array of bindings. + * + * @type {Array} + */ this.bindings = bindings; + + /** + * The group index. + * + * @type {Number} + */ this.index = index; + + /** + * An array of reference bindings. + * + * @type {Array} + */ this.bindingsReference = bindingsReference; + /** + * The group's ID. + * + * @type {Number} + */ this.id = _id$6 ++; } } +/** + * This module represents the state of a node builder after it was + * used to build the nodes for a render object. The state holds the + * results of the build for further processing in the renderer. + * + * Render objects with identical cache keys share the same node builder state. + * + * @private + */ class NodeBuilderState { + /** + * Constructs a new node builder state. + * + * @param {String?} vertexShader - The native vertex shader code. + * @param {String?} fragmentShader - The native fragment shader code. + * @param {String?} computeShader - The native compute shader code. + * @param {Array} nodeAttributes - An array of node attributes. + * @param {Array} bindings - An array of bind groups. + * @param {Array} updateNodes - An array of nodes that implement their `update()` method. + * @param {Array} updateBeforeNodes - An array of nodes that implement their `updateBefore()` method. + * @param {Array} updateAfterNodes - An array of nodes that implement their `updateAfter()` method. + * @param {NodeMaterialObserver} monitor - A node material observer. + * @param {Array} transforms - An array with transform attribute objects. Only relevant when using compute shaders with WebGL 2. + */ constructor( vertexShader, fragmentShader, computeShader, nodeAttributes, bindings, updateNodes, updateBeforeNodes, updateAfterNodes, monitor, transforms = [] ) { + /** + * The native vertex shader code. + * + * @type {String} + */ this.vertexShader = vertexShader; + + /** + * The native fragment shader code. + * + * @type {String} + */ this.fragmentShader = fragmentShader; + + /** + * The native compute shader code. + * + * @type {String} + */ this.computeShader = computeShader; + + /** + * An array with transform attribute objects. + * Only relevant when using compute shaders with WebGL 2. + * + * @type {Array} + */ this.transforms = transforms; + /** + * An array of node attributes representing + * the attributes of the shaders. + * + * @type {Array} + */ this.nodeAttributes = nodeAttributes; + + /** + * An array of bind groups representing the uniform or storage + * buffers, texture or samplers of the shader. + * + * @type {Array} + */ this.bindings = bindings; + /** + * An array of nodes that implement their `update()` method. + * + * @type {Array} + */ this.updateNodes = updateNodes; + + /** + * An array of nodes that implement their `updateBefore()` method. + * + * @type {Array} + */ this.updateBeforeNodes = updateBeforeNodes; + + /** + * An array of nodes that implement their `updateAfter()` method. + * + * @type {Array} + */ this.updateAfterNodes = updateAfterNodes; + /** + * A node material observer. + * + * @type {NodeMaterialObserver} + */ this.monitor = monitor; + /** + * How often this state is used by render objects. + * + * @type {Number} + */ this.usedTimes = 0; } + /** + * This method is used to create a array of bind groups based + * on the existing bind groups of this state. Shared groups are + * not cloned. + * + * @return {Array} A array of bind groups. + */ createBindings() { const bindings = []; for ( const instanceGroup of this.bindings ) { - const shared = instanceGroup.bindings[ 0 ].groupNode.shared; + const shared = instanceGroup.bindings[ 0 ].groupNode.shared; // TODO: Is it safe to always check the first binding in the group? if ( shared !== true ) { @@ -34631,26 +38848,79 @@ class StructTypeNode extends Node { } +/** + * Abstract base class for uniforms. + * + * @abstract + * @private + */ class Uniform { + /** + * Constructs a new uniform. + * + * @param {String} name - The uniform's name. + * @param {Any} value - The uniform's value. + */ constructor( name, value ) { + /** + * The uniform's name. + * + * @type {String} + */ this.name = name; + + /** + * The uniform's value. + * + * @type {Any} + */ this.value = value; - this.boundary = 0; // used to build the uniform buffer according to the STD140 layout + /** + * Used to build the uniform buffer according to the STD140 layout. + * Derived uniforms will set this property to a data type specific + * value. + * + * @type {Number} + */ + this.boundary = 0; + + /** + * The item size. Derived uniforms will set this property to a data + * type specific value. + * + * @type {Number} + */ this.itemSize = 0; - this.offset = 0; // this property is set by WebGPUUniformsGroup and marks the start position in the uniform buffer + /** + * This property is set by {@link UniformsGroup} and marks + * the start position in the uniform buffer. + * + * @type {Number} + */ + this.offset = 0; } + /** + * Sets the uniform's value. + * + * @param {Any} value - The value to set. + */ setValue( value ) { this.value = value; } + /** + * Returns the uniform's value. + * + * @return {Any} The value. + */ getValue() { return this.value; @@ -34659,12 +38929,31 @@ class Uniform { } +/** + * Represents a Number uniform. + * + * @private + * @augments Uniform + */ class NumberUniform extends Uniform { + /** + * Constructs a new Number uniform. + * + * @param {String} name - The uniform's name. + * @param {Number} value - The uniform's value. + */ constructor( name, value = 0 ) { super( name, value ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isNumberUniform = true; this.boundary = 4; @@ -34674,12 +38963,31 @@ class NumberUniform extends Uniform { } +/** + * Represents a Vector2 uniform. + * + * @private + * @augments Uniform + */ class Vector2Uniform extends Uniform { + /** + * Constructs a new Number uniform. + * + * @param {String} name - The uniform's name. + * @param {Vector2} value - The uniform's value. + */ constructor( name, value = new Vector2() ) { super( name, value ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isVector2Uniform = true; this.boundary = 8; @@ -34689,12 +38997,31 @@ class Vector2Uniform extends Uniform { } +/** + * Represents a Vector3 uniform. + * + * @private + * @augments Uniform + */ class Vector3Uniform extends Uniform { + /** + * Constructs a new Number uniform. + * + * @param {String} name - The uniform's name. + * @param {Vector3} value - The uniform's value. + */ constructor( name, value = new Vector3() ) { super( name, value ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isVector3Uniform = true; this.boundary = 16; @@ -34704,12 +39031,31 @@ class Vector3Uniform extends Uniform { } +/** + * Represents a Vector4 uniform. + * + * @private + * @augments Uniform + */ class Vector4Uniform extends Uniform { + /** + * Constructs a new Number uniform. + * + * @param {String} name - The uniform's name. + * @param {Vector4} value - The uniform's value. + */ constructor( name, value = new Vector4() ) { super( name, value ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isVector4Uniform = true; this.boundary = 16; @@ -34719,12 +39065,31 @@ class Vector4Uniform extends Uniform { } +/** + * Represents a Color uniform. + * + * @private + * @augments Uniform + */ class ColorUniform extends Uniform { + /** + * Constructs a new Number uniform. + * + * @param {String} name - The uniform's name. + * @param {Color} value - The uniform's value. + */ constructor( name, value = new Color() ) { super( name, value ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isColorUniform = true; this.boundary = 16; @@ -34734,12 +39099,31 @@ class ColorUniform extends Uniform { } +/** + * Represents a Matrix3 uniform. + * + * @private + * @augments Uniform + */ class Matrix3Uniform extends Uniform { + /** + * Constructs a new Number uniform. + * + * @param {String} name - The uniform's name. + * @param {Matrix3} value - The uniform's value. + */ constructor( name, value = new Matrix3() ) { super( name, value ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMatrix3Uniform = true; this.boundary = 48; @@ -34749,12 +39133,31 @@ class Matrix3Uniform extends Uniform { } +/** + * Represents a Matrix4 uniform. + * + * @private + * @augments Uniform + */ class Matrix4Uniform extends Uniform { + /** + * Constructs a new Number uniform. + * + * @param {String} name - The uniform's name. + * @param {Matrix4} value - The uniform's value. + */ constructor( name, value = new Matrix4() ) { super( name, value ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMatrix4Uniform = true; this.boundary = 64; @@ -34764,22 +39167,49 @@ class Matrix4Uniform extends Uniform { } +/** + * A special form of Number uniform binding type. + * It's value is managed by a node object. + * + * @private + * @augments NumberUniform + */ class NumberNodeUniform extends NumberUniform { + /** + * Constructs a new node-based Number uniform. + * + * @param {NodeUniform} nodeUniform - The node uniform. + */ constructor( nodeUniform ) { super( nodeUniform.name, nodeUniform.value ); + /** + * The node uniform. + * + * @type {NodeUniform} + */ this.nodeUniform = nodeUniform; } + /** + * Overwritten to return the value of the node uniform. + * + * @return {Number} The value. + */ getValue() { return this.nodeUniform.value; } + /** + * Returns the node uniform data type. + * + * @return {String} The data type. + */ getType() { return this.nodeUniform.type; @@ -34788,22 +39218,49 @@ class NumberNodeUniform extends NumberUniform { } +/** + * A special form of Vector2 uniform binding type. + * It's value is managed by a node object. + * + * @private + * @augments Vector2Uniform + */ class Vector2NodeUniform extends Vector2Uniform { + /** + * Constructs a new node-based Vector2 uniform. + * + * @param {NodeUniform} nodeUniform - The node uniform. + */ constructor( nodeUniform ) { super( nodeUniform.name, nodeUniform.value ); + /** + * The node uniform. + * + * @type {NodeUniform} + */ this.nodeUniform = nodeUniform; } + /** + * Overwritten to return the value of the node uniform. + * + * @return {Vector2} The value. + */ getValue() { return this.nodeUniform.value; } + /** + * Returns the node uniform data type. + * + * @return {String} The data type. + */ getType() { return this.nodeUniform.type; @@ -34812,22 +39269,49 @@ class Vector2NodeUniform extends Vector2Uniform { } +/** + * A special form of Vector3 uniform binding type. + * It's value is managed by a node object. + * + * @private + * @augments Vector3Uniform + */ class Vector3NodeUniform extends Vector3Uniform { + /** + * Constructs a new node-based Vector3 uniform. + * + * @param {NodeUniform} nodeUniform - The node uniform. + */ constructor( nodeUniform ) { super( nodeUniform.name, nodeUniform.value ); + /** + * The node uniform. + * + * @type {NodeUniform} + */ this.nodeUniform = nodeUniform; } + /** + * Overwritten to return the value of the node uniform. + * + * @return {Vector3} The value. + */ getValue() { return this.nodeUniform.value; } + /** + * Returns the node uniform data type. + * + * @return {String} The data type. + */ getType() { return this.nodeUniform.type; @@ -34836,22 +39320,49 @@ class Vector3NodeUniform extends Vector3Uniform { } +/** + * A special form of Vector4 uniform binding type. + * It's value is managed by a node object. + * + * @private + * @augments Vector4Uniform + */ class Vector4NodeUniform extends Vector4Uniform { + /** + * Constructs a new node-based Vector4 uniform. + * + * @param {NodeUniform} nodeUniform - The node uniform. + */ constructor( nodeUniform ) { super( nodeUniform.name, nodeUniform.value ); + /** + * The node uniform. + * + * @type {NodeUniform} + */ this.nodeUniform = nodeUniform; } + /** + * Overwritten to return the value of the node uniform. + * + * @return {Vector4} The value. + */ getValue() { return this.nodeUniform.value; } + /** + * Returns the node uniform data type. + * + * @return {String} The data type. + */ getType() { return this.nodeUniform.type; @@ -34860,22 +39371,49 @@ class Vector4NodeUniform extends Vector4Uniform { } +/** + * A special form of Color uniform binding type. + * It's value is managed by a node object. + * + * @private + * @augments ColorUniform + */ class ColorNodeUniform extends ColorUniform { + /** + * Constructs a new node-based Color uniform. + * + * @param {NodeUniform} nodeUniform - The node uniform. + */ constructor( nodeUniform ) { super( nodeUniform.name, nodeUniform.value ); + /** + * The node uniform. + * + * @type {NodeUniform} + */ this.nodeUniform = nodeUniform; } + /** + * Overwritten to return the value of the node uniform. + * + * @return {Color} The value. + */ getValue() { return this.nodeUniform.value; } + /** + * Returns the node uniform data type. + * + * @return {String} The data type. + */ getType() { return this.nodeUniform.type; @@ -34884,22 +39422,49 @@ class ColorNodeUniform extends ColorUniform { } +/** + * A special form of Matrix3 uniform binding type. + * It's value is managed by a node object. + * + * @private + * @augments Matrix3Uniform + */ class Matrix3NodeUniform extends Matrix3Uniform { + /** + * Constructs a new node-based Matrix3 uniform. + * + * @param {NodeUniform} nodeUniform - The node uniform. + */ constructor( nodeUniform ) { super( nodeUniform.name, nodeUniform.value ); + /** + * The node uniform. + * + * @type {NodeUniform} + */ this.nodeUniform = nodeUniform; } + /** + * Overwritten to return the value of the node uniform. + * + * @return {Matrix3} The value. + */ getValue() { return this.nodeUniform.value; } + /** + * Returns the node uniform data type. + * + * @return {String} The data type. + */ getType() { return this.nodeUniform.type; @@ -34908,22 +39473,49 @@ class Matrix3NodeUniform extends Matrix3Uniform { } +/** + * A special form of Matrix4 uniform binding type. + * It's value is managed by a node object. + * + * @private + * @augments Matrix4Uniform + */ class Matrix4NodeUniform extends Matrix4Uniform { + /** + * Constructs a new node-based Matrix4 uniform. + * + * @param {NodeUniform} nodeUniform - The node uniform. + */ constructor( nodeUniform ) { super( nodeUniform.name, nodeUniform.value ); + /** + * The node uniform. + * + * @type {NodeUniform} + */ this.nodeUniform = nodeUniform; } + /** + * Overwritten to return the value of the node uniform. + * + * @return {Matrix4} The value. + */ getValue() { return this.nodeUniform.value; } + /** + * Returns the node uniform data type. + * + * @return {String} The data type. + */ getType() { return this.nodeUniform.type; @@ -36229,6 +40821,15 @@ class NodeBuilder { } + /** + * Returns the output struct name which is required by + * {@link module:OutputStructNode}. + * + * @abstract + * @return {String} The name of the output struct. + */ + getOutputStructName() {} + /** * Returns a bind group for the given group name and binding. * @@ -36410,6 +41011,7 @@ class NodeBuilder { /** * It is used to add Nodes that will be used as FRAME and RENDER events, * and need to follow a certain sequence in the calls to work correctly. + * This function should be called after 'setup()' in the 'build()' process to ensure that the child nodes are processed first. * * @param {Node} node - The node to add. */ @@ -36763,10 +41365,11 @@ class NodeBuilder { * @param {Texture} texture - The texture. * @param {String} textureProperty - The texture property name. * @param {String} uvSnippet - Snippet defining the texture coordinates. + * @param {String?} depthSnippet - Snippet defining the 0-based texture array index to sample. * @param {String} levelSnippet - Snippet defining the mip level. * @return {String} The generated shader string. */ - generateTextureLod( /* texture, textureProperty, uvSnippet, levelSnippet */ ) { + generateTextureLod( /* texture, textureProperty, uvSnippet, depthSnippet, levelSnippet */ ) { console.warn( 'Abstract function.' ); @@ -36940,11 +41543,11 @@ class NodeBuilder { } /** - * Whether the given texture needs a conversion to working color space. + * Checks if the given texture requires a manual conversion to the working color space. * * @abstract * @param {Texture} texture - The texture to check. - * @return {Boolean} Whether a color space conversion is required or not. + * @return {Boolean} Whether the given texture requires a conversion to working color space or not. */ needsToWorkingColorSpace( /*texture*/ ) { @@ -39309,29 +43912,93 @@ class GLSLNodeParser extends NodeParser { } -const outputNodeMap = new WeakMap(); +const _outputNodeMap = new WeakMap(); +const _chainKeys$2 = []; +const _cacheKeyValues = []; +/** + * This renderer module manages node-related objects and is the + * primary interface between the renderer and the node system. + * + * @private + * @augments DataMap + */ class Nodes extends DataMap { + /** + * Constructs a new nodes management component. + * + * @param {Renderer} renderer - The renderer. + * @param {Backend} backend - The renderer's backend. + */ constructor( renderer, backend ) { super(); + /** + * The renderer. + * + * @type {Renderer} + */ this.renderer = renderer; + + /** + * The renderer's backend. + * + * @type {Backend} + */ this.backend = backend; + + /** + * The node frame. + * + * @type {Renderer} + */ this.nodeFrame = new NodeFrame(); + + /** + * A cache for managing node builder states. + * + * @type {Map} + */ this.nodeBuilderCache = new Map(); + + /** + * A cache for managing data cache key data. + * + * @type {ChainMap} + */ this.callHashCache = new ChainMap(); + + /** + * A cache for managing node uniforms group data. + * + * @type {ChainMap} + */ this.groupsData = new ChainMap(); + /** + * A cache for managing node objects of + * scene properties like fog or environments. + * + * @type {Object} + */ + this.cacheLib = {}; + } + /** + * Returns `true` if the given node uniforms group must be updated or not. + * + * @param {NodeUniformsGroup} nodeUniformsGroup - The node uniforms group. + * @return {Boolean} Whether the node uniforms group requires an update or not. + */ updateGroup( nodeUniformsGroup ) { const groupNode = nodeUniformsGroup.groupNode; const name = groupNode.name; - // objectGroup is every updated + // objectGroup is always updated if ( name === objectGroup.name ) return true; @@ -39375,10 +44042,13 @@ class Nodes extends DataMap { // other groups are updated just when groupNode.needsUpdate is true - const groupChain = [ groupNode, nodeUniformsGroup ]; + _chainKeys$2[ 0 ] = groupNode; + _chainKeys$2[ 1 ] = nodeUniformsGroup; + + let groupData = this.groupsData.get( _chainKeys$2 ); + if ( groupData === undefined ) this.groupsData.set( _chainKeys$2, groupData = {} ); - let groupData = this.groupsData.get( groupChain ); - if ( groupData === undefined ) this.groupsData.set( groupChain, groupData = {} ); + _chainKeys$2.length = 0; if ( groupData.version !== groupNode.version ) { @@ -39392,12 +44062,24 @@ class Nodes extends DataMap { } + /** + * Returns the cache key for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @return {Number} The cache key. + */ getForRenderCacheKey( renderObject ) { return renderObject.initialCacheKey; } + /** + * Returns a node builder state for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @return {NodeBuilderState} The node builder state. + */ getForRender( renderObject ) { const renderObjectData = this.get( renderObject ); @@ -39441,6 +44123,12 @@ class Nodes extends DataMap { } + /** + * Deletes the given object from the internal data map + * + * @param {Any} object - The object to delete. + * @return {Object?} The deleted dictionary. + */ delete( object ) { if ( object.isRenderObject ) { @@ -39460,6 +44148,12 @@ class Nodes extends DataMap { } + /** + * Returns a node builder state for the given compute node. + * + * @param {Node} computeNode - The compute node. + * @return {NodeBuilderState} The node builder state. + */ getForCompute( computeNode ) { const computeData = this.get( computeNode ); @@ -39481,6 +44175,13 @@ class Nodes extends DataMap { } + /** + * Creates a node builder state for the given node builder. + * + * @private + * @param {NodeBuilder} nodeBuilder - The node builder. + * @return {NodeBuilderState} The node builder state. + */ _createNodeBuilderState( nodeBuilder ) { return new NodeBuilderState( @@ -39498,71 +44199,149 @@ class Nodes extends DataMap { } + /** + * Returns an environment node for the current configured + * scene environment. + * + * @param {Scene} scene - The scene. + * @return {Node} A node representing the current scene environment. + */ getEnvironmentNode( scene ) { - return scene.environmentNode || this.get( scene ).environmentNode || null; + this.updateEnvironment( scene ); + + let environmentNode = null; + + if ( scene.environmentNode && scene.environmentNode.isNode ) { + + environmentNode = scene.environmentNode; + + } else { + + const sceneData = this.get( scene ); + + if ( sceneData.environmentNode ) { + + environmentNode = sceneData.environmentNode; + + } + + } + + return environmentNode; } + /** + * Returns a background node for the current configured + * scene background. + * + * @param {Scene} scene - The scene. + * @return {Node} A node representing the current scene background. + */ getBackgroundNode( scene ) { - return scene.backgroundNode || this.get( scene ).backgroundNode || null; + this.updateBackground( scene ); + + let backgroundNode = null; + + if ( scene.backgroundNode && scene.backgroundNode.isNode ) { + + backgroundNode = scene.backgroundNode; + + } else { + + const sceneData = this.get( scene ); + + if ( sceneData.backgroundNode ) { + + backgroundNode = sceneData.backgroundNode; + + } + + } + + return backgroundNode; } + /** + * Returns a fog node for the current configured scene fog. + * + * @param {Scene} scene - The scene. + * @return {Node} A node representing the current scene fog. + */ getFogNode( scene ) { + this.updateFog( scene ); + return scene.fogNode || this.get( scene ).fogNode || null; } + /** + * Returns a cache key for the given scene and lights node. + * This key is used by `RenderObject` as a part of the dynamic + * cache key (a key that must be checked every time the render + * objects is drawn). + * + * @param {Scene} scene - The scene. + * @param {LightsNode} lightsNode - The lights node. + * @return {Number} The cache key. + */ getCacheKey( scene, lightsNode ) { - const chain = [ scene, lightsNode ]; + _chainKeys$2[ 0 ] = scene; + _chainKeys$2[ 1 ] = lightsNode; + const callId = this.renderer.info.calls; - let cacheKeyData = this.callHashCache.get( chain ); + const cacheKeyData = this.callHashCache.get( _chainKeys$2 ) || {}; - if ( cacheKeyData === undefined || cacheKeyData.callId !== callId ) { + if ( cacheKeyData.callId !== callId ) { const environmentNode = this.getEnvironmentNode( scene ); const fogNode = this.getFogNode( scene ); - const values = []; + if ( lightsNode ) _cacheKeyValues.push( lightsNode.getCacheKey( true ) ); + if ( environmentNode ) _cacheKeyValues.push( environmentNode.getCacheKey() ); + if ( fogNode ) _cacheKeyValues.push( fogNode.getCacheKey() ); - if ( lightsNode ) values.push( lightsNode.getCacheKey( true ) ); - if ( environmentNode ) values.push( environmentNode.getCacheKey() ); - if ( fogNode ) values.push( fogNode.getCacheKey() ); + _cacheKeyValues.push( this.renderer.shadowMap.enabled ? 1 : 0 ); - values.push( this.renderer.shadowMap.enabled ? 1 : 0 ); + cacheKeyData.callId = callId; + cacheKeyData.cacheKey = hashArray( _cacheKeyValues ); - cacheKeyData = { - callId, - cacheKey: hashArray( values ) - }; + this.callHashCache.set( _chainKeys$2, cacheKeyData ); - this.callHashCache.set( chain, cacheKeyData ); + _cacheKeyValues.length = 0; } - return cacheKeyData.cacheKey; - - } - - updateScene( scene ) { + _chainKeys$2.length = 0; - this.updateEnvironment( scene ); - this.updateFog( scene ); - this.updateBackground( scene ); + return cacheKeyData.cacheKey; } + /** + * A boolean that indicates whether tone mapping should be enabled + * or not. + * + * @type {Boolean} + */ get isToneMappingState() { return this.renderer.getRenderTarget() ? false : true; } + /** + * If a scene background is configured, this method makes sure to + * represent the background with a corresponding node-based implementation. + * + * @param {Scene} scene - The scene. + */ updateBackground( scene ) { const sceneData = this.get( scene ); @@ -39574,41 +44353,43 @@ class Nodes extends DataMap { if ( sceneData.background !== background || forceUpdate ) { - let backgroundNode = null; + const backgroundNode = this.getCacheNode( 'background', background, () => { - if ( background.isCubeTexture === true || ( background.mapping === EquirectangularReflectionMapping || background.mapping === EquirectangularRefractionMapping || background.mapping === CubeUVReflectionMapping ) ) { + if ( background.isCubeTexture === true || ( background.mapping === EquirectangularReflectionMapping || background.mapping === EquirectangularRefractionMapping || background.mapping === CubeUVReflectionMapping ) ) { - if ( scene.backgroundBlurriness > 0 || background.mapping === CubeUVReflectionMapping ) { + if ( scene.backgroundBlurriness > 0 || background.mapping === CubeUVReflectionMapping ) { - backgroundNode = pmremTexture( background ); + return pmremTexture( background ); - } else { + } else { - let envMap; + let envMap; - if ( background.isCubeTexture === true ) { + if ( background.isCubeTexture === true ) { - envMap = cubeTexture( background ); + envMap = cubeTexture( background ); - } else { + } else { - envMap = texture( background ); + envMap = texture( background ); - } + } - backgroundNode = cubeMapNode( envMap ); + return cubeMapNode( envMap ); - } + } - } else if ( background.isTexture === true ) { + } else if ( background.isTexture === true ) { - backgroundNode = texture( background, screenUV.flipY() ).setUpdateMatrix( true ); + return texture( background, screenUV.flipY() ).setUpdateMatrix( true ); - } else if ( background.isColor !== true ) { + } else if ( background.isColor !== true ) { - console.error( 'WebGPUNodes: Unsupported background configuration.', background ); + console.error( 'WebGPUNodes: Unsupported background configuration.', background ); - } + } + + }, forceUpdate ); sceneData.backgroundNode = backgroundNode; sceneData.background = background; @@ -39625,6 +44406,39 @@ class Nodes extends DataMap { } + /** + * This method is part of the caching of nodes which are used to represents the + * scene's background, fog or environment. + * + * @param {String} type - The type of object to cache. + * @param {Object} object - The object. + * @param {Function} callback - A callback that produces a node representation for the given object. + * @param {Boolean} [forceUpdate=false] - Whether an update should be enforced or not. + * @return {Node} The node representation. + */ + getCacheNode( type, object, callback, forceUpdate = false ) { + + const nodeCache = this.cacheLib[ type ] || ( this.cacheLib[ type ] = new WeakMap() ); + + let node = nodeCache.get( object ); + + if ( node === undefined || forceUpdate ) { + + node = callback(); + nodeCache.set( object, node ); + + } + + return node; + + } + + /** + * If a scene fog is configured, this method makes sure to + * represent the fog with a corresponding node-based implementation. + * + * @param {Scene} scene - The scene. + */ updateFog( scene ) { const sceneData = this.get( scene ); @@ -39634,28 +44448,30 @@ class Nodes extends DataMap { if ( sceneData.fog !== sceneFog ) { - let fogNode = null; + const fogNode = this.getCacheNode( 'fog', sceneFog, () => { - if ( sceneFog.isFogExp2 ) { + if ( sceneFog.isFogExp2 ) { - const color = reference( 'color', 'color', sceneFog ).setGroup( renderGroup ); - const density = reference( 'density', 'float', sceneFog ).setGroup( renderGroup ); + const color = reference( 'color', 'color', sceneFog ).setGroup( renderGroup ); + const density = reference( 'density', 'float', sceneFog ).setGroup( renderGroup ); - fogNode = fog( color, densityFogFactor( density ) ); + return fog( color, densityFogFactor( density ) ); - } else if ( sceneFog.isFog ) { + } else if ( sceneFog.isFog ) { - const color = reference( 'color', 'color', sceneFog ).setGroup( renderGroup ); - const near = reference( 'near', 'float', sceneFog ).setGroup( renderGroup ); - const far = reference( 'far', 'float', sceneFog ).setGroup( renderGroup ); + const color = reference( 'color', 'color', sceneFog ).setGroup( renderGroup ); + const near = reference( 'near', 'float', sceneFog ).setGroup( renderGroup ); + const far = reference( 'far', 'float', sceneFog ).setGroup( renderGroup ); - fogNode = fog( color, rangeFogFactor( near, far ) ); + return fog( color, rangeFogFactor( near, far ) ); - } else { + } else { - console.error( 'WebGPUNodes: Unsupported fog configuration.', sceneFog ); + console.error( 'THREE.Renderer: Unsupported fog configuration.', sceneFog ); - } + } + + } ); sceneData.fogNode = fogNode; sceneData.fog = sceneFog; @@ -39671,6 +44487,12 @@ class Nodes extends DataMap { } + /** + * If a scene environment is configured, this method makes sure to + * represent the environment with a corresponding node-based implementation. + * + * @param {Scene} scene - The scene. + */ updateEnvironment( scene ) { const sceneData = this.get( scene ); @@ -39680,21 +44502,23 @@ class Nodes extends DataMap { if ( sceneData.environment !== environment ) { - let environmentNode = null; + const environmentNode = this.getCacheNode( 'environment', environment, () => { - if ( environment.isCubeTexture === true ) { + if ( environment.isCubeTexture === true ) { - environmentNode = cubeTexture( environment ); + return cubeTexture( environment ); - } else if ( environment.isTexture === true ) { + } else if ( environment.isTexture === true ) { - environmentNode = texture( environment ); + return texture( environment ); - } else { + } else { - console.error( 'Nodes: Unsupported environment configuration.', environment ); + console.error( 'Nodes: Unsupported environment configuration.', environment ); - } + } + + } ); sceneData.environmentNode = environmentNode; sceneData.environment = environment; @@ -39729,6 +44553,11 @@ class Nodes extends DataMap { } + /** + * Returns the current output cache key. + * + * @return {String} The output cache key. + */ getOutputCacheKey() { const renderer = this.renderer; @@ -39737,27 +44566,47 @@ class Nodes extends DataMap { } + /** + * Checks if the output configuration (tone mapping and color space) for + * the given target has changed. + * + * @param {Texture} outputTarget - The output target. + * @return {Boolean} Whether the output configuration has changed or not. + */ hasOutputChange( outputTarget ) { - const cacheKey = outputNodeMap.get( outputTarget ); + const cacheKey = _outputNodeMap.get( outputTarget ); return cacheKey !== this.getOutputCacheKey(); } - getOutputNode( outputTexture ) { + /** + * Returns a node that represents the output configuration (tone mapping and + * color space) for the current target. + * + * @param {Texture} outputTarget - The output target. + * @return {Node} The output node. + */ + getOutputNode( outputTarget ) { const renderer = this.renderer; const cacheKey = this.getOutputCacheKey(); - const output = texture( outputTexture, screenUV ).renderOutput( renderer.toneMapping, renderer.currentColorSpace ); + const output = texture( outputTarget, screenUV ).renderOutput( renderer.toneMapping, renderer.currentColorSpace ); - outputNodeMap.set( outputTexture, cacheKey ); + _outputNodeMap.set( outputTarget, cacheKey ); return output; } + /** + * Triggers the call of `updateBefore()` methods + * for all nodes of the given render object. + * + * @param {RenderObject} renderObject - The render object. + */ updateBefore( renderObject ) { const nodeBuilder = renderObject.getNodeBuilderState(); @@ -39772,6 +44621,12 @@ class Nodes extends DataMap { } + /** + * Triggers the call of `updateAfter()` methods + * for all nodes of the given render object. + * + * @param {RenderObject} renderObject - The render object. + */ updateAfter( renderObject ) { const nodeBuilder = renderObject.getNodeBuilderState(); @@ -39786,6 +44641,12 @@ class Nodes extends DataMap { } + /** + * Triggers the call of `update()` methods + * for all nodes of the given compute node. + * + * @param {Node} computeNode - The compute node. + */ updateForCompute( computeNode ) { const nodeFrame = this.getNodeFrame(); @@ -39799,6 +44660,12 @@ class Nodes extends DataMap { } + /** + * Triggers the call of `update()` methods + * for all nodes of the given compute node. + * + * @param {RenderObject} renderObject - The render object. + */ updateForRender( renderObject ) { const nodeFrame = this.getNodeFrameForRender( renderObject ); @@ -39812,6 +44679,12 @@ class Nodes extends DataMap { } + /** + * Returns `true` if the given render object requires a refresh. + * + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether the given render object requires a refresh or not. + */ needsRefresh( renderObject ) { const nodeFrame = this.getNodeFrameForRender( renderObject ); @@ -39821,12 +44694,16 @@ class Nodes extends DataMap { } + /** + * Frees the internal resources. + */ dispose() { super.dispose(); this.nodeFrame = new NodeFrame(); this.nodeBuilderCache = new Map(); + this.cacheLib = {}; } @@ -39834,41 +44711,110 @@ class Nodes extends DataMap { const _plane = /*@__PURE__*/ new Plane(); +/** + * Represents the state that is used to perform clipping via clipping planes. + * There is a default clipping context for each render context. When the + * scene holds instances of `ClippingGroup`, there will be a context for each + * group. + * + * @private + */ class ClippingContext { + /** + * Constructs a new clipping context. + * + * @param {ClippingContext?} [parentContext=null] - A reference to the parent clipping context. + */ constructor( parentContext = null ) { + /** + * The clipping context's version. + * + * @type {Number} + * @readonly + */ this.version = 0; + /** + * Whether the intersection of the clipping planes is used to clip objects, rather than their union. + * + * @type {Boolean?} + * @default null + */ this.clipIntersection = null; + + /** + * The clipping context's cache key. + * + * @type {String} + */ this.cacheKey = ''; + /** + * Whether the shadow pass is active or not. + * + * @type {Boolean} + * @default false + */ + this.shadowPass = false; - if ( parentContext === null ) { + /** + * The view normal matrix. + * + * @type {Matrix3} + */ + this.viewNormalMatrix = new Matrix3(); - this.intersectionPlanes = []; - this.unionPlanes = []; + /** + * Internal cache for maintaining clipping contexts. + * + * @type {WeakMap} + */ + this.clippingGroupContexts = new WeakMap(); - this.viewNormalMatrix = new Matrix3(); - this.clippingGroupContexts = new WeakMap(); + /** + * The intersection planes. + * + * @type {Array} + */ + this.intersectionPlanes = []; - this.shadowPass = false; + /** + * The intersection planes. + * + * @type {Array} + */ + this.unionPlanes = []; - } else { + /** + * The version of the clipping context's parent context. + * + * @type {Number?} + * @readonly + */ + this.parentVersion = null; + + if ( parentContext !== null ) { this.viewNormalMatrix = parentContext.viewNormalMatrix; this.clippingGroupContexts = parentContext.clippingGroupContexts; this.shadowPass = parentContext.shadowPass; - this.viewMatrix = parentContext.viewMatrix; } - this.parentVersion = null; - } + /** + * Projects the given source clipping planes and writes the result into the + * destination array. + * + * @param {Array} source - The source clipping planes. + * @param {Array} destination - The destination. + * @param {Number} offset - The offset. + */ projectPlanes( source, destination, offset ) { const l = source.length; @@ -39889,6 +44835,12 @@ class ClippingContext { } + /** + * Updates the root clipping context of a scene. + * + * @param {Scene} scene - The scene. + * @param {Camera} camera - The camera that is used to render the scene. + */ updateGlobal( scene, camera ) { this.shadowPass = ( scene.overrideMaterial !== null && scene.overrideMaterial.isShadowNodeMaterial ); @@ -39898,6 +44850,12 @@ class ClippingContext { } + /** + * Updates the clipping context. + * + * @param {ClippingContext} parentContext - The parent context. + * @param {ClippingGroup} clippingGroup - The clipping group this context belongs to. + */ update( parentContext, clippingGroup ) { let update = false; @@ -39969,6 +44927,12 @@ class ClippingContext { } + /** + * Returns a clipping context for the given clipping group. + * + * @param {ClippingGroup} clippingGroup - The clipping group. + * @return {ClippingContext} The clipping context. + */ getGroupContext( clippingGroup ) { if ( this.shadowPass && ! clippingGroup.clipShadows ) return this; @@ -39988,6 +44952,12 @@ class ClippingContext { } + /** + * The count of union clipping planes. + * + * @type {Number} + * @readonly + */ get unionClippingCount() { return this.unionPlanes.length; @@ -39996,67 +44966,141 @@ class ClippingContext { } +/** + * This module is used to represent render bundles inside the renderer + * for further processing. + * + * @private + */ class RenderBundle { - constructor( scene, camera ) { + /** + * Constructs a new bundle group. + * + * @param {BundleGroup} bundleGroup - The bundle group. + * @param {Camera} camera - The camera the bundle group is rendered with. + */ + constructor( bundleGroup, camera ) { - this.scene = scene; + this.bundleGroup = bundleGroup; this.camera = camera; } - clone() { - - return Object.assign( new this.constructor(), this ); - - } - } +const _chainKeys$1 = []; + +/** + * This renderer module manages render bundles. + * + * @private + */ class RenderBundles { + /** + * Constructs a new render bundle management component. + */ constructor() { - this.lists = new ChainMap(); + /** + * A chain map for maintaining the render bundles. + * + * @type {ChainMap} + */ + this.bundles = new ChainMap(); } - get( scene, camera ) { + /** + * Returns a render bundle for the given bundle group and camera. + * + * @param {BundleGroup} bundleGroup - The bundle group. + * @param {Camera} camera - The camera the bundle group is rendered with. + * @return {RenderBundle} The render bundle. + */ + get( bundleGroup, camera ) { - const lists = this.lists; - const keys = [ scene, camera ]; + const bundles = this.bundles; - let list = lists.get( keys ); + _chainKeys$1[ 0 ] = bundleGroup; + _chainKeys$1[ 1 ] = camera; - if ( list === undefined ) { + let bundle = bundles.get( _chainKeys$1 ); + + if ( bundle === undefined ) { - list = new RenderBundle( scene, camera ); - lists.set( keys, list ); + bundle = new RenderBundle( bundleGroup, camera ); + bundles.set( _chainKeys$1, bundle ); } - return list; + _chainKeys$1.length = 0; + + return bundle; } + /** + * Frees all internal resources. + */ dispose() { - this.lists = new ChainMap(); + this.bundles = new ChainMap(); } } +/** + * The purpose of a node library is to assign node implementations + * to existing library features. In `WebGPURenderer` lights, materials + * which are not based on `NodeMaterial` as well as tone mapping techniques + * are implemented with node-based modules. + * + * @private + */ class NodeLibrary { + /** + * Constructs a new node library. + */ constructor() { + /** + * A weak map that maps lights to light nodes. + * + * @type {WeakMap} + */ this.lightNodes = new WeakMap(); + + /** + * A map that maps materials to node materials. + * + * @type {WeakMap} + */ this.materialNodes = new Map(); + + /** + * A map that maps tone mapping techniques (constants) + * to tone mapping node functions. + * + * @type {WeakMap} + */ this.toneMappingNodes = new Map(); } + /** + * Returns a matching node material instance for the given material object. + * + * This method also assigns/copies the properties of the given material object + * to the node material. This is done to make sure the current material + * configuration carries over to the node version. + * + * @param {Material} material - A material. + * @return {NodeMaterial} The corresponding node material. + */ fromMaterial( material ) { if ( material.isNodeMaterial ) return material; @@ -40081,42 +45125,85 @@ class NodeLibrary { } + /** + * Adds a tone mapping node function for a tone mapping technique (constant). + * + * @param {Function} toneMappingNode - The tone mapping node function. + * @param {Number} toneMapping - The tone mapping. + */ addToneMapping( toneMappingNode, toneMapping ) { this.addType( toneMappingNode, toneMapping, this.toneMappingNodes ); } + /** + * Returns a tone mapping node function for a tone mapping technique (constant). + * + * @param {Number} toneMapping - The tone mapping. + * @return {Function?} The tone mapping node function. Returns `null` if no node function is found. + */ getToneMappingFunction( toneMapping ) { return this.toneMappingNodes.get( toneMapping ) || null; } + /** + * Returns a node material class definition for a material type. + * + * @param {String} materialType - The material type. + * @return {NodeMaterial.constructor?} The node material class definition. Returns `null` if no node material is found. + */ getMaterialNodeClass( materialType ) { return this.materialNodes.get( materialType ) || null; } + /** + * Adds a node material class definition for a given material type. + * + * @param {NodeMaterial.constructor} materialNodeClass - The node material class definition. + * @param {String} materialClassType - The material type. + */ addMaterial( materialNodeClass, materialClassType ) { this.addType( materialNodeClass, materialClassType, this.materialNodes ); } + /** + * Returns a light node class definition for a light class definition. + * + * @param {Light.constructor} light - The light class definition. + * @return {AnalyticLightNode.constructor?} The light node class definition. Returns `null` if no light node is found. + */ getLightNodeClass( light ) { return this.lightNodes.get( light ) || null; } + /** + * Adds a light node class definition for a given light class definition. + * + * @param {AnalyticLightNode.constructor} lightNodeClass - The light node class definition. + * @param {Light.constructor} lightClass - The light class definition. + */ addLight( lightNodeClass, lightClass ) { this.addClass( lightNodeClass, lightClass, this.lightNodes ); } + /** + * Adds a node class definition for the given type to the provided type library. + * + * @param {Any} nodeClass - The node class definition. + * @param {String} type - The object type. + * @param {Map} library - The type library. + */ addType( nodeClass, type, library ) { if ( library.has( type ) ) { @@ -40133,6 +45220,13 @@ class NodeLibrary { } + /** + * Adds a node class definition for the given class definition to the provided type library. + * + * @param {Any} nodeClass - The node class definition. + * @param {Any} baseClass - The class definition. + * @param {WeakMap} library - The type library. + */ addClass( nodeClass, baseClass, library ) { if ( library.has( baseClass ) ) { @@ -40152,46 +45246,76 @@ class NodeLibrary { } const _defaultLights = /*@__PURE__*/ new LightsNode(); +const _chainKeys = []; +/** + * This renderer module manages the lights nodes which are unique + * per scene and camera combination. + * + * The lights node itself is later configured in the render list + * with the actual lights from the scene. + * + * @private + * @augments ChainMap + */ class Lighting extends ChainMap { + /** + * Constructs a lighting management component. + */ constructor() { super(); } + /** + * Creates a new lights node for the given array of lights. + * + * @param {Array} lights - The render object. + * @return {Boolean} Whether if the given render object has an initialized geometry or not. + */ createNode( lights = [] ) { return new LightsNode().setLights( lights ); } + /** + * Returns a lights node for the given scene and camera. + * + * @param {Scene} scene - The scene. + * @param {Camera} camera - The camera. + * @return {LightsNode} The lights node. + */ getNode( scene, camera ) { // ignore post-processing if ( scene.isQuadMesh ) return _defaultLights; - // tiled lighting + _chainKeys[ 0 ] = scene; + _chainKeys[ 1 ] = camera; - const keys = [ scene, camera ]; - - let node = this.get( keys ); + let node = this.get( _chainKeys ); if ( node === undefined ) { node = this.createNode(); - this.set( keys, node ); + this.set( _chainKeys, node ); } + _chainKeys.length = 0; + return node; } } +/** @module Renderer **/ + const _scene = /*@__PURE__*/ new Scene(); const _drawingBufferSize = /*@__PURE__*/ new Vector2(); const _screen = /*@__PURE__*/ new Vector4(); @@ -40199,10 +45323,34 @@ const _frustum = /*@__PURE__*/ new Frustum(); const _projScreenMatrix = /*@__PURE__*/ new Matrix4(); const _vector4 = /*@__PURE__*/ new Vector4(); +/** + * Base class for renderers. + */ class Renderer { + /** + * Constructs a new renderer. + * + * @param {Backend} backend - The backend the renderer is targeting (e.g. WebGPU or WebGL 2). + * @param {Object} parameters - The configuration parameter. + * @param {Boolean} [parameters.logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not. + * @param {Boolean} [parameters.alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque. + * @param {Boolean} [parameters.depth=true] - Whether the default framebuffer should have a depth buffer or not. + * @param {Boolean} [parameters.stencil=false] - Whether the default framebuffer should have a stencil buffer or not. + * @param {Boolean} [parameters.antialias=false] - Whether MSAA as the default anti-aliasing should be enabled or not. + * @param {Number} [parameters.samples=0] - When `antialias` is `true`, `4` samples are used by default. This parameter can set to any other integer value than 0 + * to overwrite the default. + * @param {Function?} [parameters.getFallback=null] - This callback function can be used to provide a fallback backend, if the primary backend can't be targeted. + */ constructor( backend, parameters = {} ) { + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isRenderer = true; // @@ -40217,32 +45365,142 @@ class Renderer { getFallback = null } = parameters; - // public + /** + * A reference to the canvas element the renderer is drawing to. + * This value of this property will automatically be created by + * the renderer. + * + * @type {HTMLCanvasElement|OffscreenCanvas} + */ this.domElement = backend.getDomElement(); + /** + * A reference to the current backend. + * + * @type {Backend} + */ this.backend = backend; + /** + * The number of MSAA samples. + * + * @type {Number} + * @default 0 + */ this.samples = samples || ( antialias === true ) ? 4 : 0; + /** + * Whether the renderer should automatically clear the current rendering target + * before execute a `render()` call. The target can be the canvas (default framebuffer) + * or the current bound render target (custom framebuffer). + * + * @type {Boolean} + * @default true + */ this.autoClear = true; + + /** + * When `autoClear` is set to `true`, this property defines whether the renderer + * should clear the color buffer. + * + * @type {Boolean} + * @default true + */ this.autoClearColor = true; + + /** + * When `autoClear` is set to `true`, this property defines whether the renderer + * should clear the depth buffer. + * + * @type {Boolean} + * @default true + */ this.autoClearDepth = true; + + /** + * When `autoClear` is set to `true`, this property defines whether the renderer + * should clear the stencil buffer. + * + * @type {Boolean} + * @default true + */ this.autoClearStencil = true; + /** + * Whether the default framebuffer should be transparent or opaque. + * + * @type {Boolean} + * @default true + */ this.alpha = alpha; + /** + * Whether logarithmic depth buffer is enabled or not. + * + * @type {Boolean} + * @default false + */ this.logarithmicDepthBuffer = logarithmicDepthBuffer; + /** + * Defines the output color space of the renderer. + * + * @type {String} + * @default SRGBColorSpace + */ this.outputColorSpace = SRGBColorSpace; + /** + * Defines the tone mapping of the renderer. + * + * @type {Number} + * @default NoToneMapping + */ this.toneMapping = NoToneMapping; + + /** + * Defines the tone mapping exposure. + * + * @type {Number} + * @default 1 + */ this.toneMappingExposure = 1.0; + /** + * Whether the renderer should sort its render lists or not. + * + * Note: Sorting is used to attempt to properly render objects that have some degree of transparency. + * By definition, sorting objects may not work in all cases. Depending on the needs of application, + * it may be necessary to turn off sorting and use other methods to deal with transparency rendering + * e.g. manually determining each object's rendering order. + * + * @type {Boolean} + * @default true + */ this.sortObjects = true; + /** + * Whether the default framebuffer should have a depth buffer or not. + * + * @type {Boolean} + * @default true + */ this.depth = depth; + + /** + * Whether the default framebuffer should have a stencil buffer or not. + * + * @type {Boolean} + * @default false + */ this.stencil = stencil; + /** + * Holds a series of statistical information about the GPU memory + * and the rendering process. Useful for debugging and monitoring. + * + * @type {Boolean} + */ this.info = new Info(); this.nodes = { @@ -40250,82 +45508,449 @@ class Renderer { modelNormalViewMatrix: null }; + /** + * The node library defines how certain library objects like materials, lights + * or tone mapping functions are mapped to node types. This is required since + * although instances of classes like `MeshBasicMaterial` or `PointLight` can + * be part of the scene graph, they are internally represented as nodes for + * further processing. + * + * @type {NodeLibrary} + */ this.library = new NodeLibrary(); + + /** + * A map-like data structure for managing lights. + * + * @type {Lighting} + */ this.lighting = new Lighting(); // internals + /** + * This callback function can be used to provide a fallback backend, if the primary backend can't be targeted. + * + * @private + * @type {Function} + */ this._getFallback = getFallback; + /** + * The renderer's pixel ration. + * + * @private + * @type {Number} + * @default 1 + */ this._pixelRatio = 1; + + /** + * The width of the renderer's default framebuffer in logical pixel unit. + * + * @private + * @type {Number} + */ this._width = this.domElement.width; + + /** + * The height of the renderer's default framebuffer in logical pixel unit. + * + * @private + * @type {Number} + */ this._height = this.domElement.height; + /** + * The viewport of the renderer in logical pixel unit. + * + * @private + * @type {Vector4} + */ this._viewport = new Vector4( 0, 0, this._width, this._height ); + + /** + * The scissor rectangle of the renderer in logical pixel unit. + * + * @private + * @type {Vector4} + */ this._scissor = new Vector4( 0, 0, this._width, this._height ); + + /** + * Whether the scissor test should be enabled or not. + * + * @private + * @type {Vector4} + */ this._scissorTest = false; + /** + * A reference to a renderer module for managing shader attributes. + * + * @private + * @type {Attributes?} + * @default null + */ this._attributes = null; + + /** + * A reference to a renderer module for managing geometries. + * + * @private + * @type {Geometries?} + * @default null + */ this._geometries = null; + + /** + * A reference to a renderer module for managing node related logic. + * + * @private + * @type {Nodes?} + * @default null + */ this._nodes = null; + + /** + * A reference to a renderer module for managing the internal animation loop. + * + * @private + * @type {Animation?} + * @default null + */ this._animation = null; + + /** + * A reference to a renderer module for managing shader program bindings. + * + * @private + * @type {Bindings?} + * @default null + */ this._bindings = null; + + /** + * A reference to a renderer module for managing render objects. + * + * @private + * @type {RenderObjects?} + * @default null + */ this._objects = null; + + /** + * A reference to a renderer module for managing render and compute pipelines. + * + * @private + * @type {Pipelines?} + * @default null + */ this._pipelines = null; + + /** + * A reference to a renderer module for managing render bundles. + * + * @private + * @type {RenderBundles?} + * @default null + */ this._bundles = null; + + /** + * A reference to a renderer module for managing render lists. + * + * @private + * @type {RenderLists?} + * @default null + */ this._renderLists = null; + + /** + * A reference to a renderer module for managing render contexts. + * + * @private + * @type {RenderContexts?} + * @default null + */ this._renderContexts = null; + + /** + * A reference to a renderer module for managing textures. + * + * @private + * @type {Textures?} + * @default null + */ this._textures = null; + + /** + * A reference to a renderer module for backgrounds. + * + * @private + * @type {Background?} + * @default null + */ this._background = null; + /** + * This fullscreen quad is used for internal render passes + * like the tone mapping and color space output pass. + * + * @private + * @type {QuadMesh} + */ this._quad = new QuadMesh( new NodeMaterial() ); - this._quad.material.type = 'Renderer_output'; + this._quad.material.name = 'Renderer_output'; + /** + * A reference to the current render context. + * + * @private + * @type {RenderContext?} + * @default null + */ this._currentRenderContext = null; + /** + * A custom sort function for the opaque render list. + * + * @private + * @type {Function?} + * @default null + */ this._opaqueSort = null; + + /** + * A custom sort function for the transparent render list. + * + * @private + * @type {Function?} + * @default null + */ this._transparentSort = null; + /** + * The framebuffer target. + * + * @private + * @type {RenderTarget?} + * @default null + */ this._frameBufferTarget = null; const alphaClear = this.alpha === true ? 0 : 1; + /** + * The clear color value. + * + * @private + * @type {Color4} + */ this._clearColor = new Color4( 0, 0, 0, alphaClear ); + + /** + * The clear depth value. + * + * @private + * @type {Number} + * @default 1 + */ this._clearDepth = 1; + + /** + * The clear stencil value. + * + * @private + * @type {Number} + * @default 0 + */ this._clearStencil = 0; + /** + * The current render target. + * + * @private + * @type {RenderTarget?} + * @default null + */ this._renderTarget = null; + + /** + * The active cube face. + * + * @private + * @type {Number} + * @default 0 + */ this._activeCubeFace = 0; + + /** + * The active mipmap level. + * + * @private + * @type {Number} + * @default 0 + */ this._activeMipmapLevel = 0; + /** + * The MRT setting. + * + * @private + * @type {MRTNode?} + * @default null + */ this._mrt = null; + /** + * This function defines how a render object is going + * to be rendered. + * + * @private + * @type {Function?} + * @default null + */ this._renderObjectFunction = null; + + /** + * Used to keep track of the current render object function. + * + * @private + * @type {Function?} + * @default null + */ this._currentRenderObjectFunction = null; + + /** + * Used to keep track of the current render bundle. + * + * @private + * @type {RenderBundle?} + * @default null + */ this._currentRenderBundle = null; + /** + * Next to `_renderObjectFunction()`, this function provides another hook + * for influencing the render process of a render object. It is meant for internal + * use and only relevant for `compileAsync()` right now. Instead of using + * the default logic of `_renderObjectDirect()` which actually draws the render object, + * a different function might be used which performs no draw but just the node + * and pipeline updates. + * + * @private + * @type {Function?} + * @default null + */ this._handleObjectFunction = this._renderObjectDirect; + /** + * Indicates whether the device has been lost or not. In WebGL terms, the device + * lost is considered as a context lost. When this is set to `true`, rendering + * isn't possible anymore. + * + * @private + * @type {Boolean} + * @default false + */ this._isDeviceLost = false; + + /** + * A callback function that defines what should happen when a device/context lost occurs. + * + * @type {Function} + */ this.onDeviceLost = this._onDeviceLost; + /** + * Whether the renderer has been initialized or not. + * + * @private + * @type {Boolean} + * @default false + */ this._initialized = false; + + /** + * A reference to the promise which initializes the renderer. + * + * @private + * @type {Promise?} + * @default null + */ this._initPromise = null; + /** + * An array of compilation promises which are used in `compileAsync()`. + * + * @private + * @type {Array?} + * @default null + */ this._compilationPromises = null; + /** + * Whether the renderer should render transparent render objects or not. + * + * @type {Boolean} + * @default true + */ this.transparent = true; + + /** + * Whether the renderer should render opaque render objects or not. + * + * @type {Boolean} + * @default true + */ this.opaque = true; + /** + * Shadow map configuration + * @typedef {Object} ShadowMapConfig + * @property {Boolean} enabled - Whether to globally enable shadows or not. + * @property {Number} type - The shadow map type. + */ + + /** + * The renderer's shadow configuration. + * + * @type {module:Renderer~ShadowMapConfig} + */ this.shadowMap = { enabled: false, type: PCFShadowMap }; + /** + * XR configuration. + * @typedef {Object} XRConfig + * @property {Boolean} enabled - Whether to globally enable XR or not. + */ + + /** + * The renderer's XR configuration. + * + * @type {module:Renderer~XRConfig} + */ this.xr = { enabled: false }; + /** + * Debug configuration. + * @typedef {Object} DebugConfig + * @property {Boolean} checkShaderErrors - Whether shader errors should be checked or not. + * @property {Function} onShaderError - A callback function that is executed when a shader error happens. Only supported with WebGL 2 right now. + * @property {Function} getShaderAsync - Allows the get the raw shader code for the given scene, camera and 3D object. + */ + + /** + * The renderer's debug configuration. + * + * @type {module:Renderer~DebugConfig} + */ this.debug = { checkShaderErrors: true, onShaderError: null, @@ -40349,6 +45974,12 @@ class Renderer { } + /** + * Initializes the renderer so it is ready for usage. + * + * @async + * @return {Promise} A Promise that resolves when the renderer has been initialized. + */ async init() { if ( this._initialized ) { @@ -40424,12 +46055,35 @@ class Renderer { } + /** + * The coordinate system of the renderer. The value of this property + * depends on the selected backend. Either `THREE.WebGLCoordinateSystem` or + * `THREE.WebGPUCoordinateSystem`. + * + * @readonly + * @type {Number} + */ get coordinateSystem() { return this.backend.coordinateSystem; } + /** + * Compiles all materials in the given scene. This can be useful to avoid a + * phenomenon which is called "shader compilation stutter", which occurs when + * rendering an object with a new shader for the first time. + * + * If you want to add a 3D object to an existing scene, use the third optional + * parameter for applying the target scene. Note that the (target) scene's lighting + * and environment must be configured before calling this method. + * + * @async + * @param {Object3D} scene - The scene or 3D object to precompile. + * @param {Camera} camera - The camera that is used to render the scene. + * @param {Scene} targetScene - If the first argument is a 3D object, this parameter must represent the scene the 3D object is going to be added. + * @return {Promise} A Promise that resolves when the compile has been finished. + */ async compileAsync( scene, camera, targetScene = null ) { if ( this._isDeviceLost === true ) return; @@ -40526,10 +46180,6 @@ class Renderer { // - this._nodes.updateScene( sceneRef ); - - // - this._background.update( sceneRef, renderList, renderContext ); // process render lists @@ -40558,6 +46208,14 @@ class Renderer { } + /** + * Renders the scene in an async fashion. + * + * @async + * @param {Object3D} scene - The scene or 3D object to render. + * @param {Camera} camera - The camera. + * @return {Promise} A Promise that resolves when the render has been finished. + */ async renderAsync( scene, camera ) { if ( this._initialized === false ) await this.init(); @@ -40568,12 +46226,25 @@ class Renderer { } + /** + * Can be used to synchronize CPU operations with GPU tasks. So when this method is called, + * the CPU waits for the GPU to complete its operation (e.g. a compute task). + * + * @async + * @return {Promise} A Promise that resolves when synchronization has been finished. + */ async waitForGPU() { await this.backend.waitForGPU(); } + /** + * Sets the given MRT configuration. + * + * @param {MRTNode} mrt - The MRT node to set. + * @return {Renderer} A reference to this renderer. + */ setMRT( mrt ) { this._mrt = mrt; @@ -40582,12 +46253,23 @@ class Renderer { } + /** + * Returns the MRT configuration. + * + * @return {MRTNode} The MRT configuration. + */ getMRT() { return this._mrt; } + /** + * Default implementation of the device lost callback. + * + * @private + * @param {Object} info - Information about the context lost. + */ _onDeviceLost( info ) { let errorMessage = `THREE.WebGPURenderer: ${info.api} Device Lost:\n\nMessage: ${info.message}`; @@ -40604,7 +46286,14 @@ class Renderer { } - + /** + * Renders the given render bundle. + * + * @private + * @param {Object} bundle - Render bundle data. + * @param {Scene} sceneRef - The scene the render bundle belongs to. + * @param {LightsNode} lightsNode - The current lights node. + */ _renderBundle( bundle, sceneRef, lightsNode ) { const { bundleGroup, camera, renderList } = bundle; @@ -40676,6 +46365,18 @@ class Renderer { } + /** + * Renders the scene or 3D object with the given camera. This method can only be called + * if the renderer has been initialized. + * + * The target of the method is the default framebuffer (meaning the canvas) + * or alternatively a render target when specified via `setRenderTarget()`. + * + * @param {Object3D} scene - The scene or 3D object to render. + * @param {Camera} camera - The camera to render the scene with. + * @return {Promise?} A Promise that resolve when the scene has been rendered. + * Only returned when the renderer has not been initialized. + */ render( scene, camera ) { if ( this._initialized === false ) { @@ -40690,6 +46391,14 @@ class Renderer { } + /** + * Returns an internal render target which is used when computing the output tone mapping + * and color space conversion. Unlike in `WebGLRenderer`, this is done in a separate render + * pass and not inline to achieve more correct results. + * + * @private + * @return {RenderTarget?} The render target. The method returns `null` if no output conversion should be applied. + */ _getFrameBufferTarget() { const { currentToneMapping, currentColorSpace } = this; @@ -40737,6 +46446,15 @@ class Renderer { } + /** + * Renders the scene or 3D object with the given camera. + * + * @private + * @param {Object3D} scene - The scene or 3D object to render. + * @param {Camera} camera - The camera to render the scene with. + * @param {Boolean} [useFrameBufferTarget=true] - Whether to use a framebuffer target or not. + * @return {RenderContext} The current render context. + */ _renderScene( scene, camera, useFrameBufferTarget = true ) { if ( this._isDeviceLost === true ) return; @@ -40902,10 +46620,6 @@ class Renderer { // - this._nodes.updateScene( sceneRef ); - - // - this._background.update( sceneRef, renderList, renderContext ); // @@ -40966,24 +46680,48 @@ class Renderer { } + /** + * Returns the maximum available anisotropy for texture filtering. + * + * @return {Number} The maximum available anisotropy. + */ getMaxAnisotropy() { return this.backend.getMaxAnisotropy(); } + /** + * Returns the active cube face. + * + * @return {Number} The active cube face. + */ getActiveCubeFace() { return this._activeCubeFace; } + /** + * Returns the active mipmap level. + * + * @return {Number} The active mipmap level. + */ getActiveMipmapLevel() { return this._activeMipmapLevel; } + /** + * Applications are advised to always define the animation loop + * with this method and not manually with `requestAnimationFrame()` + * for best compatibility. + * + * @async + * @param {Function} callback - The application's animation loop. + * @return {Promise} A Promise that resolves when the set has been executed. + */ async setAnimationLoop( callback ) { if ( this._initialized === false ) await this.init(); @@ -40992,36 +46730,71 @@ class Renderer { } + /** + * Can be used to transfer buffer data from a storage buffer attribute + * from the GPU to the CPU in context of compute shaders. + * + * @async + * @param {StorageBufferAttribute} attribute - The storage buffer attribute. + * @return {Promise} A promise that resolves with the buffer data when the data are ready. + */ async getArrayBufferAsync( attribute ) { return await this.backend.getArrayBufferAsync( attribute ); } + /** + * Returns the rendering context. + * + * @return {GPUCanvasContext|WebGL2RenderingContext} The rendering context. + */ getContext() { return this.backend.getContext(); } + /** + * Returns the pixel ratio. + * + * @return {Number} The pixel ratio. + */ getPixelRatio() { return this._pixelRatio; } + /** + * Returns the drawing buffer size in physical pixels. This method honors the pixel ratio. + * + * @param {Vector2} target - The method writes the result in this target object. + * @return {Vector2} The drawing buffer size. + */ getDrawingBufferSize( target ) { return target.set( this._width * this._pixelRatio, this._height * this._pixelRatio ).floor(); } + /** + * Returns the renderer's size in logical pixels. This method does not honor the pixel ratio. + * + * @param {Vector2} target - The method writes the result in this target object. + * @return {Vector2} The drawing buffer size. + */ getSize( target ) { return target.set( this._width, this._height ); } + /** + * Sets the given pixel ration and resizes the canvas if necessary. + * + * @param {Number} [value=1] - The pixel ratio. + */ setPixelRatio( value = 1 ) { if ( this._pixelRatio === value ) return; @@ -41032,6 +46805,19 @@ class Renderer { } + /** + * This method allows to define the drawing buffer size by specifying + * width, height and pixel ratio all at once. The size of the drawing + * buffer is computed with this formula: + * ```` + * size.x = width * pixelRatio; + * size.y = height * pixelRatio; + *``` + * + * @param {Number} width - The width in logical pixels. + * @param {Number} height - The height in logical pixels. + * @param {Number} pixelRatio - The pixel ratio. + */ setDrawingBufferSize( width, height, pixelRatio ) { this._width = width; @@ -41048,6 +46834,13 @@ class Renderer { } + /** + * Sets the size of the renderer. + * + * @param {Number} width - The width in logical pixels. + * @param {Number} height - The height in logical pixels. + * @param {Boolean} [updateStyle=true] - Whether to update the `style` attribute of the canvas or not. + */ setSize( width, height, updateStyle = true ) { this._width = width; @@ -41069,18 +46862,36 @@ class Renderer { } + /** + * Defines a manual sort function for the opaque render list. + * Pass `null` to use the default sort. + * + * @param {Function} method - The sort function. + */ setOpaqueSort( method ) { this._opaqueSort = method; } + /** + * Defines a manual sort function for the transparent render list. + * Pass `null` to use the default sort. + * + * @param {Function} method - The sort function. + */ setTransparentSort( method ) { this._transparentSort = method; } + /** + * Returns the scissor rectangle. + * + * @param {Vector4} target - The method writes the result in this target object. + * @return {Vector4} The scissor rectangle. + */ getScissor( target ) { const scissor = this._scissor; @@ -41094,6 +46905,15 @@ class Renderer { } + /** + * Defines the scissor rectangle. + * + * @param {Number | Vector4} x - The horizontal coordinate for the lower left corner of the box in logical pixel unit. + * Instead of passing four arguments, the method also works with a single four-dimensional vector. + * @param {Number} y - The vertical coordinate for the lower left corner of the box in logical pixel unit. + * @param {Number} width - The width of the scissor box in logical pixel unit. + * @param {Number} height - The height of the scissor box in logical pixel unit. + */ setScissor( x, y, width, height ) { const scissor = this._scissor; @@ -41110,12 +46930,22 @@ class Renderer { } + /** + * Returns the scissor test value. + * + * @return {Boolean} Whether the scissor test should be enabled or not. + */ getScissorTest() { return this._scissorTest; } + /** + * Defines the scissor test. + * + * @param {Boolean} boolean - Whether the scissor test should be enabled or not. + */ setScissorTest( boolean ) { this._scissorTest = boolean; @@ -41124,12 +46954,28 @@ class Renderer { } + /** + * Returns the viewport definition. + * + * @param {Vector4} target - The method writes the result in this target object. + * @return {Vector4} The viewport definition. + */ getViewport( target ) { return target.copy( this._viewport ); } + /** + * Defines the viewport. + * + * @param {Number | Vector4} x - The horizontal coordinate for the lower left corner of the viewport origin in logical pixel unit. + * @param {Number} y - The vertical coordinate for the lower left corner of the viewport origin in logical pixel unit. + * @param {Number} width - The width of the viewport in logical pixel unit. + * @param {Number} height - The height of the viewport in logical pixel unit. + * @param {Number} minDepth - The minimum depth value of the viewport. WebGPU only. + * @param {Number} maxDepth - The maximum depth value of the viewport. WebGPU only. + */ setViewport( x, y, width, height, minDepth = 0, maxDepth = 1 ) { const viewport = this._viewport; @@ -41149,12 +46995,24 @@ class Renderer { } + /** + * Returns the clear color. + * + * @param {Color} target - The method writes the result in this target object. + * @return {Color} The clear color. + */ getClearColor( target ) { return target.copy( this._clearColor ); } + /** + * Defines the clear color and optionally the clear alpha. + * + * @param {Color} color - The clear color. + * @param {Number} [alpha=1] - The clear alpha. + */ setClearColor( color, alpha = 1 ) { this._clearColor.set( color ); @@ -41162,42 +47020,80 @@ class Renderer { } + /** + * Returns the clear alpha. + * + * @return {Number} The clear alpha. + */ getClearAlpha() { return this._clearColor.a; } + /** + * Defines the clear alpha. + * + * @param {Number} alpha - The clear alpha. + */ setClearAlpha( alpha ) { this._clearColor.a = alpha; } + /** + * Returns the clear depth. + * + * @return {Number} The clear depth. + */ getClearDepth() { return this._clearDepth; } + /** + * Defines the clear depth. + * + * @param {Number} depth - The clear depth. + */ setClearDepth( depth ) { this._clearDepth = depth; } + /** + * Returns the clear stencil. + * + * @return {Number} The clear stencil. + */ getClearStencil() { return this._clearStencil; } + /** + * Defines the clear stencil. + * + * @param {Number} stencil - The clear stencil. + */ setClearStencil( stencil ) { this._clearStencil = stencil; } + /** + * This method performs an occlusion query for the given 3D object. + * It returns `true` if the given 3D object is fully occluded by other + * 3D objects in the scene. + * + * @param {Object3D} object - The 3D object to test. + * @return {Boolean} Whether the 3D object is fully occluded or not. + */ isOccluded( object ) { const renderContext = this._currentRenderContext; @@ -41206,6 +47102,15 @@ class Renderer { } + /** + * Performs a manual clear operation. This method ignores `autoClear` properties. + * + * @param {Boolean} [color=true] - Whether the color buffer should be cleared or not. + * @param {Boolean} [depth=true] - Whether the depth buffer should be cleared or not. + * @param {Boolean} [stencil=true] - Whether the stencil buffer should be cleared or not. + * @return {Promise} A Promise that resolves when the clear operation has been executed. + * Only returned when the renderer has not been initialized. + */ clear( color = true, depth = true, stencil = true ) { if ( this._initialized === false ) { @@ -41218,17 +47123,26 @@ class Renderer { const renderTarget = this._renderTarget || this._getFrameBufferTarget(); - let renderTargetData = null; + let renderContext = null; if ( renderTarget !== null ) { this._textures.updateRenderTarget( renderTarget ); - renderTargetData = this._textures.get( renderTarget ); + const renderTargetData = this._textures.get( renderTarget ); + + renderContext = this._renderContexts.getForClear( renderTarget ); + renderContext.textures = renderTargetData.textures; + renderContext.depthTexture = renderTargetData.depthTexture; + renderContext.width = renderTargetData.width; + renderContext.height = renderTargetData.height; + renderContext.renderTarget = renderTarget; + renderContext.depth = renderTarget.depthBuffer; + renderContext.stencil = renderTarget.stencilBuffer; } - this.backend.clear( color, depth, stencil, renderTargetData ); + this.backend.clear( color, depth, stencil, renderContext ); if ( renderTarget !== null && this._renderTarget === null ) { @@ -41250,24 +47164,51 @@ class Renderer { } + /** + * Performs a manual clear operation of the color buffer. This method ignores `autoClear` properties. + * + * @return {Promise} A Promise that resolves when the clear operation has been executed. + * Only returned when the renderer has not been initialized. + */ clearColor() { return this.clear( true, false, false ); } + /** + * Performs a manual clear operation of the depth buffer. This method ignores `autoClear` properties. + * + * @return {Promise} A Promise that resolves when the clear operation has been executed. + * Only returned when the renderer has not been initialized. + */ clearDepth() { return this.clear( false, true, false ); } + /** + * Performs a manual clear operation of the stencil buffer. This method ignores `autoClear` properties. + * + * @return {Promise} A Promise that resolves when the clear operation has been executed. + * Only returned when the renderer has not been initialized. + */ clearStencil() { return this.clear( false, false, true ); } + /** + * Async version of {@link module:Renderer~Renderer#clear}. + * + * @async + * @param {Boolean} [color=true] - Whether the color buffer should be cleared or not. + * @param {Boolean} [depth=true] - Whether the depth buffer should be cleared or not. + * @param {Boolean} [stencil=true] - Whether the stencil buffer should be cleared or not. + * @return {Promise} A Promise that resolves when the clear operation has been executed. + */ async clearAsync( color = true, depth = true, stencil = true ) { if ( this._initialized === false ) await this.init(); @@ -41276,36 +47217,70 @@ class Renderer { } - clearColorAsync() { + /** + * Async version of {@link module:Renderer~Renderer#clearColor}. + * + * @async + * @return {Promise} A Promise that resolves when the clear operation has been executed. + */ + async clearColorAsync() { - return this.clearAsync( true, false, false ); + this.clearAsync( true, false, false ); } - clearDepthAsync() { + /** + * Async version of {@link module:Renderer~Renderer#clearDepth}. + * + * @async + * @return {Promise} A Promise that resolves when the clear operation has been executed. + */ + async clearDepthAsync() { - return this.clearAsync( false, true, false ); + this.clearAsync( false, true, false ); } - clearStencilAsync() { + /** + * Async version of {@link module:Renderer~Renderer#clearStencil}. + * + * @async + * @return {Promise} A Promise that resolves when the clear operation has been executed. + */ + async clearStencilAsync() { - return this.clearAsync( false, false, true ); + this.clearAsync( false, false, true ); } + /** + * The current output tone mapping of the renderer. When a render target is set, + * the output tone mapping is always `NoToneMapping`. + * + * @type {Number} + */ get currentToneMapping() { return this._renderTarget !== null ? NoToneMapping : this.toneMapping; } + /** + * The current output color space of the renderer. When a render target is set, + * the output color space is always `LinearSRGBColorSpace`. + * + * @type {String} + */ get currentColorSpace() { return this._renderTarget !== null ? LinearSRGBColorSpace : this.outputColorSpace; } + /** + * Frees all internal resources of the renderer. Call this method if the renderer + * is no longer in use by your app. + */ dispose() { this.info.dispose(); @@ -41325,6 +47300,15 @@ class Renderer { } + /** + * Sets the given render target. Calling this method means the renderer does not + * target the default framebuffer (meaning the canvas) anymore but a custom framebuffer. + * Use `null` as the first argument to reset the state. + * + * @param {RenderTarget?} renderTarget - The render target to set. + * @param {Number} [activeCubeFace=0] - The active cube face. + * @param {Number} [activeMipmapLevel=0] - The active mipmap level. + */ setRenderTarget( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) { this._renderTarget = renderTarget; @@ -41333,24 +47317,67 @@ class Renderer { } + /** + * Returns the current render target. + * + * @return {RenderTarget?} The render target. Returns `null` if no render target is set. + */ getRenderTarget() { return this._renderTarget; } + /** + * Callback for {@link module:Renderer~Renderer#setRenderObjectFunction}. + * + * @callback renderObjectFunction + * @param {Object3D} object - The 3D object. + * @param {Scene} scene - The scene the 3D object belongs to. + * @param {Camera} camera - The camera the object should be rendered with. + * @param {BufferGeometry} geometry - The object's geometry. + * @param {Material} material - The object's material. + * @param {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`. + * @param {LightsNode} lightsNode - The current lights node. + * @param {ClippingContext} clippingContext - The clipping context. + * @param {String?} [passId=null] - An optional ID for identifying the pass. + */ + + /** + * Sets the given render object function. Calling this method overwrites the default implementation + * which is {@link module:Renderer~Renderer#renderObject}. Defining a custom function can be useful + * if you want to modify the way objects are rendered. For example you can define things like "every + * object that has material of a certain type should perform a pre-pass with a special overwrite material". + * The custom function must always call `renderObject()` in its implementation. + * + * Use `null` as the first argument to reset the state. + * + * @param {module:Renderer~renderObjectFunction?} renderObjectFunction - The render object function. + */ setRenderObjectFunction( renderObjectFunction ) { this._renderObjectFunction = renderObjectFunction; } + /** + * Returns the current render object function. + * + * @return {Function?} The current render object function. Returns `null` if no function is set. + */ getRenderObjectFunction() { return this._renderObjectFunction; } + /** + * Execute a single or an array of compute nodes. This method can only be called + * if the renderer has been initialized. + * + * @param {Node|Array} computeNodes - The compute node(s). + * @return {Promise?} A Promise that resolve when the compute has finished. Only returned when the renderer has not been initialized. + */ compute( computeNodes ) { if ( this.isDeviceLost === true ) return; @@ -41442,6 +47469,13 @@ class Renderer { } + /** + * Execute a single or an array of compute nodes. + * + * @async + * @param {Node|Array} computeNodes - The compute node(s). + * @return {Promise?} A Promise that resolve when the compute has finished. + */ async computeAsync( computeNodes ) { if ( this._initialized === false ) await this.init(); @@ -41452,6 +47486,13 @@ class Renderer { } + /** + * Checks if the given feature is supported by the selected backend. + * + * @async + * @param {String} name - The feature's name. + * @return {Promise} A Promise that resolves with a bool that indicates whether the feature is supported or not. + */ async hasFeatureAsync( name ) { if ( this._initialized === false ) await this.init(); @@ -41460,6 +47501,13 @@ class Renderer { } + /** + * Checks if the given feature is supported by the selected backend. If the + * renderer has not been initialized, this method always returns `false`. + * + * @param {String} name - The feature's name. + * @return {Boolean} Whether the feature is supported or not. + */ hasFeature( name ) { if ( this._initialized === false ) { @@ -41474,12 +47522,25 @@ class Renderer { } + /** + * Returns `true` when the renderer has been initialized. + * + * @return {Boolean} Whether the renderer has been initialized or not. + */ hasInitialized() { return this._initialized; } + /** + * Initializes the given textures. Useful for preloading a texture rather than waiting until first render + * (which can cause noticeable lags due to decode and GPU upload overhead). + * + * @async + * @param {Texture} texture - The texture. + * @return {Promise} A Promise that resolves when the texture has been initialized. + */ async initTextureAsync( texture ) { if ( this._initialized === false ) await this.init(); @@ -41488,20 +47549,32 @@ class Renderer { } + /** + * Initializes the given textures. Useful for preloading a texture rather than waiting until first render + * (which can cause noticeable lags due to decode and GPU upload overhead). + * + * This method can only be used if the renderer has been initialized. + * + * @param {Texture} texture - The texture. + */ initTexture( texture ) { if ( this._initialized === false ) { console.warn( 'THREE.Renderer: .initTexture() called before the backend is initialized. Try using .initTextureAsync() instead.' ); - return false; - } this._textures.updateTexture( texture ); } + /** + * Copies the current bound framebuffer into the given texture. + * + * @param {FramebufferTexture} framebufferTexture - The texture. + * @param {Vector2|Vector4} rectangle - A two or four dimensional vector that defines the rectangular portion of the framebuffer that should be copied. + */ copyFramebufferToTexture( framebufferTexture, rectangle = null ) { if ( rectangle !== null ) { @@ -41559,6 +47632,15 @@ class Renderer { } + /** + * Copies data of source texture into a destination texture. + * + * @param {Texture} srcTexture - The source texture. + * @param {Texture} dstTexture - The destination texture. + * @param {Box2|Box3} [srcRegion=null] - A bounding box which describes the source region. Can be two or three-dimensional. + * @param {Vector2|Vector3} [dstPosition=null] - A vector that represents the origin of the destination region. Can be two or three-dimensional. + * @param {Number} level - The mipmap level to copy. + */ copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { this._textures.updateTexture( srcTexture ); @@ -41568,12 +47650,35 @@ class Renderer { } - readRenderTargetPixelsAsync( renderTarget, x, y, width, height, index = 0, faceIndex = 0 ) { + /** + * Reads pixel data from the given render target. + * + * @async + * @param {RenderTarget} renderTarget - The render target to read from. + * @param {Number} x - The `x` coordinate of the copy region's origin. + * @param {Number} y - The `y` coordinate of the copy region's origin. + * @param {Number} width - The width of the copy region. + * @param {Number} height - The height of the copy region. + * @param {Number} [textureIndex=0] - The texture index of a MRT render target. + * @param {Number} [faceIndex=0] - The active cube face index. + * @return {Promise} A Promise that resolves when the read has been finished. The resolve provides the read data as a typed array. + */ + async readRenderTargetPixelsAsync( renderTarget, x, y, width, height, textureIndex = 0, faceIndex = 0 ) { - return this.backend.copyTextureToBuffer( renderTarget.textures[ index ], x, y, width, height, faceIndex ); + return this.backend.copyTextureToBuffer( renderTarget.textures[ textureIndex ], x, y, width, height, faceIndex ); } + /** + * Analyzes the given 3D object's hierarchy and builds render lists from the + * processed hierarchy. + * + * @param {Object3D} object - The 3D object to process (usually a scene). + * @param {Camera} camera - The camera the object is rendered with. + * @param {Number} groupOrder - The group order is derived from the `renderOrder` of groups and is used to group 3D objects within groups. + * @param {RenderList} renderList - The current render list. + * @param {ClippingContext} clippingContext - The current clipping context. + */ _projectObject( object, camera, groupOrder, renderList, clippingContext ) { if ( object.visible === false ) return; @@ -41695,6 +47800,14 @@ class Renderer { } + /** + * Renders the given render bundles. + * + * @private + * @param {Array} bundles - Array with render bundle data. + * @param {Scene} sceneRef - The scene the render bundles belong to. + * @param {LightsNode} lightsNode - The current lights node. + */ _renderBundles( bundles, sceneRef, lightsNode ) { for ( const bundle of bundles ) { @@ -41705,6 +47818,16 @@ class Renderer { } + /** + * Renders the transparent objects from the given render lists. + * + * @private + * @param {Array} renderList - The transparent render list. + * @param {Array} doublePassList - The list of transparent objects which require a double pass (e.g. because of transmission). + * @param {Camera} camera - The camera the render list should be rendered with. + * @param {Scene} scene - The scene the render list belongs to. + * @param {LightsNode} lightsNode - The current lights node. + */ _renderTransparents( renderList, doublePassList, camera, scene, lightsNode ) { if ( doublePassList.length > 0 ) { @@ -41745,6 +47868,16 @@ class Renderer { } + /** + * Renders the objects from the given render list. + * + * @private + * @param {Array} renderList - The render list. + * @param {Camera} camera - The camera the render list should be rendered with. + * @param {Scene} scene - The scene the render list belongs to. + * @param {LightsNode} lightsNode - The current lights node. + * @param {String?} [passId=null] - An optional ID for identifying the pass. + */ _renderObjects( renderList, camera, scene, lightsNode, passId = null ) { // process renderable objects @@ -41795,6 +47928,20 @@ class Renderer { } + /** + * This method represents the default render object function that manages the render lifecycle + * of the object. + * + * @param {Object3D} object - The 3D object. + * @param {Scene} scene - The scene the 3D object belongs to. + * @param {Camera} camera - The camera the object should be rendered with. + * @param {BufferGeometry} geometry - The object's geometry. + * @param {Material} material - The object's material. + * @param {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`. + * @param {LightsNode} lightsNode - The current lights node. + * @param {ClippingContext} clippingContext - The clipping context. + * @param {String?} [passId=null] - An optional ID for identifying the pass. + */ renderObject( object, scene, camera, geometry, material, group, lightsNode, clippingContext = null, passId = null ) { let overridePositionNode; @@ -41890,6 +48037,20 @@ class Renderer { } + /** + * This method represents the default `_handleObjectFunction` implementation which creates + * a render object from the given data and performs the draw command with the selected backend. + * + * @private + * @param {Object3D} object - The 3D object. + * @param {Material} material - The object's material. + * @param {Scene} scene - The scene the 3D object belongs to. + * @param {Camera} camera - The camera the object should be rendered with. + * @param {LightsNode} lightsNode - The current lights node. + * @param {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`. + * @param {ClippingContext} clippingContext - The clipping context. + * @param {String?} [passId=null] - An optional ID for identifying the pass. + */ _renderObjectDirect( object, material, scene, camera, lightsNode, group, clippingContext, passId ) { const renderObject = this._objects.get( object, material, scene, camera, lightsNode, this._currentRenderContext, clippingContext, passId ); @@ -41921,7 +48082,7 @@ class Renderer { renderBundleData.renderObjects.push( renderObject ); - renderObject.bundle = this._currentRenderBundle.scene; + renderObject.bundle = this._currentRenderBundle.bundleGroup; } @@ -41931,6 +48092,20 @@ class Renderer { } + /** + * A different implementation for `_handleObjectFunction` which only makes sure the object is ready for rendering. + * Used in `compileAsync()`. + * + * @private + * @param {Object3D} object - The 3D object. + * @param {Material} material - The object's material. + * @param {Scene} scene - The scene the 3D object belongs to. + * @param {Camera} camera - The camera the object should be rendered with. + * @param {LightsNode} lightsNode - The current lights node. + * @param {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`. + * @param {ClippingContext} clippingContext - The clipping context. + * @param {String?} [passId=null] - An optional ID for identifying the pass. + */ _createObjectPipeline( object, material, scene, camera, lightsNode, group, clippingContext, passId ) { const renderObject = this._objects.get( object, material, scene, camera, lightsNode, this._currentRenderContext, clippingContext, passId ); @@ -41952,6 +48127,15 @@ class Renderer { } + /** + * Alias for `compileAsync()`. + * + * @method + * @param {Object3D} scene - The scene or 3D object to precompile. + * @param {Camera} camera - The camera that is used to render the scene. + * @param {Scene} targetScene - If the first argument is a 3D object, this parameter must represent the scene the 3D object is going to be added. + * @return {Promise} A Promise that resolves when the compile has been finished. + */ get compile() { return this.compileAsync; @@ -41960,22 +48144,57 @@ class Renderer { } +/** + * A binding represents the connection between a resource (like a texture, sampler + * or uniform buffer) and the resource definition in a shader stage. + * + * This module is an abstract base class for all concrete bindings types. + * + * @abstract + * @private + */ class Binding { + /** + * Constructs a new binding. + * + * @param {String} [name=''] - The binding's name. + */ constructor( name = '' ) { + /** + * The binding's name. + * + * @type {String} + */ this.name = name; + /** + * A bitmask that defines in what shader stages the + * binding's resource is accessible. + * + * @type {String} + */ this.visibility = 0; } + /** + * Makes sure binding's resource is visible for the given shader stage. + * + * @param {Number} visibility - The shader stage. + */ setVisibility( visibility ) { this.visibility |= visibility; } + /** + * Clones the binding. + * + * @return {Binding} The cloned binding. + */ clone() { return Object.assign( new this.constructor(), this ); @@ -41984,6 +48203,16 @@ class Binding { } +/** @module BufferUtils **/ + +/** + * This function is usually called with the length in bytes of an array buffer. + * It returns an padded value which ensure chunk size alignment according to STD140 layout. + * + * @function + * @param {Number} floatLength - The buffer length. + * @return {Number} The padded length. + */ function getFloatLength( floatLength ) { // ensure chunk size alignment (STD140 layout) @@ -41992,32 +48221,81 @@ function getFloatLength( floatLength ) { } +/** + * Represents a buffer binding type. + * + * @private + * @abstract + * @augments Binding + */ class Buffer extends Binding { + /** + * Constructs a new buffer. + * + * @param {String} name - The buffer's name. + * @param {TypedArray} [buffer=null] - The buffer. + */ constructor( name, buffer = null ) { super( name ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isBuffer = true; + /** + * The bytes per element. + * + * @type {Number} + */ this.bytesPerElement = Float32Array.BYTES_PER_ELEMENT; + /** + * A reference to the internal buffer. + * + * @private + * @type {TypedArray} + */ this._buffer = buffer; } + /** + * The buffer's byte length. + * + * @type {Number} + * @readonly + */ get byteLength() { return getFloatLength( this._buffer.byteLength ); } + /** + * A reference to the internal buffer. + * + * @type {Float32Array} + * @readonly + */ get buffer() { return this._buffer; } + /** + * Updates the binding. + * + * @return {Boolean} Whether the buffer has been updated and must be + * uploaded to the GPU. + */ update() { return true; @@ -42026,12 +48304,31 @@ class Buffer extends Binding { } +/** + * Represents a uniform buffer binding type. + * + * @private + * @augments Buffer + */ class UniformBuffer extends Buffer { + /** + * Constructs a new uniform buffer. + * + * @param {String} name - The buffer's name. + * @param {TypedArray} [buffer=null] - The buffer. + */ constructor( name, buffer = null ) { super( name, buffer ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isUniformBuffer = true; } @@ -42040,17 +48337,46 @@ class UniformBuffer extends Buffer { let _id$4 = 0; +/** + * A special form of uniform buffer binding type. + * It's buffer value is managed by a node object. + * + * @private + * @augments UniformBuffer + */ class NodeUniformBuffer extends UniformBuffer { + /** + * Constructs a new node-based uniform buffer. + * + * @param {BufferNode} nodeUniform - The uniform buffer node. + * @param {UniformGroupNode} groupNode - The uniform group node. + */ constructor( nodeUniform, groupNode ) { super( 'UniformBuffer_' + _id$4 ++, nodeUniform ? nodeUniform.value : null ); + /** + * The uniform buffer node. + * + * @type {BufferNode} + */ this.nodeUniform = nodeUniform; + + /** + * The uniform group node. + * + * @type {UniformGroupNode} + */ this.groupNode = groupNode; } + /** + * The uniform buffer. + * + * @type {Float32Array} + */ get buffer() { return this.nodeUniform.value; @@ -42059,22 +48385,59 @@ class NodeUniformBuffer extends UniformBuffer { } +/** + * This class represents a uniform buffer binding but with + * an API that allows to maintain individual uniform objects. + * + * @private + * @augments UniformBuffer + */ class UniformsGroup extends UniformBuffer { + /** + * Constructs a new uniforms group. + * + * @param {String} name - The group's name. + */ constructor( name ) { super( name ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isUniformsGroup = true; + /** + * An array with the raw uniform values. + * + * @private + * @type {Array?} + * @default null + */ this._values = null; - // the order of uniforms in this array must match the order of uniforms in the shader - + /** + * An array of uniform objects. + * + * The order of uniforms in this array must match the order of uniforms in the shader. + * + * @type {Array} + */ this.uniforms = []; } + /** + * Adds a uniform to this group. + * + * @param {Uniform} uniform - The uniform to add. + * @return {UniformsGroup} A reference to this group. + */ addUniform( uniform ) { this.uniforms.push( uniform ); @@ -42083,6 +48446,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Removes a uniform from this group. + * + * @param {Uniform} uniform - The uniform to remove. + * @return {UniformsGroup} A reference to this group. + */ removeUniform( uniform ) { const index = this.uniforms.indexOf( uniform ); @@ -42097,6 +48466,11 @@ class UniformsGroup extends UniformBuffer { } + /** + * An array with the raw uniform values. + * + * @type {Array} + */ get values() { if ( this._values === null ) { @@ -42109,6 +48483,11 @@ class UniformsGroup extends UniformBuffer { } + /** + * A Float32 array buffer with the uniform values. + * + * @type {Float32Array} + */ get buffer() { let buffer = this._buffer; @@ -42127,6 +48506,11 @@ class UniformsGroup extends UniformBuffer { } + /** + * The byte length of the buffer with correct buffer alignment. + * + * @type {Number} + */ get byteLength() { let offset = 0; // global buffer offset in bytes @@ -42168,6 +48552,15 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates this group by updating each uniform object of + * the internal uniform list. The uniform objects check if their + * values has actually changed so this method only returns + * `true` if there is a real value change. + * + * @return {Boolean} Whether the uniforms have been updated and + * must be uploaded to the GPU. + */ update() { let updated = false; @@ -42186,6 +48579,13 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given uniform by calling an update method matching + * the uniforms type. + * + * @param {Uniform} uniform - The uniform to update. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateByType( uniform ) { if ( uniform.isNumberUniform ) return this.updateNumber( uniform ); @@ -42200,6 +48600,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given Number uniform. + * + * @param {NumberUniform} uniform - The Number uniform. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateNumber( uniform ) { let updated = false; @@ -42222,6 +48628,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given Vector2 uniform. + * + * @param {Vector2Uniform} uniform - The Vector2 uniform. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateVector2( uniform ) { let updated = false; @@ -42246,6 +48658,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given Vector3 uniform. + * + * @param {Vector3Uniform} uniform - The Vector3 uniform. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateVector3( uniform ) { let updated = false; @@ -42271,6 +48689,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given Vector4 uniform. + * + * @param {Vector4Uniform} uniform - The Vector4 uniform. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateVector4( uniform ) { let updated = false; @@ -42297,6 +48721,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given Color uniform. + * + * @param {ColorUniform} uniform - The Color uniform. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateColor( uniform ) { let updated = false; @@ -42321,6 +48751,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given Matrix3 uniform. + * + * @param {Matrix3Uniform} uniform - The Matrix3 uniform. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateMatrix3( uniform ) { let updated = false; @@ -42353,6 +48789,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given Matrix4 uniform. + * + * @param {Matrix4Uniform} uniform - The Matrix4 uniform. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateMatrix4( uniform ) { let updated = false; @@ -42374,6 +48816,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Returns a typed array that matches the given data type. + * + * @param {String} type - The data type. + * @return {TypedArray} The typed array. + */ _getBufferForType( type ) { if ( type === 'int' || type === 'ivec2' || type === 'ivec3' || type === 'ivec4' ) return new Int32Array( this.buffer.buffer ); @@ -42384,6 +48832,14 @@ class UniformsGroup extends UniformBuffer { } +/** + * Sets the values of the second array to the first array. + * + * @private + * @param {TypedArray} a - The first array. + * @param {TypedArray} b - The second array. + * @param {Number} offset - An index offset for the first array. + */ function setArray( a, b, offset ) { for ( let i = 0, l = b.length; i < l; i ++ ) { @@ -42394,6 +48850,15 @@ function setArray( a, b, offset ) { } +/** + * Returns `true` if the given arrays are equal. + * + * @private + * @param {TypedArray} a - The first array. + * @param {TypedArray} b - The second array. + * @param {Number} offset - An index offset for the first array. + * @return {Boolean} Whether the given arrays are equal or not. + */ function arraysEqual( a, b, offset ) { for ( let i = 0, l = b.length; i < l; i ++ ) { @@ -42408,58 +48873,128 @@ function arraysEqual( a, b, offset ) { let _id$3 = 0; +/** + * A special form of uniforms group that represents + * the individual uniforms as node-based uniforms. + * + * @private + * @augments UniformsGroup + */ class NodeUniformsGroup extends UniformsGroup { + /** + * Constructs a new node-based uniforms group. + * + * @param {String} name - The group's name. + * @param {UniformGroupNode} groupNode - The uniform group node. + */ constructor( name, groupNode ) { super( name ); + /** + * The group's ID. + * + * @type {Number} + */ this.id = _id$3 ++; + + /** + * The uniform group node. + * + * @type {UniformGroupNode} + */ this.groupNode = groupNode; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isNodeUniformsGroup = true; } - getNodes() { - - const nodes = []; - - for ( const uniform of this.uniforms ) { - - const node = uniform.nodeUniform.node; - - if ( ! node ) throw new Error( 'NodeUniformsGroup: Uniform has no node.' ); - - nodes.push( node ); - - } - - return nodes; - - } - } let _id$2 = 0; +/** + * Represents a sampled texture binding type. + * + * @private + * @augments Binding + */ class SampledTexture extends Binding { + /** + * Constructs a new sampled texture. + * + * @param {String} name - The sampled texture's name. + * @param {Texture?} texture - The texture this binding is referring to. + */ constructor( name, texture ) { super( name ); + /** + * This identifier. + * + * @type {Number} + */ this.id = _id$2 ++; + /** + * The texture this binding is referring to. + * + * @type {Texture?} + */ this.texture = texture; + + /** + * The binding's version. + * + * @type {Number} + */ this.version = texture ? texture.version : 0; + + /** + * Whether the texture is a storage texture or not. + * + * @type {Boolean} + * @default false + */ this.store = false; + + /** + * The binding's generation which is an additional version + * qualifier. + * + * @type {Number?} + * @default null + */ this.generation = null; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isSampledTexture = true; } + /** + * Returns `true` whether this binding requires an update for the + * given generation. + * + * @param {Number} generation - The generation. + * @return {Boolean} Whether an update is required or not. + */ needsBindingsUpdate( generation ) { const { texture } = this; @@ -42476,6 +49011,13 @@ class SampledTexture extends Binding { } + /** + * Updates the binding. + * + * @param {Number} generation - The generation. + * @return {Boolean} Whether the texture has been updated and must be + * uploaded to the GPU. + */ update() { const { texture, version } = this; @@ -42494,25 +49036,70 @@ class SampledTexture extends Binding { } +/** + * A special form of sampled texture binding type. + * It's texture value is managed by a node object. + * + * @private + * @augments SampledTexture + */ class NodeSampledTexture extends SampledTexture { + /** + * Constructs a new node-based sampled texture. + * + * @param {String} name - The textures's name. + * @param {TextureNode} textureNode - The texture node. + * @param {UniformGroupNode} groupNode - The uniform group node. + * @param {String?} [access=null] - The access type. + */ constructor( name, textureNode, groupNode, access = null ) { super( name, textureNode ? textureNode.value : null ); + /** + * The texture node. + * + * @type {TextureNode} + */ this.textureNode = textureNode; + + /** + * The uniform group node. + * + * @type {UniformGroupNode} + */ this.groupNode = groupNode; + /** + * The access type. + * + * @type {String?} + * @default null + */ this.access = access; } + /** + * Overwrites the default to additionally check if the node value has changed. + * + * @param {Number} generation - The generation. + * @return {Boolean} Whether an update is required or not. + */ needsBindingsUpdate( generation ) { return this.textureNode.value !== this.texture || super.needsBindingsUpdate( generation ); } + /** + * Updates the binding. + * + * @param {Number} generation - The generation. + * @return {Boolean} Whether the texture has been updated and must be + * uploaded to the GPU. + */ update() { const { textureNode } = this; @@ -42531,24 +49118,68 @@ class NodeSampledTexture extends SampledTexture { } +/** + * A special form of sampled cube texture binding type. + * It's texture value is managed by a node object. + * + * @private + * @augments NodeSampledTexture + */ class NodeSampledCubeTexture extends NodeSampledTexture { - constructor( name, textureNode, groupNode, access ) { + /** + * Constructs a new node-based sampled cube texture. + * + * @param {String} name - The textures's name. + * @param {TextureNode} textureNode - The texture node. + * @param {UniformGroupNode} groupNode - The uniform group node. + * @param {String?} [access=null] - The access type. + */ + constructor( name, textureNode, groupNode, access = null ) { super( name, textureNode, groupNode, access ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isSampledCubeTexture = true; } } +/** + * A special form of sampled 3D texture binding type. + * It's texture value is managed by a node object. + * + * @private + * @augments NodeSampledTexture + */ class NodeSampledTexture3D extends NodeSampledTexture { - constructor( name, textureNode, groupNode, access ) { + /** + * Constructs a new node-based sampled 3D texture. + * + * @param {String} name - The textures's name. + * @param {TextureNode} textureNode - The texture node. + * @param {UniformGroupNode} groupNode - The uniform group node. + * @param {String?} [access=null] - The access type. + */ + constructor( name, textureNode, groupNode, access = null ) { super( name, textureNode, groupNode, access ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isSampledTexture3D = true; } @@ -42592,39 +49223,109 @@ precision highp isampler2DArray; precision lowp sampler2DShadow; `; +/** + * A node builder targeting GLSL. + * + * This module generates GLSL shader code from node materials and also + * generates the respective bindings and vertex buffer definitions. These + * data are later used by the renderer to create render and compute pipelines + * for render objects. + * + * @augments NodeBuilder + */ class GLSLNodeBuilder extends NodeBuilder { + /** + * Constructs a new GLSL node builder renderer. + * + * @param {Object3D} object - The 3D object. + * @param {Renderer} renderer - The renderer. + */ constructor( object, renderer ) { super( object, renderer, new GLSLNodeParser() ); + /** + * A dictionary holds for each shader stage ('vertex', 'fragment', 'compute') + * another dictionary which manages UBOs per group ('render','frame','object'). + * + * @type {Object>} + */ this.uniformGroups = {}; + + /** + * An array that holds objects defining the varying and attribute data in + * context of Transform Feedback. + * + * @type {Object>} + */ this.transforms = []; + + /** + * A dictionary that holds for each shader stage a Map of used extensions. + * + * @type {Object>} + */ this.extensions = {}; + + /** + * A dictionary that holds for each shader stage an Array of used builtins. + * + * @type {Object>} + */ this.builtins = { vertex: [], fragment: [], compute: [] }; + /** + * Whether comparison in shader code are generated with methods or not. + * + * @type {Boolean} + * @default true + */ this.useComparisonMethod = true; } + /** + * Checks if the given texture requires a manual conversion to the working color space. + * + * @param {Texture} texture - The texture to check. + * @return {Boolean} Whether the given texture requires a conversion to working color space or not. + */ needsToWorkingColorSpace( texture ) { return texture.isVideoTexture === true && texture.colorSpace !== NoColorSpace; } + /** + * Returns the native shader method name for a given generic name. + * + * @param {String} method - The method name to resolve. + * @return {String} The resolved GLSL method name. + */ getMethod( method ) { return glslMethods[ method ] || method; } + /** + * Returns the output struct name. Not relevant for GLSL. + * + * @return {String} + */ getOutputStructName() { return ''; } + /** + * Builds the given shader node. + * + * @param {ShaderNodeInternal} shaderNode - The shader node. + * @return {String} The GLSL function code. + */ buildFunctionCode( shaderNode ) { const layout = shaderNode.layout; @@ -42655,6 +49356,12 @@ ${ flowData.code } } + /** + * Setups the Pixel Buffer Object (PBO) for the given storage + * buffer node. + * + * @param {StorageBufferNode} storageBufferNode - The storage buffer node. + */ setupPBO( storageBufferNode ) { const attribute = storageBufferNode.value; @@ -42723,6 +49430,13 @@ ${ flowData.code } } + /** + * Returns a GLSL snippet that represents the property name of the given node. + * + * @param {Node} node - The node. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The property name. + */ getPropertyName( node, shaderStage = this.shaderStage ) { if ( node.isNodeUniform && node.node.isTextureNode !== true && node.node.isBufferNode !== true ) { @@ -42735,6 +49449,13 @@ ${ flowData.code } } + /** + * Setups the Pixel Buffer Object (PBO) for the given storage + * buffer node. + * + * @param {StorageArrayElementNode} storageArrayElementNode - The storage array element node. + * @return {String} The property name. + */ generatePBO( storageArrayElementNode ) { const { node, indexNode } = storageArrayElementNode; @@ -42817,6 +49538,16 @@ ${ flowData.code } } + /** + * Generates the GLSL snippet that reads a single texel from a texture without sampling or filtering. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvIndexSnippet - A GLSL snippet that represents texture coordinates used for sampling. + * @param {String?} depthSnippet - A GLSL snippet that represents the 0-based texture array index to sample. + * @param {String} [levelSnippet='0u'] - A GLSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @return {String} The GLSL snippet. + */ generateTextureLoad( texture, textureProperty, uvIndexSnippet, depthSnippet, levelSnippet = '0' ) { if ( depthSnippet ) { @@ -42831,6 +49562,15 @@ ${ flowData.code } } + /** + * Generates the GLSL snippet for sampling/loading the given texture. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A GLSL snippet that represents texture coordinates used for sampling. + * @param {String?} depthSnippet - A GLSL snippet that represents the 0-based texture array index to sample. + * @return {String} The GLSL snippet. + */ generateTexture( texture, textureProperty, uvSnippet, depthSnippet ) { if ( texture.isDepthTexture ) { @@ -42847,24 +49587,63 @@ ${ flowData.code } } + /** + * Generates the GLSL snippet when sampling textures with explicit mip level. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A GLSL snippet that represents texture coordinates used for sampling. + * @param {String} levelSnippet - A GLSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @return {String} The GLSL snippet. + */ generateTextureLevel( texture, textureProperty, uvSnippet, levelSnippet ) { return `textureLod( ${ textureProperty }, ${ uvSnippet }, ${ levelSnippet } )`; } + /** + * Generates the GLSL snippet when sampling textures with a bias to the mip level. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A GLSL snippet that represents texture coordinates used for sampling. + * @param {String} biasSnippet - A GLSL snippet that represents the bias to apply to the mip level before sampling. + * @return {String} The GLSL snippet. + */ generateTextureBias( texture, textureProperty, uvSnippet, biasSnippet ) { return `texture( ${ textureProperty }, ${ uvSnippet }, ${ biasSnippet } )`; } + /** + * Generates the GLSL snippet for sampling/loading the given texture using explicit gradients. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A GLSL snippet that represents texture coordinates used for sampling. + * @param {Array} gradSnippet - An array holding both gradient GLSL snippets. + * @return {String} The GLSL snippet. + */ generateTextureGrad( texture, textureProperty, uvSnippet, gradSnippet ) { return `textureGrad( ${ textureProperty }, ${ uvSnippet }, ${ gradSnippet[ 0 ] }, ${ gradSnippet[ 1 ] } )`; } + /** + * Generates the GLSL snippet for sampling a depth texture and comparing the sampled depth values + * against a reference value. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A GLSL snippet that represents texture coordinates used for sampling. + * @param {String} compareSnippet - A GLSL snippet that represents the reference value. + * @param {String?} depthSnippet - A GLSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The GLSL snippet. + */ generateTextureCompare( texture, textureProperty, uvSnippet, compareSnippet, depthSnippet, shaderStage = this.shaderStage ) { if ( shaderStage === 'fragment' ) { @@ -42879,6 +49658,12 @@ ${ flowData.code } } + /** + * Returns the variables of the given shader stage as a GLSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The GLSL snippet that defines the variables. + */ getVars( shaderStage ) { const snippets = []; @@ -42899,6 +49684,12 @@ ${ flowData.code } } + /** + * Returns the uniforms of the given shader stage as a GLSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The GLSL snippet that defines the uniforms. + */ getUniforms( shaderStage ) { const uniforms = this.uniforms[ shaderStage ]; @@ -43016,6 +49807,12 @@ ${ flowData.code } } + /** + * Returns the type for a given buffer attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + * @return {String} The type. + */ getTypeFromAttribute( attribute ) { let nodeType = super.getTypeFromAttribute( attribute ); @@ -43040,6 +49837,12 @@ ${ flowData.code } } + /** + * Returns the shader attributes of the given shader stage as a GLSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The GLSL snippet that defines the shader attributes. + */ getAttributes( shaderStage ) { let snippet = ''; @@ -43062,6 +49865,12 @@ ${ flowData.code } } + /** + * Returns the members of the given struct type node as a GLSL string. + * + * @param {StructTypeNode} struct - The struct type node. + * @return {String} The GLSL snippet that defines the struct members. + */ getStructMembers( struct ) { const snippets = []; @@ -43078,6 +49887,12 @@ ${ flowData.code } } + /** + * Returns the structs of the given shader stage as a GLSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The GLSL snippet that defines the structs. + */ getStructs( shaderStage ) { const snippets = []; @@ -43105,6 +49920,12 @@ ${ flowData.code } } + /** + * Returns the varyings of the given shader stage as a GLSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The GLSL snippet that defines the varyings. + */ getVaryings( shaderStage ) { let snippet = ''; @@ -43150,18 +49971,33 @@ ${ flowData.code } } + /** + * Returns the vertex index builtin. + * + * @return {String} The vertex index. + */ getVertexIndex() { return 'uint( gl_VertexID )'; } + /** + * Returns the instance index builtin. + * + * @return {String} The instance index. + */ getInstanceIndex() { return 'uint( gl_InstanceID )'; } + /** + * Returns the invocation local index builtin. + * + * @return {String} The invocation local index. + */ getInvocationLocalIndex() { const workgroupSize = this.object.workgroupSize; @@ -43172,6 +50008,11 @@ ${ flowData.code } } + /** + * Returns the draw index builtin. + * + * @return {String?} The drawIndex shader string. Returns `null` if `WEBGL_multi_draw` isn't supported by the device. + */ getDrawIndex() { const extensions = this.renderer.backend.extensions; @@ -43186,24 +50027,46 @@ ${ flowData.code } } + /** + * Returns the front facing builtin. + * + * @return {String} The front facing builtin. + */ getFrontFacing() { return 'gl_FrontFacing'; } + /** + * Returns the frag coord builtin. + * + * @return {String} The frag coord builtin. + */ getFragCoord() { return 'gl_FragCoord.xy'; } + /** + * Returns the frag depth builtin. + * + * @return {String} The frag depth builtin. + */ getFragDepth() { return 'gl_FragDepth'; } + /** + * Enables the given extension. + * + * @param {String} name - The extension name. + * @param {String} behavior - The extension behavior. + * @param {String} [shaderStage=this.shaderStage] - The shader stage. + */ enableExtension( name, behavior, shaderStage = this.shaderStage ) { const map = this.extensions[ shaderStage ] || ( this.extensions[ shaderStage ] = new Map() ); @@ -43219,6 +50082,12 @@ ${ flowData.code } } + /** + * Returns the enabled extensions of the given shader stage as a GLSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The GLSL snippet that defines the enabled extensions. + */ getExtensions( shaderStage ) { const snippets = []; @@ -43252,12 +50121,23 @@ ${ flowData.code } } + /** + * Returns the clip distances builtin. + * + * @return {String} The clip distances builtin. + */ getClipDistance() { return 'gl_ClipDistance'; } + /** + * Whether the requested feature is available or not. + * + * @param {String} name - The requested feature. + * @return {Boolean} Whether the requested feature is supported or not. + */ isAvailable( name ) { let result = supports$1[ name ]; @@ -43301,12 +50181,22 @@ ${ flowData.code } } + /** + * Whether to flip texture data along its vertical axis or not. + * + * @return {Boolean} Returns always `true` in context of GLSL. + */ isFlipY() { return true; } + /** + * Enables hardware clipping. + * + * @param {String} planeCount - The clipping plane count. + */ enableHardwareClipping( planeCount ) { this.enableExtension( 'GL_ANGLE_clip_cull_distance', 'require' ); @@ -43315,12 +50205,24 @@ ${ flowData.code } } + /** + * Registers a transform in context of Transform Feedback. + * + * @param {String} varyingName - The varying name. + * @param {AttributeNode} attributeNode - The attribute node. + */ registerTransform( varyingName, attributeNode ) { this.transforms.push( { varyingName, attributeNode } ); } + /** + * Returns the transforms of the given shader stage as a GLSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The GLSL snippet that defines the transforms. + */ getTransforms( /* shaderStage */ ) { const transforms = this.transforms; @@ -43341,6 +50243,14 @@ ${ flowData.code } } + /** + * Returns a GLSL struct based on the given name and variables. + * + * @private + * @param {String} name - The struct name. + * @param {String} vars - The struct variables. + * @return {String} The GLSL snippet representing a struct. + */ _getGLSLUniformStruct( name, vars ) { return ` @@ -43350,6 +50260,13 @@ ${vars} } + /** + * Returns a GLSL vertex shader based on the given shader data. + * + * @private + * @param {Object} shaderData - The shader data. + * @return {String} The vertex shader. + */ _getGLSLVertexCode( shaderData ) { return `#version 300 es @@ -43392,6 +50309,13 @@ void main() { } + /** + * Returns a GLSL fragment shader based on the given shader data. + * + * @private + * @param {Object} shaderData - The shader data. + * @return {String} The vertex shader. + */ _getGLSLFragmentCode( shaderData ) { return `#version 300 es @@ -43425,6 +50349,9 @@ void main() { } + /** + * Controls the code build of the shader stages. + */ buildCode() { const shadersData = this.material !== null ? { fragment: {}, vertex: {} } : { compute: {} }; @@ -43505,6 +50432,19 @@ void main() { } + /** + * This method is one of the more important ones since it's responsible + * for generating a matching binding instance for the given uniform node. + * + * These bindings are later used in the renderer to create bind groups + * and layouts. + * + * @param {UniformNode} node - The uniform node. + * @param {String} type - The node data type. + * @param {String} shaderStage - The shader stage. + * @param {String?} [name=null] - An optional uniform name. + * @return {NodeUniform} The node uniform object. + */ getUniformFromNode( node, type, shaderStage, name = null ) { const uniformNode = super.getUniformFromNode( node, type, shaderStage, name ); @@ -43579,141 +50519,540 @@ void main() { } -let vector2 = null; -let vector4 = null; -let color4 = null; +let _vector2 = null; +let _color4 = null; +/** + * Most of the rendering related logic is implemented in the + * {@link module:Renderer} module and related management components. + * Sometimes it is required though to execute commands which are + * specific to the current 3D backend (which is WebGPU or WebGL 2). + * This abstract base class defines an interface that encapsulates + * all backend-related logic. Derived classes for each backend must + * implement the interface. + * + * @abstract + * @private + */ class Backend { + /** + * Constructs a new backend. + * + * @param {Object} parameters - An object holding parameters for the backend. + */ constructor( parameters = {} ) { + /** + * The parameters of the backend. + * + * @type {Object} + */ this.parameters = Object.assign( {}, parameters ); + + /** + * This weak map holds backend-specific data of objects + * like textures, attributes or render targets. + * + * @type {WeakMap} + */ this.data = new WeakMap(); + + /** + * A reference to the renderer. + * + * @type {Renderer?} + * @default null + */ this.renderer = null; + + /** + * A reference to the canvas element the renderer is drawing to. + * + * @type {(HTMLCanvasElement|OffscreenCanvas)?} + * @default null + */ this.domElement = null; } + /** + * Initializes the backend so it is ready for usage. Concrete backends + * are supposed to implement their rendering context creation and related + * operations in this method. + * + * @async + * @param {Renderer} renderer - The renderer. + * @return {Promise} A Promise that resolves when the backend has been initialized. + */ async init( renderer ) { this.renderer = renderer; } + /** + * The coordinate system of the backend. + * + * @abstract + * @type {Number} + * @readonly + */ + get coordinateSystem() {} + // render context - begin( /*renderContext*/ ) { } + /** + * This method is executed at the beginning of a render call and + * can be used by the backend to prepare the state for upcoming + * draw calls. + * + * @abstract + * @param {RenderContext} renderContext - The render context. + */ + beginRender( /*renderContext*/ ) {} - finish( /*renderContext*/ ) { } + /** + * This method is executed at the end of a render call and + * can be used by the backend to finalize work after draw + * calls. + * + * @abstract + * @param {RenderContext} renderContext - The render context. + */ + finishRender( /*renderContext*/ ) {} + + /** + * This method is executed at the beginning of a compute call and + * can be used by the backend to prepare the state for upcoming + * compute tasks. + * + * @abstract + * @param {Node|Array} computeGroup - The compute node(s). + */ + beginCompute( /*computeGroup*/ ) {} + + /** + * This method is executed at the end of a compute call and + * can be used by the backend to finalize work after compute + * tasks. + * + * @abstract + * @param {Node|Array} computeGroup - The compute node(s). + */ + finishCompute( /*computeGroup*/ ) {} // render object + /** + * Executes a draw command for the given render object. + * + * @abstract + * @param {RenderObject} renderObject - The render object to draw. + * @param {Info} info - Holds a series of statistical information about the GPU memory and the rendering process. + */ draw( /*renderObject, info*/ ) { } + // compute node + + /** + * Executes a compute command for the given compute node. + * + * @abstract + * @param {Node|Array} computeGroup - The group of compute nodes of a compute call. Can be a single compute node. + * @param {Node} computeNode - The compute node. + * @param {Array} bindings - The bindings. + * @param {ComputePipeline} computePipeline - The compute pipeline. + */ + compute( /*computeGroup, computeNode, computeBindings, computePipeline*/ ) { } + // program + /** + * Creates a shader program from the given programmable stage. + * + * @abstract + * @param {ProgrammableStage} program - The programmable stage. + */ createProgram( /*program*/ ) { } + /** + * Destroys the shader program of the given programmable stage. + * + * @abstract + * @param {ProgrammableStage} program - The programmable stage. + */ destroyProgram( /*program*/ ) { } // bindings - createBindings( /*bingGroup, bindings*/ ) { } + /** + * Creates bindings from the given bind group definition. + * + * @abstract + * @param {BindGroup} bindGroup - The bind group. + * @param {Array} bindings - Array of bind groups. + * @param {Number} cacheIndex - The cache index. + * @param {Number} version - The version. + */ + createBindings( /*bindGroup, bindings, cacheIndex, version*/ ) { } - updateBindings( /*bingGroup, bindings*/ ) { } + /** + * Updates the given bind group definition. + * + * @abstract + * @param {BindGroup} bindGroup - The bind group. + * @param {Array} bindings - Array of bind groups. + * @param {Number} cacheIndex - The cache index. + * @param {Number} version - The version. + */ + updateBindings( /*bindGroup, bindings, cacheIndex, version*/ ) { } - // pipeline + /** + * Updates a buffer binding. + * + * @abstract + * @param {Buffer} binding - The buffer binding to update. + */ + updateBinding( /*binding*/ ) { } - createRenderPipeline( /*renderObject*/ ) { } + // pipeline - createComputePipeline( /*computeNode, pipeline*/ ) { } + /** + * Creates a render pipeline for the given render object. + * + * @abstract + * @param {RenderObject} renderObject - The render object. + * @param {Array} promises - An array of compilation promises which are used in `compileAsync()`. + */ + createRenderPipeline( /*renderObject, promises*/ ) { } - destroyPipeline( /*pipeline*/ ) { } + /** + * Creates a compute pipeline for the given compute node. + * + * @abstract + * @param {ComputePipeline} computePipeline - The compute pipeline. + * @param {Array} bindings - The bindings. + */ + createComputePipeline( /*computePipeline, bindings*/ ) { } // cache key - needsRenderUpdate( /*renderObject*/ ) { } // return Boolean ( fast test ) + /** + * Returns `true` if the render pipeline requires an update. + * + * @abstract + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether the render pipeline requires an update or not. + */ + needsRenderUpdate( /*renderObject*/ ) { } - getRenderCacheKey( /*renderObject*/ ) { } // return String + /** + * Returns a cache key that is used to identify render pipelines. + * + * @abstract + * @param {RenderObject} renderObject - The render object. + * @return {String} The cache key. + */ + getRenderCacheKey( /*renderObject*/ ) { } // node builder - createNodeBuilder( /*renderObject*/ ) { } // return NodeBuilder (ADD IT) + /** + * Returns a node builder for the given render object. + * + * @abstract + * @param {RenderObject} renderObject - The render object. + * @param {Renderer} renderer - The renderer. + * @return {NodeBuilder} The node builder. + */ + createNodeBuilder( /*renderObject, renderer*/ ) { } // textures + /** + * Creates a GPU sampler for the given texture. + * + * @abstract + * @param {Texture} texture - The texture to create the sampler for. + */ createSampler( /*texture*/ ) { } + /** + * Destroys the GPU sampler for the given texture. + * + * @abstract + * @param {Texture} texture - The texture to destroy the sampler for. + */ + destroySampler( /*texture*/ ) {} + + /** + * Creates a default texture for the given texture that can be used + * as a placeholder until the actual texture is ready for usage. + * + * @abstract + * @param {Texture} texture - The texture to create a default texture for. + */ createDefaultTexture( /*texture*/ ) { } - createTexture( /*texture*/ ) { } + /** + * Defines a texture on the GPU for the given texture object. + * + * @abstract + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ + createTexture( /*texture, options={}*/ ) { } + + /** + * Uploads the updated texture data to the GPU. + * + * @abstract + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ + updateTexture( /*texture, options = {}*/ ) { } - copyTextureToBuffer( /*texture, x, y, width, height*/ ) {} + /** + * Generates mipmaps for the given texture. + * + * @abstract + * @param {Texture} texture - The texture. + */ + generateMipmaps( /*texture*/ ) { } + + /** + * Destroys the GPU data for the given texture object. + * + * @abstract + * @param {Texture} texture - The texture. + */ + destroyTexture( /*texture*/ ) { } + + /** + * Returns texture data as a typed array. + * + * @abstract + * @async + * @param {Texture} texture - The texture to copy. + * @param {Number} x - The x coordinate of the copy origin. + * @param {Number} y - The y coordinate of the copy origin. + * @param {Number} width - The width of the copy. + * @param {Number} height - The height of the copy. + * @param {Number} faceIndex - The face index. + * @return {Promise} A Promise that resolves with a typed array when the copy operation has finished. + */ + async copyTextureToBuffer( /*texture, x, y, width, height, faceIndex*/ ) {} + + /** + * Copies data of the given source texture to the given destination texture. + * + * @abstract + * @param {Texture} srcTexture - The source texture. + * @param {Texture} dstTexture - The destination texture. + * @param {Vector4?} [srcRegion=null] - The region of the source texture to copy. + * @param {(Vector2|Vector3)?} [dstPosition=null] - The destination position of the copy. + * @param {Number} [level=0] - The mip level to copy. + */ + copyTextureToTexture( /*srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0*/ ) {} + + /** + * Copies the current bound framebuffer to the given texture. + * + * @abstract + * @param {Texture} texture - The destination texture. + * @param {RenderContext} renderContext - The render context. + * @param {Vector4} rectangle - A four dimensional vector defining the origin and dimension of the copy. + */ + copyFramebufferToTexture( /*texture, renderContext, rectangle*/ ) {} // attributes + /** + * Creates the GPU buffer of a shader attribute. + * + * @abstract + * @param {BufferAttribute} attribute - The buffer attribute. + */ createAttribute( /*attribute*/ ) { } + /** + * Creates the GPU buffer of an indexed shader attribute. + * + * @abstract + * @param {BufferAttribute} attribute - The indexed buffer attribute. + */ createIndexAttribute( /*attribute*/ ) { } + /** + * Creates the GPU buffer of a storage attribute. + * + * @abstract + * @param {BufferAttribute} attribute - The buffer attribute. + */ + createStorageAttribute( /*attribute*/ ) { } + + /** + * Updates the GPU buffer of a shader attribute. + * + * @abstract + * @param {BufferAttribute} attribute - The buffer attribute to update. + */ updateAttribute( /*attribute*/ ) { } + /** + * Destroys the GPU buffer of a shader attribute. + * + * @abstract + * @param {BufferAttribute} attribute - The buffer attribute to destroy. + */ destroyAttribute( /*attribute*/ ) { } // canvas + /** + * Returns the backend's rendering context. + * + * @abstract + * @return {Object} The rendering context. + */ getContext() { } + /** + * Backends can use this method if they have to run + * logic when the renderer gets resized. + * + * @abstract + */ updateSize() { } + /** + * Updates the viewport with the values from the given render context. + * + * @abstract + * @param {RenderContext} renderContext - The render context. + */ + updateViewport( /*renderContext*/ ) {} + // utils - resolveTimestampAsync( /*renderContext, type*/ ) { } + /** + * Returns `true` if the given 3D object is fully occluded by other + * 3D objects in the scene. Backends must implement this method by using + * a Occlusion Query API. + * + * @abstract + * @param {RenderContext} renderContext - The render context. + * @param {Object3D} object - The 3D object to test. + * @return {Boolean} Whether the 3D object is fully occluded or not. + */ + isOccluded( /*renderContext, object*/ ) {} - hasFeatureAsync( /*name*/ ) { } // return Boolean + /** + * Resolves the time stamp for the given render context and type. + * + * @async + * @abstract + * @param {RenderContext} renderContext - The render context. + * @param {String} type - The render context. + * @return {Promise} A Promise that resolves when the time stamp has been computed. + */ + async resolveTimestampAsync( /*renderContext, type*/ ) { } - hasFeature( /*name*/ ) { } // return Boolean + /** + * Can be used to synchronize CPU operations with GPU tasks. So when this method is called, + * the CPU waits for the GPU to complete its operation (e.g. a compute task). + * + * @async + * @abstract + * @return {Promise} A Promise that resolves when synchronization has been finished. + */ + async waitForGPU() {} - getInstanceCount( renderObject ) { + /** + * This method performs a readback operation by moving buffer data from + * a storage buffer attribute from the GPU to the CPU. + * + * @async + * @param {StorageBufferAttribute} attribute - The storage buffer attribute. + * @return {Promise} A promise that resolves with the buffer data when the data are ready. + */ + async getArrayBufferAsync( /* attribute */ ) {} - const { object, geometry } = renderObject; + /** + * Checks if the given feature is supported by the backend. + * + * @async + * @abstract + * @param {String} name - The feature's name. + * @return {Promise} A Promise that resolves with a bool that indicates whether the feature is supported or not. + */ + async hasFeatureAsync( /*name*/ ) { } - return geometry.isInstancedBufferGeometry ? geometry.instanceCount : ( object.count > 1 ? object.count : 1 ); + /** + * Checks if the given feature is supported by the backend. + * + * @abstract + * @param {String} name - The feature's name. + * @return {Boolean} Whether the feature is supported or not. + */ + hasFeature( /*name*/ ) {} - } + /** + * Returns the maximum anisotropy texture filtering value. + * + * @abstract + * @return {Number} The maximum anisotropy texture filtering value. + */ + getMaxAnisotropy() {} + /** + * Returns the drawing buffer size. + * + * @return {Vector2} The drawing buffer size. + */ getDrawingBufferSize() { - vector2 = vector2 || new Vector2(); + _vector2 = _vector2 || new Vector2(); - return this.renderer.getDrawingBufferSize( vector2 ); - - } - - getScissor() { - - vector4 = vector4 || new Vector4(); - - return this.renderer.getScissor( vector4 ); + return this.renderer.getDrawingBufferSize( _vector2 ); } + /** + * Defines the scissor test. + * + * @abstract + * @param {Boolean} boolean - Whether the scissor test should be enabled or not. + */ setScissorTest( /*boolean*/ ) { } + /** + * Returns the clear color and alpha into a single + * color object. + * + * @return {Color4} The clear color. + */ getClearColor() { const renderer = this.renderer; - color4 = color4 || new Color4(); + _color4 = _color4 || new Color4(); - renderer.getClearColor( color4 ); + renderer.getClearColor( _color4 ); - color4.getRGB( color4, this.renderer.currentColorSpace ); + _color4.getRGB( _color4, this.renderer.currentColorSpace ); - return color4; + return _color4; } + /** + * Returns the DOM element. If no DOM element exists, the backend + * creates a new one. + * + * @return {HTMLCanvasElement} The DOM element. + */ getDomElement() { let domElement = this.domElement; @@ -43733,14 +51072,25 @@ class Backend { } - // resource properties - + /** + * Sets a dictionary for the given object into the + * internal data structure. + * + * @param {Object} object - The object. + * @param {Object} value - The dictionary to set. + */ set( object, value ) { this.data.set( object, value ); } + /** + * Returns the dictionary for the given object. + * + * @param {Object} object - The object. + * @return {Object} The object's dictionary. + */ get( object ) { let map = this.data.get( object ); @@ -43756,24 +51106,49 @@ class Backend { } + /** + * Checks if the given object has a dictionary + * with data defined. + * + * @param {Object} object - The object. + * @return {Boolean} Whether a dictionary for the given object as been defined or not. + */ has( object ) { return this.data.has( object ); } + /** + * Deletes an object from the internal data structure. + * + * @param {Object} object - The object to delete. + */ delete( object ) { this.data.delete( object ); } + /** + * Frees internal resources. + * + * @abstract + */ dispose() { } } let _id$1 = 0; +/** + * This module is internally used in context of compute shaders. + * This type of shader is not natively supported in WebGL 2 and + * thus implemented via Transform Feedback. `DualAttributeData` + * manages the related data. + * + * @private + */ class DualAttributeData { constructor( attributeData, dualBuffer ) { @@ -43818,14 +51193,35 @@ class DualAttributeData { } +/** + * A WebGL 2 backend utility module for managing shader attributes. + * + * @private + */ class WebGLAttributeUtils { + /** + * Constructs a new utility object. + * + * @param {WebGLBackend} backend - The WebGL 2 backend. + */ constructor( backend ) { + /** + * A reference to the WebGL 2 backend. + * + * @type {WebGLBackend} + */ this.backend = backend; } + /** + * Creates the GPU buffer for the given buffer attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + * @param {GLenum } bufferType - A flag that indicates the buffer type and thus binding point target. + */ createAttribute( attribute, bufferType ) { const backend = this.backend; @@ -43923,6 +51319,11 @@ class WebGLAttributeUtils { } + /** + * Updates the GPU buffer of the given buffer attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ updateAttribute( attribute ) { const backend = this.backend; @@ -43962,6 +51363,11 @@ class WebGLAttributeUtils { } + /** + * Destroys the GPU buffer of the given buffer attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ destroyAttribute( attribute ) { const backend = this.backend; @@ -43981,6 +51387,14 @@ class WebGLAttributeUtils { } + /** + * This method performs a readback operation by moving buffer data from + * a storage buffer attribute from the GPU to the CPU. + * + * @async + * @param {StorageBufferAttribute} attribute - The storage buffer attribute. + * @return {Promise} A promise that resolves with the buffer data when the data are ready. + */ async getArrayBufferAsync( attribute ) { const backend = this.backend; @@ -44019,6 +51433,16 @@ class WebGLAttributeUtils { } + /** + * Creates a WebGL buffer with the given data. + * + * @private + * @param {WebGL2RenderingContext} gl - The rendering context. + * @param {GLenum } bufferType - A flag that indicates the buffer type and thus binding point target. + * @param {TypedArray} array - The array of the buffer attribute. + * @param {GLenum} usage - The usage. + * @return {WebGLBuffer} The WebGL buffer. + */ _createBuffer( gl, bufferType, array, usage ) { const bufferGPU = gl.createBuffer(); @@ -44035,14 +51459,43 @@ class WebGLAttributeUtils { let initialized$1 = false, equationToGL, factorToGL; +/** + * A WebGL 2 backend utility module for managing the WebGL state. + * + * The major goal of this module is to reduce the number of state changes + * by caching the WEbGL state with a series of variables. In this way, the + * renderer only executes state change commands when necessary which + * improves the overall performance. + * + * @private + */ class WebGLState { + /** + * Constructs a new utility object. + * + * @param {WebGLBackend} backend - The WebGL 2 backend. + */ constructor( backend ) { + /** + * A reference to the WebGL 2 backend. + * + * @type {WebGLBackend} + */ this.backend = backend; + /** + * A reference to the rendering context. + * + * @type {WebGL2RenderingContext} + */ this.gl = this.backend.gl; + // Below properties are intended to cache + // the WebGL state and are not explicitly + // documented for convenience reasons. + this.enabled = {}; this.currentFlipSided = null; this.currentCullFace = null; @@ -44079,7 +51532,7 @@ class WebGLState { if ( initialized$1 === false ) { - this._init( this.gl ); + this._init(); initialized$1 = true; @@ -44087,7 +51540,14 @@ class WebGLState { } - _init( gl ) { + /** + * Inits the state of the utility. + * + * @private + */ + _init() { + + const gl = this.gl; // Store only WebGL constants here. @@ -44113,6 +51573,14 @@ class WebGLState { } + /** + * Enables the given WebGL capability. + * + * This method caches the capability state so + * `gl.enable()` is only called when necessary. + * + * @param {GLenum} id - The capability to enable. + */ enable( id ) { const { enabled } = this; @@ -44126,6 +51594,14 @@ class WebGLState { } + /** + * Disables the given WebGL capability. + * + * This method caches the capability state so + * `gl.disable()` is only called when necessary. + * + * @param {GLenum} id - The capability to enable. + */ disable( id ) { const { enabled } = this; @@ -44139,6 +51615,15 @@ class WebGLState { } + /** + * Specifies whether polygons are front- or back-facing + * by setting the winding orientation. + * + * This method caches the state so `gl.frontFace()` is only + * called when necessary. + * + * @param {Boolean} flipSided - Whether triangles flipped their sides or not. + */ setFlipSided( flipSided ) { if ( this.currentFlipSided !== flipSided ) { @@ -44161,6 +51646,15 @@ class WebGLState { } + /** + * Specifies whether or not front- and/or back-facing + * polygons can be culled. + * + * This method caches the state so `gl.cullFace()` is only + * called when necessary. + * + * @param {Number} cullFace - Defines which polygons are candidates for culling. + */ setCullFace( cullFace ) { const { gl } = this; @@ -44197,6 +51691,14 @@ class WebGLState { } + /** + * Specifies the width of line primitives. + * + * This method caches the state so `gl.lineWidth()` is only + * called when necessary. + * + * @param {Number} width - The line width. + */ setLineWidth( width ) { const { currentLineWidth, gl } = this; @@ -44211,7 +51713,21 @@ class WebGLState { } - + /** + * Defines the blending. + * + * This method caches the state so `gl.blendEquation()`, `gl.blendEquationSeparate()`, + * `gl.blendFunc()` and `gl.blendFuncSeparate()` are only called when necessary. + * + * @param {Number} blending - The blending type. + * @param {Number} blendEquation - The blending equation. + * @param {Number} blendSrc - Only relevant for custom blending. The RGB source blending factor. + * @param {Number} blendDst - Only relevant for custom blending. The RGB destination blending factor. + * @param {Number} blendEquationAlpha - Only relevant for custom blending. The blending equation for alpha. + * @param {Number} blendSrcAlpha - Only relevant for custom blending. The alpha source blending factor. + * @param {Number} blendDstAlpha - Only relevant for custom blending. The alpha destination blending factor. + * @param {Boolean} premultipliedAlpha - Whether premultiplied alpha is enabled or not. + */ setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) { const { gl } = this; @@ -44348,6 +51864,15 @@ class WebGLState { } + /** + * Specifies whether colors can be written when rendering + * into a framebuffer or not. + * + * This method caches the state so `gl.colorMask()` is only + * called when necessary. + * + * @param {Boolean} colorMask - The color mask. + */ setColorMask( colorMask ) { if ( this.currentColorMask !== colorMask ) { @@ -44359,6 +51884,11 @@ class WebGLState { } + /** + * Specifies whether the depth test is enabled or not. + * + * @param {Boolean} depthTest - Whether the depth test is enabled or not. + */ setDepthTest( depthTest ) { const { gl } = this; @@ -44375,6 +51905,15 @@ class WebGLState { } + /** + * Specifies whether depth values can be written when rendering + * into a framebuffer or not. + * + * This method caches the state so `gl.depthMask()` is only + * called when necessary. + * + * @param {Boolean} depthMask - The depth mask. + */ setDepthMask( depthMask ) { if ( this.currentDepthMask !== depthMask ) { @@ -44386,6 +51925,14 @@ class WebGLState { } + /** + * Specifies the depth compare function. + * + * This method caches the state so `gl.depthFunc()` is only + * called when necessary. + * + * @param {Number} depthFunc - The depth compare function. + */ setDepthFunc( depthFunc ) { if ( this.currentDepthFunc !== depthFunc ) { @@ -44446,6 +51993,11 @@ class WebGLState { } + /** + * Specifies whether the stencil test is enabled or not. + * + * @param {Boolean} stencilTest - Whether the stencil test is enabled or not. + */ setStencilTest( stencilTest ) { const { gl } = this; @@ -44462,6 +52014,15 @@ class WebGLState { } + /** + * Specifies whether stencil values can be written when rendering + * into a framebuffer or not. + * + * This method caches the state so `gl.stencilMask()` is only + * called when necessary. + * + * @param {Boolean} stencilMask - The stencil mask. + */ setStencilMask( stencilMask ) { if ( this.currentStencilMask !== stencilMask ) { @@ -44473,6 +52034,16 @@ class WebGLState { } + /** + * Specifies whether the stencil test functions. + * + * This method caches the state so `gl.stencilFunc()` is only + * called when necessary. + * + * @param {Number} stencilFunc - The stencil compare function. + * @param {Number} stencilRef - The reference value for the stencil test. + * @param {Number} stencilMask - A bit-wise mask that is used to AND the reference value and the stored stencil value when the test is done. + */ setStencilFunc( stencilFunc, stencilRef, stencilMask ) { if ( this.currentStencilFunc !== stencilFunc || @@ -44489,6 +52060,17 @@ class WebGLState { } + /** + * Specifies whether the stencil test operation. + * + * This method caches the state so `gl.stencilOp()` is only + * called when necessary. + * + * @param {Number} stencilFail - The function to use when the stencil test fails. + * @param {Number} stencilZFail - The function to use when the stencil test passes, but the depth test fail. + * @param {Number} stencilZPass - The function to use when both the stencil test and the depth test pass, + * or when the stencil test passes and there is no depth buffer or depth testing is disabled. + */ setStencilOp( stencilFail, stencilZFail, stencilZPass ) { if ( this.currentStencilFail !== stencilFail || @@ -44505,6 +52087,13 @@ class WebGLState { } + /** + * Configures the WebGL state for the given material. + * + * @param {Material} material - The material to configure the state for. + * @param {Number} frontFaceCW - Whether the front faces are counter-clockwise or not. + * @param {Number} hardwareClippingPlanes - The number of hardware clipping planes. + */ setMaterial( material, frontFaceCW, hardwareClippingPlanes ) { const { gl } = this; @@ -44569,6 +52158,16 @@ class WebGLState { } + /** + * Specifies the polygon offset. + * + * This method caches the state so `gl.polygonOffset()` is only + * called when necessary. + * + * @param {Boolean} polygonOffset - Whether polygon offset is enabled or not. + * @param {Number} factor - The scale factor for the variable depth offset for each polygon. + * @param {Number} units - The multiplier by which an implementation-specific value is multiplied with to create a constant depth offset. + */ setPolygonOffset( polygonOffset, factor, units ) { const { gl } = this; @@ -44594,6 +52193,15 @@ class WebGLState { } + /** + * Defines the usage of the given WebGL program. + * + * This method caches the state so `gl.useProgram()` is only + * called when necessary. + * + * @param {WebGLProgram} program - The WebGL program to use. + * @return {Boolean} Whether a program change has been executed or not. + */ useProgram( program ) { if ( this.currentProgram !== program ) { @@ -44613,6 +52221,16 @@ class WebGLState { // framebuffer + /** + * Binds the given framebuffer. + * + * This method caches the state so `gl.bindFramebuffer()` is only + * called when necessary. + * + * @param {Number} target - The binding point (target). + * @param {WebGLFramebuffer} framebuffer - The WebGL framebuffer to bind. + * @return {Boolean} Whether a bind has been executed or not. + */ bindFramebuffer( target, framebuffer ) { const { gl, currentBoundFramebuffers } = this; @@ -44645,6 +52263,16 @@ class WebGLState { } + /** + * Defines draw buffers to which fragment colors are written into. + * Configures the MRT setup of custom framebuffers. + * + * This method caches the state so `gl.drawBuffers()` is only + * called when necessary. + * + * @param {RenderContext} renderContext - The render context. + * @param {WebGLFramebuffer} framebuffer - The WebGL framebuffer. + */ drawBuffers( renderContext, framebuffer ) { const { gl } = this; @@ -44705,6 +52333,14 @@ class WebGLState { // texture + /** + * Makes the given texture unit active. + * + * This method caches the state so `gl.activeTexture()` is only + * called when necessary. + * + * @param {Number} webglSlot - The texture unit to make active. + */ activeTexture( webglSlot ) { const { gl, currentTextureSlot, maxTextures } = this; @@ -44720,6 +52356,16 @@ class WebGLState { } + /** + * Binds the given WebGL texture to a target. + * + * This method caches the state so `gl.bindTexture()` is only + * called when necessary. + * + * @param {Number} webglType - The binding point (target). + * @param {WebGLTexture} webglTexture - The WebGL texture to bind. + * @param {Number} webglSlot - The texture. + */ bindTexture( webglType, webglTexture, webglSlot ) { const { gl, currentTextureSlot, currentBoundTextures, maxTextures } = this; @@ -44765,6 +52411,17 @@ class WebGLState { } + /** + * Binds a given WebGL buffer to a given binding point (target) at a given index. + * + * This method caches the state so `gl.bindBufferBase()` is only + * called when necessary. + * + * @param {Number} target - The target for the bind operation. + * @param {Number} index - The index of the target. + * @param {WebGLBuffer} buffer - The WebGL buffer. + * @return {Boolean} Whether a bind has been executed or not. + */ bindBufferBase( target, index, buffer ) { const { gl } = this; @@ -44785,6 +52442,12 @@ class WebGLState { } + /** + * Unbinds the current bound texture. + * + * This method caches the state so `gl.bindTexture()` is only + * called when necessary. + */ unbindTexture() { const { gl, currentTextureSlot, currentBoundTextures } = this; @@ -44804,17 +52467,53 @@ class WebGLState { } +/** + * A WebGL 2 backend utility module with common helpers. + * + * @private + */ class WebGLUtils { + /** + * Constructs a new utility object. + * + * @param {WebGLBackend} backend - The WebGL 2 backend. + */ constructor( backend ) { + /** + * A reference to the WebGL 2 backend. + * + * @type {WebGLBackend} + */ this.backend = backend; + /** + * A reference to the rendering context. + * + * @type {WebGL2RenderingContext} + */ this.gl = this.backend.gl; + + /** + * A reference to a backend module holding extension-related + * utility functions. + * + * @type {WebGLExtensions} + */ this.extensions = backend.extensions; } + /** + * Converts the given three.js constant into a WebGL constant. + * The method currently supports the conversion of texture formats + * and types. + * + * @param {Number} p - The three.js constant. + * @param {String} [colorSpace=NoColorSpace] - The color space. + * @return {Number} The corresponding WebGL constant. + */ convert( p, colorSpace = NoColorSpace ) { const { gl, extensions } = this; @@ -45025,6 +52724,13 @@ class WebGLUtils { } + /** + * This method can be used to synchronize the CPU with the GPU by waiting until + * ongoing GPU commands have been completed. + * + * @private + * @return {Promise} A promise that resolves when all ongoing GPU commands have been completed. + */ _clientWaitAsync() { const { gl } = this; @@ -45071,19 +52777,53 @@ class WebGLUtils { let initialized = false, wrappingToGL, filterToGL, compareToGL; +/** + * A WebGL 2 backend utility module for managing textures. + * + * @private + */ class WebGLTextureUtils { + /** + * Constructs a new utility object. + * + * @param {WebGLBackend} backend - The WebGL 2 backend. + */ constructor( backend ) { + /** + * A reference to the WebGL 2 backend. + * + * @type {WebGLBackend} + */ this.backend = backend; + /** + * A reference to the rendering context. + * + * @type {WebGL2RenderingContext} + */ this.gl = backend.gl; + + /** + * A reference to a backend module holding extension-related + * utility functions. + * + * @type {WebGLExtensions} + */ this.extensions = backend.extensions; + + /** + * A dictionary for managing default textures. The key + * is the binding point (target), the value the WEbGL texture object. + * + * @type {Object} + */ this.defaultTextures = {}; if ( initialized === false ) { - this._init( this.gl ); + this._init(); initialized = true; @@ -45091,7 +52831,14 @@ class WebGLTextureUtils { } - _init( gl ) { + /** + * Inits the state of the utility. + * + * @private + */ + _init() { + + const gl = this.gl; // Store only WebGL constants here. @@ -45124,20 +52871,12 @@ class WebGLTextureUtils { } - filterFallback( f ) { - - const { gl } = this; - - if ( f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter ) { - - return gl.NEAREST; - - } - - return gl.LINEAR; - - } - + /** + * Returns the native texture type for the given texture. + * + * @param {Texture} texture - The texture. + * @return {GLenum} The native texture type. + */ getGLTextureType( texture ) { const { gl } = this; @@ -45167,6 +52906,16 @@ class WebGLTextureUtils { } + /** + * Returns the native texture type for the given texture. + * + * @param {String?} internalFormatName - The internal format name. When `null`, the internal format is derived from the subsequent parameters. + * @param {GLenum} glFormat - The WebGL format. + * @param {GLenum} glType - The WebGL type. + * @param {String} colorSpace - The texture's color space. + * @param {Boolean} [forceLinearTransfer=false] - Whether to force a linear transfer or not. + * @return {GLenum} The internal format. + */ getInternalFormat( internalFormatName, glFormat, glType, colorSpace, forceLinearTransfer = false ) { const { gl, extensions } = this; @@ -45310,6 +53059,12 @@ class WebGLTextureUtils { } + /** + * Sets the texture parameters for the given texture. + * + * @param {GLenum} textureType - The texture type. + * @param {Texture} texture - The texture. + */ setTextureParameters( textureType, texture ) { const { gl, extensions, backend } = this; @@ -45363,6 +53118,12 @@ class WebGLTextureUtils { } + /** + * Creates a default texture for the given texture that can be used + * as a placeholder until the actual texture is ready for usage. + * + * @param {Texture} texture - The texture to create a default texture for. + */ createDefaultTexture( texture ) { const { gl, backend, defaultTextures } = this; @@ -45394,6 +53155,13 @@ class WebGLTextureUtils { } + /** + * Defines a texture on the GPU for the given texture object. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + * @return {undefined} + */ createTexture( texture, options ) { const { gl, backend } = this; @@ -45434,6 +53202,12 @@ class WebGLTextureUtils { } + /** + * Uploads texture buffer data to the GPU memory. + * + * @param {WebGLBuffer} buffer - The buffer data. + * @param {Texture} texture - The texture, + */ copyBufferToTexture( buffer, texture ) { const { gl, backend } = this; @@ -45469,6 +53243,12 @@ class WebGLTextureUtils { } + /** + * Uploads the updated texture data to the GPU. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ updateTexture( texture, options ) { const { gl } = this; @@ -45589,6 +53369,11 @@ class WebGLTextureUtils { } + /** + * Generates mipmaps for the given texture. + * + * @param {Texture} texture - The texture. + */ generateMipmaps( texture ) { const { gl, backend } = this; @@ -45599,6 +53384,11 @@ class WebGLTextureUtils { } + /** + * Deallocates the render buffers of the given render target. + * + * @param {RenderTarget} renderTarget - The render target. + */ deallocateRenderBuffers( renderTarget ) { const { gl, backend } = this; @@ -45659,6 +53449,11 @@ class WebGLTextureUtils { } + /** + * Destroys the GPU data for the given texture object. + * + * @param {Texture} texture - The texture. + */ destroyTexture( texture ) { const { gl, backend } = this; @@ -45671,6 +53466,15 @@ class WebGLTextureUtils { } + /** + * Copies data of the given source texture to the given destination texture. + * + * @param {Texture} srcTexture - The source texture. + * @param {Texture} dstTexture - The destination texture. + * @param {Vector4?} [srcRegion=null] - The region of the source texture to copy. + * @param {(Vector2|Vector3)?} [dstPosition=null] - The destination position of the copy. + * @param {Number} [level=0] - The mip level to copy. + */ copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { const { gl, backend } = this; @@ -45789,6 +53593,13 @@ class WebGLTextureUtils { } + /** + * Copies the current bound framebuffer to the given texture. + * + * @param {Texture} texture - The destination texture. + * @param {RenderContext} renderContext - The render context. + * @param {Vector4} rectangle - A four dimensional vector defining the origin and dimension of the copy. + */ copyFramebufferToTexture( texture, renderContext, rectangle ) { const { gl } = this; @@ -45800,7 +53611,7 @@ class WebGLTextureUtils { const requireDrawFrameBuffer = texture.isDepthTexture === true || ( renderContext.renderTarget && renderContext.renderTarget.samples > 0 ); - const srcHeight = renderContext.renderTarget ? renderContext.renderTarget.height : this.backend.gerDrawingBufferSize().y; + const srcHeight = renderContext.renderTarget ? renderContext.renderTarget.height : this.backend.getDrawingBufferSize().y; if ( requireDrawFrameBuffer ) { @@ -45876,7 +53687,12 @@ class WebGLTextureUtils { } - // Setup storage for internal depth/stencil buffers and bind to correct framebuffer + /** + * SetupS storage for internal depth/stencil buffers and bind to correct framebuffer. + * + * @param {WebGLRenderbuffer} renderbuffer - The render buffer. + * @param {RenderContext} renderContext - The render context. + */ setupRenderBufferStorage( renderbuffer, renderContext ) { const { gl } = this; @@ -45931,6 +53747,18 @@ class WebGLTextureUtils { } + /** + * Returns texture data as a typed array. + * + * @async + * @param {Texture} texture - The texture to copy. + * @param {Number} x - The x coordinate of the copy origin. + * @param {Number} y - The y coordinate of the copy origin. + * @param {Number} width - The width of the copy. + * @param {Number} height - The height of the copy. + * @param {Number} faceIndex - The face index. + * @return {Promise} A Promise that resolves with a typed array when the copy operation has finished. + */ async copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { const { backend, gl } = this; @@ -45972,6 +53800,13 @@ class WebGLTextureUtils { } + /** + * Returns the corresponding typed array type for the given WebGL data type. + * + * @private + * @param {GLenum} glType - The WebGL data type. + * @return {TypedArray.constructor} The typed array type. + */ _getTypedArrayType( glType ) { const { gl } = this; @@ -45991,6 +53826,14 @@ class WebGLTextureUtils { } + /** + * Returns the bytes-per-texel value for the given WebGL data type and texture format. + * + * @private + * @param {GLenum} glType - The WebGL data type. + * @param {GLenum} glFormat - The WebGL texture format. + * @return {Number} The bytes-per-texel. + */ _getBytesPerTexel( glType, glFormat ) { const { gl } = this; @@ -46016,19 +53859,58 @@ class WebGLTextureUtils { } +/** + * A WebGL 2 backend utility module for managing extensions. + * + * @private + */ class WebGLExtensions { + /** + * Constructs a new utility object. + * + * @param {WebGLBackend} backend - The WebGL 2 backend. + */ constructor( backend ) { + /** + * A reference to the WebGL 2 backend. + * + * @type {WebGLBackend} + */ this.backend = backend; + /** + * A reference to the rendering context. + * + * @type {WebGL2RenderingContext} + */ this.gl = this.backend.gl; + + /** + * A list with all the supported WebGL extensions. + * + * @type {Array} + */ this.availableExtensions = this.gl.getSupportedExtensions(); + /** + * A dictionary with requested WebGL extensions. + * The key is the name of the extension, the value + * the requested extension object. + * + * @type {Object} + */ this.extensions = {}; } + /** + * Returns the extension object for the given extension name. + * + * @param {String} name - The extension name. + * @return {Object} The extension object. + */ get( name ) { let extension = this.extensions[ name ]; @@ -46045,6 +53927,12 @@ class WebGLExtensions { } + /** + * Returns `true` if the requested extension is available. + * + * @param {String} name - The extension name. + * @return {Boolean} Whether the given extension is available or not. + */ has( name ) { return this.availableExtensions.includes( name ); @@ -46053,16 +53941,44 @@ class WebGLExtensions { } +/** + * A WebGL 2 backend utility module for managing the device's capabilities. + * + * @private + */ class WebGLCapabilities { + /** + * Constructs a new utility object. + * + * @param {WebGLBackend} backend - The WebGL 2 backend. + */ constructor( backend ) { + /** + * A reference to the WebGL 2 backend. + * + * @type {WebGLBackend} + */ this.backend = backend; + /** + * This value holds the cached max anisotropy value. + * + * @type {Number?} + * @default null + */ this.maxAnisotropy = null; } + /** + * Returns the maximum anisotropy texture filtering value. This value + * depends on the device and is reported by the `EXT_texture_filter_anisotropic` + * WebGL extension. + * + * @return {Number} The maximum anisotropy texture filtering value. + */ getMaxAnisotropy() { if ( this.maxAnisotropy !== null ) return this.maxAnisotropy; @@ -46240,18 +54156,184 @@ class WebGLBufferRenderer { } -// - +/** + * A backend implementation targeting WebGL 2. + * + * @private + * @augments Backend + */ class WebGLBackend extends Backend { + /** + * Constructs a new WebGPU backend. + * + * @param {Object} parameters - The configuration parameter. + * @param {Boolean} [parameters.logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not. + * @param {Boolean} [parameters.alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque. + * @param {Boolean} [parameters.depth=true] - Whether the default framebuffer should have a depth buffer or not. + * @param {Boolean} [parameters.stencil=false] - Whether the default framebuffer should have a stencil buffer or not. + * @param {Boolean} [parameters.antialias=false] - Whether MSAA as the default anti-aliasing should be enabled or not. + * @param {Number} [parameters.samples=0] - When `antialias` is `true`, `4` samples are used by default. Set this parameter to any other integer value than 0 to overwrite the default. + * @param {Boolean} [parameters.forceWebGL=false] - If set to `true`, the renderer uses a WebGL 2 backend no matter if WebGPU is supported or not. + * @param {WebGL2RenderingContext} [parameters.context=undefined] - A WebGL 2 rendering context. + */ constructor( parameters = {} ) { super( parameters ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isWebGLBackend = true; + /** + * A reference to a backend module holding shader attribute-related + * utility functions. + * + * @type {WebGLAttributeUtils?} + * @default null + */ + this.attributeUtils = null; + + /** + * A reference to a backend module holding extension-related + * utility functions. + * + * @type {WebGLExtensions?} + * @default null + */ + this.extensions = null; + + /** + * A reference to a backend module holding capability-related + * utility functions. + * + * @type {WebGLCapabilities?} + * @default null + */ + this.capabilities = null; + + /** + * A reference to a backend module holding texture-related + * utility functions. + * + * @type {WebGLTextureUtils?} + * @default null + */ + this.textureUtils = null; + + /** + * A reference to a backend module holding renderer-related + * utility functions. + * + * @type {WebGLBufferRenderer?} + * @default null + */ + this.bufferRenderer = null; + + /** + * A reference to the rendering context. + * + * @type {WebGL2RenderingContext?} + * @default null + */ + this.gl = null; + + /** + * A reference to a backend module holding state-related + * utility functions. + * + * @type {WebGLState?} + * @default null + */ + this.state = null; + + /** + * A reference to a backend module holding common + * utility functions. + * + * @type {WebGLUtils?} + * @default null + */ + this.utils = null; + + /** + * Dictionary for caching VAOs. + * + * @type {Object} + */ + this.vaoCache = {}; + + /** + * Dictionary for caching transform feedback objects. + * + * @type {Object} + */ + this.transformFeedbackCache = {}; + + /** + * Controls if `gl.RASTERIZER_DISCARD` should be enabled or not. + * Only relevant when using compute shaders. + * + * @type {Boolean} + * @default false + */ + this.discard = false; + + /** + * A reference to the `EXT_disjoint_timer_query_webgl2` extension. `null` if the + * device does not support the extension. + * + * @type {EXTDisjointTimerQueryWebGL2?} + * @default null + */ + this.disjoint = null; + + /** + * A reference to the `KHR_parallel_shader_compile` extension. `null` if the + * device does not support the extension. + * + * @type {KHRParallelShaderCompile?} + * @default null + */ + this.parallel = null; + + /** + * Whether to track timestamps with a Timestamp Query API or not. + * + * @type {Boolean} + * @default false + */ + this.trackTimestamp = ( parameters.trackTimestamp === true ); + + /** + * A reference to the current render context. + * + * @private + * @type {RenderContext} + * @default null + */ + this._currentContext = null; + + /** + * A unique collection of bindings. + * + * @private + * @type {WeakSet} + */ + this._knownBindings = new WeakSet(); + } + /** + * Initializes the backend so it is ready for usage. + * + * @param {Renderer} renderer - The renderer. + */ init( renderer ) { super.init( renderer ); @@ -46292,11 +54374,6 @@ class WebGLBackend extends Backend { this.state = new WebGLState( this ); this.utils = new WebGLUtils( this ); - this.vaoCache = {}; - this.transformFeedbackCache = {}; - this.discard = false; - this.trackTimestamp = ( parameters.trackTimestamp === true ); - this.extensions.get( 'EXT_color_buffer_float' ); this.extensions.get( 'WEBGL_clip_cull_distance' ); this.extensions.get( 'OES_texture_float_linear' ); @@ -46308,30 +54385,52 @@ class WebGLBackend extends Backend { this.disjoint = this.extensions.get( 'EXT_disjoint_timer_query_webgl2' ); this.parallel = this.extensions.get( 'KHR_parallel_shader_compile' ); - this._knownBindings = new WeakSet(); - - this._currentContext = null; - } + /** + * The coordinate system of the backend. + * + * @type {Number} + * @readonly + */ get coordinateSystem() { return WebGLCoordinateSystem; } + /** + * This method performs a readback operation by moving buffer data from + * a storage buffer attribute from the GPU to the CPU. + * + * @async + * @param {StorageBufferAttribute} attribute - The storage buffer attribute. + * @return {Promise} A promise that resolves with the buffer data when the data are ready. + */ async getArrayBufferAsync( attribute ) { return await this.attributeUtils.getArrayBufferAsync( attribute ); } + /** + * Can be used to synchronize CPU operations with GPU tasks. So when this method is called, + * the CPU waits for the GPU to complete its operation (e.g. a compute task). + * + * @async + * @return {Promise} A Promise that resolves when synchronization has been finished. + */ async waitForGPU() { await this.utils._clientWaitAsync(); } + /** + * Inits a time stamp query for the given render context. + * + * @param {RenderContext} renderContext - The render context. + */ initTimestampQuery( renderContext ) { if ( ! this.disjoint || ! this.trackTimestamp ) return; @@ -46366,6 +54465,11 @@ class WebGLBackend extends Backend { // timestamp utils + /** + * Prepares the timestamp buffer. + * + * @param {RenderContext} renderContext - The render context. + */ prepareTimestampBuffer( renderContext ) { if ( ! this.disjoint || ! this.trackTimestamp ) return; @@ -46392,6 +54496,14 @@ class WebGLBackend extends Backend { } + /** + * Resolves the time stamp for the given render context and type. + * + * @async + * @param {RenderContext} renderContext - The render context. + * @param {String} type - The render context. + * @return {Promise} A Promise that resolves when the time stamp has been computed. + */ async resolveTimestampAsync( renderContext, type = 'render' ) { if ( ! this.disjoint || ! this.trackTimestamp ) return; @@ -46421,12 +54533,23 @@ class WebGLBackend extends Backend { } + /** + * Returns the backend's rendering context. + * + * @return {WebGL2RenderingContext} The rendering context. + */ getContext() { return this.gl; } + /** + * This method is executed at the beginning of a render call and prepares + * the WebGL state for upcoming render calls + * + * @param {RenderContext} renderContext - The render context. + */ beginRender( renderContext ) { const { gl } = this; @@ -46482,6 +54605,12 @@ class WebGLBackend extends Backend { } + /** + * This method is executed at the end of a render call and finalizes work + * after draw calls. + * + * @param {RenderContext} renderContext - The render context. + */ finishRender( renderContext ) { const { gl, state } = this; @@ -46588,6 +54717,13 @@ class WebGLBackend extends Backend { } + /** + * This method processes the result of occlusion queries and writes it + * into render context data. + * + * @async + * @param {RenderContext} renderContext - The render context. + */ resolveOccludedAsync( renderContext ) { const renderContextData = this.get( renderContext ); @@ -46646,6 +54782,14 @@ class WebGLBackend extends Backend { } + /** + * Returns `true` if the given 3D object is fully occluded by other + * 3D objects in the scene. + * + * @param {RenderContext} renderContext - The render context. + * @param {Object3D} object - The 3D object to test. + * @return {Boolean} Whether the 3D object is fully occluded or not. + */ isOccluded( renderContext, object ) { const renderContextData = this.get( renderContext ); @@ -46654,6 +54798,11 @@ class WebGLBackend extends Backend { } + /** + * Updates the viewport with the values from the given render context. + * + * @param {RenderContext} renderContext - The render context. + */ updateViewport( renderContext ) { const gl = this.gl; @@ -46663,6 +54812,11 @@ class WebGLBackend extends Backend { } + /** + * Defines the scissor test. + * + * @param {Boolean} boolean - Whether the scissor test should be enabled or not. + */ setScissorTest( boolean ) { const gl = this.gl; @@ -46679,6 +54833,15 @@ class WebGLBackend extends Backend { } + /** + * Performs a clear operation. + * + * @param {Boolean} color - Whether the color buffer should be cleared or not. + * @param {Boolean} depth - Whether the depth buffer should be cleared or not. + * @param {Boolean} stencil - Whether the stencil buffer should be cleared or not. + * @param {Object?} [descriptor=null] - The render context of the current set render target. + * @param {Boolean} [setFrameBuffer=true] - TODO. + */ clear( color, depth, stencil, descriptor = null, setFrameBuffer = true ) { const { gl } = this; @@ -46769,6 +54932,12 @@ class WebGLBackend extends Backend { } + /** + * This method is executed at the beginning of a compute call and + * prepares the state for upcoming compute tasks. + * + * @param {Node|Array} computeGroup - The compute node(s). + */ beginCompute( computeGroup ) { const { state, gl } = this; @@ -46778,11 +54947,19 @@ class WebGLBackend extends Backend { } + /** + * Executes a compute command for the given compute node. + * + * @param {Node|Array} computeGroup - The group of compute nodes of a compute call. Can be a single compute node. + * @param {Node} computeNode - The compute node. + * @param {Array} bindings - The bindings. + * @param {ComputePipeline} pipeline - The compute pipeline. + */ compute( computeGroup, computeNode, bindings, pipeline ) { const { state, gl } = this; - if ( ! this.discard ) { + if ( this.discard === false ) { // required here to handle async behaviour of render.compute() gl.enable( gl.RASTERIZER_DISCARD ); @@ -46847,6 +55024,12 @@ class WebGLBackend extends Backend { } + /** + * This method is executed at the end of a compute call and + * finalizes work after compute tasks. + * + * @param {Node|Array} computeGroup - The compute node(s). + */ finishCompute( computeGroup ) { const gl = this.gl; @@ -46865,6 +55048,12 @@ class WebGLBackend extends Backend { } + /** + * Executes a draw command for the given render object. + * + * @param {RenderObject} renderObject - The render object to draw. + * @param {Info} info - Holds a series of statistical information about the GPU memory and the rendering process. + */ draw( renderObject/*, info*/ ) { const { object, pipeline, material, context, hardwareClippingPlanes } = renderObject; @@ -47027,12 +55216,24 @@ class WebGLBackend extends Backend { } + /** + * Explain why always null is returned. + * + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether the render pipeline requires an update or not. + */ needsRenderUpdate( /*renderObject*/ ) { return false; } + /** + * Explain why no cache key is computed. + * + * @param {RenderObject} renderObject - The render object. + * @return {String} The cache key. + */ getRenderCacheKey( /*renderObject*/ ) { return ''; @@ -47041,53 +55242,109 @@ class WebGLBackend extends Backend { // textures + /** + * Creates a default texture for the given texture that can be used + * as a placeholder until the actual texture is ready for usage. + * + * @param {Texture} texture - The texture to create a default texture for. + */ createDefaultTexture( texture ) { this.textureUtils.createDefaultTexture( texture ); } + /** + * Defines a texture on the GPU for the given texture object. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ createTexture( texture, options ) { this.textureUtils.createTexture( texture, options ); } + /** + * Uploads the updated texture data to the GPU. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ updateTexture( texture, options ) { this.textureUtils.updateTexture( texture, options ); } + /** + * Generates mipmaps for the given texture. + * + * @param {Texture} texture - The texture. + */ generateMipmaps( texture ) { this.textureUtils.generateMipmaps( texture ); } - + /** + * Destroys the GPU data for the given texture object. + * + * @param {Texture} texture - The texture. + */ destroyTexture( texture ) { this.textureUtils.destroyTexture( texture ); } - copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { + /** + * Returns texture data as a typed array. + * + * @async + * @param {Texture} texture - The texture to copy. + * @param {Number} x - The x coordinate of the copy origin. + * @param {Number} y - The y coordinate of the copy origin. + * @param {Number} width - The width of the copy. + * @param {Number} height - The height of the copy. + * @param {Number} faceIndex - The face index. + * @return {Promise} A Promise that resolves with a typed array when the copy operation has finished. + */ + async copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { return this.textureUtils.copyTextureToBuffer( texture, x, y, width, height, faceIndex ); } + /** + * This method does nothing since WebGL 2 has no concept of samplers. + * + * @param {Texture} texture - The texture to create the sampler for. + */ createSampler( /*texture*/ ) { //console.warn( 'Abstract class.' ); } - destroySampler() {} + /** + * This method does nothing since WebGL 2 has no concept of samplers. + * + * @param {Texture} texture - The texture to destroy the sampler for. + */ + destroySampler( /*texture*/ ) {} // node builder + /** + * Returns a node builder for the given render object. + * + * @param {RenderObject} object - The render object. + * @param {Renderer} renderer - The renderer. + * @return {GLSLNodeBuilder} The node builder. + */ createNodeBuilder( object, renderer ) { return new GLSLNodeBuilder( object, renderer ); @@ -47096,6 +55353,11 @@ class WebGLBackend extends Backend { // program + /** + * Creates a shader program from the given programmable stage. + * + * @param {ProgrammableStage} program - The programmable stage. + */ createProgram( program ) { const gl = this.gl; @@ -47112,12 +55374,23 @@ class WebGLBackend extends Backend { } - destroyProgram( /*program*/ ) { + /** + * Destroys the shader program of the given programmable stage. + * + * @param {ProgrammableStage} program - The programmable stage. + */ + destroyProgram( program ) { - console.warn( 'Abstract class.' ); + this.delete( program ); } + /** + * Creates a render pipeline for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @param {Array} promises - An array of compilation promises which are used in `compileAsync()`. + */ createRenderPipeline( renderObject, promises ) { const gl = this.gl; @@ -47176,6 +55449,14 @@ class WebGLBackend extends Backend { } + /** + * Formats the source code of error messages. + * + * @private + * @param {String} string - The code. + * @param {Number} errorLine - The error line. + * @return {String} The formatted code. + */ _handleSource( string, errorLine ) { const lines = string.split( '\n' ); @@ -47195,6 +55476,15 @@ class WebGLBackend extends Backend { } + /** + * Gets the shader compilation errors from the info log. + * + * @private + * @param {WebGL2RenderingContext} gl - The rendering context. + * @param {WebGLShader} shader - The WebGL shader object. + * @param {String} type - The shader type. + * @return {String} The shader errors. + */ _getShaderErrors( gl, shader, type ) { const status = gl.getShaderParameter( shader, gl.COMPILE_STATUS ); @@ -47216,6 +55506,14 @@ class WebGLBackend extends Backend { } + /** + * Logs shader compilation errors. + * + * @private + * @param {WebGLProgram} programGPU - The WebGL program. + * @param {WebGLShader} glFragmentShader - The fragment shader as a native WebGL shader object. + * @param {WebGLShader} glVertexShader - The vertex shader as a native WebGL shader object. + */ _logProgramError( programGPU, glFragmentShader, glVertexShader ) { if ( this.renderer.debug.checkShaderErrors ) { @@ -47258,6 +55556,13 @@ class WebGLBackend extends Backend { } + /** + * Completes the shader program setup for the given render object. + * + * @private + * @param {RenderObject} renderObject - The render object. + * @param {RenderPipeline} pipeline - The render pipeline. + */ _completeCompile( renderObject, pipeline ) { const { state, gl } = this; @@ -47286,6 +55591,12 @@ class WebGLBackend extends Backend { } + /** + * Creates a compute pipeline for the given compute node. + * + * @param {ComputePipeline} computePipeline - The compute pipeline. + * @param {Array} bindings - The bindings. + */ createComputePipeline( computePipeline, bindings ) { const { state, gl } = this; @@ -47380,7 +55691,15 @@ class WebGLBackend extends Backend { } - createBindings( bindGroup, bindings ) { + /** + * Creates bindings from the given bind group definition. + * + * @param {BindGroup} bindGroup - The bind group. + * @param {Array} bindings - Array of bind groups. + * @param {Number} cacheIndex - The cache index. + * @param {Number} version - The version. + */ + createBindings( bindGroup, bindings /*, cacheIndex, version*/ ) { if ( this._knownBindings.has( bindings ) === false ) { @@ -47411,7 +55730,15 @@ class WebGLBackend extends Backend { } - updateBindings( bindGroup /*, bindings*/ ) { + /** + * Updates the given bind group definition. + * + * @param {BindGroup} bindGroup - The bind group. + * @param {Array} bindings - Array of bind groups. + * @param {Number} cacheIndex - The cache index. + * @param {Number} version - The version. + */ + updateBindings( bindGroup /*, bindings, cacheIndex, version*/ ) { const { gl } = this; @@ -47451,6 +55778,11 @@ class WebGLBackend extends Backend { } + /** + * Updates a buffer binding. + * + * @param {Buffer} binding - The buffer binding to update. + */ updateBinding( binding ) { const gl = this.gl; @@ -47470,6 +55802,11 @@ class WebGLBackend extends Backend { // attributes + /** + * Creates the GPU buffer of an indexed shader attribute. + * + * @param {BufferAttribute} attribute - The indexed buffer attribute. + */ createIndexAttribute( attribute ) { const gl = this.gl; @@ -47478,6 +55815,11 @@ class WebGLBackend extends Backend { } + /** + * Creates the GPU buffer of a shader attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ createAttribute( attribute ) { if ( this.has( attribute ) ) return; @@ -47488,6 +55830,11 @@ class WebGLBackend extends Backend { } + /** + * Creates the GPU buffer of a storage attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ createStorageAttribute( attribute ) { if ( this.has( attribute ) ) return; @@ -47498,24 +55845,34 @@ class WebGLBackend extends Backend { } + /** + * Updates the GPU buffer of a shader attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute to update. + */ updateAttribute( attribute ) { this.attributeUtils.updateAttribute( attribute ); } + /** + * Destroys the GPU buffer of a shader attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute to destroy. + */ destroyAttribute( attribute ) { this.attributeUtils.destroyAttribute( attribute ); } - updateSize() { - - //console.warn( 'Abstract class.' ); - - } - + /** + * Checks if the given feature is supported by the backend. + * + * @param {String} name - The feature's name. + * @return {Boolean} Whether the feature is supported or not. + */ hasFeature( name ) { const keysMatching = Object.keys( GLFeatureName ).filter( key => GLFeatureName[ key ] === name ); @@ -47532,24 +55889,51 @@ class WebGLBackend extends Backend { } + /** + * Returns the maximum anisotropy texture filtering value. + * + * @return {Number} The maximum anisotropy texture filtering value. + */ getMaxAnisotropy() { return this.capabilities.getMaxAnisotropy(); } - copyTextureToTexture( srcTexture, dstTexture, srcRegion, dstPosition, level ) { + /** + * Copies data of the given source texture to the given destination texture. + * + * @param {Texture} srcTexture - The source texture. + * @param {Texture} dstTexture - The destination texture. + * @param {Vector4?} [srcRegion=null] - The region of the source texture to copy. + * @param {(Vector2|Vector3)?} [dstPosition=null] - The destination position of the copy. + * @param {Number} [level=0] - The mip level to copy. + */ + copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { this.textureUtils.copyTextureToTexture( srcTexture, dstTexture, srcRegion, dstPosition, level ); } + /** + * Copies the current bound framebuffer to the given texture. + * + * @param {Texture} texture - The destination texture. + * @param {RenderContext} renderContext - The render context. + * @param {Vector4} rectangle - A four dimensional vector defining the origin and dimension of the copy. + */ copyFramebufferToTexture( texture, renderContext, rectangle ) { this.textureUtils.copyFramebufferToTexture( texture, renderContext, rectangle ); } + /** + * Configures the active framebuffer from the given render context. + * + * @private + * @param {RenderContext} descriptor - The render context. + */ _setFramebuffer( descriptor ) { const { gl, state } = this; @@ -47563,6 +55947,8 @@ class WebGLBackend extends Backend { const { samples, depthBuffer, stencilBuffer } = renderTarget; const isCube = renderTarget.isWebGLCubeRenderTarget === true; + const isRenderTarget3D = renderTarget.isRenderTarget3D === true; + const isRenderTargetArray = renderTarget.isRenderTargetArray === true; let msaaFb = renderTargetContextData.msaaFrameBuffer; let depthRenderbuffer = renderTargetContextData.depthRenderbuffer; @@ -47616,7 +56002,19 @@ class WebGLBackend extends Backend { const attachment = gl.COLOR_ATTACHMENT0 + i; - gl.framebufferTexture2D( gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureData.textureGPU, 0 ); + if ( isRenderTarget3D || isRenderTargetArray ) { + + const layer = this.renderer._activeCubeFace; + + gl.framebufferTextureLayer( gl.FRAMEBUFFER, attachment, textureData.textureGPU, 0, layer ); + + } else { + + gl.framebufferTexture2D( gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureData.textureGPU, 0 ); + + } + + } @@ -47708,10 +56106,17 @@ class WebGLBackend extends Backend { } - + /** + * Computes the VAO key for the given index and attributes. + * + * @private + * @param {BufferAttribute?} index - The index. `null` for non-indexed geometries. + * @param {Array} attributes - An array of buffer attributes. + * @return {String} The VAO key. + */ _getVaoKey( index, attributes ) { - let key = []; + let key = ''; if ( index !== null ) { @@ -47733,6 +56138,14 @@ class WebGLBackend extends Backend { } + /** + * Creates a VAO from the index and attributes. + * + * @private + * @param {BufferAttribute?} index - The index. `null` for non-indexed geometries. + * @param {Array} attributes - An array of buffer attributes. + * @return {Object} The VAO data. + */ _createVao( index, attributes ) { const { gl } = this; @@ -47810,6 +56223,13 @@ class WebGLBackend extends Backend { } + /** + * Creates a transform feedback from the given transform buffers. + * + * @private + * @param {Array} transformBuffers - The transform buffers. + * @return {WebGLTransformFeedback} The transform feedback. + */ _getTransformFeedback( transformBuffers ) { let key = ''; @@ -47850,7 +56270,13 @@ class WebGLBackend extends Backend { } - + /** + * Setups the given bindings. + * + * @private + * @param {Array} bindings - The bindings. + * @param {WebGLProgram} programGPU - The WebGL program. + */ _setupBindings( bindings, programGPU ) { const gl = this.gl; @@ -47880,6 +56306,12 @@ class WebGLBackend extends Backend { } + /** + * Binds the given uniforms. + * + * @private + * @param {Array} bindings - The bindings. + */ _bindUniforms( bindings ) { const { gl, state } = this; @@ -47908,6 +56340,9 @@ class WebGLBackend extends Backend { } + /** + * Frees internal resources. + */ dispose() { this.renderer.domElement.removeEventListener( 'webglcontextlost', this._onContextLost ); @@ -48211,32 +56646,90 @@ const GPUFeatureName = { Subgroups: 'subgroups' }; +/** + * Represents a sampler binding type. + * + * @private + * @augments Binding + */ class Sampler extends Binding { + /** + * Constructs a new sampler. + * + * @param {String} name - The samplers's name. + * @param {Texture?} texture - The texture this binding is referring to. + */ constructor( name, texture ) { super( name ); + /** + * The texture the sampler is referring to. + * + * @type {Texture?} + */ this.texture = texture; + + /** + * The binding's version. + * + * @type {Number} + */ this.version = texture ? texture.version : 0; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isSampler = true; } } +/** + * A special form of sampler binding type. + * It's texture value is managed by a node object. + * + * @private + * @augments Sampler + */ class NodeSampler extends Sampler { + /** + * Constructs a new node-based sampler. + * + * @param {String} name - The samplers's name. + * @param {TextureNode} textureNode - The texture node. + * @param {UniformGroupNode} groupNode - The uniform group node. + */ constructor( name, textureNode, groupNode ) { super( name, textureNode ? textureNode.value : null ); + /** + * The texture node. + * + * @type {TextureNode} + */ this.textureNode = textureNode; + + /** + * The uniform group node. + * + * @type {UniformGroupNode} + */ this.groupNode = groupNode; } + /** + * Updates the texture value of this sampler. + */ update() { this.texture = this.textureNode.value; @@ -48245,14 +56738,38 @@ class NodeSampler extends Sampler { } +/** + * Represents a storage buffer binding type. + * + * @private + * @augments Buffer + */ class StorageBuffer extends Buffer { + /** + * Constructs a new uniform buffer. + * + * @param {String} name - The buffer's name. + * @param {BufferAttribute} attribute - The buffer attribute. + */ constructor( name, attribute ) { super( name, attribute ? attribute.array : null ); + /** + * This flag can be used for type testing. + * + * @type {BufferAttribute} + */ this.attribute = attribute; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isStorageBuffer = true; } @@ -48261,18 +56778,53 @@ class StorageBuffer extends Buffer { let _id = 0; +/** + * A special form of storage buffer binding type. + * It's buffer value is managed by a node object. + * + * @private + * @augments StorageBuffer + */ class NodeStorageBuffer extends StorageBuffer { + /** + * Constructs a new node-based storage buffer. + * + * @param {StorageBufferNode} nodeUniform - The storage buffer node. + * @param {UniformGroupNode} groupNode - The uniform group node. + */ constructor( nodeUniform, groupNode ) { super( 'StorageBuffer_' + _id ++, nodeUniform ? nodeUniform.value : null ); + /** + * The node uniform. + * + * @type {StorageBufferNode} + */ this.nodeUniform = nodeUniform; + + /** + * The access type. + * + * @type {String} + */ this.access = nodeUniform ? nodeUniform.access : NodeAccess.READ_WRITE; + + /** + * The uniform group node. + * + * @type {UniformGroupNode} + */ this.groupNode = groupNode; } + /** + * The storage buffer. + * + * @type {BufferAttribute} + */ get buffer() { return this.nodeUniform.value; @@ -48281,12 +56833,27 @@ class NodeStorageBuffer extends StorageBuffer { } +/** + * A WebGPU backend utility module used by {@link WebGPUTextureUtils}. + * + * @private + */ class WebGPUTexturePassUtils extends DataMap { + /** + * Constructs a new utility object. + * + * @param {GPUDevice} device - The WebGPU device. + */ constructor( device ) { super(); + /** + * The WebGPU device. + * + * @type {GPUDevice} + */ this.device = device; const mipmapVertexSource = ` @@ -48351,23 +56918,62 @@ fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { } `; + + /** + * The mipmap GPU sampler. + * + * @type {GPUSampler} + */ this.mipmapSampler = device.createSampler( { minFilter: GPUFilterMode.Linear } ); + + /** + * The flipY GPU sampler. + * + * @type {GPUSampler} + */ this.flipYSampler = device.createSampler( { minFilter: GPUFilterMode.Nearest } ); //@TODO?: Consider using textureLoad() - // We'll need a new pipeline for every texture format used. + /** + * A cache for GPU render pipelines used for copy/transfer passes. + * Every texture format requires a unique pipeline. + * + * @type {Object} + */ this.transferPipelines = {}; + + /** + * A cache for GPU render pipelines used for flipY passes. + * Every texture format requires a unique pipeline. + * + * @type {Object} + */ this.flipYPipelines = {}; + /** + * The mipmap vertex shader module. + * + * @type {GPUShaderModule} + */ this.mipmapVertexShaderModule = device.createShaderModule( { label: 'mipmapVertex', code: mipmapVertexSource } ); + /** + * The mipmap fragment shader module. + * + * @type {GPUShaderModule} + */ this.mipmapFragmentShaderModule = device.createShaderModule( { label: 'mipmapFragment', code: mipmapFragmentSource } ); + /** + * The flipY fragment shader module. + * + * @type {GPUShaderModule} + */ this.flipYFragmentShaderModule = device.createShaderModule( { label: 'flipYFragment', code: flipYFragmentSource @@ -48375,6 +56981,13 @@ fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { } + /** + * Returns a render pipeline for the internal copy render pass. The pass + * requires a unique render pipeline for each texture format. + * + * @param {String} format - The GPU texture format + * @return {GPURenderPipeline} The GPU render pipeline. + */ getTransferPipeline( format ) { let pipeline = this.transferPipelines[ format ]; @@ -48407,6 +57020,13 @@ fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { } + /** + * Returns a render pipeline for the flipY render pass. The pass + * requires a unique render pipeline for each texture format. + * + * @param {String} format - The GPU texture format + * @return {GPURenderPipeline} The GPU render pipeline. + */ getFlipYPipeline( format ) { let pipeline = this.flipYPipelines[ format ]; @@ -48439,6 +57059,13 @@ fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { } + /** + * Flip the contents of the given GPU texture along its vertical axis. + * + * @param {GPUTexture} textureGPU - The GPU texture object. + * @param {Object} textureGPUDescriptor - The texture descriptor. + * @param {Number} [baseArrayLayer=0] - The index of the first array layer accessible to the texture view. + */ flipY( textureGPU, textureGPUDescriptor, baseArrayLayer = 0 ) { const format = textureGPUDescriptor.format; @@ -48509,6 +57136,13 @@ fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { } + /** + * Generates mipmaps for the given GPU texture. + * + * @param {GPUTexture} textureGPU - The GPU texture object. + * @param {Object} textureGPUDescriptor - The texture descriptor. + * @param {Number} [baseArrayLayer=0] - The index of the first array layer accessible to the texture view. + */ generateMipmaps( textureGPU, textureGPUDescriptor, baseArrayLayer = 0 ) { const textureData = this.get( textureGPU ); @@ -48534,6 +57168,15 @@ fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { } + /** + * Since multiple copy render passes are required to generate mipmaps, the passes + * are managed as render bundles to improve performance. + * + * @param {GPUTexture} textureGPU - The GPU texture object. + * @param {Object} textureGPUDescriptor - The texture descriptor. + * @param {Number} baseArrayLayer - The index of the first array layer accessible to the texture view. + * @return {Array} An array of render bundles. + */ _mipmapCreateBundles( textureGPU, textureGPUDescriptor, baseArrayLayer ) { const pipeline = this.getTransferPipeline( textureGPUDescriptor.format ); @@ -48599,6 +57242,12 @@ fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { } + /** + * Executes the render bundles. + * + * @param {GPUCommandEncoder} commandEncoder - The GPU command encoder. + * @param {Array} passes - An array of render bundles. + */ _mipmapRunBundles( commandEncoder, passes ) { const levels = passes.length; @@ -48632,25 +57281,82 @@ const _compareToWebGPU = { const _flipMap = [ 0, 1, 3, 2, 4, 5 ]; +/** + * A WebGPU backend utility module for managing textures. + * + * @private + */ class WebGPUTextureUtils { + /** + * Constructs a new utility object. + * + * @param {WebGPUBackend} backend - The WebGPU backend. + */ constructor( backend ) { + /** + * A reference to the WebGPU backend. + * + * @type {WebGPUBackend} + */ this.backend = backend; + /** + * A reference to the pass utils. + * + * @type {WebGPUTexturePassUtils?} + * @default null + */ this._passUtils = null; + /** + * A dictionary for managing default textures. The key + * is the texture format, the value the texture object. + * + * @type {Object} + */ this.defaultTexture = {}; + + /** + * A dictionary for managing default cube textures. The key + * is the texture format, the value the texture object. + * + * @type {Object} + */ this.defaultCubeTexture = {}; + + /** + * A default video frame. + * + * @type {VideoFrame?} + * @default null + */ this.defaultVideoFrame = null; + /** + * Represents the color attachment of the default framebuffer. + * + * @type {GPUTexture?} + * @default null + */ this.colorBuffer = null; + /** + * Represents the depth attachment of the default framebuffer. + * + * @type {DepthTexture} + */ this.depthTexture = new DepthTexture(); this.depthTexture.name = 'depthBuffer'; } + /** + * Creates a GPU sampler for the given texture. + * + * @param {Texture} texture - The texture to create the sampler for. + */ createSampler( texture ) { const backend = this.backend; @@ -48686,6 +57392,12 @@ class WebGPUTextureUtils { } + /** + * Creates a default texture for the given texture that can be used + * as a placeholder until the actual texture is ready for usage. + * + * @param {Texture} texture - The texture to create a default texture for. + */ createDefaultTexture( texture ) { let textureGPU; @@ -48710,6 +57422,13 @@ class WebGPUTextureUtils { } + /** + * Defines a texture on the GPU for the given texture object. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + * @return {undefined} + */ createTexture( texture, options = {} ) { const backend = this.backend; @@ -48821,6 +57540,11 @@ class WebGPUTextureUtils { } + /** + * Destroys the GPU data for the given texture object. + * + * @param {Texture} texture - The texture. + */ destroyTexture( texture ) { const backend = this.backend; @@ -48834,6 +57558,11 @@ class WebGPUTextureUtils { } + /** + * Destroys the GPU sampler for the given texture. + * + * @param {Texture} texture - The texture to destroy the sampler for. + */ destroySampler( texture ) { const backend = this.backend; @@ -48843,6 +57572,11 @@ class WebGPUTextureUtils { } + /** + * Generates mipmaps for the given texture. + * + * @param {Texture} texture - The texture. + */ generateMipmaps( texture ) { const textureData = this.backend.get( texture ); @@ -48869,6 +57603,12 @@ class WebGPUTextureUtils { } + /** + * Returns the color buffer representing the color + * attachment of the default framebuffer. + * + * @return {GPUTexture} The color buffer. + */ getColorBuffer() { if ( this.colorBuffer ) this.colorBuffer.destroy(); @@ -48892,6 +57632,14 @@ class WebGPUTextureUtils { } + /** + * Returns the depth buffer representing the depth + * attachment of the default framebuffer. + * + * @param {Boolean} [depth=true] - Whether depth is enabled or not. + * @param {Boolean} [stencil=false] - Whether stencil is enabled or not. + * @return {GPUTexture} The depth buffer. + */ getDepthBuffer( depth = true, stencil = false ) { const backend = this.backend; @@ -48938,6 +57686,12 @@ class WebGPUTextureUtils { } + /** + * Uploads the updated texture data to the GPU. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ updateTexture( texture, options ) { const textureData = this.backend.get( texture ); @@ -48989,6 +57743,18 @@ class WebGPUTextureUtils { } + /** + * Returns texture data as a typed array. + * + * @async + * @param {Texture} texture - The texture to copy. + * @param {Number} x - The x coordinate of the copy origin. + * @param {Number} y - The y coordinate of the copy origin. + * @param {Number} width - The width of the copy. + * @param {Number} height - The height of the copy. + * @param {Number} faceIndex - The face index. + * @return {Promise} A Promise that resolves with a typed array when the copy operation has finished. + */ async copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { const device = this.backend.device; @@ -49038,6 +57804,13 @@ class WebGPUTextureUtils { } + /** + * Returns `true` if the given texture is an environment map. + * + * @private + * @param {Texture} texture - The texture. + * @return {Boolean} Whether the given texture is an environment map or not. + */ _isEnvironmentTexture( texture ) { const mapping = texture.mapping; @@ -49046,6 +57819,13 @@ class WebGPUTextureUtils { } + /** + * Returns the default GPU texture for the given format. + * + * @private + * @param {String} format - The GPU format. + * @return {GPUTexture} The GPU texture. + */ _getDefaultTextureGPU( format ) { let defaultTexture = this.defaultTexture[ format ]; @@ -49066,6 +57846,13 @@ class WebGPUTextureUtils { } + /** + * Returns the default GPU cube texture for the given format. + * + * @private + * @param {String} format - The GPU format. + * @return {GPUTexture} The GPU texture. + */ _getDefaultCubeTextureGPU( format ) { let defaultCubeTexture = this.defaultTexture[ format ]; @@ -49086,6 +57873,12 @@ class WebGPUTextureUtils { } + /** + * Returns the default video frame used as default data in context of video textures. + * + * @private + * @return {VideoFrame} The video frame. + */ _getDefaultVideoFrame() { let defaultVideoFrame = this.defaultVideoFrame; @@ -49107,6 +57900,15 @@ class WebGPUTextureUtils { } + /** + * Uploads cube texture image data to the GPU memory. + * + * @private + * @param {Array} images - The cube image data. + * @param {GPUTexture} textureGPU - The GPU texture. + * @param {Object} textureDescriptorGPU - The GPU texture descriptor. + * @param {Boolean} flipY - Whether to flip texture data along their vertical axis or not. + */ _copyCubeMapToTexture( images, textureGPU, textureDescriptorGPU, flipY ) { for ( let i = 0; i < 6; i ++ ) { @@ -49129,13 +57931,24 @@ class WebGPUTextureUtils { } + /** + * Uploads texture image data to the GPU memory. + * + * @private + * @param {HTMLImageElement|ImageBitmap|HTMLCanvasElement} image - The image data. + * @param {GPUTexture} textureGPU - The GPU texture. + * @param {Object} textureDescriptorGPU - The GPU texture descriptor. + * @param {Number} originDepth - The origin depth. + * @param {Boolean} flipY - Whether to flip texture data along their vertical axis or not. + */ _copyImageToTexture( image, textureGPU, textureDescriptorGPU, originDepth, flipY ) { const device = this.backend.device; device.queue.copyExternalImageToTexture( { - source: image + source: image, + flipY: flipY }, { texture: textureGPU, mipLevel: 0, @@ -49147,14 +57960,14 @@ class WebGPUTextureUtils { } ); - if ( flipY === true ) { - - this._flipY( textureGPU, textureDescriptorGPU, originDepth ); - - } - } + /** + * Returns the pass utils singleton. + * + * @private + * @return {WebGPUTexturePassUtils} The utils instance. + */ _getPassUtils() { let passUtils = this._passUtils; @@ -49169,18 +57982,45 @@ class WebGPUTextureUtils { } + /** + * Generates mipmaps for the given GPU texture. + * + * @private + * @param {GPUTexture} textureGPU - The GPU texture object. + * @param {Object} textureDescriptorGPU - The texture descriptor. + * @param {Number} [baseArrayLayer=0] - The index of the first array layer accessible to the texture view. + */ _generateMipmaps( textureGPU, textureDescriptorGPU, baseArrayLayer = 0 ) { this._getPassUtils().generateMipmaps( textureGPU, textureDescriptorGPU, baseArrayLayer ); } + /** + * Flip the contents of the given GPU texture along its vertical axis. + * + * @private + * @param {GPUTexture} textureGPU - The GPU texture object. + * @param {Object} textureDescriptorGPU - The texture descriptor. + * @param {Number} [originDepth=0] - The origin depth. + */ _flipY( textureGPU, textureDescriptorGPU, originDepth = 0 ) { this._getPassUtils().flipY( textureGPU, textureDescriptorGPU, originDepth ); } + /** + * Uploads texture buffer data to the GPU memory. + * + * @private + * @param {Object} image - An object defining the image buffer data. + * @param {GPUTexture} textureGPU - The GPU texture. + * @param {Object} textureDescriptorGPU - The GPU texture descriptor. + * @param {Number} originDepth - The origin depth. + * @param {Boolean} flipY - Whether to flip texture data along their vertical axis or not. + * @param {Number} [depth=0] - TODO. + */ _copyBufferToTexture( image, textureGPU, textureDescriptorGPU, originDepth, flipY, depth = 0 ) { // @TODO: Consider to use GPUCommandEncoder.copyBufferToTexture() @@ -49218,6 +58058,14 @@ class WebGPUTextureUtils { } + /** + * Uploads compressed texture data to the GPU memory. + * + * @private + * @param {Array} mipmaps - An array with mipmap data. + * @param {GPUTexture} textureGPU - The GPU texture. + * @param {Object} textureDescriptorGPU - The GPU texture descriptor. + */ _copyCompressedBufferToTexture( mipmaps, textureGPU, textureDescriptorGPU ) { // @TODO: Consider to use GPUCommandEncoder.copyBufferToTexture() @@ -49265,10 +58113,16 @@ class WebGPUTextureUtils { } + /** + * This method is only relevant for compressed texture formats. It returns a block + * data descriptor for the given GPU compressed texture format. + * + * @private + * @param {String} format - The GPU compressed texture format. + * @return {Object} The block data descriptor. + */ _getBlockData( format ) { - // this method is only relevant for compressed texture formats - if ( format === GPUTextureFormat.BC1RGBAUnorm || format === GPUTextureFormat.BC1RGBAUnormSRGB ) return { byteLength: 8, width: 4, height: 4 }; // DXT1 if ( format === GPUTextureFormat.BC2RGBAUnorm || format === GPUTextureFormat.BC2RGBAUnormSRGB ) return { byteLength: 16, width: 4, height: 4 }; // DXT3 if ( format === GPUTextureFormat.BC3RGBAUnorm || format === GPUTextureFormat.BC3RGBAUnormSRGB ) return { byteLength: 16, width: 4, height: 4 }; // DXT5 @@ -49302,6 +58156,13 @@ class WebGPUTextureUtils { } + /** + * Converts the three.js uv wrapping constants to GPU address mode constants. + * + * @private + * @param {Number} value - The three.js constant defining a uv wrapping mode. + * @return {String} The GPU address mode. + */ _convertAddressMode( value ) { let addressMode = GPUAddressMode.ClampToEdge; @@ -49320,6 +58181,13 @@ class WebGPUTextureUtils { } + /** + * Converts the three.js filter constants to GPU filter constants. + * + * @private + * @param {Number} value - The three.js constant defining a filter mode. + * @return {String} The GPU filter mode. + */ _convertFilterMode( value ) { let filterMode = GPUFilterMode.Linear; @@ -49334,6 +58202,13 @@ class WebGPUTextureUtils { } + /** + * Returns the bytes-per-texel value for the given GPU texture format. + * + * @private + * @param {String} format - The GPU texture format. + * @return {Number} The bytes-per-texel. + */ _getBytesPerTexel( format ) { // 8-bit formats @@ -49390,6 +58265,13 @@ class WebGPUTextureUtils { } + /** + * Returns the corresponding typed array type for the given GPU texture format. + * + * @private + * @param {String} format - The GPU texture format. + * @return {TypedArray.constructor} The typed array type. + */ _getTypedArrayType( format ) { if ( format === GPUTextureFormat.R8Uint ) return Uint8Array; @@ -49440,6 +58322,13 @@ class WebGPUTextureUtils { } + /** + * Returns the GPU dimensions for the given texture. + * + * @private + * @param {Texture} texture - The texture. + * @return {String} The GPU dimension. + */ _getDimension( texture ) { let dimension; @@ -49460,6 +58349,14 @@ class WebGPUTextureUtils { } +/** + * Returns the GPU format for the given texture. + * + * @param {Texture} texture - The texture. + * @param {GPUDevice?} [device=null] - The GPU device which is used for feature detection. + * It is not necessary to apply the device for most formats. + * @return {String} The GPU format. + */ function getFormat( texture, device = null ) { const format = texture.format; @@ -50162,30 +59059,83 @@ if ( ( typeof navigator !== 'undefined' && /Firefox|Deno/g.test( navigator.userA } -// - +/** + * A node builder targeting WGSL. + * + * This module generates WGSL shader code from node materials and also + * generates the respective bindings and vertex buffer definitions. These + * data are later used by the renderer to create render and compute pipelines + * for render objects. + * + * @augments NodeBuilder + */ class WGSLNodeBuilder extends NodeBuilder { + /** + * Constructs a new WGSL node builder renderer. + * + * @param {Object3D} object - The 3D object. + * @param {Renderer} renderer - The renderer. + */ constructor( object, renderer ) { super( object, renderer, new WGSLNodeParser() ); + /** + * A dictionary that holds for each shader stage ('vertex', 'fragment', 'compute') + * another dictionary which manages UBOs per group ('render','frame','object'). + * + * @type {Object>} + */ this.uniformGroups = {}; + /** + * A dictionary that holds for each shader stage a Map of builtins. + * + * @type {Object>} + */ this.builtins = {}; + /** + * A dictionary that holds for each shader stage a Set of directives. + * + * @type {Object>} + */ this.directives = {}; + /** + * A map for managing scope arrays. Only relevant for when using + * {@link module:WorkgroupInfoNode} in context of compute shaders. + * + * @type {Map} + */ this.scopedArrays = new Map(); } + /** + * Checks if the given texture requires a manual conversion to the working color space. + * + * @param {Texture} texture - The texture to check. + * @return {Boolean} Whether the given texture requires a conversion to working color space or not. + */ needsToWorkingColorSpace( texture ) { return texture.isVideoTexture === true && texture.colorSpace !== NoColorSpace; } + /** + * Generates the WGSL snippet for sampled textures. + * + * @private + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ _generateTextureSample( texture, textureProperty, uvSnippet, depthSnippet, shaderStage = this.shaderStage ) { if ( shaderStage === 'fragment' ) { @@ -50212,6 +59162,15 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet when sampling video textures. + * + * @private + * @param {String} textureProperty - The name of the video texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ _generateVideoSample( textureProperty, uvSnippet, shaderStage = this.shaderStage ) { if ( shaderStage === 'fragment' ) { @@ -50226,6 +59185,18 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet when sampling textures with explicit mip level. + * + * @private + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String} levelSnippet - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ _generateTextureSampleLevel( texture, textureProperty, uvSnippet, levelSnippet, depthSnippet, shaderStage = this.shaderStage ) { if ( ( shaderStage === 'fragment' || shaderStage === 'compute' ) && this.isUnfilterable( texture ) === false ) { @@ -50244,9 +59215,15 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates a wrap function used in context of textures. + * + * @param {Texture} texture - The texture to generate the function for. + * @return {String} The name of the generated function. + */ generateWrapFunction( texture ) { - const functionName = `tsl_coord_${ wrapNames[ texture.wrapS ] }S_${ wrapNames[ texture.wrapT ] }T`; + const functionName = `tsl_coord_${ wrapNames[ texture.wrapS ] }S_${ wrapNames[ texture.wrapT ] }_${texture.isData3DTexture ? '3d' : '2d'}T`; let nodeCode = wgslCodeCache[ functionName ]; @@ -50254,7 +59231,9 @@ class WGSLNodeBuilder extends NodeBuilder { const includes = []; - let code = `fn ${ functionName }( coord : vec2f ) -> vec2f {\n\n\treturn vec2f(\n`; + // For 3D textures, use vec3f; for texture arrays, keep vec2f since array index is separate + const coordType = texture.isData3DTexture ? 'vec3f' : 'vec2f'; + let code = `fn ${functionName}( coord : ${coordType} ) -> ${coordType} {\n\n\treturn ${coordType}(\n`; const addWrapSnippet = ( wrap, axis ) => { @@ -50292,6 +59271,13 @@ class WGSLNodeBuilder extends NodeBuilder { addWrapSnippet( texture.wrapT, 'y' ); + if ( texture.isData3DTexture ) { + + code += ',\n'; + addWrapSnippet( texture.wrapR, 'z' ); + + } + code += '\n\t);\n\n}\n'; wgslCodeCache[ functionName ] = nodeCode = new CodeNode( code, includes ); @@ -50304,6 +59290,16 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates a WGSL variable that holds the texture dimension of the given texture. + * It also returns information about the the number of layers (elements) of an arrayed + * texture as well as the cube face count of cube textures. + * + * @param {Texture} texture - The texture to generate the function for. + * @param {String} textureProperty - The name of the video texture uniform in the shader. + * @param {String} levelSnippet - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @return {String} The name of the dimension variable. + */ generateTextureDimension( texture, textureProperty, levelSnippet ) { const textureData = this.getDataFromNode( texture, this.shaderStage, this.globalCache ); @@ -50315,29 +59311,72 @@ class WGSLNodeBuilder extends NodeBuilder { if ( textureData.dimensionsSnippet[ levelSnippet ] === undefined ) { let textureDimensionsParams; + let dimensionType; const { primarySamples } = this.renderer.backend.utils.getTextureSampleData( texture ); + const isMultisampled = primarySamples > 1; + + if ( texture.isData3DTexture ) { + + dimensionType = 'vec3'; + + } else { + + // Regular 2D textures, depth textures, etc. + dimensionType = 'vec2'; + + } - if ( primarySamples > 1 ) { + // Build parameters string based on texture type and multisampling + if ( isMultisampled || texture.isVideoTexture || texture.isStorageTexture ) { textureDimensionsParams = textureProperty; } else { - textureDimensionsParams = `${ textureProperty }, u32( ${ levelSnippet } )`; + textureDimensionsParams = `${textureProperty}${levelSnippet ? `, u32( ${ levelSnippet } )` : ''}`; } - textureDimensionNode = new VarNode( new ExpressionNode( `textureDimensions( ${ textureDimensionsParams } )`, 'uvec2' ) ); + textureDimensionNode = new VarNode( new ExpressionNode( `textureDimensions( ${ textureDimensionsParams } )`, dimensionType ) ); textureData.dimensionsSnippet[ levelSnippet ] = textureDimensionNode; + if ( texture.isDataArrayTexture || texture.isData3DTexture ) { + + textureData.arrayLayerCount = new VarNode( + new ExpressionNode( + `textureNumLayers(${textureProperty})`, + 'u32' + ) + ); + + } + + // For cube textures, we know it's always 6 faces + if ( texture.isTextureCube ) { + + textureData.cubeFaceCount = new VarNode( + new ExpressionNode( '6u', 'u32' ) + ); + + } + } return textureDimensionNode.build( this ); } + /** + * Generates the WGSL snippet for a manual filtered texture. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String} levelSnippet - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @return {String} The WGSL snippet. + */ generateFilteredTexture( texture, textureProperty, uvSnippet, levelSnippet = '0u' ) { this._include( 'biquadraticTexture' ); @@ -50349,17 +59388,39 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet for a texture lookup with explicit level-of-detail. + * Since it's a lookup, no sampling or filtering is applied. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [levelSnippet='0u'] - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @return {String} The WGSL snippet. + */ generateTextureLod( texture, textureProperty, uvSnippet, depthSnippet, levelSnippet = '0u' ) { const wrapFunction = this.generateWrapFunction( texture ); const textureDimension = this.generateTextureDimension( texture, textureProperty, levelSnippet ); - const coordSnippet = `vec2u( ${ wrapFunction }( ${ uvSnippet } ) * vec2f( ${ textureDimension } ) )`; + const vecType = texture.isData3DTexture ? 'vec3' : 'vec2'; + const coordSnippet = `${vecType}(${wrapFunction}(${uvSnippet}) * ${vecType}(${textureDimension}))`; return this.generateTextureLoad( texture, textureProperty, coordSnippet, depthSnippet, levelSnippet ); } + /** + * Generates the WGSL snippet that reads a single texel from a texture without sampling or filtering. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvIndexSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [levelSnippet='0u'] - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @return {String} The WGSL snippet. + */ generateTextureLoad( texture, textureProperty, uvIndexSnippet, depthSnippet, levelSnippet = '0u' ) { if ( texture.isVideoTexture === true || texture.isStorageTexture === true ) { @@ -50378,18 +59439,39 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet that writes a single texel to a texture. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvIndexSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String} valueSnippet - A WGSL snippet that represent the new texel value. + * @return {String} The WGSL snippet. + */ generateTextureStore( texture, textureProperty, uvIndexSnippet, valueSnippet ) { return `textureStore( ${ textureProperty }, ${ uvIndexSnippet }, ${ valueSnippet } )`; } + /** + * Returns `true` if the sampled values of the given texture should be compared against a reference value. + * + * @param {Texture} texture - The texture. + * @return {Boolean} Whether the sampled values of the given texture should be compared against a reference value or not. + */ isSampleCompare( texture ) { return texture.isDepthTexture === true && texture.compareFunction !== null; } + /** + * Returns `true` if the given texture is unfilterable. + * + * @param {Texture} texture - The texture. + * @return {Boolean} Whether the given texture is unfilterable or not. + */ isUnfilterable( texture ) { return this.getComponentTypeFromTexture( texture ) !== 'float' || @@ -50399,6 +59481,16 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet for sampling/loading the given texture. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ generateTexture( texture, textureProperty, uvSnippet, depthSnippet, shaderStage = this.shaderStage ) { let snippet = null; @@ -50421,6 +59513,17 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet for sampling/loading the given texture using explicit gradients. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {Array} gradSnippet - An array holding both gradient WGSL snippets. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ generateTextureGrad( texture, textureProperty, uvSnippet, gradSnippet, depthSnippet, shaderStage = this.shaderStage ) { if ( shaderStage === 'fragment' ) { @@ -50436,6 +59539,18 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet for sampling a depth texture and comparing the sampled depth values + * against a reference value. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String} compareSnippet - A WGSL snippet that represents the reference value. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ generateTextureCompare( texture, textureProperty, uvSnippet, compareSnippet, depthSnippet, shaderStage = this.shaderStage ) { if ( shaderStage === 'fragment' ) { @@ -50450,6 +59565,17 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet when sampling textures with explicit mip level. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String} levelSnippet - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ generateTextureLevel( texture, textureProperty, uvSnippet, levelSnippet, depthSnippet, shaderStage = this.shaderStage ) { let snippet = null; @@ -50468,6 +59594,17 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet when sampling textures with a bias to the mip level. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String} biasSnippet - A WGSL snippet that represents the bias to apply to the mip level before sampling. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ generateTextureBias( texture, textureProperty, uvSnippet, biasSnippet, depthSnippet, shaderStage = this.shaderStage ) { if ( shaderStage === 'fragment' ) { @@ -50482,6 +59619,13 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Returns a WGSL snippet that represents the property name of the given node. + * + * @param {Node} node - The node. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The property name. + */ getPropertyName( node, shaderStage = this.shaderStage ) { if ( node.isNodeVarying === true && node.needsInterpolation === true ) { @@ -50517,18 +59661,36 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Returns the output struct name. + * + * @return {String} The name of the output struct. + */ getOutputStructName() { return 'output'; } + /** + * Returns uniforms group count for the given shader stage. + * + * @private + * @param {String} shaderStage - The shader stage. + * @return {Number} The uniforms group count for the given shader stage. + */ _getUniformGroupCount( shaderStage ) { return Object.keys( this.uniforms[ shaderStage ] ).length; } + /** + * Returns the native shader operator name for a given generic name. + * + * @param {String} op - The operator name to resolve. + * @return {String} The resolved operator name. + */ getFunctionOperator( op ) { const fnOp = wgslFnOpLib[ op ]; @@ -50545,6 +59707,13 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Returns the node access for the given node and shader stage. + * + * @param {StorageTextureNode|StorageBufferNode} node - The storage node. + * @param {String} shaderStage - The shader stage. + * @return {String} The node access. + */ getNodeAccess( node, shaderStage ) { if ( shaderStage !== 'compute' ) @@ -50554,12 +59723,32 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Returns A WGSL snippet representing the storage access. + * + * @param {StorageTextureNode|StorageBufferNode} node - The storage node. + * @param {String} shaderStage - The shader stage. + * @return {String} The WGSL snippet representing the storage access. + */ getStorageAccess( node, shaderStage ) { return accessNames[ this.getNodeAccess( node, shaderStage ) ]; } + /** + * This method is one of the more important ones since it's responsible + * for generating a matching binding instance for the given uniform node. + * + * These bindings are later used in the renderer to create bind groups + * and layouts. + * + * @param {UniformNode} node - The uniform node. + * @param {String} type - The node data type. + * @param {String} shaderStage - The shader stage. + * @param {String?} [name=null] - An optional uniform name. + * @return {NodeUniform} The node uniform object. + */ getUniformFromNode( node, type, shaderStage, name = null ) { const uniformNode = super.getUniformFromNode( node, type, shaderStage, name ); @@ -50656,6 +59845,17 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * This method should be used whenever builtins are required in nodes. + * The internal builtins data structure will make sure builtins are + * defined in the WGSL source. + * + * @param {String} name - The builtin name. + * @param {String} property - The property name. + * @param {String} type - The node data type. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The property name. + */ getBuiltin( name, property, type, shaderStage = this.shaderStage ) { const map = this.builtins[ shaderStage ] || ( this.builtins[ shaderStage ] = new Map() ); @@ -50674,12 +59874,24 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Returns `true` if the given builtin is defined in the given shader stage. + * + * @param {String} name - The builtin name. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} Whether the given builtin is defined in the given shader stage or not. + */ hasBuiltin( name, shaderStage = this.shaderStage ) { return ( this.builtins[ shaderStage ] !== undefined && this.builtins[ shaderStage ].has( name ) ); } + /** + * Returns the vertex index builtin. + * + * @return {String} The vertex index. + */ getVertexIndex() { if ( this.shaderStage === 'vertex' ) { @@ -50692,6 +59904,12 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Builds the given shader node. + * + * @param {ShaderNodeInternal} shaderNode - The shader node. + * @return {String} The WGSL function code. + */ buildFunctionCode( shaderNode ) { const layout = shaderNode.layout; @@ -50726,6 +59944,11 @@ ${ flowData.code } } + /** + * Returns the instance index builtin. + * + * @return {String} The instance index. + */ getInstanceIndex() { if ( this.shaderStage === 'vertex' ) { @@ -50738,12 +59961,22 @@ ${ flowData.code } } + /** + * Returns the invocation local index builtin. + * + * @return {String} The invocation local index. + */ getInvocationLocalIndex() { return this.getBuiltin( 'local_invocation_index', 'invocationLocalIndex', 'u32', 'attribute' ); } + /** + * Returns the subgroup size builtin. + * + * @return {String} The subgroup size. + */ getSubgroupSize() { this.enableSubGroups(); @@ -50752,6 +59985,11 @@ ${ flowData.code } } + /** + * Returns the invocation subgroup index builtin. + * + * @return {String} The invocation subgroup index. + */ getInvocationSubgroupIndex() { this.enableSubGroups(); @@ -50760,6 +59998,11 @@ ${ flowData.code } } + /** + * Returns the subgroup index builtin. + * + * @return {String} The subgroup index. + */ getSubgroupIndex() { this.enableSubGroups(); @@ -50768,42 +60011,78 @@ ${ flowData.code } } + /** + * Overwritten as a NOP since this method is intended for the WebGL 2 backend. + * + * @return {null} Null. + */ getDrawIndex() { return null; } + /** + * Returns the front facing builtin. + * + * @return {String} The front facing builtin. + */ getFrontFacing() { return this.getBuiltin( 'front_facing', 'isFront', 'bool' ); } + /** + * Returns the frag coord builtin. + * + * @return {String} The frag coord builtin. + */ getFragCoord() { return this.getBuiltin( 'position', 'fragCoord', 'vec4' ) + '.xy'; } + /** + * Returns the frag depth builtin. + * + * @return {String} The frag depth builtin. + */ getFragDepth() { return 'output.' + this.getBuiltin( 'frag_depth', 'depth', 'f32', 'output' ); } + /** + * Returns the clip distances builtin. + * + * @return {String} The clip distances builtin. + */ getClipDistance() { return 'varyings.hw_clip_distances'; } + /** + * Whether to flip texture data along its vertical axis or not. + * + * @return {Boolean} Returns always `false` in context of WGSL. + */ isFlipY() { return false; } + /** + * Enables the given directive for the given shader stage. + * + * @param {String} name - The directive name. + * @param {String} [shaderStage=this.shaderStage] - The shader stage to enable the directive for. + */ enableDirective( name, shaderStage = this.shaderStage ) { const stage = this.directives[ shaderStage ] || ( this.directives[ shaderStage ] = new Set() ); @@ -50811,6 +60090,12 @@ ${ flowData.code } } + /** + * Returns the directives of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} A WGSL snippet that enables the directives of the given stage. + */ getDirectives( shaderStage ) { const snippets = []; @@ -50830,36 +60115,56 @@ ${ flowData.code } } + /** + * Enables the 'subgroups' directive. + */ enableSubGroups() { this.enableDirective( 'subgroups' ); } + /** + * Enables the 'subgroups-f16' directive. + */ enableSubgroupsF16() { this.enableDirective( 'subgroups-f16' ); } + /** + * Enables the 'clip_distances' directive. + */ enableClipDistances() { this.enableDirective( 'clip_distances' ); } + /** + * Enables the 'f16' directive. + */ enableShaderF16() { this.enableDirective( 'f16' ); } + /** + * Enables the 'dual_source_blending' directive. + */ enableDualSourceBlending() { this.enableDirective( 'dual_source_blending' ); } + /** + * Enables hardware clipping. + * + * @param {String} planeCount - The clipping plane count. + */ enableHardwareClipping( planeCount ) { this.enableClipDistances(); @@ -50867,6 +60172,12 @@ ${ flowData.code } } + /** + * Returns the builtins of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} A WGSL snippet that represents the builtins of the given stage. + */ getBuiltins( shaderStage ) { const snippets = []; @@ -50886,6 +60197,17 @@ ${ flowData.code } } + /** + * This method should be used when a new scoped buffer is used in context of + * compute shaders. It adds the array to the internal data structure which is + * later used to generate the respective WGSL. + * + * @param {String} name - The array name. + * @param {String} scope - The scope. + * @param {String} bufferType - The buffer type. + * @param {String} bufferCount - The buffer count. + * @return {String} The array name. + */ getScopedArray( name, scope, bufferType, bufferCount ) { if ( this.scopedArrays.has( name ) === false ) { @@ -50903,6 +60225,13 @@ ${ flowData.code } } + /** + * Returns the scoped arrays of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String|undefined} The WGSL snippet that defines the scoped arrays. + * Returns `undefined` when used in the vertex or fragment stage. + */ getScopedArrays( shaderStage ) { if ( shaderStage !== 'compute' ) { @@ -50925,6 +60254,12 @@ ${ flowData.code } } + /** + * Returns the shader attributes of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The WGSL snippet that defines the shader attributes. + */ getAttributes( shaderStage ) { const snippets = []; @@ -50969,6 +60304,12 @@ ${ flowData.code } } + /** + * Returns the members of the given struct type node as a WGSL string. + * + * @param {StructTypeNode} struct - The struct type node. + * @return {String} The WGSL snippet that defines the struct members. + */ getStructMembers( struct ) { const snippets = []; @@ -50989,6 +60330,12 @@ ${ flowData.code } } + /** + * Returns the structs of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The WGSL snippet that defines the structs. + */ getStructs( shaderStage ) { const snippets = []; @@ -51014,12 +60361,25 @@ ${ flowData.code } } + /** + * Returns a WGSL string representing a variable. + * + * @param {String} type - The variable's type. + * @param {String} name - The variable's name. + * @return {String} The WGSL snippet that defines a variable. + */ getVar( type, name ) { return `var ${ name } : ${ this.getType( type ) }`; } + /** + * Returns the variables of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The WGSL snippet that defines the variables. + */ getVars( shaderStage ) { const snippets = []; @@ -51039,6 +60399,12 @@ ${ flowData.code } } + /** + * Returns the varyings of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The WGSL snippet that defines the varyings. + */ getVaryings( shaderStage ) { const snippets = []; @@ -51091,6 +60457,12 @@ ${ flowData.code } } + /** + * Returns the uniforms of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The WGSL snippet that defines the uniforms. + */ getUniforms( shaderStage ) { const uniforms = this.uniforms[ shaderStage ]; @@ -51218,6 +60590,9 @@ ${ flowData.code } } + /** + * Controls the code build of the shader stages. + */ buildCode() { const shadersData = this.material !== null ? { fragment: {}, vertex: {} } : { compute: {} }; @@ -51318,6 +60693,13 @@ ${ flowData.code } } + /** + * Returns the native shader method name for a given generic name. + * + * @param {String} method - The method name to resolve. + * @param {String} [output=null] - An optional output. + * @return {String} The resolved WGSL method name. + */ getMethod( method, output = null ) { let wgslMethod; @@ -51338,12 +60720,24 @@ ${ flowData.code } } + /** + * Returns the WGSL type of the given node data type. + * + * @param {String} type - The node data type. + * @return {String} The WGSL type. + */ getType( type ) { return wgslTypeLib[ type ] || type; } + /** + * Whether the requested feature is available or not. + * + * @param {String} name - The requested feature. + * @return {Boolean} Whether the requested feature is supported or not. + */ isAvailable( name ) { let result = supports[ name ]; @@ -51368,6 +60762,13 @@ ${ flowData.code } } + /** + * Returns the native shader method name for a given generic name. + * + * @private + * @param {String} method - The method name to resolve. + * @return {String} The resolved WGSL method name. + */ _getWGSLMethod( method ) { if ( wgslPolyfill[ method ] !== undefined ) { @@ -51380,6 +60781,14 @@ ${ flowData.code } } + /** + * Includes the given method name into the current + * function node. + * + * @private + * @param {String} name - The method name to include. + * @return {CodeNode} The respective code node. + */ _include( name ) { const codeNode = wgslPolyfill[ name ]; @@ -51395,6 +60804,13 @@ ${ flowData.code } } + /** + * Returns a WGSL vertex shader based on the given shader data. + * + * @private + * @param {Object} shaderData - The shader data. + * @return {String} The vertex shader. + */ _getWGSLVertexCode( shaderData ) { return `${ this.getSignature() } @@ -51427,6 +60843,13 @@ fn main( ${shaderData.attributes} ) -> VaryingsStruct { } + /** + * Returns a WGSL fragment shader based on the given shader data. + * + * @private + * @param {Object} shaderData - The shader data. + * @return {String} The vertex shader. + */ _getWGSLFragmentCode( shaderData ) { return `${ this.getSignature() } @@ -51456,6 +60879,14 @@ fn main( ${shaderData.varyings} ) -> ${shaderData.returnType} { } + /** + * Returns a WGSL compute shader based on the given shader data. + * + * @private + * @param {Object} shaderData - The shader data. + * @param {String} workgroupSize - The workgroup size. + * @return {String} The vertex shader. + */ _getWGSLComputeCode( shaderData, workgroupSize ) { return `${ this.getSignature() } @@ -51491,6 +60922,14 @@ fn main( ${shaderData.attributes} ) { } + /** + * Returns a WGSL struct based on the given name and variables. + * + * @private + * @param {String} name - The struct name. + * @param {String} vars - The struct variables. + * @return {String} The WGSL snippet representing a struct. + */ _getWGSLStruct( name, vars ) { return ` @@ -51500,6 +60939,17 @@ ${vars} } + /** + * Returns a WGSL struct binding. + * + * @private + * @param {String} name - The struct name. + * @param {String} vars - The struct variables. + * @param {String} access - The access. + * @param {Number} [binding=0] - The binding index. + * @param {Number} [group=0] - The group index. + * @return {String} The WGSL snippet representing a struct binding. + */ _getWGSLStructBinding( name, vars, access, binding = 0, group = 0 ) { const structName = name + 'Struct'; @@ -51513,14 +60963,35 @@ var<${access}> ${name} : ${structName};`; } +/** + * A WebGPU backend utility module with common helpers. + * + * @private + */ class WebGPUUtils { + /** + * Constructs a new utility object. + * + * @param {WebGPUBackend} backend - The WebGPU backend. + */ constructor( backend ) { + /** + * A reference to the WebGPU backend. + * + * @type {WebGPUBackend} + */ this.backend = backend; } + /** + * Returns the depth/stencil GPU format for the given render context. + * + * @param {RenderContext} renderContext - The render context. + * @return {String} The depth/stencil GPU texture format. + */ getCurrentDepthStencilFormat( renderContext ) { let format; @@ -51543,12 +61014,24 @@ class WebGPUUtils { } + /** + * Returns the GPU format for the given texture. + * + * @param {Texture} texture - The texture. + * @return {String} The GPU texture format. + */ getTextureFormatGPU( texture ) { return this.backend.get( texture ).format; } + /** + * Returns an object that defines the multi-sampling state of the given texture. + * + * @param {Texture} texture - The texture. + * @return {Object} The multi-sampling state. + */ getTextureSampleData( texture ) { let samples; @@ -51579,6 +61062,12 @@ class WebGPUUtils { } + /** + * Returns the default color attachment's GPU format of the current render context. + * + * @param {RenderContext} renderContext - The render context. + * @return {String} The GPU texture format of the default color attachment. + */ getCurrentColorFormat( renderContext ) { let format; @@ -51597,6 +61086,12 @@ class WebGPUUtils { } + /** + * Returns the output color space of the current render context. + * + * @param {RenderContext} renderContext - The render context. + * @return {String} The output color space. + */ getCurrentColorSpace( renderContext ) { if ( renderContext.textures !== null ) { @@ -51609,6 +61104,13 @@ class WebGPUUtils { } + /** + * Returns GPU primitive topology for the given object and material. + * + * @param {Object3D} object - The 3D object. + * @param {Material} material - The material. + * @return {String} The GPU primitive topology. + */ getPrimitiveTopology( object, material ) { if ( object.isPoints ) return GPUPrimitiveTopology.PointList; @@ -51618,6 +61120,14 @@ class WebGPUUtils { } + /** + * Returns a modified sample count from the given sample count value. + * + * That is required since WebGPU does not support arbitrary sample counts. + * + * @param {Number} sampleCount - The input sample count. + * @return {Number} The (potentially updated) output sample count. + */ getSampleCount( sampleCount ) { let count = 1; @@ -51639,6 +61149,12 @@ class WebGPUUtils { } + /** + * Returns the sample count of the given render context. + * + * @param {RenderContext} renderContext - The render context. + * @return {Number} The sample count. + */ getSampleCountRenderContext( renderContext ) { if ( renderContext.textures !== null ) { @@ -51651,6 +61167,14 @@ class WebGPUUtils { } + /** + * Returns the preferred canvas format. + * + * There is a separate method for this so it's possible to + * honor edge cases for specific devices. + * + * @return {String} The GPU texture format of the canvas. + */ getPreferredCanvasFormat() { // TODO: Remove this check when Quest 34.5 is out @@ -51692,14 +61216,35 @@ const typeArraysToVertexFormatPrefixForItemSize1 = new Map( [ [ Float32Array, 'float32' ] ] ); +/** + * A WebGPU backend utility module for managing shader attributes. + * + * @private + */ class WebGPUAttributeUtils { + /** + * Constructs a new utility object. + * + * @param {WebGPUBackend} backend - The WebGPU backend. + */ constructor( backend ) { + /** + * A reference to the WebGPU backend. + * + * @type {WebGPUBackend} + */ this.backend = backend; } + /** + * Creates the GPU buffer for the given buffer attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + * @param {GPUBufferUsage} usage - A flag that indicates how the buffer may be used after its creation. + */ createAttribute( attribute, usage ) { const bufferAttribute = this._getBufferAttribute( attribute ); @@ -51716,16 +61261,27 @@ class WebGPUAttributeUtils { let array = bufferAttribute.array; // patch for INT16 and UINT16 - if ( attribute.normalized === false && ( array.constructor === Int16Array || array.constructor === Uint16Array ) ) { + if ( attribute.normalized === false ) { - const tempArray = new Uint32Array( array.length ); - for ( let i = 0; i < array.length; i ++ ) { + if ( array.constructor === Int16Array ) { - tempArray[ i ] = array[ i ]; + array = new Int32Array( array ); - } + } else if ( array.constructor === Uint16Array ) { + + array = new Uint32Array( array ); - array = tempArray; + if ( usage & GPUBufferUsage.INDEX ) { + + for ( let i = 0; i < array.length; i ++ ) { + + if ( array[ i ] === 0xffff ) array[ i ] = 0xffffffff; // use correct primitive restart index + + } + + } + + } } @@ -51766,6 +61322,11 @@ class WebGPUAttributeUtils { } + /** + * Updates the GPU buffer of the given buffer attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ updateAttribute( attribute ) { const bufferAttribute = this._getBufferAttribute( attribute ); @@ -51817,6 +61378,13 @@ class WebGPUAttributeUtils { } + /** + * This method creates the vertex buffer layout data which are + * require when creating a render pipeline for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @return {Array} An array holding objects which describe the vertex buffer layout. + */ createShaderVertexBuffers( renderObject ) { const attributes = renderObject.getAttributes(); @@ -51878,6 +61446,11 @@ class WebGPUAttributeUtils { } + /** + * Destroys the GPU buffer of the given buffer attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ destroyAttribute( attribute ) { const backend = this.backend; @@ -51889,6 +61462,14 @@ class WebGPUAttributeUtils { } + /** + * This method performs a readback operation by moving buffer data from + * a storage buffer attribute from the GPU to the CPU. + * + * @async + * @param {StorageBufferAttribute} attribute - The storage buffer attribute. + * @return {Promise} A promise that resolves with the buffer data when the data are ready. + */ async getArrayBufferAsync( attribute ) { const backend = this.backend; @@ -51931,6 +61512,13 @@ class WebGPUAttributeUtils { } + /** + * Returns the vertex format of the given buffer attribute. + * + * @private + * @param {BufferAttribute} geometryAttribute - The buffer attribute. + * @return {String} The vertex format (e.g. 'float32x3'). + */ _getVertexFormat( geometryAttribute ) { const { itemSize, normalized } = geometryAttribute; @@ -51976,12 +61564,27 @@ class WebGPUAttributeUtils { } + /** + * Returns `true` if the given array is a typed array. + * + * @private + * @param {Any} array - The array. + * @return {Boolean} Whether the given array is a typed array or not. + */ _isTypedArray( array ) { return ArrayBuffer.isView( array ) && ! ( array instanceof DataView ); } + /** + * Utility method for handling interleaved buffer attributes correctly. + * To process them, their `InterleavedBuffer` is returned. + * + * @private + * @param {BufferAttribute} attribute - The attribute. + * @return {BufferAttribute|InterleavedBuffer} + */ _getBufferAttribute( attribute ) { if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; @@ -51992,15 +61595,47 @@ class WebGPUAttributeUtils { } +/** + * A WebGPU backend utility module for managing bindings. + * + * When reading the documentation it's helpful to keep in mind that + * all class definitions starting with 'GPU*' are modules from the + * WebGPU API. So for example `BindGroup` is a class from the engine + * whereas `GPUBindGroup` is a class from WebGPU. + * + * @private + */ class WebGPUBindingUtils { + /** + * Constructs a new utility object. + * + * @param {WebGPUBackend} backend - The WebGPU backend. + */ constructor( backend ) { + /** + * A reference to the WebGPU backend. + * + * @type {WebGPUBackend} + */ this.backend = backend; + + /** + * A cache for managing bind group layouts. + * + * @type {WeakMap,GPUBindGroupLayout>} + */ this.bindGroupLayoutCache = new WeakMap(); } + /** + * Creates a GPU bind group layout for the given bind group. + * + * @param {BindGroup} bindGroup - The bind group. + * @return {GPUBindGroupLayout} The GPU bind group layout. + */ createBindingsLayout( bindGroup ) { const backend = this.backend; @@ -52170,6 +61805,14 @@ class WebGPUBindingUtils { } + /** + * Creates bindings from the given bind group definition. + * + * @param {BindGroup} bindGroup - The bind group. + * @param {Array} bindings - Array of bind groups. + * @param {Number} cacheIndex - The cache index. + * @param {Number} version - The version. + */ createBindings( bindGroup, bindings, cacheIndex, version = 0 ) { const { backend, bindGroupLayoutCache } = this; @@ -52223,6 +61866,11 @@ class WebGPUBindingUtils { } + /** + * Updates a buffer binding. + * + * @param {Buffer} binding - The buffer binding to update. + */ updateBinding( binding ) { const backend = this.backend; @@ -52235,6 +61883,13 @@ class WebGPUBindingUtils { } + /** + * Creates a GPU bind group for the given bind group and GPU layout. + * + * @param {BindGroup} bindGroup - The bind group. + * @param {GPUBindGroupLayout} layoutGPU - The GPU bind group layout. + * @return {GPUBindGroup} The GPU bind group. + */ createBindGroup( bindGroup, layoutGPU ) { const backend = this.backend; @@ -52355,20 +62010,48 @@ class WebGPUBindingUtils { } +/** + * A WebGPU backend utility module for managing pipelines. + * + * @private + */ class WebGPUPipelineUtils { + /** + * Constructs a new utility object. + * + * @param {WebGPUBackend} backend - The WebGPU backend. + */ constructor( backend ) { + /** + * A reference to the WebGPU backend. + * + * @type {WebGPUBackend} + */ this.backend = backend; } - _getSampleCount( renderObjectContext ) { + /** + * Returns the sample count derived from the given render context. + * + * @private + * @param {RenderContext} renderContext - The render context. + * @return {Number} The sample count. + */ + _getSampleCount( renderContext ) { - return this.backend.utils.getSampleCountRenderContext( renderObjectContext ); + return this.backend.utils.getSampleCountRenderContext( renderContext ); } + /** + * Creates a render pipeline for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @param {Array} promises - An array of compilation promises which are used in `compileAsync()`. + */ createRenderPipeline( renderObject, promises ) { const { object, material, geometry, pipeline } = renderObject; @@ -52528,6 +62211,12 @@ class WebGPUPipelineUtils { } + /** + * Creates GPU render bundle encoder for the given render context. + * + * @param {RenderContext} renderContext - The render context. + * @return {GPURenderBundleEncoder} The GPU render bundle encoder. + */ createBundleEncoder( renderContext ) { const backend = this.backend; @@ -52548,6 +62237,12 @@ class WebGPUPipelineUtils { } + /** + * Creates a compute pipeline for the given compute node. + * + * @param {ComputePipeline} pipeline - The compute pipeline. + * @param {Array} bindings - The bindings. + */ createComputePipeline( pipeline, bindings ) { const backend = this.backend; @@ -52578,6 +62273,14 @@ class WebGPUPipelineUtils { } + /** + * Returns the blending state as a descriptor object required + * for the pipeline creation. + * + * @private + * @param {Material} material - The material. + * @return {Object} The blending state. + */ _getBlending( material ) { let color, alpha; @@ -52685,7 +62388,13 @@ class WebGPUPipelineUtils { } } - + /** + * Returns the GPU blend factor which is required for the pipeline creation. + * + * @private + * @param {Number} blend - The blend factor as a three.js constant. + * @return {String} The GPU blend factor. + */ _getBlendFactor( blend ) { let blendFactor; @@ -52753,6 +62462,13 @@ class WebGPUPipelineUtils { } + /** + * Returns the GPU stencil compare function which is required for the pipeline creation. + * + * @private + * @param {Material} material - The material. + * @return {String} The GPU stencil compare function. + */ _getStencilCompare( material ) { let stencilCompare; @@ -52802,6 +62518,13 @@ class WebGPUPipelineUtils { } + /** + * Returns the GPU stencil operation which is required for the pipeline creation. + * + * @private + * @param {Number} op - A three.js constant defining the stencil operation. + * @return {String} The GPU stencil operation. + */ _getStencilOperation( op ) { let stencilOperation; @@ -52849,6 +62572,13 @@ class WebGPUPipelineUtils { } + /** + * Returns the GPU blend operation which is required for the pipeline creation. + * + * @private + * @param {Number} blendEquation - A three.js constant defining the blend equation. + * @return {String} The GPU blend operation. + */ _getBlendOperation( blendEquation ) { let blendOperation; @@ -52884,6 +62614,16 @@ class WebGPUPipelineUtils { } + /** + * Returns the primitive state as a descriptor object required + * for the pipeline creation. + * + * @private + * @param {Object3D} object - The 3D object. + * @param {BufferGeometry} geometry - The geometry. + * @param {Material} material - The material. + * @return {Object} The primitive state. + */ _getPrimitiveState( object, geometry, material ) { const descriptor = {}; @@ -52924,12 +62664,26 @@ class WebGPUPipelineUtils { } + /** + * Returns the GPU color write mask which is required for the pipeline creation. + * + * @private + * @param {Material} material - The material. + * @return {String} The GPU color write mask. + */ _getColorWriteMask( material ) { return ( material.colorWrite === true ) ? GPUColorWriteFlags.All : GPUColorWriteFlags.None; } + /** + * Returns the GPU depth compare function which is required for the pipeline creation. + * + * @private + * @param {Material} material - The material. + * @return {String} The GPU depth compare function. + */ _getDepthCompare( material ) { let depthCompare; @@ -52994,14 +62748,41 @@ import 'https://greggman.github.io/webgpu-avoid-redundant-state-setting/webgpu-c //*/ -// - +/** + * A backend implementation targeting WebGPU. + * + * @private + * @augments Backend + */ class WebGPUBackend extends Backend { + /** + * Constructs a new WebGPU backend. + * + * @param {Object} parameters - The configuration parameter. + * @param {Boolean} [parameters.logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not. + * @param {Boolean} [parameters.alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque. + * @param {Boolean} [parameters.depth=true] - Whether the default framebuffer should have a depth buffer or not. + * @param {Boolean} [parameters.stencil=false] - Whether the default framebuffer should have a stencil buffer or not. + * @param {Boolean} [parameters.antialias=false] - Whether MSAA as the default anti-aliasing should be enabled or not. + * @param {Number} [parameters.samples=0] - When `antialias` is `true`, `4` samples are used by default. Set this parameter to any other integer value than 0 to overwrite the default. + * @param {Boolean} [parameters.forceWebGL=false] - If set to `true`, the renderer uses a WebGL 2 backend no matter if WebGPU is supported or not. + * @param {Boolean} [parameters.trackTimestamp=false] - Whether to track timestamps with a Timestamp Query API or not. + * @param {String} [parameters.powerPreference=undefined] - The power preference. + * @param {Object} [parameters.requiredLimits=undefined] - Specifies the limits that are required by the device request. The request will fail if the adapter cannot provide these limits. + * @param {GPUDevice} [parameters.device=undefined] - If there is an existing GPU device on app level, it can be passed to the renderer as a parameter. + */ constructor( parameters = {} ) { super( parameters ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isWebGPUBackend = true; // some parameters require default values other than "undefined" @@ -53009,22 +62790,101 @@ class WebGPUBackend extends Backend { this.parameters.requiredLimits = ( parameters.requiredLimits === undefined ) ? {} : parameters.requiredLimits; + /** + * Whether to track timestamps with a Timestamp Query API or not. + * + * @type {Boolean} + * @default false + */ this.trackTimestamp = ( parameters.trackTimestamp === true ); + /** + * A reference to the device. + * + * @type {GPUDevice?} + * @default null + */ this.device = null; + + /** + * A reference to the context. + * + * @type {GPUCanvasContext?} + * @default null + */ this.context = null; + + /** + * A reference to the color attachment of the default framebuffer. + * + * @type {GPUTexture?} + * @default null + */ this.colorBuffer = null; + + /** + * A reference to the default render pass descriptor. + * + * @type {Object?} + * @default null + */ this.defaultRenderPassdescriptor = null; + /** + * A reference to a backend module holding common utility functions. + * + * @type {WebGPUUtils} + */ this.utils = new WebGPUUtils( this ); + + /** + * A reference to a backend module holding shader attribute-related + * utility functions. + * + * @type {WebGPUAttributeUtils} + */ this.attributeUtils = new WebGPUAttributeUtils( this ); + + /** + * A reference to a backend module holding shader binding-related + * utility functions. + * + * @type {WebGPUBindingUtils} + */ this.bindingUtils = new WebGPUBindingUtils( this ); + + /** + * A reference to a backend module holding shader pipeline-related + * utility functions. + * + * @type {WebGPUPipelineUtils} + */ this.pipelineUtils = new WebGPUPipelineUtils( this ); + + /** + * A reference to a backend module holding shader texture-related + * utility functions. + * + * @type {WebGPUTextureUtils} + */ this.textureUtils = new WebGPUTextureUtils( this ); + + /** + * A map that manages the resolve buffers for occlusion queries. + * + * @type {Map} + */ this.occludedResolveCache = new Map(); } + /** + * Initializes the backend so it is ready for usage. + * + * @async + * @param {Renderer} renderer - The renderer. + * @return {Promise} A Promise that resolves when the backend has been initialized. + */ async init( renderer ) { await super.init( renderer ); @@ -53113,24 +62973,53 @@ class WebGPUBackend extends Backend { } + /** + * The coordinate system of the backend. + * + * @type {Number} + * @readonly + */ get coordinateSystem() { return WebGPUCoordinateSystem; } + /** + * This method performs a readback operation by moving buffer data from + * a storage buffer attribute from the GPU to the CPU. + * + * @async + * @param {StorageBufferAttribute} attribute - The storage buffer attribute. + * @return {Promise} A promise that resolves with the buffer data when the data are ready. + */ async getArrayBufferAsync( attribute ) { return await this.attributeUtils.getArrayBufferAsync( attribute ); } + /** + * Returns the backend's rendering context. + * + * @return {GPUCanvasContext} The rendering context. + */ getContext() { return this.context; } + /** + * Returns the default render pass descriptor. + * + * In WebGPU, the default framebuffer must be configured + * like custom framebuffers so the backend needs a render + * pass descriptor even when rendering directly to screen. + * + * @private + * @return {Object} The render pass descriptor. + */ _getDefaultRenderPassDescriptor() { let descriptor = this.defaultRenderPassdescriptor; @@ -53185,7 +63074,15 @@ class WebGPUBackend extends Backend { } - _getRenderPassDescriptor( renderContext ) { + /** + * Returns the render pass descriptor for the given render context. + * + * @private + * @param {RenderContext} renderContext - The render context. + * @param {Object} colorAttachmentsConfig - Configuration object for the color attachments. + * @return {Object} The render pass descriptor. + */ + _getRenderPassDescriptor( renderContext, colorAttachmentsConfig = {} ) { const renderTarget = renderContext.renderTarget; const renderTargetData = this.get( renderTarget ); @@ -53195,8 +63092,11 @@ class WebGPUBackend extends Backend { if ( descriptors === undefined || renderTargetData.width !== renderTarget.width || renderTargetData.height !== renderTarget.height || + renderTargetData.dimensions !== renderTarget.dimensions || renderTargetData.activeMipmapLevel !== renderTarget.activeMipmapLevel || - renderTargetData.samples !== renderTarget.samples + renderTargetData.activeCubeFace !== renderContext.activeCubeFace || + renderTargetData.samples !== renderTarget.samples || + renderTargetData.loadOp !== colorAttachmentsConfig.loadOp ) { descriptors = {}; @@ -53226,16 +63126,37 @@ class WebGPUBackend extends Backend { const textures = renderContext.textures; const colorAttachments = []; + let sliceIndex; + for ( let i = 0; i < textures.length; i ++ ) { const textureData = this.get( textures[ i ] ); - const textureView = textureData.texture.createView( { + const viewDescriptor = { + label: `colorAttachment_${ i }`, baseMipLevel: renderContext.activeMipmapLevel, mipLevelCount: 1, baseArrayLayer: renderContext.activeCubeFace, + arrayLayerCount: 1, dimension: GPUTextureViewDimension.TwoD - } ); + }; + + if ( renderTarget.isRenderTarget3D ) { + + sliceIndex = renderContext.activeCubeFace; + + viewDescriptor.baseArrayLayer = 0; + viewDescriptor.dimension = GPUTextureViewDimension.ThreeD; + viewDescriptor.depthOrArrayLayers = textures[ i ].image.depth; + + } else if ( renderTarget.isRenderTargetArray ) { + + viewDescriptor.dimension = GPUTextureViewDimension.TwoDArray; + viewDescriptor.depthOrArrayLayers = textures[ i ].image.depth; + + } + + const textureView = textureData.texture.createView( viewDescriptor ); let view, resolveTarget; @@ -53253,9 +63174,11 @@ class WebGPUBackend extends Backend { colorAttachments.push( { view, + depthSlice: sliceIndex, resolveTarget, loadOp: GPULoadOp.Load, - storeOp: GPUStoreOp.Store + storeOp: GPUStoreOp.Store, + ...colorAttachmentsConfig } ); } @@ -53281,7 +63204,11 @@ class WebGPUBackend extends Backend { renderTargetData.width = renderTarget.width; renderTargetData.height = renderTarget.height; renderTargetData.samples = renderTarget.samples; - renderTargetData.activeMipmapLevel = renderTarget.activeMipmapLevel; + renderTargetData.activeMipmapLevel = renderContext.activeMipmapLevel; + renderTargetData.activeCubeFace = renderContext.activeCubeFace; + renderTargetData.dimensions = renderTarget.dimensions; + renderTargetData.depthSlice = sliceIndex; + renderTargetData.loadOp = colorAttachments[ 0 ].loadOp; } @@ -53289,6 +63216,12 @@ class WebGPUBackend extends Backend { } + /** + * This method is executed at the beginning of a render call and prepares + * the WebGPU state for upcoming render calls + * + * @param {RenderContext} renderContext - The render context. + */ beginRender( renderContext ) { const renderContextData = this.get( renderContext ); @@ -53329,7 +63262,7 @@ class WebGPUBackend extends Backend { } else { - descriptor = this._getRenderPassDescriptor( renderContext ); + descriptor = this._getRenderPassDescriptor( renderContext, { loadOp: GPULoadOp.Load } ); } @@ -53448,6 +63381,12 @@ class WebGPUBackend extends Backend { } + /** + * This method is executed at the end of a render call and finalizes work + * after draw calls. + * + * @param {RenderContext} renderContext - The render context. + */ finishRender( renderContext ) { const renderContextData = this.get( renderContext ); @@ -53536,6 +63475,14 @@ class WebGPUBackend extends Backend { } + /** + * Returns `true` if the given 3D object is fully occluded by other + * 3D objects in the scene. + * + * @param {RenderContext} renderContext - The render context. + * @param {Object3D} object - The 3D object to test. + * @return {Boolean} Whether the 3D object is fully occluded or not. + */ isOccluded( renderContext, object ) { const renderContextData = this.get( renderContext ); @@ -53544,6 +63491,13 @@ class WebGPUBackend extends Backend { } + /** + * This method processes the result of occlusion queries and writes it + * into render context data. + * + * @async + * @param {RenderContext} renderContext - The render context. + */ async resolveOccludedAsync( renderContext ) { const renderContextData = this.get( renderContext ); @@ -53582,6 +63536,11 @@ class WebGPUBackend extends Backend { } + /** + * Updates the viewport with the values from the given render context. + * + * @param {RenderContext} renderContext - The render context. + */ updateViewport( renderContext ) { const { currentPass } = this.get( renderContext ); @@ -53591,7 +63550,15 @@ class WebGPUBackend extends Backend { } - clear( color, depth, stencil, renderTargetData = null ) { + /** + * Performs a clear operation. + * + * @param {Boolean} color - Whether the color buffer should be cleared or not. + * @param {Boolean} depth - Whether the depth buffer should be cleared or not. + * @param {Boolean} stencil - Whether the stencil buffer should be cleared or not. + * @param {RenderContext?} [renderTargetContext=null] - The render context of the current set render target. + */ + clear( color, depth, stencil, renderTargetContext = null ) { const device = this.device; const renderer = this.renderer; @@ -53624,7 +63591,7 @@ class WebGPUBackend extends Backend { } - if ( renderTargetData === null ) { + if ( renderTargetContext === null ) { supportsDepth = renderer.depth; supportsStencil = renderer.stencil; @@ -53651,45 +63618,20 @@ class WebGPUBackend extends Backend { } else { - supportsDepth = renderTargetData.depth; - supportsStencil = renderTargetData.stencil; + supportsDepth = renderTargetContext.depth; + supportsStencil = renderTargetContext.stencil; if ( color ) { - for ( const texture of renderTargetData.textures ) { - - const textureData = this.get( texture ); - const textureView = textureData.texture.createView(); - - let view, resolveTarget; + const descriptor = this._getRenderPassDescriptor( renderTargetContext, { loadOp: GPULoadOp.Clear } ); - if ( textureData.msaaTexture !== undefined ) { - - view = textureData.msaaTexture.createView(); - resolveTarget = textureView; - - } else { - - view = textureView; - resolveTarget = undefined; - - } - - colorAttachments.push( { - view, - resolveTarget, - clearValue, - loadOp: GPULoadOp.Clear, - storeOp: GPUStoreOp.Store - } ); - - } + colorAttachments = descriptor.colorAttachments; } if ( supportsDepth || supportsStencil ) { - const depthTextureData = this.get( renderTargetData.depthTexture ); + const depthTextureData = this.get( renderTargetContext.depthTexture ); depthStencilAttachment = { view: depthTextureData.texture.createView() @@ -53753,6 +63695,12 @@ class WebGPUBackend extends Backend { // compute + /** + * This method is executed at the beginning of a compute call and + * prepares the state for upcoming compute tasks. + * + * @param {Node|Array} computeGroup - The compute node(s). + */ beginCompute( computeGroup ) { const groupGPU = this.get( computeGroup ); @@ -53768,6 +63716,14 @@ class WebGPUBackend extends Backend { } + /** + * Executes a compute command for the given compute node. + * + * @param {Node|Array} computeGroup - The group of compute nodes of a compute call. Can be a single compute node. + * @param {Node} computeNode - The compute node. + * @param {Array} bindings - The bindings. + * @param {ComputePipeline} pipeline - The compute pipeline. + */ compute( computeGroup, computeNode, bindings, pipeline ) { const { passEncoderGPU } = this.get( computeGroup ); @@ -53815,6 +63771,12 @@ class WebGPUBackend extends Backend { } + /** + * This method is executed at the end of a compute call and + * finalizes work after compute tasks. + * + * @param {Node|Array} computeGroup - The compute node(s). + */ finishCompute( computeGroup ) { const groupData = this.get( computeGroup ); @@ -53827,6 +63789,13 @@ class WebGPUBackend extends Backend { } + /** + * Can be used to synchronize CPU operations with GPU tasks. So when this method is called, + * the CPU waits for the GPU to complete its operation (e.g. a compute task). + * + * @async + * @return {Promise} A Promise that resolves when synchronization has been finished. + */ async waitForGPU() { await this.device.queue.onSubmittedWorkDone(); @@ -53835,6 +63804,12 @@ class WebGPUBackend extends Backend { // render object + /** + * Executes a draw command for the given render object. + * + * @param {RenderObject} renderObject - The render object to draw. + * @param {Info} info - Holds a series of statistical information about the GPU memory and the rendering process. + */ draw( renderObject, info ) { const { object, context, pipeline } = renderObject; @@ -54018,6 +63993,12 @@ class WebGPUBackend extends Backend { // cache key + /** + * Returns `true` if the render pipeline requires an update. + * + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether the render pipeline requires an update or not. + */ needsRenderUpdate( renderObject ) { const data = this.get( renderObject ); @@ -54074,6 +64055,12 @@ class WebGPUBackend extends Backend { } + /** + * Returns a cache key that is used to identify render pipelines. + * + * @param {RenderObject} renderObject - The render object. + * @return {String} The cache key. + */ getRenderCacheKey( renderObject ) { const { object, material } = renderObject; @@ -54102,55 +64089,110 @@ class WebGPUBackend extends Backend { // textures + /** + * Creates a GPU sampler for the given texture. + * + * @param {Texture} texture - The texture to create the sampler for. + */ createSampler( texture ) { this.textureUtils.createSampler( texture ); } + /** + * Destroys the GPU sampler for the given texture. + * + * @param {Texture} texture - The texture to destroy the sampler for. + */ destroySampler( texture ) { this.textureUtils.destroySampler( texture ); } + /** + * Creates a default texture for the given texture that can be used + * as a placeholder until the actual texture is ready for usage. + * + * @param {Texture} texture - The texture to create a default texture for. + */ createDefaultTexture( texture ) { this.textureUtils.createDefaultTexture( texture ); } + /** + * Defines a texture on the GPU for the given texture object. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ createTexture( texture, options ) { this.textureUtils.createTexture( texture, options ); } + /** + * Uploads the updated texture data to the GPU. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ updateTexture( texture, options ) { this.textureUtils.updateTexture( texture, options ); } + /** + * Generates mipmaps for the given texture. + * + * @param {Texture} texture - The texture. + */ generateMipmaps( texture ) { this.textureUtils.generateMipmaps( texture ); } + /** + * Destroys the GPU data for the given texture object. + * + * @param {Texture} texture - The texture. + */ destroyTexture( texture ) { this.textureUtils.destroyTexture( texture ); } - copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { + /** + * Returns texture data as a typed array. + * + * @async + * @param {Texture} texture - The texture to copy. + * @param {Number} x - The x coordinate of the copy origin. + * @param {Number} y - The y coordinate of the copy origin. + * @param {Number} width - The width of the copy. + * @param {Number} height - The height of the copy. + * @param {Number} faceIndex - The face index. + * @return {Promise} A Promise that resolves with a typed array when the copy operation has finished. + */ + async copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { return this.textureUtils.copyTextureToBuffer( texture, x, y, width, height, faceIndex ); } - + /** + * Inits a time stamp query for the given render context. + * + * @param {RenderContext} renderContext - The render context. + * @param {Object} descriptor - The query descriptor. + */ initTimestampQuery( renderContext, descriptor ) { if ( ! this.trackTimestamp ) return; @@ -54177,8 +64219,12 @@ class WebGPUBackend extends Backend { } - // timestamp utils - + /** + * Prepares the timestamp buffer. + * + * @param {RenderContext} renderContext - The render context. + * @param {GPUCommandEncoder} encoder - The command encoder. + */ prepareTimestampBuffer( renderContext, encoder ) { if ( ! this.trackTimestamp ) return; @@ -54218,6 +64264,14 @@ class WebGPUBackend extends Backend { } + /** + * Resolves the time stamp for the given render context and type. + * + * @async + * @param {RenderContext} renderContext - The render context. + * @param {String} type - The render context. + * @return {Promise} A Promise that resolves when the time stamp has been computed. + */ async resolveTimestampAsync( renderContext, type = 'render' ) { if ( ! this.trackTimestamp ) return; @@ -54249,6 +64303,13 @@ class WebGPUBackend extends Backend { // node builder + /** + * Returns a node builder for the given render object. + * + * @param {RenderObject} object - The render object. + * @param {Renderer} renderer - The renderer. + * @return {WGSLNodeBuilder} The node builder. + */ createNodeBuilder( object, renderer ) { return new WGSLNodeBuilder( object, renderer ); @@ -54257,17 +64318,27 @@ class WebGPUBackend extends Backend { // program + /** + * Creates a shader program from the given programmable stage. + * + * @param {ProgrammableStage} program - The programmable stage. + */ createProgram( program ) { const programGPU = this.get( program ); programGPU.module = { - module: this.device.createShaderModule( { code: program.code, label: program.stage } ), + module: this.device.createShaderModule( { code: program.code, label: program.stage + ( program.name !== '' ? `_${ program.name }` : '' ) } ), entryPoint: 'main' }; } + /** + * Destroys the shader program of the given programmable stage. + * + * @param {ProgrammableStage} program - The programmable stage. + */ destroyProgram( program ) { this.delete( program ); @@ -54276,18 +64347,35 @@ class WebGPUBackend extends Backend { // pipelines + /** + * Creates a render pipeline for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @param {Array} promises - An array of compilation promises which are used in `compileAsync()`. + */ createRenderPipeline( renderObject, promises ) { this.pipelineUtils.createRenderPipeline( renderObject, promises ); } + /** + * Creates a compute pipeline for the given compute node. + * + * @param {ComputePipeline} computePipeline - The compute pipeline. + * @param {Array} bindings - The bindings. + */ createComputePipeline( computePipeline, bindings ) { this.pipelineUtils.createComputePipeline( computePipeline, bindings ); } + /** + * Prepares the state for encoding render bundles. + * + * @param {RenderContext} renderContext - The render context. + */ beginBundle( renderContext ) { const renderContextData = this.get( renderContext ); @@ -54300,6 +64388,12 @@ class WebGPUBackend extends Backend { } + /** + * After processing render bundles this method finalizes related work. + * + * @param {RenderContext} renderContext - The render context. + * @param {RenderBundle} bundle - The render bundle. + */ finishBundle( renderContext, bundle ) { const renderContextData = this.get( renderContext ); @@ -54316,6 +64410,12 @@ class WebGPUBackend extends Backend { } + /** + * Adds a render bundle to the render context data. + * + * @param {RenderContext} renderContext - The render context. + * @param {RenderBundle} bundle - The render bundle to add. + */ addBundle( renderContext, bundle ) { const renderContextData = this.get( renderContext ); @@ -54326,18 +64426,39 @@ class WebGPUBackend extends Backend { // bindings + /** + * Creates bindings from the given bind group definition. + * + * @param {BindGroup} bindGroup - The bind group. + * @param {Array} bindings - Array of bind groups. + * @param {Number} cacheIndex - The cache index. + * @param {Number} version - The version. + */ createBindings( bindGroup, bindings, cacheIndex, version ) { this.bindingUtils.createBindings( bindGroup, bindings, cacheIndex, version ); } + /** + * Updates the given bind group definition. + * + * @param {BindGroup} bindGroup - The bind group. + * @param {Array} bindings - Array of bind groups. + * @param {Number} cacheIndex - The cache index. + * @param {Number} version - The version. + */ updateBindings( bindGroup, bindings, cacheIndex, version ) { this.bindingUtils.createBindings( bindGroup, bindings, cacheIndex, version ); } + /** + * Updates a buffer binding. + * + * @param {Buffer} binding - The buffer binding to update. + */ updateBinding( binding ) { this.bindingUtils.updateBinding( binding ); @@ -54346,36 +64467,66 @@ class WebGPUBackend extends Backend { // attributes + /** + * Creates the buffer of an indexed shader attribute. + * + * @param {BufferAttribute} attribute - The indexed buffer attribute. + */ createIndexAttribute( attribute ) { this.attributeUtils.createAttribute( attribute, GPUBufferUsage.INDEX | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST ); } + /** + * Creates the GPU buffer of a shader attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ createAttribute( attribute ) { this.attributeUtils.createAttribute( attribute, GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST ); } + /** + * Creates the GPU buffer of a storage attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ createStorageAttribute( attribute ) { this.attributeUtils.createAttribute( attribute, GPUBufferUsage.STORAGE | GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST ); } + /** + * Creates the GPU buffer of an indirect storage attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ createIndirectStorageAttribute( attribute ) { this.attributeUtils.createAttribute( attribute, GPUBufferUsage.STORAGE | GPUBufferUsage.INDIRECT | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST ); } + /** + * Updates the GPU buffer of a shader attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute to update. + */ updateAttribute( attribute ) { this.attributeUtils.updateAttribute( attribute ); } + /** + * Destroys the GPU buffer of a shader attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute to destroy. + */ destroyAttribute( attribute ) { this.attributeUtils.destroyAttribute( attribute ); @@ -54384,6 +64535,9 @@ class WebGPUBackend extends Backend { // canvas + /** + * Triggers an update of the default render pass descriptor. + */ updateSize() { this.colorBuffer = this.textureUtils.getColorBuffer(); @@ -54393,18 +64547,38 @@ class WebGPUBackend extends Backend { // utils public + /** + * Returns the maximum anisotropy texture filtering value. + * + * @return {Number} The maximum anisotropy texture filtering value. + */ getMaxAnisotropy() { return 16; } + /** + * Checks if the given feature is supported by the backend. + * + * @param {String} name - The feature's name. + * @return {Boolean} Whether the feature is supported or not. + */ hasFeature( name ) { return this.device.features.has( name ); } + /** + * Copies data of the given source texture to the given destination texture. + * + * @param {Texture} srcTexture - The source texture. + * @param {Texture} dstTexture - The destination texture. + * @param {Vector4?} [srcRegion=null] - The region of the source texture to copy. + * @param {(Vector2|Vector3)?} [dstPosition=null] - The destination position of the copy. + * @param {Number} [level=0] - The mip level to copy. + */ copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { let dstX = 0; @@ -54463,6 +64637,13 @@ class WebGPUBackend extends Backend { } + /** + * Copies the current bound framebuffer to the given texture. + * + * @param {Texture} texture - The destination texture. + * @param {RenderContext} renderContext - The render context. + * @param {Vector4} rectangle - A four dimensional vector defining the origin and dimension of the copy. + */ copyFramebufferToTexture( texture, renderContext, rectangle ) { const renderContextData = this.get( renderContext ); @@ -54597,8 +64778,18 @@ class IESSpotLight extends SpotLight { } +/** + * This version of a node library represents a basic version + * just focusing on lights and tone mapping techniques. + * + * @private + * @augments NodeLibrary + */ class BasicNodeLibrary extends NodeLibrary { + /** + * Constructs a new basic node library. + */ constructor() { super(); @@ -54623,8 +64814,28 @@ class BasicNodeLibrary extends NodeLibrary { } +/** + * This alternative version of {@link WebGPURenderer} only supports node materials. + * So classes like `MeshBasicMaterial` are not compatible. + * + * @augments module:Renderer~Renderer + */ class WebGPURenderer extends Renderer { + /** + * Constructs a new WebGPU renderer. + * + * @param {Object} parameters - The configuration parameter. + * @param {Boolean} [parameters.logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not. + * @param {Boolean} [parameters.alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque. + * @param {Boolean} [parameters.depth=true] - Whether the default framebuffer should have a depth buffer or not. + * @param {Boolean} [parameters.stencil=false] - Whether the default framebuffer should have a stencil buffer or not. + * @param {Boolean} [parameters.antialias=false] - Whether MSAA as the default anti-aliasing should be enabled or not. + * @param {Number} [parameters.samples=0] - When `antialias` is `true`, `4` samples are used by default. Set this parameter to any other integer value than 0 + * to overwrite the default. + * @param {Boolean} [parameters.forceWebGL=false] - If set to `true`, the renderer uses it + * WebGL 2 backend no matter if WebGPU is supported or not. + */ constructor( parameters = {} ) { let BackendClass; @@ -54651,29 +64862,100 @@ class WebGPURenderer extends Renderer { super( backend, parameters ); + /** + * The generic default value is overwritten with the + * standard node library for type mapping. Material + * mapping is not supported with this version. + * + * @type {BasicNodeLibrary} + */ this.library = new BasicNodeLibrary(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isWebGPURenderer = true; } } +/** + * A specialized group which enables applications access to the + * Render Bundle API of WebGPU. The group with all its descendant nodes + * are considered as one render bundle and processed as such by + * the renderer. + * + * This module is only fully supported by `WebGPURenderer` with a WebGPU backend. + * With a WebGL backend, the group can technically be rendered but without + * any performance improvements. + * + * @augments Group + */ class BundleGroup extends Group { + /** + * Constructs a new bundle group. + */ constructor() { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isBundleGroup = true; + /** + * This property is only relevant for detecting types + * during serialization/deserialization. It should always + * match the class name. + * + * @type {String} + * @readonly + * @default 'BundleGroup' + */ this.type = 'BundleGroup'; + /** + * Whether the bundle is static or not. When set to `true`, the structure + * is assumed to be static and does not change. E.g. no new objects are + * added to the group + * + * If a change is required, an update can still be forced by setting the + * `needsUpdate` flag to `true`. + * + * @type {Boolean} + * @default true + */ this.static = true; + + /** + * The bundle group's version. + * + * @type {Number} + * @readonly + * @default 0 + */ this.version = 0; } + /** + * Set this property to `true` when the bundle group has changed. + * + * @type {Boolean} + * @default false + * @param {Boolean} value + */ set needsUpdate( value ) { if ( value === true ) this.version ++; @@ -54682,27 +64964,93 @@ class BundleGroup extends Group { } -const _material = /*@__PURE__*/ new NodeMaterial(); -const _quadMesh = /*@__PURE__*/ new QuadMesh( _material ); - +/** + * This module is responsible to manage the post processing setups in apps. + * You usually create a single instance of this class and use it to define + * the output of your post processing effect chain. + * ```js + * const postProcessing = new PostProcessing( renderer ); + * + * const scenePass = pass( scene, camera ); + * + * postProcessing.outputNode = scenePass; + * ``` + */ class PostProcessing { + /** + * Constructs a new post processing management module. + * + * @param {Renderer} renderer - A reference to the renderer. + * @param {Node} outputNode - An optional output node. + */ constructor( renderer, outputNode = vec4( 0, 0, 1, 1 ) ) { + /** + * A reference to the renderer. + * + * @type {Renderer} + */ this.renderer = renderer; + + /** + * A node which defines the final output of the post + * processing. This is usually the last node in a chain + * of effect nodes. + * + * @type {Node} + */ this.outputNode = outputNode; + /** + * Whether the default output tone mapping and color + * space transformation should be enabled or not. + * + * It is enabled by default by it must be disabled when + * effects must be executed after tone mapping and color + * space conversion. A typical example is FXAA which + * requires sRGB input. + * + * When set to `false`, the app must control the output + * transformation with `RenderOutputNode`. + * + * ```js + * const outputPass = renderOutput( scenePass ); + * ``` + * + * @type {Boolean} + */ this.outputColorTransform = true; + /** + * Must be set to `true` when the output node changes. + * + * @type {Node} + */ this.needsUpdate = true; - _material.name = 'PostProcessing'; + const material = new NodeMaterial(); + material.name = 'PostProcessing'; + + /** + * The full screen quad that is used to render + * the effects. + * + * @private + * @type {QuadMesh} + */ + this._quadMesh = new QuadMesh( material ); } + /** + * When `PostProcessing` is used to apply post processing effects, + * the application must use this version of `render()` inside + * its animation loop (not the one from the renderer). + */ render() { - this.update(); + this._update(); const renderer = this.renderer; @@ -54714,7 +65062,7 @@ class PostProcessing { // - _quadMesh.render( renderer ); + this._quadMesh.render( renderer ); // @@ -54723,7 +65071,21 @@ class PostProcessing { } - update() { + /** + * Frees internal resources. + */ + dispose() { + + this._quadMesh.material.dispose(); + + } + + /** + * Updates the state of the module. + * + * @private + */ + _update() { if ( this.needsUpdate === true ) { @@ -54732,8 +65094,8 @@ class PostProcessing { const toneMapping = renderer.toneMapping; const outputColorSpace = renderer.outputColorSpace; - _quadMesh.material.fragmentNode = this.outputColorTransform === true ? renderOutput( this.outputNode, toneMapping, outputColorSpace ) : this.outputNode.context( { toneMapping, outputColorSpace } ); - _quadMesh.material.needsUpdate = true; + this._quadMesh.material.fragmentNode = this.outputColorTransform === true ? renderOutput( this.outputNode, toneMapping, outputColorSpace ) : this.outputNode.context( { toneMapping, outputColorSpace } ); + this._quadMesh.material.needsUpdate = true; this.needsUpdate = false; @@ -54741,9 +65103,17 @@ class PostProcessing { } + /** + * When `PostProcessing` is used to apply post processing effects, + * the application must use this version of `renderAsync()` inside + * its animation loop (not the one from the renderer). + * + * @async + * @return {Promise} A Promise that resolves when the render has been finished. + */ async renderAsync() { - this.update(); + this._update(); const renderer = this.renderer; @@ -54755,7 +65125,7 @@ class PostProcessing { // - await _quadMesh.renderAsync( renderer ); + await this._quadMesh.renderAsync( renderer ); // @@ -54766,124 +65136,90 @@ class PostProcessing { } -// renderer state - -function saveRendererState( renderer, state = {} ) { - - state.toneMapping = renderer.toneMapping; - state.toneMappingExposure = renderer.toneMappingExposure; - state.outputColorSpace = renderer.outputColorSpace; - state.renderTarget = renderer.getRenderTarget(); - state.activeCubeFace = renderer.getActiveCubeFace(); - state.activeMipmapLevel = renderer.getActiveMipmapLevel(); - state.renderObjectFunction = renderer.getRenderObjectFunction(); - state.pixelRatio = renderer.getPixelRatio(); - state.mrt = renderer.getMRT(); - state.clearColor = renderer.getClearColor( state.clearColor || new Color() ); - state.clearAlpha = renderer.getClearAlpha(); - state.autoClear = renderer.autoClear; - state.scissorTest = renderer.getScissorTest(); - - return state; - -} - -function resetRendererState( renderer, state ) { - - state = saveRendererState( renderer, state ); - - renderer.setMRT( null ); - renderer.setRenderObjectFunction( null ); - renderer.setClearColor( 0x000000, 1 ); - renderer.autoClear = true; - - return state; - -} - -function restoreRendererState( renderer, state ) { - - renderer.toneMapping = state.toneMapping; - renderer.toneMappingExposure = state.toneMappingExposure; - renderer.outputColorSpace = state.outputColorSpace; - renderer.setRenderTarget( state.renderTarget, state.activeCubeFace, state.activeMipmapLevel ); - renderer.setRenderObjectFunction( state.renderObjectFunction ); - renderer.setPixelRatio( state.pixelRatio ); - renderer.setMRT( state.mrt ); - renderer.setClearColor( state.clearColor, state.clearAlpha ); - renderer.autoClear = state.autoClear; - renderer.setScissorTest( state.scissorTest ); - -} - -// renderer and scene state - -function saveRendererAndSceneState( renderer, scene, state = {} ) { - - state = saveRendererState( renderer, state ); - state.background = scene.background; - state.backgroundNode = scene.backgroundNode; - state.overrideMaterial = scene.overrideMaterial; - - return state; - -} - -function resetRendererAndSceneState( renderer, scene, state ) { - - state = saveRendererAndSceneState( renderer, scene, state ); - - scene.background = null; - scene.backgroundNode = null; - scene.overrideMaterial = null; - - return state; - -} - -function restoreRendererAndSceneState( renderer, scene, state ) { - - restoreRendererState( renderer, state ); - - scene.background = state.background; - scene.backgroundNode = state.backgroundNode; - scene.overrideMaterial = state.overrideMaterial; - -} - -var PostProcessingUtils = /*#__PURE__*/Object.freeze({ - __proto__: null, - resetRendererAndSceneState: resetRendererAndSceneState, - resetRendererState: resetRendererState, - restoreRendererAndSceneState: restoreRendererAndSceneState, - restoreRendererState: restoreRendererState, - saveRendererAndSceneState: saveRendererAndSceneState, - saveRendererState: saveRendererState -}); - +/** + * This special type of texture is intended for compute shaders. + * It can be used to compute the data of a texture with a compute shader. + * + * Note: This type of texture can only be used with `WebGPURenderer` + * and a WebGPU backend. + * + * @augments Texture + */ class StorageTexture extends Texture { + /** + * Constructs a new storage texture. + * + * @param {Number} [width=1] - The storage texture's width. + * @param {Number} [height=1] - The storage texture's height. + */ constructor( width = 1, height = 1 ) { super(); + /** + * The image object which just represents the texture's dimension. + * + * @type {{width: Number, height:Number}} + */ this.image = { width, height }; + /** + * The default `magFilter` for storage textures is `THREE.LinearFilter`. + * + * @type {Number} + */ this.magFilter = LinearFilter; + + /** + * The default `minFilter` for storage textures is `THREE.LinearFilter`. + * + * @type {Number} + */ this.minFilter = LinearFilter; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isStorageTexture = true; } } +/** + * This special type of buffer attribute is intended for compute shaders. + * It can be used to encode draw parameters for indirect draw calls. + * + * Note: This type of buffer attribute can only be used with `WebGPURenderer` + * and a WebGPU backend. + * + * @augments StorageBufferAttribute + */ class IndirectStorageBufferAttribute extends StorageBufferAttribute { - constructor( array, itemSize ) { + /** + * Constructs a new storage buffer attribute. + * + * @param {Number|Uint32Array} count - The item count. It is also valid to pass a `Uint32Array` as an argument. + * The subsequent parameter is then obsolete. + * @param {Number} itemSize - The item size. + */ + constructor( count, itemSize ) { - super( array, itemSize, Uint32Array ); + super( count, itemSize, Uint32Array ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isIndirectStorageBufferAttribute = true; } @@ -55210,7 +65546,7 @@ class NodeObjectLoader extends ObjectLoader { this.nodeMaterials = {}; /** - * A reference for holdng the `nodes` JSON property. + * A reference to hold the `nodes` JSON property. * * @private * @type {Object?} @@ -55323,20 +65659,69 @@ class NodeObjectLoader extends ObjectLoader { } +/** + * In earlier three.js versions, clipping was defined globally + * on the renderer or on material level. This special version of + * `THREE.Group` allows to encode the clipping state into the scene + * graph. Meaning if you create an instance of this group, all + * descendant 3D objects will be affected by the respective clipping + * planes. + * + * Note: `ClippingGroup` can only be used with `WebGPURenderer`. + * + * @augments Group + */ class ClippingGroup extends Group { + /** + * Constructs a new clipping group. + */ constructor() { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isClippingGroup = true; + + /** + * An array with clipping planes. + * + * @type {Array} + */ this.clippingPlanes = []; + + /** + * Whether clipping should be enabled or not. + * + * @type {Boolean} + * @default true + */ this.enabled = true; + + /** + * Whether the intersection of the clipping planes is used to clip objects, rather than their union. + * + * @type {Boolean} + * @default false + */ this.clipIntersection = false; + + /** + * Whether shadows should be clipped or not. + * + * @type {Boolean} + * @default false + */ this.clipShadows = false; } } -export { ACESFilmicToneMapping, AONode, AddEquation, AddOperation, AdditiveBlending, AgXToneMapping, AlphaFormat, AlwaysCompare, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AmbientLightNode, AnalyticLightNode, ArrayElementNode, AssignNode, AttributeNode, BackSide, BasicEnvironmentNode, BasicShadowMap, BatchNode, BoxGeometry, BufferAttribute, BufferAttributeNode, BufferGeometry, BufferNode, BumpMapNode, BundleGroup, BypassNode, ByteType, CacheNode, CineonToneMapping, ClampToEdgeWrapping, ClippingGroup, CodeNode, Color, ColorManagement, ColorSpaceNode, ComputeNode, ConstNode, ContextNode, ConvertNode, CubeCamera, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureNode, CubeUVReflectionMapping, CullFaceBack, CullFaceFront, CullFaceNone, CustomBlending, DataArrayTexture, DataTexture, DecrementStencilOp, DecrementWrapStencilOp, DepthFormat, DepthStencilFormat, DepthTexture, DirectionalLight, DirectionalLightNode, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicDrawUsage, EnvironmentNode, EqualCompare, EqualDepth, EqualStencilFunc, EquirectUVNode, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExpressionNode, FileLoader, Float16BufferAttribute, Float32BufferAttribute, FloatType, FramebufferTexture, FrontFacingNode, FrontSide, Frustum, FunctionCallNode, FunctionNode, FunctionOverloadingNode, GLSLNodeParser, GreaterCompare, GreaterDepth, GreaterEqualCompare, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, Group, HalfFloatType, HemisphereLight, HemisphereLightNode, IESSpotLight, IESSpotLightNode, IncrementStencilOp, IncrementWrapStencilOp, IndexNode, IndirectStorageBufferAttribute, InstanceNode, InstancedBufferAttribute, InstancedInterleavedBuffer, InstancedMeshNode, InstancedPointsNodeMaterial, IntType, InterleavedBuffer, InterleavedBufferAttribute, InvertStencilOp, IrradianceNode, JoinNode, KeepStencilOp, LessCompare, LessDepth, LessEqualCompare, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, LightProbe, LightProbeNode, Lighting, LightingContextNode, LightingModel, LightingNode, LightsNode, Line2NodeMaterial, LineBasicMaterial, LineBasicNodeMaterial, LineDashedMaterial, LineDashedNodeMaterial, LinearFilter, LinearMipMapLinearFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearSRGBColorSpace, LinearToneMapping, Loader, LoopNode, LuminanceAlphaFormat, LuminanceFormat, MRTNode, MatcapUVNode, Material, MaterialLoader, MaterialNode, MaterialReferenceNode, MathUtils, Matrix3, Matrix4, MaxEquation, MaxMipLevelNode, Mesh, MeshBasicMaterial, MeshBasicNodeMaterial, MeshLambertMaterial, MeshLambertNodeMaterial, MeshMatcapMaterial, MeshMatcapNodeMaterial, MeshNormalMaterial, MeshNormalNodeMaterial, MeshPhongMaterial, MeshPhongNodeMaterial, MeshPhysicalMaterial, MeshPhysicalNodeMaterial, MeshSSSNodeMaterial, MeshStandardMaterial, MeshStandardNodeMaterial, MeshToonMaterial, MeshToonNodeMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, ModelNode, MorphNode, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeutralToneMapping, NeverCompare, NeverDepth, NeverStencilFunc, NoBlending, NoColorSpace, NoToneMapping, Node, NodeAccess, NodeAttribute, NodeBuilder, NodeCache, NodeCode, NodeFrame, NodeFunctionInput, NodeLoader, NodeMaterial, NodeMaterialLoader, NodeMaterialObserver, NodeObjectLoader, NodeShaderStage, NodeType, NodeUniform, NodeUpdateType, NodeUtils, NodeVar, NodeVarying, NormalBlending, NormalMapNode, NotEqualCompare, NotEqualDepth, NotEqualStencilFunc, Object3D, Object3DNode, ObjectLoader, ObjectSpaceNormalMap, OneFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, OutputStructNode, PCFShadowMap, PMREMGenerator, PMREMNode, ParameterNode, PassNode, PerspectiveCamera, PhongLightingModel, PhysicalLightingModel, Plane, PointLight, PointLightNode, PointUVNode, PointsMaterial, PointsNodeMaterial, PostProcessing, PostProcessingUtils, PosterizeNode, PropertyNode, QuadMesh, RED_GREEN_RGTC2_Format, RED_RGTC1_Format, REVISION, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBFormat, RGBIntegerFormat, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, RTTNode, RangeNode, RectAreaLight, RectAreaLightNode, RedFormat, RedIntegerFormat, ReferenceNode, ReflectorNode, ReinhardToneMapping, RemapNode, RenderOutputNode, RenderTarget, RendererReferenceNode, RepeatWrapping, ReplaceStencilOp, ReverseSubtractEquation, RotateNode, SIGNED_RED_GREEN_RGTC2_Format, SIGNED_RED_RGTC1_Format, SRGBColorSpace, SRGBTransfer, Scene, SceneNode, ScreenNode, ScriptableNode, ScriptableValueNode, SetNode, ShadowBaseNode, ShadowMaterial, ShadowNode, ShadowNodeMaterial, ShortType, SkinningNode, SphereGeometry, SplitNode, SpotLight, SpotLightNode, SpriteMaterial, SpriteNodeMaterial, SpriteSheetUVNode, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StackNode, StaticDrawUsage, StorageArrayElementNode, StorageBufferAttribute, StorageBufferNode, StorageInstancedBufferAttribute, StorageTexture, StorageTextureNode, SubtractEquation, SubtractiveBlending, TSL, TangentSpaceNormalMap, TempNode, Texture, Texture3DNode, TextureNode, TextureSizeNode, ToneMappingNode, ToonOutlinePassNode, TriplanarTexturesNode, UVMapping, Uint16BufferAttribute, Uint32BufferAttribute, UniformArrayNode, UniformGroupNode, UniformNode, UnsignedByteType, UnsignedInt248Type, UnsignedInt5999Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, UserDataNode, VSMShadowMap, VarNode, VaryingNode, Vector2, Vector3, Vector4, VertexColorNode, ViewportDepthNode, ViewportDepthTextureNode, ViewportSharedTextureNode, ViewportTextureNode, VolumeNodeMaterial, WebGLCoordinateSystem, WebGLCubeRenderTarget, WebGPUCoordinateSystem, WebGPURenderer, ZeroFactor, ZeroStencilOp, createCanvasElement, defaultBuildStages, defaultShaderStages, shaderStages, vectorComponents }; +export { ACESFilmicToneMapping, AONode, AddEquation, AddOperation, AdditiveBlending, AgXToneMapping, AlphaFormat, AlwaysCompare, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AmbientLightNode, AnalyticLightNode, ArrayElementNode, AssignNode, AttributeNode, BackSide, BasicEnvironmentNode, BasicShadowMap, BatchNode, BoxGeometry, BufferAttribute, BufferAttributeNode, BufferGeometry, BufferNode, BumpMapNode, BundleGroup, BypassNode, ByteType, CacheNode, Camera, CineonToneMapping, ClampToEdgeWrapping, ClippingGroup, CodeNode, Color, ColorManagement, ColorSpaceNode, ComputeNode, ConstNode, ContextNode, ConvertNode, CubeCamera, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureNode, CubeUVReflectionMapping, CullFaceBack, CullFaceFront, CullFaceNone, CustomBlending, DataArrayTexture, DataTexture, DecrementStencilOp, DecrementWrapStencilOp, DepthFormat, DepthStencilFormat, DepthTexture, DirectionalLight, DirectionalLightNode, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicDrawUsage, EnvironmentNode, EqualCompare, EqualDepth, EqualStencilFunc, EquirectUVNode, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExpressionNode, FileLoader, Float16BufferAttribute, Float32BufferAttribute, FloatType, FramebufferTexture, FrontFacingNode, FrontSide, Frustum, FunctionCallNode, FunctionNode, FunctionOverloadingNode, GLSLNodeParser, GreaterCompare, GreaterDepth, GreaterEqualCompare, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, Group, HalfFloatType, HemisphereLight, HemisphereLightNode, IESSpotLight, IESSpotLightNode, IncrementStencilOp, IncrementWrapStencilOp, IndexNode, IndirectStorageBufferAttribute, InstanceNode, InstancedBufferAttribute, InstancedInterleavedBuffer, InstancedMeshNode, InstancedPointsNodeMaterial, IntType, InterleavedBuffer, InterleavedBufferAttribute, InvertStencilOp, IrradianceNode, JoinNode, KeepStencilOp, LessCompare, LessDepth, LessEqualCompare, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, LightProbe, LightProbeNode, Lighting, LightingContextNode, LightingModel, LightingNode, LightsNode, Line2NodeMaterial, LineBasicMaterial, LineBasicNodeMaterial, LineDashedMaterial, LineDashedNodeMaterial, LinearFilter, LinearMipMapLinearFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearSRGBColorSpace, LinearToneMapping, Loader, LoopNode, LuminanceAlphaFormat, LuminanceFormat, MRTNode, MatcapUVNode, Material, MaterialLoader, MaterialNode, MaterialReferenceNode, MathUtils, Matrix3, Matrix4, MaxEquation, MaxMipLevelNode, Mesh, MeshBasicMaterial, MeshBasicNodeMaterial, MeshLambertMaterial, MeshLambertNodeMaterial, MeshMatcapMaterial, MeshMatcapNodeMaterial, MeshNormalMaterial, MeshNormalNodeMaterial, MeshPhongMaterial, MeshPhongNodeMaterial, MeshPhysicalMaterial, MeshPhysicalNodeMaterial, MeshSSSNodeMaterial, MeshStandardMaterial, MeshStandardNodeMaterial, MeshToonMaterial, MeshToonNodeMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, ModelNode, MorphNode, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeutralToneMapping, NeverCompare, NeverDepth, NeverStencilFunc, NoBlending, NoColorSpace, NoToneMapping, Node, NodeAccess, NodeAttribute, NodeBuilder, NodeCache, NodeCode, NodeFrame, NodeFunctionInput, NodeLoader, NodeMaterial, NodeMaterialLoader, NodeMaterialObserver, NodeObjectLoader, NodeShaderStage, NodeType, NodeUniform, NodeUpdateType, NodeUtils, NodeVar, NodeVarying, NormalBlending, NormalMapNode, NotEqualCompare, NotEqualDepth, NotEqualStencilFunc, Object3D, Object3DNode, ObjectLoader, ObjectSpaceNormalMap, OneFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, OutputStructNode, PCFShadowMap, PMREMGenerator, PMREMNode, ParameterNode, PassNode, PerspectiveCamera, PhongLightingModel, PhysicalLightingModel, Plane, PointLight, PointLightNode, PointUVNode, PointsMaterial, PointsNodeMaterial, PostProcessing, PosterizeNode, PropertyNode, QuadMesh, RED_GREEN_RGTC2_Format, RED_RGTC1_Format, REVISION, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBFormat, RGBIntegerFormat, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, RTTNode, RangeNode, RectAreaLight, RectAreaLightNode, RedFormat, RedIntegerFormat, ReferenceNode, ReflectorNode, ReinhardToneMapping, RemapNode, RenderOutputNode, RenderTarget, RendererReferenceNode, RendererUtils, RepeatWrapping, ReplaceStencilOp, ReverseSubtractEquation, RotateNode, SIGNED_RED_GREEN_RGTC2_Format, SIGNED_RED_RGTC1_Format, SRGBColorSpace, SRGBTransfer, Scene, SceneNode, ScreenNode, ScriptableNode, ScriptableValueNode, SetNode, ShadowBaseNode, ShadowMaterial, ShadowNode, ShadowNodeMaterial, ShortType, SkinningNode, SphereGeometry, SplitNode, SpotLight, SpotLightNode, SpriteMaterial, SpriteNodeMaterial, SpriteSheetUVNode, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StackNode, StaticDrawUsage, StorageArrayElementNode, StorageBufferAttribute, StorageBufferNode, StorageInstancedBufferAttribute, StorageTexture, StorageTextureNode, SubtractEquation, SubtractiveBlending, TSL, TangentSpaceNormalMap, TempNode, Texture, Texture3DNode, TextureNode, TextureSizeNode, ToneMappingNode, ToonOutlinePassNode, TriplanarTexturesNode, UVMapping, Uint16BufferAttribute, Uint32BufferAttribute, UniformArrayNode, UniformGroupNode, UniformNode, UnsignedByteType, UnsignedInt248Type, UnsignedInt5999Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, UserDataNode, VSMShadowMap, VarNode, VaryingNode, Vector2, Vector3, Vector4, VertexColorNode, ViewportDepthNode, ViewportDepthTextureNode, ViewportSharedTextureNode, ViewportTextureNode, VolumeNodeMaterial, WebGLCoordinateSystem, WebGLCubeRenderTarget, WebGPUCoordinateSystem, WebGPURenderer, ZeroFactor, ZeroStencilOp, createCanvasElement, defaultBuildStages, defaultShaderStages, shaderStages, vectorComponents }; diff --git a/build/three.webgpu.nodes.min.js b/build/three.webgpu.nodes.min.js index c7af0e7daa6c11..3d55e1478a27d6 100644 --- a/build/three.webgpu.nodes.min.js +++ b/build/three.webgpu.nodes.min.js @@ -1,6 +1,6 @@ /** * @license - * Copyright 2010-2024 Three.js Authors + * Copyright 2010-2025 Three.js Authors * SPDX-License-Identifier: MIT */ -import{Color as e,Vector2 as t,Vector3 as r,Vector4 as s,Matrix3 as i,Matrix4 as n,EventDispatcher as o,MathUtils as a,WebGLCoordinateSystem as u,WebGPUCoordinateSystem as l,ColorManagement as d,SRGBTransfer as c,NoToneMapping as h,StaticDrawUsage as p,InterleavedBuffer as g,DynamicDrawUsage as m,InterleavedBufferAttribute as f,NoColorSpace as y,UnsignedIntType as x,IntType as b,BackSide as T,CubeReflectionMapping as _,CubeRefractionMapping as v,TangentSpaceNormalMap as N,ObjectSpaceNormalMap as S,InstancedInterleavedBuffer as A,InstancedBufferAttribute as R,DataArrayTexture as C,FloatType as E,FramebufferTexture as w,LinearMipmapLinearFilter as M,DepthTexture as B,Material as U,NormalBlending as F,PointsMaterial as P,LineBasicMaterial as I,LineDashedMaterial as L,NoBlending as V,MeshNormalMaterial as D,WebGLCubeRenderTarget as O,BoxGeometry as G,Mesh as k,Scene as z,LinearFilter as $,CubeCamera as H,CubeTexture as W,EquirectangularReflectionMapping as j,EquirectangularRefractionMapping as q,AddOperation as K,MixOperation as X,MultiplyOperation as Y,MeshBasicMaterial as Q,MeshLambertMaterial as Z,MeshPhongMaterial as J,Texture as ee,MeshStandardMaterial as te,MeshPhysicalMaterial as re,MeshToonMaterial as se,MeshMatcapMaterial as ie,SpriteMaterial as ne,ShadowMaterial as oe,Uint32BufferAttribute as ae,Uint16BufferAttribute as ue,DoubleSide as le,DepthStencilFormat as de,DepthFormat as ce,UnsignedInt248Type as he,UnsignedByteType as pe,RenderTarget as ge,Plane as me,Object3D as fe,HalfFloatType as ye,LinearMipMapLinearFilter as xe,OrthographicCamera as be,BufferGeometry as Te,Float32BufferAttribute as _e,BufferAttribute as ve,UVMapping as Ne,Euler as Se,LinearSRGBColorSpace as Ae,LessCompare as Re,VSMShadowMap as Ce,RGFormat as Ee,BasicShadowMap as we,SphereGeometry as Me,CubeUVReflectionMapping as Be,PerspectiveCamera as Ue,RGBAFormat as Fe,LinearMipmapNearestFilter as Pe,NearestMipmapLinearFilter as Ie,Float16BufferAttribute as Le,REVISION as Ve,SRGBColorSpace as De,PCFShadowMap as Oe,FrontSide as Ge,Frustum as ke,DataTexture as ze,RedIntegerFormat as $e,RedFormat as He,RGIntegerFormat as We,RGBIntegerFormat as je,RGBFormat as qe,RGBAIntegerFormat as Ke,UnsignedShortType as Xe,ByteType as Ye,ShortType as Qe,createCanvasElement as Ze,AddEquation as Je,SubtractEquation as et,ReverseSubtractEquation as tt,ZeroFactor as rt,OneFactor as st,SrcColorFactor as it,SrcAlphaFactor as nt,SrcAlphaSaturateFactor as ot,DstColorFactor as at,DstAlphaFactor as ut,OneMinusSrcColorFactor as lt,OneMinusSrcAlphaFactor as dt,OneMinusDstColorFactor as ct,OneMinusDstAlphaFactor as ht,CullFaceNone as pt,CullFaceBack as gt,CullFaceFront as mt,CustomBlending as ft,MultiplyBlending as yt,SubtractiveBlending as xt,AdditiveBlending as bt,NotEqualDepth as Tt,GreaterDepth as _t,GreaterEqualDepth as vt,EqualDepth as Nt,LessEqualDepth as St,LessDepth as At,AlwaysDepth as Rt,NeverDepth as Ct,UnsignedShort4444Type as Et,UnsignedShort5551Type as wt,UnsignedInt5999Type as Mt,AlphaFormat as Bt,LuminanceFormat as Ut,LuminanceAlphaFormat as Ft,RGB_S3TC_DXT1_Format as Pt,RGBA_S3TC_DXT1_Format as It,RGBA_S3TC_DXT3_Format as Lt,RGBA_S3TC_DXT5_Format as Vt,RGB_PVRTC_4BPPV1_Format as Dt,RGB_PVRTC_2BPPV1_Format as Ot,RGBA_PVRTC_4BPPV1_Format as Gt,RGBA_PVRTC_2BPPV1_Format as kt,RGB_ETC1_Format as zt,RGB_ETC2_Format as $t,RGBA_ETC2_EAC_Format as Ht,RGBA_ASTC_4x4_Format as Wt,RGBA_ASTC_5x4_Format as jt,RGBA_ASTC_5x5_Format as qt,RGBA_ASTC_6x5_Format as Kt,RGBA_ASTC_6x6_Format as Xt,RGBA_ASTC_8x5_Format as Yt,RGBA_ASTC_8x6_Format as Qt,RGBA_ASTC_8x8_Format as Zt,RGBA_ASTC_10x5_Format as Jt,RGBA_ASTC_10x6_Format as er,RGBA_ASTC_10x8_Format as tr,RGBA_ASTC_10x10_Format as rr,RGBA_ASTC_12x10_Format as sr,RGBA_ASTC_12x12_Format as ir,RGBA_BPTC_Format as nr,RED_RGTC1_Format as or,SIGNED_RED_RGTC1_Format as ar,RED_GREEN_RGTC2_Format as ur,SIGNED_RED_GREEN_RGTC2_Format as lr,RepeatWrapping as dr,ClampToEdgeWrapping as cr,MirroredRepeatWrapping as hr,NearestFilter as pr,NearestMipmapNearestFilter as gr,NeverCompare as mr,AlwaysCompare as fr,LessEqualCompare as yr,EqualCompare as xr,GreaterEqualCompare as br,GreaterCompare as Tr,NotEqualCompare as _r,warnOnce as vr,NotEqualStencilFunc as Nr,GreaterStencilFunc as Sr,GreaterEqualStencilFunc as Ar,EqualStencilFunc as Rr,LessEqualStencilFunc as Cr,LessStencilFunc as Er,AlwaysStencilFunc as wr,NeverStencilFunc as Mr,DecrementWrapStencilOp as Br,IncrementWrapStencilOp as Ur,DecrementStencilOp as Fr,IncrementStencilOp as Pr,InvertStencilOp as Ir,ReplaceStencilOp as Lr,ZeroStencilOp as Vr,KeepStencilOp as Dr,MaxEquation as Or,MinEquation as Gr,SpotLight as kr,PointLight as zr,DirectionalLight as $r,RectAreaLight as Hr,AmbientLight as Wr,HemisphereLight as jr,LightProbe as qr,LinearToneMapping as Kr,ReinhardToneMapping as Xr,CineonToneMapping as Yr,ACESFilmicToneMapping as Qr,AgXToneMapping as Zr,NeutralToneMapping as Jr,Group as es,Loader as ts,FileLoader as rs,MaterialLoader as ss,ObjectLoader as is}from"./three.core.min.js";export{AdditiveAnimationBlendMode,AnimationAction,AnimationClip,AnimationLoader,AnimationMixer,AnimationObjectGroup,AnimationUtils,ArcCurve,ArrayCamera,ArrowHelper,AttachedBindMode,Audio,AudioAnalyser,AudioContext,AudioListener,AudioLoader,AxesHelper,BasicDepthPacking,BatchedMesh,Bone,BooleanKeyframeTrack,Box2,Box3,Box3Helper,BoxHelper,BufferGeometryLoader,Cache,Camera,CameraHelper,CanvasTexture,CapsuleGeometry,CatmullRomCurve3,CircleGeometry,Clock,ColorKeyframeTrack,CompressedArrayTexture,CompressedCubeTexture,CompressedTexture,CompressedTextureLoader,ConeGeometry,ConstantAlphaFactor,ConstantColorFactor,Controls,CubeTextureLoader,CubicBezierCurve,CubicBezierCurve3,CubicInterpolant,CullFaceFrontBack,Curve,CurvePath,CustomToneMapping,CylinderGeometry,Cylindrical,Data3DTexture,DataTextureLoader,DataUtils,DefaultLoadingManager,DetachedBindMode,DirectionalLightHelper,DiscreteInterpolant,DodecahedronGeometry,DynamicCopyUsage,DynamicReadUsage,EdgesGeometry,EllipseCurve,ExtrudeGeometry,Fog,FogExp2,GLBufferAttribute,GLSL1,GLSL3,GridHelper,HemisphereLightHelper,IcosahedronGeometry,ImageBitmapLoader,ImageLoader,ImageUtils,InstancedBufferGeometry,InstancedMesh,Int16BufferAttribute,Int32BufferAttribute,Int8BufferAttribute,Interpolant,InterpolateDiscrete,InterpolateLinear,InterpolateSmooth,KeyframeTrack,LOD,LatheGeometry,Layers,Light,Line,Line3,LineCurve,LineCurve3,LineLoop,LineSegments,LinearInterpolant,LinearMipMapNearestFilter,LinearTransfer,LoaderUtils,LoadingManager,LoopOnce,LoopPingPong,LoopRepeat,MOUSE,Matrix2,MeshDepthMaterial,MeshDistanceMaterial,NearestMipMapLinearFilter,NearestMipMapNearestFilter,NormalAnimationBlendMode,NumberKeyframeTrack,OctahedronGeometry,OneMinusConstantAlphaFactor,OneMinusConstantColorFactor,PCFSoftShadowMap,Path,PlaneGeometry,PlaneHelper,PointLightHelper,Points,PolarGridHelper,PolyhedronGeometry,PositionalAudio,PropertyBinding,PropertyMixer,QuadraticBezierCurve,QuadraticBezierCurve3,Quaternion,QuaternionKeyframeTrack,QuaternionLinearInterpolant,RGBADepthPacking,RGBDepthPacking,RGB_BPTC_SIGNED_Format,RGB_BPTC_UNSIGNED_Format,RGDepthPacking,RawShaderMaterial,Ray,Raycaster,RingGeometry,ShaderMaterial,Shape,ShapeGeometry,ShapePath,ShapeUtils,Skeleton,SkeletonHelper,SkinnedMesh,Source,Sphere,Spherical,SphericalHarmonics3,SplineCurve,SpotLightHelper,Sprite,StaticCopyUsage,StaticReadUsage,StereoCamera,StreamCopyUsage,StreamDrawUsage,StreamReadUsage,StringKeyframeTrack,TOUCH,TetrahedronGeometry,TextureLoader,TextureUtils,TorusGeometry,TorusKnotGeometry,Triangle,TriangleFanDrawMode,TriangleStripDrawMode,TrianglesDrawMode,TubeGeometry,Uint8BufferAttribute,Uint8ClampedBufferAttribute,Uniform,UniformsGroup,VectorKeyframeTrack,VideoTexture,WebGL3DRenderTarget,WebGLArrayRenderTarget,WebGLRenderTarget,WireframeGeometry,WrapAroundEnding,ZeroCurvatureEnding,ZeroSlopeEnding}from"./three.core.min.js";const ns=["alphaMap","alphaTest","anisotropy","anisotropyMap","anisotropyRotation","aoMap","attenuationColor","attenuationDistance","bumpMap","clearcoat","clearcoatMap","clearcoatNormalMap","clearcoatNormalScale","clearcoatRoughness","color","dispersion","displacementMap","emissive","emissiveMap","envMap","gradientMap","ior","iridescence","iridescenceIOR","iridescenceMap","iridescenceThicknessMap","lightMap","map","matcap","metalness","metalnessMap","normalMap","normalScale","opacity","roughness","roughnessMap","sheen","sheenColor","sheenColorMap","sheenRoughnessMap","shininess","specular","specularColor","specularColorMap","specularIntensity","specularIntensityMap","specularMap","thickness","transmission","transmissionMap"];class os{constructor(e){this.renderObjects=new WeakMap,this.hasNode=this.containsNode(e),this.hasAnimation=!0===e.object.isSkinnedMesh,this.refreshUniforms=ns,this.renderId=0}firstInitialization(e){return!1===this.renderObjects.has(e)&&(this.getRenderObjectData(e),!0)}getRenderObjectData(e){let t=this.renderObjects.get(e);if(void 0===t){const{geometry:r,material:s,object:i}=e;if(t={material:this.getMaterialData(s),geometry:{attributes:this.getAttributesData(r.attributes),indexVersion:r.index?r.index.version:null,drawRange:{start:r.drawRange.start,count:r.drawRange.count}},worldMatrix:i.matrixWorld.clone()},i.center&&(t.center=i.center.clone()),i.morphTargetInfluences&&(t.morphTargetInfluences=i.morphTargetInfluences.slice()),null!==e.bundle&&(t.version=e.bundle.version),t.material.transmission>0){const{width:r,height:s}=e.context;t.bufferWidth=r,t.bufferHeight=s}this.renderObjects.set(e,t)}return t}getAttributesData(e){const t={};for(const r in e){const s=e[r];t[r]={version:s.version}}return t}containsNode(e){const t=e.material;for(const e in t)if(t[e]&&t[e].isNode)return!0;return null!==e.renderer.nodes.modelViewMatrix||null!==e.renderer.nodes.modelNormalViewMatrix}getMaterialData(e){const t={};for(const r of this.refreshUniforms){const s=e[r];null!=s&&("object"==typeof s&&void 0!==s.clone?!0===s.isTexture?t[r]={id:s.id,version:s.version}:t[r]=s.clone():t[r]=s)}return t}equals(e){const{object:t,material:r,geometry:s}=e,i=this.getRenderObjectData(e);if(!0!==i.worldMatrix.equals(t.matrixWorld))return i.worldMatrix.copy(t.matrixWorld),!1;const n=i.material;for(const e in n){const t=n[e],s=r[e];if(void 0!==t.equals){if(!1===t.equals(s))return t.copy(s),!1}else if(!0===s.isTexture){if(t.id!==s.id||t.version!==s.version)return t.id=s.id,t.version=s.version,!1}else if(t!==s)return n[e]=s,!1}if(n.transmission>0){const{width:t,height:r}=e.context;if(i.bufferWidth!==t||i.bufferHeight!==r)return i.bufferWidth=t,i.bufferHeight=r,!1}const o=i.geometry,a=s.attributes,u=o.attributes,l=Object.keys(u),d=Object.keys(a);if(l.length!==d.length)return i.geometry.attributes=this.getAttributesData(a),!1;for(const e of l){const t=u[e],r=a[e];if(void 0===r)return delete u[e],!1;if(t.version!==r.version)return t.version=r.version,!1}const c=s.index,h=o.indexVersion,p=c?c.version:null;if(h!==p)return o.indexVersion=p,!1;if(o.drawRange.start!==s.drawRange.start||o.drawRange.count!==s.drawRange.count)return o.drawRange.start=s.drawRange.start,o.drawRange.count=s.drawRange.count,!1;if(i.morphTargetInfluences){let e=!1;for(let r=0;r>>16,2246822507),r^=Math.imul(s^s>>>13,3266489909),s=Math.imul(s^s>>>16,2246822507),s^=Math.imul(r^r>>>13,3266489909),4294967296*(2097151&s)+(r>>>0)}const us=e=>as(e),ls=e=>as(e),ds=(...e)=>as(e);function cs(e,t=!1){const r=[];!0===e.isNode&&(r.push(e.id),e=e.getSelf());for(const{property:s,childNode:i}of hs(e))r.push(r,as(s.slice(0,-4)),i.getCacheKey(t));return as(r)}function*hs(e,t=!1){for(const r in e){if(!0===r.startsWith("_"))continue;const s=e[r];if(!0===Array.isArray(s))for(let e=0;ee.charCodeAt(0))).buffer}var Ts=Object.freeze({__proto__:null,arrayBufferToBase64:xs,base64ToArrayBuffer:bs,getCacheKey:cs,getLengthFromType:ms,getNodeChildren:hs,getTypeFromLength:gs,getValueFromType:ys,getValueType:fs,hash:ds,hashArray:ls,hashString:us});const _s={VERTEX:"vertex",FRAGMENT:"fragment"},vs={NONE:"none",FRAME:"frame",RENDER:"render",OBJECT:"object"},Ns={BOOLEAN:"bool",INTEGER:"int",FLOAT:"float",VECTOR2:"vec2",VECTOR3:"vec3",VECTOR4:"vec4",MATRIX2:"mat2",MATRIX3:"mat3",MATRIX4:"mat4"},Ss={READ_ONLY:"readOnly",WRITE_ONLY:"writeOnly",READ_WRITE:"readWrite"},As=["fragment","vertex"],Rs=["setup","analyze","generate"],Cs=[...As,"compute"],Es=["x","y","z","w"];let ws=0;class Ms extends o{static get type(){return"Node"}constructor(e=null){super(),this.nodeType=e,this.updateType=vs.NONE,this.updateBeforeType=vs.NONE,this.updateAfterType=vs.NONE,this.uuid=a.generateUUID(),this.version=0,this.global=!1,this.isNode=!0,this._cacheKey=null,this._cacheKeyVersion=0,Object.defineProperty(this,"id",{value:ws++})}set needsUpdate(e){!0===e&&this.version++}get type(){return this.constructor.type}onUpdate(e,t){return this.updateType=t,this.update=e.bind(this.getSelf()),this}onFrameUpdate(e){return this.onUpdate(e,vs.FRAME)}onRenderUpdate(e){return this.onUpdate(e,vs.RENDER)}onObjectUpdate(e){return this.onUpdate(e,vs.OBJECT)}onReference(e){return this.updateReference=e.bind(this.getSelf()),this}getSelf(){return this.self||this}updateReference(){return this}isGlobal(){return this.global}*getChildren(){for(const{childNode:e}of hs(this))yield e}dispose(){this.dispatchEvent({type:"dispose"})}traverse(e){e(this);for(const t of this.getChildren())t.traverse(e)}getCacheKey(e=!1){return!0!==(e=e||this.version!==this._cacheKeyVersion)&&null!==this._cacheKey||(this._cacheKey=ds(cs(this,e),this.customCacheKey()),this._cacheKeyVersion=this.version),this._cacheKey}customCacheKey(){return 0}getScope(){return this}getHash(){return this.uuid}getUpdateType(){return this.updateType}getUpdateBeforeType(){return this.updateBeforeType}getUpdateAfterType(){return this.updateAfterType}getElementType(e){const t=this.getNodeType(e);return e.getElementType(t)}getNodeType(e){const t=e.getNodeProperties(this);return t.outputNode?t.outputNode.getNodeType(e):this.nodeType}getShared(e){const t=this.getHash(e);return e.getNodeFromHash(t)||this}setup(e){const t=e.getNodeProperties(this);let r=0;for(const e of this.getChildren())t["node"+r++]=e;return null}analyze(e){if(1===e.increaseUsage(this)){const t=e.getNodeProperties(this);for(const r of Object.values(t))r&&!0===r.isNode&&r.build(e)}}generate(e,t){const{outputNode:r}=e.getNodeProperties(this);if(r&&!0===r.isNode)return r.build(e,t)}updateBefore(){console.warn("Abstract function.")}updateAfter(){console.warn("Abstract function.")}update(){console.warn("Abstract function.")}build(e,t=null){const r=this.getShared(e);if(this!==r)return r.build(e,t);e.addNode(this),e.addChain(this);let s=null;const i=e.getBuildStage();if("setup"===i){this.updateReference(e);const t=e.getNodeProperties(this);if(!0!==t.initialized){e.stack.nodes.length;t.initialized=!0,t.outputNode=this.setup(e),null!==t.outputNode&&e.stack.nodes.length;for(const r of Object.values(t))r&&!0===r.isNode&&r.build(e)}}else if("analyze"===i)this.analyze(e);else if("generate"===i){if(1===this.generate.length){const r=this.getNodeType(e),i=e.getDataFromNode(this);s=i.snippet,void 0===s?(s=this.generate(e)||"",i.snippet=s):void 0!==i.flowCodes&&void 0!==e.context.nodeBlock&&e.addFlowCodeHierarchy(this,e.context.nodeBlock),s=e.format(s,r,t)}else s=this.generate(e,t)||""}return e.removeChain(this),e.addSequentialNode(this),s}getSerializeChildren(){return hs(this)}serialize(e){const t=this.getSerializeChildren(),r={};for(const{property:s,index:i,childNode:n}of t)void 0!==i?(void 0===r[s]&&(r[s]=Number.isInteger(i)?[]:{}),r[s][i]=n.toJSON(e.meta).uuid):r[s]=n.toJSON(e.meta).uuid;Object.keys(r).length>0&&(e.inputNodes=r)}deserialize(e){if(void 0!==e.inputNodes){const t=e.meta.nodes;for(const r in e.inputNodes)if(Array.isArray(e.inputNodes[r])){const s=[];for(const i of e.inputNodes[r])s.push(t[i]);this[r]=s}else if("object"==typeof e.inputNodes[r]){const s={};for(const i in e.inputNodes[r]){const n=e.inputNodes[r][i];s[i]=t[n]}this[r]=s}else{const s=e.inputNodes[r];this[r]=t[s]}}}toJSON(e){const{uuid:t,type:r}=this,s=void 0===e||"string"==typeof e;s&&(e={textures:{},images:{},nodes:{}});let i=e.nodes[t];function n(e){const t=[];for(const r in e){const s=e[r];delete s.metadata,t.push(s)}return t}if(void 0===i&&(i={uuid:t,type:r,meta:e,metadata:{version:4.6,type:"Node",generator:"Node.toJSON"}},!0!==s&&(e.nodes[i.uuid]=i),this.serialize(i),delete i.meta),s){const t=n(e.textures),r=n(e.images),s=n(e.nodes);t.length>0&&(i.textures=t),r.length>0&&(i.images=r),s.length>0&&(i.nodes=s)}return i}}class Bs extends Ms{static get type(){return"ArrayElementNode"}constructor(e,t){super(),this.node=e,this.indexNode=t,this.isArrayElementNode=!0}getNodeType(e){return this.node.getElementType(e)}generate(e){return`${this.node.build(e)}[ ${this.indexNode.build(e,"uint")} ]`}}class Us extends Ms{static get type(){return"ConvertNode"}constructor(e,t){super(),this.node=e,this.convertTo=t}getNodeType(e){const t=this.node.getNodeType(e);let r=null;for(const s of this.convertTo.split("|"))null!==r&&e.getTypeLength(t)!==e.getTypeLength(s)||(r=s);return r}serialize(e){super.serialize(e),e.convertTo=this.convertTo}deserialize(e){super.deserialize(e),this.convertTo=e.convertTo}generate(e,t){const r=this.node,s=this.getNodeType(e),i=r.build(e,s);return e.format(i,s,t)}}class Fs extends Ms{static get type(){return"TempNode"}constructor(e=null){super(e),this.isTempNode=!0}hasDependencies(e){return e.getDataFromNode(this).usageCount>1}build(e,t){if("generate"===e.getBuildStage()){const r=e.getVectorType(this.getNodeType(e,t)),s=e.getDataFromNode(this);if(void 0!==s.propertyName)return e.format(s.propertyName,r,t);if("void"!==r&&"void"!==t&&this.hasDependencies(e)){const i=super.build(e,r),n=e.getVarFromNode(this,null,r),o=e.getPropertyName(n);return e.addLineFlowCode(`${o} = ${i}`,this),s.snippet=i,s.propertyName=o,e.format(s.propertyName,r,t)}}return super.build(e,t)}}class Ps extends Fs{static get type(){return"JoinNode"}constructor(e=[],t=null){super(t),this.nodes=e}getNodeType(e){return null!==this.nodeType?e.getVectorType(this.nodeType):e.getTypeFromLength(this.nodes.reduce(((t,r)=>t+e.getTypeLength(r.getNodeType(e))),0))}generate(e,t){const r=this.getNodeType(e),s=this.nodes,i=e.getComponentType(r),n=[];for(const t of s){let r=t.build(e);const s=e.getComponentType(t.getNodeType(e));s!==i&&(r=e.format(r,s,i)),n.push(r)}const o=`${e.getType(r)}( ${n.join(", ")} )`;return e.format(o,r,t)}}const Is=Es.join("");class Ls extends Ms{static get type(){return"SplitNode"}constructor(e,t="x"){super(),this.node=e,this.components=t,this.isSplitNode=!0}getVectorLength(){let e=this.components.length;for(const t of this.components)e=Math.max(Es.indexOf(t)+1,e);return e}getComponentType(e){return e.getComponentType(this.node.getNodeType(e))}getNodeType(e){return e.getTypeFromLength(this.components.length,this.getComponentType(e))}generate(e,t){const r=this.node,s=e.getTypeLength(r.getNodeType(e));let i=null;if(s>1){let n=null;this.getVectorLength()>=s&&(n=e.getTypeFromLength(this.getVectorLength(),this.getComponentType(e)));const o=r.build(e,n);i=this.components.length===s&&this.components===Is.slice(0,this.components.length)?e.format(o,n,t):e.format(`${o}.${this.components}`,this.getNodeType(e),t)}else i=r.build(e,t);return i}serialize(e){super.serialize(e),e.components=this.components}deserialize(e){super.deserialize(e),this.components=e.components}}class Vs extends Fs{static get type(){return"SetNode"}constructor(e,t,r){super(),this.sourceNode=e,this.components=t,this.targetNode=r}getNodeType(e){return this.sourceNode.getNodeType(e)}generate(e){const{sourceNode:t,components:r,targetNode:s}=this,i=this.getNodeType(e),n=e.getComponentType(s.getNodeType(e)),o=e.getTypeFromLength(r.length,n),a=s.build(e,o),u=t.build(e,i),l=e.getTypeLength(i),d=[];for(let e=0;ee.replace(/r|s/g,"x").replace(/g|t/g,"y").replace(/b|p/g,"z").replace(/a|q/g,"w"),Ws=e=>Hs(e).split("").sort().join(""),js={setup(e,t){const r=t.shift();return e(yi(r),...t)},get(e,t,r){if("string"==typeof t&&void 0===e[t]){if(!0!==e.isStackNode&&"assign"===t)return(...e)=>(ks.assign(r,...e),r);if(zs.has(t)){const s=zs.get(t);return e.isStackNode?(...e)=>r.add(s(...e)):(...e)=>s(r,...e)}if("self"===t)return e;if(t.endsWith("Assign")&&zs.has(t.slice(0,t.length-6))){const s=zs.get(t.slice(0,t.length-6));return e.isStackNode?(...e)=>r.assign(e[0],s(...e)):(...e)=>r.assign(s(r,...e))}if(!0===/^[xyzwrgbastpq]{1,4}$/.test(t))return t=Hs(t),fi(new Ls(r,t));if(!0===/^set[XYZWRGBASTPQ]{1,4}$/.test(t))return t=Ws(t.slice(3).toLowerCase()),r=>fi(new Vs(e,t,r));if(!0===/^flip[XYZWRGBASTPQ]{1,4}$/.test(t))return t=Ws(t.slice(4).toLowerCase()),()=>fi(new Ds(fi(e),t));if("width"===t||"height"===t||"depth"===t)return"width"===t?t="x":"height"===t?t="y":"depth"===t&&(t="z"),fi(new Ls(e,t));if(!0===/^\d+$/.test(t))return fi(new Bs(r,new Gs(Number(t),"uint")))}return Reflect.get(e,t,r)},set:(e,t,r,s)=>"string"!=typeof t||void 0!==e[t]||!0!==/^[xyzwrgbastpq]{1,4}$/.test(t)&&"width"!==t&&"height"!==t&&"depth"!==t&&!0!==/^\d+$/.test(t)?Reflect.set(e,t,r,s):(s[t].assign(r),!0)},qs=new WeakMap,Ks=new WeakMap,Xs=function(e,t=null){for(const r in e)e[r]=fi(e[r],t);return e},Ys=function(e,t=null){const r=e.length;for(let s=0;sfi(null!==s?Object.assign(e,s):e);return null===t?(...t)=>i(new e(...xi(t))):null!==r?(r=fi(r),(...s)=>i(new e(t,...xi(s),r))):(...r)=>i(new e(t,...xi(r)))},Zs=function(e,...t){return fi(new e(...xi(t)))};class Js extends Ms{constructor(e,t){super(),this.shaderNode=e,this.inputNodes=t}getNodeType(e){return this.shaderNode.nodeType||this.getOutputNode(e).getNodeType(e)}call(e){const{shaderNode:t,inputNodes:r}=this,s=e.getNodeProperties(t);if(s.onceOutput)return s.onceOutput;let i=null;if(t.layout){let s=Ks.get(e.constructor);void 0===s&&(s=new WeakMap,Ks.set(e.constructor,s));let n=s.get(t);void 0===n&&(n=fi(e.buildFunctionNode(t)),s.set(t,n)),null!==e.currentFunctionNode&&e.currentFunctionNode.includes.push(n),i=fi(n.call(r))}else{const s=t.jsFunc,n=null!==r?s(r,e):s(e);i=fi(n)}return t.once&&(s.onceOutput=i),i}getOutputNode(e){const t=e.getNodeProperties(this);return null===t.outputNode&&(t.outputNode=this.setupOutput(e)),t.outputNode}setup(e){return this.getOutputNode(e)}setupOutput(e){return e.addStack(),e.stack.outputNode=this.call(e),e.removeStack()}generate(e,t){return this.getOutputNode(e).build(e,t)}}class ei extends Ms{constructor(e,t){super(t),this.jsFunc=e,this.layout=null,this.global=!0,this.once=!1}setLayout(e){return this.layout=e,this}call(e=null){return yi(e),fi(new Js(this,e))}setup(){return this.call()}}const ti=[!1,!0],ri=[0,1,2,3],si=[-1,-2],ii=[.5,1.5,1/3,1e-6,1e6,Math.PI,2*Math.PI,1/Math.PI,2/Math.PI,1/(2*Math.PI),Math.PI/2],ni=new Map;for(const e of ti)ni.set(e,new Gs(e));const oi=new Map;for(const e of ri)oi.set(e,new Gs(e,"uint"));const ai=new Map([...oi].map((e=>new Gs(e.value,"int"))));for(const e of si)ai.set(e,new Gs(e,"int"));const ui=new Map([...ai].map((e=>new Gs(e.value))));for(const e of ii)ui.set(e,new Gs(e));for(const e of ii)ui.set(-e,new Gs(-e));const li={bool:ni,uint:oi,ints:ai,float:ui},di=new Map([...ni,...ui]),ci=(e,t)=>di.has(e)?di.get(e):!0===e.isNode?e:new Gs(e,t),hi=function(e,t=null){return(...r)=>{if((0===r.length||!["bool","float","int","uint"].includes(e)&&r.every((e=>"object"!=typeof e)))&&(r=[ys(e,...r)]),1===r.length&&null!==t&&t.has(r[0]))return fi(t.get(r[0]));if(1===r.length){const t=ci(r[0],e);return(e=>{try{return e.getNodeType()}catch(e){return}})(t)===e?fi(t):fi(new Us(t,e))}const s=r.map((e=>ci(e)));return fi(new Ps(s,e))}},pi=e=>"object"==typeof e&&null!==e?e.value:e,gi=e=>null!=e?e.nodeType||e.convertTo||("string"==typeof e?e:null):null;function mi(e,t){return new Proxy(new ei(e,t),js)}const fi=(e,t=null)=>function(e,t=null){const r=fs(e);if("node"===r){let t=qs.get(e);return void 0===t&&(t=new Proxy(e,js),qs.set(e,t),qs.set(t,t)),t}return null===t&&("float"===r||"boolean"===r)||r&&"shader"!==r&&"string"!==r?fi(ci(e,t)):"shader"===r?_i(e):e}(e,t),yi=(e,t=null)=>new Xs(e,t),xi=(e,t=null)=>new Ys(e,t),bi=(...e)=>new Qs(...e),Ti=(...e)=>new Zs(...e),_i=(e,t)=>{const r=new mi(e,t),s=(...e)=>{let t;return yi(e),t=e[0]&&e[0].isNode?[...e]:e[0],r.call(t)};return s.shaderNode=r,s.setLayout=e=>(r.setLayout(e),s),s.once=()=>(r.once=!0,s),s};$s("toGlobal",(e=>(e.global=!0,e)));const vi=e=>{ks=e},Ni=()=>ks,Si=(...e)=>ks.If(...e);function Ai(e){return ks&&ks.add(e),e}$s("append",Ai);const Ri=new hi("color"),Ci=new hi("float",li.float),Ei=new hi("int",li.ints),wi=new hi("uint",li.uint),Mi=new hi("bool",li.bool),Bi=new hi("vec2"),Ui=new hi("ivec2"),Fi=new hi("uvec2"),Pi=new hi("bvec2"),Ii=new hi("vec3"),Li=new hi("ivec3"),Vi=new hi("uvec3"),Di=new hi("bvec3"),Oi=new hi("vec4"),Gi=new hi("ivec4"),ki=new hi("uvec4"),zi=new hi("bvec4"),$i=new hi("mat2"),Hi=new hi("mat3"),Wi=new hi("mat4");$s("toColor",Ri),$s("toFloat",Ci),$s("toInt",Ei),$s("toUint",wi),$s("toBool",Mi),$s("toVec2",Bi),$s("toIVec2",Ui),$s("toUVec2",Fi),$s("toBVec2",Pi),$s("toVec3",Ii),$s("toIVec3",Li),$s("toUVec3",Vi),$s("toBVec3",Di),$s("toVec4",Oi),$s("toIVec4",Gi),$s("toUVec4",ki),$s("toBVec4",zi),$s("toMat2",$i),$s("toMat3",Hi),$s("toMat4",Wi);const ji=bi(Bs),qi=(e,t)=>fi(new Us(fi(e),t));$s("element",ji),$s("convert",qi);class Ki extends Ms{static get type(){return"UniformGroupNode"}constructor(e,t=!1,r=1){super("string"),this.name=e,this.shared=t,this.order=r,this.isUniformGroup=!0}serialize(e){super.serialize(e),e.name=this.name,e.version=this.version,e.shared=this.shared}deserialize(e){super.deserialize(e),this.name=e.name,this.version=e.version,this.shared=e.shared}}const Xi=e=>new Ki(e),Yi=(e,t=0)=>new Ki(e,!0,t),Qi=Yi("frame"),Zi=Yi("render"),Ji=Xi("object");class en extends Os{static get type(){return"UniformNode"}constructor(e,t=null){super(e,t),this.isUniformNode=!0,this.name="",this.groupNode=Ji}label(e){return this.name=e,this}setGroup(e){return this.groupNode=e,this}getGroup(){return this.groupNode}getUniformHash(e){return this.getHash(e)}onUpdate(e,t){const r=this.getSelf();return e=e.bind(r),super.onUpdate((t=>{const s=e(t,r);void 0!==s&&(this.value=s)}),t)}generate(e,t){const r=this.getNodeType(e),s=this.getUniformHash(e);let i=e.getNodeFromHash(s);void 0===i&&(e.setHashNode(this,s),i=this);const n=i.getInputType(e),o=e.getUniformFromNode(i,n,e.shaderStage,this.name||e.context.label),a=e.getPropertyName(o);return void 0!==e.context.label&&delete e.context.label,e.format(a,r,t)}}const tn=(e,t)=>{const r=gi(t||e),s=e&&!0===e.isNode?e.node&&e.node.value||e.value:e;return fi(new en(s,r))};class rn extends Ms{static get type(){return"PropertyNode"}constructor(e,t=null,r=!1){super(e),this.name=t,this.varying=r,this.isPropertyNode=!0}getHash(e){return this.name||super.getHash(e)}isGlobal(){return!0}generate(e){let t;return!0===this.varying?(t=e.getVaryingFromNode(this,this.name),t.needsInterpolation=!0):t=e.getVarFromNode(this,this.name),e.getPropertyName(t)}}const sn=(e,t)=>fi(new rn(e,t)),nn=(e,t)=>fi(new rn(e,t,!0)),on=Ti(rn,"vec4","DiffuseColor"),an=Ti(rn,"vec3","EmissiveColor"),un=Ti(rn,"float","Roughness"),ln=Ti(rn,"float","Metalness"),dn=Ti(rn,"float","Clearcoat"),cn=Ti(rn,"float","ClearcoatRoughness"),hn=Ti(rn,"vec3","Sheen"),pn=Ti(rn,"float","SheenRoughness"),gn=Ti(rn,"float","Iridescence"),mn=Ti(rn,"float","IridescenceIOR"),fn=Ti(rn,"float","IridescenceThickness"),yn=Ti(rn,"float","AlphaT"),xn=Ti(rn,"float","Anisotropy"),bn=Ti(rn,"vec3","AnisotropyT"),Tn=Ti(rn,"vec3","AnisotropyB"),_n=Ti(rn,"color","SpecularColor"),vn=Ti(rn,"float","SpecularF90"),Nn=Ti(rn,"float","Shininess"),Sn=Ti(rn,"vec4","Output"),An=Ti(rn,"float","dashSize"),Rn=Ti(rn,"float","gapSize"),Cn=Ti(rn,"float","pointWidth"),En=Ti(rn,"float","IOR"),wn=Ti(rn,"float","Transmission"),Mn=Ti(rn,"float","Thickness"),Bn=Ti(rn,"float","AttenuationDistance"),Un=Ti(rn,"color","AttenuationColor"),Fn=Ti(rn,"float","Dispersion");class Pn extends Fs{static get type(){return"AssignNode"}constructor(e,t){super(),this.targetNode=e,this.sourceNode=t}hasDependencies(){return!1}getNodeType(e,t){return"void"!==t?this.targetNode.getNodeType(e):"void"}needsSplitAssign(e){const{targetNode:t}=this;if(!1===e.isAvailable("swizzleAssign")&&t.isSplitNode&&t.components.length>1){const r=e.getTypeLength(t.node.getNodeType(e));return Es.join("").slice(0,r)!==t.components}return!1}generate(e,t){const{targetNode:r,sourceNode:s}=this,i=this.needsSplitAssign(e),n=r.getNodeType(e),o=r.context({assign:!0}).build(e),a=s.build(e,n),u=s.getNodeType(e),l=e.getDataFromNode(this);let d;if(!0===l.initialized)"void"!==t&&(d=o);else if(i){const s=e.getVarFromNode(this,null,n),i=e.getPropertyName(s);e.addLineFlowCode(`${i} = ${a}`,this);const u=r.node.context({assign:!0}).build(e);for(let t=0;t{const s=r.type;let i;return i="pointer"===s?"&"+t.build(e):t.build(e,s),i};if(Array.isArray(i))for(let e=0;e(t=t.length>1||t[0]&&!0===t[0].isNode?xi(t):yi(t[0]),fi(new Ln(fi(e),t)));$s("call",Vn);class Dn extends Fs{static get type(){return"OperatorNode"}constructor(e,t,r,...s){if(super(),s.length>0){let i=new Dn(e,t,r);for(let t=0;t>"===r||"<<"===r)return e.getIntegerType(n);if("!"===r||"=="===r||"&&"===r||"||"===r||"^^"===r)return"bool";if("<"===r||">"===r||"<="===r||">="===r){const r=t?e.getTypeLength(t):Math.max(e.getTypeLength(n),e.getTypeLength(o));return r>1?`bvec${r}`:"bool"}return"float"===n&&e.isMatrix(o)?o:e.isMatrix(n)&&e.isVector(o)?e.getVectorFromMatrix(n):e.isVector(n)&&e.isMatrix(o)?e.getVectorFromMatrix(o):e.getTypeLength(o)>e.getTypeLength(n)?o:n}generate(e,t){const r=this.op,s=this.aNode,i=this.bNode,n=this.getNodeType(e,t);let o=null,a=null;"void"!==n?(o=s.getNodeType(e),a=void 0!==i?i.getNodeType(e):null,"<"===r||">"===r||"<="===r||">="===r||"=="===r?e.isVector(o)?a=o:o!==a&&(o=a="float"):">>"===r||"<<"===r?(o=n,a=e.changeComponentType(a,"uint")):e.isMatrix(o)&&e.isVector(a)?a=e.getVectorFromMatrix(o):o=e.isVector(o)&&e.isMatrix(a)?e.getVectorFromMatrix(a):a=n):o=a=n;const u=s.build(e,o),l=void 0!==i?i.build(e,a):null,d=e.getTypeLength(t),c=e.getFunctionOperator(r);return"void"!==t?"<"===r&&d>1?e.useComparisonMethod?e.format(`${e.getMethod("lessThan",t)}( ${u}, ${l} )`,n,t):e.format(`( ${u} < ${l} )`,n,t):"<="===r&&d>1?e.useComparisonMethod?e.format(`${e.getMethod("lessThanEqual",t)}( ${u}, ${l} )`,n,t):e.format(`( ${u} <= ${l} )`,n,t):">"===r&&d>1?e.useComparisonMethod?e.format(`${e.getMethod("greaterThan",t)}( ${u}, ${l} )`,n,t):e.format(`( ${u} > ${l} )`,n,t):">="===r&&d>1?e.useComparisonMethod?e.format(`${e.getMethod("greaterThanEqual",t)}( ${u}, ${l} )`,n,t):e.format(`( ${u} >= ${l} )`,n,t):"!"===r||"~"===r?e.format(`(${r}${u})`,o,t):c?e.format(`${c}( ${u}, ${l} )`,n,t):e.format(`( ${u} ${r} ${l} )`,n,t):"void"!==o?c?e.format(`${c}( ${u}, ${l} )`,n,t):e.format(`${u} ${r} ${l}`,n,t):void 0}serialize(e){super.serialize(e),e.op=this.op}deserialize(e){super.deserialize(e),this.op=e.op}}const On=bi(Dn,"+"),Gn=bi(Dn,"-"),kn=bi(Dn,"*"),zn=bi(Dn,"/"),$n=bi(Dn,"%"),Hn=bi(Dn,"=="),Wn=bi(Dn,"!="),jn=bi(Dn,"<"),qn=bi(Dn,">"),Kn=bi(Dn,"<="),Xn=bi(Dn,">="),Yn=bi(Dn,"&&"),Qn=bi(Dn,"||"),Zn=bi(Dn,"!"),Jn=bi(Dn,"^^"),eo=bi(Dn,"&"),to=bi(Dn,"~"),ro=bi(Dn,"|"),so=bi(Dn,"^"),io=bi(Dn,"<<"),no=bi(Dn,">>");$s("add",On),$s("sub",Gn),$s("mul",kn),$s("div",zn),$s("modInt",$n),$s("equal",Hn),$s("notEqual",Wn),$s("lessThan",jn),$s("greaterThan",qn),$s("lessThanEqual",Kn),$s("greaterThanEqual",Xn),$s("and",Yn),$s("or",Qn),$s("not",Zn),$s("xor",Jn),$s("bitAnd",eo),$s("bitNot",to),$s("bitOr",ro),$s("bitXor",so),$s("shiftLeft",io),$s("shiftRight",no);const oo=(...e)=>(console.warn("TSL.OperatorNode: .remainder() has been renamed to .modInt()."),$n(...e));$s("remainder",oo);class ao extends Fs{static get type(){return"MathNode"}constructor(e,t,r=null,s=null){super(),this.method=e,this.aNode=t,this.bNode=r,this.cNode=s}getInputType(e){const t=this.aNode.getNodeType(e),r=this.bNode?this.bNode.getNodeType(e):null,s=this.cNode?this.cNode.getNodeType(e):null,i=e.isMatrix(t)?0:e.getTypeLength(t),n=e.isMatrix(r)?0:e.getTypeLength(r),o=e.isMatrix(s)?0:e.getTypeLength(s);return i>n&&i>o?t:n>o?r:o>i?s:t}getNodeType(e){const t=this.method;return t===ao.LENGTH||t===ao.DISTANCE||t===ao.DOT?"float":t===ao.CROSS?"vec3":t===ao.ALL?"bool":t===ao.EQUALS?e.changeComponentType(this.aNode.getNodeType(e),"bool"):t===ao.MOD?this.aNode.getNodeType(e):this.getInputType(e)}generate(e,t){let r=this.method;const s=this.getNodeType(e),i=this.getInputType(e),n=this.aNode,o=this.bNode,a=this.cNode,d=e.renderer.coordinateSystem;if(r===ao.TRANSFORM_DIRECTION){let r=n,s=o;e.isMatrix(r.getNodeType(e))?s=Oi(Ii(s),0):r=Oi(Ii(r),0);const i=kn(r,s).xyz;return Ao(i).build(e,t)}if(r===ao.NEGATE)return e.format("( - "+n.build(e,i)+" )",s,t);if(r===ao.ONE_MINUS)return Gn(1,n).build(e,t);if(r===ao.RECIPROCAL)return zn(1,n).build(e,t);if(r===ao.DIFFERENCE)return Fo(Gn(n,o)).build(e,t);{const c=[];return r===ao.CROSS||r===ao.MOD?c.push(n.build(e,s),o.build(e,s)):d===u&&r===ao.STEP?c.push(n.build(e,1===e.getTypeLength(n.getNodeType(e))?"float":i),o.build(e,i)):d===u&&(r===ao.MIN||r===ao.MAX)||r===ao.MOD?c.push(n.build(e,i),o.build(e,1===e.getTypeLength(o.getNodeType(e))?"float":i)):r===ao.REFRACT?c.push(n.build(e,i),o.build(e,i),a.build(e,"float")):r===ao.MIX?c.push(n.build(e,i),o.build(e,i),a.build(e,1===e.getTypeLength(a.getNodeType(e))?"float":i)):(d===l&&r===ao.ATAN&&null!==o&&(r="atan2"),c.push(n.build(e,i)),null!==o&&c.push(o.build(e,i)),null!==a&&c.push(a.build(e,i))),e.format(`${e.getMethod(r,s)}( ${c.join(", ")} )`,s,t)}}serialize(e){super.serialize(e),e.method=this.method}deserialize(e){super.deserialize(e),this.method=e.method}}ao.ALL="all",ao.ANY="any",ao.RADIANS="radians",ao.DEGREES="degrees",ao.EXP="exp",ao.EXP2="exp2",ao.LOG="log",ao.LOG2="log2",ao.SQRT="sqrt",ao.INVERSE_SQRT="inversesqrt",ao.FLOOR="floor",ao.CEIL="ceil",ao.NORMALIZE="normalize",ao.FRACT="fract",ao.SIN="sin",ao.COS="cos",ao.TAN="tan",ao.ASIN="asin",ao.ACOS="acos",ao.ATAN="atan",ao.ABS="abs",ao.SIGN="sign",ao.LENGTH="length",ao.NEGATE="negate",ao.ONE_MINUS="oneMinus",ao.DFDX="dFdx",ao.DFDY="dFdy",ao.ROUND="round",ao.RECIPROCAL="reciprocal",ao.TRUNC="trunc",ao.FWIDTH="fwidth",ao.TRANSPOSE="transpose",ao.BITCAST="bitcast",ao.EQUALS="equals",ao.MIN="min",ao.MAX="max",ao.MOD="mod",ao.STEP="step",ao.REFLECT="reflect",ao.DISTANCE="distance",ao.DIFFERENCE="difference",ao.DOT="dot",ao.CROSS="cross",ao.POW="pow",ao.TRANSFORM_DIRECTION="transformDirection",ao.MIX="mix",ao.CLAMP="clamp",ao.REFRACT="refract",ao.SMOOTHSTEP="smoothstep",ao.FACEFORWARD="faceforward";const uo=Ci(1e-6),lo=Ci(1e6),co=Ci(Math.PI),ho=Ci(2*Math.PI),po=bi(ao,ao.ALL),go=bi(ao,ao.ANY),mo=bi(ao,ao.RADIANS),fo=bi(ao,ao.DEGREES),yo=bi(ao,ao.EXP),xo=bi(ao,ao.EXP2),bo=bi(ao,ao.LOG),To=bi(ao,ao.LOG2),_o=bi(ao,ao.SQRT),vo=bi(ao,ao.INVERSE_SQRT),No=bi(ao,ao.FLOOR),So=bi(ao,ao.CEIL),Ao=bi(ao,ao.NORMALIZE),Ro=bi(ao,ao.FRACT),Co=bi(ao,ao.SIN),Eo=bi(ao,ao.COS),wo=bi(ao,ao.TAN),Mo=bi(ao,ao.ASIN),Bo=bi(ao,ao.ACOS),Uo=bi(ao,ao.ATAN),Fo=bi(ao,ao.ABS),Po=bi(ao,ao.SIGN),Io=bi(ao,ao.LENGTH),Lo=bi(ao,ao.NEGATE),Vo=bi(ao,ao.ONE_MINUS),Do=bi(ao,ao.DFDX),Oo=bi(ao,ao.DFDY),Go=bi(ao,ao.ROUND),ko=bi(ao,ao.RECIPROCAL),zo=bi(ao,ao.TRUNC),$o=bi(ao,ao.FWIDTH),Ho=bi(ao,ao.TRANSPOSE),Wo=bi(ao,ao.BITCAST),jo=bi(ao,ao.EQUALS),qo=bi(ao,ao.MIN),Ko=bi(ao,ao.MAX),Xo=bi(ao,ao.MOD),Yo=bi(ao,ao.STEP),Qo=bi(ao,ao.REFLECT),Zo=bi(ao,ao.DISTANCE),Jo=bi(ao,ao.DIFFERENCE),ea=bi(ao,ao.DOT),ta=bi(ao,ao.CROSS),ra=bi(ao,ao.POW),sa=bi(ao,ao.POW,2),ia=bi(ao,ao.POW,3),na=bi(ao,ao.POW,4),oa=bi(ao,ao.TRANSFORM_DIRECTION),aa=e=>kn(Po(e),ra(Fo(e),1/3)),ua=e=>ea(e,e),la=bi(ao,ao.MIX),da=(e,t=0,r=1)=>fi(new ao(ao.CLAMP,fi(e),fi(t),fi(r))),ca=e=>da(e),ha=bi(ao,ao.REFRACT),pa=bi(ao,ao.SMOOTHSTEP),ga=bi(ao,ao.FACEFORWARD),ma=_i((([e])=>{const t=ea(e.xy,Bi(12.9898,78.233)),r=Xo(t,co);return Ro(Co(r).mul(43758.5453))})),fa=(e,t,r)=>la(t,r,e),ya=(e,t,r)=>pa(t,r,e),xa=(e,t)=>(console.warn('THREE.TSL: "atan2" is overloaded. Use "atan" instead.'),Uo(e,t));$s("all",po),$s("any",go),$s("equals",jo),$s("radians",mo),$s("degrees",fo),$s("exp",yo),$s("exp2",xo),$s("log",bo),$s("log2",To),$s("sqrt",_o),$s("inverseSqrt",vo),$s("floor",No),$s("ceil",So),$s("normalize",Ao),$s("fract",Ro),$s("sin",Co),$s("cos",Eo),$s("tan",wo),$s("asin",Mo),$s("acos",Bo),$s("atan",Uo),$s("abs",Fo),$s("sign",Po),$s("length",Io),$s("lengthSq",ua),$s("negate",Lo),$s("oneMinus",Vo),$s("dFdx",Do),$s("dFdy",Oo),$s("round",Go),$s("reciprocal",ko),$s("trunc",zo),$s("fwidth",$o),$s("atan2",xa),$s("min",qo),$s("max",Ko),$s("mod",Xo),$s("step",Yo),$s("reflect",Qo),$s("distance",Zo),$s("dot",ea),$s("cross",ta),$s("pow",ra),$s("pow2",sa),$s("pow3",ia),$s("pow4",na),$s("transformDirection",oa),$s("mix",fa),$s("clamp",da),$s("refract",ha),$s("smoothstep",ya),$s("faceForward",ga),$s("difference",Jo),$s("saturate",ca),$s("cbrt",aa),$s("transpose",Ho),$s("rand",ma);class ba extends Ms{static get type(){return"ConditionalNode"}constructor(e,t,r=null){super(),this.condNode=e,this.ifNode=t,this.elseNode=r}getNodeType(e){const t=this.ifNode.getNodeType(e);if(null!==this.elseNode){const r=this.elseNode.getNodeType(e);if(e.getTypeLength(r)>e.getTypeLength(t))return r}return t}setup(e){const t=this.condNode.cache(),r=this.ifNode.cache(),s=this.elseNode?this.elseNode.cache():null,i=e.context.nodeBlock;e.getDataFromNode(r).parentNodeBlock=i,null!==s&&(e.getDataFromNode(s).parentNodeBlock=i);const n=e.getNodeProperties(this);n.condNode=t,n.ifNode=r.context({nodeBlock:r}),n.elseNode=s?s.context({nodeBlock:s}):null}generate(e,t){const r=this.getNodeType(e),s=e.getDataFromNode(this);if(void 0!==s.nodeProperty)return s.nodeProperty;const{condNode:i,ifNode:n,elseNode:o}=e.getNodeProperties(this),a="void"!==t,u=a?sn(r).build(e):"";s.nodeProperty=u;const l=i.build(e,"bool");e.addFlowCode(`\n${e.tab}if ( ${l} ) {\n\n`).addFlowTab();let d=n.build(e,r);if(d&&(d=a?u+" = "+d+";":"return "+d+";"),e.removeFlowTab().addFlowCode(e.tab+"\t"+d+"\n\n"+e.tab+"}"),null!==o){e.addFlowCode(" else {\n\n").addFlowTab();let t=o.build(e,r);t&&(t=a?u+" = "+t+";":"return "+t+";"),e.removeFlowTab().addFlowCode(e.tab+"\t"+t+"\n\n"+e.tab+"}\n\n")}else e.addFlowCode("\n\n");return e.format(u,r,t)}}const Ta=bi(ba);$s("select",Ta);const _a=(...e)=>(console.warn("TSL.ConditionalNode: cond() has been renamed to select()."),Ta(...e));$s("cond",_a);class va extends Ms{static get type(){return"ContextNode"}constructor(e,t={}){super(),this.isContextNode=!0,this.node=e,this.value=t}getScope(){return this.node.getScope()}getNodeType(e){return this.node.getNodeType(e)}analyze(e){this.node.build(e)}setup(e){const t=e.getContext();e.setContext({...e.context,...this.value});const r=this.node.build(e);return e.setContext(t),r}generate(e,t){const r=e.getContext();e.setContext({...e.context,...this.value});const s=this.node.build(e,t);return e.setContext(r),s}}const Na=bi(va),Sa=(e,t)=>Na(e,{label:t});$s("context",Na),$s("label",Sa);class Aa extends Ms{static get type(){return"VarNode"}constructor(e,t=null){super(),this.node=e,this.name=t,this.global=!0,this.isVarNode=!0}getHash(e){return this.name||super.getHash(e)}getNodeType(e){return this.node.getNodeType(e)}generate(e){const{node:t,name:r}=this,s=e.getVarFromNode(this,r,e.getVectorType(this.getNodeType(e))),i=e.getPropertyName(s),n=t.build(e,s.type);return e.addLineFlowCode(`${i} = ${n}`,this),i}}const Ra=bi(Aa);$s("toVar",((...e)=>Ra(...e).append()));const Ca=e=>(console.warn('TSL: "temp" is deprecated. Use ".toVar()" instead.'),Ra(e));$s("temp",Ca);class Ea extends Ms{static get type(){return"VaryingNode"}constructor(e,t=null){super(),this.node=e,this.name=t,this.isVaryingNode=!0}isGlobal(){return!0}getHash(e){return this.name||super.getHash(e)}getNodeType(e){return this.node.getNodeType(e)}setupVarying(e){const t=e.getNodeProperties(this);let r=t.varying;if(void 0===r){const s=this.name,i=this.getNodeType(e);t.varying=r=e.getVaryingFromNode(this,s,i),t.node=this.node}return r.needsInterpolation||(r.needsInterpolation="fragment"===e.shaderStage),r}setup(e){this.setupVarying(e)}analyze(e){return this.setupVarying(e),this.node.analyze(e)}generate(e){const t=e.getNodeProperties(this),r=this.setupVarying(e),s="fragment"===e.shaderStage&&!0===t.reassignPosition&&e.context.needsPositionReassign;if(void 0===t.propertyName||s){const i=this.getNodeType(e),n=e.getPropertyName(r,_s.VERTEX);e.flowNodeFromShaderStage(_s.VERTEX,this.node,i,n),t.propertyName=n,s?t.reassignPosition=!1:void 0===t.reassignPosition&&e.context.isPositionNodeInput&&(t.reassignPosition=!0)}return e.getPropertyName(r)}}const wa=bi(Ea);$s("varying",wa);const Ma=_i((([e])=>{const t=e.mul(.9478672986).add(.0521327014).pow(2.4),r=e.mul(.0773993808),s=e.lessThanEqual(.04045);return la(t,r,s)})).setLayout({name:"sRGBTransferEOTF",type:"vec3",inputs:[{name:"color",type:"vec3"}]}),Ba=_i((([e])=>{const t=e.pow(.41666).mul(1.055).sub(.055),r=e.mul(12.92),s=e.lessThanEqual(.0031308);return la(t,r,s)})).setLayout({name:"sRGBTransferOETF",type:"vec3",inputs:[{name:"color",type:"vec3"}]}),Ua="WorkingColorSpace",Fa="OutputColorSpace";class Pa extends Fs{static get type(){return"ColorSpaceNode"}constructor(e,t,r){super("vec4"),this.colorNode=e,this.source=t,this.target=r}resolveColorSpace(e,t){return t===Ua?d.workingColorSpace:t===Fa?e.context.outputColorSpace||e.renderer.outputColorSpace:t}setup(e){const{colorNode:t}=this,r=this.resolveColorSpace(e,this.source),s=this.resolveColorSpace(e,this.target);let n=t;return!1!==d.enabled&&r!==s&&r&&s?(d.getTransfer(r)===c&&(n=Oi(Ma(n.rgb),n.a)),d.getPrimaries(r)!==d.getPrimaries(s)&&(n=Oi(Hi(d._getMatrix(new i,r,s)).mul(n.rgb),n.a)),d.getTransfer(s)===c&&(n=Oi(Ba(n.rgb),n.a)),n):n}}const Ia=e=>fi(new Pa(fi(e),Ua,Fa)),La=e=>fi(new Pa(fi(e),Fa,Ua)),Va=(e,t)=>fi(new Pa(fi(e),Ua,t)),Da=(e,t)=>fi(new Pa(fi(e),t,Ua));$s("toOutputColorSpace",Ia),$s("toWorkingColorSpace",La),$s("workingToColorSpace",Va),$s("colorSpaceToWorking",Da);let Oa=class extends Bs{static get type(){return"ReferenceElementNode"}constructor(e,t){super(e,t),this.referenceNode=e,this.isReferenceElementNode=!0}getNodeType(){return this.referenceNode.uniformType}generate(e){const t=super.generate(e),r=this.referenceNode.getNodeType(),s=this.getNodeType();return e.format(t,r,s)}};class Ga extends Ms{static get type(){return"ReferenceBaseNode"}constructor(e,t,r=null,s=null){super(),this.property=e,this.uniformType=t,this.object=r,this.count=s,this.properties=e.split("."),this.reference=r,this.node=null,this.group=null,this.updateType=vs.OBJECT}setGroup(e){return this.group=e,this}element(e){return fi(new Oa(this,fi(e)))}setNodeType(e){const t=tn(null,e).getSelf();null!==this.group&&t.setGroup(this.group),this.node=t}getNodeType(e){return null===this.node&&(this.updateReference(e),this.updateValue()),this.node.getNodeType(e)}getValueFromReference(e=this.reference){const{properties:t}=this;let r=e[t[0]];for(let e=1;efi(new ka(e,t,r));class $a extends Fs{static get type(){return"ToneMappingNode"}constructor(e,t=Wa,r=null){super("vec3"),this.toneMapping=e,this.exposureNode=t,this.colorNode=r}customCacheKey(){return ds(this.toneMapping)}setup(e){const t=this.colorNode||e.context.color,r=this.toneMapping;if(r===h)return t;let s=null;const i=e.renderer.library.getToneMappingFunction(r);return null!==i?s=Oi(i(t.rgb,this.exposureNode),t.a):(console.error("ToneMappingNode: Unsupported Tone Mapping configuration.",r),s=t),s}}const Ha=(e,t,r)=>fi(new $a(e,fi(t),fi(r))),Wa=za("toneMappingExposure","float");$s("toneMapping",((e,t,r)=>Ha(t,r,e)));class ja extends Os{static get type(){return"BufferAttributeNode"}constructor(e,t=null,r=0,s=0){super(e,t),this.isBufferNode=!0,this.bufferType=t,this.bufferStride=r,this.bufferOffset=s,this.usage=p,this.instanced=!1,this.attribute=null,this.global=!0,e&&!0===e.isBufferAttribute&&(this.attribute=e,this.usage=e.usage,this.instanced=e.isInstancedBufferAttribute)}getHash(e){if(0===this.bufferStride&&0===this.bufferOffset){let t=e.globalCache.getData(this.value);return void 0===t&&(t={node:this},e.globalCache.setData(this.value,t)),t.node.uuid}return this.uuid}getNodeType(e){return null===this.bufferType&&(this.bufferType=e.getTypeFromAttribute(this.attribute)),this.bufferType}setup(e){if(null!==this.attribute)return;const t=this.getNodeType(e),r=this.value,s=e.getTypeLength(t),i=this.bufferStride||s,n=this.bufferOffset,o=!0===r.isInterleavedBuffer?r:new g(r,i),a=new f(o,s,n);o.setUsage(this.usage),this.attribute=a,this.attribute.isInstancedBufferAttribute=this.instanced}generate(e){const t=this.getNodeType(e),r=e.getBufferAttributeFromNode(this,t),s=e.getPropertyName(r);let i=null;if("vertex"===e.shaderStage||"compute"===e.shaderStage)this.name=s,i=s;else{i=wa(this).build(e,t)}return i}getInputType(){return"bufferAttribute"}setUsage(e){return this.usage=e,this.attribute&&!0===this.attribute.isBufferAttribute&&(this.attribute.usage=e),this}setInstanced(e){return this.instanced=e,this}}const qa=(e,t=null,r=0,s=0)=>fi(new ja(e,t,r,s)),Ka=(e,t=null,r=0,s=0)=>qa(e,t,r,s).setUsage(m),Xa=(e,t=null,r=0,s=0)=>qa(e,t,r,s).setInstanced(!0),Ya=(e,t=null,r=0,s=0)=>Ka(e,t,r,s).setInstanced(!0);$s("toAttribute",(e=>qa(e.value)));class Qa extends Ms{static get type(){return"ComputeNode"}constructor(e,t,r=[64]){super("void"),this.isComputeNode=!0,this.computeNode=e,this.count=t,this.workgroupSize=r,this.dispatchCount=0,this.version=1,this.updateBeforeType=vs.OBJECT,this.onInitFunction=null,this.updateDispatchCount()}dispose(){this.dispatchEvent({type:"dispose"})}updateDispatchCount(){const{count:e,workgroupSize:t}=this;let r=t[0];for(let e=1;efi(new Qa(fi(e),t,r));$s("compute",Za);class Ja extends Ms{static get type(){return"CacheNode"}constructor(e,t=!0){super(),this.node=e,this.parent=t,this.isCacheNode=!0}getNodeType(e){return this.node.getNodeType(e)}build(e,...t){const r=e.getCache(),s=e.getCacheFromNode(this,this.parent);e.setCache(s);const i=this.node.build(e,...t);return e.setCache(r),i}}const eu=(e,t)=>fi(new Ja(fi(e),t));$s("cache",eu);class tu extends Ms{static get type(){return"BypassNode"}constructor(e,t){super(),this.isBypassNode=!0,this.outputNode=e,this.callNode=t}getNodeType(e){return this.outputNode.getNodeType(e)}generate(e){const t=this.callNode.build(e,"void");return""!==t&&e.addLineFlowCode(t,this),this.outputNode.build(e)}}const ru=bi(tu);$s("bypass",ru);class su extends Ms{static get type(){return"RemapNode"}constructor(e,t,r,s=Ci(0),i=Ci(1)){super(),this.node=e,this.inLowNode=t,this.inHighNode=r,this.outLowNode=s,this.outHighNode=i,this.doClamp=!0}setup(){const{node:e,inLowNode:t,inHighNode:r,outLowNode:s,outHighNode:i,doClamp:n}=this;let o=e.sub(t).div(r.sub(t));return!0===n&&(o=o.clamp()),o.mul(i.sub(s)).add(s)}}const iu=bi(su,null,null,{doClamp:!1}),nu=bi(su);$s("remap",iu),$s("remapClamp",nu);class ou extends Ms{static get type(){return"ExpressionNode"}constructor(e="",t="void"){super(t),this.snippet=e}generate(e,t){const r=this.getNodeType(e),s=this.snippet;if("void"!==r)return e.format(`( ${s} )`,r,t);e.addLineFlowCode(s,this)}}const au=bi(ou),uu=e=>(e?Ta(e,au("discard")):au("discard")).append();$s("discard",uu);class lu extends Fs{static get type(){return"RenderOutputNode"}constructor(e,t,r){super("vec4"),this.colorNode=e,this.toneMapping=t,this.outputColorSpace=r,this.isRenderOutputNode=!0}setup({context:e}){let t=this.colorNode||e.color;const r=(null!==this.toneMapping?this.toneMapping:e.toneMapping)||h,s=(null!==this.outputColorSpace?this.outputColorSpace:e.outputColorSpace)||y;return r!==h&&(t=t.toneMapping(r)),s!==y&&s!==d.workingColorSpace&&(t=t.workingToColorSpace(s)),t}}const du=(e,t=null,r=null)=>fi(new lu(fi(e),t,r));$s("renderOutput",du);class cu extends Ms{static get type(){return"AttributeNode"}constructor(e,t=null){super(t),this.global=!0,this._attributeName=e}getHash(e){return this.getAttributeName(e)}getNodeType(e){let t=this.nodeType;if(null===t){const r=this.getAttributeName(e);if(e.hasGeometryAttribute(r)){const s=e.geometry.getAttribute(r);t=e.getTypeFromAttribute(s)}else t="float"}return t}setAttributeName(e){return this._attributeName=e,this}getAttributeName(){return this._attributeName}generate(e){const t=this.getAttributeName(e),r=this.getNodeType(e);if(!0===e.hasGeometryAttribute(t)){const s=e.geometry.getAttribute(t),i=e.getTypeFromAttribute(s),n=e.getAttribute(t,i);if("vertex"===e.shaderStage)return e.format(n.name,i,r);return wa(this).build(e,r)}return console.warn(`AttributeNode: Vertex attribute "${t}" not found on geometry.`),e.generateConst(r)}serialize(e){super.serialize(e),e.global=this.global,e._attributeName=this._attributeName}deserialize(e){super.deserialize(e),this.global=e.global,this._attributeName=e._attributeName}}const hu=(e,t)=>fi(new cu(e,t)),pu=(e=0)=>hu("uv"+(e>0?e:""),"vec2");class gu extends Ms{static get type(){return"TextureSizeNode"}constructor(e,t=null){super("uvec2"),this.isTextureSizeNode=!0,this.textureNode=e,this.levelNode=t}generate(e,t){const r=this.textureNode.build(e,"property"),s=null===this.levelNode?"0":this.levelNode.build(e,"int");return e.format(`${e.getMethod("textureDimensions")}( ${r}, ${s} )`,this.getNodeType(e),t)}}const mu=bi(gu);class fu extends en{static get type(){return"MaxMipLevelNode"}constructor(e){super(0),this._textureNode=e,this.updateType=vs.FRAME}get textureNode(){return this._textureNode}get texture(){return this._textureNode.value}update(){const e=this.texture,t=e.images,r=t&&t.length>0?t[0]&&t[0].image||t[0]:e.image;if(r&&void 0!==r.width){const{width:e,height:t}=r;this.value=Math.log2(Math.max(e,t))}}}const yu=bi(fu);class xu extends en{static get type(){return"TextureNode"}constructor(e,t=null,r=null,s=null){super(e),this.isTextureNode=!0,this.uvNode=t,this.levelNode=r,this.biasNode=s,this.compareNode=null,this.depthNode=null,this.gradNode=null,this.sampler=!0,this.updateMatrix=!1,this.updateType=vs.NONE,this.referenceNode=null,this._value=e,this._matrixUniform=null,this.setUpdateMatrix(null===t)}set value(e){this.referenceNode?this.referenceNode.value=e:this._value=e}get value(){return this.referenceNode?this.referenceNode.value:this._value}getUniformHash(){return this.value.uuid}getNodeType(){return!0===this.value.isDepthTexture?"float":this.value.type===x?"uvec4":this.value.type===b?"ivec4":"vec4"}getInputType(){return"texture"}getDefaultUV(){return pu(this.value.channel)}updateReference(){return this.value}getTransformedUV(e){return null===this._matrixUniform&&(this._matrixUniform=tn(this.value.matrix)),this._matrixUniform.mul(Ii(e,1)).xy}setUpdateMatrix(e){return this.updateMatrix=e,this.updateType=e?vs.FRAME:vs.NONE,this}setupUV(e,t){const r=this.value;return e.isFlipY()&&(r.image instanceof ImageBitmap&&!0===r.flipY||!0===r.isRenderTargetTexture||!0===r.isFramebufferTexture||!0===r.isDepthTexture)&&(t=this.sampler?t.flipY():t.setY(Ei(mu(this,this.levelNode).y).sub(t.y).sub(1))),t}setup(e){const t=e.getNodeProperties(this);t.referenceNode=this.referenceNode;let r=this.uvNode;null!==r&&!0!==e.context.forceUVContext||!e.context.getUV||(r=e.context.getUV(this)),r||(r=this.getDefaultUV()),!0===this.updateMatrix&&(r=this.getTransformedUV(r)),r=this.setupUV(e,r);let s=this.levelNode;null===s&&e.context.getTextureLevel&&(s=e.context.getTextureLevel(this)),t.uvNode=r,t.levelNode=s,t.biasNode=this.biasNode,t.compareNode=this.compareNode,t.gradNode=this.gradNode,t.depthNode=this.depthNode}generateUV(e,t){return t.build(e,!0===this.sampler?"vec2":"ivec2")}generateSnippet(e,t,r,s,i,n,o,a){const u=this.value;let l;return l=s?e.generateTextureLevel(u,t,r,s,n):i?e.generateTextureBias(u,t,r,i,n):a?e.generateTextureGrad(u,t,r,a,n):o?e.generateTextureCompare(u,t,r,o,n):!1===this.sampler?e.generateTextureLoad(u,t,r,n):e.generateTexture(u,t,r,n),l}generate(e,t){const r=e.getNodeProperties(this),s=this.value;if(!s||!0!==s.isTexture)throw new Error("TextureNode: Need a three.js texture.");const i=super.generate(e,"property");if("sampler"===t)return i+"_sampler";if(e.isReference(t))return i;{const n=e.getDataFromNode(this);let o=n.propertyName;if(void 0===o){const{uvNode:t,levelNode:s,biasNode:a,compareNode:u,depthNode:l,gradNode:d}=r,c=this.generateUV(e,t),h=s?s.build(e,"float"):null,p=a?a.build(e,"float"):null,g=l?l.build(e,"int"):null,m=u?u.build(e,"float"):null,f=d?[d[0].build(e,"vec2"),d[1].build(e,"vec2")]:null,y=e.getVarFromNode(this);o=e.getPropertyName(y);const x=this.generateSnippet(e,i,c,h,p,g,m,f);e.addLineFlowCode(`${o} = ${x}`,this),n.snippet=x,n.propertyName=o}let a=o;const u=this.getNodeType(e);return e.needsToWorkingColorSpace(s)&&(a=Da(au(a,u),s.colorSpace).setup(e).build(e,u)),e.format(a,u,t)}}setSampler(e){return this.sampler=e,this}getSampler(){return this.sampler}uv(e){return console.warn("THREE.TextureNode: .uv() has been renamed. Use .sample() instead."),this.sample(e)}sample(e){const t=this.clone();return t.uvNode=fi(e),t.referenceNode=this.getSelf(),fi(t)}blur(e){const t=this.clone();return t.biasNode=fi(e).mul(yu(t)),t.referenceNode=this.getSelf(),fi(t)}level(e){const t=this.clone();return t.levelNode=fi(e),t.referenceNode=this.getSelf(),fi(t)}size(e){return mu(this,e)}bias(e){const t=this.clone();return t.biasNode=fi(e),t.referenceNode=this.getSelf(),fi(t)}compare(e){const t=this.clone();return t.compareNode=fi(e),t.referenceNode=this.getSelf(),fi(t)}grad(e,t){const r=this.clone();return r.gradNode=[fi(e),fi(t)],r.referenceNode=this.getSelf(),fi(r)}depth(e){const t=this.clone();return t.depthNode=fi(e),t.referenceNode=this.getSelf(),fi(t)}serialize(e){super.serialize(e),e.value=this.value.toJSON(e.meta).uuid,e.sampler=this.sampler,e.updateMatrix=this.updateMatrix,e.updateType=this.updateType}deserialize(e){super.deserialize(e),this.value=e.meta.textures[e.value],this.sampler=e.sampler,this.updateMatrix=e.updateMatrix,this.updateType=e.updateType}update(){const e=this.value,t=this._matrixUniform;null!==t&&(t.value=e.matrix),!0===e.matrixAutoUpdate&&e.updateMatrix()}clone(){const e=new this.constructor(this.value,this.uvNode,this.levelNode,this.biasNode);return e.sampler=this.sampler,e}}const bu=bi(xu),Tu=(...e)=>bu(...e).setSampler(!1),_u=tn("float").label("cameraNear").setGroup(Zi).onRenderUpdate((({camera:e})=>e.near)),vu=tn("float").label("cameraFar").setGroup(Zi).onRenderUpdate((({camera:e})=>e.far)),Nu=tn("mat4").label("cameraProjectionMatrix").setGroup(Zi).onRenderUpdate((({camera:e})=>e.projectionMatrix)),Su=tn("mat4").label("cameraProjectionMatrixInverse").setGroup(Zi).onRenderUpdate((({camera:e})=>e.projectionMatrixInverse)),Au=tn("mat4").label("cameraViewMatrix").setGroup(Zi).onRenderUpdate((({camera:e})=>e.matrixWorldInverse)),Ru=tn("mat4").label("cameraWorldMatrix").setGroup(Zi).onRenderUpdate((({camera:e})=>e.matrixWorld)),Cu=tn("mat3").label("cameraNormalMatrix").setGroup(Zi).onRenderUpdate((({camera:e})=>e.normalMatrix)),Eu=tn(new r).label("cameraPosition").setGroup(Zi).onRenderUpdate((({camera:e},t)=>t.value.setFromMatrixPosition(e.matrixWorld)));class wu extends Ms{static get type(){return"Object3DNode"}constructor(e,t=null){super(),this.scope=e,this.object3d=t,this.updateType=vs.OBJECT,this._uniformNode=new en(null)}getNodeType(){const e=this.scope;return e===wu.WORLD_MATRIX?"mat4":e===wu.POSITION||e===wu.VIEW_POSITION||e===wu.DIRECTION||e===wu.SCALE?"vec3":void 0}update(e){const t=this.object3d,s=this._uniformNode,i=this.scope;if(i===wu.WORLD_MATRIX)s.value=t.matrixWorld;else if(i===wu.POSITION)s.value=s.value||new r,s.value.setFromMatrixPosition(t.matrixWorld);else if(i===wu.SCALE)s.value=s.value||new r,s.value.setFromMatrixScale(t.matrixWorld);else if(i===wu.DIRECTION)s.value=s.value||new r,t.getWorldDirection(s.value);else if(i===wu.VIEW_POSITION){const i=e.camera;s.value=s.value||new r,s.value.setFromMatrixPosition(t.matrixWorld),s.value.applyMatrix4(i.matrixWorldInverse)}}generate(e){const t=this.scope;return t===wu.WORLD_MATRIX?this._uniformNode.nodeType="mat4":t!==wu.POSITION&&t!==wu.VIEW_POSITION&&t!==wu.DIRECTION&&t!==wu.SCALE||(this._uniformNode.nodeType="vec3"),this._uniformNode.build(e)}serialize(e){super.serialize(e),e.scope=this.scope}deserialize(e){super.deserialize(e),this.scope=e.scope}}wu.WORLD_MATRIX="worldMatrix",wu.POSITION="position",wu.SCALE="scale",wu.VIEW_POSITION="viewPosition",wu.DIRECTION="direction";const Mu=bi(wu,wu.DIRECTION),Bu=bi(wu,wu.WORLD_MATRIX),Uu=bi(wu,wu.POSITION),Fu=bi(wu,wu.SCALE),Pu=bi(wu,wu.VIEW_POSITION);class Iu extends wu{static get type(){return"ModelNode"}constructor(e){super(e)}update(e){this.object3d=e.object,super.update(e)}}const Lu=Ti(Iu,Iu.DIRECTION),Vu=Ti(Iu,Iu.WORLD_MATRIX),Du=Ti(Iu,Iu.POSITION),Ou=Ti(Iu,Iu.SCALE),Gu=Ti(Iu,Iu.VIEW_POSITION),ku=tn(new i).onObjectUpdate((({object:e},t)=>t.value.getNormalMatrix(e.matrixWorld))),zu=tn(new n).onObjectUpdate((({object:e},t)=>t.value.copy(e.matrixWorld).invert())),$u=_i((e=>e.renderer.nodes.modelViewMatrix||Hu)).once()().toVar("modelViewMatrix"),Hu=Au.mul(Vu),Wu=_i((e=>(e.context.isHighPrecisionModelViewMatrix=!0,tn("mat4").onObjectUpdate((({object:e,camera:t})=>e.modelViewMatrix.multiplyMatrices(t.matrixWorldInverse,e.matrixWorld)))))).once()().toVar("highpModelViewMatrix"),ju=_i((e=>{const t=e.context.isHighPrecisionModelViewMatrix;return tn("mat3").onObjectUpdate((({object:e,camera:r})=>(!0!==t&&e.modelViewMatrix.multiplyMatrices(r.matrixWorldInverse,e.matrixWorld),e.normalMatrix.getNormalMatrix(e.modelViewMatrix))))})).once()().toVar("highpModelNormalViewMatrix"),qu=hu("position","vec3"),Ku=qu.varying("positionLocal"),Xu=qu.varying("positionPrevious"),Yu=Vu.mul(Ku).xyz.varying("v_positionWorld").context({needsPositionReassign:!0}),Qu=Ku.transformDirection(Vu).varying("v_positionWorldDirection").normalize().toVar("positionWorldDirection").context({needsPositionReassign:!0}),Zu=_i((e=>e.context.setupPositionView()),"vec3").once()().varying("v_positionView").context({needsPositionReassign:!0}),Ju=Zu.negate().varying("v_positionViewDirection").normalize().toVar("positionViewDirection");class el extends Ms{static get type(){return"FrontFacingNode"}constructor(){super("bool"),this.isFrontFacingNode=!0}generate(e){const{renderer:t,material:r}=e;return t.coordinateSystem===u&&r.side===T?"false":e.getFrontFacing()}}const tl=Ti(el),rl=Ci(tl).mul(2).sub(1),sl=hu("normal","vec3"),il=_i((e=>!1===e.geometry.hasAttribute("normal")?(console.warn('TSL.NormalNode: Vertex attribute "normal" not found on geometry.'),Ii(0,1,0)):sl),"vec3").once()().toVar("normalLocal"),nl=Zu.dFdx().cross(Zu.dFdy()).normalize().toVar("normalFlat"),ol=_i((e=>{let t;return t=!0===e.material.flatShading?nl:wa(hl(il),"v_normalView").normalize(),t}),"vec3").once()().toVar("normalView"),al=wa(ol.transformDirection(Au),"v_normalWorld").normalize().toVar("normalWorld"),ul=_i((e=>e.context.setupNormal()),"vec3").once()().mul(rl).toVar("transformedNormalView"),ll=ul.transformDirection(Au).toVar("transformedNormalWorld"),dl=_i((e=>e.context.setupClearcoatNormal()),"vec3").once()().mul(rl).toVar("transformedClearcoatNormalView"),cl=_i((([e,t=Vu])=>{const r=Hi(t),s=e.div(Ii(r[0].dot(r[0]),r[1].dot(r[1]),r[2].dot(r[2])));return r.mul(s).xyz})),hl=_i((([e],t)=>{const r=t.renderer.nodes.modelNormalViewMatrix;if(null!==r)return r.transformDirection(e);const s=ku.mul(e);return Au.transformDirection(s)})),pl=tn(0).onReference((({material:e})=>e)).onRenderUpdate((({material:e})=>e.refractionRatio)),gl=Ju.negate().reflect(ul),ml=Ju.negate().refract(ul,pl),fl=gl.transformDirection(Au).toVar("reflectVector"),yl=ml.transformDirection(Au).toVar("reflectVector");class xl extends xu{static get type(){return"CubeTextureNode"}constructor(e,t=null,r=null,s=null){super(e,t,r,s),this.isCubeTextureNode=!0}getInputType(){return"cubeTexture"}getDefaultUV(){const e=this.value;return e.mapping===_?fl:e.mapping===v?yl:(console.error('THREE.CubeTextureNode: Mapping "%s" not supported.',e.mapping),Ii(0,0,0))}setUpdateMatrix(){}setupUV(e,t){const r=this.value;return e.renderer.coordinateSystem!==l&&r.isRenderTargetTexture?t:Ii(t.x.negate(),t.yz)}generateUV(e,t){return t.build(e,"vec3")}}const bl=bi(xl);class Tl extends en{static get type(){return"BufferNode"}constructor(e,t,r=0){super(e,t),this.isBufferNode=!0,this.bufferType=t,this.bufferCount=r}getElementType(e){return this.getNodeType(e)}getInputType(){return"buffer"}}const _l=(e,t,r)=>fi(new Tl(e,t,r));class vl extends Bs{static get type(){return"UniformArrayElementNode"}constructor(e,t){super(e,t),this.isArrayBufferElementNode=!0}generate(e){const t=super.generate(e),r=this.getNodeType(),s=this.node.getPaddedType();return e.format(t,s,r)}}class Nl extends Tl{static get type(){return"UniformArrayNode"}constructor(e,t=null){super(null),this.array=e,this.elementType=null===t?fs(e[0]):t,this.paddedType=this.getPaddedType(),this.updateType=vs.RENDER,this.isArrayBufferNode=!0}getNodeType(){return this.paddedType}getElementType(){return this.elementType}getPaddedType(){const e=this.elementType;let t="vec4";return"mat2"===e?t="mat2":!0===/mat/.test(e)?t="mat4":"i"===e.charAt(0)?t="ivec4":"u"===e.charAt(0)&&(t="uvec4"),t}update(){const{array:e,value:t}=this,r=this.elementType;if("float"===r||"int"===r||"uint"===r)for(let r=0;rfi(new Nl(e,t));class Al extends Bs{static get type(){return"ReferenceElementNode"}constructor(e,t){super(e,t),this.referenceNode=e,this.isReferenceElementNode=!0}getNodeType(){return this.referenceNode.uniformType}generate(e){const t=super.generate(e),r=this.referenceNode.getNodeType(),s=this.getNodeType();return e.format(t,r,s)}}class Rl extends Ms{static get type(){return"ReferenceNode"}constructor(e,t,r=null,s=null){super(),this.property=e,this.uniformType=t,this.object=r,this.count=s,this.properties=e.split("."),this.reference=r,this.node=null,this.group=null,this.name=null,this.updateType=vs.OBJECT}element(e){return fi(new Al(this,fi(e)))}setGroup(e){return this.group=e,this}label(e){return this.name=e,this}setNodeType(e){let t=null;t=null!==this.count?_l(null,e,this.count):Array.isArray(this.getValueFromReference())?Sl(null,e):"texture"===e?bu(null):"cubeTexture"===e?bl(null):tn(null,e),null!==this.group&&t.setGroup(this.group),null!==this.name&&t.label(this.name),this.node=t.getSelf()}getNodeType(e){return null===this.node&&(this.updateReference(e),this.updateValue()),this.node.getNodeType(e)}getValueFromReference(e=this.reference){const{properties:t}=this;let r=e[t[0]];for(let e=1;efi(new Rl(e,t,r)),El=(e,t,r,s)=>fi(new Rl(e,t,s,r));class wl extends Rl{static get type(){return"MaterialReferenceNode"}constructor(e,t,r=null){super(e,t,r),this.material=r,this.isMaterialReferenceNode=!0}updateReference(e){return this.reference=null!==this.material?this.material:e.material,this.reference}}const Ml=(e,t,r=null)=>fi(new wl(e,t,r)),Bl=_i((e=>(!1===e.geometry.hasAttribute("tangent")&&e.geometry.computeTangents(),hu("tangent","vec4"))))(),Ul=Bl.xyz.toVar("tangentLocal"),Fl=$u.mul(Oi(Ul,0)).xyz.varying("v_tangentView").normalize().toVar("tangentView"),Pl=Fl.transformDirection(Au).varying("v_tangentWorld").normalize().toVar("tangentWorld"),Il=Fl.toVar("transformedTangentView"),Ll=Il.transformDirection(Au).normalize().toVar("transformedTangentWorld"),Vl=e=>e.mul(Bl.w).xyz,Dl=wa(Vl(sl.cross(Bl)),"v_bitangentGeometry").normalize().toVar("bitangentGeometry"),Ol=wa(Vl(il.cross(Ul)),"v_bitangentLocal").normalize().toVar("bitangentLocal"),Gl=wa(Vl(ol.cross(Fl)),"v_bitangentView").normalize().toVar("bitangentView"),kl=wa(Vl(al.cross(Pl)),"v_bitangentWorld").normalize().toVar("bitangentWorld"),zl=Vl(ul.cross(Il)).normalize().toVar("transformedBitangentView"),$l=zl.transformDirection(Au).normalize().toVar("transformedBitangentWorld"),Hl=Hi(Fl,Gl,ol),Wl=Ju.mul(Hl),jl=(()=>{let e=Tn.cross(Ju);return e=e.cross(Tn).normalize(),e=la(e,ul,xn.mul(un.oneMinus()).oneMinus().pow2().pow2()).normalize(),e})(),ql=_i((e=>{const{eye_pos:t,surf_norm:r,mapN:s,uv:i}=e,n=t.dFdx(),o=t.dFdy(),a=i.dFdx(),u=i.dFdy(),l=r,d=o.cross(l),c=l.cross(n),h=d.mul(a.x).add(c.mul(u.x)),p=d.mul(a.y).add(c.mul(u.y)),g=h.dot(h).max(p.dot(p)),m=rl.mul(g.inverseSqrt());return On(h.mul(s.x,m),p.mul(s.y,m),l.mul(s.z)).normalize()}));class Kl extends Fs{static get type(){return"NormalMapNode"}constructor(e,t=null){super("vec3"),this.node=e,this.scaleNode=t,this.normalMapType=N}setup(e){const{normalMapType:t,scaleNode:r}=this;let s=this.node.mul(2).sub(1);null!==r&&(s=Ii(s.xy.mul(r),s.z));let i=null;if(t===S)i=hl(s);else if(t===N){i=!0===e.hasGeometryAttribute("tangent")?Hl.mul(s).normalize():ql({eye_pos:Zu,surf_norm:ol,mapN:s,uv:pu()})}return i}}const Xl=bi(Kl),Yl=_i((({textureNode:e,bumpScale:t})=>{const r=t=>e.cache().context({getUV:e=>t(e.uvNode||pu()),forceUVContext:!0}),s=Ci(r((e=>e)));return Bi(Ci(r((e=>e.add(e.dFdx())))).sub(s),Ci(r((e=>e.add(e.dFdy())))).sub(s)).mul(t)})),Ql=_i((e=>{const{surf_pos:t,surf_norm:r,dHdxy:s}=e,i=t.dFdx().normalize(),n=r,o=t.dFdy().normalize().cross(n),a=n.cross(i),u=i.dot(o).mul(rl),l=u.sign().mul(s.x.mul(o).add(s.y.mul(a)));return u.abs().mul(r).sub(l).normalize()}));class Zl extends Fs{static get type(){return"BumpMapNode"}constructor(e,t=null){super("vec3"),this.textureNode=e,this.scaleNode=t}setup(){const e=null!==this.scaleNode?this.scaleNode:1,t=Yl({textureNode:this.textureNode,bumpScale:e});return Ql({surf_pos:Zu,surf_norm:ol,dHdxy:t})}}const Jl=bi(Zl),ed=new Map;class td extends Ms{static get type(){return"MaterialNode"}constructor(e){super(),this.scope=e}getCache(e,t){let r=ed.get(e);return void 0===r&&(r=Ml(e,t),ed.set(e,r)),r}getFloat(e){return this.getCache(e,"float")}getColor(e){return this.getCache(e,"color")}getTexture(e){return this.getCache("map"===e?"map":e+"Map","texture")}setup(e){const t=e.context.material,r=this.scope;let s=null;if(r===td.COLOR){const e=void 0!==t.color?this.getColor(r):Ii();s=t.map&&!0===t.map.isTexture?e.mul(this.getTexture("map")):e}else if(r===td.OPACITY){const e=this.getFloat(r);s=t.alphaMap&&!0===t.alphaMap.isTexture?e.mul(this.getTexture("alpha")):e}else if(r===td.SPECULAR_STRENGTH)s=t.specularMap&&!0===t.specularMap.isTexture?this.getTexture("specular").r:Ci(1);else if(r===td.SPECULAR_INTENSITY){const e=this.getFloat(r);s=t.specularMap?e.mul(this.getTexture(r).a):e}else if(r===td.SPECULAR_COLOR){const e=this.getColor(r);s=t.specularColorMap&&!0===t.specularColorMap.isTexture?e.mul(this.getTexture(r).rgb):e}else if(r===td.ROUGHNESS){const e=this.getFloat(r);s=t.roughnessMap&&!0===t.roughnessMap.isTexture?e.mul(this.getTexture(r).g):e}else if(r===td.METALNESS){const e=this.getFloat(r);s=t.metalnessMap&&!0===t.metalnessMap.isTexture?e.mul(this.getTexture(r).b):e}else if(r===td.EMISSIVE){const e=this.getFloat("emissiveIntensity"),i=this.getColor(r).mul(e);s=t.emissiveMap&&!0===t.emissiveMap.isTexture?i.mul(this.getTexture(r)):i}else if(r===td.NORMAL)t.normalMap?(s=Xl(this.getTexture("normal"),this.getCache("normalScale","vec2")),s.normalMapType=t.normalMapType):s=t.bumpMap?Jl(this.getTexture("bump").r,this.getFloat("bumpScale")):ol;else if(r===td.CLEARCOAT){const e=this.getFloat(r);s=t.clearcoatMap&&!0===t.clearcoatMap.isTexture?e.mul(this.getTexture(r).r):e}else if(r===td.CLEARCOAT_ROUGHNESS){const e=this.getFloat(r);s=t.clearcoatRoughnessMap&&!0===t.clearcoatRoughnessMap.isTexture?e.mul(this.getTexture(r).r):e}else if(r===td.CLEARCOAT_NORMAL)s=t.clearcoatNormalMap?Xl(this.getTexture(r),this.getCache(r+"Scale","vec2")):ol;else if(r===td.SHEEN){const e=this.getColor("sheenColor").mul(this.getFloat("sheen"));s=t.sheenColorMap&&!0===t.sheenColorMap.isTexture?e.mul(this.getTexture("sheenColor").rgb):e}else if(r===td.SHEEN_ROUGHNESS){const e=this.getFloat(r);s=t.sheenRoughnessMap&&!0===t.sheenRoughnessMap.isTexture?e.mul(this.getTexture(r).a):e,s=s.clamp(.07,1)}else if(r===td.ANISOTROPY)if(t.anisotropyMap&&!0===t.anisotropyMap.isTexture){const e=this.getTexture(r);s=$i(Od.x,Od.y,Od.y.negate(),Od.x).mul(e.rg.mul(2).sub(Bi(1)).normalize().mul(e.b))}else s=Od;else if(r===td.IRIDESCENCE_THICKNESS){const e=Cl("1","float",t.iridescenceThicknessRange);if(t.iridescenceThicknessMap){const i=Cl("0","float",t.iridescenceThicknessRange);s=e.sub(i).mul(this.getTexture(r).g).add(i)}else s=e}else if(r===td.TRANSMISSION){const e=this.getFloat(r);s=t.transmissionMap?e.mul(this.getTexture(r).r):e}else if(r===td.THICKNESS){const e=this.getFloat(r);s=t.thicknessMap?e.mul(this.getTexture(r).g):e}else if(r===td.IOR)s=this.getFloat(r);else if(r===td.LIGHT_MAP)s=this.getTexture(r).rgb.mul(this.getFloat("lightMapIntensity"));else if(r===td.AO_MAP)s=this.getTexture(r).r.sub(1).mul(this.getFloat("aoMapIntensity")).add(1);else{const t=this.getNodeType(e);s=this.getCache(r,t)}return s}}td.ALPHA_TEST="alphaTest",td.COLOR="color",td.OPACITY="opacity",td.SHININESS="shininess",td.SPECULAR="specular",td.SPECULAR_STRENGTH="specularStrength",td.SPECULAR_INTENSITY="specularIntensity",td.SPECULAR_COLOR="specularColor",td.REFLECTIVITY="reflectivity",td.ROUGHNESS="roughness",td.METALNESS="metalness",td.NORMAL="normal",td.CLEARCOAT="clearcoat",td.CLEARCOAT_ROUGHNESS="clearcoatRoughness",td.CLEARCOAT_NORMAL="clearcoatNormal",td.EMISSIVE="emissive",td.ROTATION="rotation",td.SHEEN="sheen",td.SHEEN_ROUGHNESS="sheenRoughness",td.ANISOTROPY="anisotropy",td.IRIDESCENCE="iridescence",td.IRIDESCENCE_IOR="iridescenceIOR",td.IRIDESCENCE_THICKNESS="iridescenceThickness",td.IOR="ior",td.TRANSMISSION="transmission",td.THICKNESS="thickness",td.ATTENUATION_DISTANCE="attenuationDistance",td.ATTENUATION_COLOR="attenuationColor",td.LINE_SCALE="scale",td.LINE_DASH_SIZE="dashSize",td.LINE_GAP_SIZE="gapSize",td.LINE_WIDTH="linewidth",td.LINE_DASH_OFFSET="dashOffset",td.POINT_WIDTH="pointWidth",td.DISPERSION="dispersion",td.LIGHT_MAP="light",td.AO_MAP="ao";const rd=Ti(td,td.ALPHA_TEST),sd=Ti(td,td.COLOR),id=Ti(td,td.SHININESS),nd=Ti(td,td.EMISSIVE),od=Ti(td,td.OPACITY),ad=Ti(td,td.SPECULAR),ud=Ti(td,td.SPECULAR_INTENSITY),ld=Ti(td,td.SPECULAR_COLOR),dd=Ti(td,td.SPECULAR_STRENGTH),cd=Ti(td,td.REFLECTIVITY),hd=Ti(td,td.ROUGHNESS),pd=Ti(td,td.METALNESS),gd=Ti(td,td.NORMAL).context({getUV:null}),md=Ti(td,td.CLEARCOAT),fd=Ti(td,td.CLEARCOAT_ROUGHNESS),yd=Ti(td,td.CLEARCOAT_NORMAL).context({getUV:null}),xd=Ti(td,td.ROTATION),bd=Ti(td,td.SHEEN),Td=Ti(td,td.SHEEN_ROUGHNESS),_d=Ti(td,td.ANISOTROPY),vd=Ti(td,td.IRIDESCENCE),Nd=Ti(td,td.IRIDESCENCE_IOR),Sd=Ti(td,td.IRIDESCENCE_THICKNESS),Ad=Ti(td,td.TRANSMISSION),Rd=Ti(td,td.THICKNESS),Cd=Ti(td,td.IOR),Ed=Ti(td,td.ATTENUATION_DISTANCE),wd=Ti(td,td.ATTENUATION_COLOR),Md=Ti(td,td.LINE_SCALE),Bd=Ti(td,td.LINE_DASH_SIZE),Ud=Ti(td,td.LINE_GAP_SIZE),Fd=Ti(td,td.LINE_WIDTH),Pd=Ti(td,td.LINE_DASH_OFFSET),Id=Ti(td,td.POINT_WIDTH),Ld=Ti(td,td.DISPERSION),Vd=Ti(td,td.LIGHT_MAP),Dd=Ti(td,td.AO_MAP),Od=tn(new t).onReference((function(e){return e.material})).onRenderUpdate((function({material:e}){this.value.set(e.anisotropy*Math.cos(e.anisotropyRotation),e.anisotropy*Math.sin(e.anisotropyRotation))})),Gd=_i((e=>e.context.setupModelViewProjection()),"vec4").once()().varying("v_modelViewProjection");class kd extends Ms{static get type(){return"IndexNode"}constructor(e){super("uint"),this.scope=e,this.isIndexNode=!0}generate(e){const t=this.getNodeType(e),r=this.scope;let s,i;if(r===kd.VERTEX)s=e.getVertexIndex();else if(r===kd.INSTANCE)s=e.getInstanceIndex();else if(r===kd.DRAW)s=e.getDrawIndex();else if(r===kd.INVOCATION_LOCAL)s=e.getInvocationLocalIndex();else if(r===kd.INVOCATION_SUBGROUP)s=e.getInvocationSubgroupIndex();else{if(r!==kd.SUBGROUP)throw new Error("THREE.IndexNode: Unknown scope: "+r);s=e.getSubgroupIndex()}if("vertex"===e.shaderStage||"compute"===e.shaderStage)i=s;else{i=wa(this).build(e,t)}return i}}kd.VERTEX="vertex",kd.INSTANCE="instance",kd.SUBGROUP="subgroup",kd.INVOCATION_LOCAL="invocationLocal",kd.INVOCATION_SUBGROUP="invocationSubgroup",kd.DRAW="draw";const zd=Ti(kd,kd.VERTEX),$d=Ti(kd,kd.INSTANCE),Hd=Ti(kd,kd.SUBGROUP),Wd=Ti(kd,kd.INVOCATION_SUBGROUP),jd=Ti(kd,kd.INVOCATION_LOCAL),qd=Ti(kd,kd.DRAW);class Kd extends Ms{static get type(){return"InstanceNode"}constructor(e,t,r){super("void"),this.count=e,this.instanceMatrix=t,this.instanceColor=r,this.instanceMatrixNode=null,this.instanceColorNode=null,this.updateType=vs.FRAME,this.buffer=null,this.bufferColor=null}setup(e){const{count:t,instanceMatrix:r,instanceColor:s}=this;let{instanceMatrixNode:i,instanceColorNode:n}=this;if(null===i){if(t<=1e3)i=_l(r.array,"mat4",Math.max(t,1)).element($d);else{const e=new A(r.array,16,1);this.buffer=e;const t=r.usage===m?Ya:Xa,s=[t(e,"vec4",16,0),t(e,"vec4",16,4),t(e,"vec4",16,8),t(e,"vec4",16,12)];i=Wi(...s)}this.instanceMatrixNode=i}if(s&&null===n){const e=new R(s.array,3),t=s.usage===m?Ya:Xa;this.bufferColor=e,n=Ii(t(e,"vec3",3,0)),this.instanceColorNode=n}const o=i.mul(Ku).xyz;if(Ku.assign(o),e.hasGeometryAttribute("normal")){const e=cl(il,i);il.assign(e)}null!==this.instanceColorNode&&nn("vec3","vInstanceColor").assign(this.instanceColorNode)}update(){this.instanceMatrix.usage!==m&&null!==this.buffer&&this.instanceMatrix.version!==this.buffer.version&&(this.buffer.version=this.instanceMatrix.version),this.instanceColor&&this.instanceColor.usage!==m&&null!==this.bufferColor&&this.instanceColor.version!==this.bufferColor.version&&(this.bufferColor.version=this.instanceColor.version)}}const Xd=bi(Kd);class Yd extends Kd{static get type(){return"InstancedMeshNode"}constructor(e){const{count:t,instanceMatrix:r,instanceColor:s}=e;super(t,r,s),this.instancedMesh=e}}const Qd=bi(Yd);class Zd extends Ms{static get type(){return"BatchNode"}constructor(e){super("void"),this.batchMesh=e,this.batchingIdNode=null}setup(e){null===this.batchingIdNode&&(null===e.getDrawIndex()?this.batchingIdNode=$d:this.batchingIdNode=qd);const t=_i((([e])=>{const t=mu(Tu(this.batchMesh._indirectTexture),0),r=Ei(e).modInt(Ei(t)),s=Ei(e).div(Ei(t));return Tu(this.batchMesh._indirectTexture,Ui(r,s)).x})).setLayout({name:"getIndirectIndex",type:"uint",inputs:[{name:"id",type:"int"}]}),r=t(Ei(this.batchingIdNode)),s=this.batchMesh._matricesTexture,i=mu(Tu(s),0),n=Ci(r).mul(4).toInt().toVar(),o=n.modInt(i),a=n.div(Ei(i)),u=Wi(Tu(s,Ui(o,a)),Tu(s,Ui(o.add(1),a)),Tu(s,Ui(o.add(2),a)),Tu(s,Ui(o.add(3),a))),l=this.batchMesh._colorsTexture;if(null!==l){const e=_i((([e])=>{const t=mu(Tu(l),0).x,r=e,s=r.modInt(t),i=r.div(t);return Tu(l,Ui(s,i)).rgb})).setLayout({name:"getBatchingColor",type:"vec3",inputs:[{name:"id",type:"int"}]}),t=e(r);nn("vec3","vBatchColor").assign(t)}const d=Hi(u);Ku.assign(u.mul(Ku));const c=il.div(Ii(d[0].dot(d[0]),d[1].dot(d[1]),d[2].dot(d[2]))),h=d.mul(c).xyz;il.assign(h),e.hasGeometryAttribute("tangent")&&Ul.mulAssign(d)}}const Jd=bi(Zd),ec=new WeakMap;class tc extends Ms{static get type(){return"SkinningNode"}constructor(e,t=!1){let r,s,i;super("void"),this.skinnedMesh=e,this.useReference=t,this.updateType=vs.OBJECT,this.skinIndexNode=hu("skinIndex","uvec4"),this.skinWeightNode=hu("skinWeight","vec4"),t?(r=Cl("bindMatrix","mat4"),s=Cl("bindMatrixInverse","mat4"),i=El("skeleton.boneMatrices","mat4",e.skeleton.bones.length)):(r=tn(e.bindMatrix,"mat4"),s=tn(e.bindMatrixInverse,"mat4"),i=_l(e.skeleton.boneMatrices,"mat4",e.skeleton.bones.length)),this.bindMatrixNode=r,this.bindMatrixInverseNode=s,this.boneMatricesNode=i,this.previousBoneMatricesNode=null}getSkinnedPosition(e=this.boneMatricesNode,t=Ku){const{skinIndexNode:r,skinWeightNode:s,bindMatrixNode:i,bindMatrixInverseNode:n}=this,o=e.element(r.x),a=e.element(r.y),u=e.element(r.z),l=e.element(r.w),d=i.mul(t),c=On(o.mul(s.x).mul(d),a.mul(s.y).mul(d),u.mul(s.z).mul(d),l.mul(s.w).mul(d));return n.mul(c).xyz}getSkinnedNormal(e=this.boneMatricesNode,t=il){const{skinIndexNode:r,skinWeightNode:s,bindMatrixNode:i,bindMatrixInverseNode:n}=this,o=e.element(r.x),a=e.element(r.y),u=e.element(r.z),l=e.element(r.w);let d=On(s.x.mul(o),s.y.mul(a),s.z.mul(u),s.w.mul(l));return d=n.mul(d).mul(i),d.transformDirection(t).xyz}getPreviousSkinnedPosition(e){const t=e.object;return null===this.previousBoneMatricesNode&&(t.skeleton.previousBoneMatrices=new Float32Array(t.skeleton.boneMatrices),this.previousBoneMatricesNode=El("skeleton.previousBoneMatrices","mat4",t.skeleton.bones.length)),this.getSkinnedPosition(this.previousBoneMatricesNode,Xu)}needsPreviousBoneMatrices(e){const t=e.renderer.getMRT();return t&&t.has("velocity")}setup(e){this.needsPreviousBoneMatrices(e)&&Xu.assign(this.getPreviousSkinnedPosition(e));const t=this.getSkinnedPosition();if(Ku.assign(t),e.hasGeometryAttribute("normal")){const t=this.getSkinnedNormal();il.assign(t),e.hasGeometryAttribute("tangent")&&Ul.assign(t)}}generate(e,t){if("void"!==t)return Ku.build(e,t)}update(e){const t=(this.useReference?e.object:this.skinnedMesh).skeleton;ec.get(t)!==e.frameId&&(ec.set(t,e.frameId),null!==this.previousBoneMatricesNode&&t.previousBoneMatrices.set(t.boneMatrices),t.update())}}const rc=e=>fi(new tc(e,!0));class sc extends Ms{static get type(){return"LoopNode"}constructor(e=[]){super(),this.params=e}getVarName(e){return String.fromCharCode("i".charCodeAt(0)+e)}getProperties(e){const t=e.getNodeProperties(this);if(void 0!==t.stackNode)return t;const r={};for(let e=0,t=this.params.length-1;eNumber(n)?">=":"<"));const d={start:i,end:n,condition:u},c=d.start,h=d.end;let p="",g="",m="";l||(l="int"===a||"uint"===a?u.includes("<")?"++":"--":u.includes("<")?"+= 1.":"-= 1."),p+=e.getVar(a,o)+" = "+c,g+=o+" "+u+" "+h,m+=o+" "+l;const f=`for ( ${p}; ${g}; ${m} )`;e.addFlowCode((0===t?"\n":"")+e.tab+f+" {\n\n").addFlowTab()}const i=s.build(e,"void"),n=t.returnsNode?t.returnsNode.build(e):"";e.removeFlowTab().addFlowCode("\n"+e.tab+i);for(let t=0,r=this.params.length-1;tfi(new sc(xi(e,"int"))).append(),nc=()=>au("break").append(),oc=new WeakMap,ac=new s,uc=_i((({bufferMap:e,influence:t,stride:r,width:s,depth:i,offset:n})=>{const o=Ei(zd).mul(r).add(n),a=o.div(s),u=o.sub(a.mul(s));return Tu(e,Ui(u,a)).depth(i).mul(t)}));class lc extends Ms{static get type(){return"MorphNode"}constructor(e){super("void"),this.mesh=e,this.morphBaseInfluence=tn(1),this.updateType=vs.OBJECT}setup(e){const{geometry:r}=e,s=void 0!==r.morphAttributes.position,i=r.hasAttribute("normal")&&void 0!==r.morphAttributes.normal,n=r.morphAttributes.position||r.morphAttributes.normal||r.morphAttributes.color,o=void 0!==n?n.length:0,{texture:a,stride:u,size:l}=function(e){const r=void 0!==e.morphAttributes.position,s=void 0!==e.morphAttributes.normal,i=void 0!==e.morphAttributes.color,n=e.morphAttributes.position||e.morphAttributes.normal||e.morphAttributes.color,o=void 0!==n?n.length:0;let a=oc.get(e);if(void 0===a||a.count!==o){void 0!==a&&a.texture.dispose();const u=e.morphAttributes.position||[],l=e.morphAttributes.normal||[],d=e.morphAttributes.color||[];let c=0;!0===r&&(c=1),!0===s&&(c=2),!0===i&&(c=3);let h=e.attributes.position.count*c,p=1;const g=4096;h>g&&(p=Math.ceil(h/g),h=g);const m=new Float32Array(h*p*4*o),f=new C(m,h,p,o);f.type=E,f.needsUpdate=!0;const y=4*c;for(let b=0;b{const t=Ci(0).toVar();this.mesh.count>1&&null!==this.mesh.morphTexture&&void 0!==this.mesh.morphTexture?t.assign(Tu(this.mesh.morphTexture,Ui(Ei(e).add(1),Ei($d))).r):t.assign(Cl("morphTargetInfluences","float").element(e).toVar()),!0===s&&Ku.addAssign(uc({bufferMap:a,influence:t,stride:u,width:d,depth:e,offset:Ei(0)})),!0===i&&il.addAssign(uc({bufferMap:a,influence:t,stride:u,width:d,depth:e,offset:Ei(1)}))}))}update(){const e=this.morphBaseInfluence;this.mesh.geometry.morphTargetsRelative?e.value=1:e.value=1-this.mesh.morphTargetInfluences.reduce(((e,t)=>e+t),0)}}const dc=bi(lc);class cc extends Ms{static get type(){return"LightingNode"}constructor(){super("vec3"),this.isLightingNode=!0}}class hc extends cc{static get type(){return"AONode"}constructor(e=null){super(),this.aoNode=e}setup(e){e.context.ambientOcclusion.mulAssign(this.aoNode)}}class pc extends va{static get type(){return"LightingContextNode"}constructor(e,t=null,r=null,s=null){super(e),this.lightingModel=t,this.backdropNode=r,this.backdropAlphaNode=s,this._value=null}getContext(){const{backdropNode:e,backdropAlphaNode:t}=this,r={directDiffuse:Ii().toVar("directDiffuse"),directSpecular:Ii().toVar("directSpecular"),indirectDiffuse:Ii().toVar("indirectDiffuse"),indirectSpecular:Ii().toVar("indirectSpecular")};return{radiance:Ii().toVar("radiance"),irradiance:Ii().toVar("irradiance"),iblIrradiance:Ii().toVar("iblIrradiance"),ambientOcclusion:Ci(1).toVar("ambientOcclusion"),reflectedLight:r,backdrop:e,backdropAlpha:t}}setup(e){return this.value=this._value||(this._value=this.getContext()),this.value.lightingModel=this.lightingModel||e.context.lightingModel,super.setup(e)}}const gc=bi(pc);class mc extends cc{static get type(){return"IrradianceNode"}constructor(e){super(),this.node=e}setup(e){e.context.irradiance.addAssign(this.node)}}let fc,yc;class xc extends Ms{static get type(){return"ScreenNode"}constructor(e){super(),this.scope=e,this.isViewportNode=!0}getNodeType(){return this.scope===xc.VIEWPORT?"vec4":"vec2"}getUpdateType(){let e=vs.NONE;return this.scope!==xc.SIZE&&this.scope!==xc.VIEWPORT||(e=vs.RENDER),this.updateType=e,e}update({renderer:e}){const t=e.getRenderTarget();this.scope===xc.VIEWPORT?null!==t?yc.copy(t.viewport):(e.getViewport(yc),yc.multiplyScalar(e.getPixelRatio())):null!==t?(fc.width=t.width,fc.height=t.height):e.getDrawingBufferSize(fc)}setup(){const e=this.scope;let r=null;return r=e===xc.SIZE?tn(fc||(fc=new t)):e===xc.VIEWPORT?tn(yc||(yc=new s)):Bi(_c.div(Tc)),r}generate(e){if(this.scope===xc.COORDINATE){let t=e.getFragCoord();if(e.isFlipY()){const r=e.getNodeProperties(Tc).outputNode.build(e);t=`${e.getType("vec2")}( ${t}.x, ${r}.y - ${t}.y )`}return t}return super.generate(e)}}xc.COORDINATE="coordinate",xc.VIEWPORT="viewport",xc.SIZE="size",xc.UV="uv";const bc=Ti(xc,xc.UV),Tc=Ti(xc,xc.SIZE),_c=Ti(xc,xc.COORDINATE),vc=Ti(xc,xc.VIEWPORT),Nc=vc.zw,Sc=_c.sub(vc.xy),Ac=Sc.div(Nc),Rc=_i((()=>(console.warn('TSL.ViewportNode: "viewportResolution" is deprecated. Use "screenSize" instead.'),Tc)),"vec2").once()(),Cc=_i((()=>(console.warn('TSL.ViewportNode: "viewportTopLeft" is deprecated. Use "screenUV" instead.'),bc)),"vec2").once()(),Ec=_i((()=>(console.warn('TSL.ViewportNode: "viewportBottomLeft" is deprecated. Use "screenUV.flipY()" instead.'),bc.flipY())),"vec2").once()(),wc=new t;class Mc extends xu{static get type(){return"ViewportTextureNode"}constructor(e=bc,t=null,r=null){null===r&&((r=new w).minFilter=M),super(r,e,t),this.generateMipmaps=!1,this.isOutputTextureNode=!0,this.updateBeforeType=vs.FRAME}updateBefore(e){const t=e.renderer;t.getDrawingBufferSize(wc);const r=this.value;r.image.width===wc.width&&r.image.height===wc.height||(r.image.width=wc.width,r.image.height=wc.height,r.needsUpdate=!0);const s=r.generateMipmaps;r.generateMipmaps=this.generateMipmaps,t.copyFramebufferToTexture(r),r.generateMipmaps=s}clone(){const e=new this.constructor(this.uvNode,this.levelNode,this.value);return e.generateMipmaps=this.generateMipmaps,e}}const Bc=bi(Mc),Uc=bi(Mc,null,null,{generateMipmaps:!0});let Fc=null;class Pc extends Mc{static get type(){return"ViewportDepthTextureNode"}constructor(e=bc,t=null){null===Fc&&(Fc=new B),super(e,t,Fc)}}const Ic=bi(Pc);class Lc extends Ms{static get type(){return"ViewportDepthNode"}constructor(e,t=null){super("float"),this.scope=e,this.valueNode=t,this.isViewportDepthNode=!0}generate(e){const{scope:t}=this;return t===Lc.DEPTH_BASE?e.getFragDepth():super.generate(e)}setup({camera:e}){const{scope:t}=this,r=this.valueNode;let s=null;if(t===Lc.DEPTH_BASE)null!==r&&(s=kc().assign(r));else if(t===Lc.DEPTH)s=e.isPerspectiveCamera?Dc(Zu.z,_u,vu):Vc(Zu.z,_u,vu);else if(t===Lc.LINEAR_DEPTH)if(null!==r)if(e.isPerspectiveCamera){const e=Oc(r,_u,vu);s=Vc(e,_u,vu)}else s=r;else s=Vc(Zu.z,_u,vu);return s}}Lc.DEPTH_BASE="depthBase",Lc.DEPTH="depth",Lc.LINEAR_DEPTH="linearDepth";const Vc=(e,t,r)=>e.add(t).div(t.sub(r)),Dc=(e,t,r)=>t.add(e).mul(r).div(r.sub(t).mul(e)),Oc=(e,t,r)=>t.mul(r).div(r.sub(t).mul(e).sub(r)),Gc=(e,t,r)=>{t=t.max(1e-6).toVar();const s=To(e.negate().div(t)),i=To(r.div(t));return s.div(i)},kc=bi(Lc,Lc.DEPTH_BASE),zc=Ti(Lc,Lc.DEPTH),$c=bi(Lc,Lc.LINEAR_DEPTH),Hc=$c(Ic());zc.assign=e=>kc(e);const Wc=bi(class extends Ms{constructor(e){super("float"),this.name=e,this.isBuiltinNode=!0}generate(){return this.name}});class jc extends Ms{static get type(){return"ClippingNode"}constructor(e=jc.DEFAULT){super(),this.scope=e}setup(e){super.setup(e);const t=e.clippingContext,{intersectionPlanes:r,unionPlanes:s}=t;return this.hardwareClipping=e.material.hardwareClipping,this.scope===jc.ALPHA_TO_COVERAGE?this.setupAlphaToCoverage(r,s):this.scope===jc.HARDWARE?this.setupHardwareClipping(s,e):this.setupDefault(r,s)}setupAlphaToCoverage(e,t){return _i((()=>{const r=Ci().toVar("distanceToPlane"),s=Ci().toVar("distanceToGradient"),i=Ci(1).toVar("clipOpacity"),n=t.length;if(!1===this.hardwareClipping&&n>0){const e=Sl(t);ic(n,(({i:t})=>{const n=e.element(t);r.assign(Zu.dot(n.xyz).negate().add(n.w)),s.assign(r.fwidth().div(2)),i.mulAssign(pa(s.negate(),s,r))}))}const o=e.length;if(o>0){const t=Sl(e),n=Ci(1).toVar("intersectionClipOpacity");ic(o,(({i:e})=>{const i=t.element(e);r.assign(Zu.dot(i.xyz).negate().add(i.w)),s.assign(r.fwidth().div(2)),n.mulAssign(pa(s.negate(),s,r).oneMinus())})),i.mulAssign(n.oneMinus())}on.a.mulAssign(i),on.a.equal(0).discard()}))()}setupDefault(e,t){return _i((()=>{const r=t.length;if(!1===this.hardwareClipping&&r>0){const e=Sl(t);ic(r,(({i:t})=>{const r=e.element(t);Zu.dot(r.xyz).greaterThan(r.w).discard()}))}const s=e.length;if(s>0){const t=Sl(e),r=Mi(!0).toVar("clipped");ic(s,(({i:e})=>{const s=t.element(e);r.assign(Zu.dot(s.xyz).greaterThan(s.w).and(r))})),r.discard()}}))()}setupHardwareClipping(e,t){const r=e.length;return t.enableHardwareClipping(r),_i((()=>{const s=Sl(e),i=Wc(t.getClipDistance());ic(r,(({i:e})=>{const t=s.element(e),r=Zu.dot(t.xyz).sub(t.w).negate();i.element(e).assign(r)}))}))()}}jc.ALPHA_TO_COVERAGE="alphaToCoverage",jc.DEFAULT="default",jc.HARDWARE="hardware";const qc=_i((([e])=>Ro(kn(1e4,Co(kn(17,e.x).add(kn(.1,e.y)))).mul(On(.1,Fo(Co(kn(13,e.y).add(e.x)))))))),Kc=_i((([e])=>qc(Bi(qc(e.xy),e.z)))),Xc=_i((([e])=>{const t=Ko(Io(Do(e.xyz)),Io(Oo(e.xyz))),r=Ci(1).div(Ci(.05).mul(t)).toVar("pixScale"),s=Bi(xo(No(To(r))),xo(So(To(r)))),i=Bi(Kc(No(s.x.mul(e.xyz))),Kc(No(s.y.mul(e.xyz)))),n=Ro(To(r)),o=On(kn(n.oneMinus(),i.x),kn(n,i.y)),a=qo(n,n.oneMinus()),u=Ii(o.mul(o).div(kn(2,a).mul(Gn(1,a))),o.sub(kn(.5,a)).div(Gn(1,a)),Gn(1,Gn(1,o).mul(Gn(1,o)).div(kn(2,a).mul(Gn(1,a))))),l=o.lessThan(a.oneMinus()).select(o.lessThan(a).select(u.x,u.y),u.z);return da(l,1e-6,1)})).setLayout({name:"getAlphaHashThreshold",type:"float",inputs:[{name:"position",type:"vec3"}]});class Yc extends U{static get type(){return"NodeMaterial"}get type(){return this.constructor.type}set type(e){}constructor(){super(),this.isNodeMaterial=!0,this.forceSinglePass=!1,this.fog=!0,this.lights=!1,this.hardwareClipping=!1,this.lightsNode=null,this.envNode=null,this.aoNode=null,this.colorNode=null,this.normalNode=null,this.opacityNode=null,this.backdropNode=null,this.backdropAlphaNode=null,this.alphaTestNode=null,this.positionNode=null,this.geometryNode=null,this.depthNode=null,this.shadowPositionNode=null,this.receivedShadowNode=null,this.castShadowNode=null,this.outputNode=null,this.mrtNode=null,this.fragmentNode=null,this.vertexNode=null}customProgramCacheKey(){return this.type+cs(this)}build(e){this.setup(e)}setupObserver(e){return new os(e)}setup(e){e.context.setupNormal=()=>this.setupNormal(e),e.context.setupPositionView=()=>this.setupPositionView(e),e.context.setupModelViewProjection=()=>this.setupModelViewProjection(e);const t=e.renderer,r=t.getRenderTarget();e.addStack();const s=this.vertexNode||this.setupVertex(e);let i;e.stack.outputNode=s,this.setupHardwareClipping(e),null!==this.geometryNode&&(e.stack.outputNode=e.stack.outputNode.bypass(this.geometryNode)),e.addFlow("vertex",e.removeStack()),e.addStack();const n=this.setupClipping(e);if(!0===this.depthWrite&&(null!==r?!0===r.depthBuffer&&this.setupDepth(e):!0===t.depth&&this.setupDepth(e)),null===this.fragmentNode){this.setupDiffuseColor(e),this.setupVariants(e);const s=this.setupLighting(e);null!==n&&e.stack.add(n);const o=Oi(s,on.a).max(0);if(i=this.setupOutput(e,o),Sn.assign(i),null!==this.outputNode&&(i=this.outputNode),null!==r){const e=t.getMRT(),r=this.mrtNode;null!==e?(i=e,null!==r&&(i=e.merge(r))):null!==r&&(i=r)}}else{let t=this.fragmentNode;!0!==t.isOutputStructNode&&(t=Oi(t)),i=this.setupOutput(e,t)}e.stack.outputNode=i,e.addFlow("fragment",e.removeStack()),e.monitor=this.setupObserver(e)}setupClipping(e){if(null===e.clippingContext)return null;const{unionPlanes:t,intersectionPlanes:r}=e.clippingContext;let s=null;if(t.length>0||r.length>0){const t=e.renderer.samples;this.alphaToCoverage&&t>1?s=fi(new jc(jc.ALPHA_TO_COVERAGE)):e.stack.add(fi(new jc))}return s}setupHardwareClipping(e){if(this.hardwareClipping=!1,null===e.clippingContext)return;const t=e.clippingContext.unionPlanes.length;t>0&&t<=8&&e.isAvailable("clipDistance")&&(e.stack.add(fi(new jc(jc.HARDWARE))),this.hardwareClipping=!0)}setupDepth(e){const{renderer:t,camera:r}=e;let s=this.depthNode;if(null===s){const e=t.getMRT();e&&e.has("depth")?s=e.get("depth"):!0===t.logarithmicDepthBuffer&&(s=r.isPerspectiveCamera?Gc(Zu.z,_u,vu):Vc(Zu.z,_u,vu))}null!==s&&zc.assign(s).append()}setupPositionView(){return $u.mul(Ku).xyz}setupModelViewProjection(){return Nu.mul(Zu)}setupVertex(e){return e.addStack(),this.setupPosition(e),e.context.vertex=e.removeStack(),Gd}setupPosition(e){const{object:t,geometry:r}=e;if((r.morphAttributes.position||r.morphAttributes.normal||r.morphAttributes.color)&&dc(t).append(),!0===t.isSkinnedMesh&&rc(t).append(),this.displacementMap){const e=Ml("displacementMap","texture"),t=Ml("displacementScale","float"),r=Ml("displacementBias","float");Ku.addAssign(il.normalize().mul(e.x.mul(t).add(r)))}return t.isBatchedMesh&&Jd(t).append(),t.isInstancedMesh&&t.instanceMatrix&&!0===t.instanceMatrix.isInstancedBufferAttribute&&Qd(t).append(),null!==this.positionNode&&Ku.assign(this.positionNode.context({isPositionNodeInput:!0})),Ku}setupDiffuseColor({object:e,geometry:t}){let r=this.colorNode?Oi(this.colorNode):sd;if(!0===this.vertexColors&&t.hasAttribute("color")&&(r=Oi(r.xyz.mul(hu("color","vec3")),r.a)),e.instanceColor){r=nn("vec3","vInstanceColor").mul(r)}if(e.isBatchedMesh&&e._colorsTexture){r=nn("vec3","vBatchColor").mul(r)}on.assign(r);const s=this.opacityNode?Ci(this.opacityNode):od;if(on.a.assign(on.a.mul(s)),null!==this.alphaTestNode||this.alphaTest>0){const e=null!==this.alphaTestNode?Ci(this.alphaTestNode):rd;on.a.lessThanEqual(e).discard()}!0===this.alphaHash&&on.a.lessThan(Xc(Ku)).discard(),!1===this.transparent&&this.blending===F&&!1===this.alphaToCoverage&&on.a.assign(1)}setupVariants(){}setupOutgoingLight(){return!0===this.lights?Ii(0):on.rgb}setupNormal(){return this.normalNode?Ii(this.normalNode):gd}setupEnvironment(){let e=null;return this.envNode?e=this.envNode:this.envMap&&(e=this.envMap.isCubeTexture?Ml("envMap","cubeTexture"):Ml("envMap","texture")),e}setupLightMap(e){let t=null;return e.material.lightMap&&(t=new mc(Vd)),t}setupLights(e){const t=[],r=this.setupEnvironment(e);r&&r.isLightingNode&&t.push(r);const s=this.setupLightMap(e);if(s&&s.isLightingNode&&t.push(s),null!==this.aoNode||e.material.aoMap){const e=null!==this.aoNode?this.aoNode:Dd;t.push(new hc(e))}let i=this.lightsNode||e.lightsNode;return t.length>0&&(i=e.renderer.lighting.createNode([...i.getLights(),...t])),i}setupLightingModel(){}setupLighting(e){const{material:t}=e,{backdropNode:r,backdropAlphaNode:s,emissiveNode:i}=this,n=!0===this.lights||null!==this.lightsNode?this.setupLights(e):null;let o=this.setupOutgoingLight(e);if(n&&n.getScope().hasLights){const t=this.setupLightingModel(e);o=gc(n,t,r,s)}else null!==r&&(o=Ii(null!==s?la(o,r,s):r));return(i&&!0===i.isNode||t.emissive&&!0===t.emissive.isColor)&&(an.assign(Ii(i||nd)),o=o.add(an)),o}setupOutput(e,t){if(!0===this.fog){const r=e.fogNode;r&&(Sn.assign(t),t=Oi(r))}return t}setDefaultValues(e){for(const t in e){const r=e[t];void 0===this[t]&&(this[t]=r,r&&r.clone&&(this[t]=r.clone()))}const t=Object.getOwnPropertyDescriptors(e.constructor.prototype);for(const e in t)void 0===Object.getOwnPropertyDescriptor(this.constructor.prototype,e)&&void 0!==t[e].get&&Object.defineProperty(this.constructor.prototype,e,t[e])}toJSON(e){const t=void 0===e||"string"==typeof e;t&&(e={textures:{},images:{},nodes:{}});const r=U.prototype.toJSON.call(this,e),s=hs(this);r.inputNodes={};for(const{property:t,childNode:i}of s)r.inputNodes[t]=i.toJSON(e).uuid;function i(e){const t=[];for(const r in e){const s=e[r];delete s.metadata,t.push(s)}return t}if(t){const t=i(e.textures),s=i(e.images),n=i(e.nodes);t.length>0&&(r.textures=t),s.length>0&&(r.images=s),n.length>0&&(r.nodes=n)}return r}copy(e){return this.lightsNode=e.lightsNode,this.envNode=e.envNode,this.colorNode=e.colorNode,this.normalNode=e.normalNode,this.opacityNode=e.opacityNode,this.backdropNode=e.backdropNode,this.backdropAlphaNode=e.backdropAlphaNode,this.alphaTestNode=e.alphaTestNode,this.positionNode=e.positionNode,this.geometryNode=e.geometryNode,this.depthNode=e.depthNode,this.shadowPositionNode=e.shadowPositionNode,this.receivedShadowNode=e.receivedShadowNode,this.castShadowNode=e.castShadowNode,this.outputNode=e.outputNode,this.mrtNode=e.mrtNode,this.fragmentNode=e.fragmentNode,this.vertexNode=e.vertexNode,super.copy(e)}}const Qc=new P;class Zc extends Yc{static get type(){return"InstancedPointsNodeMaterial"}constructor(e={}){super(),this.lights=!1,this.useAlphaToCoverage=!0,this.useColor=e.vertexColors,this.pointWidth=1,this.pointColorNode=null,this.pointWidthNode=null,this.setDefaultValues(Qc),this.setValues(e)}setup(e){this.setupShaders(e),super.setup(e)}setupShaders({renderer:e}){const t=this.alphaToCoverage,r=this.useColor;this.vertexNode=_i((()=>{const e=hu("instancePosition").xyz,t=Oi($u.mul(Oi(e,1))),r=vc.z.div(vc.w),s=Nu.mul(t),i=qu.xy.toVar();return i.mulAssign(this.pointWidthNode?this.pointWidthNode:Id),i.assign(i.div(vc.z)),i.y.assign(i.y.mul(r)),i.assign(i.mul(s.w)),s.addAssign(Oi(i,0,0)),s}))(),this.fragmentNode=_i((()=>{const s=Ci(1).toVar(),i=ua(pu().mul(2).sub(1));if(t&&e.samples>1){const e=Ci(i.fwidth()).toVar();s.assign(pa(e.oneMinus(),e.add(1),i).oneMinus())}else i.greaterThan(1).discard();let n;if(this.pointColorNode)n=this.pointColorNode;else if(r){n=hu("instanceColor").mul(sd)}else n=sd;return s.mulAssign(od),Oi(n,s)}))()}get alphaToCoverage(){return this.useAlphaToCoverage}set alphaToCoverage(e){this.useAlphaToCoverage!==e&&(this.useAlphaToCoverage=e,this.needsUpdate=!0)}}const Jc=new I;class eh extends Yc{static get type(){return"LineBasicNodeMaterial"}constructor(e){super(),this.isLineBasicNodeMaterial=!0,this.lights=!1,this.setDefaultValues(Jc),this.setValues(e)}}const th=new L;class rh extends Yc{static get type(){return"LineDashedNodeMaterial"}constructor(e){super(),this.isLineDashedNodeMaterial=!0,this.lights=!1,this.setDefaultValues(th),this.dashOffset=0,this.offsetNode=null,this.dashScaleNode=null,this.dashSizeNode=null,this.gapSizeNode=null,this.setValues(e)}setupVariants(){const e=this.offsetNode?Ci(this.offsetNodeNode):Pd,t=this.dashScaleNode?Ci(this.dashScaleNode):Md,r=this.dashSizeNode?Ci(this.dashSizeNode):Bd,s=this.dashSizeNode?Ci(this.dashGapNode):Ud;An.assign(r),Rn.assign(s);const i=wa(hu("lineDistance").mul(t));(e?i.add(e):i).mod(An.add(Rn)).greaterThan(An).discard()}}let sh=null;class ih extends Mc{static get type(){return"ViewportSharedTextureNode"}constructor(e=bc,t=null){null===sh&&(sh=new w),super(e,t,sh)}updateReference(){return this}}const nh=bi(ih),oh=new L;class ah extends Yc{static get type(){return"Line2NodeMaterial"}constructor(e={}){super(),this.lights=!1,this.setDefaultValues(oh),this.useAlphaToCoverage=!0,this.useColor=e.vertexColors,this.useDash=e.dashed,this.useWorldUnits=!1,this.dashOffset=0,this.lineWidth=1,this.lineColorNode=null,this.offsetNode=null,this.dashScaleNode=null,this.dashSizeNode=null,this.gapSizeNode=null,this.blending=V,this.setValues(e)}setup(e){this.setupShaders(e),super.setup(e)}setupShaders({renderer:e}){const t=this.alphaToCoverage,r=this.useColor,s=this.dashed,i=this.worldUnits,n=_i((({start:e,end:t})=>{const r=Nu.element(2).element(2),s=Nu.element(3).element(2).mul(-.5).div(r).sub(e.z).div(t.z.sub(e.z));return Oi(la(e.xyz,t.xyz,s),t.w)})).setLayout({name:"trimSegment",type:"vec4",inputs:[{name:"start",type:"vec4"},{name:"end",type:"vec4"}]});this.vertexNode=_i((()=>{const e=hu("instanceStart"),t=hu("instanceEnd"),r=Oi($u.mul(Oi(e,1))).toVar("start"),o=Oi($u.mul(Oi(t,1))).toVar("end");if(s){const e=this.dashScaleNode?Ci(this.dashScaleNode):Md,t=this.offsetNode?Ci(this.offsetNode):Pd,r=hu("instanceDistanceStart"),s=hu("instanceDistanceEnd");let i=qu.y.lessThan(.5).select(e.mul(r),e.mul(s));i=i.add(t),nn("float","lineDistance").assign(i)}i&&(nn("vec3","worldStart").assign(r.xyz),nn("vec3","worldEnd").assign(o.xyz));const a=vc.z.div(vc.w),u=Nu.element(2).element(3).equal(-1);Si(u,(()=>{Si(r.z.lessThan(0).and(o.z.greaterThan(0)),(()=>{o.assign(n({start:r,end:o}))})).ElseIf(o.z.lessThan(0).and(r.z.greaterThanEqual(0)),(()=>{r.assign(n({start:o,end:r}))}))}));const l=Nu.mul(r),d=Nu.mul(o),c=l.xyz.div(l.w),h=d.xyz.div(d.w),p=h.xy.sub(c.xy).toVar();p.x.assign(p.x.mul(a)),p.assign(p.normalize());const g=Oi().toVar();if(i){const e=o.xyz.sub(r.xyz).normalize(),t=la(r.xyz,o.xyz,.5).normalize(),i=e.cross(t).normalize(),n=e.cross(i),a=nn("vec4","worldPos");a.assign(qu.y.lessThan(.5).select(r,o));const u=Fd.mul(.5);a.addAssign(Oi(qu.x.lessThan(0).select(i.mul(u),i.mul(u).negate()),0)),s||(a.addAssign(Oi(qu.y.lessThan(.5).select(e.mul(u).negate(),e.mul(u)),0)),a.addAssign(Oi(n.mul(u),0)),Si(qu.y.greaterThan(1).or(qu.y.lessThan(0)),(()=>{a.subAssign(Oi(n.mul(2).mul(u),0))}))),g.assign(Nu.mul(a));const l=Ii().toVar();l.assign(qu.y.lessThan(.5).select(c,h)),g.z.assign(l.z.mul(g.w))}else{const e=Bi(p.y,p.x.negate()).toVar("offset");p.x.assign(p.x.div(a)),e.x.assign(e.x.div(a)),e.assign(qu.x.lessThan(0).select(e.negate(),e)),Si(qu.y.lessThan(0),(()=>{e.assign(e.sub(p))})).ElseIf(qu.y.greaterThan(1),(()=>{e.assign(e.add(p))})),e.assign(e.mul(Fd)),e.assign(e.div(vc.w)),g.assign(qu.y.lessThan(.5).select(l,d)),e.assign(e.mul(g.w)),g.assign(g.add(Oi(e,0,0)))}return g}))();const o=_i((({p1:e,p2:t,p3:r,p4:s})=>{const i=e.sub(r),n=s.sub(r),o=t.sub(e),a=i.dot(n),u=n.dot(o),l=i.dot(o),d=n.dot(n),c=o.dot(o).mul(d).sub(u.mul(u)),h=a.mul(u).sub(l.mul(d)).div(c).clamp(),p=a.add(u.mul(h)).div(d).clamp();return Bi(h,p)}));if(this.colorNode=_i((()=>{const n=pu();if(s){const e=this.dashSizeNode?Ci(this.dashSizeNode):Bd,t=this.gapSizeNode?Ci(this.gapSizeNode):Ud;An.assign(e),Rn.assign(t);const r=nn("float","lineDistance");n.y.lessThan(-1).or(n.y.greaterThan(1)).discard(),r.mod(An.add(Rn)).greaterThan(An).discard()}const a=Ci(1).toVar("alpha");if(i){const r=nn("vec3","worldStart"),i=nn("vec3","worldEnd"),n=nn("vec4","worldPos").xyz.normalize().mul(1e5),u=i.sub(r),l=o({p1:r,p2:i,p3:Ii(0,0,0),p4:n}),d=r.add(u.mul(l.x)),c=n.mul(l.y),h=d.sub(c).length().div(Fd);if(!s)if(t&&e.samples>1){const e=h.fwidth();a.assign(pa(e.negate().add(.5),e.add(.5),h).oneMinus())}else h.greaterThan(.5).discard()}else if(t&&e.samples>1){const e=n.x,t=n.y.greaterThan(0).select(n.y.sub(1),n.y.add(1)),r=e.mul(e).add(t.mul(t)),s=Ci(r.fwidth()).toVar("dlen");Si(n.y.abs().greaterThan(1),(()=>{a.assign(pa(s.oneMinus(),s.add(1),r).oneMinus())}))}else Si(n.y.abs().greaterThan(1),(()=>{const e=n.x,t=n.y.greaterThan(0).select(n.y.sub(1),n.y.add(1));e.mul(e).add(t.mul(t)).greaterThan(1).discard()}));let u;if(this.lineColorNode)u=this.lineColorNode;else if(r){const e=hu("instanceColorStart"),t=hu("instanceColorEnd");u=qu.y.lessThan(.5).select(e,t).mul(sd)}else u=sd;return Oi(u,a)}))(),this.transparent){const e=this.opacityNode?Ci(this.opacityNode):od;this.outputNode=Oi(this.colorNode.rgb.mul(e).add(nh().rgb.mul(e.oneMinus())),this.colorNode.a)}}get worldUnits(){return this.useWorldUnits}set worldUnits(e){this.useWorldUnits!==e&&(this.useWorldUnits=e,this.needsUpdate=!0)}get dashed(){return this.useDash}set dashed(e){this.useDash!==e&&(this.useDash=e,this.needsUpdate=!0)}get alphaToCoverage(){return this.useAlphaToCoverage}set alphaToCoverage(e){this.useAlphaToCoverage!==e&&(this.useAlphaToCoverage=e,this.needsUpdate=!0)}}const uh=e=>fi(e).mul(.5).add(.5),lh=new D;class dh extends Yc{static get type(){return"MeshNormalNodeMaterial"}constructor(e){super(),this.lights=!1,this.isMeshNormalNodeMaterial=!0,this.setDefaultValues(lh),this.setValues(e)}setupDiffuseColor(){const e=this.opacityNode?Ci(this.opacityNode):od;on.assign(Oi(uh(ul),e))}}class ch extends Fs{static get type(){return"EquirectUVNode"}constructor(e=Qu){super("vec2"),this.dirNode=e}setup(){const e=this.dirNode,t=e.z.atan(e.x).mul(1/(2*Math.PI)).add(.5),r=e.y.clamp(-1,1).asin().mul(1/Math.PI).add(.5);return Bi(t,r)}}const hh=bi(ch);class ph extends O{constructor(e=1,t={}){super(e,t),this.isCubeRenderTarget=!0}fromEquirectangularTexture(e,t){const r=t.minFilter,s=t.generateMipmaps;t.generateMipmaps=!0,this.texture.type=t.type,this.texture.colorSpace=t.colorSpace,this.texture.generateMipmaps=t.generateMipmaps,this.texture.minFilter=t.minFilter,this.texture.magFilter=t.magFilter;const i=new G(5,5,5),n=hh(Qu),o=new Yc;o.colorNode=bu(t,n,0),o.side=T,o.blending=V;const a=new k(i,o),u=new z;u.add(a),t.minFilter===M&&(t.minFilter=$);const l=new H(1,10,this),d=e.getMRT();return e.setMRT(null),l.update(e,u),e.setMRT(d),t.minFilter=r,t.currentGenerateMipmaps=s,a.geometry.dispose(),a.material.dispose(),this}}const gh=new WeakMap;class mh extends Fs{static get type(){return"CubeMapNode"}constructor(e){super("vec3"),this.envNode=e,this._cubeTexture=null,this._cubeTextureNode=bl();const t=new W;t.isRenderTargetTexture=!0,this._defaultTexture=t,this.updateBeforeType=vs.RENDER}updateBefore(e){const{renderer:t,material:r}=e,s=this.envNode;if(s.isTextureNode||s.isMaterialReferenceNode){const e=s.isTextureNode?s.value:r[s.property];if(e&&e.isTexture){const r=e.mapping;if(r===j||r===q){if(gh.has(e)){const t=gh.get(e);yh(t,e.mapping),this._cubeTexture=t}else{const r=e.image;if(function(e){return null!=e&&e.height>0}(r)){const s=new ph(r.height);s.fromEquirectangularTexture(t,e),yh(s.texture,e.mapping),this._cubeTexture=s.texture,gh.set(e,s.texture),e.addEventListener("dispose",fh)}else this._cubeTexture=this._defaultTexture}this._cubeTextureNode.value=this._cubeTexture}else this._cubeTextureNode=this.envNode}}}setup(e){return this.updateBefore(e),this._cubeTextureNode}}function fh(e){const t=e.target;t.removeEventListener("dispose",fh);const r=gh.get(t);void 0!==r&&(gh.delete(t),r.dispose())}function yh(e,t){t===j?e.mapping=_:t===q&&(e.mapping=v)}const xh=bi(mh);class bh extends cc{static get type(){return"BasicEnvironmentNode"}constructor(e=null){super(),this.envNode=e}setup(e){e.context.environment=xh(this.envNode)}}class Th extends cc{static get type(){return"BasicLightMapNode"}constructor(e=null){super(),this.lightMapNode=e}setup(e){const t=Ci(1/Math.PI);e.context.irradianceLightMap=this.lightMapNode.mul(t)}}class _h{start(){}finish(){}direct(){}directRectArea(){}indirect(){}ambientOcclusion(){}}class vh extends _h{constructor(){super()}indirect(e,t,r){const s=e.ambientOcclusion,i=e.reflectedLight,n=r.context.irradianceLightMap;i.indirectDiffuse.assign(Oi(0)),n?i.indirectDiffuse.addAssign(n):i.indirectDiffuse.addAssign(Oi(1,1,1,0)),i.indirectDiffuse.mulAssign(s),i.indirectDiffuse.mulAssign(on.rgb)}finish(e,t,r){const s=r.material,i=e.outgoingLight,n=r.context.environment;if(n)switch(s.combine){case Y:i.rgb.assign(la(i.rgb,i.rgb.mul(n.rgb),dd.mul(cd)));break;case X:i.rgb.assign(la(i.rgb,n.rgb,dd.mul(cd)));break;case K:i.rgb.addAssign(n.rgb.mul(dd.mul(cd)));break;default:console.warn("THREE.BasicLightingModel: Unsupported .combine value:",s.combine)}}}const Nh=new Q;class Sh extends Yc{static get type(){return"MeshBasicNodeMaterial"}constructor(e){super(),this.isMeshBasicNodeMaterial=!0,this.lights=!0,this.setDefaultValues(Nh),this.setValues(e)}setupNormal(){return ol}setupEnvironment(e){const t=super.setupEnvironment(e);return t?new bh(t):null}setupLightMap(e){let t=null;return e.material.lightMap&&(t=new Th(Vd)),t}setupOutgoingLight(){return on.rgb}setupLightingModel(){return new vh}}const Ah=_i((({f0:e,f90:t,dotVH:r})=>{const s=r.mul(-5.55473).sub(6.98316).mul(r).exp2();return e.mul(s.oneMinus()).add(t.mul(s))})),Rh=_i((e=>e.diffuseColor.mul(1/Math.PI))),Ch=_i((({dotNH:e})=>Nn.mul(Ci(.5)).add(1).mul(Ci(1/Math.PI)).mul(e.pow(Nn)))),Eh=_i((({lightDirection:e})=>{const t=e.add(Ju).normalize(),r=ul.dot(t).clamp(),s=Ju.dot(t).clamp(),i=Ah({f0:_n,f90:1,dotVH:s}),n=Ci(.25),o=Ch({dotNH:r});return i.mul(n).mul(o)}));class wh extends vh{constructor(e=!0){super(),this.specular=e}direct({lightDirection:e,lightColor:t,reflectedLight:r}){const s=ul.dot(e).clamp().mul(t);r.directDiffuse.addAssign(s.mul(Rh({diffuseColor:on.rgb}))),!0===this.specular&&r.directSpecular.addAssign(s.mul(Eh({lightDirection:e})).mul(dd))}indirect({ambientOcclusion:e,irradiance:t,reflectedLight:r}){r.indirectDiffuse.addAssign(t.mul(Rh({diffuseColor:on}))),r.indirectDiffuse.mulAssign(e)}}const Mh=new Z;class Bh extends Yc{static get type(){return"MeshLambertNodeMaterial"}constructor(e){super(),this.isMeshLambertNodeMaterial=!0,this.lights=!0,this.setDefaultValues(Mh),this.setValues(e)}setupEnvironment(e){const t=super.setupEnvironment(e);return t?new bh(t):null}setupLightingModel(){return new wh(!1)}}const Uh=new J;class Fh extends Yc{static get type(){return"MeshPhongNodeMaterial"}constructor(e){super(),this.isMeshPhongNodeMaterial=!0,this.lights=!0,this.shininessNode=null,this.specularNode=null,this.setDefaultValues(Uh),this.setValues(e)}setupEnvironment(e){const t=super.setupEnvironment(e);return t?new bh(t):null}setupLightingModel(){return new wh}setupVariants(){const e=(this.shininessNode?Ci(this.shininessNode):id).max(1e-4);Nn.assign(e);const t=this.specularNode||ad;_n.assign(t)}copy(e){return this.shininessNode=e.shininessNode,this.specularNode=e.specularNode,super.copy(e)}}const Ph=_i((e=>{if(!1===e.geometry.hasAttribute("normal"))return Ci(0);const t=ol.dFdx().abs().max(ol.dFdy().abs());return t.x.max(t.y).max(t.z)})),Ih=_i((e=>{const{roughness:t}=e,r=Ph();let s=t.max(.0525);return s=s.add(r),s=s.min(1),s})),Lh=_i((({alpha:e,dotNL:t,dotNV:r})=>{const s=e.pow2(),i=t.mul(s.add(s.oneMinus().mul(r.pow2())).sqrt()),n=r.mul(s.add(s.oneMinus().mul(t.pow2())).sqrt());return zn(.5,i.add(n).max(uo))})).setLayout({name:"V_GGX_SmithCorrelated",type:"float",inputs:[{name:"alpha",type:"float"},{name:"dotNL",type:"float"},{name:"dotNV",type:"float"}]}),Vh=_i((({alphaT:e,alphaB:t,dotTV:r,dotBV:s,dotTL:i,dotBL:n,dotNV:o,dotNL:a})=>{const u=a.mul(Ii(e.mul(r),t.mul(s),o).length()),l=o.mul(Ii(e.mul(i),t.mul(n),a).length());return zn(.5,u.add(l)).saturate()})).setLayout({name:"V_GGX_SmithCorrelated_Anisotropic",type:"float",inputs:[{name:"alphaT",type:"float",qualifier:"in"},{name:"alphaB",type:"float",qualifier:"in"},{name:"dotTV",type:"float",qualifier:"in"},{name:"dotBV",type:"float",qualifier:"in"},{name:"dotTL",type:"float",qualifier:"in"},{name:"dotBL",type:"float",qualifier:"in"},{name:"dotNV",type:"float",qualifier:"in"},{name:"dotNL",type:"float",qualifier:"in"}]}),Dh=_i((({alpha:e,dotNH:t})=>{const r=e.pow2(),s=t.pow2().mul(r.oneMinus()).oneMinus();return r.div(s.pow2()).mul(1/Math.PI)})).setLayout({name:"D_GGX",type:"float",inputs:[{name:"alpha",type:"float"},{name:"dotNH",type:"float"}]}),Oh=Ci(1/Math.PI),Gh=_i((({alphaT:e,alphaB:t,dotNH:r,dotTH:s,dotBH:i})=>{const n=e.mul(t),o=Ii(t.mul(s),e.mul(i),n.mul(r)),a=o.dot(o),u=n.div(a);return Oh.mul(n.mul(u.pow2()))})).setLayout({name:"D_GGX_Anisotropic",type:"float",inputs:[{name:"alphaT",type:"float",qualifier:"in"},{name:"alphaB",type:"float",qualifier:"in"},{name:"dotNH",type:"float",qualifier:"in"},{name:"dotTH",type:"float",qualifier:"in"},{name:"dotBH",type:"float",qualifier:"in"}]}),kh=_i((e=>{const{lightDirection:t,f0:r,f90:s,roughness:i,f:n,USE_IRIDESCENCE:o,USE_ANISOTROPY:a}=e,u=e.normalView||ul,l=i.pow2(),d=t.add(Ju).normalize(),c=u.dot(t).clamp(),h=u.dot(Ju).clamp(),p=u.dot(d).clamp(),g=Ju.dot(d).clamp();let m,f,y=Ah({f0:r,f90:s,dotVH:g});if(pi(o)&&(y=gn.mix(y,n)),pi(a)){const e=bn.dot(t),r=bn.dot(Ju),s=bn.dot(d),i=Tn.dot(t),n=Tn.dot(Ju),o=Tn.dot(d);m=Vh({alphaT:yn,alphaB:l,dotTV:r,dotBV:n,dotTL:e,dotBL:i,dotNV:h,dotNL:c}),f=Gh({alphaT:yn,alphaB:l,dotNH:p,dotTH:s,dotBH:o})}else m=Lh({alpha:l,dotNL:c,dotNV:h}),f=Dh({alpha:l,dotNH:p});return y.mul(m).mul(f)})),zh=_i((({roughness:e,dotNV:t})=>{const r=Oi(-1,-.0275,-.572,.022),s=Oi(1,.0425,1.04,-.04),i=e.mul(r).add(s),n=i.x.mul(i.x).min(t.mul(-9.28).exp2()).mul(i.x).add(i.y);return Bi(-1.04,1.04).mul(n).add(i.zw)})).setLayout({name:"DFGApprox",type:"vec2",inputs:[{name:"roughness",type:"float"},{name:"dotNV",type:"vec3"}]}),$h=_i((e=>{const{dotNV:t,specularColor:r,specularF90:s,roughness:i}=e,n=zh({dotNV:t,roughness:i});return r.mul(n.x).add(s.mul(n.y))})),Hh=_i((({f:e,f90:t,dotVH:r})=>{const s=r.oneMinus().saturate(),i=s.mul(s),n=s.mul(i,i).clamp(0,.9999);return e.sub(Ii(t).mul(n)).div(n.oneMinus())})).setLayout({name:"Schlick_to_F0",type:"vec3",inputs:[{name:"f",type:"vec3"},{name:"f90",type:"float"},{name:"dotVH",type:"float"}]}),Wh=_i((({roughness:e,dotNH:t})=>{const r=e.pow2(),s=Ci(1).div(r),i=t.pow2().oneMinus().max(.0078125);return Ci(2).add(s).mul(i.pow(s.mul(.5))).div(2*Math.PI)})).setLayout({name:"D_Charlie",type:"float",inputs:[{name:"roughness",type:"float"},{name:"dotNH",type:"float"}]}),jh=_i((({dotNV:e,dotNL:t})=>Ci(1).div(Ci(4).mul(t.add(e).sub(t.mul(e)))))).setLayout({name:"V_Neubelt",type:"float",inputs:[{name:"dotNV",type:"float"},{name:"dotNL",type:"float"}]}),qh=_i((({lightDirection:e})=>{const t=e.add(Ju).normalize(),r=ul.dot(e).clamp(),s=ul.dot(Ju).clamp(),i=ul.dot(t).clamp(),n=Wh({roughness:pn,dotNH:i}),o=jh({dotNV:s,dotNL:r});return hn.mul(n).mul(o)})),Kh=_i((({N:e,V:t,roughness:r})=>{const s=e.dot(t).saturate(),i=Bi(r,s.oneMinus().sqrt());return i.assign(i.mul(.984375).add(.0078125)),i})).setLayout({name:"LTC_Uv",type:"vec2",inputs:[{name:"N",type:"vec3"},{name:"V",type:"vec3"},{name:"roughness",type:"float"}]}),Xh=_i((({f:e})=>{const t=e.length();return Ko(t.mul(t).add(e.z).div(t.add(1)),0)})).setLayout({name:"LTC_ClippedSphereFormFactor",type:"float",inputs:[{name:"f",type:"vec3"}]}),Yh=_i((({v1:e,v2:t})=>{const r=e.dot(t),s=r.abs().toVar(),i=s.mul(.0145206).add(.4965155).mul(s).add(.8543985).toVar(),n=s.add(4.1616724).mul(s).add(3.417594).toVar(),o=i.div(n),a=r.greaterThan(0).select(o,Ko(r.mul(r).oneMinus(),1e-7).inverseSqrt().mul(.5).sub(o));return e.cross(t).mul(a)})).setLayout({name:"LTC_EdgeVectorFormFactor",type:"vec3",inputs:[{name:"v1",type:"vec3"},{name:"v2",type:"vec3"}]}),Qh=_i((({N:e,V:t,P:r,mInv:s,p0:i,p1:n,p2:o,p3:a})=>{const u=n.sub(i).toVar(),l=a.sub(i).toVar(),d=u.cross(l),c=Ii().toVar();return Si(d.dot(r.sub(i)).greaterThanEqual(0),(()=>{const u=t.sub(e.mul(t.dot(e))).normalize(),l=e.cross(u).negate(),d=s.mul(Hi(u,l,e).transpose()).toVar(),h=d.mul(i.sub(r)).normalize().toVar(),p=d.mul(n.sub(r)).normalize().toVar(),g=d.mul(o.sub(r)).normalize().toVar(),m=d.mul(a.sub(r)).normalize().toVar(),f=Ii(0).toVar();f.addAssign(Yh({v1:h,v2:p})),f.addAssign(Yh({v1:p,v2:g})),f.addAssign(Yh({v1:g,v2:m})),f.addAssign(Yh({v1:m,v2:h})),c.assign(Ii(Xh({f:f})))})),c})).setLayout({name:"LTC_Evaluate",type:"vec3",inputs:[{name:"N",type:"vec3"},{name:"V",type:"vec3"},{name:"P",type:"vec3"},{name:"mInv",type:"mat3"},{name:"p0",type:"vec3"},{name:"p1",type:"vec3"},{name:"p2",type:"vec3"},{name:"p3",type:"vec3"}]}),Zh=1/6,Jh=e=>kn(Zh,kn(e,kn(e,e.negate().add(3)).sub(3)).add(1)),ep=e=>kn(Zh,kn(e,kn(e,kn(3,e).sub(6))).add(4)),tp=e=>kn(Zh,kn(e,kn(e,kn(-3,e).add(3)).add(3)).add(1)),rp=e=>kn(Zh,ra(e,3)),sp=e=>Jh(e).add(ep(e)),ip=e=>tp(e).add(rp(e)),np=e=>On(-1,ep(e).div(Jh(e).add(ep(e)))),op=e=>On(1,rp(e).div(tp(e).add(rp(e)))),ap=(e,t,r)=>{const s=e.uvNode,i=kn(s,t.zw).add(.5),n=No(i),o=Ro(i),a=sp(o.x),u=ip(o.x),l=np(o.x),d=op(o.x),c=np(o.y),h=op(o.y),p=Bi(n.x.add(l),n.y.add(c)).sub(.5).mul(t.xy),g=Bi(n.x.add(d),n.y.add(c)).sub(.5).mul(t.xy),m=Bi(n.x.add(l),n.y.add(h)).sub(.5).mul(t.xy),f=Bi(n.x.add(d),n.y.add(h)).sub(.5).mul(t.xy),y=sp(o.y).mul(On(a.mul(e.sample(p).level(r)),u.mul(e.sample(g).level(r)))),x=ip(o.y).mul(On(a.mul(e.sample(m).level(r)),u.mul(e.sample(f).level(r))));return y.add(x)},up=_i((([e,t=Ci(3)])=>{const r=Bi(e.size(Ei(t))),s=Bi(e.size(Ei(t.add(1)))),i=zn(1,r),n=zn(1,s),o=ap(e,Oi(i,r),No(t)),a=ap(e,Oi(n,s),So(t));return Ro(t).mix(o,a)})),lp=_i((([e,t,r,s,i])=>{const n=Ii(ha(t.negate(),Ao(e),zn(1,s))),o=Ii(Io(i[0].xyz),Io(i[1].xyz),Io(i[2].xyz));return Ao(n).mul(r.mul(o))})).setLayout({name:"getVolumeTransmissionRay",type:"vec3",inputs:[{name:"n",type:"vec3"},{name:"v",type:"vec3"},{name:"thickness",type:"float"},{name:"ior",type:"float"},{name:"modelMatrix",type:"mat4"}]}),dp=_i((([e,t])=>e.mul(da(t.mul(2).sub(2),0,1)))).setLayout({name:"applyIorToRoughness",type:"float",inputs:[{name:"roughness",type:"float"},{name:"ior",type:"float"}]}),cp=Uc(),hp=Uc(),pp=_i((([e,t,r],{material:s})=>{const i=(s.side===T?cp:hp).sample(e),n=To(Tc.x).mul(dp(t,r));return up(i,n)})),gp=_i((([e,t,r])=>(Si(r.notEqual(0),(()=>{const s=bo(t).negate().div(r);return yo(s.negate().mul(e))})),Ii(1)))).setLayout({name:"volumeAttenuation",type:"vec3",inputs:[{name:"transmissionDistance",type:"float"},{name:"attenuationColor",type:"vec3"},{name:"attenuationDistance",type:"float"}]}),mp=_i((([e,t,r,s,i,n,o,a,u,l,d,c,h,p,g])=>{let m,f;if(g){m=Oi().toVar(),f=Ii().toVar();const i=d.sub(1).mul(g.mul(.025)),n=Ii(d.sub(i),d,d.add(i));ic({start:0,end:3},(({i:i})=>{const d=n.element(i),g=lp(e,t,c,d,a),y=o.add(g),x=l.mul(u.mul(Oi(y,1))),b=Bi(x.xy.div(x.w)).toVar();b.addAssign(1),b.divAssign(2),b.assign(Bi(b.x,b.y.oneMinus()));const T=pp(b,r,d);m.element(i).assign(T.element(i)),m.a.addAssign(T.a),f.element(i).assign(s.element(i).mul(gp(Io(g),h,p).element(i)))})),m.a.divAssign(3)}else{const i=lp(e,t,c,d,a),n=o.add(i),g=l.mul(u.mul(Oi(n,1))),y=Bi(g.xy.div(g.w)).toVar();y.addAssign(1),y.divAssign(2),y.assign(Bi(y.x,y.y.oneMinus())),m=pp(y,r,d),f=s.mul(gp(Io(i),h,p))}const y=f.rgb.mul(m.rgb),x=e.dot(t).clamp(),b=Ii($h({dotNV:x,specularColor:i,specularF90:n,roughness:r})),T=f.r.add(f.g,f.b).div(3);return Oi(b.oneMinus().mul(y),m.a.oneMinus().mul(T).oneMinus())})),fp=Hi(3.2404542,-.969266,.0556434,-1.5371385,1.8760108,-.2040259,-.4985314,.041556,1.0572252),yp=(e,t)=>e.sub(t).div(e.add(t)).pow2(),xp=_i((({outsideIOR:e,eta2:t,cosTheta1:r,thinFilmThickness:s,baseF0:i})=>{const n=la(e,t,pa(0,.03,s)),o=e.div(n).pow2().mul(r.pow2().oneMinus()).oneMinus();Si(o.lessThan(0),(()=>Ii(1)));const a=o.sqrt(),u=yp(n,e),l=Ah({f0:u,f90:1,dotVH:r}),d=l.oneMinus(),c=n.lessThan(e).select(Math.PI,0),h=Ci(Math.PI).sub(c),p=(e=>{const t=e.sqrt();return Ii(1).add(t).div(Ii(1).sub(t))})(i.clamp(0,.9999)),g=yp(p,n.toVec3()),m=Ah({f0:g,f90:1,dotVH:a}),f=Ii(p.x.lessThan(n).select(Math.PI,0),p.y.lessThan(n).select(Math.PI,0),p.z.lessThan(n).select(Math.PI,0)),y=n.mul(s,a,2),x=Ii(h).add(f),b=l.mul(m).clamp(1e-5,.9999),T=b.sqrt(),_=d.pow2().mul(m).div(Ii(1).sub(b)),v=l.add(_).toVar(),N=_.sub(d).toVar();return ic({start:1,end:2,condition:"<=",name:"m"},(({m:e})=>{N.mulAssign(T);const t=((e,t)=>{const r=e.mul(2*Math.PI*1e-9),s=Ii(54856e-17,44201e-17,52481e-17),i=Ii(1681e3,1795300,2208400),n=Ii(43278e5,93046e5,66121e5),o=Ci(9747e-17*Math.sqrt(2*Math.PI*45282e5)).mul(r.mul(2239900).add(t.x).cos()).mul(r.pow2().mul(-45282e5).exp());let a=s.mul(n.mul(2*Math.PI).sqrt()).mul(i.mul(r).add(t).cos()).mul(r.pow2().negate().mul(n).exp());return a=Ii(a.x.add(o),a.y,a.z).div(1.0685e-7),fp.mul(a)})(Ci(e).mul(y),Ci(e).mul(x)).mul(2);v.addAssign(N.mul(t))})),v.max(Ii(0))})).setLayout({name:"evalIridescence",type:"vec3",inputs:[{name:"outsideIOR",type:"float"},{name:"eta2",type:"float"},{name:"cosTheta1",type:"float"},{name:"thinFilmThickness",type:"float"},{name:"baseF0",type:"vec3"}]}),bp=_i((({normal:e,viewDir:t,roughness:r})=>{const s=e.dot(t).saturate(),i=r.pow2(),n=Ta(r.lessThan(.25),Ci(-339.2).mul(i).add(Ci(161.4).mul(r)).sub(25.9),Ci(-8.48).mul(i).add(Ci(14.3).mul(r)).sub(9.95)),o=Ta(r.lessThan(.25),Ci(44).mul(i).sub(Ci(23.7).mul(r)).add(3.26),Ci(1.97).mul(i).sub(Ci(3.27).mul(r)).add(.72));return Ta(r.lessThan(.25),0,Ci(.1).mul(r).sub(.025)).add(n.mul(s).add(o).exp()).mul(1/Math.PI).saturate()})),Tp=Ii(.04),_p=Ci(1);class vp extends _h{constructor(e=!1,t=!1,r=!1,s=!1,i=!1,n=!1){super(),this.clearcoat=e,this.sheen=t,this.iridescence=r,this.anisotropy=s,this.transmission=i,this.dispersion=n,this.clearcoatRadiance=null,this.clearcoatSpecularDirect=null,this.clearcoatSpecularIndirect=null,this.sheenSpecularDirect=null,this.sheenSpecularIndirect=null,this.iridescenceFresnel=null,this.iridescenceF0=null}start(e){if(!0===this.clearcoat&&(this.clearcoatRadiance=Ii().toVar("clearcoatRadiance"),this.clearcoatSpecularDirect=Ii().toVar("clearcoatSpecularDirect"),this.clearcoatSpecularIndirect=Ii().toVar("clearcoatSpecularIndirect")),!0===this.sheen&&(this.sheenSpecularDirect=Ii().toVar("sheenSpecularDirect"),this.sheenSpecularIndirect=Ii().toVar("sheenSpecularIndirect")),!0===this.iridescence){const e=ul.dot(Ju).clamp();this.iridescenceFresnel=xp({outsideIOR:Ci(1),eta2:mn,cosTheta1:e,thinFilmThickness:fn,baseF0:_n}),this.iridescenceF0=Hh({f:this.iridescenceFresnel,f90:1,dotVH:e})}if(!0===this.transmission){const t=Yu,r=Eu.sub(Yu).normalize(),s=ll;e.backdrop=mp(s,r,un,on,_n,vn,t,Vu,Au,Nu,En,Mn,Un,Bn,this.dispersion?Fn:null),e.backdropAlpha=wn,on.a.mulAssign(la(1,e.backdrop.a,wn))}}computeMultiscattering(e,t,r){const s=ul.dot(Ju).clamp(),i=zh({roughness:un,dotNV:s}),n=(this.iridescenceF0?gn.mix(_n,this.iridescenceF0):_n).mul(i.x).add(r.mul(i.y)),o=i.x.add(i.y).oneMinus(),a=_n.add(_n.oneMinus().mul(.047619)),u=n.mul(a).div(o.mul(a).oneMinus());e.addAssign(n),t.addAssign(u.mul(o))}direct({lightDirection:e,lightColor:t,reflectedLight:r}){const s=ul.dot(e).clamp().mul(t);if(!0===this.sheen&&this.sheenSpecularDirect.addAssign(s.mul(qh({lightDirection:e}))),!0===this.clearcoat){const r=dl.dot(e).clamp().mul(t);this.clearcoatSpecularDirect.addAssign(r.mul(kh({lightDirection:e,f0:Tp,f90:_p,roughness:cn,normalView:dl})))}r.directDiffuse.addAssign(s.mul(Rh({diffuseColor:on.rgb}))),r.directSpecular.addAssign(s.mul(kh({lightDirection:e,f0:_n,f90:1,roughness:un,iridescence:this.iridescence,f:this.iridescenceFresnel,USE_IRIDESCENCE:this.iridescence,USE_ANISOTROPY:this.anisotropy})))}directRectArea({lightColor:e,lightPosition:t,halfWidth:r,halfHeight:s,reflectedLight:i,ltc_1:n,ltc_2:o}){const a=t.add(r).sub(s),u=t.sub(r).sub(s),l=t.sub(r).add(s),d=t.add(r).add(s),c=ul,h=Ju,p=Zu.toVar(),g=Kh({N:c,V:h,roughness:un}),m=n.sample(g).toVar(),f=o.sample(g).toVar(),y=Hi(Ii(m.x,0,m.y),Ii(0,1,0),Ii(m.z,0,m.w)).toVar(),x=_n.mul(f.x).add(_n.oneMinus().mul(f.y)).toVar();i.directSpecular.addAssign(e.mul(x).mul(Qh({N:c,V:h,P:p,mInv:y,p0:a,p1:u,p2:l,p3:d}))),i.directDiffuse.addAssign(e.mul(on).mul(Qh({N:c,V:h,P:p,mInv:Hi(1,0,0,0,1,0,0,0,1),p0:a,p1:u,p2:l,p3:d})))}indirect(e,t,r){this.indirectDiffuse(e,t,r),this.indirectSpecular(e,t,r),this.ambientOcclusion(e,t,r)}indirectDiffuse({irradiance:e,reflectedLight:t}){t.indirectDiffuse.addAssign(e.mul(Rh({diffuseColor:on})))}indirectSpecular({radiance:e,iblIrradiance:t,reflectedLight:r}){if(!0===this.sheen&&this.sheenSpecularIndirect.addAssign(t.mul(hn,bp({normal:ul,viewDir:Ju,roughness:pn}))),!0===this.clearcoat){const e=dl.dot(Ju).clamp(),t=$h({dotNV:e,specularColor:Tp,specularF90:_p,roughness:cn});this.clearcoatSpecularIndirect.addAssign(this.clearcoatRadiance.mul(t))}const s=Ii().toVar("singleScattering"),i=Ii().toVar("multiScattering"),n=t.mul(1/Math.PI);this.computeMultiscattering(s,i,vn);const o=s.add(i),a=on.mul(o.r.max(o.g).max(o.b).oneMinus());r.indirectSpecular.addAssign(e.mul(s)),r.indirectSpecular.addAssign(i.mul(n)),r.indirectDiffuse.addAssign(a.mul(n))}ambientOcclusion({ambientOcclusion:e,reflectedLight:t}){const r=ul.dot(Ju).clamp().add(e),s=un.mul(-16).oneMinus().negate().exp2(),i=e.sub(r.pow(s).oneMinus()).clamp();!0===this.clearcoat&&this.clearcoatSpecularIndirect.mulAssign(e),!0===this.sheen&&this.sheenSpecularIndirect.mulAssign(e),t.indirectDiffuse.mulAssign(e),t.indirectSpecular.mulAssign(i)}finish(e){const{outgoingLight:t}=e;if(!0===this.clearcoat){const e=dl.dot(Ju).clamp(),r=Ah({dotVH:e,f0:Tp,f90:_p}),s=t.mul(dn.mul(r).oneMinus()).add(this.clearcoatSpecularDirect.add(this.clearcoatSpecularIndirect).mul(dn));t.assign(s)}if(!0===this.sheen){const e=hn.r.max(hn.g).max(hn.b).mul(.157).oneMinus(),r=t.mul(e).add(this.sheenSpecularDirect,this.sheenSpecularIndirect);t.assign(r)}}}const Np=Ci(1),Sp=Ci(-2),Ap=Ci(.8),Rp=Ci(-1),Cp=Ci(.4),Ep=Ci(2),wp=Ci(.305),Mp=Ci(3),Bp=Ci(.21),Up=Ci(4),Fp=Ci(4),Pp=Ci(16),Ip=_i((([e])=>{const t=Ii(Fo(e)).toVar(),r=Ci(-1).toVar();return Si(t.x.greaterThan(t.z),(()=>{Si(t.x.greaterThan(t.y),(()=>{r.assign(Ta(e.x.greaterThan(0),0,3))})).Else((()=>{r.assign(Ta(e.y.greaterThan(0),1,4))}))})).Else((()=>{Si(t.z.greaterThan(t.y),(()=>{r.assign(Ta(e.z.greaterThan(0),2,5))})).Else((()=>{r.assign(Ta(e.y.greaterThan(0),1,4))}))})),r})).setLayout({name:"getFace",type:"float",inputs:[{name:"direction",type:"vec3"}]}),Lp=_i((([e,t])=>{const r=Bi().toVar();return Si(t.equal(0),(()=>{r.assign(Bi(e.z,e.y).div(Fo(e.x)))})).ElseIf(t.equal(1),(()=>{r.assign(Bi(e.x.negate(),e.z.negate()).div(Fo(e.y)))})).ElseIf(t.equal(2),(()=>{r.assign(Bi(e.x.negate(),e.y).div(Fo(e.z)))})).ElseIf(t.equal(3),(()=>{r.assign(Bi(e.z.negate(),e.y).div(Fo(e.x)))})).ElseIf(t.equal(4),(()=>{r.assign(Bi(e.x.negate(),e.z).div(Fo(e.y)))})).Else((()=>{r.assign(Bi(e.x,e.y).div(Fo(e.z)))})),kn(.5,r.add(1))})).setLayout({name:"getUV",type:"vec2",inputs:[{name:"direction",type:"vec3"},{name:"face",type:"float"}]}),Vp=_i((([e])=>{const t=Ci(0).toVar();return Si(e.greaterThanEqual(Ap),(()=>{t.assign(Np.sub(e).mul(Rp.sub(Sp)).div(Np.sub(Ap)).add(Sp))})).ElseIf(e.greaterThanEqual(Cp),(()=>{t.assign(Ap.sub(e).mul(Ep.sub(Rp)).div(Ap.sub(Cp)).add(Rp))})).ElseIf(e.greaterThanEqual(wp),(()=>{t.assign(Cp.sub(e).mul(Mp.sub(Ep)).div(Cp.sub(wp)).add(Ep))})).ElseIf(e.greaterThanEqual(Bp),(()=>{t.assign(wp.sub(e).mul(Up.sub(Mp)).div(wp.sub(Bp)).add(Mp))})).Else((()=>{t.assign(Ci(-2).mul(To(kn(1.16,e))))})),t})).setLayout({name:"roughnessToMip",type:"float",inputs:[{name:"roughness",type:"float"}]}),Dp=_i((([e,t])=>{const r=e.toVar();r.assign(kn(2,r).sub(1));const s=Ii(r,1).toVar();return Si(t.equal(0),(()=>{s.assign(s.zyx)})).ElseIf(t.equal(1),(()=>{s.assign(s.xzy),s.xz.mulAssign(-1)})).ElseIf(t.equal(2),(()=>{s.x.mulAssign(-1)})).ElseIf(t.equal(3),(()=>{s.assign(s.zyx),s.xz.mulAssign(-1)})).ElseIf(t.equal(4),(()=>{s.assign(s.xzy),s.xy.mulAssign(-1)})).ElseIf(t.equal(5),(()=>{s.z.mulAssign(-1)})),s})).setLayout({name:"getDirection",type:"vec3",inputs:[{name:"uv",type:"vec2"},{name:"face",type:"float"}]}),Op=_i((([e,t,r,s,i,n])=>{const o=Ci(r),a=Ii(t),u=da(Vp(o),Sp,n),l=Ro(u),d=No(u),c=Ii(Gp(e,a,d,s,i,n)).toVar();return Si(l.notEqual(0),(()=>{const t=Ii(Gp(e,a,d.add(1),s,i,n)).toVar();c.assign(la(c,t,l))})),c})),Gp=_i((([e,t,r,s,i,n])=>{const o=Ci(r).toVar(),a=Ii(t),u=Ci(Ip(a)).toVar(),l=Ci(Ko(Fp.sub(o),0)).toVar();o.assign(Ko(o,Fp));const d=Ci(xo(o)).toVar(),c=Bi(Lp(a,u).mul(d.sub(2)).add(1)).toVar();return Si(u.greaterThan(2),(()=>{c.y.addAssign(d),u.subAssign(3)})),c.x.addAssign(u.mul(d)),c.x.addAssign(l.mul(kn(3,Pp))),c.y.addAssign(kn(4,xo(n).sub(d))),c.x.mulAssign(s),c.y.mulAssign(i),e.sample(c).grad(Bi(),Bi())})),kp=_i((({envMap:e,mipInt:t,outputDirection:r,theta:s,axis:i,CUBEUV_TEXEL_WIDTH:n,CUBEUV_TEXEL_HEIGHT:o,CUBEUV_MAX_MIP:a})=>{const u=Eo(s),l=r.mul(u).add(i.cross(r).mul(Co(s))).add(i.mul(i.dot(r).mul(u.oneMinus())));return Gp(e,l,t,n,o,a)})),zp=_i((({n:e,latitudinal:t,poleAxis:r,outputDirection:s,weights:i,samples:n,dTheta:o,mipInt:a,envMap:u,CUBEUV_TEXEL_WIDTH:l,CUBEUV_TEXEL_HEIGHT:d,CUBEUV_MAX_MIP:c})=>{const h=Ii(Ta(t,r,ta(r,s))).toVar();Si(po(h.equals(Ii(0))),(()=>{h.assign(Ii(s.z,0,s.x.negate()))})),h.assign(Ao(h));const p=Ii().toVar();return p.addAssign(i.element(Ei(0)).mul(kp({theta:0,axis:h,outputDirection:s,mipInt:a,envMap:u,CUBEUV_TEXEL_WIDTH:l,CUBEUV_TEXEL_HEIGHT:d,CUBEUV_MAX_MIP:c}))),ic({start:Ei(1),end:e},(({i:e})=>{Si(e.greaterThanEqual(n),(()=>{nc()}));const t=Ci(o.mul(Ci(e))).toVar();p.addAssign(i.element(e).mul(kp({theta:t.mul(-1),axis:h,outputDirection:s,mipInt:a,envMap:u,CUBEUV_TEXEL_WIDTH:l,CUBEUV_TEXEL_HEIGHT:d,CUBEUV_MAX_MIP:c}))),p.addAssign(i.element(e).mul(kp({theta:t,axis:h,outputDirection:s,mipInt:a,envMap:u,CUBEUV_TEXEL_WIDTH:l,CUBEUV_TEXEL_HEIGHT:d,CUBEUV_MAX_MIP:c})))})),Oi(p,1)}));let $p=null;const Hp=new WeakMap;function Wp(e){let t=Hp.get(e);if((void 0!==t?t.pmremVersion:-1)!==e.pmremVersion){const r=e.image;if(e.isCubeTexture){if(!function(e){if(null==e)return!1;let t=0;const r=6;for(let s=0;s0}(r))return null;t=$p.fromEquirectangular(e,t)}t.pmremVersion=e.pmremVersion,Hp.set(e,t)}return t.texture}class jp extends Fs{static get type(){return"PMREMNode"}constructor(e,t=null,r=null){super("vec3"),this._value=e,this._pmrem=null,this.uvNode=t,this.levelNode=r,this._generator=null;const s=new ee;s.isRenderTargetTexture=!0,this._texture=bu(s),this._width=tn(0),this._height=tn(0),this._maxMip=tn(0),this.updateBeforeType=vs.RENDER}set value(e){this._value=e,this._pmrem=null}get value(){return this._value}updateFromTexture(e){const t=function(e){const t=Math.log2(e)-2,r=1/e;return{texelWidth:1/(3*Math.max(Math.pow(2,t),112)),texelHeight:r,maxMip:t}}(e.image.height);this._texture.value=e,this._width.value=t.texelWidth,this._height.value=t.texelHeight,this._maxMip.value=t.maxMip}updateBefore(){let e=this._pmrem;const t=e?e.pmremVersion:-1,r=this._value;t!==r.pmremVersion&&(e=!0===r.isPMREMTexture?r:Wp(r),null!==e&&(this._pmrem=e,this.updateFromTexture(e)))}setup(e){null===$p&&($p=e.createPMREMGenerator()),this.updateBefore(e);let t=this.uvNode;null===t&&e.context.getUV&&(t=e.context.getUV(this));const r=this.value;e.renderer.coordinateSystem===u&&!0!==r.isPMREMTexture&&!0===r.isRenderTargetTexture&&(t=Ii(t.x.negate(),t.yz)),t=Ii(t.x,t.y.negate(),t.z);let s=this.levelNode;return null===s&&e.context.getTextureLevel&&(s=e.context.getTextureLevel(this)),Op(this._texture,t,s,this._width,this._height,this._maxMip)}}const qp=bi(jp),Kp=new WeakMap;class Xp extends cc{static get type(){return"EnvironmentNode"}constructor(e=null){super(),this.envNode=e}setup(e){const{material:t}=e;let r=this.envNode;if(r.isTextureNode||r.isMaterialReferenceNode){const e=r.isTextureNode?r.value:t[r.property];let s=Kp.get(e);void 0===s&&(s=qp(e),Kp.set(e,s)),r=s}const s=t.envMap?Cl("envMapIntensity","float",e.material):Cl("environmentIntensity","float",e.scene),i=!0===t.useAnisotropy||t.anisotropy>0?jl:ul,n=r.context(Yp(un,i)).mul(s),o=r.context(Qp(ll)).mul(Math.PI).mul(s),a=eu(n),u=eu(o);e.context.radiance.addAssign(a),e.context.iblIrradiance.addAssign(u);const l=e.context.lightingModel.clearcoatRadiance;if(l){const e=r.context(Yp(cn,dl)).mul(s),t=eu(e);l.addAssign(t)}}}const Yp=(e,t)=>{let r=null;return{getUV:()=>(null===r&&(r=Ju.negate().reflect(t),r=e.mul(e).mix(r,t).normalize(),r=r.transformDirection(Au)),r),getTextureLevel:()=>e}},Qp=e=>({getUV:()=>e,getTextureLevel:()=>Ci(1)}),Zp=new te;class Jp extends Yc{static get type(){return"MeshStandardNodeMaterial"}constructor(e){super(),this.isMeshStandardNodeMaterial=!0,this.lights=!0,this.emissiveNode=null,this.metalnessNode=null,this.roughnessNode=null,this.setDefaultValues(Zp),this.setValues(e)}setupEnvironment(e){let t=super.setupEnvironment(e);return null===t&&e.environmentNode&&(t=e.environmentNode),t?new Xp(t):null}setupLightingModel(){return new vp}setupSpecular(){const e=la(Ii(.04),on.rgb,ln);_n.assign(e),vn.assign(1)}setupVariants(){const e=this.metalnessNode?Ci(this.metalnessNode):pd;ln.assign(e);let t=this.roughnessNode?Ci(this.roughnessNode):hd;t=Ih({roughness:t}),un.assign(t),this.setupSpecular(),on.assign(Oi(on.rgb.mul(e.oneMinus()),on.a))}copy(e){return this.emissiveNode=e.emissiveNode,this.metalnessNode=e.metalnessNode,this.roughnessNode=e.roughnessNode,super.copy(e)}}const eg=new re;class tg extends Jp{static get type(){return"MeshPhysicalNodeMaterial"}constructor(e){super(),this.isMeshPhysicalNodeMaterial=!0,this.clearcoatNode=null,this.clearcoatRoughnessNode=null,this.clearcoatNormalNode=null,this.sheenNode=null,this.sheenRoughnessNode=null,this.iridescenceNode=null,this.iridescenceIORNode=null,this.iridescenceThicknessNode=null,this.specularIntensityNode=null,this.specularColorNode=null,this.iorNode=null,this.transmissionNode=null,this.thicknessNode=null,this.attenuationDistanceNode=null,this.attenuationColorNode=null,this.dispersionNode=null,this.anisotropyNode=null,this.setDefaultValues(eg),this.setValues(e)}get useClearcoat(){return this.clearcoat>0||null!==this.clearcoatNode}get useIridescence(){return this.iridescence>0||null!==this.iridescenceNode}get useSheen(){return this.sheen>0||null!==this.sheenNode}get useAnisotropy(){return this.anisotropy>0||null!==this.anisotropyNode}get useTransmission(){return this.transmission>0||null!==this.transmissionNode}get useDispersion(){return this.dispersion>0||null!==this.dispersionNode}setupSpecular(){const e=this.iorNode?Ci(this.iorNode):Cd;En.assign(e),_n.assign(la(qo(sa(En.sub(1).div(En.add(1))).mul(ld),Ii(1)).mul(ud),on.rgb,ln)),vn.assign(la(ud,1,ln))}setupLightingModel(){return new vp(this.useClearcoat,this.useSheen,this.useIridescence,this.useAnisotropy,this.useTransmission,this.useDispersion)}setupVariants(e){if(super.setupVariants(e),this.useClearcoat){const e=this.clearcoatNode?Ci(this.clearcoatNode):md,t=this.clearcoatRoughnessNode?Ci(this.clearcoatRoughnessNode):fd;dn.assign(e),cn.assign(Ih({roughness:t}))}if(this.useSheen){const e=this.sheenNode?Ii(this.sheenNode):bd,t=this.sheenRoughnessNode?Ci(this.sheenRoughnessNode):Td;hn.assign(e),pn.assign(t)}if(this.useIridescence){const e=this.iridescenceNode?Ci(this.iridescenceNode):vd,t=this.iridescenceIORNode?Ci(this.iridescenceIORNode):Nd,r=this.iridescenceThicknessNode?Ci(this.iridescenceThicknessNode):Sd;gn.assign(e),mn.assign(t),fn.assign(r)}if(this.useAnisotropy){const e=(this.anisotropyNode?Bi(this.anisotropyNode):_d).toVar();xn.assign(e.length()),Si(xn.equal(0),(()=>{e.assign(Bi(1,0))})).Else((()=>{e.divAssign(Bi(xn)),xn.assign(xn.saturate())})),yn.assign(xn.pow2().mix(un.pow2(),1)),bn.assign(Hl[0].mul(e.x).add(Hl[1].mul(e.y))),Tn.assign(Hl[1].mul(e.x).sub(Hl[0].mul(e.y)))}if(this.useTransmission){const e=this.transmissionNode?Ci(this.transmissionNode):Ad,t=this.thicknessNode?Ci(this.thicknessNode):Rd,r=this.attenuationDistanceNode?Ci(this.attenuationDistanceNode):Ed,s=this.attenuationColorNode?Ii(this.attenuationColorNode):wd;if(wn.assign(e),Mn.assign(t),Bn.assign(r),Un.assign(s),this.useDispersion){const e=this.dispersionNode?Ci(this.dispersionNode):Ld;Fn.assign(e)}}}setupClearcoatNormal(){return this.clearcoatNormalNode?Ii(this.clearcoatNormalNode):yd}setup(e){e.context.setupClearcoatNormal=()=>this.setupClearcoatNormal(e),super.setup(e)}copy(e){return this.clearcoatNode=e.clearcoatNode,this.clearcoatRoughnessNode=e.clearcoatRoughnessNode,this.clearcoatNormalNode=e.clearcoatNormalNode,this.sheenNode=e.sheenNode,this.sheenRoughnessNode=e.sheenRoughnessNode,this.iridescenceNode=e.iridescenceNode,this.iridescenceIORNode=e.iridescenceIORNode,this.iridescenceThicknessNode=e.iridescenceThicknessNode,this.specularIntensityNode=e.specularIntensityNode,this.specularColorNode=e.specularColorNode,this.transmissionNode=e.transmissionNode,this.thicknessNode=e.thicknessNode,this.attenuationDistanceNode=e.attenuationDistanceNode,this.attenuationColorNode=e.attenuationColorNode,this.dispersionNode=e.dispersionNode,this.anisotropyNode=e.anisotropyNode,super.copy(e)}}class rg extends vp{constructor(e,t,r,s){super(e,t,r),this.useSSS=s}direct({lightDirection:e,lightColor:t,reflectedLight:r},s,i){if(!0===this.useSSS){const s=i.material,{thicknessColorNode:n,thicknessDistortionNode:o,thicknessAmbientNode:a,thicknessAttenuationNode:u,thicknessPowerNode:l,thicknessScaleNode:d}=s,c=e.add(ul.mul(o)).normalize(),h=Ci(Ju.dot(c.negate()).saturate().pow(l).mul(d)),p=Ii(h.add(a).mul(n));r.directDiffuse.addAssign(p.mul(u.mul(t)))}super.direct({lightDirection:e,lightColor:t,reflectedLight:r},s,i)}}class sg extends tg{static get type(){return"MeshSSSNodeMaterial"}constructor(e){super(e),this.thicknessColorNode=null,this.thicknessDistortionNode=Ci(.1),this.thicknessAmbientNode=Ci(0),this.thicknessAttenuationNode=Ci(.1),this.thicknessPowerNode=Ci(2),this.thicknessScaleNode=Ci(10)}get useSSS(){return null!==this.thicknessColorNode}setupLightingModel(){return new rg(this.useClearcoat,this.useSheen,this.useIridescence,this.useSSS)}copy(e){return this.thicknessColorNode=e.thicknessColorNode,this.thicknessDistortionNode=e.thicknessDistortionNode,this.thicknessAmbientNode=e.thicknessAmbientNode,this.thicknessAttenuationNode=e.thicknessAttenuationNode,this.thicknessPowerNode=e.thicknessPowerNode,this.thicknessScaleNode=e.thicknessScaleNode,super.copy(e)}}const ig=_i((({normal:e,lightDirection:t,builder:r})=>{const s=e.dot(t),i=Bi(s.mul(.5).add(.5),0);if(r.material.gradientMap){const e=Ml("gradientMap","texture").context({getUV:()=>i});return Ii(e.r)}{const e=i.fwidth().mul(.5);return la(Ii(.7),Ii(1),pa(Ci(.7).sub(e.x),Ci(.7).add(e.x),i.x))}}));class ng extends _h{direct({lightDirection:e,lightColor:t,reflectedLight:r},s,i){const n=ig({normal:sl,lightDirection:e,builder:i}).mul(t);r.directDiffuse.addAssign(n.mul(Rh({diffuseColor:on.rgb})))}indirect({ambientOcclusion:e,irradiance:t,reflectedLight:r}){r.indirectDiffuse.addAssign(t.mul(Rh({diffuseColor:on}))),r.indirectDiffuse.mulAssign(e)}}const og=new se;class ag extends Yc{static get type(){return"MeshToonNodeMaterial"}constructor(e){super(),this.isMeshToonNodeMaterial=!0,this.lights=!0,this.setDefaultValues(og),this.setValues(e)}setupLightingModel(){return new ng}}class ug extends Fs{static get type(){return"MatcapUVNode"}constructor(){super("vec2")}setup(){const e=Ii(Ju.z,0,Ju.x.negate()).normalize(),t=Ju.cross(e);return Bi(e.dot(ul),t.dot(ul)).mul(.495).add(.5)}}const lg=Ti(ug),dg=new ie;class cg extends Yc{static get type(){return"MeshMatcapNodeMaterial"}constructor(e){super(),this.lights=!1,this.isMeshMatcapNodeMaterial=!0,this.setDefaultValues(dg),this.setValues(e)}setupVariants(e){const t=lg;let r;r=e.material.matcap?Ml("matcap","texture").context({getUV:()=>t}):Ii(la(.2,.8,t.y)),on.rgb.mulAssign(r.rgb)}}const hg=new P;class pg extends Yc{static get type(){return"PointsNodeMaterial"}constructor(e){super(),this.isPointsNodeMaterial=!0,this.lights=!1,this.transparent=!0,this.sizeNode=null,this.setDefaultValues(hg),this.setValues(e)}copy(e){return this.sizeNode=e.sizeNode,super.copy(e)}}class gg extends Fs{static get type(){return"RotateNode"}constructor(e,t){super(),this.positionNode=e,this.rotationNode=t}getNodeType(e){return this.positionNode.getNodeType(e)}setup(e){const{rotationNode:t,positionNode:r}=this;if("vec2"===this.getNodeType(e)){const e=t.cos(),s=t.sin();return $i(e,s,s.negate(),e).mul(r)}{const e=t,s=Wi(Oi(1,0,0,0),Oi(0,Eo(e.x),Co(e.x).negate(),0),Oi(0,Co(e.x),Eo(e.x),0),Oi(0,0,0,1)),i=Wi(Oi(Eo(e.y),0,Co(e.y),0),Oi(0,1,0,0),Oi(Co(e.y).negate(),0,Eo(e.y),0),Oi(0,0,0,1)),n=Wi(Oi(Eo(e.z),Co(e.z).negate(),0,0),Oi(Co(e.z),Eo(e.z),0,0),Oi(0,0,1,0),Oi(0,0,0,1));return s.mul(i).mul(n).mul(Oi(r,1)).xyz}}}const mg=bi(gg),fg=new ne;class yg extends Yc{static get type(){return"SpriteNodeMaterial"}constructor(e){super(),this.isSpriteNodeMaterial=!0,this.lights=!1,this._useSizeAttenuation=!0,this.positionNode=null,this.rotationNode=null,this.scaleNode=null,this.setDefaultValues(fg),this.setValues(e)}setupPositionView(e){const{object:t,camera:r}=e,s=this.sizeAttenuation,{positionNode:i,rotationNode:n,scaleNode:o}=this,a=$u.mul(Ii(i||0));let u=Bi(Vu[0].xyz.length(),Vu[1].xyz.length());if(null!==o&&(u=u.mul(o)),!s)if(r.isPerspectiveCamera)u=u.mul(a.z.negate());else{const e=Ci(2).div(Nu.element(1).element(1));u=u.mul(e.mul(2))}let l=qu.xy;if(t.center&&!0===t.center.isVector2){const e=((e,t,r)=>fi(new Ga(e,t,r)))("center","vec2");l=l.sub(e.sub(.5))}l=l.mul(u);const d=Ci(n||xd),c=mg(l,d);return Oi(a.xy.add(c),a.zw)}copy(e){return this.positionNode=e.positionNode,this.rotationNode=e.rotationNode,this.scaleNode=e.scaleNode,super.copy(e)}get sizeAttenuation(){return this._useSizeAttenuation}set sizeAttenuation(e){this._useSizeAttenuation!==e&&(this._useSizeAttenuation=e,this.needsUpdate=!0)}}class xg extends _h{constructor(){super(),this.shadowNode=Ci(1).toVar("shadowMask")}direct({shadowMask:e}){this.shadowNode.mulAssign(e)}finish(e){on.a.mulAssign(this.shadowNode.oneMinus()),e.outgoingLight.rgb.assign(on.rgb)}}const bg=new oe;class Tg extends Yc{static get type(){return"ShadowNodeMaterial"}constructor(e){super(),this.isShadowNodeMaterial=!0,this.lights=!0,this.setDefaultValues(bg),this.setValues(e)}setupLightingModel(){return new xg}}const _g=_i((({texture:e,uv:t})=>{const r=1e-4,s=Ii().toVar();return Si(t.x.lessThan(r),(()=>{s.assign(Ii(1,0,0))})).ElseIf(t.y.lessThan(r),(()=>{s.assign(Ii(0,1,0))})).ElseIf(t.z.lessThan(r),(()=>{s.assign(Ii(0,0,1))})).ElseIf(t.x.greaterThan(.9999),(()=>{s.assign(Ii(-1,0,0))})).ElseIf(t.y.greaterThan(.9999),(()=>{s.assign(Ii(0,-1,0))})).ElseIf(t.z.greaterThan(.9999),(()=>{s.assign(Ii(0,0,-1))})).Else((()=>{const r=.01,i=e.sample(t.add(Ii(-.01,0,0))).r.sub(e.sample(t.add(Ii(r,0,0))).r),n=e.sample(t.add(Ii(0,-.01,0))).r.sub(e.sample(t.add(Ii(0,r,0))).r),o=e.sample(t.add(Ii(0,0,-.01))).r.sub(e.sample(t.add(Ii(0,0,r))).r);s.assign(Ii(i,n,o))})),s.normalize()}));class vg extends xu{static get type(){return"Texture3DNode"}constructor(e,t=null,r=null){super(e,t,r),this.isTexture3DNode=!0}getInputType(){return"texture3D"}getDefaultUV(){return Ii(.5,.5,.5)}setUpdateMatrix(){}setupUV(e,t){return t}generateUV(e,t){return t.build(e,"vec3")}normal(e){return _g({texture:this,uv:e})}}const Ng=bi(vg);class Sg extends Yc{static get type(){return"VolumeNodeMaterial"}constructor(e={}){super(),this.lights=!1,this.isVolumeNodeMaterial=!0,this.testNode=null,this.setValues(e)}setup(e){const t=Ng(this.map,null,0),r=_i((({orig:e,dir:t})=>{const r=Ii(-.5),s=Ii(.5),i=t.reciprocal(),n=r.sub(e).mul(i),o=s.sub(e).mul(i),a=qo(n,o),u=Ko(n,o),l=Ko(a.x,Ko(a.y,a.z)),d=qo(u.x,qo(u.y,u.z));return Bi(l,d)}));this.fragmentNode=_i((()=>{const e=wa(Ii(zu.mul(Oi(Eu,1)))),s=wa(qu.sub(e)).normalize(),i=Bi(r({orig:e,dir:s})).toVar();i.x.greaterThan(i.y).discard(),i.assign(Bi(Ko(i.x,0),i.y));const n=Ii(e.add(i.x.mul(s))).toVar(),o=Ii(s.abs().reciprocal()).toVar(),a=Ci(qo(o.x,qo(o.y,o.z))).toVar("delta");a.divAssign(Ml("steps","float"));const u=Oi(Ml("base","color"),0).toVar();return ic({type:"float",start:i.x,end:i.y,update:"+= delta"},(()=>{const e=sn("float","d").assign(t.sample(n.add(.5)).r);null!==this.testNode?this.testNode({map:t,mapValue:e,probe:n,finalColor:u}).append():(u.a.assign(1),nc()),n.addAssign(s.mul(a))})),u.a.equal(0).discard(),Oi(u)}))(),super.setup(e)}}class Ag{constructor(e,t){this.nodes=e,this.info=t,this._context=self,this._animationLoop=null,this._requestId=null}start(){const e=(t,r)=>{this._requestId=this._context.requestAnimationFrame(e),!0===this.info.autoReset&&this.info.reset(),this.nodes.nodeFrame.update(),this.info.frame=this.nodes.nodeFrame.frameId,null!==this._animationLoop&&this._animationLoop(t,r)};e()}stop(){this._context.cancelAnimationFrame(this._requestId),this._requestId=null}setAnimationLoop(e){this._animationLoop=e}setContext(e){this._context=e}dispose(){this.stop()}}class Rg{constructor(){this.weakMap=new WeakMap}get(e){let t=this.weakMap;for(let r=0;r{this.dispose()},this.material.addEventListener("dispose",this.onMaterialDispose)}updateClipping(e){this.clippingContext=e}get clippingNeedsUpdate(){return null!==this.clippingContext&&this.clippingContext.cacheKey!==this.clippingContextCacheKey&&(this.clippingContextCacheKey=this.clippingContext.cacheKey,!0)}get hardwareClippingPlanes(){return!0===this.material.hardwareClipping?this.clippingContext.unionClippingCount:0}getNodeBuilderState(){return this._nodeBuilderState||(this._nodeBuilderState=this._nodes.getForRender(this))}getMonitor(){return this._monitor||(this._monitor=this.getNodeBuilderState().monitor)}getBindings(){return this._bindings||(this._bindings=this.getNodeBuilderState().createBindings())}getIndex(){return this._geometries.getIndex(this)}getIndirect(){return this._geometries.getIndirect(this)}getChainArray(){return[this.object,this.material,this.context,this.lightsNode]}setGeometry(e){this.geometry=e,this.attributes=null}getAttributes(){if(null!==this.attributes)return this.attributes;const e=this.getNodeBuilderState().nodeAttributes,t=this.geometry,r=[],s=new Set;for(const i of e){const e=i.node&&i.node.attribute?i.node.attribute:t.getAttribute(i.name);if(void 0===e)continue;r.push(e);const n=e.isInterleavedBufferAttribute?e.data:e;s.add(n)}return this.attributes=r,this.vertexBuffers=Array.from(s.values()),r}getVertexBuffers(){return null===this.vertexBuffers&&this.getAttributes(),this.vertexBuffers}getDrawParameters(){const{object:e,material:t,geometry:r,group:s,drawRange:i}=this,n=this.drawParams||(this.drawParams={vertexCount:0,firstVertex:0,instanceCount:0,firstInstance:0}),o=this.getIndex(),a=null!==o,u=r.isInstancedBufferGeometry?r.instanceCount:e.count>1?e.count:1;if(0===u)return null;if(n.instanceCount=u,!0===e.isBatchedMesh)return n;let l=1;!0!==t.wireframe||e.isPoints||e.isLineSegments||e.isLine||e.isLineLoop||(l=2);let d=i.start*l,c=(i.start+i.count)*l;null!==s&&(d=Math.max(d,s.start*l),c=Math.min(c,(s.start+s.count)*l));const h=r.attributes.position;let p=1/0;a?p=o.count:null!=h&&(p=h.count),d=Math.max(d,0),c=Math.min(c,p);const g=c-d;return g<0||g===1/0?null:(n.vertexCount=g,n.firstVertex=d,n)}getGeometryCacheKey(){const{geometry:e}=this;let t="";for(const r of Object.keys(e.attributes).sort()){const s=e.attributes[r];t+=r+",",s.data&&(t+=s.data.stride+","),s.offset&&(t+=s.offset+","),s.itemSize&&(t+=s.itemSize+","),s.normalized&&(t+="n,")}return e.index&&(t+="index,"),t}getMaterialCacheKey(){const{object:e,material:t}=this;let r=t.customProgramCacheKey();for(const e of function(e){const t=Object.keys(e);let r=Object.getPrototypeOf(e);for(;r;){const e=Object.getOwnPropertyDescriptors(r);for(const r in e)if(void 0!==e[r]){const s=e[r];s&&"function"==typeof s.get&&t.push(r)}r=Object.getPrototypeOf(r)}return t}(t)){if(/^(is[A-Z]|_)|^(visible|version|uuid|name|opacity|userData)$/.test(e))continue;const s=t[e];let i;if(null!==s){const e=typeof s;"number"===e?i=0!==s?"1":"0":"object"===e?(i="{",s.isTexture&&(i+=s.mapping),i+="}"):i=String(s)}else i=String(s);r+=i+","}return r+=this.clippingContextCacheKey+",",e.geometry&&(r+=this.getGeometryCacheKey()),e.skeleton&&(r+=e.skeleton.bones.length+","),e.morphTargetInfluences&&(r+=e.morphTargetInfluences.length+","),e.isBatchedMesh&&(r+=e._matricesTexture.uuid+",",null!==e._colorsTexture&&(r+=e._colorsTexture.uuid+",")),e.count>1&&(r+=e.uuid+","),r+=e.receiveShadow+",",us(r)}get needsGeometryUpdate(){return this.geometry.id!==this.object.geometry.id}get needsUpdate(){return this.initialNodesCacheKey!==this.getDynamicCacheKey()||this.clippingNeedsUpdate}getDynamicCacheKey(){let e=this._nodes.getCacheKey(this.scene,this.lightsNode);return this.object.receiveShadow&&(e+=1),e}getCacheKey(){return this.getMaterialCacheKey()+this.getDynamicCacheKey()}dispose(){this.material.removeEventListener("dispose",this.onMaterialDispose),this.onDispose()}}const wg=[];class Mg{constructor(e,t,r,s,i,n){this.renderer=e,this.nodes=t,this.geometries=r,this.pipelines=s,this.bindings=i,this.info=n,this.chainMaps={}}get(e,t,r,s,i,n,o,a){const u=this.getChainMap(a);wg[0]=e,wg[1]=t,wg[2]=n,wg[3]=i;let l=u.get(wg);return void 0===l?(l=this.createRenderObject(this.nodes,this.geometries,this.renderer,e,t,r,s,i,n,o,a),u.set(wg,l)):(l.updateClipping(o),l.needsGeometryUpdate&&l.setGeometry(e.geometry),(l.version!==t.version||l.needsUpdate)&&(l.initialCacheKey!==l.getCacheKey()?(l.dispose(),l=this.get(e,t,r,s,i,n,o,a)):l.version=t.version)),l}getChainMap(e="default"){return this.chainMaps[e]||(this.chainMaps[e]=new Rg)}dispose(){this.chainMaps={}}createRenderObject(e,t,r,s,i,n,o,a,u,l,d){const c=this.getChainMap(d),h=new Eg(e,t,r,s,i,n,o,a,u,l);return h.onDispose=()=>{this.pipelines.delete(h),this.bindings.delete(h),this.nodes.delete(h),c.delete(h.getChainArray())},h}}class Bg{constructor(){this.data=new WeakMap}get(e){let t=this.data.get(e);return void 0===t&&(t={},this.data.set(e,t)),t}delete(e){let t;return this.data.has(e)&&(t=this.data.get(e),this.data.delete(e)),t}has(e){return this.data.has(e)}dispose(){this.data=new WeakMap}}const Ug=1,Fg=2,Pg=3,Ig=4,Lg=16;class Vg extends Bg{constructor(e){super(),this.backend=e}delete(e){const t=super.delete(e);return void 0!==t&&this.backend.destroyAttribute(e),t}update(e,t){const r=this.get(e);if(void 0===r.version)t===Ug?this.backend.createAttribute(e):t===Fg?this.backend.createIndexAttribute(e):t===Pg?this.backend.createStorageAttribute(e):t===Ig&&this.backend.createIndirectStorageAttribute(e),r.version=this._getBufferAttribute(e).version;else{const t=this._getBufferAttribute(e);(r.version=0;--t)if(e[t]>=65535)return!0;return!1}(t)?ae:ue)(t,1);return i.version=Dg(e),i}class Gg extends Bg{constructor(e,t){super(),this.attributes=e,this.info=t,this.wireframes=new WeakMap,this.attributeCall=new WeakMap}has(e){const t=e.geometry;return super.has(t)&&!0===this.get(t).initialized}updateForRender(e){!1===this.has(e)&&this.initGeometry(e),this.updateAttributes(e)}initGeometry(e){const t=e.geometry;this.get(t).initialized=!0,this.info.memory.geometries++;const r=()=>{this.info.memory.geometries--;const s=t.index,i=e.getAttributes();null!==s&&this.attributes.delete(s);for(const e of i)this.attributes.delete(e);const n=this.wireframes.get(t);void 0!==n&&this.attributes.delete(n),t.removeEventListener("dispose",r)};t.addEventListener("dispose",r)}updateAttributes(e){const t=e.getAttributes();for(const e of t)e.isStorageBufferAttribute||e.isStorageInstancedBufferAttribute?this.updateAttribute(e,Pg):this.updateAttribute(e,Ug);const r=this.getIndex(e);null!==r&&this.updateAttribute(r,Fg);const s=e.geometry.indirect;null!==s&&this.updateAttribute(s,Ig)}updateAttribute(e,t){const r=this.info.render.calls;e.isInterleavedBufferAttribute?void 0===this.attributeCall.get(e)?(this.attributes.update(e,t),this.attributeCall.set(e,r)):this.attributeCall.get(e.data)!==r&&(this.attributes.update(e,t),this.attributeCall.set(e.data,r),this.attributeCall.set(e,r)):this.attributeCall.get(e)!==r&&(this.attributes.update(e,t),this.attributeCall.set(e,r))}getIndirect(e){return e.geometry.indirect}getIndex(e){const{geometry:t,material:r}=e;let s=t.index;if(!0===r.wireframe){const e=this.wireframes;let r=e.get(t);void 0===r?(r=Og(t),e.set(t,r)):r.version!==Dg(t)&&(this.attributes.delete(r),r=Og(t),e.set(t,r)),s=r}return s}}class kg{constructor(){this.autoReset=!0,this.frame=0,this.calls=0,this.render={calls:0,frameCalls:0,drawCalls:0,triangles:0,points:0,lines:0,timestamp:0,previousFrameCalls:0,timestampCalls:0},this.compute={calls:0,frameCalls:0,timestamp:0,previousFrameCalls:0,timestampCalls:0},this.memory={geometries:0,textures:0}}update(e,t,r){this.render.drawCalls++,e.isMesh||e.isSprite?this.render.triangles+=r*(t/3):e.isPoints?this.render.points+=r*t:e.isLineSegments?this.render.lines+=r*(t/2):e.isLine?this.render.lines+=r*(t-1):console.error("THREE.WebGPUInfo: Unknown object type.")}updateTimestamp(e,t){0===this[e].timestampCalls&&(this[e].timestamp=0),this[e].timestamp+=t,this[e].timestampCalls++,this[e].timestampCalls>=this[e].previousFrameCalls&&(this[e].timestampCalls=0)}reset(){const e=this.render.frameCalls;this.render.previousFrameCalls=e;const t=this.compute.frameCalls;this.compute.previousFrameCalls=t,this.render.drawCalls=0,this.render.frameCalls=0,this.compute.frameCalls=0,this.render.triangles=0,this.render.points=0,this.render.lines=0}dispose(){this.reset(),this.calls=0,this.render.calls=0,this.compute.calls=0,this.render.timestamp=0,this.compute.timestamp=0,this.memory.geometries=0,this.memory.textures=0}}class zg{constructor(e){this.cacheKey=e,this.usedTimes=0}}class $g extends zg{constructor(e,t,r){super(e),this.vertexProgram=t,this.fragmentProgram=r}}class Hg extends zg{constructor(e,t){super(e),this.computeProgram=t,this.isComputePipeline=!0}}let Wg=0;class jg{constructor(e,t,r=null,s=null){this.id=Wg++,this.code=e,this.stage=t,this.transforms=r,this.attributes=s,this.usedTimes=0}}class qg extends Bg{constructor(e,t){super(),this.backend=e,this.nodes=t,this.bindings=null,this.caches=new Map,this.programs={vertex:new Map,fragment:new Map,compute:new Map}}getForCompute(e,t){const{backend:r}=this,s=this.get(e);if(this._needsComputeUpdate(e)){const i=s.pipeline;i&&(i.usedTimes--,i.computeProgram.usedTimes--);const n=this.nodes.getForCompute(e);let o=this.programs.compute.get(n.computeShader);void 0===o&&(i&&0===i.computeProgram.usedTimes&&this._releaseProgram(i.computeProgram),o=new jg(n.computeShader,"compute",n.transforms,n.nodeAttributes),this.programs.compute.set(n.computeShader,o),r.createProgram(o));const a=this._getComputeCacheKey(e,o);let u=this.caches.get(a);void 0===u&&(i&&0===i.usedTimes&&this._releasePipeline(i),u=this._getComputePipeline(e,o,a,t)),u.usedTimes++,o.usedTimes++,s.version=e.version,s.pipeline=u}return s.pipeline}getForRender(e,t=null){const{backend:r}=this,s=this.get(e);if(this._needsRenderUpdate(e)){const i=s.pipeline;i&&(i.usedTimes--,i.vertexProgram.usedTimes--,i.fragmentProgram.usedTimes--);const n=e.getNodeBuilderState();let o=this.programs.vertex.get(n.vertexShader);void 0===o&&(i&&0===i.vertexProgram.usedTimes&&this._releaseProgram(i.vertexProgram),o=new jg(n.vertexShader,"vertex"),this.programs.vertex.set(n.vertexShader,o),r.createProgram(o));let a=this.programs.fragment.get(n.fragmentShader);void 0===a&&(i&&0===i.fragmentProgram.usedTimes&&this._releaseProgram(i.fragmentProgram),a=new jg(n.fragmentShader,"fragment"),this.programs.fragment.set(n.fragmentShader,a),r.createProgram(a));const u=this._getRenderCacheKey(e,o,a);let l=this.caches.get(u);void 0===l?(i&&0===i.usedTimes&&this._releasePipeline(i),l=this._getRenderPipeline(e,o,a,u,t)):e.pipeline=l,l.usedTimes++,o.usedTimes++,a.usedTimes++,s.pipeline=l}return s.pipeline}delete(e){const t=this.get(e).pipeline;return t&&(t.usedTimes--,0===t.usedTimes&&this._releasePipeline(t),t.isComputePipeline?(t.computeProgram.usedTimes--,0===t.computeProgram.usedTimes&&this._releaseProgram(t.computeProgram)):(t.fragmentProgram.usedTimes--,t.vertexProgram.usedTimes--,0===t.vertexProgram.usedTimes&&this._releaseProgram(t.vertexProgram),0===t.fragmentProgram.usedTimes&&this._releaseProgram(t.fragmentProgram))),super.delete(e)}dispose(){super.dispose(),this.caches=new Map,this.programs={vertex:new Map,fragment:new Map,compute:new Map}}updateForRender(e){this.getForRender(e)}_getComputePipeline(e,t,r,s){r=r||this._getComputeCacheKey(e,t);let i=this.caches.get(r);return void 0===i&&(i=new Hg(r,t),this.caches.set(r,i),this.backend.createComputePipeline(i,s)),i}_getRenderPipeline(e,t,r,s,i){s=s||this._getRenderCacheKey(e,t,r);let n=this.caches.get(s);return void 0===n&&(n=new $g(s,t,r),this.caches.set(s,n),e.pipeline=n,this.backend.createRenderPipeline(e,i)),n}_getComputeCacheKey(e,t){return e.id+","+t.id}_getRenderCacheKey(e,t,r){return t.id+","+r.id+","+this.backend.getRenderCacheKey(e)}_releasePipeline(e){this.caches.delete(e.cacheKey)}_releaseProgram(e){const t=e.code,r=e.stage;this.programs[r].delete(t)}_needsComputeUpdate(e){const t=this.get(e);return void 0===t.pipeline||t.version!==e.version}_needsRenderUpdate(e){return void 0===this.get(e).pipeline||this.backend.needsRenderUpdate(e)}}class Kg extends Bg{constructor(e,t,r,s,i,n){super(),this.backend=e,this.textures=r,this.pipelines=i,this.attributes=s,this.nodes=t,this.info=n,this.pipelines.bindings=this}getForRender(e){const t=e.getBindings();for(const e of t){const r=this.get(e);void 0===r.bindGroup&&(this._init(e),this.backend.createBindings(e,t,0),r.bindGroup=e)}return t}getForCompute(e){const t=this.nodes.getForCompute(e).bindings;for(const e of t){const r=this.get(e);void 0===r.bindGroup&&(this._init(e),this.backend.createBindings(e,t,0),r.bindGroup=e)}return t}updateForCompute(e){this._updateBindings(this.getForCompute(e))}updateForRender(e){this._updateBindings(this.getForRender(e))}_updateBindings(e){for(const t of e)this._update(t,e)}_init(e){for(const t of e.bindings)if(t.isSampledTexture)this.textures.updateTexture(t.texture);else if(t.isStorageBuffer){const e=t.attribute,r=e.isIndirectStorageBufferAttribute?Ig:Pg;this.attributes.update(e,r)}}_update(e,t){const{backend:r}=this;let s=!1,i=!0,n=0,o=0;for(const t of e.bindings){if(t.isNodeUniformsGroup){if(!this.nodes.updateGroup(t))continue}if(t.isUniformBuffer){t.update()&&r.updateBinding(t)}else if(t.isSampler)t.update();else if(t.isSampledTexture){const e=this.textures.get(t.texture);t.needsBindingsUpdate(e.generation)&&(s=!0);const a=t.update(),u=t.texture;a&&this.textures.updateTexture(u);const l=r.get(u);if(void 0!==l.externalTexture||e.isDefaultTexture?i=!1:(n=10*n+u.id,o+=u.version),!0===r.isWebGPUBackend&&void 0===l.texture&&void 0===l.externalTexture&&(console.error("Bindings._update: binding should be available:",t,a,u,t.textureNode.value,s),this.textures.updateTexture(u),s=!0),!0===u.isStorageTexture){const e=this.get(u);!0===t.store?e.needsMipmap=!0:this.textures.needsMipmaps(u)&&!0===e.needsMipmap&&(this.backend.generateMipmaps(u),e.needsMipmap=!1)}}}!0===s&&this.backend.updateBindings(e,t,i?n:0,o)}}function Xg(e,t){return e.groupOrder!==t.groupOrder?e.groupOrder-t.groupOrder:e.renderOrder!==t.renderOrder?e.renderOrder-t.renderOrder:e.material.id!==t.material.id?e.material.id-t.material.id:e.z!==t.z?e.z-t.z:e.id-t.id}function Yg(e,t){return e.groupOrder!==t.groupOrder?e.groupOrder-t.groupOrder:e.renderOrder!==t.renderOrder?e.renderOrder-t.renderOrder:e.z!==t.z?t.z-e.z:e.id-t.id}function Qg(e){return(e.transmission>0||e.transmissionNode)&&e.side===le&&!1===e.forceSinglePass}class Zg{constructor(e,t,r){this.renderItems=[],this.renderItemsIndex=0,this.opaque=[],this.transparentDoublePass=[],this.transparent=[],this.bundles=[],this.lightsNode=e.getNode(t,r),this.lightsArray=[],this.scene=t,this.camera=r,this.occlusionQueryCount=0}begin(){return this.renderItemsIndex=0,this.opaque.length=0,this.transparentDoublePass.length=0,this.transparent.length=0,this.bundles.length=0,this.lightsArray.length=0,this.occlusionQueryCount=0,this}getNextRenderItem(e,t,r,s,i,n,o){let a=this.renderItems[this.renderItemsIndex];return void 0===a?(a={id:e.id,object:e,geometry:t,material:r,groupOrder:s,renderOrder:e.renderOrder,z:i,group:n,clippingContext:o},this.renderItems[this.renderItemsIndex]=a):(a.id=e.id,a.object=e,a.geometry=t,a.material=r,a.groupOrder=s,a.renderOrder=e.renderOrder,a.z=i,a.group=n,a.clippingContext=o),this.renderItemsIndex++,a}push(e,t,r,s,i,n,o){const a=this.getNextRenderItem(e,t,r,s,i,n,o);!0===e.occlusionTest&&this.occlusionQueryCount++,!0===r.transparent||r.transmission>0?(Qg(r)&&this.transparentDoublePass.push(a),this.transparent.push(a)):this.opaque.push(a)}unshift(e,t,r,s,i,n,o){const a=this.getNextRenderItem(e,t,r,s,i,n,o);!0===r.transparent||r.transmission>0?(Qg(r)&&this.transparentDoublePass.unshift(a),this.transparent.unshift(a)):this.opaque.unshift(a)}pushBundle(e){this.bundles.push(e)}pushLight(e){this.lightsArray.push(e)}sort(e,t){this.opaque.length>1&&this.opaque.sort(e||Xg),this.transparentDoublePass.length>1&&this.transparentDoublePass.sort(t||Yg),this.transparent.length>1&&this.transparent.sort(t||Yg)}finish(){this.lightsNode.setLights(this.lightsArray);for(let e=this.renderItemsIndex,t=this.renderItems.length;e>t,u=o.height>>t;let l=e.depthTexture||i[t];const d=!0===e.depthBuffer||!0===e.stencilBuffer;let c=!1;void 0===l&&d&&(l=new B,l.format=e.stencilBuffer?de:ce,l.type=e.stencilBuffer?he:x,l.image.width=a,l.image.height=u,i[t]=l),r.width===o.width&&o.height===r.height||(c=!0,l&&(l.needsUpdate=!0,l.image.width=a,l.image.height=u)),r.width=o.width,r.height=o.height,r.textures=n,r.depthTexture=l||null,r.depth=e.depthBuffer,r.stencil=e.stencilBuffer,r.renderTarget=e,r.sampleCount!==s&&(c=!0,l&&(l.needsUpdate=!0),r.sampleCount=s);const h={sampleCount:s};for(let e=0;e{e.removeEventListener("dispose",t);for(let e=0;e0){const s=e.image;if(void 0===s)console.warn("THREE.Renderer: Texture marked for update but image is undefined.");else if(!1===s.complete)console.warn("THREE.Renderer: Texture marked for update but image is incomplete.");else{if(e.images){const r=[];for(const t of e.images)r.push(t);t.images=r}else t.image=s;void 0!==r.isDefaultTexture&&!0!==r.isDefaultTexture||(i.createTexture(e,t),r.isDefaultTexture=!1,r.generation=e.version),!0===e.source.dataReady&&i.updateTexture(e,t),t.needsMipmaps&&0===e.mipmaps.length&&i.generateMipmaps(e)}}else i.createDefaultTexture(e),r.isDefaultTexture=!0,r.generation=e.version}if(!0!==r.initialized){r.initialized=!0,r.generation=e.version,this.info.memory.textures++;const t=()=>{e.removeEventListener("dispose",t),this._destroyTexture(e),this.info.memory.textures--};e.addEventListener("dispose",t)}r.version=e.version}getSize(e,t=im){let r=e.images?e.images[0]:e.image;return r?(void 0!==r.image&&(r=r.image),t.width=r.width||1,t.height=r.height||1,t.depth=e.isCubeTexture?6:r.depth||1):t.width=t.height=t.depth=1,t}getMipLevels(e,t,r){let s;return s=e.isCompressedTexture?e.mipmaps?e.mipmaps.length:1:Math.floor(Math.log2(Math.max(t,r)))+1,s}needsMipmaps(e){return this.isEnvironmentTexture(e)||!0===e.isCompressedTexture||e.generateMipmaps}isEnvironmentTexture(e){const t=e.mapping;return t===j||t===q||t===_||t===v}_destroyTexture(e){this.backend.destroySampler(e),this.backend.destroyTexture(e),this.delete(e)}}class om extends e{constructor(e,t,r,s=1){super(e,t,r),this.a=s}set(e,t,r,s=1){return this.a=s,super.set(e,t,r)}copy(e){return void 0!==e.a&&(this.a=e.a),super.copy(e)}clone(){return new this.constructor(this.r,this.g,this.b,this.a)}}class am extends rn{static get type(){return"ParameterNode"}constructor(e,t=null){super(e,t),this.isParameterNode=!0}getHash(){return this.uuid}generate(){return this.name}}class um extends Ms{static get type(){return"StackNode"}constructor(e=null){super(),this.nodes=[],this.outputNode=null,this.parent=e,this._currentCond=null,this.isStackNode=!0}getNodeType(e){return this.outputNode?this.outputNode.getNodeType(e):"void"}add(e){return this.nodes.push(e),this}If(e,t){const r=new mi(t);return this._currentCond=Ta(e,r),this.add(this._currentCond)}ElseIf(e,t){const r=new mi(t),s=Ta(e,r);return this._currentCond.elseNode=s,this._currentCond=s,this}Else(e){return this._currentCond.elseNode=new mi(e),this}build(e,...t){const r=Ni();vi(this);for(const t of this.nodes)t.build(e,"void");return vi(r),this.outputNode?this.outputNode.build(e,...t):super.build(e,...t)}else(...e){return console.warn("TSL.StackNode: .else() has been renamed to .Else()."),this.Else(...e)}elseif(...e){return console.warn("TSL.StackNode: .elseif() has been renamed to .ElseIf()."),this.ElseIf(...e)}}const lm=bi(um);class dm extends Ms{static get type(){return"OutputStructNode"}constructor(...e){super(),this.members=e,this.isOutputStructNode=!0}setup(e){super.setup(e);const t=this.members,r=[];for(let s=0;s{const t=e.toUint().mul(747796405).add(2891336453),r=t.shiftRight(t.shiftRight(28).add(4)).bitXor(t).mul(277803737);return r.shiftRight(22).bitXor(r).toFloat().mul(1/2**32)})),fm=(e,t)=>ra(kn(4,e.mul(Gn(1,e))),t),ym=_i((([e])=>e.fract().sub(.5).abs())).setLayout({name:"tri",type:"float",inputs:[{name:"x",type:"float"}]}),xm=_i((([e])=>Ii(ym(e.z.add(ym(e.y.mul(1)))),ym(e.z.add(ym(e.x.mul(1)))),ym(e.y.add(ym(e.x.mul(1))))))).setLayout({name:"tri3",type:"vec3",inputs:[{name:"p",type:"vec3"}]}),bm=_i((([e,t,r])=>{const s=Ii(e).toVar(),i=Ci(1.4).toVar(),n=Ci(0).toVar(),o=Ii(s).toVar();return ic({start:Ci(0),end:Ci(3),type:"float",condition:"<="},(()=>{const e=Ii(xm(o.mul(2))).toVar();s.addAssign(e.add(r.mul(Ci(.1).mul(t)))),o.mulAssign(1.8),i.mulAssign(1.5),s.mulAssign(1.2);const a=Ci(ym(s.z.add(ym(s.x.add(ym(s.y)))))).toVar();n.addAssign(a.div(i)),o.addAssign(.14)})),n})).setLayout({name:"triNoise3D",type:"float",inputs:[{name:"position",type:"vec3"},{name:"speed",type:"float"},{name:"time",type:"float"}]});class Tm extends Ms{static get type(){return"FunctionOverloadingNode"}constructor(e=[],...t){super(),this.functionNodes=e,this.parametersNodes=t,this._candidateFnCall=null,this.global=!0}getNodeType(){return this.functionNodes[0].shaderNode.layout.type}setup(e){const t=this.parametersNodes;let r=this._candidateFnCall;if(null===r){let s=null,i=-1;for(const r of this.functionNodes){const n=r.shaderNode.layout;if(null===n)throw new Error("FunctionOverloadingNode: FunctionNode must be a layout.");const o=n.inputs;if(t.length===o.length){let n=0;for(let r=0;ri&&(s=r,i=n)}}this._candidateFnCall=r=s(...t)}return r}}const _m=bi(Tm),vm=e=>(...t)=>_m(e,...t),Nm=tn(0).setGroup(Zi).onRenderUpdate((e=>e.time)),Sm=tn(0).setGroup(Zi).onRenderUpdate((e=>e.deltaTime)),Am=tn(0,"uint").setGroup(Zi).onRenderUpdate((e=>e.frameId)),Rm=_i((([e,t,r=Bi(.5)])=>mg(e.sub(r),t).add(r))),Cm=_i((([e,t,r=Bi(.5)])=>{const s=e.sub(r),i=s.dot(s),n=i.mul(i).mul(t);return e.add(s.mul(n))})),Em=_i((({position:e=null,horizontal:t=!0,vertical:r=!1})=>{let s;null!==e?(s=Vu.toVar(),s[3][0]=e.x,s[3][1]=e.y,s[3][2]=e.z):s=Vu;const i=Au.mul(s);return pi(t)&&(i[0][0]=Vu[0].length(),i[0][1]=0,i[0][2]=0),pi(r)&&(i[1][0]=0,i[1][1]=Vu[1].length(),i[1][2]=0),i[2][0]=0,i[2][1]=0,i[2][2]=1,Nu.mul(i).mul(Ku)})),wm=_i((([e=null])=>{const t=$c();return $c(Ic(e)).sub(t).lessThan(0).select(bc,e)}));class Mm extends Ms{static get type(){return"SpriteSheetUVNode"}constructor(e,t=pu(),r=Ci(0)){super("vec2"),this.countNode=e,this.uvNode=t,this.frameNode=r}setup(){const{frameNode:e,uvNode:t,countNode:r}=this,{width:s,height:i}=r,n=e.mod(s.mul(i)).floor(),o=n.mod(s),a=i.sub(n.add(1).div(s).ceil()),u=r.reciprocal(),l=Bi(o,a);return t.add(l).mul(u)}}const Bm=bi(Mm);class Um extends Ms{static get type(){return"TriplanarTexturesNode"}constructor(e,t=null,r=null,s=Ci(1),i=Ku,n=il){super("vec4"),this.textureXNode=e,this.textureYNode=t,this.textureZNode=r,this.scaleNode=s,this.positionNode=i,this.normalNode=n}setup(){const{textureXNode:e,textureYNode:t,textureZNode:r,scaleNode:s,positionNode:i,normalNode:n}=this;let o=n.abs().normalize();o=o.div(o.dot(Ii(1)));const a=i.yz.mul(s),u=i.zx.mul(s),l=i.xy.mul(s),d=e.value,c=null!==t?t.value:d,h=null!==r?r.value:d,p=bu(d,a).mul(o.x),g=bu(c,u).mul(o.y),m=bu(h,l).mul(o.z);return On(p,g,m)}}const Fm=bi(Um),Pm=new me,Im=new r,Lm=new r,Vm=new r,Dm=new n,Om=new r(0,0,-1),Gm=new s,km=new r,zm=new r,$m=new s,Hm=new t,Wm=new ge,jm=bc.flipX();Wm.depthTexture=new B(1,1);let qm=!1;class Km extends xu{static get type(){return"ReflectorNode"}constructor(e={}){super(e.defaultTexture||Wm.texture,jm),this._reflectorBaseNode=e.reflector||new Xm(this,e),this._depthNode=null,this.setUpdateMatrix(!1)}get reflector(){return this._reflectorBaseNode}get target(){return this._reflectorBaseNode.target}getDepthNode(){if(null===this._depthNode){if(!0!==this._reflectorBaseNode.depth)throw new Error("THREE.ReflectorNode: Depth node can only be requested when the reflector is created with { depth: true }. ");this._depthNode=fi(new Km({defaultTexture:Wm.depthTexture,reflector:this._reflectorBaseNode}))}return this._depthNode}setup(e){return e.object.isQuadMesh||this._reflectorBaseNode.build(e),super.setup(e)}clone(){const e=new this.constructor(this.reflectorNode);return e._reflectorBaseNode=this._reflectorBaseNode,e}}class Xm extends Ms{static get type(){return"ReflectorBaseNode"}constructor(e,t={}){super();const{target:r=new fe,resolution:s=1,generateMipmaps:i=!1,bounces:n=!0,depth:o=!1}=t;this.textureNode=e,this.target=r,this.resolution=s,this.generateMipmaps=i,this.bounces=n,this.depth=o,this.updateBeforeType=n?vs.RENDER:vs.FRAME,this.virtualCameras=new WeakMap,this.renderTargets=new WeakMap}_updateResolution(e,t){const r=this.resolution;t.getDrawingBufferSize(Hm),e.setSize(Math.round(Hm.width*r),Math.round(Hm.height*r))}setup(e){return this._updateResolution(Wm,e.renderer),super.setup(e)}getVirtualCamera(e){let t=this.virtualCameras.get(e);return void 0===t&&(t=e.clone(),this.virtualCameras.set(e,t)),t}getRenderTarget(e){let t=this.renderTargets.get(e);return void 0===t&&(t=new ge(0,0,{type:ye}),!0===this.generateMipmaps&&(t.texture.minFilter=xe,t.texture.generateMipmaps=!0),!0===this.depth&&(t.depthTexture=new B),this.renderTargets.set(e,t)),t}updateBefore(e){if(!1===this.bounces&&qm)return;qm=!0;const{scene:t,camera:r,renderer:s,material:i}=e,{target:n}=this,o=this.getVirtualCamera(r),a=this.getRenderTarget(o);if(s.getDrawingBufferSize(Hm),this._updateResolution(a,s),Lm.setFromMatrixPosition(n.matrixWorld),Vm.setFromMatrixPosition(r.matrixWorld),Dm.extractRotation(n.matrixWorld),Im.set(0,0,1),Im.applyMatrix4(Dm),km.subVectors(Lm,Vm),km.dot(Im)>0)return;km.reflect(Im).negate(),km.add(Lm),Dm.extractRotation(r.matrixWorld),Om.set(0,0,-1),Om.applyMatrix4(Dm),Om.add(Vm),zm.subVectors(Lm,Om),zm.reflect(Im).negate(),zm.add(Lm),o.coordinateSystem=r.coordinateSystem,o.position.copy(km),o.up.set(0,1,0),o.up.applyMatrix4(Dm),o.up.reflect(Im),o.lookAt(zm),o.near=r.near,o.far=r.far,o.updateMatrixWorld(),o.projectionMatrix.copy(r.projectionMatrix),Pm.setFromNormalAndCoplanarPoint(Im,Lm),Pm.applyMatrix4(o.matrixWorldInverse),Gm.set(Pm.normal.x,Pm.normal.y,Pm.normal.z,Pm.constant);const u=o.projectionMatrix;$m.x=(Math.sign(Gm.x)+u.elements[8])/u.elements[0],$m.y=(Math.sign(Gm.y)+u.elements[9])/u.elements[5],$m.z=-1,$m.w=(1+u.elements[10])/u.elements[14],Gm.multiplyScalar(1/Gm.dot($m));u.elements[2]=Gm.x,u.elements[6]=Gm.y,u.elements[10]=s.coordinateSystem===l?Gm.z-0:Gm.z+1-0,u.elements[14]=Gm.w,this.textureNode.value=a.texture,!0===this.depth&&(this.textureNode.getDepthNode().value=a.depthTexture),i.visible=!1;const d=s.getRenderTarget(),c=s.getMRT();s.setMRT(null),s.setRenderTarget(a),s.render(t,o),s.setMRT(c),s.setRenderTarget(d),i.visible=!0,qm=!1}}const Ym=new be(-1,1,1,-1,0,1);class Qm extends Te{constructor(e=!1){super();const t=!1===e?[0,-1,0,1,2,1]:[0,2,0,0,2,0];this.setAttribute("position",new _e([-1,3,0,-1,-1,0,3,-1,0],3)),this.setAttribute("uv",new _e(t,2))}}const Zm=new Qm;class Jm extends k{constructor(e=null){super(Zm,e),this.camera=Ym,this.isQuadMesh=!0}renderAsync(e){return e.renderAsync(this,Ym)}render(e){e.render(this,Ym)}}const ef=new t;class tf extends xu{static get type(){return"RTTNode"}constructor(e,t=null,r=null,s={type:ye}){const i=new ge(t,r,s);super(i.texture,pu()),this.node=e,this.width=t,this.height=r,this.pixelRatio=1,this.renderTarget=i,this.textureNeedsUpdate=!0,this.autoUpdate=!0,this._rttNode=null,this._quadMesh=new Jm(new Yc),this.updateBeforeType=vs.RENDER}get autoSize(){return null===this.width}setup(e){return this._rttNode=this.node.context(e.getSharedContext()),this._quadMesh.material.name="RTT",this._quadMesh.material.needsUpdate=!0,super.setup(e)}setSize(e,t){this.width=e,this.height=t;const r=e*this.pixelRatio,s=t*this.pixelRatio;this.renderTarget.setSize(r,s),this.textureNeedsUpdate=!0}setPixelRatio(e){this.pixelRatio=e,this.setSize(this.width,this.height)}updateBefore({renderer:e}){if(!1===this.textureNeedsUpdate&&!1===this.autoUpdate)return;if(this.textureNeedsUpdate=!1,!0===this.autoSize){this.pixelRatio=e.getPixelRatio();const t=e.getSize(ef);this.setSize(t.width,t.height)}this._quadMesh.material.fragmentNode=this._rttNode;const t=e.getRenderTarget();e.setRenderTarget(this.renderTarget),this._quadMesh.render(e),e.setRenderTarget(t)}clone(){const e=new xu(this.value,this.uvNode,this.levelNode);return e.sampler=this.sampler,e.referenceNode=this,e}}const rf=(e,...t)=>fi(new tf(fi(e),...t)),sf=_i((([e,t,r],s)=>{let i;s.renderer.coordinateSystem===l?(e=Bi(e.x,e.y.oneMinus()).mul(2).sub(1),i=Oi(Ii(e,t),1)):i=Oi(Ii(e.x,e.y.oneMinus(),t).mul(2).sub(1),1);const n=Oi(r.mul(i));return n.xyz.div(n.w)})),nf=_i((([e,t])=>{const r=t.mul(Oi(e,1)),s=r.xy.div(r.w).mul(.5).add(.5).toVar();return Bi(s.x,s.y.oneMinus())})),of=_i((([e,t,r])=>{const s=mu(Tu(t)),i=Ui(e.mul(s)).toVar(),n=Tu(t,i).toVar(),o=Tu(t,i.sub(Ui(2,0))).toVar(),a=Tu(t,i.sub(Ui(1,0))).toVar(),u=Tu(t,i.add(Ui(1,0))).toVar(),l=Tu(t,i.add(Ui(2,0))).toVar(),d=Tu(t,i.add(Ui(0,2))).toVar(),c=Tu(t,i.add(Ui(0,1))).toVar(),h=Tu(t,i.sub(Ui(0,1))).toVar(),p=Tu(t,i.sub(Ui(0,2))).toVar(),g=Fo(Gn(Ci(2).mul(a).sub(o),n)).toVar(),m=Fo(Gn(Ci(2).mul(u).sub(l),n)).toVar(),f=Fo(Gn(Ci(2).mul(c).sub(d),n)).toVar(),y=Fo(Gn(Ci(2).mul(h).sub(p),n)).toVar(),x=sf(e,n,r).toVar(),b=g.lessThan(m).select(x.sub(sf(e.sub(Bi(Ci(1).div(s.x),0)),a,r)),x.negate().add(sf(e.add(Bi(Ci(1).div(s.x),0)),u,r))),T=f.lessThan(y).select(x.sub(sf(e.add(Bi(0,Ci(1).div(s.y))),c,r)),x.negate().add(sf(e.sub(Bi(0,Ci(1).div(s.y))),h,r)));return Ao(ta(b,T))}));class af extends R{constructor(e,t,r=Float32Array){!1===ArrayBuffer.isView(e)&&(e=new r(e*t)),super(e,t),this.isStorageInstancedBufferAttribute=!0}}class uf extends ve{constructor(e,t,r=Float32Array){!1===ArrayBuffer.isView(e)&&(e=new r(e*t)),super(e,t),this.isStorageBufferAttribute=!0}}class lf extends Bs{static get type(){return"StorageArrayElementNode"}constructor(e,t){super(e,t),this.isStorageArrayElementNode=!0}set storageBufferNode(e){this.node=e}get storageBufferNode(){return this.node}setup(e){return!1===e.isAvailable("storageBuffer")&&!0===this.node.isPBO&&e.setupPBO(this.node),super.setup(e)}generate(e,t){let r;const s=e.context.assign;if(r=!1===e.isAvailable("storageBuffer")?!0!==this.node.isPBO||!0===s||!this.node.value.isInstancedBufferAttribute&&"compute"===e.shaderStage?this.node.build(e):e.generatePBO(this):super.generate(e),!0!==s){const s=this.getNodeType(e);r=e.format(r,s,t)}return r}}const df=bi(lf);class cf extends Tl{static get type(){return"StorageBufferNode"}constructor(e,t=null,r=0){null===t&&(e.isStorageBufferAttribute||e.isStorageInstancedBufferAttribute)&&(t=gs(e.itemSize),r=e.count),super(e,t,r),this.isStorageBufferNode=!0,this.access=Ss.READ_WRITE,this.isAtomic=!1,this.isPBO=!1,this._attribute=null,this._varying=null,this.global=!0,!0!==e.isStorageBufferAttribute&&!0!==e.isStorageInstancedBufferAttribute&&(e.isInstancedBufferAttribute?e.isStorageInstancedBufferAttribute=!0:e.isStorageBufferAttribute=!0)}getHash(e){if(0===this.bufferCount){let t=e.globalCache.getData(this.value);return void 0===t&&(t={node:this},e.globalCache.setData(this.value,t)),t.node.uuid}return this.uuid}getInputType(){return this.value.isIndirectStorageBufferAttribute?"indirectStorageBuffer":"storageBuffer"}element(e){return df(this,e)}setPBO(e){return this.isPBO=e,this}getPBO(){return this.isPBO}setAccess(e){return this.access=e,this}toReadOnly(){return this.setAccess(Ss.READ_ONLY)}setAtomic(e){return this.isAtomic=e,this}toAtomic(){return this.setAtomic(!0)}getAttributeData(){return null===this._attribute&&(this._attribute=qa(this.value),this._varying=wa(this._attribute)),{attribute:this._attribute,varying:this._varying}}getNodeType(e){if(e.isAvailable("storageBuffer")||e.isAvailable("indirectStorageBuffer"))return super.getNodeType(e);const{attribute:t}=this.getAttributeData();return t.getNodeType(e)}generate(e){if(e.isAvailable("storageBuffer")||e.isAvailable("indirectStorageBuffer"))return super.generate(e);const{attribute:t,varying:r}=this.getAttributeData(),s=r.build(e);return e.registerTransform(s,t),s}}const hf=(e,t=null,r=0)=>fi(new cf(e,t,r));class pf extends cu{static get type(){return"VertexColorNode"}constructor(e=0){super(null,"vec4"),this.isVertexColorNode=!0,this.index=e}getAttributeName(){const e=this.index;return"color"+(e>0?e:"")}generate(e){const t=this.getAttributeName(e);let r;return r=!0===e.hasGeometryAttribute(t)?super.generate(e):e.generateConst(this.nodeType,new s(1,1,1,1)),r}serialize(e){super.serialize(e),e.index=this.index}deserialize(e){super.deserialize(e),this.index=e.index}}class gf extends Ms{static get type(){return"PointUVNode"}constructor(){super("vec2"),this.isPointUVNode=!0}generate(){return"vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y )"}}const mf=Ti(gf),ff=new Se,yf=new n;class xf extends Ms{static get type(){return"SceneNode"}constructor(e=xf.BACKGROUND_BLURRINESS,t=null){super(),this.scope=e,this.scene=t}setup(e){const t=this.scope,r=null!==this.scene?this.scene:e.scene;let s;return t===xf.BACKGROUND_BLURRINESS?s=Cl("backgroundBlurriness","float",r):t===xf.BACKGROUND_INTENSITY?s=Cl("backgroundIntensity","float",r):t===xf.BACKGROUND_ROTATION?s=tn("mat4").label("backgroundRotation").setGroup(Zi).onRenderUpdate((()=>{const e=r.background;return null!==e&&e.isTexture&&e.mapping!==Ne?(ff.copy(r.backgroundRotation),ff.x*=-1,ff.y*=-1,ff.z*=-1,yf.makeRotationFromEuler(ff)):yf.identity(),yf})):console.error("THREE.SceneNode: Unknown scope:",t),s}}xf.BACKGROUND_BLURRINESS="backgroundBlurriness",xf.BACKGROUND_INTENSITY="backgroundIntensity",xf.BACKGROUND_ROTATION="backgroundRotation";const bf=Ti(xf,xf.BACKGROUND_BLURRINESS),Tf=Ti(xf,xf.BACKGROUND_INTENSITY),_f=Ti(xf,xf.BACKGROUND_ROTATION);class vf extends xu{static get type(){return"StorageTextureNode"}constructor(e,t,r=null){super(e,t),this.storeNode=r,this.isStorageTextureNode=!0,this.access=Ss.WRITE_ONLY}getInputType(){return"storageTexture"}setup(e){super.setup(e);e.getNodeProperties(this).storeNode=this.storeNode}setAccess(e){return this.access=e,this}generate(e,t){let r;return r=null!==this.storeNode?this.generateStore(e):super.generate(e,t),r}toReadWrite(){return this.setAccess(Ss.READ_WRITE)}toReadOnly(){return this.setAccess(Ss.READ_ONLY)}toWriteOnly(){return this.setAccess(Ss.WRITE_ONLY)}generateStore(e){const t=e.getNodeProperties(this),{uvNode:r,storeNode:s}=t,i=super.generate(e,"property"),n=r.build(e,"uvec2"),o=s.build(e,"vec4"),a=e.generateTextureStore(e,i,n,o);e.addLineFlowCode(a,this)}}const Nf=bi(vf);class Sf extends Rl{static get type(){return"UserDataNode"}constructor(e,t,r=null){super(e,t,r),this.userData=r}updateReference(e){return this.reference=null!==this.userData?this.userData:e.object.userData,this.reference}}const Af=new WeakMap;class Rf extends Fs{static get type(){return"VelocityNode"}constructor(){super("vec2"),this.projectionMatrix=null,this.updateType=vs.OBJECT,this.updateAfterType=vs.OBJECT,this.previousModelWorldMatrix=tn(new n),this.previousProjectionMatrix=tn(new n).setGroup(Zi),this.previousCameraViewMatrix=tn(new n)}setProjectionMatrix(e){this.projectionMatrix=e}update({frameId:e,camera:t,object:r}){const s=Ef(r);this.previousModelWorldMatrix.value.copy(s);const i=Cf(t);i.frameId!==e&&(i.frameId=e,void 0===i.previousProjectionMatrix?(i.previousProjectionMatrix=new n,i.previousCameraViewMatrix=new n,i.currentProjectionMatrix=new n,i.currentCameraViewMatrix=new n,i.previousProjectionMatrix.copy(this.projectionMatrix||t.projectionMatrix),i.previousCameraViewMatrix.copy(t.matrixWorldInverse)):(i.previousProjectionMatrix.copy(i.currentProjectionMatrix),i.previousCameraViewMatrix.copy(i.currentCameraViewMatrix)),i.currentProjectionMatrix.copy(this.projectionMatrix||t.projectionMatrix),i.currentCameraViewMatrix.copy(t.matrixWorldInverse),this.previousProjectionMatrix.value.copy(i.previousProjectionMatrix),this.previousCameraViewMatrix.value.copy(i.previousCameraViewMatrix))}updateAfter({object:e}){Ef(e).copy(e.matrixWorld)}setup(){const e=null===this.projectionMatrix?Nu:tn(this.projectionMatrix),t=this.previousCameraViewMatrix.mul(this.previousModelWorldMatrix),r=e.mul($u).mul(Ku),s=this.previousProjectionMatrix.mul(t).mul(Xu),i=r.xy.div(r.w),n=s.xy.div(s.w);return Gn(i,n)}}function Cf(e){let t=Af.get(e);return void 0===t&&(t={},Af.set(e,t)),t}function Ef(e,t=0){const r=Cf(e);let s=r[t];return void 0===s&&(r[t]=s=new n),s}const wf=Ti(Rf),Mf=_i((([e,t])=>qo(1,e.oneMinus().div(t)).oneMinus())).setLayout({name:"blendBurn",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),Bf=_i((([e,t])=>qo(e.div(t.oneMinus()),1))).setLayout({name:"blendDodge",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),Uf=_i((([e,t])=>e.oneMinus().mul(t.oneMinus()).oneMinus())).setLayout({name:"blendScreen",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),Ff=_i((([e,t])=>la(e.mul(2).mul(t),e.oneMinus().mul(2).mul(t.oneMinus()).oneMinus(),Yo(.5,e)))).setLayout({name:"blendOverlay",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),Pf=_i((([e,t])=>{const r=t.a.add(e.a.mul(t.a.oneMinus()));return Oi(t.rgb.mul(t.a).add(e.rgb.mul(e.a).mul(t.a.oneMinus())).div(r),r)})).setLayout({name:"blendColor",type:"vec4",inputs:[{name:"base",type:"vec4"},{name:"blend",type:"vec4"}]}),If=_i((([e])=>Of(e.rgb))),Lf=_i((([e,t=Ci(1)])=>t.mix(Of(e.rgb),e.rgb))),Vf=_i((([e,t=Ci(1)])=>{const r=On(e.r,e.g,e.b).div(3),s=e.r.max(e.g.max(e.b)),i=s.sub(r).mul(t).mul(-3);return la(e.rgb,s,i)})),Df=_i((([e,t=Ci(1)])=>{const r=Ii(.57735,.57735,.57735),s=t.cos();return Ii(e.rgb.mul(s).add(r.cross(e.rgb).mul(t.sin()).add(r.mul(ea(r,e.rgb).mul(s.oneMinus())))))})),Of=(e,t=Ii(d.getLuminanceCoefficients(new r)))=>ea(e,t),Gf=_i((([e,t=Ii(1),s=Ii(0),i=Ii(1),n=Ci(1),o=Ii(d.getLuminanceCoefficients(new r,Ae))])=>{const a=e.rgb.dot(Ii(o)),u=Ko(e.rgb.mul(t).add(s),0).toVar(),l=u.pow(i).toVar();return Si(u.r.greaterThan(0),(()=>{u.r.assign(l.r)})),Si(u.g.greaterThan(0),(()=>{u.g.assign(l.g)})),Si(u.b.greaterThan(0),(()=>{u.b.assign(l.b)})),u.assign(a.add(u.sub(a).mul(n))),Oi(u.rgb,e.a)}));class kf extends Fs{static get type(){return"PosterizeNode"}constructor(e,t){super(),this.sourceNode=e,this.stepsNode=t}setup(){const{sourceNode:e,stepsNode:t}=this;return e.mul(t).floor().div(t)}}const zf=bi(kf),$f=new t;class Hf extends xu{static get type(){return"PassTextureNode"}constructor(e,t){super(t),this.passNode=e,this.setUpdateMatrix(!1)}setup(e){return e.object.isQuadMesh&&this.passNode.build(e),super.setup(e)}clone(){return new this.constructor(this.passNode,this.value)}}class Wf extends Hf{static get type(){return"PassMultipleTextureNode"}constructor(e,t,r=!1){super(e,null),this.textureName=t,this.previousTexture=r}updateTexture(){this.value=this.previousTexture?this.passNode.getPreviousTexture(this.textureName):this.passNode.getTexture(this.textureName)}setup(e){return this.updateTexture(),super.setup(e)}clone(){return new this.constructor(this.passNode,this.textureName,this.previousTexture)}}class jf extends Fs{static get type(){return"PassNode"}constructor(e,t,r,s={}){super("vec4"),this.scope=e,this.scene=t,this.camera=r,this.options=s,this._pixelRatio=1,this._width=1,this._height=1;const i=new B;i.isRenderTargetTexture=!0,i.name="depth";const n=new ge(this._width*this._pixelRatio,this._height*this._pixelRatio,{type:ye,...s});n.texture.name="output",n.depthTexture=i,this.renderTarget=n,this._textures={output:n.texture,depth:i},this._textureNodes={},this._linearDepthNodes={},this._viewZNodes={},this._previousTextures={},this._previousTextureNodes={},this._cameraNear=tn(0),this._cameraFar=tn(0),this._mrt=null,this.isPassNode=!0,this.updateBeforeType=vs.FRAME}setMRT(e){return this._mrt=e,this}getMRT(){return this._mrt}isGlobal(){return!0}getTexture(e){let t=this._textures[e];if(void 0===t){t=this.renderTarget.texture.clone(),t.name=e,this._textures[e]=t,this.renderTarget.textures.push(t)}return t}getPreviousTexture(e){let t=this._previousTextures[e];return void 0===t&&(t=this.getTexture(e).clone(),this._previousTextures[e]=t),t}toggleTexture(e){const t=this._previousTextures[e];if(void 0!==t){const r=this._textures[e],s=this.renderTarget.textures.indexOf(r);this.renderTarget.textures[s]=t,this._textures[e]=t,this._previousTextures[e]=r,this._textureNodes[e].updateTexture(),this._previousTextureNodes[e].updateTexture()}}getTextureNode(e="output"){let t=this._textureNodes[e];return void 0===t&&(t=fi(new Wf(this,e)),t.updateTexture(),this._textureNodes[e]=t),t}getPreviousTextureNode(e="output"){let t=this._previousTextureNodes[e];return void 0===t&&(void 0===this._textureNodes[e]&&this.getTextureNode(e),t=fi(new Wf(this,e,!0)),t.updateTexture(),this._previousTextureNodes[e]=t),t}getViewZNode(e="depth"){let t=this._viewZNodes[e];if(void 0===t){const r=this._cameraNear,s=this._cameraFar;this._viewZNodes[e]=t=Oc(this.getTextureNode(e),r,s)}return t}getLinearDepthNode(e="depth"){let t=this._linearDepthNodes[e];if(void 0===t){const r=this._cameraNear,s=this._cameraFar,i=this.getViewZNode(e);this._linearDepthNodes[e]=t=Vc(i,r,s)}return t}setup({renderer:e}){return this.renderTarget.samples=void 0===this.options.samples?e.samples:this.options.samples,!0===e.backend.isWebGLBackend&&(this.renderTarget.samples=0),this.scope===jf.COLOR?this.getTextureNode():this.getLinearDepthNode()}updateBefore(e){const{renderer:t}=e,{scene:r,camera:s}=this;this._pixelRatio=t.getPixelRatio();const i=t.getSize($f);this.setSize(i.width,i.height);const n=t.getRenderTarget(),o=t.getMRT();this._cameraNear.value=s.near,this._cameraFar.value=s.far;for(const e in this._previousTextures)this.toggleTexture(e);t.setRenderTarget(this.renderTarget),t.setMRT(this._mrt),t.render(r,s),t.setRenderTarget(n),t.setMRT(o)}setSize(e,t){this._width=e,this._height=t;const r=this._width*this._pixelRatio,s=this._height*this._pixelRatio;this.renderTarget.setSize(r,s)}setPixelRatio(e){this._pixelRatio=e,this.setSize(this._width,this._height)}dispose(){this.renderTarget.dispose()}}jf.COLOR="color",jf.DEPTH="depth";class qf extends jf{static get type(){return"ToonOutlinePassNode"}constructor(e,t,r,s,i){super(jf.COLOR,e,t),this.colorNode=r,this.thicknessNode=s,this.alphaNode=i,this._materialCache=new WeakMap}updateBefore(e){const{renderer:t}=e,r=t.getRenderObjectFunction();t.setRenderObjectFunction(((e,r,s,i,n,o,a,u)=>{if((n.isMeshToonMaterial||n.isMeshToonNodeMaterial)&&!1===n.wireframe){const l=this._getOutlineMaterial(n);t.renderObject(e,r,s,i,l,o,a,u)}t.renderObject(e,r,s,i,n,o,a,u)})),super.updateBefore(e),t.setRenderObjectFunction(r)}_createMaterial(){const e=new Yc;e.isMeshToonOutlineMaterial=!0,e.name="Toon_Outline",e.side=T;const t=il.negate(),r=Nu.mul($u),s=Ci(1),i=r.mul(Oi(Ku,1)),n=r.mul(Oi(Ku.add(t),1)),o=Ao(i.sub(n));return e.vertexNode=i.add(o.mul(this.thicknessNode).mul(i.w).mul(s)),e.colorNode=Oi(this.colorNode,this.alphaNode),e}_getOutlineMaterial(e){let t=this._materialCache.get(e);return void 0===t&&(t=this._createMaterial(),this._materialCache.set(e,t)),t}}const Kf=_i((([e,t])=>e.mul(t).clamp())).setLayout({name:"linearToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),Xf=_i((([e,t])=>(e=e.mul(t)).div(e.add(1)).clamp())).setLayout({name:"reinhardToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),Yf=_i((([e,t])=>{const r=(e=(e=e.mul(t)).sub(.004).max(0)).mul(e.mul(6.2).add(.5)),s=e.mul(e.mul(6.2).add(1.7)).add(.06);return r.div(s).pow(2.2)})).setLayout({name:"cineonToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),Qf=_i((([e])=>{const t=e.mul(e.add(.0245786)).sub(90537e-9),r=e.mul(e.add(.432951).mul(.983729)).add(.238081);return t.div(r)})),Zf=_i((([e,t])=>{const r=Hi(.59719,.35458,.04823,.076,.90834,.01566,.0284,.13383,.83777),s=Hi(1.60475,-.53108,-.07367,-.10208,1.10813,-.00605,-.00327,-.07276,1.07602);return e=e.mul(t).div(.6),e=r.mul(e),e=Qf(e),(e=s.mul(e)).clamp()})).setLayout({name:"acesFilmicToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),Jf=Hi(Ii(1.6605,-.1246,-.0182),Ii(-.5876,1.1329,-.1006),Ii(-.0728,-.0083,1.1187)),ey=Hi(Ii(.6274,.0691,.0164),Ii(.3293,.9195,.088),Ii(.0433,.0113,.8956)),ty=_i((([e])=>{const t=Ii(e).toVar(),r=Ii(t.mul(t)).toVar(),s=Ii(r.mul(r)).toVar();return Ci(15.5).mul(s.mul(r)).sub(kn(40.14,s.mul(t))).add(kn(31.96,s).sub(kn(6.868,r.mul(t))).add(kn(.4298,r).add(kn(.1191,t).sub(.00232))))})),ry=_i((([e,t])=>{const r=Ii(e).toVar(),s=Hi(Ii(.856627153315983,.137318972929847,.11189821299995),Ii(.0951212405381588,.761241990602591,.0767994186031903),Ii(.0482516061458583,.101439036467562,.811302368396859)),i=Hi(Ii(1.1271005818144368,-.1413297634984383,-.14132976349843826),Ii(-.11060664309660323,1.157823702216272,-.11060664309660294),Ii(-.016493938717834573,-.016493938717834257,1.2519364065950405)),n=Ci(-12.47393),o=Ci(4.026069);return r.mulAssign(t),r.assign(ey.mul(r)),r.assign(s.mul(r)),r.assign(Ko(r,1e-10)),r.assign(To(r)),r.assign(r.sub(n).div(o.sub(n))),r.assign(da(r,0,1)),r.assign(ty(r)),r.assign(i.mul(r)),r.assign(ra(Ko(Ii(0),r),Ii(2.2))),r.assign(Jf.mul(r)),r.assign(da(r,0,1)),r})).setLayout({name:"agxToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),sy=_i((([e,t])=>{const r=Ci(.76),s=Ci(.15);e=e.mul(t);const i=qo(e.r,qo(e.g,e.b)),n=Ta(i.lessThan(.08),i.sub(kn(6.25,i.mul(i))),.04);e.subAssign(n);const o=Ko(e.r,Ko(e.g,e.b));Si(o.lessThan(r),(()=>e));const a=Gn(1,r),u=Gn(1,a.mul(a).div(o.add(a.sub(r))));e.mulAssign(u.div(o));const l=Gn(1,zn(1,s.mul(o.sub(u)).add(1)));return la(e,Ii(u),l)})).setLayout({name:"neutralToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]});class iy extends Ms{static get type(){return"CodeNode"}constructor(e="",t=[],r=""){super("code"),this.isCodeNode=!0,this.code=e,this.includes=t,this.language=r}isGlobal(){return!0}setIncludes(e){return this.includes=e,this}getIncludes(){return this.includes}generate(e){const t=this.getIncludes(e);for(const r of t)r.build(e);const r=e.getCodeFromNode(this,this.getNodeType(e));return r.code=this.code,r.code}serialize(e){super.serialize(e),e.code=this.code,e.language=this.language}deserialize(e){super.deserialize(e),this.code=e.code,this.language=e.language}}const ny=bi(iy);class oy extends iy{static get type(){return"FunctionNode"}constructor(e="",t=[],r=""){super(e,t,r)}getNodeType(e){return this.getNodeFunction(e).type}getInputs(e){return this.getNodeFunction(e).inputs}getNodeFunction(e){const t=e.getDataFromNode(this);let r=t.nodeFunction;return void 0===r&&(r=e.parser.parseFunction(this.code),t.nodeFunction=r),r}generate(e,t){super.generate(e);const r=this.getNodeFunction(e),s=r.name,i=r.type,n=e.getCodeFromNode(this,i);""!==s&&(n.name=s);const o=e.getPropertyName(n),a=this.getNodeFunction(e).getCode(o);return n.code=a+"\n","property"===t?o:e.format(`${o}()`,i,t)}}const ay=(e,t=[],r="")=>{for(let e=0;es.call(...e);return i.functionNode=s,i};class uy extends Ms{static get type(){return"ScriptableValueNode"}constructor(e=null){super(),this._value=e,this._cache=null,this.inputType=null,this.outputType=null,this.events=new o,this.isScriptableValueNode=!0}get isScriptableOutputNode(){return null!==this.outputType}set value(e){this._value!==e&&(this._cache&&"URL"===this.inputType&&this.value.value instanceof ArrayBuffer&&(URL.revokeObjectURL(this._cache),this._cache=null),this._value=e,this.events.dispatchEvent({type:"change"}),this.refresh())}get value(){return this._value}refresh(){this.events.dispatchEvent({type:"refresh"})}getValue(){const e=this.value;if(e&&null===this._cache&&"URL"===this.inputType&&e.value instanceof ArrayBuffer)this._cache=URL.createObjectURL(new Blob([e.value]));else if(e&&null!==e.value&&void 0!==e.value&&(("URL"===this.inputType||"String"===this.inputType)&&"string"==typeof e.value||"Number"===this.inputType&&"number"==typeof e.value||"Vector2"===this.inputType&&e.value.isVector2||"Vector3"===this.inputType&&e.value.isVector3||"Vector4"===this.inputType&&e.value.isVector4||"Color"===this.inputType&&e.value.isColor||"Matrix3"===this.inputType&&e.value.isMatrix3||"Matrix4"===this.inputType&&e.value.isMatrix4))return e.value;return this._cache||e}getNodeType(e){return this.value&&this.value.isNode?this.value.getNodeType(e):"float"}setup(){return this.value&&this.value.isNode?this.value:Ci()}serialize(e){super.serialize(e),null!==this.value?"ArrayBuffer"===this.inputType?e.value=xs(this.value):e.value=this.value?this.value.toJSON(e.meta).uuid:null:e.value=null,e.inputType=this.inputType,e.outputType=this.outputType}deserialize(e){super.deserialize(e);let t=null;null!==e.value&&(t="ArrayBuffer"===e.inputType?bs(e.value):"Texture"===e.inputType?e.meta.textures[e.value]:e.meta.nodes[e.value]||null),this.value=t,this.inputType=e.inputType,this.outputType=e.outputType}}const ly=bi(uy);class dy extends Map{get(e,t=null,...r){if(this.has(e))return super.get(e);if(null!==t){const s=t(...r);return this.set(e,s),s}}}class cy{constructor(e){this.scriptableNode=e}get parameters(){return this.scriptableNode.parameters}get layout(){return this.scriptableNode.getLayout()}getInputLayout(e){return this.scriptableNode.getInputLayout(e)}get(e){const t=this.parameters[e];return t?t.getValue():null}}const hy=new dy;class py extends Ms{static get type(){return"ScriptableNode"}constructor(e=null,t={}){super(),this.codeNode=e,this.parameters=t,this._local=new dy,this._output=ly(),this._outputs={},this._source=this.source,this._method=null,this._object=null,this._value=null,this._needsOutputUpdate=!0,this.onRefresh=this.onRefresh.bind(this),this.isScriptableNode=!0}get source(){return this.codeNode?this.codeNode.code:""}setLocal(e,t){return this._local.set(e,t)}getLocal(e){return this._local.get(e)}onRefresh(){this._refresh()}getInputLayout(e){for(const t of this.getLayout())if(t.inputType&&(t.id===e||t.name===e))return t}getOutputLayout(e){for(const t of this.getLayout())if(t.outputType&&(t.id===e||t.name===e))return t}setOutput(e,t){const r=this._outputs;return void 0===r[e]?r[e]=ly(t):r[e].value=t,this}getOutput(e){return this._outputs[e]}getParameter(e){return this.parameters[e]}setParameter(e,t){const r=this.parameters;return t&&t.isScriptableNode?(this.deleteParameter(e),r[e]=t,r[e].getDefaultOutput().events.addEventListener("refresh",this.onRefresh)):t&&t.isScriptableValueNode?(this.deleteParameter(e),r[e]=t,r[e].events.addEventListener("refresh",this.onRefresh)):void 0===r[e]?(r[e]=ly(t),r[e].events.addEventListener("refresh",this.onRefresh)):r[e].value=t,this}getValue(){return this.getDefaultOutput().getValue()}deleteParameter(e){let t=this.parameters[e];return t&&(t.isScriptableNode&&(t=t.getDefaultOutput()),t.events.removeEventListener("refresh",this.onRefresh)),this}clearParameters(){for(const e of Object.keys(this.parameters))this.deleteParameter(e);return this.needsUpdate=!0,this}call(e,...t){const r=this.getObject()[e];if("function"==typeof r)return r(...t)}async callAsync(e,...t){const r=this.getObject()[e];if("function"==typeof r)return"AsyncFunction"===r.constructor.name?await r(...t):r(...t)}getNodeType(e){return this.getDefaultOutputNode().getNodeType(e)}refresh(e=null){null!==e?this.getOutput(e).refresh():this._refresh()}getObject(){if(this.needsUpdate&&this.dispose(),null!==this._object)return this._object;const e=new cy(this),t=hy.get("THREE"),r=hy.get("TSL"),s=this.getMethod(this.codeNode),i=[e,this._local,hy,()=>this.refresh(),(e,t)=>this.setOutput(e,t),t,r];this._object=s(...i);const n=this._object.layout;if(n&&(!1===n.cache&&this._local.clear(),this._output.outputType=n.outputType||null,Array.isArray(n.elements)))for(const e of n.elements){const t=e.id||e.name;e.inputType&&(void 0===this.getParameter(t)&&this.setParameter(t,null),this.getParameter(t).inputType=e.inputType),e.outputType&&(void 0===this.getOutput(t)&&this.setOutput(t,null),this.getOutput(t).outputType=e.outputType)}return this._object}deserialize(e){super.deserialize(e);for(const e in this.parameters){let t=this.parameters[e];t.isScriptableNode&&(t=t.getDefaultOutput()),t.events.addEventListener("refresh",this.onRefresh)}}getLayout(){return this.getObject().layout}getDefaultOutputNode(){const e=this.getDefaultOutput().value;return e&&e.isNode?e:Ci()}getDefaultOutput(){return this._exec()._output}getMethod(){if(this.needsUpdate&&this.dispose(),null!==this._method)return this._method;const e=["layout","init","main","dispose"].join(", "),t="\nreturn { ...output, "+e+" };",r="var "+e+"; var output = {};\n"+this.codeNode.code+t;return this._method=new Function(...["parameters","local","global","refresh","setOutput","THREE","TSL"],r),this._method}dispose(){null!==this._method&&(this._object&&"function"==typeof this._object.dispose&&this._object.dispose(),this._method=null,this._object=null,this._source=null,this._value=null,this._needsOutputUpdate=!0,this._output.value=null,this._outputs={})}setup(){return this.getDefaultOutputNode()}getCacheKey(e){const t=[us(this.source),this.getDefaultOutputNode().getCacheKey(e)];for(const r in this.parameters)t.push(this.parameters[r].getCacheKey(e));return ls(t)}set needsUpdate(e){!0===e&&this.dispose()}get needsUpdate(){return this.source!==this._source}_exec(){return null===this.codeNode||(!0===this._needsOutputUpdate&&(this._value=this.call("main"),this._needsOutputUpdate=!1),this._output.value=this._value),this}_refresh(){this.needsUpdate=!0,this._exec(),this._output.refresh()}}const gy=bi(py);function my(e){let t;const r=e.context.getViewZ;return void 0!==r&&(t=r(this)),(t||Zu.z).negate()}const fy=_i((([e,t],r)=>{const s=my(r);return pa(e,t,s)})),yy=_i((([e],t)=>{const r=my(t);return e.mul(e,r,r).negate().exp().oneMinus()})),xy=_i((([e,t])=>Oi(t.toFloat().mix(Sn.rgb,e.toVec3()),Sn.a)));let by=null,Ty=null;class _y extends Ms{static get type(){return"RangeNode"}constructor(e=Ci(),t=Ci()){super(),this.minNode=e,this.maxNode=t}getVectorLength(e){const t=e.getTypeLength(fs(this.minNode.value)),r=e.getTypeLength(fs(this.maxNode.value));return t>r?t:r}getNodeType(e){return e.object.count>1?e.getTypeFromLength(this.getVectorLength(e)):"float"}setup(e){const t=e.object;let r=null;if(t.count>1){const i=this.minNode.value,n=this.maxNode.value,o=e.getTypeLength(fs(i)),u=e.getTypeLength(fs(n));by=by||new s,Ty=Ty||new s,by.setScalar(0),Ty.setScalar(0),1===o?by.setScalar(i):i.isColor?by.set(i.r,i.g,i.b,1):by.set(i.x,i.y,i.z||0,i.w||0),1===u?Ty.setScalar(n):n.isColor?Ty.set(n.r,n.g,n.b,1):Ty.set(n.x,n.y,n.z||0,n.w||0);const l=4,d=l*t.count,c=new Float32Array(d);for(let e=0;efi(new Ny(e,t)),Ay=Sy("numWorkgroups","uvec3"),Ry=Sy("workgroupId","uvec3"),Cy=Sy("localId","uvec3"),Ey=Sy("subgroupSize","uint");const wy=bi(class extends Ms{constructor(e){super(),this.scope=e}generate(e){const{scope:t}=this,{renderer:r}=e;!0===r.backend.isWebGLBackend?e.addFlowCode(`\t// ${t}Barrier \n`):e.addLineFlowCode(`${t}Barrier()`,this)}});class My extends Bs{constructor(e,t){super(e,t),this.isWorkgroupInfoElementNode=!0}generate(e,t){let r;const s=e.context.assign;if(r=super.generate(e),!0!==s){const s=this.getNodeType(e);r=e.format(r,s,t)}return r}}class By extends Ms{constructor(e,t,r=0){super(t),this.bufferType=t,this.bufferCount=r,this.isWorkgroupInfoNode=!0,this.scope=e}label(e){return this.name=e,this}setScope(e){return this.scope=e,this}getInputType(){return`${this.scope}Array`}element(e){return fi(new My(this,e))}generate(e){return e.getScopedArray(this.name||`${this.scope}Array_${this.id}`,this.scope.toLowerCase(),this.bufferType,this.bufferCount)}}class Uy extends Fs{static get type(){return"AtomicFunctionNode"}constructor(e,t,r,s=null){super("uint"),this.method=e,this.pointerNode=t,this.valueNode=r,this.storeNode=s}getInputType(e){return this.pointerNode.getNodeType(e)}getNodeType(e){return this.getInputType(e)}generate(e){const t=this.method,r=this.getNodeType(e),s=this.getInputType(e),i=this.pointerNode,n=this.valueNode,o=[];o.push(`&${i.build(e,s)}`),o.push(n.build(e,s));const a=`${e.getMethod(t,r)}( ${o.join(", ")} )`;if(null!==this.storeNode){const t=this.storeNode.build(e,s);e.addLineFlowCode(`${t} = ${a}`,this)}else e.addLineFlowCode(a,this)}}Uy.ATOMIC_LOAD="atomicLoad",Uy.ATOMIC_STORE="atomicStore",Uy.ATOMIC_ADD="atomicAdd",Uy.ATOMIC_SUB="atomicSub",Uy.ATOMIC_MAX="atomicMax",Uy.ATOMIC_MIN="atomicMin",Uy.ATOMIC_AND="atomicAnd",Uy.ATOMIC_OR="atomicOr",Uy.ATOMIC_XOR="atomicXor";const Fy=bi(Uy),Py=(e,t,r,s=null)=>{const i=Fy(e,t,r,s);return i.append(),i};let Iy;function Ly(e){Iy=Iy||new WeakMap;let t=Iy.get(e);return void 0===t&&Iy.set(e,t={}),t}function Vy(e){const t=Ly(e);return t.shadowMatrix||(t.shadowMatrix=tn("mat4").setGroup(Zi).onRenderUpdate((()=>(!0!==e.castShadow&&e.shadow.updateMatrices(e),e.shadow.matrix))))}function Dy(e){const t=Ly(e);if(void 0===t.projectionUV){const r=Vy(e).mul(Yu);t.projectionUV=r.xyz.div(r.w)}return t.projectionUV}function Oy(e){const t=Ly(e);return t.position||(t.position=tn(new r).setGroup(Zi).onRenderUpdate(((t,r)=>r.value.setFromMatrixPosition(e.matrixWorld))))}function Gy(e){const t=Ly(e);return t.targetPosition||(t.targetPosition=tn(new r).setGroup(Zi).onRenderUpdate(((t,r)=>r.value.setFromMatrixPosition(e.target.matrixWorld))))}function ky(e){const t=Ly(e);return t.viewPosition||(t.viewPosition=tn(new r).setGroup(Zi).onRenderUpdate((({camera:t},s)=>{s.value=s.value||new r,s.value.setFromMatrixPosition(e.matrixWorld),s.value.applyMatrix4(t.matrixWorldInverse)})))}const zy=e=>Au.transformDirection(Oy(e).sub(Gy(e))),$y=(e,t)=>{for(const r of t)if(r.isAnalyticLightNode&&r.light.id===e)return r;return null},Hy=new WeakMap;class Wy extends Ms{static get type(){return"LightsNode"}constructor(){super("vec3"),this.totalDiffuseNode=Ii().toVar("totalDiffuse"),this.totalSpecularNode=Ii().toVar("totalSpecular"),this.outgoingLightNode=Ii().toVar("outgoingLight"),this._lights=[],this._lightNodes=null,this._lightNodesHash=null,this.global=!0}customCacheKey(){const e=[],t=this._lights;for(let r=0;re.sort(((e,t)=>e.id-t.id)))(this._lights),i=e.renderer.library;for(const e of s)if(e.isNode)t.push(fi(e));else{let s=null;if(null!==r&&(s=$y(e.id,r)),null===s){const r=i.getLightNodeClass(e.constructor);if(null===r){console.warn(`LightsNode.setupNodeLights: Light node not found for ${e.constructor.name}`);continue}let s=null;Hy.has(e)?s=Hy.get(e):(s=fi(new r(e)),Hy.set(e,s)),t.push(s)}}this._lightNodes=t}setupLights(e,t){for(const r of t)r.build(e)}setup(e){null===this._lightNodes&&this.setupLightsNode(e);const t=e.context,r=t.lightingModel;let s=this.outgoingLightNode;if(r){const{_lightNodes:i,totalDiffuseNode:n,totalSpecularNode:o}=this;t.outgoingLight=s;const a=e.addStack();e.getDataFromNode(this).nodes=a.nodes,r.start(t,a,e),this.setupLights(e,i),r.indirect(t,a,e);const{backdrop:u,backdropAlpha:l}=t,{directDiffuse:d,directSpecular:c,indirectDiffuse:h,indirectSpecular:p}=t.reflectedLight;let g=d.add(h);null!==u&&(g=Ii(null!==l?l.mix(g,u):u),t.material.transparent=!0),n.assign(g),o.assign(c.add(p)),s.assign(n.add(o)),r.finish(t,a,e),s=s.bypass(e.removeStack())}return s}setLights(e){return this._lights=e,this._lightNodes=null,this._lightNodesHash=null,this}getLights(){return this._lights}get hasLights(){return this._lights.length>0}}class jy extends Ms{static get type(){return"ShadowBaseNode"}constructor(e){super(),this.light=e,this.updateBeforeType=vs.RENDER,this.isShadowBaseNode=!0}setupShadowPosition({material:e}){qy.assign(e.shadowPositionNode||Yu)}dispose(){this.updateBeforeType=vs.NONE}}const qy=Ii().toVar("shadowWorldPosition"),Ky=new WeakMap,Xy=_i((([e,t,r])=>{let s=Yu.sub(e).length();return s=s.sub(t).div(r.sub(t)),s=s.saturate(),s})),Yy=e=>{let t=Ky.get(e);if(void 0===t){const r=e.isPointLight?(e=>{const t=e.shadow.camera,r=Cl("near","float",t).setGroup(Zi),s=Cl("far","float",t).setGroup(Zi),i=Uu(e);return Xy(i,r,s)})(e):null;t=new Yc,t.colorNode=Oi(0,0,0,1),t.depthNode=r,t.isShadowNodeMaterial=!0,t.name="ShadowMaterial",Ky.set(e,t)}return t},Qy=_i((({depthTexture:e,shadowCoord:t})=>bu(e,t.xy).compare(t.z))),Zy=_i((({depthTexture:e,shadowCoord:t,shadow:r})=>{const s=(t,r)=>bu(e,t).compare(r),i=Cl("mapSize","vec2",r).setGroup(Zi),n=Cl("radius","float",r).setGroup(Zi),o=Bi(1).div(i),a=o.x.negate().mul(n),u=o.y.negate().mul(n),l=o.x.mul(n),d=o.y.mul(n),c=a.div(2),h=u.div(2),p=l.div(2),g=d.div(2);return On(s(t.xy.add(Bi(a,u)),t.z),s(t.xy.add(Bi(0,u)),t.z),s(t.xy.add(Bi(l,u)),t.z),s(t.xy.add(Bi(c,h)),t.z),s(t.xy.add(Bi(0,h)),t.z),s(t.xy.add(Bi(p,h)),t.z),s(t.xy.add(Bi(a,0)),t.z),s(t.xy.add(Bi(c,0)),t.z),s(t.xy,t.z),s(t.xy.add(Bi(p,0)),t.z),s(t.xy.add(Bi(l,0)),t.z),s(t.xy.add(Bi(c,g)),t.z),s(t.xy.add(Bi(0,g)),t.z),s(t.xy.add(Bi(p,g)),t.z),s(t.xy.add(Bi(a,d)),t.z),s(t.xy.add(Bi(0,d)),t.z),s(t.xy.add(Bi(l,d)),t.z)).mul(1/17)})),Jy=_i((({depthTexture:e,shadowCoord:t,shadow:r})=>{const s=(t,r)=>bu(e,t).compare(r),i=Cl("mapSize","vec2",r).setGroup(Zi),n=Bi(1).div(i),o=n.x,a=n.y,u=t.xy,l=Ro(u.mul(i).add(.5));return u.subAssign(l.mul(n)),On(s(u,t.z),s(u.add(Bi(o,0)),t.z),s(u.add(Bi(0,a)),t.z),s(u.add(n),t.z),la(s(u.add(Bi(o.negate(),0)),t.z),s(u.add(Bi(o.mul(2),0)),t.z),l.x),la(s(u.add(Bi(o.negate(),a)),t.z),s(u.add(Bi(o.mul(2),a)),t.z),l.x),la(s(u.add(Bi(0,a.negate())),t.z),s(u.add(Bi(0,a.mul(2))),t.z),l.y),la(s(u.add(Bi(o,a.negate())),t.z),s(u.add(Bi(o,a.mul(2))),t.z),l.y),la(la(s(u.add(Bi(o.negate(),a.negate())),t.z),s(u.add(Bi(o.mul(2),a.negate())),t.z),l.x),la(s(u.add(Bi(o.negate(),a.mul(2))),t.z),s(u.add(Bi(o.mul(2),a.mul(2))),t.z),l.x),l.y)).mul(1/9)})),ex=_i((({depthTexture:e,shadowCoord:t})=>{const r=Ci(1).toVar(),s=bu(e).sample(t.xy).rg,i=Yo(t.z,s.x);return Si(i.notEqual(Ci(1)),(()=>{const e=t.z.sub(s.x),n=Ko(0,s.y.mul(s.y));let o=n.div(n.add(e.mul(e)));o=da(Gn(o,.3).div(.95-.3)),r.assign(da(Ko(i,o)))})),r})),tx=_i((({samples:e,radius:t,size:r,shadowPass:s})=>{const i=Ci(0).toVar(),n=Ci(0).toVar(),o=e.lessThanEqual(Ci(1)).select(Ci(0),Ci(2).div(e.sub(1))),a=e.lessThanEqual(Ci(1)).select(Ci(0),Ci(-1));ic({start:Ei(0),end:Ei(e),type:"int",condition:"<"},(({i:e})=>{const u=a.add(Ci(e).mul(o)),l=s.sample(On(_c.xy,Bi(0,u).mul(t)).div(r)).x;i.addAssign(l),n.addAssign(l.mul(l))})),i.divAssign(e),n.divAssign(e);const u=_o(n.sub(i.mul(i)));return Bi(i,u)})),rx=_i((({samples:e,radius:t,size:r,shadowPass:s})=>{const i=Ci(0).toVar(),n=Ci(0).toVar(),o=e.lessThanEqual(Ci(1)).select(Ci(0),Ci(2).div(e.sub(1))),a=e.lessThanEqual(Ci(1)).select(Ci(0),Ci(-1));ic({start:Ei(0),end:Ei(e),type:"int",condition:"<"},(({i:e})=>{const u=a.add(Ci(e).mul(o)),l=s.sample(On(_c.xy,Bi(u,0).mul(t)).div(r));i.addAssign(l.x),n.addAssign(On(l.y.mul(l.y),l.x.mul(l.x)))})),i.divAssign(e),n.divAssign(e);const u=_o(n.sub(i.mul(i)));return Bi(i,u)})),sx=[Qy,Zy,Jy,ex],ix=new Jm;class nx extends jy{static get type(){return"ShadowNode"}constructor(e,t=null){super(e),this.shadow=t||e.shadow,this.shadowMap=null,this.vsmShadowMapVertical=null,this.vsmShadowMapHorizontal=null,this.vsmMaterialVertical=null,this.vsmMaterialHorizontal=null,this._node=null,this.isShadowNode=!0}setupShadowFilter(e,{filterFn:t,depthTexture:r,shadowCoord:s,shadow:i}){const n=s.x.greaterThanEqual(0).and(s.x.lessThanEqual(1)).and(s.y.greaterThanEqual(0)).and(s.y.lessThanEqual(1)).and(s.z.lessThanEqual(1)),o=t({depthTexture:r,shadowCoord:s,shadow:i});return n.select(o,Ci(1))}setupShadowCoord(e,t){const{shadow:r}=this,{renderer:s}=e,i=Cl("bias","float",r).setGroup(Zi);let n,o=t;if(r.camera.isOrthographicCamera||!0!==s.logarithmicDepthBuffer)o=o.xyz.div(o.w),n=o.z,s.coordinateSystem===l&&(n=n.mul(2).sub(1));else{const e=o.w;o=o.xy.div(e);const t=Cl("near","float",r.camera).setGroup(Zi),s=Cl("far","float",r.camera).setGroup(Zi);n=Gc(e.negate(),t,s)}return o=Ii(o.x,o.y.oneMinus(),n.add(i)),o}getShadowFilterFn(e){return sx[e]}setupShadow(e){const{renderer:t}=e,{light:r,shadow:s}=this,i=t.shadowMap.type,n=new B(s.mapSize.width,s.mapSize.height);n.compareFunction=Re;const o=e.createRenderTarget(s.mapSize.width,s.mapSize.height);if(o.depthTexture=n,s.camera.updateProjectionMatrix(),i===Ce){n.compareFunction=null,this.vsmShadowMapVertical=e.createRenderTarget(s.mapSize.width,s.mapSize.height,{format:Ee,type:ye}),this.vsmShadowMapHorizontal=e.createRenderTarget(s.mapSize.width,s.mapSize.height,{format:Ee,type:ye});const t=bu(n),r=bu(this.vsmShadowMapVertical.texture),i=Cl("blurSamples","float",s).setGroup(Zi),o=Cl("radius","float",s).setGroup(Zi),a=Cl("mapSize","vec2",s).setGroup(Zi);let u=this.vsmMaterialVertical||(this.vsmMaterialVertical=new Yc);u.fragmentNode=tx({samples:i,radius:o,size:a,shadowPass:t}).context(e.getSharedContext()),u.name="VSMVertical",u=this.vsmMaterialHorizontal||(this.vsmMaterialHorizontal=new Yc),u.fragmentNode=rx({samples:i,radius:o,size:a,shadowPass:r}).context(e.getSharedContext()),u.name="VSMHorizontal"}const a=Cl("intensity","float",s).setGroup(Zi),u=Cl("normalBias","float",s).setGroup(Zi),l=Vy(r).mul(qy.add(ll.mul(u))),d=this.setupShadowCoord(e,l),c=s.filterNode||this.getShadowFilterFn(t.shadowMap.type)||null;if(null===c)throw new Error("THREE.WebGPURenderer: Shadow map type not supported yet.");const h=i===Ce?this.vsmShadowMapHorizontal.texture:n,p=this.setupShadowFilter(e,{filterFn:c,shadowTexture:o.texture,depthTexture:h,shadowCoord:d,shadow:s}),g=bu(o.texture,d),m=la(1,p.rgb.mix(g,1),a.mul(g.a)).toVar();return this.shadowMap=o,this.shadow.map=o,m}setup(e){if(!1!==e.renderer.shadowMap.enabled)return _i((()=>{let t=this._node;return this.setupShadowPosition(e),null===t&&(this._node=t=this.setupShadow(e)),e.material.shadowNode&&console.warn('THREE.NodeMaterial: ".shadowNode" is deprecated. Use ".castShadowNode" instead.'),e.material.receivedShadowNode&&(t=e.material.receivedShadowNode(t)),t}))()}renderShadow(e){const{shadow:t,shadowMap:r,light:s}=this,{renderer:i,scene:n}=e;t.updateMatrices(s),r.setSize(t.mapSize.width,t.mapSize.height),i.render(n,t.camera)}updateShadow(e){const{shadowMap:t,light:r,shadow:s}=this,{renderer:i,scene:n,camera:o}=e,a=i.shadowMap.type,u=t.depthTexture.version;this._depthVersionCached=u;const l=n.overrideMaterial;n.overrideMaterial=Yy(r),s.camera.layers.mask=o.layers.mask;const d=i.getRenderTarget(),c=i.getRenderObjectFunction(),h=i.getMRT();i.setMRT(null),i.setRenderObjectFunction(((e,t,r,n,u,l,...d)=>{(!0===e.castShadow||e.receiveShadow&&a===Ce)&&(e.onBeforeShadow(i,e,o,s.camera,n,t.overrideMaterial,l),i.renderObject(e,t,r,n,u,l,...d),e.onAfterShadow(i,e,o,s.camera,n,t.overrideMaterial,l))})),i.setRenderTarget(t),this.renderShadow(e),i.setRenderObjectFunction(c),!0!==r.isPointLight&&a===Ce&&this.vsmPass(i),i.setRenderTarget(d),i.setMRT(h),n.overrideMaterial=l}vsmPass(e){const{shadow:t}=this;this.vsmShadowMapVertical.setSize(t.mapSize.width,t.mapSize.height),this.vsmShadowMapHorizontal.setSize(t.mapSize.width,t.mapSize.height),e.setRenderTarget(this.vsmShadowMapVertical),ix.material=this.vsmMaterialVertical,ix.render(e),e.setRenderTarget(this.vsmShadowMapHorizontal),ix.material=this.vsmMaterialHorizontal,ix.render(e)}dispose(){this.shadowMap.dispose(),this.shadowMap=null,null!==this.vsmShadowMapVertical&&(this.vsmShadowMapVertical.dispose(),this.vsmShadowMapVertical=null,this.vsmMaterialVertical.dispose(),this.vsmMaterialVertical=null),null!==this.vsmShadowMapHorizontal&&(this.vsmShadowMapHorizontal.dispose(),this.vsmShadowMapHorizontal=null,this.vsmMaterialHorizontal.dispose(),this.vsmMaterialHorizontal=null),super.dispose()}updateBefore(e){const{shadow:t}=this;(t.needsUpdate||t.autoUpdate)&&(this.updateShadow(e),this.shadowMap.depthTexture.version===this._depthVersionCached&&(t.needsUpdate=!1))}}const ox=(e,t)=>fi(new nx(e,t));class ax extends cc{static get type(){return"AnalyticLightNode"}constructor(t=null){super(),this.light=t,this.color=new e,this.colorNode=t&&t.colorNode||tn(this.color).setGroup(Zi),this.baseColorNode=null,this.shadowNode=null,this.shadowColorNode=null,this.isAnalyticLightNode=!0,this.updateType=vs.FRAME}customCacheKey(){return ds(this.light.id,this.light.castShadow?1:0)}getHash(){return this.light.uuid}setupShadowNode(){return ox(this.light)}setupShadow(e){const{renderer:t}=e;if(!1===t.shadowMap.enabled)return;let r=this.shadowColorNode;if(null===r){const t=this.light.shadow.shadowNode;let s;s=void 0!==t?fi(t):this.setupShadowNode(e),this.shadowNode=s,this.shadowColorNode=r=this.colorNode.mul(s),this.baseColorNode=this.colorNode}this.colorNode=r}setup(e){this.colorNode=this.baseColorNode||this.colorNode,this.light.castShadow?e.object.receiveShadow&&this.setupShadow(e):null!==this.shadowNode&&(this.shadowNode.dispose(),this.shadowNode=null,this.shadowColorNode=null)}update(){const{light:e}=this;this.color.copy(e.color).multiplyScalar(e.intensity)}}const ux=_i((e=>{const{lightDistance:t,cutoffDistance:r,decayExponent:s}=e,i=t.pow(s).max(.01).reciprocal();return r.greaterThan(0).select(i.mul(t.div(r).pow4().oneMinus().clamp().pow2()),i)})),lx=new e,dx=_i((([e,t])=>{const r=e.toVar(),s=Fo(r),i=zn(1,Ko(s.x,Ko(s.y,s.z)));s.mulAssign(i),r.mulAssign(i.mul(t.mul(2).oneMinus()));const n=Bi(r.xy).toVar(),o=t.mul(1.5).oneMinus();return Si(s.z.greaterThanEqual(o),(()=>{Si(r.z.greaterThan(0),(()=>{n.x.assign(Gn(4,r.x))}))})).ElseIf(s.x.greaterThanEqual(o),(()=>{const e=Po(r.x);n.x.assign(r.z.mul(e).add(e.mul(2)))})).ElseIf(s.y.greaterThanEqual(o),(()=>{const e=Po(r.y);n.x.assign(r.x.add(e.mul(2)).add(2)),n.y.assign(r.z.mul(e).sub(2))})),Bi(.125,.25).mul(n).add(Bi(.375,.75)).flipY()})).setLayout({name:"cubeToUV",type:"vec2",inputs:[{name:"pos",type:"vec3"},{name:"texelSizeY",type:"float"}]}),cx=_i((({depthTexture:e,bd3D:t,dp:r,texelSize:s})=>bu(e,dx(t,s.y)).compare(r))),hx=_i((({depthTexture:e,bd3D:t,dp:r,texelSize:s,shadow:i})=>{const n=Cl("radius","float",i).setGroup(Zi),o=Bi(-1,1).mul(n).mul(s.y);return bu(e,dx(t.add(o.xyy),s.y)).compare(r).add(bu(e,dx(t.add(o.yyy),s.y)).compare(r)).add(bu(e,dx(t.add(o.xyx),s.y)).compare(r)).add(bu(e,dx(t.add(o.yyx),s.y)).compare(r)).add(bu(e,dx(t,s.y)).compare(r)).add(bu(e,dx(t.add(o.xxy),s.y)).compare(r)).add(bu(e,dx(t.add(o.yxy),s.y)).compare(r)).add(bu(e,dx(t.add(o.xxx),s.y)).compare(r)).add(bu(e,dx(t.add(o.yxx),s.y)).compare(r)).mul(1/9)})),px=_i((({filterFn:e,depthTexture:t,shadowCoord:r,shadow:s})=>{const i=r.xyz.toVar(),n=i.length(),o=tn("float").setGroup(Zi).onRenderUpdate((()=>s.camera.near)),a=tn("float").setGroup(Zi).onRenderUpdate((()=>s.camera.far)),u=Cl("bias","float",s).setGroup(Zi),l=tn(s.mapSize).setGroup(Zi),d=Ci(1).toVar();return Si(n.sub(a).lessThanEqual(0).and(n.sub(o).greaterThanEqual(0)),(()=>{const r=n.sub(o).div(a.sub(o)).toVar();r.addAssign(u);const c=i.normalize(),h=Bi(1).div(l.mul(Bi(4,2)));d.assign(e({depthTexture:t,bd3D:c,dp:r,texelSize:h,shadow:s}))})),d})),gx=new s,mx=new t,fx=new t;class yx extends nx{static get type(){return"PointShadowNode"}constructor(e,t=null){super(e,t)}getShadowFilterFn(e){return e===we?cx:hx}setupShadowCoord(e,t){return t}setupShadowFilter(e,{filterFn:t,shadowTexture:r,depthTexture:s,shadowCoord:i,shadow:n}){return px({filterFn:t,shadowTexture:r,depthTexture:s,shadowCoord:i,shadow:n})}renderShadow(e){const{shadow:t,shadowMap:r,light:s}=this,{renderer:i,scene:n}=e,o=t.getFrameExtents();fx.copy(t.mapSize),fx.multiply(o),r.setSize(fx.width,fx.height),mx.copy(t.mapSize);const a=i.autoClear,u=i.getClearColor(lx),l=i.getClearAlpha();i.autoClear=!1,i.setClearColor(t.clearColor,t.clearAlpha),i.clear();const d=t.getViewportCount();for(let e=0;e{const n=i.context.lightingModel,o=t.sub(Zu),a=o.normalize(),u=o.length(),l=ux({lightDistance:u,cutoffDistance:r,decayExponent:s}),d=e.mul(l),c=i.context.reflectedLight;n.direct({lightDirection:a,lightColor:d,reflectedLight:c},i.stack,i)}));class bx extends ax{static get type(){return"PointLightNode"}constructor(e=null){super(e),this.cutoffDistanceNode=tn(0).setGroup(Zi),this.decayExponentNode=tn(2).setGroup(Zi)}update(e){const{light:t}=this;super.update(e),this.cutoffDistanceNode.value=t.distance,this.decayExponentNode.value=t.decay}setupShadowNode(){return((e,t)=>fi(new yx(e,t)))(this.light)}setup(e){super.setup(e),xx({color:this.colorNode,lightViewPosition:ky(this.light),cutoffDistance:this.cutoffDistanceNode,decayExponent:this.decayExponentNode}).append()}}const Tx=_i((([e=t()])=>{const t=e.mul(2),r=t.x.floor(),s=t.y.floor();return r.add(s).mod(2).sign()})),_x=_i((([e,t,r])=>{const s=Ci(r).toVar(),i=Ci(t).toVar(),n=Mi(e).toVar();return Ta(n,i,s)})).setLayout({name:"mx_select",type:"float",inputs:[{name:"b",type:"bool"},{name:"t",type:"float"},{name:"f",type:"float"}]}),vx=_i((([e,t])=>{const r=Mi(t).toVar(),s=Ci(e).toVar();return Ta(r,s.negate(),s)})).setLayout({name:"mx_negate_if",type:"float",inputs:[{name:"val",type:"float"},{name:"b",type:"bool"}]}),Nx=_i((([e])=>{const t=Ci(e).toVar();return Ei(No(t))})).setLayout({name:"mx_floor",type:"int",inputs:[{name:"x",type:"float"}]}),Sx=_i((([e,t])=>{const r=Ci(e).toVar();return t.assign(Nx(r)),r.sub(Ci(t))})),Ax=vm([_i((([e,t,r,s,i,n])=>{const o=Ci(n).toVar(),a=Ci(i).toVar(),u=Ci(s).toVar(),l=Ci(r).toVar(),d=Ci(t).toVar(),c=Ci(e).toVar(),h=Ci(Gn(1,a)).toVar();return Gn(1,o).mul(c.mul(h).add(d.mul(a))).add(o.mul(l.mul(h).add(u.mul(a))))})).setLayout({name:"mx_bilerp_0",type:"float",inputs:[{name:"v0",type:"float"},{name:"v1",type:"float"},{name:"v2",type:"float"},{name:"v3",type:"float"},{name:"s",type:"float"},{name:"t",type:"float"}]}),_i((([e,t,r,s,i,n])=>{const o=Ci(n).toVar(),a=Ci(i).toVar(),u=Ii(s).toVar(),l=Ii(r).toVar(),d=Ii(t).toVar(),c=Ii(e).toVar(),h=Ci(Gn(1,a)).toVar();return Gn(1,o).mul(c.mul(h).add(d.mul(a))).add(o.mul(l.mul(h).add(u.mul(a))))})).setLayout({name:"mx_bilerp_1",type:"vec3",inputs:[{name:"v0",type:"vec3"},{name:"v1",type:"vec3"},{name:"v2",type:"vec3"},{name:"v3",type:"vec3"},{name:"s",type:"float"},{name:"t",type:"float"}]})]),Rx=vm([_i((([e,t,r,s,i,n,o,a,u,l,d])=>{const c=Ci(d).toVar(),h=Ci(l).toVar(),p=Ci(u).toVar(),g=Ci(a).toVar(),m=Ci(o).toVar(),f=Ci(n).toVar(),y=Ci(i).toVar(),x=Ci(s).toVar(),b=Ci(r).toVar(),T=Ci(t).toVar(),_=Ci(e).toVar(),v=Ci(Gn(1,p)).toVar(),N=Ci(Gn(1,h)).toVar();return Ci(Gn(1,c)).toVar().mul(N.mul(_.mul(v).add(T.mul(p))).add(h.mul(b.mul(v).add(x.mul(p))))).add(c.mul(N.mul(y.mul(v).add(f.mul(p))).add(h.mul(m.mul(v).add(g.mul(p))))))})).setLayout({name:"mx_trilerp_0",type:"float",inputs:[{name:"v0",type:"float"},{name:"v1",type:"float"},{name:"v2",type:"float"},{name:"v3",type:"float"},{name:"v4",type:"float"},{name:"v5",type:"float"},{name:"v6",type:"float"},{name:"v7",type:"float"},{name:"s",type:"float"},{name:"t",type:"float"},{name:"r",type:"float"}]}),_i((([e,t,r,s,i,n,o,a,u,l,d])=>{const c=Ci(d).toVar(),h=Ci(l).toVar(),p=Ci(u).toVar(),g=Ii(a).toVar(),m=Ii(o).toVar(),f=Ii(n).toVar(),y=Ii(i).toVar(),x=Ii(s).toVar(),b=Ii(r).toVar(),T=Ii(t).toVar(),_=Ii(e).toVar(),v=Ci(Gn(1,p)).toVar(),N=Ci(Gn(1,h)).toVar();return Ci(Gn(1,c)).toVar().mul(N.mul(_.mul(v).add(T.mul(p))).add(h.mul(b.mul(v).add(x.mul(p))))).add(c.mul(N.mul(y.mul(v).add(f.mul(p))).add(h.mul(m.mul(v).add(g.mul(p))))))})).setLayout({name:"mx_trilerp_1",type:"vec3",inputs:[{name:"v0",type:"vec3"},{name:"v1",type:"vec3"},{name:"v2",type:"vec3"},{name:"v3",type:"vec3"},{name:"v4",type:"vec3"},{name:"v5",type:"vec3"},{name:"v6",type:"vec3"},{name:"v7",type:"vec3"},{name:"s",type:"float"},{name:"t",type:"float"},{name:"r",type:"float"}]})]),Cx=_i((([e,t,r])=>{const s=Ci(r).toVar(),i=Ci(t).toVar(),n=wi(e).toVar(),o=wi(n.bitAnd(wi(7))).toVar(),a=Ci(_x(o.lessThan(wi(4)),i,s)).toVar(),u=Ci(kn(2,_x(o.lessThan(wi(4)),s,i))).toVar();return vx(a,Mi(o.bitAnd(wi(1)))).add(vx(u,Mi(o.bitAnd(wi(2)))))})).setLayout({name:"mx_gradient_float_0",type:"float",inputs:[{name:"hash",type:"uint"},{name:"x",type:"float"},{name:"y",type:"float"}]}),Ex=_i((([e,t,r,s])=>{const i=Ci(s).toVar(),n=Ci(r).toVar(),o=Ci(t).toVar(),a=wi(e).toVar(),u=wi(a.bitAnd(wi(15))).toVar(),l=Ci(_x(u.lessThan(wi(8)),o,n)).toVar(),d=Ci(_x(u.lessThan(wi(4)),n,_x(u.equal(wi(12)).or(u.equal(wi(14))),o,i))).toVar();return vx(l,Mi(u.bitAnd(wi(1)))).add(vx(d,Mi(u.bitAnd(wi(2)))))})).setLayout({name:"mx_gradient_float_1",type:"float",inputs:[{name:"hash",type:"uint"},{name:"x",type:"float"},{name:"y",type:"float"},{name:"z",type:"float"}]}),wx=vm([Cx,Ex]),Mx=_i((([e,t,r])=>{const s=Ci(r).toVar(),i=Ci(t).toVar(),n=Vi(e).toVar();return Ii(wx(n.x,i,s),wx(n.y,i,s),wx(n.z,i,s))})).setLayout({name:"mx_gradient_vec3_0",type:"vec3",inputs:[{name:"hash",type:"uvec3"},{name:"x",type:"float"},{name:"y",type:"float"}]}),Bx=_i((([e,t,r,s])=>{const i=Ci(s).toVar(),n=Ci(r).toVar(),o=Ci(t).toVar(),a=Vi(e).toVar();return Ii(wx(a.x,o,n,i),wx(a.y,o,n,i),wx(a.z,o,n,i))})).setLayout({name:"mx_gradient_vec3_1",type:"vec3",inputs:[{name:"hash",type:"uvec3"},{name:"x",type:"float"},{name:"y",type:"float"},{name:"z",type:"float"}]}),Ux=vm([Mx,Bx]),Fx=_i((([e])=>{const t=Ci(e).toVar();return kn(.6616,t)})).setLayout({name:"mx_gradient_scale2d_0",type:"float",inputs:[{name:"v",type:"float"}]}),Px=_i((([e])=>{const t=Ci(e).toVar();return kn(.982,t)})).setLayout({name:"mx_gradient_scale3d_0",type:"float",inputs:[{name:"v",type:"float"}]}),Ix=vm([Fx,_i((([e])=>{const t=Ii(e).toVar();return kn(.6616,t)})).setLayout({name:"mx_gradient_scale2d_1",type:"vec3",inputs:[{name:"v",type:"vec3"}]})]),Lx=vm([Px,_i((([e])=>{const t=Ii(e).toVar();return kn(.982,t)})).setLayout({name:"mx_gradient_scale3d_1",type:"vec3",inputs:[{name:"v",type:"vec3"}]})]),Vx=_i((([e,t])=>{const r=Ei(t).toVar(),s=wi(e).toVar();return s.shiftLeft(r).bitOr(s.shiftRight(Ei(32).sub(r)))})).setLayout({name:"mx_rotl32",type:"uint",inputs:[{name:"x",type:"uint"},{name:"k",type:"int"}]}),Dx=_i((([e,t,r])=>{e.subAssign(r),e.bitXorAssign(Vx(r,Ei(4))),r.addAssign(t),t.subAssign(e),t.bitXorAssign(Vx(e,Ei(6))),e.addAssign(r),r.subAssign(t),r.bitXorAssign(Vx(t,Ei(8))),t.addAssign(e),e.subAssign(r),e.bitXorAssign(Vx(r,Ei(16))),r.addAssign(t),t.subAssign(e),t.bitXorAssign(Vx(e,Ei(19))),e.addAssign(r),r.subAssign(t),r.bitXorAssign(Vx(t,Ei(4))),t.addAssign(e)})),Ox=_i((([e,t,r])=>{const s=wi(r).toVar(),i=wi(t).toVar(),n=wi(e).toVar();return s.bitXorAssign(i),s.subAssign(Vx(i,Ei(14))),n.bitXorAssign(s),n.subAssign(Vx(s,Ei(11))),i.bitXorAssign(n),i.subAssign(Vx(n,Ei(25))),s.bitXorAssign(i),s.subAssign(Vx(i,Ei(16))),n.bitXorAssign(s),n.subAssign(Vx(s,Ei(4))),i.bitXorAssign(n),i.subAssign(Vx(n,Ei(14))),s.bitXorAssign(i),s.subAssign(Vx(i,Ei(24))),s})).setLayout({name:"mx_bjfinal",type:"uint",inputs:[{name:"a",type:"uint"},{name:"b",type:"uint"},{name:"c",type:"uint"}]}),Gx=_i((([e])=>{const t=wi(e).toVar();return Ci(t).div(Ci(wi(Ei(4294967295))))})).setLayout({name:"mx_bits_to_01",type:"float",inputs:[{name:"bits",type:"uint"}]}),kx=_i((([e])=>{const t=Ci(e).toVar();return t.mul(t).mul(t).mul(t.mul(t.mul(6).sub(15)).add(10))})).setLayout({name:"mx_fade",type:"float",inputs:[{name:"t",type:"float"}]}),zx=vm([_i((([e])=>{const t=Ei(e).toVar(),r=wi(wi(1)).toVar(),s=wi(wi(Ei(3735928559)).add(r.shiftLeft(wi(2))).add(wi(13))).toVar();return Ox(s.add(wi(t)),s,s)})).setLayout({name:"mx_hash_int_0",type:"uint",inputs:[{name:"x",type:"int"}]}),_i((([e,t])=>{const r=Ei(t).toVar(),s=Ei(e).toVar(),i=wi(wi(2)).toVar(),n=wi().toVar(),o=wi().toVar(),a=wi().toVar();return n.assign(o.assign(a.assign(wi(Ei(3735928559)).add(i.shiftLeft(wi(2))).add(wi(13))))),n.addAssign(wi(s)),o.addAssign(wi(r)),Ox(n,o,a)})).setLayout({name:"mx_hash_int_1",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"}]}),_i((([e,t,r])=>{const s=Ei(r).toVar(),i=Ei(t).toVar(),n=Ei(e).toVar(),o=wi(wi(3)).toVar(),a=wi().toVar(),u=wi().toVar(),l=wi().toVar();return a.assign(u.assign(l.assign(wi(Ei(3735928559)).add(o.shiftLeft(wi(2))).add(wi(13))))),a.addAssign(wi(n)),u.addAssign(wi(i)),l.addAssign(wi(s)),Ox(a,u,l)})).setLayout({name:"mx_hash_int_2",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"}]}),_i((([e,t,r,s])=>{const i=Ei(s).toVar(),n=Ei(r).toVar(),o=Ei(t).toVar(),a=Ei(e).toVar(),u=wi(wi(4)).toVar(),l=wi().toVar(),d=wi().toVar(),c=wi().toVar();return l.assign(d.assign(c.assign(wi(Ei(3735928559)).add(u.shiftLeft(wi(2))).add(wi(13))))),l.addAssign(wi(a)),d.addAssign(wi(o)),c.addAssign(wi(n)),Dx(l,d,c),l.addAssign(wi(i)),Ox(l,d,c)})).setLayout({name:"mx_hash_int_3",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"},{name:"xx",type:"int"}]}),_i((([e,t,r,s,i])=>{const n=Ei(i).toVar(),o=Ei(s).toVar(),a=Ei(r).toVar(),u=Ei(t).toVar(),l=Ei(e).toVar(),d=wi(wi(5)).toVar(),c=wi().toVar(),h=wi().toVar(),p=wi().toVar();return c.assign(h.assign(p.assign(wi(Ei(3735928559)).add(d.shiftLeft(wi(2))).add(wi(13))))),c.addAssign(wi(l)),h.addAssign(wi(u)),p.addAssign(wi(a)),Dx(c,h,p),c.addAssign(wi(o)),h.addAssign(wi(n)),Ox(c,h,p)})).setLayout({name:"mx_hash_int_4",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"},{name:"xx",type:"int"},{name:"yy",type:"int"}]})]),$x=vm([_i((([e,t])=>{const r=Ei(t).toVar(),s=Ei(e).toVar(),i=wi(zx(s,r)).toVar(),n=Vi().toVar();return n.x.assign(i.bitAnd(Ei(255))),n.y.assign(i.shiftRight(Ei(8)).bitAnd(Ei(255))),n.z.assign(i.shiftRight(Ei(16)).bitAnd(Ei(255))),n})).setLayout({name:"mx_hash_vec3_0",type:"uvec3",inputs:[{name:"x",type:"int"},{name:"y",type:"int"}]}),_i((([e,t,r])=>{const s=Ei(r).toVar(),i=Ei(t).toVar(),n=Ei(e).toVar(),o=wi(zx(n,i,s)).toVar(),a=Vi().toVar();return a.x.assign(o.bitAnd(Ei(255))),a.y.assign(o.shiftRight(Ei(8)).bitAnd(Ei(255))),a.z.assign(o.shiftRight(Ei(16)).bitAnd(Ei(255))),a})).setLayout({name:"mx_hash_vec3_1",type:"uvec3",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"}]})]),Hx=vm([_i((([e])=>{const t=Bi(e).toVar(),r=Ei().toVar(),s=Ei().toVar(),i=Ci(Sx(t.x,r)).toVar(),n=Ci(Sx(t.y,s)).toVar(),o=Ci(kx(i)).toVar(),a=Ci(kx(n)).toVar(),u=Ci(Ax(wx(zx(r,s),i,n),wx(zx(r.add(Ei(1)),s),i.sub(1),n),wx(zx(r,s.add(Ei(1))),i,n.sub(1)),wx(zx(r.add(Ei(1)),s.add(Ei(1))),i.sub(1),n.sub(1)),o,a)).toVar();return Ix(u)})).setLayout({name:"mx_perlin_noise_float_0",type:"float",inputs:[{name:"p",type:"vec2"}]}),_i((([e])=>{const t=Ii(e).toVar(),r=Ei().toVar(),s=Ei().toVar(),i=Ei().toVar(),n=Ci(Sx(t.x,r)).toVar(),o=Ci(Sx(t.y,s)).toVar(),a=Ci(Sx(t.z,i)).toVar(),u=Ci(kx(n)).toVar(),l=Ci(kx(o)).toVar(),d=Ci(kx(a)).toVar(),c=Ci(Rx(wx(zx(r,s,i),n,o,a),wx(zx(r.add(Ei(1)),s,i),n.sub(1),o,a),wx(zx(r,s.add(Ei(1)),i),n,o.sub(1),a),wx(zx(r.add(Ei(1)),s.add(Ei(1)),i),n.sub(1),o.sub(1),a),wx(zx(r,s,i.add(Ei(1))),n,o,a.sub(1)),wx(zx(r.add(Ei(1)),s,i.add(Ei(1))),n.sub(1),o,a.sub(1)),wx(zx(r,s.add(Ei(1)),i.add(Ei(1))),n,o.sub(1),a.sub(1)),wx(zx(r.add(Ei(1)),s.add(Ei(1)),i.add(Ei(1))),n.sub(1),o.sub(1),a.sub(1)),u,l,d)).toVar();return Lx(c)})).setLayout({name:"mx_perlin_noise_float_1",type:"float",inputs:[{name:"p",type:"vec3"}]})]),Wx=vm([_i((([e])=>{const t=Bi(e).toVar(),r=Ei().toVar(),s=Ei().toVar(),i=Ci(Sx(t.x,r)).toVar(),n=Ci(Sx(t.y,s)).toVar(),o=Ci(kx(i)).toVar(),a=Ci(kx(n)).toVar(),u=Ii(Ax(Ux($x(r,s),i,n),Ux($x(r.add(Ei(1)),s),i.sub(1),n),Ux($x(r,s.add(Ei(1))),i,n.sub(1)),Ux($x(r.add(Ei(1)),s.add(Ei(1))),i.sub(1),n.sub(1)),o,a)).toVar();return Ix(u)})).setLayout({name:"mx_perlin_noise_vec3_0",type:"vec3",inputs:[{name:"p",type:"vec2"}]}),_i((([e])=>{const t=Ii(e).toVar(),r=Ei().toVar(),s=Ei().toVar(),i=Ei().toVar(),n=Ci(Sx(t.x,r)).toVar(),o=Ci(Sx(t.y,s)).toVar(),a=Ci(Sx(t.z,i)).toVar(),u=Ci(kx(n)).toVar(),l=Ci(kx(o)).toVar(),d=Ci(kx(a)).toVar(),c=Ii(Rx(Ux($x(r,s,i),n,o,a),Ux($x(r.add(Ei(1)),s,i),n.sub(1),o,a),Ux($x(r,s.add(Ei(1)),i),n,o.sub(1),a),Ux($x(r.add(Ei(1)),s.add(Ei(1)),i),n.sub(1),o.sub(1),a),Ux($x(r,s,i.add(Ei(1))),n,o,a.sub(1)),Ux($x(r.add(Ei(1)),s,i.add(Ei(1))),n.sub(1),o,a.sub(1)),Ux($x(r,s.add(Ei(1)),i.add(Ei(1))),n,o.sub(1),a.sub(1)),Ux($x(r.add(Ei(1)),s.add(Ei(1)),i.add(Ei(1))),n.sub(1),o.sub(1),a.sub(1)),u,l,d)).toVar();return Lx(c)})).setLayout({name:"mx_perlin_noise_vec3_1",type:"vec3",inputs:[{name:"p",type:"vec3"}]})]),jx=vm([_i((([e])=>{const t=Ci(e).toVar(),r=Ei(Nx(t)).toVar();return Gx(zx(r))})).setLayout({name:"mx_cell_noise_float_0",type:"float",inputs:[{name:"p",type:"float"}]}),_i((([e])=>{const t=Bi(e).toVar(),r=Ei(Nx(t.x)).toVar(),s=Ei(Nx(t.y)).toVar();return Gx(zx(r,s))})).setLayout({name:"mx_cell_noise_float_1",type:"float",inputs:[{name:"p",type:"vec2"}]}),_i((([e])=>{const t=Ii(e).toVar(),r=Ei(Nx(t.x)).toVar(),s=Ei(Nx(t.y)).toVar(),i=Ei(Nx(t.z)).toVar();return Gx(zx(r,s,i))})).setLayout({name:"mx_cell_noise_float_2",type:"float",inputs:[{name:"p",type:"vec3"}]}),_i((([e])=>{const t=Oi(e).toVar(),r=Ei(Nx(t.x)).toVar(),s=Ei(Nx(t.y)).toVar(),i=Ei(Nx(t.z)).toVar(),n=Ei(Nx(t.w)).toVar();return Gx(zx(r,s,i,n))})).setLayout({name:"mx_cell_noise_float_3",type:"float",inputs:[{name:"p",type:"vec4"}]})]),qx=vm([_i((([e])=>{const t=Ci(e).toVar(),r=Ei(Nx(t)).toVar();return Ii(Gx(zx(r,Ei(0))),Gx(zx(r,Ei(1))),Gx(zx(r,Ei(2))))})).setLayout({name:"mx_cell_noise_vec3_0",type:"vec3",inputs:[{name:"p",type:"float"}]}),_i((([e])=>{const t=Bi(e).toVar(),r=Ei(Nx(t.x)).toVar(),s=Ei(Nx(t.y)).toVar();return Ii(Gx(zx(r,s,Ei(0))),Gx(zx(r,s,Ei(1))),Gx(zx(r,s,Ei(2))))})).setLayout({name:"mx_cell_noise_vec3_1",type:"vec3",inputs:[{name:"p",type:"vec2"}]}),_i((([e])=>{const t=Ii(e).toVar(),r=Ei(Nx(t.x)).toVar(),s=Ei(Nx(t.y)).toVar(),i=Ei(Nx(t.z)).toVar();return Ii(Gx(zx(r,s,i,Ei(0))),Gx(zx(r,s,i,Ei(1))),Gx(zx(r,s,i,Ei(2))))})).setLayout({name:"mx_cell_noise_vec3_2",type:"vec3",inputs:[{name:"p",type:"vec3"}]}),_i((([e])=>{const t=Oi(e).toVar(),r=Ei(Nx(t.x)).toVar(),s=Ei(Nx(t.y)).toVar(),i=Ei(Nx(t.z)).toVar(),n=Ei(Nx(t.w)).toVar();return Ii(Gx(zx(r,s,i,n,Ei(0))),Gx(zx(r,s,i,n,Ei(1))),Gx(zx(r,s,i,n,Ei(2))))})).setLayout({name:"mx_cell_noise_vec3_3",type:"vec3",inputs:[{name:"p",type:"vec4"}]})]),Kx=_i((([e,t,r,s])=>{const i=Ci(s).toVar(),n=Ci(r).toVar(),o=Ei(t).toVar(),a=Ii(e).toVar(),u=Ci(0).toVar(),l=Ci(1).toVar();return ic(o,(()=>{u.addAssign(l.mul(Hx(a))),l.mulAssign(i),a.mulAssign(n)})),u})).setLayout({name:"mx_fractal_noise_float",type:"float",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),Xx=_i((([e,t,r,s])=>{const i=Ci(s).toVar(),n=Ci(r).toVar(),o=Ei(t).toVar(),a=Ii(e).toVar(),u=Ii(0).toVar(),l=Ci(1).toVar();return ic(o,(()=>{u.addAssign(l.mul(Wx(a))),l.mulAssign(i),a.mulAssign(n)})),u})).setLayout({name:"mx_fractal_noise_vec3",type:"vec3",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),Yx=_i((([e,t,r,s])=>{const i=Ci(s).toVar(),n=Ci(r).toVar(),o=Ei(t).toVar(),a=Ii(e).toVar();return Bi(Kx(a,o,n,i),Kx(a.add(Ii(Ei(19),Ei(193),Ei(17))),o,n,i))})).setLayout({name:"mx_fractal_noise_vec2",type:"vec2",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),Qx=_i((([e,t,r,s])=>{const i=Ci(s).toVar(),n=Ci(r).toVar(),o=Ei(t).toVar(),a=Ii(e).toVar(),u=Ii(Xx(a,o,n,i)).toVar(),l=Ci(Kx(a.add(Ii(Ei(19),Ei(193),Ei(17))),o,n,i)).toVar();return Oi(u,l)})).setLayout({name:"mx_fractal_noise_vec4",type:"vec4",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),Zx=vm([_i((([e,t,r,s,i,n,o])=>{const a=Ei(o).toVar(),u=Ci(n).toVar(),l=Ei(i).toVar(),d=Ei(s).toVar(),c=Ei(r).toVar(),h=Ei(t).toVar(),p=Bi(e).toVar(),g=Ii(qx(Bi(h.add(d),c.add(l)))).toVar(),m=Bi(g.x,g.y).toVar();m.subAssign(.5),m.mulAssign(u),m.addAssign(.5);const f=Bi(Bi(Ci(h),Ci(c)).add(m)).toVar(),y=Bi(f.sub(p)).toVar();return Si(a.equal(Ei(2)),(()=>Fo(y.x).add(Fo(y.y)))),Si(a.equal(Ei(3)),(()=>Ko(Fo(y.x),Fo(y.y)))),ea(y,y)})).setLayout({name:"mx_worley_distance_0",type:"float",inputs:[{name:"p",type:"vec2"},{name:"x",type:"int"},{name:"y",type:"int"},{name:"xoff",type:"int"},{name:"yoff",type:"int"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),_i((([e,t,r,s,i,n,o,a,u])=>{const l=Ei(u).toVar(),d=Ci(a).toVar(),c=Ei(o).toVar(),h=Ei(n).toVar(),p=Ei(i).toVar(),g=Ei(s).toVar(),m=Ei(r).toVar(),f=Ei(t).toVar(),y=Ii(e).toVar(),x=Ii(qx(Ii(f.add(p),m.add(h),g.add(c)))).toVar();x.subAssign(.5),x.mulAssign(d),x.addAssign(.5);const b=Ii(Ii(Ci(f),Ci(m),Ci(g)).add(x)).toVar(),T=Ii(b.sub(y)).toVar();return Si(l.equal(Ei(2)),(()=>Fo(T.x).add(Fo(T.y)).add(Fo(T.z)))),Si(l.equal(Ei(3)),(()=>Ko(Ko(Fo(T.x),Fo(T.y)),Fo(T.z)))),ea(T,T)})).setLayout({name:"mx_worley_distance_1",type:"float",inputs:[{name:"p",type:"vec3"},{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"},{name:"xoff",type:"int"},{name:"yoff",type:"int"},{name:"zoff",type:"int"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),Jx=_i((([e,t,r])=>{const s=Ei(r).toVar(),i=Ci(t).toVar(),n=Bi(e).toVar(),o=Ei().toVar(),a=Ei().toVar(),u=Bi(Sx(n.x,o),Sx(n.y,a)).toVar(),l=Ci(1e6).toVar();return ic({start:-1,end:Ei(1),name:"x",condition:"<="},(({x:e})=>{ic({start:-1,end:Ei(1),name:"y",condition:"<="},(({y:t})=>{const r=Ci(Zx(u,e,t,o,a,i,s)).toVar();l.assign(qo(l,r))}))})),Si(s.equal(Ei(0)),(()=>{l.assign(_o(l))})),l})).setLayout({name:"mx_worley_noise_float_0",type:"float",inputs:[{name:"p",type:"vec2"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),eb=_i((([e,t,r])=>{const s=Ei(r).toVar(),i=Ci(t).toVar(),n=Bi(e).toVar(),o=Ei().toVar(),a=Ei().toVar(),u=Bi(Sx(n.x,o),Sx(n.y,a)).toVar(),l=Bi(1e6,1e6).toVar();return ic({start:-1,end:Ei(1),name:"x",condition:"<="},(({x:e})=>{ic({start:-1,end:Ei(1),name:"y",condition:"<="},(({y:t})=>{const r=Ci(Zx(u,e,t,o,a,i,s)).toVar();Si(r.lessThan(l.x),(()=>{l.y.assign(l.x),l.x.assign(r)})).ElseIf(r.lessThan(l.y),(()=>{l.y.assign(r)}))}))})),Si(s.equal(Ei(0)),(()=>{l.assign(_o(l))})),l})).setLayout({name:"mx_worley_noise_vec2_0",type:"vec2",inputs:[{name:"p",type:"vec2"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),tb=_i((([e,t,r])=>{const s=Ei(r).toVar(),i=Ci(t).toVar(),n=Bi(e).toVar(),o=Ei().toVar(),a=Ei().toVar(),u=Bi(Sx(n.x,o),Sx(n.y,a)).toVar(),l=Ii(1e6,1e6,1e6).toVar();return ic({start:-1,end:Ei(1),name:"x",condition:"<="},(({x:e})=>{ic({start:-1,end:Ei(1),name:"y",condition:"<="},(({y:t})=>{const r=Ci(Zx(u,e,t,o,a,i,s)).toVar();Si(r.lessThan(l.x),(()=>{l.z.assign(l.y),l.y.assign(l.x),l.x.assign(r)})).ElseIf(r.lessThan(l.y),(()=>{l.z.assign(l.y),l.y.assign(r)})).ElseIf(r.lessThan(l.z),(()=>{l.z.assign(r)}))}))})),Si(s.equal(Ei(0)),(()=>{l.assign(_o(l))})),l})).setLayout({name:"mx_worley_noise_vec3_0",type:"vec3",inputs:[{name:"p",type:"vec2"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),rb=vm([Jx,_i((([e,t,r])=>{const s=Ei(r).toVar(),i=Ci(t).toVar(),n=Ii(e).toVar(),o=Ei().toVar(),a=Ei().toVar(),u=Ei().toVar(),l=Ii(Sx(n.x,o),Sx(n.y,a),Sx(n.z,u)).toVar(),d=Ci(1e6).toVar();return ic({start:-1,end:Ei(1),name:"x",condition:"<="},(({x:e})=>{ic({start:-1,end:Ei(1),name:"y",condition:"<="},(({y:t})=>{ic({start:-1,end:Ei(1),name:"z",condition:"<="},(({z:r})=>{const n=Ci(Zx(l,e,t,r,o,a,u,i,s)).toVar();d.assign(qo(d,n))}))}))})),Si(s.equal(Ei(0)),(()=>{d.assign(_o(d))})),d})).setLayout({name:"mx_worley_noise_float_1",type:"float",inputs:[{name:"p",type:"vec3"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),sb=vm([eb,_i((([e,t,r])=>{const s=Ei(r).toVar(),i=Ci(t).toVar(),n=Ii(e).toVar(),o=Ei().toVar(),a=Ei().toVar(),u=Ei().toVar(),l=Ii(Sx(n.x,o),Sx(n.y,a),Sx(n.z,u)).toVar(),d=Bi(1e6,1e6).toVar();return ic({start:-1,end:Ei(1),name:"x",condition:"<="},(({x:e})=>{ic({start:-1,end:Ei(1),name:"y",condition:"<="},(({y:t})=>{ic({start:-1,end:Ei(1),name:"z",condition:"<="},(({z:r})=>{const n=Ci(Zx(l,e,t,r,o,a,u,i,s)).toVar();Si(n.lessThan(d.x),(()=>{d.y.assign(d.x),d.x.assign(n)})).ElseIf(n.lessThan(d.y),(()=>{d.y.assign(n)}))}))}))})),Si(s.equal(Ei(0)),(()=>{d.assign(_o(d))})),d})).setLayout({name:"mx_worley_noise_vec2_1",type:"vec2",inputs:[{name:"p",type:"vec3"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),ib=vm([tb,_i((([e,t,r])=>{const s=Ei(r).toVar(),i=Ci(t).toVar(),n=Ii(e).toVar(),o=Ei().toVar(),a=Ei().toVar(),u=Ei().toVar(),l=Ii(Sx(n.x,o),Sx(n.y,a),Sx(n.z,u)).toVar(),d=Ii(1e6,1e6,1e6).toVar();return ic({start:-1,end:Ei(1),name:"x",condition:"<="},(({x:e})=>{ic({start:-1,end:Ei(1),name:"y",condition:"<="},(({y:t})=>{ic({start:-1,end:Ei(1),name:"z",condition:"<="},(({z:r})=>{const n=Ci(Zx(l,e,t,r,o,a,u,i,s)).toVar();Si(n.lessThan(d.x),(()=>{d.z.assign(d.y),d.y.assign(d.x),d.x.assign(n)})).ElseIf(n.lessThan(d.y),(()=>{d.z.assign(d.y),d.y.assign(n)})).ElseIf(n.lessThan(d.z),(()=>{d.z.assign(n)}))}))}))})),Si(s.equal(Ei(0)),(()=>{d.assign(_o(d))})),d})).setLayout({name:"mx_worley_noise_vec3_1",type:"vec3",inputs:[{name:"p",type:"vec3"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),nb=_i((([e])=>{const t=e.y,r=e.z,s=Ii().toVar();return Si(t.lessThan(1e-4),(()=>{s.assign(Ii(r,r,r))})).Else((()=>{let i=e.x;i=i.sub(No(i)).mul(6).toVar();const n=Ei(zo(i)),o=i.sub(Ci(n)),a=r.mul(t.oneMinus()),u=r.mul(t.mul(o).oneMinus()),l=r.mul(t.mul(o.oneMinus()).oneMinus());Si(n.equal(Ei(0)),(()=>{s.assign(Ii(r,l,a))})).ElseIf(n.equal(Ei(1)),(()=>{s.assign(Ii(u,r,a))})).ElseIf(n.equal(Ei(2)),(()=>{s.assign(Ii(a,r,l))})).ElseIf(n.equal(Ei(3)),(()=>{s.assign(Ii(a,u,r))})).ElseIf(n.equal(Ei(4)),(()=>{s.assign(Ii(l,a,r))})).Else((()=>{s.assign(Ii(r,a,u))}))})),s})).setLayout({name:"mx_hsvtorgb",type:"vec3",inputs:[{name:"hsv",type:"vec3"}]}),ob=_i((([e])=>{const t=Ii(e).toVar(),r=Ci(t.x).toVar(),s=Ci(t.y).toVar(),i=Ci(t.z).toVar(),n=Ci(qo(r,qo(s,i))).toVar(),o=Ci(Ko(r,Ko(s,i))).toVar(),a=Ci(o.sub(n)).toVar(),u=Ci().toVar(),l=Ci().toVar(),d=Ci().toVar();return d.assign(o),Si(o.greaterThan(0),(()=>{l.assign(a.div(o))})).Else((()=>{l.assign(0)})),Si(l.lessThanEqual(0),(()=>{u.assign(0)})).Else((()=>{Si(r.greaterThanEqual(o),(()=>{u.assign(s.sub(i).div(a))})).ElseIf(s.greaterThanEqual(o),(()=>{u.assign(On(2,i.sub(r).div(a)))})).Else((()=>{u.assign(On(4,r.sub(s).div(a)))})),u.mulAssign(1/6),Si(u.lessThan(0),(()=>{u.addAssign(1)}))})),Ii(u,l,d)})).setLayout({name:"mx_rgbtohsv",type:"vec3",inputs:[{name:"c",type:"vec3"}]}),ab=_i((([e])=>{const t=Ii(e).toVar(),r=Di(qn(t,Ii(.04045))).toVar(),s=Ii(t.div(12.92)).toVar(),i=Ii(ra(Ko(t.add(Ii(.055)),Ii(0)).div(1.055),Ii(2.4))).toVar();return la(s,i,r)})).setLayout({name:"mx_srgb_texture_to_lin_rec709",type:"vec3",inputs:[{name:"color",type:"vec3"}]}),ub=(e,t)=>{e=Ci(e),t=Ci(t);const r=Bi(t.dFdx(),t.dFdy()).length().mul(.7071067811865476);return pa(e.sub(r),e.add(r),t)},lb=(e,t,r,s)=>la(e,t,r[s].clamp()),db=(e,t,r,s,i)=>la(e,t,ub(r,s[i])),cb=_i((([e,t,r])=>{const s=Ao(e).toVar("nDir"),i=Gn(Ci(.5).mul(t.sub(r)),Yu).div(s).toVar("rbmax"),n=Gn(Ci(-.5).mul(t.sub(r)),Yu).div(s).toVar("rbmin"),o=Ii().toVar("rbminmax");o.x=s.x.greaterThan(Ci(0)).select(i.x,n.x),o.y=s.y.greaterThan(Ci(0)).select(i.y,n.y),o.z=s.z.greaterThan(Ci(0)).select(i.z,n.z);const a=qo(qo(o.x,o.y),o.z).toVar("correction");return Yu.add(s.mul(a)).toVar("boxIntersection").sub(r)})),hb=_i((([e,t])=>{const r=e.x,s=e.y,i=e.z;let n=t.element(0).mul(.886227);return n=n.add(t.element(1).mul(1.023328).mul(s)),n=n.add(t.element(2).mul(1.023328).mul(i)),n=n.add(t.element(3).mul(1.023328).mul(r)),n=n.add(t.element(4).mul(.858086).mul(r).mul(s)),n=n.add(t.element(5).mul(.858086).mul(s).mul(i)),n=n.add(t.element(6).mul(i.mul(i).mul(.743125).sub(.247708))),n=n.add(t.element(7).mul(.858086).mul(r).mul(i)),n=n.add(t.element(8).mul(.429043).mul(kn(r,r).sub(kn(s,s)))),n}));var pb=Object.freeze({__proto__:null,BRDF_GGX:kh,BRDF_Lambert:Rh,BasicShadowFilter:Qy,Break:nc,Continue:()=>au("continue").append(),DFGApprox:zh,D_GGX:Dh,Discard:uu,EPSILON:uo,F_Schlick:Ah,Fn:_i,INFINITY:lo,If:Si,Loop:ic,NodeAccess:Ss,NodeShaderStage:_s,NodeType:Ns,NodeUpdateType:vs,PCFShadowFilter:Zy,PCFSoftShadowFilter:Jy,PI:co,PI2:ho,Return:()=>au("return").append(),Schlick_to_F0:Hh,ScriptableNodeResources:hy,ShaderNode:mi,TBNViewMatrix:Hl,VSMShadowFilter:ex,V_GGX_SmithCorrelated:Lh,abs:Fo,acesFilmicToneMapping:Zf,acos:Bo,add:On,addMethodChaining:$s,addNodeElement:function(e){console.warn("THREE.TSLBase: AddNodeElement has been removed in favor of tree-shaking. Trying add",e)},agxToneMapping:ry,all:po,alphaT:yn,and:Yn,anisotropy:xn,anisotropyB:Tn,anisotropyT:bn,any:go,append:Ai,arrayBuffer:e=>fi(new Gs(e,"ArrayBuffer")),asin:Mo,assign:In,atan:Uo,atan2:xa,atomicAdd:(e,t,r=null)=>Py(Uy.ATOMIC_ADD,e,t,r),atomicAnd:(e,t,r=null)=>Py(Uy.ATOMIC_AND,e,t,r),atomicFunc:Py,atomicMax:(e,t,r=null)=>Py(Uy.ATOMIC_MAX,e,t,r),atomicMin:(e,t,r=null)=>Py(Uy.ATOMIC_MIN,e,t,r),atomicOr:(e,t,r=null)=>Py(Uy.ATOMIC_OR,e,t,r),atomicStore:(e,t,r=null)=>Py(Uy.ATOMIC_STORE,e,t,r),atomicSub:(e,t,r=null)=>Py(Uy.ATOMIC_SUB,e,t,r),atomicXor:(e,t,r=null)=>Py(Uy.ATOMIC_XOR,e,t,r),attenuationColor:Un,attenuationDistance:Bn,attribute:hu,attributeArray:(e,t="float")=>{const r=ms(t),s=new uf(e,r);return hf(s,t,e)},backgroundBlurriness:bf,backgroundIntensity:Tf,backgroundRotation:_f,batch:Jd,billboarding:Em,bitAnd:eo,bitNot:to,bitOr:ro,bitXor:so,bitangentGeometry:Dl,bitangentLocal:Ol,bitangentView:Gl,bitangentWorld:kl,bitcast:Wo,blendBurn:Mf,blendColor:Pf,blendDodge:Bf,blendOverlay:Ff,blendScreen:Uf,blur:zp,bool:Mi,buffer:_l,bufferAttribute:qa,bumpMap:Jl,burn:(...e)=>(console.warn('THREE.TSL: "burn" has been renamed. Use "blendBurn" instead.'),Mf(e)),bvec2:Pi,bvec3:Di,bvec4:zi,bypass:ru,cache:eu,call:Vn,cameraFar:vu,cameraNear:_u,cameraNormalMatrix:Cu,cameraPosition:Eu,cameraProjectionMatrix:Nu,cameraProjectionMatrixInverse:Su,cameraViewMatrix:Au,cameraWorldMatrix:Ru,cbrt:aa,cdl:Gf,ceil:So,checker:Tx,cineonToneMapping:Yf,clamp:da,clearcoat:dn,clearcoatRoughness:cn,code:ny,color:Ri,colorSpaceToWorking:Da,colorToDirection:e=>fi(e).mul(2).sub(1),compute:Za,cond:_a,context:Na,convert:qi,convertColorSpace:(e,t,r)=>fi(new Pa(fi(e),t,r)),convertToTexture:(e,...t)=>e.isTextureNode?e:e.isPassNode?e.getTextureNode():rf(e,...t),cos:Eo,cross:ta,cubeTexture:bl,dFdx:Do,dFdy:Oo,dashSize:An,defaultBuildStages:Rs,defaultShaderStages:As,defined:pi,degrees:fo,deltaTime:Sm,densityFog:function(e,t){return console.warn('THREE.TSL: "densityFog( color, density )" is deprecated. Use "fog( color, densityFogFactor( density ) )" instead.'),xy(e,yy(t))},densityFogFactor:yy,depth:zc,depthPass:(e,t,r)=>fi(new jf(jf.DEPTH,e,t,r)),difference:Jo,diffuseColor:on,directPointLight:xx,directionToColor:uh,dispersion:Fn,distance:Zo,div:zn,dodge:(...e)=>(console.warn('THREE.TSL: "dodge" has been renamed. Use "blendDodge" instead.'),Bf(e)),dot:ea,drawIndex:qd,dynamicBufferAttribute:Ka,element:ji,emissive:an,equal:Hn,equals:jo,equirectUV:hh,exp:yo,exp2:xo,expression:au,faceDirection:rl,faceForward:ga,float:Ci,floor:No,fog:xy,fract:Ro,frameGroup:Qi,frameId:Am,frontFacing:tl,fwidth:$o,gain:(e,t)=>e.lessThan(.5)?fm(e.mul(2),t).div(2):Gn(1,fm(kn(Gn(1,e),2),t).div(2)),gapSize:Rn,getConstNodeType:gi,getCurrentStack:Ni,getDirection:Dp,getDistanceAttenuation:ux,getGeometryRoughness:Ph,getNormalFromDepth:of,getParallaxCorrectNormal:cb,getRoughness:Ih,getScreenPosition:nf,getShIrradianceAt:hb,getTextureIndex:hm,getViewPosition:sf,glsl:(e,t)=>ny(e,t,"glsl"),glslFn:(e,t)=>ay(e,t,"glsl"),grayscale:If,greaterThan:qn,greaterThanEqual:Xn,hash:mm,highpModelNormalViewMatrix:ju,highpModelViewMatrix:Wu,hue:Df,instance:Xd,instanceIndex:$d,instancedArray:(e,t="float")=>{const r=ms(t),s=new af(e,r);return hf(s,t,e)},instancedBufferAttribute:Xa,instancedDynamicBufferAttribute:Ya,instancedMesh:Qd,int:Ei,inverseSqrt:vo,invocationLocalIndex:jd,invocationSubgroupIndex:Wd,ior:En,iridescence:gn,iridescenceIOR:mn,iridescenceThickness:fn,ivec2:Ui,ivec3:Li,ivec4:Gi,js:(e,t)=>ny(e,t,"js"),label:Sa,length:Io,lengthSq:ua,lessThan:jn,lessThanEqual:Kn,lightPosition:Oy,lightProjectionUV:Dy,lightShadowMatrix:Vy,lightTargetDirection:zy,lightTargetPosition:Gy,lightViewPosition:ky,lightingContext:gc,lights:(e=[])=>fi(new Wy).setLights(e),linearDepth:$c,linearToneMapping:Kf,localId:Cy,log:bo,log2:To,logarithmicDepthToViewZ:(e,t,r)=>{const s=e.mul(bo(r.div(t)));return Ci(Math.E).pow(s).mul(t).negate()},loop:(...e)=>(console.warn("TSL.LoopNode: loop() has been renamed to Loop()."),ic(...e)),luminance:Of,mat2:$i,mat3:Hi,mat4:Wi,matcapUV:lg,materialAOMap:Dd,materialAlphaTest:rd,materialAnisotropy:_d,materialAnisotropyVector:Od,materialAttenuationColor:wd,materialAttenuationDistance:Ed,materialClearcoat:md,materialClearcoatNormal:yd,materialClearcoatRoughness:fd,materialColor:sd,materialDispersion:Ld,materialEmissive:nd,materialIOR:Cd,materialIridescence:vd,materialIridescenceIOR:Nd,materialIridescenceThickness:Sd,materialLightMap:Vd,materialLineDashOffset:Pd,materialLineDashSize:Bd,materialLineGapSize:Ud,materialLineScale:Md,materialLineWidth:Fd,materialMetalness:pd,materialNormal:gd,materialOpacity:od,materialPointWidth:Id,materialReference:Ml,materialReflectivity:cd,materialRefractionRatio:pl,materialRotation:xd,materialRoughness:hd,materialSheen:bd,materialSheenRoughness:Td,materialShininess:id,materialSpecular:ad,materialSpecularColor:ld,materialSpecularIntensity:ud,materialSpecularStrength:dd,materialThickness:Rd,materialTransmission:Ad,max:Ko,maxMipLevel:yu,mediumpModelViewMatrix:Hu,metalness:ln,min:qo,mix:la,mixElement:fa,mod:Xo,modInt:$n,modelDirection:Lu,modelNormalMatrix:ku,modelPosition:Du,modelScale:Ou,modelViewMatrix:$u,modelViewPosition:Gu,modelViewProjection:Gd,modelWorldMatrix:Vu,modelWorldMatrixInverse:zu,morphReference:dc,mrt:gm,mul:kn,mx_aastep:ub,mx_cell_noise_float:(e=pu())=>jx(e.convert("vec2|vec3")),mx_contrast:(e,t=1,r=.5)=>Ci(e).sub(r).mul(t).add(r),mx_fractal_noise_float:(e=pu(),t=3,r=2,s=.5,i=1)=>Kx(e,Ei(t),r,s).mul(i),mx_fractal_noise_vec2:(e=pu(),t=3,r=2,s=.5,i=1)=>Yx(e,Ei(t),r,s).mul(i),mx_fractal_noise_vec3:(e=pu(),t=3,r=2,s=.5,i=1)=>Xx(e,Ei(t),r,s).mul(i),mx_fractal_noise_vec4:(e=pu(),t=3,r=2,s=.5,i=1)=>Qx(e,Ei(t),r,s).mul(i),mx_hsvtorgb:nb,mx_noise_float:(e=pu(),t=1,r=0)=>Hx(e.convert("vec2|vec3")).mul(t).add(r),mx_noise_vec3:(e=pu(),t=1,r=0)=>Wx(e.convert("vec2|vec3")).mul(t).add(r),mx_noise_vec4:(e=pu(),t=1,r=0)=>{e=e.convert("vec2|vec3");return Oi(Wx(e),Hx(e.add(Bi(19,73)))).mul(t).add(r)},mx_ramplr:(e,t,r=pu())=>lb(e,t,r,"x"),mx_ramptb:(e,t,r=pu())=>lb(e,t,r,"y"),mx_rgbtohsv:ob,mx_safepower:(e,t=1)=>(e=Ci(e)).abs().pow(t).mul(e.sign()),mx_splitlr:(e,t,r,s=pu())=>db(e,t,r,s,"x"),mx_splittb:(e,t,r,s=pu())=>db(e,t,r,s,"y"),mx_srgb_texture_to_lin_rec709:ab,mx_transform_uv:(e=1,t=0,r=pu())=>r.mul(e).add(t),mx_worley_noise_float:(e=pu(),t=1)=>rb(e.convert("vec2|vec3"),t,Ei(1)),mx_worley_noise_vec2:(e=pu(),t=1)=>sb(e.convert("vec2|vec3"),t,Ei(1)),mx_worley_noise_vec3:(e=pu(),t=1)=>ib(e.convert("vec2|vec3"),t,Ei(1)),negate:Lo,neutralToneMapping:sy,nodeArray:xi,nodeImmutable:Ti,nodeObject:fi,nodeObjects:yi,nodeProxy:bi,normalFlat:nl,normalGeometry:sl,normalLocal:il,normalMap:Xl,normalView:ol,normalWorld:al,normalize:Ao,not:Zn,notEqual:Wn,numWorkgroups:Ay,objectDirection:Mu,objectGroup:Ji,objectPosition:Uu,objectScale:Fu,objectViewPosition:Pu,objectWorldMatrix:Bu,oneMinus:Vo,or:Qn,orthographicDepthToViewZ:(e,t,r)=>t.sub(r).mul(e).sub(t),oscSawtooth:(e=Nm)=>e.fract(),oscSine:(e=Nm)=>e.add(.75).mul(2*Math.PI).sin().mul(.5).add(.5),oscSquare:(e=Nm)=>e.fract().round(),oscTriangle:(e=Nm)=>e.add(.5).fract().mul(2).sub(1).abs(),output:Sn,outputStruct:cm,overlay:(...e)=>(console.warn('THREE.TSL: "overlay" has been renamed. Use "blendOverlay" instead.'),Ff(e)),overloadingFn:vm,parabola:fm,parallaxDirection:Wl,parallaxUV:(e,t)=>e.sub(Wl.mul(t)),parameter:(e,t)=>fi(new am(e,t)),pass:(e,t,r)=>fi(new jf(jf.COLOR,e,t,r)),passTexture:(e,t)=>fi(new Hf(e,t)),pcurve:(e,t,r)=>ra(zn(ra(e,t),On(ra(e,t),ra(Gn(1,e),r))),1/t),perspectiveDepthToViewZ:Oc,pmremTexture:qp,pointUV:mf,pointWidth:Cn,positionGeometry:qu,positionLocal:Ku,positionPrevious:Xu,positionView:Zu,positionViewDirection:Ju,positionWorld:Yu,positionWorldDirection:Qu,posterize:zf,pow:ra,pow2:sa,pow3:ia,pow4:na,property:sn,radians:mo,rand:ma,range:vy,rangeFog:function(e,t,r){return console.warn('THREE.TSL: "rangeFog( color, near, far )" is deprecated. Use "fog( color, rangeFogFactor( near, far ) )" instead.'),xy(e,fy(t,r))},rangeFogFactor:fy,reciprocal:ko,reference:Cl,referenceBuffer:El,reflect:Qo,reflectVector:fl,reflectView:gl,reflector:e=>fi(new Km(e)),refract:ha,refractVector:yl,refractView:ml,reinhardToneMapping:Xf,remainder:oo,remap:iu,remapClamp:nu,renderGroup:Zi,renderOutput:du,rendererReference:za,rotate:mg,rotateUV:Rm,roughness:un,round:Go,rtt:rf,sRGBTransferEOTF:Ma,sRGBTransferOETF:Ba,sampler:e=>(!0===e.isNode?e:bu(e)).convert("sampler"),saturate:ca,saturation:Lf,screen:(...e)=>(console.warn('THREE.TSL: "screen" has been renamed. Use "blendScreen" instead.'),Uf(e)),screenCoordinate:_c,screenSize:Tc,screenUV:bc,scriptable:gy,scriptableValue:ly,select:Ta,setCurrentStack:vi,shaderStages:Cs,shadow:ox,shadowWorldPosition:qy,sharedUniformGroup:Yi,sheen:hn,sheenRoughness:pn,shiftLeft:io,shiftRight:no,shininess:Nn,sign:Po,sin:Co,sinc:(e,t)=>Co(co.mul(t.mul(e).sub(1))).div(co.mul(t.mul(e).sub(1))),skinning:e=>fi(new tc(e)),skinningReference:rc,smoothstep:pa,smoothstepElement:ya,specularColor:_n,specularF90:vn,spherizeUV:Cm,split:(e,t)=>fi(new Ls(fi(e),t)),spritesheetUV:Bm,sqrt:_o,stack:lm,step:Yo,storage:hf,storageBarrier:()=>wy("storage").append(),storageObject:(e,t,r)=>(console.warn('THREE.TSL: "storageObject()" is deprecated. Use "storage().setPBO( true )" instead.'),hf(e,t,r).setPBO(!0)),storageTexture:Nf,string:(e="")=>fi(new Gs(e,"string")),sub:Gn,subgroupIndex:Hd,subgroupSize:Ey,tan:wo,tangentGeometry:Bl,tangentLocal:Ul,tangentView:Fl,tangentWorld:Pl,temp:Ca,texture:bu,texture3D:Ng,textureBarrier:()=>wy("texture").append(),textureBicubic:up,textureCubeUV:Op,textureLoad:Tu,textureSize:mu,textureStore:(e,t,r)=>{const s=Nf(e,t,r);return null!==r&&s.append(),s},thickness:Mn,time:Nm,timerDelta:(e=1)=>(console.warn('TSL: timerDelta() is deprecated. Use "deltaTime" instead.'),Sm.mul(e)),timerGlobal:(e=1)=>(console.warn('TSL: timerGlobal() is deprecated. Use "time" instead.'),Nm.mul(e)),timerLocal:(e=1)=>(console.warn('TSL: timerLocal() is deprecated. Use "time" instead.'),Nm.mul(e)),toOutputColorSpace:Ia,toWorkingColorSpace:La,toneMapping:Ha,toneMappingExposure:Wa,toonOutlinePass:(t,r,s=new e(0,0,0),i=.003,n=1)=>fi(new qf(t,r,fi(s),fi(i),fi(n))),transformDirection:oa,transformNormal:cl,transformNormalToView:hl,transformedBentNormalView:jl,transformedBitangentView:zl,transformedBitangentWorld:$l,transformedClearcoatNormalView:dl,transformedNormalView:ul,transformedNormalWorld:ll,transformedTangentView:Il,transformedTangentWorld:Ll,transmission:wn,transpose:Ho,triNoise3D:bm,triplanarTexture:(...e)=>Fm(...e),triplanarTextures:Fm,trunc:zo,tslFn:(...e)=>(console.warn("TSL.ShaderNode: tslFn() has been renamed to Fn()."),_i(...e)),uint:wi,uniform:tn,uniformArray:Sl,uniformGroup:Xi,uniforms:(e,t)=>(console.warn("TSL.UniformArrayNode: uniforms() has been renamed to uniformArray()."),fi(new Nl(e,t))),userData:(e,t,r)=>fi(new Sf(e,t,r)),uv:pu,uvec2:Fi,uvec3:Vi,uvec4:ki,varying:wa,varyingProperty:nn,vec2:Bi,vec3:Ii,vec4:Oi,vectorComponents:Es,velocity:wf,vertexColor:e=>fi(new pf(e)),vertexIndex:zd,vibrance:Vf,viewZToLogarithmicDepth:Gc,viewZToOrthographicDepth:Vc,viewZToPerspectiveDepth:Dc,viewport:vc,viewportBottomLeft:Ec,viewportCoordinate:Sc,viewportDepthTexture:Ic,viewportLinearDepth:Hc,viewportMipTexture:Uc,viewportResolution:Rc,viewportSafeUV:wm,viewportSharedTexture:nh,viewportSize:Nc,viewportTexture:Bc,viewportTopLeft:Cc,viewportUV:Ac,wgsl:(e,t)=>ny(e,t,"wgsl"),wgslFn:(e,t)=>ay(e,t,"wgsl"),workgroupArray:(e,t)=>fi(new By("Workgroup",e,t)),workgroupBarrier:()=>wy("workgroup").append(),workgroupId:Ry,workingToColorSpace:Va,xor:Jn});const gb=new om;class mb extends Bg{constructor(e,t){super(),this.renderer=e,this.nodes=t}update(e,t,r){const s=this.renderer,i=this.nodes.getBackgroundNode(e)||e.background;let n=!1;if(null===i)s._clearColor.getRGB(gb,Ae),gb.a=s._clearColor.a;else if(!0===i.isColor)i.getRGB(gb,Ae),gb.a=1,n=!0;else if(!0===i.isNode){const r=this.get(e),n=i;gb.copy(s._clearColor);let o=r.backgroundMesh;if(void 0===o){const e=Na(Oi(n).mul(Tf),{getUV:()=>_f.mul(al),getTextureLevel:()=>bf});let t=Gd;t=t.setZ(t.w);const s=new Yc;s.name="Background.material",s.side=T,s.depthTest=!1,s.depthWrite=!1,s.fog=!1,s.lights=!1,s.vertexNode=t,s.colorNode=e,r.backgroundMeshNode=e,r.backgroundMesh=o=new k(new Me(1,32,32),s),o.frustumCulled=!1,o.name="Background.mesh",o.onBeforeRender=function(e,t,r){this.matrixWorld.copyPosition(r.matrixWorld)}}const a=n.getCacheKey();r.backgroundCacheKey!==a&&(r.backgroundMeshNode.node=Oi(n).mul(Tf),r.backgroundMeshNode.needsUpdate=!0,o.material.needsUpdate=!0,r.backgroundCacheKey=a),t.unshift(o,o.geometry,o.material,0,0,null,null)}else console.error("THREE.Renderer: Unsupported background configuration.",i);if(!0===s.autoClear||!0===n){const e=r.clearColorValue;e.r=gb.r,e.g=gb.g,e.b=gb.b,e.a=gb.a,!0!==s.backend.isWebGLBackend&&!0!==s.alpha||(e.r*=e.a,e.g*=e.a,e.b*=e.a),r.depthClearValue=s._clearDepth,r.stencilClearValue=s._clearStencil,r.clearColor=!0===s.autoClearColor,r.clearDepth=!0===s.autoClearDepth,r.clearStencil=!0===s.autoClearStencil}else r.clearColor=!1,r.clearDepth=!1,r.clearStencil=!1}}let fb=0;class yb{constructor(e="",t=[],r=0,s=[]){this.name=e,this.bindings=t,this.index=r,this.bindingsReference=s,this.id=fb++}}class xb{constructor(e,t,r,s,i,n,o,a,u,l=[]){this.vertexShader=e,this.fragmentShader=t,this.computeShader=r,this.transforms=l,this.nodeAttributes=s,this.bindings=i,this.updateNodes=n,this.updateBeforeNodes=o,this.updateAfterNodes=a,this.monitor=u,this.usedTimes=0}createBindings(){const e=[];for(const t of this.bindings){if(!0!==t.bindings[0].groupNode.shared){const r=new yb(t.name,[],t.index,t);e.push(r);for(const e of t.bindings)r.bindings.push(e.clone())}else e.push(t)}return e}}class bb{constructor(e,t,r=null){this.isNodeAttribute=!0,this.name=e,this.type=t,this.node=r}}class Tb{constructor(e,t,r){this.isNodeUniform=!0,this.name=e,this.type=t,this.node=r.getSelf()}get value(){return this.node.value}set value(e){this.node.value=e}get id(){return this.node.id}get groupNode(){return this.node.groupNode}}class _b{constructor(e,t){this.isNodeVar=!0,this.name=e,this.type=t}}class vb extends _b{constructor(e,t){super(e,t),this.needsInterpolation=!1,this.isNodeVarying=!0}}class Nb{constructor(e,t,r=""){this.name=e,this.type=t,this.code=r,Object.defineProperty(this,"isNodeCode",{value:!0})}}let Sb=0;class Ab{constructor(e=null){this.id=Sb++,this.nodesData=new WeakMap,this.parent=e}getData(e){let t=this.nodesData.get(e);return void 0===t&&null!==this.parent&&(t=this.parent.getData(e)),t}setData(e,t){this.nodesData.set(e,t)}}class Rb extends Ms{static get type(){return"StructTypeNode"}constructor(e,t){super(),this.name=e,this.types=t,this.isStructTypeNode=!0}getMemberTypes(){return this.types}}class Cb{constructor(e,t){this.name=e,this.value=t,this.boundary=0,this.itemSize=0,this.offset=0}setValue(e){this.value=e}getValue(){return this.value}}class Eb extends Cb{constructor(e,t=0){super(e,t),this.isNumberUniform=!0,this.boundary=4,this.itemSize=1}}class wb extends Cb{constructor(e,r=new t){super(e,r),this.isVector2Uniform=!0,this.boundary=8,this.itemSize=2}}class Mb extends Cb{constructor(e,t=new r){super(e,t),this.isVector3Uniform=!0,this.boundary=16,this.itemSize=3}}class Bb extends Cb{constructor(e,t=new s){super(e,t),this.isVector4Uniform=!0,this.boundary=16,this.itemSize=4}}class Ub extends Cb{constructor(t,r=new e){super(t,r),this.isColorUniform=!0,this.boundary=16,this.itemSize=3}}class Fb extends Cb{constructor(e,t=new i){super(e,t),this.isMatrix3Uniform=!0,this.boundary=48,this.itemSize=12}}class Pb extends Cb{constructor(e,t=new n){super(e,t),this.isMatrix4Uniform=!0,this.boundary=64,this.itemSize=16}}class Ib extends Eb{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class Lb extends wb{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class Vb extends Mb{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class Db extends Bb{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class Ob extends Ub{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class Gb extends Fb{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class kb extends Pb{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}const zb=[.125,.215,.35,.446,.526,.582],$b=20,Hb=new be(-1,1,1,-1,0,1),Wb=new Ue(90,1),jb=new e;let qb=null,Kb=0,Xb=0;const Yb=(1+Math.sqrt(5))/2,Qb=1/Yb,Zb=[new r(-Yb,Qb,0),new r(Yb,Qb,0),new r(-Qb,0,Yb),new r(Qb,0,Yb),new r(0,Yb,-Qb),new r(0,Yb,Qb),new r(-1,1,-1),new r(1,1,-1),new r(-1,1,1),new r(1,1,1)],Jb=[3,1,5,0,4,2],eT=Dp(pu(),hu("faceIndex")).normalize(),tT=Ii(eT.x,eT.y,eT.z);class rT{constructor(e){this._renderer=e,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._lodPlanes=[],this._sizeLods=[],this._sigmas=[],this._lodMeshes=[],this._blurMaterial=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._backgroundBox=null}get _hasInitialized(){return this._renderer.hasInitialized()}fromScene(e,t=0,r=.1,s=100,i=null){if(this._setSize(256),!1===this._hasInitialized){console.warn("THREE.PMREMGenerator: .fromScene() called before the backend is initialized. Try using .fromSceneAsync() instead.");const n=i||this._allocateTargets();return this.fromSceneAsync(e,t,r,s,n),n}qb=this._renderer.getRenderTarget(),Kb=this._renderer.getActiveCubeFace(),Xb=this._renderer.getActiveMipmapLevel();const n=i||this._allocateTargets();return n.depthBuffer=!0,this._sceneToCubeUV(e,r,s,n),t>0&&this._blur(n,0,0,t),this._applyPMREM(n),this._cleanup(n),n}async fromSceneAsync(e,t=0,r=.1,s=100,i=null){return!1===this._hasInitialized&&await this._renderer.init(),this.fromScene(e,t,r,s,i)}fromEquirectangular(e,t=null){if(!1===this._hasInitialized){console.warn("THREE.PMREMGenerator: .fromEquirectangular() called before the backend is initialized. Try using .fromEquirectangularAsync() instead."),this._setSizeFromTexture(e);const r=t||this._allocateTargets();return this.fromEquirectangularAsync(e,r),r}return this._fromTexture(e,t)}async fromEquirectangularAsync(e,t=null){return!1===this._hasInitialized&&await this._renderer.init(),this._fromTexture(e,t)}fromCubemap(e,t=null){if(!1===this._hasInitialized){console.warn("THREE.PMREMGenerator: .fromCubemap() called before the backend is initialized. Try using .fromCubemapAsync() instead."),this._setSizeFromTexture(e);const r=t||this._allocateTargets();return this.fromCubemapAsync(e,t),r}return this._fromTexture(e,t)}async fromCubemapAsync(e,t=null){return!1===this._hasInitialized&&await this._renderer.init(),this._fromTexture(e,t)}async compileCubemapShader(){null===this._cubemapMaterial&&(this._cubemapMaterial=oT(),await this._compileMaterial(this._cubemapMaterial))}async compileEquirectangularShader(){null===this._equirectMaterial&&(this._equirectMaterial=aT(),await this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),null!==this._cubemapMaterial&&this._cubemapMaterial.dispose(),null!==this._equirectMaterial&&this._equirectMaterial.dispose(),null!==this._backgroundBox&&(this._backgroundBox.geometry.dispose(),this._backgroundBox.material.dispose())}_setSizeFromTexture(e){e.mapping===_||e.mapping===v?this._setSize(0===e.image.length?16:e.image[0].width||e.image[0].image.width):this._setSize(e.image.width/4)}_setSize(e){this._lodMax=Math.floor(Math.log2(e)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){null!==this._blurMaterial&&this._blurMaterial.dispose(),null!==this._pingPongRenderTarget&&this._pingPongRenderTarget.dispose();for(let e=0;ee-4?u=zb[a-e+4-1]:0===a&&(u=0),s.push(u);const l=1/(o-2),d=-l,c=1+l,h=[d,d,c,d,c,c,d,d,c,c,d,c],p=6,g=6,m=3,f=2,y=1,x=new Float32Array(m*g*p),b=new Float32Array(f*g*p),T=new Float32Array(y*g*p);for(let e=0;e2?0:-1,s=[t,r,0,t+2/3,r,0,t+2/3,r+1,0,t,r,0,t+2/3,r+1,0,t,r+1,0],i=Jb[e];x.set(s,m*g*i),b.set(h,f*g*i);const n=[i,i,i,i,i,i];T.set(n,y*g*i)}const _=new Te;_.setAttribute("position",new ve(x,m)),_.setAttribute("uv",new ve(b,f)),_.setAttribute("faceIndex",new ve(T,y)),t.push(_),i.push(new k(_,null)),n>4&&n--}return{lodPlanes:t,sizeLods:r,sigmas:s,lodMeshes:i}}(i)),this._blurMaterial=function(e,t,s){const i=Sl(new Array($b).fill(0)),n=tn(new r(0,1,0)),o=tn(0),a=Ci($b),u=tn(0),l=tn(1),d=bu(null),c=tn(0),h=Ci(1/t),p=Ci(1/s),g=Ci(e),m={n:a,latitudinal:u,weights:i,poleAxis:n,outputDirection:tT,dTheta:o,samples:l,envMap:d,mipInt:c,CUBEUV_TEXEL_WIDTH:h,CUBEUV_TEXEL_HEIGHT:p,CUBEUV_MAX_MIP:g},f=nT("blur");return f.uniforms=m,f.fragmentNode=zp({...m,latitudinal:u.equal(1)}),f}(i,e,t)}return i}async _compileMaterial(e){const t=new k(this._lodPlanes[0],e);await this._renderer.compile(t,Hb)}_sceneToCubeUV(e,t,r,s){const i=Wb;i.near=t,i.far=r;const n=[1,1,1,1,-1,1],o=[1,-1,1,-1,1,-1],a=this._renderer,u=a.autoClear;a.getClearColor(jb),a.autoClear=!1;let l=this._backgroundBox;if(null===l){const e=new Q({name:"PMREM.Background",side:T,depthWrite:!1,depthTest:!1});l=new k(new G,e)}let d=!1;const c=e.background;c?c.isColor&&(l.material.color.copy(c),e.background=null,d=!0):(l.material.color.copy(jb),d=!0),a.setRenderTarget(s),a.clear(),d&&a.render(l,i);for(let t=0;t<6;t++){const r=t%3;0===r?(i.up.set(0,n[t],0),i.lookAt(o[t],0,0)):1===r?(i.up.set(0,0,n[t]),i.lookAt(0,o[t],0)):(i.up.set(0,n[t],0),i.lookAt(0,0,o[t]));const u=this._cubeSize;iT(s,r*u,t>2?u:0,u,u),a.render(e,i)}a.autoClear=u,e.background=c}_textureToCubeUV(e,t){const r=this._renderer,s=e.mapping===_||e.mapping===v;s?null===this._cubemapMaterial&&(this._cubemapMaterial=oT(e)):null===this._equirectMaterial&&(this._equirectMaterial=aT(e));const i=s?this._cubemapMaterial:this._equirectMaterial;i.fragmentNode.value=e;const n=this._lodMeshes[0];n.material=i;const o=this._cubeSize;iT(t,0,0,3*o,2*o),r.setRenderTarget(t),r.render(n,Hb)}_applyPMREM(e){const t=this._renderer,r=t.autoClear;t.autoClear=!1;const s=this._lodPlanes.length;for(let t=1;t$b&&console.warn(`sigmaRadians, ${i}, is too large and will clip, as it requested ${g} samples when the maximum is set to 20`);const m=[];let f=0;for(let e=0;e<$b;++e){const t=e/p,r=Math.exp(-t*t/2);m.push(r),0===e?f+=r:ey-4?s-y+4:0),4*(this._cubeSize-x),3*x,2*x),a.setRenderTarget(t),a.render(l,Hb)}}function sT(e,t,r){const s=new ge(e,t,r);return s.texture.mapping=Be,s.texture.name="PMREM.cubeUv",s.texture.isPMREMTexture=!0,s.scissorTest=!0,s}function iT(e,t,r,s,i){e.viewport.set(t,r,s,i),e.scissor.set(t,r,s,i)}function nT(e){const t=new Yc;return t.depthTest=!1,t.depthWrite=!1,t.blending=V,t.name=`PMREM_${e}`,t}function oT(e){const t=nT("cubemap");return t.fragmentNode=bl(e,tT),t}function aT(e){const t=nT("equirect");return t.fragmentNode=bu(e,hh(tT),0),t}const uT=new WeakMap,lT=new Map([[Int8Array,"int"],[Int16Array,"int"],[Int32Array,"int"],[Uint8Array,"uint"],[Uint16Array,"uint"],[Uint32Array,"uint"],[Float32Array,"float"]]),dT=e=>/e/g.test(e)?String(e).replace(/\+/g,""):(e=Number(e))+(e%1?"":".0");class cT{constructor(e,t,r){this.object=e,this.material=e&&e.material||null,this.geometry=e&&e.geometry||null,this.renderer=t,this.parser=r,this.scene=null,this.camera=null,this.nodes=[],this.sequentialNodes=[],this.updateNodes=[],this.updateBeforeNodes=[],this.updateAfterNodes=[],this.hashNodes={},this.monitor=null,this.lightsNode=null,this.environmentNode=null,this.fogNode=null,this.clippingContext=null,this.vertexShader=null,this.fragmentShader=null,this.computeShader=null,this.flowNodes={vertex:[],fragment:[],compute:[]},this.flowCode={vertex:"",fragment:"",compute:""},this.uniforms={vertex:[],fragment:[],compute:[],index:0},this.structs={vertex:[],fragment:[],compute:[],index:0},this.bindings={vertex:{},fragment:{},compute:{}},this.bindingsIndexes={},this.bindGroups=null,this.attributes=[],this.bufferAttributes=[],this.varyings=[],this.codes={},this.vars={},this.flow={code:""},this.chaining=[],this.stack=lm(),this.stacks=[],this.tab="\t",this.currentFunctionNode=null,this.context={material:this.material},this.cache=new Ab,this.globalCache=this.cache,this.flowsData=new WeakMap,this.shaderStage=null,this.buildStage=null,this.useComparisonMethod=!1}getBindGroupsCache(){let e=uT.get(this.renderer);return void 0===e&&(e=new Rg,uT.set(this.renderer,e)),e}createRenderTarget(e,t,r){return new ge(e,t,r)}createCubeRenderTarget(e,t){return new ph(e,t)}createPMREMGenerator(){return new rT(this.renderer)}includes(e){return this.nodes.includes(e)}_getBindGroup(e,t){const r=this.getBindGroupsCache(),s=[];let i,n=!0;for(const e of t)s.push(e),n=n&&!0!==e.groupNode.shared;return n?(i=r.get(s),void 0===i&&(i=new yb(e,s,this.bindingsIndexes[e].group,s),r.set(s,i))):i=new yb(e,s,this.bindingsIndexes[e].group,s),i}getBindGroupArray(e,t){const r=this.bindings[t];let s=r[e];return void 0===s&&(void 0===this.bindingsIndexes[e]&&(this.bindingsIndexes[e]={binding:0,group:Object.keys(this.bindingsIndexes).length}),r[e]=s=[]),s}getBindings(){let e=this.bindGroups;if(null===e){const t={},r=this.bindings;for(const e of Cs)for(const s in r[e]){const i=r[e][s];(t[s]||(t[s]=[])).push(...i)}e=[];for(const r in t){const s=t[r],i=this._getBindGroup(r,s);e.push(i)}this.bindGroups=e}return e}sortBindingGroups(){const e=this.getBindings();e.sort(((e,t)=>e.bindings[0].groupNode.order-t.bindings[0].groupNode.order));for(let t=0;t=0?`${Math.round(n)}u`:"0u";if("bool"===i)return n?"true":"false";if("color"===i)return`${this.getType("vec3")}( ${dT(n.r)}, ${dT(n.g)}, ${dT(n.b)} )`;const o=this.getTypeLength(i),a=this.getComponentType(i),u=e=>this.generateConst(a,e);if(2===o)return`${this.getType(i)}( ${u(n.x)}, ${u(n.y)} )`;if(3===o)return`${this.getType(i)}( ${u(n.x)}, ${u(n.y)}, ${u(n.z)} )`;if(4===o)return`${this.getType(i)}( ${u(n.x)}, ${u(n.y)}, ${u(n.z)}, ${u(n.w)} )`;if(o>4&&n&&(n.isMatrix3||n.isMatrix4))return`${this.getType(i)}( ${n.elements.map(u).join(", ")} )`;if(o>4)return`${this.getType(i)}()`;throw new Error(`NodeBuilder: Type '${i}' not found in generate constant attempt.`)}getType(e){return"color"===e?"vec3":e}hasGeometryAttribute(e){return this.geometry&&void 0!==this.geometry.getAttribute(e)}getAttribute(e,t){const r=this.attributes;for(const t of r)if(t.name===e)return t;const s=new bb(e,t);return r.push(s),s}getPropertyName(e){return e.name}isVector(e){return/vec\d/.test(e)}isMatrix(e){return/mat\d/.test(e)}isReference(e){return"void"===e||"property"===e||"sampler"===e||"texture"===e||"cubeTexture"===e||"storageTexture"===e||"depthTexture"===e||"texture3D"===e}needsToWorkingColorSpace(){return!1}getComponentTypeFromTexture(e){const t=e.type;if(e.isDataTexture){if(t===b)return"int";if(t===x)return"uint"}return"float"}getElementType(e){return"mat2"===e?"vec2":"mat3"===e?"vec3":"mat4"===e?"vec4":this.getComponentType(e)}getComponentType(e){if("float"===(e=this.getVectorType(e))||"bool"===e||"int"===e||"uint"===e)return e;const t=/(b|i|u|)(vec|mat)([2-4])/.exec(e);return null===t?null:"b"===t[1]?"bool":"i"===t[1]?"int":"u"===t[1]?"uint":"float"}getVectorType(e){return"color"===e?"vec3":"texture"===e||"cubeTexture"===e||"storageTexture"===e||"texture3D"===e?"vec4":e}getTypeFromLength(e,t="float"){if(1===e)return t;const r=gs(e);return("float"===t?"":t[0])+r}getTypeFromArray(e){return lT.get(e.constructor)}getTypeFromAttribute(e){let t=e;e.isInterleavedBufferAttribute&&(t=e.data);const r=t.array,s=e.itemSize,i=e.normalized;let n;return e instanceof Le||!0===i||(n=this.getTypeFromArray(r)),this.getTypeFromLength(s,n)}getTypeLength(e){const t=this.getVectorType(e),r=/vec([2-4])/.exec(t);return null!==r?Number(r[1]):"float"===t||"bool"===t||"int"===t||"uint"===t?1:!0===/mat2/.test(e)?4:!0===/mat3/.test(e)?9:!0===/mat4/.test(e)?16:0}getVectorFromMatrix(e){return e.replace("mat","vec")}changeComponentType(e,t){return this.getTypeFromLength(this.getTypeLength(e),t)}getIntegerType(e){const t=this.getComponentType(e);return"int"===t||"uint"===t?e:this.changeComponentType(e,"int")}addStack(){return this.stack=lm(this.stack),this.stacks.push(Ni()||this.stack),vi(this.stack),this.stack}removeStack(){const e=this.stack;return this.stack=e.parent,vi(this.stacks.pop()),e}getDataFromNode(e,t=this.shaderStage,r=null){let s=(r=null===r?e.isGlobal(this)?this.globalCache:this.cache:r).getData(e);return void 0===s&&(s={},r.setData(e,s)),void 0===s[t]&&(s[t]={}),s[t]}getNodeProperties(e,t="any"){const r=this.getDataFromNode(e,t);return r.properties||(r.properties={outputNode:null})}getBufferAttributeFromNode(e,t){const r=this.getDataFromNode(e);let s=r.bufferAttribute;if(void 0===s){const i=this.uniforms.index++;s=new bb("nodeAttribute"+i,t,e),this.bufferAttributes.push(s),r.bufferAttribute=s}return s}getStructTypeFromNode(e,t,r=this.shaderStage){const s=this.getDataFromNode(e,r);let i=s.structType;if(void 0===i){const e=this.structs.index++;i=new Rb("StructType"+e,t),this.structs[r].push(i),s.structType=i}return i}getUniformFromNode(e,t,r=this.shaderStage,s=null){const i=this.getDataFromNode(e,r,this.globalCache);let n=i.uniform;if(void 0===n){const o=this.uniforms.index++;n=new Tb(s||"nodeUniform"+o,t,e),this.uniforms[r].push(n),i.uniform=n}return n}getVarFromNode(e,t=null,r=e.getNodeType(this),s=this.shaderStage){const i=this.getDataFromNode(e,s);let n=i.variable;if(void 0===n){const e=this.vars[s]||(this.vars[s]=[]);null===t&&(t="nodeVar"+e.length),n=new _b(t,r),e.push(n),i.variable=n}return n}getVaryingFromNode(e,t=null,r=e.getNodeType(this)){const s=this.getDataFromNode(e,"any");let i=s.varying;if(void 0===i){const e=this.varyings,n=e.length;null===t&&(t="nodeVarying"+n),i=new vb(t,r),e.push(i),s.varying=i}return i}getCodeFromNode(e,t,r=this.shaderStage){const s=this.getDataFromNode(e);let i=s.code;if(void 0===i){const e=this.codes[r]||(this.codes[r]=[]),n=e.length;i=new Nb("nodeCode"+n,t),e.push(i),s.code=i}return i}addFlowCodeHierarchy(e,t){const{flowCodes:r,flowCodeBlock:s}=this.getDataFromNode(e);let i=!0,n=t;for(;n;){if(!0===s.get(n)){i=!1;break}n=this.getDataFromNode(n).parentNodeBlock}if(i)for(const e of r)this.addLineFlowCode(e)}addLineFlowCodeBlock(e,t,r){const s=this.getDataFromNode(e),i=s.flowCodes||(s.flowCodes=[]),n=s.flowCodeBlock||(s.flowCodeBlock=new WeakMap);i.push(t),n.set(r,!0)}addLineFlowCode(e,t=null){return""===e||(null!==t&&this.context.nodeBlock&&this.addLineFlowCodeBlock(t,e,this.context.nodeBlock),e=this.tab+e,/;\s*$/.test(e)||(e+=";\n"),this.flow.code+=e),this}addFlowCode(e){return this.flow.code+=e,this}addFlowTab(){return this.tab+="\t",this}removeFlowTab(){return this.tab=this.tab.slice(0,-1),this}getFlowData(e){return this.flowsData.get(e)}flowNode(e){const t=e.getNodeType(this),r=this.flowChildNode(e,t);return this.flowsData.set(e,r),r}buildFunctionNode(e){const t=new oy,r=this.currentFunctionNode;return this.currentFunctionNode=t,t.code=this.buildFunctionCode(e),this.currentFunctionNode=r,t}flowShaderNode(e){const t=e.layout,r={[Symbol.iterator](){let e=0;const t=Object.values(this);return{next:()=>({value:t[e],done:e++>=t.length})}}};for(const e of t.inputs)r[e.name]=new am(e.type,e.name);e.layout=null;const s=e.call(r),i=this.flowStagesNode(s,t.type);return e.layout=t,i}flowStagesNode(e,t=null){const r=this.flow,s=this.vars,i=this.cache,n=this.buildStage,o=this.stack,a={code:""};this.flow=a,this.vars={},this.cache=new Ab,this.stack=lm();for(const r of Rs)this.setBuildStage(r),a.result=e.build(this,t);return a.vars=this.getVars(this.shaderStage),this.flow=r,this.vars=s,this.cache=i,this.stack=o,this.setBuildStage(n),a}getFunctionOperator(){return null}flowChildNode(e,t=null){const r=this.flow,s={code:""};return this.flow=s,s.result=e.build(this,t),this.flow=r,s}flowNodeFromShaderStage(e,t,r=null,s=null){const i=this.shaderStage;this.setShaderStage(e);const n=this.flowChildNode(t,r);return null!==s&&(n.code+=`${this.tab+s} = ${n.result};\n`),this.flowCode[e]=this.flowCode[e]+n.code,this.setShaderStage(i),n}getAttributesArray(){return this.attributes.concat(this.bufferAttributes)}getAttributes(){console.warn("Abstract function.")}getVaryings(){console.warn("Abstract function.")}getVar(e,t){return`${this.getType(e)} ${t}`}getVars(e){let t="";const r=this.vars[e];if(void 0!==r)for(const e of r)t+=`${this.getVar(e.type,e.name)}; `;return t}getUniforms(){console.warn("Abstract function.")}getCodes(e){const t=this.codes[e];let r="";if(void 0!==t)for(const e of t)r+=e.code+"\n";return r}getHash(){return this.vertexShader+this.fragmentShader+this.computeShader}setShaderStage(e){this.shaderStage=e}getShaderStage(){return this.shaderStage}setBuildStage(e){this.buildStage=e}getBuildStage(){return this.buildStage}buildCode(){console.warn("Abstract function.")}build(){const{object:e,material:t,renderer:r}=this;if(null!==t){let e=r.library.fromMaterial(t);null===e&&(console.error(`NodeMaterial: Material "${t.type}" is not compatible.`),e=new Yc),e.build(this)}else this.addFlow("compute",e);for(const e of Rs){this.setBuildStage(e),this.context.vertex&&this.context.vertex.isNode&&this.flowNodeFromShaderStage("vertex",this.context.vertex);for(const t of Cs){this.setShaderStage(t);const r=this.flowNodes[t];for(const t of r)"generate"===e?this.flowNode(t):t.build(this)}}return this.setBuildStage(null),this.setShaderStage(null),this.buildCode(),this.buildUpdateNodes(),this}getNodeUniform(e,t){if("float"===t||"int"===t||"uint"===t)return new Ib(e);if("vec2"===t||"ivec2"===t||"uvec2"===t)return new Lb(e);if("vec3"===t||"ivec3"===t||"uvec3"===t)return new Vb(e);if("vec4"===t||"ivec4"===t||"uvec4"===t)return new Db(e);if("color"===t)return new Ob(e);if("mat3"===t)return new Gb(e);if("mat4"===t)return new kb(e);throw new Error(`Uniform "${t}" not declared.`)}format(e,t,r){if((t=this.getVectorType(t))===(r=this.getVectorType(r))||null===r||this.isReference(r))return e;const s=this.getTypeLength(t),i=this.getTypeLength(r);return 16===s&&9===i?`${this.getType(r)}(${e}[0].xyz, ${e}[1].xyz, ${e}[2].xyz)`:9===s&&4===i?`${this.getType(r)}(${e}[0].xy, ${e}[1].xy)`:s>4||i>4||0===i?e:s===i?`${this.getType(r)}( ${e} )`:s>i?this.format(`${e}.${"xyz".slice(0,i)}`,this.getTypeFromLength(i,this.getComponentType(t)),r):4===i&&s>1?`${this.getType(r)}( ${this.format(e,t,"vec3")}, 1.0 )`:2===s?`${this.getType(r)}( ${this.format(e,t,"vec2")}, 0.0 )`:(1===s&&i>1&&t!==this.getComponentType(r)&&(e=`${this.getType(this.getComponentType(r))}( ${e} )`),`${this.getType(r)}( ${e} )`)}getSignature(){return`// Three.js r${Ve} - Node System\n`}createNodeMaterial(e="NodeMaterial"){throw new Error(`THREE.NodeBuilder: createNodeMaterial() was deprecated. Use new ${e}() instead.`)}}class hT{constructor(){this.time=0,this.deltaTime=0,this.frameId=0,this.renderId=0,this.updateMap=new WeakMap,this.updateBeforeMap=new WeakMap,this.updateAfterMap=new WeakMap,this.renderer=null,this.material=null,this.camera=null,this.object=null,this.scene=null}_getMaps(e,t){let r=e.get(t);return void 0===r&&(r={renderMap:new WeakMap,frameMap:new WeakMap},e.set(t,r)),r}updateBeforeNode(e){const t=e.getUpdateBeforeType(),r=e.updateReference(this);if(t===vs.FRAME){const{frameMap:t}=this._getMaps(this.updateBeforeMap,r);t.get(r)!==this.frameId&&!1!==e.updateBefore(this)&&t.set(r,this.frameId)}else if(t===vs.RENDER){const{renderMap:t}=this._getMaps(this.updateBeforeMap,r);t.get(r)!==this.renderId&&!1!==e.updateBefore(this)&&t.set(r,this.renderId)}else t===vs.OBJECT&&e.updateBefore(this)}updateAfterNode(e){const t=e.getUpdateAfterType(),r=e.updateReference(this);if(t===vs.FRAME){const{frameMap:t}=this._getMaps(this.updateAfterMap,r);t.get(r)!==this.frameId&&!1!==e.updateAfter(this)&&t.set(r,this.frameId)}else if(t===vs.RENDER){const{renderMap:t}=this._getMaps(this.updateAfterMap,r);t.get(r)!==this.renderId&&!1!==e.updateAfter(this)&&t.set(r,this.renderId)}else t===vs.OBJECT&&e.updateAfter(this)}updateNode(e){const t=e.getUpdateType(),r=e.updateReference(this);if(t===vs.FRAME){const{frameMap:t}=this._getMaps(this.updateMap,r);t.get(r)!==this.frameId&&!1!==e.update(this)&&t.set(r,this.frameId)}else if(t===vs.RENDER){const{renderMap:t}=this._getMaps(this.updateMap,r);t.get(r)!==this.renderId&&!1!==e.update(this)&&t.set(r,this.renderId)}else t===vs.OBJECT&&e.update(this)}update(){this.frameId++,void 0===this.lastTime&&(this.lastTime=performance.now()),this.deltaTime=(performance.now()-this.lastTime)/1e3,this.lastTime=performance.now(),this.time+=this.deltaTime}}class pT{constructor(e,t,r=null,s="",i=!1){this.type=e,this.name=t,this.count=r,this.qualifier=s,this.isConst=i}}pT.isNodeFunctionInput=!0;class gT extends ax{static get type(){return"DirectionalLightNode"}constructor(e=null){super(e)}setup(e){super.setup(e);const t=e.context.lightingModel,r=this.colorNode,s=zy(this.light),i=e.context.reflectedLight;t.direct({lightDirection:s,lightColor:r,reflectedLight:i},e.stack,e)}}const mT=new n,fT=new n;let yT=null;class xT extends ax{static get type(){return"RectAreaLightNode"}constructor(e=null){super(e),this.halfHeight=tn(new r).setGroup(Zi),this.halfWidth=tn(new r).setGroup(Zi),this.updateType=vs.RENDER}update(e){super.update(e);const{light:t}=this,r=e.camera.matrixWorldInverse;fT.identity(),mT.copy(t.matrixWorld),mT.premultiply(r),fT.extractRotation(mT),this.halfWidth.value.set(.5*t.width,0,0),this.halfHeight.value.set(0,.5*t.height,0),this.halfWidth.value.applyMatrix4(fT),this.halfHeight.value.applyMatrix4(fT)}setup(e){let t,r;super.setup(e),e.isAvailable("float32Filterable")?(t=bu(yT.LTC_FLOAT_1),r=bu(yT.LTC_FLOAT_2)):(t=bu(yT.LTC_HALF_1),r=bu(yT.LTC_HALF_2));const{colorNode:s,light:i}=this,n=e.context.lightingModel,o=ky(i),a=e.context.reflectedLight;n.directRectArea({lightColor:s,lightPosition:o,halfWidth:this.halfWidth,halfHeight:this.halfHeight,reflectedLight:a,ltc_1:t,ltc_2:r},e.stack,e)}static setLTC(e){yT=e}}class bT extends ax{static get type(){return"SpotLightNode"}constructor(e=null){super(e),this.coneCosNode=tn(0).setGroup(Zi),this.penumbraCosNode=tn(0).setGroup(Zi),this.cutoffDistanceNode=tn(0).setGroup(Zi),this.decayExponentNode=tn(0).setGroup(Zi)}update(e){super.update(e);const{light:t}=this;this.coneCosNode.value=Math.cos(t.angle),this.penumbraCosNode.value=Math.cos(t.angle*(1-t.penumbra)),this.cutoffDistanceNode.value=t.distance,this.decayExponentNode.value=t.decay}getSpotAttenuation(e){const{coneCosNode:t,penumbraCosNode:r}=this;return pa(t,r,e)}setup(e){super.setup(e);const t=e.context.lightingModel,{colorNode:r,cutoffDistanceNode:s,decayExponentNode:i,light:n}=this,o=ky(n).sub(Zu),a=o.normalize(),u=a.dot(zy(n)),l=this.getSpotAttenuation(u),d=o.length(),c=ux({lightDistance:d,cutoffDistance:s,decayExponent:i});let h=r.mul(l).mul(c);if(n.map){const e=Dy(n),t=bu(n.map,e.xy).onRenderUpdate((()=>n.map));h=e.mul(2).sub(1).abs().lessThan(1).all().select(h.mul(t),h)}const p=e.context.reflectedLight;t.direct({lightDirection:a,lightColor:h,reflectedLight:p},e.stack,e)}}class TT extends bT{static get type(){return"IESSpotLightNode"}getSpotAttenuation(e){const t=this.light.iesMap;let r=null;if(t&&!0===t.isTexture){const s=e.acos().mul(1/Math.PI);r=bu(t,Bi(s,0),0).r}else r=super.getSpotAttenuation(e);return r}}class _T extends ax{static get type(){return"AmbientLightNode"}constructor(e=null){super(e)}setup({context:e}){e.irradiance.addAssign(this.colorNode)}}class vT extends ax{static get type(){return"HemisphereLightNode"}constructor(t=null){super(t),this.lightPositionNode=Oy(t),this.lightDirectionNode=this.lightPositionNode.normalize(),this.groundColorNode=tn(new e).setGroup(Zi)}update(e){const{light:t}=this;super.update(e),this.lightPositionNode.object3d=t,this.groundColorNode.value.copy(t.groundColor).multiplyScalar(t.intensity)}setup(e){const{colorNode:t,groundColorNode:r,lightDirectionNode:s}=this,i=ol.dot(s).mul(.5).add(.5),n=la(r,t,i);e.context.irradiance.addAssign(n)}}class NT extends ax{static get type(){return"LightProbeNode"}constructor(e=null){super(e);const t=[];for(let e=0;e<9;e++)t.push(new r);this.lightProbe=Sl(t)}update(e){const{light:t}=this;super.update(e);for(let e=0;e<9;e++)this.lightProbe.array[e].copy(t.sh.coefficients[e]).multiplyScalar(t.intensity)}setup(e){const t=hb(al,this.lightProbe);e.context.irradiance.addAssign(t)}}class ST{parseFunction(){console.warn("Abstract function.")}}class AT{constructor(e,t,r="",s=""){this.type=e,this.inputs=t,this.name=r,this.precision=s}getCode(){console.warn("Abstract function.")}}AT.isNodeFunction=!0;const RT=/^\s*(highp|mediump|lowp)?\s*([a-z_0-9]+)\s*([a-z_0-9]+)?\s*\(([\s\S]*?)\)/i,CT=/[a-z_0-9]+/gi,ET="#pragma main";class wT extends AT{constructor(e){const{type:t,inputs:r,name:s,precision:i,inputsCode:n,blockCode:o,headerCode:a}=(e=>{const t=(e=e.trim()).indexOf(ET),r=-1!==t?e.slice(t+12):e,s=r.match(RT);if(null!==s&&5===s.length){const i=s[4],n=[];let o=null;for(;null!==(o=CT.exec(i));)n.push(o);const a=[];let u=0;for(;u0||e.backgroundBlurriness>0&&0===t.backgroundBlurriness;if(t.background!==r||s){let s=null;if(!0===r.isCubeTexture||r.mapping===j||r.mapping===q||r.mapping===Be)if(e.backgroundBlurriness>0||r.mapping===Be)s=qp(r);else{let e;e=!0===r.isCubeTexture?bl(r):bu(r),s=xh(e)}else!0===r.isTexture?s=bu(r,bc.flipY()).setUpdateMatrix(!0):!0!==r.isColor&&console.error("WebGPUNodes: Unsupported background configuration.",r);t.backgroundNode=s,t.background=r,t.backgroundBlurriness=e.backgroundBlurriness}}else t.backgroundNode&&(delete t.backgroundNode,delete t.background)}updateFog(e){const t=this.get(e),r=e.fog;if(r){if(t.fog!==r){let e=null;if(r.isFogExp2){const t=Cl("color","color",r).setGroup(Zi),s=Cl("density","float",r).setGroup(Zi);e=xy(t,yy(s))}else if(r.isFog){const t=Cl("color","color",r).setGroup(Zi),s=Cl("near","float",r).setGroup(Zi),i=Cl("far","float",r).setGroup(Zi);e=xy(t,fy(s,i))}else console.error("WebGPUNodes: Unsupported fog configuration.",r);t.fogNode=e,t.fog=r}}else delete t.fogNode,delete t.fog}updateEnvironment(e){const t=this.get(e),r=e.environment;if(r){if(t.environment!==r){let e=null;!0===r.isCubeTexture?e=bl(r):!0===r.isTexture?e=bu(r):console.error("Nodes: Unsupported environment configuration.",r),t.environmentNode=e,t.environment=r}}else t.environmentNode&&(delete t.environmentNode,delete t.environment)}getNodeFrame(e=this.renderer,t=null,r=null,s=null,i=null){const n=this.nodeFrame;return n.renderer=e,n.scene=t,n.object=r,n.camera=s,n.material=i,n}getNodeFrameForRender(e){return this.getNodeFrame(e.renderer,e.scene,e.object,e.camera,e.material)}getOutputCacheKey(){const e=this.renderer;return e.toneMapping+","+e.currentColorSpace}hasOutputChange(e){return BT.get(e)!==this.getOutputCacheKey()}getOutputNode(e){const t=this.renderer,r=this.getOutputCacheKey(),s=bu(e,bc).renderOutput(t.toneMapping,t.currentColorSpace);return BT.set(e,r),s}updateBefore(e){const t=e.getNodeBuilderState();for(const r of t.updateBeforeNodes)this.getNodeFrameForRender(e).updateBeforeNode(r)}updateAfter(e){const t=e.getNodeBuilderState();for(const r of t.updateAfterNodes)this.getNodeFrameForRender(e).updateAfterNode(r)}updateForCompute(e){const t=this.getNodeFrame(),r=this.getForCompute(e);for(const e of r.updateNodes)t.updateNode(e)}updateForRender(e){const t=this.getNodeFrameForRender(e),r=e.getNodeBuilderState();for(const e of r.updateNodes)t.updateNode(e)}needsRefresh(e){const t=this.getNodeFrameForRender(e);return e.getMonitor().needsRefresh(e,t)}dispose(){super.dispose(),this.nodeFrame=new hT,this.nodeBuilderCache=new Map}}const FT=new me;class PT{constructor(e=null){this.version=0,this.clipIntersection=null,this.cacheKey="",null===e?(this.intersectionPlanes=[],this.unionPlanes=[],this.viewNormalMatrix=new i,this.clippingGroupContexts=new WeakMap,this.shadowPass=!1):(this.viewNormalMatrix=e.viewNormalMatrix,this.clippingGroupContexts=e.clippingGroupContexts,this.shadowPass=e.shadowPass,this.viewMatrix=e.viewMatrix),this.parentVersion=null}projectPlanes(e,t,r){const s=e.length;for(let i=0;i{await this.compileAsync(e,t);const s=this._renderLists.get(e,t),i=this._renderContexts.get(e,t,this._renderTarget),n=e.overrideMaterial||r.material,o=this._objects.get(r,n,e,t,s.lightsNode,i,i.clippingContext),{fragmentShader:a,vertexShader:u}=o.getNodeBuilderState();return{fragmentShader:a,vertexShader:u}}}}async init(){if(this._initialized)throw new Error("Renderer: Backend has already been initialized.");return null!==this._initPromise||(this._initPromise=new Promise((async(e,t)=>{let r=this.backend;try{await r.init(this)}catch(e){if(null===this._getFallback)return void t(e);try{this.backend=r=this._getFallback(e),await r.init(this)}catch(e){return void t(e)}}this._nodes=new UT(this,r),this._animation=new Ag(this._nodes,this.info),this._attributes=new Vg(r),this._background=new mb(this,this._nodes),this._geometries=new Gg(this._attributes,this.info),this._textures=new nm(this,r,this.info),this._pipelines=new qg(r,this._nodes),this._bindings=new Kg(r,this._nodes,this._textures,this._attributes,this._pipelines,this.info),this._objects=new Mg(this,this._nodes,this._geometries,this._pipelines,this._bindings,this.info),this._renderLists=new Jg(this.lighting),this._bundles=new LT,this._renderContexts=new sm,this._animation.start(),this._initialized=!0,e()}))),this._initPromise}get coordinateSystem(){return this.backend.coordinateSystem}async compileAsync(e,t,r=null){if(!0===this._isDeviceLost)return;!1===this._initialized&&await this.init();const s=this._nodes.nodeFrame,i=s.renderId,n=this._currentRenderContext,o=this._currentRenderObjectFunction,a=this._compilationPromises,u=!0===e.isScene?e:GT;null===r&&(r=e);const l=this._renderTarget,d=this._renderContexts.get(r,t,l),c=this._activeMipmapLevel,h=[];this._currentRenderContext=d,this._currentRenderObjectFunction=this.renderObject,this._handleObjectFunction=this._createObjectPipeline,this._compilationPromises=h,s.renderId++,s.update(),d.depth=this.depth,d.stencil=this.stencil,d.clippingContext||(d.clippingContext=new PT),d.clippingContext.updateGlobal(u,t),u.onBeforeRender(this,e,t,l);const p=this._renderLists.get(e,t);if(p.begin(),this._projectObject(e,t,0,p,d.clippingContext),r!==e&&r.traverseVisible((function(e){e.isLight&&e.layers.test(t.layers)&&p.pushLight(e)})),p.finish(),null!==l){this._textures.updateRenderTarget(l,c);const e=this._textures.get(l);d.textures=e.textures,d.depthTexture=e.depthTexture}else d.textures=null,d.depthTexture=null;this._nodes.updateScene(u),this._background.update(u,p,d);const g=p.opaque,m=p.transparent,f=p.transparentDoublePass,y=p.lightsNode;!0===this.opaque&&g.length>0&&this._renderObjects(g,t,u,y),!0===this.transparent&&m.length>0&&this._renderTransparents(m,f,t,u,y),s.renderId=i,this._currentRenderContext=n,this._currentRenderObjectFunction=o,this._compilationPromises=a,this._handleObjectFunction=this._renderObjectDirect,await Promise.all(h)}async renderAsync(e,t){!1===this._initialized&&await this.init();const r=this._renderScene(e,t);await this.backend.resolveTimestampAsync(r,"render")}async waitForGPU(){await this.backend.waitForGPU()}setMRT(e){return this._mrt=e,this}getMRT(){return this._mrt}_onDeviceLost(e){let t=`THREE.WebGPURenderer: ${e.api} Device Lost:\n\nMessage: ${e.message}`;e.reason&&(t+=`\nReason: ${e.reason}`),console.error(t),this._isDeviceLost=!0}_renderBundle(e,t,r){const{bundleGroup:s,camera:i,renderList:n}=e,o=this._currentRenderContext,a=this._bundles.get(s,i),u=this.backend.get(a);void 0===u.renderContexts&&(u.renderContexts=new Set);const l=s.version!==u.version,d=!1===u.renderContexts.has(o)||l;if(u.renderContexts.add(o),d){this.backend.beginBundle(o),(void 0===u.renderObjects||l)&&(u.renderObjects=[]),this._currentRenderBundle=a;const e=n.opaque;!0===this.opaque&&e.length>0&&this._renderObjects(e,i,t,r),this._currentRenderBundle=null,this.backend.finishBundle(o,a),u.version=s.version}else{const{renderObjects:e}=u;for(let t=0,r=e.length;t>=c,p.viewportValue.height>>=c,p.viewportValue.minDepth=x,p.viewportValue.maxDepth=b,p.viewport=!1===p.viewportValue.equals(zT),p.scissorValue.copy(f).multiplyScalar(y).floor(),p.scissor=this._scissorTest&&!1===p.scissorValue.equals(zT),p.scissorValue.width>>=c,p.scissorValue.height>>=c,p.clippingContext||(p.clippingContext=new PT),p.clippingContext.updateGlobal(u,t),u.onBeforeRender(this,e,t,h),HT.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),$T.setFromProjectionMatrix(HT,g);const T=this._renderLists.get(e,t);if(T.begin(),this._projectObject(e,t,0,T,p.clippingContext),T.finish(),!0===this.sortObjects&&T.sort(this._opaqueSort,this._transparentSort),null!==h){this._textures.updateRenderTarget(h,c);const e=this._textures.get(h);p.textures=e.textures,p.depthTexture=e.depthTexture,p.width=e.width,p.height=e.height,p.renderTarget=h,p.depth=h.depthBuffer,p.stencil=h.stencilBuffer}else p.textures=null,p.depthTexture=null,p.width=this.domElement.width,p.height=this.domElement.height,p.depth=this.depth,p.stencil=this.stencil;p.width>>=c,p.height>>=c,p.activeCubeFace=d,p.activeMipmapLevel=c,p.occlusionQueryCount=T.occlusionQueryCount,this._nodes.updateScene(u),this._background.update(u,T,p),this.backend.beginRender(p);const{bundles:_,lightsNode:v,transparentDoublePass:N,transparent:S,opaque:A}=T;if(_.length>0&&this._renderBundles(_,u,v),!0===this.opaque&&A.length>0&&this._renderObjects(A,t,u,v),!0===this.transparent&&S.length>0&&this._renderTransparents(S,N,t,u,v),this.backend.finishRender(p),i.renderId=n,this._currentRenderContext=o,this._currentRenderObjectFunction=a,null!==s){this.setRenderTarget(l,d,c);const e=this._quad;this._nodes.hasOutputChange(h.texture)&&(e.material.fragmentNode=this._nodes.getOutputNode(h.texture),e.material.needsUpdate=!0),this._renderScene(e,e.camera,!1)}return u.onAfterRender(this,e,t,h),p}getMaxAnisotropy(){return this.backend.getMaxAnisotropy()}getActiveCubeFace(){return this._activeCubeFace}getActiveMipmapLevel(){return this._activeMipmapLevel}async setAnimationLoop(e){!1===this._initialized&&await this.init(),this._animation.setAnimationLoop(e)}async getArrayBufferAsync(e){return await this.backend.getArrayBufferAsync(e)}getContext(){return this.backend.getContext()}getPixelRatio(){return this._pixelRatio}getDrawingBufferSize(e){return e.set(this._width*this._pixelRatio,this._height*this._pixelRatio).floor()}getSize(e){return e.set(this._width,this._height)}setPixelRatio(e=1){this._pixelRatio!==e&&(this._pixelRatio=e,this.setSize(this._width,this._height,!1))}setDrawingBufferSize(e,t,r){this._width=e,this._height=t,this._pixelRatio=r,this.domElement.width=Math.floor(e*r),this.domElement.height=Math.floor(t*r),this.setViewport(0,0,e,t),this._initialized&&this.backend.updateSize()}setSize(e,t,r=!0){this._width=e,this._height=t,this.domElement.width=Math.floor(e*this._pixelRatio),this.domElement.height=Math.floor(t*this._pixelRatio),!0===r&&(this.domElement.style.width=e+"px",this.domElement.style.height=t+"px"),this.setViewport(0,0,e,t),this._initialized&&this.backend.updateSize()}setOpaqueSort(e){this._opaqueSort=e}setTransparentSort(e){this._transparentSort=e}getScissor(e){const t=this._scissor;return e.x=t.x,e.y=t.y,e.width=t.width,e.height=t.height,e}setScissor(e,t,r,s){const i=this._scissor;e.isVector4?i.copy(e):i.set(e,t,r,s)}getScissorTest(){return this._scissorTest}setScissorTest(e){this._scissorTest=e,this.backend.setScissorTest(e)}getViewport(e){return e.copy(this._viewport)}setViewport(e,t,r,s,i=0,n=1){const o=this._viewport;e.isVector4?o.copy(e):o.set(e,t,r,s),o.minDepth=i,o.maxDepth=n}getClearColor(e){return e.copy(this._clearColor)}setClearColor(e,t=1){this._clearColor.set(e),this._clearColor.a=t}getClearAlpha(){return this._clearColor.a}setClearAlpha(e){this._clearColor.a=e}getClearDepth(){return this._clearDepth}setClearDepth(e){this._clearDepth=e}getClearStencil(){return this._clearStencil}setClearStencil(e){this._clearStencil=e}isOccluded(e){const t=this._currentRenderContext;return t&&this.backend.isOccluded(t,e)}clear(e=!0,t=!0,r=!0){if(!1===this._initialized)return console.warn("THREE.Renderer: .clear() called before the backend is initialized. Try using .clearAsync() instead."),this.clearAsync(e,t,r);const s=this._renderTarget||this._getFrameBufferTarget();let i=null;if(null!==s&&(this._textures.updateRenderTarget(s),i=this._textures.get(s)),this.backend.clear(e,t,r,i),null!==s&&null===this._renderTarget){const e=this._quad;this._nodes.hasOutputChange(s.texture)&&(e.material.fragmentNode=this._nodes.getOutputNode(s.texture),e.material.needsUpdate=!0),this._renderScene(e,e.camera,!1)}}clearColor(){return this.clear(!0,!1,!1)}clearDepth(){return this.clear(!1,!0,!1)}clearStencil(){return this.clear(!1,!1,!0)}async clearAsync(e=!0,t=!0,r=!0){!1===this._initialized&&await this.init(),this.clear(e,t,r)}clearColorAsync(){return this.clearAsync(!0,!1,!1)}clearDepthAsync(){return this.clearAsync(!1,!0,!1)}clearStencilAsync(){return this.clearAsync(!1,!1,!0)}get currentToneMapping(){return null!==this._renderTarget?h:this.toneMapping}get currentColorSpace(){return null!==this._renderTarget?Ae:this.outputColorSpace}dispose(){this.info.dispose(),this.backend.dispose(),this._animation.dispose(),this._objects.dispose(),this._pipelines.dispose(),this._nodes.dispose(),this._bindings.dispose(),this._renderLists.dispose(),this._renderContexts.dispose(),this._textures.dispose(),this.setRenderTarget(null),this.setAnimationLoop(null)}setRenderTarget(e,t=0,r=0){this._renderTarget=e,this._activeCubeFace=t,this._activeMipmapLevel=r}getRenderTarget(){return this._renderTarget}setRenderObjectFunction(e){this._renderObjectFunction=e}getRenderObjectFunction(){return this._renderObjectFunction}compute(e){if(!0===this.isDeviceLost)return;if(!1===this._initialized)return console.warn("THREE.Renderer: .compute() called before the backend is initialized. Try using .computeAsync() instead."),this.computeAsync(e);const t=this._nodes.nodeFrame,r=t.renderId;this.info.calls++,this.info.compute.calls++,this.info.compute.frameCalls++,t.renderId=this.info.calls;const s=this.backend,i=this._pipelines,n=this._bindings,o=this._nodes,a=Array.isArray(e)?e:[e];if(void 0===a[0]||!0!==a[0].isComputeNode)throw new Error("THREE.Renderer: .compute() expects a ComputeNode.");s.beginCompute(e);for(const t of a){if(!1===i.has(t)){const e=()=>{t.removeEventListener("dispose",e),i.delete(t),n.delete(t),o.delete(t)};t.addEventListener("dispose",e);const r=t.onInitFunction;null!==r&&r.call(t,{renderer:this})}o.updateForCompute(t),n.updateForCompute(t);const r=n.getForCompute(t),a=i.getForCompute(t,r);s.compute(e,t,r,a)}s.finishCompute(e),t.renderId=r}async computeAsync(e){!1===this._initialized&&await this.init(),this.compute(e),await this.backend.resolveTimestampAsync(e,"compute")}async hasFeatureAsync(e){return!1===this._initialized&&await this.init(),this.backend.hasFeature(e)}hasFeature(e){return!1===this._initialized?(console.warn("THREE.Renderer: .hasFeature() called before the backend is initialized. Try using .hasFeatureAsync() instead."),!1):this.backend.hasFeature(e)}hasInitialized(){return this._initialized}async initTextureAsync(e){!1===this._initialized&&await this.init(),this._textures.updateTexture(e)}initTexture(e){if(!1===this._initialized)return console.warn("THREE.Renderer: .initTexture() called before the backend is initialized. Try using .initTextureAsync() instead."),!1;this._textures.updateTexture(e)}copyFramebufferToTexture(e,t=null){if(null!==t)if(t.isVector2)t=WT.set(t.x,t.y,e.image.width,e.image.height).floor();else{if(!t.isVector4)return void console.error("THREE.Renderer.copyFramebufferToTexture: Invalid rectangle.");t=WT.copy(t).floor()}else t=WT.set(0,0,e.image.width,e.image.height);let r,s=this._currentRenderContext;null!==s?r=s.renderTarget:(r=this._renderTarget||this._getFrameBufferTarget(),null!==r&&(this._textures.updateRenderTarget(r),s=this._textures.get(r))),this._textures.updateTexture(e,{renderTarget:r}),this.backend.copyFramebufferToTexture(e,s,t)}copyTextureToTexture(e,t,r=null,s=null,i=0){this._textures.updateTexture(e),this._textures.updateTexture(t),this.backend.copyTextureToTexture(e,t,r,s,i)}readRenderTargetPixelsAsync(e,t,r,s,i,n=0,o=0){return this.backend.copyTextureToBuffer(e.textures[n],t,r,s,i,o)}_projectObject(e,t,r,s,i){if(!1===e.visible)return;if(e.layers.test(t.layers))if(e.isGroup)r=e.renderOrder,e.isClippingGroup&&e.enabled&&(i=i.getGroupContext(e));else if(e.isLOD)!0===e.autoUpdate&&e.update(t);else if(e.isLight)s.pushLight(e);else if(e.isSprite){if(!e.frustumCulled||$T.intersectsSprite(e)){!0===this.sortObjects&&WT.setFromMatrixPosition(e.matrixWorld).applyMatrix4(HT);const{geometry:t,material:n}=e;n.visible&&s.push(e,t,n,r,WT.z,null,i)}}else if(e.isLineLoop)console.error("THREE.Renderer: Objects of type THREE.LineLoop are not supported. Please use THREE.Line or THREE.LineSegments.");else if((e.isMesh||e.isLine||e.isPoints)&&(!e.frustumCulled||$T.intersectsObject(e))){const{geometry:t,material:n}=e;if(!0===this.sortObjects&&(null===t.boundingSphere&&t.computeBoundingSphere(),WT.copy(t.boundingSphere.center).applyMatrix4(e.matrixWorld).applyMatrix4(HT)),Array.isArray(n)){const o=t.groups;for(let a=0,u=o.length;a0){for(const{material:e}of t)e.side=T;this._renderObjects(t,r,s,i,"backSide");for(const{material:e}of t)e.side=Ge;this._renderObjects(e,r,s,i);for(const{material:e}of t)e.side=le}else this._renderObjects(e,r,s,i)}_renderObjects(e,t,r,s,i=null){for(let n=0,o=e.length;n0,e.isShadowNodeMaterial&&(e.side=null===i.shadowSide?i.side:i.shadowSide,i.depthNode&&i.depthNode.isNode&&(c=e.depthNode,e.depthNode=i.depthNode),i.castShadowNode&&i.castShadowNode.isNode&&(d=e.colorNode,e.colorNode=i.castShadowNode)),i=e}!0===i.transparent&&i.side===le&&!1===i.forceSinglePass?(i.side=T,this._handleObjectFunction(e,i,t,r,o,n,a,"backSide"),i.side=Ge,this._handleObjectFunction(e,i,t,r,o,n,a,u),i.side=le):this._handleObjectFunction(e,i,t,r,o,n,a,u),void 0!==l&&(t.overrideMaterial.positionNode=l),void 0!==c&&(t.overrideMaterial.depthNode=c),void 0!==d&&(t.overrideMaterial.colorNode=d),e.onAfterRender(this,t,r,s,i,n)}_renderObjectDirect(e,t,r,s,i,n,o,a){const u=this._objects.get(e,t,r,s,i,this._currentRenderContext,o,a);u.drawRange=e.geometry.drawRange,u.group=n;const l=this._nodes.needsRefresh(u);if(l&&(this._nodes.updateBefore(u),this._geometries.updateForRender(u),this._nodes.updateForRender(u),this._bindings.updateForRender(u)),this._pipelines.updateForRender(u),null!==this._currentRenderBundle){this.backend.get(this._currentRenderBundle).renderObjects.push(u),u.bundle=this._currentRenderBundle.scene}this.backend.draw(u,this.info),l&&this._nodes.updateAfter(u)}_createObjectPipeline(e,t,r,s,i,n,o,a){const u=this._objects.get(e,t,r,s,i,this._currentRenderContext,o,a);u.drawRange=e.geometry.drawRange,u.group=n,this._nodes.updateBefore(u),this._geometries.updateForRender(u),this._nodes.updateForRender(u),this._bindings.updateForRender(u),this._pipelines.getForRender(u,this._compilationPromises),this._nodes.updateAfter(u)}get compile(){return this.compileAsync}}class qT{constructor(e=""){this.name=e,this.visibility=0}setVisibility(e){this.visibility|=e}clone(){return Object.assign(new this.constructor,this)}}class KT extends qT{constructor(e,t=null){super(e),this.isBuffer=!0,this.bytesPerElement=Float32Array.BYTES_PER_ELEMENT,this._buffer=t}get byteLength(){return(e=this._buffer.byteLength)+(Lg-e%Lg)%Lg;var e}get buffer(){return this._buffer}update(){return!0}}class XT extends KT{constructor(e,t=null){super(e,t),this.isUniformBuffer=!0}}let YT=0;class QT extends XT{constructor(e,t){super("UniformBuffer_"+YT++,e?e.value:null),this.nodeUniform=e,this.groupNode=t}get buffer(){return this.nodeUniform.value}}class ZT extends XT{constructor(e){super(e),this.isUniformsGroup=!0,this._values=null,this.uniforms=[]}addUniform(e){return this.uniforms.push(e),this}removeUniform(e){const t=this.uniforms.indexOf(e);return-1!==t&&this.uniforms.splice(t,1),this}get values(){return null===this._values&&(this._values=Array.from(this.buffer)),this._values}get buffer(){let e=this._buffer;if(null===e){const t=this.byteLength;e=new Float32Array(new ArrayBuffer(t)),this._buffer=e}return e}get byteLength(){let e=0;for(let t=0,r=this.uniforms.length;t0?s:"";t=`${e.name} {\n\t${r} ${i.name}[${n}];\n};\n`}else{t=`${this.getVectorType(i.type)} ${this.getPropertyName(i,e)};`,n=!0}const o=i.node.precision;if(null!==o&&(t=a_[o]+" "+t),n){t="\t"+t;const e=i.groupNode.name;(s[e]||(s[e]=[])).push(t)}else t="uniform "+t,r.push(t)}let i="";for(const t in s){const r=s[t];i+=this._getGLSLUniformStruct(e+"_"+t,r.join("\n"))+"\n"}return i+=r.join("\n"),i}getTypeFromAttribute(e){let t=super.getTypeFromAttribute(e);if(/^[iu]/.test(t)&&e.gpuType!==b){let r=e;e.isInterleavedBufferAttribute&&(r=e.data);const s=r.array;!1==(s instanceof Uint32Array||s instanceof Int32Array)&&(t=t.slice(1))}return t}getAttributes(e){let t="";if("vertex"===e||"compute"===e){const e=this.getAttributesArray();let r=0;for(const s of e)t+=`layout( location = ${r++} ) in ${s.type} ${s.name};\n`}return t}getStructMembers(e){const t=[],r=e.getMemberTypes();for(let e=0;ee*t),1)}u`}getDrawIndex(){return this.renderer.backend.extensions.has("WEBGL_multi_draw")?"uint( gl_DrawID )":null}getFrontFacing(){return"gl_FrontFacing"}getFragCoord(){return"gl_FragCoord.xy"}getFragDepth(){return"gl_FragDepth"}enableExtension(e,t,r=this.shaderStage){const s=this.extensions[r]||(this.extensions[r]=new Map);!1===s.has(e)&&s.set(e,{name:e,behavior:t})}getExtensions(e){const t=[];if("vertex"===e){const t=this.renderer.backend.extensions;this.object.isBatchedMesh&&t.has("WEBGL_multi_draw")&&this.enableExtension("GL_ANGLE_multi_draw","require",e)}const r=this.extensions[e];if(void 0!==r)for(const{name:e,behavior:s}of r.values())t.push(`#extension ${e} : ${s}`);return t.join("\n")}getClipDistance(){return"gl_ClipDistance"}isAvailable(e){let t=u_[e];if(void 0===t){let r;switch(t=!1,e){case"float32Filterable":r="OES_texture_float_linear";break;case"clipDistance":r="WEBGL_clip_cull_distance"}if(void 0!==r){const e=this.renderer.backend.extensions;e.has(r)&&(e.get(r),t=!0)}u_[e]=t}return t}isFlipY(){return!0}enableHardwareClipping(e){this.enableExtension("GL_ANGLE_clip_cull_distance","require"),this.builtins.vertex.push(`out float gl_ClipDistance[ ${e} ]`)}registerTransform(e,t){this.transforms.push({varyingName:e,attributeNode:t})}getTransforms(){const e=this.transforms;let t="";for(let r=0;r0&&(r+="\n"),r+=`\t// flow -> ${n}\n\t`),r+=`${s.code}\n\t`,e===i&&"compute"!==t&&(r+="// result\n\t","vertex"===t?(r+="gl_Position = ",r+=`${s.result};`):"fragment"===t&&(e.outputNode.isOutputStructNode||(r+="fragColor = ",r+=`${s.result};`)))}const n=e[t];n.extensions=this.getExtensions(t),n.uniforms=this.getUniforms(t),n.attributes=this.getAttributes(t),n.varyings=this.getVaryings(t),n.vars=this.getVars(t),n.structs=this.getStructs(t),n.codes=this.getCodes(t),n.transforms=this.getTransforms(t),n.flow=r}null!==this.material?(this.vertexShader=this._getGLSLVertexCode(e.vertex),this.fragmentShader=this._getGLSLFragmentCode(e.fragment)):this.computeShader=this._getGLSLVertexCode(e.compute)}getUniformFromNode(e,t,r,s=null){const i=super.getUniformFromNode(e,t,r,s),n=this.getDataFromNode(e,r,this.globalCache);let o=n.uniformGPU;if(void 0===o){const s=e.groupNode,a=s.name,u=this.getBindGroupArray(a,r);if("texture"===t)o=new s_(i.name,i.node,s),u.push(o);else if("cubeTexture"===t)o=new i_(i.name,i.node,s),u.push(o);else if("texture3D"===t)o=new n_(i.name,i.node,s),u.push(o);else if("buffer"===t){e.name=`NodeBuffer_${e.id}`,i.name=`buffer${e.id}`;const t=new QT(e,s);t.name=e.name,u.push(t),o=t}else{const e=this.uniformGroups[r]||(this.uniformGroups[r]={});let n=e[a];void 0===n&&(n=new e_(r+"_"+a,s),e[a]=n,u.push(n)),o=this.getNodeUniform(i,t),n.addUniform(o)}n.uniformGPU=o}return i}}let c_=null,h_=null,p_=null;class g_{constructor(e={}){this.parameters=Object.assign({},e),this.data=new WeakMap,this.renderer=null,this.domElement=null}async init(e){this.renderer=e}begin(){}finish(){}draw(){}createProgram(){}destroyProgram(){}createBindings(){}updateBindings(){}createRenderPipeline(){}createComputePipeline(){}destroyPipeline(){}needsRenderUpdate(){}getRenderCacheKey(){}createNodeBuilder(){}createSampler(){}createDefaultTexture(){}createTexture(){}copyTextureToBuffer(){}createAttribute(){}createIndexAttribute(){}updateAttribute(){}destroyAttribute(){}getContext(){}updateSize(){}resolveTimestampAsync(){}hasFeatureAsync(){}hasFeature(){}getInstanceCount(e){const{object:t,geometry:r}=e;return r.isInstancedBufferGeometry?r.instanceCount:t.count>1?t.count:1}getDrawingBufferSize(){return c_=c_||new t,this.renderer.getDrawingBufferSize(c_)}getScissor(){return h_=h_||new s,this.renderer.getScissor(h_)}setScissorTest(){}getClearColor(){const e=this.renderer;return p_=p_||new om,e.getClearColor(p_),p_.getRGB(p_,this.renderer.currentColorSpace),p_}getDomElement(){let e=this.domElement;return null===e&&(e=void 0!==this.parameters.canvas?this.parameters.canvas:Ze(),"setAttribute"in e&&e.setAttribute("data-engine",`three.js r${Ve} webgpu`),this.domElement=e),e}set(e,t){this.data.set(e,t)}get(e){let t=this.data.get(e);return void 0===t&&(t={},this.data.set(e,t)),t}has(e){return this.data.has(e)}delete(e){this.data.delete(e)}dispose(){}}let m_=0;class f_{constructor(e,t){this.buffers=[e.bufferGPU,t],this.type=e.type,this.bufferType=e.bufferType,this.pbo=e.pbo,this.byteLength=e.byteLength,this.bytesPerElement=e.BYTES_PER_ELEMENT,this.version=e.version,this.isInteger=e.isInteger,this.activeBufferIndex=0,this.baseId=e.id}get id(){return`${this.baseId}|${this.activeBufferIndex}`}get bufferGPU(){return this.buffers[this.activeBufferIndex]}get transformBuffer(){return this.buffers[1^this.activeBufferIndex]}switchBuffers(){this.activeBufferIndex^=1}}class y_{constructor(e){this.backend=e}createAttribute(e,t){const r=this.backend,{gl:s}=r,i=e.array,n=e.usage||s.STATIC_DRAW,o=e.isInterleavedBufferAttribute?e.data:e,a=r.get(o);let u,l=a.bufferGPU;if(void 0===l&&(l=this._createBuffer(s,t,i,n),a.bufferGPU=l,a.bufferType=t,a.version=o.version),i instanceof Float32Array)u=s.FLOAT;else if(i instanceof Uint16Array)u=e.isFloat16BufferAttribute?s.HALF_FLOAT:s.UNSIGNED_SHORT;else if(i instanceof Int16Array)u=s.SHORT;else if(i instanceof Uint32Array)u=s.UNSIGNED_INT;else if(i instanceof Int32Array)u=s.INT;else if(i instanceof Int8Array)u=s.BYTE;else if(i instanceof Uint8Array)u=s.UNSIGNED_BYTE;else{if(!(i instanceof Uint8ClampedArray))throw new Error("THREE.WebGLBackend: Unsupported buffer data format: "+i);u=s.UNSIGNED_BYTE}let d={bufferGPU:l,bufferType:t,type:u,byteLength:i.byteLength,bytesPerElement:i.BYTES_PER_ELEMENT,version:e.version,pbo:e.pbo,isInteger:u===s.INT||u===s.UNSIGNED_INT||e.gpuType===b,id:m_++};if(e.isStorageBufferAttribute||e.isStorageInstancedBufferAttribute){const e=this._createBuffer(s,t,i,n);d=new f_(d,e)}r.set(e,d)}updateAttribute(e){const t=this.backend,{gl:r}=t,s=e.array,i=e.isInterleavedBufferAttribute?e.data:e,n=t.get(i),o=n.bufferType,a=e.isInterleavedBufferAttribute?e.data.updateRanges:e.updateRanges;if(r.bindBuffer(o,n.bufferGPU),0===a.length)r.bufferSubData(o,0,s);else{for(let e=0,t=a.length;e1?this.enable(s.SAMPLE_ALPHA_TO_COVERAGE):this.disable(s.SAMPLE_ALPHA_TO_COVERAGE),r>0&&this.currentClippingPlanes!==r){const e=12288;for(let t=0;t<8;t++)t{!function i(){const n=e.clientWaitSync(t,e.SYNC_FLUSH_COMMANDS_BIT,0);if(n===e.WAIT_FAILED)return e.deleteSync(t),void s();n!==e.TIMEOUT_EXPIRED?(e.deleteSync(t),r()):requestAnimationFrame(i)}()}))}}let N_,S_,A_,R_=!1;class C_{constructor(e){this.backend=e,this.gl=e.gl,this.extensions=e.extensions,this.defaultTextures={},!1===R_&&(this._init(this.gl),R_=!0)}_init(e){N_={[dr]:e.REPEAT,[cr]:e.CLAMP_TO_EDGE,[hr]:e.MIRRORED_REPEAT},S_={[pr]:e.NEAREST,[gr]:e.NEAREST_MIPMAP_NEAREST,[Ie]:e.NEAREST_MIPMAP_LINEAR,[$]:e.LINEAR,[Pe]:e.LINEAR_MIPMAP_NEAREST,[M]:e.LINEAR_MIPMAP_LINEAR},A_={[mr]:e.NEVER,[fr]:e.ALWAYS,[Re]:e.LESS,[yr]:e.LEQUAL,[xr]:e.EQUAL,[br]:e.GEQUAL,[Tr]:e.GREATER,[_r]:e.NOTEQUAL}}filterFallback(e){const{gl:t}=this;return e===pr||e===gr||e===Ie?t.NEAREST:t.LINEAR}getGLTextureType(e){const{gl:t}=this;let r;return r=!0===e.isCubeTexture?t.TEXTURE_CUBE_MAP:!0===e.isDataArrayTexture||!0===e.isCompressedArrayTexture?t.TEXTURE_2D_ARRAY:!0===e.isData3DTexture?t.TEXTURE_3D:t.TEXTURE_2D,r}getInternalFormat(e,t,r,s,i=!1){const{gl:n,extensions:o}=this;if(null!==e){if(void 0!==n[e])return n[e];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+e+"'")}let a=t;return t===n.RED&&(r===n.FLOAT&&(a=n.R32F),r===n.HALF_FLOAT&&(a=n.R16F),r===n.UNSIGNED_BYTE&&(a=n.R8),r===n.UNSIGNED_SHORT&&(a=n.R16),r===n.UNSIGNED_INT&&(a=n.R32UI),r===n.BYTE&&(a=n.R8I),r===n.SHORT&&(a=n.R16I),r===n.INT&&(a=n.R32I)),t===n.RED_INTEGER&&(r===n.UNSIGNED_BYTE&&(a=n.R8UI),r===n.UNSIGNED_SHORT&&(a=n.R16UI),r===n.UNSIGNED_INT&&(a=n.R32UI),r===n.BYTE&&(a=n.R8I),r===n.SHORT&&(a=n.R16I),r===n.INT&&(a=n.R32I)),t===n.RG&&(r===n.FLOAT&&(a=n.RG32F),r===n.HALF_FLOAT&&(a=n.RG16F),r===n.UNSIGNED_BYTE&&(a=n.RG8),r===n.UNSIGNED_SHORT&&(a=n.RG16),r===n.UNSIGNED_INT&&(a=n.RG32UI),r===n.BYTE&&(a=n.RG8I),r===n.SHORT&&(a=n.RG16I),r===n.INT&&(a=n.RG32I)),t===n.RG_INTEGER&&(r===n.UNSIGNED_BYTE&&(a=n.RG8UI),r===n.UNSIGNED_SHORT&&(a=n.RG16UI),r===n.UNSIGNED_INT&&(a=n.RG32UI),r===n.BYTE&&(a=n.RG8I),r===n.SHORT&&(a=n.RG16I),r===n.INT&&(a=n.RG32I)),t===n.RGB&&(r===n.FLOAT&&(a=n.RGB32F),r===n.HALF_FLOAT&&(a=n.RGB16F),r===n.UNSIGNED_BYTE&&(a=n.RGB8),r===n.UNSIGNED_SHORT&&(a=n.RGB16),r===n.UNSIGNED_INT&&(a=n.RGB32UI),r===n.BYTE&&(a=n.RGB8I),r===n.SHORT&&(a=n.RGB16I),r===n.INT&&(a=n.RGB32I),r===n.UNSIGNED_BYTE&&(a=s===De&&!1===i?n.SRGB8:n.RGB8),r===n.UNSIGNED_SHORT_5_6_5&&(a=n.RGB565),r===n.UNSIGNED_SHORT_5_5_5_1&&(a=n.RGB5_A1),r===n.UNSIGNED_SHORT_4_4_4_4&&(a=n.RGB4),r===n.UNSIGNED_INT_5_9_9_9_REV&&(a=n.RGB9_E5)),t===n.RGB_INTEGER&&(r===n.UNSIGNED_BYTE&&(a=n.RGB8UI),r===n.UNSIGNED_SHORT&&(a=n.RGB16UI),r===n.UNSIGNED_INT&&(a=n.RGB32UI),r===n.BYTE&&(a=n.RGB8I),r===n.SHORT&&(a=n.RGB16I),r===n.INT&&(a=n.RGB32I)),t===n.RGBA&&(r===n.FLOAT&&(a=n.RGBA32F),r===n.HALF_FLOAT&&(a=n.RGBA16F),r===n.UNSIGNED_BYTE&&(a=n.RGBA8),r===n.UNSIGNED_SHORT&&(a=n.RGBA16),r===n.UNSIGNED_INT&&(a=n.RGBA32UI),r===n.BYTE&&(a=n.RGBA8I),r===n.SHORT&&(a=n.RGBA16I),r===n.INT&&(a=n.RGBA32I),r===n.UNSIGNED_BYTE&&(a=s===De&&!1===i?n.SRGB8_ALPHA8:n.RGBA8),r===n.UNSIGNED_SHORT_4_4_4_4&&(a=n.RGBA4),r===n.UNSIGNED_SHORT_5_5_5_1&&(a=n.RGB5_A1)),t===n.RGBA_INTEGER&&(r===n.UNSIGNED_BYTE&&(a=n.RGBA8UI),r===n.UNSIGNED_SHORT&&(a=n.RGBA16UI),r===n.UNSIGNED_INT&&(a=n.RGBA32UI),r===n.BYTE&&(a=n.RGBA8I),r===n.SHORT&&(a=n.RGBA16I),r===n.INT&&(a=n.RGBA32I)),t===n.DEPTH_COMPONENT&&(r===n.UNSIGNED_INT&&(a=n.DEPTH24_STENCIL8),r===n.FLOAT&&(a=n.DEPTH_COMPONENT32F)),t===n.DEPTH_STENCIL&&r===n.UNSIGNED_INT_24_8&&(a=n.DEPTH24_STENCIL8),a!==n.R16F&&a!==n.R32F&&a!==n.RG16F&&a!==n.RG32F&&a!==n.RGBA16F&&a!==n.RGBA32F||o.get("EXT_color_buffer_float"),a}setTextureParameters(e,t){const{gl:r,extensions:s,backend:i}=this;r.pixelStorei(r.UNPACK_FLIP_Y_WEBGL,t.flipY),r.pixelStorei(r.UNPACK_PREMULTIPLY_ALPHA_WEBGL,t.premultiplyAlpha),r.pixelStorei(r.UNPACK_ALIGNMENT,t.unpackAlignment),r.pixelStorei(r.UNPACK_COLORSPACE_CONVERSION_WEBGL,r.NONE),r.texParameteri(e,r.TEXTURE_WRAP_S,N_[t.wrapS]),r.texParameteri(e,r.TEXTURE_WRAP_T,N_[t.wrapT]),e!==r.TEXTURE_3D&&e!==r.TEXTURE_2D_ARRAY||r.texParameteri(e,r.TEXTURE_WRAP_R,N_[t.wrapR]),r.texParameteri(e,r.TEXTURE_MAG_FILTER,S_[t.magFilter]);const n=void 0!==t.mipmaps&&t.mipmaps.length>0,o=t.minFilter===$&&n?M:t.minFilter;if(r.texParameteri(e,r.TEXTURE_MIN_FILTER,S_[o]),t.compareFunction&&(r.texParameteri(e,r.TEXTURE_COMPARE_MODE,r.COMPARE_REF_TO_TEXTURE),r.texParameteri(e,r.TEXTURE_COMPARE_FUNC,A_[t.compareFunction])),!0===s.has("EXT_texture_filter_anisotropic")){if(t.magFilter===pr)return;if(t.minFilter!==Ie&&t.minFilter!==M)return;if(t.type===E&&!1===s.has("OES_texture_float_linear"))return;if(t.anisotropy>1){const n=s.get("EXT_texture_filter_anisotropic");r.texParameterf(e,n.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(t.anisotropy,i.getMaxAnisotropy()))}}}createDefaultTexture(e){const{gl:t,backend:r,defaultTextures:s}=this,i=this.getGLTextureType(e);let n=s[i];void 0===n&&(n=t.createTexture(),r.state.bindTexture(i,n),t.texParameteri(i,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(i,t.TEXTURE_MAG_FILTER,t.NEAREST),s[i]=n),r.set(e,{textureGPU:n,glTextureType:i,isDefault:!0})}createTexture(e,t){const{gl:r,backend:s}=this,{levels:i,width:n,height:o,depth:a}=t,u=s.utils.convert(e.format,e.colorSpace),l=s.utils.convert(e.type),d=this.getInternalFormat(e.internalFormat,u,l,e.colorSpace,e.isVideoTexture),c=r.createTexture(),h=this.getGLTextureType(e);s.state.bindTexture(h,c),this.setTextureParameters(h,e),e.isDataArrayTexture||e.isCompressedArrayTexture?r.texStorage3D(r.TEXTURE_2D_ARRAY,i,d,n,o,a):e.isData3DTexture?r.texStorage3D(r.TEXTURE_3D,i,d,n,o,a):e.isVideoTexture||r.texStorage2D(h,i,d,n,o),s.set(e,{textureGPU:c,glTextureType:h,glFormat:u,glType:l,glInternalFormat:d})}copyBufferToTexture(e,t){const{gl:r,backend:s}=this,{textureGPU:i,glTextureType:n,glFormat:o,glType:a}=s.get(t),{width:u,height:l}=t.source.data;r.bindBuffer(r.PIXEL_UNPACK_BUFFER,e),s.state.bindTexture(n,i),r.pixelStorei(r.UNPACK_FLIP_Y_WEBGL,!1),r.pixelStorei(r.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),r.texSubImage2D(n,0,0,0,u,l,o,a,0),r.bindBuffer(r.PIXEL_UNPACK_BUFFER,null),s.state.unbindTexture()}updateTexture(e,t){const{gl:r}=this,{width:s,height:i}=t,{textureGPU:n,glTextureType:o,glFormat:a,glType:u,glInternalFormat:l}=this.backend.get(e);if(e.isRenderTargetTexture||void 0===n)return;const d=e=>e.isDataTexture?e.image.data:"undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&e instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap||e instanceof OffscreenCanvas?e:e.data;if(this.backend.state.bindTexture(o,n),this.setTextureParameters(o,e),e.isCompressedTexture){const s=e.mipmaps,i=t.image;for(let t=0;t0,c=t.renderTarget?t.renderTarget.height:this.backend.gerDrawingBufferSize().y;if(d){const r=0!==o||0!==a;let d,h;if(!0===e.isDepthTexture?(d=s.DEPTH_BUFFER_BIT,h=s.DEPTH_ATTACHMENT,t.stencil&&(d|=s.STENCIL_BUFFER_BIT)):(d=s.COLOR_BUFFER_BIT,h=s.COLOR_ATTACHMENT0),r){const e=this.backend.get(t.renderTarget),r=e.framebuffers[t.getCacheKey()],h=e.msaaFrameBuffer;i.bindFramebuffer(s.DRAW_FRAMEBUFFER,r),i.bindFramebuffer(s.READ_FRAMEBUFFER,h);const p=c-a-l;s.blitFramebuffer(o,p,o+u,p+l,o,p,o+u,p+l,d,s.NEAREST),i.bindFramebuffer(s.READ_FRAMEBUFFER,r),i.bindTexture(s.TEXTURE_2D,n),s.copyTexSubImage2D(s.TEXTURE_2D,0,0,0,o,p,u,l),i.unbindTexture()}else{const e=s.createFramebuffer();i.bindFramebuffer(s.DRAW_FRAMEBUFFER,e),s.framebufferTexture2D(s.DRAW_FRAMEBUFFER,h,s.TEXTURE_2D,n,0),s.blitFramebuffer(0,0,u,l,0,0,u,l,d,s.NEAREST),s.deleteFramebuffer(e)}}else i.bindTexture(s.TEXTURE_2D,n),s.copyTexSubImage2D(s.TEXTURE_2D,0,0,0,o,c-l-a,u,l),i.unbindTexture();e.generateMipmaps&&this.generateMipmaps(e),this.backend._setFramebuffer(t)}setupRenderBufferStorage(e,t){const{gl:r}=this,s=t.renderTarget,{samples:i,depthTexture:n,depthBuffer:o,stencilBuffer:a,width:u,height:l}=s;if(r.bindRenderbuffer(r.RENDERBUFFER,e),o&&!a){let t=r.DEPTH_COMPONENT24;i>0?(n&&n.isDepthTexture&&n.type===r.FLOAT&&(t=r.DEPTH_COMPONENT32F),r.renderbufferStorageMultisample(r.RENDERBUFFER,i,t,u,l)):r.renderbufferStorage(r.RENDERBUFFER,t,u,l),r.framebufferRenderbuffer(r.FRAMEBUFFER,r.DEPTH_ATTACHMENT,r.RENDERBUFFER,e)}else o&&a&&(i>0?r.renderbufferStorageMultisample(r.RENDERBUFFER,i,r.DEPTH24_STENCIL8,u,l):r.renderbufferStorage(r.RENDERBUFFER,r.DEPTH_STENCIL,u,l),r.framebufferRenderbuffer(r.FRAMEBUFFER,r.DEPTH_STENCIL_ATTACHMENT,r.RENDERBUFFER,e))}async copyTextureToBuffer(e,t,r,s,i,n){const{backend:o,gl:a}=this,{textureGPU:u,glFormat:l,glType:d}=this.backend.get(e),c=a.createFramebuffer();a.bindFramebuffer(a.READ_FRAMEBUFFER,c);const h=e.isCubeTexture?a.TEXTURE_CUBE_MAP_POSITIVE_X+n:a.TEXTURE_2D;a.framebufferTexture2D(a.READ_FRAMEBUFFER,a.COLOR_ATTACHMENT0,h,u,0);const p=this._getTypedArrayType(d),g=s*i*this._getBytesPerTexel(d,l),m=a.createBuffer();a.bindBuffer(a.PIXEL_PACK_BUFFER,m),a.bufferData(a.PIXEL_PACK_BUFFER,g,a.STREAM_READ),a.readPixels(t,r,s,i,l,d,0),a.bindBuffer(a.PIXEL_PACK_BUFFER,null),await o.utils._clientWaitAsync();const f=new p(g/p.BYTES_PER_ELEMENT);return a.bindBuffer(a.PIXEL_PACK_BUFFER,m),a.getBufferSubData(a.PIXEL_PACK_BUFFER,0,f),a.bindBuffer(a.PIXEL_PACK_BUFFER,null),a.deleteFramebuffer(c),f}_getTypedArrayType(e){const{gl:t}=this;if(e===t.UNSIGNED_BYTE)return Uint8Array;if(e===t.UNSIGNED_SHORT_4_4_4_4)return Uint16Array;if(e===t.UNSIGNED_SHORT_5_5_5_1)return Uint16Array;if(e===t.UNSIGNED_SHORT_5_6_5)return Uint16Array;if(e===t.UNSIGNED_SHORT)return Uint16Array;if(e===t.UNSIGNED_INT)return Uint32Array;if(e===t.HALF_FLOAT)return Uint16Array;if(e===t.FLOAT)return Float32Array;throw new Error(`Unsupported WebGL type: ${e}`)}_getBytesPerTexel(e,t){const{gl:r}=this;let s=0;return e===r.UNSIGNED_BYTE&&(s=1),e!==r.UNSIGNED_SHORT_4_4_4_4&&e!==r.UNSIGNED_SHORT_5_5_5_1&&e!==r.UNSIGNED_SHORT_5_6_5&&e!==r.UNSIGNED_SHORT&&e!==r.HALF_FLOAT||(s=2),e!==r.UNSIGNED_INT&&e!==r.FLOAT||(s=4),t===r.RGBA?4*s:t===r.RGB?3*s:t===r.ALPHA?s:void 0}}class E_{constructor(e){this.backend=e,this.gl=this.backend.gl,this.availableExtensions=this.gl.getSupportedExtensions(),this.extensions={}}get(e){let t=this.extensions[e];return void 0===t&&(t=this.gl.getExtension(e),this.extensions[e]=t),t}has(e){return this.availableExtensions.includes(e)}}class w_{constructor(e){this.backend=e,this.maxAnisotropy=null}getMaxAnisotropy(){if(null!==this.maxAnisotropy)return this.maxAnisotropy;const e=this.backend.gl,t=this.backend.extensions;if(!0===t.has("EXT_texture_filter_anisotropic")){const r=t.get("EXT_texture_filter_anisotropic");this.maxAnisotropy=e.getParameter(r.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else this.maxAnisotropy=0;return this.maxAnisotropy}}const M_={WEBGL_multi_draw:"WEBGL_multi_draw",WEBGL_compressed_texture_astc:"texture-compression-astc",WEBGL_compressed_texture_etc:"texture-compression-etc2",WEBGL_compressed_texture_etc1:"texture-compression-etc1",WEBGL_compressed_texture_pvrtc:"texture-compression-pvrtc",WEBKIT_WEBGL_compressed_texture_pvrtc:"texture-compression-pvrtc",WEBGL_compressed_texture_s3tc:"texture-compression-bc",EXT_texture_compression_bptc:"texture-compression-bptc",EXT_disjoint_timer_query_webgl2:"timestamp-query"};class B_{constructor(e){this.gl=e.gl,this.extensions=e.extensions,this.info=e.renderer.info,this.mode=null,this.index=0,this.type=null,this.object=null}render(e,t){const{gl:r,mode:s,object:i,type:n,info:o,index:a}=this;0!==a?r.drawElements(s,t,n,e):r.drawArrays(s,e,t),o.update(i,t,s,1)}renderInstances(e,t,r){const{gl:s,mode:i,type:n,index:o,object:a,info:u}=this;0!==r&&(0!==o?s.drawElementsInstanced(i,t,n,e,r):s.drawArraysInstanced(i,e,t,r),u.update(a,t,i,r))}renderMultiDraw(e,t,r){const{extensions:s,mode:i,object:n,info:o}=this;if(0===r)return;const a=s.get("WEBGL_multi_draw");if(null===a)for(let s=0;s0)){const e=t.queryQueue.shift();this.initTimestampQuery(e)}}async resolveTimestampAsync(e,t="render"){if(!this.disjoint||!this.trackTimestamp)return;const r=this.get(e);r.gpuQueries||(r.gpuQueries=[]);for(let e=0;e0&&(r.currentOcclusionQueries=r.occlusionQueries,r.currentOcclusionQueryObjects=r.occlusionQueryObjects,r.lastOcclusionObject=null,r.occlusionQueries=new Array(s),r.occlusionQueryObjects=new Array(s),r.occlusionQueryIndex=0)}finishRender(e){const{gl:t,state:r}=this,s=this.get(e),i=s.previousContext,n=e.occlusionQueryCount;n>0&&(n>s.occlusionQueryIndex&&t.endQuery(t.ANY_SAMPLES_PASSED),this.resolveOccludedAsync(e));const o=e.textures;if(null!==o)for(let e=0;e0){const i=s.framebuffers[e.getCacheKey()],n=t.COLOR_BUFFER_BIT,o=s.msaaFrameBuffer,a=e.textures;r.bindFramebuffer(t.READ_FRAMEBUFFER,o),r.bindFramebuffer(t.DRAW_FRAMEBUFFER,i);for(let r=0;r{let o=0;for(let t=0;t0&&e.add(s[t]),r[t]=null,i.deleteQuery(n),o++))}o1?f.renderInstances(b,y,x):f.render(b,y),a.bindVertexArray(null)}needsRenderUpdate(){return!1}getRenderCacheKey(){return""}createDefaultTexture(e){this.textureUtils.createDefaultTexture(e)}createTexture(e,t){this.textureUtils.createTexture(e,t)}updateTexture(e,t){this.textureUtils.updateTexture(e,t)}generateMipmaps(e){this.textureUtils.generateMipmaps(e)}destroyTexture(e){this.textureUtils.destroyTexture(e)}copyTextureToBuffer(e,t,r,s,i,n){return this.textureUtils.copyTextureToBuffer(e,t,r,s,i,n)}createSampler(){}destroySampler(){}createNodeBuilder(e,t){return new d_(e,t)}createProgram(e){const t=this.gl,{stage:r,code:s}=e,i="fragment"===r?t.createShader(t.FRAGMENT_SHADER):t.createShader(t.VERTEX_SHADER);t.shaderSource(i,s),t.compileShader(i),this.set(e,{shaderGPU:i})}destroyProgram(){console.warn("Abstract class.")}createRenderPipeline(e,t){const r=this.gl,s=e.pipeline,{fragmentProgram:i,vertexProgram:n}=s,o=r.createProgram(),a=this.get(i).shaderGPU,u=this.get(n).shaderGPU;if(r.attachShader(o,a),r.attachShader(o,u),r.linkProgram(o),this.set(s,{programGPU:o,fragmentShader:a,vertexShader:u}),null!==t&&this.parallel){const i=new Promise((t=>{const i=this.parallel,n=()=>{r.getProgramParameter(o,i.COMPLETION_STATUS_KHR)?(this._completeCompile(e,s),t()):requestAnimationFrame(n)};n()}));t.push(i)}else this._completeCompile(e,s)}_handleSource(e,t){const r=e.split("\n"),s=[],i=Math.max(t-6,0),n=Math.min(t+6,r.length);for(let e=i;e":" "} ${i}: ${r[e]}`)}return s.join("\n")}_getShaderErrors(e,t,r){const s=e.getShaderParameter(t,e.COMPILE_STATUS),i=e.getShaderInfoLog(t).trim();if(s&&""===i)return"";const n=/ERROR: 0:(\d+)/.exec(i);if(n){const s=parseInt(n[1]);return r.toUpperCase()+"\n\n"+i+"\n\n"+this._handleSource(e.getShaderSource(t),s)}return i}_logProgramError(e,t,r){if(this.renderer.debug.checkShaderErrors){const s=this.gl,i=s.getProgramInfoLog(e).trim();if(!1===s.getProgramParameter(e,s.LINK_STATUS))if("function"==typeof this.renderer.debug.onShaderError)this.renderer.debug.onShaderError(s,e,r,t);else{const n=this._getShaderErrors(s,r,"vertex"),o=this._getShaderErrors(s,t,"fragment");console.error("THREE.WebGLProgram: Shader Error "+s.getError()+" - VALIDATE_STATUS "+s.getProgramParameter(e,s.VALIDATE_STATUS)+"\n\nProgram Info Log: "+i+"\n"+n+"\n"+o)}else""!==i&&console.warn("THREE.WebGLProgram: Program Info Log:",i)}}_completeCompile(e,t){const{state:r,gl:s}=this,i=this.get(t),{programGPU:n,fragmentShader:o,vertexShader:a}=i;!1===s.getProgramParameter(n,s.LINK_STATUS)&&this._logProgramError(n,o,a),r.useProgram(n);const u=e.getBindings();this._setupBindings(u,n),this.set(t,{programGPU:n})}createComputePipeline(e,t){const{state:r,gl:s}=this,i={stage:"fragment",code:"#version 300 es\nprecision highp float;\nvoid main() {}"};this.createProgram(i);const{computeProgram:n}=e,o=s.createProgram(),a=this.get(i).shaderGPU,u=this.get(n).shaderGPU,l=n.transforms,d=[],c=[];for(let e=0;eM_[t]===e)),r=this.extensions;for(let e=0;e0){if(void 0===d){const s=[];d=t.createFramebuffer(),r.bindFramebuffer(t.FRAMEBUFFER,d);const i=[],l=e.textures;for(let r=0;r,\n\t@location( 0 ) vTex : vec2\n};\n\n@vertex\nfn main( @builtin( vertex_index ) vertexIndex : u32 ) -> VarysStruct {\n\n\tvar Varys : VarysStruct;\n\n\tvar pos = array< vec2, 4 >(\n\t\tvec2( -1.0, 1.0 ),\n\t\tvec2( 1.0, 1.0 ),\n\t\tvec2( -1.0, -1.0 ),\n\t\tvec2( 1.0, -1.0 )\n\t);\n\n\tvar tex = array< vec2, 4 >(\n\t\tvec2( 0.0, 0.0 ),\n\t\tvec2( 1.0, 0.0 ),\n\t\tvec2( 0.0, 1.0 ),\n\t\tvec2( 1.0, 1.0 )\n\t);\n\n\tVarys.vTex = tex[ vertexIndex ];\n\tVarys.Position = vec4( pos[ vertexIndex ], 0.0, 1.0 );\n\n\treturn Varys;\n\n}\n"}),this.mipmapFragmentShaderModule=e.createShaderModule({label:"mipmapFragment",code:"\n@group( 0 ) @binding( 0 )\nvar imgSampler : sampler;\n\n@group( 0 ) @binding( 1 )\nvar img : texture_2d;\n\n@fragment\nfn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 {\n\n\treturn textureSample( img, imgSampler, vTex );\n\n}\n"}),this.flipYFragmentShaderModule=e.createShaderModule({label:"flipYFragment",code:"\n@group( 0 ) @binding( 0 )\nvar imgSampler : sampler;\n\n@group( 0 ) @binding( 1 )\nvar img : texture_2d;\n\n@fragment\nfn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 {\n\n\treturn textureSample( img, imgSampler, vec2( vTex.x, 1.0 - vTex.y ) );\n\n}\n"})}getTransferPipeline(e){let t=this.transferPipelines[e];return void 0===t&&(t=this.device.createRenderPipeline({label:`mipmap-${e}`,vertex:{module:this.mipmapVertexShaderModule,entryPoint:"main"},fragment:{module:this.mipmapFragmentShaderModule,entryPoint:"main",targets:[{format:e}]},primitive:{topology:V_,stripIndexFormat:ev},layout:"auto"}),this.transferPipelines[e]=t),t}getFlipYPipeline(e){let t=this.flipYPipelines[e];return void 0===t&&(t=this.device.createRenderPipeline({label:`flipY-${e}`,vertex:{module:this.mipmapVertexShaderModule,entryPoint:"main"},fragment:{module:this.flipYFragmentShaderModule,entryPoint:"main",targets:[{format:e}]},primitive:{topology:V_,stripIndexFormat:ev},layout:"auto"}),this.flipYPipelines[e]=t),t}flipY(e,t,r=0){const s=t.format,{width:i,height:n}=t.size,o=this.getTransferPipeline(s),a=this.getFlipYPipeline(s),u=this.device.createTexture({size:{width:i,height:n,depthOrArrayLayers:1},format:s,usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.TEXTURE_BINDING}),l=e.createView({baseMipLevel:0,mipLevelCount:1,dimension:qv,baseArrayLayer:r}),d=u.createView({baseMipLevel:0,mipLevelCount:1,dimension:qv,baseArrayLayer:0}),c=this.device.createCommandEncoder({}),h=(e,t,r)=>{const s=e.getBindGroupLayout(0),i=this.device.createBindGroup({layout:s,entries:[{binding:0,resource:this.flipYSampler},{binding:1,resource:t}]}),n=c.beginRenderPass({colorAttachments:[{view:r,loadOp:K_,storeOp:j_,clearValue:[0,0,0,0]}]});n.setPipeline(e),n.setBindGroup(0,i),n.draw(4,1,0,0),n.end()};h(o,l,d),h(a,d,l),this.device.queue.submit([c.finish()]),u.destroy()}generateMipmaps(e,t,r=0){const s=this.get(e);void 0===s.useCount&&(s.useCount=0,s.layers=[]);const i=s.layers[r]||this._mipmapCreateBundles(e,t,r),n=this.device.createCommandEncoder({});this._mipmapRunBundles(n,i),this.device.queue.submit([n.finish()]),0!==s.useCount&&(s.layers[r]=i),s.useCount++}_mipmapCreateBundles(e,t,r){const s=this.getTransferPipeline(t.format),i=s.getBindGroupLayout(0);let n=e.createView({baseMipLevel:0,mipLevelCount:1,dimension:qv,baseArrayLayer:r});const o=[];for(let a=1;a1;for(let o=0;o]*\s*([a-z_0-9]+(?:<[\s\S]+?>)?)/i,hN=/([a-z_0-9]+)\s*:\s*([a-z_0-9]+(?:<[\s\S]+?>)?)/gi,pN={f32:"float",i32:"int",u32:"uint",bool:"bool","vec2":"vec2","vec2":"ivec2","vec2":"uvec2","vec2":"bvec2",vec2f:"vec2",vec2i:"ivec2",vec2u:"uvec2",vec2b:"bvec2","vec3":"vec3","vec3":"ivec3","vec3":"uvec3","vec3":"bvec3",vec3f:"vec3",vec3i:"ivec3",vec3u:"uvec3",vec3b:"bvec3","vec4":"vec4","vec4":"ivec4","vec4":"uvec4","vec4":"bvec4",vec4f:"vec4",vec4i:"ivec4",vec4u:"uvec4",vec4b:"bvec4","mat2x2":"mat2",mat2x2f:"mat2","mat3x3":"mat3",mat3x3f:"mat3","mat4x4":"mat4",mat4x4f:"mat4",sampler:"sampler",texture_1d:"texture",texture_2d:"texture",texture_2d_array:"texture",texture_multisampled_2d:"cubeTexture",texture_depth_2d:"depthTexture",texture_depth_multisampled_2d:"depthTexture",texture_3d:"texture3D",texture_cube:"cubeTexture",texture_cube_array:"cubeTexture",texture_storage_1d:"storageTexture",texture_storage_2d:"storageTexture",texture_storage_2d_array:"storageTexture",texture_storage_3d:"storageTexture"};class gN extends AT{constructor(e){const{type:t,inputs:r,name:s,inputsCode:i,blockCode:n,outputType:o}=(e=>{const t=(e=e.trim()).match(cN);if(null!==t&&4===t.length){const r=t[2],s=[];let i=null;for(;null!==(i=hN.exec(r));)s.push({name:i[1],type:i[2]});const n=[];for(let e=0;e "+this.outputType:"";return`fn ${e} ( ${this.inputsCode.trim()} ) ${t}`+this.blockCode}}class mN extends ST{parseFunction(e){return new gN(e)}}const fN="undefined"!=typeof self?self.GPUShaderStage:{VERTEX:1,FRAGMENT:2,COMPUTE:4},yN={[Ss.READ_ONLY]:"read",[Ss.WRITE_ONLY]:"write",[Ss.READ_WRITE]:"read_write"},xN={[dr]:"repeat",[cr]:"clamp",[hr]:"mirror"},bN={vertex:fN?fN.VERTEX:1,fragment:fN?fN.FRAGMENT:2,compute:fN?fN.COMPUTE:4},TN={instance:!0,swizzleAssign:!1,storageBuffer:!0},_N={"^^":"tsl_xor"},vN={float:"f32",int:"i32",uint:"u32",bool:"bool",color:"vec3",vec2:"vec2",ivec2:"vec2",uvec2:"vec2",bvec2:"vec2",vec3:"vec3",ivec3:"vec3",uvec3:"vec3",bvec3:"vec3",vec4:"vec4",ivec4:"vec4",uvec4:"vec4",bvec4:"vec4",mat2:"mat2x2",mat3:"mat3x3",mat4:"mat4x4"},NN={},SN={tsl_xor:new iy("fn tsl_xor( a : bool, b : bool ) -> bool { return ( a || b ) && !( a && b ); }"),mod_float:new iy("fn tsl_mod_float( x : f32, y : f32 ) -> f32 { return x - y * floor( x / y ); }"),mod_vec2:new iy("fn tsl_mod_vec2( x : vec2f, y : vec2f ) -> vec2f { return x - y * floor( x / y ); }"),mod_vec3:new iy("fn tsl_mod_vec3( x : vec3f, y : vec3f ) -> vec3f { return x - y * floor( x / y ); }"),mod_vec4:new iy("fn tsl_mod_vec4( x : vec4f, y : vec4f ) -> vec4f { return x - y * floor( x / y ); }"),equals_bool:new iy("fn tsl_equals_bool( a : bool, b : bool ) -> bool { return a == b; }"),equals_bvec2:new iy("fn tsl_equals_bvec2( a : vec2f, b : vec2f ) -> vec2 { return vec2( a.x == b.x, a.y == b.y ); }"),equals_bvec3:new iy("fn tsl_equals_bvec3( a : vec3f, b : vec3f ) -> vec3 { return vec3( a.x == b.x, a.y == b.y, a.z == b.z ); }"),equals_bvec4:new iy("fn tsl_equals_bvec4( a : vec4f, b : vec4f ) -> vec4 { return vec4( a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w ); }"),repeatWrapping_float:new iy("fn tsl_repeatWrapping_float( coord: f32 ) -> f32 { return fract( coord ); }"),mirrorWrapping_float:new iy("fn tsl_mirrorWrapping_float( coord: f32 ) -> f32 { let mirrored = fract( coord * 0.5 ) * 2.0; return 1.0 - abs( 1.0 - mirrored ); }"),clampWrapping_float:new iy("fn tsl_clampWrapping_float( coord: f32 ) -> f32 { return clamp( coord, 0.0, 1.0 ); }"),biquadraticTexture:new iy("\nfn tsl_biquadraticTexture( map : texture_2d, coord : vec2f, iRes : vec2u, level : u32 ) -> vec4f {\n\n\tlet res = vec2f( iRes );\n\n\tlet uvScaled = coord * res;\n\tlet uvWrapping = ( ( uvScaled % res ) + res ) % res;\n\n\t// https://www.shadertoy.com/view/WtyXRy\n\n\tlet uv = uvWrapping - 0.5;\n\tlet iuv = floor( uv );\n\tlet f = fract( uv );\n\n\tlet rg1 = textureLoad( map, vec2u( iuv + vec2( 0.5, 0.5 ) ) % iRes, level );\n\tlet rg2 = textureLoad( map, vec2u( iuv + vec2( 1.5, 0.5 ) ) % iRes, level );\n\tlet rg3 = textureLoad( map, vec2u( iuv + vec2( 0.5, 1.5 ) ) % iRes, level );\n\tlet rg4 = textureLoad( map, vec2u( iuv + vec2( 1.5, 1.5 ) ) % iRes, level );\n\n\treturn mix( mix( rg1, rg2, f.x ), mix( rg3, rg4, f.x ), f.y );\n\n}\n")},AN={dFdx:"dpdx",dFdy:"- dpdy",mod_float:"tsl_mod_float",mod_vec2:"tsl_mod_vec2",mod_vec3:"tsl_mod_vec3",mod_vec4:"tsl_mod_vec4",equals_bool:"tsl_equals_bool",equals_bvec2:"tsl_equals_bvec2",equals_bvec3:"tsl_equals_bvec3",equals_bvec4:"tsl_equals_bvec4",inversesqrt:"inverseSqrt",bitcast:"bitcast"};"undefined"!=typeof navigator&&/Windows/g.test(navigator.userAgent)&&(SN.pow_float=new iy("fn tsl_pow_float( a : f32, b : f32 ) -> f32 { return select( -pow( -a, b ), pow( a, b ), a > 0.0 ); }"),SN.pow_vec2=new iy("fn tsl_pow_vec2( a : vec2f, b : vec2f ) -> vec2f { return vec2f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ) ); }",[SN.pow_float]),SN.pow_vec3=new iy("fn tsl_pow_vec3( a : vec3f, b : vec3f ) -> vec3f { return vec3f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ), tsl_pow_float( a.z, b.z ) ); }",[SN.pow_float]),SN.pow_vec4=new iy("fn tsl_pow_vec4( a : vec4f, b : vec4f ) -> vec4f { return vec4f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ), tsl_pow_float( a.z, b.z ), tsl_pow_float( a.w, b.w ) ); }",[SN.pow_float]),AN.pow_float="tsl_pow_float",AN.pow_vec2="tsl_pow_vec2",AN.pow_vec3="tsl_pow_vec3",AN.pow_vec4="tsl_pow_vec4");let RN="";!0!==("undefined"!=typeof navigator&&/Firefox|Deno/g.test(navigator.userAgent))&&(RN+="diagnostic( off, derivative_uniformity );\n");class CN extends cT{constructor(e,t){super(e,t,new mN),this.uniformGroups={},this.builtins={},this.directives={},this.scopedArrays=new Map}needsToWorkingColorSpace(e){return!0===e.isVideoTexture&&e.colorSpace!==y}_generateTextureSample(e,t,r,s,i=this.shaderStage){return"fragment"===i?s?`textureSample( ${t}, ${t}_sampler, ${r}, ${s} )`:`textureSample( ${t}, ${t}_sampler, ${r} )`:this.isFilteredTexture(e)?this.generateFilteredTexture(e,t,r):this.generateTextureLod(e,t,r,s,"0")}_generateVideoSample(e,t,r=this.shaderStage){if("fragment"===r)return`textureSampleBaseClampToEdge( ${e}, ${e}_sampler, vec2( ${t}.x, 1.0 - ${t}.y ) )`;console.error(`WebGPURenderer: THREE.VideoTexture does not support ${r} shader.`)}_generateTextureSampleLevel(e,t,r,s,i,n=this.shaderStage){return"fragment"!==n&&"compute"!==n||!1!==this.isUnfilterable(e)?this.isFilteredTexture(e)?this.generateFilteredTexture(e,t,r,s):this.generateTextureLod(e,t,r,i,s):`textureSampleLevel( ${t}, ${t}_sampler, ${r}, ${s} )`}generateWrapFunction(e){const t=`tsl_coord_${xN[e.wrapS]}S_${xN[e.wrapT]}T`;let r=NN[t];if(void 0===r){const s=[];let i=`fn ${t}( coord : vec2f ) -> vec2f {\n\n\treturn vec2f(\n`;const n=(e,t)=>{e===dr?(s.push(SN.repeatWrapping_float),i+=`\t\ttsl_repeatWrapping_float( coord.${t} )`):e===cr?(s.push(SN.clampWrapping_float),i+=`\t\ttsl_clampWrapping_float( coord.${t} )`):e===hr?(s.push(SN.mirrorWrapping_float),i+=`\t\ttsl_mirrorWrapping_float( coord.${t} )`):(i+=`\t\tcoord.${t}`,console.warn(`WebGPURenderer: Unsupported texture wrap type "${e}" for vertex shader.`))};n(e.wrapS,"x"),i+=",\n",n(e.wrapT,"y"),i+="\n\t);\n\n}\n",NN[t]=r=new iy(i,s)}return r.build(this),t}generateTextureDimension(e,t,r){const s=this.getDataFromNode(e,this.shaderStage,this.globalCache);void 0===s.dimensionsSnippet&&(s.dimensionsSnippet={});let i=s.dimensionsSnippet[r];if(void 0===s.dimensionsSnippet[r]){let n;const{primarySamples:o}=this.renderer.backend.utils.getTextureSampleData(e);n=o>1?t:`${t}, u32( ${r} )`,i=new Aa(new ou(`textureDimensions( ${n} )`,"uvec2")),s.dimensionsSnippet[r]=i}return i.build(this)}generateFilteredTexture(e,t,r,s="0u"){this._include("biquadraticTexture");return`tsl_biquadraticTexture( ${t}, ${this.generateWrapFunction(e)}( ${r} ), ${this.generateTextureDimension(e,t,s)}, u32( ${s} ) )`}generateTextureLod(e,t,r,s,i="0u"){const n=`vec2u( ${this.generateWrapFunction(e)}( ${r} ) * vec2f( ${this.generateTextureDimension(e,t,i)} ) )`;return this.generateTextureLoad(e,t,n,s,i)}generateTextureLoad(e,t,r,s,i="0u"){return!0===e.isVideoTexture||!0===e.isStorageTexture?`textureLoad( ${t}, ${r} )`:s?`textureLoad( ${t}, ${r}, ${s}, u32( ${i} ) )`:`textureLoad( ${t}, ${r}, u32( ${i} ) )`}generateTextureStore(e,t,r,s){return`textureStore( ${t}, ${r}, ${s} )`}isSampleCompare(e){return!0===e.isDepthTexture&&null!==e.compareFunction}isUnfilterable(e){return"float"!==this.getComponentTypeFromTexture(e)||!this.isAvailable("float32Filterable")&&!0===e.isDataTexture&&e.type===E||!1===this.isSampleCompare(e)&&e.minFilter===pr&&e.magFilter===pr||this.renderer.backend.utils.getTextureSampleData(e).primarySamples>1}generateTexture(e,t,r,s,i=this.shaderStage){let n=null;return n=!0===e.isVideoTexture?this._generateVideoSample(t,r,i):this.isUnfilterable(e)?this.generateTextureLod(e,t,r,s,"0",i):this._generateTextureSample(e,t,r,s,i),n}generateTextureGrad(e,t,r,s,i,n=this.shaderStage){if("fragment"===n)return`textureSampleGrad( ${t}, ${t}_sampler, ${r}, ${s[0]}, ${s[1]} )`;console.error(`WebGPURenderer: THREE.TextureNode.gradient() does not support ${n} shader.`)}generateTextureCompare(e,t,r,s,i,n=this.shaderStage){if("fragment"===n)return`textureSampleCompare( ${t}, ${t}_sampler, ${r}, ${s} )`;console.error(`WebGPURenderer: THREE.DepthTexture.compareFunction() does not support ${n} shader.`)}generateTextureLevel(e,t,r,s,i,n=this.shaderStage){let o=null;return o=!0===e.isVideoTexture?this._generateVideoSample(t,r,n):this._generateTextureSampleLevel(e,t,r,s,i,n),o}generateTextureBias(e,t,r,s,i,n=this.shaderStage){if("fragment"===n)return`textureSampleBias( ${t}, ${t}_sampler, ${r}, ${s} )`;console.error(`WebGPURenderer: THREE.TextureNode.biasNode does not support ${n} shader.`)}getPropertyName(e,t=this.shaderStage){if(!0===e.isNodeVarying&&!0===e.needsInterpolation){if("vertex"===t)return`varyings.${e.name}`}else if(!0===e.isNodeUniform){const t=e.name,r=e.type;return"texture"===r||"cubeTexture"===r||"storageTexture"===r||"texture3D"===r?t:"buffer"===r||"storageBuffer"===r||"indirectStorageBuffer"===r?`NodeBuffer_${e.id}.${t}`:e.groupNode.name+"."+t}return super.getPropertyName(e)}getOutputStructName(){return"output"}_getUniformGroupCount(e){return Object.keys(this.uniforms[e]).length}getFunctionOperator(e){const t=_N[e];return void 0!==t?(this._include(t),t):null}getNodeAccess(e,t){return"compute"!==t?Ss.READ_ONLY:e.access}getStorageAccess(e,t){return yN[this.getNodeAccess(e,t)]}getUniformFromNode(e,t,r,s=null){const i=super.getUniformFromNode(e,t,r,s),n=this.getDataFromNode(e,r,this.globalCache);if(void 0===n.uniformGPU){let s;const o=e.groupNode,a=o.name,u=this.getBindGroupArray(a,r);if("texture"===t||"cubeTexture"===t||"storageTexture"===t||"texture3D"===t){let n=null;const a=this.getNodeAccess(e,r);if("texture"===t||"storageTexture"===t?n=new s_(i.name,i.node,o,a):"cubeTexture"===t?n=new i_(i.name,i.node,o,a):"texture3D"===t&&(n=new n_(i.name,i.node,o,a)),n.store=!0===e.isStorageTextureNode,n.setVisibility(bN[r]),"fragment"!==r&&"compute"!==r||!1!==this.isUnfilterable(e.value)||!1!==n.store)u.push(n),s=[n];else{const e=new rN(`${i.name}_sampler`,i.node,o);e.setVisibility(bN[r]),u.push(e,n),s=[e,n]}}else if("buffer"===t||"storageBuffer"===t||"indirectStorageBuffer"===t){const i=new("buffer"===t?QT:nN)(e,o);i.setVisibility(bN[r]),u.push(i),s=i}else{const e=this.uniformGroups[r]||(this.uniformGroups[r]={});let n=e[a];void 0===n&&(n=new e_(a,o),n.setVisibility(bN[r]),e[a]=n,u.push(n)),s=this.getNodeUniform(i,t),n.addUniform(s)}n.uniformGPU=s}return i}getBuiltin(e,t,r,s=this.shaderStage){const i=this.builtins[s]||(this.builtins[s]=new Map);return!1===i.has(e)&&i.set(e,{name:e,property:t,type:r}),t}hasBuiltin(e,t=this.shaderStage){return void 0!==this.builtins[t]&&this.builtins[t].has(e)}getVertexIndex(){return"vertex"===this.shaderStage?this.getBuiltin("vertex_index","vertexIndex","u32","attribute"):"vertexIndex"}buildFunctionCode(e){const t=e.layout,r=this.flowShaderNode(e),s=[];for(const e of t.inputs)s.push(e.name+" : "+this.getType(e.type));let i=`fn ${t.name}( ${s.join(", ")} ) -> ${this.getType(t.type)} {\n${r.vars}\n${r.code}\n`;return r.result&&(i+=`\treturn ${r.result};\n`),i+="\n}\n",i}getInstanceIndex(){return"vertex"===this.shaderStage?this.getBuiltin("instance_index","instanceIndex","u32","attribute"):"instanceIndex"}getInvocationLocalIndex(){return this.getBuiltin("local_invocation_index","invocationLocalIndex","u32","attribute")}getSubgroupSize(){return this.enableSubGroups(),this.getBuiltin("subgroup_size","subgroupSize","u32","attribute")}getInvocationSubgroupIndex(){return this.enableSubGroups(),this.getBuiltin("subgroup_invocation_id","invocationSubgroupIndex","u32","attribute")}getSubgroupIndex(){return this.enableSubGroups(),this.getBuiltin("subgroup_id","subgroupIndex","u32","attribute")}getDrawIndex(){return null}getFrontFacing(){return this.getBuiltin("front_facing","isFront","bool")}getFragCoord(){return this.getBuiltin("position","fragCoord","vec4")+".xy"}getFragDepth(){return"output."+this.getBuiltin("frag_depth","depth","f32","output")}getClipDistance(){return"varyings.hw_clip_distances"}isFlipY(){return!1}enableDirective(e,t=this.shaderStage){(this.directives[t]||(this.directives[t]=new Set)).add(e)}getDirectives(e){const t=[],r=this.directives[e];if(void 0!==r)for(const e of r)t.push(`enable ${e};`);return t.join("\n")}enableSubGroups(){this.enableDirective("subgroups")}enableSubgroupsF16(){this.enableDirective("subgroups-f16")}enableClipDistances(){this.enableDirective("clip_distances")}enableShaderF16(){this.enableDirective("f16")}enableDualSourceBlending(){this.enableDirective("dual_source_blending")}enableHardwareClipping(e){this.enableClipDistances(),this.getBuiltin("clip_distances","hw_clip_distances",`array`,"vertex")}getBuiltins(e){const t=[],r=this.builtins[e];if(void 0!==r)for(const{name:e,property:s,type:i}of r.values())t.push(`@builtin( ${e} ) ${s} : ${i}`);return t.join(",\n\t")}getScopedArray(e,t,r,s){return!1===this.scopedArrays.has(e)&&this.scopedArrays.set(e,{name:e,scope:t,bufferType:r,bufferCount:s}),e}getScopedArrays(e){if("compute"!==e)return;const t=[];for(const{name:e,scope:r,bufferType:s,bufferCount:i}of this.scopedArrays.values()){const n=this.getType(s);t.push(`var<${r}> ${e}: array< ${n}, ${i} >;`)}return t.join("\n")}getAttributes(e){const t=[];if("compute"===e&&(this.getBuiltin("global_invocation_id","id","vec3","attribute"),this.getBuiltin("workgroup_id","workgroupId","vec3","attribute"),this.getBuiltin("local_invocation_id","localId","vec3","attribute"),this.getBuiltin("num_workgroups","numWorkgroups","vec3","attribute"),this.renderer.hasFeature("subgroups")&&(this.enableDirective("subgroups",e),this.getBuiltin("subgroup_size","subgroupSize","u32","attribute"))),"vertex"===e||"compute"===e){const e=this.getBuiltins("attribute");e&&t.push(e);const r=this.getAttributesArray();for(let e=0,s=r.length;e`)}const s=this.getBuiltins("output");return s&&t.push("\t"+s),t.join(",\n")}getStructs(e){const t=[],r=this.structs[e];for(let e=0,s=r.length;e output : ${i};\n\n`)}return t.join("\n\n")}getVar(e,t){return`var ${t} : ${this.getType(e)}`}getVars(e){const t=[],r=this.vars[e];if(void 0!==r)for(const e of r)t.push(`\t${this.getVar(e.type,e.name)};`);return`\n${t.join("\n")}\n`}getVaryings(e){const t=[];if("vertex"===e&&this.getBuiltin("position","Vertex","vec4","vertex"),"vertex"===e||"fragment"===e){const r=this.varyings,s=this.vars[e];for(let i=0;i1&&(n="_multisampled"),!0===t.isCubeTexture)s="texture_cube";else if(!0===t.isDataArrayTexture||!0===t.isCompressedArrayTexture)s="texture_2d_array";else if(!0===t.isDepthTexture)s=`texture_depth${n}_2d`;else if(!0===t.isVideoTexture)s="texture_external";else if(!0===t.isData3DTexture)s="texture_3d";else if(!0===i.node.isStorageTextureNode){s=`texture_storage_2d<${dN(t)}, ${this.getStorageAccess(i.node,e)}>`}else{s=`texture${n}_2d<${this.getComponentTypeFromTexture(t).charAt(0)}32>`}r.push(`@binding( ${o.binding++} ) @group( ${o.group} ) var ${i.name} : ${s};`)}else if("buffer"===i.type||"storageBuffer"===i.type||"indirectStorageBuffer"===i.type){const t=i.node,r=this.getType(t.bufferType),n=t.bufferCount,a=n>0&&"buffer"===i.type?", "+n:"",u=t.isAtomic?`atomic<${r}>`:`${r}`,l=`\t${i.name} : array< ${u}${a} >\n`,d=t.isStorageBufferNode?`storage, ${this.getStorageAccess(t,e)}`:"uniform";s.push(this._getWGSLStructBinding("NodeBuffer_"+t.id,l,d,o.binding++,o.group))}else{const e=this.getType(this.getVectorType(i.type)),t=i.groupNode.name;(n[t]||(n[t]={index:o.binding++,id:o.group,snippets:[]})).snippets.push(`\t${i.name} : ${e}`)}}for(const e in n){const t=n[e];i.push(this._getWGSLStructBinding(e,t.snippets.join(",\n"),"uniform",t.index,t.id))}let o=r.join("\n");return o+=s.join("\n"),o+=i.join("\n"),o}buildCode(){const e=null!==this.material?{fragment:{},vertex:{}}:{compute:{}};this.sortBindingGroups();for(const t in e){const r=e[t];r.uniforms=this.getUniforms(t),r.attributes=this.getAttributes(t),r.varyings=this.getVaryings(t),r.structs=this.getStructs(t),r.vars=this.getVars(t),r.codes=this.getCodes(t),r.directives=this.getDirectives(t),r.scopedArrays=this.getScopedArrays(t);let s="// code\n\n";s+=this.flowCode[t];const i=this.flowNodes[t],n=i[i.length-1],o=n.outputNode,a=void 0!==o&&!0===o.isOutputStructNode;for(const e of i){const i=this.getFlowData(e),u=e.name;if(u&&(s.length>0&&(s+="\n"),s+=`\t// flow -> ${u}\n\t`),s+=`${i.code}\n\t`,e===n&&"compute"!==t)if(s+="// result\n\n\t","vertex"===t)s+=`varyings.Vertex = ${i.result};`;else if("fragment"===t)if(a)r.returnType=o.nodeType,s+=`return ${i.result};`;else{let e="\t@location(0) color: vec4";const t=this.getBuiltins("output");t&&(e+=",\n\t"+t),r.returnType="OutputStruct",r.structs+=this._getWGSLStruct("OutputStruct",e),r.structs+="\nvar output : OutputStruct;\n\n",s+=`output.color = ${i.result};\n\n\treturn output;`}}r.flow=s}null!==this.material?(this.vertexShader=this._getWGSLVertexCode(e.vertex),this.fragmentShader=this._getWGSLFragmentCode(e.fragment)):this.computeShader=this._getWGSLComputeCode(e.compute,(this.object.workgroupSize||[64]).join(", "))}getMethod(e,t=null){let r;return null!==t&&(r=this._getWGSLMethod(e+"_"+t)),void 0===r&&(r=this._getWGSLMethod(e)),r||e}getType(e){return vN[e]||e}isAvailable(e){let t=TN[e];return void 0===t&&("float32Filterable"===e?t=this.renderer.hasFeature("float32-filterable"):"clipDistance"===e&&(t=this.renderer.hasFeature("clip-distances")),TN[e]=t),t}_getWGSLMethod(e){return void 0!==SN[e]&&this._include(e),AN[e]}_include(e){const t=SN[e];return t.build(this),null!==this.currentFunctionNode&&this.currentFunctionNode.includes.push(t),t}_getWGSLVertexCode(e){return`${this.getSignature()}\n// directives\n${e.directives}\n\n// uniforms\n${e.uniforms}\n\n// varyings\n${e.varyings}\nvar varyings : VaryingsStruct;\n\n// codes\n${e.codes}\n\n@vertex\nfn main( ${e.attributes} ) -> VaryingsStruct {\n\n\t// vars\n\t${e.vars}\n\n\t// flow\n\t${e.flow}\n\n\treturn varyings;\n\n}\n`}_getWGSLFragmentCode(e){return`${this.getSignature()}\n// global\n${RN}\n\n// uniforms\n${e.uniforms}\n\n// structs\n${e.structs}\n\n// codes\n${e.codes}\n\n@fragment\nfn main( ${e.varyings} ) -> ${e.returnType} {\n\n\t// vars\n\t${e.vars}\n\n\t// flow\n\t${e.flow}\n\n}\n`}_getWGSLComputeCode(e,t){return`${this.getSignature()}\n// directives\n${e.directives}\n\n// system\nvar instanceIndex : u32;\n\n// locals\n${e.scopedArrays}\n\n// uniforms\n${e.uniforms}\n\n// codes\n${e.codes}\n\n@compute @workgroup_size( ${t} )\nfn main( ${e.attributes} ) {\n\n\t// system\n\tinstanceIndex = id.x + id.y * numWorkgroups.x * u32(${t}) + id.z * numWorkgroups.x * numWorkgroups.y * u32(${t});\n\n\t// vars\n\t${e.vars}\n\n\t// flow\n\t${e.flow}\n\n}\n`}_getWGSLStruct(e,t){return`\nstruct ${e} {\n${t}\n};`}_getWGSLStructBinding(e,t,r,s=0,i=0){const n=e+"Struct";return`${this._getWGSLStruct(n,t)}\n@binding( ${s} ) @group( ${i} )\nvar<${r}> ${e} : ${n};`}}class EN{constructor(e){this.backend=e}getCurrentDepthStencilFormat(e){let t;return null!==e.depthTexture?t=this.getTextureFormatGPU(e.depthTexture):e.depth&&e.stencil?t=tv.Depth24PlusStencil8:e.depth&&(t=tv.Depth24Plus),t}getTextureFormatGPU(e){return this.backend.get(e).format}getTextureSampleData(e){let t;if(e.isFramebufferTexture)t=1;else if(e.isDepthTexture&&!e.renderTarget){const e=this.backend.renderer,r=e.getRenderTarget();t=r?r.samples:e.samples}else e.renderTarget&&(t=e.renderTarget.samples);t=t||1;const r=t>1&&null!==e.renderTarget&&!0!==e.isDepthTexture&&!0!==e.isFramebufferTexture;return{samples:t,primarySamples:r?1:t,isMSAA:r}}getCurrentColorFormat(e){let t;return t=null!==e.textures?this.getTextureFormatGPU(e.textures[0]):this.getPreferredCanvasFormat(),t}getCurrentColorSpace(e){return null!==e.textures?e.textures[0].colorSpace:this.backend.renderer.outputColorSpace}getPrimitiveTopology(e,t){return e.isPoints?F_:e.isLineSegments||e.isMesh&&!0===t.wireframe?P_:e.isLine?I_:e.isMesh?L_:void 0}getSampleCount(e){let t=1;return e>1&&(t=Math.pow(2,Math.floor(Math.log2(e))),2===t&&(t=4)),t}getSampleCountRenderContext(e){return null!==e.textures?this.getSampleCount(e.sampleCount):this.getSampleCount(this.backend.renderer.samples)}getPreferredCanvasFormat(){return navigator.userAgent.includes("Quest")?tv.BGRA8Unorm:navigator.gpu.getPreferredCanvasFormat()}}const wN=new Map([[Int8Array,["sint8","snorm8"]],[Uint8Array,["uint8","unorm8"]],[Int16Array,["sint16","snorm16"]],[Uint16Array,["uint16","unorm16"]],[Int32Array,["sint32","snorm32"]],[Uint32Array,["uint32","unorm32"]],[Float32Array,["float32"]]]),MN=new Map([[Le,["float16"]]]),BN=new Map([[Int32Array,"sint32"],[Int16Array,"sint32"],[Uint32Array,"uint32"],[Uint16Array,"uint32"],[Float32Array,"float32"]]);class UN{constructor(e){this.backend=e}createAttribute(e,t){const r=this._getBufferAttribute(e),s=this.backend,i=s.get(r);let n=i.buffer;if(void 0===n){const o=s.device;let a=r.array;if(!1===e.normalized&&(a.constructor===Int16Array||a.constructor===Uint16Array)){const e=new Uint32Array(a.length);for(let t=0;t1&&(s.multisampled=!0,r.texture.isDepthTexture||(s.sampleType=kv)),r.texture.isDepthTexture)s.sampleType=zv;else if(r.texture.isDataTexture||r.texture.isDataArrayTexture||r.texture.isData3DTexture){const e=r.texture.type;e===b?s.sampleType=$v:e===x?s.sampleType=Hv:e===E&&(this.backend.hasFeature("float32-filterable")?s.sampleType=Gv:s.sampleType=kv)}r.isSampledCubeTexture?s.viewDimension=Xv:r.texture.isDataArrayTexture||r.texture.isCompressedArrayTexture?s.viewDimension=Kv:r.isSampledTexture3D&&(s.viewDimension=Yv),e.texture=s}else console.error(`WebGPUBindingUtils: Unsupported binding "${r}".`);s.push(e)}return r.createBindGroupLayout({entries:s})}createBindings(e,t,r,s=0){const{backend:i,bindGroupLayoutCache:n}=this,o=i.get(e);let a,u=n.get(e.bindingsReference);void 0===u&&(u=this.createBindingsLayout(e),n.set(e.bindingsReference,u)),r>0&&(void 0===o.groups&&(o.groups=[],o.versions=[]),o.versions[r]===s&&(a=o.groups[r])),void 0===a&&(a=this.createBindGroup(e,u),r>0&&(o.groups[r]=a,o.versions[r]=s)),o.group=a,o.layout=u}updateBinding(e){const t=this.backend,r=t.device,s=e.buffer,i=t.get(e).buffer;r.queue.writeBuffer(i,0,s,0)}createBindGroup(e,t){const r=this.backend,s=r.device;let i=0;const n=[];for(const t of e.bindings){if(t.isUniformBuffer){const e=r.get(t);if(void 0===e.buffer){const r=t.byteLength,i=GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST,n=s.createBuffer({label:"bindingBuffer_"+t.name,size:r,usage:i});e.buffer=n}n.push({binding:i,resource:{buffer:e.buffer}})}else if(t.isStorageBuffer){const e=r.get(t);if(void 0===e.buffer){const s=t.attribute;e.buffer=r.get(s).buffer}n.push({binding:i,resource:{buffer:e.buffer}})}else if(t.isSampler){const e=r.get(t.texture);n.push({binding:i,resource:e.sampler})}else if(t.isSampledTexture){const e=r.get(t.texture);let o;if(void 0!==e.externalTexture)o=s.importExternalTexture({source:e.externalTexture});else{const r=t.store?1:e.texture.mipLevelCount,s=`view-${e.texture.width}-${e.texture.height}-${r}`;if(o=e[s],void 0===o){const i=Qv;let n;n=t.isSampledCubeTexture?Xv:t.isSampledTexture3D?Yv:t.texture.isDataArrayTexture||t.texture.isCompressedArrayTexture?Kv:qv,o=e[s]=e.texture.createView({aspect:i,dimension:n,mipLevelCount:r})}}n.push({binding:i,resource:o})}i++}return s.createBindGroup({label:"bindGroup_"+e.name,layout:t,entries:n})}}class PN{constructor(e){this.backend=e}_getSampleCount(e){return this.backend.utils.getSampleCountRenderContext(e)}createRenderPipeline(e,t){const{object:r,material:s,geometry:i,pipeline:n}=e,{vertexProgram:o,fragmentProgram:a}=n,u=this.backend,l=u.device,d=u.utils,c=u.get(n),h=[];for(const t of e.getBindings()){const e=u.get(t);h.push(e.layout)}const p=u.attributeUtils.createShaderVertexBuffers(e);let g;!0===s.transparent&&s.blending!==V&&(g=this._getBlending(s));let m={};!0===s.stencilWrite&&(m={compare:this._getStencilCompare(s),failOp:this._getStencilOperation(s.stencilFail),depthFailOp:this._getStencilOperation(s.stencilZFail),passOp:this._getStencilOperation(s.stencilZPass)});const f=this._getColorWriteMask(s),y=[];if(null!==e.context.textures){const t=e.context.textures;for(let e=0;e1},layout:l.createPipelineLayout({bindGroupLayouts:h})},A={},R=e.context.depth,C=e.context.stencil;if(!0!==R&&!0!==C||(!0===R&&(A.format=v,A.depthWriteEnabled=s.depthWrite,A.depthCompare=_),!0===C&&(A.stencilFront=m,A.stencilBack={},A.stencilReadMask=s.stencilFuncMask,A.stencilWriteMask=s.stencilWriteMask),S.depthStencil=A),null===t)c.pipeline=l.createRenderPipeline(S);else{const e=new Promise((e=>{l.createRenderPipelineAsync(S).then((t=>{c.pipeline=t,e()}))}));t.push(e)}}createBundleEncoder(e){const t=this.backend,{utils:r,device:s}=t,i=r.getCurrentDepthStencilFormat(e),n={label:"renderBundleEncoder",colorFormats:[r.getCurrentColorFormat(e)],depthStencilFormat:i,sampleCount:this._getSampleCount(e)};return s.createRenderBundleEncoder(n)}createComputePipeline(e,t){const r=this.backend,s=r.device,i=r.get(e.computeProgram).module,n=r.get(e),o=[];for(const e of t){const t=r.get(e);o.push(t.layout)}n.pipeline=s.createComputePipeline({compute:i,layout:s.createPipelineLayout({bindGroupLayouts:o})})}_getBlending(e){let t,r;const s=e.blending,i=e.blendSrc,n=e.blendDst,o=e.blendEquation;if(s===ft){const s=null!==e.blendSrcAlpha?e.blendSrcAlpha:i,a=null!==e.blendDstAlpha?e.blendDstAlpha:n,u=null!==e.blendEquationAlpha?e.blendEquationAlpha:o;t={srcFactor:this._getBlendFactor(i),dstFactor:this._getBlendFactor(n),operation:this._getBlendOperation(o)},r={srcFactor:this._getBlendFactor(s),dstFactor:this._getBlendFactor(a),operation:this._getBlendOperation(u)}}else{const i=(e,s,i,n)=>{t={srcFactor:e,dstFactor:s,operation:Tv},r={srcFactor:i,dstFactor:n,operation:Tv}};if(e.premultipliedAlpha)switch(s){case F:i(uv,hv,uv,hv);break;case bt:i(uv,uv,uv,uv);break;case xt:i(av,dv,av,uv);break;case yt:i(av,lv,av,cv)}else switch(s){case F:i(cv,hv,uv,hv);break;case bt:i(cv,uv,cv,uv);break;case xt:i(av,dv,av,uv);break;case yt:i(av,lv,av,lv)}}if(void 0!==t&&void 0!==r)return{color:t,alpha:r};console.error("THREE.WebGPURenderer: Invalid blending: ",s)}_getBlendFactor(e){let t;switch(e){case rt:t=av;break;case st:t=uv;break;case it:t=lv;break;case lt:t=dv;break;case nt:t=cv;break;case dt:t=hv;break;case at:t=pv;break;case ct:t=gv;break;case ut:t=mv;break;case ht:t=fv;break;case ot:t=yv;break;case 211:t=xv;break;case 212:t=bv;break;default:console.error("THREE.WebGPURenderer: Blend factor not supported.",e)}return t}_getStencilCompare(e){let t;const r=e.stencilFunc;switch(r){case Mr:t=D_;break;case wr:t=W_;break;case Er:t=O_;break;case Cr:t=k_;break;case Rr:t=G_;break;case Ar:t=H_;break;case Sr:t=z_;break;case Nr:t=$_;break;default:console.error("THREE.WebGPURenderer: Invalid stencil function.",r)}return t}_getStencilOperation(e){let t;switch(e){case Dr:t=Cv;break;case Vr:t=Ev;break;case Lr:t=wv;break;case Ir:t=Mv;break;case Pr:t=Bv;break;case Fr:t=Uv;break;case Ur:t=Fv;break;case Br:t=Pv;break;default:console.error("THREE.WebGPURenderer: Invalid stencil operation.",t)}return t}_getBlendOperation(e){let t;switch(e){case Je:t=Tv;break;case et:t=_v;break;case tt:t=vv;break;case Gr:t=Nv;break;case Or:t=Sv;break;default:console.error("THREE.WebGPUPipelineUtils: Blend equation not supported.",e)}return t}_getPrimitiveState(e,t,r){const s={},i=this.backend.utils;switch(s.topology=i.getPrimitiveTopology(e,r),null!==t.index&&!0===e.isLine&&!0!==e.isLineSegments&&(s.stripIndexFormat=t.index.array instanceof Uint16Array?J_:ev),r.side){case Ge:s.frontFace=X_,s.cullMode=Z_;break;case T:s.frontFace=X_,s.cullMode=Q_;break;case le:s.frontFace=X_,s.cullMode=Y_;break;default:console.error("THREE.WebGPUPipelineUtils: Unknown material.side value.",r.side)}return s}_getColorWriteMask(e){return!0===e.colorWrite?Rv:Av}_getDepthCompare(e){let t;if(!1===e.depthTest)t=W_;else{const r=e.depthFunc;switch(r){case Ct:t=D_;break;case Rt:t=W_;break;case At:t=O_;break;case St:t=k_;break;case Nt:t=G_;break;case vt:t=H_;break;case _t:t=z_;break;case Tt:t=$_;break;default:console.error("THREE.WebGPUPipelineUtils: Invalid depth function.",r)}}return t}}class IN extends g_{constructor(e={}){super(e),this.isWebGPUBackend=!0,this.parameters.alpha=void 0===e.alpha||e.alpha,this.parameters.requiredLimits=void 0===e.requiredLimits?{}:e.requiredLimits,this.trackTimestamp=!0===e.trackTimestamp,this.device=null,this.context=null,this.colorBuffer=null,this.defaultRenderPassdescriptor=null,this.utils=new EN(this),this.attributeUtils=new UN(this),this.bindingUtils=new FN(this),this.pipelineUtils=new PN(this),this.textureUtils=new lN(this),this.occludedResolveCache=new Map}async init(e){await super.init(e);const t=this.parameters;let r;if(void 0===t.device){const e={powerPreference:t.powerPreference},s="undefined"!=typeof navigator?await navigator.gpu.requestAdapter(e):null;if(null===s)throw new Error("WebGPUBackend: Unable to create WebGPU adapter.");const i=Object.values(eN),n=[];for(const e of i)s.features.has(e)&&n.push(e);const o={requiredFeatures:n,requiredLimits:t.requiredLimits};r=await s.requestDevice(o)}else r=t.device;r.lost.then((t=>{const r={api:"WebGPU",message:t.message||"Unknown reason",reason:t.reason||null,originalEvent:t};e.onDeviceLost(r)}));const s=void 0!==t.context?t.context:e.domElement.getContext("webgpu");this.device=r,this.context=s;const i=t.alpha?"premultiplied":"opaque";this.trackTimestamp=this.trackTimestamp&&this.hasFeature(eN.TimestampQuery),this.context.configure({device:this.device,format:this.utils.getPreferredCanvasFormat(),usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.COPY_SRC,alphaMode:i}),this.updateSize()}get coordinateSystem(){return l}async getArrayBufferAsync(e){return await this.attributeUtils.getArrayBufferAsync(e)}getContext(){return this.context}_getDefaultRenderPassDescriptor(){let e=this.defaultRenderPassdescriptor;if(null===e){const t=this.renderer;e={colorAttachments:[{view:null}]},!0!==this.renderer.depth&&!0!==this.renderer.stencil||(e.depthStencilAttachment={view:this.textureUtils.getDepthBuffer(t.depth,t.stencil).createView()});const r=e.colorAttachments[0];this.renderer.samples>0?r.view=this.colorBuffer.createView():r.resolveTarget=void 0,this.defaultRenderPassdescriptor=e}const t=e.colorAttachments[0];return this.renderer.samples>0?t.resolveTarget=this.context.getCurrentTexture().createView():t.view=this.context.getCurrentTexture().createView(),e}_getRenderPassDescriptor(e){const t=e.renderTarget,r=this.get(t);let s=r.descriptors;if(void 0===s||r.width!==t.width||r.height!==t.height||r.activeMipmapLevel!==t.activeMipmapLevel||r.samples!==t.samples){s={},r.descriptors=s;const e=()=>{t.removeEventListener("dispose",e),this.delete(t)};t.addEventListener("dispose",e)}const i=e.getCacheKey();let n=s[i];if(void 0===n){const o=e.textures,a=[];for(let t=0;t0&&(t.currentOcclusionQuerySet&&t.currentOcclusionQuerySet.destroy(),t.currentOcclusionQueryBuffer&&t.currentOcclusionQueryBuffer.destroy(),t.currentOcclusionQuerySet=t.occlusionQuerySet,t.currentOcclusionQueryBuffer=t.occlusionQueryBuffer,t.currentOcclusionQueryObjects=t.occlusionQueryObjects,i=r.createQuerySet({type:"occlusion",count:s,label:`occlusionQuerySet_${e.id}`}),t.occlusionQuerySet=i,t.occlusionQueryIndex=0,t.occlusionQueryObjects=new Array(s),t.lastOcclusionObject=null),n=null===e.textures?this._getDefaultRenderPassDescriptor():this._getRenderPassDescriptor(e),this.initTimestampQuery(e,n),n.occlusionQuerySet=i;const o=n.depthStencilAttachment;if(null!==e.textures){const t=n.colorAttachments;for(let r=0;r0&&t.currentPass.executeBundles(t.renderBundles),r>t.occlusionQueryIndex&&t.currentPass.endOcclusionQuery(),t.currentPass.end(),r>0){const s=8*r;let i=this.occludedResolveCache.get(s);void 0===i&&(i=this.device.createBuffer({size:s,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),this.occludedResolveCache.set(s,i));const n=this.device.createBuffer({size:s,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});t.encoder.resolveQuerySet(t.occlusionQuerySet,0,r,i,0),t.encoder.copyBufferToBuffer(i,0,n,0,s),t.occlusionQueryBuffer=n,this.resolveOccludedAsync(e)}if(this.prepareTimestampBuffer(e,t.encoder),this.device.queue.submit([t.encoder.finish()]),null!==e.textures){const t=e.textures;for(let e=0;eo?(u.x=Math.min(t.dispatchCount,o),u.y=Math.ceil(t.dispatchCount/o)):u.x=t.dispatchCount,i.dispatchWorkgroups(u.x,u.y,u.z)}finishCompute(e){const t=this.get(e);t.passEncoderGPU.end(),this.prepareTimestampBuffer(e,t.cmdEncoderGPU),this.device.queue.submit([t.cmdEncoderGPU.finish()])}async waitForGPU(){await this.device.queue.onSubmittedWorkDone()}draw(e,t){const{object:r,context:s,pipeline:i}=e,n=e.getBindings(),o=this.get(s),a=this.get(i).pipeline,u=o.currentSets,l=o.currentPass,d=e.getDrawParameters();if(null===d)return;u.pipeline!==a&&(l.setPipeline(a),u.pipeline=a);const c=u.bindingGroups;for(let e=0,t=n.length;e1?0:r;!0===p?l.drawIndexed(t[r],s,e[r]/h.array.BYTES_PER_ELEMENT,0,n):l.draw(t[r],s,e[r],n)}}else if(!0===p){const{vertexCount:s,instanceCount:i,firstVertex:n}=d,o=e.getIndirect();if(null!==o){const e=this.get(o).buffer;l.drawIndexedIndirect(e,0)}else l.drawIndexed(s,i,n,0,0);t.update(r,s,i)}else{const{vertexCount:s,instanceCount:i,firstVertex:n}=d,o=e.getIndirect();if(null!==o){const e=this.get(o).buffer;l.drawIndirect(e,0)}else l.draw(s,i,n,0);t.update(r,s,i)}}needsRenderUpdate(e){const t=this.get(e),{object:r,material:s}=e,i=this.utils,n=i.getSampleCountRenderContext(e.context),o=i.getCurrentColorSpace(e.context),a=i.getCurrentColorFormat(e.context),u=i.getCurrentDepthStencilFormat(e.context),l=i.getPrimitiveTopology(r,s);let d=!1;return t.material===s&&t.materialVersion===s.version&&t.transparent===s.transparent&&t.blending===s.blending&&t.premultipliedAlpha===s.premultipliedAlpha&&t.blendSrc===s.blendSrc&&t.blendDst===s.blendDst&&t.blendEquation===s.blendEquation&&t.blendSrcAlpha===s.blendSrcAlpha&&t.blendDstAlpha===s.blendDstAlpha&&t.blendEquationAlpha===s.blendEquationAlpha&&t.colorWrite===s.colorWrite&&t.depthWrite===s.depthWrite&&t.depthTest===s.depthTest&&t.depthFunc===s.depthFunc&&t.stencilWrite===s.stencilWrite&&t.stencilFunc===s.stencilFunc&&t.stencilFail===s.stencilFail&&t.stencilZFail===s.stencilZFail&&t.stencilZPass===s.stencilZPass&&t.stencilFuncMask===s.stencilFuncMask&&t.stencilWriteMask===s.stencilWriteMask&&t.side===s.side&&t.alphaToCoverage===s.alphaToCoverage&&t.sampleCount===n&&t.colorSpace===o&&t.colorFormat===a&&t.depthStencilFormat===u&&t.primitiveTopology===l&&t.clippingContextCacheKey===e.clippingContextCacheKey||(t.material=s,t.materialVersion=s.version,t.transparent=s.transparent,t.blending=s.blending,t.premultipliedAlpha=s.premultipliedAlpha,t.blendSrc=s.blendSrc,t.blendDst=s.blendDst,t.blendEquation=s.blendEquation,t.blendSrcAlpha=s.blendSrcAlpha,t.blendDstAlpha=s.blendDstAlpha,t.blendEquationAlpha=s.blendEquationAlpha,t.colorWrite=s.colorWrite,t.depthWrite=s.depthWrite,t.depthTest=s.depthTest,t.depthFunc=s.depthFunc,t.stencilWrite=s.stencilWrite,t.stencilFunc=s.stencilFunc,t.stencilFail=s.stencilFail,t.stencilZFail=s.stencilZFail,t.stencilZPass=s.stencilZPass,t.stencilFuncMask=s.stencilFuncMask,t.stencilWriteMask=s.stencilWriteMask,t.side=s.side,t.alphaToCoverage=s.alphaToCoverage,t.sampleCount=n,t.colorSpace=o,t.colorFormat=a,t.depthStencilFormat=u,t.primitiveTopology=l,t.clippingContextCacheKey=e.clippingContextCacheKey,d=!0),d}getRenderCacheKey(e){const{object:t,material:r}=e,s=this.utils,i=e.context;return[r.transparent,r.blending,r.premultipliedAlpha,r.blendSrc,r.blendDst,r.blendEquation,r.blendSrcAlpha,r.blendDstAlpha,r.blendEquationAlpha,r.colorWrite,r.depthWrite,r.depthTest,r.depthFunc,r.stencilWrite,r.stencilFunc,r.stencilFail,r.stencilZFail,r.stencilZPass,r.stencilFuncMask,r.stencilWriteMask,r.side,s.getSampleCountRenderContext(i),s.getCurrentColorSpace(i),s.getCurrentColorFormat(i),s.getCurrentDepthStencilFormat(i),s.getPrimitiveTopology(t,r),e.getGeometryCacheKey(),e.clippingContextCacheKey].join()}createSampler(e){this.textureUtils.createSampler(e)}destroySampler(e){this.textureUtils.destroySampler(e)}createDefaultTexture(e){this.textureUtils.createDefaultTexture(e)}createTexture(e,t){this.textureUtils.createTexture(e,t)}updateTexture(e,t){this.textureUtils.updateTexture(e,t)}generateMipmaps(e){this.textureUtils.generateMipmaps(e)}destroyTexture(e){this.textureUtils.destroyTexture(e)}copyTextureToBuffer(e,t,r,s,i,n){return this.textureUtils.copyTextureToBuffer(e,t,r,s,i,n)}initTimestampQuery(e,t){if(!this.trackTimestamp)return;const r=this.get(e);if(!r.timeStampQuerySet){const s=e.isComputeNode?"compute":"render",i=this.device.createQuerySet({type:"timestamp",count:2,label:`timestamp_${s}_${e.id}`}),n={querySet:i,beginningOfPassWriteIndex:0,endOfPassWriteIndex:1};Object.assign(t,{timestampWrites:n}),r.timeStampQuerySet=i}}prepareTimestampBuffer(e,t){if(!this.trackTimestamp)return;const r=this.get(e),s=2*BigInt64Array.BYTES_PER_ELEMENT;void 0===r.currentTimestampQueryBuffers&&(r.currentTimestampQueryBuffers={resolveBuffer:this.device.createBuffer({label:"timestamp resolve buffer",size:s,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),resultBuffer:this.device.createBuffer({label:"timestamp result buffer",size:s,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ})});const{resolveBuffer:i,resultBuffer:n}=r.currentTimestampQueryBuffers;t.resolveQuerySet(r.timeStampQuerySet,0,2,i,0),"unmapped"===n.mapState&&t.copyBufferToBuffer(i,0,n,0,s)}async resolveTimestampAsync(e,t="render"){if(!this.trackTimestamp)return;const r=this.get(e);if(void 0===r.currentTimestampQueryBuffers)return;const{resultBuffer:s}=r.currentTimestampQueryBuffers;"unmapped"===s.mapState&&s.mapAsync(GPUMapMode.READ).then((()=>{const e=new BigUint64Array(s.getMappedRange()),r=Number(e[1]-e[0])/1e6;this.renderer.info.updateTimestamp(t,r),s.unmap()}))}createNodeBuilder(e,t){return new CN(e,t)}createProgram(e){this.get(e).module={module:this.device.createShaderModule({code:e.code,label:e.stage}),entryPoint:"main"}}destroyProgram(e){this.delete(e)}createRenderPipeline(e,t){this.pipelineUtils.createRenderPipeline(e,t)}createComputePipeline(e,t){this.pipelineUtils.createComputePipeline(e,t)}beginBundle(e){const t=this.get(e);t._currentPass=t.currentPass,t._currentSets=t.currentSets,t.currentSets={attributes:{},bindingGroups:[],pipeline:null,index:null},t.currentPass=this.pipelineUtils.createBundleEncoder(e)}finishBundle(e,t){const r=this.get(e),s=r.currentPass.finish();this.get(t).bundleGPU=s,r.currentSets=r._currentSets,r.currentPass=r._currentPass}addBundle(e,t){this.get(e).renderBundles.push(this.get(t).bundleGPU)}createBindings(e,t,r,s){this.bindingUtils.createBindings(e,t,r,s)}updateBindings(e,t,r,s){this.bindingUtils.createBindings(e,t,r,s)}updateBinding(e){this.bindingUtils.updateBinding(e)}createIndexAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.INDEX|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}createAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}createStorageAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.STORAGE|GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}createIndirectStorageAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.STORAGE|GPUBufferUsage.INDIRECT|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}updateAttribute(e){this.attributeUtils.updateAttribute(e)}destroyAttribute(e){this.attributeUtils.destroyAttribute(e)}updateSize(){this.colorBuffer=this.textureUtils.getColorBuffer(),this.defaultRenderPassdescriptor=null}getMaxAnisotropy(){return 16}hasFeature(e){return this.device.features.has(e)}copyTextureToTexture(e,t,r=null,s=null,i=0){let n=0,o=0,a=0,u=0,l=0,d=0,c=e.image.width,h=e.image.height;null!==r&&(u=r.x,l=r.y,d=r.z||0,c=r.width,h=r.height),null!==s&&(n=s.x,o=s.y,a=s.z||0);const p=this.device.createCommandEncoder({label:"copyTextureToTexture_"+e.id+"_"+t.id}),g=this.get(e).texture,m=this.get(t).texture;p.copyTextureToTexture({texture:g,mipLevel:i,origin:{x:u,y:l,z:d}},{texture:m,mipLevel:i,origin:{x:n,y:o,z:a}},[c,h,1]),this.device.queue.submit([p.finish()])}copyFramebufferToTexture(e,t,r){const s=this.get(t);let i=null;i=t.renderTarget?e.isDepthTexture?this.get(t.depthTexture).texture:this.get(t.textures[0]).texture:e.isDepthTexture?this.textureUtils.getDepthBuffer(t.depth,t.stencil):this.context.getCurrentTexture();const n=this.get(e).texture;if(i.format!==n.format)return void console.error("WebGPUBackend: copyFramebufferToTexture: Source and destination formats do not match.",i.format,n.format);let o;if(s.currentPass?(s.currentPass.end(),o=s.encoder):o=this.device.createCommandEncoder({label:"copyFramebufferToTexture_"+e.id}),o.copyTextureToTexture({texture:i,origin:[r.x,r.y,0]},{texture:n},[r.z,r.w]),e.generateMipmaps&&this.textureUtils.generateMipmaps(e),s.currentPass){const{descriptor:e}=s;for(let t=0;t(console.warn("THREE.WebGPURenderer: WebGPU is not available, running under WebGL2 backend."),new U_(e)));super(new t(e),e),this.library=new VN,this.isWebGPURenderer=!0}}class ON extends es{constructor(){super(),this.isBundleGroup=!0,this.type="BundleGroup",this.static=!0,this.version=0}set needsUpdate(e){!0===e&&this.version++}}const GN=new Yc,kN=new Jm(GN);class zN{constructor(e,t=Oi(0,0,1,1)){this.renderer=e,this.outputNode=t,this.outputColorTransform=!0,this.needsUpdate=!0,GN.name="PostProcessing"}render(){this.update();const e=this.renderer,t=e.toneMapping,r=e.outputColorSpace;e.toneMapping=h,e.outputColorSpace=Ae,kN.render(e),e.toneMapping=t,e.outputColorSpace=r}update(){if(!0===this.needsUpdate){const e=this.renderer,t=e.toneMapping,r=e.outputColorSpace;kN.material.fragmentNode=!0===this.outputColorTransform?du(this.outputNode,t,r):this.outputNode.context({toneMapping:t,outputColorSpace:r}),kN.material.needsUpdate=!0,this.needsUpdate=!1}}async renderAsync(){this.update();const e=this.renderer,t=e.toneMapping,r=e.outputColorSpace;e.toneMapping=h,e.outputColorSpace=Ae,await kN.renderAsync(e),e.toneMapping=t,e.outputColorSpace=r}}function $N(t,r={}){return r.toneMapping=t.toneMapping,r.toneMappingExposure=t.toneMappingExposure,r.outputColorSpace=t.outputColorSpace,r.renderTarget=t.getRenderTarget(),r.activeCubeFace=t.getActiveCubeFace(),r.activeMipmapLevel=t.getActiveMipmapLevel(),r.renderObjectFunction=t.getRenderObjectFunction(),r.pixelRatio=t.getPixelRatio(),r.mrt=t.getMRT(),r.clearColor=t.getClearColor(r.clearColor||new e),r.clearAlpha=t.getClearAlpha(),r.autoClear=t.autoClear,r.scissorTest=t.getScissorTest(),r}function HN(e,t){e.toneMapping=t.toneMapping,e.toneMappingExposure=t.toneMappingExposure,e.outputColorSpace=t.outputColorSpace,e.setRenderTarget(t.renderTarget,t.activeCubeFace,t.activeMipmapLevel),e.setRenderObjectFunction(t.renderObjectFunction),e.setPixelRatio(t.pixelRatio),e.setMRT(t.mrt),e.setClearColor(t.clearColor,t.clearAlpha),e.autoClear=t.autoClear,e.setScissorTest(t.scissorTest)}function WN(e,t,r={}){return(r=$N(e,r)).background=t.background,r.backgroundNode=t.backgroundNode,r.overrideMaterial=t.overrideMaterial,r}var jN=Object.freeze({__proto__:null,resetRendererAndSceneState:function(e,t,r){return r=WN(e,t,r),t.background=null,t.backgroundNode=null,t.overrideMaterial=null,r},resetRendererState:function(e,t){return t=$N(e,t),e.setMRT(null),e.setRenderObjectFunction(null),e.setClearColor(0,1),e.autoClear=!0,t},restoreRendererAndSceneState:function(e,t,r){HN(e,r),t.background=r.background,t.backgroundNode=r.backgroundNode,t.overrideMaterial=r.overrideMaterial},restoreRendererState:HN,saveRendererAndSceneState:WN,saveRendererState:$N});class qN extends ee{constructor(e=1,t=1){super(),this.image={width:e,height:t},this.magFilter=$,this.minFilter=$,this.isStorageTexture=!0}}class KN extends uf{constructor(e,t){super(e,t,Uint32Array),this.isIndirectStorageBufferAttribute=!0}}class XN extends ts{constructor(e){super(e),this.textures={},this.nodes={}}load(e,t,r,s){const i=new rs(this.manager);i.setPath(this.path),i.setRequestHeader(this.requestHeader),i.setWithCredentials(this.withCredentials),i.load(e,(r=>{try{t(this.parse(JSON.parse(r)))}catch(t){s?s(t):console.error(t),this.manager.itemError(e)}}),r,s)}parseNodes(e){const t={};if(void 0!==e){for(const r of e){const{uuid:e,type:s}=r;t[e]=this.createNodeFromType(s),t[e].uuid=e}const r={nodes:t,textures:this.textures};for(const s of e){s.meta=r;t[s.uuid].deserialize(s),delete s.meta}}return t}parse(e){const t=this.createNodeFromType(e.type);t.uuid=e.uuid;const r={nodes:this.parseNodes(e.nodes),textures:this.textures};return e.meta=r,t.deserialize(e),delete e.meta,t}setTextures(e){return this.textures=e,this}setNodes(e){return this.nodes=e,this}createNodeFromType(e){return void 0===this.nodes[e]?(console.error("THREE.NodeLoader: Node type not found:",e),Ci()):fi(new this.nodes[e])}}class YN extends ss{constructor(e){super(e),this.nodes={},this.nodeMaterials={}}parse(e){const t=super.parse(e),r=this.nodes,s=e.inputNodes;for(const e in s){const i=s[e];t[e]=r[i]}return t}setNodes(e){return this.nodes=e,this}setNodeMaterials(e){return this.nodeMaterials=e,this}createMaterialFromType(e){const t=this.nodeMaterials[e];return void 0!==t?new t:super.createMaterialFromType(e)}}class QN extends is{constructor(e){super(e),this.nodes={},this.nodeMaterials={},this._nodesJSON=null}setNodes(e){return this.nodes=e,this}setNodeMaterials(e){return this.nodeMaterials=e,this}parse(e,t){this._nodesJSON=e.nodes;const r=super.parse(e,t);return this._nodesJSON=null,r}parseNodes(e,t){if(void 0!==e){const r=new XN;return r.setNodes(this.nodes),r.setTextures(t),r.parseNodes(e)}return{}}parseMaterials(e,t){const r={};if(void 0!==e){const s=this.parseNodes(this._nodesJSON,t),i=new YN;i.setTextures(t),i.setNodes(s),i.setNodeMaterials(this.nodeMaterials);for(let t=0,s=e.length;t0){const{width:r,height:s}=e.context;t.bufferWidth=r,t.bufferHeight=s}this.renderObjects.set(e,t)}return t}getAttributesData(e){const t={};for(const r in e){const s=e[r];t[r]={version:s.version}}return t}containsNode(e){const t=e.material;for(const e in t)if(t[e]&&t[e].isNode)return!0;return null!==e.renderer.nodes.modelViewMatrix||null!==e.renderer.nodes.modelNormalViewMatrix}getMaterialData(e){const t={};for(const r of this.refreshUniforms){const s=e[r];null!=s&&("object"==typeof s&&void 0!==s.clone?!0===s.isTexture?t[r]={id:s.id,version:s.version}:t[r]=s.clone():t[r]=s)}return t}equals(e){const{object:t,material:r,geometry:s}=e,i=this.getRenderObjectData(e);if(!0!==i.worldMatrix.equals(t.matrixWorld))return i.worldMatrix.copy(t.matrixWorld),!1;const n=i.material;for(const e in n){const t=n[e],s=r[e];if(void 0!==t.equals){if(!1===t.equals(s))return t.copy(s),!1}else if(!0===s.isTexture){if(t.id!==s.id||t.version!==s.version)return t.id=s.id,t.version=s.version,!1}else if(t!==s)return n[e]=s,!1}if(n.transmission>0){const{width:t,height:r}=e.context;if(i.bufferWidth!==t||i.bufferHeight!==r)return i.bufferWidth=t,i.bufferHeight=r,!1}const o=i.geometry,a=s.attributes,u=o.attributes,l=Object.keys(u),d=Object.keys(a);if(l.length!==d.length)return i.geometry.attributes=this.getAttributesData(a),!1;for(const e of l){const t=u[e],r=a[e];if(void 0===r)return delete u[e],!1;if(t.version!==r.version)return t.version=r.version,!1}const c=s.index,h=o.indexVersion,p=c?c.version:null;if(h!==p)return o.indexVersion=p,!1;if(o.drawRange.start!==s.drawRange.start||o.drawRange.count!==s.drawRange.count)return o.drawRange.start=s.drawRange.start,o.drawRange.count=s.drawRange.count,!1;if(i.morphTargetInfluences){let e=!1;for(let r=0;r>>16,2246822507),r^=Math.imul(s^s>>>13,3266489909),s=Math.imul(s^s>>>16,2246822507),s^=Math.imul(r^r>>>13,3266489909),4294967296*(2097151&s)+(r>>>0)}const ls=e=>us(e),ds=e=>us(e),cs=(...e)=>us(e);function hs(e,t=!1){const r=[];!0===e.isNode&&(r.push(e.id),e=e.getSelf());for(const{property:s,childNode:i}of ps(e))r.push(r,us(s.slice(0,-4)),i.getCacheKey(t));return us(r)}function*ps(e,t=!1){for(const r in e){if(!0===r.startsWith("_"))continue;const s=e[r];if(!0===Array.isArray(s))for(let e=0;ee.charCodeAt(0))).buffer}var Ss=Object.freeze({__proto__:null,arrayBufferToBase64:vs,base64ToArrayBuffer:Ns,getCacheKey:hs,getDataFromObject:_s,getLengthFromType:bs,getNodeChildren:ps,getTypeFromLength:fs,getTypedArrayFromType:ys,getValueFromType:Ts,getValueType:xs,hash:cs,hashArray:ds,hashString:ls});const As={VERTEX:"vertex",FRAGMENT:"fragment"},Rs={NONE:"none",FRAME:"frame",RENDER:"render",OBJECT:"object"},Cs={BOOLEAN:"bool",INTEGER:"int",FLOAT:"float",VECTOR2:"vec2",VECTOR3:"vec3",VECTOR4:"vec4",MATRIX2:"mat2",MATRIX3:"mat3",MATRIX4:"mat4"},Es={READ_ONLY:"readOnly",WRITE_ONLY:"writeOnly",READ_WRITE:"readWrite"},ws=["fragment","vertex"],Ms=["setup","analyze","generate"],Bs=[...ws,"compute"],Fs=["x","y","z","w"];let Us=0;class Ps extends o{static get type(){return"Node"}constructor(e=null){super(),this.nodeType=e,this.updateType=Rs.NONE,this.updateBeforeType=Rs.NONE,this.updateAfterType=Rs.NONE,this.uuid=a.generateUUID(),this.version=0,this.global=!1,this.isNode=!0,this._cacheKey=null,this._cacheKeyVersion=0,Object.defineProperty(this,"id",{value:Us++})}set needsUpdate(e){!0===e&&this.version++}get type(){return this.constructor.type}onUpdate(e,t){return this.updateType=t,this.update=e.bind(this.getSelf()),this}onFrameUpdate(e){return this.onUpdate(e,Rs.FRAME)}onRenderUpdate(e){return this.onUpdate(e,Rs.RENDER)}onObjectUpdate(e){return this.onUpdate(e,Rs.OBJECT)}onReference(e){return this.updateReference=e.bind(this.getSelf()),this}getSelf(){return this.self||this}updateReference(){return this}isGlobal(){return this.global}*getChildren(){for(const{childNode:e}of ps(this))yield e}dispose(){this.dispatchEvent({type:"dispose"})}traverse(e){e(this);for(const t of this.getChildren())t.traverse(e)}getCacheKey(e=!1){return!0!==(e=e||this.version!==this._cacheKeyVersion)&&null!==this._cacheKey||(this._cacheKey=cs(hs(this,e),this.customCacheKey()),this._cacheKeyVersion=this.version),this._cacheKey}customCacheKey(){return 0}getScope(){return this}getHash(){return this.uuid}getUpdateType(){return this.updateType}getUpdateBeforeType(){return this.updateBeforeType}getUpdateAfterType(){return this.updateAfterType}getElementType(e){const t=this.getNodeType(e);return e.getElementType(t)}getNodeType(e){const t=e.getNodeProperties(this);return t.outputNode?t.outputNode.getNodeType(e):this.nodeType}getShared(e){const t=this.getHash(e);return e.getNodeFromHash(t)||this}setup(e){const t=e.getNodeProperties(this);let r=0;for(const e of this.getChildren())t["node"+r++]=e;return t.outputNode||null}analyze(e){if(1===e.increaseUsage(this)){const t=e.getNodeProperties(this);for(const r of Object.values(t))r&&!0===r.isNode&&r.build(e)}}generate(e,t){const{outputNode:r}=e.getNodeProperties(this);if(r&&!0===r.isNode)return r.build(e,t)}updateBefore(){console.warn("Abstract function.")}updateAfter(){console.warn("Abstract function.")}update(){console.warn("Abstract function.")}build(e,t=null){const r=this.getShared(e);if(this!==r)return r.build(e,t);e.addNode(this),e.addChain(this);let s=null;const i=e.getBuildStage();if("setup"===i){this.updateReference(e);const t=e.getNodeProperties(this);if(!0!==t.initialized){t.initialized=!0;const r=this.setup(e),s=r&&!0===r.isNode;for(const r of Object.values(t))r&&!0===r.isNode&&r.build(e);s&&r.build(e),t.outputNode=r}}else if("analyze"===i)this.analyze(e);else if("generate"===i){if(1===this.generate.length){const r=this.getNodeType(e),i=e.getDataFromNode(this);s=i.snippet,void 0===s?(s=this.generate(e)||"",i.snippet=s):void 0!==i.flowCodes&&void 0!==e.context.nodeBlock&&e.addFlowCodeHierarchy(this,e.context.nodeBlock),s=e.format(s,r,t)}else s=this.generate(e,t)||""}return e.removeChain(this),e.addSequentialNode(this),s}getSerializeChildren(){return ps(this)}serialize(e){const t=this.getSerializeChildren(),r={};for(const{property:s,index:i,childNode:n}of t)void 0!==i?(void 0===r[s]&&(r[s]=Number.isInteger(i)?[]:{}),r[s][i]=n.toJSON(e.meta).uuid):r[s]=n.toJSON(e.meta).uuid;Object.keys(r).length>0&&(e.inputNodes=r)}deserialize(e){if(void 0!==e.inputNodes){const t=e.meta.nodes;for(const r in e.inputNodes)if(Array.isArray(e.inputNodes[r])){const s=[];for(const i of e.inputNodes[r])s.push(t[i]);this[r]=s}else if("object"==typeof e.inputNodes[r]){const s={};for(const i in e.inputNodes[r]){const n=e.inputNodes[r][i];s[i]=t[n]}this[r]=s}else{const s=e.inputNodes[r];this[r]=t[s]}}}toJSON(e){const{uuid:t,type:r}=this,s=void 0===e||"string"==typeof e;s&&(e={textures:{},images:{},nodes:{}});let i=e.nodes[t];function n(e){const t=[];for(const r in e){const s=e[r];delete s.metadata,t.push(s)}return t}if(void 0===i&&(i={uuid:t,type:r,meta:e,metadata:{version:4.6,type:"Node",generator:"Node.toJSON"}},!0!==s&&(e.nodes[i.uuid]=i),this.serialize(i),delete i.meta),s){const t=n(e.textures),r=n(e.images),s=n(e.nodes);t.length>0&&(i.textures=t),r.length>0&&(i.images=r),s.length>0&&(i.nodes=s)}return i}}class Is extends Ps{static get type(){return"ArrayElementNode"}constructor(e,t){super(),this.node=e,this.indexNode=t,this.isArrayElementNode=!0}getNodeType(e){return this.node.getElementType(e)}generate(e){return`${this.node.build(e)}[ ${this.indexNode.build(e,"uint")} ]`}}class Ds extends Ps{static get type(){return"ConvertNode"}constructor(e,t){super(),this.node=e,this.convertTo=t}getNodeType(e){const t=this.node.getNodeType(e);let r=null;for(const s of this.convertTo.split("|"))null!==r&&e.getTypeLength(t)!==e.getTypeLength(s)||(r=s);return r}serialize(e){super.serialize(e),e.convertTo=this.convertTo}deserialize(e){super.deserialize(e),this.convertTo=e.convertTo}generate(e,t){const r=this.node,s=this.getNodeType(e),i=r.build(e,s);return e.format(i,s,t)}}class Ls extends Ps{static get type(){return"TempNode"}constructor(e=null){super(e),this.isTempNode=!0}hasDependencies(e){return e.getDataFromNode(this).usageCount>1}build(e,t){if("generate"===e.getBuildStage()){const r=e.getVectorType(this.getNodeType(e,t)),s=e.getDataFromNode(this);if(void 0!==s.propertyName)return e.format(s.propertyName,r,t);if("void"!==r&&"void"!==t&&this.hasDependencies(e)){const i=super.build(e,r),n=e.getVarFromNode(this,null,r),o=e.getPropertyName(n);return e.addLineFlowCode(`${o} = ${i}`,this),s.snippet=i,s.propertyName=o,e.format(s.propertyName,r,t)}}return super.build(e,t)}}class Vs extends Ls{static get type(){return"JoinNode"}constructor(e=[],t=null){super(t),this.nodes=e}getNodeType(e){return null!==this.nodeType?e.getVectorType(this.nodeType):e.getTypeFromLength(this.nodes.reduce(((t,r)=>t+e.getTypeLength(r.getNodeType(e))),0))}generate(e,t){const r=this.getNodeType(e),s=this.nodes,i=e.getComponentType(r),n=[];for(const t of s){let r=t.build(e);const s=e.getComponentType(t.getNodeType(e));s!==i&&(r=e.format(r,s,i)),n.push(r)}const o=`${e.getType(r)}( ${n.join(", ")} )`;return e.format(o,r,t)}}const Os=Fs.join("");class Gs extends Ps{static get type(){return"SplitNode"}constructor(e,t="x"){super(),this.node=e,this.components=t,this.isSplitNode=!0}getVectorLength(){let e=this.components.length;for(const t of this.components)e=Math.max(Fs.indexOf(t)+1,e);return e}getComponentType(e){return e.getComponentType(this.node.getNodeType(e))}getNodeType(e){return e.getTypeFromLength(this.components.length,this.getComponentType(e))}generate(e,t){const r=this.node,s=e.getTypeLength(r.getNodeType(e));let i=null;if(s>1){let n=null;this.getVectorLength()>=s&&(n=e.getTypeFromLength(this.getVectorLength(),this.getComponentType(e)));const o=r.build(e,n);i=this.components.length===s&&this.components===Os.slice(0,this.components.length)?e.format(o,n,t):e.format(`${o}.${this.components}`,this.getNodeType(e),t)}else i=r.build(e,t);return i}serialize(e){super.serialize(e),e.components=this.components}deserialize(e){super.deserialize(e),this.components=e.components}}class ks extends Ls{static get type(){return"SetNode"}constructor(e,t,r){super(),this.sourceNode=e,this.components=t,this.targetNode=r}getNodeType(e){return this.sourceNode.getNodeType(e)}generate(e){const{sourceNode:t,components:r,targetNode:s}=this,i=this.getNodeType(e),n=e.getComponentType(s.getNodeType(e)),o=e.getTypeFromLength(r.length,n),a=s.build(e,o),u=t.build(e,i),l=e.getTypeLength(i),d=[];for(let e=0;ee.replace(/r|s/g,"x").replace(/g|t/g,"y").replace(/b|p/g,"z").replace(/a|q/g,"w"),Xs=e=>Ks(e).split("").sort().join(""),Ys={setup(e,t){const r=t.shift();return e(_i(r),...t)},get(e,t,r){if("string"==typeof t&&void 0===e[t]){if(!0!==e.isStackNode&&"assign"===t)return(...e)=>(Ws.assign(r,...e),r);if(js.has(t)){const s=js.get(t);return e.isStackNode?(...e)=>r.add(s(...e)):(...e)=>s(r,...e)}if("self"===t)return e;if(t.endsWith("Assign")&&js.has(t.slice(0,t.length-6))){const s=js.get(t.slice(0,t.length-6));return e.isStackNode?(...e)=>r.assign(e[0],s(...e)):(...e)=>r.assign(s(r,...e))}if(!0===/^[xyzwrgbastpq]{1,4}$/.test(t))return t=Ks(t),Ti(new Gs(r,t));if(!0===/^set[XYZWRGBASTPQ]{1,4}$/.test(t))return t=Xs(t.slice(3).toLowerCase()),r=>Ti(new ks(e,t,r));if(!0===/^flip[XYZWRGBASTPQ]{1,4}$/.test(t))return t=Xs(t.slice(4).toLowerCase()),()=>Ti(new zs(Ti(e),t));if("width"===t||"height"===t||"depth"===t)return"width"===t?t="x":"height"===t?t="y":"depth"===t&&(t="z"),Ti(new Gs(e,t));if(!0===/^\d+$/.test(t))return Ti(new Is(r,new Hs(Number(t),"uint")))}return Reflect.get(e,t,r)},set:(e,t,r,s)=>"string"!=typeof t||void 0!==e[t]||!0!==/^[xyzwrgbastpq]{1,4}$/.test(t)&&"width"!==t&&"height"!==t&&"depth"!==t&&!0!==/^\d+$/.test(t)?Reflect.set(e,t,r,s):(s[t].assign(r),!0)},Qs=new WeakMap,Zs=new WeakMap,Js=function(e,t=null){for(const r in e)e[r]=Ti(e[r],t);return e},ei=function(e,t=null){const r=e.length;for(let s=0;sTi(null!==s?Object.assign(e,s):e);return null===t?(...t)=>i(new e(...vi(t))):null!==r?(r=Ti(r),(...s)=>i(new e(t,...vi(s),r))):(...r)=>i(new e(t,...vi(r)))},ri=function(e,...t){return Ti(new e(...vi(t)))};class si extends Ps{constructor(e,t){super(),this.shaderNode=e,this.inputNodes=t}getNodeType(e){return this.shaderNode.nodeType||this.getOutputNode(e).getNodeType(e)}call(e){const{shaderNode:t,inputNodes:r}=this,s=e.getNodeProperties(t);if(s.onceOutput)return s.onceOutput;let i=null;if(t.layout){let s=Zs.get(e.constructor);void 0===s&&(s=new WeakMap,Zs.set(e.constructor,s));let n=s.get(t);void 0===n&&(n=Ti(e.buildFunctionNode(t)),s.set(t,n)),null!==e.currentFunctionNode&&e.currentFunctionNode.includes.push(n),i=Ti(n.call(r))}else{const s=t.jsFunc,n=null!==r?s(r,e):s(e);i=Ti(n)}return t.once&&(s.onceOutput=i),i}getOutputNode(e){const t=e.getNodeProperties(this);return null===t.outputNode&&(t.outputNode=this.setupOutput(e)),t.outputNode}setup(e){return this.getOutputNode(e)}setupOutput(e){return e.addStack(),e.stack.outputNode=this.call(e),e.removeStack()}generate(e,t){return this.getOutputNode(e).build(e,t)}}class ii extends Ps{constructor(e,t){super(t),this.jsFunc=e,this.layout=null,this.global=!0,this.once=!1}setLayout(e){return this.layout=e,this}call(e=null){return _i(e),Ti(new si(this,e))}setup(){return this.call()}}const ni=[!1,!0],oi=[0,1,2,3],ai=[-1,-2],ui=[.5,1.5,1/3,1e-6,1e6,Math.PI,2*Math.PI,1/Math.PI,2/Math.PI,1/(2*Math.PI),Math.PI/2],li=new Map;for(const e of ni)li.set(e,new Hs(e));const di=new Map;for(const e of oi)di.set(e,new Hs(e,"uint"));const ci=new Map([...di].map((e=>new Hs(e.value,"int"))));for(const e of ai)ci.set(e,new Hs(e,"int"));const hi=new Map([...ci].map((e=>new Hs(e.value))));for(const e of ui)hi.set(e,new Hs(e));for(const e of ui)hi.set(-e,new Hs(-e));const pi={bool:li,uint:di,ints:ci,float:hi},gi=new Map([...li,...hi]),mi=(e,t)=>gi.has(e)?gi.get(e):!0===e.isNode?e:new Hs(e,t),fi=function(e,t=null){return(...r)=>{if((0===r.length||!["bool","float","int","uint"].includes(e)&&r.every((e=>"object"!=typeof e)))&&(r=[Ts(e,...r)]),1===r.length&&null!==t&&t.has(r[0]))return Ti(t.get(r[0]));if(1===r.length){const t=mi(r[0],e);return(e=>{try{return e.getNodeType()}catch(e){return}})(t)===e?Ti(t):Ti(new Ds(t,e))}const s=r.map((e=>mi(e)));return Ti(new Vs(s,e))}},yi=e=>"object"==typeof e&&null!==e?e.value:e,bi=e=>null!=e?e.nodeType||e.convertTo||("string"==typeof e?e:null):null;function xi(e,t){return new Proxy(new ii(e,t),Ys)}const Ti=(e,t=null)=>function(e,t=null){const r=xs(e);if("node"===r){let t=Qs.get(e);return void 0===t&&(t=new Proxy(e,Ys),Qs.set(e,t),Qs.set(t,t)),t}return null===t&&("float"===r||"boolean"===r)||r&&"shader"!==r&&"string"!==r?Ti(mi(e,t)):"shader"===r?Ai(e):e}(e,t),_i=(e,t=null)=>new Js(e,t),vi=(e,t=null)=>new ei(e,t),Ni=(...e)=>new ti(...e),Si=(...e)=>new ri(...e),Ai=(e,t)=>{const r=new xi(e,t),s=(...e)=>{let t;return _i(e),t=e[0]&&e[0].isNode?[...e]:e[0],r.call(t)};return s.shaderNode=r,s.setLayout=e=>(r.setLayout(e),s),s.once=()=>(r.once=!0,s),s};qs("toGlobal",(e=>(e.global=!0,e)));const Ri=e=>{Ws=e},Ci=()=>Ws,Ei=(...e)=>Ws.If(...e);function wi(e){return Ws&&Ws.add(e),e}qs("append",wi);const Mi=new fi("color"),Bi=new fi("float",pi.float),Fi=new fi("int",pi.ints),Ui=new fi("uint",pi.uint),Pi=new fi("bool",pi.bool),Ii=new fi("vec2"),Di=new fi("ivec2"),Li=new fi("uvec2"),Vi=new fi("bvec2"),Oi=new fi("vec3"),Gi=new fi("ivec3"),ki=new fi("uvec3"),zi=new fi("bvec3"),$i=new fi("vec4"),Hi=new fi("ivec4"),Wi=new fi("uvec4"),ji=new fi("bvec4"),qi=new fi("mat2"),Ki=new fi("mat3"),Xi=new fi("mat4");qs("toColor",Mi),qs("toFloat",Bi),qs("toInt",Fi),qs("toUint",Ui),qs("toBool",Pi),qs("toVec2",Ii),qs("toIVec2",Di),qs("toUVec2",Li),qs("toBVec2",Vi),qs("toVec3",Oi),qs("toIVec3",Gi),qs("toUVec3",ki),qs("toBVec3",zi),qs("toVec4",$i),qs("toIVec4",Hi),qs("toUVec4",Wi),qs("toBVec4",ji),qs("toMat2",qi),qs("toMat3",Ki),qs("toMat4",Xi);const Yi=Ni(Is),Qi=(e,t)=>Ti(new Ds(Ti(e),t));qs("element",Yi),qs("convert",Qi);class Zi extends Ps{static get type(){return"UniformGroupNode"}constructor(e,t=!1,r=1){super("string"),this.name=e,this.shared=t,this.order=r,this.isUniformGroup=!0}serialize(e){super.serialize(e),e.name=this.name,e.version=this.version,e.shared=this.shared}deserialize(e){super.deserialize(e),this.name=e.name,this.version=e.version,this.shared=e.shared}}const Ji=e=>new Zi(e),en=(e,t=0)=>new Zi(e,!0,t),tn=en("frame"),rn=en("render"),sn=Ji("object");class nn extends $s{static get type(){return"UniformNode"}constructor(e,t=null){super(e,t),this.isUniformNode=!0,this.name="",this.groupNode=sn}label(e){return this.name=e,this}setGroup(e){return this.groupNode=e,this}getGroup(){return this.groupNode}getUniformHash(e){return this.getHash(e)}onUpdate(e,t){const r=this.getSelf();return e=e.bind(r),super.onUpdate((t=>{const s=e(t,r);void 0!==s&&(this.value=s)}),t)}generate(e,t){const r=this.getNodeType(e),s=this.getUniformHash(e);let i=e.getNodeFromHash(s);void 0===i&&(e.setHashNode(this,s),i=this);const n=i.getInputType(e),o=e.getUniformFromNode(i,n,e.shaderStage,this.name||e.context.label),a=e.getPropertyName(o);return void 0!==e.context.label&&delete e.context.label,e.format(a,r,t)}}const on=(e,t)=>{const r=bi(t||e),s=e&&!0===e.isNode?e.node&&e.node.value||e.value:e;return Ti(new nn(s,r))};class an extends Ps{static get type(){return"PropertyNode"}constructor(e,t=null,r=!1){super(e),this.name=t,this.varying=r,this.isPropertyNode=!0}getHash(e){return this.name||super.getHash(e)}isGlobal(){return!0}generate(e){let t;return!0===this.varying?(t=e.getVaryingFromNode(this,this.name),t.needsInterpolation=!0):t=e.getVarFromNode(this,this.name),e.getPropertyName(t)}}const un=(e,t)=>Ti(new an(e,t)),ln=(e,t)=>Ti(new an(e,t,!0)),dn=Si(an,"vec4","DiffuseColor"),cn=Si(an,"vec3","EmissiveColor"),hn=Si(an,"float","Roughness"),pn=Si(an,"float","Metalness"),gn=Si(an,"float","Clearcoat"),mn=Si(an,"float","ClearcoatRoughness"),fn=Si(an,"vec3","Sheen"),yn=Si(an,"float","SheenRoughness"),bn=Si(an,"float","Iridescence"),xn=Si(an,"float","IridescenceIOR"),Tn=Si(an,"float","IridescenceThickness"),_n=Si(an,"float","AlphaT"),vn=Si(an,"float","Anisotropy"),Nn=Si(an,"vec3","AnisotropyT"),Sn=Si(an,"vec3","AnisotropyB"),An=Si(an,"color","SpecularColor"),Rn=Si(an,"float","SpecularF90"),Cn=Si(an,"float","Shininess"),En=Si(an,"vec4","Output"),wn=Si(an,"float","dashSize"),Mn=Si(an,"float","gapSize"),Bn=Si(an,"float","pointWidth"),Fn=Si(an,"float","IOR"),Un=Si(an,"float","Transmission"),Pn=Si(an,"float","Thickness"),In=Si(an,"float","AttenuationDistance"),Dn=Si(an,"color","AttenuationColor"),Ln=Si(an,"float","Dispersion");class Vn extends Ls{static get type(){return"AssignNode"}constructor(e,t){super(),this.targetNode=e,this.sourceNode=t}hasDependencies(){return!1}getNodeType(e,t){return"void"!==t?this.targetNode.getNodeType(e):"void"}needsSplitAssign(e){const{targetNode:t}=this;if(!1===e.isAvailable("swizzleAssign")&&t.isSplitNode&&t.components.length>1){const r=e.getTypeLength(t.node.getNodeType(e));return Fs.join("").slice(0,r)!==t.components}return!1}generate(e,t){const{targetNode:r,sourceNode:s}=this,i=this.needsSplitAssign(e),n=r.getNodeType(e),o=r.context({assign:!0}).build(e),a=s.build(e,n),u=s.getNodeType(e),l=e.getDataFromNode(this);let d;if(!0===l.initialized)"void"!==t&&(d=o);else if(i){const s=e.getVarFromNode(this,null,n),i=e.getPropertyName(s);e.addLineFlowCode(`${i} = ${a}`,this);const u=r.node.context({assign:!0}).build(e);for(let t=0;t{const s=r.type;let i;return i="pointer"===s?"&"+t.build(e):t.build(e,s),i};if(Array.isArray(i))for(let e=0;e(t=t.length>1||t[0]&&!0===t[0].isNode?vi(t):_i(t[0]),Ti(new Gn(Ti(e),t)));qs("call",kn);class zn extends Ls{static get type(){return"OperatorNode"}constructor(e,t,r,...s){if(super(),s.length>0){let i=new zn(e,t,r);for(let t=0;t>"===r||"<<"===r)return e.getIntegerType(n);if("!"===r||"=="===r||"&&"===r||"||"===r||"^^"===r)return"bool";if("<"===r||">"===r||"<="===r||">="===r){const r=t?e.getTypeLength(t):Math.max(e.getTypeLength(n),e.getTypeLength(o));return r>1?`bvec${r}`:"bool"}return"float"===n&&e.isMatrix(o)?o:e.isMatrix(n)&&e.isVector(o)?e.getVectorFromMatrix(n):e.isVector(n)&&e.isMatrix(o)?e.getVectorFromMatrix(o):e.getTypeLength(o)>e.getTypeLength(n)?o:n}generate(e,t){const r=this.op,s=this.aNode,i=this.bNode,n=this.getNodeType(e,t);let o=null,a=null;"void"!==n?(o=s.getNodeType(e),a=void 0!==i?i.getNodeType(e):null,"<"===r||">"===r||"<="===r||">="===r||"=="===r?e.isVector(o)?a=o:o!==a&&(o=a="float"):">>"===r||"<<"===r?(o=n,a=e.changeComponentType(a,"uint")):e.isMatrix(o)&&e.isVector(a)?a=e.getVectorFromMatrix(o):o=e.isVector(o)&&e.isMatrix(a)?e.getVectorFromMatrix(a):a=n):o=a=n;const u=s.build(e,o),l=void 0!==i?i.build(e,a):null,d=e.getTypeLength(t),c=e.getFunctionOperator(r);return"void"!==t?"<"===r&&d>1?e.useComparisonMethod?e.format(`${e.getMethod("lessThan",t)}( ${u}, ${l} )`,n,t):e.format(`( ${u} < ${l} )`,n,t):"<="===r&&d>1?e.useComparisonMethod?e.format(`${e.getMethod("lessThanEqual",t)}( ${u}, ${l} )`,n,t):e.format(`( ${u} <= ${l} )`,n,t):">"===r&&d>1?e.useComparisonMethod?e.format(`${e.getMethod("greaterThan",t)}( ${u}, ${l} )`,n,t):e.format(`( ${u} > ${l} )`,n,t):">="===r&&d>1?e.useComparisonMethod?e.format(`${e.getMethod("greaterThanEqual",t)}( ${u}, ${l} )`,n,t):e.format(`( ${u} >= ${l} )`,n,t):"!"===r||"~"===r?e.format(`(${r}${u})`,o,t):c?e.format(`${c}( ${u}, ${l} )`,n,t):e.format(`( ${u} ${r} ${l} )`,n,t):"void"!==o?c?e.format(`${c}( ${u}, ${l} )`,n,t):e.format(`${u} ${r} ${l}`,n,t):void 0}serialize(e){super.serialize(e),e.op=this.op}deserialize(e){super.deserialize(e),this.op=e.op}}const $n=Ni(zn,"+"),Hn=Ni(zn,"-"),Wn=Ni(zn,"*"),jn=Ni(zn,"/"),qn=Ni(zn,"%"),Kn=Ni(zn,"=="),Xn=Ni(zn,"!="),Yn=Ni(zn,"<"),Qn=Ni(zn,">"),Zn=Ni(zn,"<="),Jn=Ni(zn,">="),eo=Ni(zn,"&&"),to=Ni(zn,"||"),ro=Ni(zn,"!"),so=Ni(zn,"^^"),io=Ni(zn,"&"),no=Ni(zn,"~"),oo=Ni(zn,"|"),ao=Ni(zn,"^"),uo=Ni(zn,"<<"),lo=Ni(zn,">>");qs("add",$n),qs("sub",Hn),qs("mul",Wn),qs("div",jn),qs("modInt",qn),qs("equal",Kn),qs("notEqual",Xn),qs("lessThan",Yn),qs("greaterThan",Qn),qs("lessThanEqual",Zn),qs("greaterThanEqual",Jn),qs("and",eo),qs("or",to),qs("not",ro),qs("xor",so),qs("bitAnd",io),qs("bitNot",no),qs("bitOr",oo),qs("bitXor",ao),qs("shiftLeft",uo),qs("shiftRight",lo);const co=(...e)=>(console.warn("TSL.OperatorNode: .remainder() has been renamed to .modInt()."),qn(...e));qs("remainder",co);class ho extends Ls{static get type(){return"MathNode"}constructor(e,t,r=null,s=null){super(),this.method=e,this.aNode=t,this.bNode=r,this.cNode=s}getInputType(e){const t=this.aNode.getNodeType(e),r=this.bNode?this.bNode.getNodeType(e):null,s=this.cNode?this.cNode.getNodeType(e):null,i=e.isMatrix(t)?0:e.getTypeLength(t),n=e.isMatrix(r)?0:e.getTypeLength(r),o=e.isMatrix(s)?0:e.getTypeLength(s);return i>n&&i>o?t:n>o?r:o>i?s:t}getNodeType(e){const t=this.method;return t===ho.LENGTH||t===ho.DISTANCE||t===ho.DOT?"float":t===ho.CROSS?"vec3":t===ho.ALL?"bool":t===ho.EQUALS?e.changeComponentType(this.aNode.getNodeType(e),"bool"):t===ho.MOD?this.aNode.getNodeType(e):this.getInputType(e)}generate(e,t){let r=this.method;const s=this.getNodeType(e),i=this.getInputType(e),n=this.aNode,o=this.bNode,a=this.cNode,d=e.renderer.coordinateSystem;if(r===ho.TRANSFORM_DIRECTION){let r=n,s=o;e.isMatrix(r.getNodeType(e))?s=$i(Oi(s),0):r=$i(Oi(r),0);const i=Wn(r,s).xyz;return wo(i).build(e,t)}if(r===ho.NEGATE)return e.format("( - "+n.build(e,i)+" )",s,t);if(r===ho.ONE_MINUS)return Hn(1,n).build(e,t);if(r===ho.RECIPROCAL)return jn(1,n).build(e,t);if(r===ho.DIFFERENCE)return Lo(Hn(n,o)).build(e,t);{const c=[];return r===ho.CROSS||r===ho.MOD?c.push(n.build(e,s),o.build(e,s)):d===u&&r===ho.STEP?c.push(n.build(e,1===e.getTypeLength(n.getNodeType(e))?"float":i),o.build(e,i)):d===u&&(r===ho.MIN||r===ho.MAX)||r===ho.MOD?c.push(n.build(e,i),o.build(e,1===e.getTypeLength(o.getNodeType(e))?"float":i)):r===ho.REFRACT?c.push(n.build(e,i),o.build(e,i),a.build(e,"float")):r===ho.MIX?c.push(n.build(e,i),o.build(e,i),a.build(e,1===e.getTypeLength(a.getNodeType(e))?"float":i)):(d===l&&r===ho.ATAN&&null!==o&&(r="atan2"),c.push(n.build(e,i)),null!==o&&c.push(o.build(e,i)),null!==a&&c.push(a.build(e,i))),e.format(`${e.getMethod(r,s)}( ${c.join(", ")} )`,s,t)}}serialize(e){super.serialize(e),e.method=this.method}deserialize(e){super.deserialize(e),this.method=e.method}}ho.ALL="all",ho.ANY="any",ho.RADIANS="radians",ho.DEGREES="degrees",ho.EXP="exp",ho.EXP2="exp2",ho.LOG="log",ho.LOG2="log2",ho.SQRT="sqrt",ho.INVERSE_SQRT="inversesqrt",ho.FLOOR="floor",ho.CEIL="ceil",ho.NORMALIZE="normalize",ho.FRACT="fract",ho.SIN="sin",ho.COS="cos",ho.TAN="tan",ho.ASIN="asin",ho.ACOS="acos",ho.ATAN="atan",ho.ABS="abs",ho.SIGN="sign",ho.LENGTH="length",ho.NEGATE="negate",ho.ONE_MINUS="oneMinus",ho.DFDX="dFdx",ho.DFDY="dFdy",ho.ROUND="round",ho.RECIPROCAL="reciprocal",ho.TRUNC="trunc",ho.FWIDTH="fwidth",ho.TRANSPOSE="transpose",ho.BITCAST="bitcast",ho.EQUALS="equals",ho.MIN="min",ho.MAX="max",ho.MOD="mod",ho.STEP="step",ho.REFLECT="reflect",ho.DISTANCE="distance",ho.DIFFERENCE="difference",ho.DOT="dot",ho.CROSS="cross",ho.POW="pow",ho.TRANSFORM_DIRECTION="transformDirection",ho.MIX="mix",ho.CLAMP="clamp",ho.REFRACT="refract",ho.SMOOTHSTEP="smoothstep",ho.FACEFORWARD="faceforward";const po=Bi(1e-6),go=Bi(1e6),mo=Bi(Math.PI),fo=Bi(2*Math.PI),yo=Ni(ho,ho.ALL),bo=Ni(ho,ho.ANY),xo=Ni(ho,ho.RADIANS),To=Ni(ho,ho.DEGREES),_o=Ni(ho,ho.EXP),vo=Ni(ho,ho.EXP2),No=Ni(ho,ho.LOG),So=Ni(ho,ho.LOG2),Ao=Ni(ho,ho.SQRT),Ro=Ni(ho,ho.INVERSE_SQRT),Co=Ni(ho,ho.FLOOR),Eo=Ni(ho,ho.CEIL),wo=Ni(ho,ho.NORMALIZE),Mo=Ni(ho,ho.FRACT),Bo=Ni(ho,ho.SIN),Fo=Ni(ho,ho.COS),Uo=Ni(ho,ho.TAN),Po=Ni(ho,ho.ASIN),Io=Ni(ho,ho.ACOS),Do=Ni(ho,ho.ATAN),Lo=Ni(ho,ho.ABS),Vo=Ni(ho,ho.SIGN),Oo=Ni(ho,ho.LENGTH),Go=Ni(ho,ho.NEGATE),ko=Ni(ho,ho.ONE_MINUS),zo=Ni(ho,ho.DFDX),$o=Ni(ho,ho.DFDY),Ho=Ni(ho,ho.ROUND),Wo=Ni(ho,ho.RECIPROCAL),jo=Ni(ho,ho.TRUNC),qo=Ni(ho,ho.FWIDTH),Ko=Ni(ho,ho.TRANSPOSE),Xo=Ni(ho,ho.BITCAST),Yo=Ni(ho,ho.EQUALS),Qo=Ni(ho,ho.MIN),Zo=Ni(ho,ho.MAX),Jo=Ni(ho,ho.MOD),ea=Ni(ho,ho.STEP),ta=Ni(ho,ho.REFLECT),ra=Ni(ho,ho.DISTANCE),sa=Ni(ho,ho.DIFFERENCE),ia=Ni(ho,ho.DOT),na=Ni(ho,ho.CROSS),oa=Ni(ho,ho.POW),aa=Ni(ho,ho.POW,2),ua=Ni(ho,ho.POW,3),la=Ni(ho,ho.POW,4),da=Ni(ho,ho.TRANSFORM_DIRECTION),ca=e=>Wn(Vo(e),oa(Lo(e),1/3)),ha=e=>ia(e,e),pa=Ni(ho,ho.MIX),ga=(e,t=0,r=1)=>Ti(new ho(ho.CLAMP,Ti(e),Ti(t),Ti(r))),ma=e=>ga(e),fa=Ni(ho,ho.REFRACT),ya=Ni(ho,ho.SMOOTHSTEP),ba=Ni(ho,ho.FACEFORWARD),xa=Ai((([e])=>{const t=ia(e.xy,Ii(12.9898,78.233)),r=Jo(t,mo);return Mo(Bo(r).mul(43758.5453))})),Ta=(e,t,r)=>pa(t,r,e),_a=(e,t,r)=>ya(t,r,e),va=(e,t)=>(console.warn('THREE.TSL: "atan2" is overloaded. Use "atan" instead.'),Do(e,t)),Na=ba,Sa=Ro;qs("all",yo),qs("any",bo),qs("equals",Yo),qs("radians",xo),qs("degrees",To),qs("exp",_o),qs("exp2",vo),qs("log",No),qs("log2",So),qs("sqrt",Ao),qs("inverseSqrt",Ro),qs("floor",Co),qs("ceil",Eo),qs("normalize",wo),qs("fract",Mo),qs("sin",Bo),qs("cos",Fo),qs("tan",Uo),qs("asin",Po),qs("acos",Io),qs("atan",Do),qs("abs",Lo),qs("sign",Vo),qs("length",Oo),qs("lengthSq",ha),qs("negate",Go),qs("oneMinus",ko),qs("dFdx",zo),qs("dFdy",$o),qs("round",Ho),qs("reciprocal",Wo),qs("trunc",jo),qs("fwidth",qo),qs("atan2",va),qs("min",Qo),qs("max",Zo),qs("mod",Jo),qs("step",ea),qs("reflect",ta),qs("distance",ra),qs("dot",ia),qs("cross",na),qs("pow",oa),qs("pow2",aa),qs("pow3",ua),qs("pow4",la),qs("transformDirection",da),qs("mix",Ta),qs("clamp",ga),qs("refract",fa),qs("smoothstep",_a),qs("faceForward",ba),qs("difference",sa),qs("saturate",ma),qs("cbrt",ca),qs("transpose",Ko),qs("rand",xa);class Aa extends Ps{static get type(){return"ConditionalNode"}constructor(e,t,r=null){super(),this.condNode=e,this.ifNode=t,this.elseNode=r}getNodeType(e){const{ifNode:t,elseNode:r}=e.getNodeProperties(this);if(void 0===t)return this.setup(e),this.getNodeType(e);const s=t.getNodeType(e);if(null!==r){const t=r.getNodeType(e);if(e.getTypeLength(t)>e.getTypeLength(s))return t}return s}setup(e){const t=this.condNode.cache(),r=this.ifNode.cache(),s=this.elseNode?this.elseNode.cache():null,i=e.context.nodeBlock;e.getDataFromNode(r).parentNodeBlock=i,null!==s&&(e.getDataFromNode(s).parentNodeBlock=i);const n=e.getNodeProperties(this);n.condNode=t,n.ifNode=r.context({nodeBlock:r}),n.elseNode=s?s.context({nodeBlock:s}):null}generate(e,t){const r=this.getNodeType(e),s=e.getDataFromNode(this);if(void 0!==s.nodeProperty)return s.nodeProperty;const{condNode:i,ifNode:n,elseNode:o}=e.getNodeProperties(this),a="void"!==t,u=a?un(r).build(e):"";s.nodeProperty=u;const l=i.build(e,"bool");e.addFlowCode(`\n${e.tab}if ( ${l} ) {\n\n`).addFlowTab();let d=n.build(e,r);if(d&&(d=a?u+" = "+d+";":"return "+d+";"),e.removeFlowTab().addFlowCode(e.tab+"\t"+d+"\n\n"+e.tab+"}"),null!==o){e.addFlowCode(" else {\n\n").addFlowTab();let t=o.build(e,r);t&&(t=a?u+" = "+t+";":"return "+t+";"),e.removeFlowTab().addFlowCode(e.tab+"\t"+t+"\n\n"+e.tab+"}\n\n")}else e.addFlowCode("\n\n");return e.format(u,r,t)}}const Ra=Ni(Aa);qs("select",Ra);const Ca=(...e)=>(console.warn("TSL.ConditionalNode: cond() has been renamed to select()."),Ra(...e));qs("cond",Ca);class Ea extends Ps{static get type(){return"ContextNode"}constructor(e,t={}){super(),this.isContextNode=!0,this.node=e,this.value=t}getScope(){return this.node.getScope()}getNodeType(e){return this.node.getNodeType(e)}analyze(e){this.node.build(e)}setup(e){const t=e.getContext();e.setContext({...e.context,...this.value});const r=this.node.build(e);return e.setContext(t),r}generate(e,t){const r=e.getContext();e.setContext({...e.context,...this.value});const s=this.node.build(e,t);return e.setContext(r),s}}const wa=Ni(Ea),Ma=(e,t)=>wa(e,{label:t});qs("context",wa),qs("label",Ma);class Ba extends Ps{static get type(){return"VarNode"}constructor(e,t=null){super(),this.node=e,this.name=t,this.global=!0,this.isVarNode=!0}getHash(e){return this.name||super.getHash(e)}getNodeType(e){return this.node.getNodeType(e)}generate(e){const{node:t,name:r}=this,s=e.getVarFromNode(this,r,e.getVectorType(this.getNodeType(e))),i=e.getPropertyName(s),n=t.build(e,s.type);return e.addLineFlowCode(`${i} = ${n}`,this),i}}const Fa=Ni(Ba);qs("toVar",((...e)=>Fa(...e).append()));const Ua=e=>(console.warn('TSL: "temp" is deprecated. Use ".toVar()" instead.'),Fa(e));qs("temp",Ua);class Pa extends Ps{static get type(){return"VaryingNode"}constructor(e,t=null){super(),this.node=e,this.name=t,this.isVaryingNode=!0}isGlobal(){return!0}getHash(e){return this.name||super.getHash(e)}getNodeType(e){return this.node.getNodeType(e)}setupVarying(e){const t=e.getNodeProperties(this);let r=t.varying;if(void 0===r){const s=this.name,i=this.getNodeType(e);t.varying=r=e.getVaryingFromNode(this,s,i),t.node=this.node}return r.needsInterpolation||(r.needsInterpolation="fragment"===e.shaderStage),r}setup(e){this.setupVarying(e)}analyze(e){return this.setupVarying(e),this.node.analyze(e)}generate(e){const t=e.getNodeProperties(this),r=this.setupVarying(e),s="fragment"===e.shaderStage&&!0===t.reassignPosition&&e.context.needsPositionReassign;if(void 0===t.propertyName||s){const i=this.getNodeType(e),n=e.getPropertyName(r,As.VERTEX);e.flowNodeFromShaderStage(As.VERTEX,this.node,i,n),t.propertyName=n,s?t.reassignPosition=!1:void 0===t.reassignPosition&&e.context.isPositionNodeInput&&(t.reassignPosition=!0)}return e.getPropertyName(r)}}const Ia=Ni(Pa),Da=e=>Ia(e);qs("varying",Ia),qs("vertexStage",Da);const La=Ai((([e])=>{const t=e.mul(.9478672986).add(.0521327014).pow(2.4),r=e.mul(.0773993808),s=e.lessThanEqual(.04045);return pa(t,r,s)})).setLayout({name:"sRGBTransferEOTF",type:"vec3",inputs:[{name:"color",type:"vec3"}]}),Va=Ai((([e])=>{const t=e.pow(.41666).mul(1.055).sub(.055),r=e.mul(12.92),s=e.lessThanEqual(.0031308);return pa(t,r,s)})).setLayout({name:"sRGBTransferOETF",type:"vec3",inputs:[{name:"color",type:"vec3"}]}),Oa="WorkingColorSpace",Ga="OutputColorSpace";class ka extends Ls{static get type(){return"ColorSpaceNode"}constructor(e,t,r){super("vec4"),this.colorNode=e,this.source=t,this.target=r}resolveColorSpace(e,t){return t===Oa?d.workingColorSpace:t===Ga?e.context.outputColorSpace||e.renderer.outputColorSpace:t}setup(e){const{colorNode:t}=this,r=this.resolveColorSpace(e,this.source),s=this.resolveColorSpace(e,this.target);let n=t;return!1!==d.enabled&&r!==s&&r&&s?(d.getTransfer(r)===c&&(n=$i(La(n.rgb),n.a)),d.getPrimaries(r)!==d.getPrimaries(s)&&(n=$i(Ki(d._getMatrix(new i,r,s)).mul(n.rgb),n.a)),d.getTransfer(s)===c&&(n=$i(Va(n.rgb),n.a)),n):n}}const za=e=>Ti(new ka(Ti(e),Oa,Ga)),$a=e=>Ti(new ka(Ti(e),Ga,Oa)),Ha=(e,t)=>Ti(new ka(Ti(e),Oa,t)),Wa=(e,t)=>Ti(new ka(Ti(e),t,Oa));qs("toOutputColorSpace",za),qs("toWorkingColorSpace",$a),qs("workingToColorSpace",Ha),qs("colorSpaceToWorking",Wa);let ja=class extends Is{static get type(){return"ReferenceElementNode"}constructor(e,t){super(e,t),this.referenceNode=e,this.isReferenceElementNode=!0}getNodeType(){return this.referenceNode.uniformType}generate(e){const t=super.generate(e),r=this.referenceNode.getNodeType(),s=this.getNodeType();return e.format(t,r,s)}};class qa extends Ps{static get type(){return"ReferenceBaseNode"}constructor(e,t,r=null,s=null){super(),this.property=e,this.uniformType=t,this.object=r,this.count=s,this.properties=e.split("."),this.reference=r,this.node=null,this.group=null,this.updateType=Rs.OBJECT}setGroup(e){return this.group=e,this}element(e){return Ti(new ja(this,Ti(e)))}setNodeType(e){const t=on(null,e).getSelf();null!==this.group&&t.setGroup(this.group),this.node=t}getNodeType(e){return null===this.node&&(this.updateReference(e),this.updateValue()),this.node.getNodeType(e)}getValueFromReference(e=this.reference){const{properties:t}=this;let r=e[t[0]];for(let e=1;eTi(new Ka(e,t,r));class Ya extends Ls{static get type(){return"ToneMappingNode"}constructor(e,t=Za,r=null){super("vec3"),this.toneMapping=e,this.exposureNode=t,this.colorNode=r}customCacheKey(){return cs(this.toneMapping)}setup(e){const t=this.colorNode||e.context.color,r=this.toneMapping;if(r===h)return t;let s=null;const i=e.renderer.library.getToneMappingFunction(r);return null!==i?s=$i(i(t.rgb,this.exposureNode),t.a):(console.error("ToneMappingNode: Unsupported Tone Mapping configuration.",r),s=t),s}}const Qa=(e,t,r)=>Ti(new Ya(e,Ti(t),Ti(r))),Za=Xa("toneMappingExposure","float");qs("toneMapping",((e,t,r)=>Qa(t,r,e)));class Ja extends $s{static get type(){return"BufferAttributeNode"}constructor(e,t=null,r=0,s=0){super(e,t),this.isBufferNode=!0,this.bufferType=t,this.bufferStride=r,this.bufferOffset=s,this.usage=p,this.instanced=!1,this.attribute=null,this.global=!0,e&&!0===e.isBufferAttribute&&(this.attribute=e,this.usage=e.usage,this.instanced=e.isInstancedBufferAttribute)}getHash(e){if(0===this.bufferStride&&0===this.bufferOffset){let t=e.globalCache.getData(this.value);return void 0===t&&(t={node:this},e.globalCache.setData(this.value,t)),t.node.uuid}return this.uuid}getNodeType(e){return null===this.bufferType&&(this.bufferType=e.getTypeFromAttribute(this.attribute)),this.bufferType}setup(e){if(null!==this.attribute)return;const t=this.getNodeType(e),r=this.value,s=e.getTypeLength(t),i=this.bufferStride||s,n=this.bufferOffset,o=!0===r.isInterleavedBuffer?r:new g(r,i),a=new f(o,s,n);o.setUsage(this.usage),this.attribute=a,this.attribute.isInstancedBufferAttribute=this.instanced}generate(e){const t=this.getNodeType(e),r=e.getBufferAttributeFromNode(this,t),s=e.getPropertyName(r);let i=null;if("vertex"===e.shaderStage||"compute"===e.shaderStage)this.name=s,i=s;else{i=Ia(this).build(e,t)}return i}getInputType(){return"bufferAttribute"}setUsage(e){return this.usage=e,this.attribute&&!0===this.attribute.isBufferAttribute&&(this.attribute.usage=e),this}setInstanced(e){return this.instanced=e,this}}const eu=(e,t=null,r=0,s=0)=>Ti(new Ja(e,t,r,s)),tu=(e,t=null,r=0,s=0)=>eu(e,t,r,s).setUsage(m),ru=(e,t=null,r=0,s=0)=>eu(e,t,r,s).setInstanced(!0),su=(e,t=null,r=0,s=0)=>tu(e,t,r,s).setInstanced(!0);qs("toAttribute",(e=>eu(e.value)));class iu extends Ps{static get type(){return"ComputeNode"}constructor(e,t,r=[64]){super("void"),this.isComputeNode=!0,this.computeNode=e,this.count=t,this.workgroupSize=r,this.dispatchCount=0,this.version=1,this.name="",this.updateBeforeType=Rs.OBJECT,this.onInitFunction=null,this.updateDispatchCount()}dispose(){this.dispatchEvent({type:"dispose"})}label(e){return this.name=e,this}updateDispatchCount(){const{count:e,workgroupSize:t}=this;let r=t[0];for(let e=1;eTi(new iu(Ti(e),t,r));qs("compute",nu);class ou extends Ps{static get type(){return"CacheNode"}constructor(e,t=!0){super(),this.node=e,this.parent=t,this.isCacheNode=!0}getNodeType(e){const t=e.getCache(),r=e.getCacheFromNode(this,this.parent);e.setCache(r);const s=this.node.getNodeType(e);return e.setCache(t),s}build(e,...t){const r=e.getCache(),s=e.getCacheFromNode(this,this.parent);e.setCache(s);const i=this.node.build(e,...t);return e.setCache(r),i}}const au=(e,t)=>Ti(new ou(Ti(e),t));qs("cache",au);class uu extends Ps{static get type(){return"BypassNode"}constructor(e,t){super(),this.isBypassNode=!0,this.outputNode=e,this.callNode=t}getNodeType(e){return this.outputNode.getNodeType(e)}generate(e){const t=this.callNode.build(e,"void");return""!==t&&e.addLineFlowCode(t,this),this.outputNode.build(e)}}const lu=Ni(uu);qs("bypass",lu);class du extends Ps{static get type(){return"RemapNode"}constructor(e,t,r,s=Bi(0),i=Bi(1)){super(),this.node=e,this.inLowNode=t,this.inHighNode=r,this.outLowNode=s,this.outHighNode=i,this.doClamp=!0}setup(){const{node:e,inLowNode:t,inHighNode:r,outLowNode:s,outHighNode:i,doClamp:n}=this;let o=e.sub(t).div(r.sub(t));return!0===n&&(o=o.clamp()),o.mul(i.sub(s)).add(s)}}const cu=Ni(du,null,null,{doClamp:!1}),hu=Ni(du);qs("remap",cu),qs("remapClamp",hu);class pu extends Ps{static get type(){return"ExpressionNode"}constructor(e="",t="void"){super(t),this.snippet=e}generate(e,t){const r=this.getNodeType(e),s=this.snippet;if("void"!==r)return e.format(`( ${s} )`,r,t);e.addLineFlowCode(s,this)}}const gu=Ni(pu),mu=e=>(e?Ra(e,gu("discard")):gu("discard")).append();qs("discard",mu);class fu extends Ls{static get type(){return"RenderOutputNode"}constructor(e,t,r){super("vec4"),this.colorNode=e,this.toneMapping=t,this.outputColorSpace=r,this.isRenderOutputNode=!0}setup({context:e}){let t=this.colorNode||e.color;const r=(null!==this.toneMapping?this.toneMapping:e.toneMapping)||h,s=(null!==this.outputColorSpace?this.outputColorSpace:e.outputColorSpace)||y;return r!==h&&(t=t.toneMapping(r)),s!==y&&s!==d.workingColorSpace&&(t=t.workingToColorSpace(s)),t}}const yu=(e,t=null,r=null)=>Ti(new fu(Ti(e),t,r));qs("renderOutput",yu);class bu extends Ps{static get type(){return"AttributeNode"}constructor(e,t=null){super(t),this.global=!0,this._attributeName=e}getHash(e){return this.getAttributeName(e)}getNodeType(e){let t=this.nodeType;if(null===t){const r=this.getAttributeName(e);if(e.hasGeometryAttribute(r)){const s=e.geometry.getAttribute(r);t=e.getTypeFromAttribute(s)}else t="float"}return t}setAttributeName(e){return this._attributeName=e,this}getAttributeName(){return this._attributeName}generate(e){const t=this.getAttributeName(e),r=this.getNodeType(e);if(!0===e.hasGeometryAttribute(t)){const s=e.geometry.getAttribute(t),i=e.getTypeFromAttribute(s),n=e.getAttribute(t,i);if("vertex"===e.shaderStage)return e.format(n.name,i,r);return Ia(this).build(e,r)}return console.warn(`AttributeNode: Vertex attribute "${t}" not found on geometry.`),e.generateConst(r)}serialize(e){super.serialize(e),e.global=this.global,e._attributeName=this._attributeName}deserialize(e){super.deserialize(e),this.global=e.global,this._attributeName=e._attributeName}}const xu=(e,t)=>Ti(new bu(e,t)),Tu=(e=0)=>xu("uv"+(e>0?e:""),"vec2");class _u extends Ps{static get type(){return"TextureSizeNode"}constructor(e,t=null){super("uvec2"),this.isTextureSizeNode=!0,this.textureNode=e,this.levelNode=t}generate(e,t){const r=this.textureNode.build(e,"property"),s=null===this.levelNode?"0":this.levelNode.build(e,"int");return e.format(`${e.getMethod("textureDimensions")}( ${r}, ${s} )`,this.getNodeType(e),t)}}const vu=Ni(_u);class Nu extends nn{static get type(){return"MaxMipLevelNode"}constructor(e){super(0),this._textureNode=e,this.updateType=Rs.FRAME}get textureNode(){return this._textureNode}get texture(){return this._textureNode.value}update(){const e=this.texture,t=e.images,r=t&&t.length>0?t[0]&&t[0].image||t[0]:e.image;if(r&&void 0!==r.width){const{width:e,height:t}=r;this.value=Math.log2(Math.max(e,t))}}}const Su=Ni(Nu);class Au extends nn{static get type(){return"TextureNode"}constructor(e,t=null,r=null,s=null){super(e),this.isTextureNode=!0,this.uvNode=t,this.levelNode=r,this.biasNode=s,this.compareNode=null,this.depthNode=null,this.gradNode=null,this.sampler=!0,this.updateMatrix=!1,this.updateType=Rs.NONE,this.referenceNode=null,this._value=e,this._matrixUniform=null,this.setUpdateMatrix(null===t)}set value(e){this.referenceNode?this.referenceNode.value=e:this._value=e}get value(){return this.referenceNode?this.referenceNode.value:this._value}getUniformHash(){return this.value.uuid}getNodeType(){return!0===this.value.isDepthTexture?"float":this.value.type===b?"uvec4":this.value.type===x?"ivec4":"vec4"}getInputType(){return"texture"}getDefaultUV(){return Tu(this.value.channel)}updateReference(){return this.value}getTransformedUV(e){return null===this._matrixUniform&&(this._matrixUniform=on(this.value.matrix)),this._matrixUniform.mul(Oi(e,1)).xy}setUpdateMatrix(e){return this.updateMatrix=e,this.updateType=e?Rs.RENDER:Rs.NONE,this}setupUV(e,t){const r=this.value;return e.isFlipY()&&(r.image instanceof ImageBitmap&&!0===r.flipY||!0===r.isRenderTargetTexture||!0===r.isFramebufferTexture||!0===r.isDepthTexture)&&(t=this.sampler?t.flipY():t.setY(Fi(vu(this,this.levelNode).y).sub(t.y).sub(1))),t}setup(e){const t=e.getNodeProperties(this);t.referenceNode=this.referenceNode;const r=this.value;if(!r||!0!==r.isTexture)throw new Error("THREE.TSL: `texture( value )` function expects a valid instance of THREE.Texture().");let s=this.uvNode;null!==s&&!0!==e.context.forceUVContext||!e.context.getUV||(s=e.context.getUV(this)),s||(s=this.getDefaultUV()),!0===this.updateMatrix&&(s=this.getTransformedUV(s)),s=this.setupUV(e,s);let i=this.levelNode;null===i&&e.context.getTextureLevel&&(i=e.context.getTextureLevel(this)),t.uvNode=s,t.levelNode=i,t.biasNode=this.biasNode,t.compareNode=this.compareNode,t.gradNode=this.gradNode,t.depthNode=this.depthNode}generateUV(e,t){return t.build(e,!0===this.sampler?"vec2":"ivec2")}generateSnippet(e,t,r,s,i,n,o,a){const u=this.value;let l;return l=s?e.generateTextureLevel(u,t,r,s,n):i?e.generateTextureBias(u,t,r,i,n):a?e.generateTextureGrad(u,t,r,a,n):o?e.generateTextureCompare(u,t,r,o,n):!1===this.sampler?e.generateTextureLoad(u,t,r,n):e.generateTexture(u,t,r,n),l}generate(e,t){const r=this.value,s=e.getNodeProperties(this),i=super.generate(e,"property");if("sampler"===t)return i+"_sampler";if(e.isReference(t))return i;{const n=e.getDataFromNode(this);let o=n.propertyName;if(void 0===o){const{uvNode:t,levelNode:r,biasNode:a,compareNode:u,depthNode:l,gradNode:d}=s,c=this.generateUV(e,t),h=r?r.build(e,"float"):null,p=a?a.build(e,"float"):null,g=l?l.build(e,"int"):null,m=u?u.build(e,"float"):null,f=d?[d[0].build(e,"vec2"),d[1].build(e,"vec2")]:null,y=e.getVarFromNode(this);o=e.getPropertyName(y);const b=this.generateSnippet(e,i,c,h,p,g,m,f);e.addLineFlowCode(`${o} = ${b}`,this),n.snippet=b,n.propertyName=o}let a=o;const u=this.getNodeType(e);return e.needsToWorkingColorSpace(r)&&(a=Wa(gu(a,u),r.colorSpace).setup(e).build(e,u)),e.format(a,u,t)}}setSampler(e){return this.sampler=e,this}getSampler(){return this.sampler}uv(e){return console.warn("THREE.TextureNode: .uv() has been renamed. Use .sample() instead."),this.sample(e)}sample(e){const t=this.clone();return t.uvNode=Ti(e),t.referenceNode=this.getSelf(),Ti(t)}blur(e){const t=this.clone();return t.biasNode=Ti(e).mul(Su(t)),t.referenceNode=this.getSelf(),Ti(t)}level(e){const t=this.clone();return t.levelNode=Ti(e),t.referenceNode=this.getSelf(),Ti(t)}size(e){return vu(this,e)}bias(e){const t=this.clone();return t.biasNode=Ti(e),t.referenceNode=this.getSelf(),Ti(t)}compare(e){const t=this.clone();return t.compareNode=Ti(e),t.referenceNode=this.getSelf(),Ti(t)}grad(e,t){const r=this.clone();return r.gradNode=[Ti(e),Ti(t)],r.referenceNode=this.getSelf(),Ti(r)}depth(e){const t=this.clone();return t.depthNode=Ti(e),t.referenceNode=this.getSelf(),Ti(t)}serialize(e){super.serialize(e),e.value=this.value.toJSON(e.meta).uuid,e.sampler=this.sampler,e.updateMatrix=this.updateMatrix,e.updateType=this.updateType}deserialize(e){super.deserialize(e),this.value=e.meta.textures[e.value],this.sampler=e.sampler,this.updateMatrix=e.updateMatrix,this.updateType=e.updateType}update(){const e=this.value,t=this._matrixUniform;null!==t&&(t.value=e.matrix),!0===e.matrixAutoUpdate&&e.updateMatrix()}clone(){const e=new this.constructor(this.value,this.uvNode,this.levelNode,this.biasNode);return e.sampler=this.sampler,e}}const Ru=Ni(Au),Cu=(...e)=>Ru(...e).setSampler(!1),Eu=on("float").label("cameraNear").setGroup(rn).onRenderUpdate((({camera:e})=>e.near)),wu=on("float").label("cameraFar").setGroup(rn).onRenderUpdate((({camera:e})=>e.far)),Mu=on("mat4").label("cameraProjectionMatrix").setGroup(rn).onRenderUpdate((({camera:e})=>e.projectionMatrix)),Bu=on("mat4").label("cameraProjectionMatrixInverse").setGroup(rn).onRenderUpdate((({camera:e})=>e.projectionMatrixInverse)),Fu=on("mat4").label("cameraViewMatrix").setGroup(rn).onRenderUpdate((({camera:e})=>e.matrixWorldInverse)),Uu=on("mat4").label("cameraWorldMatrix").setGroup(rn).onRenderUpdate((({camera:e})=>e.matrixWorld)),Pu=on("mat3").label("cameraNormalMatrix").setGroup(rn).onRenderUpdate((({camera:e})=>e.normalMatrix)),Iu=on(new r).label("cameraPosition").setGroup(rn).onRenderUpdate((({camera:e},t)=>t.value.setFromMatrixPosition(e.matrixWorld)));class Du extends Ps{static get type(){return"Object3DNode"}constructor(e,t=null){super(),this.scope=e,this.object3d=t,this.updateType=Rs.OBJECT,this._uniformNode=new nn(null)}getNodeType(){const e=this.scope;return e===Du.WORLD_MATRIX?"mat4":e===Du.POSITION||e===Du.VIEW_POSITION||e===Du.DIRECTION||e===Du.SCALE?"vec3":void 0}update(e){const t=this.object3d,s=this._uniformNode,i=this.scope;if(i===Du.WORLD_MATRIX)s.value=t.matrixWorld;else if(i===Du.POSITION)s.value=s.value||new r,s.value.setFromMatrixPosition(t.matrixWorld);else if(i===Du.SCALE)s.value=s.value||new r,s.value.setFromMatrixScale(t.matrixWorld);else if(i===Du.DIRECTION)s.value=s.value||new r,t.getWorldDirection(s.value);else if(i===Du.VIEW_POSITION){const i=e.camera;s.value=s.value||new r,s.value.setFromMatrixPosition(t.matrixWorld),s.value.applyMatrix4(i.matrixWorldInverse)}}generate(e){const t=this.scope;return t===Du.WORLD_MATRIX?this._uniformNode.nodeType="mat4":t!==Du.POSITION&&t!==Du.VIEW_POSITION&&t!==Du.DIRECTION&&t!==Du.SCALE||(this._uniformNode.nodeType="vec3"),this._uniformNode.build(e)}serialize(e){super.serialize(e),e.scope=this.scope}deserialize(e){super.deserialize(e),this.scope=e.scope}}Du.WORLD_MATRIX="worldMatrix",Du.POSITION="position",Du.SCALE="scale",Du.VIEW_POSITION="viewPosition",Du.DIRECTION="direction";const Lu=Ni(Du,Du.DIRECTION),Vu=Ni(Du,Du.WORLD_MATRIX),Ou=Ni(Du,Du.POSITION),Gu=Ni(Du,Du.SCALE),ku=Ni(Du,Du.VIEW_POSITION);class zu extends Du{static get type(){return"ModelNode"}constructor(e){super(e)}update(e){this.object3d=e.object,super.update(e)}}const $u=Si(zu,zu.DIRECTION),Hu=Si(zu,zu.WORLD_MATRIX),Wu=Si(zu,zu.POSITION),ju=Si(zu,zu.SCALE),qu=Si(zu,zu.VIEW_POSITION),Ku=on(new i).onObjectUpdate((({object:e},t)=>t.value.getNormalMatrix(e.matrixWorld))),Xu=on(new n).onObjectUpdate((({object:e},t)=>t.value.copy(e.matrixWorld).invert())),Yu=Ai((e=>e.renderer.nodes.modelViewMatrix||Qu)).once()().toVar("modelViewMatrix"),Qu=Fu.mul(Hu),Zu=Ai((e=>(e.context.isHighPrecisionModelViewMatrix=!0,on("mat4").onObjectUpdate((({object:e,camera:t})=>e.modelViewMatrix.multiplyMatrices(t.matrixWorldInverse,e.matrixWorld)))))).once()().toVar("highpModelViewMatrix"),Ju=Ai((e=>{const t=e.context.isHighPrecisionModelViewMatrix;return on("mat3").onObjectUpdate((({object:e,camera:r})=>(!0!==t&&e.modelViewMatrix.multiplyMatrices(r.matrixWorldInverse,e.matrixWorld),e.normalMatrix.getNormalMatrix(e.modelViewMatrix))))})).once()().toVar("highpModelNormalViewMatrix"),el=xu("position","vec3"),tl=el.varying("positionLocal"),rl=el.varying("positionPrevious"),sl=Hu.mul(tl).xyz.varying("v_positionWorld").context({needsPositionReassign:!0}),il=tl.transformDirection(Hu).varying("v_positionWorldDirection").normalize().toVar("positionWorldDirection").context({needsPositionReassign:!0}),nl=Ai((e=>e.context.setupPositionView()),"vec3").once()().varying("v_positionView").context({needsPositionReassign:!0}),ol=nl.negate().varying("v_positionViewDirection").normalize().toVar("positionViewDirection");class al extends Ps{static get type(){return"FrontFacingNode"}constructor(){super("bool"),this.isFrontFacingNode=!0}generate(e){const{renderer:t,material:r}=e;return t.coordinateSystem===u&&r.side===T?"false":e.getFrontFacing()}}const ul=Si(al),ll=Bi(ul).mul(2).sub(1),dl=xu("normal","vec3"),cl=Ai((e=>!1===e.geometry.hasAttribute("normal")?(console.warn('TSL.NormalNode: Vertex attribute "normal" not found on geometry.'),Oi(0,1,0)):dl),"vec3").once()().toVar("normalLocal"),hl=nl.dFdx().cross(nl.dFdy()).normalize().toVar("normalFlat"),pl=Ai((e=>{let t;return t=!0===e.material.flatShading?hl:Ia(xl(cl),"v_normalView").normalize(),t}),"vec3").once()().toVar("normalView"),gl=Ia(pl.transformDirection(Fu),"v_normalWorld").normalize().toVar("normalWorld"),ml=Ai((e=>e.context.setupNormal().context({getUV:null})),"vec3").once()().mul(ll).toVar("transformedNormalView"),fl=ml.transformDirection(Fu).toVar("transformedNormalWorld"),yl=Ai((e=>e.context.setupClearcoatNormal().context({getUV:null})),"vec3").once()().mul(ll).toVar("transformedClearcoatNormalView"),bl=Ai((([e,t=Hu])=>{const r=Ki(t),s=e.div(Oi(r[0].dot(r[0]),r[1].dot(r[1]),r[2].dot(r[2])));return r.mul(s).xyz})),xl=Ai((([e],t)=>{const r=t.renderer.nodes.modelNormalViewMatrix;if(null!==r)return r.transformDirection(e);const s=Ku.mul(e);return Fu.transformDirection(s)})),Tl=on(0).onReference((({material:e})=>e)).onRenderUpdate((({material:e})=>e.refractionRatio)),_l=ol.negate().reflect(ml),vl=ol.negate().refract(ml,Tl),Nl=_l.transformDirection(Fu).toVar("reflectVector"),Sl=vl.transformDirection(Fu).toVar("reflectVector");class Al extends Au{static get type(){return"CubeTextureNode"}constructor(e,t=null,r=null,s=null){super(e,t,r,s),this.isCubeTextureNode=!0}getInputType(){return"cubeTexture"}getDefaultUV(){const e=this.value;return e.mapping===_?Nl:e.mapping===v?Sl:(console.error('THREE.CubeTextureNode: Mapping "%s" not supported.',e.mapping),Oi(0,0,0))}setUpdateMatrix(){}setupUV(e,t){const r=this.value;return e.renderer.coordinateSystem!==l&&r.isRenderTargetTexture?t:Oi(t.x.negate(),t.yz)}generateUV(e,t){return t.build(e,"vec3")}}const Rl=Ni(Al);class Cl extends nn{static get type(){return"BufferNode"}constructor(e,t,r=0){super(e,t),this.isBufferNode=!0,this.bufferType=t,this.bufferCount=r}getElementType(e){return this.getNodeType(e)}getInputType(){return"buffer"}}const El=(e,t,r)=>Ti(new Cl(e,t,r));class wl extends Is{static get type(){return"UniformArrayElementNode"}constructor(e,t){super(e,t),this.isArrayBufferElementNode=!0}generate(e){const t=super.generate(e),r=this.getNodeType(),s=this.node.getPaddedType();return e.format(t,s,r)}}class Ml extends Cl{static get type(){return"UniformArrayNode"}constructor(e,t=null){super(null),this.array=e,this.elementType=null===t?xs(e[0]):t,this.paddedType=this.getPaddedType(),this.updateType=Rs.RENDER,this.isArrayBufferNode=!0}getNodeType(){return this.paddedType}getElementType(){return this.elementType}getPaddedType(){const e=this.elementType;let t="vec4";return"mat2"===e?t="mat2":!0===/mat/.test(e)?t="mat4":"i"===e.charAt(0)?t="ivec4":"u"===e.charAt(0)&&(t="uvec4"),t}update(){const{array:e,value:t}=this,r=this.elementType;if("float"===r||"int"===r||"uint"===r)for(let r=0;rTi(new Ml(e,t));class Fl extends Is{static get type(){return"ReferenceElementNode"}constructor(e,t){super(e,t),this.referenceNode=e,this.isReferenceElementNode=!0}getNodeType(){return this.referenceNode.uniformType}generate(e){const t=super.generate(e),r=this.referenceNode.getNodeType(),s=this.getNodeType();return e.format(t,r,s)}}class Ul extends Ps{static get type(){return"ReferenceNode"}constructor(e,t,r=null,s=null){super(),this.property=e,this.uniformType=t,this.object=r,this.count=s,this.properties=e.split("."),this.reference=r,this.node=null,this.group=null,this.name=null,this.updateType=Rs.OBJECT}element(e){return Ti(new Fl(this,Ti(e)))}setGroup(e){return this.group=e,this}label(e){return this.name=e,this}setNodeType(e){let t=null;t=null!==this.count?El(null,e,this.count):Array.isArray(this.getValueFromReference())?Bl(null,e):"texture"===e?Ru(null):"cubeTexture"===e?Rl(null):on(null,e),null!==this.group&&t.setGroup(this.group),null!==this.name&&t.label(this.name),this.node=t.getSelf()}getNodeType(e){return null===this.node&&(this.updateReference(e),this.updateValue()),this.node.getNodeType(e)}getValueFromReference(e=this.reference){const{properties:t}=this;let r=e[t[0]];for(let e=1;eTi(new Ul(e,t,r)),Il=(e,t,r,s)=>Ti(new Ul(e,t,s,r));class Dl extends Ul{static get type(){return"MaterialReferenceNode"}constructor(e,t,r=null){super(e,t,r),this.material=r,this.isMaterialReferenceNode=!0}updateReference(e){return this.reference=null!==this.material?this.material:e.material,this.reference}}const Ll=(e,t,r=null)=>Ti(new Dl(e,t,r)),Vl=Ai((e=>(!1===e.geometry.hasAttribute("tangent")&&e.geometry.computeTangents(),xu("tangent","vec4"))))(),Ol=Vl.xyz.toVar("tangentLocal"),Gl=Yu.mul($i(Ol,0)).xyz.varying("v_tangentView").normalize().toVar("tangentView"),kl=Gl.transformDirection(Fu).varying("v_tangentWorld").normalize().toVar("tangentWorld"),zl=Gl.toVar("transformedTangentView"),$l=zl.transformDirection(Fu).normalize().toVar("transformedTangentWorld"),Hl=e=>e.mul(Vl.w).xyz,Wl=Ia(Hl(dl.cross(Vl)),"v_bitangentGeometry").normalize().toVar("bitangentGeometry"),jl=Ia(Hl(cl.cross(Ol)),"v_bitangentLocal").normalize().toVar("bitangentLocal"),ql=Ia(Hl(pl.cross(Gl)),"v_bitangentView").normalize().toVar("bitangentView"),Kl=Ia(Hl(gl.cross(kl)),"v_bitangentWorld").normalize().toVar("bitangentWorld"),Xl=Hl(ml.cross(zl)).normalize().toVar("transformedBitangentView"),Yl=Xl.transformDirection(Fu).normalize().toVar("transformedBitangentWorld"),Ql=Ki(Gl,ql,pl),Zl=ol.mul(Ql),Jl=(()=>{let e=Sn.cross(ol);return e=e.cross(Sn).normalize(),e=pa(e,ml,vn.mul(hn.oneMinus()).oneMinus().pow2().pow2()).normalize(),e})(),ed=Ai((e=>{const{eye_pos:t,surf_norm:r,mapN:s,uv:i}=e,n=t.dFdx(),o=t.dFdy(),a=i.dFdx(),u=i.dFdy(),l=r,d=o.cross(l),c=l.cross(n),h=d.mul(a.x).add(c.mul(u.x)),p=d.mul(a.y).add(c.mul(u.y)),g=h.dot(h).max(p.dot(p)),m=ll.mul(g.inverseSqrt());return $n(h.mul(s.x,m),p.mul(s.y,m),l.mul(s.z)).normalize()}));class td extends Ls{static get type(){return"NormalMapNode"}constructor(e,t=null){super("vec3"),this.node=e,this.scaleNode=t,this.normalMapType=N}setup(e){const{normalMapType:t,scaleNode:r}=this;let s=this.node.mul(2).sub(1);null!==r&&(s=Oi(s.xy.mul(r),s.z));let i=null;if(t===S)i=xl(s);else if(t===N){i=!0===e.hasGeometryAttribute("tangent")?Ql.mul(s).normalize():ed({eye_pos:nl,surf_norm:pl,mapN:s,uv:Tu()})}return i}}const rd=Ni(td),sd=Ai((({textureNode:e,bumpScale:t})=>{const r=t=>e.cache().context({getUV:e=>t(e.uvNode||Tu()),forceUVContext:!0}),s=Bi(r((e=>e)));return Ii(Bi(r((e=>e.add(e.dFdx())))).sub(s),Bi(r((e=>e.add(e.dFdy())))).sub(s)).mul(t)})),id=Ai((e=>{const{surf_pos:t,surf_norm:r,dHdxy:s}=e,i=t.dFdx().normalize(),n=r,o=t.dFdy().normalize().cross(n),a=n.cross(i),u=i.dot(o).mul(ll),l=u.sign().mul(s.x.mul(o).add(s.y.mul(a)));return u.abs().mul(r).sub(l).normalize()}));class nd extends Ls{static get type(){return"BumpMapNode"}constructor(e,t=null){super("vec3"),this.textureNode=e,this.scaleNode=t}setup(){const e=null!==this.scaleNode?this.scaleNode:1,t=sd({textureNode:this.textureNode,bumpScale:e});return id({surf_pos:nl,surf_norm:pl,dHdxy:t})}}const od=Ni(nd),ad=new Map;class ud extends Ps{static get type(){return"MaterialNode"}constructor(e){super(),this.scope=e}getCache(e,t){let r=ad.get(e);return void 0===r&&(r=Ll(e,t),ad.set(e,r)),r}getFloat(e){return this.getCache(e,"float")}getColor(e){return this.getCache(e,"color")}getTexture(e){return this.getCache("map"===e?"map":e+"Map","texture")}setup(e){const t=e.context.material,r=this.scope;let s=null;if(r===ud.COLOR){const e=void 0!==t.color?this.getColor(r):Oi();s=t.map&&!0===t.map.isTexture?e.mul(this.getTexture("map")):e}else if(r===ud.OPACITY){const e=this.getFloat(r);s=t.alphaMap&&!0===t.alphaMap.isTexture?e.mul(this.getTexture("alpha")):e}else if(r===ud.SPECULAR_STRENGTH)s=t.specularMap&&!0===t.specularMap.isTexture?this.getTexture("specular").r:Bi(1);else if(r===ud.SPECULAR_INTENSITY){const e=this.getFloat(r);s=t.specularIntensityMap&&!0===t.specularIntensityMap.isTexture?e.mul(this.getTexture(r).a):e}else if(r===ud.SPECULAR_COLOR){const e=this.getColor(r);s=t.specularColorMap&&!0===t.specularColorMap.isTexture?e.mul(this.getTexture(r).rgb):e}else if(r===ud.ROUGHNESS){const e=this.getFloat(r);s=t.roughnessMap&&!0===t.roughnessMap.isTexture?e.mul(this.getTexture(r).g):e}else if(r===ud.METALNESS){const e=this.getFloat(r);s=t.metalnessMap&&!0===t.metalnessMap.isTexture?e.mul(this.getTexture(r).b):e}else if(r===ud.EMISSIVE){const e=this.getFloat("emissiveIntensity"),i=this.getColor(r).mul(e);s=t.emissiveMap&&!0===t.emissiveMap.isTexture?i.mul(this.getTexture(r)):i}else if(r===ud.NORMAL)t.normalMap?(s=rd(this.getTexture("normal"),this.getCache("normalScale","vec2")),s.normalMapType=t.normalMapType):s=t.bumpMap?od(this.getTexture("bump").r,this.getFloat("bumpScale")):pl;else if(r===ud.CLEARCOAT){const e=this.getFloat(r);s=t.clearcoatMap&&!0===t.clearcoatMap.isTexture?e.mul(this.getTexture(r).r):e}else if(r===ud.CLEARCOAT_ROUGHNESS){const e=this.getFloat(r);s=t.clearcoatRoughnessMap&&!0===t.clearcoatRoughnessMap.isTexture?e.mul(this.getTexture(r).r):e}else if(r===ud.CLEARCOAT_NORMAL)s=t.clearcoatNormalMap?rd(this.getTexture(r),this.getCache(r+"Scale","vec2")):pl;else if(r===ud.SHEEN){const e=this.getColor("sheenColor").mul(this.getFloat("sheen"));s=t.sheenColorMap&&!0===t.sheenColorMap.isTexture?e.mul(this.getTexture("sheenColor").rgb):e}else if(r===ud.SHEEN_ROUGHNESS){const e=this.getFloat(r);s=t.sheenRoughnessMap&&!0===t.sheenRoughnessMap.isTexture?e.mul(this.getTexture(r).a):e,s=s.clamp(.07,1)}else if(r===ud.ANISOTROPY)if(t.anisotropyMap&&!0===t.anisotropyMap.isTexture){const e=this.getTexture(r);s=qi(jd.x,jd.y,jd.y.negate(),jd.x).mul(e.rg.mul(2).sub(Ii(1)).normalize().mul(e.b))}else s=jd;else if(r===ud.IRIDESCENCE_THICKNESS){const e=Pl("1","float",t.iridescenceThicknessRange);if(t.iridescenceThicknessMap){const i=Pl("0","float",t.iridescenceThicknessRange);s=e.sub(i).mul(this.getTexture(r).g).add(i)}else s=e}else if(r===ud.TRANSMISSION){const e=this.getFloat(r);s=t.transmissionMap?e.mul(this.getTexture(r).r):e}else if(r===ud.THICKNESS){const e=this.getFloat(r);s=t.thicknessMap?e.mul(this.getTexture(r).g):e}else if(r===ud.IOR)s=this.getFloat(r);else if(r===ud.LIGHT_MAP)s=this.getTexture(r).rgb.mul(this.getFloat("lightMapIntensity"));else if(r===ud.AO)s=this.getTexture(r).r.sub(1).mul(this.getFloat("aoMapIntensity")).add(1);else{const t=this.getNodeType(e);s=this.getCache(r,t)}return s}}ud.ALPHA_TEST="alphaTest",ud.COLOR="color",ud.OPACITY="opacity",ud.SHININESS="shininess",ud.SPECULAR="specular",ud.SPECULAR_STRENGTH="specularStrength",ud.SPECULAR_INTENSITY="specularIntensity",ud.SPECULAR_COLOR="specularColor",ud.REFLECTIVITY="reflectivity",ud.ROUGHNESS="roughness",ud.METALNESS="metalness",ud.NORMAL="normal",ud.CLEARCOAT="clearcoat",ud.CLEARCOAT_ROUGHNESS="clearcoatRoughness",ud.CLEARCOAT_NORMAL="clearcoatNormal",ud.EMISSIVE="emissive",ud.ROTATION="rotation",ud.SHEEN="sheen",ud.SHEEN_ROUGHNESS="sheenRoughness",ud.ANISOTROPY="anisotropy",ud.IRIDESCENCE="iridescence",ud.IRIDESCENCE_IOR="iridescenceIOR",ud.IRIDESCENCE_THICKNESS="iridescenceThickness",ud.IOR="ior",ud.TRANSMISSION="transmission",ud.THICKNESS="thickness",ud.ATTENUATION_DISTANCE="attenuationDistance",ud.ATTENUATION_COLOR="attenuationColor",ud.LINE_SCALE="scale",ud.LINE_DASH_SIZE="dashSize",ud.LINE_GAP_SIZE="gapSize",ud.LINE_WIDTH="linewidth",ud.LINE_DASH_OFFSET="dashOffset",ud.POINT_WIDTH="pointWidth",ud.DISPERSION="dispersion",ud.LIGHT_MAP="light",ud.AO="ao";const ld=Si(ud,ud.ALPHA_TEST),dd=Si(ud,ud.COLOR),cd=Si(ud,ud.SHININESS),hd=Si(ud,ud.EMISSIVE),pd=Si(ud,ud.OPACITY),gd=Si(ud,ud.SPECULAR),md=Si(ud,ud.SPECULAR_INTENSITY),fd=Si(ud,ud.SPECULAR_COLOR),yd=Si(ud,ud.SPECULAR_STRENGTH),bd=Si(ud,ud.REFLECTIVITY),xd=Si(ud,ud.ROUGHNESS),Td=Si(ud,ud.METALNESS),_d=Si(ud,ud.NORMAL),vd=Si(ud,ud.CLEARCOAT),Nd=Si(ud,ud.CLEARCOAT_ROUGHNESS),Sd=Si(ud,ud.CLEARCOAT_NORMAL),Ad=Si(ud,ud.ROTATION),Rd=Si(ud,ud.SHEEN),Cd=Si(ud,ud.SHEEN_ROUGHNESS),Ed=Si(ud,ud.ANISOTROPY),wd=Si(ud,ud.IRIDESCENCE),Md=Si(ud,ud.IRIDESCENCE_IOR),Bd=Si(ud,ud.IRIDESCENCE_THICKNESS),Fd=Si(ud,ud.TRANSMISSION),Ud=Si(ud,ud.THICKNESS),Pd=Si(ud,ud.IOR),Id=Si(ud,ud.ATTENUATION_DISTANCE),Dd=Si(ud,ud.ATTENUATION_COLOR),Ld=Si(ud,ud.LINE_SCALE),Vd=Si(ud,ud.LINE_DASH_SIZE),Od=Si(ud,ud.LINE_GAP_SIZE),Gd=Si(ud,ud.LINE_WIDTH),kd=Si(ud,ud.LINE_DASH_OFFSET),zd=Si(ud,ud.POINT_WIDTH),$d=Si(ud,ud.DISPERSION),Hd=Si(ud,ud.LIGHT_MAP),Wd=Si(ud,ud.AO),jd=on(new t).onReference((function(e){return e.material})).onRenderUpdate((function({material:e}){this.value.set(e.anisotropy*Math.cos(e.anisotropyRotation),e.anisotropy*Math.sin(e.anisotropyRotation))})),qd=Ai((e=>e.context.setupModelViewProjection()),"vec4").once()().varying("v_modelViewProjection");class Kd extends Ps{static get type(){return"IndexNode"}constructor(e){super("uint"),this.scope=e,this.isIndexNode=!0}generate(e){const t=this.getNodeType(e),r=this.scope;let s,i;if(r===Kd.VERTEX)s=e.getVertexIndex();else if(r===Kd.INSTANCE)s=e.getInstanceIndex();else if(r===Kd.DRAW)s=e.getDrawIndex();else if(r===Kd.INVOCATION_LOCAL)s=e.getInvocationLocalIndex();else if(r===Kd.INVOCATION_SUBGROUP)s=e.getInvocationSubgroupIndex();else{if(r!==Kd.SUBGROUP)throw new Error("THREE.IndexNode: Unknown scope: "+r);s=e.getSubgroupIndex()}if("vertex"===e.shaderStage||"compute"===e.shaderStage)i=s;else{i=Ia(this).build(e,t)}return i}}Kd.VERTEX="vertex",Kd.INSTANCE="instance",Kd.SUBGROUP="subgroup",Kd.INVOCATION_LOCAL="invocationLocal",Kd.INVOCATION_SUBGROUP="invocationSubgroup",Kd.DRAW="draw";const Xd=Si(Kd,Kd.VERTEX),Yd=Si(Kd,Kd.INSTANCE),Qd=Si(Kd,Kd.SUBGROUP),Zd=Si(Kd,Kd.INVOCATION_SUBGROUP),Jd=Si(Kd,Kd.INVOCATION_LOCAL),ec=Si(Kd,Kd.DRAW);class tc extends Ps{static get type(){return"InstanceNode"}constructor(e,t,r){super("void"),this.count=e,this.instanceMatrix=t,this.instanceColor=r,this.instanceMatrixNode=null,this.instanceColorNode=null,this.updateType=Rs.FRAME,this.buffer=null,this.bufferColor=null}setup(e){const{count:t,instanceMatrix:r,instanceColor:s}=this;let{instanceMatrixNode:i,instanceColorNode:n}=this;if(null===i){if(t<=1e3)i=El(r.array,"mat4",Math.max(t,1)).element(Yd);else{const e=new A(r.array,16,1);this.buffer=e;const t=r.usage===m?su:ru,s=[t(e,"vec4",16,0),t(e,"vec4",16,4),t(e,"vec4",16,8),t(e,"vec4",16,12)];i=Xi(...s)}this.instanceMatrixNode=i}if(s&&null===n){const e=new R(s.array,3),t=s.usage===m?su:ru;this.bufferColor=e,n=Oi(t(e,"vec3",3,0)),this.instanceColorNode=n}const o=i.mul(tl).xyz;if(tl.assign(o),e.hasGeometryAttribute("normal")){const e=bl(cl,i);cl.assign(e)}null!==this.instanceColorNode&&ln("vec3","vInstanceColor").assign(this.instanceColorNode)}update(){this.instanceMatrix.usage!==m&&null!==this.buffer&&this.instanceMatrix.version!==this.buffer.version&&(this.buffer.version=this.instanceMatrix.version),this.instanceColor&&this.instanceColor.usage!==m&&null!==this.bufferColor&&this.instanceColor.version!==this.bufferColor.version&&(this.bufferColor.version=this.instanceColor.version)}}const rc=Ni(tc);class sc extends tc{static get type(){return"InstancedMeshNode"}constructor(e){const{count:t,instanceMatrix:r,instanceColor:s}=e;super(t,r,s),this.instancedMesh=e}}const ic=Ni(sc);class nc extends Ps{static get type(){return"BatchNode"}constructor(e){super("void"),this.batchMesh=e,this.batchingIdNode=null}setup(e){null===this.batchingIdNode&&(null===e.getDrawIndex()?this.batchingIdNode=Yd:this.batchingIdNode=ec);const t=Ai((([e])=>{const t=vu(Cu(this.batchMesh._indirectTexture),0),r=Fi(e).modInt(Fi(t)),s=Fi(e).div(Fi(t));return Cu(this.batchMesh._indirectTexture,Di(r,s)).x})).setLayout({name:"getIndirectIndex",type:"uint",inputs:[{name:"id",type:"int"}]}),r=t(Fi(this.batchingIdNode)),s=this.batchMesh._matricesTexture,i=vu(Cu(s),0),n=Bi(r).mul(4).toInt().toVar(),o=n.modInt(i),a=n.div(Fi(i)),u=Xi(Cu(s,Di(o,a)),Cu(s,Di(o.add(1),a)),Cu(s,Di(o.add(2),a)),Cu(s,Di(o.add(3),a))),l=this.batchMesh._colorsTexture;if(null!==l){const e=Ai((([e])=>{const t=vu(Cu(l),0).x,r=e,s=r.modInt(t),i=r.div(t);return Cu(l,Di(s,i)).rgb})).setLayout({name:"getBatchingColor",type:"vec3",inputs:[{name:"id",type:"int"}]}),t=e(r);ln("vec3","vBatchColor").assign(t)}const d=Ki(u);tl.assign(u.mul(tl));const c=cl.div(Oi(d[0].dot(d[0]),d[1].dot(d[1]),d[2].dot(d[2]))),h=d.mul(c).xyz;cl.assign(h),e.hasGeometryAttribute("tangent")&&Ol.mulAssign(d)}}const oc=Ni(nc),ac=new WeakMap;class uc extends Ps{static get type(){return"SkinningNode"}constructor(e,t=!1){let r,s,i;super("void"),this.skinnedMesh=e,this.useReference=t,this.updateType=Rs.OBJECT,this.skinIndexNode=xu("skinIndex","uvec4"),this.skinWeightNode=xu("skinWeight","vec4"),t?(r=Pl("bindMatrix","mat4"),s=Pl("bindMatrixInverse","mat4"),i=Il("skeleton.boneMatrices","mat4",e.skeleton.bones.length)):(r=on(e.bindMatrix,"mat4"),s=on(e.bindMatrixInverse,"mat4"),i=El(e.skeleton.boneMatrices,"mat4",e.skeleton.bones.length)),this.bindMatrixNode=r,this.bindMatrixInverseNode=s,this.boneMatricesNode=i,this.previousBoneMatricesNode=null}getSkinnedPosition(e=this.boneMatricesNode,t=tl){const{skinIndexNode:r,skinWeightNode:s,bindMatrixNode:i,bindMatrixInverseNode:n}=this,o=e.element(r.x),a=e.element(r.y),u=e.element(r.z),l=e.element(r.w),d=i.mul(t),c=$n(o.mul(s.x).mul(d),a.mul(s.y).mul(d),u.mul(s.z).mul(d),l.mul(s.w).mul(d));return n.mul(c).xyz}getSkinnedNormal(e=this.boneMatricesNode,t=cl){const{skinIndexNode:r,skinWeightNode:s,bindMatrixNode:i,bindMatrixInverseNode:n}=this,o=e.element(r.x),a=e.element(r.y),u=e.element(r.z),l=e.element(r.w);let d=$n(s.x.mul(o),s.y.mul(a),s.z.mul(u),s.w.mul(l));return d=n.mul(d).mul(i),d.transformDirection(t).xyz}getPreviousSkinnedPosition(e){const t=e.object;return null===this.previousBoneMatricesNode&&(t.skeleton.previousBoneMatrices=new Float32Array(t.skeleton.boneMatrices),this.previousBoneMatricesNode=Il("skeleton.previousBoneMatrices","mat4",t.skeleton.bones.length)),this.getSkinnedPosition(this.previousBoneMatricesNode,rl)}needsPreviousBoneMatrices(e){const t=e.renderer.getMRT();return t&&t.has("velocity")||!0===_s(e.object).useVelocity}setup(e){this.needsPreviousBoneMatrices(e)&&rl.assign(this.getPreviousSkinnedPosition(e));const t=this.getSkinnedPosition();if(tl.assign(t),e.hasGeometryAttribute("normal")){const t=this.getSkinnedNormal();cl.assign(t),e.hasGeometryAttribute("tangent")&&Ol.assign(t)}}generate(e,t){if("void"!==t)return tl.build(e,t)}update(e){const t=(this.useReference?e.object:this.skinnedMesh).skeleton;ac.get(t)!==e.frameId&&(ac.set(t,e.frameId),null!==this.previousBoneMatricesNode&&t.previousBoneMatrices.set(t.boneMatrices),t.update())}}const lc=e=>Ti(new uc(e,!0));class dc extends Ps{static get type(){return"LoopNode"}constructor(e=[]){super(),this.params=e}getVarName(e){return String.fromCharCode("i".charCodeAt(0)+e)}getProperties(e){const t=e.getNodeProperties(this);if(void 0!==t.stackNode)return t;const r={};for(let e=0,t=this.params.length-1;eNumber(n)?">=":"<"));const d={start:i,end:n,condition:u},c=d.start,h=d.end;let p="",g="",m="";l||(l="int"===a||"uint"===a?u.includes("<")?"++":"--":u.includes("<")?"+= 1.":"-= 1."),p+=e.getVar(a,o)+" = "+c,g+=o+" "+u+" "+h,m+=o+" "+l;const f=`for ( ${p}; ${g}; ${m} )`;e.addFlowCode((0===t?"\n":"")+e.tab+f+" {\n\n").addFlowTab()}const i=s.build(e,"void"),n=t.returnsNode?t.returnsNode.build(e):"";e.removeFlowTab().addFlowCode("\n"+e.tab+i);for(let t=0,r=this.params.length-1;tTi(new dc(vi(e,"int"))).append(),hc=()=>gu("break").append(),pc=new WeakMap,gc=new s,mc=Ai((({bufferMap:e,influence:t,stride:r,width:s,depth:i,offset:n})=>{const o=Fi(Xd).mul(r).add(n),a=o.div(s),u=o.sub(a.mul(s));return Cu(e,Di(u,a)).depth(i).mul(t)}));class fc extends Ps{static get type(){return"MorphNode"}constructor(e){super("void"),this.mesh=e,this.morphBaseInfluence=on(1),this.updateType=Rs.OBJECT}setup(e){const{geometry:r}=e,s=void 0!==r.morphAttributes.position,i=r.hasAttribute("normal")&&void 0!==r.morphAttributes.normal,n=r.morphAttributes.position||r.morphAttributes.normal||r.morphAttributes.color,o=void 0!==n?n.length:0,{texture:a,stride:u,size:l}=function(e){const r=void 0!==e.morphAttributes.position,s=void 0!==e.morphAttributes.normal,i=void 0!==e.morphAttributes.color,n=e.morphAttributes.position||e.morphAttributes.normal||e.morphAttributes.color,o=void 0!==n?n.length:0;let a=pc.get(e);if(void 0===a||a.count!==o){void 0!==a&&a.texture.dispose();const u=e.morphAttributes.position||[],l=e.morphAttributes.normal||[],d=e.morphAttributes.color||[];let c=0;!0===r&&(c=1),!0===s&&(c=2),!0===i&&(c=3);let h=e.attributes.position.count*c,p=1;const g=4096;h>g&&(p=Math.ceil(h/g),h=g);const m=new Float32Array(h*p*4*o),f=new C(m,h,p,o);f.type=E,f.needsUpdate=!0;const y=4*c;for(let x=0;x{const t=Bi(0).toVar();this.mesh.count>1&&null!==this.mesh.morphTexture&&void 0!==this.mesh.morphTexture?t.assign(Cu(this.mesh.morphTexture,Di(Fi(e).add(1),Fi(Yd))).r):t.assign(Pl("morphTargetInfluences","float").element(e).toVar()),!0===s&&tl.addAssign(mc({bufferMap:a,influence:t,stride:u,width:d,depth:e,offset:Fi(0)})),!0===i&&cl.addAssign(mc({bufferMap:a,influence:t,stride:u,width:d,depth:e,offset:Fi(1)}))}))}update(){const e=this.morphBaseInfluence;this.mesh.geometry.morphTargetsRelative?e.value=1:e.value=1-this.mesh.morphTargetInfluences.reduce(((e,t)=>e+t),0)}}const yc=Ni(fc);class bc extends Ps{static get type(){return"LightingNode"}constructor(){super("vec3"),this.isLightingNode=!0}}class xc extends bc{static get type(){return"AONode"}constructor(e=null){super(),this.aoNode=e}setup(e){e.context.ambientOcclusion.mulAssign(this.aoNode)}}class Tc extends Ea{static get type(){return"LightingContextNode"}constructor(e,t=null,r=null,s=null){super(e),this.lightingModel=t,this.backdropNode=r,this.backdropAlphaNode=s,this._value=null}getContext(){const{backdropNode:e,backdropAlphaNode:t}=this,r={directDiffuse:Oi().toVar("directDiffuse"),directSpecular:Oi().toVar("directSpecular"),indirectDiffuse:Oi().toVar("indirectDiffuse"),indirectSpecular:Oi().toVar("indirectSpecular")};return{radiance:Oi().toVar("radiance"),irradiance:Oi().toVar("irradiance"),iblIrradiance:Oi().toVar("iblIrradiance"),ambientOcclusion:Bi(1).toVar("ambientOcclusion"),reflectedLight:r,backdrop:e,backdropAlpha:t}}setup(e){return this.value=this._value||(this._value=this.getContext()),this.value.lightingModel=this.lightingModel||e.context.lightingModel,super.setup(e)}}const _c=Ni(Tc);class vc extends bc{static get type(){return"IrradianceNode"}constructor(e){super(),this.node=e}setup(e){e.context.irradiance.addAssign(this.node)}}let Nc,Sc;class Ac extends Ps{static get type(){return"ScreenNode"}constructor(e){super(),this.scope=e,this.isViewportNode=!0}getNodeType(){return this.scope===Ac.VIEWPORT?"vec4":"vec2"}getUpdateType(){let e=Rs.NONE;return this.scope!==Ac.SIZE&&this.scope!==Ac.VIEWPORT||(e=Rs.RENDER),this.updateType=e,e}update({renderer:e}){const t=e.getRenderTarget();this.scope===Ac.VIEWPORT?null!==t?Sc.copy(t.viewport):(e.getViewport(Sc),Sc.multiplyScalar(e.getPixelRatio())):null!==t?(Nc.width=t.width,Nc.height=t.height):e.getDrawingBufferSize(Nc)}setup(){const e=this.scope;let r=null;return r=e===Ac.SIZE?on(Nc||(Nc=new t)):e===Ac.VIEWPORT?on(Sc||(Sc=new s)):Ii(Ec.div(Cc)),r}generate(e){if(this.scope===Ac.COORDINATE){let t=e.getFragCoord();if(e.isFlipY()){const r=e.getNodeProperties(Cc).outputNode.build(e);t=`${e.getType("vec2")}( ${t}.x, ${r}.y - ${t}.y )`}return t}return super.generate(e)}}Ac.COORDINATE="coordinate",Ac.VIEWPORT="viewport",Ac.SIZE="size",Ac.UV="uv";const Rc=Si(Ac,Ac.UV),Cc=Si(Ac,Ac.SIZE),Ec=Si(Ac,Ac.COORDINATE),wc=Si(Ac,Ac.VIEWPORT),Mc=wc.zw,Bc=Ec.sub(wc.xy),Fc=Bc.div(Mc),Uc=Ai((()=>(console.warn('TSL.ViewportNode: "viewportResolution" is deprecated. Use "screenSize" instead.'),Cc)),"vec2").once()(),Pc=Ai((()=>(console.warn('TSL.ViewportNode: "viewportTopLeft" is deprecated. Use "screenUV" instead.'),Rc)),"vec2").once()(),Ic=Ai((()=>(console.warn('TSL.ViewportNode: "viewportBottomLeft" is deprecated. Use "screenUV.flipY()" instead.'),Rc.flipY())),"vec2").once()(),Dc=new t;class Lc extends Au{static get type(){return"ViewportTextureNode"}constructor(e=Rc,t=null,r=null){null===r&&((r=new w).minFilter=M),super(r,e,t),this.generateMipmaps=!1,this.isOutputTextureNode=!0,this.updateBeforeType=Rs.FRAME}updateBefore(e){const t=e.renderer;t.getDrawingBufferSize(Dc);const r=this.value;r.image.width===Dc.width&&r.image.height===Dc.height||(r.image.width=Dc.width,r.image.height=Dc.height,r.needsUpdate=!0);const s=r.generateMipmaps;r.generateMipmaps=this.generateMipmaps,t.copyFramebufferToTexture(r),r.generateMipmaps=s}clone(){const e=new this.constructor(this.uvNode,this.levelNode,this.value);return e.generateMipmaps=this.generateMipmaps,e}}const Vc=Ni(Lc),Oc=Ni(Lc,null,null,{generateMipmaps:!0});let Gc=null;class kc extends Lc{static get type(){return"ViewportDepthTextureNode"}constructor(e=Rc,t=null){null===Gc&&(Gc=new B),super(e,t,Gc)}}const zc=Ni(kc);class $c extends Ps{static get type(){return"ViewportDepthNode"}constructor(e,t=null){super("float"),this.scope=e,this.valueNode=t,this.isViewportDepthNode=!0}generate(e){const{scope:t}=this;return t===$c.DEPTH_BASE?e.getFragDepth():super.generate(e)}setup({camera:e}){const{scope:t}=this,r=this.valueNode;let s=null;if(t===$c.DEPTH_BASE)null!==r&&(s=Kc().assign(r));else if(t===$c.DEPTH)s=e.isPerspectiveCamera?Wc(nl.z,Eu,wu):Hc(nl.z,Eu,wu);else if(t===$c.LINEAR_DEPTH)if(null!==r)if(e.isPerspectiveCamera){const e=jc(r,Eu,wu);s=Hc(e,Eu,wu)}else s=r;else s=Hc(nl.z,Eu,wu);return s}}$c.DEPTH_BASE="depthBase",$c.DEPTH="depth",$c.LINEAR_DEPTH="linearDepth";const Hc=(e,t,r)=>e.add(t).div(t.sub(r)),Wc=(e,t,r)=>t.add(e).mul(r).div(r.sub(t).mul(e)),jc=(e,t,r)=>t.mul(r).div(r.sub(t).mul(e).sub(r)),qc=(e,t,r)=>{t=t.max(1e-6).toVar();const s=So(e.negate().div(t)),i=So(r.div(t));return s.div(i)},Kc=Ni($c,$c.DEPTH_BASE),Xc=Si($c,$c.DEPTH),Yc=Ni($c,$c.LINEAR_DEPTH),Qc=Yc(zc());Xc.assign=e=>Kc(e);const Zc=Ni(class extends Ps{constructor(e){super("float"),this.name=e,this.isBuiltinNode=!0}generate(){return this.name}});class Jc extends Ps{static get type(){return"ClippingNode"}constructor(e=Jc.DEFAULT){super(),this.scope=e}setup(e){super.setup(e);const t=e.clippingContext,{intersectionPlanes:r,unionPlanes:s}=t;return this.hardwareClipping=e.material.hardwareClipping,this.scope===Jc.ALPHA_TO_COVERAGE?this.setupAlphaToCoverage(r,s):this.scope===Jc.HARDWARE?this.setupHardwareClipping(s,e):this.setupDefault(r,s)}setupAlphaToCoverage(e,t){return Ai((()=>{const r=Bi().toVar("distanceToPlane"),s=Bi().toVar("distanceToGradient"),i=Bi(1).toVar("clipOpacity"),n=t.length;if(!1===this.hardwareClipping&&n>0){const e=Bl(t);cc(n,(({i:t})=>{const n=e.element(t);r.assign(nl.dot(n.xyz).negate().add(n.w)),s.assign(r.fwidth().div(2)),i.mulAssign(ya(s.negate(),s,r))}))}const o=e.length;if(o>0){const t=Bl(e),n=Bi(1).toVar("intersectionClipOpacity");cc(o,(({i:e})=>{const i=t.element(e);r.assign(nl.dot(i.xyz).negate().add(i.w)),s.assign(r.fwidth().div(2)),n.mulAssign(ya(s.negate(),s,r).oneMinus())})),i.mulAssign(n.oneMinus())}dn.a.mulAssign(i),dn.a.equal(0).discard()}))()}setupDefault(e,t){return Ai((()=>{const r=t.length;if(!1===this.hardwareClipping&&r>0){const e=Bl(t);cc(r,(({i:t})=>{const r=e.element(t);nl.dot(r.xyz).greaterThan(r.w).discard()}))}const s=e.length;if(s>0){const t=Bl(e),r=Pi(!0).toVar("clipped");cc(s,(({i:e})=>{const s=t.element(e);r.assign(nl.dot(s.xyz).greaterThan(s.w).and(r))})),r.discard()}}))()}setupHardwareClipping(e,t){const r=e.length;return t.enableHardwareClipping(r),Ai((()=>{const s=Bl(e),i=Zc(t.getClipDistance());cc(r,(({i:e})=>{const t=s.element(e),r=nl.dot(t.xyz).sub(t.w).negate();i.element(e).assign(r)}))}))()}}Jc.ALPHA_TO_COVERAGE="alphaToCoverage",Jc.DEFAULT="default",Jc.HARDWARE="hardware";const eh=Ai((([e])=>Mo(Wn(1e4,Bo(Wn(17,e.x).add(Wn(.1,e.y)))).mul($n(.1,Lo(Bo(Wn(13,e.y).add(e.x)))))))),th=Ai((([e])=>eh(Ii(eh(e.xy),e.z)))),rh=Ai((([e])=>{const t=Zo(Oo(zo(e.xyz)),Oo($o(e.xyz))),r=Bi(1).div(Bi(.05).mul(t)).toVar("pixScale"),s=Ii(vo(Co(So(r))),vo(Eo(So(r)))),i=Ii(th(Co(s.x.mul(e.xyz))),th(Co(s.y.mul(e.xyz)))),n=Mo(So(r)),o=$n(Wn(n.oneMinus(),i.x),Wn(n,i.y)),a=Qo(n,n.oneMinus()),u=Oi(o.mul(o).div(Wn(2,a).mul(Hn(1,a))),o.sub(Wn(.5,a)).div(Hn(1,a)),Hn(1,Hn(1,o).mul(Hn(1,o)).div(Wn(2,a).mul(Hn(1,a))))),l=o.lessThan(a.oneMinus()).select(o.lessThan(a).select(u.x,u.y),u.z);return ga(l,1e-6,1)})).setLayout({name:"getAlphaHashThreshold",type:"float",inputs:[{name:"position",type:"vec3"}]});class sh extends F{static get type(){return"NodeMaterial"}get type(){return this.constructor.type}set type(e){}constructor(){super(),this.isNodeMaterial=!0,this.fog=!0,this.lights=!1,this.hardwareClipping=!1,this.lightsNode=null,this.envNode=null,this.aoNode=null,this.colorNode=null,this.normalNode=null,this.opacityNode=null,this.backdropNode=null,this.backdropAlphaNode=null,this.alphaTestNode=null,this.positionNode=null,this.geometryNode=null,this.depthNode=null,this.shadowPositionNode=null,this.receivedShadowNode=null,this.castShadowNode=null,this.outputNode=null,this.mrtNode=null,this.fragmentNode=null,this.vertexNode=null}customProgramCacheKey(){return this.type+hs(this)}build(e){this.setup(e)}setupObserver(e){return new as(e)}setup(e){e.context.setupNormal=()=>this.setupNormal(e),e.context.setupPositionView=()=>this.setupPositionView(e),e.context.setupModelViewProjection=()=>this.setupModelViewProjection(e);const t=e.renderer,r=t.getRenderTarget();e.addStack();const s=this.vertexNode||this.setupVertex(e);let i;e.stack.outputNode=s,this.setupHardwareClipping(e),null!==this.geometryNode&&(e.stack.outputNode=e.stack.outputNode.bypass(this.geometryNode)),e.addFlow("vertex",e.removeStack()),e.addStack();const n=this.setupClipping(e);if(!0!==this.depthWrite&&!0!==this.depthTest||(null!==r?!0===r.depthBuffer&&this.setupDepth(e):!0===t.depth&&this.setupDepth(e)),null===this.fragmentNode){this.setupDiffuseColor(e),this.setupVariants(e);const s=this.setupLighting(e);null!==n&&e.stack.add(n);const o=$i(s,dn.a).max(0);if(i=this.setupOutput(e,o),En.assign(i),null!==this.outputNode&&(i=this.outputNode),null!==r){const e=t.getMRT(),r=this.mrtNode;null!==e?(i=e,null!==r&&(i=e.merge(r))):null!==r&&(i=r)}}else{let t=this.fragmentNode;!0!==t.isOutputStructNode&&(t=$i(t)),i=this.setupOutput(e,t)}e.stack.outputNode=i,e.addFlow("fragment",e.removeStack()),e.monitor=this.setupObserver(e)}setupClipping(e){if(null===e.clippingContext)return null;const{unionPlanes:t,intersectionPlanes:r}=e.clippingContext;let s=null;if(t.length>0||r.length>0){const t=e.renderer.samples;this.alphaToCoverage&&t>1?s=Ti(new Jc(Jc.ALPHA_TO_COVERAGE)):e.stack.add(Ti(new Jc))}return s}setupHardwareClipping(e){if(this.hardwareClipping=!1,null===e.clippingContext)return;const t=e.clippingContext.unionPlanes.length;t>0&&t<=8&&e.isAvailable("clipDistance")&&(e.stack.add(Ti(new Jc(Jc.HARDWARE))),this.hardwareClipping=!0)}setupDepth(e){const{renderer:t,camera:r}=e;let s=this.depthNode;if(null===s){const e=t.getMRT();e&&e.has("depth")?s=e.get("depth"):!0===t.logarithmicDepthBuffer&&(s=r.isPerspectiveCamera?qc(nl.z,Eu,wu):Hc(nl.z,Eu,wu))}null!==s&&Xc.assign(s).append()}setupPositionView(){return Yu.mul(tl).xyz}setupModelViewProjection(){return Mu.mul(nl)}setupVertex(e){return e.addStack(),this.setupPosition(e),e.context.vertex=e.removeStack(),qd}setupPosition(e){const{object:t,geometry:r}=e;if((r.morphAttributes.position||r.morphAttributes.normal||r.morphAttributes.color)&&yc(t).append(),!0===t.isSkinnedMesh&&lc(t).append(),this.displacementMap){const e=Ll("displacementMap","texture"),t=Ll("displacementScale","float"),r=Ll("displacementBias","float");tl.addAssign(cl.normalize().mul(e.x.mul(t).add(r)))}return t.isBatchedMesh&&oc(t).append(),t.isInstancedMesh&&t.instanceMatrix&&!0===t.instanceMatrix.isInstancedBufferAttribute&&ic(t).append(),null!==this.positionNode&&tl.assign(this.positionNode.context({isPositionNodeInput:!0})),tl}setupDiffuseColor({object:e,geometry:t}){let r=this.colorNode?$i(this.colorNode):dd;if(!0===this.vertexColors&&t.hasAttribute("color")&&(r=$i(r.xyz.mul(xu("color","vec3")),r.a)),e.instanceColor){r=ln("vec3","vInstanceColor").mul(r)}if(e.isBatchedMesh&&e._colorsTexture){r=ln("vec3","vBatchColor").mul(r)}dn.assign(r);const s=this.opacityNode?Bi(this.opacityNode):pd;if(dn.a.assign(dn.a.mul(s)),null!==this.alphaTestNode||this.alphaTest>0){const e=null!==this.alphaTestNode?Bi(this.alphaTestNode):ld;dn.a.lessThanEqual(e).discard()}!0===this.alphaHash&&dn.a.lessThan(rh(tl)).discard(),!1===this.transparent&&this.blending===U&&!1===this.alphaToCoverage&&dn.a.assign(1)}setupVariants(){}setupOutgoingLight(){return!0===this.lights?Oi(0):dn.rgb}setupNormal(){return this.normalNode?Oi(this.normalNode):_d}setupEnvironment(){let e=null;return this.envNode?e=this.envNode:this.envMap&&(e=this.envMap.isCubeTexture?Ll("envMap","cubeTexture"):Ll("envMap","texture")),e}setupLightMap(e){let t=null;return e.material.lightMap&&(t=new vc(Hd)),t}setupLights(e){const t=[],r=this.setupEnvironment(e);r&&r.isLightingNode&&t.push(r);const s=this.setupLightMap(e);if(s&&s.isLightingNode&&t.push(s),null!==this.aoNode||e.material.aoMap){const e=null!==this.aoNode?this.aoNode:Wd;t.push(new xc(e))}let i=this.lightsNode||e.lightsNode;return t.length>0&&(i=e.renderer.lighting.createNode([...i.getLights(),...t])),i}setupLightingModel(){}setupLighting(e){const{material:t}=e,{backdropNode:r,backdropAlphaNode:s,emissiveNode:i}=this,n=!0===this.lights||null!==this.lightsNode?this.setupLights(e):null;let o=this.setupOutgoingLight(e);if(n&&n.getScope().hasLights){const t=this.setupLightingModel(e);o=_c(n,t,r,s)}else null!==r&&(o=Oi(null!==s?pa(o,r,s):r));return(i&&!0===i.isNode||t.emissive&&!0===t.emissive.isColor)&&(cn.assign(Oi(i||hd)),o=o.add(cn)),o}setupOutput(e,t){if(!0===this.fog){const r=e.fogNode;r&&(En.assign(t),t=$i(r))}return t}setDefaultValues(e){for(const t in e){const r=e[t];void 0===this[t]&&(this[t]=r,r&&r.clone&&(this[t]=r.clone()))}const t=Object.getOwnPropertyDescriptors(e.constructor.prototype);for(const e in t)void 0===Object.getOwnPropertyDescriptor(this.constructor.prototype,e)&&void 0!==t[e].get&&Object.defineProperty(this.constructor.prototype,e,t[e])}toJSON(e){const t=void 0===e||"string"==typeof e;t&&(e={textures:{},images:{},nodes:{}});const r=F.prototype.toJSON.call(this,e),s=ps(this);r.inputNodes={};for(const{property:t,childNode:i}of s)r.inputNodes[t]=i.toJSON(e).uuid;function i(e){const t=[];for(const r in e){const s=e[r];delete s.metadata,t.push(s)}return t}if(t){const t=i(e.textures),s=i(e.images),n=i(e.nodes);t.length>0&&(r.textures=t),s.length>0&&(r.images=s),n.length>0&&(r.nodes=n)}return r}copy(e){return this.lightsNode=e.lightsNode,this.envNode=e.envNode,this.colorNode=e.colorNode,this.normalNode=e.normalNode,this.opacityNode=e.opacityNode,this.backdropNode=e.backdropNode,this.backdropAlphaNode=e.backdropAlphaNode,this.alphaTestNode=e.alphaTestNode,this.positionNode=e.positionNode,this.geometryNode=e.geometryNode,this.depthNode=e.depthNode,this.shadowPositionNode=e.shadowPositionNode,this.receivedShadowNode=e.receivedShadowNode,this.castShadowNode=e.castShadowNode,this.outputNode=e.outputNode,this.mrtNode=e.mrtNode,this.fragmentNode=e.fragmentNode,this.vertexNode=e.vertexNode,super.copy(e)}}const ih=new P;class nh extends sh{static get type(){return"InstancedPointsNodeMaterial"}constructor(e={}){super(),this.isInstancedPointsNodeMaterial=!0,this.useColor=e.vertexColors,this.pointWidth=1,this.pointColorNode=null,this.pointWidthNode=null,this._useAlphaToCoverage=!0,this.setDefaultValues(ih),this.setValues(e)}setup(e){const{renderer:t}=e,r=this._useAlphaToCoverage,s=this.useColor;this.vertexNode=Ai((()=>{const e=xu("instancePosition").xyz,t=$i(Yu.mul($i(e,1))),r=wc.z.div(wc.w),s=Mu.mul(t),i=el.xy.toVar();return i.mulAssign(this.pointWidthNode?this.pointWidthNode:zd),i.assign(i.div(wc.z)),i.y.assign(i.y.mul(r)),i.assign(i.mul(s.w)),s.addAssign($i(i,0,0)),s}))(),this.fragmentNode=Ai((()=>{const e=Bi(1).toVar(),i=ha(Tu().mul(2).sub(1));if(r&&t.samples>1){const t=Bi(i.fwidth()).toVar();e.assign(ya(t.oneMinus(),t.add(1),i).oneMinus())}else i.greaterThan(1).discard();let n;if(this.pointColorNode)n=this.pointColorNode;else if(s){n=xu("instanceColor").mul(dd)}else n=dd;return e.mulAssign(pd),$i(n,e)}))(),super.setup(e)}get alphaToCoverage(){return this._useAlphaToCoverage}set alphaToCoverage(e){this._useAlphaToCoverage!==e&&(this._useAlphaToCoverage=e,this.needsUpdate=!0)}}const oh=new I;class ah extends sh{static get type(){return"LineBasicNodeMaterial"}constructor(e){super(),this.isLineBasicNodeMaterial=!0,this.setDefaultValues(oh),this.setValues(e)}}const uh=new D;class lh extends sh{static get type(){return"LineDashedNodeMaterial"}constructor(e){super(),this.isLineDashedNodeMaterial=!0,this.setDefaultValues(uh),this.dashOffset=0,this.offsetNode=null,this.dashScaleNode=null,this.dashSizeNode=null,this.gapSizeNode=null,this.setValues(e)}setupVariants(){const e=this.offsetNode?Bi(this.offsetNode):kd,t=this.dashScaleNode?Bi(this.dashScaleNode):Ld,r=this.dashSizeNode?Bi(this.dashSizeNode):Vd,s=this.gapSizeNode?Bi(this.gapSizeNode):Od;wn.assign(r),Mn.assign(s);const i=Ia(xu("lineDistance").mul(t));(e?i.add(e):i).mod(wn.add(Mn)).greaterThan(wn).discard()}}let dh=null;class ch extends Lc{static get type(){return"ViewportSharedTextureNode"}constructor(e=Rc,t=null){null===dh&&(dh=new w),super(e,t,dh)}updateReference(){return this}}const hh=Ni(ch),ph=new D;class gh extends sh{static get type(){return"Line2NodeMaterial"}constructor(e={}){super(),this.isLine2NodeMaterial=!0,this.setDefaultValues(ph),this.useColor=e.vertexColors,this.dashOffset=0,this.lineWidth=1,this.lineColorNode=null,this.offsetNode=null,this.dashScaleNode=null,this.dashSizeNode=null,this.gapSizeNode=null,this.blending=L,this._useDash=e.dashed,this._useAlphaToCoverage=!0,this._useWorldUnits=!1,this.setValues(e)}setup(e){const{renderer:t}=e,r=this._useAlphaToCoverage,s=this.useColor,i=this._useDash,n=this._useWorldUnits,o=Ai((({start:e,end:t})=>{const r=Mu.element(2).element(2),s=Mu.element(3).element(2).mul(-.5).div(r).sub(e.z).div(t.z.sub(e.z));return $i(pa(e.xyz,t.xyz,s),t.w)})).setLayout({name:"trimSegment",type:"vec4",inputs:[{name:"start",type:"vec4"},{name:"end",type:"vec4"}]});this.vertexNode=Ai((()=>{const e=xu("instanceStart"),t=xu("instanceEnd"),r=$i(Yu.mul($i(e,1))).toVar("start"),s=$i(Yu.mul($i(t,1))).toVar("end");if(i){const e=this.dashScaleNode?Bi(this.dashScaleNode):Ld,t=this.offsetNode?Bi(this.offsetNode):kd,r=xu("instanceDistanceStart"),s=xu("instanceDistanceEnd");let i=el.y.lessThan(.5).select(e.mul(r),e.mul(s));i=i.add(t),ln("float","lineDistance").assign(i)}n&&(ln("vec3","worldStart").assign(r.xyz),ln("vec3","worldEnd").assign(s.xyz));const a=wc.z.div(wc.w),u=Mu.element(2).element(3).equal(-1);Ei(u,(()=>{Ei(r.z.lessThan(0).and(s.z.greaterThan(0)),(()=>{s.assign(o({start:r,end:s}))})).ElseIf(s.z.lessThan(0).and(r.z.greaterThanEqual(0)),(()=>{r.assign(o({start:s,end:r}))}))}));const l=Mu.mul(r),d=Mu.mul(s),c=l.xyz.div(l.w),h=d.xyz.div(d.w),p=h.xy.sub(c.xy).toVar();p.x.assign(p.x.mul(a)),p.assign(p.normalize());const g=$i().toVar();if(n){const e=s.xyz.sub(r.xyz).normalize(),t=pa(r.xyz,s.xyz,.5).normalize(),n=e.cross(t).normalize(),o=e.cross(n),a=ln("vec4","worldPos");a.assign(el.y.lessThan(.5).select(r,s));const u=Gd.mul(.5);a.addAssign($i(el.x.lessThan(0).select(n.mul(u),n.mul(u).negate()),0)),i||(a.addAssign($i(el.y.lessThan(.5).select(e.mul(u).negate(),e.mul(u)),0)),a.addAssign($i(o.mul(u),0)),Ei(el.y.greaterThan(1).or(el.y.lessThan(0)),(()=>{a.subAssign($i(o.mul(2).mul(u),0))}))),g.assign(Mu.mul(a));const l=Oi().toVar();l.assign(el.y.lessThan(.5).select(c,h)),g.z.assign(l.z.mul(g.w))}else{const e=Ii(p.y,p.x.negate()).toVar("offset");p.x.assign(p.x.div(a)),e.x.assign(e.x.div(a)),e.assign(el.x.lessThan(0).select(e.negate(),e)),Ei(el.y.lessThan(0),(()=>{e.assign(e.sub(p))})).ElseIf(el.y.greaterThan(1),(()=>{e.assign(e.add(p))})),e.assign(e.mul(Gd)),e.assign(e.div(wc.w)),g.assign(el.y.lessThan(.5).select(l,d)),e.assign(e.mul(g.w)),g.assign(g.add($i(e,0,0)))}return g}))();const a=Ai((({p1:e,p2:t,p3:r,p4:s})=>{const i=e.sub(r),n=s.sub(r),o=t.sub(e),a=i.dot(n),u=n.dot(o),l=i.dot(o),d=n.dot(n),c=o.dot(o).mul(d).sub(u.mul(u)),h=a.mul(u).sub(l.mul(d)).div(c).clamp(),p=a.add(u.mul(h)).div(d).clamp();return Ii(h,p)}));if(this.colorNode=Ai((()=>{const e=Tu();if(i){const t=this.dashSizeNode?Bi(this.dashSizeNode):Vd,r=this.gapSizeNode?Bi(this.gapSizeNode):Od;wn.assign(t),Mn.assign(r);const s=ln("float","lineDistance");e.y.lessThan(-1).or(e.y.greaterThan(1)).discard(),s.mod(wn.add(Mn)).greaterThan(wn).discard()}const o=Bi(1).toVar("alpha");if(n){const e=ln("vec3","worldStart"),s=ln("vec3","worldEnd"),n=ln("vec4","worldPos").xyz.normalize().mul(1e5),u=s.sub(e),l=a({p1:e,p2:s,p3:Oi(0,0,0),p4:n}),d=e.add(u.mul(l.x)),c=n.mul(l.y),h=d.sub(c).length().div(Gd);if(!i)if(r&&t.samples>1){const e=h.fwidth();o.assign(ya(e.negate().add(.5),e.add(.5),h).oneMinus())}else h.greaterThan(.5).discard()}else if(r&&t.samples>1){const t=e.x,r=e.y.greaterThan(0).select(e.y.sub(1),e.y.add(1)),s=t.mul(t).add(r.mul(r)),i=Bi(s.fwidth()).toVar("dlen");Ei(e.y.abs().greaterThan(1),(()=>{o.assign(ya(i.oneMinus(),i.add(1),s).oneMinus())}))}else Ei(e.y.abs().greaterThan(1),(()=>{const t=e.x,r=e.y.greaterThan(0).select(e.y.sub(1),e.y.add(1));t.mul(t).add(r.mul(r)).greaterThan(1).discard()}));let u;if(this.lineColorNode)u=this.lineColorNode;else if(s){const e=xu("instanceColorStart"),t=xu("instanceColorEnd");u=el.y.lessThan(.5).select(e,t).mul(dd)}else u=dd;return $i(u,o)}))(),this.transparent){const e=this.opacityNode?Bi(this.opacityNode):pd;this.outputNode=$i(this.colorNode.rgb.mul(e).add(hh().rgb.mul(e.oneMinus())),this.colorNode.a)}super.setup(e)}get worldUnits(){return this._useWorldUnits}set worldUnits(e){this._useWorldUnits!==e&&(this._useWorldUnits=e,this.needsUpdate=!0)}get dashed(){return this._useDash}set dashed(e){this._useDash!==e&&(this._useDash=e,this.needsUpdate=!0)}get alphaToCoverage(){return this._useAlphaToCoverage}set alphaToCoverage(e){this._useAlphaToCoverage!==e&&(this._useAlphaToCoverage=e,this.needsUpdate=!0)}}const mh=e=>Ti(e).mul(.5).add(.5),fh=new V;class yh extends sh{static get type(){return"MeshNormalNodeMaterial"}constructor(e){super(),this.isMeshNormalNodeMaterial=!0,this.setDefaultValues(fh),this.setValues(e)}setupDiffuseColor(){const e=this.opacityNode?Bi(this.opacityNode):pd;dn.assign($i(mh(ml),e))}}class bh extends Ls{static get type(){return"EquirectUVNode"}constructor(e=il){super("vec2"),this.dirNode=e}setup(){const e=this.dirNode,t=e.z.atan(e.x).mul(1/(2*Math.PI)).add(.5),r=e.y.clamp(-1,1).asin().mul(1/Math.PI).add(.5);return Ii(t,r)}}const xh=Ni(bh);class Th extends O{constructor(e=1,t={}){super(e,t),this.isCubeRenderTarget=!0}fromEquirectangularTexture(e,t){const r=t.minFilter,s=t.generateMipmaps;t.generateMipmaps=!0,this.texture.type=t.type,this.texture.colorSpace=t.colorSpace,this.texture.generateMipmaps=t.generateMipmaps,this.texture.minFilter=t.minFilter,this.texture.magFilter=t.magFilter;const i=new G(5,5,5),n=xh(il),o=new sh;o.colorNode=Ru(t,n,0),o.side=T,o.blending=L;const a=new k(i,o),u=new z;u.add(a),t.minFilter===M&&(t.minFilter=$);const l=new H(1,10,this),d=e.getMRT();return e.setMRT(null),l.update(e,u),e.setMRT(d),t.minFilter=r,t.currentGenerateMipmaps=s,a.geometry.dispose(),a.material.dispose(),this}}const _h=new WeakMap;class vh extends Ls{static get type(){return"CubeMapNode"}constructor(e){super("vec3"),this.envNode=e,this._cubeTexture=null,this._cubeTextureNode=Rl();const t=new W;t.isRenderTargetTexture=!0,this._defaultTexture=t,this.updateBeforeType=Rs.RENDER}updateBefore(e){const{renderer:t,material:r}=e,s=this.envNode;if(s.isTextureNode||s.isMaterialReferenceNode){const e=s.isTextureNode?s.value:r[s.property];if(e&&e.isTexture){const r=e.mapping;if(r===j||r===q){if(_h.has(e)){const t=_h.get(e);Sh(t,e.mapping),this._cubeTexture=t}else{const r=e.image;if(function(e){return null!=e&&e.height>0}(r)){const s=new Th(r.height);s.fromEquirectangularTexture(t,e),Sh(s.texture,e.mapping),this._cubeTexture=s.texture,_h.set(e,s.texture),e.addEventListener("dispose",Nh)}else this._cubeTexture=this._defaultTexture}this._cubeTextureNode.value=this._cubeTexture}else this._cubeTextureNode=this.envNode}}}setup(e){return this.updateBefore(e),this._cubeTextureNode}}function Nh(e){const t=e.target;t.removeEventListener("dispose",Nh);const r=_h.get(t);void 0!==r&&(_h.delete(t),r.dispose())}function Sh(e,t){t===j?e.mapping=_:t===q&&(e.mapping=v)}const Ah=Ni(vh);class Rh extends bc{static get type(){return"BasicEnvironmentNode"}constructor(e=null){super(),this.envNode=e}setup(e){e.context.environment=Ah(this.envNode)}}class Ch extends bc{static get type(){return"BasicLightMapNode"}constructor(e=null){super(),this.lightMapNode=e}setup(e){const t=Bi(1/Math.PI);e.context.irradianceLightMap=this.lightMapNode.mul(t)}}class Eh{start(){}finish(){}direct(){}directRectArea(){}indirect(){}ambientOcclusion(){}}class wh extends Eh{constructor(){super()}indirect(e,t,r){const s=e.ambientOcclusion,i=e.reflectedLight,n=r.context.irradianceLightMap;i.indirectDiffuse.assign($i(0)),n?i.indirectDiffuse.addAssign(n):i.indirectDiffuse.addAssign($i(1,1,1,0)),i.indirectDiffuse.mulAssign(s),i.indirectDiffuse.mulAssign(dn.rgb)}finish(e,t,r){const s=r.material,i=e.outgoingLight,n=r.context.environment;if(n)switch(s.combine){case Y:i.rgb.assign(pa(i.rgb,i.rgb.mul(n.rgb),yd.mul(bd)));break;case X:i.rgb.assign(pa(i.rgb,n.rgb,yd.mul(bd)));break;case K:i.rgb.addAssign(n.rgb.mul(yd.mul(bd)));break;default:console.warn("THREE.BasicLightingModel: Unsupported .combine value:",s.combine)}}}const Mh=new Q;class Bh extends sh{static get type(){return"MeshBasicNodeMaterial"}constructor(e){super(),this.isMeshBasicNodeMaterial=!0,this.lights=!0,this.setDefaultValues(Mh),this.setValues(e)}setupNormal(){return pl}setupEnvironment(e){const t=super.setupEnvironment(e);return t?new Rh(t):null}setupLightMap(e){let t=null;return e.material.lightMap&&(t=new Ch(Hd)),t}setupOutgoingLight(){return dn.rgb}setupLightingModel(){return new wh}}const Fh=Ai((({f0:e,f90:t,dotVH:r})=>{const s=r.mul(-5.55473).sub(6.98316).mul(r).exp2();return e.mul(s.oneMinus()).add(t.mul(s))})),Uh=Ai((e=>e.diffuseColor.mul(1/Math.PI))),Ph=Ai((({dotNH:e})=>Cn.mul(Bi(.5)).add(1).mul(Bi(1/Math.PI)).mul(e.pow(Cn)))),Ih=Ai((({lightDirection:e})=>{const t=e.add(ol).normalize(),r=ml.dot(t).clamp(),s=ol.dot(t).clamp(),i=Fh({f0:An,f90:1,dotVH:s}),n=Bi(.25),o=Ph({dotNH:r});return i.mul(n).mul(o)}));class Dh extends wh{constructor(e=!0){super(),this.specular=e}direct({lightDirection:e,lightColor:t,reflectedLight:r}){const s=ml.dot(e).clamp().mul(t);r.directDiffuse.addAssign(s.mul(Uh({diffuseColor:dn.rgb}))),!0===this.specular&&r.directSpecular.addAssign(s.mul(Ih({lightDirection:e})).mul(yd))}indirect({ambientOcclusion:e,irradiance:t,reflectedLight:r}){r.indirectDiffuse.addAssign(t.mul(Uh({diffuseColor:dn}))),r.indirectDiffuse.mulAssign(e)}}const Lh=new Z;class Vh extends sh{static get type(){return"MeshLambertNodeMaterial"}constructor(e){super(),this.isMeshLambertNodeMaterial=!0,this.lights=!0,this.setDefaultValues(Lh),this.setValues(e)}setupEnvironment(e){const t=super.setupEnvironment(e);return t?new Rh(t):null}setupLightingModel(){return new Dh(!1)}}const Oh=new J;class Gh extends sh{static get type(){return"MeshPhongNodeMaterial"}constructor(e){super(),this.isMeshPhongNodeMaterial=!0,this.lights=!0,this.shininessNode=null,this.specularNode=null,this.setDefaultValues(Oh),this.setValues(e)}setupEnvironment(e){const t=super.setupEnvironment(e);return t?new Rh(t):null}setupLightingModel(){return new Dh}setupVariants(){const e=(this.shininessNode?Bi(this.shininessNode):cd).max(1e-4);Cn.assign(e);const t=this.specularNode||gd;An.assign(t)}copy(e){return this.shininessNode=e.shininessNode,this.specularNode=e.specularNode,super.copy(e)}}const kh=Ai((e=>{if(!1===e.geometry.hasAttribute("normal"))return Bi(0);const t=pl.dFdx().abs().max(pl.dFdy().abs());return t.x.max(t.y).max(t.z)})),zh=Ai((e=>{const{roughness:t}=e,r=kh();let s=t.max(.0525);return s=s.add(r),s=s.min(1),s})),$h=Ai((({alpha:e,dotNL:t,dotNV:r})=>{const s=e.pow2(),i=t.mul(s.add(s.oneMinus().mul(r.pow2())).sqrt()),n=r.mul(s.add(s.oneMinus().mul(t.pow2())).sqrt());return jn(.5,i.add(n).max(po))})).setLayout({name:"V_GGX_SmithCorrelated",type:"float",inputs:[{name:"alpha",type:"float"},{name:"dotNL",type:"float"},{name:"dotNV",type:"float"}]}),Hh=Ai((({alphaT:e,alphaB:t,dotTV:r,dotBV:s,dotTL:i,dotBL:n,dotNV:o,dotNL:a})=>{const u=a.mul(Oi(e.mul(r),t.mul(s),o).length()),l=o.mul(Oi(e.mul(i),t.mul(n),a).length());return jn(.5,u.add(l)).saturate()})).setLayout({name:"V_GGX_SmithCorrelated_Anisotropic",type:"float",inputs:[{name:"alphaT",type:"float",qualifier:"in"},{name:"alphaB",type:"float",qualifier:"in"},{name:"dotTV",type:"float",qualifier:"in"},{name:"dotBV",type:"float",qualifier:"in"},{name:"dotTL",type:"float",qualifier:"in"},{name:"dotBL",type:"float",qualifier:"in"},{name:"dotNV",type:"float",qualifier:"in"},{name:"dotNL",type:"float",qualifier:"in"}]}),Wh=Ai((({alpha:e,dotNH:t})=>{const r=e.pow2(),s=t.pow2().mul(r.oneMinus()).oneMinus();return r.div(s.pow2()).mul(1/Math.PI)})).setLayout({name:"D_GGX",type:"float",inputs:[{name:"alpha",type:"float"},{name:"dotNH",type:"float"}]}),jh=Bi(1/Math.PI),qh=Ai((({alphaT:e,alphaB:t,dotNH:r,dotTH:s,dotBH:i})=>{const n=e.mul(t),o=Oi(t.mul(s),e.mul(i),n.mul(r)),a=o.dot(o),u=n.div(a);return jh.mul(n.mul(u.pow2()))})).setLayout({name:"D_GGX_Anisotropic",type:"float",inputs:[{name:"alphaT",type:"float",qualifier:"in"},{name:"alphaB",type:"float",qualifier:"in"},{name:"dotNH",type:"float",qualifier:"in"},{name:"dotTH",type:"float",qualifier:"in"},{name:"dotBH",type:"float",qualifier:"in"}]}),Kh=Ai((e=>{const{lightDirection:t,f0:r,f90:s,roughness:i,f:n,USE_IRIDESCENCE:o,USE_ANISOTROPY:a}=e,u=e.normalView||ml,l=i.pow2(),d=t.add(ol).normalize(),c=u.dot(t).clamp(),h=u.dot(ol).clamp(),p=u.dot(d).clamp(),g=ol.dot(d).clamp();let m,f,y=Fh({f0:r,f90:s,dotVH:g});if(yi(o)&&(y=bn.mix(y,n)),yi(a)){const e=Nn.dot(t),r=Nn.dot(ol),s=Nn.dot(d),i=Sn.dot(t),n=Sn.dot(ol),o=Sn.dot(d);m=Hh({alphaT:_n,alphaB:l,dotTV:r,dotBV:n,dotTL:e,dotBL:i,dotNV:h,dotNL:c}),f=qh({alphaT:_n,alphaB:l,dotNH:p,dotTH:s,dotBH:o})}else m=$h({alpha:l,dotNL:c,dotNV:h}),f=Wh({alpha:l,dotNH:p});return y.mul(m).mul(f)})),Xh=Ai((({roughness:e,dotNV:t})=>{const r=$i(-1,-.0275,-.572,.022),s=$i(1,.0425,1.04,-.04),i=e.mul(r).add(s),n=i.x.mul(i.x).min(t.mul(-9.28).exp2()).mul(i.x).add(i.y);return Ii(-1.04,1.04).mul(n).add(i.zw)})).setLayout({name:"DFGApprox",type:"vec2",inputs:[{name:"roughness",type:"float"},{name:"dotNV",type:"vec3"}]}),Yh=Ai((e=>{const{dotNV:t,specularColor:r,specularF90:s,roughness:i}=e,n=Xh({dotNV:t,roughness:i});return r.mul(n.x).add(s.mul(n.y))})),Qh=Ai((({f:e,f90:t,dotVH:r})=>{const s=r.oneMinus().saturate(),i=s.mul(s),n=s.mul(i,i).clamp(0,.9999);return e.sub(Oi(t).mul(n)).div(n.oneMinus())})).setLayout({name:"Schlick_to_F0",type:"vec3",inputs:[{name:"f",type:"vec3"},{name:"f90",type:"float"},{name:"dotVH",type:"float"}]}),Zh=Ai((({roughness:e,dotNH:t})=>{const r=e.pow2(),s=Bi(1).div(r),i=t.pow2().oneMinus().max(.0078125);return Bi(2).add(s).mul(i.pow(s.mul(.5))).div(2*Math.PI)})).setLayout({name:"D_Charlie",type:"float",inputs:[{name:"roughness",type:"float"},{name:"dotNH",type:"float"}]}),Jh=Ai((({dotNV:e,dotNL:t})=>Bi(1).div(Bi(4).mul(t.add(e).sub(t.mul(e)))))).setLayout({name:"V_Neubelt",type:"float",inputs:[{name:"dotNV",type:"float"},{name:"dotNL",type:"float"}]}),ep=Ai((({lightDirection:e})=>{const t=e.add(ol).normalize(),r=ml.dot(e).clamp(),s=ml.dot(ol).clamp(),i=ml.dot(t).clamp(),n=Zh({roughness:yn,dotNH:i}),o=Jh({dotNV:s,dotNL:r});return fn.mul(n).mul(o)})),tp=Ai((({N:e,V:t,roughness:r})=>{const s=e.dot(t).saturate(),i=Ii(r,s.oneMinus().sqrt());return i.assign(i.mul(.984375).add(.0078125)),i})).setLayout({name:"LTC_Uv",type:"vec2",inputs:[{name:"N",type:"vec3"},{name:"V",type:"vec3"},{name:"roughness",type:"float"}]}),rp=Ai((({f:e})=>{const t=e.length();return Zo(t.mul(t).add(e.z).div(t.add(1)),0)})).setLayout({name:"LTC_ClippedSphereFormFactor",type:"float",inputs:[{name:"f",type:"vec3"}]}),sp=Ai((({v1:e,v2:t})=>{const r=e.dot(t),s=r.abs().toVar(),i=s.mul(.0145206).add(.4965155).mul(s).add(.8543985).toVar(),n=s.add(4.1616724).mul(s).add(3.417594).toVar(),o=i.div(n),a=r.greaterThan(0).select(o,Zo(r.mul(r).oneMinus(),1e-7).inverseSqrt().mul(.5).sub(o));return e.cross(t).mul(a)})).setLayout({name:"LTC_EdgeVectorFormFactor",type:"vec3",inputs:[{name:"v1",type:"vec3"},{name:"v2",type:"vec3"}]}),ip=Ai((({N:e,V:t,P:r,mInv:s,p0:i,p1:n,p2:o,p3:a})=>{const u=n.sub(i).toVar(),l=a.sub(i).toVar(),d=u.cross(l),c=Oi().toVar();return Ei(d.dot(r.sub(i)).greaterThanEqual(0),(()=>{const u=t.sub(e.mul(t.dot(e))).normalize(),l=e.cross(u).negate(),d=s.mul(Ki(u,l,e).transpose()).toVar(),h=d.mul(i.sub(r)).normalize().toVar(),p=d.mul(n.sub(r)).normalize().toVar(),g=d.mul(o.sub(r)).normalize().toVar(),m=d.mul(a.sub(r)).normalize().toVar(),f=Oi(0).toVar();f.addAssign(sp({v1:h,v2:p})),f.addAssign(sp({v1:p,v2:g})),f.addAssign(sp({v1:g,v2:m})),f.addAssign(sp({v1:m,v2:h})),c.assign(Oi(rp({f:f})))})),c})).setLayout({name:"LTC_Evaluate",type:"vec3",inputs:[{name:"N",type:"vec3"},{name:"V",type:"vec3"},{name:"P",type:"vec3"},{name:"mInv",type:"mat3"},{name:"p0",type:"vec3"},{name:"p1",type:"vec3"},{name:"p2",type:"vec3"},{name:"p3",type:"vec3"}]}),np=1/6,op=e=>Wn(np,Wn(e,Wn(e,e.negate().add(3)).sub(3)).add(1)),ap=e=>Wn(np,Wn(e,Wn(e,Wn(3,e).sub(6))).add(4)),up=e=>Wn(np,Wn(e,Wn(e,Wn(-3,e).add(3)).add(3)).add(1)),lp=e=>Wn(np,oa(e,3)),dp=e=>op(e).add(ap(e)),cp=e=>up(e).add(lp(e)),hp=e=>$n(-1,ap(e).div(op(e).add(ap(e)))),pp=e=>$n(1,lp(e).div(up(e).add(lp(e)))),gp=(e,t,r)=>{const s=e.uvNode,i=Wn(s,t.zw).add(.5),n=Co(i),o=Mo(i),a=dp(o.x),u=cp(o.x),l=hp(o.x),d=pp(o.x),c=hp(o.y),h=pp(o.y),p=Ii(n.x.add(l),n.y.add(c)).sub(.5).mul(t.xy),g=Ii(n.x.add(d),n.y.add(c)).sub(.5).mul(t.xy),m=Ii(n.x.add(l),n.y.add(h)).sub(.5).mul(t.xy),f=Ii(n.x.add(d),n.y.add(h)).sub(.5).mul(t.xy),y=dp(o.y).mul($n(a.mul(e.sample(p).level(r)),u.mul(e.sample(g).level(r)))),b=cp(o.y).mul($n(a.mul(e.sample(m).level(r)),u.mul(e.sample(f).level(r))));return y.add(b)},mp=Ai((([e,t=Bi(3)])=>{const r=Ii(e.size(Fi(t))),s=Ii(e.size(Fi(t.add(1)))),i=jn(1,r),n=jn(1,s),o=gp(e,$i(i,r),Co(t)),a=gp(e,$i(n,s),Eo(t));return Mo(t).mix(o,a)})),fp=Ai((([e,t,r,s,i])=>{const n=Oi(fa(t.negate(),wo(e),jn(1,s))),o=Oi(Oo(i[0].xyz),Oo(i[1].xyz),Oo(i[2].xyz));return wo(n).mul(r.mul(o))})).setLayout({name:"getVolumeTransmissionRay",type:"vec3",inputs:[{name:"n",type:"vec3"},{name:"v",type:"vec3"},{name:"thickness",type:"float"},{name:"ior",type:"float"},{name:"modelMatrix",type:"mat4"}]}),yp=Ai((([e,t])=>e.mul(ga(t.mul(2).sub(2),0,1)))).setLayout({name:"applyIorToRoughness",type:"float",inputs:[{name:"roughness",type:"float"},{name:"ior",type:"float"}]}),bp=Oc(),xp=Oc(),Tp=Ai((([e,t,r],{material:s})=>{const i=(s.side===T?bp:xp).sample(e),n=So(Cc.x).mul(yp(t,r));return mp(i,n)})),_p=Ai((([e,t,r])=>(Ei(r.notEqual(0),(()=>{const s=No(t).negate().div(r);return _o(s.negate().mul(e))})),Oi(1)))).setLayout({name:"volumeAttenuation",type:"vec3",inputs:[{name:"transmissionDistance",type:"float"},{name:"attenuationColor",type:"vec3"},{name:"attenuationDistance",type:"float"}]}),vp=Ai((([e,t,r,s,i,n,o,a,u,l,d,c,h,p,g])=>{let m,f;if(g){m=$i().toVar(),f=Oi().toVar();const i=d.sub(1).mul(g.mul(.025)),n=Oi(d.sub(i),d,d.add(i));cc({start:0,end:3},(({i:i})=>{const d=n.element(i),g=fp(e,t,c,d,a),y=o.add(g),b=l.mul(u.mul($i(y,1))),x=Ii(b.xy.div(b.w)).toVar();x.addAssign(1),x.divAssign(2),x.assign(Ii(x.x,x.y.oneMinus()));const T=Tp(x,r,d);m.element(i).assign(T.element(i)),m.a.addAssign(T.a),f.element(i).assign(s.element(i).mul(_p(Oo(g),h,p).element(i)))})),m.a.divAssign(3)}else{const i=fp(e,t,c,d,a),n=o.add(i),g=l.mul(u.mul($i(n,1))),y=Ii(g.xy.div(g.w)).toVar();y.addAssign(1),y.divAssign(2),y.assign(Ii(y.x,y.y.oneMinus())),m=Tp(y,r,d),f=s.mul(_p(Oo(i),h,p))}const y=f.rgb.mul(m.rgb),b=e.dot(t).clamp(),x=Oi(Yh({dotNV:b,specularColor:i,specularF90:n,roughness:r})),T=f.r.add(f.g,f.b).div(3);return $i(x.oneMinus().mul(y),m.a.oneMinus().mul(T).oneMinus())})),Np=Ki(3.2404542,-.969266,.0556434,-1.5371385,1.8760108,-.2040259,-.4985314,.041556,1.0572252),Sp=(e,t)=>e.sub(t).div(e.add(t)).pow2(),Ap=Ai((({outsideIOR:e,eta2:t,cosTheta1:r,thinFilmThickness:s,baseF0:i})=>{const n=pa(e,t,ya(0,.03,s)),o=e.div(n).pow2().mul(r.pow2().oneMinus()).oneMinus();Ei(o.lessThan(0),(()=>Oi(1)));const a=o.sqrt(),u=Sp(n,e),l=Fh({f0:u,f90:1,dotVH:r}),d=l.oneMinus(),c=n.lessThan(e).select(Math.PI,0),h=Bi(Math.PI).sub(c),p=(e=>{const t=e.sqrt();return Oi(1).add(t).div(Oi(1).sub(t))})(i.clamp(0,.9999)),g=Sp(p,n.toVec3()),m=Fh({f0:g,f90:1,dotVH:a}),f=Oi(p.x.lessThan(n).select(Math.PI,0),p.y.lessThan(n).select(Math.PI,0),p.z.lessThan(n).select(Math.PI,0)),y=n.mul(s,a,2),b=Oi(h).add(f),x=l.mul(m).clamp(1e-5,.9999),T=x.sqrt(),_=d.pow2().mul(m).div(Oi(1).sub(x)),v=l.add(_).toVar(),N=_.sub(d).toVar();return cc({start:1,end:2,condition:"<=",name:"m"},(({m:e})=>{N.mulAssign(T);const t=((e,t)=>{const r=e.mul(2*Math.PI*1e-9),s=Oi(54856e-17,44201e-17,52481e-17),i=Oi(1681e3,1795300,2208400),n=Oi(43278e5,93046e5,66121e5),o=Bi(9747e-17*Math.sqrt(2*Math.PI*45282e5)).mul(r.mul(2239900).add(t.x).cos()).mul(r.pow2().mul(-45282e5).exp());let a=s.mul(n.mul(2*Math.PI).sqrt()).mul(i.mul(r).add(t).cos()).mul(r.pow2().negate().mul(n).exp());return a=Oi(a.x.add(o),a.y,a.z).div(1.0685e-7),Np.mul(a)})(Bi(e).mul(y),Bi(e).mul(b)).mul(2);v.addAssign(N.mul(t))})),v.max(Oi(0))})).setLayout({name:"evalIridescence",type:"vec3",inputs:[{name:"outsideIOR",type:"float"},{name:"eta2",type:"float"},{name:"cosTheta1",type:"float"},{name:"thinFilmThickness",type:"float"},{name:"baseF0",type:"vec3"}]}),Rp=Ai((({normal:e,viewDir:t,roughness:r})=>{const s=e.dot(t).saturate(),i=r.pow2(),n=Ra(r.lessThan(.25),Bi(-339.2).mul(i).add(Bi(161.4).mul(r)).sub(25.9),Bi(-8.48).mul(i).add(Bi(14.3).mul(r)).sub(9.95)),o=Ra(r.lessThan(.25),Bi(44).mul(i).sub(Bi(23.7).mul(r)).add(3.26),Bi(1.97).mul(i).sub(Bi(3.27).mul(r)).add(.72));return Ra(r.lessThan(.25),0,Bi(.1).mul(r).sub(.025)).add(n.mul(s).add(o).exp()).mul(1/Math.PI).saturate()})),Cp=Oi(.04),Ep=Bi(1);class wp extends Eh{constructor(e=!1,t=!1,r=!1,s=!1,i=!1,n=!1){super(),this.clearcoat=e,this.sheen=t,this.iridescence=r,this.anisotropy=s,this.transmission=i,this.dispersion=n,this.clearcoatRadiance=null,this.clearcoatSpecularDirect=null,this.clearcoatSpecularIndirect=null,this.sheenSpecularDirect=null,this.sheenSpecularIndirect=null,this.iridescenceFresnel=null,this.iridescenceF0=null}start(e){if(!0===this.clearcoat&&(this.clearcoatRadiance=Oi().toVar("clearcoatRadiance"),this.clearcoatSpecularDirect=Oi().toVar("clearcoatSpecularDirect"),this.clearcoatSpecularIndirect=Oi().toVar("clearcoatSpecularIndirect")),!0===this.sheen&&(this.sheenSpecularDirect=Oi().toVar("sheenSpecularDirect"),this.sheenSpecularIndirect=Oi().toVar("sheenSpecularIndirect")),!0===this.iridescence){const e=ml.dot(ol).clamp();this.iridescenceFresnel=Ap({outsideIOR:Bi(1),eta2:xn,cosTheta1:e,thinFilmThickness:Tn,baseF0:An}),this.iridescenceF0=Qh({f:this.iridescenceFresnel,f90:1,dotVH:e})}if(!0===this.transmission){const t=sl,r=Iu.sub(sl).normalize(),s=fl;e.backdrop=vp(s,r,hn,dn,An,Rn,t,Hu,Fu,Mu,Fn,Pn,Dn,In,this.dispersion?Ln:null),e.backdropAlpha=Un,dn.a.mulAssign(pa(1,e.backdrop.a,Un))}}computeMultiscattering(e,t,r){const s=ml.dot(ol).clamp(),i=Xh({roughness:hn,dotNV:s}),n=(this.iridescenceF0?bn.mix(An,this.iridescenceF0):An).mul(i.x).add(r.mul(i.y)),o=i.x.add(i.y).oneMinus(),a=An.add(An.oneMinus().mul(.047619)),u=n.mul(a).div(o.mul(a).oneMinus());e.addAssign(n),t.addAssign(u.mul(o))}direct({lightDirection:e,lightColor:t,reflectedLight:r}){const s=ml.dot(e).clamp().mul(t);if(!0===this.sheen&&this.sheenSpecularDirect.addAssign(s.mul(ep({lightDirection:e}))),!0===this.clearcoat){const r=yl.dot(e).clamp().mul(t);this.clearcoatSpecularDirect.addAssign(r.mul(Kh({lightDirection:e,f0:Cp,f90:Ep,roughness:mn,normalView:yl})))}r.directDiffuse.addAssign(s.mul(Uh({diffuseColor:dn.rgb}))),r.directSpecular.addAssign(s.mul(Kh({lightDirection:e,f0:An,f90:1,roughness:hn,iridescence:this.iridescence,f:this.iridescenceFresnel,USE_IRIDESCENCE:this.iridescence,USE_ANISOTROPY:this.anisotropy})))}directRectArea({lightColor:e,lightPosition:t,halfWidth:r,halfHeight:s,reflectedLight:i,ltc_1:n,ltc_2:o}){const a=t.add(r).sub(s),u=t.sub(r).sub(s),l=t.sub(r).add(s),d=t.add(r).add(s),c=ml,h=ol,p=nl.toVar(),g=tp({N:c,V:h,roughness:hn}),m=n.sample(g).toVar(),f=o.sample(g).toVar(),y=Ki(Oi(m.x,0,m.y),Oi(0,1,0),Oi(m.z,0,m.w)).toVar(),b=An.mul(f.x).add(An.oneMinus().mul(f.y)).toVar();i.directSpecular.addAssign(e.mul(b).mul(ip({N:c,V:h,P:p,mInv:y,p0:a,p1:u,p2:l,p3:d}))),i.directDiffuse.addAssign(e.mul(dn).mul(ip({N:c,V:h,P:p,mInv:Ki(1,0,0,0,1,0,0,0,1),p0:a,p1:u,p2:l,p3:d})))}indirect(e,t,r){this.indirectDiffuse(e,t,r),this.indirectSpecular(e,t,r),this.ambientOcclusion(e,t,r)}indirectDiffuse({irradiance:e,reflectedLight:t}){t.indirectDiffuse.addAssign(e.mul(Uh({diffuseColor:dn})))}indirectSpecular({radiance:e,iblIrradiance:t,reflectedLight:r}){if(!0===this.sheen&&this.sheenSpecularIndirect.addAssign(t.mul(fn,Rp({normal:ml,viewDir:ol,roughness:yn}))),!0===this.clearcoat){const e=yl.dot(ol).clamp(),t=Yh({dotNV:e,specularColor:Cp,specularF90:Ep,roughness:mn});this.clearcoatSpecularIndirect.addAssign(this.clearcoatRadiance.mul(t))}const s=Oi().toVar("singleScattering"),i=Oi().toVar("multiScattering"),n=t.mul(1/Math.PI);this.computeMultiscattering(s,i,Rn);const o=s.add(i),a=dn.mul(o.r.max(o.g).max(o.b).oneMinus());r.indirectSpecular.addAssign(e.mul(s)),r.indirectSpecular.addAssign(i.mul(n)),r.indirectDiffuse.addAssign(a.mul(n))}ambientOcclusion({ambientOcclusion:e,reflectedLight:t}){const r=ml.dot(ol).clamp().add(e),s=hn.mul(-16).oneMinus().negate().exp2(),i=e.sub(r.pow(s).oneMinus()).clamp();!0===this.clearcoat&&this.clearcoatSpecularIndirect.mulAssign(e),!0===this.sheen&&this.sheenSpecularIndirect.mulAssign(e),t.indirectDiffuse.mulAssign(e),t.indirectSpecular.mulAssign(i)}finish(e){const{outgoingLight:t}=e;if(!0===this.clearcoat){const e=yl.dot(ol).clamp(),r=Fh({dotVH:e,f0:Cp,f90:Ep}),s=t.mul(gn.mul(r).oneMinus()).add(this.clearcoatSpecularDirect.add(this.clearcoatSpecularIndirect).mul(gn));t.assign(s)}if(!0===this.sheen){const e=fn.r.max(fn.g).max(fn.b).mul(.157).oneMinus(),r=t.mul(e).add(this.sheenSpecularDirect,this.sheenSpecularIndirect);t.assign(r)}}}const Mp=Bi(1),Bp=Bi(-2),Fp=Bi(.8),Up=Bi(-1),Pp=Bi(.4),Ip=Bi(2),Dp=Bi(.305),Lp=Bi(3),Vp=Bi(.21),Op=Bi(4),Gp=Bi(4),kp=Bi(16),zp=Ai((([e])=>{const t=Oi(Lo(e)).toVar(),r=Bi(-1).toVar();return Ei(t.x.greaterThan(t.z),(()=>{Ei(t.x.greaterThan(t.y),(()=>{r.assign(Ra(e.x.greaterThan(0),0,3))})).Else((()=>{r.assign(Ra(e.y.greaterThan(0),1,4))}))})).Else((()=>{Ei(t.z.greaterThan(t.y),(()=>{r.assign(Ra(e.z.greaterThan(0),2,5))})).Else((()=>{r.assign(Ra(e.y.greaterThan(0),1,4))}))})),r})).setLayout({name:"getFace",type:"float",inputs:[{name:"direction",type:"vec3"}]}),$p=Ai((([e,t])=>{const r=Ii().toVar();return Ei(t.equal(0),(()=>{r.assign(Ii(e.z,e.y).div(Lo(e.x)))})).ElseIf(t.equal(1),(()=>{r.assign(Ii(e.x.negate(),e.z.negate()).div(Lo(e.y)))})).ElseIf(t.equal(2),(()=>{r.assign(Ii(e.x.negate(),e.y).div(Lo(e.z)))})).ElseIf(t.equal(3),(()=>{r.assign(Ii(e.z.negate(),e.y).div(Lo(e.x)))})).ElseIf(t.equal(4),(()=>{r.assign(Ii(e.x.negate(),e.z).div(Lo(e.y)))})).Else((()=>{r.assign(Ii(e.x,e.y).div(Lo(e.z)))})),Wn(.5,r.add(1))})).setLayout({name:"getUV",type:"vec2",inputs:[{name:"direction",type:"vec3"},{name:"face",type:"float"}]}),Hp=Ai((([e])=>{const t=Bi(0).toVar();return Ei(e.greaterThanEqual(Fp),(()=>{t.assign(Mp.sub(e).mul(Up.sub(Bp)).div(Mp.sub(Fp)).add(Bp))})).ElseIf(e.greaterThanEqual(Pp),(()=>{t.assign(Fp.sub(e).mul(Ip.sub(Up)).div(Fp.sub(Pp)).add(Up))})).ElseIf(e.greaterThanEqual(Dp),(()=>{t.assign(Pp.sub(e).mul(Lp.sub(Ip)).div(Pp.sub(Dp)).add(Ip))})).ElseIf(e.greaterThanEqual(Vp),(()=>{t.assign(Dp.sub(e).mul(Op.sub(Lp)).div(Dp.sub(Vp)).add(Lp))})).Else((()=>{t.assign(Bi(-2).mul(So(Wn(1.16,e))))})),t})).setLayout({name:"roughnessToMip",type:"float",inputs:[{name:"roughness",type:"float"}]}),Wp=Ai((([e,t])=>{const r=e.toVar();r.assign(Wn(2,r).sub(1));const s=Oi(r,1).toVar();return Ei(t.equal(0),(()=>{s.assign(s.zyx)})).ElseIf(t.equal(1),(()=>{s.assign(s.xzy),s.xz.mulAssign(-1)})).ElseIf(t.equal(2),(()=>{s.x.mulAssign(-1)})).ElseIf(t.equal(3),(()=>{s.assign(s.zyx),s.xz.mulAssign(-1)})).ElseIf(t.equal(4),(()=>{s.assign(s.xzy),s.xy.mulAssign(-1)})).ElseIf(t.equal(5),(()=>{s.z.mulAssign(-1)})),s})).setLayout({name:"getDirection",type:"vec3",inputs:[{name:"uv",type:"vec2"},{name:"face",type:"float"}]}),jp=Ai((([e,t,r,s,i,n])=>{const o=Bi(r),a=Oi(t),u=ga(Hp(o),Bp,n),l=Mo(u),d=Co(u),c=Oi(qp(e,a,d,s,i,n)).toVar();return Ei(l.notEqual(0),(()=>{const t=Oi(qp(e,a,d.add(1),s,i,n)).toVar();c.assign(pa(c,t,l))})),c})),qp=Ai((([e,t,r,s,i,n])=>{const o=Bi(r).toVar(),a=Oi(t),u=Bi(zp(a)).toVar(),l=Bi(Zo(Gp.sub(o),0)).toVar();o.assign(Zo(o,Gp));const d=Bi(vo(o)).toVar(),c=Ii($p(a,u).mul(d.sub(2)).add(1)).toVar();return Ei(u.greaterThan(2),(()=>{c.y.addAssign(d),u.subAssign(3)})),c.x.addAssign(u.mul(d)),c.x.addAssign(l.mul(Wn(3,kp))),c.y.addAssign(Wn(4,vo(n).sub(d))),c.x.mulAssign(s),c.y.mulAssign(i),e.sample(c).grad(Ii(),Ii())})),Kp=Ai((({envMap:e,mipInt:t,outputDirection:r,theta:s,axis:i,CUBEUV_TEXEL_WIDTH:n,CUBEUV_TEXEL_HEIGHT:o,CUBEUV_MAX_MIP:a})=>{const u=Fo(s),l=r.mul(u).add(i.cross(r).mul(Bo(s))).add(i.mul(i.dot(r).mul(u.oneMinus())));return qp(e,l,t,n,o,a)})),Xp=Ai((({n:e,latitudinal:t,poleAxis:r,outputDirection:s,weights:i,samples:n,dTheta:o,mipInt:a,envMap:u,CUBEUV_TEXEL_WIDTH:l,CUBEUV_TEXEL_HEIGHT:d,CUBEUV_MAX_MIP:c})=>{const h=Oi(Ra(t,r,na(r,s))).toVar();Ei(yo(h.equals(Oi(0))),(()=>{h.assign(Oi(s.z,0,s.x.negate()))})),h.assign(wo(h));const p=Oi().toVar();return p.addAssign(i.element(Fi(0)).mul(Kp({theta:0,axis:h,outputDirection:s,mipInt:a,envMap:u,CUBEUV_TEXEL_WIDTH:l,CUBEUV_TEXEL_HEIGHT:d,CUBEUV_MAX_MIP:c}))),cc({start:Fi(1),end:e},(({i:e})=>{Ei(e.greaterThanEqual(n),(()=>{hc()}));const t=Bi(o.mul(Bi(e))).toVar();p.addAssign(i.element(e).mul(Kp({theta:t.mul(-1),axis:h,outputDirection:s,mipInt:a,envMap:u,CUBEUV_TEXEL_WIDTH:l,CUBEUV_TEXEL_HEIGHT:d,CUBEUV_MAX_MIP:c}))),p.addAssign(i.element(e).mul(Kp({theta:t,axis:h,outputDirection:s,mipInt:a,envMap:u,CUBEUV_TEXEL_WIDTH:l,CUBEUV_TEXEL_HEIGHT:d,CUBEUV_MAX_MIP:c})))})),$i(p,1)}));let Yp=null;const Qp=new WeakMap;function Zp(e){let t=Qp.get(e);if((void 0!==t?t.pmremVersion:-1)!==e.pmremVersion){const r=e.image;if(e.isCubeTexture){if(!function(e){if(null==e)return!1;let t=0;const r=6;for(let s=0;s0}(r))return null;t=Yp.fromEquirectangular(e,t)}t.pmremVersion=e.pmremVersion,Qp.set(e,t)}return t.texture}class Jp extends Ls{static get type(){return"PMREMNode"}constructor(e,t=null,r=null){super("vec3"),this._value=e,this._pmrem=null,this.uvNode=t,this.levelNode=r,this._generator=null;const s=new ee;s.isRenderTargetTexture=!0,this._texture=Ru(s),this._width=on(0),this._height=on(0),this._maxMip=on(0),this.updateBeforeType=Rs.RENDER}set value(e){this._value=e,this._pmrem=null}get value(){return this._value}updateFromTexture(e){const t=function(e){const t=Math.log2(e)-2,r=1/e;return{texelWidth:1/(3*Math.max(Math.pow(2,t),112)),texelHeight:r,maxMip:t}}(e.image.height);this._texture.value=e,this._width.value=t.texelWidth,this._height.value=t.texelHeight,this._maxMip.value=t.maxMip}updateBefore(){let e=this._pmrem;const t=e?e.pmremVersion:-1,r=this._value;t!==r.pmremVersion&&(e=!0===r.isPMREMTexture?r:Zp(r),null!==e&&(this._pmrem=e,this.updateFromTexture(e)))}setup(e){null===Yp&&(Yp=e.createPMREMGenerator()),this.updateBefore(e);let t=this.uvNode;null===t&&e.context.getUV&&(t=e.context.getUV(this));const r=this.value;e.renderer.coordinateSystem===u&&!0!==r.isPMREMTexture&&!0===r.isRenderTargetTexture&&(t=Oi(t.x.negate(),t.yz)),t=Oi(t.x,t.y.negate(),t.z);let s=this.levelNode;return null===s&&e.context.getTextureLevel&&(s=e.context.getTextureLevel(this)),jp(this._texture,t,s,this._width,this._height,this._maxMip)}}const eg=Ni(Jp),tg=new WeakMap;class rg extends bc{static get type(){return"EnvironmentNode"}constructor(e=null){super(),this.envNode=e}setup(e){const{material:t}=e;let r=this.envNode;if(r.isTextureNode||r.isMaterialReferenceNode){const e=r.isTextureNode?r.value:t[r.property];let s=tg.get(e);void 0===s&&(s=eg(e),tg.set(e,s)),r=s}const s=t.envMap?Pl("envMapIntensity","float",e.material):Pl("environmentIntensity","float",e.scene),i=!0===t.useAnisotropy||t.anisotropy>0?Jl:ml,n=r.context(sg(hn,i)).mul(s),o=r.context(ig(fl)).mul(Math.PI).mul(s),a=au(n),u=au(o);e.context.radiance.addAssign(a),e.context.iblIrradiance.addAssign(u);const l=e.context.lightingModel.clearcoatRadiance;if(l){const e=r.context(sg(mn,yl)).mul(s),t=au(e);l.addAssign(t)}}}const sg=(e,t)=>{let r=null;return{getUV:()=>(null===r&&(r=ol.negate().reflect(t),r=e.mul(e).mix(r,t).normalize(),r=r.transformDirection(Fu)),r),getTextureLevel:()=>e}},ig=e=>({getUV:()=>e,getTextureLevel:()=>Bi(1)}),ng=new te;class og extends sh{static get type(){return"MeshStandardNodeMaterial"}constructor(e){super(),this.isMeshStandardNodeMaterial=!0,this.lights=!0,this.emissiveNode=null,this.metalnessNode=null,this.roughnessNode=null,this.setDefaultValues(ng),this.setValues(e)}setupEnvironment(e){let t=super.setupEnvironment(e);return null===t&&e.environmentNode&&(t=e.environmentNode),t?new rg(t):null}setupLightingModel(){return new wp}setupSpecular(){const e=pa(Oi(.04),dn.rgb,pn);An.assign(e),Rn.assign(1)}setupVariants(){const e=this.metalnessNode?Bi(this.metalnessNode):Td;pn.assign(e);let t=this.roughnessNode?Bi(this.roughnessNode):xd;t=zh({roughness:t}),hn.assign(t),this.setupSpecular(),dn.assign($i(dn.rgb.mul(e.oneMinus()),dn.a))}copy(e){return this.emissiveNode=e.emissiveNode,this.metalnessNode=e.metalnessNode,this.roughnessNode=e.roughnessNode,super.copy(e)}}const ag=new re;class ug extends og{static get type(){return"MeshPhysicalNodeMaterial"}constructor(e){super(),this.isMeshPhysicalNodeMaterial=!0,this.clearcoatNode=null,this.clearcoatRoughnessNode=null,this.clearcoatNormalNode=null,this.sheenNode=null,this.sheenRoughnessNode=null,this.iridescenceNode=null,this.iridescenceIORNode=null,this.iridescenceThicknessNode=null,this.specularIntensityNode=null,this.specularColorNode=null,this.iorNode=null,this.transmissionNode=null,this.thicknessNode=null,this.attenuationDistanceNode=null,this.attenuationColorNode=null,this.dispersionNode=null,this.anisotropyNode=null,this.setDefaultValues(ag),this.setValues(e)}get useClearcoat(){return this.clearcoat>0||null!==this.clearcoatNode}get useIridescence(){return this.iridescence>0||null!==this.iridescenceNode}get useSheen(){return this.sheen>0||null!==this.sheenNode}get useAnisotropy(){return this.anisotropy>0||null!==this.anisotropyNode}get useTransmission(){return this.transmission>0||null!==this.transmissionNode}get useDispersion(){return this.dispersion>0||null!==this.dispersionNode}setupSpecular(){const e=this.iorNode?Bi(this.iorNode):Pd;Fn.assign(e),An.assign(pa(Qo(aa(Fn.sub(1).div(Fn.add(1))).mul(fd),Oi(1)).mul(md),dn.rgb,pn)),Rn.assign(pa(md,1,pn))}setupLightingModel(){return new wp(this.useClearcoat,this.useSheen,this.useIridescence,this.useAnisotropy,this.useTransmission,this.useDispersion)}setupVariants(e){if(super.setupVariants(e),this.useClearcoat){const e=this.clearcoatNode?Bi(this.clearcoatNode):vd,t=this.clearcoatRoughnessNode?Bi(this.clearcoatRoughnessNode):Nd;gn.assign(e),mn.assign(zh({roughness:t}))}if(this.useSheen){const e=this.sheenNode?Oi(this.sheenNode):Rd,t=this.sheenRoughnessNode?Bi(this.sheenRoughnessNode):Cd;fn.assign(e),yn.assign(t)}if(this.useIridescence){const e=this.iridescenceNode?Bi(this.iridescenceNode):wd,t=this.iridescenceIORNode?Bi(this.iridescenceIORNode):Md,r=this.iridescenceThicknessNode?Bi(this.iridescenceThicknessNode):Bd;bn.assign(e),xn.assign(t),Tn.assign(r)}if(this.useAnisotropy){const e=(this.anisotropyNode?Ii(this.anisotropyNode):Ed).toVar();vn.assign(e.length()),Ei(vn.equal(0),(()=>{e.assign(Ii(1,0))})).Else((()=>{e.divAssign(Ii(vn)),vn.assign(vn.saturate())})),_n.assign(vn.pow2().mix(hn.pow2(),1)),Nn.assign(Ql[0].mul(e.x).add(Ql[1].mul(e.y))),Sn.assign(Ql[1].mul(e.x).sub(Ql[0].mul(e.y)))}if(this.useTransmission){const e=this.transmissionNode?Bi(this.transmissionNode):Fd,t=this.thicknessNode?Bi(this.thicknessNode):Ud,r=this.attenuationDistanceNode?Bi(this.attenuationDistanceNode):Id,s=this.attenuationColorNode?Oi(this.attenuationColorNode):Dd;if(Un.assign(e),Pn.assign(t),In.assign(r),Dn.assign(s),this.useDispersion){const e=this.dispersionNode?Bi(this.dispersionNode):$d;Ln.assign(e)}}}setupClearcoatNormal(){return this.clearcoatNormalNode?Oi(this.clearcoatNormalNode):Sd}setup(e){e.context.setupClearcoatNormal=()=>this.setupClearcoatNormal(e),super.setup(e)}copy(e){return this.clearcoatNode=e.clearcoatNode,this.clearcoatRoughnessNode=e.clearcoatRoughnessNode,this.clearcoatNormalNode=e.clearcoatNormalNode,this.sheenNode=e.sheenNode,this.sheenRoughnessNode=e.sheenRoughnessNode,this.iridescenceNode=e.iridescenceNode,this.iridescenceIORNode=e.iridescenceIORNode,this.iridescenceThicknessNode=e.iridescenceThicknessNode,this.specularIntensityNode=e.specularIntensityNode,this.specularColorNode=e.specularColorNode,this.transmissionNode=e.transmissionNode,this.thicknessNode=e.thicknessNode,this.attenuationDistanceNode=e.attenuationDistanceNode,this.attenuationColorNode=e.attenuationColorNode,this.dispersionNode=e.dispersionNode,this.anisotropyNode=e.anisotropyNode,super.copy(e)}}class lg extends wp{constructor(e=!1,t=!1,r=!1,s=!1,i=!1,n=!1,o=!1){super(e,t,r,s,i,n),this.useSSS=o}direct({lightDirection:e,lightColor:t,reflectedLight:r},s,i){if(!0===this.useSSS){const s=i.material,{thicknessColorNode:n,thicknessDistortionNode:o,thicknessAmbientNode:a,thicknessAttenuationNode:u,thicknessPowerNode:l,thicknessScaleNode:d}=s,c=e.add(ml.mul(o)).normalize(),h=Bi(ol.dot(c.negate()).saturate().pow(l).mul(d)),p=Oi(h.add(a).mul(n));r.directDiffuse.addAssign(p.mul(u.mul(t)))}super.direct({lightDirection:e,lightColor:t,reflectedLight:r},s,i)}}class dg extends ug{static get type(){return"MeshSSSNodeMaterial"}constructor(e){super(e),this.thicknessColorNode=null,this.thicknessDistortionNode=Bi(.1),this.thicknessAmbientNode=Bi(0),this.thicknessAttenuationNode=Bi(.1),this.thicknessPowerNode=Bi(2),this.thicknessScaleNode=Bi(10)}get useSSS(){return null!==this.thicknessColorNode}setupLightingModel(){return new lg(this.useClearcoat,this.useSheen,this.useIridescence,this.useAnisotropy,this.useTransmission,this.useDispersion,this.useSSS)}copy(e){return this.thicknessColorNode=e.thicknessColorNode,this.thicknessDistortionNode=e.thicknessDistortionNode,this.thicknessAmbientNode=e.thicknessAmbientNode,this.thicknessAttenuationNode=e.thicknessAttenuationNode,this.thicknessPowerNode=e.thicknessPowerNode,this.thicknessScaleNode=e.thicknessScaleNode,super.copy(e)}}const cg=Ai((({normal:e,lightDirection:t,builder:r})=>{const s=e.dot(t),i=Ii(s.mul(.5).add(.5),0);if(r.material.gradientMap){const e=Ll("gradientMap","texture").context({getUV:()=>i});return Oi(e.r)}{const e=i.fwidth().mul(.5);return pa(Oi(.7),Oi(1),ya(Bi(.7).sub(e.x),Bi(.7).add(e.x),i.x))}}));class hg extends Eh{direct({lightDirection:e,lightColor:t,reflectedLight:r},s,i){const n=cg({normal:dl,lightDirection:e,builder:i}).mul(t);r.directDiffuse.addAssign(n.mul(Uh({diffuseColor:dn.rgb})))}indirect({ambientOcclusion:e,irradiance:t,reflectedLight:r}){r.indirectDiffuse.addAssign(t.mul(Uh({diffuseColor:dn}))),r.indirectDiffuse.mulAssign(e)}}const pg=new se;class gg extends sh{static get type(){return"MeshToonNodeMaterial"}constructor(e){super(),this.isMeshToonNodeMaterial=!0,this.lights=!0,this.setDefaultValues(pg),this.setValues(e)}setupLightingModel(){return new hg}}class mg extends Ls{static get type(){return"MatcapUVNode"}constructor(){super("vec2")}setup(){const e=Oi(ol.z,0,ol.x.negate()).normalize(),t=ol.cross(e);return Ii(e.dot(ml),t.dot(ml)).mul(.495).add(.5)}}const fg=Si(mg),yg=new ie;class bg extends sh{static get type(){return"MeshMatcapNodeMaterial"}constructor(e){super(),this.isMeshMatcapNodeMaterial=!0,this.setDefaultValues(yg),this.setValues(e)}setupVariants(e){const t=fg;let r;r=e.material.matcap?Ll("matcap","texture").context({getUV:()=>t}):Oi(pa(.2,.8,t.y)),dn.rgb.mulAssign(r.rgb)}}const xg=new P;class Tg extends sh{static get type(){return"PointsNodeMaterial"}constructor(e){super(),this.isPointsNodeMaterial=!0,this.setDefaultValues(xg),this.setValues(e)}}class _g extends Ls{static get type(){return"RotateNode"}constructor(e,t){super(),this.positionNode=e,this.rotationNode=t}getNodeType(e){return this.positionNode.getNodeType(e)}setup(e){const{rotationNode:t,positionNode:r}=this;if("vec2"===this.getNodeType(e)){const e=t.cos(),s=t.sin();return qi(e,s,s.negate(),e).mul(r)}{const e=t,s=Xi($i(1,0,0,0),$i(0,Fo(e.x),Bo(e.x).negate(),0),$i(0,Bo(e.x),Fo(e.x),0),$i(0,0,0,1)),i=Xi($i(Fo(e.y),0,Bo(e.y),0),$i(0,1,0,0),$i(Bo(e.y).negate(),0,Fo(e.y),0),$i(0,0,0,1)),n=Xi($i(Fo(e.z),Bo(e.z).negate(),0,0),$i(Bo(e.z),Fo(e.z),0,0),$i(0,0,1,0),$i(0,0,0,1));return s.mul(i).mul(n).mul($i(r,1)).xyz}}}const vg=Ni(_g),Ng=new ne;class Sg extends sh{static get type(){return"SpriteNodeMaterial"}constructor(e){super(),this.isSpriteNodeMaterial=!0,this._useSizeAttenuation=!0,this.positionNode=null,this.rotationNode=null,this.scaleNode=null,this.setDefaultValues(Ng),this.setValues(e)}setupPositionView(e){const{object:t,camera:r}=e,s=this.sizeAttenuation,{positionNode:i,rotationNode:n,scaleNode:o}=this,a=Yu.mul(Oi(i||0));let u=Ii(Hu[0].xyz.length(),Hu[1].xyz.length());if(null!==o&&(u=u.mul(o)),!1===s)if(r.isPerspectiveCamera)u=u.mul(a.z.negate());else{const e=Bi(2).div(Mu.element(1).element(1));u=u.mul(e.mul(2))}let l=el.xy;if(t.center&&!0===t.center.isVector2){const e=((e,t,r)=>Ti(new qa(e,t,r)))("center","vec2",t);l=l.sub(e.sub(.5))}l=l.mul(u);const d=Bi(n||Ad),c=vg(l,d);return $i(a.xy.add(c),a.zw)}copy(e){return this.positionNode=e.positionNode,this.rotationNode=e.rotationNode,this.scaleNode=e.scaleNode,super.copy(e)}get sizeAttenuation(){return this._useSizeAttenuation}set sizeAttenuation(e){this._useSizeAttenuation!==e&&(this._useSizeAttenuation=e,this.needsUpdate=!0)}}class Ag extends Eh{constructor(){super(),this.shadowNode=Bi(1).toVar("shadowMask")}direct({shadowMask:e}){this.shadowNode.mulAssign(e)}finish(e){dn.a.mulAssign(this.shadowNode.oneMinus()),e.outgoingLight.rgb.assign(dn.rgb)}}const Rg=new oe;class Cg extends sh{static get type(){return"ShadowNodeMaterial"}constructor(e){super(),this.isShadowNodeMaterial=!0,this.lights=!0,this.setDefaultValues(Rg),this.setValues(e)}setupLightingModel(){return new Ag}}const Eg=Ai((({texture:e,uv:t})=>{const r=1e-4,s=Oi().toVar();return Ei(t.x.lessThan(r),(()=>{s.assign(Oi(1,0,0))})).ElseIf(t.y.lessThan(r),(()=>{s.assign(Oi(0,1,0))})).ElseIf(t.z.lessThan(r),(()=>{s.assign(Oi(0,0,1))})).ElseIf(t.x.greaterThan(.9999),(()=>{s.assign(Oi(-1,0,0))})).ElseIf(t.y.greaterThan(.9999),(()=>{s.assign(Oi(0,-1,0))})).ElseIf(t.z.greaterThan(.9999),(()=>{s.assign(Oi(0,0,-1))})).Else((()=>{const r=.01,i=e.sample(t.add(Oi(-.01,0,0))).r.sub(e.sample(t.add(Oi(r,0,0))).r),n=e.sample(t.add(Oi(0,-.01,0))).r.sub(e.sample(t.add(Oi(0,r,0))).r),o=e.sample(t.add(Oi(0,0,-.01))).r.sub(e.sample(t.add(Oi(0,0,r))).r);s.assign(Oi(i,n,o))})),s.normalize()}));class wg extends Au{static get type(){return"Texture3DNode"}constructor(e,t=null,r=null){super(e,t,r),this.isTexture3DNode=!0}getInputType(){return"texture3D"}getDefaultUV(){return Oi(.5,.5,.5)}setUpdateMatrix(){}setupUV(e,t){const r=this.value;return!e.isFlipY()||!0!==r.isRenderTargetTexture&&!0!==r.isFramebufferTexture||(t=this.sampler?t.flipY():t.setY(Fi(vu(this,this.levelNode).y).sub(t.y).sub(1))),t}generateUV(e,t){return t.build(e,"vec3")}normal(e){return Eg({texture:this,uv:e})}}const Mg=Ni(wg);class Bg extends sh{static get type(){return"VolumeNodeMaterial"}constructor(t){super(),this.isVolumeNodeMaterial=!0,this.base=new e(16777215),this.map=null,this.steps=100,this.testNode=null,this.setValues(t)}setup(e){const t=Mg(this.map,null,0),r=Ai((({orig:e,dir:t})=>{const r=Oi(-.5),s=Oi(.5),i=t.reciprocal(),n=r.sub(e).mul(i),o=s.sub(e).mul(i),a=Qo(n,o),u=Zo(n,o),l=Zo(a.x,Zo(a.y,a.z)),d=Qo(u.x,Qo(u.y,u.z));return Ii(l,d)}));this.fragmentNode=Ai((()=>{const e=Ia(Oi(Xu.mul($i(Iu,1)))),s=Ia(el.sub(e)).normalize(),i=Ii(r({orig:e,dir:s})).toVar();i.x.greaterThan(i.y).discard(),i.assign(Ii(Zo(i.x,0),i.y));const n=Oi(e.add(i.x.mul(s))).toVar(),o=Oi(s.abs().reciprocal()).toVar(),a=Bi(Qo(o.x,Qo(o.y,o.z))).toVar("delta");a.divAssign(Ll("steps","float"));const u=$i(Ll("base","color"),0).toVar();return cc({type:"float",start:i.x,end:i.y,update:"+= delta"},(()=>{const e=un("float","d").assign(t.sample(n.add(.5)).r);null!==this.testNode?this.testNode({map:t,mapValue:e,probe:n,finalColor:u}).append():(u.a.assign(1),hc()),n.addAssign(s.mul(a))})),u.a.equal(0).discard(),$i(u)}))(),super.setup(e)}}class Fg{constructor(e,t){this.nodes=e,this.info=t,this._context=self,this._animationLoop=null,this._requestId=null}start(){const e=(t,r)=>{this._requestId=this._context.requestAnimationFrame(e),!0===this.info.autoReset&&this.info.reset(),this.nodes.nodeFrame.update(),this.info.frame=this.nodes.nodeFrame.frameId,null!==this._animationLoop&&this._animationLoop(t,r)};e()}stop(){this._context.cancelAnimationFrame(this._requestId),this._requestId=null}setAnimationLoop(e){this._animationLoop=e}setContext(e){this._context=e}dispose(){this.stop()}}class Ug{constructor(){this.weakMap=new WeakMap}get(e){let t=this.weakMap;for(let r=0;r{this.dispose()},this.material.addEventListener("dispose",this.onMaterialDispose)}updateClipping(e){this.clippingContext=e}get clippingNeedsUpdate(){return null!==this.clippingContext&&this.clippingContext.cacheKey!==this.clippingContextCacheKey&&(this.clippingContextCacheKey=this.clippingContext.cacheKey,!0)}get hardwareClippingPlanes(){return!0===this.material.hardwareClipping?this.clippingContext.unionClippingCount:0}getNodeBuilderState(){return this._nodeBuilderState||(this._nodeBuilderState=this._nodes.getForRender(this))}getMonitor(){return this._monitor||(this._monitor=this.getNodeBuilderState().monitor)}getBindings(){return this._bindings||(this._bindings=this.getNodeBuilderState().createBindings())}getIndex(){return this._geometries.getIndex(this)}getIndirect(){return this._geometries.getIndirect(this)}getChainArray(){return[this.object,this.material,this.context,this.lightsNode]}setGeometry(e){this.geometry=e,this.attributes=null}getAttributes(){if(null!==this.attributes)return this.attributes;const e=this.getNodeBuilderState().nodeAttributes,t=this.geometry,r=[],s=new Set;for(const i of e){const e=i.node&&i.node.attribute?i.node.attribute:t.getAttribute(i.name);if(void 0===e)continue;r.push(e);const n=e.isInterleavedBufferAttribute?e.data:e;s.add(n)}return this.attributes=r,this.vertexBuffers=Array.from(s.values()),r}getVertexBuffers(){return null===this.vertexBuffers&&this.getAttributes(),this.vertexBuffers}getDrawParameters(){const{object:e,material:t,geometry:r,group:s,drawRange:i}=this,n=this.drawParams||(this.drawParams={vertexCount:0,firstVertex:0,instanceCount:0,firstInstance:0}),o=this.getIndex(),a=null!==o,u=r.isInstancedBufferGeometry?r.instanceCount:e.count>1?e.count:1;if(0===u)return null;if(n.instanceCount=u,!0===e.isBatchedMesh)return n;let l=1;!0!==t.wireframe||e.isPoints||e.isLineSegments||e.isLine||e.isLineLoop||(l=2);let d=i.start*l,c=(i.start+i.count)*l;null!==s&&(d=Math.max(d,s.start*l),c=Math.min(c,(s.start+s.count)*l));const h=r.attributes.position;let p=1/0;a?p=o.count:null!=h&&(p=h.count),d=Math.max(d,0),c=Math.min(c,p);const g=c-d;return g<0||g===1/0?null:(n.vertexCount=g,n.firstVertex=d,n)}getGeometryCacheKey(){const{geometry:e}=this;let t="";for(const r of Object.keys(e.attributes).sort()){const s=e.attributes[r];t+=r+",",s.data&&(t+=s.data.stride+","),s.offset&&(t+=s.offset+","),s.itemSize&&(t+=s.itemSize+","),s.normalized&&(t+="n,")}return e.index&&(t+="index,"),t}getMaterialCacheKey(){const{object:e,material:t}=this;let r=t.customProgramCacheKey();for(const e of function(e){const t=Object.keys(e);let r=Object.getPrototypeOf(e);for(;r;){const e=Object.getOwnPropertyDescriptors(r);for(const r in e)if(void 0!==e[r]){const s=e[r];s&&"function"==typeof s.get&&t.push(r)}r=Object.getPrototypeOf(r)}return t}(t)){if(/^(is[A-Z]|_)|^(visible|version|uuid|name|opacity|userData)$/.test(e))continue;const s=t[e];let i;if(null!==s){const e=typeof s;"number"===e?i=0!==s?"1":"0":"object"===e?(i="{",s.isTexture&&(i+=s.mapping),i+="}"):i=String(s)}else i=String(s);r+=i+","}return r+=this.clippingContextCacheKey+",",e.geometry&&(r+=this.getGeometryCacheKey()),e.skeleton&&(r+=e.skeleton.bones.length+","),e.morphTargetInfluences&&(r+=e.morphTargetInfluences.length+","),e.isBatchedMesh&&(r+=e._matricesTexture.uuid+",",null!==e._colorsTexture&&(r+=e._colorsTexture.uuid+",")),e.count>1&&(r+=e.uuid+","),r+=e.receiveShadow+",",ls(r)}get needsGeometryUpdate(){return this.geometry.id!==this.object.geometry.id}get needsUpdate(){return this.initialNodesCacheKey!==this.getDynamicCacheKey()||this.clippingNeedsUpdate}getDynamicCacheKey(){let e=this._nodes.getCacheKey(this.scene,this.lightsNode);return this.object.receiveShadow&&(e+=1),e}getCacheKey(){return this.getMaterialCacheKey()+this.getDynamicCacheKey()}dispose(){this.material.removeEventListener("dispose",this.onMaterialDispose),this.onDispose()}}const Dg=[];class Lg{constructor(e,t,r,s,i,n){this.renderer=e,this.nodes=t,this.geometries=r,this.pipelines=s,this.bindings=i,this.info=n,this.chainMaps={}}get(e,t,r,s,i,n,o,a){const u=this.getChainMap(a);Dg[0]=e,Dg[1]=t,Dg[2]=n,Dg[3]=i;let l=u.get(Dg);return void 0===l?(l=this.createRenderObject(this.nodes,this.geometries,this.renderer,e,t,r,s,i,n,o,a),u.set(Dg,l)):(l.updateClipping(o),l.needsGeometryUpdate&&l.setGeometry(e.geometry),(l.version!==t.version||l.needsUpdate)&&(l.initialCacheKey!==l.getCacheKey()?(l.dispose(),l=this.get(e,t,r,s,i,n,o,a)):l.version=t.version)),Dg.length=0,l}getChainMap(e="default"){return this.chainMaps[e]||(this.chainMaps[e]=new Ug)}dispose(){this.chainMaps={}}createRenderObject(e,t,r,s,i,n,o,a,u,l,d){const c=this.getChainMap(d),h=new Ig(e,t,r,s,i,n,o,a,u,l);return h.onDispose=()=>{this.pipelines.delete(h),this.bindings.delete(h),this.nodes.delete(h),c.delete(h.getChainArray())},h}}class Vg{constructor(){this.data=new WeakMap}get(e){let t=this.data.get(e);return void 0===t&&(t={},this.data.set(e,t)),t}delete(e){let t=null;return this.data.has(e)&&(t=this.data.get(e),this.data.delete(e)),t}has(e){return this.data.has(e)}dispose(){this.data=new WeakMap}}const Og=1,Gg=2,kg=3,zg=4,$g=16;class Hg extends Vg{constructor(e){super(),this.backend=e}delete(e){const t=super.delete(e);return void 0!==t&&this.backend.destroyAttribute(e),t}update(e,t){const r=this.get(e);if(void 0===r.version)t===Og?this.backend.createAttribute(e):t===Gg?this.backend.createIndexAttribute(e):t===kg?this.backend.createStorageAttribute(e):t===zg&&this.backend.createIndirectStorageAttribute(e),r.version=this._getBufferAttribute(e).version;else{const t=this._getBufferAttribute(e);(r.version=0;--t)if(e[t]>=65535)return!0;return!1}(t)?ae:ue)(t,1);return i.version=Wg(e),i}class qg extends Vg{constructor(e,t){super(),this.attributes=e,this.info=t,this.wireframes=new WeakMap,this.attributeCall=new WeakMap}has(e){const t=e.geometry;return super.has(t)&&!0===this.get(t).initialized}updateForRender(e){!1===this.has(e)&&this.initGeometry(e),this.updateAttributes(e)}initGeometry(e){const t=e.geometry;this.get(t).initialized=!0,this.info.memory.geometries++;const r=()=>{this.info.memory.geometries--;const s=t.index,i=e.getAttributes();null!==s&&this.attributes.delete(s);for(const e of i)this.attributes.delete(e);const n=this.wireframes.get(t);void 0!==n&&this.attributes.delete(n),t.removeEventListener("dispose",r)};t.addEventListener("dispose",r)}updateAttributes(e){const t=e.getAttributes();for(const e of t)e.isStorageBufferAttribute||e.isStorageInstancedBufferAttribute?this.updateAttribute(e,kg):this.updateAttribute(e,Og);const r=this.getIndex(e);null!==r&&this.updateAttribute(r,Gg);const s=e.geometry.indirect;null!==s&&this.updateAttribute(s,zg)}updateAttribute(e,t){const r=this.info.render.calls;e.isInterleavedBufferAttribute?void 0===this.attributeCall.get(e)?(this.attributes.update(e,t),this.attributeCall.set(e,r)):this.attributeCall.get(e.data)!==r&&(this.attributes.update(e,t),this.attributeCall.set(e.data,r),this.attributeCall.set(e,r)):this.attributeCall.get(e)!==r&&(this.attributes.update(e,t),this.attributeCall.set(e,r))}getIndirect(e){return e.geometry.indirect}getIndex(e){const{geometry:t,material:r}=e;let s=t.index;if(!0===r.wireframe){const e=this.wireframes;let r=e.get(t);void 0===r?(r=jg(t),e.set(t,r)):r.version!==Wg(t)&&(this.attributes.delete(r),r=jg(t),e.set(t,r)),s=r}return s}}class Kg{constructor(){this.autoReset=!0,this.frame=0,this.calls=0,this.render={calls:0,frameCalls:0,drawCalls:0,triangles:0,points:0,lines:0,timestamp:0,previousFrameCalls:0,timestampCalls:0},this.compute={calls:0,frameCalls:0,timestamp:0,previousFrameCalls:0,timestampCalls:0},this.memory={geometries:0,textures:0}}update(e,t,r){this.render.drawCalls++,e.isMesh||e.isSprite?this.render.triangles+=r*(t/3):e.isPoints?this.render.points+=r*t:e.isLineSegments?this.render.lines+=r*(t/2):e.isLine?this.render.lines+=r*(t-1):console.error("THREE.WebGPUInfo: Unknown object type.")}updateTimestamp(e,t){0===this[e].timestampCalls&&(this[e].timestamp=0),this[e].timestamp+=t,this[e].timestampCalls++,this[e].timestampCalls>=this[e].previousFrameCalls&&(this[e].timestampCalls=0)}reset(){const e=this.render.frameCalls;this.render.previousFrameCalls=e;const t=this.compute.frameCalls;this.compute.previousFrameCalls=t,this.render.drawCalls=0,this.render.frameCalls=0,this.compute.frameCalls=0,this.render.triangles=0,this.render.points=0,this.render.lines=0}dispose(){this.reset(),this.calls=0,this.render.calls=0,this.compute.calls=0,this.render.timestamp=0,this.compute.timestamp=0,this.memory.geometries=0,this.memory.textures=0}}class Xg{constructor(e){this.cacheKey=e,this.usedTimes=0}}class Yg extends Xg{constructor(e,t,r){super(e),this.vertexProgram=t,this.fragmentProgram=r}}class Qg extends Xg{constructor(e,t){super(e),this.computeProgram=t,this.isComputePipeline=!0}}let Zg=0;class Jg{constructor(e,t,r,s=null,i=null){this.id=Zg++,this.code=e,this.stage=t,this.name=r,this.transforms=s,this.attributes=i,this.usedTimes=0}}class em extends Vg{constructor(e,t){super(),this.backend=e,this.nodes=t,this.bindings=null,this.caches=new Map,this.programs={vertex:new Map,fragment:new Map,compute:new Map}}getForCompute(e,t){const{backend:r}=this,s=this.get(e);if(this._needsComputeUpdate(e)){const i=s.pipeline;i&&(i.usedTimes--,i.computeProgram.usedTimes--);const n=this.nodes.getForCompute(e);let o=this.programs.compute.get(n.computeShader);void 0===o&&(i&&0===i.computeProgram.usedTimes&&this._releaseProgram(i.computeProgram),o=new Jg(n.computeShader,"compute",e.name,n.transforms,n.nodeAttributes),this.programs.compute.set(n.computeShader,o),r.createProgram(o));const a=this._getComputeCacheKey(e,o);let u=this.caches.get(a);void 0===u&&(i&&0===i.usedTimes&&this._releasePipeline(i),u=this._getComputePipeline(e,o,a,t)),u.usedTimes++,o.usedTimes++,s.version=e.version,s.pipeline=u}return s.pipeline}getForRender(e,t=null){const{backend:r}=this,s=this.get(e);if(this._needsRenderUpdate(e)){const i=s.pipeline;i&&(i.usedTimes--,i.vertexProgram.usedTimes--,i.fragmentProgram.usedTimes--);const n=e.getNodeBuilderState(),o=e.material?e.material.name:"";let a=this.programs.vertex.get(n.vertexShader);void 0===a&&(i&&0===i.vertexProgram.usedTimes&&this._releaseProgram(i.vertexProgram),a=new Jg(n.vertexShader,"vertex",o),this.programs.vertex.set(n.vertexShader,a),r.createProgram(a));let u=this.programs.fragment.get(n.fragmentShader);void 0===u&&(i&&0===i.fragmentProgram.usedTimes&&this._releaseProgram(i.fragmentProgram),u=new Jg(n.fragmentShader,"fragment",o),this.programs.fragment.set(n.fragmentShader,u),r.createProgram(u));const l=this._getRenderCacheKey(e,a,u);let d=this.caches.get(l);void 0===d?(i&&0===i.usedTimes&&this._releasePipeline(i),d=this._getRenderPipeline(e,a,u,l,t)):e.pipeline=d,d.usedTimes++,a.usedTimes++,u.usedTimes++,s.pipeline=d}return s.pipeline}delete(e){const t=this.get(e).pipeline;return t&&(t.usedTimes--,0===t.usedTimes&&this._releasePipeline(t),t.isComputePipeline?(t.computeProgram.usedTimes--,0===t.computeProgram.usedTimes&&this._releaseProgram(t.computeProgram)):(t.fragmentProgram.usedTimes--,t.vertexProgram.usedTimes--,0===t.vertexProgram.usedTimes&&this._releaseProgram(t.vertexProgram),0===t.fragmentProgram.usedTimes&&this._releaseProgram(t.fragmentProgram))),super.delete(e)}dispose(){super.dispose(),this.caches=new Map,this.programs={vertex:new Map,fragment:new Map,compute:new Map}}updateForRender(e){this.getForRender(e)}_getComputePipeline(e,t,r,s){r=r||this._getComputeCacheKey(e,t);let i=this.caches.get(r);return void 0===i&&(i=new Qg(r,t),this.caches.set(r,i),this.backend.createComputePipeline(i,s)),i}_getRenderPipeline(e,t,r,s,i){s=s||this._getRenderCacheKey(e,t,r);let n=this.caches.get(s);return void 0===n&&(n=new Yg(s,t,r),this.caches.set(s,n),e.pipeline=n,this.backend.createRenderPipeline(e,i)),n}_getComputeCacheKey(e,t){return e.id+","+t.id}_getRenderCacheKey(e,t,r){return t.id+","+r.id+","+this.backend.getRenderCacheKey(e)}_releasePipeline(e){this.caches.delete(e.cacheKey)}_releaseProgram(e){const t=e.code,r=e.stage;this.programs[r].delete(t)}_needsComputeUpdate(e){const t=this.get(e);return void 0===t.pipeline||t.version!==e.version}_needsRenderUpdate(e){return void 0===this.get(e).pipeline||this.backend.needsRenderUpdate(e)}}class tm extends Vg{constructor(e,t,r,s,i,n){super(),this.backend=e,this.textures=r,this.pipelines=i,this.attributes=s,this.nodes=t,this.info=n,this.pipelines.bindings=this}getForRender(e){const t=e.getBindings();for(const e of t){const r=this.get(e);void 0===r.bindGroup&&(this._init(e),this.backend.createBindings(e,t,0),r.bindGroup=e)}return t}getForCompute(e){const t=this.nodes.getForCompute(e).bindings;for(const e of t){const r=this.get(e);void 0===r.bindGroup&&(this._init(e),this.backend.createBindings(e,t,0),r.bindGroup=e)}return t}updateForCompute(e){this._updateBindings(this.getForCompute(e))}updateForRender(e){this._updateBindings(this.getForRender(e))}_updateBindings(e){for(const t of e)this._update(t,e)}_init(e){for(const t of e.bindings)if(t.isSampledTexture)this.textures.updateTexture(t.texture);else if(t.isStorageBuffer){const e=t.attribute,r=e.isIndirectStorageBufferAttribute?zg:kg;this.attributes.update(e,r)}}_update(e,t){const{backend:r}=this;let s=!1,i=!0,n=0,o=0;for(const t of e.bindings){if(t.isNodeUniformsGroup){if(!1===this.nodes.updateGroup(t))continue}if(t.isUniformBuffer){t.update()&&r.updateBinding(t)}else if(t.isSampler)t.update();else if(t.isSampledTexture){const e=this.textures.get(t.texture);t.needsBindingsUpdate(e.generation)&&(s=!0);const a=t.update(),u=t.texture;a&&this.textures.updateTexture(u);const l=r.get(u);if(void 0!==l.externalTexture||e.isDefaultTexture?i=!1:(n=10*n+u.id,o+=u.version),!0===r.isWebGPUBackend&&void 0===l.texture&&void 0===l.externalTexture&&(console.error("Bindings._update: binding should be available:",t,a,u,t.textureNode.value,s),this.textures.updateTexture(u),s=!0),!0===u.isStorageTexture){const e=this.get(u);!0===t.store?e.needsMipmap=!0:this.textures.needsMipmaps(u)&&!0===e.needsMipmap&&(this.backend.generateMipmaps(u),e.needsMipmap=!1)}}}!0===s&&this.backend.updateBindings(e,t,i?n:0,o)}}function rm(e,t){return e.groupOrder!==t.groupOrder?e.groupOrder-t.groupOrder:e.renderOrder!==t.renderOrder?e.renderOrder-t.renderOrder:e.material.id!==t.material.id?e.material.id-t.material.id:e.z!==t.z?e.z-t.z:e.id-t.id}function sm(e,t){return e.groupOrder!==t.groupOrder?e.groupOrder-t.groupOrder:e.renderOrder!==t.renderOrder?e.renderOrder-t.renderOrder:e.z!==t.z?t.z-e.z:e.id-t.id}function im(e){return(e.transmission>0||e.transmissionNode)&&e.side===le&&!1===e.forceSinglePass}class nm{constructor(e,t,r){this.renderItems=[],this.renderItemsIndex=0,this.opaque=[],this.transparentDoublePass=[],this.transparent=[],this.bundles=[],this.lightsNode=e.getNode(t,r),this.lightsArray=[],this.scene=t,this.camera=r,this.occlusionQueryCount=0}begin(){return this.renderItemsIndex=0,this.opaque.length=0,this.transparentDoublePass.length=0,this.transparent.length=0,this.bundles.length=0,this.lightsArray.length=0,this.occlusionQueryCount=0,this}getNextRenderItem(e,t,r,s,i,n,o){let a=this.renderItems[this.renderItemsIndex];return void 0===a?(a={id:e.id,object:e,geometry:t,material:r,groupOrder:s,renderOrder:e.renderOrder,z:i,group:n,clippingContext:o},this.renderItems[this.renderItemsIndex]=a):(a.id=e.id,a.object=e,a.geometry=t,a.material=r,a.groupOrder=s,a.renderOrder=e.renderOrder,a.z=i,a.group=n,a.clippingContext=o),this.renderItemsIndex++,a}push(e,t,r,s,i,n,o){const a=this.getNextRenderItem(e,t,r,s,i,n,o);!0===e.occlusionTest&&this.occlusionQueryCount++,!0===r.transparent||r.transmission>0?(im(r)&&this.transparentDoublePass.push(a),this.transparent.push(a)):this.opaque.push(a)}unshift(e,t,r,s,i,n,o){const a=this.getNextRenderItem(e,t,r,s,i,n,o);!0===r.transparent||r.transmission>0?(im(r)&&this.transparentDoublePass.unshift(a),this.transparent.unshift(a)):this.opaque.unshift(a)}pushBundle(e){this.bundles.push(e)}pushLight(e){this.lightsArray.push(e)}sort(e,t){this.opaque.length>1&&this.opaque.sort(e||rm),this.transparentDoublePass.length>1&&this.transparentDoublePass.sort(t||sm),this.transparent.length>1&&this.transparent.sort(t||sm)}finish(){this.lightsNode.setLights(this.lightsArray);for(let e=this.renderItemsIndex,t=this.renderItems.length;e>t,u=o.height>>t;let l=e.depthTexture||i[t];const d=!0===e.depthBuffer||!0===e.stencilBuffer;let c=!1;void 0===l&&d&&(l=new B,l.format=e.stencilBuffer?ce:he,l.type=e.stencilBuffer?pe:b,l.image.width=a,l.image.height=u,i[t]=l),r.width===o.width&&o.height===r.height||(c=!0,l&&(l.needsUpdate=!0,l.image.width=a,l.image.height=u)),r.width=o.width,r.height=o.height,r.textures=n,r.depthTexture=l||null,r.depth=e.depthBuffer,r.stencil=e.stencilBuffer,r.renderTarget=e,r.sampleCount!==s&&(c=!0,l&&(l.needsUpdate=!0),r.sampleCount=s);const h={sampleCount:s};for(let e=0;e{e.removeEventListener("dispose",t);for(let e=0;e0){const s=e.image;if(void 0===s)console.warn("THREE.Renderer: Texture marked for update but image is undefined.");else if(!1===s.complete)console.warn("THREE.Renderer: Texture marked for update but image is incomplete.");else{if(e.images){const r=[];for(const t of e.images)r.push(t);t.images=r}else t.image=s;void 0!==r.isDefaultTexture&&!0!==r.isDefaultTexture||(i.createTexture(e,t),r.isDefaultTexture=!1,r.generation=e.version),!0===e.source.dataReady&&i.updateTexture(e,t),t.needsMipmaps&&0===e.mipmaps.length&&i.generateMipmaps(e)}}else i.createDefaultTexture(e),r.isDefaultTexture=!0,r.generation=e.version}if(!0!==r.initialized){r.initialized=!0,r.generation=e.version,this.info.memory.textures++;const t=()=>{e.removeEventListener("dispose",t),this._destroyTexture(e),this.info.memory.textures--};e.addEventListener("dispose",t)}r.version=e.version}getSize(e,t=mm){let r=e.images?e.images[0]:e.image;return r?(void 0!==r.image&&(r=r.image),t.width=r.width||1,t.height=r.height||1,t.depth=e.isCubeTexture?6:r.depth||1):t.width=t.height=t.depth=1,t}getMipLevels(e,t,r){let s;return s=e.isCompressedTexture?e.mipmaps?e.mipmaps.length:1:Math.floor(Math.log2(Math.max(t,r)))+1,s}needsMipmaps(e){return this.isEnvironmentTexture(e)||!0===e.isCompressedTexture||e.generateMipmaps}isEnvironmentTexture(e){const t=e.mapping;return t===j||t===q||t===_||t===v}_destroyTexture(e){this.backend.destroySampler(e),this.backend.destroyTexture(e),this.delete(e)}}class ym extends e{constructor(e,t,r,s=1){super(e,t,r),this.a=s}set(e,t,r,s=1){return this.a=s,super.set(e,t,r)}copy(e){return void 0!==e.a&&(this.a=e.a),super.copy(e)}clone(){return new this.constructor(this.r,this.g,this.b,this.a)}}class bm extends an{static get type(){return"ParameterNode"}constructor(e,t=null){super(e,t),this.isParameterNode=!0}getHash(){return this.uuid}generate(){return this.name}}class xm extends Ps{static get type(){return"StackNode"}constructor(e=null){super(),this.nodes=[],this.outputNode=null,this.parent=e,this._currentCond=null,this.isStackNode=!0}getNodeType(e){return this.outputNode?this.outputNode.getNodeType(e):"void"}add(e){return this.nodes.push(e),this}If(e,t){const r=new xi(t);return this._currentCond=Ra(e,r),this.add(this._currentCond)}ElseIf(e,t){const r=new xi(t),s=Ra(e,r);return this._currentCond.elseNode=s,this._currentCond=s,this}Else(e){return this._currentCond.elseNode=new xi(e),this}build(e,...t){const r=Ci();Ri(this);for(const t of this.nodes)t.build(e,"void");return Ri(r),this.outputNode?this.outputNode.build(e,...t):super.build(e,...t)}else(...e){return console.warn("TSL.StackNode: .else() has been renamed to .Else()."),this.Else(...e)}elseif(...e){return console.warn("TSL.StackNode: .elseif() has been renamed to .ElseIf()."),this.ElseIf(...e)}}const Tm=Ni(xm);class _m extends Ps{static get type(){return"OutputStructNode"}constructor(...e){super(),this.members=e,this.isOutputStructNode=!0}setup(e){super.setup(e);const t=this.members,r=[];for(let s=0;s{const t=e.toUint().mul(747796405).add(2891336453),r=t.shiftRight(t.shiftRight(28).add(4)).bitXor(t).mul(277803737);return r.shiftRight(22).bitXor(r).toFloat().mul(1/2**32)})),Cm=(e,t)=>oa(Wn(4,e.mul(Hn(1,e))),t),Em=Ai((([e])=>e.fract().sub(.5).abs())).setLayout({name:"tri",type:"float",inputs:[{name:"x",type:"float"}]}),wm=Ai((([e])=>Oi(Em(e.z.add(Em(e.y.mul(1)))),Em(e.z.add(Em(e.x.mul(1)))),Em(e.y.add(Em(e.x.mul(1))))))).setLayout({name:"tri3",type:"vec3",inputs:[{name:"p",type:"vec3"}]}),Mm=Ai((([e,t,r])=>{const s=Oi(e).toVar(),i=Bi(1.4).toVar(),n=Bi(0).toVar(),o=Oi(s).toVar();return cc({start:Bi(0),end:Bi(3),type:"float",condition:"<="},(()=>{const e=Oi(wm(o.mul(2))).toVar();s.addAssign(e.add(r.mul(Bi(.1).mul(t)))),o.mulAssign(1.8),i.mulAssign(1.5),s.mulAssign(1.2);const a=Bi(Em(s.z.add(Em(s.x.add(Em(s.y)))))).toVar();n.addAssign(a.div(i)),o.addAssign(.14)})),n})).setLayout({name:"triNoise3D",type:"float",inputs:[{name:"position",type:"vec3"},{name:"speed",type:"float"},{name:"time",type:"float"}]});class Bm extends Ps{static get type(){return"FunctionOverloadingNode"}constructor(e=[],...t){super(),this.functionNodes=e,this.parametersNodes=t,this._candidateFnCall=null,this.global=!0}getNodeType(){return this.functionNodes[0].shaderNode.layout.type}setup(e){const t=this.parametersNodes;let r=this._candidateFnCall;if(null===r){let s=null,i=-1;for(const r of this.functionNodes){const n=r.shaderNode.layout;if(null===n)throw new Error("FunctionOverloadingNode: FunctionNode must be a layout.");const o=n.inputs;if(t.length===o.length){let n=0;for(let r=0;ri&&(s=r,i=n)}}this._candidateFnCall=r=s(...t)}return r}}const Fm=Ni(Bm),Um=e=>(...t)=>Fm(e,...t),Pm=on(0).setGroup(rn).onRenderUpdate((e=>e.time)),Im=on(0).setGroup(rn).onRenderUpdate((e=>e.deltaTime)),Dm=on(0,"uint").setGroup(rn).onRenderUpdate((e=>e.frameId)),Lm=Ai((([e,t,r=Ii(.5)])=>vg(e.sub(r),t).add(r))),Vm=Ai((([e,t,r=Ii(.5)])=>{const s=e.sub(r),i=s.dot(s),n=i.mul(i).mul(t);return e.add(s.mul(n))})),Om=Ai((({position:e=null,horizontal:t=!0,vertical:r=!1})=>{let s;null!==e?(s=Hu.toVar(),s[3][0]=e.x,s[3][1]=e.y,s[3][2]=e.z):s=Hu;const i=Fu.mul(s);return yi(t)&&(i[0][0]=Hu[0].length(),i[0][1]=0,i[0][2]=0),yi(r)&&(i[1][0]=0,i[1][1]=Hu[1].length(),i[1][2]=0),i[2][0]=0,i[2][1]=0,i[2][2]=1,Mu.mul(i).mul(tl)})),Gm=Ai((([e=null])=>{const t=Yc();return Yc(zc(e)).sub(t).lessThan(0).select(Rc,e)}));class km extends Ps{static get type(){return"SpriteSheetUVNode"}constructor(e,t=Tu(),r=Bi(0)){super("vec2"),this.countNode=e,this.uvNode=t,this.frameNode=r}setup(){const{frameNode:e,uvNode:t,countNode:r}=this,{width:s,height:i}=r,n=e.mod(s.mul(i)).floor(),o=n.mod(s),a=i.sub(n.add(1).div(s).ceil()),u=r.reciprocal(),l=Ii(o,a);return t.add(l).mul(u)}}const zm=Ni(km);class $m extends Ps{static get type(){return"TriplanarTexturesNode"}constructor(e,t=null,r=null,s=Bi(1),i=tl,n=cl){super("vec4"),this.textureXNode=e,this.textureYNode=t,this.textureZNode=r,this.scaleNode=s,this.positionNode=i,this.normalNode=n}setup(){const{textureXNode:e,textureYNode:t,textureZNode:r,scaleNode:s,positionNode:i,normalNode:n}=this;let o=n.abs().normalize();o=o.div(o.dot(Oi(1)));const a=i.yz.mul(s),u=i.zx.mul(s),l=i.xy.mul(s),d=e.value,c=null!==t?t.value:d,h=null!==r?r.value:d,p=Ru(d,a).mul(o.x),g=Ru(c,u).mul(o.y),m=Ru(h,l).mul(o.z);return $n(p,g,m)}}const Hm=Ni($m),Wm=new fe,jm=new r,qm=new r,Km=new r,Xm=new n,Ym=new r(0,0,-1),Qm=new s,Zm=new r,Jm=new r,ef=new s,tf=new t,rf=new me,sf=Rc.flipX();rf.depthTexture=new B(1,1);let nf=!1;class of extends Au{static get type(){return"ReflectorNode"}constructor(e={}){super(e.defaultTexture||rf.texture,sf),this._reflectorBaseNode=e.reflector||new af(this,e),this._depthNode=null,this.setUpdateMatrix(!1)}get reflector(){return this._reflectorBaseNode}get target(){return this._reflectorBaseNode.target}getDepthNode(){if(null===this._depthNode){if(!0!==this._reflectorBaseNode.depth)throw new Error("THREE.ReflectorNode: Depth node can only be requested when the reflector is created with { depth: true }. ");this._depthNode=Ti(new of({defaultTexture:rf.depthTexture,reflector:this._reflectorBaseNode}))}return this._depthNode}setup(e){return e.object.isQuadMesh||this._reflectorBaseNode.build(e),super.setup(e)}clone(){const e=new this.constructor(this.reflectorNode);return e._reflectorBaseNode=this._reflectorBaseNode,e}}class af extends Ps{static get type(){return"ReflectorBaseNode"}constructor(e,t={}){super();const{target:r=new ye,resolution:s=1,generateMipmaps:i=!1,bounces:n=!0,depth:o=!1}=t;this.textureNode=e,this.target=r,this.resolution=s,this.generateMipmaps=i,this.bounces=n,this.depth=o,this.updateBeforeType=n?Rs.RENDER:Rs.FRAME,this.virtualCameras=new WeakMap,this.renderTargets=new WeakMap}_updateResolution(e,t){const r=this.resolution;t.getDrawingBufferSize(tf),e.setSize(Math.round(tf.width*r),Math.round(tf.height*r))}setup(e){return this._updateResolution(rf,e.renderer),super.setup(e)}getVirtualCamera(e){let t=this.virtualCameras.get(e);return void 0===t&&(t=e.clone(),this.virtualCameras.set(e,t)),t}getRenderTarget(e){let t=this.renderTargets.get(e);return void 0===t&&(t=new me(0,0,{type:be}),!0===this.generateMipmaps&&(t.texture.minFilter=xe,t.texture.generateMipmaps=!0),!0===this.depth&&(t.depthTexture=new B),this.renderTargets.set(e,t)),t}updateBefore(e){if(!1===this.bounces&&nf)return!1;nf=!0;const{scene:t,camera:r,renderer:s,material:i}=e,{target:n}=this,o=this.getVirtualCamera(r),a=this.getRenderTarget(o);if(s.getDrawingBufferSize(tf),this._updateResolution(a,s),qm.setFromMatrixPosition(n.matrixWorld),Km.setFromMatrixPosition(r.matrixWorld),Xm.extractRotation(n.matrixWorld),jm.set(0,0,1),jm.applyMatrix4(Xm),Zm.subVectors(qm,Km),Zm.dot(jm)>0)return;Zm.reflect(jm).negate(),Zm.add(qm),Xm.extractRotation(r.matrixWorld),Ym.set(0,0,-1),Ym.applyMatrix4(Xm),Ym.add(Km),Jm.subVectors(qm,Ym),Jm.reflect(jm).negate(),Jm.add(qm),o.coordinateSystem=r.coordinateSystem,o.position.copy(Zm),o.up.set(0,1,0),o.up.applyMatrix4(Xm),o.up.reflect(jm),o.lookAt(Jm),o.near=r.near,o.far=r.far,o.updateMatrixWorld(),o.projectionMatrix.copy(r.projectionMatrix),Wm.setFromNormalAndCoplanarPoint(jm,qm),Wm.applyMatrix4(o.matrixWorldInverse),Qm.set(Wm.normal.x,Wm.normal.y,Wm.normal.z,Wm.constant);const u=o.projectionMatrix;ef.x=(Math.sign(Qm.x)+u.elements[8])/u.elements[0],ef.y=(Math.sign(Qm.y)+u.elements[9])/u.elements[5],ef.z=-1,ef.w=(1+u.elements[10])/u.elements[14],Qm.multiplyScalar(1/Qm.dot(ef));u.elements[2]=Qm.x,u.elements[6]=Qm.y,u.elements[10]=s.coordinateSystem===l?Qm.z-0:Qm.z+1-0,u.elements[14]=Qm.w,this.textureNode.value=a.texture,!0===this.depth&&(this.textureNode.getDepthNode().value=a.depthTexture),i.visible=!1;const d=s.getRenderTarget(),c=s.getMRT(),h=s.autoClear;s.setMRT(null),s.setRenderTarget(a),s.autoClear=!0,s.render(t,o),s.setMRT(c),s.setRenderTarget(d),s.autoClear=h,i.visible=!0,nf=!1}}const uf=new Te(-1,1,1,-1,0,1);class lf extends _e{constructor(e=!1){super();const t=!1===e?[0,-1,0,1,2,1]:[0,2,0,0,2,0];this.setAttribute("position",new ve([-1,3,0,-1,-1,0,3,-1,0],3)),this.setAttribute("uv",new ve(t,2))}}const df=new lf;class cf extends k{constructor(e=null){super(df,e),this.camera=uf,this.isQuadMesh=!0}async renderAsync(e){return e.renderAsync(this,uf)}render(e){e.render(this,uf)}}const hf=new t;class pf extends Au{static get type(){return"RTTNode"}constructor(e,t=null,r=null,s={type:be}){const i=new me(t,r,s);super(i.texture,Tu()),this.node=e,this.width=t,this.height=r,this.pixelRatio=1,this.renderTarget=i,this.textureNeedsUpdate=!0,this.autoUpdate=!0,this._rttNode=null,this._quadMesh=new cf(new sh),this.updateBeforeType=Rs.RENDER}get autoSize(){return null===this.width}setup(e){return this._rttNode=this.node.context(e.getSharedContext()),this._quadMesh.material.name="RTT",this._quadMesh.material.needsUpdate=!0,super.setup(e)}setSize(e,t){this.width=e,this.height=t;const r=e*this.pixelRatio,s=t*this.pixelRatio;this.renderTarget.setSize(r,s),this.textureNeedsUpdate=!0}setPixelRatio(e){this.pixelRatio=e,this.setSize(this.width,this.height)}updateBefore({renderer:e}){if(!1===this.textureNeedsUpdate&&!1===this.autoUpdate)return;if(this.textureNeedsUpdate=!1,!0===this.autoSize){this.pixelRatio=e.getPixelRatio();const t=e.getSize(hf);this.setSize(t.width,t.height)}this._quadMesh.material.fragmentNode=this._rttNode;const t=e.getRenderTarget();e.setRenderTarget(this.renderTarget),this._quadMesh.render(e),e.setRenderTarget(t)}clone(){const e=new Au(this.value,this.uvNode,this.levelNode);return e.sampler=this.sampler,e.referenceNode=this,e}}const gf=(e,...t)=>Ti(new pf(Ti(e),...t)),mf=Ai((([e,t,r],s)=>{let i;s.renderer.coordinateSystem===l?(e=Ii(e.x,e.y.oneMinus()).mul(2).sub(1),i=$i(Oi(e,t),1)):i=$i(Oi(e.x,e.y.oneMinus(),t).mul(2).sub(1),1);const n=$i(r.mul(i));return n.xyz.div(n.w)})),ff=Ai((([e,t])=>{const r=t.mul($i(e,1)),s=r.xy.div(r.w).mul(.5).add(.5).toVar();return Ii(s.x,s.y.oneMinus())})),yf=Ai((([e,t,r])=>{const s=vu(Cu(t)),i=Di(e.mul(s)).toVar(),n=Cu(t,i).toVar(),o=Cu(t,i.sub(Di(2,0))).toVar(),a=Cu(t,i.sub(Di(1,0))).toVar(),u=Cu(t,i.add(Di(1,0))).toVar(),l=Cu(t,i.add(Di(2,0))).toVar(),d=Cu(t,i.add(Di(0,2))).toVar(),c=Cu(t,i.add(Di(0,1))).toVar(),h=Cu(t,i.sub(Di(0,1))).toVar(),p=Cu(t,i.sub(Di(0,2))).toVar(),g=Lo(Hn(Bi(2).mul(a).sub(o),n)).toVar(),m=Lo(Hn(Bi(2).mul(u).sub(l),n)).toVar(),f=Lo(Hn(Bi(2).mul(c).sub(d),n)).toVar(),y=Lo(Hn(Bi(2).mul(h).sub(p),n)).toVar(),b=mf(e,n,r).toVar(),x=g.lessThan(m).select(b.sub(mf(e.sub(Ii(Bi(1).div(s.x),0)),a,r)),b.negate().add(mf(e.add(Ii(Bi(1).div(s.x),0)),u,r))),T=f.lessThan(y).select(b.sub(mf(e.add(Ii(0,Bi(1).div(s.y))),c,r)),b.negate().add(mf(e.sub(Ii(0,Bi(1).div(s.y))),h,r)));return wo(na(x,T))}));class bf extends R{constructor(e,t,r=Float32Array){super(ArrayBuffer.isView(e)?e:new r(e*t),t),this.isStorageInstancedBufferAttribute=!0}}class xf extends Ne{constructor(e,t,r=Float32Array){super(ArrayBuffer.isView(e)?e:new r(e*t),t),this.isStorageBufferAttribute=!0}}class Tf extends Is{static get type(){return"StorageArrayElementNode"}constructor(e,t){super(e,t),this.isStorageArrayElementNode=!0}set storageBufferNode(e){this.node=e}get storageBufferNode(){return this.node}setup(e){return!1===e.isAvailable("storageBuffer")&&!0===this.node.isPBO&&e.setupPBO(this.node),super.setup(e)}generate(e,t){let r;const s=e.context.assign;if(r=!1===e.isAvailable("storageBuffer")?!0!==this.node.isPBO||!0===s||!this.node.value.isInstancedBufferAttribute&&"compute"===e.shaderStage?this.node.build(e):e.generatePBO(this):super.generate(e),!0!==s){const s=this.getNodeType(e);r=e.format(r,s,t)}return r}}const _f=Ni(Tf);class vf extends Cl{static get type(){return"StorageBufferNode"}constructor(e,t=null,r=0){null===t&&(e.isStorageBufferAttribute||e.isStorageInstancedBufferAttribute)&&(t=fs(e.itemSize),r=e.count),super(e,t,r),this.isStorageBufferNode=!0,this.access=Es.READ_WRITE,this.isAtomic=!1,this.isPBO=!1,this._attribute=null,this._varying=null,this.global=!0,!0!==e.isStorageBufferAttribute&&!0!==e.isStorageInstancedBufferAttribute&&(e.isInstancedBufferAttribute?e.isStorageInstancedBufferAttribute=!0:e.isStorageBufferAttribute=!0)}getHash(e){if(0===this.bufferCount){let t=e.globalCache.getData(this.value);return void 0===t&&(t={node:this},e.globalCache.setData(this.value,t)),t.node.uuid}return this.uuid}getInputType(){return this.value.isIndirectStorageBufferAttribute?"indirectStorageBuffer":"storageBuffer"}element(e){return _f(this,e)}setPBO(e){return this.isPBO=e,this}getPBO(){return this.isPBO}setAccess(e){return this.access=e,this}toReadOnly(){return this.setAccess(Es.READ_ONLY)}setAtomic(e){return this.isAtomic=e,this}toAtomic(){return this.setAtomic(!0)}getAttributeData(){return null===this._attribute&&(this._attribute=eu(this.value),this._varying=Ia(this._attribute)),{attribute:this._attribute,varying:this._varying}}getNodeType(e){if(e.isAvailable("storageBuffer")||e.isAvailable("indirectStorageBuffer"))return super.getNodeType(e);const{attribute:t}=this.getAttributeData();return t.getNodeType(e)}generate(e){if(e.isAvailable("storageBuffer")||e.isAvailable("indirectStorageBuffer"))return super.generate(e);const{attribute:t,varying:r}=this.getAttributeData(),s=r.build(e);return e.registerTransform(s,t),s}}const Nf=(e,t=null,r=0)=>Ti(new vf(e,t,r));class Sf extends bu{static get type(){return"VertexColorNode"}constructor(e=0){super(null,"vec4"),this.isVertexColorNode=!0,this.index=e}getAttributeName(){const e=this.index;return"color"+(e>0?e:"")}generate(e){const t=this.getAttributeName(e);let r;return r=!0===e.hasGeometryAttribute(t)?super.generate(e):e.generateConst(this.nodeType,new s(1,1,1,1)),r}serialize(e){super.serialize(e),e.index=this.index}deserialize(e){super.deserialize(e),this.index=e.index}}class Af extends Ps{static get type(){return"PointUVNode"}constructor(){super("vec2"),this.isPointUVNode=!0}generate(){return"vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y )"}}const Rf=Si(Af),Cf=new Ae,Ef=new n;class wf extends Ps{static get type(){return"SceneNode"}constructor(e=wf.BACKGROUND_BLURRINESS,t=null){super(),this.scope=e,this.scene=t}setup(e){const t=this.scope,r=null!==this.scene?this.scene:e.scene;let s;return t===wf.BACKGROUND_BLURRINESS?s=Pl("backgroundBlurriness","float",r):t===wf.BACKGROUND_INTENSITY?s=Pl("backgroundIntensity","float",r):t===wf.BACKGROUND_ROTATION?s=on("mat4").label("backgroundRotation").setGroup(rn).onRenderUpdate((()=>{const e=r.background;return null!==e&&e.isTexture&&e.mapping!==Se?(Cf.copy(r.backgroundRotation),Cf.x*=-1,Cf.y*=-1,Cf.z*=-1,Ef.makeRotationFromEuler(Cf)):Ef.identity(),Ef})):console.error("THREE.SceneNode: Unknown scope:",t),s}}wf.BACKGROUND_BLURRINESS="backgroundBlurriness",wf.BACKGROUND_INTENSITY="backgroundIntensity",wf.BACKGROUND_ROTATION="backgroundRotation";const Mf=Si(wf,wf.BACKGROUND_BLURRINESS),Bf=Si(wf,wf.BACKGROUND_INTENSITY),Ff=Si(wf,wf.BACKGROUND_ROTATION);class Uf extends Au{static get type(){return"StorageTextureNode"}constructor(e,t,r=null){super(e,t),this.storeNode=r,this.isStorageTextureNode=!0,this.access=Es.WRITE_ONLY}getInputType(){return"storageTexture"}setup(e){super.setup(e);e.getNodeProperties(this).storeNode=this.storeNode}setAccess(e){return this.access=e,this}generate(e,t){let r;return r=null!==this.storeNode?this.generateStore(e):super.generate(e,t),r}toReadWrite(){return this.setAccess(Es.READ_WRITE)}toReadOnly(){return this.setAccess(Es.READ_ONLY)}toWriteOnly(){return this.setAccess(Es.WRITE_ONLY)}generateStore(e){const t=e.getNodeProperties(this),{uvNode:r,storeNode:s}=t,i=super.generate(e,"property"),n=r.build(e,"uvec2"),o=s.build(e,"vec4"),a=e.generateTextureStore(e,i,n,o);e.addLineFlowCode(a,this)}}const Pf=Ni(Uf);class If extends Ul{static get type(){return"UserDataNode"}constructor(e,t,r=null){super(e,t,r),this.userData=r}updateReference(e){return this.reference=null!==this.userData?this.userData:e.object.userData,this.reference}}const Df=new WeakMap;class Lf extends Ls{static get type(){return"VelocityNode"}constructor(){super("vec2"),this.projectionMatrix=null,this.updateType=Rs.OBJECT,this.updateAfterType=Rs.OBJECT,this.previousModelWorldMatrix=on(new n),this.previousProjectionMatrix=on(new n).setGroup(rn),this.previousCameraViewMatrix=on(new n)}setProjectionMatrix(e){this.projectionMatrix=e}update({frameId:e,camera:t,object:r}){const s=Of(r);this.previousModelWorldMatrix.value.copy(s);const i=Vf(t);i.frameId!==e&&(i.frameId=e,void 0===i.previousProjectionMatrix?(i.previousProjectionMatrix=new n,i.previousCameraViewMatrix=new n,i.currentProjectionMatrix=new n,i.currentCameraViewMatrix=new n,i.previousProjectionMatrix.copy(this.projectionMatrix||t.projectionMatrix),i.previousCameraViewMatrix.copy(t.matrixWorldInverse)):(i.previousProjectionMatrix.copy(i.currentProjectionMatrix),i.previousCameraViewMatrix.copy(i.currentCameraViewMatrix)),i.currentProjectionMatrix.copy(this.projectionMatrix||t.projectionMatrix),i.currentCameraViewMatrix.copy(t.matrixWorldInverse),this.previousProjectionMatrix.value.copy(i.previousProjectionMatrix),this.previousCameraViewMatrix.value.copy(i.previousCameraViewMatrix))}updateAfter({object:e}){Of(e).copy(e.matrixWorld)}setup(){const e=null===this.projectionMatrix?Mu:on(this.projectionMatrix),t=this.previousCameraViewMatrix.mul(this.previousModelWorldMatrix),r=e.mul(Yu).mul(tl),s=this.previousProjectionMatrix.mul(t).mul(rl),i=r.xy.div(r.w),n=s.xy.div(s.w);return Hn(i,n)}}function Vf(e){let t=Df.get(e);return void 0===t&&(t={},Df.set(e,t)),t}function Of(e,t=0){const r=Vf(e);let s=r[t];return void 0===s&&(r[t]=s=new n),s}const Gf=Si(Lf),kf=Ai((([e,t])=>Qo(1,e.oneMinus().div(t)).oneMinus())).setLayout({name:"blendBurn",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),zf=Ai((([e,t])=>Qo(e.div(t.oneMinus()),1))).setLayout({name:"blendDodge",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),$f=Ai((([e,t])=>e.oneMinus().mul(t.oneMinus()).oneMinus())).setLayout({name:"blendScreen",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),Hf=Ai((([e,t])=>pa(e.mul(2).mul(t),e.oneMinus().mul(2).mul(t.oneMinus()).oneMinus(),ea(.5,e)))).setLayout({name:"blendOverlay",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),Wf=Ai((([e,t])=>{const r=t.a.add(e.a.mul(t.a.oneMinus()));return $i(t.rgb.mul(t.a).add(e.rgb.mul(e.a).mul(t.a.oneMinus())).div(r),r)})).setLayout({name:"blendColor",type:"vec4",inputs:[{name:"base",type:"vec4"},{name:"blend",type:"vec4"}]}),jf=Ai((([e])=>Yf(e.rgb))),qf=Ai((([e,t=Bi(1)])=>t.mix(Yf(e.rgb),e.rgb))),Kf=Ai((([e,t=Bi(1)])=>{const r=$n(e.r,e.g,e.b).div(3),s=e.r.max(e.g.max(e.b)),i=s.sub(r).mul(t).mul(-3);return pa(e.rgb,s,i)})),Xf=Ai((([e,t=Bi(1)])=>{const r=Oi(.57735,.57735,.57735),s=t.cos();return Oi(e.rgb.mul(s).add(r.cross(e.rgb).mul(t.sin()).add(r.mul(ia(r,e.rgb).mul(s.oneMinus())))))})),Yf=(e,t=Oi(d.getLuminanceCoefficients(new r)))=>ia(e,t),Qf=Ai((([e,t=Oi(1),s=Oi(0),i=Oi(1),n=Bi(1),o=Oi(d.getLuminanceCoefficients(new r,Re))])=>{const a=e.rgb.dot(Oi(o)),u=Zo(e.rgb.mul(t).add(s),0).toVar(),l=u.pow(i).toVar();return Ei(u.r.greaterThan(0),(()=>{u.r.assign(l.r)})),Ei(u.g.greaterThan(0),(()=>{u.g.assign(l.g)})),Ei(u.b.greaterThan(0),(()=>{u.b.assign(l.b)})),u.assign(a.add(u.sub(a).mul(n))),$i(u.rgb,e.a)}));class Zf extends Ls{static get type(){return"PosterizeNode"}constructor(e,t){super(),this.sourceNode=e,this.stepsNode=t}setup(){const{sourceNode:e,stepsNode:t}=this;return e.mul(t).floor().div(t)}}const Jf=Ni(Zf),ey=new t;class ty extends Au{static get type(){return"PassTextureNode"}constructor(e,t){super(t),this.passNode=e,this.setUpdateMatrix(!1)}setup(e){return e.object.isQuadMesh&&this.passNode.build(e),super.setup(e)}clone(){return new this.constructor(this.passNode,this.value)}}class ry extends ty{static get type(){return"PassMultipleTextureNode"}constructor(e,t,r=!1){super(e,null),this.textureName=t,this.previousTexture=r}updateTexture(){this.value=this.previousTexture?this.passNode.getPreviousTexture(this.textureName):this.passNode.getTexture(this.textureName)}setup(e){return this.updateTexture(),super.setup(e)}clone(){return new this.constructor(this.passNode,this.textureName,this.previousTexture)}}class sy extends Ls{static get type(){return"PassNode"}constructor(e,t,r,s={}){super("vec4"),this.scope=e,this.scene=t,this.camera=r,this.options=s,this._pixelRatio=1,this._width=1,this._height=1;const i=new B;i.isRenderTargetTexture=!0,i.name="depth";const n=new me(this._width*this._pixelRatio,this._height*this._pixelRatio,{type:be,...s});n.texture.name="output",n.depthTexture=i,this.renderTarget=n,this._textures={output:n.texture,depth:i},this._textureNodes={},this._linearDepthNodes={},this._viewZNodes={},this._previousTextures={},this._previousTextureNodes={},this._cameraNear=on(0),this._cameraFar=on(0),this._mrt=null,this.isPassNode=!0,this.updateBeforeType=Rs.FRAME}setMRT(e){return this._mrt=e,this}getMRT(){return this._mrt}isGlobal(){return!0}getTexture(e){let t=this._textures[e];if(void 0===t){t=this.renderTarget.texture.clone(),t.name=e,this._textures[e]=t,this.renderTarget.textures.push(t)}return t}getPreviousTexture(e){let t=this._previousTextures[e];return void 0===t&&(t=this.getTexture(e).clone(),this._previousTextures[e]=t),t}toggleTexture(e){const t=this._previousTextures[e];if(void 0!==t){const r=this._textures[e],s=this.renderTarget.textures.indexOf(r);this.renderTarget.textures[s]=t,this._textures[e]=t,this._previousTextures[e]=r,this._textureNodes[e].updateTexture(),this._previousTextureNodes[e].updateTexture()}}getTextureNode(e="output"){let t=this._textureNodes[e];return void 0===t&&(t=Ti(new ry(this,e)),t.updateTexture(),this._textureNodes[e]=t),t}getPreviousTextureNode(e="output"){let t=this._previousTextureNodes[e];return void 0===t&&(void 0===this._textureNodes[e]&&this.getTextureNode(e),t=Ti(new ry(this,e,!0)),t.updateTexture(),this._previousTextureNodes[e]=t),t}getViewZNode(e="depth"){let t=this._viewZNodes[e];if(void 0===t){const r=this._cameraNear,s=this._cameraFar;this._viewZNodes[e]=t=jc(this.getTextureNode(e),r,s)}return t}getLinearDepthNode(e="depth"){let t=this._linearDepthNodes[e];if(void 0===t){const r=this._cameraNear,s=this._cameraFar,i=this.getViewZNode(e);this._linearDepthNodes[e]=t=Hc(i,r,s)}return t}setup({renderer:e}){return this.renderTarget.samples=void 0===this.options.samples?e.samples:this.options.samples,!0===e.backend.isWebGLBackend&&(this.renderTarget.samples=0),this.scope===sy.COLOR?this.getTextureNode():this.getLinearDepthNode()}updateBefore(e){const{renderer:t}=e,{scene:r,camera:s}=this;this._pixelRatio=t.getPixelRatio();const i=t.getSize(ey);this.setSize(i.width,i.height);const n=t.getRenderTarget(),o=t.getMRT();this._cameraNear.value=s.near,this._cameraFar.value=s.far;for(const e in this._previousTextures)this.toggleTexture(e);t.setRenderTarget(this.renderTarget),t.setMRT(this._mrt),t.render(r,s),t.setRenderTarget(n),t.setMRT(o)}setSize(e,t){this._width=e,this._height=t;const r=this._width*this._pixelRatio,s=this._height*this._pixelRatio;this.renderTarget.setSize(r,s)}setPixelRatio(e){this._pixelRatio=e,this.setSize(this._width,this._height)}dispose(){this.renderTarget.dispose()}}sy.COLOR="color",sy.DEPTH="depth";class iy extends sy{static get type(){return"ToonOutlinePassNode"}constructor(e,t,r,s,i){super(sy.COLOR,e,t),this.colorNode=r,this.thicknessNode=s,this.alphaNode=i,this._materialCache=new WeakMap}updateBefore(e){const{renderer:t}=e,r=t.getRenderObjectFunction();t.setRenderObjectFunction(((e,r,s,i,n,o,a,u)=>{if((n.isMeshToonMaterial||n.isMeshToonNodeMaterial)&&!1===n.wireframe){const l=this._getOutlineMaterial(n);t.renderObject(e,r,s,i,l,o,a,u)}t.renderObject(e,r,s,i,n,o,a,u)})),super.updateBefore(e),t.setRenderObjectFunction(r)}_createMaterial(){const e=new sh;e.isMeshToonOutlineMaterial=!0,e.name="Toon_Outline",e.side=T;const t=cl.negate(),r=Mu.mul(Yu),s=Bi(1),i=r.mul($i(tl,1)),n=r.mul($i(tl.add(t),1)),o=wo(i.sub(n));return e.vertexNode=i.add(o.mul(this.thicknessNode).mul(i.w).mul(s)),e.colorNode=$i(this.colorNode,this.alphaNode),e}_getOutlineMaterial(e){let t=this._materialCache.get(e);return void 0===t&&(t=this._createMaterial(),this._materialCache.set(e,t)),t}}const ny=Ai((([e,t])=>e.mul(t).clamp())).setLayout({name:"linearToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),oy=Ai((([e,t])=>(e=e.mul(t)).div(e.add(1)).clamp())).setLayout({name:"reinhardToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),ay=Ai((([e,t])=>{const r=(e=(e=e.mul(t)).sub(.004).max(0)).mul(e.mul(6.2).add(.5)),s=e.mul(e.mul(6.2).add(1.7)).add(.06);return r.div(s).pow(2.2)})).setLayout({name:"cineonToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),uy=Ai((([e])=>{const t=e.mul(e.add(.0245786)).sub(90537e-9),r=e.mul(e.add(.432951).mul(.983729)).add(.238081);return t.div(r)})),ly=Ai((([e,t])=>{const r=Ki(.59719,.35458,.04823,.076,.90834,.01566,.0284,.13383,.83777),s=Ki(1.60475,-.53108,-.07367,-.10208,1.10813,-.00605,-.00327,-.07276,1.07602);return e=e.mul(t).div(.6),e=r.mul(e),e=uy(e),(e=s.mul(e)).clamp()})).setLayout({name:"acesFilmicToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),dy=Ki(Oi(1.6605,-.1246,-.0182),Oi(-.5876,1.1329,-.1006),Oi(-.0728,-.0083,1.1187)),cy=Ki(Oi(.6274,.0691,.0164),Oi(.3293,.9195,.088),Oi(.0433,.0113,.8956)),hy=Ai((([e])=>{const t=Oi(e).toVar(),r=Oi(t.mul(t)).toVar(),s=Oi(r.mul(r)).toVar();return Bi(15.5).mul(s.mul(r)).sub(Wn(40.14,s.mul(t))).add(Wn(31.96,s).sub(Wn(6.868,r.mul(t))).add(Wn(.4298,r).add(Wn(.1191,t).sub(.00232))))})),py=Ai((([e,t])=>{const r=Oi(e).toVar(),s=Ki(Oi(.856627153315983,.137318972929847,.11189821299995),Oi(.0951212405381588,.761241990602591,.0767994186031903),Oi(.0482516061458583,.101439036467562,.811302368396859)),i=Ki(Oi(1.1271005818144368,-.1413297634984383,-.14132976349843826),Oi(-.11060664309660323,1.157823702216272,-.11060664309660294),Oi(-.016493938717834573,-.016493938717834257,1.2519364065950405)),n=Bi(-12.47393),o=Bi(4.026069);return r.mulAssign(t),r.assign(cy.mul(r)),r.assign(s.mul(r)),r.assign(Zo(r,1e-10)),r.assign(So(r)),r.assign(r.sub(n).div(o.sub(n))),r.assign(ga(r,0,1)),r.assign(hy(r)),r.assign(i.mul(r)),r.assign(oa(Zo(Oi(0),r),Oi(2.2))),r.assign(dy.mul(r)),r.assign(ga(r,0,1)),r})).setLayout({name:"agxToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),gy=Ai((([e,t])=>{const r=Bi(.76),s=Bi(.15);e=e.mul(t);const i=Qo(e.r,Qo(e.g,e.b)),n=Ra(i.lessThan(.08),i.sub(Wn(6.25,i.mul(i))),.04);e.subAssign(n);const o=Zo(e.r,Zo(e.g,e.b));Ei(o.lessThan(r),(()=>e));const a=Hn(1,r),u=Hn(1,a.mul(a).div(o.add(a.sub(r))));e.mulAssign(u.div(o));const l=Hn(1,jn(1,s.mul(o.sub(u)).add(1)));return pa(e,Oi(u),l)})).setLayout({name:"neutralToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]});class my extends Ps{static get type(){return"CodeNode"}constructor(e="",t=[],r=""){super("code"),this.isCodeNode=!0,this.code=e,this.includes=t,this.language=r}isGlobal(){return!0}setIncludes(e){return this.includes=e,this}getIncludes(){return this.includes}generate(e){const t=this.getIncludes(e);for(const r of t)r.build(e);const r=e.getCodeFromNode(this,this.getNodeType(e));return r.code=this.code,r.code}serialize(e){super.serialize(e),e.code=this.code,e.language=this.language}deserialize(e){super.deserialize(e),this.code=e.code,this.language=e.language}}const fy=Ni(my);class yy extends my{static get type(){return"FunctionNode"}constructor(e="",t=[],r=""){super(e,t,r)}getNodeType(e){return this.getNodeFunction(e).type}getInputs(e){return this.getNodeFunction(e).inputs}getNodeFunction(e){const t=e.getDataFromNode(this);let r=t.nodeFunction;return void 0===r&&(r=e.parser.parseFunction(this.code),t.nodeFunction=r),r}generate(e,t){super.generate(e);const r=this.getNodeFunction(e),s=r.name,i=r.type,n=e.getCodeFromNode(this,i);""!==s&&(n.name=s);const o=e.getPropertyName(n),a=this.getNodeFunction(e).getCode(o);return n.code=a+"\n","property"===t?o:e.format(`${o}()`,i,t)}}const by=(e,t=[],r="")=>{for(let e=0;es.call(...e);return i.functionNode=s,i};class xy extends Ps{static get type(){return"ScriptableValueNode"}constructor(e=null){super(),this._value=e,this._cache=null,this.inputType=null,this.outputType=null,this.events=new o,this.isScriptableValueNode=!0}get isScriptableOutputNode(){return null!==this.outputType}set value(e){this._value!==e&&(this._cache&&"URL"===this.inputType&&this.value.value instanceof ArrayBuffer&&(URL.revokeObjectURL(this._cache),this._cache=null),this._value=e,this.events.dispatchEvent({type:"change"}),this.refresh())}get value(){return this._value}refresh(){this.events.dispatchEvent({type:"refresh"})}getValue(){const e=this.value;if(e&&null===this._cache&&"URL"===this.inputType&&e.value instanceof ArrayBuffer)this._cache=URL.createObjectURL(new Blob([e.value]));else if(e&&null!==e.value&&void 0!==e.value&&(("URL"===this.inputType||"String"===this.inputType)&&"string"==typeof e.value||"Number"===this.inputType&&"number"==typeof e.value||"Vector2"===this.inputType&&e.value.isVector2||"Vector3"===this.inputType&&e.value.isVector3||"Vector4"===this.inputType&&e.value.isVector4||"Color"===this.inputType&&e.value.isColor||"Matrix3"===this.inputType&&e.value.isMatrix3||"Matrix4"===this.inputType&&e.value.isMatrix4))return e.value;return this._cache||e}getNodeType(e){return this.value&&this.value.isNode?this.value.getNodeType(e):"float"}setup(){return this.value&&this.value.isNode?this.value:Bi()}serialize(e){super.serialize(e),null!==this.value?"ArrayBuffer"===this.inputType?e.value=vs(this.value):e.value=this.value?this.value.toJSON(e.meta).uuid:null:e.value=null,e.inputType=this.inputType,e.outputType=this.outputType}deserialize(e){super.deserialize(e);let t=null;null!==e.value&&(t="ArrayBuffer"===e.inputType?Ns(e.value):"Texture"===e.inputType?e.meta.textures[e.value]:e.meta.nodes[e.value]||null),this.value=t,this.inputType=e.inputType,this.outputType=e.outputType}}const Ty=Ni(xy);class _y extends Map{get(e,t=null,...r){if(this.has(e))return super.get(e);if(null!==t){const s=t(...r);return this.set(e,s),s}}}class vy{constructor(e){this.scriptableNode=e}get parameters(){return this.scriptableNode.parameters}get layout(){return this.scriptableNode.getLayout()}getInputLayout(e){return this.scriptableNode.getInputLayout(e)}get(e){const t=this.parameters[e];return t?t.getValue():null}}const Ny=new _y;class Sy extends Ps{static get type(){return"ScriptableNode"}constructor(e=null,t={}){super(),this.codeNode=e,this.parameters=t,this._local=new _y,this._output=Ty(),this._outputs={},this._source=this.source,this._method=null,this._object=null,this._value=null,this._needsOutputUpdate=!0,this.onRefresh=this.onRefresh.bind(this),this.isScriptableNode=!0}get source(){return this.codeNode?this.codeNode.code:""}setLocal(e,t){return this._local.set(e,t)}getLocal(e){return this._local.get(e)}onRefresh(){this._refresh()}getInputLayout(e){for(const t of this.getLayout())if(t.inputType&&(t.id===e||t.name===e))return t}getOutputLayout(e){for(const t of this.getLayout())if(t.outputType&&(t.id===e||t.name===e))return t}setOutput(e,t){const r=this._outputs;return void 0===r[e]?r[e]=Ty(t):r[e].value=t,this}getOutput(e){return this._outputs[e]}getParameter(e){return this.parameters[e]}setParameter(e,t){const r=this.parameters;return t&&t.isScriptableNode?(this.deleteParameter(e),r[e]=t,r[e].getDefaultOutput().events.addEventListener("refresh",this.onRefresh)):t&&t.isScriptableValueNode?(this.deleteParameter(e),r[e]=t,r[e].events.addEventListener("refresh",this.onRefresh)):void 0===r[e]?(r[e]=Ty(t),r[e].events.addEventListener("refresh",this.onRefresh)):r[e].value=t,this}getValue(){return this.getDefaultOutput().getValue()}deleteParameter(e){let t=this.parameters[e];return t&&(t.isScriptableNode&&(t=t.getDefaultOutput()),t.events.removeEventListener("refresh",this.onRefresh)),this}clearParameters(){for(const e of Object.keys(this.parameters))this.deleteParameter(e);return this.needsUpdate=!0,this}call(e,...t){const r=this.getObject()[e];if("function"==typeof r)return r(...t)}async callAsync(e,...t){const r=this.getObject()[e];if("function"==typeof r)return"AsyncFunction"===r.constructor.name?await r(...t):r(...t)}getNodeType(e){return this.getDefaultOutputNode().getNodeType(e)}refresh(e=null){null!==e?this.getOutput(e).refresh():this._refresh()}getObject(){if(this.needsUpdate&&this.dispose(),null!==this._object)return this._object;const e=new vy(this),t=Ny.get("THREE"),r=Ny.get("TSL"),s=this.getMethod(),i=[e,this._local,Ny,()=>this.refresh(),(e,t)=>this.setOutput(e,t),t,r];this._object=s(...i);const n=this._object.layout;if(n&&(!1===n.cache&&this._local.clear(),this._output.outputType=n.outputType||null,Array.isArray(n.elements)))for(const e of n.elements){const t=e.id||e.name;e.inputType&&(void 0===this.getParameter(t)&&this.setParameter(t,null),this.getParameter(t).inputType=e.inputType),e.outputType&&(void 0===this.getOutput(t)&&this.setOutput(t,null),this.getOutput(t).outputType=e.outputType)}return this._object}deserialize(e){super.deserialize(e);for(const e in this.parameters){let t=this.parameters[e];t.isScriptableNode&&(t=t.getDefaultOutput()),t.events.addEventListener("refresh",this.onRefresh)}}getLayout(){return this.getObject().layout}getDefaultOutputNode(){const e=this.getDefaultOutput().value;return e&&e.isNode?e:Bi()}getDefaultOutput(){return this._exec()._output}getMethod(){if(this.needsUpdate&&this.dispose(),null!==this._method)return this._method;const e=["layout","init","main","dispose"].join(", "),t="\nreturn { ...output, "+e+" };",r="var "+e+"; var output = {};\n"+this.codeNode.code+t;return this._method=new Function(...["parameters","local","global","refresh","setOutput","THREE","TSL"],r),this._method}dispose(){null!==this._method&&(this._object&&"function"==typeof this._object.dispose&&this._object.dispose(),this._method=null,this._object=null,this._source=null,this._value=null,this._needsOutputUpdate=!0,this._output.value=null,this._outputs={})}setup(){return this.getDefaultOutputNode()}getCacheKey(e){const t=[ls(this.source),this.getDefaultOutputNode().getCacheKey(e)];for(const r in this.parameters)t.push(this.parameters[r].getCacheKey(e));return ds(t)}set needsUpdate(e){!0===e&&this.dispose()}get needsUpdate(){return this.source!==this._source}_exec(){return null===this.codeNode||(!0===this._needsOutputUpdate&&(this._value=this.call("main"),this._needsOutputUpdate=!1),this._output.value=this._value),this}_refresh(){this.needsUpdate=!0,this._exec(),this._output.refresh()}}const Ay=Ni(Sy);function Ry(e){let t;const r=e.context.getViewZ;return void 0!==r&&(t=r(this)),(t||nl.z).negate()}const Cy=Ai((([e,t],r)=>{const s=Ry(r);return ya(e,t,s)})),Ey=Ai((([e],t)=>{const r=Ry(t);return e.mul(e,r,r).negate().exp().oneMinus()})),wy=Ai((([e,t])=>$i(t.toFloat().mix(En.rgb,e.toVec3()),En.a)));let My=null,By=null;class Fy extends Ps{static get type(){return"RangeNode"}constructor(e=Bi(),t=Bi()){super(),this.minNode=e,this.maxNode=t}getVectorLength(e){const t=e.getTypeLength(xs(this.minNode.value)),r=e.getTypeLength(xs(this.maxNode.value));return t>r?t:r}getNodeType(e){return e.object.count>1?e.getTypeFromLength(this.getVectorLength(e)):"float"}setup(e){const t=e.object;let r=null;if(t.count>1){const i=this.minNode.value,n=this.maxNode.value,o=e.getTypeLength(xs(i)),u=e.getTypeLength(xs(n));My=My||new s,By=By||new s,My.setScalar(0),By.setScalar(0),1===o?My.setScalar(i):i.isColor?My.set(i.r,i.g,i.b,1):My.set(i.x,i.y,i.z||0,i.w||0),1===u?By.setScalar(n):n.isColor?By.set(n.r,n.g,n.b,1):By.set(n.x,n.y,n.z||0,n.w||0);const l=4,d=l*t.count,c=new Float32Array(d);for(let e=0;eTi(new Py(e,t)),Dy=Iy("numWorkgroups","uvec3"),Ly=Iy("workgroupId","uvec3"),Vy=Iy("localId","uvec3"),Oy=Iy("subgroupSize","uint");const Gy=Ni(class extends Ps{constructor(e){super(),this.scope=e}generate(e){const{scope:t}=this,{renderer:r}=e;!0===r.backend.isWebGLBackend?e.addFlowCode(`\t// ${t}Barrier \n`):e.addLineFlowCode(`${t}Barrier()`,this)}});class ky extends Is{constructor(e,t){super(e,t),this.isWorkgroupInfoElementNode=!0}generate(e,t){let r;const s=e.context.assign;if(r=super.generate(e),!0!==s){const s=this.getNodeType(e);r=e.format(r,s,t)}return r}}class zy extends Ps{constructor(e,t,r=0){super(t),this.bufferType=t,this.bufferCount=r,this.isWorkgroupInfoNode=!0,this.elementType=t,this.scope=e}label(e){return this.name=e,this}setScope(e){return this.scope=e,this}getElementType(){return this.elementType}getInputType(){return`${this.scope}Array`}element(e){return Ti(new ky(this,e))}generate(e){return e.getScopedArray(this.name||`${this.scope}Array_${this.id}`,this.scope.toLowerCase(),this.bufferType,this.bufferCount)}}class $y extends Ls{static get type(){return"AtomicFunctionNode"}constructor(e,t,r,s=null){super("uint"),this.method=e,this.pointerNode=t,this.valueNode=r,this.storeNode=s}getInputType(e){return this.pointerNode.getNodeType(e)}getNodeType(e){return this.getInputType(e)}generate(e){const t=this.method,r=this.getNodeType(e),s=this.getInputType(e),i=this.pointerNode,n=this.valueNode,o=[];o.push(`&${i.build(e,s)}`),o.push(n.build(e,s));const a=`${e.getMethod(t,r)}( ${o.join(", ")} )`;if(null!==this.storeNode){const t=this.storeNode.build(e,s);e.addLineFlowCode(`${t} = ${a}`,this)}else e.addLineFlowCode(a,this)}}$y.ATOMIC_LOAD="atomicLoad",$y.ATOMIC_STORE="atomicStore",$y.ATOMIC_ADD="atomicAdd",$y.ATOMIC_SUB="atomicSub",$y.ATOMIC_MAX="atomicMax",$y.ATOMIC_MIN="atomicMin",$y.ATOMIC_AND="atomicAnd",$y.ATOMIC_OR="atomicOr",$y.ATOMIC_XOR="atomicXor";const Hy=Ni($y),Wy=(e,t,r,s=null)=>{const i=Hy(e,t,r,s);return i.append(),i};let jy;function qy(e){jy=jy||new WeakMap;let t=jy.get(e);return void 0===t&&jy.set(e,t={}),t}function Ky(e){const t=qy(e);return t.shadowMatrix||(t.shadowMatrix=on("mat4").setGroup(rn).onRenderUpdate((()=>(!0!==e.castShadow&&e.shadow.updateMatrices(e),e.shadow.matrix))))}function Xy(e){const t=qy(e);if(void 0===t.projectionUV){const r=Ky(e).mul(sl);t.projectionUV=r.xyz.div(r.w)}return t.projectionUV}function Yy(e){const t=qy(e);return t.position||(t.position=on(new r).setGroup(rn).onRenderUpdate(((t,r)=>r.value.setFromMatrixPosition(e.matrixWorld))))}function Qy(e){const t=qy(e);return t.targetPosition||(t.targetPosition=on(new r).setGroup(rn).onRenderUpdate(((t,r)=>r.value.setFromMatrixPosition(e.target.matrixWorld))))}function Zy(e){const t=qy(e);return t.viewPosition||(t.viewPosition=on(new r).setGroup(rn).onRenderUpdate((({camera:t},s)=>{s.value=s.value||new r,s.value.setFromMatrixPosition(e.matrixWorld),s.value.applyMatrix4(t.matrixWorldInverse)})))}const Jy=e=>Fu.transformDirection(Yy(e).sub(Qy(e))),eb=(e,t)=>{for(const r of t)if(r.isAnalyticLightNode&&r.light.id===e)return r;return null},tb=new WeakMap;class rb extends Ps{static get type(){return"LightsNode"}constructor(){super("vec3"),this.totalDiffuseNode=Oi().toVar("totalDiffuse"),this.totalSpecularNode=Oi().toVar("totalSpecular"),this.outgoingLightNode=Oi().toVar("outgoingLight"),this._lights=[],this._lightNodes=null,this._lightNodesHash=null,this.global=!0}customCacheKey(){const e=[],t=this._lights;for(let r=0;re.sort(((e,t)=>e.id-t.id)))(this._lights),i=e.renderer.library;for(const e of s)if(e.isNode)t.push(Ti(e));else{let s=null;if(null!==r&&(s=eb(e.id,r)),null===s){const r=i.getLightNodeClass(e.constructor);if(null===r){console.warn(`LightsNode.setupNodeLights: Light node not found for ${e.constructor.name}`);continue}let s=null;tb.has(e)?s=tb.get(e):(s=Ti(new r(e)),tb.set(e,s)),t.push(s)}}this._lightNodes=t}setupLights(e,t){for(const r of t)r.build(e)}setup(e){null===this._lightNodes&&this.setupLightsNode(e);const t=e.context,r=t.lightingModel;let s=this.outgoingLightNode;if(r){const{_lightNodes:i,totalDiffuseNode:n,totalSpecularNode:o}=this;t.outgoingLight=s;const a=e.addStack();e.getDataFromNode(this).nodes=a.nodes,r.start(t,a,e),this.setupLights(e,i),r.indirect(t,a,e);const{backdrop:u,backdropAlpha:l}=t,{directDiffuse:d,directSpecular:c,indirectDiffuse:h,indirectSpecular:p}=t.reflectedLight;let g=d.add(h);null!==u&&(g=Oi(null!==l?l.mix(g,u):u),t.material.transparent=!0),n.assign(g),o.assign(c.add(p)),s.assign(n.add(o)),r.finish(t,a,e),s=s.bypass(e.removeStack())}return s}setLights(e){return this._lights=e,this._lightNodes=null,this._lightNodesHash=null,this}getLights(){return this._lights}get hasLights(){return this._lights.length>0}}class sb extends Ps{static get type(){return"ShadowBaseNode"}constructor(e){super(),this.light=e,this.updateBeforeType=Rs.RENDER,this.isShadowBaseNode=!0}setupShadowPosition({material:e}){ib.assign(e.shadowPositionNode||sl)}dispose(){this.updateBeforeType=Rs.NONE}}const ib=Oi().toVar("shadowPositionWorld");function nb(t,r={}){return r.toneMapping=t.toneMapping,r.toneMappingExposure=t.toneMappingExposure,r.outputColorSpace=t.outputColorSpace,r.renderTarget=t.getRenderTarget(),r.activeCubeFace=t.getActiveCubeFace(),r.activeMipmapLevel=t.getActiveMipmapLevel(),r.renderObjectFunction=t.getRenderObjectFunction(),r.pixelRatio=t.getPixelRatio(),r.mrt=t.getMRT(),r.clearColor=t.getClearColor(r.clearColor||new e),r.clearAlpha=t.getClearAlpha(),r.autoClear=t.autoClear,r.scissorTest=t.getScissorTest(),r}function ob(e,t){return t=nb(e,t),e.setMRT(null),e.setRenderObjectFunction(null),e.setClearColor(0,1),e.autoClear=!0,t}function ab(e,t){e.toneMapping=t.toneMapping,e.toneMappingExposure=t.toneMappingExposure,e.outputColorSpace=t.outputColorSpace,e.setRenderTarget(t.renderTarget,t.activeCubeFace,t.activeMipmapLevel),e.setRenderObjectFunction(t.renderObjectFunction),e.setPixelRatio(t.pixelRatio),e.setMRT(t.mrt),e.setClearColor(t.clearColor,t.clearAlpha),e.autoClear=t.autoClear,e.setScissorTest(t.scissorTest)}function ub(e,t={}){return t.background=e.background,t.backgroundNode=e.backgroundNode,t.overrideMaterial=e.overrideMaterial,t}function lb(e,t){return t=ub(e,t),e.background=null,e.backgroundNode=null,e.overrideMaterial=null,t}function db(e,t){e.background=t.background,e.backgroundNode=t.backgroundNode,e.overrideMaterial=t.overrideMaterial}function cb(e,t,r){return r=lb(t,r=ob(e,r))}function hb(e,t,r){ab(e,r),db(t,r)}var pb=Object.freeze({__proto__:null,resetRendererAndSceneState:cb,resetRendererState:ob,resetSceneState:lb,restoreRendererAndSceneState:hb,restoreRendererState:ab,restoreSceneState:db,saveRendererAndSceneState:function(e,t,r={}){return r=ub(t,r=nb(e,r))},saveRendererState:nb,saveSceneState:ub});const gb=new WeakMap,mb=Ai((([e,t,r])=>{let s=sl.sub(e).length();return s=s.sub(t).div(r.sub(t)),s=s.saturate(),s})),fb=e=>{let t=gb.get(e);if(void 0===t){const r=e.isPointLight?(e=>{const t=e.shadow.camera,r=Pl("near","float",t).setGroup(rn),s=Pl("far","float",t).setGroup(rn),i=Ou(e);return mb(i,r,s)})(e):null;t=new sh,t.colorNode=$i(0,0,0,1),t.depthNode=r,t.isShadowNodeMaterial=!0,t.name="ShadowMaterial",t.fog=!1,gb.set(e,t)}return t},yb=Ai((({depthTexture:e,shadowCoord:t})=>Ru(e,t.xy).compare(t.z))),bb=Ai((({depthTexture:e,shadowCoord:t,shadow:r})=>{const s=(t,r)=>Ru(e,t).compare(r),i=Pl("mapSize","vec2",r).setGroup(rn),n=Pl("radius","float",r).setGroup(rn),o=Ii(1).div(i),a=o.x.negate().mul(n),u=o.y.negate().mul(n),l=o.x.mul(n),d=o.y.mul(n),c=a.div(2),h=u.div(2),p=l.div(2),g=d.div(2);return $n(s(t.xy.add(Ii(a,u)),t.z),s(t.xy.add(Ii(0,u)),t.z),s(t.xy.add(Ii(l,u)),t.z),s(t.xy.add(Ii(c,h)),t.z),s(t.xy.add(Ii(0,h)),t.z),s(t.xy.add(Ii(p,h)),t.z),s(t.xy.add(Ii(a,0)),t.z),s(t.xy.add(Ii(c,0)),t.z),s(t.xy,t.z),s(t.xy.add(Ii(p,0)),t.z),s(t.xy.add(Ii(l,0)),t.z),s(t.xy.add(Ii(c,g)),t.z),s(t.xy.add(Ii(0,g)),t.z),s(t.xy.add(Ii(p,g)),t.z),s(t.xy.add(Ii(a,d)),t.z),s(t.xy.add(Ii(0,d)),t.z),s(t.xy.add(Ii(l,d)),t.z)).mul(1/17)})),xb=Ai((({depthTexture:e,shadowCoord:t,shadow:r})=>{const s=(t,r)=>Ru(e,t).compare(r),i=Pl("mapSize","vec2",r).setGroup(rn),n=Ii(1).div(i),o=n.x,a=n.y,u=t.xy,l=Mo(u.mul(i).add(.5));return u.subAssign(l.mul(n)),$n(s(u,t.z),s(u.add(Ii(o,0)),t.z),s(u.add(Ii(0,a)),t.z),s(u.add(n),t.z),pa(s(u.add(Ii(o.negate(),0)),t.z),s(u.add(Ii(o.mul(2),0)),t.z),l.x),pa(s(u.add(Ii(o.negate(),a)),t.z),s(u.add(Ii(o.mul(2),a)),t.z),l.x),pa(s(u.add(Ii(0,a.negate())),t.z),s(u.add(Ii(0,a.mul(2))),t.z),l.y),pa(s(u.add(Ii(o,a.negate())),t.z),s(u.add(Ii(o,a.mul(2))),t.z),l.y),pa(pa(s(u.add(Ii(o.negate(),a.negate())),t.z),s(u.add(Ii(o.mul(2),a.negate())),t.z),l.x),pa(s(u.add(Ii(o.negate(),a.mul(2))),t.z),s(u.add(Ii(o.mul(2),a.mul(2))),t.z),l.x),l.y)).mul(1/9)})),Tb=Ai((({depthTexture:e,shadowCoord:t})=>{const r=Bi(1).toVar(),s=Ru(e).sample(t.xy).rg,i=ea(t.z,s.x);return Ei(i.notEqual(Bi(1)),(()=>{const e=t.z.sub(s.x),n=Zo(0,s.y.mul(s.y));let o=n.div(n.add(e.mul(e)));o=ga(Hn(o,.3).div(.95-.3)),r.assign(ga(Zo(i,o)))})),r})),_b=Ai((({samples:e,radius:t,size:r,shadowPass:s})=>{const i=Bi(0).toVar(),n=Bi(0).toVar(),o=e.lessThanEqual(Bi(1)).select(Bi(0),Bi(2).div(e.sub(1))),a=e.lessThanEqual(Bi(1)).select(Bi(0),Bi(-1));cc({start:Fi(0),end:Fi(e),type:"int",condition:"<"},(({i:e})=>{const u=a.add(Bi(e).mul(o)),l=s.sample($n(Ec.xy,Ii(0,u).mul(t)).div(r)).x;i.addAssign(l),n.addAssign(l.mul(l))})),i.divAssign(e),n.divAssign(e);const u=Ao(n.sub(i.mul(i)));return Ii(i,u)})),vb=Ai((({samples:e,radius:t,size:r,shadowPass:s})=>{const i=Bi(0).toVar(),n=Bi(0).toVar(),o=e.lessThanEqual(Bi(1)).select(Bi(0),Bi(2).div(e.sub(1))),a=e.lessThanEqual(Bi(1)).select(Bi(0),Bi(-1));cc({start:Fi(0),end:Fi(e),type:"int",condition:"<"},(({i:e})=>{const u=a.add(Bi(e).mul(o)),l=s.sample($n(Ec.xy,Ii(u,0).mul(t)).div(r));i.addAssign(l.x),n.addAssign($n(l.y.mul(l.y),l.x.mul(l.x)))})),i.divAssign(e),n.divAssign(e);const u=Ao(n.sub(i.mul(i)));return Ii(i,u)})),Nb=[yb,bb,xb,Tb];let Sb;const Ab=new cf;class Rb extends sb{static get type(){return"ShadowNode"}constructor(e,t=null){super(e),this.shadow=t||e.shadow,this.shadowMap=null,this.vsmShadowMapVertical=null,this.vsmShadowMapHorizontal=null,this.vsmMaterialVertical=null,this.vsmMaterialHorizontal=null,this._node=null,this.isShadowNode=!0}setupShadowFilter(e,{filterFn:t,depthTexture:r,shadowCoord:s,shadow:i}){const n=s.x.greaterThanEqual(0).and(s.x.lessThanEqual(1)).and(s.y.greaterThanEqual(0)).and(s.y.lessThanEqual(1)).and(s.z.lessThanEqual(1)),o=t({depthTexture:r,shadowCoord:s,shadow:i});return n.select(o,Bi(1))}setupShadowCoord(e,t){const{shadow:r}=this,{renderer:s}=e,i=Pl("bias","float",r).setGroup(rn);let n,o=t;if(r.camera.isOrthographicCamera||!0!==s.logarithmicDepthBuffer)o=o.xyz.div(o.w),n=o.z,s.coordinateSystem===l&&(n=n.mul(2).sub(1));else{const e=o.w;o=o.xy.div(e);const t=Pl("near","float",r.camera).setGroup(rn),s=Pl("far","float",r.camera).setGroup(rn);n=qc(e.negate(),t,s)}return o=Oi(o.x,o.y.oneMinus(),n.add(i)),o}getShadowFilterFn(e){return Nb[e]}setupShadow(e){const{renderer:t}=e,{light:r,shadow:s}=this,i=t.shadowMap.type,n=new B(s.mapSize.width,s.mapSize.height);n.compareFunction=Ce;const o=e.createRenderTarget(s.mapSize.width,s.mapSize.height);if(o.depthTexture=n,s.camera.updateProjectionMatrix(),i===Ee){n.compareFunction=null,this.vsmShadowMapVertical=e.createRenderTarget(s.mapSize.width,s.mapSize.height,{format:we,type:be}),this.vsmShadowMapHorizontal=e.createRenderTarget(s.mapSize.width,s.mapSize.height,{format:we,type:be});const t=Ru(n),r=Ru(this.vsmShadowMapVertical.texture),i=Pl("blurSamples","float",s).setGroup(rn),o=Pl("radius","float",s).setGroup(rn),a=Pl("mapSize","vec2",s).setGroup(rn);let u=this.vsmMaterialVertical||(this.vsmMaterialVertical=new sh);u.fragmentNode=_b({samples:i,radius:o,size:a,shadowPass:t}).context(e.getSharedContext()),u.name="VSMVertical",u=this.vsmMaterialHorizontal||(this.vsmMaterialHorizontal=new sh),u.fragmentNode=vb({samples:i,radius:o,size:a,shadowPass:r}).context(e.getSharedContext()),u.name="VSMHorizontal"}const a=Pl("intensity","float",s).setGroup(rn),u=Pl("normalBias","float",s).setGroup(rn),l=Ky(r).mul(ib.add(fl.mul(u))),d=this.setupShadowCoord(e,l),c=s.filterNode||this.getShadowFilterFn(t.shadowMap.type)||null;if(null===c)throw new Error("THREE.WebGPURenderer: Shadow map type not supported yet.");const h=i===Ee?this.vsmShadowMapHorizontal.texture:n,p=this.setupShadowFilter(e,{filterFn:c,shadowTexture:o.texture,depthTexture:h,shadowCoord:d,shadow:s}),g=Ru(o.texture,d),m=pa(1,p.rgb.mix(g,1),a.mul(g.a)).toVar();return this.shadowMap=o,this.shadow.map=o,m}setup(e){if(!1!==e.renderer.shadowMap.enabled)return Ai((()=>{let t=this._node;return this.setupShadowPosition(e),null===t&&(this._node=t=this.setupShadow(e)),e.material.shadowNode&&console.warn('THREE.NodeMaterial: ".shadowNode" is deprecated. Use ".castShadowNode" instead.'),e.material.receivedShadowNode&&(t=e.material.receivedShadowNode(t)),t}))()}renderShadow(e){const{shadow:t,shadowMap:r,light:s}=this,{renderer:i,scene:n}=e;t.updateMatrices(s),r.setSize(t.mapSize.width,t.mapSize.height),i.render(n,t.camera)}updateShadow(e){const{shadowMap:t,light:r,shadow:s}=this,{renderer:i,scene:n,camera:o}=e,a=i.shadowMap.type,u=t.depthTexture.version;this._depthVersionCached=u,s.camera.layers.mask=o.layers.mask;const l=i.getRenderObjectFunction(),d=i.getMRT(),c=!!d&&d.has("velocity");Sb=cb(i,n,Sb),n.overrideMaterial=fb(r),i.setRenderObjectFunction(((e,t,r,n,u,l,...d)=>{(!0===e.castShadow||e.receiveShadow&&a===Ee)&&(c&&(_s(e).useVelocity=!0),e.onBeforeShadow(i,e,o,s.camera,n,t.overrideMaterial,l),i.renderObject(e,t,r,n,u,l,...d),e.onAfterShadow(i,e,o,s.camera,n,t.overrideMaterial,l))})),i.setRenderTarget(t),this.renderShadow(e),i.setRenderObjectFunction(l),!0!==r.isPointLight&&a===Ee&&this.vsmPass(i),hb(i,n,Sb)}vsmPass(e){const{shadow:t}=this;this.vsmShadowMapVertical.setSize(t.mapSize.width,t.mapSize.height),this.vsmShadowMapHorizontal.setSize(t.mapSize.width,t.mapSize.height),e.setRenderTarget(this.vsmShadowMapVertical),Ab.material=this.vsmMaterialVertical,Ab.render(e),e.setRenderTarget(this.vsmShadowMapHorizontal),Ab.material=this.vsmMaterialHorizontal,Ab.render(e)}dispose(){this.shadowMap.dispose(),this.shadowMap=null,null!==this.vsmShadowMapVertical&&(this.vsmShadowMapVertical.dispose(),this.vsmShadowMapVertical=null,this.vsmMaterialVertical.dispose(),this.vsmMaterialVertical=null),null!==this.vsmShadowMapHorizontal&&(this.vsmShadowMapHorizontal.dispose(),this.vsmShadowMapHorizontal=null,this.vsmMaterialHorizontal.dispose(),this.vsmMaterialHorizontal=null),super.dispose()}updateBefore(e){const{shadow:t}=this;(t.needsUpdate||t.autoUpdate)&&(this.updateShadow(e),this.shadowMap.depthTexture.version===this._depthVersionCached&&(t.needsUpdate=!1))}}const Cb=(e,t)=>Ti(new Rb(e,t));class Eb extends bc{static get type(){return"AnalyticLightNode"}constructor(t=null){super(),this.light=t,this.color=new e,this.colorNode=t&&t.colorNode||on(this.color).setGroup(rn),this.baseColorNode=null,this.shadowNode=null,this.shadowColorNode=null,this.isAnalyticLightNode=!0,this.updateType=Rs.FRAME}customCacheKey(){return cs(this.light.id,this.light.castShadow?1:0)}getHash(){return this.light.uuid}setupShadowNode(){return Cb(this.light)}setupShadow(e){const{renderer:t}=e;if(!1===t.shadowMap.enabled)return;let r=this.shadowColorNode;if(null===r){const t=this.light.shadow.shadowNode;let s;s=void 0!==t?Ti(t):this.setupShadowNode(e),this.shadowNode=s,this.shadowColorNode=r=this.colorNode.mul(s),this.baseColorNode=this.colorNode}this.colorNode=r}setup(e){this.colorNode=this.baseColorNode||this.colorNode,this.light.castShadow?e.object.receiveShadow&&this.setupShadow(e):null!==this.shadowNode&&(this.shadowNode.dispose(),this.shadowNode=null,this.shadowColorNode=null)}update(){const{light:e}=this;this.color.copy(e.color).multiplyScalar(e.intensity)}}const wb=Ai((e=>{const{lightDistance:t,cutoffDistance:r,decayExponent:s}=e,i=t.pow(s).max(.01).reciprocal();return r.greaterThan(0).select(i.mul(t.div(r).pow4().oneMinus().clamp().pow2()),i)})),Mb=new e,Bb=Ai((([e,t])=>{const r=e.toVar(),s=Lo(r),i=jn(1,Zo(s.x,Zo(s.y,s.z)));s.mulAssign(i),r.mulAssign(i.mul(t.mul(2).oneMinus()));const n=Ii(r.xy).toVar(),o=t.mul(1.5).oneMinus();return Ei(s.z.greaterThanEqual(o),(()=>{Ei(r.z.greaterThan(0),(()=>{n.x.assign(Hn(4,r.x))}))})).ElseIf(s.x.greaterThanEqual(o),(()=>{const e=Vo(r.x);n.x.assign(r.z.mul(e).add(e.mul(2)))})).ElseIf(s.y.greaterThanEqual(o),(()=>{const e=Vo(r.y);n.x.assign(r.x.add(e.mul(2)).add(2)),n.y.assign(r.z.mul(e).sub(2))})),Ii(.125,.25).mul(n).add(Ii(.375,.75)).flipY()})).setLayout({name:"cubeToUV",type:"vec2",inputs:[{name:"pos",type:"vec3"},{name:"texelSizeY",type:"float"}]}),Fb=Ai((({depthTexture:e,bd3D:t,dp:r,texelSize:s})=>Ru(e,Bb(t,s.y)).compare(r))),Ub=Ai((({depthTexture:e,bd3D:t,dp:r,texelSize:s,shadow:i})=>{const n=Pl("radius","float",i).setGroup(rn),o=Ii(-1,1).mul(n).mul(s.y);return Ru(e,Bb(t.add(o.xyy),s.y)).compare(r).add(Ru(e,Bb(t.add(o.yyy),s.y)).compare(r)).add(Ru(e,Bb(t.add(o.xyx),s.y)).compare(r)).add(Ru(e,Bb(t.add(o.yyx),s.y)).compare(r)).add(Ru(e,Bb(t,s.y)).compare(r)).add(Ru(e,Bb(t.add(o.xxy),s.y)).compare(r)).add(Ru(e,Bb(t.add(o.yxy),s.y)).compare(r)).add(Ru(e,Bb(t.add(o.xxx),s.y)).compare(r)).add(Ru(e,Bb(t.add(o.yxx),s.y)).compare(r)).mul(1/9)})),Pb=Ai((({filterFn:e,depthTexture:t,shadowCoord:r,shadow:s})=>{const i=r.xyz.toVar(),n=i.length(),o=on("float").setGroup(rn).onRenderUpdate((()=>s.camera.near)),a=on("float").setGroup(rn).onRenderUpdate((()=>s.camera.far)),u=Pl("bias","float",s).setGroup(rn),l=on(s.mapSize).setGroup(rn),d=Bi(1).toVar();return Ei(n.sub(a).lessThanEqual(0).and(n.sub(o).greaterThanEqual(0)),(()=>{const r=n.sub(o).div(a.sub(o)).toVar();r.addAssign(u);const c=i.normalize(),h=Ii(1).div(l.mul(Ii(4,2)));d.assign(e({depthTexture:t,bd3D:c,dp:r,texelSize:h,shadow:s}))})),d})),Ib=new s,Db=new t,Lb=new t;class Vb extends Rb{static get type(){return"PointShadowNode"}constructor(e,t=null){super(e,t)}getShadowFilterFn(e){return e===Me?Fb:Ub}setupShadowCoord(e,t){return t}setupShadowFilter(e,{filterFn:t,shadowTexture:r,depthTexture:s,shadowCoord:i,shadow:n}){return Pb({filterFn:t,shadowTexture:r,depthTexture:s,shadowCoord:i,shadow:n})}renderShadow(e){const{shadow:t,shadowMap:r,light:s}=this,{renderer:i,scene:n}=e,o=t.getFrameExtents();Lb.copy(t.mapSize),Lb.multiply(o),r.setSize(Lb.width,Lb.height),Db.copy(t.mapSize);const a=i.autoClear,u=i.getClearColor(Mb),l=i.getClearAlpha();i.autoClear=!1,i.setClearColor(t.clearColor,t.clearAlpha),i.clear();const d=t.getViewportCount();for(let e=0;e{const n=i.context.lightingModel,o=t.sub(nl),a=o.normalize(),u=o.length(),l=wb({lightDistance:u,cutoffDistance:r,decayExponent:s}),d=e.mul(l),c=i.context.reflectedLight;n.direct({lightDirection:a,lightColor:d,reflectedLight:c},i.stack,i)}));class Gb extends Eb{static get type(){return"PointLightNode"}constructor(e=null){super(e),this.cutoffDistanceNode=on(0).setGroup(rn),this.decayExponentNode=on(2).setGroup(rn)}update(e){const{light:t}=this;super.update(e),this.cutoffDistanceNode.value=t.distance,this.decayExponentNode.value=t.decay}setupShadowNode(){return((e,t)=>Ti(new Vb(e,t)))(this.light)}setup(e){super.setup(e),Ob({color:this.colorNode,lightViewPosition:Zy(this.light),cutoffDistance:this.cutoffDistanceNode,decayExponent:this.decayExponentNode}).append()}}const kb=Ai((([e=t()])=>{const t=e.mul(2),r=t.x.floor(),s=t.y.floor();return r.add(s).mod(2).sign()})),zb=Ai((([e,t,r])=>{const s=Bi(r).toVar(),i=Bi(t).toVar(),n=Pi(e).toVar();return Ra(n,i,s)})).setLayout({name:"mx_select",type:"float",inputs:[{name:"b",type:"bool"},{name:"t",type:"float"},{name:"f",type:"float"}]}),$b=Ai((([e,t])=>{const r=Pi(t).toVar(),s=Bi(e).toVar();return Ra(r,s.negate(),s)})).setLayout({name:"mx_negate_if",type:"float",inputs:[{name:"val",type:"float"},{name:"b",type:"bool"}]}),Hb=Ai((([e])=>{const t=Bi(e).toVar();return Fi(Co(t))})).setLayout({name:"mx_floor",type:"int",inputs:[{name:"x",type:"float"}]}),Wb=Ai((([e,t])=>{const r=Bi(e).toVar();return t.assign(Hb(r)),r.sub(Bi(t))})),jb=Um([Ai((([e,t,r,s,i,n])=>{const o=Bi(n).toVar(),a=Bi(i).toVar(),u=Bi(s).toVar(),l=Bi(r).toVar(),d=Bi(t).toVar(),c=Bi(e).toVar(),h=Bi(Hn(1,a)).toVar();return Hn(1,o).mul(c.mul(h).add(d.mul(a))).add(o.mul(l.mul(h).add(u.mul(a))))})).setLayout({name:"mx_bilerp_0",type:"float",inputs:[{name:"v0",type:"float"},{name:"v1",type:"float"},{name:"v2",type:"float"},{name:"v3",type:"float"},{name:"s",type:"float"},{name:"t",type:"float"}]}),Ai((([e,t,r,s,i,n])=>{const o=Bi(n).toVar(),a=Bi(i).toVar(),u=Oi(s).toVar(),l=Oi(r).toVar(),d=Oi(t).toVar(),c=Oi(e).toVar(),h=Bi(Hn(1,a)).toVar();return Hn(1,o).mul(c.mul(h).add(d.mul(a))).add(o.mul(l.mul(h).add(u.mul(a))))})).setLayout({name:"mx_bilerp_1",type:"vec3",inputs:[{name:"v0",type:"vec3"},{name:"v1",type:"vec3"},{name:"v2",type:"vec3"},{name:"v3",type:"vec3"},{name:"s",type:"float"},{name:"t",type:"float"}]})]),qb=Um([Ai((([e,t,r,s,i,n,o,a,u,l,d])=>{const c=Bi(d).toVar(),h=Bi(l).toVar(),p=Bi(u).toVar(),g=Bi(a).toVar(),m=Bi(o).toVar(),f=Bi(n).toVar(),y=Bi(i).toVar(),b=Bi(s).toVar(),x=Bi(r).toVar(),T=Bi(t).toVar(),_=Bi(e).toVar(),v=Bi(Hn(1,p)).toVar(),N=Bi(Hn(1,h)).toVar();return Bi(Hn(1,c)).toVar().mul(N.mul(_.mul(v).add(T.mul(p))).add(h.mul(x.mul(v).add(b.mul(p))))).add(c.mul(N.mul(y.mul(v).add(f.mul(p))).add(h.mul(m.mul(v).add(g.mul(p))))))})).setLayout({name:"mx_trilerp_0",type:"float",inputs:[{name:"v0",type:"float"},{name:"v1",type:"float"},{name:"v2",type:"float"},{name:"v3",type:"float"},{name:"v4",type:"float"},{name:"v5",type:"float"},{name:"v6",type:"float"},{name:"v7",type:"float"},{name:"s",type:"float"},{name:"t",type:"float"},{name:"r",type:"float"}]}),Ai((([e,t,r,s,i,n,o,a,u,l,d])=>{const c=Bi(d).toVar(),h=Bi(l).toVar(),p=Bi(u).toVar(),g=Oi(a).toVar(),m=Oi(o).toVar(),f=Oi(n).toVar(),y=Oi(i).toVar(),b=Oi(s).toVar(),x=Oi(r).toVar(),T=Oi(t).toVar(),_=Oi(e).toVar(),v=Bi(Hn(1,p)).toVar(),N=Bi(Hn(1,h)).toVar();return Bi(Hn(1,c)).toVar().mul(N.mul(_.mul(v).add(T.mul(p))).add(h.mul(x.mul(v).add(b.mul(p))))).add(c.mul(N.mul(y.mul(v).add(f.mul(p))).add(h.mul(m.mul(v).add(g.mul(p))))))})).setLayout({name:"mx_trilerp_1",type:"vec3",inputs:[{name:"v0",type:"vec3"},{name:"v1",type:"vec3"},{name:"v2",type:"vec3"},{name:"v3",type:"vec3"},{name:"v4",type:"vec3"},{name:"v5",type:"vec3"},{name:"v6",type:"vec3"},{name:"v7",type:"vec3"},{name:"s",type:"float"},{name:"t",type:"float"},{name:"r",type:"float"}]})]),Kb=Ai((([e,t,r])=>{const s=Bi(r).toVar(),i=Bi(t).toVar(),n=Ui(e).toVar(),o=Ui(n.bitAnd(Ui(7))).toVar(),a=Bi(zb(o.lessThan(Ui(4)),i,s)).toVar(),u=Bi(Wn(2,zb(o.lessThan(Ui(4)),s,i))).toVar();return $b(a,Pi(o.bitAnd(Ui(1)))).add($b(u,Pi(o.bitAnd(Ui(2)))))})).setLayout({name:"mx_gradient_float_0",type:"float",inputs:[{name:"hash",type:"uint"},{name:"x",type:"float"},{name:"y",type:"float"}]}),Xb=Ai((([e,t,r,s])=>{const i=Bi(s).toVar(),n=Bi(r).toVar(),o=Bi(t).toVar(),a=Ui(e).toVar(),u=Ui(a.bitAnd(Ui(15))).toVar(),l=Bi(zb(u.lessThan(Ui(8)),o,n)).toVar(),d=Bi(zb(u.lessThan(Ui(4)),n,zb(u.equal(Ui(12)).or(u.equal(Ui(14))),o,i))).toVar();return $b(l,Pi(u.bitAnd(Ui(1)))).add($b(d,Pi(u.bitAnd(Ui(2)))))})).setLayout({name:"mx_gradient_float_1",type:"float",inputs:[{name:"hash",type:"uint"},{name:"x",type:"float"},{name:"y",type:"float"},{name:"z",type:"float"}]}),Yb=Um([Kb,Xb]),Qb=Ai((([e,t,r])=>{const s=Bi(r).toVar(),i=Bi(t).toVar(),n=ki(e).toVar();return Oi(Yb(n.x,i,s),Yb(n.y,i,s),Yb(n.z,i,s))})).setLayout({name:"mx_gradient_vec3_0",type:"vec3",inputs:[{name:"hash",type:"uvec3"},{name:"x",type:"float"},{name:"y",type:"float"}]}),Zb=Ai((([e,t,r,s])=>{const i=Bi(s).toVar(),n=Bi(r).toVar(),o=Bi(t).toVar(),a=ki(e).toVar();return Oi(Yb(a.x,o,n,i),Yb(a.y,o,n,i),Yb(a.z,o,n,i))})).setLayout({name:"mx_gradient_vec3_1",type:"vec3",inputs:[{name:"hash",type:"uvec3"},{name:"x",type:"float"},{name:"y",type:"float"},{name:"z",type:"float"}]}),Jb=Um([Qb,Zb]),ex=Ai((([e])=>{const t=Bi(e).toVar();return Wn(.6616,t)})).setLayout({name:"mx_gradient_scale2d_0",type:"float",inputs:[{name:"v",type:"float"}]}),tx=Ai((([e])=>{const t=Bi(e).toVar();return Wn(.982,t)})).setLayout({name:"mx_gradient_scale3d_0",type:"float",inputs:[{name:"v",type:"float"}]}),rx=Um([ex,Ai((([e])=>{const t=Oi(e).toVar();return Wn(.6616,t)})).setLayout({name:"mx_gradient_scale2d_1",type:"vec3",inputs:[{name:"v",type:"vec3"}]})]),sx=Um([tx,Ai((([e])=>{const t=Oi(e).toVar();return Wn(.982,t)})).setLayout({name:"mx_gradient_scale3d_1",type:"vec3",inputs:[{name:"v",type:"vec3"}]})]),ix=Ai((([e,t])=>{const r=Fi(t).toVar(),s=Ui(e).toVar();return s.shiftLeft(r).bitOr(s.shiftRight(Fi(32).sub(r)))})).setLayout({name:"mx_rotl32",type:"uint",inputs:[{name:"x",type:"uint"},{name:"k",type:"int"}]}),nx=Ai((([e,t,r])=>{e.subAssign(r),e.bitXorAssign(ix(r,Fi(4))),r.addAssign(t),t.subAssign(e),t.bitXorAssign(ix(e,Fi(6))),e.addAssign(r),r.subAssign(t),r.bitXorAssign(ix(t,Fi(8))),t.addAssign(e),e.subAssign(r),e.bitXorAssign(ix(r,Fi(16))),r.addAssign(t),t.subAssign(e),t.bitXorAssign(ix(e,Fi(19))),e.addAssign(r),r.subAssign(t),r.bitXorAssign(ix(t,Fi(4))),t.addAssign(e)})),ox=Ai((([e,t,r])=>{const s=Ui(r).toVar(),i=Ui(t).toVar(),n=Ui(e).toVar();return s.bitXorAssign(i),s.subAssign(ix(i,Fi(14))),n.bitXorAssign(s),n.subAssign(ix(s,Fi(11))),i.bitXorAssign(n),i.subAssign(ix(n,Fi(25))),s.bitXorAssign(i),s.subAssign(ix(i,Fi(16))),n.bitXorAssign(s),n.subAssign(ix(s,Fi(4))),i.bitXorAssign(n),i.subAssign(ix(n,Fi(14))),s.bitXorAssign(i),s.subAssign(ix(i,Fi(24))),s})).setLayout({name:"mx_bjfinal",type:"uint",inputs:[{name:"a",type:"uint"},{name:"b",type:"uint"},{name:"c",type:"uint"}]}),ax=Ai((([e])=>{const t=Ui(e).toVar();return Bi(t).div(Bi(Ui(Fi(4294967295))))})).setLayout({name:"mx_bits_to_01",type:"float",inputs:[{name:"bits",type:"uint"}]}),ux=Ai((([e])=>{const t=Bi(e).toVar();return t.mul(t).mul(t).mul(t.mul(t.mul(6).sub(15)).add(10))})).setLayout({name:"mx_fade",type:"float",inputs:[{name:"t",type:"float"}]}),lx=Um([Ai((([e])=>{const t=Fi(e).toVar(),r=Ui(Ui(1)).toVar(),s=Ui(Ui(Fi(3735928559)).add(r.shiftLeft(Ui(2))).add(Ui(13))).toVar();return ox(s.add(Ui(t)),s,s)})).setLayout({name:"mx_hash_int_0",type:"uint",inputs:[{name:"x",type:"int"}]}),Ai((([e,t])=>{const r=Fi(t).toVar(),s=Fi(e).toVar(),i=Ui(Ui(2)).toVar(),n=Ui().toVar(),o=Ui().toVar(),a=Ui().toVar();return n.assign(o.assign(a.assign(Ui(Fi(3735928559)).add(i.shiftLeft(Ui(2))).add(Ui(13))))),n.addAssign(Ui(s)),o.addAssign(Ui(r)),ox(n,o,a)})).setLayout({name:"mx_hash_int_1",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"}]}),Ai((([e,t,r])=>{const s=Fi(r).toVar(),i=Fi(t).toVar(),n=Fi(e).toVar(),o=Ui(Ui(3)).toVar(),a=Ui().toVar(),u=Ui().toVar(),l=Ui().toVar();return a.assign(u.assign(l.assign(Ui(Fi(3735928559)).add(o.shiftLeft(Ui(2))).add(Ui(13))))),a.addAssign(Ui(n)),u.addAssign(Ui(i)),l.addAssign(Ui(s)),ox(a,u,l)})).setLayout({name:"mx_hash_int_2",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"}]}),Ai((([e,t,r,s])=>{const i=Fi(s).toVar(),n=Fi(r).toVar(),o=Fi(t).toVar(),a=Fi(e).toVar(),u=Ui(Ui(4)).toVar(),l=Ui().toVar(),d=Ui().toVar(),c=Ui().toVar();return l.assign(d.assign(c.assign(Ui(Fi(3735928559)).add(u.shiftLeft(Ui(2))).add(Ui(13))))),l.addAssign(Ui(a)),d.addAssign(Ui(o)),c.addAssign(Ui(n)),nx(l,d,c),l.addAssign(Ui(i)),ox(l,d,c)})).setLayout({name:"mx_hash_int_3",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"},{name:"xx",type:"int"}]}),Ai((([e,t,r,s,i])=>{const n=Fi(i).toVar(),o=Fi(s).toVar(),a=Fi(r).toVar(),u=Fi(t).toVar(),l=Fi(e).toVar(),d=Ui(Ui(5)).toVar(),c=Ui().toVar(),h=Ui().toVar(),p=Ui().toVar();return c.assign(h.assign(p.assign(Ui(Fi(3735928559)).add(d.shiftLeft(Ui(2))).add(Ui(13))))),c.addAssign(Ui(l)),h.addAssign(Ui(u)),p.addAssign(Ui(a)),nx(c,h,p),c.addAssign(Ui(o)),h.addAssign(Ui(n)),ox(c,h,p)})).setLayout({name:"mx_hash_int_4",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"},{name:"xx",type:"int"},{name:"yy",type:"int"}]})]),dx=Um([Ai((([e,t])=>{const r=Fi(t).toVar(),s=Fi(e).toVar(),i=Ui(lx(s,r)).toVar(),n=ki().toVar();return n.x.assign(i.bitAnd(Fi(255))),n.y.assign(i.shiftRight(Fi(8)).bitAnd(Fi(255))),n.z.assign(i.shiftRight(Fi(16)).bitAnd(Fi(255))),n})).setLayout({name:"mx_hash_vec3_0",type:"uvec3",inputs:[{name:"x",type:"int"},{name:"y",type:"int"}]}),Ai((([e,t,r])=>{const s=Fi(r).toVar(),i=Fi(t).toVar(),n=Fi(e).toVar(),o=Ui(lx(n,i,s)).toVar(),a=ki().toVar();return a.x.assign(o.bitAnd(Fi(255))),a.y.assign(o.shiftRight(Fi(8)).bitAnd(Fi(255))),a.z.assign(o.shiftRight(Fi(16)).bitAnd(Fi(255))),a})).setLayout({name:"mx_hash_vec3_1",type:"uvec3",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"}]})]),cx=Um([Ai((([e])=>{const t=Ii(e).toVar(),r=Fi().toVar(),s=Fi().toVar(),i=Bi(Wb(t.x,r)).toVar(),n=Bi(Wb(t.y,s)).toVar(),o=Bi(ux(i)).toVar(),a=Bi(ux(n)).toVar(),u=Bi(jb(Yb(lx(r,s),i,n),Yb(lx(r.add(Fi(1)),s),i.sub(1),n),Yb(lx(r,s.add(Fi(1))),i,n.sub(1)),Yb(lx(r.add(Fi(1)),s.add(Fi(1))),i.sub(1),n.sub(1)),o,a)).toVar();return rx(u)})).setLayout({name:"mx_perlin_noise_float_0",type:"float",inputs:[{name:"p",type:"vec2"}]}),Ai((([e])=>{const t=Oi(e).toVar(),r=Fi().toVar(),s=Fi().toVar(),i=Fi().toVar(),n=Bi(Wb(t.x,r)).toVar(),o=Bi(Wb(t.y,s)).toVar(),a=Bi(Wb(t.z,i)).toVar(),u=Bi(ux(n)).toVar(),l=Bi(ux(o)).toVar(),d=Bi(ux(a)).toVar(),c=Bi(qb(Yb(lx(r,s,i),n,o,a),Yb(lx(r.add(Fi(1)),s,i),n.sub(1),o,a),Yb(lx(r,s.add(Fi(1)),i),n,o.sub(1),a),Yb(lx(r.add(Fi(1)),s.add(Fi(1)),i),n.sub(1),o.sub(1),a),Yb(lx(r,s,i.add(Fi(1))),n,o,a.sub(1)),Yb(lx(r.add(Fi(1)),s,i.add(Fi(1))),n.sub(1),o,a.sub(1)),Yb(lx(r,s.add(Fi(1)),i.add(Fi(1))),n,o.sub(1),a.sub(1)),Yb(lx(r.add(Fi(1)),s.add(Fi(1)),i.add(Fi(1))),n.sub(1),o.sub(1),a.sub(1)),u,l,d)).toVar();return sx(c)})).setLayout({name:"mx_perlin_noise_float_1",type:"float",inputs:[{name:"p",type:"vec3"}]})]),hx=Um([Ai((([e])=>{const t=Ii(e).toVar(),r=Fi().toVar(),s=Fi().toVar(),i=Bi(Wb(t.x,r)).toVar(),n=Bi(Wb(t.y,s)).toVar(),o=Bi(ux(i)).toVar(),a=Bi(ux(n)).toVar(),u=Oi(jb(Jb(dx(r,s),i,n),Jb(dx(r.add(Fi(1)),s),i.sub(1),n),Jb(dx(r,s.add(Fi(1))),i,n.sub(1)),Jb(dx(r.add(Fi(1)),s.add(Fi(1))),i.sub(1),n.sub(1)),o,a)).toVar();return rx(u)})).setLayout({name:"mx_perlin_noise_vec3_0",type:"vec3",inputs:[{name:"p",type:"vec2"}]}),Ai((([e])=>{const t=Oi(e).toVar(),r=Fi().toVar(),s=Fi().toVar(),i=Fi().toVar(),n=Bi(Wb(t.x,r)).toVar(),o=Bi(Wb(t.y,s)).toVar(),a=Bi(Wb(t.z,i)).toVar(),u=Bi(ux(n)).toVar(),l=Bi(ux(o)).toVar(),d=Bi(ux(a)).toVar(),c=Oi(qb(Jb(dx(r,s,i),n,o,a),Jb(dx(r.add(Fi(1)),s,i),n.sub(1),o,a),Jb(dx(r,s.add(Fi(1)),i),n,o.sub(1),a),Jb(dx(r.add(Fi(1)),s.add(Fi(1)),i),n.sub(1),o.sub(1),a),Jb(dx(r,s,i.add(Fi(1))),n,o,a.sub(1)),Jb(dx(r.add(Fi(1)),s,i.add(Fi(1))),n.sub(1),o,a.sub(1)),Jb(dx(r,s.add(Fi(1)),i.add(Fi(1))),n,o.sub(1),a.sub(1)),Jb(dx(r.add(Fi(1)),s.add(Fi(1)),i.add(Fi(1))),n.sub(1),o.sub(1),a.sub(1)),u,l,d)).toVar();return sx(c)})).setLayout({name:"mx_perlin_noise_vec3_1",type:"vec3",inputs:[{name:"p",type:"vec3"}]})]),px=Um([Ai((([e])=>{const t=Bi(e).toVar(),r=Fi(Hb(t)).toVar();return ax(lx(r))})).setLayout({name:"mx_cell_noise_float_0",type:"float",inputs:[{name:"p",type:"float"}]}),Ai((([e])=>{const t=Ii(e).toVar(),r=Fi(Hb(t.x)).toVar(),s=Fi(Hb(t.y)).toVar();return ax(lx(r,s))})).setLayout({name:"mx_cell_noise_float_1",type:"float",inputs:[{name:"p",type:"vec2"}]}),Ai((([e])=>{const t=Oi(e).toVar(),r=Fi(Hb(t.x)).toVar(),s=Fi(Hb(t.y)).toVar(),i=Fi(Hb(t.z)).toVar();return ax(lx(r,s,i))})).setLayout({name:"mx_cell_noise_float_2",type:"float",inputs:[{name:"p",type:"vec3"}]}),Ai((([e])=>{const t=$i(e).toVar(),r=Fi(Hb(t.x)).toVar(),s=Fi(Hb(t.y)).toVar(),i=Fi(Hb(t.z)).toVar(),n=Fi(Hb(t.w)).toVar();return ax(lx(r,s,i,n))})).setLayout({name:"mx_cell_noise_float_3",type:"float",inputs:[{name:"p",type:"vec4"}]})]),gx=Um([Ai((([e])=>{const t=Bi(e).toVar(),r=Fi(Hb(t)).toVar();return Oi(ax(lx(r,Fi(0))),ax(lx(r,Fi(1))),ax(lx(r,Fi(2))))})).setLayout({name:"mx_cell_noise_vec3_0",type:"vec3",inputs:[{name:"p",type:"float"}]}),Ai((([e])=>{const t=Ii(e).toVar(),r=Fi(Hb(t.x)).toVar(),s=Fi(Hb(t.y)).toVar();return Oi(ax(lx(r,s,Fi(0))),ax(lx(r,s,Fi(1))),ax(lx(r,s,Fi(2))))})).setLayout({name:"mx_cell_noise_vec3_1",type:"vec3",inputs:[{name:"p",type:"vec2"}]}),Ai((([e])=>{const t=Oi(e).toVar(),r=Fi(Hb(t.x)).toVar(),s=Fi(Hb(t.y)).toVar(),i=Fi(Hb(t.z)).toVar();return Oi(ax(lx(r,s,i,Fi(0))),ax(lx(r,s,i,Fi(1))),ax(lx(r,s,i,Fi(2))))})).setLayout({name:"mx_cell_noise_vec3_2",type:"vec3",inputs:[{name:"p",type:"vec3"}]}),Ai((([e])=>{const t=$i(e).toVar(),r=Fi(Hb(t.x)).toVar(),s=Fi(Hb(t.y)).toVar(),i=Fi(Hb(t.z)).toVar(),n=Fi(Hb(t.w)).toVar();return Oi(ax(lx(r,s,i,n,Fi(0))),ax(lx(r,s,i,n,Fi(1))),ax(lx(r,s,i,n,Fi(2))))})).setLayout({name:"mx_cell_noise_vec3_3",type:"vec3",inputs:[{name:"p",type:"vec4"}]})]),mx=Ai((([e,t,r,s])=>{const i=Bi(s).toVar(),n=Bi(r).toVar(),o=Fi(t).toVar(),a=Oi(e).toVar(),u=Bi(0).toVar(),l=Bi(1).toVar();return cc(o,(()=>{u.addAssign(l.mul(cx(a))),l.mulAssign(i),a.mulAssign(n)})),u})).setLayout({name:"mx_fractal_noise_float",type:"float",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),fx=Ai((([e,t,r,s])=>{const i=Bi(s).toVar(),n=Bi(r).toVar(),o=Fi(t).toVar(),a=Oi(e).toVar(),u=Oi(0).toVar(),l=Bi(1).toVar();return cc(o,(()=>{u.addAssign(l.mul(hx(a))),l.mulAssign(i),a.mulAssign(n)})),u})).setLayout({name:"mx_fractal_noise_vec3",type:"vec3",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),yx=Ai((([e,t,r,s])=>{const i=Bi(s).toVar(),n=Bi(r).toVar(),o=Fi(t).toVar(),a=Oi(e).toVar();return Ii(mx(a,o,n,i),mx(a.add(Oi(Fi(19),Fi(193),Fi(17))),o,n,i))})).setLayout({name:"mx_fractal_noise_vec2",type:"vec2",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),bx=Ai((([e,t,r,s])=>{const i=Bi(s).toVar(),n=Bi(r).toVar(),o=Fi(t).toVar(),a=Oi(e).toVar(),u=Oi(fx(a,o,n,i)).toVar(),l=Bi(mx(a.add(Oi(Fi(19),Fi(193),Fi(17))),o,n,i)).toVar();return $i(u,l)})).setLayout({name:"mx_fractal_noise_vec4",type:"vec4",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),xx=Um([Ai((([e,t,r,s,i,n,o])=>{const a=Fi(o).toVar(),u=Bi(n).toVar(),l=Fi(i).toVar(),d=Fi(s).toVar(),c=Fi(r).toVar(),h=Fi(t).toVar(),p=Ii(e).toVar(),g=Oi(gx(Ii(h.add(d),c.add(l)))).toVar(),m=Ii(g.x,g.y).toVar();m.subAssign(.5),m.mulAssign(u),m.addAssign(.5);const f=Ii(Ii(Bi(h),Bi(c)).add(m)).toVar(),y=Ii(f.sub(p)).toVar();return Ei(a.equal(Fi(2)),(()=>Lo(y.x).add(Lo(y.y)))),Ei(a.equal(Fi(3)),(()=>Zo(Lo(y.x),Lo(y.y)))),ia(y,y)})).setLayout({name:"mx_worley_distance_0",type:"float",inputs:[{name:"p",type:"vec2"},{name:"x",type:"int"},{name:"y",type:"int"},{name:"xoff",type:"int"},{name:"yoff",type:"int"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),Ai((([e,t,r,s,i,n,o,a,u])=>{const l=Fi(u).toVar(),d=Bi(a).toVar(),c=Fi(o).toVar(),h=Fi(n).toVar(),p=Fi(i).toVar(),g=Fi(s).toVar(),m=Fi(r).toVar(),f=Fi(t).toVar(),y=Oi(e).toVar(),b=Oi(gx(Oi(f.add(p),m.add(h),g.add(c)))).toVar();b.subAssign(.5),b.mulAssign(d),b.addAssign(.5);const x=Oi(Oi(Bi(f),Bi(m),Bi(g)).add(b)).toVar(),T=Oi(x.sub(y)).toVar();return Ei(l.equal(Fi(2)),(()=>Lo(T.x).add(Lo(T.y)).add(Lo(T.z)))),Ei(l.equal(Fi(3)),(()=>Zo(Zo(Lo(T.x),Lo(T.y)),Lo(T.z)))),ia(T,T)})).setLayout({name:"mx_worley_distance_1",type:"float",inputs:[{name:"p",type:"vec3"},{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"},{name:"xoff",type:"int"},{name:"yoff",type:"int"},{name:"zoff",type:"int"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),Tx=Ai((([e,t,r])=>{const s=Fi(r).toVar(),i=Bi(t).toVar(),n=Ii(e).toVar(),o=Fi().toVar(),a=Fi().toVar(),u=Ii(Wb(n.x,o),Wb(n.y,a)).toVar(),l=Bi(1e6).toVar();return cc({start:-1,end:Fi(1),name:"x",condition:"<="},(({x:e})=>{cc({start:-1,end:Fi(1),name:"y",condition:"<="},(({y:t})=>{const r=Bi(xx(u,e,t,o,a,i,s)).toVar();l.assign(Qo(l,r))}))})),Ei(s.equal(Fi(0)),(()=>{l.assign(Ao(l))})),l})).setLayout({name:"mx_worley_noise_float_0",type:"float",inputs:[{name:"p",type:"vec2"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),_x=Ai((([e,t,r])=>{const s=Fi(r).toVar(),i=Bi(t).toVar(),n=Ii(e).toVar(),o=Fi().toVar(),a=Fi().toVar(),u=Ii(Wb(n.x,o),Wb(n.y,a)).toVar(),l=Ii(1e6,1e6).toVar();return cc({start:-1,end:Fi(1),name:"x",condition:"<="},(({x:e})=>{cc({start:-1,end:Fi(1),name:"y",condition:"<="},(({y:t})=>{const r=Bi(xx(u,e,t,o,a,i,s)).toVar();Ei(r.lessThan(l.x),(()=>{l.y.assign(l.x),l.x.assign(r)})).ElseIf(r.lessThan(l.y),(()=>{l.y.assign(r)}))}))})),Ei(s.equal(Fi(0)),(()=>{l.assign(Ao(l))})),l})).setLayout({name:"mx_worley_noise_vec2_0",type:"vec2",inputs:[{name:"p",type:"vec2"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),vx=Ai((([e,t,r])=>{const s=Fi(r).toVar(),i=Bi(t).toVar(),n=Ii(e).toVar(),o=Fi().toVar(),a=Fi().toVar(),u=Ii(Wb(n.x,o),Wb(n.y,a)).toVar(),l=Oi(1e6,1e6,1e6).toVar();return cc({start:-1,end:Fi(1),name:"x",condition:"<="},(({x:e})=>{cc({start:-1,end:Fi(1),name:"y",condition:"<="},(({y:t})=>{const r=Bi(xx(u,e,t,o,a,i,s)).toVar();Ei(r.lessThan(l.x),(()=>{l.z.assign(l.y),l.y.assign(l.x),l.x.assign(r)})).ElseIf(r.lessThan(l.y),(()=>{l.z.assign(l.y),l.y.assign(r)})).ElseIf(r.lessThan(l.z),(()=>{l.z.assign(r)}))}))})),Ei(s.equal(Fi(0)),(()=>{l.assign(Ao(l))})),l})).setLayout({name:"mx_worley_noise_vec3_0",type:"vec3",inputs:[{name:"p",type:"vec2"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),Nx=Um([Tx,Ai((([e,t,r])=>{const s=Fi(r).toVar(),i=Bi(t).toVar(),n=Oi(e).toVar(),o=Fi().toVar(),a=Fi().toVar(),u=Fi().toVar(),l=Oi(Wb(n.x,o),Wb(n.y,a),Wb(n.z,u)).toVar(),d=Bi(1e6).toVar();return cc({start:-1,end:Fi(1),name:"x",condition:"<="},(({x:e})=>{cc({start:-1,end:Fi(1),name:"y",condition:"<="},(({y:t})=>{cc({start:-1,end:Fi(1),name:"z",condition:"<="},(({z:r})=>{const n=Bi(xx(l,e,t,r,o,a,u,i,s)).toVar();d.assign(Qo(d,n))}))}))})),Ei(s.equal(Fi(0)),(()=>{d.assign(Ao(d))})),d})).setLayout({name:"mx_worley_noise_float_1",type:"float",inputs:[{name:"p",type:"vec3"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),Sx=Um([_x,Ai((([e,t,r])=>{const s=Fi(r).toVar(),i=Bi(t).toVar(),n=Oi(e).toVar(),o=Fi().toVar(),a=Fi().toVar(),u=Fi().toVar(),l=Oi(Wb(n.x,o),Wb(n.y,a),Wb(n.z,u)).toVar(),d=Ii(1e6,1e6).toVar();return cc({start:-1,end:Fi(1),name:"x",condition:"<="},(({x:e})=>{cc({start:-1,end:Fi(1),name:"y",condition:"<="},(({y:t})=>{cc({start:-1,end:Fi(1),name:"z",condition:"<="},(({z:r})=>{const n=Bi(xx(l,e,t,r,o,a,u,i,s)).toVar();Ei(n.lessThan(d.x),(()=>{d.y.assign(d.x),d.x.assign(n)})).ElseIf(n.lessThan(d.y),(()=>{d.y.assign(n)}))}))}))})),Ei(s.equal(Fi(0)),(()=>{d.assign(Ao(d))})),d})).setLayout({name:"mx_worley_noise_vec2_1",type:"vec2",inputs:[{name:"p",type:"vec3"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),Ax=Um([vx,Ai((([e,t,r])=>{const s=Fi(r).toVar(),i=Bi(t).toVar(),n=Oi(e).toVar(),o=Fi().toVar(),a=Fi().toVar(),u=Fi().toVar(),l=Oi(Wb(n.x,o),Wb(n.y,a),Wb(n.z,u)).toVar(),d=Oi(1e6,1e6,1e6).toVar();return cc({start:-1,end:Fi(1),name:"x",condition:"<="},(({x:e})=>{cc({start:-1,end:Fi(1),name:"y",condition:"<="},(({y:t})=>{cc({start:-1,end:Fi(1),name:"z",condition:"<="},(({z:r})=>{const n=Bi(xx(l,e,t,r,o,a,u,i,s)).toVar();Ei(n.lessThan(d.x),(()=>{d.z.assign(d.y),d.y.assign(d.x),d.x.assign(n)})).ElseIf(n.lessThan(d.y),(()=>{d.z.assign(d.y),d.y.assign(n)})).ElseIf(n.lessThan(d.z),(()=>{d.z.assign(n)}))}))}))})),Ei(s.equal(Fi(0)),(()=>{d.assign(Ao(d))})),d})).setLayout({name:"mx_worley_noise_vec3_1",type:"vec3",inputs:[{name:"p",type:"vec3"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),Rx=Ai((([e])=>{const t=e.y,r=e.z,s=Oi().toVar();return Ei(t.lessThan(1e-4),(()=>{s.assign(Oi(r,r,r))})).Else((()=>{let i=e.x;i=i.sub(Co(i)).mul(6).toVar();const n=Fi(jo(i)),o=i.sub(Bi(n)),a=r.mul(t.oneMinus()),u=r.mul(t.mul(o).oneMinus()),l=r.mul(t.mul(o.oneMinus()).oneMinus());Ei(n.equal(Fi(0)),(()=>{s.assign(Oi(r,l,a))})).ElseIf(n.equal(Fi(1)),(()=>{s.assign(Oi(u,r,a))})).ElseIf(n.equal(Fi(2)),(()=>{s.assign(Oi(a,r,l))})).ElseIf(n.equal(Fi(3)),(()=>{s.assign(Oi(a,u,r))})).ElseIf(n.equal(Fi(4)),(()=>{s.assign(Oi(l,a,r))})).Else((()=>{s.assign(Oi(r,a,u))}))})),s})).setLayout({name:"mx_hsvtorgb",type:"vec3",inputs:[{name:"hsv",type:"vec3"}]}),Cx=Ai((([e])=>{const t=Oi(e).toVar(),r=Bi(t.x).toVar(),s=Bi(t.y).toVar(),i=Bi(t.z).toVar(),n=Bi(Qo(r,Qo(s,i))).toVar(),o=Bi(Zo(r,Zo(s,i))).toVar(),a=Bi(o.sub(n)).toVar(),u=Bi().toVar(),l=Bi().toVar(),d=Bi().toVar();return d.assign(o),Ei(o.greaterThan(0),(()=>{l.assign(a.div(o))})).Else((()=>{l.assign(0)})),Ei(l.lessThanEqual(0),(()=>{u.assign(0)})).Else((()=>{Ei(r.greaterThanEqual(o),(()=>{u.assign(s.sub(i).div(a))})).ElseIf(s.greaterThanEqual(o),(()=>{u.assign($n(2,i.sub(r).div(a)))})).Else((()=>{u.assign($n(4,r.sub(s).div(a)))})),u.mulAssign(1/6),Ei(u.lessThan(0),(()=>{u.addAssign(1)}))})),Oi(u,l,d)})).setLayout({name:"mx_rgbtohsv",type:"vec3",inputs:[{name:"c",type:"vec3"}]}),Ex=Ai((([e])=>{const t=Oi(e).toVar(),r=zi(Qn(t,Oi(.04045))).toVar(),s=Oi(t.div(12.92)).toVar(),i=Oi(oa(Zo(t.add(Oi(.055)),Oi(0)).div(1.055),Oi(2.4))).toVar();return pa(s,i,r)})).setLayout({name:"mx_srgb_texture_to_lin_rec709",type:"vec3",inputs:[{name:"color",type:"vec3"}]}),wx=(e,t)=>{e=Bi(e),t=Bi(t);const r=Ii(t.dFdx(),t.dFdy()).length().mul(.7071067811865476);return ya(e.sub(r),e.add(r),t)},Mx=(e,t,r,s)=>pa(e,t,r[s].clamp()),Bx=(e,t,r,s,i)=>pa(e,t,wx(r,s[i])),Fx=Ai((([e,t,r])=>{const s=wo(e).toVar("nDir"),i=Hn(Bi(.5).mul(t.sub(r)),sl).div(s).toVar("rbmax"),n=Hn(Bi(-.5).mul(t.sub(r)),sl).div(s).toVar("rbmin"),o=Oi().toVar("rbminmax");o.x=s.x.greaterThan(Bi(0)).select(i.x,n.x),o.y=s.y.greaterThan(Bi(0)).select(i.y,n.y),o.z=s.z.greaterThan(Bi(0)).select(i.z,n.z);const a=Qo(Qo(o.x,o.y),o.z).toVar("correction");return sl.add(s.mul(a)).toVar("boxIntersection").sub(r)})),Ux=Ai((([e,t])=>{const r=e.x,s=e.y,i=e.z;let n=t.element(0).mul(.886227);return n=n.add(t.element(1).mul(1.023328).mul(s)),n=n.add(t.element(2).mul(1.023328).mul(i)),n=n.add(t.element(3).mul(1.023328).mul(r)),n=n.add(t.element(4).mul(.858086).mul(r).mul(s)),n=n.add(t.element(5).mul(.858086).mul(s).mul(i)),n=n.add(t.element(6).mul(i.mul(i).mul(.743125).sub(.247708))),n=n.add(t.element(7).mul(.858086).mul(r).mul(i)),n=n.add(t.element(8).mul(.429043).mul(Wn(r,r).sub(Wn(s,s)))),n}));var Px=Object.freeze({__proto__:null,BRDF_GGX:Kh,BRDF_Lambert:Uh,BasicShadowFilter:yb,Break:hc,Continue:()=>gu("continue").append(),DFGApprox:Xh,D_GGX:Wh,Discard:mu,EPSILON:po,F_Schlick:Fh,Fn:Ai,INFINITY:go,If:Ei,Loop:cc,NodeAccess:Es,NodeShaderStage:As,NodeType:Cs,NodeUpdateType:Rs,PCFShadowFilter:bb,PCFSoftShadowFilter:xb,PI:mo,PI2:fo,Return:()=>gu("return").append(),Schlick_to_F0:Qh,ScriptableNodeResources:Ny,ShaderNode:xi,TBNViewMatrix:Ql,VSMShadowFilter:Tb,V_GGX_SmithCorrelated:$h,abs:Lo,acesFilmicToneMapping:ly,acos:Io,add:$n,addMethodChaining:qs,addNodeElement:function(e){console.warn("THREE.TSLBase: AddNodeElement has been removed in favor of tree-shaking. Trying add",e)},agxToneMapping:py,all:yo,alphaT:_n,and:eo,anisotropy:vn,anisotropyB:Sn,anisotropyT:Nn,any:bo,append:wi,arrayBuffer:e=>Ti(new Hs(e,"ArrayBuffer")),asin:Po,assign:On,atan:Do,atan2:va,atomicAdd:(e,t,r=null)=>Wy($y.ATOMIC_ADD,e,t,r),atomicAnd:(e,t,r=null)=>Wy($y.ATOMIC_AND,e,t,r),atomicFunc:Wy,atomicMax:(e,t,r=null)=>Wy($y.ATOMIC_MAX,e,t,r),atomicMin:(e,t,r=null)=>Wy($y.ATOMIC_MIN,e,t,r),atomicOr:(e,t,r=null)=>Wy($y.ATOMIC_OR,e,t,r),atomicStore:(e,t,r=null)=>Wy($y.ATOMIC_STORE,e,t,r),atomicSub:(e,t,r=null)=>Wy($y.ATOMIC_SUB,e,t,r),atomicXor:(e,t,r=null)=>Wy($y.ATOMIC_XOR,e,t,r),attenuationColor:Dn,attenuationDistance:In,attribute:xu,attributeArray:(e,t="float")=>{const r=bs(t),s=ys(t),i=new xf(e,r,s);return Nf(i,t,e)},backgroundBlurriness:Mf,backgroundIntensity:Bf,backgroundRotation:Ff,batch:oc,billboarding:Om,bitAnd:io,bitNot:no,bitOr:oo,bitXor:ao,bitangentGeometry:Wl,bitangentLocal:jl,bitangentView:ql,bitangentWorld:Kl,bitcast:Xo,blendBurn:kf,blendColor:Wf,blendDodge:zf,blendOverlay:Hf,blendScreen:$f,blur:Xp,bool:Pi,buffer:El,bufferAttribute:eu,bumpMap:od,burn:(...e)=>(console.warn('THREE.TSL: "burn" has been renamed. Use "blendBurn" instead.'),kf(e)),bvec2:Vi,bvec3:zi,bvec4:ji,bypass:lu,cache:au,call:kn,cameraFar:wu,cameraNear:Eu,cameraNormalMatrix:Pu,cameraPosition:Iu,cameraProjectionMatrix:Mu,cameraProjectionMatrixInverse:Bu,cameraViewMatrix:Fu,cameraWorldMatrix:Uu,cbrt:ca,cdl:Qf,ceil:Eo,checker:kb,cineonToneMapping:ay,clamp:ga,clearcoat:gn,clearcoatRoughness:mn,code:fy,color:Mi,colorSpaceToWorking:Wa,colorToDirection:e=>Ti(e).mul(2).sub(1),compute:nu,cond:Ca,context:wa,convert:Qi,convertColorSpace:(e,t,r)=>Ti(new ka(Ti(e),t,r)),convertToTexture:(e,...t)=>e.isTextureNode?e:e.isPassNode?e.getTextureNode():gf(e,...t),cos:Fo,cross:na,cubeTexture:Rl,dFdx:zo,dFdy:$o,dashSize:wn,defaultBuildStages:Ms,defaultShaderStages:ws,defined:yi,degrees:To,deltaTime:Im,densityFog:function(e,t){return console.warn('THREE.TSL: "densityFog( color, density )" is deprecated. Use "fog( color, densityFogFactor( density ) )" instead.'),wy(e,Ey(t))},densityFogFactor:Ey,depth:Xc,depthPass:(e,t,r)=>Ti(new sy(sy.DEPTH,e,t,r)),difference:sa,diffuseColor:dn,directPointLight:Ob,directionToColor:mh,dispersion:Ln,distance:ra,div:jn,dodge:(...e)=>(console.warn('THREE.TSL: "dodge" has been renamed. Use "blendDodge" instead.'),zf(e)),dot:ia,drawIndex:ec,dynamicBufferAttribute:tu,element:Yi,emissive:cn,equal:Kn,equals:Yo,equirectUV:xh,exp:_o,exp2:vo,expression:gu,faceDirection:ll,faceForward:ba,faceforward:Na,float:Bi,floor:Co,fog:wy,fract:Mo,frameGroup:tn,frameId:Dm,frontFacing:ul,fwidth:qo,gain:(e,t)=>e.lessThan(.5)?Cm(e.mul(2),t).div(2):Hn(1,Cm(Wn(Hn(1,e),2),t).div(2)),gapSize:Mn,getConstNodeType:bi,getCurrentStack:Ci,getDirection:Wp,getDistanceAttenuation:wb,getGeometryRoughness:kh,getNormalFromDepth:yf,getParallaxCorrectNormal:Fx,getRoughness:zh,getScreenPosition:ff,getShIrradianceAt:Ux,getTextureIndex:Nm,getViewPosition:mf,glsl:(e,t)=>fy(e,t,"glsl"),glslFn:(e,t)=>by(e,t,"glsl"),grayscale:jf,greaterThan:Qn,greaterThanEqual:Jn,hash:Rm,highpModelNormalViewMatrix:Ju,highpModelViewMatrix:Zu,hue:Xf,instance:rc,instanceIndex:Yd,instancedArray:(e,t="float")=>{const r=bs(t),s=ys(t),i=new bf(e,r,s);return Nf(i,t,e)},instancedBufferAttribute:ru,instancedDynamicBufferAttribute:su,instancedMesh:ic,int:Fi,inverseSqrt:Ro,inversesqrt:Sa,invocationLocalIndex:Jd,invocationSubgroupIndex:Zd,ior:Fn,iridescence:bn,iridescenceIOR:xn,iridescenceThickness:Tn,ivec2:Di,ivec3:Gi,ivec4:Hi,js:(e,t)=>fy(e,t,"js"),label:Ma,length:Oo,lengthSq:ha,lessThan:Yn,lessThanEqual:Zn,lightPosition:Yy,lightProjectionUV:Xy,lightShadowMatrix:Ky,lightTargetDirection:Jy,lightTargetPosition:Qy,lightViewPosition:Zy,lightingContext:_c,lights:(e=[])=>Ti(new rb).setLights(e),linearDepth:Yc,linearToneMapping:ny,localId:Vy,log:No,log2:So,logarithmicDepthToViewZ:(e,t,r)=>{const s=e.mul(No(r.div(t)));return Bi(Math.E).pow(s).mul(t).negate()},loop:(...e)=>(console.warn("TSL.LoopNode: loop() has been renamed to Loop()."),cc(...e)),luminance:Yf,mat2:qi,mat3:Ki,mat4:Xi,matcapUV:fg,materialAO:Wd,materialAlphaTest:ld,materialAnisotropy:Ed,materialAnisotropyVector:jd,materialAttenuationColor:Dd,materialAttenuationDistance:Id,materialClearcoat:vd,materialClearcoatNormal:Sd,materialClearcoatRoughness:Nd,materialColor:dd,materialDispersion:$d,materialEmissive:hd,materialIOR:Pd,materialIridescence:wd,materialIridescenceIOR:Md,materialIridescenceThickness:Bd,materialLightMap:Hd,materialLineDashOffset:kd,materialLineDashSize:Vd,materialLineGapSize:Od,materialLineScale:Ld,materialLineWidth:Gd,materialMetalness:Td,materialNormal:_d,materialOpacity:pd,materialPointWidth:zd,materialReference:Ll,materialReflectivity:bd,materialRefractionRatio:Tl,materialRotation:Ad,materialRoughness:xd,materialSheen:Rd,materialSheenRoughness:Cd,materialShininess:cd,materialSpecular:gd,materialSpecularColor:fd,materialSpecularIntensity:md,materialSpecularStrength:yd,materialThickness:Ud,materialTransmission:Fd,max:Zo,maxMipLevel:Su,mediumpModelViewMatrix:Qu,metalness:pn,min:Qo,mix:pa,mixElement:Ta,mod:Jo,modInt:qn,modelDirection:$u,modelNormalMatrix:Ku,modelPosition:Wu,modelScale:ju,modelViewMatrix:Yu,modelViewPosition:qu,modelViewProjection:qd,modelWorldMatrix:Hu,modelWorldMatrixInverse:Xu,morphReference:yc,mrt:Am,mul:Wn,mx_aastep:wx,mx_cell_noise_float:(e=Tu())=>px(e.convert("vec2|vec3")),mx_contrast:(e,t=1,r=.5)=>Bi(e).sub(r).mul(t).add(r),mx_fractal_noise_float:(e=Tu(),t=3,r=2,s=.5,i=1)=>mx(e,Fi(t),r,s).mul(i),mx_fractal_noise_vec2:(e=Tu(),t=3,r=2,s=.5,i=1)=>yx(e,Fi(t),r,s).mul(i),mx_fractal_noise_vec3:(e=Tu(),t=3,r=2,s=.5,i=1)=>fx(e,Fi(t),r,s).mul(i),mx_fractal_noise_vec4:(e=Tu(),t=3,r=2,s=.5,i=1)=>bx(e,Fi(t),r,s).mul(i),mx_hsvtorgb:Rx,mx_noise_float:(e=Tu(),t=1,r=0)=>cx(e.convert("vec2|vec3")).mul(t).add(r),mx_noise_vec3:(e=Tu(),t=1,r=0)=>hx(e.convert("vec2|vec3")).mul(t).add(r),mx_noise_vec4:(e=Tu(),t=1,r=0)=>{e=e.convert("vec2|vec3");return $i(hx(e),cx(e.add(Ii(19,73)))).mul(t).add(r)},mx_ramplr:(e,t,r=Tu())=>Mx(e,t,r,"x"),mx_ramptb:(e,t,r=Tu())=>Mx(e,t,r,"y"),mx_rgbtohsv:Cx,mx_safepower:(e,t=1)=>(e=Bi(e)).abs().pow(t).mul(e.sign()),mx_splitlr:(e,t,r,s=Tu())=>Bx(e,t,r,s,"x"),mx_splittb:(e,t,r,s=Tu())=>Bx(e,t,r,s,"y"),mx_srgb_texture_to_lin_rec709:Ex,mx_transform_uv:(e=1,t=0,r=Tu())=>r.mul(e).add(t),mx_worley_noise_float:(e=Tu(),t=1)=>Nx(e.convert("vec2|vec3"),t,Fi(1)),mx_worley_noise_vec2:(e=Tu(),t=1)=>Sx(e.convert("vec2|vec3"),t,Fi(1)),mx_worley_noise_vec3:(e=Tu(),t=1)=>Ax(e.convert("vec2|vec3"),t,Fi(1)),negate:Go,neutralToneMapping:gy,nodeArray:vi,nodeImmutable:Si,nodeObject:Ti,nodeObjects:_i,nodeProxy:Ni,normalFlat:hl,normalGeometry:dl,normalLocal:cl,normalMap:rd,normalView:pl,normalWorld:gl,normalize:wo,not:ro,notEqual:Xn,numWorkgroups:Dy,objectDirection:Lu,objectGroup:sn,objectPosition:Ou,objectScale:Gu,objectViewPosition:ku,objectWorldMatrix:Vu,oneMinus:ko,or:to,orthographicDepthToViewZ:(e,t,r)=>t.sub(r).mul(e).sub(t),oscSawtooth:(e=Pm)=>e.fract(),oscSine:(e=Pm)=>e.add(.75).mul(2*Math.PI).sin().mul(.5).add(.5),oscSquare:(e=Pm)=>e.fract().round(),oscTriangle:(e=Pm)=>e.add(.5).fract().mul(2).sub(1).abs(),output:En,outputStruct:vm,overlay:(...e)=>(console.warn('THREE.TSL: "overlay" has been renamed. Use "blendOverlay" instead.'),Hf(e)),overloadingFn:Um,parabola:Cm,parallaxDirection:Zl,parallaxUV:(e,t)=>e.sub(Zl.mul(t)),parameter:(e,t)=>Ti(new bm(e,t)),pass:(e,t,r)=>Ti(new sy(sy.COLOR,e,t,r)),passTexture:(e,t)=>Ti(new ty(e,t)),pcurve:(e,t,r)=>oa(jn(oa(e,t),$n(oa(e,t),oa(Hn(1,e),r))),1/t),perspectiveDepthToViewZ:jc,pmremTexture:eg,pointUV:Rf,pointWidth:Bn,positionGeometry:el,positionLocal:tl,positionPrevious:rl,positionView:nl,positionViewDirection:ol,positionWorld:sl,positionWorldDirection:il,posterize:Jf,pow:oa,pow2:aa,pow3:ua,pow4:la,property:un,radians:xo,rand:xa,range:Uy,rangeFog:function(e,t,r){return console.warn('THREE.TSL: "rangeFog( color, near, far )" is deprecated. Use "fog( color, rangeFogFactor( near, far ) )" instead.'),wy(e,Cy(t,r))},rangeFogFactor:Cy,reciprocal:Wo,reference:Pl,referenceBuffer:Il,reflect:ta,reflectVector:Nl,reflectView:_l,reflector:e=>Ti(new of(e)),refract:fa,refractVector:Sl,refractView:vl,reinhardToneMapping:oy,remainder:co,remap:cu,remapClamp:hu,renderGroup:rn,renderOutput:yu,rendererReference:Xa,rotate:vg,rotateUV:Lm,roughness:hn,round:Ho,rtt:gf,sRGBTransferEOTF:La,sRGBTransferOETF:Va,sampler:e=>(!0===e.isNode?e:Ru(e)).convert("sampler"),saturate:ma,saturation:qf,screen:(...e)=>(console.warn('THREE.TSL: "screen" has been renamed. Use "blendScreen" instead.'),$f(e)),screenCoordinate:Ec,screenSize:Cc,screenUV:Rc,scriptable:Ay,scriptableValue:Ty,select:Ra,setCurrentStack:Ri,shaderStages:Bs,shadow:Cb,shadowPositionWorld:ib,sharedUniformGroup:en,sheen:fn,sheenRoughness:yn,shiftLeft:uo,shiftRight:lo,shininess:Cn,sign:Vo,sin:Bo,sinc:(e,t)=>Bo(mo.mul(t.mul(e).sub(1))).div(mo.mul(t.mul(e).sub(1))),skinning:e=>Ti(new uc(e)),skinningReference:lc,smoothstep:ya,smoothstepElement:_a,specularColor:An,specularF90:Rn,spherizeUV:Vm,split:(e,t)=>Ti(new Gs(Ti(e),t)),spritesheetUV:zm,sqrt:Ao,stack:Tm,step:ea,storage:Nf,storageBarrier:()=>Gy("storage").append(),storageObject:(e,t,r)=>(console.warn('THREE.TSL: "storageObject()" is deprecated. Use "storage().setPBO( true )" instead.'),Nf(e,t,r).setPBO(!0)),storageTexture:Pf,string:(e="")=>Ti(new Hs(e,"string")),sub:Hn,subgroupIndex:Qd,subgroupSize:Oy,tan:Uo,tangentGeometry:Vl,tangentLocal:Ol,tangentView:Gl,tangentWorld:kl,temp:Ua,texture:Ru,texture3D:Mg,textureBarrier:()=>Gy("texture").append(),textureBicubic:mp,textureCubeUV:jp,textureLoad:Cu,textureSize:vu,textureStore:(e,t,r)=>{const s=Pf(e,t,r);return null!==r&&s.append(),s},thickness:Pn,time:Pm,timerDelta:(e=1)=>(console.warn('TSL: timerDelta() is deprecated. Use "deltaTime" instead.'),Im.mul(e)),timerGlobal:(e=1)=>(console.warn('TSL: timerGlobal() is deprecated. Use "time" instead.'),Pm.mul(e)),timerLocal:(e=1)=>(console.warn('TSL: timerLocal() is deprecated. Use "time" instead.'),Pm.mul(e)),toOutputColorSpace:za,toWorkingColorSpace:$a,toneMapping:Qa,toneMappingExposure:Za,toonOutlinePass:(t,r,s=new e(0,0,0),i=.003,n=1)=>Ti(new iy(t,r,Ti(s),Ti(i),Ti(n))),transformDirection:da,transformNormal:bl,transformNormalToView:xl,transformedBentNormalView:Jl,transformedBitangentView:Xl,transformedBitangentWorld:Yl,transformedClearcoatNormalView:yl,transformedNormalView:ml,transformedNormalWorld:fl,transformedTangentView:zl,transformedTangentWorld:$l,transmission:Un,transpose:Ko,triNoise3D:Mm,triplanarTexture:(...e)=>Hm(...e),triplanarTextures:Hm,trunc:jo,tslFn:(...e)=>(console.warn("TSL.ShaderNode: tslFn() has been renamed to Fn()."),Ai(...e)),uint:Ui,uniform:on,uniformArray:Bl,uniformGroup:Ji,uniforms:(e,t)=>(console.warn("TSL.UniformArrayNode: uniforms() has been renamed to uniformArray()."),Ti(new Ml(e,t))),userData:(e,t,r)=>Ti(new If(e,t,r)),uv:Tu,uvec2:Li,uvec3:ki,uvec4:Wi,varying:Ia,varyingProperty:ln,vec2:Ii,vec3:Oi,vec4:$i,vectorComponents:Fs,velocity:Gf,vertexColor:e=>Ti(new Sf(e)),vertexIndex:Xd,vertexStage:Da,vibrance:Kf,viewZToLogarithmicDepth:qc,viewZToOrthographicDepth:Hc,viewZToPerspectiveDepth:Wc,viewport:wc,viewportBottomLeft:Ic,viewportCoordinate:Bc,viewportDepthTexture:zc,viewportLinearDepth:Qc,viewportMipTexture:Oc,viewportResolution:Uc,viewportSafeUV:Gm,viewportSharedTexture:hh,viewportSize:Mc,viewportTexture:Vc,viewportTopLeft:Pc,viewportUV:Fc,wgsl:(e,t)=>fy(e,t,"wgsl"),wgslFn:(e,t)=>by(e,t,"wgsl"),workgroupArray:(e,t)=>Ti(new zy("Workgroup",e,t)),workgroupBarrier:()=>Gy("workgroup").append(),workgroupId:Ly,workingToColorSpace:Ha,xor:so});const Ix=new ym;class Dx extends Vg{constructor(e,t){super(),this.renderer=e,this.nodes=t}update(e,t,r){const s=this.renderer,i=this.nodes.getBackgroundNode(e)||e.background;let n=!1;if(null===i)s._clearColor.getRGB(Ix,Re),Ix.a=s._clearColor.a;else if(!0===i.isColor)i.getRGB(Ix,Re),Ix.a=1,n=!0;else if(!0===i.isNode){const r=this.get(e),n=i;Ix.copy(s._clearColor);let o=r.backgroundMesh;if(void 0===o){const e=wa($i(n).mul(Bf),{getUV:()=>Ff.mul(gl),getTextureLevel:()=>Mf});let t=qd;t=t.setZ(t.w);const s=new sh;s.name="Background.material",s.side=T,s.depthTest=!1,s.depthWrite=!1,s.fog=!1,s.lights=!1,s.vertexNode=t,s.colorNode=e,r.backgroundMeshNode=e,r.backgroundMesh=o=new k(new Be(1,32,32),s),o.frustumCulled=!1,o.name="Background.mesh",o.onBeforeRender=function(e,t,r){this.matrixWorld.copyPosition(r.matrixWorld)}}const a=n.getCacheKey();r.backgroundCacheKey!==a&&(r.backgroundMeshNode.node=$i(n).mul(Bf),r.backgroundMeshNode.needsUpdate=!0,o.material.needsUpdate=!0,r.backgroundCacheKey=a),t.unshift(o,o.geometry,o.material,0,0,null,null)}else console.error("THREE.Renderer: Unsupported background configuration.",i);if(!0===s.autoClear||!0===n){const e=r.clearColorValue;e.r=Ix.r,e.g=Ix.g,e.b=Ix.b,e.a=Ix.a,!0!==s.backend.isWebGLBackend&&!0!==s.alpha||(e.r*=e.a,e.g*=e.a,e.b*=e.a),r.depthClearValue=s._clearDepth,r.stencilClearValue=s._clearStencil,r.clearColor=!0===s.autoClearColor,r.clearDepth=!0===s.autoClearDepth,r.clearStencil=!0===s.autoClearStencil}else r.clearColor=!1,r.clearDepth=!1,r.clearStencil=!1}}let Lx=0;class Vx{constructor(e="",t=[],r=0,s=[]){this.name=e,this.bindings=t,this.index=r,this.bindingsReference=s,this.id=Lx++}}class Ox{constructor(e,t,r,s,i,n,o,a,u,l=[]){this.vertexShader=e,this.fragmentShader=t,this.computeShader=r,this.transforms=l,this.nodeAttributes=s,this.bindings=i,this.updateNodes=n,this.updateBeforeNodes=o,this.updateAfterNodes=a,this.monitor=u,this.usedTimes=0}createBindings(){const e=[];for(const t of this.bindings){if(!0!==t.bindings[0].groupNode.shared){const r=new Vx(t.name,[],t.index,t);e.push(r);for(const e of t.bindings)r.bindings.push(e.clone())}else e.push(t)}return e}}class Gx{constructor(e,t,r=null){this.isNodeAttribute=!0,this.name=e,this.type=t,this.node=r}}class kx{constructor(e,t,r){this.isNodeUniform=!0,this.name=e,this.type=t,this.node=r.getSelf()}get value(){return this.node.value}set value(e){this.node.value=e}get id(){return this.node.id}get groupNode(){return this.node.groupNode}}class zx{constructor(e,t){this.isNodeVar=!0,this.name=e,this.type=t}}class $x extends zx{constructor(e,t){super(e,t),this.needsInterpolation=!1,this.isNodeVarying=!0}}class Hx{constructor(e,t,r=""){this.name=e,this.type=t,this.code=r,Object.defineProperty(this,"isNodeCode",{value:!0})}}let Wx=0;class jx{constructor(e=null){this.id=Wx++,this.nodesData=new WeakMap,this.parent=e}getData(e){let t=this.nodesData.get(e);return void 0===t&&null!==this.parent&&(t=this.parent.getData(e)),t}setData(e,t){this.nodesData.set(e,t)}}class qx extends Ps{static get type(){return"StructTypeNode"}constructor(e,t){super(),this.name=e,this.types=t,this.isStructTypeNode=!0}getMemberTypes(){return this.types}}class Kx{constructor(e,t){this.name=e,this.value=t,this.boundary=0,this.itemSize=0,this.offset=0}setValue(e){this.value=e}getValue(){return this.value}}class Xx extends Kx{constructor(e,t=0){super(e,t),this.isNumberUniform=!0,this.boundary=4,this.itemSize=1}}class Yx extends Kx{constructor(e,r=new t){super(e,r),this.isVector2Uniform=!0,this.boundary=8,this.itemSize=2}}class Qx extends Kx{constructor(e,t=new r){super(e,t),this.isVector3Uniform=!0,this.boundary=16,this.itemSize=3}}class Zx extends Kx{constructor(e,t=new s){super(e,t),this.isVector4Uniform=!0,this.boundary=16,this.itemSize=4}}class Jx extends Kx{constructor(t,r=new e){super(t,r),this.isColorUniform=!0,this.boundary=16,this.itemSize=3}}class eT extends Kx{constructor(e,t=new i){super(e,t),this.isMatrix3Uniform=!0,this.boundary=48,this.itemSize=12}}class tT extends Kx{constructor(e,t=new n){super(e,t),this.isMatrix4Uniform=!0,this.boundary=64,this.itemSize=16}}class rT extends Xx{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class sT extends Yx{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class iT extends Qx{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class nT extends Zx{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class oT extends Jx{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class aT extends eT{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}class uT extends tT{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}getType(){return this.nodeUniform.type}}const lT=[.125,.215,.35,.446,.526,.582],dT=20,cT=new Te(-1,1,1,-1,0,1),hT=new Ue(90,1),pT=new e;let gT=null,mT=0,fT=0;const yT=(1+Math.sqrt(5))/2,bT=1/yT,xT=[new r(-yT,bT,0),new r(yT,bT,0),new r(-bT,0,yT),new r(bT,0,yT),new r(0,yT,-bT),new r(0,yT,bT),new r(-1,1,-1),new r(1,1,-1),new r(-1,1,1),new r(1,1,1)],TT=[3,1,5,0,4,2],_T=Wp(Tu(),xu("faceIndex")).normalize(),vT=Oi(_T.x,_T.y,_T.z);class NT{constructor(e){this._renderer=e,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._lodPlanes=[],this._sizeLods=[],this._sigmas=[],this._lodMeshes=[],this._blurMaterial=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._backgroundBox=null}get _hasInitialized(){return this._renderer.hasInitialized()}fromScene(e,t=0,r=.1,s=100,i=null){if(this._setSize(256),!1===this._hasInitialized){console.warn("THREE.PMREMGenerator: .fromScene() called before the backend is initialized. Try using .fromSceneAsync() instead.");const n=i||this._allocateTargets();return this.fromSceneAsync(e,t,r,s,n),n}gT=this._renderer.getRenderTarget(),mT=this._renderer.getActiveCubeFace(),fT=this._renderer.getActiveMipmapLevel();const n=i||this._allocateTargets();return n.depthBuffer=!0,this._sceneToCubeUV(e,r,s,n),t>0&&this._blur(n,0,0,t),this._applyPMREM(n),this._cleanup(n),n}async fromSceneAsync(e,t=0,r=.1,s=100,i=null){return!1===this._hasInitialized&&await this._renderer.init(),this.fromScene(e,t,r,s,i)}fromEquirectangular(e,t=null){if(!1===this._hasInitialized){console.warn("THREE.PMREMGenerator: .fromEquirectangular() called before the backend is initialized. Try using .fromEquirectangularAsync() instead."),this._setSizeFromTexture(e);const r=t||this._allocateTargets();return this.fromEquirectangularAsync(e,r),r}return this._fromTexture(e,t)}async fromEquirectangularAsync(e,t=null){return!1===this._hasInitialized&&await this._renderer.init(),this._fromTexture(e,t)}fromCubemap(e,t=null){if(!1===this._hasInitialized){console.warn("THREE.PMREMGenerator: .fromCubemap() called before the backend is initialized. Try using .fromCubemapAsync() instead."),this._setSizeFromTexture(e);const r=t||this._allocateTargets();return this.fromCubemapAsync(e,t),r}return this._fromTexture(e,t)}async fromCubemapAsync(e,t=null){return!1===this._hasInitialized&&await this._renderer.init(),this._fromTexture(e,t)}async compileCubemapShader(){null===this._cubemapMaterial&&(this._cubemapMaterial=CT(),await this._compileMaterial(this._cubemapMaterial))}async compileEquirectangularShader(){null===this._equirectMaterial&&(this._equirectMaterial=ET(),await this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),null!==this._cubemapMaterial&&this._cubemapMaterial.dispose(),null!==this._equirectMaterial&&this._equirectMaterial.dispose(),null!==this._backgroundBox&&(this._backgroundBox.geometry.dispose(),this._backgroundBox.material.dispose())}_setSizeFromTexture(e){e.mapping===_||e.mapping===v?this._setSize(0===e.image.length?16:e.image[0].width||e.image[0].image.width):this._setSize(e.image.width/4)}_setSize(e){this._lodMax=Math.floor(Math.log2(e)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){null!==this._blurMaterial&&this._blurMaterial.dispose(),null!==this._pingPongRenderTarget&&this._pingPongRenderTarget.dispose();for(let e=0;ee-4?u=lT[a-e+4-1]:0===a&&(u=0),s.push(u);const l=1/(o-2),d=-l,c=1+l,h=[d,d,c,d,c,c,d,d,c,c,d,c],p=6,g=6,m=3,f=2,y=1,b=new Float32Array(m*g*p),x=new Float32Array(f*g*p),T=new Float32Array(y*g*p);for(let e=0;e2?0:-1,s=[t,r,0,t+2/3,r,0,t+2/3,r+1,0,t,r,0,t+2/3,r+1,0,t,r+1,0],i=TT[e];b.set(s,m*g*i),x.set(h,f*g*i);const n=[i,i,i,i,i,i];T.set(n,y*g*i)}const _=new _e;_.setAttribute("position",new Ne(b,m)),_.setAttribute("uv",new Ne(x,f)),_.setAttribute("faceIndex",new Ne(T,y)),t.push(_),i.push(new k(_,null)),n>4&&n--}return{lodPlanes:t,sizeLods:r,sigmas:s,lodMeshes:i}}(i)),this._blurMaterial=function(e,t,s){const i=Bl(new Array(dT).fill(0)),n=on(new r(0,1,0)),o=on(0),a=Bi(dT),u=on(0),l=on(1),d=Ru(null),c=on(0),h=Bi(1/t),p=Bi(1/s),g=Bi(e),m={n:a,latitudinal:u,weights:i,poleAxis:n,outputDirection:vT,dTheta:o,samples:l,envMap:d,mipInt:c,CUBEUV_TEXEL_WIDTH:h,CUBEUV_TEXEL_HEIGHT:p,CUBEUV_MAX_MIP:g},f=RT("blur");return f.uniforms=m,f.fragmentNode=Xp({...m,latitudinal:u.equal(1)}),f}(i,e,t)}return i}async _compileMaterial(e){const t=new k(this._lodPlanes[0],e);await this._renderer.compile(t,cT)}_sceneToCubeUV(e,t,r,s){const i=hT;i.near=t,i.far=r;const n=[1,1,1,1,-1,1],o=[1,-1,1,-1,1,-1],a=this._renderer,u=a.autoClear;a.getClearColor(pT),a.autoClear=!1;let l=this._backgroundBox;if(null===l){const e=new Q({name:"PMREM.Background",side:T,depthWrite:!1,depthTest:!1});l=new k(new G,e)}let d=!1;const c=e.background;c?c.isColor&&(l.material.color.copy(c),e.background=null,d=!0):(l.material.color.copy(pT),d=!0),a.setRenderTarget(s),a.clear(),d&&a.render(l,i);for(let t=0;t<6;t++){const r=t%3;0===r?(i.up.set(0,n[t],0),i.lookAt(o[t],0,0)):1===r?(i.up.set(0,0,n[t]),i.lookAt(0,o[t],0)):(i.up.set(0,n[t],0),i.lookAt(0,0,o[t]));const u=this._cubeSize;AT(s,r*u,t>2?u:0,u,u),a.render(e,i)}a.autoClear=u,e.background=c}_textureToCubeUV(e,t){const r=this._renderer,s=e.mapping===_||e.mapping===v;s?null===this._cubemapMaterial&&(this._cubemapMaterial=CT(e)):null===this._equirectMaterial&&(this._equirectMaterial=ET(e));const i=s?this._cubemapMaterial:this._equirectMaterial;i.fragmentNode.value=e;const n=this._lodMeshes[0];n.material=i;const o=this._cubeSize;AT(t,0,0,3*o,2*o),r.setRenderTarget(t),r.render(n,cT)}_applyPMREM(e){const t=this._renderer,r=t.autoClear;t.autoClear=!1;const s=this._lodPlanes.length;for(let t=1;tdT&&console.warn(`sigmaRadians, ${i}, is too large and will clip, as it requested ${g} samples when the maximum is set to 20`);const m=[];let f=0;for(let e=0;ey-4?s-y+4:0),4*(this._cubeSize-b),3*b,2*b),a.setRenderTarget(t),a.render(l,cT)}}function ST(e,t,r){const s=new me(e,t,r);return s.texture.mapping=Fe,s.texture.name="PMREM.cubeUv",s.texture.isPMREMTexture=!0,s.scissorTest=!0,s}function AT(e,t,r,s,i){e.viewport.set(t,r,s,i),e.scissor.set(t,r,s,i)}function RT(e){const t=new sh;return t.depthTest=!1,t.depthWrite=!1,t.blending=L,t.name=`PMREM_${e}`,t}function CT(e){const t=RT("cubemap");return t.fragmentNode=Rl(e,vT),t}function ET(e){const t=RT("equirect");return t.fragmentNode=Ru(e,xh(vT),0),t}const wT=new WeakMap,MT=new Map([[Int8Array,"int"],[Int16Array,"int"],[Int32Array,"int"],[Uint8Array,"uint"],[Uint16Array,"uint"],[Uint32Array,"uint"],[Float32Array,"float"]]),BT=e=>/e/g.test(e)?String(e).replace(/\+/g,""):(e=Number(e))+(e%1?"":".0");class FT{constructor(e,t,r){this.object=e,this.material=e&&e.material||null,this.geometry=e&&e.geometry||null,this.renderer=t,this.parser=r,this.scene=null,this.camera=null,this.nodes=[],this.sequentialNodes=[],this.updateNodes=[],this.updateBeforeNodes=[],this.updateAfterNodes=[],this.hashNodes={},this.monitor=null,this.lightsNode=null,this.environmentNode=null,this.fogNode=null,this.clippingContext=null,this.vertexShader=null,this.fragmentShader=null,this.computeShader=null,this.flowNodes={vertex:[],fragment:[],compute:[]},this.flowCode={vertex:"",fragment:"",compute:""},this.uniforms={vertex:[],fragment:[],compute:[],index:0},this.structs={vertex:[],fragment:[],compute:[],index:0},this.bindings={vertex:{},fragment:{},compute:{}},this.bindingsIndexes={},this.bindGroups=null,this.attributes=[],this.bufferAttributes=[],this.varyings=[],this.codes={},this.vars={},this.flow={code:""},this.chaining=[],this.stack=Tm(),this.stacks=[],this.tab="\t",this.currentFunctionNode=null,this.context={material:this.material},this.cache=new jx,this.globalCache=this.cache,this.flowsData=new WeakMap,this.shaderStage=null,this.buildStage=null,this.useComparisonMethod=!1}getBindGroupsCache(){let e=wT.get(this.renderer);return void 0===e&&(e=new Ug,wT.set(this.renderer,e)),e}createRenderTarget(e,t,r){return new me(e,t,r)}createCubeRenderTarget(e,t){return new Th(e,t)}createPMREMGenerator(){return new NT(this.renderer)}includes(e){return this.nodes.includes(e)}getOutputStructName(){}_getBindGroup(e,t){const r=this.getBindGroupsCache(),s=[];let i,n=!0;for(const e of t)s.push(e),n=n&&!0!==e.groupNode.shared;return n?(i=r.get(s),void 0===i&&(i=new Vx(e,s,this.bindingsIndexes[e].group,s),r.set(s,i))):i=new Vx(e,s,this.bindingsIndexes[e].group,s),i}getBindGroupArray(e,t){const r=this.bindings[t];let s=r[e];return void 0===s&&(void 0===this.bindingsIndexes[e]&&(this.bindingsIndexes[e]={binding:0,group:Object.keys(this.bindingsIndexes).length}),r[e]=s=[]),s}getBindings(){let e=this.bindGroups;if(null===e){const t={},r=this.bindings;for(const e of Bs)for(const s in r[e]){const i=r[e][s];(t[s]||(t[s]=[])).push(...i)}e=[];for(const r in t){const s=t[r],i=this._getBindGroup(r,s);e.push(i)}this.bindGroups=e}return e}sortBindingGroups(){const e=this.getBindings();e.sort(((e,t)=>e.bindings[0].groupNode.order-t.bindings[0].groupNode.order));for(let t=0;t=0?`${Math.round(n)}u`:"0u";if("bool"===i)return n?"true":"false";if("color"===i)return`${this.getType("vec3")}( ${BT(n.r)}, ${BT(n.g)}, ${BT(n.b)} )`;const o=this.getTypeLength(i),a=this.getComponentType(i),u=e=>this.generateConst(a,e);if(2===o)return`${this.getType(i)}( ${u(n.x)}, ${u(n.y)} )`;if(3===o)return`${this.getType(i)}( ${u(n.x)}, ${u(n.y)}, ${u(n.z)} )`;if(4===o)return`${this.getType(i)}( ${u(n.x)}, ${u(n.y)}, ${u(n.z)}, ${u(n.w)} )`;if(o>4&&n&&(n.isMatrix3||n.isMatrix4))return`${this.getType(i)}( ${n.elements.map(u).join(", ")} )`;if(o>4)return`${this.getType(i)}()`;throw new Error(`NodeBuilder: Type '${i}' not found in generate constant attempt.`)}getType(e){return"color"===e?"vec3":e}hasGeometryAttribute(e){return this.geometry&&void 0!==this.geometry.getAttribute(e)}getAttribute(e,t){const r=this.attributes;for(const t of r)if(t.name===e)return t;const s=new Gx(e,t);return r.push(s),s}getPropertyName(e){return e.name}isVector(e){return/vec\d/.test(e)}isMatrix(e){return/mat\d/.test(e)}isReference(e){return"void"===e||"property"===e||"sampler"===e||"texture"===e||"cubeTexture"===e||"storageTexture"===e||"depthTexture"===e||"texture3D"===e}needsToWorkingColorSpace(){return!1}getComponentTypeFromTexture(e){const t=e.type;if(e.isDataTexture){if(t===x)return"int";if(t===b)return"uint"}return"float"}getElementType(e){return"mat2"===e?"vec2":"mat3"===e?"vec3":"mat4"===e?"vec4":this.getComponentType(e)}getComponentType(e){if("float"===(e=this.getVectorType(e))||"bool"===e||"int"===e||"uint"===e)return e;const t=/(b|i|u|)(vec|mat)([2-4])/.exec(e);return null===t?null:"b"===t[1]?"bool":"i"===t[1]?"int":"u"===t[1]?"uint":"float"}getVectorType(e){return"color"===e?"vec3":"texture"===e||"cubeTexture"===e||"storageTexture"===e||"texture3D"===e?"vec4":e}getTypeFromLength(e,t="float"){if(1===e)return t;const r=fs(e);return("float"===t?"":t[0])+r}getTypeFromArray(e){return MT.get(e.constructor)}getTypeFromAttribute(e){let t=e;e.isInterleavedBufferAttribute&&(t=e.data);const r=t.array,s=e.itemSize,i=e.normalized;let n;return e instanceof Le||!0===i||(n=this.getTypeFromArray(r)),this.getTypeFromLength(s,n)}getTypeLength(e){const t=this.getVectorType(e),r=/vec([2-4])/.exec(t);return null!==r?Number(r[1]):"float"===t||"bool"===t||"int"===t||"uint"===t?1:!0===/mat2/.test(e)?4:!0===/mat3/.test(e)?9:!0===/mat4/.test(e)?16:0}getVectorFromMatrix(e){return e.replace("mat","vec")}changeComponentType(e,t){return this.getTypeFromLength(this.getTypeLength(e),t)}getIntegerType(e){const t=this.getComponentType(e);return"int"===t||"uint"===t?e:this.changeComponentType(e,"int")}addStack(){return this.stack=Tm(this.stack),this.stacks.push(Ci()||this.stack),Ri(this.stack),this.stack}removeStack(){const e=this.stack;return this.stack=e.parent,Ri(this.stacks.pop()),e}getDataFromNode(e,t=this.shaderStage,r=null){let s=(r=null===r?e.isGlobal(this)?this.globalCache:this.cache:r).getData(e);return void 0===s&&(s={},r.setData(e,s)),void 0===s[t]&&(s[t]={}),s[t]}getNodeProperties(e,t="any"){const r=this.getDataFromNode(e,t);return r.properties||(r.properties={outputNode:null})}getBufferAttributeFromNode(e,t){const r=this.getDataFromNode(e);let s=r.bufferAttribute;if(void 0===s){const i=this.uniforms.index++;s=new Gx("nodeAttribute"+i,t,e),this.bufferAttributes.push(s),r.bufferAttribute=s}return s}getStructTypeFromNode(e,t,r=this.shaderStage){const s=this.getDataFromNode(e,r);let i=s.structType;if(void 0===i){const e=this.structs.index++;i=new qx("StructType"+e,t),this.structs[r].push(i),s.structType=i}return i}getUniformFromNode(e,t,r=this.shaderStage,s=null){const i=this.getDataFromNode(e,r,this.globalCache);let n=i.uniform;if(void 0===n){const o=this.uniforms.index++;n=new kx(s||"nodeUniform"+o,t,e),this.uniforms[r].push(n),i.uniform=n}return n}getVarFromNode(e,t=null,r=e.getNodeType(this),s=this.shaderStage){const i=this.getDataFromNode(e,s);let n=i.variable;if(void 0===n){const e=this.vars[s]||(this.vars[s]=[]);null===t&&(t="nodeVar"+e.length),n=new zx(t,r),e.push(n),i.variable=n}return n}getVaryingFromNode(e,t=null,r=e.getNodeType(this)){const s=this.getDataFromNode(e,"any");let i=s.varying;if(void 0===i){const e=this.varyings,n=e.length;null===t&&(t="nodeVarying"+n),i=new $x(t,r),e.push(i),s.varying=i}return i}getCodeFromNode(e,t,r=this.shaderStage){const s=this.getDataFromNode(e);let i=s.code;if(void 0===i){const e=this.codes[r]||(this.codes[r]=[]),n=e.length;i=new Hx("nodeCode"+n,t),e.push(i),s.code=i}return i}addFlowCodeHierarchy(e,t){const{flowCodes:r,flowCodeBlock:s}=this.getDataFromNode(e);let i=!0,n=t;for(;n;){if(!0===s.get(n)){i=!1;break}n=this.getDataFromNode(n).parentNodeBlock}if(i)for(const e of r)this.addLineFlowCode(e)}addLineFlowCodeBlock(e,t,r){const s=this.getDataFromNode(e),i=s.flowCodes||(s.flowCodes=[]),n=s.flowCodeBlock||(s.flowCodeBlock=new WeakMap);i.push(t),n.set(r,!0)}addLineFlowCode(e,t=null){return""===e||(null!==t&&this.context.nodeBlock&&this.addLineFlowCodeBlock(t,e,this.context.nodeBlock),e=this.tab+e,/;\s*$/.test(e)||(e+=";\n"),this.flow.code+=e),this}addFlowCode(e){return this.flow.code+=e,this}addFlowTab(){return this.tab+="\t",this}removeFlowTab(){return this.tab=this.tab.slice(0,-1),this}getFlowData(e){return this.flowsData.get(e)}flowNode(e){const t=e.getNodeType(this),r=this.flowChildNode(e,t);return this.flowsData.set(e,r),r}buildFunctionNode(e){const t=new yy,r=this.currentFunctionNode;return this.currentFunctionNode=t,t.code=this.buildFunctionCode(e),this.currentFunctionNode=r,t}flowShaderNode(e){const t=e.layout,r={[Symbol.iterator](){let e=0;const t=Object.values(this);return{next:()=>({value:t[e],done:e++>=t.length})}}};for(const e of t.inputs)r[e.name]=new bm(e.type,e.name);e.layout=null;const s=e.call(r),i=this.flowStagesNode(s,t.type);return e.layout=t,i}flowStagesNode(e,t=null){const r=this.flow,s=this.vars,i=this.cache,n=this.buildStage,o=this.stack,a={code:""};this.flow=a,this.vars={},this.cache=new jx,this.stack=Tm();for(const r of Ms)this.setBuildStage(r),a.result=e.build(this,t);return a.vars=this.getVars(this.shaderStage),this.flow=r,this.vars=s,this.cache=i,this.stack=o,this.setBuildStage(n),a}getFunctionOperator(){return null}flowChildNode(e,t=null){const r=this.flow,s={code:""};return this.flow=s,s.result=e.build(this,t),this.flow=r,s}flowNodeFromShaderStage(e,t,r=null,s=null){const i=this.shaderStage;this.setShaderStage(e);const n=this.flowChildNode(t,r);return null!==s&&(n.code+=`${this.tab+s} = ${n.result};\n`),this.flowCode[e]=this.flowCode[e]+n.code,this.setShaderStage(i),n}getAttributesArray(){return this.attributes.concat(this.bufferAttributes)}getAttributes(){console.warn("Abstract function.")}getVaryings(){console.warn("Abstract function.")}getVar(e,t){return`${this.getType(e)} ${t}`}getVars(e){let t="";const r=this.vars[e];if(void 0!==r)for(const e of r)t+=`${this.getVar(e.type,e.name)}; `;return t}getUniforms(){console.warn("Abstract function.")}getCodes(e){const t=this.codes[e];let r="";if(void 0!==t)for(const e of t)r+=e.code+"\n";return r}getHash(){return this.vertexShader+this.fragmentShader+this.computeShader}setShaderStage(e){this.shaderStage=e}getShaderStage(){return this.shaderStage}setBuildStage(e){this.buildStage=e}getBuildStage(){return this.buildStage}buildCode(){console.warn("Abstract function.")}build(){const{object:e,material:t,renderer:r}=this;if(null!==t){let e=r.library.fromMaterial(t);null===e&&(console.error(`NodeMaterial: Material "${t.type}" is not compatible.`),e=new sh),e.build(this)}else this.addFlow("compute",e);for(const e of Ms){this.setBuildStage(e),this.context.vertex&&this.context.vertex.isNode&&this.flowNodeFromShaderStage("vertex",this.context.vertex);for(const t of Bs){this.setShaderStage(t);const r=this.flowNodes[t];for(const t of r)"generate"===e?this.flowNode(t):t.build(this)}}return this.setBuildStage(null),this.setShaderStage(null),this.buildCode(),this.buildUpdateNodes(),this}getNodeUniform(e,t){if("float"===t||"int"===t||"uint"===t)return new rT(e);if("vec2"===t||"ivec2"===t||"uvec2"===t)return new sT(e);if("vec3"===t||"ivec3"===t||"uvec3"===t)return new iT(e);if("vec4"===t||"ivec4"===t||"uvec4"===t)return new nT(e);if("color"===t)return new oT(e);if("mat3"===t)return new aT(e);if("mat4"===t)return new uT(e);throw new Error(`Uniform "${t}" not declared.`)}format(e,t,r){if((t=this.getVectorType(t))===(r=this.getVectorType(r))||null===r||this.isReference(r))return e;const s=this.getTypeLength(t),i=this.getTypeLength(r);return 16===s&&9===i?`${this.getType(r)}(${e}[0].xyz, ${e}[1].xyz, ${e}[2].xyz)`:9===s&&4===i?`${this.getType(r)}(${e}[0].xy, ${e}[1].xy)`:s>4||i>4||0===i?e:s===i?`${this.getType(r)}( ${e} )`:s>i?this.format(`${e}.${"xyz".slice(0,i)}`,this.getTypeFromLength(i,this.getComponentType(t)),r):4===i&&s>1?`${this.getType(r)}( ${this.format(e,t,"vec3")}, 1.0 )`:2===s?`${this.getType(r)}( ${this.format(e,t,"vec2")}, 0.0 )`:(1===s&&i>1&&t!==this.getComponentType(r)&&(e=`${this.getType(this.getComponentType(r))}( ${e} )`),`${this.getType(r)}( ${e} )`)}getSignature(){return`// Three.js r${Ve} - Node System\n`}createNodeMaterial(e="NodeMaterial"){throw new Error(`THREE.NodeBuilder: createNodeMaterial() was deprecated. Use new ${e}() instead.`)}}class UT{constructor(){this.time=0,this.deltaTime=0,this.frameId=0,this.renderId=0,this.updateMap=new WeakMap,this.updateBeforeMap=new WeakMap,this.updateAfterMap=new WeakMap,this.renderer=null,this.material=null,this.camera=null,this.object=null,this.scene=null}_getMaps(e,t){let r=e.get(t);return void 0===r&&(r={renderMap:new WeakMap,frameMap:new WeakMap},e.set(t,r)),r}updateBeforeNode(e){const t=e.getUpdateBeforeType(),r=e.updateReference(this);if(t===Rs.FRAME){const{frameMap:t}=this._getMaps(this.updateBeforeMap,r);t.get(r)!==this.frameId&&!1!==e.updateBefore(this)&&t.set(r,this.frameId)}else if(t===Rs.RENDER){const{renderMap:t}=this._getMaps(this.updateBeforeMap,r);t.get(r)!==this.renderId&&!1!==e.updateBefore(this)&&t.set(r,this.renderId)}else t===Rs.OBJECT&&e.updateBefore(this)}updateAfterNode(e){const t=e.getUpdateAfterType(),r=e.updateReference(this);if(t===Rs.FRAME){const{frameMap:t}=this._getMaps(this.updateAfterMap,r);t.get(r)!==this.frameId&&!1!==e.updateAfter(this)&&t.set(r,this.frameId)}else if(t===Rs.RENDER){const{renderMap:t}=this._getMaps(this.updateAfterMap,r);t.get(r)!==this.renderId&&!1!==e.updateAfter(this)&&t.set(r,this.renderId)}else t===Rs.OBJECT&&e.updateAfter(this)}updateNode(e){const t=e.getUpdateType(),r=e.updateReference(this);if(t===Rs.FRAME){const{frameMap:t}=this._getMaps(this.updateMap,r);t.get(r)!==this.frameId&&!1!==e.update(this)&&t.set(r,this.frameId)}else if(t===Rs.RENDER){const{renderMap:t}=this._getMaps(this.updateMap,r);t.get(r)!==this.renderId&&!1!==e.update(this)&&t.set(r,this.renderId)}else t===Rs.OBJECT&&e.update(this)}update(){this.frameId++,void 0===this.lastTime&&(this.lastTime=performance.now()),this.deltaTime=(performance.now()-this.lastTime)/1e3,this.lastTime=performance.now(),this.time+=this.deltaTime}}class PT{constructor(e,t,r=null,s="",i=!1){this.type=e,this.name=t,this.count=r,this.qualifier=s,this.isConst=i}}PT.isNodeFunctionInput=!0;class IT extends Eb{static get type(){return"DirectionalLightNode"}constructor(e=null){super(e)}setup(e){super.setup(e);const t=e.context.lightingModel,r=this.colorNode,s=Jy(this.light),i=e.context.reflectedLight;t.direct({lightDirection:s,lightColor:r,reflectedLight:i},e.stack,e)}}const DT=new n,LT=new n;let VT=null;class OT extends Eb{static get type(){return"RectAreaLightNode"}constructor(e=null){super(e),this.halfHeight=on(new r).setGroup(rn),this.halfWidth=on(new r).setGroup(rn),this.updateType=Rs.RENDER}update(e){super.update(e);const{light:t}=this,r=e.camera.matrixWorldInverse;LT.identity(),DT.copy(t.matrixWorld),DT.premultiply(r),LT.extractRotation(DT),this.halfWidth.value.set(.5*t.width,0,0),this.halfHeight.value.set(0,.5*t.height,0),this.halfWidth.value.applyMatrix4(LT),this.halfHeight.value.applyMatrix4(LT)}setup(e){let t,r;super.setup(e),e.isAvailable("float32Filterable")?(t=Ru(VT.LTC_FLOAT_1),r=Ru(VT.LTC_FLOAT_2)):(t=Ru(VT.LTC_HALF_1),r=Ru(VT.LTC_HALF_2));const{colorNode:s,light:i}=this,n=e.context.lightingModel,o=Zy(i),a=e.context.reflectedLight;n.directRectArea({lightColor:s,lightPosition:o,halfWidth:this.halfWidth,halfHeight:this.halfHeight,reflectedLight:a,ltc_1:t,ltc_2:r},e.stack,e)}static setLTC(e){VT=e}}class GT extends Eb{static get type(){return"SpotLightNode"}constructor(e=null){super(e),this.coneCosNode=on(0).setGroup(rn),this.penumbraCosNode=on(0).setGroup(rn),this.cutoffDistanceNode=on(0).setGroup(rn),this.decayExponentNode=on(0).setGroup(rn)}update(e){super.update(e);const{light:t}=this;this.coneCosNode.value=Math.cos(t.angle),this.penumbraCosNode.value=Math.cos(t.angle*(1-t.penumbra)),this.cutoffDistanceNode.value=t.distance,this.decayExponentNode.value=t.decay}getSpotAttenuation(e){const{coneCosNode:t,penumbraCosNode:r}=this;return ya(t,r,e)}setup(e){super.setup(e);const t=e.context.lightingModel,{colorNode:r,cutoffDistanceNode:s,decayExponentNode:i,light:n}=this,o=Zy(n).sub(nl),a=o.normalize(),u=a.dot(Jy(n)),l=this.getSpotAttenuation(u),d=o.length(),c=wb({lightDistance:d,cutoffDistance:s,decayExponent:i});let h=r.mul(l).mul(c);if(n.map){const e=Xy(n),t=Ru(n.map,e.xy).onRenderUpdate((()=>n.map));h=e.mul(2).sub(1).abs().lessThan(1).all().select(h.mul(t),h)}const p=e.context.reflectedLight;t.direct({lightDirection:a,lightColor:h,reflectedLight:p},e.stack,e)}}class kT extends GT{static get type(){return"IESSpotLightNode"}getSpotAttenuation(e){const t=this.light.iesMap;let r=null;if(t&&!0===t.isTexture){const s=e.acos().mul(1/Math.PI);r=Ru(t,Ii(s,0),0).r}else r=super.getSpotAttenuation(e);return r}}class zT extends Eb{static get type(){return"AmbientLightNode"}constructor(e=null){super(e)}setup({context:e}){e.irradiance.addAssign(this.colorNode)}}class $T extends Eb{static get type(){return"HemisphereLightNode"}constructor(t=null){super(t),this.lightPositionNode=Yy(t),this.lightDirectionNode=this.lightPositionNode.normalize(),this.groundColorNode=on(new e).setGroup(rn)}update(e){const{light:t}=this;super.update(e),this.lightPositionNode.object3d=t,this.groundColorNode.value.copy(t.groundColor).multiplyScalar(t.intensity)}setup(e){const{colorNode:t,groundColorNode:r,lightDirectionNode:s}=this,i=pl.dot(s).mul(.5).add(.5),n=pa(r,t,i);e.context.irradiance.addAssign(n)}}class HT extends Eb{static get type(){return"LightProbeNode"}constructor(e=null){super(e);const t=[];for(let e=0;e<9;e++)t.push(new r);this.lightProbe=Bl(t)}update(e){const{light:t}=this;super.update(e);for(let e=0;e<9;e++)this.lightProbe.array[e].copy(t.sh.coefficients[e]).multiplyScalar(t.intensity)}setup(e){const t=Ux(gl,this.lightProbe);e.context.irradiance.addAssign(t)}}class WT{parseFunction(){console.warn("Abstract function.")}}class jT{constructor(e,t,r="",s=""){this.type=e,this.inputs=t,this.name=r,this.precision=s}getCode(){console.warn("Abstract function.")}}jT.isNodeFunction=!0;const qT=/^\s*(highp|mediump|lowp)?\s*([a-z_0-9]+)\s*([a-z_0-9]+)?\s*\(([\s\S]*?)\)/i,KT=/[a-z_0-9]+/gi,XT="#pragma main";class YT extends jT{constructor(e){const{type:t,inputs:r,name:s,precision:i,inputsCode:n,blockCode:o,headerCode:a}=(e=>{const t=(e=e.trim()).indexOf(XT),r=-1!==t?e.slice(t+12):e,s=r.match(qT);if(null!==s&&5===s.length){const i=s[4],n=[];let o=null;for(;null!==(o=KT.exec(i));)n.push(o);const a=[];let u=0;for(;u0||e.backgroundBlurriness>0&&0===t.backgroundBlurriness;if(t.background!==r||s){const i=this.getCacheNode("background",r,(()=>{if(!0===r.isCubeTexture||r.mapping===j||r.mapping===q||r.mapping===Fe){if(e.backgroundBlurriness>0||r.mapping===Fe)return eg(r);{let e;return e=!0===r.isCubeTexture?Rl(r):Ru(r),Ah(e)}}if(!0===r.isTexture)return Ru(r,Rc.flipY()).setUpdateMatrix(!0);!0!==r.isColor&&console.error("WebGPUNodes: Unsupported background configuration.",r)}),s);t.backgroundNode=i,t.background=r,t.backgroundBlurriness=e.backgroundBlurriness}}else t.backgroundNode&&(delete t.backgroundNode,delete t.background)}getCacheNode(e,t,r,s=!1){const i=this.cacheLib[e]||(this.cacheLib[e]=new WeakMap);let n=i.get(t);return(void 0===n||s)&&(n=r(),i.set(t,n)),n}updateFog(e){const t=this.get(e),r=e.fog;if(r){if(t.fog!==r){const e=this.getCacheNode("fog",r,(()=>{if(r.isFogExp2){const e=Pl("color","color",r).setGroup(rn),t=Pl("density","float",r).setGroup(rn);return wy(e,Ey(t))}if(r.isFog){const e=Pl("color","color",r).setGroup(rn),t=Pl("near","float",r).setGroup(rn),s=Pl("far","float",r).setGroup(rn);return wy(e,Cy(t,s))}console.error("THREE.Renderer: Unsupported fog configuration.",r)}));t.fogNode=e,t.fog=r}}else delete t.fogNode,delete t.fog}updateEnvironment(e){const t=this.get(e),r=e.environment;if(r){if(t.environment!==r){const e=this.getCacheNode("environment",r,(()=>!0===r.isCubeTexture?Rl(r):!0===r.isTexture?Ru(r):void console.error("Nodes: Unsupported environment configuration.",r)));t.environmentNode=e,t.environment=r}}else t.environmentNode&&(delete t.environmentNode,delete t.environment)}getNodeFrame(e=this.renderer,t=null,r=null,s=null,i=null){const n=this.nodeFrame;return n.renderer=e,n.scene=t,n.object=r,n.camera=s,n.material=i,n}getNodeFrameForRender(e){return this.getNodeFrame(e.renderer,e.scene,e.object,e.camera,e.material)}getOutputCacheKey(){const e=this.renderer;return e.toneMapping+","+e.currentColorSpace}hasOutputChange(e){return ZT.get(e)!==this.getOutputCacheKey()}getOutputNode(e){const t=this.renderer,r=this.getOutputCacheKey(),s=Ru(e,Rc).renderOutput(t.toneMapping,t.currentColorSpace);return ZT.set(e,r),s}updateBefore(e){const t=e.getNodeBuilderState();for(const r of t.updateBeforeNodes)this.getNodeFrameForRender(e).updateBeforeNode(r)}updateAfter(e){const t=e.getNodeBuilderState();for(const r of t.updateAfterNodes)this.getNodeFrameForRender(e).updateAfterNode(r)}updateForCompute(e){const t=this.getNodeFrame(),r=this.getForCompute(e);for(const e of r.updateNodes)t.updateNode(e)}updateForRender(e){const t=this.getNodeFrameForRender(e),r=e.getNodeBuilderState();for(const e of r.updateNodes)t.updateNode(e)}needsRefresh(e){const t=this.getNodeFrameForRender(e);return e.getMonitor().needsRefresh(e,t)}dispose(){super.dispose(),this.nodeFrame=new UT,this.nodeBuilderCache=new Map,this.cacheLib={}}}const r_=new fe;class s_{constructor(e=null){this.version=0,this.clipIntersection=null,this.cacheKey="",this.shadowPass=!1,this.viewNormalMatrix=new i,this.clippingGroupContexts=new WeakMap,this.intersectionPlanes=[],this.unionPlanes=[],this.parentVersion=null,null!==e&&(this.viewNormalMatrix=e.viewNormalMatrix,this.clippingGroupContexts=e.clippingGroupContexts,this.shadowPass=e.shadowPass,this.viewMatrix=e.viewMatrix)}projectPlanes(e,t,r){const s=e.length;for(let i=0;i{await this.compileAsync(e,t);const s=this._renderLists.get(e,t),i=this._renderContexts.get(e,t,this._renderTarget),n=e.overrideMaterial||r.material,o=this._objects.get(r,n,e,t,s.lightsNode,i,i.clippingContext),{fragmentShader:a,vertexShader:u}=o.getNodeBuilderState();return{fragmentShader:a,vertexShader:u}}}}async init(){if(this._initialized)throw new Error("Renderer: Backend has already been initialized.");return null!==this._initPromise||(this._initPromise=new Promise((async(e,t)=>{let r=this.backend;try{await r.init(this)}catch(e){if(null===this._getFallback)return void t(e);try{this.backend=r=this._getFallback(e),await r.init(this)}catch(e){return void t(e)}}this._nodes=new t_(this,r),this._animation=new Fg(this._nodes,this.info),this._attributes=new Hg(r),this._background=new Dx(this,this._nodes),this._geometries=new qg(this._attributes,this.info),this._textures=new fm(this,r,this.info),this._pipelines=new em(r,this._nodes),this._bindings=new tm(r,this._nodes,this._textures,this._attributes,this._pipelines,this.info),this._objects=new Lg(this,this._nodes,this._geometries,this._pipelines,this._bindings,this.info),this._renderLists=new am(this.lighting),this._bundles=new o_,this._renderContexts=new gm,this._animation.start(),this._initialized=!0,e()}))),this._initPromise}get coordinateSystem(){return this.backend.coordinateSystem}async compileAsync(e,t,r=null){if(!0===this._isDeviceLost)return;!1===this._initialized&&await this.init();const s=this._nodes.nodeFrame,i=s.renderId,n=this._currentRenderContext,o=this._currentRenderObjectFunction,a=this._compilationPromises,u=!0===e.isScene?e:c_;null===r&&(r=e);const l=this._renderTarget,d=this._renderContexts.get(r,t,l),c=this._activeMipmapLevel,h=[];this._currentRenderContext=d,this._currentRenderObjectFunction=this.renderObject,this._handleObjectFunction=this._createObjectPipeline,this._compilationPromises=h,s.renderId++,s.update(),d.depth=this.depth,d.stencil=this.stencil,d.clippingContext||(d.clippingContext=new s_),d.clippingContext.updateGlobal(u,t),u.onBeforeRender(this,e,t,l);const p=this._renderLists.get(e,t);if(p.begin(),this._projectObject(e,t,0,p,d.clippingContext),r!==e&&r.traverseVisible((function(e){e.isLight&&e.layers.test(t.layers)&&p.pushLight(e)})),p.finish(),null!==l){this._textures.updateRenderTarget(l,c);const e=this._textures.get(l);d.textures=e.textures,d.depthTexture=e.depthTexture}else d.textures=null,d.depthTexture=null;this._background.update(u,p,d);const g=p.opaque,m=p.transparent,f=p.transparentDoublePass,y=p.lightsNode;!0===this.opaque&&g.length>0&&this._renderObjects(g,t,u,y),!0===this.transparent&&m.length>0&&this._renderTransparents(m,f,t,u,y),s.renderId=i,this._currentRenderContext=n,this._currentRenderObjectFunction=o,this._compilationPromises=a,this._handleObjectFunction=this._renderObjectDirect,await Promise.all(h)}async renderAsync(e,t){!1===this._initialized&&await this.init();const r=this._renderScene(e,t);await this.backend.resolveTimestampAsync(r,"render")}async waitForGPU(){await this.backend.waitForGPU()}setMRT(e){return this._mrt=e,this}getMRT(){return this._mrt}_onDeviceLost(e){let t=`THREE.WebGPURenderer: ${e.api} Device Lost:\n\nMessage: ${e.message}`;e.reason&&(t+=`\nReason: ${e.reason}`),console.error(t),this._isDeviceLost=!0}_renderBundle(e,t,r){const{bundleGroup:s,camera:i,renderList:n}=e,o=this._currentRenderContext,a=this._bundles.get(s,i),u=this.backend.get(a);void 0===u.renderContexts&&(u.renderContexts=new Set);const l=s.version!==u.version,d=!1===u.renderContexts.has(o)||l;if(u.renderContexts.add(o),d){this.backend.beginBundle(o),(void 0===u.renderObjects||l)&&(u.renderObjects=[]),this._currentRenderBundle=a;const e=n.opaque;!0===this.opaque&&e.length>0&&this._renderObjects(e,i,t,r),this._currentRenderBundle=null,this.backend.finishBundle(o,a),u.version=s.version}else{const{renderObjects:e}=u;for(let t=0,r=e.length;t>=c,p.viewportValue.height>>=c,p.viewportValue.minDepth=b,p.viewportValue.maxDepth=x,p.viewport=!1===p.viewportValue.equals(p_),p.scissorValue.copy(f).multiplyScalar(y).floor(),p.scissor=this._scissorTest&&!1===p.scissorValue.equals(p_),p.scissorValue.width>>=c,p.scissorValue.height>>=c,p.clippingContext||(p.clippingContext=new s_),p.clippingContext.updateGlobal(u,t),u.onBeforeRender(this,e,t,h),m_.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),g_.setFromProjectionMatrix(m_,g);const T=this._renderLists.get(e,t);if(T.begin(),this._projectObject(e,t,0,T,p.clippingContext),T.finish(),!0===this.sortObjects&&T.sort(this._opaqueSort,this._transparentSort),null!==h){this._textures.updateRenderTarget(h,c);const e=this._textures.get(h);p.textures=e.textures,p.depthTexture=e.depthTexture,p.width=e.width,p.height=e.height,p.renderTarget=h,p.depth=h.depthBuffer,p.stencil=h.stencilBuffer}else p.textures=null,p.depthTexture=null,p.width=this.domElement.width,p.height=this.domElement.height,p.depth=this.depth,p.stencil=this.stencil;p.width>>=c,p.height>>=c,p.activeCubeFace=d,p.activeMipmapLevel=c,p.occlusionQueryCount=T.occlusionQueryCount,this._background.update(u,T,p),this.backend.beginRender(p);const{bundles:_,lightsNode:v,transparentDoublePass:N,transparent:S,opaque:A}=T;if(_.length>0&&this._renderBundles(_,u,v),!0===this.opaque&&A.length>0&&this._renderObjects(A,t,u,v),!0===this.transparent&&S.length>0&&this._renderTransparents(S,N,t,u,v),this.backend.finishRender(p),i.renderId=n,this._currentRenderContext=o,this._currentRenderObjectFunction=a,null!==s){this.setRenderTarget(l,d,c);const e=this._quad;this._nodes.hasOutputChange(h.texture)&&(e.material.fragmentNode=this._nodes.getOutputNode(h.texture),e.material.needsUpdate=!0),this._renderScene(e,e.camera,!1)}return u.onAfterRender(this,e,t,h),p}getMaxAnisotropy(){return this.backend.getMaxAnisotropy()}getActiveCubeFace(){return this._activeCubeFace}getActiveMipmapLevel(){return this._activeMipmapLevel}async setAnimationLoop(e){!1===this._initialized&&await this.init(),this._animation.setAnimationLoop(e)}async getArrayBufferAsync(e){return await this.backend.getArrayBufferAsync(e)}getContext(){return this.backend.getContext()}getPixelRatio(){return this._pixelRatio}getDrawingBufferSize(e){return e.set(this._width*this._pixelRatio,this._height*this._pixelRatio).floor()}getSize(e){return e.set(this._width,this._height)}setPixelRatio(e=1){this._pixelRatio!==e&&(this._pixelRatio=e,this.setSize(this._width,this._height,!1))}setDrawingBufferSize(e,t,r){this._width=e,this._height=t,this._pixelRatio=r,this.domElement.width=Math.floor(e*r),this.domElement.height=Math.floor(t*r),this.setViewport(0,0,e,t),this._initialized&&this.backend.updateSize()}setSize(e,t,r=!0){this._width=e,this._height=t,this.domElement.width=Math.floor(e*this._pixelRatio),this.domElement.height=Math.floor(t*this._pixelRatio),!0===r&&(this.domElement.style.width=e+"px",this.domElement.style.height=t+"px"),this.setViewport(0,0,e,t),this._initialized&&this.backend.updateSize()}setOpaqueSort(e){this._opaqueSort=e}setTransparentSort(e){this._transparentSort=e}getScissor(e){const t=this._scissor;return e.x=t.x,e.y=t.y,e.width=t.width,e.height=t.height,e}setScissor(e,t,r,s){const i=this._scissor;e.isVector4?i.copy(e):i.set(e,t,r,s)}getScissorTest(){return this._scissorTest}setScissorTest(e){this._scissorTest=e,this.backend.setScissorTest(e)}getViewport(e){return e.copy(this._viewport)}setViewport(e,t,r,s,i=0,n=1){const o=this._viewport;e.isVector4?o.copy(e):o.set(e,t,r,s),o.minDepth=i,o.maxDepth=n}getClearColor(e){return e.copy(this._clearColor)}setClearColor(e,t=1){this._clearColor.set(e),this._clearColor.a=t}getClearAlpha(){return this._clearColor.a}setClearAlpha(e){this._clearColor.a=e}getClearDepth(){return this._clearDepth}setClearDepth(e){this._clearDepth=e}getClearStencil(){return this._clearStencil}setClearStencil(e){this._clearStencil=e}isOccluded(e){const t=this._currentRenderContext;return t&&this.backend.isOccluded(t,e)}clear(e=!0,t=!0,r=!0){if(!1===this._initialized)return console.warn("THREE.Renderer: .clear() called before the backend is initialized. Try using .clearAsync() instead."),this.clearAsync(e,t,r);const s=this._renderTarget||this._getFrameBufferTarget();let i=null;if(null!==s){this._textures.updateRenderTarget(s);const e=this._textures.get(s);i=this._renderContexts.getForClear(s),i.textures=e.textures,i.depthTexture=e.depthTexture,i.width=e.width,i.height=e.height,i.renderTarget=s,i.depth=s.depthBuffer,i.stencil=s.stencilBuffer}if(this.backend.clear(e,t,r,i),null!==s&&null===this._renderTarget){const e=this._quad;this._nodes.hasOutputChange(s.texture)&&(e.material.fragmentNode=this._nodes.getOutputNode(s.texture),e.material.needsUpdate=!0),this._renderScene(e,e.camera,!1)}}clearColor(){return this.clear(!0,!1,!1)}clearDepth(){return this.clear(!1,!0,!1)}clearStencil(){return this.clear(!1,!1,!0)}async clearAsync(e=!0,t=!0,r=!0){!1===this._initialized&&await this.init(),this.clear(e,t,r)}async clearColorAsync(){this.clearAsync(!0,!1,!1)}async clearDepthAsync(){this.clearAsync(!1,!0,!1)}async clearStencilAsync(){this.clearAsync(!1,!1,!0)}get currentToneMapping(){return null!==this._renderTarget?h:this.toneMapping}get currentColorSpace(){return null!==this._renderTarget?Re:this.outputColorSpace}dispose(){this.info.dispose(),this.backend.dispose(),this._animation.dispose(),this._objects.dispose(),this._pipelines.dispose(),this._nodes.dispose(),this._bindings.dispose(),this._renderLists.dispose(),this._renderContexts.dispose(),this._textures.dispose(),this.setRenderTarget(null),this.setAnimationLoop(null)}setRenderTarget(e,t=0,r=0){this._renderTarget=e,this._activeCubeFace=t,this._activeMipmapLevel=r}getRenderTarget(){return this._renderTarget}setRenderObjectFunction(e){this._renderObjectFunction=e}getRenderObjectFunction(){return this._renderObjectFunction}compute(e){if(!0===this.isDeviceLost)return;if(!1===this._initialized)return console.warn("THREE.Renderer: .compute() called before the backend is initialized. Try using .computeAsync() instead."),this.computeAsync(e);const t=this._nodes.nodeFrame,r=t.renderId;this.info.calls++,this.info.compute.calls++,this.info.compute.frameCalls++,t.renderId=this.info.calls;const s=this.backend,i=this._pipelines,n=this._bindings,o=this._nodes,a=Array.isArray(e)?e:[e];if(void 0===a[0]||!0!==a[0].isComputeNode)throw new Error("THREE.Renderer: .compute() expects a ComputeNode.");s.beginCompute(e);for(const t of a){if(!1===i.has(t)){const e=()=>{t.removeEventListener("dispose",e),i.delete(t),n.delete(t),o.delete(t)};t.addEventListener("dispose",e);const r=t.onInitFunction;null!==r&&r.call(t,{renderer:this})}o.updateForCompute(t),n.updateForCompute(t);const r=n.getForCompute(t),a=i.getForCompute(t,r);s.compute(e,t,r,a)}s.finishCompute(e),t.renderId=r}async computeAsync(e){!1===this._initialized&&await this.init(),this.compute(e),await this.backend.resolveTimestampAsync(e,"compute")}async hasFeatureAsync(e){return!1===this._initialized&&await this.init(),this.backend.hasFeature(e)}hasFeature(e){return!1===this._initialized?(console.warn("THREE.Renderer: .hasFeature() called before the backend is initialized. Try using .hasFeatureAsync() instead."),!1):this.backend.hasFeature(e)}hasInitialized(){return this._initialized}async initTextureAsync(e){!1===this._initialized&&await this.init(),this._textures.updateTexture(e)}initTexture(e){!1===this._initialized&&console.warn("THREE.Renderer: .initTexture() called before the backend is initialized. Try using .initTextureAsync() instead."),this._textures.updateTexture(e)}copyFramebufferToTexture(e,t=null){if(null!==t)if(t.isVector2)t=f_.set(t.x,t.y,e.image.width,e.image.height).floor();else{if(!t.isVector4)return void console.error("THREE.Renderer.copyFramebufferToTexture: Invalid rectangle.");t=f_.copy(t).floor()}else t=f_.set(0,0,e.image.width,e.image.height);let r,s=this._currentRenderContext;null!==s?r=s.renderTarget:(r=this._renderTarget||this._getFrameBufferTarget(),null!==r&&(this._textures.updateRenderTarget(r),s=this._textures.get(r))),this._textures.updateTexture(e,{renderTarget:r}),this.backend.copyFramebufferToTexture(e,s,t)}copyTextureToTexture(e,t,r=null,s=null,i=0){this._textures.updateTexture(e),this._textures.updateTexture(t),this.backend.copyTextureToTexture(e,t,r,s,i)}async readRenderTargetPixelsAsync(e,t,r,s,i,n=0,o=0){return this.backend.copyTextureToBuffer(e.textures[n],t,r,s,i,o)}_projectObject(e,t,r,s,i){if(!1===e.visible)return;if(e.layers.test(t.layers))if(e.isGroup)r=e.renderOrder,e.isClippingGroup&&e.enabled&&(i=i.getGroupContext(e));else if(e.isLOD)!0===e.autoUpdate&&e.update(t);else if(e.isLight)s.pushLight(e);else if(e.isSprite){if(!e.frustumCulled||g_.intersectsSprite(e)){!0===this.sortObjects&&f_.setFromMatrixPosition(e.matrixWorld).applyMatrix4(m_);const{geometry:t,material:n}=e;n.visible&&s.push(e,t,n,r,f_.z,null,i)}}else if(e.isLineLoop)console.error("THREE.Renderer: Objects of type THREE.LineLoop are not supported. Please use THREE.Line or THREE.LineSegments.");else if((e.isMesh||e.isLine||e.isPoints)&&(!e.frustumCulled||g_.intersectsObject(e))){const{geometry:t,material:n}=e;if(!0===this.sortObjects&&(null===t.boundingSphere&&t.computeBoundingSphere(),f_.copy(t.boundingSphere.center).applyMatrix4(e.matrixWorld).applyMatrix4(m_)),Array.isArray(n)){const o=t.groups;for(let a=0,u=o.length;a0){for(const{material:e}of t)e.side=T;this._renderObjects(t,r,s,i,"backSide");for(const{material:e}of t)e.side=ke;this._renderObjects(e,r,s,i);for(const{material:e}of t)e.side=le}else this._renderObjects(e,r,s,i)}_renderObjects(e,t,r,s,i=null){for(let n=0,o=e.length;n0,e.isShadowNodeMaterial&&(e.side=null===i.shadowSide?i.side:i.shadowSide,i.depthNode&&i.depthNode.isNode&&(c=e.depthNode,e.depthNode=i.depthNode),i.castShadowNode&&i.castShadowNode.isNode&&(d=e.colorNode,e.colorNode=i.castShadowNode)),i=e}!0===i.transparent&&i.side===le&&!1===i.forceSinglePass?(i.side=T,this._handleObjectFunction(e,i,t,r,o,n,a,"backSide"),i.side=ke,this._handleObjectFunction(e,i,t,r,o,n,a,u),i.side=le):this._handleObjectFunction(e,i,t,r,o,n,a,u),void 0!==l&&(t.overrideMaterial.positionNode=l),void 0!==c&&(t.overrideMaterial.depthNode=c),void 0!==d&&(t.overrideMaterial.colorNode=d),e.onAfterRender(this,t,r,s,i,n)}_renderObjectDirect(e,t,r,s,i,n,o,a){const u=this._objects.get(e,t,r,s,i,this._currentRenderContext,o,a);u.drawRange=e.geometry.drawRange,u.group=n;const l=this._nodes.needsRefresh(u);if(l&&(this._nodes.updateBefore(u),this._geometries.updateForRender(u),this._nodes.updateForRender(u),this._bindings.updateForRender(u)),this._pipelines.updateForRender(u),null!==this._currentRenderBundle){this.backend.get(this._currentRenderBundle).renderObjects.push(u),u.bundle=this._currentRenderBundle.bundleGroup}this.backend.draw(u,this.info),l&&this._nodes.updateAfter(u)}_createObjectPipeline(e,t,r,s,i,n,o,a){const u=this._objects.get(e,t,r,s,i,this._currentRenderContext,o,a);u.drawRange=e.geometry.drawRange,u.group=n,this._nodes.updateBefore(u),this._geometries.updateForRender(u),this._nodes.updateForRender(u),this._bindings.updateForRender(u),this._pipelines.getForRender(u,this._compilationPromises),this._nodes.updateAfter(u)}get compile(){return this.compileAsync}}class b_{constructor(e=""){this.name=e,this.visibility=0}setVisibility(e){this.visibility|=e}clone(){return Object.assign(new this.constructor,this)}}class x_ extends b_{constructor(e,t=null){super(e),this.isBuffer=!0,this.bytesPerElement=Float32Array.BYTES_PER_ELEMENT,this._buffer=t}get byteLength(){return(e=this._buffer.byteLength)+($g-e%$g)%$g;var e}get buffer(){return this._buffer}update(){return!0}}class T_ extends x_{constructor(e,t=null){super(e,t),this.isUniformBuffer=!0}}let __=0;class v_ extends T_{constructor(e,t){super("UniformBuffer_"+__++,e?e.value:null),this.nodeUniform=e,this.groupNode=t}get buffer(){return this.nodeUniform.value}}class N_ extends T_{constructor(e){super(e),this.isUniformsGroup=!0,this._values=null,this.uniforms=[]}addUniform(e){return this.uniforms.push(e),this}removeUniform(e){const t=this.uniforms.indexOf(e);return-1!==t&&this.uniforms.splice(t,1),this}get values(){return null===this._values&&(this._values=Array.from(this.buffer)),this._values}get buffer(){let e=this._buffer;if(null===e){const t=this.byteLength;e=new Float32Array(new ArrayBuffer(t)),this._buffer=e}return e}get byteLength(){let e=0;for(let t=0,r=this.uniforms.length;t0?s:"";t=`${e.name} {\n\t${r} ${i.name}[${n}];\n};\n`}else{t=`${this.getVectorType(i.type)} ${this.getPropertyName(i,e)};`,n=!0}const o=i.node.precision;if(null!==o&&(t=F_[o]+" "+t),n){t="\t"+t;const e=i.groupNode.name;(s[e]||(s[e]=[])).push(t)}else t="uniform "+t,r.push(t)}let i="";for(const t in s){const r=s[t];i+=this._getGLSLUniformStruct(e+"_"+t,r.join("\n"))+"\n"}return i+=r.join("\n"),i}getTypeFromAttribute(e){let t=super.getTypeFromAttribute(e);if(/^[iu]/.test(t)&&e.gpuType!==x){let r=e;e.isInterleavedBufferAttribute&&(r=e.data);const s=r.array;!1==(s instanceof Uint32Array||s instanceof Int32Array)&&(t=t.slice(1))}return t}getAttributes(e){let t="";if("vertex"===e||"compute"===e){const e=this.getAttributesArray();let r=0;for(const s of e)t+=`layout( location = ${r++} ) in ${s.type} ${s.name};\n`}return t}getStructMembers(e){const t=[],r=e.getMemberTypes();for(let e=0;ee*t),1)}u`}getDrawIndex(){return this.renderer.backend.extensions.has("WEBGL_multi_draw")?"uint( gl_DrawID )":null}getFrontFacing(){return"gl_FrontFacing"}getFragCoord(){return"gl_FragCoord.xy"}getFragDepth(){return"gl_FragDepth"}enableExtension(e,t,r=this.shaderStage){const s=this.extensions[r]||(this.extensions[r]=new Map);!1===s.has(e)&&s.set(e,{name:e,behavior:t})}getExtensions(e){const t=[];if("vertex"===e){const t=this.renderer.backend.extensions;this.object.isBatchedMesh&&t.has("WEBGL_multi_draw")&&this.enableExtension("GL_ANGLE_multi_draw","require",e)}const r=this.extensions[e];if(void 0!==r)for(const{name:e,behavior:s}of r.values())t.push(`#extension ${e} : ${s}`);return t.join("\n")}getClipDistance(){return"gl_ClipDistance"}isAvailable(e){let t=U_[e];if(void 0===t){let r;switch(t=!1,e){case"float32Filterable":r="OES_texture_float_linear";break;case"clipDistance":r="WEBGL_clip_cull_distance"}if(void 0!==r){const e=this.renderer.backend.extensions;e.has(r)&&(e.get(r),t=!0)}U_[e]=t}return t}isFlipY(){return!0}enableHardwareClipping(e){this.enableExtension("GL_ANGLE_clip_cull_distance","require"),this.builtins.vertex.push(`out float gl_ClipDistance[ ${e} ]`)}registerTransform(e,t){this.transforms.push({varyingName:e,attributeNode:t})}getTransforms(){const e=this.transforms;let t="";for(let r=0;r0&&(r+="\n"),r+=`\t// flow -> ${n}\n\t`),r+=`${s.code}\n\t`,e===i&&"compute"!==t&&(r+="// result\n\t","vertex"===t?(r+="gl_Position = ",r+=`${s.result};`):"fragment"===t&&(e.outputNode.isOutputStructNode||(r+="fragColor = ",r+=`${s.result};`)))}const n=e[t];n.extensions=this.getExtensions(t),n.uniforms=this.getUniforms(t),n.attributes=this.getAttributes(t),n.varyings=this.getVaryings(t),n.vars=this.getVars(t),n.structs=this.getStructs(t),n.codes=this.getCodes(t),n.transforms=this.getTransforms(t),n.flow=r}null!==this.material?(this.vertexShader=this._getGLSLVertexCode(e.vertex),this.fragmentShader=this._getGLSLFragmentCode(e.fragment)):this.computeShader=this._getGLSLVertexCode(e.compute)}getUniformFromNode(e,t,r,s=null){const i=super.getUniformFromNode(e,t,r,s),n=this.getDataFromNode(e,r,this.globalCache);let o=n.uniformGPU;if(void 0===o){const s=e.groupNode,a=s.name,u=this.getBindGroupArray(a,r);if("texture"===t)o=new E_(i.name,i.node,s),u.push(o);else if("cubeTexture"===t)o=new w_(i.name,i.node,s),u.push(o);else if("texture3D"===t)o=new M_(i.name,i.node,s),u.push(o);else if("buffer"===t){e.name=`NodeBuffer_${e.id}`,i.name=`buffer${e.id}`;const t=new v_(e,s);t.name=e.name,u.push(t),o=t}else{const e=this.uniformGroups[r]||(this.uniformGroups[r]={});let n=e[a];void 0===n&&(n=new A_(r+"_"+a,s),e[a]=n,u.push(n)),o=this.getNodeUniform(i,t),n.addUniform(o)}n.uniformGPU=o}return i}}let D_=null,L_=null;class V_{constructor(e={}){this.parameters=Object.assign({},e),this.data=new WeakMap,this.renderer=null,this.domElement=null}async init(e){this.renderer=e}get coordinateSystem(){}beginRender(){}finishRender(){}beginCompute(){}finishCompute(){}draw(){}compute(){}createProgram(){}destroyProgram(){}createBindings(){}updateBindings(){}updateBinding(){}createRenderPipeline(){}createComputePipeline(){}needsRenderUpdate(){}getRenderCacheKey(){}createNodeBuilder(){}createSampler(){}destroySampler(){}createDefaultTexture(){}createTexture(){}updateTexture(){}generateMipmaps(){}destroyTexture(){}async copyTextureToBuffer(){}copyTextureToTexture(){}copyFramebufferToTexture(){}createAttribute(){}createIndexAttribute(){}createStorageAttribute(){}updateAttribute(){}destroyAttribute(){}getContext(){}updateSize(){}updateViewport(){}isOccluded(){}async resolveTimestampAsync(){}async waitForGPU(){}async getArrayBufferAsync(){}async hasFeatureAsync(){}hasFeature(){}getMaxAnisotropy(){}getDrawingBufferSize(){return D_=D_||new t,this.renderer.getDrawingBufferSize(D_)}setScissorTest(){}getClearColor(){const e=this.renderer;return L_=L_||new ym,e.getClearColor(L_),L_.getRGB(L_,this.renderer.currentColorSpace),L_}getDomElement(){let e=this.domElement;return null===e&&(e=void 0!==this.parameters.canvas?this.parameters.canvas:Je(),"setAttribute"in e&&e.setAttribute("data-engine",`three.js r${Ve} webgpu`),this.domElement=e),e}set(e,t){this.data.set(e,t)}get(e){let t=this.data.get(e);return void 0===t&&(t={},this.data.set(e,t)),t}has(e){return this.data.has(e)}delete(e){this.data.delete(e)}dispose(){}}let O_=0;class G_{constructor(e,t){this.buffers=[e.bufferGPU,t],this.type=e.type,this.bufferType=e.bufferType,this.pbo=e.pbo,this.byteLength=e.byteLength,this.bytesPerElement=e.BYTES_PER_ELEMENT,this.version=e.version,this.isInteger=e.isInteger,this.activeBufferIndex=0,this.baseId=e.id}get id(){return`${this.baseId}|${this.activeBufferIndex}`}get bufferGPU(){return this.buffers[this.activeBufferIndex]}get transformBuffer(){return this.buffers[1^this.activeBufferIndex]}switchBuffers(){this.activeBufferIndex^=1}}class k_{constructor(e){this.backend=e}createAttribute(e,t){const r=this.backend,{gl:s}=r,i=e.array,n=e.usage||s.STATIC_DRAW,o=e.isInterleavedBufferAttribute?e.data:e,a=r.get(o);let u,l=a.bufferGPU;if(void 0===l&&(l=this._createBuffer(s,t,i,n),a.bufferGPU=l,a.bufferType=t,a.version=o.version),i instanceof Float32Array)u=s.FLOAT;else if(i instanceof Uint16Array)u=e.isFloat16BufferAttribute?s.HALF_FLOAT:s.UNSIGNED_SHORT;else if(i instanceof Int16Array)u=s.SHORT;else if(i instanceof Uint32Array)u=s.UNSIGNED_INT;else if(i instanceof Int32Array)u=s.INT;else if(i instanceof Int8Array)u=s.BYTE;else if(i instanceof Uint8Array)u=s.UNSIGNED_BYTE;else{if(!(i instanceof Uint8ClampedArray))throw new Error("THREE.WebGLBackend: Unsupported buffer data format: "+i);u=s.UNSIGNED_BYTE}let d={bufferGPU:l,bufferType:t,type:u,byteLength:i.byteLength,bytesPerElement:i.BYTES_PER_ELEMENT,version:e.version,pbo:e.pbo,isInteger:u===s.INT||u===s.UNSIGNED_INT||e.gpuType===x,id:O_++};if(e.isStorageBufferAttribute||e.isStorageInstancedBufferAttribute){const e=this._createBuffer(s,t,i,n);d=new G_(d,e)}r.set(e,d)}updateAttribute(e){const t=this.backend,{gl:r}=t,s=e.array,i=e.isInterleavedBufferAttribute?e.data:e,n=t.get(i),o=n.bufferType,a=e.isInterleavedBufferAttribute?e.data.updateRanges:e.updateRanges;if(r.bindBuffer(o,n.bufferGPU),0===a.length)r.bufferSubData(o,0,s);else{for(let e=0,t=a.length;e1?this.enable(s.SAMPLE_ALPHA_TO_COVERAGE):this.disable(s.SAMPLE_ALPHA_TO_COVERAGE),r>0&&this.currentClippingPlanes!==r){const e=12288;for(let t=0;t<8;t++)t{!function i(){const n=e.clientWaitSync(t,e.SYNC_FLUSH_COMMANDS_BIT,0);if(n===e.WAIT_FAILED)return e.deleteSync(t),void s();n!==e.TIMEOUT_EXPIRED?(e.deleteSync(t),r()):requestAnimationFrame(i)}()}))}}let q_,K_,X_,Y_=!1;class Q_{constructor(e){this.backend=e,this.gl=e.gl,this.extensions=e.extensions,this.defaultTextures={},!1===Y_&&(this._init(),Y_=!0)}_init(){const e=this.gl;q_={[cr]:e.REPEAT,[hr]:e.CLAMP_TO_EDGE,[pr]:e.MIRRORED_REPEAT},K_={[gr]:e.NEAREST,[mr]:e.NEAREST_MIPMAP_NEAREST,[De]:e.NEAREST_MIPMAP_LINEAR,[$]:e.LINEAR,[Ie]:e.LINEAR_MIPMAP_NEAREST,[M]:e.LINEAR_MIPMAP_LINEAR},X_={[fr]:e.NEVER,[yr]:e.ALWAYS,[Ce]:e.LESS,[br]:e.LEQUAL,[xr]:e.EQUAL,[Tr]:e.GEQUAL,[_r]:e.GREATER,[vr]:e.NOTEQUAL}}getGLTextureType(e){const{gl:t}=this;let r;return r=!0===e.isCubeTexture?t.TEXTURE_CUBE_MAP:!0===e.isDataArrayTexture||!0===e.isCompressedArrayTexture?t.TEXTURE_2D_ARRAY:!0===e.isData3DTexture?t.TEXTURE_3D:t.TEXTURE_2D,r}getInternalFormat(e,t,r,s,i=!1){const{gl:n,extensions:o}=this;if(null!==e){if(void 0!==n[e])return n[e];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+e+"'")}let a=t;return t===n.RED&&(r===n.FLOAT&&(a=n.R32F),r===n.HALF_FLOAT&&(a=n.R16F),r===n.UNSIGNED_BYTE&&(a=n.R8),r===n.UNSIGNED_SHORT&&(a=n.R16),r===n.UNSIGNED_INT&&(a=n.R32UI),r===n.BYTE&&(a=n.R8I),r===n.SHORT&&(a=n.R16I),r===n.INT&&(a=n.R32I)),t===n.RED_INTEGER&&(r===n.UNSIGNED_BYTE&&(a=n.R8UI),r===n.UNSIGNED_SHORT&&(a=n.R16UI),r===n.UNSIGNED_INT&&(a=n.R32UI),r===n.BYTE&&(a=n.R8I),r===n.SHORT&&(a=n.R16I),r===n.INT&&(a=n.R32I)),t===n.RG&&(r===n.FLOAT&&(a=n.RG32F),r===n.HALF_FLOAT&&(a=n.RG16F),r===n.UNSIGNED_BYTE&&(a=n.RG8),r===n.UNSIGNED_SHORT&&(a=n.RG16),r===n.UNSIGNED_INT&&(a=n.RG32UI),r===n.BYTE&&(a=n.RG8I),r===n.SHORT&&(a=n.RG16I),r===n.INT&&(a=n.RG32I)),t===n.RG_INTEGER&&(r===n.UNSIGNED_BYTE&&(a=n.RG8UI),r===n.UNSIGNED_SHORT&&(a=n.RG16UI),r===n.UNSIGNED_INT&&(a=n.RG32UI),r===n.BYTE&&(a=n.RG8I),r===n.SHORT&&(a=n.RG16I),r===n.INT&&(a=n.RG32I)),t===n.RGB&&(r===n.FLOAT&&(a=n.RGB32F),r===n.HALF_FLOAT&&(a=n.RGB16F),r===n.UNSIGNED_BYTE&&(a=n.RGB8),r===n.UNSIGNED_SHORT&&(a=n.RGB16),r===n.UNSIGNED_INT&&(a=n.RGB32UI),r===n.BYTE&&(a=n.RGB8I),r===n.SHORT&&(a=n.RGB16I),r===n.INT&&(a=n.RGB32I),r===n.UNSIGNED_BYTE&&(a=s===Oe&&!1===i?n.SRGB8:n.RGB8),r===n.UNSIGNED_SHORT_5_6_5&&(a=n.RGB565),r===n.UNSIGNED_SHORT_5_5_5_1&&(a=n.RGB5_A1),r===n.UNSIGNED_SHORT_4_4_4_4&&(a=n.RGB4),r===n.UNSIGNED_INT_5_9_9_9_REV&&(a=n.RGB9_E5)),t===n.RGB_INTEGER&&(r===n.UNSIGNED_BYTE&&(a=n.RGB8UI),r===n.UNSIGNED_SHORT&&(a=n.RGB16UI),r===n.UNSIGNED_INT&&(a=n.RGB32UI),r===n.BYTE&&(a=n.RGB8I),r===n.SHORT&&(a=n.RGB16I),r===n.INT&&(a=n.RGB32I)),t===n.RGBA&&(r===n.FLOAT&&(a=n.RGBA32F),r===n.HALF_FLOAT&&(a=n.RGBA16F),r===n.UNSIGNED_BYTE&&(a=n.RGBA8),r===n.UNSIGNED_SHORT&&(a=n.RGBA16),r===n.UNSIGNED_INT&&(a=n.RGBA32UI),r===n.BYTE&&(a=n.RGBA8I),r===n.SHORT&&(a=n.RGBA16I),r===n.INT&&(a=n.RGBA32I),r===n.UNSIGNED_BYTE&&(a=s===Oe&&!1===i?n.SRGB8_ALPHA8:n.RGBA8),r===n.UNSIGNED_SHORT_4_4_4_4&&(a=n.RGBA4),r===n.UNSIGNED_SHORT_5_5_5_1&&(a=n.RGB5_A1)),t===n.RGBA_INTEGER&&(r===n.UNSIGNED_BYTE&&(a=n.RGBA8UI),r===n.UNSIGNED_SHORT&&(a=n.RGBA16UI),r===n.UNSIGNED_INT&&(a=n.RGBA32UI),r===n.BYTE&&(a=n.RGBA8I),r===n.SHORT&&(a=n.RGBA16I),r===n.INT&&(a=n.RGBA32I)),t===n.DEPTH_COMPONENT&&(r===n.UNSIGNED_INT&&(a=n.DEPTH24_STENCIL8),r===n.FLOAT&&(a=n.DEPTH_COMPONENT32F)),t===n.DEPTH_STENCIL&&r===n.UNSIGNED_INT_24_8&&(a=n.DEPTH24_STENCIL8),a!==n.R16F&&a!==n.R32F&&a!==n.RG16F&&a!==n.RG32F&&a!==n.RGBA16F&&a!==n.RGBA32F||o.get("EXT_color_buffer_float"),a}setTextureParameters(e,t){const{gl:r,extensions:s,backend:i}=this;r.pixelStorei(r.UNPACK_FLIP_Y_WEBGL,t.flipY),r.pixelStorei(r.UNPACK_PREMULTIPLY_ALPHA_WEBGL,t.premultiplyAlpha),r.pixelStorei(r.UNPACK_ALIGNMENT,t.unpackAlignment),r.pixelStorei(r.UNPACK_COLORSPACE_CONVERSION_WEBGL,r.NONE),r.texParameteri(e,r.TEXTURE_WRAP_S,q_[t.wrapS]),r.texParameteri(e,r.TEXTURE_WRAP_T,q_[t.wrapT]),e!==r.TEXTURE_3D&&e!==r.TEXTURE_2D_ARRAY||r.texParameteri(e,r.TEXTURE_WRAP_R,q_[t.wrapR]),r.texParameteri(e,r.TEXTURE_MAG_FILTER,K_[t.magFilter]);const n=void 0!==t.mipmaps&&t.mipmaps.length>0,o=t.minFilter===$&&n?M:t.minFilter;if(r.texParameteri(e,r.TEXTURE_MIN_FILTER,K_[o]),t.compareFunction&&(r.texParameteri(e,r.TEXTURE_COMPARE_MODE,r.COMPARE_REF_TO_TEXTURE),r.texParameteri(e,r.TEXTURE_COMPARE_FUNC,X_[t.compareFunction])),!0===s.has("EXT_texture_filter_anisotropic")){if(t.magFilter===gr)return;if(t.minFilter!==De&&t.minFilter!==M)return;if(t.type===E&&!1===s.has("OES_texture_float_linear"))return;if(t.anisotropy>1){const n=s.get("EXT_texture_filter_anisotropic");r.texParameterf(e,n.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(t.anisotropy,i.getMaxAnisotropy()))}}}createDefaultTexture(e){const{gl:t,backend:r,defaultTextures:s}=this,i=this.getGLTextureType(e);let n=s[i];void 0===n&&(n=t.createTexture(),r.state.bindTexture(i,n),t.texParameteri(i,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(i,t.TEXTURE_MAG_FILTER,t.NEAREST),s[i]=n),r.set(e,{textureGPU:n,glTextureType:i,isDefault:!0})}createTexture(e,t){const{gl:r,backend:s}=this,{levels:i,width:n,height:o,depth:a}=t,u=s.utils.convert(e.format,e.colorSpace),l=s.utils.convert(e.type),d=this.getInternalFormat(e.internalFormat,u,l,e.colorSpace,e.isVideoTexture),c=r.createTexture(),h=this.getGLTextureType(e);s.state.bindTexture(h,c),this.setTextureParameters(h,e),e.isDataArrayTexture||e.isCompressedArrayTexture?r.texStorage3D(r.TEXTURE_2D_ARRAY,i,d,n,o,a):e.isData3DTexture?r.texStorage3D(r.TEXTURE_3D,i,d,n,o,a):e.isVideoTexture||r.texStorage2D(h,i,d,n,o),s.set(e,{textureGPU:c,glTextureType:h,glFormat:u,glType:l,glInternalFormat:d})}copyBufferToTexture(e,t){const{gl:r,backend:s}=this,{textureGPU:i,glTextureType:n,glFormat:o,glType:a}=s.get(t),{width:u,height:l}=t.source.data;r.bindBuffer(r.PIXEL_UNPACK_BUFFER,e),s.state.bindTexture(n,i),r.pixelStorei(r.UNPACK_FLIP_Y_WEBGL,!1),r.pixelStorei(r.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),r.texSubImage2D(n,0,0,0,u,l,o,a,0),r.bindBuffer(r.PIXEL_UNPACK_BUFFER,null),s.state.unbindTexture()}updateTexture(e,t){const{gl:r}=this,{width:s,height:i}=t,{textureGPU:n,glTextureType:o,glFormat:a,glType:u,glInternalFormat:l}=this.backend.get(e);if(e.isRenderTargetTexture||void 0===n)return;const d=e=>e.isDataTexture?e.image.data:"undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&e instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap||e instanceof OffscreenCanvas?e:e.data;if(this.backend.state.bindTexture(o,n),this.setTextureParameters(o,e),e.isCompressedTexture){const s=e.mipmaps,i=t.image;for(let t=0;t0,c=t.renderTarget?t.renderTarget.height:this.backend.getDrawingBufferSize().y;if(d){const r=0!==o||0!==a;let d,h;if(!0===e.isDepthTexture?(d=s.DEPTH_BUFFER_BIT,h=s.DEPTH_ATTACHMENT,t.stencil&&(d|=s.STENCIL_BUFFER_BIT)):(d=s.COLOR_BUFFER_BIT,h=s.COLOR_ATTACHMENT0),r){const e=this.backend.get(t.renderTarget),r=e.framebuffers[t.getCacheKey()],h=e.msaaFrameBuffer;i.bindFramebuffer(s.DRAW_FRAMEBUFFER,r),i.bindFramebuffer(s.READ_FRAMEBUFFER,h);const p=c-a-l;s.blitFramebuffer(o,p,o+u,p+l,o,p,o+u,p+l,d,s.NEAREST),i.bindFramebuffer(s.READ_FRAMEBUFFER,r),i.bindTexture(s.TEXTURE_2D,n),s.copyTexSubImage2D(s.TEXTURE_2D,0,0,0,o,p,u,l),i.unbindTexture()}else{const e=s.createFramebuffer();i.bindFramebuffer(s.DRAW_FRAMEBUFFER,e),s.framebufferTexture2D(s.DRAW_FRAMEBUFFER,h,s.TEXTURE_2D,n,0),s.blitFramebuffer(0,0,u,l,0,0,u,l,d,s.NEAREST),s.deleteFramebuffer(e)}}else i.bindTexture(s.TEXTURE_2D,n),s.copyTexSubImage2D(s.TEXTURE_2D,0,0,0,o,c-l-a,u,l),i.unbindTexture();e.generateMipmaps&&this.generateMipmaps(e),this.backend._setFramebuffer(t)}setupRenderBufferStorage(e,t){const{gl:r}=this,s=t.renderTarget,{samples:i,depthTexture:n,depthBuffer:o,stencilBuffer:a,width:u,height:l}=s;if(r.bindRenderbuffer(r.RENDERBUFFER,e),o&&!a){let t=r.DEPTH_COMPONENT24;i>0?(n&&n.isDepthTexture&&n.type===r.FLOAT&&(t=r.DEPTH_COMPONENT32F),r.renderbufferStorageMultisample(r.RENDERBUFFER,i,t,u,l)):r.renderbufferStorage(r.RENDERBUFFER,t,u,l),r.framebufferRenderbuffer(r.FRAMEBUFFER,r.DEPTH_ATTACHMENT,r.RENDERBUFFER,e)}else o&&a&&(i>0?r.renderbufferStorageMultisample(r.RENDERBUFFER,i,r.DEPTH24_STENCIL8,u,l):r.renderbufferStorage(r.RENDERBUFFER,r.DEPTH_STENCIL,u,l),r.framebufferRenderbuffer(r.FRAMEBUFFER,r.DEPTH_STENCIL_ATTACHMENT,r.RENDERBUFFER,e))}async copyTextureToBuffer(e,t,r,s,i,n){const{backend:o,gl:a}=this,{textureGPU:u,glFormat:l,glType:d}=this.backend.get(e),c=a.createFramebuffer();a.bindFramebuffer(a.READ_FRAMEBUFFER,c);const h=e.isCubeTexture?a.TEXTURE_CUBE_MAP_POSITIVE_X+n:a.TEXTURE_2D;a.framebufferTexture2D(a.READ_FRAMEBUFFER,a.COLOR_ATTACHMENT0,h,u,0);const p=this._getTypedArrayType(d),g=s*i*this._getBytesPerTexel(d,l),m=a.createBuffer();a.bindBuffer(a.PIXEL_PACK_BUFFER,m),a.bufferData(a.PIXEL_PACK_BUFFER,g,a.STREAM_READ),a.readPixels(t,r,s,i,l,d,0),a.bindBuffer(a.PIXEL_PACK_BUFFER,null),await o.utils._clientWaitAsync();const f=new p(g/p.BYTES_PER_ELEMENT);return a.bindBuffer(a.PIXEL_PACK_BUFFER,m),a.getBufferSubData(a.PIXEL_PACK_BUFFER,0,f),a.bindBuffer(a.PIXEL_PACK_BUFFER,null),a.deleteFramebuffer(c),f}_getTypedArrayType(e){const{gl:t}=this;if(e===t.UNSIGNED_BYTE)return Uint8Array;if(e===t.UNSIGNED_SHORT_4_4_4_4)return Uint16Array;if(e===t.UNSIGNED_SHORT_5_5_5_1)return Uint16Array;if(e===t.UNSIGNED_SHORT_5_6_5)return Uint16Array;if(e===t.UNSIGNED_SHORT)return Uint16Array;if(e===t.UNSIGNED_INT)return Uint32Array;if(e===t.HALF_FLOAT)return Uint16Array;if(e===t.FLOAT)return Float32Array;throw new Error(`Unsupported WebGL type: ${e}`)}_getBytesPerTexel(e,t){const{gl:r}=this;let s=0;return e===r.UNSIGNED_BYTE&&(s=1),e!==r.UNSIGNED_SHORT_4_4_4_4&&e!==r.UNSIGNED_SHORT_5_5_5_1&&e!==r.UNSIGNED_SHORT_5_6_5&&e!==r.UNSIGNED_SHORT&&e!==r.HALF_FLOAT||(s=2),e!==r.UNSIGNED_INT&&e!==r.FLOAT||(s=4),t===r.RGBA?4*s:t===r.RGB?3*s:t===r.ALPHA?s:void 0}}class Z_{constructor(e){this.backend=e,this.gl=this.backend.gl,this.availableExtensions=this.gl.getSupportedExtensions(),this.extensions={}}get(e){let t=this.extensions[e];return void 0===t&&(t=this.gl.getExtension(e),this.extensions[e]=t),t}has(e){return this.availableExtensions.includes(e)}}class J_{constructor(e){this.backend=e,this.maxAnisotropy=null}getMaxAnisotropy(){if(null!==this.maxAnisotropy)return this.maxAnisotropy;const e=this.backend.gl,t=this.backend.extensions;if(!0===t.has("EXT_texture_filter_anisotropic")){const r=t.get("EXT_texture_filter_anisotropic");this.maxAnisotropy=e.getParameter(r.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else this.maxAnisotropy=0;return this.maxAnisotropy}}const ev={WEBGL_multi_draw:"WEBGL_multi_draw",WEBGL_compressed_texture_astc:"texture-compression-astc",WEBGL_compressed_texture_etc:"texture-compression-etc2",WEBGL_compressed_texture_etc1:"texture-compression-etc1",WEBGL_compressed_texture_pvrtc:"texture-compression-pvrtc",WEBKIT_WEBGL_compressed_texture_pvrtc:"texture-compression-pvrtc",WEBGL_compressed_texture_s3tc:"texture-compression-bc",EXT_texture_compression_bptc:"texture-compression-bptc",EXT_disjoint_timer_query_webgl2:"timestamp-query"};class tv{constructor(e){this.gl=e.gl,this.extensions=e.extensions,this.info=e.renderer.info,this.mode=null,this.index=0,this.type=null,this.object=null}render(e,t){const{gl:r,mode:s,object:i,type:n,info:o,index:a}=this;0!==a?r.drawElements(s,t,n,e):r.drawArrays(s,e,t),o.update(i,t,s,1)}renderInstances(e,t,r){const{gl:s,mode:i,type:n,index:o,object:a,info:u}=this;0!==r&&(0!==o?s.drawElementsInstanced(i,t,n,e,r):s.drawArraysInstanced(i,e,t,r),u.update(a,t,i,r))}renderMultiDraw(e,t,r){const{extensions:s,mode:i,object:n,info:o}=this;if(0===r)return;const a=s.get("WEBGL_multi_draw");if(null===a)for(let s=0;s0)){const e=t.queryQueue.shift();this.initTimestampQuery(e)}}async resolveTimestampAsync(e,t="render"){if(!this.disjoint||!this.trackTimestamp)return;const r=this.get(e);r.gpuQueries||(r.gpuQueries=[]);for(let e=0;e0&&(r.currentOcclusionQueries=r.occlusionQueries,r.currentOcclusionQueryObjects=r.occlusionQueryObjects,r.lastOcclusionObject=null,r.occlusionQueries=new Array(s),r.occlusionQueryObjects=new Array(s),r.occlusionQueryIndex=0)}finishRender(e){const{gl:t,state:r}=this,s=this.get(e),i=s.previousContext,n=e.occlusionQueryCount;n>0&&(n>s.occlusionQueryIndex&&t.endQuery(t.ANY_SAMPLES_PASSED),this.resolveOccludedAsync(e));const o=e.textures;if(null!==o)for(let e=0;e0){const i=s.framebuffers[e.getCacheKey()],n=t.COLOR_BUFFER_BIT,o=s.msaaFrameBuffer,a=e.textures;r.bindFramebuffer(t.READ_FRAMEBUFFER,o),r.bindFramebuffer(t.DRAW_FRAMEBUFFER,i);for(let r=0;r{let o=0;for(let t=0;t0&&e.add(s[t]),r[t]=null,i.deleteQuery(n),o++))}o1?f.renderInstances(x,y,b):f.render(x,y),a.bindVertexArray(null)}needsRenderUpdate(){return!1}getRenderCacheKey(){return""}createDefaultTexture(e){this.textureUtils.createDefaultTexture(e)}createTexture(e,t){this.textureUtils.createTexture(e,t)}updateTexture(e,t){this.textureUtils.updateTexture(e,t)}generateMipmaps(e){this.textureUtils.generateMipmaps(e)}destroyTexture(e){this.textureUtils.destroyTexture(e)}async copyTextureToBuffer(e,t,r,s,i,n){return this.textureUtils.copyTextureToBuffer(e,t,r,s,i,n)}createSampler(){}destroySampler(){}createNodeBuilder(e,t){return new I_(e,t)}createProgram(e){const t=this.gl,{stage:r,code:s}=e,i="fragment"===r?t.createShader(t.FRAGMENT_SHADER):t.createShader(t.VERTEX_SHADER);t.shaderSource(i,s),t.compileShader(i),this.set(e,{shaderGPU:i})}destroyProgram(e){this.delete(e)}createRenderPipeline(e,t){const r=this.gl,s=e.pipeline,{fragmentProgram:i,vertexProgram:n}=s,o=r.createProgram(),a=this.get(i).shaderGPU,u=this.get(n).shaderGPU;if(r.attachShader(o,a),r.attachShader(o,u),r.linkProgram(o),this.set(s,{programGPU:o,fragmentShader:a,vertexShader:u}),null!==t&&this.parallel){const i=new Promise((t=>{const i=this.parallel,n=()=>{r.getProgramParameter(o,i.COMPLETION_STATUS_KHR)?(this._completeCompile(e,s),t()):requestAnimationFrame(n)};n()}));t.push(i)}else this._completeCompile(e,s)}_handleSource(e,t){const r=e.split("\n"),s=[],i=Math.max(t-6,0),n=Math.min(t+6,r.length);for(let e=i;e":" "} ${i}: ${r[e]}`)}return s.join("\n")}_getShaderErrors(e,t,r){const s=e.getShaderParameter(t,e.COMPILE_STATUS),i=e.getShaderInfoLog(t).trim();if(s&&""===i)return"";const n=/ERROR: 0:(\d+)/.exec(i);if(n){const s=parseInt(n[1]);return r.toUpperCase()+"\n\n"+i+"\n\n"+this._handleSource(e.getShaderSource(t),s)}return i}_logProgramError(e,t,r){if(this.renderer.debug.checkShaderErrors){const s=this.gl,i=s.getProgramInfoLog(e).trim();if(!1===s.getProgramParameter(e,s.LINK_STATUS))if("function"==typeof this.renderer.debug.onShaderError)this.renderer.debug.onShaderError(s,e,r,t);else{const n=this._getShaderErrors(s,r,"vertex"),o=this._getShaderErrors(s,t,"fragment");console.error("THREE.WebGLProgram: Shader Error "+s.getError()+" - VALIDATE_STATUS "+s.getProgramParameter(e,s.VALIDATE_STATUS)+"\n\nProgram Info Log: "+i+"\n"+n+"\n"+o)}else""!==i&&console.warn("THREE.WebGLProgram: Program Info Log:",i)}}_completeCompile(e,t){const{state:r,gl:s}=this,i=this.get(t),{programGPU:n,fragmentShader:o,vertexShader:a}=i;!1===s.getProgramParameter(n,s.LINK_STATUS)&&this._logProgramError(n,o,a),r.useProgram(n);const u=e.getBindings();this._setupBindings(u,n),this.set(t,{programGPU:n})}createComputePipeline(e,t){const{state:r,gl:s}=this,i={stage:"fragment",code:"#version 300 es\nprecision highp float;\nvoid main() {}"};this.createProgram(i);const{computeProgram:n}=e,o=s.createProgram(),a=this.get(i).shaderGPU,u=this.get(n).shaderGPU,l=n.transforms,d=[],c=[];for(let e=0;eev[t]===e)),r=this.extensions;for(let e=0;e0){if(void 0===h){const s=[];h=t.createFramebuffer(),r.bindFramebuffer(t.FRAMEBUFFER,h);const i=[],l=e.textures;for(let r=0;r,\n\t@location( 0 ) vTex : vec2\n};\n\n@vertex\nfn main( @builtin( vertex_index ) vertexIndex : u32 ) -> VarysStruct {\n\n\tvar Varys : VarysStruct;\n\n\tvar pos = array< vec2, 4 >(\n\t\tvec2( -1.0, 1.0 ),\n\t\tvec2( 1.0, 1.0 ),\n\t\tvec2( -1.0, -1.0 ),\n\t\tvec2( 1.0, -1.0 )\n\t);\n\n\tvar tex = array< vec2, 4 >(\n\t\tvec2( 0.0, 0.0 ),\n\t\tvec2( 1.0, 0.0 ),\n\t\tvec2( 0.0, 1.0 ),\n\t\tvec2( 1.0, 1.0 )\n\t);\n\n\tVarys.vTex = tex[ vertexIndex ];\n\tVarys.Position = vec4( pos[ vertexIndex ], 0.0, 1.0 );\n\n\treturn Varys;\n\n}\n"}),this.mipmapFragmentShaderModule=e.createShaderModule({label:"mipmapFragment",code:"\n@group( 0 ) @binding( 0 )\nvar imgSampler : sampler;\n\n@group( 0 ) @binding( 1 )\nvar img : texture_2d;\n\n@fragment\nfn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 {\n\n\treturn textureSample( img, imgSampler, vTex );\n\n}\n"}),this.flipYFragmentShaderModule=e.createShaderModule({label:"flipYFragment",code:"\n@group( 0 ) @binding( 0 )\nvar imgSampler : sampler;\n\n@group( 0 ) @binding( 1 )\nvar img : texture_2d;\n\n@fragment\nfn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 {\n\n\treturn textureSample( img, imgSampler, vec2( vTex.x, 1.0 - vTex.y ) );\n\n}\n"})}getTransferPipeline(e){let t=this.transferPipelines[e];return void 0===t&&(t=this.device.createRenderPipeline({label:`mipmap-${e}`,vertex:{module:this.mipmapVertexShaderModule,entryPoint:"main"},fragment:{module:this.mipmapFragmentShaderModule,entryPoint:"main",targets:[{format:e}]},primitive:{topology:av,stripIndexFormat:Sv},layout:"auto"}),this.transferPipelines[e]=t),t}getFlipYPipeline(e){let t=this.flipYPipelines[e];return void 0===t&&(t=this.device.createRenderPipeline({label:`flipY-${e}`,vertex:{module:this.mipmapVertexShaderModule,entryPoint:"main"},fragment:{module:this.flipYFragmentShaderModule,entryPoint:"main",targets:[{format:e}]},primitive:{topology:av,stripIndexFormat:Sv},layout:"auto"}),this.flipYPipelines[e]=t),t}flipY(e,t,r=0){const s=t.format,{width:i,height:n}=t.size,o=this.getTransferPipeline(s),a=this.getFlipYPipeline(s),u=this.device.createTexture({size:{width:i,height:n,depthOrArrayLayers:1},format:s,usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.TEXTURE_BINDING}),l=e.createView({baseMipLevel:0,mipLevelCount:1,dimension:yN,baseArrayLayer:r}),d=u.createView({baseMipLevel:0,mipLevelCount:1,dimension:yN,baseArrayLayer:0}),c=this.device.createCommandEncoder({}),h=(e,t,r)=>{const s=e.getBindGroupLayout(0),i=this.device.createBindGroup({layout:s,entries:[{binding:0,resource:this.flipYSampler},{binding:1,resource:t}]}),n=c.beginRenderPass({colorAttachments:[{view:r,loadOp:bv,storeOp:fv,clearValue:[0,0,0,0]}]});n.setPipeline(e),n.setBindGroup(0,i),n.draw(4,1,0,0),n.end()};h(o,l,d),h(a,d,l),this.device.queue.submit([c.finish()]),u.destroy()}generateMipmaps(e,t,r=0){const s=this.get(e);void 0===s.useCount&&(s.useCount=0,s.layers=[]);const i=s.layers[r]||this._mipmapCreateBundles(e,t,r),n=this.device.createCommandEncoder({});this._mipmapRunBundles(n,i),this.device.queue.submit([n.finish()]),0!==s.useCount&&(s.layers[r]=i),s.useCount++}_mipmapCreateBundles(e,t,r){const s=this.getTransferPipeline(t.format),i=s.getBindGroupLayout(0);let n=e.createView({baseMipLevel:0,mipLevelCount:1,dimension:yN,baseArrayLayer:r});const o=[];for(let a=1;a1;for(let o=0;o]*\s*([a-z_0-9]+(?:<[\s\S]+?>)?)/i,DN=/([a-z_0-9]+)\s*:\s*([a-z_0-9]+(?:<[\s\S]+?>)?)/gi,LN={f32:"float",i32:"int",u32:"uint",bool:"bool","vec2":"vec2","vec2":"ivec2","vec2":"uvec2","vec2":"bvec2",vec2f:"vec2",vec2i:"ivec2",vec2u:"uvec2",vec2b:"bvec2","vec3":"vec3","vec3":"ivec3","vec3":"uvec3","vec3":"bvec3",vec3f:"vec3",vec3i:"ivec3",vec3u:"uvec3",vec3b:"bvec3","vec4":"vec4","vec4":"ivec4","vec4":"uvec4","vec4":"bvec4",vec4f:"vec4",vec4i:"ivec4",vec4u:"uvec4",vec4b:"bvec4","mat2x2":"mat2",mat2x2f:"mat2","mat3x3":"mat3",mat3x3f:"mat3","mat4x4":"mat4",mat4x4f:"mat4",sampler:"sampler",texture_1d:"texture",texture_2d:"texture",texture_2d_array:"texture",texture_multisampled_2d:"cubeTexture",texture_depth_2d:"depthTexture",texture_depth_multisampled_2d:"depthTexture",texture_3d:"texture3D",texture_cube:"cubeTexture",texture_cube_array:"cubeTexture",texture_storage_1d:"storageTexture",texture_storage_2d:"storageTexture",texture_storage_2d_array:"storageTexture",texture_storage_3d:"storageTexture"};class VN extends jT{constructor(e){const{type:t,inputs:r,name:s,inputsCode:i,blockCode:n,outputType:o}=(e=>{const t=(e=e.trim()).match(IN);if(null!==t&&4===t.length){const r=t[2],s=[];let i=null;for(;null!==(i=DN.exec(r));)s.push({name:i[1],type:i[2]});const n=[];for(let e=0;e "+this.outputType:"";return`fn ${e} ( ${this.inputsCode.trim()} ) ${t}`+this.blockCode}}class ON extends WT{parseFunction(e){return new VN(e)}}const GN="undefined"!=typeof self?self.GPUShaderStage:{VERTEX:1,FRAGMENT:2,COMPUTE:4},kN={[Es.READ_ONLY]:"read",[Es.WRITE_ONLY]:"write",[Es.READ_WRITE]:"read_write"},zN={[cr]:"repeat",[hr]:"clamp",[pr]:"mirror"},$N={vertex:GN?GN.VERTEX:1,fragment:GN?GN.FRAGMENT:2,compute:GN?GN.COMPUTE:4},HN={instance:!0,swizzleAssign:!1,storageBuffer:!0},WN={"^^":"tsl_xor"},jN={float:"f32",int:"i32",uint:"u32",bool:"bool",color:"vec3",vec2:"vec2",ivec2:"vec2",uvec2:"vec2",bvec2:"vec2",vec3:"vec3",ivec3:"vec3",uvec3:"vec3",bvec3:"vec3",vec4:"vec4",ivec4:"vec4",uvec4:"vec4",bvec4:"vec4",mat2:"mat2x2",mat3:"mat3x3",mat4:"mat4x4"},qN={},KN={tsl_xor:new my("fn tsl_xor( a : bool, b : bool ) -> bool { return ( a || b ) && !( a && b ); }"),mod_float:new my("fn tsl_mod_float( x : f32, y : f32 ) -> f32 { return x - y * floor( x / y ); }"),mod_vec2:new my("fn tsl_mod_vec2( x : vec2f, y : vec2f ) -> vec2f { return x - y * floor( x / y ); }"),mod_vec3:new my("fn tsl_mod_vec3( x : vec3f, y : vec3f ) -> vec3f { return x - y * floor( x / y ); }"),mod_vec4:new my("fn tsl_mod_vec4( x : vec4f, y : vec4f ) -> vec4f { return x - y * floor( x / y ); }"),equals_bool:new my("fn tsl_equals_bool( a : bool, b : bool ) -> bool { return a == b; }"),equals_bvec2:new my("fn tsl_equals_bvec2( a : vec2f, b : vec2f ) -> vec2 { return vec2( a.x == b.x, a.y == b.y ); }"),equals_bvec3:new my("fn tsl_equals_bvec3( a : vec3f, b : vec3f ) -> vec3 { return vec3( a.x == b.x, a.y == b.y, a.z == b.z ); }"),equals_bvec4:new my("fn tsl_equals_bvec4( a : vec4f, b : vec4f ) -> vec4 { return vec4( a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w ); }"),repeatWrapping_float:new my("fn tsl_repeatWrapping_float( coord: f32 ) -> f32 { return fract( coord ); }"),mirrorWrapping_float:new my("fn tsl_mirrorWrapping_float( coord: f32 ) -> f32 { let mirrored = fract( coord * 0.5 ) * 2.0; return 1.0 - abs( 1.0 - mirrored ); }"),clampWrapping_float:new my("fn tsl_clampWrapping_float( coord: f32 ) -> f32 { return clamp( coord, 0.0, 1.0 ); }"),biquadraticTexture:new my("\nfn tsl_biquadraticTexture( map : texture_2d, coord : vec2f, iRes : vec2u, level : u32 ) -> vec4f {\n\n\tlet res = vec2f( iRes );\n\n\tlet uvScaled = coord * res;\n\tlet uvWrapping = ( ( uvScaled % res ) + res ) % res;\n\n\t// https://www.shadertoy.com/view/WtyXRy\n\n\tlet uv = uvWrapping - 0.5;\n\tlet iuv = floor( uv );\n\tlet f = fract( uv );\n\n\tlet rg1 = textureLoad( map, vec2u( iuv + vec2( 0.5, 0.5 ) ) % iRes, level );\n\tlet rg2 = textureLoad( map, vec2u( iuv + vec2( 1.5, 0.5 ) ) % iRes, level );\n\tlet rg3 = textureLoad( map, vec2u( iuv + vec2( 0.5, 1.5 ) ) % iRes, level );\n\tlet rg4 = textureLoad( map, vec2u( iuv + vec2( 1.5, 1.5 ) ) % iRes, level );\n\n\treturn mix( mix( rg1, rg2, f.x ), mix( rg3, rg4, f.x ), f.y );\n\n}\n")},XN={dFdx:"dpdx",dFdy:"- dpdy",mod_float:"tsl_mod_float",mod_vec2:"tsl_mod_vec2",mod_vec3:"tsl_mod_vec3",mod_vec4:"tsl_mod_vec4",equals_bool:"tsl_equals_bool",equals_bvec2:"tsl_equals_bvec2",equals_bvec3:"tsl_equals_bvec3",equals_bvec4:"tsl_equals_bvec4",inversesqrt:"inverseSqrt",bitcast:"bitcast"};"undefined"!=typeof navigator&&/Windows/g.test(navigator.userAgent)&&(KN.pow_float=new my("fn tsl_pow_float( a : f32, b : f32 ) -> f32 { return select( -pow( -a, b ), pow( a, b ), a > 0.0 ); }"),KN.pow_vec2=new my("fn tsl_pow_vec2( a : vec2f, b : vec2f ) -> vec2f { return vec2f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ) ); }",[KN.pow_float]),KN.pow_vec3=new my("fn tsl_pow_vec3( a : vec3f, b : vec3f ) -> vec3f { return vec3f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ), tsl_pow_float( a.z, b.z ) ); }",[KN.pow_float]),KN.pow_vec4=new my("fn tsl_pow_vec4( a : vec4f, b : vec4f ) -> vec4f { return vec4f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ), tsl_pow_float( a.z, b.z ), tsl_pow_float( a.w, b.w ) ); }",[KN.pow_float]),XN.pow_float="tsl_pow_float",XN.pow_vec2="tsl_pow_vec2",XN.pow_vec3="tsl_pow_vec3",XN.pow_vec4="tsl_pow_vec4");let YN="";!0!==("undefined"!=typeof navigator&&/Firefox|Deno/g.test(navigator.userAgent))&&(YN+="diagnostic( off, derivative_uniformity );\n");class QN extends FT{constructor(e,t){super(e,t,new ON),this.uniformGroups={},this.builtins={},this.directives={},this.scopedArrays=new Map}needsToWorkingColorSpace(e){return!0===e.isVideoTexture&&e.colorSpace!==y}_generateTextureSample(e,t,r,s,i=this.shaderStage){return"fragment"===i?s?`textureSample( ${t}, ${t}_sampler, ${r}, ${s} )`:`textureSample( ${t}, ${t}_sampler, ${r} )`:this.isFilteredTexture(e)?this.generateFilteredTexture(e,t,r):this.generateTextureLod(e,t,r,s,"0")}_generateVideoSample(e,t,r=this.shaderStage){if("fragment"===r)return`textureSampleBaseClampToEdge( ${e}, ${e}_sampler, vec2( ${t}.x, 1.0 - ${t}.y ) )`;console.error(`WebGPURenderer: THREE.VideoTexture does not support ${r} shader.`)}_generateTextureSampleLevel(e,t,r,s,i,n=this.shaderStage){return"fragment"!==n&&"compute"!==n||!1!==this.isUnfilterable(e)?this.isFilteredTexture(e)?this.generateFilteredTexture(e,t,r,s):this.generateTextureLod(e,t,r,i,s):`textureSampleLevel( ${t}, ${t}_sampler, ${r}, ${s} )`}generateWrapFunction(e){const t=`tsl_coord_${zN[e.wrapS]}S_${zN[e.wrapT]}_${e.isData3DTexture?"3d":"2d"}T`;let r=qN[t];if(void 0===r){const s=[],i=e.isData3DTexture?"vec3f":"vec2f";let n=`fn ${t}( coord : ${i} ) -> ${i} {\n\n\treturn ${i}(\n`;const o=(e,t)=>{e===cr?(s.push(KN.repeatWrapping_float),n+=`\t\ttsl_repeatWrapping_float( coord.${t} )`):e===hr?(s.push(KN.clampWrapping_float),n+=`\t\ttsl_clampWrapping_float( coord.${t} )`):e===pr?(s.push(KN.mirrorWrapping_float),n+=`\t\ttsl_mirrorWrapping_float( coord.${t} )`):(n+=`\t\tcoord.${t}`,console.warn(`WebGPURenderer: Unsupported texture wrap type "${e}" for vertex shader.`))};o(e.wrapS,"x"),n+=",\n",o(e.wrapT,"y"),e.isData3DTexture&&(n+=",\n",o(e.wrapR,"z")),n+="\n\t);\n\n}\n",qN[t]=r=new my(n,s)}return r.build(this),t}generateTextureDimension(e,t,r){const s=this.getDataFromNode(e,this.shaderStage,this.globalCache);void 0===s.dimensionsSnippet&&(s.dimensionsSnippet={});let i=s.dimensionsSnippet[r];if(void 0===s.dimensionsSnippet[r]){let n,o;const{primarySamples:a}=this.renderer.backend.utils.getTextureSampleData(e),u=a>1;o=e.isData3DTexture?"vec3":"vec2",n=u||e.isVideoTexture||e.isStorageTexture?t:`${t}${r?`, u32( ${r} )`:""}`,i=new Ba(new pu(`textureDimensions( ${n} )`,o)),s.dimensionsSnippet[r]=i,(e.isDataArrayTexture||e.isData3DTexture)&&(s.arrayLayerCount=new Ba(new pu(`textureNumLayers(${t})`,"u32"))),e.isTextureCube&&(s.cubeFaceCount=new Ba(new pu("6u","u32")))}return i.build(this)}generateFilteredTexture(e,t,r,s="0u"){this._include("biquadraticTexture");return`tsl_biquadraticTexture( ${t}, ${this.generateWrapFunction(e)}( ${r} ), ${this.generateTextureDimension(e,t,s)}, u32( ${s} ) )`}generateTextureLod(e,t,r,s,i="0u"){const n=this.generateWrapFunction(e),o=this.generateTextureDimension(e,t,i),a=e.isData3DTexture?"vec3":"vec2",u=`${a}(${n}(${r}) * ${a}(${o}))`;return this.generateTextureLoad(e,t,u,s,i)}generateTextureLoad(e,t,r,s,i="0u"){return!0===e.isVideoTexture||!0===e.isStorageTexture?`textureLoad( ${t}, ${r} )`:s?`textureLoad( ${t}, ${r}, ${s}, u32( ${i} ) )`:`textureLoad( ${t}, ${r}, u32( ${i} ) )`}generateTextureStore(e,t,r,s){return`textureStore( ${t}, ${r}, ${s} )`}isSampleCompare(e){return!0===e.isDepthTexture&&null!==e.compareFunction}isUnfilterable(e){return"float"!==this.getComponentTypeFromTexture(e)||!this.isAvailable("float32Filterable")&&!0===e.isDataTexture&&e.type===E||!1===this.isSampleCompare(e)&&e.minFilter===gr&&e.magFilter===gr||this.renderer.backend.utils.getTextureSampleData(e).primarySamples>1}generateTexture(e,t,r,s,i=this.shaderStage){let n=null;return n=!0===e.isVideoTexture?this._generateVideoSample(t,r,i):this.isUnfilterable(e)?this.generateTextureLod(e,t,r,s,"0",i):this._generateTextureSample(e,t,r,s,i),n}generateTextureGrad(e,t,r,s,i,n=this.shaderStage){if("fragment"===n)return`textureSampleGrad( ${t}, ${t}_sampler, ${r}, ${s[0]}, ${s[1]} )`;console.error(`WebGPURenderer: THREE.TextureNode.gradient() does not support ${n} shader.`)}generateTextureCompare(e,t,r,s,i,n=this.shaderStage){if("fragment"===n)return`textureSampleCompare( ${t}, ${t}_sampler, ${r}, ${s} )`;console.error(`WebGPURenderer: THREE.DepthTexture.compareFunction() does not support ${n} shader.`)}generateTextureLevel(e,t,r,s,i,n=this.shaderStage){let o=null;return o=!0===e.isVideoTexture?this._generateVideoSample(t,r,n):this._generateTextureSampleLevel(e,t,r,s,i,n),o}generateTextureBias(e,t,r,s,i,n=this.shaderStage){if("fragment"===n)return`textureSampleBias( ${t}, ${t}_sampler, ${r}, ${s} )`;console.error(`WebGPURenderer: THREE.TextureNode.biasNode does not support ${n} shader.`)}getPropertyName(e,t=this.shaderStage){if(!0===e.isNodeVarying&&!0===e.needsInterpolation){if("vertex"===t)return`varyings.${e.name}`}else if(!0===e.isNodeUniform){const t=e.name,r=e.type;return"texture"===r||"cubeTexture"===r||"storageTexture"===r||"texture3D"===r?t:"buffer"===r||"storageBuffer"===r||"indirectStorageBuffer"===r?`NodeBuffer_${e.id}.${t}`:e.groupNode.name+"."+t}return super.getPropertyName(e)}getOutputStructName(){return"output"}_getUniformGroupCount(e){return Object.keys(this.uniforms[e]).length}getFunctionOperator(e){const t=WN[e];return void 0!==t?(this._include(t),t):null}getNodeAccess(e,t){return"compute"!==t?Es.READ_ONLY:e.access}getStorageAccess(e,t){return kN[this.getNodeAccess(e,t)]}getUniformFromNode(e,t,r,s=null){const i=super.getUniformFromNode(e,t,r,s),n=this.getDataFromNode(e,r,this.globalCache);if(void 0===n.uniformGPU){let s;const o=e.groupNode,a=o.name,u=this.getBindGroupArray(a,r);if("texture"===t||"cubeTexture"===t||"storageTexture"===t||"texture3D"===t){let n=null;const a=this.getNodeAccess(e,r);if("texture"===t||"storageTexture"===t?n=new E_(i.name,i.node,o,a):"cubeTexture"===t?n=new w_(i.name,i.node,o,a):"texture3D"===t&&(n=new M_(i.name,i.node,o,a)),n.store=!0===e.isStorageTextureNode,n.setVisibility($N[r]),"fragment"!==r&&"compute"!==r||!1!==this.isUnfilterable(e.value)||!1!==n.store)u.push(n),s=[n];else{const e=new RN(`${i.name}_sampler`,i.node,o);e.setVisibility($N[r]),u.push(e,n),s=[e,n]}}else if("buffer"===t||"storageBuffer"===t||"indirectStorageBuffer"===t){const i=new("buffer"===t?v_:wN)(e,o);i.setVisibility($N[r]),u.push(i),s=i}else{const e=this.uniformGroups[r]||(this.uniformGroups[r]={});let n=e[a];void 0===n&&(n=new A_(a,o),n.setVisibility($N[r]),e[a]=n,u.push(n)),s=this.getNodeUniform(i,t),n.addUniform(s)}n.uniformGPU=s}return i}getBuiltin(e,t,r,s=this.shaderStage){const i=this.builtins[s]||(this.builtins[s]=new Map);return!1===i.has(e)&&i.set(e,{name:e,property:t,type:r}),t}hasBuiltin(e,t=this.shaderStage){return void 0!==this.builtins[t]&&this.builtins[t].has(e)}getVertexIndex(){return"vertex"===this.shaderStage?this.getBuiltin("vertex_index","vertexIndex","u32","attribute"):"vertexIndex"}buildFunctionCode(e){const t=e.layout,r=this.flowShaderNode(e),s=[];for(const e of t.inputs)s.push(e.name+" : "+this.getType(e.type));let i=`fn ${t.name}( ${s.join(", ")} ) -> ${this.getType(t.type)} {\n${r.vars}\n${r.code}\n`;return r.result&&(i+=`\treturn ${r.result};\n`),i+="\n}\n",i}getInstanceIndex(){return"vertex"===this.shaderStage?this.getBuiltin("instance_index","instanceIndex","u32","attribute"):"instanceIndex"}getInvocationLocalIndex(){return this.getBuiltin("local_invocation_index","invocationLocalIndex","u32","attribute")}getSubgroupSize(){return this.enableSubGroups(),this.getBuiltin("subgroup_size","subgroupSize","u32","attribute")}getInvocationSubgroupIndex(){return this.enableSubGroups(),this.getBuiltin("subgroup_invocation_id","invocationSubgroupIndex","u32","attribute")}getSubgroupIndex(){return this.enableSubGroups(),this.getBuiltin("subgroup_id","subgroupIndex","u32","attribute")}getDrawIndex(){return null}getFrontFacing(){return this.getBuiltin("front_facing","isFront","bool")}getFragCoord(){return this.getBuiltin("position","fragCoord","vec4")+".xy"}getFragDepth(){return"output."+this.getBuiltin("frag_depth","depth","f32","output")}getClipDistance(){return"varyings.hw_clip_distances"}isFlipY(){return!1}enableDirective(e,t=this.shaderStage){(this.directives[t]||(this.directives[t]=new Set)).add(e)}getDirectives(e){const t=[],r=this.directives[e];if(void 0!==r)for(const e of r)t.push(`enable ${e};`);return t.join("\n")}enableSubGroups(){this.enableDirective("subgroups")}enableSubgroupsF16(){this.enableDirective("subgroups-f16")}enableClipDistances(){this.enableDirective("clip_distances")}enableShaderF16(){this.enableDirective("f16")}enableDualSourceBlending(){this.enableDirective("dual_source_blending")}enableHardwareClipping(e){this.enableClipDistances(),this.getBuiltin("clip_distances","hw_clip_distances",`array`,"vertex")}getBuiltins(e){const t=[],r=this.builtins[e];if(void 0!==r)for(const{name:e,property:s,type:i}of r.values())t.push(`@builtin( ${e} ) ${s} : ${i}`);return t.join(",\n\t")}getScopedArray(e,t,r,s){return!1===this.scopedArrays.has(e)&&this.scopedArrays.set(e,{name:e,scope:t,bufferType:r,bufferCount:s}),e}getScopedArrays(e){if("compute"!==e)return;const t=[];for(const{name:e,scope:r,bufferType:s,bufferCount:i}of this.scopedArrays.values()){const n=this.getType(s);t.push(`var<${r}> ${e}: array< ${n}, ${i} >;`)}return t.join("\n")}getAttributes(e){const t=[];if("compute"===e&&(this.getBuiltin("global_invocation_id","id","vec3","attribute"),this.getBuiltin("workgroup_id","workgroupId","vec3","attribute"),this.getBuiltin("local_invocation_id","localId","vec3","attribute"),this.getBuiltin("num_workgroups","numWorkgroups","vec3","attribute"),this.renderer.hasFeature("subgroups")&&(this.enableDirective("subgroups",e),this.getBuiltin("subgroup_size","subgroupSize","u32","attribute"))),"vertex"===e||"compute"===e){const e=this.getBuiltins("attribute");e&&t.push(e);const r=this.getAttributesArray();for(let e=0,s=r.length;e`)}const s=this.getBuiltins("output");return s&&t.push("\t"+s),t.join(",\n")}getStructs(e){const t=[],r=this.structs[e];for(let e=0,s=r.length;e output : ${i};\n\n`)}return t.join("\n\n")}getVar(e,t){return`var ${t} : ${this.getType(e)}`}getVars(e){const t=[],r=this.vars[e];if(void 0!==r)for(const e of r)t.push(`\t${this.getVar(e.type,e.name)};`);return`\n${t.join("\n")}\n`}getVaryings(e){const t=[];if("vertex"===e&&this.getBuiltin("position","Vertex","vec4","vertex"),"vertex"===e||"fragment"===e){const r=this.varyings,s=this.vars[e];for(let i=0;i1&&(n="_multisampled"),!0===t.isCubeTexture)s="texture_cube";else if(!0===t.isDataArrayTexture||!0===t.isCompressedArrayTexture)s="texture_2d_array";else if(!0===t.isDepthTexture)s=`texture_depth${n}_2d`;else if(!0===t.isVideoTexture)s="texture_external";else if(!0===t.isData3DTexture)s="texture_3d";else if(!0===i.node.isStorageTextureNode){s=`texture_storage_2d<${PN(t)}, ${this.getStorageAccess(i.node,e)}>`}else{s=`texture${n}_2d<${this.getComponentTypeFromTexture(t).charAt(0)}32>`}r.push(`@binding( ${o.binding++} ) @group( ${o.group} ) var ${i.name} : ${s};`)}else if("buffer"===i.type||"storageBuffer"===i.type||"indirectStorageBuffer"===i.type){const t=i.node,r=this.getType(t.bufferType),n=t.bufferCount,a=n>0&&"buffer"===i.type?", "+n:"",u=t.isAtomic?`atomic<${r}>`:`${r}`,l=`\t${i.name} : array< ${u}${a} >\n`,d=t.isStorageBufferNode?`storage, ${this.getStorageAccess(t,e)}`:"uniform";s.push(this._getWGSLStructBinding("NodeBuffer_"+t.id,l,d,o.binding++,o.group))}else{const e=this.getType(this.getVectorType(i.type)),t=i.groupNode.name;(n[t]||(n[t]={index:o.binding++,id:o.group,snippets:[]})).snippets.push(`\t${i.name} : ${e}`)}}for(const e in n){const t=n[e];i.push(this._getWGSLStructBinding(e,t.snippets.join(",\n"),"uniform",t.index,t.id))}let o=r.join("\n");return o+=s.join("\n"),o+=i.join("\n"),o}buildCode(){const e=null!==this.material?{fragment:{},vertex:{}}:{compute:{}};this.sortBindingGroups();for(const t in e){const r=e[t];r.uniforms=this.getUniforms(t),r.attributes=this.getAttributes(t),r.varyings=this.getVaryings(t),r.structs=this.getStructs(t),r.vars=this.getVars(t),r.codes=this.getCodes(t),r.directives=this.getDirectives(t),r.scopedArrays=this.getScopedArrays(t);let s="// code\n\n";s+=this.flowCode[t];const i=this.flowNodes[t],n=i[i.length-1],o=n.outputNode,a=void 0!==o&&!0===o.isOutputStructNode;for(const e of i){const i=this.getFlowData(e),u=e.name;if(u&&(s.length>0&&(s+="\n"),s+=`\t// flow -> ${u}\n\t`),s+=`${i.code}\n\t`,e===n&&"compute"!==t)if(s+="// result\n\n\t","vertex"===t)s+=`varyings.Vertex = ${i.result};`;else if("fragment"===t)if(a)r.returnType=o.nodeType,s+=`return ${i.result};`;else{let e="\t@location(0) color: vec4";const t=this.getBuiltins("output");t&&(e+=",\n\t"+t),r.returnType="OutputStruct",r.structs+=this._getWGSLStruct("OutputStruct",e),r.structs+="\nvar output : OutputStruct;\n\n",s+=`output.color = ${i.result};\n\n\treturn output;`}}r.flow=s}null!==this.material?(this.vertexShader=this._getWGSLVertexCode(e.vertex),this.fragmentShader=this._getWGSLFragmentCode(e.fragment)):this.computeShader=this._getWGSLComputeCode(e.compute,(this.object.workgroupSize||[64]).join(", "))}getMethod(e,t=null){let r;return null!==t&&(r=this._getWGSLMethod(e+"_"+t)),void 0===r&&(r=this._getWGSLMethod(e)),r||e}getType(e){return jN[e]||e}isAvailable(e){let t=HN[e];return void 0===t&&("float32Filterable"===e?t=this.renderer.hasFeature("float32-filterable"):"clipDistance"===e&&(t=this.renderer.hasFeature("clip-distances")),HN[e]=t),t}_getWGSLMethod(e){return void 0!==KN[e]&&this._include(e),XN[e]}_include(e){const t=KN[e];return t.build(this),null!==this.currentFunctionNode&&this.currentFunctionNode.includes.push(t),t}_getWGSLVertexCode(e){return`${this.getSignature()}\n// directives\n${e.directives}\n\n// uniforms\n${e.uniforms}\n\n// varyings\n${e.varyings}\nvar varyings : VaryingsStruct;\n\n// codes\n${e.codes}\n\n@vertex\nfn main( ${e.attributes} ) -> VaryingsStruct {\n\n\t// vars\n\t${e.vars}\n\n\t// flow\n\t${e.flow}\n\n\treturn varyings;\n\n}\n`}_getWGSLFragmentCode(e){return`${this.getSignature()}\n// global\n${YN}\n\n// uniforms\n${e.uniforms}\n\n// structs\n${e.structs}\n\n// codes\n${e.codes}\n\n@fragment\nfn main( ${e.varyings} ) -> ${e.returnType} {\n\n\t// vars\n\t${e.vars}\n\n\t// flow\n\t${e.flow}\n\n}\n`}_getWGSLComputeCode(e,t){return`${this.getSignature()}\n// directives\n${e.directives}\n\n// system\nvar instanceIndex : u32;\n\n// locals\n${e.scopedArrays}\n\n// uniforms\n${e.uniforms}\n\n// codes\n${e.codes}\n\n@compute @workgroup_size( ${t} )\nfn main( ${e.attributes} ) {\n\n\t// system\n\tinstanceIndex = id.x + id.y * numWorkgroups.x * u32(${t}) + id.z * numWorkgroups.x * numWorkgroups.y * u32(${t});\n\n\t// vars\n\t${e.vars}\n\n\t// flow\n\t${e.flow}\n\n}\n`}_getWGSLStruct(e,t){return`\nstruct ${e} {\n${t}\n};`}_getWGSLStructBinding(e,t,r,s=0,i=0){const n=e+"Struct";return`${this._getWGSLStruct(n,t)}\n@binding( ${s} ) @group( ${i} )\nvar<${r}> ${e} : ${n};`}}class ZN{constructor(e){this.backend=e}getCurrentDepthStencilFormat(e){let t;return null!==e.depthTexture?t=this.getTextureFormatGPU(e.depthTexture):e.depth&&e.stencil?t=Av.Depth24PlusStencil8:e.depth&&(t=Av.Depth24Plus),t}getTextureFormatGPU(e){return this.backend.get(e).format}getTextureSampleData(e){let t;if(e.isFramebufferTexture)t=1;else if(e.isDepthTexture&&!e.renderTarget){const e=this.backend.renderer,r=e.getRenderTarget();t=r?r.samples:e.samples}else e.renderTarget&&(t=e.renderTarget.samples);t=t||1;const r=t>1&&null!==e.renderTarget&&!0!==e.isDepthTexture&&!0!==e.isFramebufferTexture;return{samples:t,primarySamples:r?1:t,isMSAA:r}}getCurrentColorFormat(e){let t;return t=null!==e.textures?this.getTextureFormatGPU(e.textures[0]):this.getPreferredCanvasFormat(),t}getCurrentColorSpace(e){return null!==e.textures?e.textures[0].colorSpace:this.backend.renderer.outputColorSpace}getPrimitiveTopology(e,t){return e.isPoints?sv:e.isLineSegments||e.isMesh&&!0===t.wireframe?iv:e.isLine?nv:e.isMesh?ov:void 0}getSampleCount(e){let t=1;return e>1&&(t=Math.pow(2,Math.floor(Math.log2(e))),2===t&&(t=4)),t}getSampleCountRenderContext(e){return null!==e.textures?this.getSampleCount(e.sampleCount):this.getSampleCount(this.backend.renderer.samples)}getPreferredCanvasFormat(){return navigator.userAgent.includes("Quest")?Av.BGRA8Unorm:navigator.gpu.getPreferredCanvasFormat()}}const JN=new Map([[Int8Array,["sint8","snorm8"]],[Uint8Array,["uint8","unorm8"]],[Int16Array,["sint16","snorm16"]],[Uint16Array,["uint16","unorm16"]],[Int32Array,["sint32","snorm32"]],[Uint32Array,["uint32","unorm32"]],[Float32Array,["float32"]]]),eS=new Map([[Le,["float16"]]]),tS=new Map([[Int32Array,"sint32"],[Int16Array,"sint32"],[Uint32Array,"uint32"],[Uint16Array,"uint32"],[Float32Array,"float32"]]);class rS{constructor(e){this.backend=e}createAttribute(e,t){const r=this._getBufferAttribute(e),s=this.backend,i=s.get(r);let n=i.buffer;if(void 0===n){const o=s.device;let a=r.array;if(!1===e.normalized)if(a.constructor===Int16Array)a=new Int32Array(a);else if(a.constructor===Uint16Array&&(a=new Uint32Array(a),t&GPUBufferUsage.INDEX))for(let e=0;e1&&(s.multisampled=!0,r.texture.isDepthTexture||(s.sampleType=cN)),r.texture.isDepthTexture)s.sampleType=hN;else if(r.texture.isDataTexture||r.texture.isDataArrayTexture||r.texture.isData3DTexture){const e=r.texture.type;e===x?s.sampleType=pN:e===b?s.sampleType=gN:e===E&&(this.backend.hasFeature("float32-filterable")?s.sampleType=dN:s.sampleType=cN)}r.isSampledCubeTexture?s.viewDimension=xN:r.texture.isDataArrayTexture||r.texture.isCompressedArrayTexture?s.viewDimension=bN:r.isSampledTexture3D&&(s.viewDimension=TN),e.texture=s}else console.error(`WebGPUBindingUtils: Unsupported binding "${r}".`);s.push(e)}return r.createBindGroupLayout({entries:s})}createBindings(e,t,r,s=0){const{backend:i,bindGroupLayoutCache:n}=this,o=i.get(e);let a,u=n.get(e.bindingsReference);void 0===u&&(u=this.createBindingsLayout(e),n.set(e.bindingsReference,u)),r>0&&(void 0===o.groups&&(o.groups=[],o.versions=[]),o.versions[r]===s&&(a=o.groups[r])),void 0===a&&(a=this.createBindGroup(e,u),r>0&&(o.groups[r]=a,o.versions[r]=s)),o.group=a,o.layout=u}updateBinding(e){const t=this.backend,r=t.device,s=e.buffer,i=t.get(e).buffer;r.queue.writeBuffer(i,0,s,0)}createBindGroup(e,t){const r=this.backend,s=r.device;let i=0;const n=[];for(const t of e.bindings){if(t.isUniformBuffer){const e=r.get(t);if(void 0===e.buffer){const r=t.byteLength,i=GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST,n=s.createBuffer({label:"bindingBuffer_"+t.name,size:r,usage:i});e.buffer=n}n.push({binding:i,resource:{buffer:e.buffer}})}else if(t.isStorageBuffer){const e=r.get(t);if(void 0===e.buffer){const s=t.attribute;e.buffer=r.get(s).buffer}n.push({binding:i,resource:{buffer:e.buffer}})}else if(t.isSampler){const e=r.get(t.texture);n.push({binding:i,resource:e.sampler})}else if(t.isSampledTexture){const e=r.get(t.texture);let o;if(void 0!==e.externalTexture)o=s.importExternalTexture({source:e.externalTexture});else{const r=t.store?1:e.texture.mipLevelCount,s=`view-${e.texture.width}-${e.texture.height}-${r}`;if(o=e[s],void 0===o){const i=_N;let n;n=t.isSampledCubeTexture?xN:t.isSampledTexture3D?TN:t.texture.isDataArrayTexture||t.texture.isCompressedArrayTexture?bN:yN,o=e[s]=e.texture.createView({aspect:i,dimension:n,mipLevelCount:r})}}n.push({binding:i,resource:o})}i++}return s.createBindGroup({label:"bindGroup_"+e.name,layout:t,entries:n})}}class iS{constructor(e){this.backend=e}_getSampleCount(e){return this.backend.utils.getSampleCountRenderContext(e)}createRenderPipeline(e,t){const{object:r,material:s,geometry:i,pipeline:n}=e,{vertexProgram:o,fragmentProgram:a}=n,u=this.backend,l=u.device,d=u.utils,c=u.get(n),h=[];for(const t of e.getBindings()){const e=u.get(t);h.push(e.layout)}const p=u.attributeUtils.createShaderVertexBuffers(e);let g;!0===s.transparent&&s.blending!==L&&(g=this._getBlending(s));let m={};!0===s.stencilWrite&&(m={compare:this._getStencilCompare(s),failOp:this._getStencilOperation(s.stencilFail),depthFailOp:this._getStencilOperation(s.stencilZFail),passOp:this._getStencilOperation(s.stencilZPass)});const f=this._getColorWriteMask(s),y=[];if(null!==e.context.textures){const t=e.context.textures;for(let e=0;e1},layout:l.createPipelineLayout({bindGroupLayouts:h})},A={},R=e.context.depth,C=e.context.stencil;if(!0!==R&&!0!==C||(!0===R&&(A.format=v,A.depthWriteEnabled=s.depthWrite,A.depthCompare=_),!0===C&&(A.stencilFront=m,A.stencilBack={},A.stencilReadMask=s.stencilFuncMask,A.stencilWriteMask=s.stencilWriteMask),S.depthStencil=A),null===t)c.pipeline=l.createRenderPipeline(S);else{const e=new Promise((e=>{l.createRenderPipelineAsync(S).then((t=>{c.pipeline=t,e()}))}));t.push(e)}}createBundleEncoder(e){const t=this.backend,{utils:r,device:s}=t,i=r.getCurrentDepthStencilFormat(e),n={label:"renderBundleEncoder",colorFormats:[r.getCurrentColorFormat(e)],depthStencilFormat:i,sampleCount:this._getSampleCount(e)};return s.createRenderBundleEncoder(n)}createComputePipeline(e,t){const r=this.backend,s=r.device,i=r.get(e.computeProgram).module,n=r.get(e),o=[];for(const e of t){const t=r.get(e);o.push(t.layout)}n.pipeline=s.createComputePipeline({compute:i,layout:s.createPipelineLayout({bindGroupLayouts:o})})}_getBlending(e){let t,r;const s=e.blending,i=e.blendSrc,n=e.blendDst,o=e.blendEquation;if(s===yt){const s=null!==e.blendSrcAlpha?e.blendSrcAlpha:i,a=null!==e.blendDstAlpha?e.blendDstAlpha:n,u=null!==e.blendEquationAlpha?e.blendEquationAlpha:o;t={srcFactor:this._getBlendFactor(i),dstFactor:this._getBlendFactor(n),operation:this._getBlendOperation(o)},r={srcFactor:this._getBlendFactor(s),dstFactor:this._getBlendFactor(a),operation:this._getBlendOperation(u)}}else{const i=(e,s,i,n)=>{t={srcFactor:e,dstFactor:s,operation:Hv},r={srcFactor:i,dstFactor:n,operation:Hv}};if(e.premultipliedAlpha)switch(s){case U:i(Fv,Dv,Fv,Dv);break;case Tt:i(Fv,Fv,Fv,Fv);break;case xt:i(Bv,Pv,Bv,Fv);break;case bt:i(Bv,Uv,Bv,Iv)}else switch(s){case U:i(Iv,Dv,Fv,Dv);break;case Tt:i(Iv,Fv,Iv,Fv);break;case xt:i(Bv,Pv,Bv,Fv);break;case bt:i(Bv,Uv,Bv,Uv)}}if(void 0!==t&&void 0!==r)return{color:t,alpha:r};console.error("THREE.WebGPURenderer: Invalid blending: ",s)}_getBlendFactor(e){let t;switch(e){case st:t=Bv;break;case it:t=Fv;break;case nt:t=Uv;break;case dt:t=Pv;break;case ot:t=Iv;break;case ct:t=Dv;break;case ut:t=Lv;break;case ht:t=Vv;break;case lt:t=Ov;break;case pt:t=Gv;break;case at:t=kv;break;case 211:t=zv;break;case 212:t=$v;break;default:console.error("THREE.WebGPURenderer: Blend factor not supported.",e)}return t}_getStencilCompare(e){let t;const r=e.stencilFunc;switch(r){case Br:t=uv;break;case Mr:t=mv;break;case wr:t=lv;break;case Er:t=cv;break;case Cr:t=dv;break;case Rr:t=gv;break;case Ar:t=hv;break;case Sr:t=pv;break;default:console.error("THREE.WebGPURenderer: Invalid stencil function.",r)}return t}_getStencilOperation(e){let t;switch(e){case Or:t=Qv;break;case Vr:t=Zv;break;case Lr:t=Jv;break;case Dr:t=eN;break;case Ir:t=tN;break;case Pr:t=rN;break;case Ur:t=sN;break;case Fr:t=iN;break;default:console.error("THREE.WebGPURenderer: Invalid stencil operation.",t)}return t}_getBlendOperation(e){let t;switch(e){case et:t=Hv;break;case tt:t=Wv;break;case rt:t=jv;break;case kr:t=qv;break;case Gr:t=Kv;break;default:console.error("THREE.WebGPUPipelineUtils: Blend equation not supported.",e)}return t}_getPrimitiveState(e,t,r){const s={},i=this.backend.utils;switch(s.topology=i.getPrimitiveTopology(e,r),null!==t.index&&!0===e.isLine&&!0!==e.isLineSegments&&(s.stripIndexFormat=t.index.array instanceof Uint16Array?Nv:Sv),r.side){case ke:s.frontFace=xv,s.cullMode=vv;break;case T:s.frontFace=xv,s.cullMode=_v;break;case le:s.frontFace=xv,s.cullMode=Tv;break;default:console.error("THREE.WebGPUPipelineUtils: Unknown material.side value.",r.side)}return s}_getColorWriteMask(e){return!0===e.colorWrite?Yv:Xv}_getDepthCompare(e){let t;if(!1===e.depthTest)t=mv;else{const r=e.depthFunc;switch(r){case Et:t=uv;break;case Ct:t=mv;break;case Rt:t=lv;break;case At:t=cv;break;case St:t=dv;break;case Nt:t=gv;break;case vt:t=hv;break;case _t:t=pv;break;default:console.error("THREE.WebGPUPipelineUtils: Invalid depth function.",r)}}return t}}class nS extends V_{constructor(e={}){super(e),this.isWebGPUBackend=!0,this.parameters.alpha=void 0===e.alpha||e.alpha,this.parameters.requiredLimits=void 0===e.requiredLimits?{}:e.requiredLimits,this.trackTimestamp=!0===e.trackTimestamp,this.device=null,this.context=null,this.colorBuffer=null,this.defaultRenderPassdescriptor=null,this.utils=new ZN(this),this.attributeUtils=new rS(this),this.bindingUtils=new sS(this),this.pipelineUtils=new iS(this),this.textureUtils=new UN(this),this.occludedResolveCache=new Map}async init(e){await super.init(e);const t=this.parameters;let r;if(void 0===t.device){const e={powerPreference:t.powerPreference},s="undefined"!=typeof navigator?await navigator.gpu.requestAdapter(e):null;if(null===s)throw new Error("WebGPUBackend: Unable to create WebGPU adapter.");const i=Object.values(SN),n=[];for(const e of i)s.features.has(e)&&n.push(e);const o={requiredFeatures:n,requiredLimits:t.requiredLimits};r=await s.requestDevice(o)}else r=t.device;r.lost.then((t=>{const r={api:"WebGPU",message:t.message||"Unknown reason",reason:t.reason||null,originalEvent:t};e.onDeviceLost(r)}));const s=void 0!==t.context?t.context:e.domElement.getContext("webgpu");this.device=r,this.context=s;const i=t.alpha?"premultiplied":"opaque";this.trackTimestamp=this.trackTimestamp&&this.hasFeature(SN.TimestampQuery),this.context.configure({device:this.device,format:this.utils.getPreferredCanvasFormat(),usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.COPY_SRC,alphaMode:i}),this.updateSize()}get coordinateSystem(){return l}async getArrayBufferAsync(e){return await this.attributeUtils.getArrayBufferAsync(e)}getContext(){return this.context}_getDefaultRenderPassDescriptor(){let e=this.defaultRenderPassdescriptor;if(null===e){const t=this.renderer;e={colorAttachments:[{view:null}]},!0!==this.renderer.depth&&!0!==this.renderer.stencil||(e.depthStencilAttachment={view:this.textureUtils.getDepthBuffer(t.depth,t.stencil).createView()});const r=e.colorAttachments[0];this.renderer.samples>0?r.view=this.colorBuffer.createView():r.resolveTarget=void 0,this.defaultRenderPassdescriptor=e}const t=e.colorAttachments[0];return this.renderer.samples>0?t.resolveTarget=this.context.getCurrentTexture().createView():t.view=this.context.getCurrentTexture().createView(),e}_getRenderPassDescriptor(e,t={}){const r=e.renderTarget,s=this.get(r);let i=s.descriptors;if(void 0===i||s.width!==r.width||s.height!==r.height||s.dimensions!==r.dimensions||s.activeMipmapLevel!==r.activeMipmapLevel||s.activeCubeFace!==e.activeCubeFace||s.samples!==r.samples||s.loadOp!==t.loadOp){i={},s.descriptors=i;const e=()=>{r.removeEventListener("dispose",e),this.delete(r)};r.addEventListener("dispose",e)}const n=e.getCacheKey();let o=i[n];if(void 0===o){const a=e.textures,u=[];let l;for(let s=0;s0&&(t.currentOcclusionQuerySet&&t.currentOcclusionQuerySet.destroy(),t.currentOcclusionQueryBuffer&&t.currentOcclusionQueryBuffer.destroy(),t.currentOcclusionQuerySet=t.occlusionQuerySet,t.currentOcclusionQueryBuffer=t.occlusionQueryBuffer,t.currentOcclusionQueryObjects=t.occlusionQueryObjects,i=r.createQuerySet({type:"occlusion",count:s,label:`occlusionQuerySet_${e.id}`}),t.occlusionQuerySet=i,t.occlusionQueryIndex=0,t.occlusionQueryObjects=new Array(s),t.lastOcclusionObject=null),n=null===e.textures?this._getDefaultRenderPassDescriptor():this._getRenderPassDescriptor(e,{loadOp:yv}),this.initTimestampQuery(e,n),n.occlusionQuerySet=i;const o=n.depthStencilAttachment;if(null!==e.textures){const t=n.colorAttachments;for(let r=0;r0&&t.currentPass.executeBundles(t.renderBundles),r>t.occlusionQueryIndex&&t.currentPass.endOcclusionQuery(),t.currentPass.end(),r>0){const s=8*r;let i=this.occludedResolveCache.get(s);void 0===i&&(i=this.device.createBuffer({size:s,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),this.occludedResolveCache.set(s,i));const n=this.device.createBuffer({size:s,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});t.encoder.resolveQuerySet(t.occlusionQuerySet,0,r,i,0),t.encoder.copyBufferToBuffer(i,0,n,0,s),t.occlusionQueryBuffer=n,this.resolveOccludedAsync(e)}if(this.prepareTimestampBuffer(e,t.encoder),this.device.queue.submit([t.encoder.finish()]),null!==e.textures){const t=e.textures;for(let e=0;eo?(u.x=Math.min(t.dispatchCount,o),u.y=Math.ceil(t.dispatchCount/o)):u.x=t.dispatchCount,i.dispatchWorkgroups(u.x,u.y,u.z)}finishCompute(e){const t=this.get(e);t.passEncoderGPU.end(),this.prepareTimestampBuffer(e,t.cmdEncoderGPU),this.device.queue.submit([t.cmdEncoderGPU.finish()])}async waitForGPU(){await this.device.queue.onSubmittedWorkDone()}draw(e,t){const{object:r,context:s,pipeline:i}=e,n=e.getBindings(),o=this.get(s),a=this.get(i).pipeline,u=o.currentSets,l=o.currentPass,d=e.getDrawParameters();if(null===d)return;u.pipeline!==a&&(l.setPipeline(a),u.pipeline=a);const c=u.bindingGroups;for(let e=0,t=n.length;e1?0:r;!0===p?l.drawIndexed(t[r],s,e[r]/h.array.BYTES_PER_ELEMENT,0,n):l.draw(t[r],s,e[r],n)}}else if(!0===p){const{vertexCount:s,instanceCount:i,firstVertex:n}=d,o=e.getIndirect();if(null!==o){const e=this.get(o).buffer;l.drawIndexedIndirect(e,0)}else l.drawIndexed(s,i,n,0,0);t.update(r,s,i)}else{const{vertexCount:s,instanceCount:i,firstVertex:n}=d,o=e.getIndirect();if(null!==o){const e=this.get(o).buffer;l.drawIndirect(e,0)}else l.draw(s,i,n,0);t.update(r,s,i)}}needsRenderUpdate(e){const t=this.get(e),{object:r,material:s}=e,i=this.utils,n=i.getSampleCountRenderContext(e.context),o=i.getCurrentColorSpace(e.context),a=i.getCurrentColorFormat(e.context),u=i.getCurrentDepthStencilFormat(e.context),l=i.getPrimitiveTopology(r,s);let d=!1;return t.material===s&&t.materialVersion===s.version&&t.transparent===s.transparent&&t.blending===s.blending&&t.premultipliedAlpha===s.premultipliedAlpha&&t.blendSrc===s.blendSrc&&t.blendDst===s.blendDst&&t.blendEquation===s.blendEquation&&t.blendSrcAlpha===s.blendSrcAlpha&&t.blendDstAlpha===s.blendDstAlpha&&t.blendEquationAlpha===s.blendEquationAlpha&&t.colorWrite===s.colorWrite&&t.depthWrite===s.depthWrite&&t.depthTest===s.depthTest&&t.depthFunc===s.depthFunc&&t.stencilWrite===s.stencilWrite&&t.stencilFunc===s.stencilFunc&&t.stencilFail===s.stencilFail&&t.stencilZFail===s.stencilZFail&&t.stencilZPass===s.stencilZPass&&t.stencilFuncMask===s.stencilFuncMask&&t.stencilWriteMask===s.stencilWriteMask&&t.side===s.side&&t.alphaToCoverage===s.alphaToCoverage&&t.sampleCount===n&&t.colorSpace===o&&t.colorFormat===a&&t.depthStencilFormat===u&&t.primitiveTopology===l&&t.clippingContextCacheKey===e.clippingContextCacheKey||(t.material=s,t.materialVersion=s.version,t.transparent=s.transparent,t.blending=s.blending,t.premultipliedAlpha=s.premultipliedAlpha,t.blendSrc=s.blendSrc,t.blendDst=s.blendDst,t.blendEquation=s.blendEquation,t.blendSrcAlpha=s.blendSrcAlpha,t.blendDstAlpha=s.blendDstAlpha,t.blendEquationAlpha=s.blendEquationAlpha,t.colorWrite=s.colorWrite,t.depthWrite=s.depthWrite,t.depthTest=s.depthTest,t.depthFunc=s.depthFunc,t.stencilWrite=s.stencilWrite,t.stencilFunc=s.stencilFunc,t.stencilFail=s.stencilFail,t.stencilZFail=s.stencilZFail,t.stencilZPass=s.stencilZPass,t.stencilFuncMask=s.stencilFuncMask,t.stencilWriteMask=s.stencilWriteMask,t.side=s.side,t.alphaToCoverage=s.alphaToCoverage,t.sampleCount=n,t.colorSpace=o,t.colorFormat=a,t.depthStencilFormat=u,t.primitiveTopology=l,t.clippingContextCacheKey=e.clippingContextCacheKey,d=!0),d}getRenderCacheKey(e){const{object:t,material:r}=e,s=this.utils,i=e.context;return[r.transparent,r.blending,r.premultipliedAlpha,r.blendSrc,r.blendDst,r.blendEquation,r.blendSrcAlpha,r.blendDstAlpha,r.blendEquationAlpha,r.colorWrite,r.depthWrite,r.depthTest,r.depthFunc,r.stencilWrite,r.stencilFunc,r.stencilFail,r.stencilZFail,r.stencilZPass,r.stencilFuncMask,r.stencilWriteMask,r.side,s.getSampleCountRenderContext(i),s.getCurrentColorSpace(i),s.getCurrentColorFormat(i),s.getCurrentDepthStencilFormat(i),s.getPrimitiveTopology(t,r),e.getGeometryCacheKey(),e.clippingContextCacheKey].join()}createSampler(e){this.textureUtils.createSampler(e)}destroySampler(e){this.textureUtils.destroySampler(e)}createDefaultTexture(e){this.textureUtils.createDefaultTexture(e)}createTexture(e,t){this.textureUtils.createTexture(e,t)}updateTexture(e,t){this.textureUtils.updateTexture(e,t)}generateMipmaps(e){this.textureUtils.generateMipmaps(e)}destroyTexture(e){this.textureUtils.destroyTexture(e)}async copyTextureToBuffer(e,t,r,s,i,n){return this.textureUtils.copyTextureToBuffer(e,t,r,s,i,n)}initTimestampQuery(e,t){if(!this.trackTimestamp)return;const r=this.get(e);if(!r.timeStampQuerySet){const s=e.isComputeNode?"compute":"render",i=this.device.createQuerySet({type:"timestamp",count:2,label:`timestamp_${s}_${e.id}`}),n={querySet:i,beginningOfPassWriteIndex:0,endOfPassWriteIndex:1};Object.assign(t,{timestampWrites:n}),r.timeStampQuerySet=i}}prepareTimestampBuffer(e,t){if(!this.trackTimestamp)return;const r=this.get(e),s=2*BigInt64Array.BYTES_PER_ELEMENT;void 0===r.currentTimestampQueryBuffers&&(r.currentTimestampQueryBuffers={resolveBuffer:this.device.createBuffer({label:"timestamp resolve buffer",size:s,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),resultBuffer:this.device.createBuffer({label:"timestamp result buffer",size:s,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ})});const{resolveBuffer:i,resultBuffer:n}=r.currentTimestampQueryBuffers;t.resolveQuerySet(r.timeStampQuerySet,0,2,i,0),"unmapped"===n.mapState&&t.copyBufferToBuffer(i,0,n,0,s)}async resolveTimestampAsync(e,t="render"){if(!this.trackTimestamp)return;const r=this.get(e);if(void 0===r.currentTimestampQueryBuffers)return;const{resultBuffer:s}=r.currentTimestampQueryBuffers;"unmapped"===s.mapState&&s.mapAsync(GPUMapMode.READ).then((()=>{const e=new BigUint64Array(s.getMappedRange()),r=Number(e[1]-e[0])/1e6;this.renderer.info.updateTimestamp(t,r),s.unmap()}))}createNodeBuilder(e,t){return new QN(e,t)}createProgram(e){this.get(e).module={module:this.device.createShaderModule({code:e.code,label:e.stage+(""!==e.name?`_${e.name}`:"")}),entryPoint:"main"}}destroyProgram(e){this.delete(e)}createRenderPipeline(e,t){this.pipelineUtils.createRenderPipeline(e,t)}createComputePipeline(e,t){this.pipelineUtils.createComputePipeline(e,t)}beginBundle(e){const t=this.get(e);t._currentPass=t.currentPass,t._currentSets=t.currentSets,t.currentSets={attributes:{},bindingGroups:[],pipeline:null,index:null},t.currentPass=this.pipelineUtils.createBundleEncoder(e)}finishBundle(e,t){const r=this.get(e),s=r.currentPass.finish();this.get(t).bundleGPU=s,r.currentSets=r._currentSets,r.currentPass=r._currentPass}addBundle(e,t){this.get(e).renderBundles.push(this.get(t).bundleGPU)}createBindings(e,t,r,s){this.bindingUtils.createBindings(e,t,r,s)}updateBindings(e,t,r,s){this.bindingUtils.createBindings(e,t,r,s)}updateBinding(e){this.bindingUtils.updateBinding(e)}createIndexAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.INDEX|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}createAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}createStorageAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.STORAGE|GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}createIndirectStorageAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.STORAGE|GPUBufferUsage.INDIRECT|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}updateAttribute(e){this.attributeUtils.updateAttribute(e)}destroyAttribute(e){this.attributeUtils.destroyAttribute(e)}updateSize(){this.colorBuffer=this.textureUtils.getColorBuffer(),this.defaultRenderPassdescriptor=null}getMaxAnisotropy(){return 16}hasFeature(e){return this.device.features.has(e)}copyTextureToTexture(e,t,r=null,s=null,i=0){let n=0,o=0,a=0,u=0,l=0,d=0,c=e.image.width,h=e.image.height;null!==r&&(u=r.x,l=r.y,d=r.z||0,c=r.width,h=r.height),null!==s&&(n=s.x,o=s.y,a=s.z||0);const p=this.device.createCommandEncoder({label:"copyTextureToTexture_"+e.id+"_"+t.id}),g=this.get(e).texture,m=this.get(t).texture;p.copyTextureToTexture({texture:g,mipLevel:i,origin:{x:u,y:l,z:d}},{texture:m,mipLevel:i,origin:{x:n,y:o,z:a}},[c,h,1]),this.device.queue.submit([p.finish()])}copyFramebufferToTexture(e,t,r){const s=this.get(t);let i=null;i=t.renderTarget?e.isDepthTexture?this.get(t.depthTexture).texture:this.get(t.textures[0]).texture:e.isDepthTexture?this.textureUtils.getDepthBuffer(t.depth,t.stencil):this.context.getCurrentTexture();const n=this.get(e).texture;if(i.format!==n.format)return void console.error("WebGPUBackend: copyFramebufferToTexture: Source and destination formats do not match.",i.format,n.format);let o;if(s.currentPass?(s.currentPass.end(),o=s.encoder):o=this.device.createCommandEncoder({label:"copyFramebufferToTexture_"+e.id}),o.copyTextureToTexture({texture:i,origin:[r.x,r.y,0]},{texture:n},[r.z,r.w]),e.generateMipmaps&&this.textureUtils.generateMipmaps(e),s.currentPass){const{descriptor:e}=s;for(let t=0;t(console.warn("THREE.WebGPURenderer: WebGPU is not available, running under WebGL2 backend."),new rv(e)));super(new t(e),e),this.library=new aS,this.isWebGPURenderer=!0}}class lS extends ts{constructor(){super(),this.isBundleGroup=!0,this.type="BundleGroup",this.static=!0,this.version=0}set needsUpdate(e){!0===e&&this.version++}}class dS{constructor(e,t=$i(0,0,1,1)){this.renderer=e,this.outputNode=t,this.outputColorTransform=!0,this.needsUpdate=!0;const r=new sh;r.name="PostProcessing",this._quadMesh=new cf(r)}render(){this._update();const e=this.renderer,t=e.toneMapping,r=e.outputColorSpace;e.toneMapping=h,e.outputColorSpace=Re,this._quadMesh.render(e),e.toneMapping=t,e.outputColorSpace=r}dispose(){this._quadMesh.material.dispose()}_update(){if(!0===this.needsUpdate){const e=this.renderer,t=e.toneMapping,r=e.outputColorSpace;this._quadMesh.material.fragmentNode=!0===this.outputColorTransform?yu(this.outputNode,t,r):this.outputNode.context({toneMapping:t,outputColorSpace:r}),this._quadMesh.material.needsUpdate=!0,this.needsUpdate=!1}}async renderAsync(){this._update();const e=this.renderer,t=e.toneMapping,r=e.outputColorSpace;e.toneMapping=h,e.outputColorSpace=Re,await this._quadMesh.renderAsync(e),e.toneMapping=t,e.outputColorSpace=r}}class cS extends ee{constructor(e=1,t=1){super(),this.image={width:e,height:t},this.magFilter=$,this.minFilter=$,this.isStorageTexture=!0}}class hS extends xf{constructor(e,t){super(e,t,Uint32Array),this.isIndirectStorageBufferAttribute=!0}}class pS extends rs{constructor(e){super(e),this.textures={},this.nodes={}}load(e,t,r,s){const i=new ss(this.manager);i.setPath(this.path),i.setRequestHeader(this.requestHeader),i.setWithCredentials(this.withCredentials),i.load(e,(r=>{try{t(this.parse(JSON.parse(r)))}catch(t){s?s(t):console.error(t),this.manager.itemError(e)}}),r,s)}parseNodes(e){const t={};if(void 0!==e){for(const r of e){const{uuid:e,type:s}=r;t[e]=this.createNodeFromType(s),t[e].uuid=e}const r={nodes:t,textures:this.textures};for(const s of e){s.meta=r;t[s.uuid].deserialize(s),delete s.meta}}return t}parse(e){const t=this.createNodeFromType(e.type);t.uuid=e.uuid;const r={nodes:this.parseNodes(e.nodes),textures:this.textures};return e.meta=r,t.deserialize(e),delete e.meta,t}setTextures(e){return this.textures=e,this}setNodes(e){return this.nodes=e,this}createNodeFromType(e){return void 0===this.nodes[e]?(console.error("THREE.NodeLoader: Node type not found:",e),Bi()):Ti(new this.nodes[e])}}class gS extends is{constructor(e){super(e),this.nodes={},this.nodeMaterials={}}parse(e){const t=super.parse(e),r=this.nodes,s=e.inputNodes;for(const e in s){const i=s[e];t[e]=r[i]}return t}setNodes(e){return this.nodes=e,this}setNodeMaterials(e){return this.nodeMaterials=e,this}createMaterialFromType(e){const t=this.nodeMaterials[e];return void 0!==t?new t:super.createMaterialFromType(e)}}class mS extends ns{constructor(e){super(e),this.nodes={},this.nodeMaterials={},this._nodesJSON=null}setNodes(e){return this.nodes=e,this}setNodeMaterials(e){return this.nodeMaterials=e,this}parse(e,t){this._nodesJSON=e.nodes;const r=super.parse(e,t);return this._nodesJSON=null,r}parseNodes(e,t){if(void 0!==e){const r=new pS;return r.setNodes(this.nodes),r.setTextures(t),r.parseNodes(e)}return{}}parseMaterials(e,t){const r={};if(void 0!==e){const s=this.parseNodes(this._nodesJSON,t),i=new gS;i.setTextures(t),i.setNodes(s),i.setNodeMaterials(this.nodeMaterials);for(let t=0,s=e.length;t

An optional callback that is executed immediately before the shader program is compiled. This function is called with the shader source code - as a parameter. Useful for the modification of built-in materials. + as a parameter. Useful for the modification of built-in materials, but the + recommended approach moving forward is to use `WebGPURenderer` with the new + Node Material system and [link:https://github.com/mrdoob/three.js/wiki/Three.js-Shading-Language TSL].

Unlike properties, the callback is not supported by [page:Material.clone .clone](), diff --git a/docs/api/en/math/Matrix4.html b/docs/api/en/math/Matrix4.html index e97fbc9a05a468..5138ebd2f2e0ae 100644 --- a/docs/api/en/math/Matrix4.html +++ b/docs/api/en/math/Matrix4.html @@ -315,8 +315,8 @@

[method:this lookAt]( [param:Vector3 eye], [param:Vector3 target], [param:Vector3 up] )

- Constructs a rotation matrix, looking from [page:Vector3 eye] towards - [page:Vector3 target] oriented by the [page:Vector3 up] vector. + Sets the rotation component of the transformation matrix, looking from [page:Vector3 eye] towards + [page:Vector3 target], and oriented by the up-direction [page:Vector3 up].

diff --git a/docs/api/en/textures/Texture.html b/docs/api/en/textures/Texture.html index f607111122ff10..db7e0d180f3539 100644 --- a/docs/api/en/textures/Texture.html +++ b/docs/api/en/textures/Texture.html @@ -309,10 +309,7 @@

[method:undefined updateMatrix]()

[method:Texture clone]()

Make copy of the texture. Note this is not a "deep copy", the image is - shared. Besides, cloning a texture does not automatically mark it for a - texture upload. You have to set [page:Texture.needsUpdate .needsUpdate] to - true as soon as its image property (the data source) is fully loaded or - ready. + shared. Cloning the texture automatically marks it for texture upload.

[method:Object toJSON]( [param:Object meta] )

diff --git a/docs/api/en/textures/VideoFrameTexture.html b/docs/api/en/textures/VideoFrameTexture.html new file mode 100644 index 00000000000000..76bdf9c1aed584 --- /dev/null +++ b/docs/api/en/textures/VideoFrameTexture.html @@ -0,0 +1,98 @@ + + + + + + + + + + [page:VideoTexture] → + +

[name]

+ +

+ This class can be used as an alternative way to define video data. Instead of using + an instance of `HTMLVideoElement` like with `VideoTexture`, [name] expects each frame is + defined manaully via [page:.setFrame setFrame](). A typical use case for this module is when + video frames are decoded with the WebCodecs API. +

+ +

Code Example

+ + + const texture = new THREE.VideoFrameTexture(); + texture.setFrame( frame ); + + +

Examples

+ +

+ [example:webgpu_video_frame video / frame] +

+ +

Constructor

+

+ [name]( [param:Constant mapping], [param:Constant wrapS], + [param:Constant wrapT], [param:Constant magFilter], [param:Constant minFilter], + [param:Constant format], [param:Constant type], [param:Number anisotropy] ) +

+

+ [page:Constant mapping] -- How the image is applied to the object. An + object type of [page:Textures THREE.UVMapping]. + See [page:Textures mapping constants] for other choices.
+ + [page:Constant wrapS] -- The default is [page:Textures THREE.ClampToEdgeWrapping]. + See [page:Textures wrap mode constants] for + other choices.
+ + [page:Constant wrapT] -- The default is [page:Textures THREE.ClampToEdgeWrapping]. + See [page:Textures wrap mode constants] for + other choices.
+ + [page:Constant magFilter] -- How the texture is sampled when a texel + covers more than one pixel. The default is [page:Textures THREE.LinearFilter]. + See [page:Textures magnification filter constants] + for other choices.
+ + [page:Constant minFilter] -- How the texture is sampled when a texel + covers less than one pixel. The default is [page:Textures THREE.LinearFilter]. + See [page:Textures minification filter constants] for + other choices.
+ + [page:Constant format] -- The default is [page:Textures THREE.RGBAFormat]. + See [page:Textures format constants] for other choices.
+ + [page:Constant type] -- Default is [page:Textures THREE.UnsignedByteType]. + See [page:Textures type constants] for other choices.
+ + [page:Number anisotropy] -- The number of samples taken along the axis + through the pixel that has the highest density of texels. By default, this + value is `1`. A higher value gives a less blurry result than a basic mipmap, + at the cost of more texture samples being used. Use + [page:WebGLrenderer.getMaxAnisotropy renderer.getMaxAnisotropy]() to find + the maximum valid anisotropy value for the GPU; this value is usually a + power of 2.

+

+ +

Properties

+ +

See the base [page:VideoTexture VideoTexture] class for common properties.

+ +

Methods

+ +

See the base [page:VideoTexture VideoTexture] class for common methods.

+ +

[method:undefined setFrame]( [param:VideoFrame frame] )

+

+ Sets the current frame of the video. This will automatically update the texture + so the data can be used for rendering. +

+ +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/fr/materials/Material.html b/docs/api/fr/materials/Material.html index 18bc1ac1135b04..a1ca23496e8de3 100644 --- a/docs/api/fr/materials/Material.html +++ b/docs/api/fr/materials/Material.html @@ -350,7 +350,9 @@

[method:undefined dispose]()

[method:undefined onBeforeCompile]( [param:Shader shader], [param:WebGLRenderer renderer] )

Un callback facultatif qui est exécuté immédiatement avant la compilation du programme shader. - Cette fonction est appelée avec le code source du shader comme paramètre. Utile pour la modification des matériaux intégrés. + Cette fonction est appelée avec le code source du shader comme paramètre. Utile pour la modification des matériaux intégrés, + bien que la nouvelle méthode recommandée soit d'utiliser `WebGPURenderer` avec le nouveau système de Node Material et + [link:https://github.com/mrdoob/three.js/wiki/Three.js-Shading-Language TSL].

Contrairement aux propriétés, le callback n'est pas pris en charge par [page:Material.clone .clone](), [page:Material.copy .copy]() et [page:Material.toJSON .toJSON](). diff --git a/docs/api/zh/core/BufferAttribute.html b/docs/api/zh/core/BufferAttribute.html index c2ef4b2a35c57d..940681ab7c1f46 100644 --- a/docs/api/zh/core/BufferAttribute.html +++ b/docs/api/zh/core/BufferAttribute.html @@ -58,9 +58,9 @@

[property:Integer count]

[property:Number gpuType]

- Configures the bound GPU type for use in shaders. Either [page:BufferAttribute THREE.FloatType] or [page:BufferAttribute THREE.IntType], default is [page:BufferAttribute THREE.FloatType]. + 配置着色器中使用的绑定 GPU 类型。[page:BufferAttribute THREE.FloatType] 或 [page:BufferAttribute THREE.IntType],默认为 [page:BufferAttribute THREE.FloatType]。 - Note: this only has an effect for integer arrays and is not configurable for float arrays. For lower precision float types, see [page:BufferAttributeTypes THREE.Float16BufferAttribute]. + 注意:这仅对整数数组有效,对于浮点数组不可配置。对于精度较低的浮点类型,请参阅 [page:BufferAttributeTypes THREE.Float16BufferAttribute]。

[property:Boolean isBufferAttribute]

@@ -123,6 +123,16 @@

[method:this applyNormalMatrix]( [param:Matrix3 m] )

[method:this transformDirection]( [param:Matrix4 m] )

将矩阵[page:Matrix4 m]应用到此BufferAttribute的每一个Vector3元素中,并将所有元素解释为方向向量。

+ +

[method:this addUpdateRange]( [param:Integer start], [param:Integer count] )

+

+ 在数据数组中添加要在 GPU 上更新的数据范围。将描述范围的对象添加到 [page:BufferAttribute.updateRanges updateRanges] 数组。 +

+ +

[method:this clearUpdateRanges]()

+

+ 清除 [page:BufferAttribute.updateRanges updateRanges] 数组。 +

[method:BufferAttribute clone]()

返回该 BufferAttribute 的拷贝。

@@ -136,7 +146,7 @@

[method:this copyAt] ( [param:Integer index1], [param:BufferAttribute buffer

将一个矢量从 bufferAttribute[index2] 拷贝到 [page:BufferAttribute.array array][index1] 中。

[method:Number getComponent]( [param:Integer index], [param:Integer component] )

-

Returns the given component of the vector at the given index.

+

返回给定索引处的向量的给定分量。

[method:Number getX]( [param:Integer index] )

获取给定索引的矢量的第一维元素 (即 X 值)。

@@ -167,10 +177,10 @@

[method:this set] ( [param:Array value], [param:Integer offset] )

[method:this setUsage] ( [param:Usage value] )

-

Set [page:BufferAttribute.usage usage] to value. See usage [page:BufferAttributeUsage constants] for all possible input values.

+

设置 [page:BufferAttribute.usage usage] 值。查看所有可能的输入值的 usage [page:BufferAttributeUsage constants]。

[method:Number setComponent]( [param:Integer index], [param:Integer component], [param:Float value] )

-

Sets the given component of the vector at the given index.

+

在给定索引处设置向量的给定分量。

[method:this setX]( [param:Integer index], [param:Float x] )

设置给定索引的矢量的第一维数据(设置 X 值)。

diff --git a/docs/api/zh/core/BufferGeometry.html b/docs/api/zh/core/BufferGeometry.html index a6142f561ccc53..dd33f59c74f34b 100644 --- a/docs/api/zh/core/BufferGeometry.html +++ b/docs/api/zh/core/BufferGeometry.html @@ -37,6 +37,30 @@

代码示例

const material = new THREE.MeshBasicMaterial( { color: 0xff0000 } ); const mesh = new THREE.Mesh( geometry, material ); + +

代码示例 (索引Index)

+ + + const geometry = new THREE.BufferGeometry(); + + const vertices = new Float32Array( [ + -1.0, -1.0, 1.0, // v0 + 1.0, -1.0, 1.0, // v1 + 1.0, 1.0, 1.0, // v2 + -1.0, 1.0, 1.0, // v3 + ] ); + + const indices = [ + 0, 1, 2, + 2, 3, 0, + ]; + + geometry.setIndex( indices ); + geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) ); + + const material = new THREE.MeshBasicMaterial( { color: 0xff0000 } ); + const mesh = new THREE.Mesh( geometry, material ); +

例子

@@ -82,6 +106,8 @@

[property:Object drawRange]

{ start: 0, count: Infinity } + 对于非索引 BufferGeometry,count 是要渲染的顶点数。 + 对于索引 BufferGeometry,count 是要渲染的索引数。

[property:Array groups]

@@ -94,8 +120,8 @@

[property:Array groups]

start 表明当前 draw call 中的没有索引的几何体的几何体的第一个顶点;或者第一个三角面片的索引。 count 指明当前分割包含多少顶点(或 indices)。 materialIndex 指出当前用到的材质队列的索引。

- - 通过 [page:.addGroup] 来增加组,而不是直接更改当前队列。 + 通过 [page:.addGroup] 来增加组,而不是直接更改当前队列。

+ 每个顶点和索引必须恰好属于一个组,不同组之间不得共享顶点或索引,并且不得留下未使用的顶点或索引。

@@ -159,54 +185,52 @@

方法

[page:EventDispatcher EventDispatcher] 在该类上可用的所有方法。

-

[method:this setAttribute]( [param:String name], [param:BufferAttribute attribute] )

-

- 为当前几何体设置一个 attribute 属性。在类的内部,有一个存储 [page:.attributes] 的 hashmap, - 通过该 hashmap,遍历 attributes 的速度会更快。而使用该方法,可以向 hashmap 内部增加 attribute。 - 所以,你需要使用该方法来添加 attributes。 -

-

[method:undefined addGroup]( [param:Integer start], [param:Integer count], [param:Integer materialIndex] )

为当前几何体增加一个 group,详见 [page:BufferGeometry.groups groups] 属性。

-

[method:this applyMatrix4]( [param:Matrix4 matrix] )

用给定矩阵转换几何体的顶点坐标。

+

[method:this applyQuaternion]( [param:Quaternion quaternion] )

+

用给四元数表示的旋转应用于几何体的顶点坐标。

+

[method:this center] ()

根据边界矩形将几何体居中。

+ +

[method:undefined clearGroups]( )

+

清空所有的 groups。

[method:BufferGeometry clone]()

克隆当前的 BufferGeometry。

-

[method:this copy]( [param:BufferGeometry bufferGeometry] )

-

将参数指定的 BufferGeometry 的值拷贝到当前 BufferGeometry 中。

- -

[method:undefined clearGroups]( )

-

清空所有的 groups。

-

[method:undefined computeBoundingBox]()

- 计算当前几何体的的边界矩形,该操作会更新已有 [param:.boundingBox]。
+ 计算当前几何体的的边界矩形,该操作会更新已有 [page:.boundingBox]。
边界矩形不会默认计算,需要调用该接口指定计算边界矩形,否则保持默认值 *null*。

[method:undefined computeBoundingSphere]()

- 计算当前几何体的的边界球形,该操作会更新已有 [param:.boundingSphere]。
+ 计算当前几何体的的边界球形,该操作会更新已有 [page:.boundingSphere]。
边界球形不会默认计算,需要调用该接口指定计算边界球形,否则保持默认值 *null*。

[method:undefined computeTangents]()

计算并向此geometry中添加tangent attribute。
- 只支持索引化的几何体对象,并且必须拥有position(位置),normal(法向)和 uv attributes。如果使用了切线空间法向贴图,最好使用[page:BufferGeometryUtils.computeMikkTSpaceTangents]中的MikkTSpace算法。 + 只支持索引化的几何体对象,并且必须拥有position(位置),normal(法向)和 uv attributes。如果使用了切线空间法向贴图,最好使用 [page:BufferGeometryUtils.computeMikkTSpaceTangents] 中的MikkTSpace算法。

[method:undefined computeVertexNormals]()

-

通过面片法向量的平均值计算每个顶点的法向量。

+

通过面片法向量的平均值计算每个顶点的法向量。对于索引几何体,该方法将每个顶点法线设置为共享该顶点的面的面法线的平均值。对于非索引几何体,顶点不共享,该方法将每个顶点法线设置为与面法线相同。

+ +

[method:this copy]( [param:BufferGeometry bufferGeometry] )

+

将参数指定的 BufferGeometry 的值拷贝到当前 BufferGeometry 中。

+ +

[method:BufferAttribute deleteAttribute]( [param:String name] )

+

删除具有指定名称的 [page:BufferAttribute attribute]。

[method:undefined dispose]()

@@ -235,9 +259,6 @@

[method:undefined normalizeNormals]()

几何体中的每个法向量长度将会为 1。这样操作会更正光线在表面的效果。

-

[method:BufferAttribute deleteAttribute]( [param:String name] )

-

删除具有指定名称的 [page:BufferAttribute attribute]。

-

[method:this rotateX] ( [param:Float radians] )

在 X 轴上旋转几何体。该操作一般在一次处理中完成,不会循环处理。典型的用法是通过调用 [page:Object3D.rotation] 实时旋转几何体。 @@ -258,24 +279,30 @@

[method:this scale] ( [param:Float x], [param:Float y], [param:Float z] ) -

[method:this setIndex] ( [param:BufferAttribute index] )

-

设置缓存的 [page:.index]。

+

[method:this setAttribute]( [param:String name], [param:BufferAttribute attribute] )

+

+ 为当前几何体设置一个 attribute 属性。在类的内部,有一个存储 [page:.attributes] 的 hashmap, + 通过该 hashmap,遍历 attributes 的速度会更快。 +

[method:undefined setDrawRange] ( [param:Integer start], [param:Integer count] )

-

设置缓存的 [page:.drawRange]。详见相关属性说明。

+

设置 [page:.drawRange] 属性。对于非索引 BufferGeometry,count 是要渲染的顶点数。对于索引 BufferGeometry,count 是要渲染的索引数。

[method:this setFromPoints] ( [param:Array points] )

-

通过点队列设置该 BufferGeometry 的 attribute。

+

通过基于给定的 points 设置几何图形的位置属性。该数组可以保存 Vector2 或 Vector3 的实例。使用二维数据时,所有顶点的 z 坐标均设置为 0。如果该方法与现有位置属性一起使用,则顶点数据将被数组中的数据覆盖。数组的长度必须与顶点数匹配。

+ +

[method:this setIndex] ( [param:BufferAttribute index] )

+

设置缓存的 [page:.index]。

[method:Object toJSON]()

-

返回代表该 BufferGeometry 的 JSON 对象。

+

返回代表该 BufferGeometry 符合 [link:https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4 Object/Scene 规范] 的 JSON 对象。

[method:BufferGeometry toNonIndexed]()

返回已索引的 BufferGeometry 的非索引版本。

[method:this translate] ( [param:Float x], [param:Float y], [param:Float z] )

- 移动几何体。该操作一般在一次处理中完成,不会循环处理。典型的用法是通过调用 [page:Object3D.rotation] 实时旋转几何体。 + 移动几何体。该操作一般在一次处理中完成,不会循环处理。典型的用法是通过调用 [page:Object3D.position] 实时移动几何体。

Source

diff --git a/docs/examples/en/animations/CCDIKSolver.html b/docs/examples/en/animations/CCDIKSolver.html index 82b93b565fc93d..533510d8808615 100644 --- a/docs/examples/en/animations/CCDIKSolver.html +++ b/docs/examples/en/animations/CCDIKSolver.html @@ -9,7 +9,7 @@

[name]

-

A solver for IK with `CCD Algorithm`.

+

A solver for IK with `CCD Algorithm`.

[name] solves Inverse Kinematics Problem with CCD Algorithm. [name] is designed to work with [page:SkinnedMesh] but also can be used with [page:GLTFLoader] skeleton.

diff --git a/docs/examples/en/lines/LineMaterial.html b/docs/examples/en/lines/LineMaterial.html index d988ad641df6d6..fee2a764a28a6e 100644 --- a/docs/examples/en/lines/LineMaterial.html +++ b/docs/examples/en/lines/LineMaterial.html @@ -64,7 +64,7 @@

[property:number gapSize]

The size of the gap. Default is `1`.

[property:Float linewidth]

-

Controls line thickness. Default is `1`.

+

Controls line thickness in CSS pixel units when [page:worldUnits] is `false` (default), or in world units when [page:worldUnits] is `true`. Default is `1`.

[property:Vector2 resolution]

diff --git a/docs/examples/en/math/convexhull/ConvexHull.html b/docs/examples/en/math/convexhull/ConvexHull.html index 6ddf07effa9a5e..2cbacc97a25f7e 100644 --- a/docs/examples/en/math/convexhull/ConvexHull.html +++ b/docs/examples/en/math/convexhull/ConvexHull.html @@ -86,7 +86,7 @@

[method:this addNewFaces]( [param:VertexNode eyeVertex], [param:HalfEdge hor

[method:this addVertexToFace]( [param:VertexNode vertex], [param:Face face] )

- [page:VertexNodeNode vertex] - The vertex to add.
+ [page:VertexNode vertex] - The vertex to add.
[page:Face face] - The target face.

Adds a vertex to the 'assigned' list of vertices and assigns it to the given face. diff --git a/docs/examples/zh/animations/CCDIKSolver.html b/docs/examples/zh/animations/CCDIKSolver.html index 08c0ddcfeeaeef..47fedfd48b083a 100644 --- a/docs/examples/zh/animations/CCDIKSolver.html +++ b/docs/examples/zh/animations/CCDIKSolver.html @@ -11,7 +11,7 @@

CCDIK解算器([name])

-

一种基于 `CCD Algorithm` 的 IK +

一种基于 `CCD Algorithm` 的 IK 解算器。

[name] 用 CCD 算法解决逆运动学问题。 [name] 设计用于与 [page:SkinnedMesh] 配合使用,但也可与 [page:GLTFLoader] 配合使用。 diff --git a/docs/examples/zh/math/convexhull/ConvexHull.html b/docs/examples/zh/math/convexhull/ConvexHull.html index 583e79d1c7cf21..1e40d58b1dc170 100644 --- a/docs/examples/zh/math/convexhull/ConvexHull.html +++ b/docs/examples/zh/math/convexhull/ConvexHull.html @@ -88,7 +88,7 @@

[method:this addNewFaces]( [param:VertexNode eyeVertex], [param:HalfEdge hor

[method:this addVertexToFace]( [param:VertexNode vertex], [param:Face face] )

- [page:VertexNodeNode vertex] - 要添加的顶点。
+ [page:VertexNode vertex] - 要添加的顶点。
[page:Face face] - 目标面。

将一个顶点添加到 “分配(assigned)” 顶点列表,并将其分配给给定的面。 diff --git a/docs/list.json b/docs/list.json index eadf2f26603bb0..483a7c1f56316d 100644 --- a/docs/list.json +++ b/docs/list.json @@ -318,6 +318,7 @@ "FramebufferTexture": "api/en/textures/FramebufferTexture", "Source": "api/en/textures/Source", "Texture": "api/en/textures/Texture", + "VideoFrameTexture": "api/en/textures/VideoFrameTexture", "VideoTexture": "api/en/textures/VideoTexture" } diff --git a/docs/manual/en/introduction/Color-management.html b/docs/manual/en/introduction/Color-management.html index 088abde94531fc..882f8112527251 100644 --- a/docs/manual/en/introduction/Color-management.html +++ b/docs/manual/en/introduction/Color-management.html @@ -214,14 +214,10 @@

Output color space

Output to a display device, image, or video may involve conversion from the open domain - Linear-sRGB working color space to another color space. This conversion may be performed in - the main render pass ([page:WebGLRenderer.outputColorSpace]), or during post-processing. + Linear-sRGB working color space to another color space. The conversion is defined by + ([page:WebGLRenderer.outputColorSpace]). When using post-processing, this requires OutputPass.

- -renderer.outputColorSpace = THREE.SRGBColorSpace; // optional with post-processing - -
  • Display: Colors written to a WebGL canvas for display should be in the sRGB diff --git a/editor/js/Config.js b/editor/js/Config.js index 43108ceae73b6c..1f2fb51c8ef8a1 100644 --- a/editor/js/Config.js +++ b/editor/js/Config.js @@ -4,7 +4,7 @@ function Config() { const userLanguage = navigator.language.split( '-' )[ 0 ]; - const suggestedLanguage = [ 'fr', 'ja', 'zh', 'ko' ].includes( userLanguage ) ? userLanguage : 'en'; + const suggestedLanguage = [ 'fr', 'ja', 'zh', 'ko', 'fa' ].includes( userLanguage ) ? userLanguage : 'en'; const storage = { 'language': suggestedLanguage, diff --git a/editor/js/Sidebar.Settings.js b/editor/js/Sidebar.Settings.js index c66caab9137807..6756e5d497bf11 100644 --- a/editor/js/Sidebar.Settings.js +++ b/editor/js/Sidebar.Settings.js @@ -17,13 +17,11 @@ function SidebarSettings( editor ) { // language - const options = { - en: 'English', - fr: 'Français', - zh: '中文', - ja: '日本語', - ko: '한국어', - }; + const options = Object.fromEntries( [ 'en', 'fr', 'zh', 'ja', 'ko', 'fa' ].map( locale => { + + return [ locale, new Intl.DisplayNames( locale, { type: 'language' } ).of( locale ) ]; + + } ) ); const languageRow = new UIRow(); const language = new UISelect().setWidth( '150px' ); diff --git a/editor/js/Strings.js b/editor/js/Strings.js index 7a8ce1c570c6d2..4988c893eee888 100644 --- a/editor/js/Strings.js +++ b/editor/js/Strings.js @@ -3,7 +3,406 @@ function Strings( config ) { const language = config.getKey( 'language' ); const values = { +fa: { +'prompt/file/open': 'تمام داده های ذخیره نشده پاک خواهند شد آیا مطمئنید؟', + 'prompt/file/failedToOpenProject': 'خطایی در باز کردن پروژه پیش آمده', + 'prompt/file/export/noMeshSelected': 'هیچ Mesh ای انتخاب نکردید', + 'prompt/file/export/noObjectSelected': 'هیچ آبجکتی انتخاب نکردید!', + 'prompt/script/remove': 'آیا اطمینان دارید؟', + 'prompt/history/clear': 'هیستوری قبل و بعد (undo / redo) پاک خواهند شد آیا مطمئنید؟', + 'prompt/history/preserve': 'The history will be preserved across sessions.\nThis can have an impact on performance when working with textures.', + 'prompt/history/forbid': 'Undo/Redo disabled while scene is playing.', + 'prompt/rendering/realistic/unsupportedMaterial': 'REALISTIC Shading: Only MeshStandardMaterial and MeshPhysicalMaterial are supported', + + 'command/AddObject': 'افزودن آبجکت', + 'command/AddScript': 'افزودن اسکریپت', + 'command/MoveObject': 'جابجایی آبجکت', + 'command/MultiCmds': 'تغییرات گروهی', + 'command/RemoveObject': 'حذف آبجکت', + 'command/RemoveScript': 'حذف اسکریپت', + 'command/SetColor': 'تنظیم رنگ', + 'command/SetGeometry': 'تنظیم ژئومتری', + 'command/SetGeometryValue': 'تنظیم مقدار ژئومتری', + 'command/SetMaterialColor': 'تنظیم رنگ متریال', + 'command/SetMaterial': 'تنظیم متریال', + 'command/SetMaterialMap': 'تنظیم مپ متریال', + 'command/SetMaterialRange': 'تنظیم رنج متریال', + 'command/SetMaterialValue': 'تنظیم مقدار متریال', + 'command/SetMaterialVector': 'تنظیم وکتور متریال', + 'command/SetPosition': 'تنظیم پوزیشن', + 'command/SetRotation': 'تنظیم چرخش', + 'command/SetScale': 'تنظیم اندازه', + 'command/SetScene': 'تنظیم صحنه', + 'command/SetScriptValue': 'تنظیم مقدار اسکریپت', + 'command/SetShadowValue': 'تنظیم مقدار سایه', + 'command/SetUuid': 'تنظیم UUID', + 'command/SetValue': 'تنظیم مقدار', + + 'menubar/file': 'فایل', + 'menubar/file/new': 'جدید', + 'menubar/file/new/empty': 'پروژه خالی', + 'menubar/file/new/Arkanoid': 'آرکانوید', + 'menubar/file/new/Camera': 'دوربین', + 'menubar/file/new/Particles': 'Particles', + 'menubar/file/new/Pong': 'پونگ', + 'menubar/file/new/Shaders': 'Shaders', + 'menubar/file/open': 'باز کردن', + 'menubar/file/save': 'ذخیره تغییرات', + 'menubar/file/import': 'ایمپورت', + 'menubar/file/export': 'اکسپورت', + + 'menubar/edit': 'تغییر', + 'menubar/edit/undo': 'بازگشت', + 'menubar/edit/redo': 'بازگشت به جلو', + 'menubar/edit/center': 'وسط', + 'menubar/edit/clone': 'شبیه سازی', + 'menubar/edit/delete': 'حذف', + + 'menubar/add': 'افزودن', + 'menubar/add/group': 'گروه', + + 'menubar/add/mesh': 'مش', + 'menubar/add/mesh/plane': 'صفحه', + 'menubar/add/mesh/box': 'باکس', + 'menubar/add/mesh/capsule': 'کپسول', + 'menubar/add/mesh/circle': 'دایره', + 'menubar/add/mesh/cylinder': 'سیلندر', + 'menubar/add/mesh/ring': 'حلقه', + 'menubar/add/mesh/sphere': 'کره', + 'menubar/add/mesh/dodecahedron': 'دوازده وجهی', + 'menubar/add/mesh/icosahedron': 'بیست وجهی', + 'menubar/add/mesh/octahedron': 'هشت وجهی', + 'menubar/add/mesh/tetrahedron': 'چهار وجهی', + 'menubar/add/mesh/torus': 'توروس (دونات)', + 'menubar/add/mesh/tube': 'لوله', + 'menubar/add/mesh/torusknot': 'torusknot', + 'menubar/add/mesh/lathe': 'Lathe', + 'menubar/add/mesh/sprite': 'Sprite', + + 'menubar/add/light': 'نور', + 'menubar/add/light/ambient': 'محیط', + 'menubar/add/light/directional': 'جهت دار', + 'menubar/add/light/hemisphere': 'نیمکره', + 'menubar/add/light/point': 'مستقیم', + 'menubar/add/light/spot': 'نقطه ای', + + 'menubar/add/camera': 'دوربین', + 'menubar/add/camera/perspective': 'پرسپکتیو', + 'menubar/add/camera/orthographic': 'اورتوگرافیک', + + 'menubar/status/autosave': 'ذخیره اتوماتیک', + + 'menubar/view': 'نمایش', + 'menubar/view/fullscreen': 'تمام صفحه', + 'menubar/view/gridHelper': 'کمک کننده گرید', + 'menubar/view/cameraHelpers': 'کمک کننده دوربین', + 'menubar/view/lightHelpers': 'کمک کننده نور', + 'menubar/view/skeletonHelpers': 'کمک کننده اسکلتون', + + 'menubar/help': 'کمک', + 'menubar/help/source_code': 'سورس کد', + 'menubar/help/icons': 'پک آیکون', + 'menubar/help/about': 'درباره ما', + 'menubar/help/manual': 'کتابچه راهنما', + + 'sidebar/animations': 'انیمیشن ها', + 'sidebar/animations/play': 'نمایش', + 'sidebar/animations/stop': 'توقف', + 'sidebar/animations/timescale': 'مقیاس زمانی', + + 'sidebar/scene': 'صحنه', + 'sidebar/scene/background': 'پس زمینه', + 'sidebar/scene/environment': 'محیط', + 'sidebar/scene/fog': 'مه', + + 'sidebar/properties/object': 'آبجکت', + 'sidebar/properties/geometry': 'ژئومتری', + 'sidebar/properties/material': 'متریال', + 'sidebar/properties/script': 'اسکریپت', + + 'sidebar/object/type': 'انواع', + 'sidebar/object/new': 'جدید', + 'sidebar/object/uuid': 'UUID', + 'sidebar/object/name': 'نام', + 'sidebar/object/position': 'پوزیشن', + 'sidebar/object/rotation': 'چرخش', + 'sidebar/object/scale': 'مقیاس', + 'sidebar/object/fov': 'زاویه دید', + 'sidebar/object/left': 'چپ', + 'sidebar/object/right': 'راست', + 'sidebar/object/top': 'بالا', + 'sidebar/object/bottom': 'پایین', + 'sidebar/object/near': 'نزدیک', + 'sidebar/object/far': 'دور', + 'sidebar/object/intensity': 'شدت', + 'sidebar/object/color': 'رنگ', + 'sidebar/object/groundcolor': 'رنگ زمینه', + 'sidebar/object/distance': 'مسافت', + 'sidebar/object/angle': 'زاویه', + 'sidebar/object/penumbra': 'نیم سایه', + 'sidebar/object/decay': 'پوسیدگی', + 'sidebar/object/shadow': 'سایه', + 'sidebar/object/shadowIntensity': 'شدت سایه', + 'sidebar/object/shadowBias': 'انحراف سایه', + 'sidebar/object/shadowNormalBias': 'انحراف معمول سایه', + 'sidebar/object/shadowRadius': 'شعاع سایه', + 'sidebar/object/cast': 'سایه انداختن', + 'sidebar/object/receive': 'دریافت', + 'sidebar/object/visible': 'آشکار', + 'sidebar/object/frustumcull': 'فروستوم کال', + 'sidebar/object/renderorder': 'ترتیب رندر', + 'sidebar/object/userdata': 'داده کاربر', + 'sidebar/object/export': 'اکسپورت جیسون', + + 'sidebar/geometry/type': 'انواع', + 'sidebar/geometry/new': 'جدید', + 'sidebar/geometry/uuid': 'UUID', + 'sidebar/geometry/name': 'نام', + 'sidebar/geometry/bounds': 'محدوده', + 'sidebar/geometry/userdata': 'داده کاربر', + 'sidebar/geometry/show_vertex_normals': 'نمایش راس های معمول', + 'sidebar/geometry/compute_vertex_normals': 'محاسبه راس های معمول', + 'sidebar/geometry/compute_vertex_tangents': 'محاسبه مماس ها', + 'sidebar/geometry/center': 'وسط', + 'sidebar/geometry/export': 'اکسپورت جیسون', + + 'sidebar/geometry/box_geometry/width': 'عرض', + 'sidebar/geometry/box_geometry/height': 'ارتفاع', + 'sidebar/geometry/box_geometry/depth': 'عمق', + 'sidebar/geometry/box_geometry/widthseg': 'ارجاع عرض', + 'sidebar/geometry/box_geometry/heightseg': 'ارجاع ارتفاع', + 'sidebar/geometry/box_geometry/depthseg': 'ارجاع عمق', + + 'sidebar/geometry/buffer_geometry/attributes': 'صفات', + 'sidebar/geometry/buffer_geometry/index': 'شاخص', + 'sidebar/geometry/buffer_geometry/morphAttributes': 'صفات شکل (مورف)', + 'sidebar/geometry/buffer_geometry/morphRelative': 'صفات نسبی (رلتیو)', + + 'sidebar/geometry/capsule_geometry/radius': 'شعاع', + 'sidebar/geometry/capsule_geometry/length': 'طول', + 'sidebar/geometry/capsule_geometry/capseg': 'Cap Seg', + 'sidebar/geometry/capsule_geometry/radialseg': 'Radial Seg', + + 'sidebar/geometry/circle_geometry/radius': 'شعاع', + 'sidebar/geometry/circle_geometry/segments': 'بخش ها', + 'sidebar/geometry/circle_geometry/thetastart': 'شروع تتا', + 'sidebar/geometry/circle_geometry/thetalength': 'طول تتا', + + 'sidebar/geometry/cylinder_geometry/radiustop': 'شعاع بالا', + 'sidebar/geometry/cylinder_geometry/radiusbottom': 'شعاع پایین', + 'sidebar/geometry/cylinder_geometry/height': 'ارتفاع', + 'sidebar/geometry/cylinder_geometry/radialsegments': 'بخش های شعاعی', + 'sidebar/geometry/cylinder_geometry/heightsegments': 'بخش های ارتفاع', + 'sidebar/geometry/cylinder_geometry/openended': 'پایان باز', + + 'sidebar/geometry/extrude_geometry/curveSegments': 'بخش های منحنی', + 'sidebar/geometry/extrude_geometry/steps': 'گام ها', + 'sidebar/geometry/extrude_geometry/depth': 'عمق', + 'sidebar/geometry/extrude_geometry/bevelEnabled': 'اریب', + 'sidebar/geometry/extrude_geometry/bevelThickness': 'ضخامت', + 'sidebar/geometry/extrude_geometry/bevelSize': 'سایز', + 'sidebar/geometry/extrude_geometry/bevelOffset': 'افست', + 'sidebar/geometry/extrude_geometry/bevelSegments': 'بخش ها', + 'sidebar/geometry/extrude_geometry/shape': 'تبدیل به شکل', + + 'sidebar/geometry/dodecahedron_geometry/radius': 'شعاع', + 'sidebar/geometry/dodecahedron_geometry/detail': 'جزییات', + + 'sidebar/geometry/icosahedron_geometry/radius': 'شعاع', + 'sidebar/geometry/icosahedron_geometry/detail': 'جزییات', + + 'sidebar/geometry/octahedron_geometry/radius': 'شعاع', + 'sidebar/geometry/octahedron_geometry/detail': 'جزییات', + + 'sidebar/geometry/tetrahedron_geometry/radius': 'شعاع', + 'sidebar/geometry/tetrahedron_geometry/detail': 'جزییات', + + 'sidebar/geometry/lathe_geometry/segments': 'بخش ها', + 'sidebar/geometry/lathe_geometry/phistart': 'شروع فی (°)', + 'sidebar/geometry/lathe_geometry/philength': 'طول فی (°)', + 'sidebar/geometry/lathe_geometry/points': 'امتیاز ها', + + 'sidebar/geometry/plane_geometry/width': 'عرض', + 'sidebar/geometry/plane_geometry/height': 'ارتفاع', + 'sidebar/geometry/plane_geometry/widthsegments': 'بخش عرض', + 'sidebar/geometry/plane_geometry/heightsegments': 'بخش ارتفاع', + + 'sidebar/geometry/ring_geometry/innerRadius': 'شعاع داخلی', + 'sidebar/geometry/ring_geometry/outerRadius': 'شعاع خارجی', + 'sidebar/geometry/ring_geometry/thetaSegments': 'بخش های تتا', + 'sidebar/geometry/ring_geometry/phiSegments': 'بخش های فی', + 'sidebar/geometry/ring_geometry/thetastart': 'شروع تتا', + 'sidebar/geometry/ring_geometry/thetalength': 'طول تتا', + + 'sidebar/geometry/shape_geometry/curveSegments': 'بخش های منحنی', + 'sidebar/geometry/shape_geometry/extrude': 'اکسترود کردن', + + 'sidebar/geometry/sphere_geometry/radius': 'شعاع', + 'sidebar/geometry/sphere_geometry/widthsegments': 'بخش عرض', + 'sidebar/geometry/sphere_geometry/heightsegments': 'بخش ارتفاع', + 'sidebar/geometry/sphere_geometry/phistart': 'شروع فی', + 'sidebar/geometry/sphere_geometry/philength': ' طول فی', + 'sidebar/geometry/sphere_geometry/thetastart': 'شروع تتا', + 'sidebar/geometry/sphere_geometry/thetalength': 'طول تتا', + + 'sidebar/geometry/torus_geometry/radius': 'شعاع', + 'sidebar/geometry/torus_geometry/tube': 'لوله', + 'sidebar/geometry/torus_geometry/radialsegments': 'بخش های شعاعی', + 'sidebar/geometry/torus_geometry/tubularsegments': 'بخش های لوله ای', + 'sidebar/geometry/torus_geometry/arc': 'آرک', + + 'sidebar/geometry/torusKnot_geometry/radius': 'شعاع', + 'sidebar/geometry/torusKnot_geometry/tube': 'لوله', + 'sidebar/geometry/torusKnot_geometry/tubularsegments': 'بخش های لوله ای', + 'sidebar/geometry/torusKnot_geometry/radialsegments': 'بخش های شعاعی', + 'sidebar/geometry/torusKnot_geometry/p': 'P', + 'sidebar/geometry/torusKnot_geometry/q': 'Q', + 'sidebar/geometry/tube_geometry/path': 'مسیر', + 'sidebar/geometry/tube_geometry/radius': 'شعاع', + 'sidebar/geometry/tube_geometry/tube': 'لوله', + 'sidebar/geometry/tube_geometry/tubularsegments': 'بخش های لوله ای', + 'sidebar/geometry/tube_geometry/radialsegments': 'بخش های شعاعی', + 'sidebar/geometry/tube_geometry/closed': 'بسته شده', + 'sidebar/geometry/tube_geometry/curvetype': 'نوع انحنا', + 'sidebar/geometry/tube_geometry/tension': 'تنش', + + 'sidebar/material/new': 'جدید', + 'sidebar/material/copy': 'کپی', + 'sidebar/material/paste': 'پیست', + 'sidebar/material/slot': 'شکاف', + 'sidebar/material/type': 'نوع', + 'sidebar/material/uuid': 'UUID', + 'sidebar/material/name': 'نام', + 'sidebar/material/program': 'برنامه', + 'sidebar/material/info': 'اطلاعات', + 'sidebar/material/vertex': 'راس', + 'sidebar/material/fragment': 'فرگ', + 'sidebar/material/color': 'رنگ', + 'sidebar/material/depthPacking': 'بسته بندی عمق', + 'sidebar/material/roughness': 'زبری', + 'sidebar/material/metalness': 'فلزی بودن', + 'sidebar/material/reflectivity': 'انعکاس', + 'sidebar/material/emissive': 'پرتاب کنندگی', + 'sidebar/material/specular': 'اسپکولار', + 'sidebar/material/shininess': 'درخشندگی', + 'sidebar/material/clearcoat': 'کلیرکت', + 'sidebar/material/clearcoatroughness': 'زبری کلیرکت', + 'sidebar/material/dispersion': 'پراکندگی', + 'sidebar/material/ior': 'IOR', + 'sidebar/material/iridescence': 'رنگین کمانی', + 'sidebar/material/iridescenceIOR': 'IOR تین فیلم', + 'sidebar/material/iridescenceThicknessMax': 'زبری تین فیلم', + 'sidebar/material/sheen': 'درخشش (شین)', + 'sidebar/material/sheenroughness': 'زبری درخشش (شین)', + 'sidebar/material/sheencolor': 'رنگ درخشش (شین)', + 'sidebar/material/transmission': 'انتقال', + 'sidebar/material/attenuationDistance': 'تضعیف فاصله', + 'sidebar/material/attenuationColor': 'تضعیف رنگ', + 'sidebar/material/thickness': 'ضخامت', + 'sidebar/material/vertexcolors': 'رنگ راس ها', + 'sidebar/material/matcap': 'متکپ', + 'sidebar/material/map': 'مپ', + 'sidebar/material/alphamap': 'مپ آلفا', + 'sidebar/material/bumpmap': 'مپ بامپ', + 'sidebar/material/normalmap': 'مپ نرمال', + 'sidebar/material/clearcoatmap': 'مپ کلیرکت', + 'sidebar/material/clearcoatnormalmap': 'مپ معمولی کلیرکت', + 'sidebar/material/clearcoatroughnessmap': 'مپ زبری کلیرکت', + 'sidebar/material/displacementmap': 'مپ جابجایی', + 'sidebar/material/roughnessmap': 'مپ زبری', + 'sidebar/material/metalnessmap': 'مپ فلزی بودن', + 'sidebar/material/specularmap': 'مپ اسپکولار', + 'sidebar/material/iridescencemap': 'مپ رنگین کمانی', + 'sidebar/material/iridescencethicknessmap': 'مپ ضخامت تین فیلم', + 'sidebar/material/sheencolormap': 'مپ رنگ درخشش (شین)', + 'sidebar/material/sheenroughnessmap': 'مپ زبری شین', + 'sidebar/material/envmap': 'مپ محیط', + 'sidebar/material/lightmap': 'مپ نور', + 'sidebar/material/aomap': 'AO مپ', + 'sidebar/material/emissivemap': 'مپ پرتاب کننده', + 'sidebar/material/gradientmap': 'مپ گردینت', + 'sidebar/material/transmissionmap': 'مپ انتقال', + 'sidebar/material/thicknessmap': 'مپ ضخامت', + 'sidebar/material/side': 'سمت', + 'sidebar/material/size': 'سایز', + 'sidebar/material/sizeAttenuation': 'تضعیف سایز', + 'sidebar/material/flatShading': 'سایه زنی تخت', + 'sidebar/material/blending': 'مخلوط کردن', + 'sidebar/material/opacity': 'کدر بودن', + 'sidebar/material/transparent': 'شفاف', + 'sidebar/material/forcesinglepass': 'فورس سینگل پس', + 'sidebar/material/alphatest': 'تست آلفا', + 'sidebar/material/depthtest': 'تست عمق', + 'sidebar/material/depthwrite': 'نوشتن عمق', + 'sidebar/material/wireframe': 'وایرفریم', + 'sidebar/material/userdata': 'داده کاربر', + 'sidebar/material/export': 'اکسپورت جیسون', + + 'sidebar/script/new': 'جدید', + 'sidebar/script/edit': 'ویرایش', + 'sidebar/script/remove': 'حذف', + + 'sidebar/project': 'پروژه ها', + 'sidebar/project/antialias': 'آنتی الآیس', + 'sidebar/project/shadows': 'سایه ها', + 'sidebar/project/toneMapping': 'تون مپینگ', + 'sidebar/project/materials': 'متریال ها', + 'sidebar/project/Assign': 'اختصاص', + + 'sidebar/project/app': 'اپ', + 'sidebar/project/app/play': 'پخش', + 'sidebar/project/app/stop': 'توقف', + 'sidebar/project/app/title': 'تیتر', + 'sidebar/project/app/editable': 'قابل ویرایش', + 'sidebar/project/app/publish': 'انتشار', + + 'sidebar/project/image': 'عکس', + 'sidebar/project/image/samples': 'نمونه ها', + 'sidebar/project/video': 'ویدیو', + + 'sidebar/project/shading': 'سایه زنی', + 'sidebar/project/resolution': 'وضوح', + 'sidebar/project/duration': 'مدت', + 'sidebar/project/render': 'رندر', + + 'sidebar/settings': 'تنظیمات', + 'sidebar/settings/language': 'زبان ها', + + 'sidebar/settings/shortcuts': 'شورت کات ها', + 'sidebar/settings/shortcuts/translate': 'ترجمه', + 'sidebar/settings/shortcuts/rotate': 'چرخش (دوران)', + 'sidebar/settings/shortcuts/scale': 'مقیاس', + 'sidebar/settings/shortcuts/undo': 'بازگشت به عقب', + 'sidebar/settings/shortcuts/focus': 'فوکوس', + + 'sidebar/history': 'هیستوری', + 'sidebar/history/clear': 'پاک کردن', + 'sidebar/history/persistent': 'ماندگار', + + 'toolbar/translate': 'ترجمه', + 'toolbar/rotate': 'چرخش (دوران)', + 'toolbar/scale': 'مقیاس', + 'toolbar/local': 'لوکال', + + 'viewport/controls/grid': 'گرید', + 'viewport/controls/helpers': 'کمک کننده', + + 'viewport/info/object': 'آبجکت', + 'viewport/info/objects': 'آبجکت ها', + 'viewport/info/vertex': 'راس', + 'viewport/info/vertices': 'رئوس', + 'viewport/info/triangle': 'مثلث', + 'viewport/info/triangles': 'مثلث ها', + 'viewport/info/sample': 'نمونه', + 'viewport/info/samples': 'نمونه ها', + 'viewport/info/rendertime': 'زمان رندر', + + 'script/title/vertexShader': 'شیدر راس', + 'script/title/fragmentShader': 'شیدر فرگمنت', + 'script/title/programInfo': 'خواص برنامه' + + }, en: { 'prompt/file/open': 'Any unsaved data will be lost. Are you sure?', diff --git a/examples/files.json b/examples/files.json index 4690f643307c29..47dc225635b51a 100644 --- a/examples/files.json +++ b/examples/files.json @@ -408,6 +408,7 @@ "webgpu_procedural_texture", "webgpu_reflection", "webgpu_refraction", + "webgpu_rendertarget_2d-array_3d", "webgpu_rtt", "webgpu_sandbox", "webgpu_shadertoy", @@ -442,6 +443,7 @@ "webgpu_tsl_vfx_flames", "webgpu_tsl_vfx_linkedparticles", "webgpu_tsl_vfx_tornado", + "webgpu_video_frame", "webgpu_video_panorama", "webgpu_volume_cloud", "webgpu_volume_perlin", @@ -513,7 +515,8 @@ "misc_exporter_usdz", "misc_exporter_exr", "misc_exporter_ktx2", - "misc_lookat" + "misc_lookat", + "misc_raycaster_helper" ], "css2d": [ "css2d_label" diff --git a/examples/jsm/animation/CCDIKSolver.js b/examples/jsm/animation/CCDIKSolver.js index 2591d0c6aac87f..c935ac1569392d 100644 --- a/examples/jsm/animation/CCDIKSolver.js +++ b/examples/jsm/animation/CCDIKSolver.js @@ -28,7 +28,7 @@ const _matrix = new Matrix4(); /** * CCD Algorithm - * - https://sites.google.com/site/auraliusproject/ccd-algorithm + * - https://web.archive.org/web/20221206080850/https://sites.google.com/site/auraliusproject/ccd-algorithm * * // ik parameter example * // diff --git a/examples/jsm/helpers/TextureHelperGPU.js b/examples/jsm/helpers/TextureHelperGPU.js index 225be3f5842098..3f48dd40ddcb59 100644 --- a/examples/jsm/helpers/TextureHelperGPU.js +++ b/examples/jsm/helpers/TextureHelperGPU.js @@ -1,11 +1,13 @@ import { + NodeMaterial, BoxGeometry, BufferAttribute, Mesh, PlaneGeometry, + DoubleSide, Vector3, } from 'three'; -import { NodeMaterial, texture as textureNode, cubeTexture, texture3D, float, vec4 } from 'three/tsl'; +import { texture as textureNode, cubeTexture, texture3D, float, vec4, attribute } from 'three/tsl'; import { mergeGeometries } from '../utils/BufferGeometryUtils.js'; class TextureHelper extends Mesh { @@ -13,17 +15,25 @@ class TextureHelper extends Mesh { constructor( texture, width = 1, height = 1, depth = 1 ) { const material = new NodeMaterial(); + material.side = DoubleSide; + material.transparent = true; material.name = 'TextureHelper'; let colorNode; + const uvw = attribute( 'uvw' ); + if ( texture.isCubeTexture ) { - colorNode = cubeTexture( texture ); + colorNode = cubeTexture( texture ).sample( uvw ); } else if ( texture.isData3DTexture || texture.isCompressed3DTexture ) { - colorNode = texture3D( texture ); + colorNode = texture3D( texture ).sample( uvw ); + + } else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { + + colorNode = textureNode( texture ).sample( uvw.xy ).depth( uvw.z ); } else { @@ -122,7 +132,7 @@ function createCubeGeometry( width, height, depth ) { } geometry.deleteAttribute( 'uv' ); - geometry.setAttribute( 'uv', uvw ); + geometry.setAttribute( 'uvw', uvw ); return geometry; @@ -162,7 +172,7 @@ function createSliceGeometry( texture, width, height, depth ) { } geometry.deleteAttribute( 'uv' ); - geometry.setAttribute( 'uv', uvw ); + geometry.setAttribute( 'uvw', uvw ); geometries.push( geometry ); diff --git a/examples/jsm/interactive/InteractiveGroup.js b/examples/jsm/interactive/InteractiveGroup.js index 89ebec3bed6e92..4720f2ffcde7ca 100644 --- a/examples/jsm/interactive/InteractiveGroup.js +++ b/examples/jsm/interactive/InteractiveGroup.js @@ -7,97 +7,154 @@ import { const _pointer = new Vector2(); const _event = { type: '', data: _pointer }; +// TODO: Dispatch pointerevents too + +/** + * The XR events that are mapped to "standard" pointer events + */ +const _events = { + 'move': 'mousemove', + 'select': 'click', + 'selectstart': 'mousedown', + 'selectend': 'mouseup' +}; + const _raycaster = new Raycaster(); class InteractiveGroup extends Group { - listenToPointerEvents( renderer, camera ) { + constructor() { + + super(); + + this.raycaster = new Raycaster(); - const scope = this; - const raycaster = new Raycaster(); + this.element = null; + this.camera = null; - const element = renderer.domElement; + this.controllers = []; - function onPointerEvent( event ) { + this._onPointerEvent = this.onPointerEvent.bind( this ); + this._onXRControllerEvent = this.onXRControllerEvent.bind( this ); - event.stopPropagation(); + } + + onPointerEvent( event ) { - const rect = renderer.domElement.getBoundingClientRect(); + event.stopPropagation(); - _pointer.x = ( event.clientX - rect.left ) / rect.width * 2 - 1; - _pointer.y = - ( event.clientY - rect.top ) / rect.height * 2 + 1; + const rect = this.element.getBoundingClientRect(); - raycaster.setFromCamera( _pointer, camera ); + _pointer.x = ( event.clientX - rect.left ) / rect.width * 2 - 1; + _pointer.y = - ( event.clientY - rect.top ) / rect.height * 2 + 1; - const intersects = raycaster.intersectObjects( scope.children, false ); + this.raycaster.setFromCamera( _pointer, this.camera ); - if ( intersects.length > 0 ) { + const intersects = this.raycaster.intersectObjects( this.children, false ); - const intersection = intersects[ 0 ]; + if ( intersects.length > 0 ) { - const object = intersection.object; - const uv = intersection.uv; + const intersection = intersects[ 0 ]; - _event.type = event.type; - _event.data.set( uv.x, 1 - uv.y ); + const object = intersection.object; + const uv = intersection.uv; - object.dispatchEvent( _event ); + _event.type = event.type; + _event.data.set( uv.x, 1 - uv.y ); - } + object.dispatchEvent( _event ); } - element.addEventListener( 'pointerdown', onPointerEvent ); - element.addEventListener( 'pointerup', onPointerEvent ); - element.addEventListener( 'pointermove', onPointerEvent ); - element.addEventListener( 'mousedown', onPointerEvent ); - element.addEventListener( 'mouseup', onPointerEvent ); - element.addEventListener( 'mousemove', onPointerEvent ); - element.addEventListener( 'click', onPointerEvent ); + } + + onXRControllerEvent( event ) { + + const controller = event.target; + + _raycaster.setFromXRController( controller ); + + const intersections = _raycaster.intersectObjects( this.children, false ); + + if ( intersections.length > 0 ) { + + const intersection = intersections[ 0 ]; + + const object = intersection.object; + const uv = intersection.uv; + + _event.type = _events[ event.type ]; + _event.data.set( uv.x, 1 - uv.y ); + + object.dispatchEvent( _event ); + + } } - listenToXRControllerEvents( controller ) { + listenToPointerEvents( renderer, camera ) { - const scope = this; + this.camera = camera; + this.element = renderer.domElement; - // TODO: Dispatch pointerevents too + this.element.addEventListener( 'pointerdown', this._onPointerEvent ); + this.element.addEventListener( 'pointerup', this._onPointerEvent ); + this.element.addEventListener( 'pointermove', this._onPointerEvent ); + this.element.addEventListener( 'mousedown', this._onPointerEvent ); + this.element.addEventListener( 'mouseup', this._onPointerEvent ); + this.element.addEventListener( 'mousemove', this._onPointerEvent ); + this.element.addEventListener( 'click', this._onPointerEvent ); - const events = { - 'move': 'mousemove', - 'select': 'click', - 'selectstart': 'mousedown', - 'selectend': 'mouseup' - }; + } - function onXRControllerEvent( event ) { + disconnectionPointerEvents() { - const controller = event.target; + if ( this.element !== null ) { - _raycaster.setFromXRController( controller ); + this.element.removeEventListener( 'pointerdown', this._onPointerEvent ); + this.element.removeEventListener( 'pointerup', this._onPointerEvent ); + this.element.removeEventListener( 'pointermove', this._onPointerEvent ); + this.element.removeEventListener( 'mousedown', this._onPointerEvent ); + this.element.removeEventListener( 'mouseup', this._onPointerEvent ); + this.element.removeEventListener( 'mousemove', this._onPointerEvent ); + this.element.removeEventListener( 'click', this._onPointerEvent ); - const intersections = _raycaster.intersectObjects( scope.children, false ); + } - if ( intersections.length > 0 ) { + } - const intersection = intersections[ 0 ]; + listenToXRControllerEvents( controller ) { - const object = intersection.object; - const uv = intersection.uv; + this.controllers.push( controller ); + controller.addEventListener( 'move', this._onXRControllerEvent ); + controller.addEventListener( 'select', this._onXRControllerEvent ); + controller.addEventListener( 'selectstart', this._onXRControllerEvent ); + controller.addEventListener( 'selectend', this._onXRControllerEvent ); - _event.type = events[ event.type ]; - _event.data.set( uv.x, 1 - uv.y ); + } + + disconnectXrControllerEvents() { - object.dispatchEvent( _event ); + for ( const controller of this.controllers ) { - } + controller.removeEventListener( 'move', this._onXRControllerEvent ); + controller.removeEventListener( 'select', this._onXRControllerEvent ); + controller.removeEventListener( 'selectstart', this._onXRControllerEvent ); + controller.removeEventListener( 'selectend', this._onXRControllerEvent ); } - controller.addEventListener( 'move', onXRControllerEvent ); - controller.addEventListener( 'select', onXRControllerEvent ); - controller.addEventListener( 'selectstart', onXRControllerEvent ); - controller.addEventListener( 'selectend', onXRControllerEvent ); + } + + disconnect() { + + this.disconnectionPointerEvents(); + this.disconnectXrControllerEvents(); + + this.camera = null; + this.element = null; + + this.controllers = []; } diff --git a/examples/jsm/libs/demuxer_mp4.js b/examples/jsm/libs/demuxer_mp4.js new file mode 100644 index 00000000000000..d5cd68de2526c0 --- /dev/null +++ b/examples/jsm/libs/demuxer_mp4.js @@ -0,0 +1,109 @@ +import MP4Box from 'https://cdn.jsdelivr.net/npm/mp4box@0.5.3/+esm'; + +// From: https://w3c.github.io/webcodecs/samples/video-decode-display/ + +// Wraps an MP4Box File as a WritableStream underlying sink. +class MP4FileSink { + #setStatus = null; + #file = null; + #offset = 0; + + constructor(file, setStatus) { + this.#file = file; + this.#setStatus = setStatus; + } + + write(chunk) { + // MP4Box.js requires buffers to be ArrayBuffers, but we have a Uint8Array. + const buffer = new ArrayBuffer(chunk.byteLength); + new Uint8Array(buffer).set(chunk); + + // Inform MP4Box where in the file this chunk is from. + buffer.fileStart = this.#offset; + this.#offset += buffer.byteLength; + + // Append chunk. + this.#setStatus("fetch", (this.#offset / (1024 ** 2)).toFixed(1) + " MiB"); + this.#file.appendBuffer(buffer); + } + + close() { + this.#setStatus("fetch", "Done"); + this.#file.flush(); + } +} + +// Demuxes the first video track of an MP4 file using MP4Box, calling +// `onConfig()` and `onChunk()` with appropriate WebCodecs objects. +export class MP4Demuxer { + #onConfig = null; + #onChunk = null; + #setStatus = null; + #file = null; + + constructor(uri, {onConfig, onChunk, setStatus}) { + this.#onConfig = onConfig; + this.#onChunk = onChunk; + this.#setStatus = setStatus; + + // Configure an MP4Box File for demuxing. + this.#file = MP4Box.createFile(); + this.#file.onError = error => setStatus("demux", error); + this.#file.onReady = this.#onReady.bind(this); + this.#file.onSamples = this.#onSamples.bind(this); + + // Fetch the file and pipe the data through. + const fileSink = new MP4FileSink(this.#file, setStatus); + fetch(uri).then(response => { + // highWaterMark should be large enough for smooth streaming, but lower is + // better for memory usage. + response.body.pipeTo(new WritableStream(fileSink, {highWaterMark: 2})); + }); + } + + // Get the appropriate `description` for a specific track. Assumes that the + // track is H.264, H.265, VP8, VP9, or AV1. + #description(track) { + const trak = this.#file.getTrackById(track.id); + for (const entry of trak.mdia.minf.stbl.stsd.entries) { + const box = entry.avcC || entry.hvcC || entry.vpcC || entry.av1C; + if (box) { + const stream = new MP4Box.DataStream(undefined, 0, MP4Box.DataStream.BIG_ENDIAN); + box.write(stream); + return new Uint8Array(stream.buffer, 8); // Remove the box header. + } + } + throw new Error("avcC, hvcC, vpcC, or av1C box not found"); + } + + #onReady(info) { + this.#setStatus("demux", "Ready"); + const track = info.videoTracks[0]; + + // Generate and emit an appropriate VideoDecoderConfig. + this.#onConfig({ + // Browser doesn't support parsing full vp8 codec (eg: `vp08.00.41.08`), + // they only support `vp8`. + codec: track.codec.startsWith('vp08') ? 'vp8' : track.codec, + codedHeight: track.video.height, + codedWidth: track.video.width, + description: this.#description(track), + }); + + // Start demuxing. + this.#file.setExtractionOptions(track.id); + this.#file.start(); + } + + #onSamples(track_id, ref, samples) { + // Generate and emit an EncodedVideoChunk for each demuxed sample. + for (const sample of samples) { + this.#onChunk(new EncodedVideoChunk({ + type: sample.is_sync ? "key" : "delta", + timestamp: 1e6 * sample.cts / sample.timescale, + duration: 1e6 * sample.duration / sample.timescale, + data: sample.data + })); + } + } +} diff --git a/examples/jsm/objects/WaterMesh.js b/examples/jsm/objects/WaterMesh.js index 267e9975db0c1f..6d9e643745acb5 100644 --- a/examples/jsm/objects/WaterMesh.js +++ b/examples/jsm/objects/WaterMesh.js @@ -2,10 +2,10 @@ import { Color, Mesh, Vector3, - NodeMaterial + MeshLambertNodeMaterial } from 'three/webgpu'; -import { Fn, add, cameraPosition, div, normalize, positionWorld, sub, time, texture, vec2, vec3, vec4, max, dot, reflect, pow, length, float, uniform, reflector, mul, mix } from 'three/tsl'; +import { Fn, add, cameraPosition, div, normalize, positionWorld, sub, time, texture, vec2, vec3, max, dot, reflect, pow, length, float, uniform, reflector, mul, mix, diffuseColor } from 'three/tsl'; /** * Work based on : @@ -18,7 +18,7 @@ class WaterMesh extends Mesh { constructor( geometry, options ) { - const material = new NodeMaterial(); + const material = new MeshLambertNodeMaterial(); super( geometry, material ); @@ -26,7 +26,7 @@ class WaterMesh extends Mesh { this.resolution = options.resolution !== undefined ? options.resolution : 0.5; - // uniforms + // Uniforms this.waterNormals = texture( options.waterNormals ); this.alpha = uniform( options.alpha !== undefined ? options.alpha : 1.0 ); @@ -58,25 +58,32 @@ class WaterMesh extends Mesh { } ); - const fragmentNode = Fn( () => { + const noise = getNoise( positionWorld.xz.mul( this.size ) ); + const surfaceNormal = normalize( noise.xzy.mul( 1.5, 1.0, 1.5 ) ); - const noise = getNoise( positionWorld.xz.mul( this.size ) ); - const surfaceNormal = normalize( noise.xzy.mul( 1.5, 1.0, 1.5 ) ); + const worldToEye = cameraPosition.sub( positionWorld ); + const eyeDirection = normalize( worldToEye ); - const diffuseLight = vec3( 0 ).toVar(); - const specularLight = vec3( 0 ).toVar(); + const reflection = normalize( reflect( this.sunDirection.negate(), surfaceNormal ) ); + const direction = max( 0.0, dot( eyeDirection, reflection ) ); + const specularLight = pow( direction, 100 ).mul( this.sunColor ).mul( 2.0 ); + const diffuseLight = max( dot( this.sunDirection, surfaceNormal ), 0.0 ).mul( this.sunColor ).mul( 0.5 ); - const worldToEye = cameraPosition.sub( positionWorld ); - const eyeDirection = normalize( worldToEye ); + const distance = length( worldToEye ); - const reflection = normalize( reflect( this.sunDirection.negate(), surfaceNormal ) ); - const direction = max( 0.0, dot( eyeDirection, reflection ) ); - specularLight.addAssign( pow( direction, 100 ).mul( this.sunColor ).mul( 2.0 ) ); - diffuseLight.addAssign( max( dot( this.sunDirection, surfaceNormal ), 0.0 ).mul( this.sunColor ).mul( 0.5 ) ); + const distortion = surfaceNormal.xz.mul( float( 0.001 ).add( float( 1.0 ).div( distance ) ) ).mul( this.distortionScale ); - const distance = length( worldToEye ); + // Material - const distortion = surfaceNormal.xz.mul( float( 0.001 ).add( float( 1.0 ).div( distance ) ) ).mul( this.distortionScale ); + material.transparent = true; + + material.opacityNode = this.alpha; + + material.shadowPositionNode = positionWorld.add( distortion ); + + material.setupOutgoingLight = () => diffuseColor.rgb; // backwards compatibility + + material.colorNode = Fn( () => { const mirrorSampler = reflector(); mirrorSampler.uvNode = mirrorSampler.uvNode.add( distortion ); @@ -90,12 +97,10 @@ class WaterMesh extends Mesh { const scatter = max( 0.0, dot( surfaceNormal, eyeDirection ) ).mul( this.waterColor ); const albedo = mix( this.sunColor.mul( diffuseLight ).mul( 0.3 ).add( scatter ), mirrorSampler.rgb.mul( specularLight ).add( mirrorSampler.rgb.mul( 0.9 ) ).add( vec3( 0.1 ) ), reflectance ); - return vec4( albedo, this.alpha ); + return albedo; } )(); - material.fragmentNode = fragmentNode; - } } diff --git a/examples/jsm/tsl/display/AfterImageNode.js b/examples/jsm/tsl/display/AfterImageNode.js index a2e627c054fd43..4367b25dcdd59f 100644 --- a/examples/jsm/tsl/display/AfterImageNode.js +++ b/examples/jsm/tsl/display/AfterImageNode.js @@ -1,4 +1,4 @@ -import { RenderTarget, Vector2, QuadMesh, NodeMaterial, PostProcessingUtils, TempNode, NodeUpdateType } from 'three/webgpu'; +import { RenderTarget, Vector2, QuadMesh, NodeMaterial, RendererUtils, TempNode, NodeUpdateType } from 'three/webgpu'; import { nodeObject, Fn, float, vec4, uv, texture, passTexture, uniform, sign, max, convertToTexture } from 'three/tsl'; /** @module AfterImageNode **/ @@ -122,7 +122,7 @@ class AfterImageNode extends TempNode { const { renderer } = frame; - _rendererState = PostProcessingUtils.resetRendererState( renderer, _rendererState ); + _rendererState = RendererUtils.resetRendererState( renderer, _rendererState ); // @@ -157,7 +157,7 @@ class AfterImageNode extends TempNode { textureNode.value = currentTexture; - PostProcessingUtils.restoreRendererState( renderer, _rendererState ); + RendererUtils.restoreRendererState( renderer, _rendererState ); } diff --git a/examples/jsm/tsl/display/AnamorphicNode.js b/examples/jsm/tsl/display/AnamorphicNode.js index 8e500efca53f3c..70c3b7c39f781c 100644 --- a/examples/jsm/tsl/display/AnamorphicNode.js +++ b/examples/jsm/tsl/display/AnamorphicNode.js @@ -1,4 +1,4 @@ -import { RenderTarget, Vector2, TempNode, QuadMesh, NodeMaterial, PostProcessingUtils } from 'three/webgpu'; +import { RenderTarget, Vector2, TempNode, QuadMesh, NodeMaterial, RendererUtils } from 'three/webgpu'; import { nodeObject, Fn, float, NodeUpdateType, uv, passTexture, uniform, convertToTexture, vec2, vec3, Loop, mix, luminance } from 'three/tsl'; /** @module AnamorphicNode **/ @@ -147,7 +147,7 @@ class AnamorphicNode extends TempNode { const { renderer } = frame; - _rendererState = PostProcessingUtils.resetRendererState( renderer, _rendererState ); + _rendererState = RendererUtils.resetRendererState( renderer, _rendererState ); // @@ -172,7 +172,7 @@ class AnamorphicNode extends TempNode { textureNode.value = currentTexture; - PostProcessingUtils.restoreRendererState( renderer, _rendererState ); + RendererUtils.restoreRendererState( renderer, _rendererState ); } diff --git a/examples/jsm/tsl/display/BloomNode.js b/examples/jsm/tsl/display/BloomNode.js index 9071e654bae47a..fe5b4785c3bb94 100644 --- a/examples/jsm/tsl/display/BloomNode.js +++ b/examples/jsm/tsl/display/BloomNode.js @@ -1,4 +1,4 @@ -import { HalfFloatType, RenderTarget, Vector2, Vector3, TempNode, QuadMesh, NodeMaterial, PostProcessingUtils, NodeUpdateType } from 'three/webgpu'; +import { HalfFloatType, RenderTarget, Vector2, Vector3, TempNode, QuadMesh, NodeMaterial, RendererUtils, NodeUpdateType } from 'three/webgpu'; import { nodeObject, Fn, float, uv, passTexture, uniform, Loop, texture, luminance, smoothstep, mix, vec4, uniformArray, add, int } from 'three/tsl'; /** @module BloomNode **/ @@ -290,7 +290,7 @@ class BloomNode extends TempNode { const { renderer } = frame; - _rendererState = PostProcessingUtils.resetRendererState( renderer, _rendererState ); + _rendererState = RendererUtils.resetRendererState( renderer, _rendererState ); // @@ -333,7 +333,7 @@ class BloomNode extends TempNode { // restore - PostProcessingUtils.restoreRendererState( renderer, _rendererState ); + RendererUtils.restoreRendererState( renderer, _rendererState ); } diff --git a/examples/jsm/tsl/display/GTAONode.js b/examples/jsm/tsl/display/GTAONode.js index c47a3f1bf9d544..0a9fe188cf0353 100644 --- a/examples/jsm/tsl/display/GTAONode.js +++ b/examples/jsm/tsl/display/GTAONode.js @@ -1,4 +1,4 @@ -import { DataTexture, RenderTarget, RepeatWrapping, Vector2, Vector3, TempNode, QuadMesh, NodeMaterial, PostProcessingUtils } from 'three/webgpu'; +import { DataTexture, RenderTarget, RepeatWrapping, Vector2, Vector3, TempNode, QuadMesh, NodeMaterial, RendererUtils } from 'three/webgpu'; import { reference, logarithmicDepthToViewZ, viewZToPerspectiveDepth, getNormalFromDepth, getScreenPosition, getViewPosition, nodeObject, Fn, float, NodeUpdateType, uv, uniform, Loop, vec2, vec3, vec4, int, dot, max, pow, abs, If, textureSize, sin, cos, PI, texture, passTexture, mat3, add, normalize, mul, cross, div, mix, sqrt, sub, acos, clamp } from 'three/tsl'; /** @module GTAONode **/ @@ -246,7 +246,7 @@ class GTAONode extends TempNode { const { renderer } = frame; - _rendererState = PostProcessingUtils.resetRendererState( renderer, _rendererState ); + _rendererState = RendererUtils.resetRendererState( renderer, _rendererState ); // @@ -266,7 +266,7 @@ class GTAONode extends TempNode { // restore - PostProcessingUtils.restoreRendererState( renderer, _rendererState ); + RendererUtils.restoreRendererState( renderer, _rendererState ); } diff --git a/examples/jsm/tsl/display/GaussianBlurNode.js b/examples/jsm/tsl/display/GaussianBlurNode.js index 3357243b7d3f6b..e1a08928767636 100644 --- a/examples/jsm/tsl/display/GaussianBlurNode.js +++ b/examples/jsm/tsl/display/GaussianBlurNode.js @@ -1,4 +1,4 @@ -import { RenderTarget, Vector2, NodeMaterial, PostProcessingUtils, QuadMesh, TempNode, NodeUpdateType } from 'three/webgpu'; +import { RenderTarget, Vector2, NodeMaterial, RendererUtils, QuadMesh, TempNode, NodeUpdateType } from 'three/webgpu'; import { nodeObject, Fn, If, float, uv, uniform, convertToTexture, vec2, vec4, passTexture, mul } from 'three/tsl'; /** @module GaussianBlurNode **/ @@ -201,7 +201,7 @@ class GaussianBlurNode extends TempNode { const { renderer } = frame; - _rendererState = PostProcessingUtils.resetRendererState( renderer, _rendererState ); + _rendererState = RendererUtils.resetRendererState( renderer, _rendererState ); // @@ -240,7 +240,7 @@ class GaussianBlurNode extends TempNode { textureNode.value = currentTexture; - PostProcessingUtils.restoreRendererState( renderer, _rendererState ); + RendererUtils.restoreRendererState( renderer, _rendererState ); } @@ -267,7 +267,7 @@ class GaussianBlurNode extends TempNode { // - const uvNode = textureNode.uvNode || uv(); + const uvNode = uv(); const directionNode = vec2( this.directionNode || 1 ); let sampleTexture, output; diff --git a/examples/jsm/tsl/display/LensflareNode.js b/examples/jsm/tsl/display/LensflareNode.js index c9a05184ce5af0..96f7b5826e2b5e 100644 --- a/examples/jsm/tsl/display/LensflareNode.js +++ b/examples/jsm/tsl/display/LensflareNode.js @@ -1,4 +1,4 @@ -import { RenderTarget, Vector2, TempNode, NodeUpdateType, QuadMesh, PostProcessingUtils, NodeMaterial } from 'three/webgpu'; +import { RenderTarget, Vector2, TempNode, NodeUpdateType, QuadMesh, RendererUtils, NodeMaterial } from 'three/webgpu'; import { convertToTexture, nodeObject, Fn, passTexture, uv, vec2, vec3, vec4, max, float, sub, int, Loop, fract, pow, distance } from 'three/tsl'; /** @module LensflareNode **/ @@ -174,7 +174,7 @@ class LensflareNode extends TempNode { const size = renderer.getDrawingBufferSize( _size ); this.setSize( size.width, size.height ); - _rendererState = PostProcessingUtils.resetRendererState( renderer, _rendererState ); + _rendererState = RendererUtils.resetRendererState( renderer, _rendererState ); _quadMesh.material = this._material; @@ -189,7 +189,7 @@ class LensflareNode extends TempNode { // restore - PostProcessingUtils.restoreRendererState( renderer, _rendererState ); + RendererUtils.restoreRendererState( renderer, _rendererState ); } diff --git a/examples/jsm/tsl/display/OutlineNode.js b/examples/jsm/tsl/display/OutlineNode.js index 70467d51971da6..d563c485a52f52 100644 --- a/examples/jsm/tsl/display/OutlineNode.js +++ b/examples/jsm/tsl/display/OutlineNode.js @@ -1,4 +1,4 @@ -import { DepthTexture, FloatType, RenderTarget, Vector2, TempNode, QuadMesh, NodeMaterial, PostProcessingUtils, NodeUpdateType } from 'three/webgpu'; +import { DepthTexture, FloatType, RenderTarget, Vector2, TempNode, QuadMesh, NodeMaterial, RendererUtils, NodeUpdateType } from 'three/webgpu'; import { Loop, int, exp, min, float, mul, uv, vec2, vec3, Fn, textureSize, orthographicDepthToViewZ, screenUV, nodeObject, uniform, vec4, passTexture, texture, perspectiveDepthToViewZ, positionView, reference } from 'three/tsl'; /** @module OutlineNode **/ @@ -443,7 +443,7 @@ class OutlineNode extends TempNode { const { renderer } = frame; const { camera, scene } = this; - _rendererState = PostProcessingUtils.resetRendererAndSceneState( renderer, scene, _rendererState ); + _rendererState = RendererUtils.resetRendererAndSceneState( renderer, scene, _rendererState ); // @@ -546,7 +546,7 @@ class OutlineNode extends TempNode { // restore - PostProcessingUtils.restoreRendererAndSceneState( renderer, scene, _rendererState ); + RendererUtils.restoreRendererAndSceneState( renderer, scene, _rendererState ); } diff --git a/examples/jsm/tsl/display/SMAANode.js b/examples/jsm/tsl/display/SMAANode.js index 6ea22c985f1e55..1d003e710df53c 100644 --- a/examples/jsm/tsl/display/SMAANode.js +++ b/examples/jsm/tsl/display/SMAANode.js @@ -1,4 +1,4 @@ -import { HalfFloatType, LinearFilter, NearestFilter, RenderTarget, Texture, Vector2, QuadMesh, NodeMaterial, TempNode, PostProcessingUtils } from 'three/webgpu'; +import { HalfFloatType, LinearFilter, NearestFilter, RenderTarget, Texture, Vector2, QuadMesh, NodeMaterial, TempNode, RendererUtils } from 'three/webgpu'; import { abs, nodeObject, Fn, NodeUpdateType, uv, uniform, convertToTexture, varyingProperty, vec2, vec4, modelViewProjection, passTexture, max, step, dot, float, texture, If, Loop, int, Break, sqrt, sign, mix } from 'three/tsl'; /** @module SMAANode **/ @@ -240,7 +240,7 @@ class SMAANode extends TempNode { const { renderer } = frame; - _rendererState = PostProcessingUtils.resetRendererState( renderer, _rendererState ); + _rendererState = RendererUtils.resetRendererState( renderer, _rendererState ); // @@ -270,7 +270,7 @@ class SMAANode extends TempNode { // restore - PostProcessingUtils.restoreRendererState( renderer, _rendererState ); + RendererUtils.restoreRendererState( renderer, _rendererState ); } diff --git a/examples/jsm/tsl/display/SSAAPassNode.js b/examples/jsm/tsl/display/SSAAPassNode.js index 0414589ca5e074..60cccd439379b4 100644 --- a/examples/jsm/tsl/display/SSAAPassNode.js +++ b/examples/jsm/tsl/display/SSAAPassNode.js @@ -1,4 +1,4 @@ -import { AdditiveBlending, Color, Vector2, PostProcessingUtils, PassNode, QuadMesh, NodeMaterial } from 'three/webgpu'; +import { AdditiveBlending, Color, Vector2, RendererUtils, PassNode, QuadMesh, NodeMaterial } from 'three/webgpu'; import { nodeObject, uniform, mrt, texture, getTextureIndex } from 'three/tsl'; /** @module SSAAPassNode **/ @@ -114,7 +114,7 @@ class SSAAPassNode extends PassNode { const { renderer } = frame; const { scene, camera } = this; - _rendererState = PostProcessingUtils.resetRendererAndSceneState( renderer, scene, _rendererState ); + _rendererState = RendererUtils.resetRendererAndSceneState( renderer, scene, _rendererState ); // @@ -230,7 +230,7 @@ class SSAAPassNode extends PassNode { // - PostProcessingUtils.restoreRendererAndSceneState( renderer, scene, _rendererState ); + RendererUtils.restoreRendererAndSceneState( renderer, scene, _rendererState ); } diff --git a/examples/jsm/tsl/display/SSRNode.js b/examples/jsm/tsl/display/SSRNode.js index 75c794f57cec75..a7bdeeecbfff06 100644 --- a/examples/jsm/tsl/display/SSRNode.js +++ b/examples/jsm/tsl/display/SSRNode.js @@ -1,4 +1,4 @@ -import { NearestFilter, RenderTarget, Vector2, PostProcessingUtils, QuadMesh, TempNode, NodeMaterial, NodeUpdateType } from 'three/webgpu'; +import { NearestFilter, RenderTarget, Vector2, RendererUtils, QuadMesh, TempNode, NodeMaterial, NodeUpdateType } from 'three/webgpu'; import { reference, viewZToPerspectiveDepth, logarithmicDepthToViewZ, getScreenPosition, getViewPosition, sqrt, mul, div, cross, float, Continue, Break, Loop, int, max, abs, sub, If, dot, reflect, normalize, screenCoordinate, nodeObject, Fn, passTexture, uv, uniform, perspectiveDepthToViewZ, orthographicDepthToViewZ, vec2, vec3, vec4 } from 'three/tsl'; /** @module SSRNode **/ @@ -77,7 +77,7 @@ class SSRNode extends TempNode { * computational overhead. * * @type {Number} - * @default + * @default 0.5 */ this.resolutionScale = 0.5; @@ -235,7 +235,7 @@ class SSRNode extends TempNode { const { renderer } = frame; - _rendererState = PostProcessingUtils.resetRendererState( renderer, _rendererState ); + _rendererState = RendererUtils.resetRendererState( renderer, _rendererState ); const size = renderer.getDrawingBufferSize( _size ); @@ -255,7 +255,7 @@ class SSRNode extends TempNode { // restore - PostProcessingUtils.restoreRendererState( renderer, _rendererState ); + RendererUtils.restoreRendererState( renderer, _rendererState ); } diff --git a/examples/jsm/tsl/display/StereoCompositePassNode.js b/examples/jsm/tsl/display/StereoCompositePassNode.js index 532d679cd513c3..56892075095983 100644 --- a/examples/jsm/tsl/display/StereoCompositePassNode.js +++ b/examples/jsm/tsl/display/StereoCompositePassNode.js @@ -1,4 +1,4 @@ -import { RenderTarget, StereoCamera, HalfFloatType, LinearFilter, NearestFilter, Vector2, PassNode, QuadMesh, PostProcessingUtils } from 'three/webgpu'; +import { RenderTarget, StereoCamera, HalfFloatType, LinearFilter, NearestFilter, Vector2, PassNode, QuadMesh, RendererUtils } from 'three/webgpu'; import { texture } from 'three/tsl'; const _size = /*@__PURE__*/ new Vector2(); @@ -127,7 +127,7 @@ class StereoCompositePassNode extends PassNode { const { renderer } = frame; const { scene, stereo, renderTarget } = this; - _rendererState = PostProcessingUtils.resetRendererState( renderer, _rendererState ); + _rendererState = RendererUtils.resetRendererState( renderer, _rendererState ); // @@ -156,7 +156,7 @@ class StereoCompositePassNode extends PassNode { // restore - PostProcessingUtils.restoreRendererState( renderer, _rendererState ); + RendererUtils.restoreRendererState( renderer, _rendererState ); } diff --git a/examples/jsm/tsl/display/StereoPassNode.js b/examples/jsm/tsl/display/StereoPassNode.js index eb486e3bcffa5c..2df92cd39c4057 100644 --- a/examples/jsm/tsl/display/StereoPassNode.js +++ b/examples/jsm/tsl/display/StereoPassNode.js @@ -1,4 +1,4 @@ -import { StereoCamera, Vector2, PassNode, PostProcessingUtils } from 'three/webgpu'; +import { StereoCamera, Vector2, PassNode, RendererUtils } from 'three/webgpu'; import { nodeObject } from 'three/tsl'; /** @module StereoPassNode **/ @@ -59,7 +59,7 @@ class StereoPassNode extends PassNode { const { renderer } = frame; const { scene, camera, stereo, renderTarget } = this; - _rendererState = PostProcessingUtils.resetRendererState( renderer, _rendererState ); + _rendererState = RendererUtils.resetRendererState( renderer, _rendererState ); // @@ -101,7 +101,7 @@ class StereoPassNode extends PassNode { // restore - PostProcessingUtils.restoreRendererState( renderer, _rendererState ); + RendererUtils.restoreRendererState( renderer, _rendererState ); } diff --git a/examples/jsm/tsl/display/TRAAPassNode.js b/examples/jsm/tsl/display/TRAAPassNode.js index b852a5ac0d4459..4ad3c49939e7df 100644 --- a/examples/jsm/tsl/display/TRAAPassNode.js +++ b/examples/jsm/tsl/display/TRAAPassNode.js @@ -1,4 +1,4 @@ -import { Color, Vector2, NearestFilter, Matrix4, PostProcessingUtils, PassNode, QuadMesh, NodeMaterial } from 'three/webgpu'; +import { Color, Vector2, NearestFilter, Matrix4, RendererUtils, PassNode, QuadMesh, NodeMaterial } from 'three/webgpu'; import { add, float, If, Loop, int, Fn, min, max, clamp, nodeObject, texture, uniform, uv, vec2, vec4, luminance } from 'three/tsl'; /** @module TRAAPassNode **/ @@ -153,7 +153,7 @@ class TRAAPassNode extends PassNode { const { renderer } = frame; const { scene, camera } = this; - _rendererState = PostProcessingUtils.resetRendererAndSceneState( renderer, scene, _rendererState ); + _rendererState = RendererUtils.resetRendererAndSceneState( renderer, scene, _rendererState ); // @@ -291,7 +291,7 @@ class TRAAPassNode extends PassNode { velocityOutput.setProjectionMatrix( null ); - PostProcessingUtils.restoreRendererAndSceneState( renderer, scene, _rendererState ); + RendererUtils.restoreRendererAndSceneState( renderer, scene, _rendererState ); } diff --git a/examples/misc_raycaster_helper.html b/examples/misc_raycaster_helper.html new file mode 100644 index 00000000000000..6a21223ded9f2d --- /dev/null +++ b/examples/misc_raycaster_helper.html @@ -0,0 +1,112 @@ + + + + three.js misc - raycaster - helper + + + + + +
    + three.js - raycaster - helper
    + See external RaycasterHelper for more information. +
    + + + + + + + \ No newline at end of file diff --git a/examples/screenshots/misc_raycaster_helper.jpg b/examples/screenshots/misc_raycaster_helper.jpg new file mode 100644 index 00000000000000..5b5d4dd82c2670 Binary files /dev/null and b/examples/screenshots/misc_raycaster_helper.jpg differ diff --git a/examples/screenshots/webgl_geometry_teapot.jpg b/examples/screenshots/webgl_geometry_teapot.jpg index 47f95d54d598b4..ec05d359f447f3 100644 Binary files a/examples/screenshots/webgl_geometry_teapot.jpg and b/examples/screenshots/webgl_geometry_teapot.jpg differ diff --git a/examples/screenshots/webgpu_lights_ies_spotlight.jpg b/examples/screenshots/webgpu_lights_ies_spotlight.jpg index d645a62b822167..492dd1dc4c21d0 100644 Binary files a/examples/screenshots/webgpu_lights_ies_spotlight.jpg and b/examples/screenshots/webgpu_lights_ies_spotlight.jpg differ diff --git a/examples/screenshots/webgpu_postprocessing_ssr.jpg b/examples/screenshots/webgpu_postprocessing_ssr.jpg index bfed0539c6375f..89212457efb475 100644 Binary files a/examples/screenshots/webgpu_postprocessing_ssr.jpg and b/examples/screenshots/webgpu_postprocessing_ssr.jpg differ diff --git a/examples/screenshots/webgpu_rendertarget_2d-array_3d.jpg b/examples/screenshots/webgpu_rendertarget_2d-array_3d.jpg new file mode 100644 index 00000000000000..da9ddafedad849 Binary files /dev/null and b/examples/screenshots/webgpu_rendertarget_2d-array_3d.jpg differ diff --git a/examples/screenshots/webgpu_shadowmap_opacity.jpg b/examples/screenshots/webgpu_shadowmap_opacity.jpg index 6075d34a5029d6..3fb79125f00791 100644 Binary files a/examples/screenshots/webgpu_shadowmap_opacity.jpg and b/examples/screenshots/webgpu_shadowmap_opacity.jpg differ diff --git a/examples/screenshots/webgpu_textures_2d-array_compressed.jpg b/examples/screenshots/webgpu_textures_2d-array_compressed.jpg index f3b39b56d4154d..c92bba94c8d2d4 100644 Binary files a/examples/screenshots/webgpu_textures_2d-array_compressed.jpg and b/examples/screenshots/webgpu_textures_2d-array_compressed.jpg differ diff --git a/examples/screenshots/webgpu_video_frame.jpg b/examples/screenshots/webgpu_video_frame.jpg new file mode 100644 index 00000000000000..0f418a4bdb1013 Binary files /dev/null and b/examples/screenshots/webgpu_video_frame.jpg differ diff --git a/examples/tags.json b/examples/tags.json index b103ba8298fd06..1c508c2d1f4632 100644 --- a/examples/tags.json +++ b/examples/tags.json @@ -5,6 +5,7 @@ "misc_controls_orbit": [ "rotation" ], "misc_controls_trackball": [ "rotation" ], "misc_controls_transform": [ "scale", "rotate", "translate" ], + "misc_raycaster_helper": [ "external" ], "physics_ammo_cloth": [ "integration" ], "physics_jolt_instancing": [ "external" ], "physics_rapier_instancing": [ "external" ], @@ -144,8 +145,10 @@ "webgpu_postprocessing_ssaa": [ "msaa", "multisampled" ], "webgpu_refraction": [ "water" ], "webgpu_rtt": [ "renderTarget", "texture" ], + "webgpu_rendertarget_2d-array_3d": [ "renderTarget", "2d-array", "3d" ], "webgpu_sky": [ "sun" ], "webgpu_tonemapping": [ "gltf" ], "webgpu_tsl_compute_attractors_particles": [ "gpgpu" ], - "webgpu_ocean": [ "water" ] + "webgpu_ocean": [ "water" ], + "webgpu_video_frame": [ "webcodecs" ] } diff --git a/examples/webgl_geometry_teapot.html b/examples/webgl_geometry_teapot.html index 66d379f7b2034e..8c1eed556a1e40 100644 --- a/examples/webgl_geometry_teapot.html +++ b/examples/webgl_geometry_teapot.html @@ -63,9 +63,9 @@ camera.position.set( - 600, 550, 1300 ); // LIGHTS - ambientLight = new THREE.AmbientLight( 0x7c7c7c, 3.0 ); + ambientLight = new THREE.AmbientLight( 0x7c7c7c, 2.0 ); - light = new THREE.DirectionalLight( 0xFFFFFF, 3.0 ); + light = new THREE.DirectionalLight( 0xFFFFFF, 2.0 ); light.position.set( 0.32, 0.39, 0.7 ); // RENDERER @@ -96,7 +96,7 @@ materials[ 'wireframe' ] = new THREE.MeshBasicMaterial( { wireframe: true } ); materials[ 'flat' ] = new THREE.MeshPhongMaterial( { specular: 0x000000, flatShading: true, side: THREE.DoubleSide } ); materials[ 'smooth' ] = new THREE.MeshLambertMaterial( { side: THREE.DoubleSide } ); - materials[ 'glossy' ] = new THREE.MeshPhongMaterial( { side: THREE.DoubleSide } ); + materials[ 'glossy' ] = new THREE.MeshPhongMaterial( { color: 0xc0c0c0, specular: 0x404040, shininess: 300, side: THREE.DoubleSide } ); materials[ 'textured' ] = new THREE.MeshPhongMaterial( { map: textureMap, side: THREE.DoubleSide } ); materials[ 'reflective' ] = new THREE.MeshPhongMaterial( { envMap: textureCube, side: THREE.DoubleSide } ); diff --git a/examples/webgpu_backdrop_water.html b/examples/webgpu_backdrop_water.html index 03d9b3c4b755c7..e18b980b99a113 100644 --- a/examples/webgpu_backdrop_water.html +++ b/examples/webgpu_backdrop_water.html @@ -191,7 +191,7 @@ // renderer - renderer = new THREE.WebGPURenderer( { antialias: true } ); + renderer = new THREE.WebGPURenderer(); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); renderer.setAnimationLoop( animate ); diff --git a/examples/webgpu_lights_ies_spotlight.html b/examples/webgpu_lights_ies_spotlight.html index f34d1264a2c05c..6494c47b083e74 100644 --- a/examples/webgpu_lights_ies_spotlight.html +++ b/examples/webgpu_lights_ies_spotlight.html @@ -31,6 +31,8 @@ import { IESLoader } from 'three/addons/loaders/IESLoader.js'; + import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; + let renderer, scene, camera; let lights; @@ -53,42 +55,58 @@ // const spotLight = new THREE.IESSpotLight( 0xff0000, 500 ); - spotLight.position.set( 6.5, 1.5, 6.5 ); + spotLight.position.set( 6.5, 3, 6.5 ); spotLight.angle = Math.PI / 8; spotLight.penumbra = 0.7; spotLight.distance = 20; + spotLight.castShadow = true; spotLight.iesMap = iesTexture1; + spotLight.userData.helper = new THREE.SpotLightHelper( spotLight ); scene.add( spotLight ); + scene.add( spotLight.target ); + scene.add( spotLight.userData.helper ); // const spotLight2 = new THREE.IESSpotLight( 0x00ff00, 500 ); - spotLight2.position.set( 6.5, 1.5, - 6.5 ); + spotLight2.position.set( - 6.5, 3, 6.5 ); spotLight2.angle = Math.PI / 8; spotLight2.penumbra = 0.7; spotLight2.distance = 20; + spotLight2.castShadow = true; spotLight2.iesMap = iesTexture2; + spotLight2.userData.helper = new THREE.SpotLightHelper( spotLight2 ); scene.add( spotLight2 ); + scene.add( spotLight2.target ); + scene.add( spotLight2.userData.helper ); // const spotLight3 = new THREE.IESSpotLight( 0x0000ff, 500 ); - spotLight3.position.set( - 6.5, 1.5, - 6.5 ); + spotLight3.position.set( - 6.5, 3, - 6.5 ); spotLight3.angle = Math.PI / 8; spotLight3.penumbra = 0.7; spotLight3.distance = 20; + spotLight3.castShadow = true; spotLight3.iesMap = iesTexture3; + spotLight3.userData.helper = new THREE.SpotLightHelper( spotLight3 ); scene.add( spotLight3 ); + scene.add( spotLight3.target ); + scene.add( spotLight3.userData.helper ); // const spotLight4 = new THREE.IESSpotLight( 0xffffff, 500 ); - spotLight4.position.set( - 6.5, 1.5, 6.5 ); + spotLight4.position.set( 6.5, 3, - 6.5 ); spotLight4.angle = Math.PI / 8; spotLight4.penumbra = 0.7; spotLight4.distance = 20; + spotLight4.castShadow = true; spotLight4.iesMap = iesTexture4; + spotLight4.userData.helper = new THREE.SpotLightHelper( spotLight4 ); scene.add( spotLight4 ); + scene.add( spotLight4.target ); + scene.add( spotLight4.userData.helper ); // @@ -96,20 +114,30 @@ // - const material = new THREE.MeshPhongMaterial( { color: 0x808080/*, dithering: true*/ } ); + const material = new THREE.MeshPhongMaterial( { color: 0x999999/*, dithering: true*/ } ); const geometry = new THREE.PlaneGeometry( 200, 200 ); const mesh = new THREE.Mesh( geometry, material ); mesh.rotation.x = - Math.PI * 0.5; + mesh.receiveShadow = true; scene.add( mesh ); + const geometry2 = new THREE.BoxGeometry( 2, 2, 2 ); + //const geometry2 = new THREE.IcosahedronGeometry( 1, 5 ); + + const mesh2 = new THREE.Mesh( geometry2, material ); + mesh2.position.y = 1; + mesh2.castShadow = true; + scene.add( mesh2 ); + // renderer = new THREE.WebGPURenderer( { antialias: true } ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); renderer.setAnimationLoop( render ); + renderer.shadowMap.enabled = true; document.body.appendChild( renderer.domElement ); camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, .1, 100 ); @@ -122,6 +150,28 @@ // + function setHelperVisible( value ) { + + for ( let i = 0; i < lights.length; i ++ ) { + + lights[ i ].userData.helper.visible = value; + + } + + } + + setHelperVisible( false ); + + // + + const gui = new GUI(); + + gui.add( { helper: false }, 'helper' ).onChange( ( v ) => setHelperVisible( v ) ); + + gui.open(); + + // + window.addEventListener( 'resize', onWindowResize ); } @@ -137,11 +187,18 @@ function render( time ) { - time = ( time / 1000 ) * 2.0; + time = time / 1000; for ( let i = 0; i < lights.length; i ++ ) { - lights[ i ].position.y = Math.sin( time + i ) + 0.97; + const t = ( Math.sin( ( time + i ) * ( Math.PI / 2 ) ) + 1 ) / 2; + + const x = THREE.MathUtils.lerp( lights[ i ].position.x, 0, t ); + const z = THREE.MathUtils.lerp( lights[ i ].position.z, 0, t ); + + lights[ i ].target.position.x = x; + lights[ i ].target.position.z = z; + if ( lights[ i ].userData.helper ) lights[ i ].userData.helper.update(); } diff --git a/examples/webgpu_multisampled_renderbuffers.html b/examples/webgpu_multisampled_renderbuffers.html index 7b3ec32d50d484..aea799f9fdddca 100644 --- a/examples/webgpu_multisampled_renderbuffers.html +++ b/examples/webgpu_multisampled_renderbuffers.html @@ -71,7 +71,7 @@ const gui = new GUI(); gui.add( params, 'samples', 0, 4 ).step( 1 ); - gui.add( params, 'animated', true ); + gui.add( params, 'animated' ); } diff --git a/examples/webgpu_occlusion.html b/examples/webgpu_occlusion.html index 39325f63e727d4..4d42643323990e 100644 --- a/examples/webgpu_occlusion.html +++ b/examples/webgpu_occlusion.html @@ -92,7 +92,7 @@ const plane = new THREE.Mesh( planeGeometry, new THREE.MeshPhongNodeMaterial( { color: 0x00ff00, side: THREE.DoubleSide } ) ); const sphere = new THREE.Mesh( sphereGeometry, new THREE.MeshPhongNodeMaterial( { color: 0xffff00 } ) ); - const instanceUniform = nodeObject( new OcclusionNode( sphere, new THREE.Color( 0x00ff00 ), new THREE.Color( 0x0000ff ) ) ); + const instanceUniform = nodeObject( new OcclusionNode( sphere, new THREE.Color( 0x0000ff ), new THREE.Color( 0x00ff00 ) ) ); plane.material.colorNode = instanceUniform; @@ -107,11 +107,6 @@ renderer = new THREE.WebGPURenderer( { antialias: true } ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); - - // ensure shaders/pipelines are all complete before rendering - - await renderer.compileAsync( scene, camera ); - renderer.setAnimationLoop( render ); document.body.appendChild( renderer.domElement ); diff --git a/examples/webgpu_postprocessing_ssr.html b/examples/webgpu_postprocessing_ssr.html index c2a014a246fcec..3b8ce308892144 100644 --- a/examples/webgpu_postprocessing_ssr.html +++ b/examples/webgpu_postprocessing_ssr.html @@ -31,6 +31,7 @@ import * as THREE from 'three'; import { pass, mrt, output, transformedNormalView, metalness, blendColor, screenUV, color } from 'three/tsl'; import { ssr } from 'three/addons/tsl/display/SSRNode.js'; + import { smaa } from 'three/addons/tsl/display/SMAANode.js'; import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js'; import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; @@ -40,7 +41,7 @@ import Stats from 'three/addons/libs/stats.module.js'; const params = { - maxDistance: 0.2, + maxDistance: 0.5, opacity: 1, thickness: 0.015, enabled: true @@ -54,10 +55,10 @@ async function init() { camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 0.1, 50 ); - camera.position.set( 2.5, 2, 2.5 ); + camera.position.set( 3, 2, 3 ); scene = new THREE.Scene(); - scene.backgroundNode = screenUV.distance( .5 ).remap( 0, 0.5 ).mix( color( 0x666666 ), color( 0x393939 ) ); + scene.backgroundNode = screenUV.distance( .5 ).remap( 0, 0.5 ).mix( color( 0x888877 ), color( 0x776666 ) ); const dracoLoader = new DRACOLoader(); dracoLoader.setDecoderPath( 'jsm/libs/draco/' ); @@ -67,6 +68,18 @@ loader.setDRACOLoader( dracoLoader ); loader.load( 'models/gltf/steampunk_camera.glb', function ( gltf ) { + gltf.scene.traverse( function ( object ) { + + if ( object.material ) { + + // Avoid overdrawing + object.material.side = THREE.FrontSide; + + } + + } ); + + gltf.scene.position.y = 0.1; scene.add( gltf.scene ); } ); @@ -74,9 +87,10 @@ // renderer = new THREE.WebGPURenderer(); - renderer.setPixelRatio( window.devicePixelRatio ); + // renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); renderer.setAnimationLoop( animate ); + renderer.toneMapping = THREE.ACESFilmicToneMapping; document.body.appendChild( renderer.domElement ); await renderer.init(); @@ -85,7 +99,7 @@ const pmremGenerator = new THREE.PMREMGenerator( renderer ); scene.environment = pmremGenerator.fromScene( environment ).texture; - scene.environmentIntensity = 0.75; + scene.environmentIntensity = 1.25; pmremGenerator.dispose(); // @@ -105,14 +119,14 @@ const scenePassMetalness = scenePass.getTextureNode( 'metalness' ); ssrPass = ssr( scenePassColor, scenePassDepth, scenePassNormal, scenePassMetalness, camera ); + ssrPass.resolutionScale = 1.0; // blend SSR over beauty - const outputNode = blendColor( scenePassColor, ssrPass ); + const outputNode = smaa( blendColor( scenePassColor, ssrPass ) ); postProcessing.outputNode = outputNode; - // controls = new OrbitControls( camera, renderer.domElement ); diff --git a/examples/webgpu_rendertarget_2d-array_3d.html b/examples/webgpu_rendertarget_2d-array_3d.html new file mode 100644 index 00000000000000..c1565a64c36113 --- /dev/null +++ b/examples/webgpu_rendertarget_2d-array_3d.html @@ -0,0 +1,339 @@ + + + + three.js webgpu - RenderTargetArray and RenderTarget3D + + + + + + + +
    + three.js - WebGPU - RenderTargetArray and RenderTarget3D
    +
    +
    DataArrayTexture
    +
    Data3DTexture
    +
    RenderTarget3D
    +
    RenderTargetArray
    + + + + + + \ No newline at end of file diff --git a/examples/webgpu_video_frame.html b/examples/webgpu_video_frame.html new file mode 100644 index 00000000000000..99f14628fa4563 --- /dev/null +++ b/examples/webgpu_video_frame.html @@ -0,0 +1,116 @@ + + + + three.js webgpu - video frames + + + + + +
    + three.js - video - frames
    + Decodes all frames from a MP4 file and renders them onto a plane as fast as possible.
    + mp4box.js used for MP4 parsing. +
    + + + + + + diff --git a/manual/en/offscreencanvas.html b/manual/en/offscreencanvas.html index 30279c21c25c4d..260f82089c6788 100644 --- a/manual/en/offscreencanvas.html +++ b/manual/en/offscreencanvas.html @@ -815,6 +815,7 @@

    OffscreenCanvas

    'pointerType', 'clientX', 'clientY', + 'pointerId', 'pageX', 'pageY', ]); @@ -853,6 +854,10 @@

    OffscreenCanvas

    } function touchEventHandler(event, sendFn) { + // preventDefault() fixes mousemove, mouseup and mousedown + // firing when doing a simple touchup touchdown + // Happens only at offscreen canvas + event.preventDefault(); const touches = []; const data = {type: event.type, touches}; for (let i = 0; i < event.touches.length; ++i) { @@ -860,6 +865,8 @@

    OffscreenCanvas

    touches.push({ pageX: touch.pageX, pageY: touch.pageY, + clientX: touch.clientX, + clientY: touch.clientY, }); } sendFn(data); diff --git a/manual/examples/offscreencanvas-w-orbitcontrols.html b/manual/examples/offscreencanvas-w-orbitcontrols.html index 56fe3c9b35d67a..099cd34a35fb23 100644 --- a/manual/examples/offscreencanvas-w-orbitcontrols.html +++ b/manual/examples/offscreencanvas-w-orbitcontrols.html @@ -34,6 +34,7 @@ 'pointerType', 'clientX', 'clientY', + 'pointerId', 'pageX', 'pageY', ] ); @@ -84,7 +85,11 @@ } function touchEventHandler( event, sendFn ) { - + + // preventDefault() fixes mousemove, mouseup and mousedown + // firing at touch events when doing a simple touchup touchdown + // Happens only at offscreen canvas + event.preventDefault(); const touches = []; const data = { type: event.type, touches }; for ( let i = 0; i < event.touches.length; ++ i ) { @@ -93,6 +98,8 @@ touches.push( { pageX: touch.pageX, pageY: touch.pageY, + clientX: touch.clientX, + clientY: touch.clientY, } ); } diff --git a/manual/ja/offscreencanvas.html b/manual/ja/offscreencanvas.html index 997f329f0f8dd1..cd1d363e2276d2 100644 --- a/manual/ja/offscreencanvas.html +++ b/manual/ja/offscreencanvas.html @@ -767,6 +767,7 @@

    のOffscreenCanvas

    'pointerType', 'clientX', 'clientY', + 'pointerId', 'pageX', 'pageY', ]); @@ -805,6 +806,10 @@

    のOffscreenCanvas

    } function touchEventHandler(event, sendFn) { + // preventDefault() fixes mousemove, mouseup and mousedown + // firing when doing a simple touchup touchdown + // Happens only at offscreen canvas + event.preventDefault(); const touches = []; const data = {type: event.type, touches}; for (let i = 0; i < event.touches.length; ++i) { @@ -812,6 +817,8 @@

    のOffscreenCanvas

    touches.push({ pageX: touch.pageX, pageY: touch.pageY, + clientX: touch.clientX, + clientY: touch.clientY, }); } sendFn(data); diff --git a/manual/ko/offscreencanvas.html b/manual/ko/offscreencanvas.html index c9d3d87cdb68bd..3b3a64462d0c3e 100644 --- a/manual/ko/offscreencanvas.html +++ b/manual/ko/offscreencanvas.html @@ -717,6 +717,7 @@

    OffscreenCanvas

    'pointerType', 'clientX', 'clientY', + 'pointerId', 'pageX', 'pageY', ]); @@ -755,6 +756,10 @@

    OffscreenCanvas

    } function touchEventHandler(event, sendFn) { + // preventDefault() fixes mousemove, mouseup and mousedown + // firing when doing a simple touchup touchdown + // Happens only at offscreen canvas + event.preventDefault(); const touches = []; const data = { type: event.type, touches }; for (let i = 0; i < event.touches.length; ++i) { @@ -762,6 +767,8 @@

    OffscreenCanvas

    touches.push({ pageX: touch.pageX, pageY: touch.pageY, + clientX: touch.clientX, + clientY: touch.clientY, }); } sendFn(data); diff --git a/manual/resources/threejs-material-table.js b/manual/resources/threejs-material-table.js index cfe5552b74ea8d..c6ba1d49c6f47f 100644 --- a/manual/resources/threejs-material-table.js +++ b/manual/resources/threejs-material-table.js @@ -9,6 +9,8 @@ const materials = [ 'color', 'combine', 'envMap', + 'envMapRotation', + 'fog', 'lightMap', 'lightMapIntensity', 'map', @@ -16,6 +18,9 @@ const materials = [ 'refractionRatio', 'specularMap', 'wireframe', + 'wireframeLinecap', + 'wireframeLinejoin', + 'wireframeLinewidth' ], }, { @@ -29,13 +34,16 @@ const materials = [ 'bumpScale', 'color', 'combine', + 'displacementBias', 'displacementMap', 'displacementScale', - 'displacementBias', 'emissive', - 'emissiveMap', 'emissiveIntensity', + 'emissiveMap', 'envMap', + 'envMapRotation', + 'flatShading', + 'fog', 'lightMap', 'lightMapIntensity', 'map', @@ -46,6 +54,9 @@ const materials = [ 'refractionRatio', 'specularMap', 'wireframe', + 'wireframeLinecap', + 'wireframeLinejoin', + 'wireframeLinewidth' ], }, { @@ -59,13 +70,16 @@ const materials = [ 'bumpScale', 'color', 'combine', + 'displacementBias', 'displacementMap', 'displacementScale', - 'displacementBias', 'emissive', - 'emissiveMap', 'emissiveIntensity', + 'emissiveMap', 'envMap', + 'envMapRotation', + 'flatShading', + 'fog', 'lightMap', 'lightMapIntensity', 'map', @@ -78,6 +92,9 @@ const materials = [ 'specular', 'specularMap', 'wireframe', + 'wireframeLinecap', + 'wireframeLinejoin', + 'wireframeLinewidth' ], }, { @@ -90,14 +107,17 @@ const materials = [ 'bumpMap', 'bumpScale', 'color', + 'displacementBias', 'displacementMap', 'displacementScale', - 'displacementBias', 'emissive', - 'emissiveMap', 'emissiveIntensity', + 'emissiveMap', 'envMap', 'envMapIntensity', + 'envMapRotation', + 'flatShading', + 'fog', 'lightMap', 'lightMapIntensity', 'map', @@ -106,10 +126,12 @@ const materials = [ 'normalMap', 'normalMapType', 'normalScale', - 'refractionRatio', 'roughness', 'roughnessMap', 'wireframe', + 'wireframeLinecap', + 'wireframeLinejoin', + 'wireframeLinewidth' ], }, { @@ -119,38 +141,46 @@ const materials = [ 'alphaMap', 'aoMap', 'aoMapIntensity', + 'anisotropy', + 'anisotropyRotation', + 'anisotropyMap', + 'attenuationColor', + 'attenuationDistance', 'bumpMap', 'bumpScale', 'clearcoat', 'clearcoatMap', + 'clearcoatNormalMap', + 'clearcoatNormalScale', 'clearcoatRoughness', 'clearcoatRoughnessMap', - 'clearcoatNormalScale', - 'clearcoatNormalMap', 'color', + 'displacementBias', 'displacementMap', 'displacementScale', - 'displacementBias', 'emissive', - 'emissiveMap', 'emissiveIntensity', + 'emissiveMap', 'envMap', 'envMapIntensity', + 'envMapRotation', + 'flatShading', + 'fog', + 'ior', 'iridescence', - 'iridescenceMap', 'iridescenceIOR', - 'iridescenceThicknessRange', + 'iridescenceMap', 'iridescenceThicknessMap', + 'iridescenceThicknessRange', 'lightMap', 'lightMapIntensity', - 'ior', 'map', 'metalness', 'metalnessMap', 'normalMap', 'normalMapType', 'normalScale', - 'refractionRatio', + 'reflectivity', 'roughness', 'roughnessMap', 'sheen', @@ -158,31 +188,28 @@ const materials = [ 'sheenColorMap', 'sheenRoughness', 'sheenRoughnessMap', + 'specularColor', + 'specularColorMap', + 'specularIntensity', + 'specularIntensityMap', 'thickness', 'thicknessMap', 'transmission', 'transmissionMap', - 'attenuationDistance', - 'attenuationColor', - 'anisotropy', - 'anisotropyRotation', - 'anisotropyMap', - 'specularIntensity', - 'specularIntensityMap', - 'specularColor', - 'specularColorMap', 'wireframe', - 'reflectivity', + 'wireframeLinecap', + 'wireframeLinejoin', + 'wireframeLinewidth' ], }, ]; -const allProperties = {}; +const allProperties = new Set(); materials.forEach( ( material ) => { material.properties.forEach( ( property ) => { - allProperties[ property ] = true; + allProperties.add( property ); } ); @@ -222,7 +249,7 @@ const thead = addElem( 'thead', table ); } -Object.keys( allProperties ).sort().forEach( ( property ) => { +Array.from( allProperties ).sort().forEach( ( property ) => { const tr = addElem( 'tr', table ); addElem( 'td', tr, property ); diff --git a/manual/ru/offscreencanvas.html b/manual/ru/offscreencanvas.html index d2c091239dbe23..3e8edf4b2756e8 100644 --- a/manual/ru/offscreencanvas.html +++ b/manual/ru/offscreencanvas.html @@ -748,6 +748,7 @@

    OffscreenCanvas

    'pointerType', 'clientX', 'clientY', + 'pointerId', 'pageX', 'pageY', ]); @@ -786,6 +787,10 @@

    OffscreenCanvas

    } function touchEventHandler(event, sendFn) { + // preventDefault() fixes mousemove, mouseup and mousedown + // firing when doing a simple touchup touchdown + // Happens only at offscreen canvas + event.preventDefault(); const touches = []; const data = {type: event.type, touches}; for (let i = 0; i < event.touches.length; ++i) { @@ -793,6 +798,8 @@

    OffscreenCanvas

    touches.push({ pageX: touch.pageX, pageY: touch.pageY, + clientX: touch.clientX, + clientY: touch.clientY, }); } sendFn(data); diff --git a/package-lock.json b/package-lock.json index bd13998c49e0e4..d376ffb1211311 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "three", - "version": "0.171.0", + "version": "0.172.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "three", - "version": "0.171.0", + "version": "0.172.0", "license": "MIT", "devDependencies": { "@rollup/plugin-node-resolve": "^16.0.0", @@ -66,12 +66,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", - "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", + "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", "dev": true, "dependencies": { - "@babel/types": "^7.26.0" + "@babel/types": "^7.26.3" }, "bin": { "parser": "bin/babel-parser.js" @@ -92,16 +92,10 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/runtime/node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true - }, "node_modules/@babel/types": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", - "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", + "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.25.9", @@ -273,18 +267,6 @@ "node": ">=18" } }, - "node_modules/@jimp/core/node_modules/mime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/@jimp/diff": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@jimp/diff/-/diff-1.6.0.tgz", @@ -701,9 +683,9 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "dev": true, "dependencies": { "@jridgewell/set-array": "^1.2.1", @@ -759,9 +741,9 @@ } }, "node_modules/@jsdoc/salty": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.8.tgz", - "integrity": "sha512-5e+SFVavj1ORKlKaKr2BmTOekmXbelU7dC0cDkQLqag7xfuTPuGMUFx7KWJuv4bYZrTsoL2Z18VVCOKYxzoHcg==", + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.9.tgz", + "integrity": "sha512-yYxMVH7Dqw6nO0d5NIV8OQWnitU8k6vXH8NtgqAfIa/IUqRMxRv/NUJJ08VEKbAakwxlgBl5PJdrU0dMPStsnw==", "dev": true, "dependencies": { "lodash": "^4.17.21" @@ -771,11 +753,10 @@ } }, "node_modules/@mdn/browser-compat-data": { - "version": "5.6.24", - "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.6.24.tgz", - "integrity": "sha512-xNoWeI2TJN5UNTqpqpK0uGncUW1cL+QksxKfNblXsQ6Uu8ONVHcqLbTZxs6+/VMFEE4ZdRzI3j+0Mw3oJtdsyg==", - "dev": true, - "license": "CC0-1.0" + "version": "5.6.26", + "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.6.26.tgz", + "integrity": "sha512-7NdgdOR7lkzrN70zGSULmrcvKyi/aJjpTJRCbuy8IZuHiLkPTvsr10jW0MJgWzK2l2wTmhdQvegTw6yNU5AVNQ==", + "dev": true }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", @@ -1001,7 +982,6 @@ "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.0.tgz", "integrity": "sha512-0FPvAeVUT/zdWoO0jnb/V5BlBsUSNfkIOtFHzMO4H9MOklrmQFY6FduVHKucNb/aTFxvnGhj4MNj/T1oNdDfNg==", "dev": true, - "license": "MIT", "dependencies": { "@rollup/pluginutils": "^5.0.1", "@types/resolve": "1.20.2", @@ -1044,9 +1024,9 @@ } }, "node_modules/@rollup/pluginutils": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.3.tgz", - "integrity": "sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", + "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==", "dev": true, "dependencies": { "@types/estree": "^1.0.0", @@ -1066,9 +1046,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.28.1.tgz", - "integrity": "sha512-2aZp8AES04KI2dy3Ss6/MDjXbwBzj+i0GqKtWXgw2/Ma6E4jJvujryO6gJAghIRVz7Vwr9Gtl/8na3nDUKpraQ==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.29.2.tgz", + "integrity": "sha512-s/8RiF4bdmGnc/J0N7lHAr5ZFJj+NdJqJ/Hj29K+c4lEdoVlukzvWXB9XpWZCdakVT0YAw8iyIqUP2iFRz5/jA==", "cpu": [ "arm" ], @@ -1080,9 +1060,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.28.1.tgz", - "integrity": "sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.29.2.tgz", + "integrity": "sha512-mKRlVj1KsKWyEOwR6nwpmzakq6SgZXW4NUHNWlYSiyncJpuXk7wdLzuKdWsRoR1WLbWsZBKvsUCdCTIAqRn9cA==", "cpu": [ "arm64" ], @@ -1094,9 +1074,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.28.1.tgz", - "integrity": "sha512-prduvrMKU6NzMq6nxzQw445zXgaDBbMQvmKSJaxpaZ5R1QDM8w+eGxo6Y/jhT/cLoCvnZI42oEqf9KQNYz1fqQ==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.29.2.tgz", + "integrity": "sha512-vJX+vennGwygmutk7N333lvQ/yKVAHnGoBS2xMRQgXWW8tvn46YWuTDOpKroSPR9BEW0Gqdga2DHqz8Pwk6X5w==", "cpu": [ "arm64" ], @@ -1108,9 +1088,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.28.1.tgz", - "integrity": "sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.29.2.tgz", + "integrity": "sha512-e2rW9ng5O6+Mt3ht8fH0ljfjgSCC6ffmOipiLUgAnlK86CHIaiCdHCzHzmTkMj6vEkqAiRJ7ss6Ibn56B+RE5w==", "cpu": [ "x64" ], @@ -1122,9 +1102,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.28.1.tgz", - "integrity": "sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.29.2.tgz", + "integrity": "sha512-/xdNwZe+KesG6XJCK043EjEDZTacCtL4yurMZRLESIgHQdvtNyul3iz2Ab03ZJG0pQKbFTu681i+4ETMF9uE/Q==", "cpu": [ "arm64" ], @@ -1136,9 +1116,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.28.1.tgz", - "integrity": "sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.29.2.tgz", + "integrity": "sha512-eXKvpThGzREuAbc6qxnArHh8l8W4AyTcL8IfEnmx+bcnmaSGgjyAHbzZvHZI2csJ+e0MYddl7DX0X7g3sAuXDQ==", "cpu": [ "x64" ], @@ -1150,9 +1130,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.28.1.tgz", - "integrity": "sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.29.2.tgz", + "integrity": "sha512-h4VgxxmzmtXLLYNDaUcQevCmPYX6zSj4SwKuzY7SR5YlnCBYsmvfYORXgiU8axhkFCDtQF3RW5LIXT8B14Qykg==", "cpu": [ "arm" ], @@ -1164,9 +1144,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.28.1.tgz", - "integrity": "sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.29.2.tgz", + "integrity": "sha512-EObwZ45eMmWZQ1w4N7qy4+G1lKHm6mcOwDa+P2+61qxWu1PtQJ/lz2CNJ7W3CkfgN0FQ7cBUy2tk6D5yR4KeXw==", "cpu": [ "arm" ], @@ -1178,9 +1158,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.28.1.tgz", - "integrity": "sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.29.2.tgz", + "integrity": "sha512-Z7zXVHEXg1elbbYiP/29pPwlJtLeXzjrj4241/kCcECds8Zg9fDfURWbZHRIKrEriAPS8wnVtdl4ZJBvZr325w==", "cpu": [ "arm64" ], @@ -1192,9 +1172,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.28.1.tgz", - "integrity": "sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.29.2.tgz", + "integrity": "sha512-TF4kxkPq+SudS/r4zGPf0G08Bl7+NZcFrUSR3484WwsHgGgJyPQRLCNrQ/R5J6VzxfEeQR9XRpc8m2t7lD6SEQ==", "cpu": [ "arm64" ], @@ -1206,9 +1186,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.28.1.tgz", - "integrity": "sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.29.2.tgz", + "integrity": "sha512-kO9Fv5zZuyj2zB2af4KA29QF6t7YSxKrY7sxZXfw8koDQj9bx5Tk5RjH+kWKFKok0wLGTi4bG117h31N+TIBEg==", "cpu": [ "loong64" ], @@ -1220,9 +1200,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.28.1.tgz", - "integrity": "sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.29.2.tgz", + "integrity": "sha512-gIh776X7UCBaetVJGdjXPFurGsdWwHHinwRnC5JlLADU8Yk0EdS/Y+dMO264OjJFo7MXQ5PX4xVFbxrwK8zLqA==", "cpu": [ "ppc64" ], @@ -1234,9 +1214,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.28.1.tgz", - "integrity": "sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.29.2.tgz", + "integrity": "sha512-YgikssQ5UNq1GoFKZydMEkhKbjlUq7G3h8j6yWXLBF24KyoA5BcMtaOUAXq5sydPmOPEqB6kCyJpyifSpCfQ0w==", "cpu": [ "riscv64" ], @@ -1248,9 +1228,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.28.1.tgz", - "integrity": "sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.29.2.tgz", + "integrity": "sha512-9ouIR2vFWCyL0Z50dfnon5nOrpDdkTG9lNDs7MRaienQKlTyHcDxplmk3IbhFlutpifBSBr2H4rVILwmMLcaMA==", "cpu": [ "s390x" ], @@ -1262,9 +1242,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.28.1.tgz", - "integrity": "sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.29.2.tgz", + "integrity": "sha512-ckBBNRN/F+NoSUDENDIJ2U9UWmIODgwDB/vEXCPOMcsco1niTkxTXa6D2Y/pvCnpzaidvY2qVxGzLilNs9BSzw==", "cpu": [ "x64" ], @@ -1276,9 +1256,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.28.1.tgz", - "integrity": "sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.29.2.tgz", + "integrity": "sha512-jycl1wL4AgM2aBFJFlpll/kGvAjhK8GSbEmFT5v3KC3rP/b5xZ1KQmv0vQQ8Bzb2ieFQ0kZFPRMbre/l3Bu9JA==", "cpu": [ "x64" ], @@ -1290,9 +1270,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.28.1.tgz", - "integrity": "sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.29.2.tgz", + "integrity": "sha512-S2V0LlcOiYkNGlRAWZwwUdNgdZBfvsDHW0wYosYFV3c7aKgEVcbonetZXsHv7jRTTX+oY5nDYT4W6B1oUpMNOg==", "cpu": [ "arm64" ], @@ -1304,9 +1284,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.28.1.tgz", - "integrity": "sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.29.2.tgz", + "integrity": "sha512-pW8kioj9H5f/UujdoX2atFlXNQ9aCfAxFRaa+mhczwcsusm6gGrSo4z0SLvqLF5LwFqFTjiLCCzGkNK/LE0utQ==", "cpu": [ "ia32" ], @@ -1318,9 +1298,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.28.1.tgz", - "integrity": "sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.29.2.tgz", + "integrity": "sha512-p6fTArexECPf6KnOHvJXRpAEq0ON1CBtzG/EY4zw08kCHk/kivBc5vUEtnCFNCHOpJZ2ne77fxwRLIKD4wuW2Q==", "cpu": [ "x64" ], @@ -1641,9 +1621,9 @@ } }, "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.1.tgz", + "integrity": "sha512-fEzPV3hSkSMltkw152tJKNARhOupqbH96MZWyRjNaYZOMIzbrTeQDG+MTc6Mr2pgzFQzFxAfmhGDNP5QK++2ZA==", "dev": true }, "node_modules/abbrev": { @@ -1696,21 +1676,18 @@ } }, "node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", "dev": true, - "dependencies": { - "debug": "^4.3.4" - }, "engines": { "node": ">= 14" } }, "node_modules/agentkeepalive": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", - "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", "dev": true, "dependencies": { "humanize-ms": "^1.2.1" @@ -1840,13 +1817,13 @@ "dev": true }, "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" }, "engines": { "node": ">= 0.4" @@ -1902,15 +1879,15 @@ } }, "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -1920,15 +1897,15 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -1938,19 +1915,18 @@ } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" }, "engines": { "node": ">= 0.4" @@ -1964,7 +1940,6 @@ "resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.8.1.tgz", "integrity": "sha512-ht3Dm6Zr7SXv6t1Ra6gFo0+kLDglHGrEbYihTkcycrbHw7WCcuhBzPlJYHEsIpycaUwzsJHje+vUcxXUX4ztTA==", "dev": true, - "license": "MIT", "dependencies": { "@mdn/browser-compat-data": "^5.6.19" } @@ -2054,13 +2029,13 @@ } }, "node_modules/bare-stream": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.3.2.tgz", - "integrity": "sha512-EFZHSIBkDgSHIwj2l2QZfP4U5OcD4xFAOwhSb/vlr9PIqyGJGvB/nfClJbcnh3EY4jtPE4zsb5ztae96bVF79A==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.6.1.tgz", + "integrity": "sha512-eVZbtKM+4uehzrsj49KtCy3Pbg7kO1pJ3SKZ1SFrIH/0pnj9scuGGgUlNDf/7qS8WKtGdiJY5Kyhs/ivYPTB/g==", "dev": true, "optional": true, "dependencies": { - "streamx": "^2.20.0" + "streamx": "^2.21.0" } }, "node_modules/base64-js": { @@ -2315,9 +2290,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", - "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.3.tgz", + "integrity": "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==", "dev": true, "funding": [ { @@ -2334,9 +2309,9 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001669", - "electron-to-chromium": "^1.5.41", - "node-releases": "^2.0.18", + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.1" }, "bin": { @@ -2427,16 +2402,44 @@ } }, "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dev": true, "dependencies": { + "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -2477,9 +2480,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001688", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001688.tgz", - "integrity": "sha512-Nmqpru91cuABu/DTCXbM2NSRHzM2uVHfPnhJ/1zEAJx/ILBRVmz3pzH4N7DZqbdG0gWClsCC05Oj0mJ/1AWMbA==", + "version": "1.0.30001690", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz", + "integrity": "sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==", "dev": true, "funding": [ { @@ -2494,8 +2497,7 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ], - "license": "CC-BY-4.0" + ] }, "node_modules/catharsis": { "version": "0.9.0", @@ -2510,9 +2512,9 @@ } }, "node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", "dev": true, "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" @@ -2544,6 +2546,15 @@ "devtools-protocol": "*" } }, + "node_modules/chromium-bidi/node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "node_modules/clean-css": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", @@ -2573,20 +2584,6 @@ "jsdoc": ">=3.x <=4.x" } }, - "node_modules/clean-jsdoc-theme/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -2744,12 +2741,12 @@ } }, "node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", "dev": true, "engines": { - "node": ">= 10" + "node": ">=14" } }, "node_modules/concat-map": { @@ -2759,11 +2756,10 @@ "dev": true }, "node_modules/concurrently": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.1.0.tgz", - "integrity": "sha512-VxkzwMAn4LP7WyMnJNbHN5mKV9L2IbyDjpzemKr99sXNR3GqRNMMHdm7prV1ws9wg7ETj6WUkNOigZVsptwbgg==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.1.2.tgz", + "integrity": "sha512-H9MWcoPsYddwbOGM6difjVwVZHl63nwMEwDJG/L7VGtuaJhb12h2caPG2tVPWs7emuYix252iGfqOyrz1GczTQ==", "dev": true, - "license": "MIT", "dependencies": { "chalk": "^4.1.2", "lodash": "^4.17.21", @@ -2789,7 +2785,6 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -2805,7 +2800,6 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2822,7 +2816,6 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -2912,9 +2905,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "dependencies": { "path-key": "^3.1.0", @@ -2935,14 +2928,14 @@ } }, "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -2952,29 +2945,29 @@ } }, "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/inspect-js" } }, "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" }, @@ -2986,9 +2979,9 @@ } }, "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, "dependencies": { "ms": "^2.1.3" @@ -3171,9 +3164,9 @@ } }, "node_modules/domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.1.tgz", + "integrity": "sha512-xWXmuRnN9OMP6ptPd2+H0cCbcYBULa5YDTbMm/2lvkWvNA3O4wcW+GvzooqBuNM8yy6pl3VIAeJTUUWUbfI5Fw==", "dev": true, "dependencies": { "dom-serializer": "^2.0.0", @@ -3243,6 +3236,20 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/dpdm/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, "node_modules/dpdm/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -3255,6 +3262,20 @@ "node": ">=8" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/duplexer": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", @@ -3274,9 +3295,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.5.49", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.49.tgz", - "integrity": "sha512-ZXfs1Of8fDb6z7WEYZjXpgIRF6MEu8JdeGA0A40aZq6OQbS+eJpnnV49epZRna2DU/YsEjSQuGtQPPtvt6J65A==", + "version": "1.5.76", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.76.tgz", + "integrity": "sha512-CjVQyG7n7Sr+eBXE86HIulnL5N8xZY1sgmOPGuq/F0Rr0FJq63lg0kEtOIDfZBk44FnDLf6FUJ+dsJcuiUDdDQ==", "dev": true }, "node_modules/emoji-regex": { @@ -3350,57 +3371,60 @@ } }, "node_modules/es-abstract": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", - "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "version": "1.23.8", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.8.tgz", + "integrity": "sha512-lfab8IzDn6EpI1ibZakcgS6WsfEBiB+43cuJo+wgylx1xKXf+Sp+YR3vFuQwC/u3sxYwV8Cxe3B0DpVUu/WiJQ==", "dev": true, "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.2.6", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", + "is-data-view": "^1.0.2", + "is-regex": "^1.2.1", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.0", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.3", "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", + "object.assign": "^4.1.7", + "own-keys": "^1.0.0", + "regexp.prototype.flags": "^1.5.3", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.18" }, "engines": { "node": ">= 0.4" @@ -3410,13 +3434,10 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, "engines": { "node": ">= 0.4" } @@ -3466,14 +3487,14 @@ } }, "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dev": true, "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" }, "engines": { "node": ">= 0.4" @@ -3643,7 +3664,6 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-6.0.2.tgz", "integrity": "sha512-1ME+YfJjmOz1blH0nPZpHgjMGK4kjgEeoYqGCqoBPQ/mGu/dJzdoP0f1C8H2jcWZjzhZjAMccbM/VdXhPORIfA==", "dev": true, - "license": "MIT", "dependencies": { "@mdn/browser-compat-data": "^5.5.35", "ast-metadata-inferer": "^0.8.1", @@ -3662,11 +3682,10 @@ } }, "node_modules/eslint-plugin-compat/node_modules/globals": { - "version": "15.13.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.13.0.tgz", - "integrity": "sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g==", + "version": "15.14.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz", + "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==", "dev": true, - "license": "MIT", "engines": { "node": ">=18" }, @@ -3920,9 +3939,9 @@ "dev": true }, "node_modules/express": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", - "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "dev": true, "dependencies": { "accepts": "~1.3.8", @@ -3944,7 +3963,7 @@ "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", @@ -3959,6 +3978,10 @@ }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/express/node_modules/debug": { @@ -4101,9 +4124,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", + "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -4220,9 +4243,9 @@ } }, "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", "dev": true }, "node_modules/for-each": { @@ -4269,9 +4292,9 @@ } }, "node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, "dependencies": { "graceful-fs": "^4.2.0", @@ -4279,7 +4302,7 @@ "universalify": "^2.0.0" }, "engines": { - "node": ">=14.14" + "node": ">=12" } }, "node_modules/fs-minipass": { @@ -4324,15 +4347,17 @@ } }, "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" }, "engines": { "node": ">= 0.4" @@ -4406,16 +4431,21 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", + "integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==", "dev": true, "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "dunder-proto": "^1.0.0", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -4440,14 +4470,14 @@ } }, "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -4457,15 +4487,14 @@ } }, "node_modules/get-uri": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz", - "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz", + "integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==", "dev": true, "dependencies": { "basic-ftp": "^5.0.2", "data-uri-to-buffer": "^6.0.2", - "debug": "^4.3.4", - "fs-extra": "^11.2.0" + "debug": "^4.3.4" }, "engines": { "node": ">= 14" @@ -4581,12 +4610,12 @@ "dev": true }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4626,10 +4655,13 @@ "dev": true }, "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "dev": true, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -4656,10 +4688,13 @@ } }, "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", "dev": true, + "dependencies": { + "dunder-proto": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -4668,9 +4703,9 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, "engines": { "node": ">= 0.4" @@ -4713,9 +4748,9 @@ } }, "node_modules/hosted-git-info": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", - "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.3.tgz", + "integrity": "sha512-HVJyzUrLIL1c0QmviVh5E8VGyUS7xCFPS6yydaVd1UegW+ibV/CohqTH9MkOLDp5o+rb82DMo77PTuc9F/8GKw==", "dev": true, "dependencies": { "lru-cache": "^7.5.1" @@ -4754,15 +4789,6 @@ "node": "^14.13.1 || >=16.0.0" } }, - "node_modules/html-minifier-terser/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true, - "engines": { - "node": ">=14" - } - }, "node_modules/htmlparser2": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", @@ -4818,12 +4844,12 @@ } }, "node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dev": true, "dependencies": { - "agent-base": "^7.0.2", + "agent-base": "^7.1.2", "debug": "4" }, "engines": { @@ -4984,14 +5010,14 @@ "dev": true }, "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, "dependencies": { "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" + "hasown": "^2.0.2", + "side-channel": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -5020,13 +5046,14 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -5041,26 +5068,44 @@ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, "dependencies": { - "has-bigints": "^1.0.1" + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz", + "integrity": "sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -5082,9 +5127,9 @@ } }, "node_modules/is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, "dependencies": { "hasown": "^2.0.2" @@ -5097,11 +5142,13 @@ } }, "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "dev": true, "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" }, "engines": { @@ -5112,12 +5159,13 @@ } }, "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -5150,6 +5198,21 @@ "node": ">=0.10.0" } }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -5159,13 +5222,28 @@ "node": ">=8" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", "dev": true, "dependencies": { - "is-extglob": "^2.1.1" + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" }, "engines": { "node": ">=0.10.0" @@ -5186,16 +5264,10 @@ "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", "dev": true }, - "node_modules/is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", - "dev": true - }, - "node_modules/is-negative-zero": { + "node_modules/is-map": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, "engines": { "node": ">= 0.4" @@ -5204,13 +5276,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true + }, "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -5229,13 +5308,15 @@ } }, "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -5244,13 +5325,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, "dependencies": { - "call-bind": "^1.0.7" + "call-bound": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -5260,12 +5353,13 @@ } }, "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -5275,12 +5369,14 @@ } }, "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -5290,12 +5386,12 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, "dependencies": { - "which-typed-array": "^1.1.14" + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -5316,13 +5412,44 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.0.tgz", + "integrity": "sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==", "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5702,11 +5829,10 @@ "dev": true }, "node_modules/magic-string": { - "version": "0.30.15", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.15.tgz", - "integrity": "sha512-zXeaYRgZ6ldS1RJJUrMrYgNJ4fdwnyI6tVqoiIhyCyv5IVTK9BU8Ic2l253GGETQHxI4HNUwhJ3fjDhKqEoaAw==", + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", "dev": true, - "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } @@ -5982,6 +6108,15 @@ "node": ">= 12" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/mdurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", @@ -6016,15 +6151,15 @@ } }, "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", "dev": true, "bin": { "mime": "cli.js" }, "engines": { - "node": ">=4" + "node": ">=10.0.0" } }, "node_modules/mime-db": { @@ -6373,9 +6508,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "dev": true }, "node_modules/node-watch": { @@ -6659,9 +6794,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", "dev": true, "engines": { "node": ">= 0.4" @@ -6680,14 +6815,16 @@ } }, "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", "object-keys": "^1.1.1" }, "engines": { @@ -6730,12 +6867,13 @@ } }, "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, @@ -6888,6 +7026,23 @@ "node": ">=8" } }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -6934,19 +7089,19 @@ } }, "node_modules/pac-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz", - "integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.1.0.tgz", + "integrity": "sha512-Z5FnLVVZSnX7WjBg0mhDtydeRZ1xMcATZThjySQUHqr+0ksP8kqaw23fNKkaaN/Z8gwLUs/W7xdl0I75eP2Xyw==", "dev": true, "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", - "agent-base": "^7.0.2", + "agent-base": "^7.1.2", "debug": "^4.3.4", "get-uri": "^6.0.1", "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.5", + "https-proxy-agent": "^7.0.6", "pac-resolver": "^7.0.1", - "socks-proxy-agent": "^8.0.4" + "socks-proxy-agent": "^8.0.5" }, "engines": { "node": ">= 14" @@ -7149,9 +7304,9 @@ } }, "node_modules/path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "dev": true }, "node_modules/peek-readable": { @@ -7281,19 +7436,19 @@ } }, "node_modules/proxy-agent": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", - "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", + "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", "dev": true, "dependencies": { - "agent-base": "^7.0.2", + "agent-base": "^7.1.2", "debug": "^4.3.4", "http-proxy-agent": "^7.0.1", - "https-proxy-agent": "^7.0.3", + "https-proxy-agent": "^7.0.6", "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.0.1", + "pac-proxy-agent": "^7.1.0", "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.2" + "socks-proxy-agent": "^8.0.5" }, "engines": { "node": ">= 14" @@ -7423,7 +7578,6 @@ "resolved": "https://registry.npmjs.org/qunit/-/qunit-2.23.1.tgz", "integrity": "sha512-CGrsGy7NhkQmfiyOixBpbexh2PT7ekIb35uWiBi/hBNdTJF1W98UonyACFJJs8UmcP96lH+YJlX99dYZi5rZkg==", "dev": true, - "license": "MIT", "dependencies": { "commander": "7.2.0", "node-watch": "0.7.3", @@ -7436,6 +7590,15 @@ "node": ">=10" } }, + "node_modules/qunit/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -7558,6 +7721,34 @@ "url": "https://github.com/sponsors/Borewit" } }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.9.tgz", + "integrity": "sha512-r0Ay04Snci87djAsI4U+WNRcSw5S4pOH7qFjd/veA5gC7TbqESR3tcj28ia95L/fYUDw11JKP7uqUKUAfVvV5Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "dunder-proto": "^1.0.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, "node_modules/regexp.prototype.flags": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", @@ -7604,18 +7795,21 @@ } }, "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "dev": true, "dependencies": { - "is-core-module": "^2.13.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7705,9 +7899,9 @@ } }, "node_modules/rollup": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.28.1.tgz", - "integrity": "sha512-61fXYl/qNVinKmGSTHAZ6Yy8I3YIJC/r2m9feHo6SwVAVcLT5MPwOUFe7EuURA/4m0NR8lXG4BBXuo/IZEsjMg==", + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.29.2.tgz", + "integrity": "sha512-tJXpsEkzsEzyAKIaB3qv3IuvTVcTN7qBw1jL4SPPXM3vzDrJgiLGFY6+HodgFaUHAJ2RYJ94zV5MKRJCoQzQeA==", "dev": true, "license": "MIT", "dependencies": { @@ -7721,25 +7915,25 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.28.1", - "@rollup/rollup-android-arm64": "4.28.1", - "@rollup/rollup-darwin-arm64": "4.28.1", - "@rollup/rollup-darwin-x64": "4.28.1", - "@rollup/rollup-freebsd-arm64": "4.28.1", - "@rollup/rollup-freebsd-x64": "4.28.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.28.1", - "@rollup/rollup-linux-arm-musleabihf": "4.28.1", - "@rollup/rollup-linux-arm64-gnu": "4.28.1", - "@rollup/rollup-linux-arm64-musl": "4.28.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.28.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.28.1", - "@rollup/rollup-linux-riscv64-gnu": "4.28.1", - "@rollup/rollup-linux-s390x-gnu": "4.28.1", - "@rollup/rollup-linux-x64-gnu": "4.28.1", - "@rollup/rollup-linux-x64-musl": "4.28.1", - "@rollup/rollup-win32-arm64-msvc": "4.28.1", - "@rollup/rollup-win32-ia32-msvc": "4.28.1", - "@rollup/rollup-win32-x64-msvc": "4.28.1", + "@rollup/rollup-android-arm-eabi": "4.29.2", + "@rollup/rollup-android-arm64": "4.29.2", + "@rollup/rollup-darwin-arm64": "4.29.2", + "@rollup/rollup-darwin-x64": "4.29.2", + "@rollup/rollup-freebsd-arm64": "4.29.2", + "@rollup/rollup-freebsd-x64": "4.29.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.29.2", + "@rollup/rollup-linux-arm-musleabihf": "4.29.2", + "@rollup/rollup-linux-arm64-gnu": "4.29.2", + "@rollup/rollup-linux-arm64-musl": "4.29.2", + "@rollup/rollup-linux-loongarch64-gnu": "4.29.2", + "@rollup/rollup-linux-powerpc64le-gnu": "4.29.2", + "@rollup/rollup-linux-riscv64-gnu": "4.29.2", + "@rollup/rollup-linux-s390x-gnu": "4.29.2", + "@rollup/rollup-linux-x64-gnu": "4.29.2", + "@rollup/rollup-linux-x64-musl": "4.29.2", + "@rollup/rollup-win32-arm64-msvc": "4.29.2", + "@rollup/rollup-win32-ia32-msvc": "4.29.2", + "@rollup/rollup-win32-x64-msvc": "4.29.2", "fsevents": "~2.3.2" } }, @@ -7763,13 +7957,13 @@ } }, "node_modules/rollup-plugin-visualizer": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.12.0.tgz", - "integrity": "sha512-8/NU9jXcHRs7Nnj07PF2o4gjxmm9lXIrZ8r175bT9dK8qoLlvKTwRMArRCMgpMGlq8CTLugRvEmyMeMXIU2pNQ==", + "version": "5.13.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.13.1.tgz", + "integrity": "sha512-vMg8i6BprL8aFm9DKvL2c8AwS8324EgymYQo9o6E26wgVvwMhsJxS37aNL6ZsU7X9iAcMYwdME7gItLfG5fwJg==", "dev": true, "dependencies": { "open": "^8.4.0", - "picomatch": "^2.3.1", + "picomatch": "^4.0.2", "source-map": "^0.7.4", "yargs": "^17.5.1" }, @@ -7777,29 +7971,21 @@ "rollup-plugin-visualizer": "dist/bin/cli.js" }, "engines": { - "node": ">=14" + "node": ">=18" }, "peerDependencies": { + "rolldown": "1.x", "rollup": "2.x || 3.x || 4.x" }, "peerDependenciesMeta": { + "rolldown": { + "optional": true + }, "rollup": { "optional": true } } }, - "node_modules/rollup-plugin-visualizer/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/rollup-plugin-visualizer/node_modules/source-map": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", @@ -7842,14 +8028,15 @@ } }, "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", "isarray": "^2.0.5" }, "engines": { @@ -7879,15 +8066,31 @@ } ] }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", - "is-regex": "^1.1.4" + "is-regex": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -7987,6 +8190,18 @@ "node": ">= 0.8" } }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", @@ -8096,30 +8311,30 @@ "dev": true }, "node_modules/servez": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/servez/-/servez-2.2.4.tgz", - "integrity": "sha512-HcsVAEnEvDq5WH9kLQBK6SvykTRFllX052b34k5mCs/XpwTXdxYyf4+1pCJdHenLb1gGuEZzcm5HdHRdVciBHA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/servez/-/servez-2.3.0.tgz", + "integrity": "sha512-47Et/S+wuVwO2qsNMT/MhVNLvlBJD6sr+qQxTdvNoWOEzDRPfdQWSy6qjWUHWd70n39HoVLAvfPhWAFlgVMbvQ==", "dev": true, "dependencies": { "ansi-colors": "^4.1.3", "color-support": "^1.1.3", "commander": "^12.1.0", - "servez-lib": "^2.9.5" + "servez-lib": "^2.10.0" }, "bin": { "servez": "bin/servez" } }, "node_modules/servez-lib": { - "version": "2.9.5", - "resolved": "https://registry.npmjs.org/servez-lib/-/servez-lib-2.9.5.tgz", - "integrity": "sha512-ET3M1Vd4v6a0uz2bQBsZ/fOS8Mmx0GLWYr4cPVKA/QNKLrrBfnzHVkIR3wRxxsC8kU11jS93HTu8zOkZAp1wBw==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/servez-lib/-/servez-lib-2.10.0.tgz", + "integrity": "sha512-QLh3bXMBljYRajszb0f5gp5W3aJg/8LSfHY5UYY+fzWt4+egDr21ZnKUrzEPYV8XNajiAyinOlaGbzL6NHUJFQ==", "dev": true, "dependencies": { "basic-auth": "^2.0.1", "cors": "^2.8.5", - "debug": "^4.3.7", - "express": "^4.21.1", + "debug": "^4.4.0", + "express": "^4.21.2", "secure-compare": "^3.0.1", "selfsigned": "^2.4.1", "serve-index": "^1.9.1", @@ -8201,10 +8416,13 @@ } }, "node_modules/shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", + "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", "dev": true, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -8235,15 +8453,69 @@ } }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -8446,12 +8718,12 @@ } }, "node_modules/socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", "dev": true, "dependencies": { - "agent-base": "^7.1.1", + "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" }, @@ -8538,9 +8810,9 @@ } }, "node_modules/streamx": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.20.1.tgz", - "integrity": "sha512-uTa0mU6WUC65iUvzKH4X9hEdvSW7rbPxPtwfWiLMSj3qTdQbAiUboZTxauKfpFuGIGa1C2BYijZ7wgdUXICJhA==", + "version": "2.21.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.21.1.tgz", + "integrity": "sha512-PhP9wUnFLa+91CPy3N6tiQsK+gnYyUNuk15S3YG/zjYE7RuPeCjJngqnzpC31ow0lzBHQ+QGO4cNJnd0djYUsw==", "dev": true, "dependencies": { "fast-fifo": "^1.3.2", @@ -8626,15 +8898,18 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -8644,15 +8919,19 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -8840,9 +9119,9 @@ } }, "node_modules/terser": { - "version": "5.36.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", - "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", + "version": "5.37.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz", + "integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -8864,10 +9143,13 @@ "dev": true }, "node_modules/text-decoder": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.1.tgz", - "integrity": "sha512-x9v3H/lTKIJKQQe7RPQkLfKAnc9lUTkWDypIQgTzPJAq+5/GCDHonmshfvlsNSj58yyshbIJJDLmU15qNERrXQ==", - "dev": true + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "dev": true, + "dependencies": { + "b4a": "^1.6.4" + } }, "node_modules/text-table": { "version": "0.2.0", @@ -8945,9 +9227,9 @@ } }, "node_modules/tslib": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", - "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true }, "node_modules/tuf-js": { @@ -9125,30 +9407,30 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -9158,17 +9440,18 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" }, "engines": { "node": ">= 0.4" @@ -9178,17 +9461,17 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-proto": "^1.0.3", "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" }, "engines": { "node": ">= 0.4" @@ -9198,9 +9481,9 @@ } }, "node_modules/typescript": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -9217,15 +9500,18 @@ "dev": true }, "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", + "call-bound": "^1.0.3", "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9411,31 +9697,80 @@ } }, "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", + "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==", "dev": true, "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "for-each": "^0.3.3", - "gopd": "^1.0.1", + "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" }, "engines": { @@ -9758,9 +10093,9 @@ } }, "node_modules/zod": { - "version": "3.23.8", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", - "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", + "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", "dev": true, "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/package.json b/package.json index 0343b1601cbcdf..1152877339ccb4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "three", - "version": "0.171.0", + "version": "0.172.0", "description": "JavaScript 3D library", "type": "module", "main": "./build/three.cjs", diff --git a/src/Three.Core.js b/src/Three.Core.js index f7a10261f0014e..782018000d8111 100644 --- a/src/Three.Core.js +++ b/src/Three.Core.js @@ -21,6 +21,7 @@ export { Line } from './objects/Line.js'; export { Points } from './objects/Points.js'; export { Group } from './objects/Group.js'; export { VideoTexture } from './textures/VideoTexture.js'; +export { VideoFrameTexture } from './textures/VideoFrameTexture.js'; export { FramebufferTexture } from './textures/FramebufferTexture.js'; export { Source } from './textures/Source.js'; export { DataTexture } from './textures/DataTexture.js'; @@ -85,6 +86,8 @@ export { AnimationMixer } from './animation/AnimationMixer.js'; export { AnimationClip } from './animation/AnimationClip.js'; export { AnimationAction } from './animation/AnimationAction.js'; export { RenderTarget } from './core/RenderTarget.js'; +export { RenderTarget3D } from './core/RenderTarget3D.js'; +export { RenderTargetArray } from './core/RenderTargetArray.js'; export { Uniform } from './core/Uniform.js'; export { UniformsGroup } from './core/UniformsGroup.js'; export { InstancedBufferGeometry } from './core/InstancedBufferGeometry.js'; diff --git a/src/Three.TSL.js b/src/Three.TSL.js index 07fd8ff155a309..acae79ad4f26ee 100644 --- a/src/Three.TSL.js +++ b/src/Three.TSL.js @@ -33,7 +33,6 @@ export const abs = TSL.abs; export const acesFilmicToneMapping = TSL.acesFilmicToneMapping; export const acos = TSL.acos; export const add = TSL.add; -export const addMethodChaining = TSL.addMethodChaining; export const addNodeElement = TSL.addNodeElement; export const agxToneMapping = TSL.agxToneMapping; export const all = TSL.all; @@ -115,6 +114,7 @@ export const colorSpaceToWorking = TSL.colorSpaceToWorking; export const colorToDirection = TSL.colorToDirection; export const compute = TSL.compute; export const cond = TSL.cond; +export const Const = TSL.Const; export const context = TSL.context; export const convert = TSL.convert; export const convertColorSpace = TSL.convertColorSpace; @@ -155,6 +155,7 @@ export const exp2 = TSL.exp2; export const expression = TSL.expression; export const faceDirection = TSL.faceDirection; export const faceForward = TSL.faceForward; +export const faceforward = TSL.faceforward; export const float = TSL.float; export const floor = TSL.floor; export const fog = TSL.fog; @@ -194,6 +195,7 @@ export const instancedDynamicBufferAttribute = TSL.instancedDynamicBufferAttribu export const instancedMesh = TSL.instancedMesh; export const int = TSL.int; export const inverseSqrt = TSL.inverseSqrt; +export const inversesqrt = TSL.inversesqrt; export const invocationLocalIndex = TSL.invocationLocalIndex; export const invocationSubgroupIndex = TSL.invocationSubgroupIndex; export const ior = TSL.ior; @@ -218,6 +220,7 @@ export const lights = TSL.lights; export const linearDepth = TSL.linearDepth; export const linearToneMapping = TSL.linearToneMapping; export const localId = TSL.localId; +export const globalId = TSL.globalId; export const log = TSL.log; export const log2 = TSL.log2; export const logarithmicDepthToViewZ = TSL.logarithmicDepthToViewZ; @@ -228,7 +231,7 @@ export const mat2 = TSL.mat2; export const mat3 = TSL.mat3; export const mat4 = TSL.mat4; export const matcapUV = TSL.matcapUV; -export const materialAOMap = TSL.materialAOMap; +export const materialAO = TSL.materialAO; export const materialAlphaTest = TSL.materialAlphaTest; export const materialAnisotropy = TSL.materialAnisotropy; export const materialAnisotropyVector = TSL.materialAnisotropyVector; @@ -410,7 +413,7 @@ export const select = TSL.select; export const setCurrentStack = TSL.setCurrentStack; export const shaderStages = TSL.shaderStages; export const shadow = TSL.shadow; -export const shadowWorldPosition = TSL.shadowWorldPosition; +export const shadowPositionWorld = TSL.shadowPositionWorld; export const sharedUniformGroup = TSL.sharedUniformGroup; export const sheen = TSL.sheen; export const sheenRoughness = TSL.sheenRoughness; @@ -495,6 +498,7 @@ export const uv = TSL.uv; export const uvec2 = TSL.uvec2; export const uvec3 = TSL.uvec3; export const uvec4 = TSL.uvec4; +export const Var = TSL.Var; export const varying = TSL.varying; export const varyingProperty = TSL.varyingProperty; export const vec2 = TSL.vec2; diff --git a/src/Three.WebGPU.Nodes.js b/src/Three.WebGPU.Nodes.js index f3371c57d0d463..cffe29047e11f5 100644 --- a/src/Three.WebGPU.Nodes.js +++ b/src/Three.WebGPU.Nodes.js @@ -7,8 +7,8 @@ export { default as BundleGroup } from './renderers/common/BundleGroup.js'; export { default as QuadMesh } from './renderers/common/QuadMesh.js'; export { default as PMREMGenerator } from './renderers/common/extras/PMREMGenerator.js'; export { default as PostProcessing } from './renderers/common/PostProcessing.js'; -import * as PostProcessingUtils from './renderers/common/PostProcessingUtils.js'; -export { PostProcessingUtils }; +import * as RendererUtils from './renderers/common/RendererUtils.js'; +export { RendererUtils }; export { default as StorageTexture } from './renderers/common/StorageTexture.js'; export { default as StorageBufferAttribute } from './renderers/common/StorageBufferAttribute.js'; export { default as StorageInstancedBufferAttribute } from './renderers/common/StorageInstancedBufferAttribute.js'; diff --git a/src/Three.WebGPU.js b/src/Three.WebGPU.js index 4289377b368d9a..94717330c2e9ca 100644 --- a/src/Three.WebGPU.js +++ b/src/Three.WebGPU.js @@ -7,8 +7,8 @@ export { default as BundleGroup } from './renderers/common/BundleGroup.js'; export { default as QuadMesh } from './renderers/common/QuadMesh.js'; export { default as PMREMGenerator } from './renderers/common/extras/PMREMGenerator.js'; export { default as PostProcessing } from './renderers/common/PostProcessing.js'; -import * as PostProcessingUtils from './renderers/common/PostProcessingUtils.js'; -export { PostProcessingUtils }; +import * as RendererUtils from './renderers/common/RendererUtils.js'; +export { RendererUtils }; export { default as StorageTexture } from './renderers/common/StorageTexture.js'; export { default as StorageBufferAttribute } from './renderers/common/StorageBufferAttribute.js'; export { default as StorageInstancedBufferAttribute } from './renderers/common/StorageInstancedBufferAttribute.js'; diff --git a/src/constants.js b/src/constants.js index 2097edde6ab3f1..89116a5eb6cb91 100644 --- a/src/constants.js +++ b/src/constants.js @@ -1,4 +1,4 @@ -export const REVISION = '172dev'; +export const REVISION = '173dev'; export const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }; export const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }; diff --git a/src/core/RenderTarget3D.js b/src/core/RenderTarget3D.js new file mode 100644 index 00000000000000..9cd41bb2e2d318 --- /dev/null +++ b/src/core/RenderTarget3D.js @@ -0,0 +1,22 @@ +import { RenderTarget } from './RenderTarget.js'; +import { Data3DTexture } from '../textures/Data3DTexture.js'; + +class RenderTarget3D extends RenderTarget { + + constructor( width = 1, height = 1, depth = 1, options = {} ) { + + super( width, height, options ); + + this.isRenderTarget3D = true; + + this.depth = depth; + + this.texture = new Data3DTexture( null, width, height, depth ); + + this.texture.isRenderTargetTexture = true; + + } + +} + +export { RenderTarget3D }; diff --git a/src/core/RenderTargetArray.js b/src/core/RenderTargetArray.js new file mode 100644 index 00000000000000..7c4b2a25300953 --- /dev/null +++ b/src/core/RenderTargetArray.js @@ -0,0 +1,22 @@ +import { RenderTarget } from './RenderTarget.js'; +import { DataArrayTexture } from '../textures/DataArrayTexture.js'; + +class RenderTargetArray extends RenderTarget { + + constructor( width = 1, height = 1, depth = 1, options = {} ) { + + super( width, height, options ); + + this.isRenderTargetArray = true; + + this.depth = depth; + + this.texture = new DataArrayTexture( null, width, height, depth ); + + this.texture.isRenderTargetTexture = true; + + } + +} + +export { RenderTargetArray }; diff --git a/src/loaders/nodes/NodeObjectLoader.js b/src/loaders/nodes/NodeObjectLoader.js index e42bfbaf28b444..3ca748250c5f8b 100644 --- a/src/loaders/nodes/NodeObjectLoader.js +++ b/src/loaders/nodes/NodeObjectLoader.js @@ -35,7 +35,7 @@ class NodeObjectLoader extends ObjectLoader { this.nodeMaterials = {}; /** - * A reference for holdng the `nodes` JSON property. + * A reference to hold the `nodes` JSON property. * * @private * @type {Object?} diff --git a/src/materials/nodes/InstancedPointsNodeMaterial.js b/src/materials/nodes/InstancedPointsNodeMaterial.js index 0d7278225f5bdd..4c28af986f1f6c 100644 --- a/src/materials/nodes/InstancedPointsNodeMaterial.js +++ b/src/materials/nodes/InstancedPointsNodeMaterial.js @@ -13,6 +13,15 @@ import { PointsMaterial } from '../PointsMaterial.js'; const _defaultValues = /*@__PURE__*/ new PointsMaterial(); +/** + * Unlike WebGL, WebGPU can render point primitives only with a size + * of one pixel. This type node material can be used to mimic the WebGL + * points rendering by rendering small planes via instancing. + * + * This material should be used with {@link InstancedPointsGeometry}. + * + * @augments NodeMaterial + */ class InstancedPointsNodeMaterial extends NodeMaterial { static get type() { @@ -21,39 +30,75 @@ class InstancedPointsNodeMaterial extends NodeMaterial { } - constructor( params = {} ) { + /** + * Constructs a new instanced points node material. + * + * @param {Object?} parameters - The configuration parameter. + */ + constructor( parameters = {} ) { super(); - this.lights = false; - - this.useAlphaToCoverage = true; - - this.useColor = params.vertexColors; - + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ + this.isInstancedPointsNodeMaterial = true; + + /** + * Whether vertex colors should be used or not. If set to `true`, + * each point instance can receive a custom color value. + * + * @type {Boolean} + * @default false + */ + this.useColor = parameters.vertexColors; + + /** + * The points width in pixels. + * + * @type {Number} + * @default 1 + */ this.pointWidth = 1; + /** + * This node can be used to define the colors for each instance. + * + * @type {Node?} + * @default null + */ this.pointColorNode = null; + /** + * This node can be used to define the width for each point instance. + * + * @type {Node?} + * @default null + */ this.pointWidthNode = null; + this._useAlphaToCoverage = true; + this.setDefaultValues( _defaultValues ); - this.setValues( params ); + this.setValues( parameters ); } + /** + * Setups the vertex and fragment stage of this node material. + * + * @param {NodeBuilder} builder - The current node builder. + */ setup( builder ) { - this.setupShaders( builder ); - - super.setup( builder ); + const { renderer } = builder; - } - - setupShaders( { renderer } ) { - - const useAlphaToCoverage = this.alphaToCoverage; + const useAlphaToCoverage = this._useAlphaToCoverage; const useColor = this.useColor; this.vertexNode = Fn( () => { @@ -132,19 +177,27 @@ class InstancedPointsNodeMaterial extends NodeMaterial { } )(); + super.setup( builder ); + } + /** + * Whether alpha to coverage should be used or not. + * + * @type {Boolean} + * @default true + */ get alphaToCoverage() { - return this.useAlphaToCoverage; + return this._useAlphaToCoverage; } set alphaToCoverage( value ) { - if ( this.useAlphaToCoverage !== value ) { + if ( this._useAlphaToCoverage !== value ) { - this.useAlphaToCoverage = value; + this._useAlphaToCoverage = value; this.needsUpdate = true; } diff --git a/src/materials/nodes/Line2NodeMaterial.js b/src/materials/nodes/Line2NodeMaterial.js index 5613913748d90b..7a2835020b2327 100644 --- a/src/materials/nodes/Line2NodeMaterial.js +++ b/src/materials/nodes/Line2NodeMaterial.js @@ -16,6 +16,12 @@ import { NoBlending } from '../../constants.js'; const _defaultValues = /*@__PURE__*/ new LineDashedMaterial(); +/** + * This node material can be used to render lines with a size larger than one + * by representing them as instanced meshes. + * + * @augments NodeMaterial + */ class Line2NodeMaterial extends NodeMaterial { static get type() { @@ -24,49 +30,120 @@ class Line2NodeMaterial extends NodeMaterial { } - constructor( params = {} ) { + /** + * Constructs a new node material for wide line rendering. + * + * @param {Object?} parameters - The configuration parameter. + */ + constructor( parameters = {} ) { super(); - this.lights = false; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ + this.isLine2NodeMaterial = true; this.setDefaultValues( _defaultValues ); - this.useAlphaToCoverage = true; - this.useColor = params.vertexColors; - this.useDash = params.dashed; - this.useWorldUnits = false; - + /** + * Whether vertex colors should be used or not. + * + * @type {Boolean} + * @default false + */ + this.useColor = parameters.vertexColors; + + /** + * The dash offset. + * + * @type {Number} + * @default 0 + */ this.dashOffset = 0; + + /** + * The line width. + * + * @type {Number} + * @default 0 + */ this.lineWidth = 1; + /** + * Defines the lines color. + * + * @type {Node?} + * @default null + */ this.lineColorNode = null; + /** + * Defines the offset. + * + * @type {Node?} + * @default null + */ this.offsetNode = null; + + /** + * Defines the dash scale. + * + * @type {Node?} + * @default null + */ this.dashScaleNode = null; + + /** + * Defines the dash size. + * + * @type {Node?} + * @default null + */ this.dashSizeNode = null; + + /** + * Defines the gap size. + * + * @type {Node?} + * @default null + */ this.gapSizeNode = null; + /** + * Blending is set to `NoBlending` since transparency + * is not supported, yet. + * + * @type {Number} + * @default 0 + */ this.blending = NoBlending; - this.setValues( params ); + this._useDash = parameters.dashed; + this._useAlphaToCoverage = true; + this._useWorldUnits = false; + + this.setValues( parameters ); } + /** + * Setups the vertex and fragment stage of this node material. + * + * @param {NodeBuilder} builder - The current node builder. + */ setup( builder ) { - this.setupShaders( builder ); - - super.setup( builder ); - - } - - setupShaders( { renderer } ) { + const { renderer } = builder; - const useAlphaToCoverage = this.alphaToCoverage; + const useAlphaToCoverage = this._useAlphaToCoverage; const useColor = this.useColor; - const useDash = this.dashed; - const useWorldUnits = this.worldUnits; + const useDash = this._useDash; + const useWorldUnits = this._useWorldUnits; const trimSegment = Fn( ( { start, end } ) => { @@ -394,56 +471,74 @@ class Line2NodeMaterial extends NodeMaterial { } - } + super.setup( builder ); + } + /** + * Whether the lines should sized in world units or not. + * When set to `false` the unit is pixel. + * + * @type {Boolean} + * @default false + */ get worldUnits() { - return this.useWorldUnits; + return this._useWorldUnits; } set worldUnits( value ) { - if ( this.useWorldUnits !== value ) { + if ( this._useWorldUnits !== value ) { - this.useWorldUnits = value; + this._useWorldUnits = value; this.needsUpdate = true; } } - + /** + * Whether the lines should be dashed or not. + * + * @type {Boolean} + * @default false + */ get dashed() { - return this.useDash; + return this._useDash; } set dashed( value ) { - if ( this.useDash !== value ) { + if ( this._useDash !== value ) { - this.useDash = value; + this._useDash = value; this.needsUpdate = true; } } - + /** + * Whether alpha to coverage should be used or not. + * + * @type {Boolean} + * @default true + */ get alphaToCoverage() { - return this.useAlphaToCoverage; + return this._useAlphaToCoverage; } set alphaToCoverage( value ) { - if ( this.useAlphaToCoverage !== value ) { + if ( this._useAlphaToCoverage !== value ) { - this.useAlphaToCoverage = value; + this._useAlphaToCoverage = value; this.needsUpdate = true; } diff --git a/src/materials/nodes/LineBasicNodeMaterial.js b/src/materials/nodes/LineBasicNodeMaterial.js index c167ab0ecb988f..1e0fbdb4dfa118 100644 --- a/src/materials/nodes/LineBasicNodeMaterial.js +++ b/src/materials/nodes/LineBasicNodeMaterial.js @@ -4,6 +4,11 @@ import { LineBasicMaterial } from '../LineBasicMaterial.js'; const _defaultValues = /*@__PURE__*/ new LineBasicMaterial(); +/** + * Node material version of `LineBasicMaterial`. + * + * @augments NodeMaterial + */ class LineBasicNodeMaterial extends NodeMaterial { static get type() { @@ -12,14 +17,24 @@ class LineBasicNodeMaterial extends NodeMaterial { } + /** + * Constructs a new line basic node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isLineBasicNodeMaterial = true; - this.lights = false; - this.setDefaultValues( _defaultValues ); this.setValues( parameters ); diff --git a/src/materials/nodes/LineDashedNodeMaterial.js b/src/materials/nodes/LineDashedNodeMaterial.js index e1c0421d83aaf5..d60f1be7c2f8d3 100644 --- a/src/materials/nodes/LineDashedNodeMaterial.js +++ b/src/materials/nodes/LineDashedNodeMaterial.js @@ -8,6 +8,11 @@ import { LineDashedMaterial } from '../LineDashedMaterial.js'; const _defaultValues = /*@__PURE__*/ new LineDashedMaterial(); +/** + * Node material version of `LineDashedMaterial`. + * + * @augments NodeMaterial + */ class LineDashedNodeMaterial extends NodeMaterial { static get type() { @@ -16,33 +21,101 @@ class LineDashedNodeMaterial extends NodeMaterial { } + /** + * Constructs a new line dashed node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isLineDashedNodeMaterial = true; - this.lights = false; - this.setDefaultValues( _defaultValues ); + /** + * The dash offset. + * + * @type {Number} + * @default 0 + */ this.dashOffset = 0; + /** + * The offset of dash materials is by default inferred from the `dashOffset` + * property. This node property allows to overwrite the default + * and define the offset with a node instead. + * + * If you don't want to overwrite the offset but modify the existing + * value instead, use {@link module:MaterialNode.materialLineDashOffset}. + * + * @type {Node?} + * @default null + */ this.offsetNode = null; + + /** + * The scale of dash materials is by default inferred from the `scale` + * property. This node property allows to overwrite the default + * and define the scale with a node instead. + * + * If you don't want to overwrite the scale but modify the existing + * value instead, use {@link module:MaterialNode.materialLineScale}. + * + * @type {Node?} + * @default null + */ this.dashScaleNode = null; + + /** + * The dash size of dash materials is by default inferred from the `dashSize` + * property. This node property allows to overwrite the default + * and define the dash size with a node instead. + * + * If you don't want to overwrite the dash size but modify the existing + * value instead, use {@link module:MaterialNode.materialLineDashSize}. + * + * @type {Node?} + * @default null + */ this.dashSizeNode = null; + + /** + * The gap size of dash materials is by default inferred from the `gapSize` + * property. This node property allows to overwrite the default + * and define the gap size with a node instead. + * + * If you don't want to overwrite the gap size but modify the existing + * value instead, use {@link module:MaterialNode.materialLineGapSize}. + * + * @type {Node?} + * @default null + */ this.gapSizeNode = null; this.setValues( parameters ); } - setupVariants() { + /** + * Setups the dash specific node variables. + * + * @param {NodeBuilder} builder - The current node builder. + */ + setupVariants( /* builder */ ) { - const offsetNode = this.offsetNode ? float( this.offsetNodeNode ) : materialLineDashOffset; + const offsetNode = this.offsetNode ? float( this.offsetNode ) : materialLineDashOffset; const dashScaleNode = this.dashScaleNode ? float( this.dashScaleNode ) : materialLineScale; const dashSizeNode = this.dashSizeNode ? float( this.dashSizeNode ) : materialLineDashSize; - const gapSizeNode = this.dashSizeNode ? float( this.dashGapNode ) : materialLineGapSize; + const gapSizeNode = this.gapSizeNode ? float( this.gapSizeNode ) : materialLineGapSize; dashSize.assign( dashSizeNode ); gapSize.assign( gapSizeNode ); diff --git a/src/materials/nodes/MeshBasicNodeMaterial.js b/src/materials/nodes/MeshBasicNodeMaterial.js index 5be8a986df11e2..6bca9f84d18570 100644 --- a/src/materials/nodes/MeshBasicNodeMaterial.js +++ b/src/materials/nodes/MeshBasicNodeMaterial.js @@ -10,6 +10,11 @@ import { MeshBasicMaterial } from '../MeshBasicMaterial.js'; const _defaultValues = /*@__PURE__*/ new MeshBasicMaterial(); +/** + * Node material version of `MeshBasicMaterial`. + * + * @augments NodeMaterial + */ class MeshBasicNodeMaterial extends NodeMaterial { static get type() { @@ -18,12 +23,32 @@ class MeshBasicNodeMaterial extends NodeMaterial { } + /** + * Constructs a new mesh basic node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshBasicNodeMaterial = true; + /** + * Although the basic material is by definition unlit, we set + * this property to `true` since we use a lighting model to compute + * the outgoing light of the fragment shader. + * + * @type {Boolean} + * @default true + */ this.lights = true; this.setDefaultValues( _defaultValues ); @@ -32,12 +57,25 @@ class MeshBasicNodeMaterial extends NodeMaterial { } + /** + * Basic materials are not affected by normal and bump maps so we + * return by default {@link module:Normal.normalView}. + * + * @return {Node} The normal node. + */ setupNormal() { return normalView; // see #28839 } + /** + * Overwritten since this type of material uses {@link BasicEnvironmentNode} + * to implement the default environment mapping. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {BasicEnvironmentNode?} The environment node. + */ setupEnvironment( builder ) { const envNode = super.setupEnvironment( builder ); @@ -46,6 +84,13 @@ class MeshBasicNodeMaterial extends NodeMaterial { } + /** + * This method must be overwritten since light maps are evaluated + * with a special scaling factor for basic materials. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {BasicLightMapNode?} The light map node. + */ setupLightMap( builder ) { let node = null; @@ -60,12 +105,23 @@ class MeshBasicNodeMaterial extends NodeMaterial { } + /** + * The material overwrites this method because `lights` is set to `true` but + * we still want to return the diffuse color as the outgoing light. + * + * @return {Node} The outgoing light node. + */ setupOutgoingLight() { return diffuseColor.rgb; } + /** + * Setups the lighting model. + * + * @return {BasicLightingModel} The lighting model. + */ setupLightingModel() { return new BasicLightingModel(); diff --git a/src/materials/nodes/MeshLambertNodeMaterial.js b/src/materials/nodes/MeshLambertNodeMaterial.js index 033ff96c92f9cf..da4e4c28cc1dbd 100644 --- a/src/materials/nodes/MeshLambertNodeMaterial.js +++ b/src/materials/nodes/MeshLambertNodeMaterial.js @@ -6,6 +6,11 @@ import { MeshLambertMaterial } from '../MeshLambertMaterial.js'; const _defaultValues = /*@__PURE__*/ new MeshLambertMaterial(); +/** + * Node material version of `MeshLambertMaterial`. + * + * @augments NodeMaterial + */ class MeshLambertNodeMaterial extends NodeMaterial { static get type() { @@ -14,12 +19,30 @@ class MeshLambertNodeMaterial extends NodeMaterial { } + /** + * Constructs a new mesh lambert node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshLambertNodeMaterial = true; + /** + * Set to `true` because lambert materials react on lights. + * + * @type {Boolean} + * @default true + */ this.lights = true; this.setDefaultValues( _defaultValues ); @@ -28,6 +51,13 @@ class MeshLambertNodeMaterial extends NodeMaterial { } + /** + * Overwritten since this type of material uses {@link BasicEnvironmentNode} + * to implement the default environment mapping. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {BasicEnvironmentNode?} The environment node. + */ setupEnvironment( builder ) { const envNode = super.setupEnvironment( builder ); @@ -36,6 +66,11 @@ class MeshLambertNodeMaterial extends NodeMaterial { } + /** + * Setups the lighting model. + * + * @return {PhongLightingModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { return new PhongLightingModel( false ); // ( specular ) -> force lambert diff --git a/src/materials/nodes/MeshMatcapNodeMaterial.js b/src/materials/nodes/MeshMatcapNodeMaterial.js index 19f274cc78366a..df3a1ac95b3f31 100644 --- a/src/materials/nodes/MeshMatcapNodeMaterial.js +++ b/src/materials/nodes/MeshMatcapNodeMaterial.js @@ -9,6 +9,11 @@ import { MeshMatcapMaterial } from '../MeshMatcapMaterial.js'; const _defaultValues = /*@__PURE__*/ new MeshMatcapMaterial(); +/** + * Node material version of `MeshMatcapMaterial`. + * + * @augments NodeMaterial + */ class MeshMatcapNodeMaterial extends NodeMaterial { static get type() { @@ -17,12 +22,22 @@ class MeshMatcapNodeMaterial extends NodeMaterial { } + /** + * Constructs a new mesh normal node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); - this.lights = false; - + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshMatcapNodeMaterial = true; this.setDefaultValues( _defaultValues ); @@ -31,6 +46,11 @@ class MeshMatcapNodeMaterial extends NodeMaterial { } + /** + * Setups the matcap specific node variables. + * + * @param {NodeBuilder} builder - The current node builder. + */ setupVariants( builder ) { const uv = matcapUV; diff --git a/src/materials/nodes/MeshNormalNodeMaterial.js b/src/materials/nodes/MeshNormalNodeMaterial.js index 3917cc3594cb62..e88fce34737e0c 100644 --- a/src/materials/nodes/MeshNormalNodeMaterial.js +++ b/src/materials/nodes/MeshNormalNodeMaterial.js @@ -9,6 +9,11 @@ import { MeshNormalMaterial } from '../MeshNormalMaterial.js'; const _defaultValues = /*@__PURE__*/ new MeshNormalMaterial(); +/** + * Node material version of `MeshNormalMaterial`. + * + * @augments NodeMaterial + */ class MeshNormalNodeMaterial extends NodeMaterial { static get type() { @@ -17,12 +22,22 @@ class MeshNormalNodeMaterial extends NodeMaterial { } + /** + * Constructs a new mesh normal node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); - this.lights = false; - + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshNormalNodeMaterial = true; this.setDefaultValues( _defaultValues ); @@ -31,6 +46,10 @@ class MeshNormalNodeMaterial extends NodeMaterial { } + /** + * Overwrites the default implementation by computing the diffuse color + * based on the normal data. + */ setupDiffuseColor() { const opacityNode = this.opacityNode ? float( this.opacityNode ) : materialOpacity; diff --git a/src/materials/nodes/MeshPhongNodeMaterial.js b/src/materials/nodes/MeshPhongNodeMaterial.js index c152283c913690..3d47a140a9a44d 100644 --- a/src/materials/nodes/MeshPhongNodeMaterial.js +++ b/src/materials/nodes/MeshPhongNodeMaterial.js @@ -9,6 +9,11 @@ import { MeshPhongMaterial } from '../MeshPhongMaterial.js'; const _defaultValues = /*@__PURE__*/ new MeshPhongMaterial(); +/** + * Node material version of `MeshPhongMaterial`. + * + * @augments NodeMaterial + */ class MeshPhongNodeMaterial extends NodeMaterial { static get type() { @@ -17,15 +22,56 @@ class MeshPhongNodeMaterial extends NodeMaterial { } + /** + * Constructs a new mesh lambert node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshPhongNodeMaterial = true; + /** + * Set to `true` because phong materials react on lights. + * + * @type {Boolean} + * @default true + */ this.lights = true; + /** + * The shininess of phong materials is by default inferred from the `shininess` + * property. This node property allows to overwrite the default + * and define the shininess with a node instead. + * + * If you don't want to overwrite the shininess but modify the existing + * value instead, use {@link module:MaterialNode.materialShininess}. + * + * @type {Node?} + * @default null + */ this.shininessNode = null; + + /** + * The specular color of phong materials is by default inferred from the + * `specular` property. This node property allows to overwrite the default + * and define the specular color with a node instead. + * + * If you don't want to overwrite the specular color but modify the existing + * value instead, use {@link module:MaterialNode.materialSpecular}. + * + * @type {Node?} + * @default null + */ this.specularNode = null; this.setDefaultValues( _defaultValues ); @@ -34,6 +80,13 @@ class MeshPhongNodeMaterial extends NodeMaterial { } + /** + * Overwritten since this type of material uses {@link BasicEnvironmentNode} + * to implement the default environment mapping. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {BasicEnvironmentNode?} The environment node. + */ setupEnvironment( builder ) { const envNode = super.setupEnvironment( builder ); @@ -42,13 +95,23 @@ class MeshPhongNodeMaterial extends NodeMaterial { } + /** + * Setups the lighting model. + * + * @return {PhongLightingModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { return new PhongLightingModel(); } - setupVariants() { + /** + * Setups the phong specific node variables. + * + * @param {NodeBuilder} builder - The current node builder. + */ + setupVariants( /*builder*/ ) { // SHININESS diff --git a/src/materials/nodes/MeshPhysicalNodeMaterial.js b/src/materials/nodes/MeshPhysicalNodeMaterial.js index b06062ae5b0afd..0836931e87a23e 100644 --- a/src/materials/nodes/MeshPhysicalNodeMaterial.js +++ b/src/materials/nodes/MeshPhysicalNodeMaterial.js @@ -11,6 +11,11 @@ import { MeshPhysicalMaterial } from '../MeshPhysicalMaterial.js'; const _defaultValues = /*@__PURE__*/ new MeshPhysicalMaterial(); +/** + * Node material version of `MeshPhysicalMaterial`. + * + * @augments MeshStandardNodeMaterial + */ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial { static get type() { @@ -19,33 +24,243 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial { } + /** + * Constructs a new mesh physical node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshPhysicalNodeMaterial = true; + /** + * The clearcoat of physical materials is by default inferred from the `clearcoat` + * and `clearcoatMap` properties. This node property allows to overwrite the default + * and define the clearcoat with a node instead. + * + * If you don't want to overwrite the clearcoat but modify the existing + * value instead, use {@link module:MaterialNode.materialClearcoat}. + * + * @type {Node?} + * @default null + */ this.clearcoatNode = null; + + /** + * The clearcoat roughness of physical materials is by default inferred from the `clearcoatRoughness` + * and `clearcoatRoughnessMap` properties. This node property allows to overwrite the default + * and define the clearcoat roughness with a node instead. + * + * If you don't want to overwrite the clearcoat roughness but modify the existing + * value instead, use {@link module:MaterialNode.materialClearcoatRoughness}. + * + * @type {Node?} + * @default null + */ this.clearcoatRoughnessNode = null; + + /** + * The clearcoat normal of physical materials is by default inferred from the `clearcoatNormalMap` + * property. This node property allows to overwrite the default + * and define the clearcoat normal with a node instead. + * + * If you don't want to overwrite the clearcoat normal but modify the existing + * value instead, use {@link module:MaterialNode.materialClearcoatNormal}. + * + * @type {Node?} + * @default null + */ this.clearcoatNormalNode = null; + /** + * The sheen of physical materials is by default inferred from the `sheen`, `sheenColor` + * and `sheenColorMap` properties. This node property allows to overwrite the default + * and define the sheen with a node instead. + * + * If you don't want to overwrite the sheen but modify the existing + * value instead, use {@link module:MaterialNode.materialSheen}. + * + * @type {Node?} + * @default null + */ this.sheenNode = null; + + /** + * The sheen roughness of physical materials is by default inferred from the `sheenRoughness` and + * `sheenRoughnessMap` properties. This node property allows to overwrite the default + * and define the sheen roughness with a node instead. + * + * If you don't want to overwrite the sheen roughness but modify the existing + * value instead, use {@link module:MaterialNode.materialSheenRoughness}. + * + * @type {Node?} + * @default null + */ this.sheenRoughnessNode = null; + /** + * The iridescence of physical materials is by default inferred from the `iridescence` + * property. This node property allows to overwrite the default + * and define the iridescence with a node instead. + * + * If you don't want to overwrite the iridescence but modify the existing + * value instead, use {@link module:MaterialNode.materialIridescence}. + * + * @type {Node?} + * @default null + */ this.iridescenceNode = null; + + /** + * The iridescence IOR of physical materials is by default inferred from the `iridescenceIOR` + * property. This node property allows to overwrite the default + * and define the iridescence IOR with a node instead. + * + * If you don't want to overwrite the iridescence IOR but modify the existing + * value instead, use {@link module:MaterialNode.materialIridescenceIOR}. + * + * @type {Node?} + * @default null + */ this.iridescenceIORNode = null; + + /** + * The iridescence thickness of physical materials is by default inferred from the `iridescenceThicknessRange` + * and `iridescenceThicknessMap` properties. This node property allows to overwrite the default + * and define the iridescence thickness with a node instead. + * + * If you don't want to overwrite the iridescence thickness but modify the existing + * value instead, use {@link module:MaterialNode.materialIridescenceThickness}. + * + * @type {Node?} + * @default null + */ this.iridescenceThicknessNode = null; + /** + * The specular intensity of physical materials is by default inferred from the `specularIntensity` + * and `specularIntensityMap` properties. This node property allows to overwrite the default + * and define the specular intensity with a node instead. + * + * If you don't want to overwrite the specular intensity but modify the existing + * value instead, use {@link module:MaterialNode.materialSpecularIntensity}. + * + * @type {Node?} + * @default null + */ this.specularIntensityNode = null; + + /** + * The specular color of physical materials is by default inferred from the `specularColor` + * and `specularColorMap` properties. This node property allows to overwrite the default + * and define the specular color with a node instead. + * + * If you don't want to overwrite the specular color but modify the existing + * value instead, use {@link module:MaterialNode.materialSpecularColor}. + * + * @type {Node?} + * @default null + */ this.specularColorNode = null; + /** + * The ior of physical materials is by default inferred from the `ior` + * property. This node property allows to overwrite the default + * and define the ior with a node instead. + * + * If you don't want to overwrite the ior but modify the existing + * value instead, use {@link module:MaterialNode.materialIOR}. + * + * @type {Node?} + * @default null + */ this.iorNode = null; + + /** + * The transmission of physical materials is by default inferred from the `transmission` and + * `transmissionMap` properties. This node property allows to overwrite the default + * and define the transmission with a node instead. + * + * If you don't want to overwrite the transmission but modify the existing + * value instead, use {@link module:MaterialNode.materialTransmission}. + * + * @type {Node?} + * @default null + */ this.transmissionNode = null; + + /** + * The thickness of physical materials is by default inferred from the `thickness` and + * `thicknessMap` properties. This node property allows to overwrite the default + * and define the thickness with a node instead. + * + * If you don't want to overwrite the thickness but modify the existing + * value instead, use {@link module:MaterialNode.materialThickness}. + * + * @type {Node?} + * @default null + */ this.thicknessNode = null; + + /** + * The attenuation distance of physical materials is by default inferred from the + * `attenuationDistance` property. This node property allows to overwrite the default + * and define the attenuation distance with a node instead. + * + * If you don't want to overwrite the attenuation distance but modify the existing + * value instead, use {@link module:MaterialNode.materialAttenuationDistance}. + * + * @type {Node?} + * @default null + */ this.attenuationDistanceNode = null; + + /** + * The attenuation color of physical materials is by default inferred from the + * `attenuationColor` property. This node property allows to overwrite the default + * and define the attenuation color with a node instead. + * + * If you don't want to overwrite the attenuation color but modify the existing + * value instead, use {@link module:MaterialNode.materialAttenuationColor}. + * + * @type {Node?} + * @default null + */ this.attenuationColorNode = null; + + /** + * The dispersion of physical materials is by default inferred from the + * `dispersion` property. This node property allows to overwrite the default + * and define the dispersion with a node instead. + * + * If you don't want to overwrite the dispersion but modify the existing + * value instead, use {@link module:MaterialNode.materialDispersion}. + * + * @type {Node?} + * @default null + */ this.dispersionNode = null; + /** + * The anisotropy of physical materials is by default inferred from the + * `anisotropy` property. This node property allows to overwrite the default + * and define the anisotropy with a node instead. + * + * If you don't want to overwrite the anisotropy but modify the existing + * value instead, use {@link module:MaterialNode.materialAnisotropy}. + * + * @type {Node?} + * @default null + */ this.anisotropyNode = null; this.setDefaultValues( _defaultValues ); @@ -54,42 +269,81 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial { } + /** + * Whether the lighting model should use clearcoat or not. + * + * @type {Boolean} + * @default true + */ get useClearcoat() { return this.clearcoat > 0 || this.clearcoatNode !== null; } + /** + * Whether the lighting model should use iridescence or not. + * + * @type {Boolean} + * @default true + */ get useIridescence() { return this.iridescence > 0 || this.iridescenceNode !== null; } + /** + * Whether the lighting model should use sheen or not. + * + * @type {Boolean} + * @default true + */ get useSheen() { return this.sheen > 0 || this.sheenNode !== null; } + /** + * Whether the lighting model should use anisotropy or not. + * + * @type {Boolean} + * @default true + */ get useAnisotropy() { return this.anisotropy > 0 || this.anisotropyNode !== null; } + /** + * Whether the lighting model should use transmission or not. + * + * @type {Boolean} + * @default true + */ get useTransmission() { return this.transmission > 0 || this.transmissionNode !== null; } + /** + * Whether the lighting model should use dispersion or not. + * + * @type {Boolean} + * @default true + */ get useDispersion() { return this.dispersion > 0 || this.dispersionNode !== null; } + /** + * Setups the specular related node variables. + */ setupSpecular() { const iorNode = this.iorNode ? float( this.iorNode ) : materialIOR; @@ -100,12 +354,22 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial { } + /** + * Setups the lighting model. + * + * @return {PhysicalLightingModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { return new PhysicalLightingModel( this.useClearcoat, this.useSheen, this.useIridescence, this.useAnisotropy, this.useTransmission, this.useDispersion ); } + /** + * Setups the physical specific node variables. + * + * @param {NodeBuilder} builder - The current node builder. + */ setupVariants( builder ) { super.setupVariants( builder ); @@ -201,6 +465,11 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial { } + /** + * Setups the clearcoat normal node. + * + * @return {Node} The clearcoat normal. + */ setupClearcoatNormal() { return this.clearcoatNormalNode ? vec3( this.clearcoatNormalNode ) : materialClearcoatNormal; diff --git a/src/materials/nodes/MeshSSSNodeMaterial.js b/src/materials/nodes/MeshSSSNodeMaterial.js index 064d9e4b896fe3..3c5736f48a173d 100644 --- a/src/materials/nodes/MeshSSSNodeMaterial.js +++ b/src/materials/nodes/MeshSSSNodeMaterial.js @@ -4,16 +4,49 @@ import { transformedNormalView } from '../../nodes/accessors/Normal.js'; import { positionViewDirection } from '../../nodes/accessors/Position.js'; import { float, vec3 } from '../../nodes/tsl/TSLBase.js'; -class SSSLightingModel extends PhysicalLightingModel { - - constructor( useClearcoat, useSheen, useIridescence, useSSS ) { +/** @module MeshSSSNodeMaterial **/ - super( useClearcoat, useSheen, useIridescence ); +/** + * Represents the lighting model for {@link MeshSSSNodeMaterial}. + * + * @augments PhysicalLightingModel + */ +class SSSLightingModel extends PhysicalLightingModel { - this.useSSS = useSSS; + /** + * Constructs a new physical lighting model. + * + * @param {Boolean} [clearcoat=false] - Whether clearcoat is supported or not. + * @param {Boolean} [sheen=false] - Whether sheen is supported or not. + * @param {Boolean} [iridescence=false] - Whether iridescence is supported or not. + * @param {Boolean} [anisotropy=false] - Whether anisotropy is supported or not. + * @param {Boolean} [transmission=false] - Whether transmission is supported or not. + * @param {Boolean} [dispersion=false] - Whether dispersion is supported or not. + * @param {Boolean} [sss=false] - Whether SSS is supported or not. + */ + constructor( clearcoat = false, sheen = false, iridescence = false, anisotropy = false, transmission = false, dispersion = false, sss = false ) { + + super( clearcoat, sheen, iridescence, anisotropy, transmission, dispersion ); + + /** + * Whether the lighting model should use SSS or not. + * + * @type {Boolean} + * @default false + */ + this.useSSS = sss; } + /** + * Extends the default implementation with a SSS term. + * + * Reference: [Approximating Translucency for a Fast, Cheap and Convincing Subsurface Scattering Look]{@link https://colinbarrebrisebois.com/2011/03/07/gdc-2011-approximating-translucency-for-a-fast-cheap-and-convincing-subsurface-scattering-look/} + * + * @param {Object} input - The input data. + * @param {StackNode} stack - The current stack. + * @param {NodeBuilder} builder - The current node builder. + */ direct( { lightDirection, lightColor, reflectedLight }, stack, builder ) { if ( this.useSSS === true ) { @@ -36,6 +69,12 @@ class SSSLightingModel extends PhysicalLightingModel { } +/** + * This node material is an experimental extension of {@link MeshPhysicalNodeMaterial} + * that implements a Subsurface scattering (SSS) term. + * + * @augments MeshPhysicalNodeMaterial + */ class MeshSSSNodeMaterial extends MeshPhysicalNodeMaterial { static get type() { @@ -44,28 +83,80 @@ class MeshSSSNodeMaterial extends MeshPhysicalNodeMaterial { } + /** + * Constructs a new mesh SSS node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super( parameters ); + /** + * Represents the thickness color. + * + * @type {Node?} + * @default null + */ this.thicknessColorNode = null; + + /** + * Represents the distortion factor. + * + * @type {Node?} + */ this.thicknessDistortionNode = float( 0.1 ); + + /** + * Represents the thickness ambient factor. + * + * @type {Node?} + */ this.thicknessAmbientNode = float( 0.0 ); + + /** + * Represents the thickness attenuation. + * + * @type {Node?} + */ this.thicknessAttenuationNode = float( .1 ); + + /** + * Represents the thickness power. + * + * @type {Node?} + */ this.thicknessPowerNode = float( 2.0 ); + + /** + * Represents the thickness scale. + * + * @type {Node?} + */ this.thicknessScaleNode = float( 10.0 ); } + /** + * Whether the lighting model should use SSS or not. + * + * @type {Boolean} + * @default true + */ get useSSS() { return this.thicknessColorNode !== null; } + /** + * Setups the lighting model. + * + * @return {SSSLightingModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { - return new SSSLightingModel( this.useClearcoat, this.useSheen, this.useIridescence, this.useSSS ); + return new SSSLightingModel( this.useClearcoat, this.useSheen, this.useIridescence, this.useAnisotropy, this.useTransmission, this.useDispersion, this.useSSS ); } diff --git a/src/materials/nodes/MeshStandardNodeMaterial.js b/src/materials/nodes/MeshStandardNodeMaterial.js index e7b5bce191981a..ef84543c133354 100644 --- a/src/materials/nodes/MeshStandardNodeMaterial.js +++ b/src/materials/nodes/MeshStandardNodeMaterial.js @@ -11,6 +11,11 @@ import { MeshStandardMaterial } from '../MeshStandardMaterial.js'; const _defaultValues = /*@__PURE__*/ new MeshStandardMaterial(); +/** + * Node material version of `MeshStandardMaterial`. + * + * @augments NodeMaterial + */ class MeshStandardNodeMaterial extends NodeMaterial { static get type() { @@ -19,17 +24,69 @@ class MeshStandardNodeMaterial extends NodeMaterial { } + /** + * Constructs a new mesh standard node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshStandardNodeMaterial = true; + /** + * Set to `true` because standard materials react on lights. + * + * @type {Boolean} + * @default true + */ this.lights = true; + /** + * The emissive color of standard materials is by default inferred from the `emissive`, + * `emissiveIntensity` and `emissiveMap` properties. This node property allows to + * overwrite the default and define the emissive color with a node instead. + * + * If you don't want to overwrite the emissive color but modify the existing + * value instead, use {@link module:MaterialNode.materialEmissive}. + * + * @type {Node?} + * @default null + */ this.emissiveNode = null; + /** + * The metalness of standard materials is by default inferred from the `metalness`, + * and `metalnessMap` properties. This node property allows to + * overwrite the default and define the metalness with a node instead. + * + * If you don't want to overwrite the metalness but modify the existing + * value instead, use {@link module:MaterialNode.materialMetalness}. + * + * @type {Node?} + * @default null + */ this.metalnessNode = null; + + /** + * The roughness of standard materials is by default inferred from the `roughness`, + * and `roughnessMap` properties. This node property allows to + * overwrite the default and define the roughness with a node instead. + * + * If you don't want to overwrite the roughness but modify the existing + * value instead, use {@link module:MaterialNode.materialRoughness}. + * + * @type {Node?} + * @default null + */ this.roughnessNode = null; this.setDefaultValues( _defaultValues ); @@ -38,6 +95,14 @@ class MeshStandardNodeMaterial extends NodeMaterial { } + /** + * Overwritten since this type of material uses {@link EnvironmentNode} + * to implement the PBR (PMREM based) environment mapping. Besides, the + * method honors `Scene.environment`. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {EnvironmentNode?} The environment node. + */ setupEnvironment( builder ) { let envNode = super.setupEnvironment( builder ); @@ -52,12 +117,20 @@ class MeshStandardNodeMaterial extends NodeMaterial { } + /** + * Setups the lighting model. + * + * @return {PhysicalLightingModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { return new PhysicalLightingModel(); } + /** + * Setups the specular related node variables. + */ setupSpecular() { const specularColorNode = mix( vec3( 0.04 ), diffuseColor.rgb, metalness ); @@ -67,6 +140,11 @@ class MeshStandardNodeMaterial extends NodeMaterial { } + /** + * Setups the standard specific node variables. + * + * @param {NodeBuilder} builder - The current node builder. + */ setupVariants() { // METALNESS diff --git a/src/materials/nodes/MeshToonNodeMaterial.js b/src/materials/nodes/MeshToonNodeMaterial.js index 4137dcd5db5f1e..adaee0cfb0960b 100644 --- a/src/materials/nodes/MeshToonNodeMaterial.js +++ b/src/materials/nodes/MeshToonNodeMaterial.js @@ -5,6 +5,11 @@ import { MeshToonMaterial } from '../MeshToonMaterial.js'; const _defaultValues = /*@__PURE__*/ new MeshToonMaterial(); +/** + * Node material version of `MeshToonMaterial`. + * + * @augments NodeMaterial + */ class MeshToonNodeMaterial extends NodeMaterial { static get type() { @@ -13,12 +18,30 @@ class MeshToonNodeMaterial extends NodeMaterial { } + /** + * Constructs a new mesh toon node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMeshToonNodeMaterial = true; + /** + * Set to `true` because toon materials react on lights. + * + * @type {Boolean} + * @default true + */ this.lights = true; this.setDefaultValues( _defaultValues ); @@ -27,6 +50,11 @@ class MeshToonNodeMaterial extends NodeMaterial { } + /** + * Setups the lighting model. + * + * @return {ToonLightingModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { return new ToonLightingModel(); diff --git a/src/materials/nodes/NodeMaterial.js b/src/materials/nodes/NodeMaterial.js index e9654c6fc1756f..dbcaf9926cb152 100644 --- a/src/materials/nodes/NodeMaterial.js +++ b/src/materials/nodes/NodeMaterial.js @@ -4,7 +4,7 @@ import { NormalBlending } from '../../constants.js'; import { getNodeChildren, getCacheKey } from '../../nodes/core/NodeUtils.js'; import { attribute } from '../../nodes/core/AttributeNode.js'; import { output, diffuseColor, emissive, varyingProperty } from '../../nodes/core/PropertyNode.js'; -import { materialAlphaTest, materialColor, materialOpacity, materialEmissive, materialNormal, materialLightMap, materialAOMap } from '../../nodes/accessors/MaterialNode.js'; +import { materialAlphaTest, materialColor, materialOpacity, materialEmissive, materialNormal, materialLightMap, materialAO } from '../../nodes/accessors/MaterialNode.js'; import { modelViewProjection } from '../../nodes/accessors/ModelViewProjectionNode.js'; import { normalLocal } from '../../nodes/accessors/Normal.js'; import { instancedMesh } from '../../nodes/accessors/InstancedMeshNode.js'; @@ -249,13 +249,13 @@ class NodeMaterial extends Material { /** * This node property is intended for logic which modifies geometry data once or per animation step. * Apps usually place such logic randomly in initialization routines or in the animation loop. - * `geometryNode` is intended as a dedicated API so there is an intended spot where goemetry modiciations + * `geometryNode` is intended as a dedicated API so there is an intended spot where geometry modifications * can be implemented. * * The idea is to assign a `Fn` definition that holds the geometry modification logic. A typical example * would be a GPU based particle system that provides a node material for usage on app level. The particle * simulation would be implemented as compute shaders and managed inside a `Fn` function. This function is - * eventually assigned to `ParticleNodeMaterial.geometryNode`. + * eventually assigned to `geometryNode`. * * @type {Function} * @default null @@ -400,7 +400,7 @@ class NodeMaterial extends Material { } /** - * Setups the vertex and fragment stahge of this node material. + * Setups the vertex and fragment stage of this node material. * * @param {NodeBuilder} builder - The current node builder. */ @@ -439,7 +439,7 @@ class NodeMaterial extends Material { const clippingNode = this.setupClipping( builder ); - if ( this.depthWrite === true ) { + if ( this.depthWrite === true || this.depthTest === true ) { // only write depth if depth buffer is configured @@ -635,12 +635,13 @@ class NodeMaterial extends Material { } /** - * Setups the position in view space of. This method exists - * so derived node materials can modifiy the implementation e.g. sprite materials. + * Setups the position node in view space. This method exists + * so derived node materials can modify the implementation e.g. sprite materials. * + * @param {NodeBuilder} builder - The current node builder. * @return {Node} The position in view space. */ - setupPositionView() { + setupPositionView( /*builder*/ ) { return modelViewMatrix.mul( positionLocal ).xyz; @@ -649,9 +650,10 @@ class NodeMaterial extends Material { /** * Setups the position in clip space. * + * @param {NodeBuilder} builder - The current node builder. * @return {Node} The position in view space. */ - setupModelViewProjection() { + setupModelViewProjection( /*builder*/ ) { return cameraProjectionMatrix.mul( positionView ); @@ -910,7 +912,7 @@ class NodeMaterial extends Material { if ( this.aoNode !== null || builder.material.aoMap ) { - const aoNode = this.aoNode !== null ? this.aoNode : materialAOMap; + const aoNode = this.aoNode !== null ? this.aoNode : materialAO; materialLightsNode.push( new AONode( aoNode ) ); @@ -934,6 +936,7 @@ class NodeMaterial extends Material { * * @abstract * @param {NodeBuilder} builder - The current node builder. + * @return {LightingModel} The lighting model. */ setupLightingModel( /*builder*/ ) { @@ -1018,9 +1021,9 @@ class NodeMaterial extends Material { /** * Most classic material types have a node pendant e.g. for `MeshBasicMaterial` * there is `MeshBasicNodeMaterial`. This utility method is intended for - * define all material property of the classic type in the node type. + * defining all material properties of the classic type in the node type. * - * @param {Material} material - The material to copy properties with their values over to this node material. + * @param {Material} material - The material to copy properties with their values to this node material. */ setDefaultValues( material ) { diff --git a/src/materials/nodes/PointsNodeMaterial.js b/src/materials/nodes/PointsNodeMaterial.js index 028402d95f625f..193df0ded1cef6 100644 --- a/src/materials/nodes/PointsNodeMaterial.js +++ b/src/materials/nodes/PointsNodeMaterial.js @@ -4,6 +4,16 @@ import { PointsMaterial } from '../PointsMaterial.js'; const _defaultValues = /*@__PURE__*/ new PointsMaterial(); +/** + * Node material version of `PointsMaterial`. + * + * Since WebGPU can render point primitives only with a size of one pixel, + * this material type does not evaluate the `size` and `sizeAttenuation` + * property of `PointsMaterial`. Use {@link InstancedPointsNodeMaterial} + * instead if you need points with a size larger than one pixel. + * + * @augments NodeMaterial + */ class PointsNodeMaterial extends NodeMaterial { static get type() { @@ -12,31 +22,30 @@ class PointsNodeMaterial extends NodeMaterial { } + /** + * Constructs a new points node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isPointsNodeMaterial = true; - this.lights = false; - this.transparent = true; - - this.sizeNode = null; - this.setDefaultValues( _defaultValues ); this.setValues( parameters ); } - copy( source ) { - - this.sizeNode = source.sizeNode; - - return super.copy( source ); - - } - } export default PointsNodeMaterial; diff --git a/src/materials/nodes/ShadowNodeMaterial.js b/src/materials/nodes/ShadowNodeMaterial.js index 756c22599ee1c4..7470783cfd9dfa 100644 --- a/src/materials/nodes/ShadowNodeMaterial.js +++ b/src/materials/nodes/ShadowNodeMaterial.js @@ -5,6 +5,11 @@ import { ShadowMaterial } from '../ShadowMaterial.js'; const _defaultValues = /*@__PURE__*/ new ShadowMaterial(); +/** + * Node material version of `ShadowMaterial`. + * + * @augments NodeMaterial + */ class ShadowNodeMaterial extends NodeMaterial { static get type() { @@ -13,12 +18,31 @@ class ShadowNodeMaterial extends NodeMaterial { } + /** + * Constructs a new shadow node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isShadowNodeMaterial = true; + /** + * Set to `true` because so it's possible to implement + * the shadow mask effect. + * + * @type {Boolean} + * @default true + */ this.lights = true; this.setDefaultValues( _defaultValues ); @@ -27,6 +51,11 @@ class ShadowNodeMaterial extends NodeMaterial { } + /** + * Setups the lighting model. + * + * @return {ShadowMaskModel} The lighting model. + */ setupLightingModel( /*builder*/ ) { return new ShadowMaskModel(); diff --git a/src/materials/nodes/SpriteNodeMaterial.js b/src/materials/nodes/SpriteNodeMaterial.js index b0ce982208f6c4..f0880c47e5347f 100644 --- a/src/materials/nodes/SpriteNodeMaterial.js +++ b/src/materials/nodes/SpriteNodeMaterial.js @@ -11,6 +11,11 @@ import { reference } from '../../nodes/accessors/ReferenceBaseNode.js'; const _defaultValues = /*@__PURE__*/ new SpriteMaterial(); +/** + * Node material version of `SpriteMaterial`. + * + * @augments NodeMaterial + */ class SpriteNodeMaterial extends NodeMaterial { static get type() { @@ -19,17 +24,66 @@ class SpriteNodeMaterial extends NodeMaterial { } + /** + * Constructs a new sprite node material. + * + * @param {Object?} parameters - The configuration parameter. + */ constructor( parameters ) { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isSpriteNodeMaterial = true; - this.lights = false; this._useSizeAttenuation = true; + /** + * This property makes it possible to define the position of the sprite with a + * node. That can be useful when the material is used with instanced rendering + * and node data are defined with an instanced attribute node: + * ```js + * const positionAttribute = new InstancedBufferAttribute( new Float32Array( positions ), 3 ); + * material.positionNode = instancedBufferAttribute( positionAttribute ); + * ``` + * Another possibility is to compute the instanced data with a compute shader: + * ```js + * const positionBuffer = instancedArray( particleCount, 'vec3' ); + * particleMaterial.positionNode = positionBuffer.toAttribute(); + * ``` + * + * @type {Node?} + * @default null + */ this.positionNode = null; + + /** + * The rotation of sprite materials is by default inferred from the `rotation`, + * property. This node property allows to overwrite the default and define + * the rotation with a node instead. + * + * If you don't want to overwrite the rotation but modify the existing + * value instead, use {@link module:MaterialNode.materialRotation}. + * + * @type {Node?} + * @default null + */ this.rotationNode = null; + + /** + * This node property provides an additional way to scale sprites next to + * `Object3D.scale`. The scale transformation based in `Object3D.scale` + * is multiplied with the scale value of this node in the vertex shader. + * + * @type {Node?} + * @default null + */ this.scaleNode = null; this.setDefaultValues( _defaultValues ); @@ -38,14 +92,19 @@ class SpriteNodeMaterial extends NodeMaterial { } + /** + * Setups the position node in view space. This method implements + * the sprite specific vertex shader. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Node} The position in view space. + */ setupPositionView( builder ) { const { object, camera } = builder; const sizeAttenuation = this.sizeAttenuation; - // < VERTEX STAGE > - const { positionNode, rotationNode, scaleNode } = this; const mvPosition = modelViewMatrix.mul( vec3( positionNode || 0 ) ); @@ -58,7 +117,7 @@ class SpriteNodeMaterial extends NodeMaterial { } - if ( ! sizeAttenuation ) { + if ( sizeAttenuation === false ) { if ( camera.isPerspectiveCamera ) { @@ -77,7 +136,7 @@ class SpriteNodeMaterial extends NodeMaterial { if ( object.center && object.center.isVector2 === true ) { - const center = reference( 'center', 'vec2' ); + const center = reference( 'center', 'vec2', object ); alignedPosition = alignedPosition.sub( center.sub( 0.5 ) ); @@ -103,6 +162,12 @@ class SpriteNodeMaterial extends NodeMaterial { } + /** + * Whether to use size attenuation or not. + * + * @type {Boolean} + * @default true + */ get sizeAttenuation() { return this._useSizeAttenuation; diff --git a/src/materials/nodes/VolumeNodeMaterial.js b/src/materials/nodes/VolumeNodeMaterial.js index 39940174305e48..a6a0f50c96f4a5 100644 --- a/src/materials/nodes/VolumeNodeMaterial.js +++ b/src/materials/nodes/VolumeNodeMaterial.js @@ -8,7 +8,16 @@ import { Fn, varying, float, vec2, vec3, vec4 } from '../../nodes/tsl/TSLBase.js import { min, max } from '../../nodes/math/MathNode.js'; import { Loop, Break } from '../../nodes/utils/LoopNode.js'; import { texture3D } from '../../nodes/accessors/Texture3DNode.js'; +import { Color } from '../../math/Color.js'; +/** @module VolumeNodeMaterial **/ + +/** + * Node material intended for volume rendering. The volumetric data are + * defined with an instance of {@link Data3DTexture}. + * + * @augments NodeMaterial + */ class VolumeNodeMaterial extends NodeMaterial { static get type() { @@ -17,18 +26,85 @@ class VolumeNodeMaterial extends NodeMaterial { } - constructor( params = {} ) { + /** + * Constructs a new volume node material. + * + * @param {Object?} parameters - The configuration parameter. + */ + constructor( parameters ) { super(); - this.lights = false; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isVolumeNodeMaterial = true; + + /** + * The base color of the volume. + * + * @type {Color} + * @default 100 + */ + this.base = new Color( 0xffffff ); + + /** + * A 3D data texture holding the volumetric data. + * + * @type {Data3DTexture?} + * @default null + */ + this.map = null; + + /** + * This number of samples for each ray that hits the mesh's surface + * and travels through the volume. + * + * @type {Number} + * @default 100 + */ + this.steps = 100; + + /** + * Callback for {@link VolumeNodeMaterial#testNode}. + * + * @callback testNodeCallback + * @param {Data3DTexture} map - The 3D texture. + * @param {Node} mapValue - The sampled value inside the volume. + * @param {Node} probe - The probe which is the entry point of the ray on the mesh's surface. + * @param {Node} finalColor - The final color. + */ + + /** + * The volume rendering of this material works by shooting rays + * from the camera position through each fragment of the mesh's + * surface and sample the inner volume in a raymarching fashion + * multiple times. + * + * This node can be used to assign a callback function of type `Fn` + * that will be executed per sample. The callback receives the + * texture, the sampled texture value as well as position on the surface + * where the rays enters the volume. The last parameter is a color + * that allows the callback to determine the final color. + * + * @type {testNodeCallback?} + * @default null + */ this.testNode = null; - this.setValues( params ); + this.setValues( parameters ); } + /** + * Setups the vertex and fragment stage of this node material. + * + * @param {NodeBuilder} builder - The current node builder. + */ setup( builder ) { const map = texture3D( this.map, null, 0 ); diff --git a/src/materials/nodes/manager/NodeMaterialObserver.js b/src/materials/nodes/manager/NodeMaterialObserver.js index d7865a70fb6bf7..6a193f594093fd 100644 --- a/src/materials/nodes/manager/NodeMaterialObserver.js +++ b/src/materials/nodes/manager/NodeMaterialObserver.js @@ -51,18 +51,65 @@ const refreshUniforms = [ 'transmissionMap' ]; +/** + * This class is used by {@link WebGPURenderer} as management component. + * It's primary purpose is to determine whether render objects require a + * refresh right before they are going to be rendered or not. + */ class NodeMaterialObserver { + /** + * Constructs a new node material observer. + * + * @param {NodeBuilder} builder - The node builder. + */ constructor( builder ) { + /** + * A node material can be used by more than one render object so the + * monitor must maintain a list of render objects. + * + * @type {WeakMap} + */ this.renderObjects = new WeakMap(); + + /** + * Whether the material uses node objects or not. + * + * @type {Boolean} + */ this.hasNode = this.containsNode( builder ); + + /** + * Whether the node builder's 3D object is animated or not. + * + * @type {Boolean} + */ this.hasAnimation = builder.object.isSkinnedMesh === true; + + /** + * A list of all possible material uniforms + * + * @type {Array} + */ this.refreshUniforms = refreshUniforms; + + /** + * Holds the current render ID from the node frame. + * + * @type {Number} + * @default 0 + */ this.renderId = 0; } + /** + * Returns `true` if the given render object is verified for the first time of this observer. + * + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether the given render object is verified for the first time of this observer. + */ firstInitialization( renderObject ) { const hasInitialized = this.renderObjects.has( renderObject ); @@ -79,6 +126,12 @@ class NodeMaterialObserver { } + /** + * Returns monitoring data for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @return {Object} The monitoring data. + */ getRenderObjectData( renderObject ) { let data = this.renderObjects.get( renderObject ); @@ -132,6 +185,13 @@ class NodeMaterialObserver { } + /** + * Returns an attribute data structure holding the attributes versions for + * monitoring. + * + * @param {Object} attributes - The geometry attributes. + * @return {Object} An object for monitoring the versions of attributes. + */ getAttributesData( attributes ) { const attributesData = {}; @@ -150,6 +210,13 @@ class NodeMaterialObserver { } + /** + * Returns `true` if the node builder's material uses + * node properties. + * + * @param {NodeBuilder} builder - The current node builder. + * @return {Boolean} Whether the node builder's material uses node properties or not. + */ containsNode( builder ) { const material = builder.material; @@ -168,6 +235,13 @@ class NodeMaterialObserver { } + /** + * Returns a material data structure holding the material property values for + * monitoring. + * + * @param {Material} material - The material. + * @return {Object} An object for monitoring material properties. + */ getMaterialData( material ) { const data = {}; @@ -202,6 +276,12 @@ class NodeMaterialObserver { } + /** + * Returns `true` if the given render object has not changed its state. + * + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether the given render object has changed its state or not. + */ equals( renderObject ) { const { object, material, geometry } = renderObject; @@ -382,6 +462,13 @@ class NodeMaterialObserver { } + /** + * Checks if the given render object requires a refresh. + * + * @param {RenderObject} renderObject - The render object. + * @param {NodeFrame} nodeFrame - The current node frame. + * @return {Boolean} Whether the given render object requires a refresh or not. + */ needsRefresh( renderObject, nodeFrame ) { if ( this.hasNode || this.hasAnimation || this.firstInitialization( renderObject ) ) diff --git a/src/nodes/accessors/Arrays.js b/src/nodes/accessors/Arrays.js index de3320f06b32c1..219ebe8b7bf575 100644 --- a/src/nodes/accessors/Arrays.js +++ b/src/nodes/accessors/Arrays.js @@ -1,7 +1,7 @@ import StorageInstancedBufferAttribute from '../../renderers/common/StorageInstancedBufferAttribute.js'; import StorageBufferAttribute from '../../renderers/common/StorageBufferAttribute.js'; import { storage } from './StorageBufferNode.js'; -import { getLengthFromType } from '../core/NodeUtils.js'; +import { getLengthFromType, getTypedArrayFromType } from '../core/NodeUtils.js'; /** @module Arrays **/ @@ -16,8 +16,9 @@ import { getLengthFromType } from '../core/NodeUtils.js'; export const attributeArray = ( count, type = 'float' ) => { const itemSize = getLengthFromType( type ); + const typedArray = getTypedArrayFromType( type ); - const buffer = new StorageBufferAttribute( count, itemSize ); + const buffer = new StorageBufferAttribute( count, itemSize, typedArray ); const node = storage( buffer, type, count ); return node; @@ -35,8 +36,9 @@ export const attributeArray = ( count, type = 'float' ) => { export const instancedArray = ( count, type = 'float' ) => { const itemSize = getLengthFromType( type ); + const typedArray = getTypedArrayFromType( type ); - const buffer = new StorageInstancedBufferAttribute( count, itemSize ); + const buffer = new StorageInstancedBufferAttribute( count, itemSize, typedArray ); const node = storage( buffer, type, count ); return node; diff --git a/src/nodes/accessors/BufferAttributeNode.js b/src/nodes/accessors/BufferAttributeNode.js index d3a5c58933f432..ab8e241eefa916 100644 --- a/src/nodes/accessors/BufferAttributeNode.js +++ b/src/nodes/accessors/BufferAttributeNode.js @@ -24,7 +24,7 @@ import { StaticDrawUsage, DynamicDrawUsage } from '../../constants.js'; * material.colorNode = bufferAttribute( new THREE.Float32BufferAttribute( colors, 3 ) ); * ``` * This new approach is especially interesting when geometry data are generated via - * compute shaders. The below line converts a storage buffer into an attribute. + * compute shaders. The below line converts a storage buffer into an attribute node. * ```js * material.positionNode = positionBuffer.toAttribute(); * ``` diff --git a/src/nodes/accessors/MaterialNode.js b/src/nodes/accessors/MaterialNode.js index d7a4a19813993d..38db5c49139851 100644 --- a/src/nodes/accessors/MaterialNode.js +++ b/src/nodes/accessors/MaterialNode.js @@ -161,15 +161,15 @@ class MaterialNode extends Node { } else if ( scope === MaterialNode.SPECULAR_INTENSITY ) { - const specularIntensity = this.getFloat( scope ); + const specularIntensityNode = this.getFloat( scope ); - if ( material.specularMap ) { + if ( material.specularIntensityMap && material.specularIntensityMap.isTexture === true ) { - node = specularIntensity.mul( this.getTexture( scope ).a ); + node = specularIntensityNode.mul( this.getTexture( scope ).a ); } else { - node = specularIntensity; + node = specularIntensityNode; } @@ -384,7 +384,7 @@ class MaterialNode extends Node { node = this.getTexture( scope ).rgb.mul( this.getFloat( 'lightMapIntensity' ) ); - } else if ( scope === MaterialNode.AO_MAP ) { + } else if ( scope === MaterialNode.AO ) { node = this.getTexture( scope ).r.sub( 1.0 ).mul( this.getFloat( 'aoMapIntensity' ) ).add( 1.0 ); @@ -438,7 +438,7 @@ MaterialNode.LINE_DASH_OFFSET = 'dashOffset'; MaterialNode.POINT_WIDTH = 'pointWidth'; MaterialNode.DISPERSION = 'dispersion'; MaterialNode.LIGHT_MAP = 'light'; -MaterialNode.AO_MAP = 'ao'; +MaterialNode.AO = 'ao'; export default MaterialNode; @@ -499,7 +499,7 @@ export const materialSpecularIntensity = /*@__PURE__*/ nodeImmutable( MaterialNo * TSL object that represents the specular color of the current material. * The value is composed via `specularColor` * `specularMap.rgb`. * - * @type {Node} + * @type {Node} */ export const materialSpecularColor = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SPECULAR_COLOR ); @@ -520,7 +520,7 @@ export const materialReflectivity = /*@__PURE__*/ nodeImmutable( MaterialNode, M /** * TSL object that represents the roughness of the current material. - * The value is composed via `roughness` * `roughnessMap.g` + * The value is composed via `roughness` * `roughnessMap.g`. * * @type {Node} */ @@ -528,7 +528,7 @@ export const materialRoughness = /*@__PURE__*/ nodeImmutable( MaterialNode, Mate /** * TSL object that represents the metalness of the current material. - * The value is composed via `metalness` * `metalnessMap.b` + * The value is composed via `metalness` * `metalnessMap.b`. * * @type {Node} */ @@ -540,11 +540,11 @@ export const materialMetalness = /*@__PURE__*/ nodeImmutable( MaterialNode, Mate * * @type {Node} */ -export const materialNormal = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.NORMAL ).context( { getUV: null } ); +export const materialNormal = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.NORMAL ); /** * TSL object that represents the clearcoat of the current material. - * The value is composed via `clearcoat` * `clearcoat.r` + * The value is composed via `clearcoat` * `clearcoatMap.r` * * @type {Node} */ @@ -552,7 +552,7 @@ export const materialClearcoat = /*@__PURE__*/ nodeImmutable( MaterialNode, Mate /** * TSL object that represents the clearcoat roughness of the current material. - * The value is composed via `clearcoatRoughness` * `clearcoatRoughnessMap.r` + * The value is composed via `clearcoatRoughness` * `clearcoatRoughnessMap.r`. * * @type {Node} */ @@ -564,7 +564,7 @@ export const materialClearcoatRoughness = /*@__PURE__*/ nodeImmutable( MaterialN * * @type {Node} */ -export const materialClearcoatNormal = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.CLEARCOAT_NORMAL ).context( { getUV: null } ); +export const materialClearcoatNormal = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.CLEARCOAT_NORMAL ); /** * TSL object that represents the rotation of the current sprite material. @@ -583,7 +583,7 @@ export const materialSheen = /*@__PURE__*/ nodeImmutable( MaterialNode, Material /** * TSL object that represents the sheen roughness of the current material. - * The value is composed via `sheenRoughness` * `sheenRoughnessMap.a` . + * The value is composed via `sheenRoughness` * `sheenRoughnessMap.a`. * * @type {Node} */ @@ -717,7 +717,7 @@ export const materialLightMap = /*@__PURE__*/ nodeImmutable( MaterialNode, Mater * * @type {Node} */ -export const materialAOMap = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.AO_MAP ); +export const materialAO = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.AO ); /** * TSL object that represents the anisotropy vector of the current material. diff --git a/src/nodes/accessors/Normal.js b/src/nodes/accessors/Normal.js index 260f00e76176cc..e27723bf48e56b 100644 --- a/src/nodes/accessors/Normal.js +++ b/src/nodes/accessors/Normal.js @@ -77,7 +77,9 @@ export const normalWorld = /*@__PURE__*/ varying( normalView.transformDirection( */ export const transformedNormalView = /*@__PURE__*/ ( Fn( ( builder ) => { - return builder.context.setupNormal(); + // Use getUV context to avoid side effects from nodes overwriting getUV in the context (e.g. EnvironmentNode) + + return builder.context.setupNormal().context( { getUV: null } ); }, 'vec3' ).once() )().mul( faceDirection ).toVar( 'transformedNormalView' ); @@ -95,7 +97,9 @@ export const transformedNormalWorld = /*@__PURE__*/ transformedNormalView.transf */ export const transformedClearcoatNormalView = /*@__PURE__*/ ( Fn( ( builder ) => { - return builder.context.setupClearcoatNormal(); + // Use getUV context to avoid side effects from nodes overwriting getUV in the context (e.g. EnvironmentNode) + + return builder.context.setupClearcoatNormal().context( { getUV: null } ); }, 'vec3' ).once() )().mul( faceDirection ).toVar( 'transformedClearcoatNormalView' ); diff --git a/src/nodes/accessors/SkinningNode.js b/src/nodes/accessors/SkinningNode.js index c03c8b5b39f3ca..f3c62ac5f77796 100644 --- a/src/nodes/accessors/SkinningNode.js +++ b/src/nodes/accessors/SkinningNode.js @@ -9,6 +9,7 @@ import { positionLocal, positionPrevious } from './Position.js'; import { tangentLocal } from './Tangent.js'; import { uniform } from '../core/UniformNode.js'; import { buffer } from './BufferNode.js'; +import { getDataFromObject } from '../core/NodeUtils.js'; /** @module SkinningNode **/ @@ -218,7 +219,7 @@ class SkinningNode extends Node { const mrt = builder.renderer.getMRT(); - return mrt && mrt.has( 'velocity' ); + return ( mrt && mrt.has( 'velocity' ) ) || getDataFromObject( builder.object ).useVelocity === true; } diff --git a/src/nodes/accessors/StorageBufferNode.js b/src/nodes/accessors/StorageBufferNode.js index a64203e9e18528..e3d587fdac8d70 100644 --- a/src/nodes/accessors/StorageBufferNode.js +++ b/src/nodes/accessors/StorageBufferNode.js @@ -12,7 +12,7 @@ import { getTypeFromLength } from '../core/NodeUtils.js'; * storage buffer for data. A typical workflow is to create instances of * this node with the convenience functions `attributeArray()` or `instancedArray()`, * setup up a compute shader that writes into the buffers and then convert - * the storage buffers to attributes for rendering. + * the storage buffers to attribute nodes for rendering. * * ```js * const positionBuffer = instancedArray( particleCount, 'vec3' ); // the storage buffer node @@ -49,7 +49,7 @@ class StorageBufferNode extends BufferNode { /** * Constructs a new storage buffer node. * - * @param {StorageBufferAttribute|StorageInstancedBufferAttribute} value - The buffer data. + * @param {StorageBufferAttribute|StorageInstancedBufferAttribute|BufferAttribute} value - The buffer data. * @param {String?} [bufferType=null] - The buffer type (e.g. `'vec3'`). * @param {Number} [bufferCount=0] - The buffer count. */ @@ -337,7 +337,7 @@ export default StorageBufferNode; * TSL function for creating a storage buffer node. * * @function - * @param {StorageBufferAttribute|StorageInstancedBufferAttribute} value - The buffer data. + * @param {StorageBufferAttribute|StorageInstancedBufferAttribute|BufferAttribute} value - The buffer data. * @param {String?} [type=null] - The buffer type (e.g. `'vec3'`). * @param {Number} [count=0] - The buffer count. * @returns {StorageBufferNode} diff --git a/src/nodes/accessors/Texture3DNode.js b/src/nodes/accessors/Texture3DNode.js index e1f11a326e97d5..71b561ea10054c 100644 --- a/src/nodes/accessors/Texture3DNode.js +++ b/src/nodes/accessors/Texture3DNode.js @@ -1,5 +1,6 @@ import TextureNode from './TextureNode.js'; -import { nodeProxy, vec3, Fn, If } from '../tsl/TSLBase.js'; +import { nodeProxy, vec3, Fn, If, int } from '../tsl/TSLBase.js'; +import { textureSize } from './TextureSizeNode.js'; /** @module Texture3DNode **/ @@ -125,6 +126,22 @@ class Texture3DNode extends TextureNode { */ setupUV( builder, uvNode ) { + const texture = this.value; + + if ( builder.isFlipY() && ( texture.isRenderTargetTexture === true || texture.isFramebufferTexture === true ) ) { + + if ( this.sampler ) { + + uvNode = uvNode.flipY(); + + } else { + + uvNode = uvNode.setY( int( textureSize( this, this.levelNode ).y ).sub( uvNode.y ).sub( 1 ) ); + + } + + } + return uvNode; } diff --git a/src/nodes/accessors/TextureNode.js b/src/nodes/accessors/TextureNode.js index aa3b7dadb7d8d7..9ca3181f807f46 100644 --- a/src/nodes/accessors/TextureNode.js +++ b/src/nodes/accessors/TextureNode.js @@ -268,7 +268,7 @@ class TextureNode extends UniformNode { setUpdateMatrix( value ) { this.updateMatrix = value; - this.updateType = value ? NodeUpdateType.FRAME : NodeUpdateType.NONE; + this.updateType = value ? NodeUpdateType.RENDER : NodeUpdateType.NONE; return this; @@ -316,6 +316,16 @@ class TextureNode extends UniformNode { // + const texture = this.value; + + if ( ! texture || texture.isTexture !== true ) { + + throw new Error( 'THREE.TSL: `texture( value )` function expects a valid instance of THREE.Texture().' ); + + } + + // + let uvNode = this.uvNode; if ( ( uvNode === null || builder.context.forceUVContext === true ) && builder.context.getUV ) { @@ -426,16 +436,9 @@ class TextureNode extends UniformNode { */ generate( builder, output ) { - const properties = builder.getNodeProperties( this ); - const texture = this.value; - if ( ! texture || texture.isTexture !== true ) { - - throw new Error( 'TextureNode: Need a three.js texture.' ); - - } - + const properties = builder.getNodeProperties( this ); const textureProperty = super.generate( builder, 'property' ); if ( output === 'sampler' ) { diff --git a/src/nodes/code/ScriptableNode.js b/src/nodes/code/ScriptableNode.js index b51514e64ac659..e2ad49d0ea27c1 100644 --- a/src/nodes/code/ScriptableNode.js +++ b/src/nodes/code/ScriptableNode.js @@ -3,6 +3,8 @@ import { scriptableValue } from './ScriptableValueNode.js'; import { nodeProxy, float } from '../tsl/TSLBase.js'; import { hashArray, hashString } from '../core/NodeUtils.js'; +/** @module ScriptableNode **/ + /** * A Map-like data structure for managing resources of scriptable nodes. * @@ -64,7 +66,7 @@ class Parameters { } /** - * Defines the resouces (e.g. namespaces) of scriptable nodes. + * Defines the resources (e.g. namespaces) of scriptable nodes. * * @type {Resources} */ @@ -285,7 +287,7 @@ class ScriptableNode extends Node { } /** - * Returns a paramater for the given name + * Returns a parameter for the given name * * @param {String} name - The name of the parameter. * @return {ScriptableValueNode} The node value. diff --git a/src/nodes/code/ScriptableValueNode.js b/src/nodes/code/ScriptableValueNode.js index c8d53674db11bc..9114b55a2accb7 100644 --- a/src/nodes/code/ScriptableValueNode.js +++ b/src/nodes/code/ScriptableValueNode.js @@ -4,6 +4,8 @@ import { nodeProxy, float } from '../tsl/TSLBase.js'; import { EventDispatcher } from '../../core/EventDispatcher.js'; +/** @module ScriptableValueNode **/ + /** * `ScriptableNode` uses this class to manage script inputs and outputs. * diff --git a/src/nodes/core/CacheNode.js b/src/nodes/core/CacheNode.js index 2a3da0d5ccaff5..d7a5be87bd7773 100644 --- a/src/nodes/core/CacheNode.js +++ b/src/nodes/core/CacheNode.js @@ -56,7 +56,16 @@ class CacheNode extends Node { getNodeType( builder ) { - return this.node.getNodeType( builder ); + const previousCache = builder.getCache(); + const cache = builder.getCacheFromNode( this, this.parent ); + + builder.setCache( cache ); + + const nodeType = this.node.getNodeType( builder ); + + builder.setCache( previousCache ); + + return nodeType; } diff --git a/src/nodes/core/Node.js b/src/nodes/core/Node.js index 577533b6c9a69a..f4353104742e68 100644 --- a/src/nodes/core/Node.js +++ b/src/nodes/core/Node.js @@ -474,8 +474,9 @@ class Node extends EventDispatcher { } - // return a outputNode if exists - return null; + // return a outputNode if exists or null + + return nodeProperties.outputNode || null; } @@ -609,17 +610,19 @@ class Node extends EventDispatcher { if ( properties.initialized !== true ) { - const stackNodesBeforeSetup = builder.stack.nodes.length; + //const stackNodesBeforeSetup = builder.stack.nodes.length; properties.initialized = true; - properties.outputNode = this.setup( builder ); - if ( properties.outputNode !== null && builder.stack.nodes.length !== stackNodesBeforeSetup ) { + const outputNode = this.setup( builder ); // return a node or null + const isNodeOutput = outputNode && outputNode.isNode === true; + + /*if ( isNodeOutput && builder.stack.nodes.length !== stackNodesBeforeSetup ) { // !! no outputNode !! - //properties.outputNode = builder.stack; + //outputNode = builder.stack; - } + }*/ for ( const childNode of Object.values( properties ) ) { @@ -631,6 +634,14 @@ class Node extends EventDispatcher { } + if ( isNodeOutput ) { + + outputNode.build( builder ); + + } + + properties.outputNode = outputNode; + } } else if ( buildStage === 'analyze' ) { diff --git a/src/nodes/core/NodeBuilder.js b/src/nodes/core/NodeBuilder.js index d371dded2620c7..a0370c6ef6a1a1 100644 --- a/src/nodes/core/NodeBuilder.js +++ b/src/nodes/core/NodeBuilder.js @@ -497,6 +497,15 @@ class NodeBuilder { } + /** + * Returns the output struct name which is required by + * {@link module:OutputStructNode}. + * + * @abstract + * @return {String} The name of the output struct. + */ + getOutputStructName() {} + /** * Returns a bind group for the given group name and binding. * @@ -678,6 +687,7 @@ class NodeBuilder { /** * It is used to add Nodes that will be used as FRAME and RENDER events, * and need to follow a certain sequence in the calls to work correctly. + * This function should be called after 'setup()' in the 'build()' process to ensure that the child nodes are processed first. * * @param {Node} node - The node to add. */ @@ -1033,10 +1043,11 @@ class NodeBuilder { * @param {Texture} texture - The texture. * @param {String} textureProperty - The texture property name. * @param {String} uvSnippet - Snippet defining the texture coordinates. + * @param {String?} depthSnippet - Snippet defining the 0-based texture array index to sample. * @param {String} levelSnippet - Snippet defining the mip level. * @return {String} The generated shader string. */ - generateTextureLod( /* texture, textureProperty, uvSnippet, levelSnippet */ ) { + generateTextureLod( /* texture, textureProperty, uvSnippet, depthSnippet, levelSnippet */ ) { console.warn( 'Abstract function.' ); @@ -1210,11 +1221,11 @@ class NodeBuilder { } /** - * Whether the given texture needs a conversion to working color space. + * Checks if the given texture requires a manual conversion to the working color space. * * @abstract * @param {Texture} texture - The texture to check. - * @return {Boolean} Whether a color space conversion is required or not. + * @return {Boolean} Whether the given texture requires a conversion to working color space or not. */ needsToWorkingColorSpace( /*texture*/ ) { @@ -1593,9 +1604,11 @@ class NodeBuilder { * @param {String?} name - The variable's name. * @param {String} [type=node.getNodeType( this )] - The variable's type. * @param {('vertex'|'fragment'|'compute'|'any')} [shaderStage=this.shaderStage] - The shader stage. + * @param {Boolean} [readOnly=false] - Whether the variable is read-only or not. + * * @return {NodeVar} The node variable. */ - getVarFromNode( node, name = null, type = node.getNodeType( this ), shaderStage = this.shaderStage ) { + getVarFromNode( node, name = null, type = node.getNodeType( this ), shaderStage = this.shaderStage, readOnly = false ) { const nodeData = this.getDataFromNode( node, shaderStage ); @@ -1603,13 +1616,26 @@ class NodeBuilder { if ( nodeVar === undefined ) { + const idNS = readOnly ? '_const' : '_var'; + const vars = this.vars[ shaderStage ] || ( this.vars[ shaderStage ] = [] ); + const id = this.vars[ idNS ] || ( this.vars[ idNS ] = 0 ); - if ( name === null ) name = 'nodeVar' + vars.length; + if ( name === null ) { - nodeVar = new NodeVar( name, type ); + name = ( readOnly ? 'nodeConst' : 'nodeVar' ) + id; - vars.push( nodeVar ); + this.vars[ idNS ] ++; + + } + + nodeVar = new NodeVar( name, type, readOnly ); + + if ( ! readOnly ) { + + vars.push( nodeVar ); + + } nodeData.variable = nodeVar; @@ -1619,6 +1645,35 @@ class NodeBuilder { } + /** + * Returns whether a Node or its flow is deterministic, useful for use in `const`. + * + * @param {Node} node - The varying node. + * @return {Boolean} Returns true if deterministic. + */ + isDeterministic( node ) { + + if ( node.isMathNode ) { + + return this.isDeterministic( node.aNode ) && + ( node.bNode ? this.isDeterministic( node.bNode ) : true ) && + ( node.cNode ? this.isDeterministic( node.cNode ) : true ); + + } else if ( node.isOperatorNode ) { + + return this.isDeterministic( node.aNode ) && + ( node.bNode ? this.isDeterministic( node.bNode ) : true ); + + } else if ( node.isConstNode ) { + + return true; + + } + + return false; + + } + /** * Returns an instance of {@link NodeVarying} for the given varying node. * diff --git a/src/nodes/core/NodeUtils.js b/src/nodes/core/NodeUtils.js index a4f0f813ac0cf7..186092ec3023f1 100644 --- a/src/nodes/core/NodeUtils.js +++ b/src/nodes/core/NodeUtils.js @@ -168,6 +168,8 @@ const typeFromLength = /*@__PURE__*/ new Map( [ [ 16, 'mat4' ] ] ); +const dataFromObject = /*@__PURE__*/ new WeakMap(); + /** * Returns the data type for the given the length. * @@ -181,6 +183,39 @@ export function getTypeFromLength( length ) { } +/** + * Returns the typed array for the given data type. + * + * @method + * @param {String} type - The data type. + * @return {TypedArray} The typed array. + */ +export function getTypedArrayFromType( type ) { + + // Handle component type for vectors and matrices + if ( /[iu]?vec\d/.test( type ) ) { + + // Handle int vectors + if ( type.startsWith( 'ivec' ) ) return Int32Array; + // Handle uint vectors + if ( type.startsWith( 'uvec' ) ) return Uint32Array; + // Default to float vectors + return Float32Array; + + } + + // Handle matrices (always float) + if ( /mat\d/.test( type ) ) return Float32Array; + + // Basic types + if ( /float/.test( type ) ) return Float32Array; + if ( /uint/.test( type ) ) return Uint32Array; + if ( /int/.test( type ) ) return Int32Array; + + throw new Error( `THREE.NodeUtils: Unsupported type: ${type}` ); + +} + /** * Returns the length for the given data type. * @@ -334,6 +369,27 @@ export function getValueFromType( type, ...params ) { } +/** + * Gets the object data that can be shared between different rendering steps. + * + * @param {Object} object - The object to get the data for. + * @return {Object} The object data. + */ +export function getDataFromObject( object ) { + + let data = dataFromObject.get( object ); + + if ( data === undefined ) { + + data = {}; + dataFromObject.set( object, data ); + + } + + return data; + +} + /** * Converts the given array buffer to a Base64 string. * diff --git a/src/nodes/core/NodeVar.js b/src/nodes/core/NodeVar.js index 7a180f8c3b649e..b95a18db7173d8 100644 --- a/src/nodes/core/NodeVar.js +++ b/src/nodes/core/NodeVar.js @@ -11,8 +11,9 @@ class NodeVar { * * @param {String} name - The name of the variable. * @param {String} type - The type of the variable. + * @param {Boolean} [readOnly=false] - The read-only flag. */ - constructor( name, type ) { + constructor( name, type, readOnly = false ) { /** * This flag can be used for type testing. @@ -37,6 +38,13 @@ class NodeVar { */ this.type = type; + /** + * The read-only flag. + * + * @type {boolean} + */ + this.readOnly = readOnly; + } } diff --git a/src/nodes/core/PropertyNode.js b/src/nodes/core/PropertyNode.js index 681173b1d3346e..df58c8f8bf959b 100644 --- a/src/nodes/core/PropertyNode.js +++ b/src/nodes/core/PropertyNode.js @@ -1,8 +1,10 @@ import Node from './Node.js'; import { nodeImmutable, nodeObject } from '../tsl/TSLCore.js'; +/** @module PropertyNode **/ + /** - * This class represents a shader property. It can be used on + * This class represents a shader property. It can be used * to explicitly define a property and assign a value to it. * * ```js @@ -101,34 +103,218 @@ class PropertyNode extends Node { export default PropertyNode; +/** + * TSL function for creating a property node. + * + * @function + * @param {String} type - The type of the node. + * @param {String?} [name=null] - The name of the property in the shader. + * @returns {PropertyNode} + */ export const property = ( type, name ) => nodeObject( new PropertyNode( type, name ) ); + +/** + * TSL function for creating a varying property node. + * + * @function + * @param {String} type - The type of the node. + * @param {String?} [name=null] - The name of the varying in the shader. + * @returns {PropertyNode} + */ export const varyingProperty = ( type, name ) => nodeObject( new PropertyNode( type, name, true ) ); +/** + * TSL object that represents the shader variable `DiffuseColor`. + * + * @type {PropertyNode} + */ export const diffuseColor = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec4', 'DiffuseColor' ); + +/** + * TSL object that represents the shader variable `EmissiveColor`. + * + * @type {PropertyNode} + */ export const emissive = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'EmissiveColor' ); + +/** + * TSL object that represents the shader variable `Roughness`. + * + * @type {PropertyNode} + */ export const roughness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Roughness' ); + +/** + * TSL object that represents the shader variable `Metalness`. + * + * @type {PropertyNode} + */ export const metalness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Metalness' ); + +/** + * TSL object that represents the shader variable `Clearcoat`. + * + * @type {PropertyNode} + */ export const clearcoat = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Clearcoat' ); + +/** + * TSL object that represents the shader variable `ClearcoatRoughness`. + * + * @type {PropertyNode} + */ export const clearcoatRoughness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'ClearcoatRoughness' ); + +/** + * TSL object that represents the shader variable `Sheen`. + * + * @type {PropertyNode} + */ export const sheen = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'Sheen' ); + +/** + * TSL object that represents the shader variable `SheenRoughness`. + * + * @type {PropertyNode} + */ export const sheenRoughness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'SheenRoughness' ); + +/** + * TSL object that represents the shader variable `Iridescence`. + * + * @type {PropertyNode} + */ export const iridescence = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Iridescence' ); + +/** + * TSL object that represents the shader variable `IridescenceIOR`. + * + * @type {PropertyNode} + */ export const iridescenceIOR = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'IridescenceIOR' ); + +/** + * TSL object that represents the shader variable `IridescenceThickness`. + * + * @type {PropertyNode} + */ export const iridescenceThickness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'IridescenceThickness' ); + +/** + * TSL object that represents the shader variable `AlphaT`. + * + * @type {PropertyNode} + */ export const alphaT = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'AlphaT' ); + +/** + * TSL object that represents the shader variable `Anisotropy`. + * + * @type {PropertyNode} + */ export const anisotropy = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Anisotropy' ); + +/** + * TSL object that represents the shader variable `AnisotropyT`. + * + * @type {PropertyNode} + */ export const anisotropyT = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'AnisotropyT' ); + +/** + * TSL object that represents the shader variable `AnisotropyB`. + * + * @type {PropertyNode} + */ export const anisotropyB = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'AnisotropyB' ); + +/** + * TSL object that represents the shader variable `SpecularColor`. + * + * @type {PropertyNode} + */ export const specularColor = /*@__PURE__*/ nodeImmutable( PropertyNode, 'color', 'SpecularColor' ); + +/** + * TSL object that represents the shader variable `SpecularF90`. + * + * @type {PropertyNode} + */ export const specularF90 = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'SpecularF90' ); + +/** + * TSL object that represents the shader variable `Shininess`. + * + * @type {PropertyNode} + */ export const shininess = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Shininess' ); + +/** + * TSL object that represents the shader variable `Output`. + * + * @type {PropertyNode} + */ export const output = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec4', 'Output' ); + +/** + * TSL object that represents the shader variable `dashSize`. + * + * @type {PropertyNode} + */ export const dashSize = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'dashSize' ); + +/** + * TSL object that represents the shader variable `gapSize`. + * + * @type {PropertyNode} + */ export const gapSize = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'gapSize' ); + +/** + * TSL object that represents the shader variable `pointWidth`. + * + * @type {PropertyNode} + */ export const pointWidth = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'pointWidth' ); + +/** + * TSL object that represents the shader variable `IOR`. + * + * @type {PropertyNode} + */ export const ior = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'IOR' ); + +/** + * TSL object that represents the shader variable `Transmission`. + * + * @type {PropertyNode} + */ export const transmission = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Transmission' ); + +/** + * TSL object that represents the shader variable `Thickness`. + * + * @type {PropertyNode} + */ export const thickness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Thickness' ); + +/** + * TSL object that represents the shader variable `AttenuationDistance`. + * + * @type {PropertyNode} + */ export const attenuationDistance = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'AttenuationDistance' ); + +/** + * TSL object that represents the shader variable `AttenuationColor`. + * + * @type {PropertyNode} + */ export const attenuationColor = /*@__PURE__*/ nodeImmutable( PropertyNode, 'color', 'AttenuationColor' ); + +/** + * TSL object that represents the shader variable `Dispersion`. + * + * @type {PropertyNode} + */ export const dispersion = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Dispersion' ); diff --git a/src/nodes/core/VarNode.js b/src/nodes/core/VarNode.js index f81e943a736bce..a8da2b5e2b18ba 100644 --- a/src/nodes/core/VarNode.js +++ b/src/nodes/core/VarNode.js @@ -26,8 +26,9 @@ class VarNode extends Node { * * @param {Node} node - The node for which a variable should be created. * @param {String?} name - The name of the variable in the shader. + * @param {Boolean?} readOnly - The read-only flag. */ - constructor( node, name = null ) { + constructor( node, name = null, readOnly = false ) { super(); @@ -64,6 +65,15 @@ class VarNode extends Node { */ this.isVarNode = true; + /** + * + * The read-only flag. + * + * @type {Boolean} + * @default false + */ + this.readOnly = readOnly; + } getHash( builder ) { @@ -80,15 +90,50 @@ class VarNode extends Node { generate( builder ) { - const { node, name } = this; + const { node, name, readOnly } = this; + const { renderer } = builder; + + const isWebGPUBackend = renderer.backend.isWebGPUBackend === true; + + let isDeterministic = false; + let shouldTreatAsReadOnly = false; + + if ( readOnly ) { + + isDeterministic = builder.isDeterministic( node ); - const nodeVar = builder.getVarFromNode( this, name, builder.getVectorType( this.getNodeType( builder ) ) ); + shouldTreatAsReadOnly = isWebGPUBackend ? readOnly : isDeterministic; + + } + + const vectorType = builder.getVectorType( this.getNodeType( builder ) ); + const snippet = node.build( builder, vectorType ); + + const nodeVar = builder.getVarFromNode( this, name, vectorType, undefined, shouldTreatAsReadOnly ); const propertyName = builder.getPropertyName( nodeVar ); - const snippet = node.build( builder, nodeVar.type ); + let declarationPrefix = propertyName; + + if ( shouldTreatAsReadOnly ) { + + const type = builder.getType( nodeVar.type ); + + if ( isWebGPUBackend ) { + + declarationPrefix = isDeterministic + ? `const ${ propertyName }` + : `let ${ propertyName }`; + + } else { + + declarationPrefix = `const ${ type } ${ propertyName }`; - builder.addLineFlowCode( `${propertyName} = ${snippet}`, this ); + } + + } + + builder.addLineFlowCode( `${ declarationPrefix } = ${ snippet }`, this ); return propertyName; @@ -108,13 +153,36 @@ export default VarNode; */ const createVar = /*@__PURE__*/ nodeProxy( VarNode ); -addMethodChaining( 'toVar', ( ...params ) => createVar( ...params ).append() ); +/** + * TSL function for creating a var node. + * + * @function + * @param {Node} node - The node for which a variable should be created. + * @param {String?} name - The name of the variable in the shader. + * @returns {VarNode} + */ +export const Var = ( node, name = null ) => createVar( node, name ).append(); + +/** + * TSL function for creating a const node. + * + * @function + * @param {Node} node - The node for which a constant should be created. + * @param {String?} name - The name of the constant in the shader. + * @returns {VarNode} + */ +export const Const = ( node, name = null ) => createVar( node, name, true ).append(); + +// Method chaining + +addMethodChaining( 'toVar', Var ); +addMethodChaining( 'toConst', Const ); // Deprecated export const temp = ( node ) => { // @deprecated, r170 - console.warn( 'TSL: "temp" is deprecated. Use ".toVar()" instead.' ); + console.warn( 'TSL: "temp( node )" is deprecated. Use "Var( node )" or "node.toVar()" instead.' ); return createVar( node ); diff --git a/src/nodes/core/VaryingNode.js b/src/nodes/core/VaryingNode.js index caf4ab7f54ad8f..937fc973511416 100644 --- a/src/nodes/core/VaryingNode.js +++ b/src/nodes/core/VaryingNode.js @@ -176,4 +176,14 @@ export default VaryingNode; */ export const varying = /*@__PURE__*/ nodeProxy( VaryingNode ); +/** + * Computes a node in the vertex stage. + * + * @function + * @param {Node} node - The node which should be executed in the vertex stage. + * @returns {VaryingNode} + */ +export const vertexStage = ( node ) => varying( node ); + addMethodChaining( 'varying', varying ); +addMethodChaining( 'vertexStage', vertexStage ); diff --git a/src/nodes/display/BumpMapNode.js b/src/nodes/display/BumpMapNode.js index 08adb6901e2f9f..a591463b0aaf95 100644 --- a/src/nodes/display/BumpMapNode.js +++ b/src/nodes/display/BumpMapNode.js @@ -66,8 +66,8 @@ class BumpMapNode extends TempNode { /** * Constructs a new bump map node. * - * @param {Node} textureNode - Represents the bump map data. - * @param {Node?} [scaleNode=null] - Controls the intensity of the bump effect. + * @param {Node} textureNode - Represents the bump map data. + * @param {Node?} [scaleNode=null] - Controls the intensity of the bump effect. */ constructor( textureNode, scaleNode = null ) { @@ -76,14 +76,14 @@ class BumpMapNode extends TempNode { /** * Represents the bump map data. * - * @type {Node} + * @type {Node} */ this.textureNode = textureNode; /** * Controls the intensity of the bump effect. * - * @type {Node?} + * @type {Node?} * @default null */ this.scaleNode = scaleNode; @@ -111,8 +111,8 @@ export default BumpMapNode; * TSL function for creating a bump map node. * * @function - * @param {Node} textureNode - Represents the bump map data. - * @param {Node?} [scaleNode=null] - Controls the intensity of the bump effect. + * @param {Node} textureNode - Represents the bump map data. + * @param {Node?} [scaleNode=null] - Controls the intensity of the bump effect. * @returns {BumpMapNode} */ export const bumpMap = /*@__PURE__*/ nodeProxy( BumpMapNode ); diff --git a/src/nodes/display/NormalMapNode.js b/src/nodes/display/NormalMapNode.js index f4429ad6f6fa15..5d5b9c70a7d4a6 100644 --- a/src/nodes/display/NormalMapNode.js +++ b/src/nodes/display/NormalMapNode.js @@ -59,8 +59,8 @@ class NormalMapNode extends TempNode { /** * Constructs a new normal map node. * - * @param {Node} node - Represents the normal map data. - * @param {Node?} [scaleNode=null] - Controls the intensity of the effect. + * @param {Node} node - Represents the normal map data. + * @param {Node?} [scaleNode=null] - Controls the intensity of the effect. */ constructor( node, scaleNode = null ) { @@ -69,14 +69,14 @@ class NormalMapNode extends TempNode { /** * Represents the normal map data. * - * @type {Node} + * @type {Node} */ this.node = node; /** * Controls the intensity of the effect. * - * @type {Node?} + * @type {Node?} * @default null */ this.scaleNode = scaleNode; @@ -142,8 +142,8 @@ export default NormalMapNode; * TSL function for creating a normal map node. * * @function - * @param {Node} node - Represents the normal map data. - * @param {Node?} [scaleNode=null] - Controls the intensity of the effect. + * @param {Node} node - Represents the normal map data. + * @param {Node?} [scaleNode=null] - Controls the intensity of the effect. * @returns {NormalMapNode} */ export const normalMap = /*@__PURE__*/ nodeProxy( NormalMapNode ); diff --git a/src/nodes/fog/Fog.js b/src/nodes/fog/Fog.js index 0478f619fe95a3..5424812ce4f6b4 100644 --- a/src/nodes/fog/Fog.js +++ b/src/nodes/fog/Fog.js @@ -34,6 +34,7 @@ function getViewZNode( builder ) { /** * Constructs a new range factor node. * + * @function * @param {Node} near - Defines the near value. * @param {Node} far - Defines the far value. */ @@ -50,6 +51,7 @@ export const rangeFogFactor = Fn( ( [ near, far ], builder ) => { * a clear view near the camera and a faster than exponentially * densening fog farther from the camera. * + * @function * @param {Node} density - Defines the fog density. */ export const densityFogFactor = Fn( ( [ density ], builder ) => { @@ -64,6 +66,7 @@ export const densityFogFactor = Fn( ( [ density ], builder ) => { * This class can be used to configure a fog for the scene. * Nodes of this type are assigned to `Scene.fogNode`. * + * @function * @param {Node} color - Defines the color of the fog. * @param {Node} factor - Defines how the fog is factored in the scene. */ diff --git a/src/nodes/gpgpu/AtomicFunctionNode.js b/src/nodes/gpgpu/AtomicFunctionNode.js index 4ae53a5b130b63..ae821021956e1e 100644 --- a/src/nodes/gpgpu/AtomicFunctionNode.js +++ b/src/nodes/gpgpu/AtomicFunctionNode.js @@ -5,10 +5,12 @@ import { nodeProxy } from '../tsl/TSLCore.js'; /** * `AtomicFunctionNode` represents any function that can operate on atomic variable types - * within a shader. In an atomic function, any modifiation to an atomic variable will - * occur as an indivisble step with a defined order relative to other modifications. + * within a shader. In an atomic function, any modification to an atomic variable will + * occur as an indivisible step with a defined order relative to other modifications. * Accordingly, even if multiple atomic functions are modifying an atomic variable at once - * atomic operations will not interfer with each other. + * atomic operations will not interfere with each other. + * + * This node can only be used with a WebGPU backend. * * @augments TempNode */ diff --git a/src/nodes/gpgpu/BarrierNode.js b/src/nodes/gpgpu/BarrierNode.js index 0c3f06404710bb..639264a508bb4f 100644 --- a/src/nodes/gpgpu/BarrierNode.js +++ b/src/nodes/gpgpu/BarrierNode.js @@ -6,6 +6,8 @@ import { nodeProxy } from '../tsl/TSLCore.js'; /** * Represents a GPU control barrier that synchronizes compute operations within a given scope. * + * This node can only be used with a WebGPU backend. + * * @augments Node */ class BarrierNode extends Node { diff --git a/src/nodes/gpgpu/ComputeBuiltinNode.js b/src/nodes/gpgpu/ComputeBuiltinNode.js index dcb984b2f394eb..a52a66879d71a6 100644 --- a/src/nodes/gpgpu/ComputeBuiltinNode.js +++ b/src/nodes/gpgpu/ComputeBuiltinNode.js @@ -4,7 +4,10 @@ import { nodeObject } from '../tsl/TSLBase.js'; /** @module ComputeBuiltinNode **/ /** - * TODO + * `ComputeBuiltinNode` represents a compute-scope builtin value that expose information + * about the currently running dispatch and/or the device it is running on. + * + * This node can only be used with a WebGPU backend. * * @augments Node */ @@ -149,6 +152,24 @@ const computeBuiltin = ( name, nodeType ) => nodeObject( new ComputeBuiltinNode( /** * TSL function for creating a `numWorkgroups` builtin node. + * Represents the number of workgroups dispatched by the compute shader. + * ```js + * // Run 512 invocations/threads with a workgroup size of 128. + * const computeFn = Fn(() => { + * + * // numWorkgroups.x = 4 + * storageBuffer.element(0).assign(numWorkgroups.x) + * + * })().compute(512, [128]); + * + * // Run 512 invocations/threads with the default workgroup size of 64. + * const computeFn = Fn(() => { + * + * // numWorkgroups.x = 8 + * storageBuffer.element(0).assign(numWorkgroups.x) + * + * })().compute(512); + * ``` * * @function * @returns {ComputeBuiltinNode} @@ -157,6 +178,26 @@ export const numWorkgroups = /*@__PURE__*/ computeBuiltin( 'numWorkgroups', 'uve /** * TSL function for creating a `workgroupId` builtin node. + * Represents the 3-dimensional index of the workgroup the current compute invocation belongs to. + * ```js + * // Execute 12 compute threads with a workgroup size of 3. + * const computeFn = Fn( () => { + * + * If( workgroupId.x.modInt( 2 ).equal( 0 ), () => { + * + * storageBuffer.element( instanceIndex ).assign( instanceIndex ); + * + * } ).Else( () => { + * + * storageBuffer.element( instanceIndex ).assign( 0 ); + * + * } ); + * + * } )().compute( 12, [ 3 ] ); + * + * // workgroupId.x = [0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3]; + * // Buffer Output = [0, 1, 2, 0, 0, 0, 6, 7, 8, 0, 0, 0]; + * ``` * * @function * @returns {ComputeBuiltinNode} @@ -164,7 +205,16 @@ export const numWorkgroups = /*@__PURE__*/ computeBuiltin( 'numWorkgroups', 'uve export const workgroupId = /*@__PURE__*/ computeBuiltin( 'workgroupId', 'uvec3' ); /** - * TSL function for creating a `localId` builtin node. + * TSL function for creating a `globalId` builtin node. A non-linearized 3-dimensional + * representation of the current invocation's position within a 3D global grid. + * + * @function + * @returns {ComputeBuiltinNode} + */ +export const globalId = /*@__PURE__*/ computeBuiltin( 'globalId', 'uvec3' ); +/** + * TSL function for creating a `localId` builtin node. A non-linearized 3-dimensional + * representation of the current invocation's position within a 3D workgroup grid. * * @function * @returns {ComputeBuiltinNode} @@ -172,7 +222,8 @@ export const workgroupId = /*@__PURE__*/ computeBuiltin( 'workgroupId', 'uvec3' export const localId = /*@__PURE__*/ computeBuiltin( 'localId', 'uvec3' ); /** - * TSL function for creating a `subgroupSize` builtin node. + * TSL function for creating a `subgroupSize` builtin node. A device dependent variable + * that exposes the size of the current invocation's subgroup. * * @function * @returns {ComputeBuiltinNode} diff --git a/src/nodes/gpgpu/ComputeNode.js b/src/nodes/gpgpu/ComputeNode.js index eb3695786bdf52..7ca263a227982a 100644 --- a/src/nodes/gpgpu/ComputeNode.js +++ b/src/nodes/gpgpu/ComputeNode.js @@ -73,6 +73,14 @@ class ComputeNode extends Node { */ this.version = 1; + /** + * The name or label of the uniform. + * + * @type {String} + * @default '' + */ + this.name = ''; + /** * The `updateBeforeType` is set to `NodeUpdateType.OBJECT` since {@link ComputeNode#updateBefore} * is executed once per object by default. @@ -102,6 +110,20 @@ class ComputeNode extends Node { } + /** + * Sets the {@link ComputeNode#name} property. + * + * @param {String} name - The name of the uniform. + * @return {ComputeNode} A reference to this node. + */ + label( name ) { + + this.name = name; + + return this; + + } + /** * TODO */ diff --git a/src/nodes/gpgpu/WorkgroupInfoNode.js b/src/nodes/gpgpu/WorkgroupInfoNode.js index c8f0b6dc65e798..8d1bc9c0191d11 100644 --- a/src/nodes/gpgpu/WorkgroupInfoNode.js +++ b/src/nodes/gpgpu/WorkgroupInfoNode.js @@ -5,7 +5,7 @@ import Node from '../core/Node.js'; /** @module WorkgroupInfoNode **/ /** - * TODO + * Represents an element of a 'workgroup' scoped buffer. * * @augments ArrayElementNode */ @@ -56,18 +56,25 @@ class WorkgroupInfoElementNode extends ArrayElementNode { } /** - * TODO + * A node allowing the user to create a 'workgroup' scoped buffer within the + * context of a compute shader. Typically, workgroup scoped buffers are + * created to hold data that is transferred from a global storage scope into + * a local workgroup scope. For invocations within a workgroup, data + * access speeds on 'workgroup' scoped buffers can be significantly faster + * than similar access operations on globally accessible storage buffers. + * + * This node can only be used with a WebGPU backend. * * @augments Node */ class WorkgroupInfoNode extends Node { /** - * Constructs a new workgroup info node. + * Constructs a new buffer scoped to type scope. * * @param {String} scope - TODO. - * @param {String} bufferType - The buffer type. - * @param {Number} [bufferCount=0] - The buffer count. + * @param {String} bufferType - The data type of a 'workgroup' scoped buffer element. + * @param {Number} [bufferCount=0] - The number of elements in the buffer. */ constructor( scope, bufferType, bufferCount = 0 ) { @@ -97,6 +104,13 @@ class WorkgroupInfoNode extends Node { */ this.isWorkgroupInfoNode = true; + /** + * The data type of the array buffer. + * + * @type {String} + */ + this.elementType = bufferType; + /** * TODO. * @@ -134,6 +148,18 @@ class WorkgroupInfoNode extends Node { } + + /** + * The data type of the array buffer. + * + * @return {String} The element type. + */ + getElementType() { + + return this.elementType; + + } + /** * Overwrites the default implementation since the input type * is inferred from the scope. @@ -171,10 +197,11 @@ export default WorkgroupInfoNode; /** * TSL function for creating a workgroup info node. + * Creates a new 'workgroup' scoped array buffer. * * @function - * @param {String} type - The buffer type. - * @param {Number} [count=0] - The buffer count. + * @param {String} type - The data type of a 'workgroup' scoped buffer element. + * @param {Number} [count=0] - The number of elements in the buffer. * @returns {WorkgroupInfoNode} */ export const workgroupArray = ( type, count ) => nodeObject( new WorkgroupInfoNode( 'Workgroup', type, count ) ); diff --git a/src/nodes/lighting/ShadowBaseNode.js b/src/nodes/lighting/ShadowBaseNode.js index 04f8aaa034c9c1..4b3a5b894ab75f 100644 --- a/src/nodes/lighting/ShadowBaseNode.js +++ b/src/nodes/lighting/ShadowBaseNode.js @@ -58,7 +58,7 @@ class ShadowBaseNode extends Node { } /** - * Setups the shadow position node which is by default the predefined TSL node object `shadowWorldPosition`. + * Setups the shadow position node which is by default the predefined TSL node object `shadowPositionWorld`. * * @param {(NodeBuilder|{Material})} object - A configuration object that must at least hold a material reference. */ @@ -66,7 +66,7 @@ class ShadowBaseNode extends Node { // Use assign inside an Fn() - shadowWorldPosition.assign( material.shadowPositionNode || positionWorld ); + shadowPositionWorld.assign( material.shadowPositionNode || positionWorld ); } @@ -88,6 +88,6 @@ class ShadowBaseNode extends Node { * * @type {Node} */ -export const shadowWorldPosition = /*@__PURE__*/ vec3().toVar( 'shadowWorldPosition' ); +export const shadowPositionWorld = /*@__PURE__*/ vec3().toVar( 'shadowPositionWorld' ); export default ShadowBaseNode; diff --git a/src/nodes/lighting/ShadowNode.js b/src/nodes/lighting/ShadowNode.js index 922c04e289fb86..ed8072a6df7964 100644 --- a/src/nodes/lighting/ShadowNode.js +++ b/src/nodes/lighting/ShadowNode.js @@ -1,4 +1,4 @@ -import ShadowBaseNode, { shadowWorldPosition } from './ShadowBaseNode.js'; +import ShadowBaseNode, { shadowPositionWorld } from './ShadowBaseNode.js'; import { float, vec2, vec3, vec4, If, int, Fn, nodeObject } from '../tsl/TSLBase.js'; import { reference } from '../accessors/ReferenceNode.js'; import { texture } from '../accessors/TextureNode.js'; @@ -16,6 +16,8 @@ import { renderGroup } from '../core/UniformGroupNode.js'; import { viewZToLogarithmicDepth } from '../display/ViewportDepthNode.js'; import { objectPosition } from '../accessors/Object3DNode.js'; import { lightShadowMatrix } from '../accessors/Lights.js'; +import { resetRendererAndSceneState, restoreRendererAndSceneState } from '../../renderers/common/RendererUtils.js'; +import { getDataFromObject } from '../core/NodeUtils.js'; /** @module ShadowNode **/ @@ -56,6 +58,7 @@ const getShadowMaterial = ( light ) => { material.depthNode = depthNode; material.isShadowNodeMaterial = true; // Use to avoid other overrideMaterial override material.colorNode unintentionally when using material.shadowNode material.name = 'ShadowMaterial'; + material.fog = false; shadowMaterialLib.set( light, material ); @@ -305,6 +308,7 @@ const _shadowFilterLib = [ BasicShadowFilter, PCFShadowFilter, PCFSoftShadowFilt // +let _rendererState; const _quadMesh = /*@__PURE__*/ new QuadMesh(); /** @@ -548,7 +552,7 @@ class ShadowNode extends ShadowBaseNode { const shadowIntensity = reference( 'intensity', 'float', shadow ).setGroup( renderGroup ); const normalBias = reference( 'normalBias', 'float', shadow ).setGroup( renderGroup ); - const shadowPosition = lightShadowMatrix( light ).mul( shadowWorldPosition.add( transformedNormalWorld.mul( normalBias ) ) ); + const shadowPosition = lightShadowMatrix( light ).mul( shadowPositionWorld.add( transformedNormalWorld.mul( normalBias ) ) ); const shadowCoord = this.setupShadowCoord( builder, shadowPosition ); // @@ -652,22 +656,27 @@ class ShadowNode extends ShadowBaseNode { const depthVersion = shadowMap.depthTexture.version; this._depthVersionCached = depthVersion; - const currentOverrideMaterial = scene.overrideMaterial; - - scene.overrideMaterial = getShadowMaterial( light ); - shadow.camera.layers.mask = camera.layers.mask; - const currentRenderTarget = renderer.getRenderTarget(); const currentRenderObjectFunction = renderer.getRenderObjectFunction(); + const currentMRT = renderer.getMRT(); + const useVelocity = currentMRT ? currentMRT.has( 'velocity' ) : false; + + _rendererState = resetRendererAndSceneState( renderer, scene, _rendererState ); - renderer.setMRT( null ); + scene.overrideMaterial = getShadowMaterial( light ); renderer.setRenderObjectFunction( ( object, scene, _camera, geometry, material, group, ...params ) => { if ( object.castShadow === true || ( object.receiveShadow && shadowType === VSMShadowMap ) ) { + if ( useVelocity ) { + + getDataFromObject( object ).useVelocity = true; + + } + object.onBeforeShadow( renderer, object, camera, shadow.camera, geometry, scene.overrideMaterial, group ); renderer.renderObject( object, scene, _camera, geometry, material, group, ...params ); @@ -692,11 +701,7 @@ class ShadowNode extends ShadowBaseNode { } - renderer.setRenderTarget( currentRenderTarget ); - - renderer.setMRT( currentMRT ); - - scene.overrideMaterial = currentOverrideMaterial; + restoreRendererAndSceneState( renderer, scene, _rendererState ); } diff --git a/src/nodes/math/ConditionalNode.js b/src/nodes/math/ConditionalNode.js index e133237fba2a48..69fb0988c0538d 100644 --- a/src/nodes/math/ConditionalNode.js +++ b/src/nodes/math/ConditionalNode.js @@ -69,11 +69,23 @@ class ConditionalNode extends Node { */ getNodeType( builder ) { - const ifType = this.ifNode.getNodeType( builder ); + const { ifNode, elseNode } = builder.getNodeProperties( this ); - if ( this.elseNode !== null ) { + if ( ifNode === undefined ) { - const elseType = this.elseNode.getNodeType( builder ); + // fallback setup + + this.setup( builder ); + + return this.getNodeType( builder ); + + } + + const ifType = ifNode.getNodeType( builder ); + + if ( elseNode !== null ) { + + const elseType = elseNode.getNodeType( builder ); if ( builder.getTypeLength( elseType ) > builder.getTypeLength( ifType ) ) { diff --git a/src/nodes/math/MathNode.js b/src/nodes/math/MathNode.js index 1cb67be51ba0b0..5a6a507edf9f28 100644 --- a/src/nodes/math/MathNode.js +++ b/src/nodes/math/MathNode.js @@ -65,6 +65,15 @@ class MathNode extends TempNode { */ this.cNode = cNode; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ + this.isMathNode = true; + } /** @@ -534,9 +543,11 @@ export const acos = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ACOS ); /** * Returns the arc-tangent of the parameter. + * If two parameters are provided, the result is `atan2(y/x)`. * * @function - * @param {Node | Number} x - The parameter. + * @param {Node | Number} y - The y parameter. + * @param {(Node | Number)?} x - The x parameter. * @returns {Node} */ export const atan = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ATAN ); @@ -943,6 +954,13 @@ export const atan2 = ( y, x ) => { // @deprecated, r172 }; +// GLSL alias function + +export const faceforward = faceForward; +export const inversesqrt = inverseSqrt; + +// Method chaining + addMethodChaining( 'all', all ); addMethodChaining( 'any', any ); addMethodChaining( 'equals', equals ); diff --git a/src/nodes/math/OperatorNode.js b/src/nodes/math/OperatorNode.js index 9b744237729205..355d4340333d45 100644 --- a/src/nodes/math/OperatorNode.js +++ b/src/nodes/math/OperatorNode.js @@ -65,6 +65,15 @@ class OperatorNode extends TempNode { */ this.bNode = bNode; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ + this.isOperatorNode = true; + } /** diff --git a/src/nodes/tsl/TSLBase.js b/src/nodes/tsl/TSLBase.js index 4985ab6426e393..8fb44ae7df9bc0 100644 --- a/src/nodes/tsl/TSLBase.js +++ b/src/nodes/tsl/TSLBase.js @@ -11,7 +11,7 @@ export * from '../math/MathNode.js'; // abs(), floor(), ... export * from '../math/ConditionalNode.js'; // select(), ... export * from '../core/ContextNode.js'; // .context() export * from '../core/VarNode.js'; // .var() -> TODO: Maybe rename .toVar() -> .var() -export * from '../core/VaryingNode.js'; // varying() -> TODO: Add vertexStage() +export * from '../core/VaryingNode.js'; // varying(), vertexStage() export * from '../display/ColorSpaceNode.js'; // .toColorSpace() export * from '../display/ToneMappingNode.js'; // .toToneMapping() export * from '../accessors/BufferAttributeNode.js'; // .toAttribute() diff --git a/src/nodes/tsl/TSLCore.js b/src/nodes/tsl/TSLCore.js index 612362d8eaca00..5757e930f4ae1e 100644 --- a/src/nodes/tsl/TSLCore.js +++ b/src/nodes/tsl/TSLCore.js @@ -305,7 +305,7 @@ class ShaderCallNodeInternal extends Node { } else { const jsFunc = shaderNode.jsFunc; - const outputNode = inputNodes !== null ? jsFunc( inputNodes, builder ) : jsFunc( builder ); + const outputNode = inputNodes !== null || jsFunc.length > 1 ? jsFunc( inputNodes || [], builder ) : jsFunc( builder ); result = nodeObject( outputNode ); diff --git a/src/nodes/utils/ReflectorNode.js b/src/nodes/utils/ReflectorNode.js index 2d1f2a19f952e2..a55a22d3133fea 100644 --- a/src/nodes/utils/ReflectorNode.js +++ b/src/nodes/utils/ReflectorNode.js @@ -363,7 +363,7 @@ class ReflectorBaseNode extends Node { updateBefore( frame ) { - if ( this.bounces === false && _inReflector ) return; + if ( this.bounces === false && _inReflector ) return false; _inReflector = true; @@ -460,14 +460,17 @@ class ReflectorBaseNode extends Node { const currentRenderTarget = renderer.getRenderTarget(); const currentMRT = renderer.getMRT(); + const currentAutoClear = renderer.autoClear; renderer.setMRT( null ); renderer.setRenderTarget( renderTarget ); + renderer.autoClear = true; renderer.render( scene, virtualCamera ); renderer.setMRT( currentMRT ); renderer.setRenderTarget( currentRenderTarget ); + renderer.autoClear = currentAutoClear; material.visible = true; diff --git a/src/objects/ClippingGroup.js b/src/objects/ClippingGroup.js index c5db020386eb60..2ff8cb598a1cee 100644 --- a/src/objects/ClippingGroup.js +++ b/src/objects/ClippingGroup.js @@ -1,15 +1,64 @@ import { Group } from './Group.js'; +/** + * In earlier three.js versions, clipping was defined globally + * on the renderer or on material level. This special version of + * `THREE.Group` allows to encode the clipping state into the scene + * graph. Meaning if you create an instance of this group, all + * descendant 3D objects will be affected by the respective clipping + * planes. + * + * Note: `ClippingGroup` can only be used with `WebGPURenderer`. + * + * @augments Group + */ class ClippingGroup extends Group { + /** + * Constructs a new clipping group. + */ constructor() { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isClippingGroup = true; + + /** + * An array with clipping planes. + * + * @type {Array} + */ this.clippingPlanes = []; + + /** + * Whether clipping should be enabled or not. + * + * @type {Boolean} + * @default true + */ this.enabled = true; + + /** + * Whether the intersection of the clipping planes is used to clip objects, rather than their union. + * + * @type {Boolean} + * @default false + */ this.clipIntersection = false; + + /** + * Whether shadows should be clipped or not. + * + * @type {Boolean} + * @default false + */ this.clipShadows = false; } diff --git a/src/renderers/common/Animation.js b/src/renderers/common/Animation.js index ae626f97e21382..195bc2bdcd4012 100644 --- a/src/renderers/common/Animation.js +++ b/src/renderers/common/Animation.js @@ -1,16 +1,63 @@ + +/** + * This module manages the internal animation loop of the renderer. + * + * @private + */ class Animation { + /** + * Constructs a new animation loop management component. + * + * @param {Nodes} nodes - Renderer component for managing nodes related logic. + * @param {Info} info - Renderer component for managing metrics and monitoring data. + */ constructor( nodes, info ) { + /** + * Renderer component for managing nodes related logic. + * + * @type {Nodes} + */ this.nodes = nodes; + + /** + * Renderer component for managing metrics and monitoring data. + * + * @type {Info} + */ this.info = info; + /** + * A reference to the context from `requestAnimationFrame()` can + * be called (usually `window`). + * + * @type {Window|XRSession} + */ this._context = self; + + /** + * The user-defined animation loop. + * + * @type {Function?} + * @default null + */ this._animationLoop = null; + + /** + * The requestId which is returned from the `requestAnimationFrame()` call. + * Can be used to cancel the stop the animation loop. + * + * @type {Number?} + * @default null + */ this._requestId = null; } + /** + * Starts the internal animation loop. + */ start() { const update = ( time, frame ) => { @@ -31,6 +78,9 @@ class Animation { } + /** + * Stops the internal animation loop. + */ stop() { this._context.cancelAnimationFrame( this._requestId ); @@ -39,18 +89,31 @@ class Animation { } + /** + * Defines the user-level animation loop. + * + * @param {Function} callback - The animation loop. + */ setAnimationLoop( callback ) { this._animationLoop = callback; } + /** + * Defines the context in which `requestAnimationFrame()` is executed. + * + * @param {Window|XRSession} context - The context to set. + */ setContext( context ) { this._context = context; } + /** + * Frees all internal resources and stops the animation loop. + */ dispose() { this.stop(); diff --git a/src/renderers/common/Attributes.js b/src/renderers/common/Attributes.js index 0f80a46fe72619..d0cd8fcb21ab0c 100644 --- a/src/renderers/common/Attributes.js +++ b/src/renderers/common/Attributes.js @@ -3,16 +3,38 @@ import { AttributeType } from './Constants.js'; import { DynamicDrawUsage } from '../../constants.js'; +/** + * This renderer module manages geometry attributes. + * + * @private + * @augments DataMap + */ class Attributes extends DataMap { + /** + * Constructs a new attribute management component. + * + * @param {Backend} backend - The renderer's backend. + */ constructor( backend ) { super(); + /** + * The renderer's backend. + * + * @type {Backend} + */ this.backend = backend; } + /** + * Deletes the data for the given attribute. + * + * @param {BufferAttribute} attribute - The attribute. + * @return {Object} The deleted attribute data. + */ delete( attribute ) { const attributeData = super.delete( attribute ); @@ -27,6 +49,13 @@ class Attributes extends DataMap { } + /** + * Updates the given attribute. This method creates attribute buffers + * for new attributes and updates data for existing ones. + * + * @param {BufferAttribute} attribute - The attribute to update. + * @param {Number} type - The attribute type. + */ update( attribute, type ) { const data = this.get( attribute ); @@ -69,6 +98,13 @@ class Attributes extends DataMap { } + /** + * Utility method for handling interleaved buffer attributes correctly. + * To process them, their `InterleavedBuffer` is returned. + * + * @param {BufferAttribute} attribute - The attribute. + * @return {BufferAttribute|InterleavedBuffer} + */ _getBufferAttribute( attribute ) { if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; diff --git a/src/renderers/common/Backend.js b/src/renderers/common/Backend.js index da67772f88a27c..415545fdb8ad0a 100644 --- a/src/renderers/common/Backend.js +++ b/src/renderers/common/Backend.js @@ -1,144 +1,542 @@ -let vector2 = null; -let vector4 = null; -let color4 = null; +let _vector2 = null; +let _color4 = null; import Color4 from './Color4.js'; import { Vector2 } from '../../math/Vector2.js'; -import { Vector4 } from '../../math/Vector4.js'; import { createCanvasElement } from '../../utils.js'; import { REVISION } from '../../constants.js'; +/** + * Most of the rendering related logic is implemented in the + * {@link module:Renderer} module and related management components. + * Sometimes it is required though to execute commands which are + * specific to the current 3D backend (which is WebGPU or WebGL 2). + * This abstract base class defines an interface that encapsulates + * all backend-related logic. Derived classes for each backend must + * implement the interface. + * + * @abstract + * @private + */ class Backend { + /** + * Constructs a new backend. + * + * @param {Object} parameters - An object holding parameters for the backend. + */ constructor( parameters = {} ) { + /** + * The parameters of the backend. + * + * @type {Object} + */ this.parameters = Object.assign( {}, parameters ); + + /** + * This weak map holds backend-specific data of objects + * like textures, attributes or render targets. + * + * @type {WeakMap} + */ this.data = new WeakMap(); + + /** + * A reference to the renderer. + * + * @type {Renderer?} + * @default null + */ this.renderer = null; + + /** + * A reference to the canvas element the renderer is drawing to. + * + * @type {(HTMLCanvasElement|OffscreenCanvas)?} + * @default null + */ this.domElement = null; } + /** + * Initializes the backend so it is ready for usage. Concrete backends + * are supposed to implement their rendering context creation and related + * operations in this method. + * + * @async + * @param {Renderer} renderer - The renderer. + * @return {Promise} A Promise that resolves when the backend has been initialized. + */ async init( renderer ) { this.renderer = renderer; } - // render context + /** + * The coordinate system of the backend. + * + * @abstract + * @type {Number} + * @readonly + */ + get coordinateSystem() {} - begin( /*renderContext*/ ) { } + // render context - finish( /*renderContext*/ ) { } + /** + * This method is executed at the beginning of a render call and + * can be used by the backend to prepare the state for upcoming + * draw calls. + * + * @abstract + * @param {RenderContext} renderContext - The render context. + */ + beginRender( /*renderContext*/ ) {} + + /** + * This method is executed at the end of a render call and + * can be used by the backend to finalize work after draw + * calls. + * + * @abstract + * @param {RenderContext} renderContext - The render context. + */ + finishRender( /*renderContext*/ ) {} + + /** + * This method is executed at the beginning of a compute call and + * can be used by the backend to prepare the state for upcoming + * compute tasks. + * + * @abstract + * @param {Node|Array} computeGroup - The compute node(s). + */ + beginCompute( /*computeGroup*/ ) {} + + /** + * This method is executed at the end of a compute call and + * can be used by the backend to finalize work after compute + * tasks. + * + * @abstract + * @param {Node|Array} computeGroup - The compute node(s). + */ + finishCompute( /*computeGroup*/ ) {} // render object + /** + * Executes a draw command for the given render object. + * + * @abstract + * @param {RenderObject} renderObject - The render object to draw. + * @param {Info} info - Holds a series of statistical information about the GPU memory and the rendering process. + */ draw( /*renderObject, info*/ ) { } + // compute node + + /** + * Executes a compute command for the given compute node. + * + * @abstract + * @param {Node|Array} computeGroup - The group of compute nodes of a compute call. Can be a single compute node. + * @param {Node} computeNode - The compute node. + * @param {Array} bindings - The bindings. + * @param {ComputePipeline} computePipeline - The compute pipeline. + */ + compute( /*computeGroup, computeNode, computeBindings, computePipeline*/ ) { } + // program + /** + * Creates a shader program from the given programmable stage. + * + * @abstract + * @param {ProgrammableStage} program - The programmable stage. + */ createProgram( /*program*/ ) { } + /** + * Destroys the shader program of the given programmable stage. + * + * @abstract + * @param {ProgrammableStage} program - The programmable stage. + */ destroyProgram( /*program*/ ) { } // bindings - createBindings( /*bingGroup, bindings*/ ) { } - - updateBindings( /*bingGroup, bindings*/ ) { } + /** + * Creates bindings from the given bind group definition. + * + * @abstract + * @param {BindGroup} bindGroup - The bind group. + * @param {Array} bindings - Array of bind groups. + * @param {Number} cacheIndex - The cache index. + * @param {Number} version - The version. + */ + createBindings( /*bindGroup, bindings, cacheIndex, version*/ ) { } + + /** + * Updates the given bind group definition. + * + * @abstract + * @param {BindGroup} bindGroup - The bind group. + * @param {Array} bindings - Array of bind groups. + * @param {Number} cacheIndex - The cache index. + * @param {Number} version - The version. + */ + updateBindings( /*bindGroup, bindings, cacheIndex, version*/ ) { } + + /** + * Updates a buffer binding. + * + * @abstract + * @param {Buffer} binding - The buffer binding to update. + */ + updateBinding( /*binding*/ ) { } // pipeline - createRenderPipeline( /*renderObject*/ ) { } - - createComputePipeline( /*computeNode, pipeline*/ ) { } - - destroyPipeline( /*pipeline*/ ) { } + /** + * Creates a render pipeline for the given render object. + * + * @abstract + * @param {RenderObject} renderObject - The render object. + * @param {Array} promises - An array of compilation promises which are used in `compileAsync()`. + */ + createRenderPipeline( /*renderObject, promises*/ ) { } + + /** + * Creates a compute pipeline for the given compute node. + * + * @abstract + * @param {ComputePipeline} computePipeline - The compute pipeline. + * @param {Array} bindings - The bindings. + */ + createComputePipeline( /*computePipeline, bindings*/ ) { } // cache key - needsRenderUpdate( /*renderObject*/ ) { } // return Boolean ( fast test ) - - getRenderCacheKey( /*renderObject*/ ) { } // return String + /** + * Returns `true` if the render pipeline requires an update. + * + * @abstract + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether the render pipeline requires an update or not. + */ + needsRenderUpdate( /*renderObject*/ ) { } + + /** + * Returns a cache key that is used to identify render pipelines. + * + * @abstract + * @param {RenderObject} renderObject - The render object. + * @return {String} The cache key. + */ + getRenderCacheKey( /*renderObject*/ ) { } // node builder - createNodeBuilder( /*renderObject*/ ) { } // return NodeBuilder (ADD IT) + /** + * Returns a node builder for the given render object. + * + * @abstract + * @param {RenderObject} renderObject - The render object. + * @param {Renderer} renderer - The renderer. + * @return {NodeBuilder} The node builder. + */ + createNodeBuilder( /*renderObject, renderer*/ ) { } // textures + /** + * Creates a GPU sampler for the given texture. + * + * @abstract + * @param {Texture} texture - The texture to create the sampler for. + */ createSampler( /*texture*/ ) { } + /** + * Destroys the GPU sampler for the given texture. + * + * @abstract + * @param {Texture} texture - The texture to destroy the sampler for. + */ + destroySampler( /*texture*/ ) {} + + /** + * Creates a default texture for the given texture that can be used + * as a placeholder until the actual texture is ready for usage. + * + * @abstract + * @param {Texture} texture - The texture to create a default texture for. + */ createDefaultTexture( /*texture*/ ) { } - createTexture( /*texture*/ ) { } - - copyTextureToBuffer( /*texture, x, y, width, height*/ ) {} + /** + * Defines a texture on the GPU for the given texture object. + * + * @abstract + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ + createTexture( /*texture, options={}*/ ) { } + + /** + * Uploads the updated texture data to the GPU. + * + * @abstract + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ + updateTexture( /*texture, options = {}*/ ) { } + + /** + * Generates mipmaps for the given texture. + * + * @abstract + * @param {Texture} texture - The texture. + */ + generateMipmaps( /*texture*/ ) { } + + /** + * Destroys the GPU data for the given texture object. + * + * @abstract + * @param {Texture} texture - The texture. + */ + destroyTexture( /*texture*/ ) { } + + /** + * Returns texture data as a typed array. + * + * @abstract + * @async + * @param {Texture} texture - The texture to copy. + * @param {Number} x - The x coordinate of the copy origin. + * @param {Number} y - The y coordinate of the copy origin. + * @param {Number} width - The width of the copy. + * @param {Number} height - The height of the copy. + * @param {Number} faceIndex - The face index. + * @return {Promise} A Promise that resolves with a typed array when the copy operation has finished. + */ + async copyTextureToBuffer( /*texture, x, y, width, height, faceIndex*/ ) {} + + /** + * Copies data of the given source texture to the given destination texture. + * + * @abstract + * @param {Texture} srcTexture - The source texture. + * @param {Texture} dstTexture - The destination texture. + * @param {Vector4?} [srcRegion=null] - The region of the source texture to copy. + * @param {(Vector2|Vector3)?} [dstPosition=null] - The destination position of the copy. + * @param {Number} [level=0] - The mip level to copy. + */ + copyTextureToTexture( /*srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0*/ ) {} + + /** + * Copies the current bound framebuffer to the given texture. + * + * @abstract + * @param {Texture} texture - The destination texture. + * @param {RenderContext} renderContext - The render context. + * @param {Vector4} rectangle - A four dimensional vector defining the origin and dimension of the copy. + */ + copyFramebufferToTexture( /*texture, renderContext, rectangle*/ ) {} // attributes + /** + * Creates the GPU buffer of a shader attribute. + * + * @abstract + * @param {BufferAttribute} attribute - The buffer attribute. + */ createAttribute( /*attribute*/ ) { } + /** + * Creates the GPU buffer of an indexed shader attribute. + * + * @abstract + * @param {BufferAttribute} attribute - The indexed buffer attribute. + */ createIndexAttribute( /*attribute*/ ) { } + /** + * Creates the GPU buffer of a storage attribute. + * + * @abstract + * @param {BufferAttribute} attribute - The buffer attribute. + */ + createStorageAttribute( /*attribute*/ ) { } + + /** + * Updates the GPU buffer of a shader attribute. + * + * @abstract + * @param {BufferAttribute} attribute - The buffer attribute to update. + */ updateAttribute( /*attribute*/ ) { } + /** + * Destroys the GPU buffer of a shader attribute. + * + * @abstract + * @param {BufferAttribute} attribute - The buffer attribute to destroy. + */ destroyAttribute( /*attribute*/ ) { } // canvas + /** + * Returns the backend's rendering context. + * + * @abstract + * @return {Object} The rendering context. + */ getContext() { } + /** + * Backends can use this method if they have to run + * logic when the renderer gets resized. + * + * @abstract + */ updateSize() { } - // utils - - resolveTimestampAsync( /*renderContext, type*/ ) { } + /** + * Updates the viewport with the values from the given render context. + * + * @abstract + * @param {RenderContext} renderContext - The render context. + */ + updateViewport( /*renderContext*/ ) {} - hasFeatureAsync( /*name*/ ) { } // return Boolean - - hasFeature( /*name*/ ) { } // return Boolean - - getInstanceCount( renderObject ) { - - const { object, geometry } = renderObject; - - return geometry.isInstancedBufferGeometry ? geometry.instanceCount : ( object.count > 1 ? object.count : 1 ); - - } + // utils + /** + * Returns `true` if the given 3D object is fully occluded by other + * 3D objects in the scene. Backends must implement this method by using + * a Occlusion Query API. + * + * @abstract + * @param {RenderContext} renderContext - The render context. + * @param {Object3D} object - The 3D object to test. + * @return {Boolean} Whether the 3D object is fully occluded or not. + */ + isOccluded( /*renderContext, object*/ ) {} + + /** + * Resolves the time stamp for the given render context and type. + * + * @async + * @abstract + * @param {RenderContext} renderContext - The render context. + * @param {String} type - The render context. + * @return {Promise} A Promise that resolves when the time stamp has been computed. + */ + async resolveTimestampAsync( /*renderContext, type*/ ) { } + + /** + * Can be used to synchronize CPU operations with GPU tasks. So when this method is called, + * the CPU waits for the GPU to complete its operation (e.g. a compute task). + * + * @async + * @abstract + * @return {Promise} A Promise that resolves when synchronization has been finished. + */ + async waitForGPU() {} + + /** + * This method performs a readback operation by moving buffer data from + * a storage buffer attribute from the GPU to the CPU. + * + * @async + * @param {StorageBufferAttribute} attribute - The storage buffer attribute. + * @return {Promise} A promise that resolves with the buffer data when the data are ready. + */ + async getArrayBufferAsync( /* attribute */ ) {} + + /** + * Checks if the given feature is supported by the backend. + * + * @async + * @abstract + * @param {String} name - The feature's name. + * @return {Promise} A Promise that resolves with a bool that indicates whether the feature is supported or not. + */ + async hasFeatureAsync( /*name*/ ) { } + + /** + * Checks if the given feature is supported by the backend. + * + * @abstract + * @param {String} name - The feature's name. + * @return {Boolean} Whether the feature is supported or not. + */ + hasFeature( /*name*/ ) {} + + /** + * Returns the maximum anisotropy texture filtering value. + * + * @abstract + * @return {Number} The maximum anisotropy texture filtering value. + */ + getMaxAnisotropy() {} + + /** + * Returns the drawing buffer size. + * + * @return {Vector2} The drawing buffer size. + */ getDrawingBufferSize() { - vector2 = vector2 || new Vector2(); + _vector2 = _vector2 || new Vector2(); - return this.renderer.getDrawingBufferSize( vector2 ); - - } - - getScissor() { - - vector4 = vector4 || new Vector4(); - - return this.renderer.getScissor( vector4 ); + return this.renderer.getDrawingBufferSize( _vector2 ); } + /** + * Defines the scissor test. + * + * @abstract + * @param {Boolean} boolean - Whether the scissor test should be enabled or not. + */ setScissorTest( /*boolean*/ ) { } + /** + * Returns the clear color and alpha into a single + * color object. + * + * @return {Color4} The clear color. + */ getClearColor() { const renderer = this.renderer; - color4 = color4 || new Color4(); + _color4 = _color4 || new Color4(); - renderer.getClearColor( color4 ); + renderer.getClearColor( _color4 ); - color4.getRGB( color4, this.renderer.currentColorSpace ); + _color4.getRGB( _color4, this.renderer.currentColorSpace ); - return color4; + return _color4; } + /** + * Returns the DOM element. If no DOM element exists, the backend + * creates a new one. + * + * @return {HTMLCanvasElement} The DOM element. + */ getDomElement() { let domElement = this.domElement; @@ -158,14 +556,25 @@ class Backend { } - // resource properties - + /** + * Sets a dictionary for the given object into the + * internal data structure. + * + * @param {Object} object - The object. + * @param {Object} value - The dictionary to set. + */ set( object, value ) { this.data.set( object, value ); } + /** + * Returns the dictionary for the given object. + * + * @param {Object} object - The object. + * @return {Object} The object's dictionary. + */ get( object ) { let map = this.data.get( object ); @@ -181,18 +590,35 @@ class Backend { } + /** + * Checks if the given object has a dictionary + * with data defined. + * + * @param {Object} object - The object. + * @return {Boolean} Whether a dictionary for the given object as been defined or not. + */ has( object ) { return this.data.has( object ); } + /** + * Deletes an object from the internal data structure. + * + * @param {Object} object - The object to delete. + */ delete( object ) { this.data.delete( object ); } + /** + * Frees internal resources. + * + * @abstract + */ dispose() { } } diff --git a/src/renderers/common/Background.js b/src/renderers/common/Background.js index 5d396412ed76bc..97092b3b5a4608 100644 --- a/src/renderers/common/Background.js +++ b/src/renderers/common/Background.js @@ -9,17 +9,50 @@ import { BackSide, LinearSRGBColorSpace } from '../../constants.js'; const _clearColor = /*@__PURE__*/ new Color4(); +/** + * This renderer module manages the background. + * + * @private + * @augments DataMap + */ class Background extends DataMap { + /** + * Constructs a new background management component. + * + * @param {Renderer} renderer - The renderer. + * @param {Nodes} nodes - Renderer component for managing nodes related logic. + */ constructor( renderer, nodes ) { super(); + /** + * The renderer. + * + * @type {Renderer} + */ this.renderer = renderer; + + /** + * Renderer component for managing nodes related logic. + * + * @type {Nodes} + */ this.nodes = nodes; } + /** + * Updates the background for the given scene. Depending on how `Scene.background` + * or `Scene.backgroundNode` are configured, this method might configure a simple clear + * or add a mesh to the render list for rendering the background as a textured plane + * or skybox. + * + * @param {Scene} scene - The scene. + * @param {RenderList} renderList - The current render list. + * @param {RenderContext} renderContext - The current render context. + */ update( scene, renderList, renderContext ) { const renderer = this.renderer; diff --git a/src/renderers/common/BindGroup.js b/src/renderers/common/BindGroup.js index fd350b2328dc92..8255fe9cc73bd8 100644 --- a/src/renderers/common/BindGroup.js +++ b/src/renderers/common/BindGroup.js @@ -1,14 +1,57 @@ let _id = 0; +/** + * A bind group represents a collection of bindings and thus a collection + * or resources. Bind groups are assigned to pipelines to provide them + * with the required resources (like uniform buffers or textures). + * + * @private + */ class BindGroup { + /** + * Constructs a new bind group. + * + * @param {String} name - The bind group's name. + * @param {Array} bindings - An array of bindings. + * @param {Number} index - The group index. + * @param {Array} bindingsReference - An array of reference bindings. + */ constructor( name = '', bindings = [], index = 0, bindingsReference = [] ) { + /** + * The bind group's name. + * + * @type {String} + */ this.name = name; + + /** + * An array of bindings. + * + * @type {Array} + */ this.bindings = bindings; + + /** + * The group index. + * + * @type {Number} + */ this.index = index; + + /** + * An array of reference bindings. + * + * @type {Array} + */ this.bindingsReference = bindingsReference; + /** + * The group's ID. + * + * @type {Number} + */ this.id = _id ++; } diff --git a/src/renderers/common/Binding.js b/src/renderers/common/Binding.js index 9f60f4e41c2ecc..6809dd0f18e07b 100644 --- a/src/renderers/common/Binding.js +++ b/src/renderers/common/Binding.js @@ -1,19 +1,54 @@ +/** + * A binding represents the connection between a resource (like a texture, sampler + * or uniform buffer) and the resource definition in a shader stage. + * + * This module is an abstract base class for all concrete bindings types. + * + * @abstract + * @private + */ class Binding { + /** + * Constructs a new binding. + * + * @param {String} [name=''] - The binding's name. + */ constructor( name = '' ) { + /** + * The binding's name. + * + * @type {String} + */ this.name = name; + /** + * A bitmask that defines in what shader stages the + * binding's resource is accessible. + * + * @type {String} + */ this.visibility = 0; } + /** + * Makes sure binding's resource is visible for the given shader stage. + * + * @param {Number} visibility - The shader stage. + */ setVisibility( visibility ) { this.visibility |= visibility; } + /** + * Clones the binding. + * + * @return {Binding} The cloned binding. + */ clone() { return Object.assign( new this.constructor(), this ); diff --git a/src/renderers/common/Bindings.js b/src/renderers/common/Bindings.js index ca942d20714907..31800450305ed3 100644 --- a/src/renderers/common/Bindings.js +++ b/src/renderers/common/Bindings.js @@ -1,23 +1,80 @@ import DataMap from './DataMap.js'; import { AttributeType } from './Constants.js'; +/** + * This renderer module manages the bindings of the renderer. + * + * @private + * @augments DataMap + */ class Bindings extends DataMap { + /** + * Constructs a new bindings management component. + * + * @param {Backend} backend - The renderer's backend. + * @param {Nodes} nodes - Renderer component for managing nodes related logic. + * @param {Textures} textures - Renderer component for managing textures. + * @param {Attributes} attributes - Renderer component for managing attributes. + * @param {Pipelines} pipelines - Renderer component for managing pipelines. + * @param {Info} info - Renderer component for managing metrics and monitoring data. + */ constructor( backend, nodes, textures, attributes, pipelines, info ) { super(); + /** + * The renderer's backend. + * + * @type {Backend} + */ this.backend = backend; + + /** + * Renderer component for managing textures. + * + * @type {Textures} + */ this.textures = textures; + + /** + * Renderer component for managing pipelines. + * + * @type {Pipelines} + */ this.pipelines = pipelines; + + /** + * Renderer component for managing attributes. + * + * @type {Attributes} + */ this.attributes = attributes; + + /** + * Renderer component for managing nodes related logic. + * + * @type {Nodes} + */ this.nodes = nodes; + + /** + * Renderer component for managing metrics and monitoring data. + * + * @type {Info} + */ this.info = info; this.pipelines.bindings = this; // assign bindings to pipelines } + /** + * Returns the bind groups for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @return {Array} The bind groups. + */ getForRender( renderObject ) { const bindings = renderObject.getBindings(); @@ -44,6 +101,12 @@ class Bindings extends DataMap { } + /** + * Returns the bind groups for the given compute node. + * + * @param {Node} computeNode - The compute node. + * @return {Array} The bind groups. + */ getForCompute( computeNode ) { const bindings = this.nodes.getForCompute( computeNode ).bindings; @@ -68,18 +131,33 @@ class Bindings extends DataMap { } + /** + * Updates the bindings for the given compute node. + * + * @param {Node} computeNode - The compute node. + */ updateForCompute( computeNode ) { this._updateBindings( this.getForCompute( computeNode ) ); } + /** + * Updates the bindings for the given render object. + * + * @param {RenderObject} renderObject - The render object. + */ updateForRender( renderObject ) { this._updateBindings( this.getForRender( renderObject ) ); } + /** + * Updates the given array of bindings. + * + * @param {Array} bindings - The bind groups. + */ _updateBindings( bindings ) { for ( const bindGroup of bindings ) { @@ -90,6 +168,11 @@ class Bindings extends DataMap { } + /** + * Initializes the given bind group. + * + * @param {BindGroup} bindGroup - The bind group to initialize. + */ _init( bindGroup ) { for ( const binding of bindGroup.bindings ) { @@ -111,6 +194,12 @@ class Bindings extends DataMap { } + /** + * Updates the given bind group. + * + * @param {BindGroup} bindGroup - The bind group to update. + * @param {Array} bindings - The bind groups. + */ _update( bindGroup, bindings ) { const { backend } = this; @@ -128,7 +217,10 @@ class Bindings extends DataMap { const updated = this.nodes.updateGroup( binding ); - if ( ! updated ) continue; + // every uniforms group is a uniform buffer. So if no update is required, + // we move one with the next binding. Otherwise the next if block will update the group. + + if ( updated === false ) continue; } diff --git a/src/renderers/common/Buffer.js b/src/renderers/common/Buffer.js index a9a664396f0db9..adbe2cefc5c07d 100644 --- a/src/renderers/common/Buffer.js +++ b/src/renderers/common/Buffer.js @@ -1,32 +1,81 @@ import Binding from './Binding.js'; import { getFloatLength } from './BufferUtils.js'; +/** + * Represents a buffer binding type. + * + * @private + * @abstract + * @augments Binding + */ class Buffer extends Binding { + /** + * Constructs a new buffer. + * + * @param {String} name - The buffer's name. + * @param {TypedArray} [buffer=null] - The buffer. + */ constructor( name, buffer = null ) { super( name ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isBuffer = true; + /** + * The bytes per element. + * + * @type {Number} + */ this.bytesPerElement = Float32Array.BYTES_PER_ELEMENT; + /** + * A reference to the internal buffer. + * + * @private + * @type {TypedArray} + */ this._buffer = buffer; } + /** + * The buffer's byte length. + * + * @type {Number} + * @readonly + */ get byteLength() { return getFloatLength( this._buffer.byteLength ); } + /** + * A reference to the internal buffer. + * + * @type {Float32Array} + * @readonly + */ get buffer() { return this._buffer; } + /** + * Updates the binding. + * + * @return {Boolean} Whether the buffer has been updated and must be + * uploaded to the GPU. + */ update() { return true; diff --git a/src/renderers/common/BufferUtils.js b/src/renderers/common/BufferUtils.js index 0cbdd4c773d3cc..d3df612ed3032a 100644 --- a/src/renderers/common/BufferUtils.js +++ b/src/renderers/common/BufferUtils.js @@ -1,5 +1,15 @@ import { GPU_CHUNK_BYTES } from './Constants.js'; +/** @module BufferUtils **/ + +/** + * This function is usually called with the length in bytes of an array buffer. + * It returns an padded value which ensure chunk size alignment according to STD140 layout. + * + * @function + * @param {Number} floatLength - The buffer length. + * @return {Number} The padded length. + */ function getFloatLength( floatLength ) { // ensure chunk size alignment (STD140 layout) @@ -8,6 +18,15 @@ function getFloatLength( floatLength ) { } +/** + * Given the count of vectors and their vector length, this function computes + * a total length in bytes with buffer alignment according to STD140 layout. + * + * @function + * @param {Number} count - The number of vectors. + * @param {Number} [vectorLength=4] - The vector length. + * @return {Number} The padded length. + */ function getVectorLength( count, vectorLength = 4 ) { const strideLength = getStrideLength( vectorLength ); @@ -18,6 +37,14 @@ function getVectorLength( count, vectorLength = 4 ) { } +/** + * This function is called with a vector length and ensure the computed length + * matches a predefined stride (in this case `4`). + * + * @function + * @param {Number} vectorLength - The vector length. + * @return {Number} The padded length. + */ function getStrideLength( vectorLength ) { const strideLength = 4; diff --git a/src/renderers/common/BundleGroup.js b/src/renderers/common/BundleGroup.js index 9b2dff9f2888ad..5da552ef9dc277 100644 --- a/src/renderers/common/BundleGroup.js +++ b/src/renderers/common/BundleGroup.js @@ -1,20 +1,77 @@ import { Group } from '../../objects/Group.js'; +/** + * A specialized group which enables applications access to the + * Render Bundle API of WebGPU. The group with all its descendant nodes + * are considered as one render bundle and processed as such by + * the renderer. + * + * This module is only fully supported by `WebGPURenderer` with a WebGPU backend. + * With a WebGL backend, the group can technically be rendered but without + * any performance improvements. + * + * @augments Group + */ class BundleGroup extends Group { + /** + * Constructs a new bundle group. + */ constructor() { super(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isBundleGroup = true; + /** + * This property is only relevant for detecting types + * during serialization/deserialization. It should always + * match the class name. + * + * @type {String} + * @readonly + * @default 'BundleGroup' + */ this.type = 'BundleGroup'; + /** + * Whether the bundle is static or not. When set to `true`, the structure + * is assumed to be static and does not change. E.g. no new objects are + * added to the group + * + * If a change is required, an update can still be forced by setting the + * `needsUpdate` flag to `true`. + * + * @type {Boolean} + * @default true + */ this.static = true; + + /** + * The bundle group's version. + * + * @type {Number} + * @readonly + * @default 0 + */ this.version = 0; } + /** + * Set this property to `true` when the bundle group has changed. + * + * @type {Boolean} + * @default false + * @param {Boolean} value + */ set needsUpdate( value ) { if ( value === true ) this.version ++; diff --git a/src/renderers/common/ChainMap.js b/src/renderers/common/ChainMap.js index 5a3bbface0e481..02203123518275 100644 --- a/src/renderers/common/ChainMap.js +++ b/src/renderers/common/ChainMap.js @@ -1,16 +1,38 @@ -export default class ChainMap { - +/** + * Data structure for the renderer. It allows defining values + * with chained, hierarchical keys. Keys are meant to be + * objects since the module internally works with Weak Maps + * for performance reasons. + * + * @private + */ +class ChainMap { + + /** + * Constructs a new Chain Map. + */ constructor() { + /** + * The root Weak Map. + * + * @type {WeakMap} + */ this.weakMap = new WeakMap(); } + /** + * Returns the value for the given array of keys. + * + * @param {Array} keys - List of keys. + * @return {Any} The value. Returns `undefined` if no value was found. + */ get( keys ) { let map = this.weakMap; - for ( let i = 0; i < keys.length; i ++ ) { + for ( let i = 0; i < keys.length - 1; i ++ ) { map = map.get( keys[ i ] ); @@ -22,11 +44,18 @@ export default class ChainMap { } + /** + * Sets the value for the given keys. + * + * @param {Array} keys - List of keys. + * @param {Any} value - The value to set. + * @return {ChainMap} A reference to this Chain Map. + */ set( keys, value ) { let map = this.weakMap; - for ( let i = 0; i < keys.length; i ++ ) { + for ( let i = 0; i < keys.length - 1; i ++ ) { const key = keys[ i ]; @@ -36,15 +65,23 @@ export default class ChainMap { } - return map.set( keys[ keys.length - 1 ], value ); + map.set( keys[ keys.length - 1 ], value ); + + return this; } + /** + * Deletes a value for the given keys. + * + * @param {Array} keys - The keys. + * @return {Boolean} Returns `true` if the value has been removed successfully and `false` if the value has not be found. + */ delete( keys ) { let map = this.weakMap; - for ( let i = 0; i < keys.length; i ++ ) { + for ( let i = 0; i < keys.length - 1; i ++ ) { map = map.get( keys[ i ] ); @@ -57,3 +94,5 @@ export default class ChainMap { } } + +export default ChainMap; diff --git a/src/renderers/common/ClippingContext.js b/src/renderers/common/ClippingContext.js index 220a02976f079c..4c3b89fd897f94 100644 --- a/src/renderers/common/ClippingContext.js +++ b/src/renderers/common/ClippingContext.js @@ -4,41 +4,110 @@ import { Vector4 } from '../../math/Vector4.js'; const _plane = /*@__PURE__*/ new Plane(); +/** + * Represents the state that is used to perform clipping via clipping planes. + * There is a default clipping context for each render context. When the + * scene holds instances of `ClippingGroup`, there will be a context for each + * group. + * + * @private + */ class ClippingContext { + /** + * Constructs a new clipping context. + * + * @param {ClippingContext?} [parentContext=null] - A reference to the parent clipping context. + */ constructor( parentContext = null ) { + /** + * The clipping context's version. + * + * @type {Number} + * @readonly + */ this.version = 0; + /** + * Whether the intersection of the clipping planes is used to clip objects, rather than their union. + * + * @type {Boolean?} + * @default null + */ this.clipIntersection = null; - this.cacheKey = ''; - - - if ( parentContext === null ) { - this.intersectionPlanes = []; - this.unionPlanes = []; - - this.viewNormalMatrix = new Matrix3(); - this.clippingGroupContexts = new WeakMap(); + /** + * The clipping context's cache key. + * + * @type {String} + */ + this.cacheKey = ''; - this.shadowPass = false; + /** + * Whether the shadow pass is active or not. + * + * @type {Boolean} + * @default false + */ + this.shadowPass = false; + + /** + * The view normal matrix. + * + * @type {Matrix3} + */ + this.viewNormalMatrix = new Matrix3(); + + /** + * Internal cache for maintaining clipping contexts. + * + * @type {WeakMap} + */ + this.clippingGroupContexts = new WeakMap(); + + /** + * The intersection planes. + * + * @type {Array} + */ + this.intersectionPlanes = []; + + /** + * The intersection planes. + * + * @type {Array} + */ + this.unionPlanes = []; + + /** + * The version of the clipping context's parent context. + * + * @type {Number?} + * @readonly + */ + this.parentVersion = null; - } else { + if ( parentContext !== null ) { this.viewNormalMatrix = parentContext.viewNormalMatrix; this.clippingGroupContexts = parentContext.clippingGroupContexts; this.shadowPass = parentContext.shadowPass; - this.viewMatrix = parentContext.viewMatrix; } - this.parentVersion = null; - } + /** + * Projects the given source clipping planes and writes the result into the + * destination array. + * + * @param {Array} source - The source clipping planes. + * @param {Array} destination - The destination. + * @param {Number} offset - The offset. + */ projectPlanes( source, destination, offset ) { const l = source.length; @@ -59,6 +128,12 @@ class ClippingContext { } + /** + * Updates the root clipping context of a scene. + * + * @param {Scene} scene - The scene. + * @param {Camera} camera - The camera that is used to render the scene. + */ updateGlobal( scene, camera ) { this.shadowPass = ( scene.overrideMaterial !== null && scene.overrideMaterial.isShadowNodeMaterial ); @@ -68,6 +143,12 @@ class ClippingContext { } + /** + * Updates the clipping context. + * + * @param {ClippingContext} parentContext - The parent context. + * @param {ClippingGroup} clippingGroup - The clipping group this context belongs to. + */ update( parentContext, clippingGroup ) { let update = false; @@ -139,6 +220,12 @@ class ClippingContext { } + /** + * Returns a clipping context for the given clipping group. + * + * @param {ClippingGroup} clippingGroup - The clipping group. + * @return {ClippingContext} The clipping context. + */ getGroupContext( clippingGroup ) { if ( this.shadowPass && ! clippingGroup.clipShadows ) return this; @@ -158,6 +245,12 @@ class ClippingContext { } + /** + * The count of union clipping planes. + * + * @type {Number} + * @readonly + */ get unionClippingCount() { return this.unionPlanes.length; diff --git a/src/renderers/common/Color4.js b/src/renderers/common/Color4.js index 86c58b1d216f69..cc80f77fa64955 100644 --- a/src/renderers/common/Color4.js +++ b/src/renderers/common/Color4.js @@ -1,7 +1,23 @@ import { Color } from '../../math/Color.js'; +/** + * A four-component version of {@link Color} which is internally + * used by the renderer to represents clear color with alpha as + * one object. + * + * @private + * @augments Color + */ class Color4 extends Color { + /** + * Constructs a new four-component color. + * + * @param {Number|String} r - The red value. + * @param {Number} g - The green value. + * @param {Number} b - The blue value. + * @param {Number} [a=1] - The alpha value. + */ constructor( r, g, b, a = 1 ) { super( r, g, b ); @@ -10,6 +26,15 @@ class Color4 extends Color { } + /** + * Overwrites the default to honor alpha. + * + * @param {Number|String} r - The red value. + * @param {Number} g - The green value. + * @param {Number} b - The blue value. + * @param {Number} [a=1] - The alpha value. + * @return {Color4} A reference to this object. + */ set( r, g, b, a = 1 ) { this.a = a; @@ -18,6 +43,12 @@ class Color4 extends Color { } + /** + * Overwrites the default to honor alpha. + * + * @param {Color4} color - The color to copy. + * @return {Color4} A reference to this object. + */ copy( color ) { if ( color.a !== undefined ) this.a = color.a; @@ -26,6 +57,11 @@ class Color4 extends Color { } + /** + * Overwrites the default to honor alpha. + * + * @return {Color4} The cloned color. + */ clone() { return new this.constructor( this.r, this.g, this.b, this.a ); diff --git a/src/renderers/common/ComputePipeline.js b/src/renderers/common/ComputePipeline.js index 8f29dc4756dbbe..7735939208cbb4 100644 --- a/src/renderers/common/ComputePipeline.js +++ b/src/renderers/common/ComputePipeline.js @@ -1,13 +1,37 @@ import Pipeline from './Pipeline.js'; +/** + * Class for representing compute pipelines. + * + * @private + * @augments Pipeline + */ class ComputePipeline extends Pipeline { + /** + * Constructs a new render pipeline. + * + * @param {String} cacheKey - The pipeline's cache key. + * @param {ProgrammableStage} computeProgram - The pipeline's compute shader. + */ constructor( cacheKey, computeProgram ) { super( cacheKey ); + /** + * The pipeline's compute shader. + * + * @type {ProgrammableStage} + */ this.computeProgram = computeProgram; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isComputePipeline = true; } diff --git a/src/renderers/common/CubeRenderTarget.js b/src/renderers/common/CubeRenderTarget.js index 29bd3a6fbc7822..64987a3ddf6738 100644 --- a/src/renderers/common/CubeRenderTarget.js +++ b/src/renderers/common/CubeRenderTarget.js @@ -12,6 +12,12 @@ import { BackSide, NoBlending, LinearFilter, LinearMipmapLinearFilter } from '.. // @TODO: Consider rename WebGLCubeRenderTarget to just CubeRenderTarget +/** + * This class represents a cube render target. It is a special version + * of `WebGLCubeRenderTarget` which is compatible with `WebGPURenderer`. + * + * @augments WebGLCubeRenderTarget + */ class CubeRenderTarget extends WebGLCubeRenderTarget { constructor( size = 1, options = {} ) { @@ -22,6 +28,13 @@ class CubeRenderTarget extends WebGLCubeRenderTarget { } + /** + * Converts the given equirectangular texture to a cube map. + * + * @param {Renderer} renderer - The renderer. + * @param {Texture} texture - The equirectangular texture. + * @return {CubeRenderTarget} A reference to this cube render target. + */ fromEquirectangularTexture( renderer, texture ) { const currentMinFilter = texture.minFilter; diff --git a/src/renderers/common/DataMap.js b/src/renderers/common/DataMap.js index 28e05d1c46edcd..1316c0f1c2d2a3 100644 --- a/src/renderers/common/DataMap.js +++ b/src/renderers/common/DataMap.js @@ -1,11 +1,32 @@ +/** + * Data structure for the renderer. It is intended to manage + * data of objects in dictionaries. + * + * @private + */ class DataMap { + /** + * Constructs a new data map. + */ constructor() { + /** + * `DataMap` internally uses a weak map + * to manage its data. + * + * @type {WeakMap} + */ this.data = new WeakMap(); } + /** + * Returns the dictionary for the given object. + * + * @param {Object} object - The object. + * @return {Object} The dictionary. + */ get( object ) { let map = this.data.get( object ); @@ -21,9 +42,15 @@ class DataMap { } + /** + * Deletes the dictionary for the given object. + * + * @param {Object} object - The object. + * @return {Object?} The deleted dictionary. + */ delete( object ) { - let map; + let map = null; if ( this.data.has( object ) ) { @@ -37,12 +64,21 @@ class DataMap { } + /** + * Returns `true` if the given object has a dictionary defined. + * + * @param {Object} object - The object to test. + * @return {Boolean} Whether a dictionary is defined or not. + */ has( object ) { return this.data.has( object ); } + /** + * Frees internal resources. + */ dispose() { this.data = new WeakMap(); diff --git a/src/renderers/common/Geometries.js b/src/renderers/common/Geometries.js index 271f8a7991c009..3c0848ec3605b3 100644 --- a/src/renderers/common/Geometries.js +++ b/src/renderers/common/Geometries.js @@ -3,6 +3,14 @@ import { AttributeType } from './Constants.js'; import { Uint16BufferAttribute, Uint32BufferAttribute } from '../../core/BufferAttribute.js'; +/** + * Returns `true` if the given array has values that require an Uint32 array type. + * + * @private + * @function + * @param {Array} array - The array to test. + * @return {Boolean} Whether the given array has values that require an Uint32 array type or not. + */ function arrayNeedsUint32( array ) { // assumes larger values usually on last @@ -17,12 +25,28 @@ function arrayNeedsUint32( array ) { } +/** + * Returns the wireframe version for the given geometry. + * + * @private + * @function + * @param {BufferGeometry} geometry - The geometry. + * @return {Number} The version. + */ function getWireframeVersion( geometry ) { return ( geometry.index !== null ) ? geometry.index.version : geometry.attributes.position.version; } +/** + * Returns a wireframe index attribute for the given geometry. + * + * @private + * @function + * @param {BufferGeometry} geometry - The geometry. + * @return {BufferAttribute} The wireframe index attribute. + */ function getWireframeIndex( geometry ) { const indices = []; @@ -67,21 +91,61 @@ function getWireframeIndex( geometry ) { } +/** + * This renderer module manages geometries. + * + * @private + * @augments DataMap + */ class Geometries extends DataMap { + /** + * Constructs a new geometry management component. + * + * @param {Attributes} attributes - Renderer component for managing attributes. + * @param {Info} info - Renderer component for managing metrics and monitoring data. + */ constructor( attributes, info ) { super(); + /** + * Renderer component for managing attributes. + * + * @type {Attributes} + */ this.attributes = attributes; + + /** + * Renderer component for managing metrics and monitoring data. + * + * @type {Info} + */ this.info = info; + /** + * Weak Map for managing attributes for wireframe rendering. + * + * @type {WeakMap} + */ this.wireframes = new WeakMap(); + /** + * This Weak Map is used to make sure buffer attributes are + * updated only once per render call. + * + * @type {WeakMap} + */ this.attributeCall = new WeakMap(); } + /** + * Returns `true` if the given render object has an initialized geometry. + * + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether if the given render object has an initialized geometry or not. + */ has( renderObject ) { const geometry = renderObject.geometry; @@ -90,6 +154,11 @@ class Geometries extends DataMap { } + /** + * Prepares the geometry of the given render object for rendering. + * + * @param {RenderObject} renderObject - The render object. + */ updateForRender( renderObject ) { if ( this.has( renderObject ) === false ) this.initGeometry( renderObject ); @@ -98,6 +167,11 @@ class Geometries extends DataMap { } + /** + * Initializes the geometry of the given render object. + * + * @param {RenderObject} renderObject - The render object. + */ initGeometry( renderObject ) { const geometry = renderObject.geometry; @@ -142,6 +216,11 @@ class Geometries extends DataMap { } + /** + * Updates the geometry attributes of the given render object. + * + * @param {RenderObject} renderObject - The render object. + */ updateAttributes( renderObject ) { // attributes @@ -184,6 +263,12 @@ class Geometries extends DataMap { } + /** + * Updates the given attribute. + * + * @param {BufferAttribute} attribute - The attribute to update. + * @param {Number} type - The attribute type. + */ updateAttribute( attribute, type ) { const callId = this.info.render.calls; @@ -220,12 +305,25 @@ class Geometries extends DataMap { } + /** + * Returns the indirect buffer attribute of the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @return {BufferAttribute?} The indirect attribute. `null` if no indirect drawing is used. + */ getIndirect( renderObject ) { return renderObject.geometry.indirect; } + /** + * Returns the index of the given render object's geometry. This is implemented + * in a method to return a wireframe index if necessary. + * + * @param {RenderObject} renderObject - The render object. + * @return {BufferAttribute?} The index. Returns `null` for non-indexed geometries. + */ getIndex( renderObject ) { const { geometry, material } = renderObject; diff --git a/src/renderers/common/IndirectStorageBufferAttribute.js b/src/renderers/common/IndirectStorageBufferAttribute.js index aaa2fb7bb668c6..731543f63e35f3 100644 --- a/src/renderers/common/IndirectStorageBufferAttribute.js +++ b/src/renderers/common/IndirectStorageBufferAttribute.js @@ -1,11 +1,34 @@ import StorageBufferAttribute from './StorageBufferAttribute.js'; +/** + * This special type of buffer attribute is intended for compute shaders. + * It can be used to encode draw parameters for indirect draw calls. + * + * Note: This type of buffer attribute can only be used with `WebGPURenderer` + * and a WebGPU backend. + * + * @augments StorageBufferAttribute + */ class IndirectStorageBufferAttribute extends StorageBufferAttribute { - constructor( array, itemSize ) { + /** + * Constructs a new storage buffer attribute. + * + * @param {Number|Uint32Array} count - The item count. It is also valid to pass a `Uint32Array` as an argument. + * The subsequent parameter is then obsolete. + * @param {Number} itemSize - The item size. + */ + constructor( count, itemSize ) { - super( array, itemSize, Uint32Array ); + super( count, itemSize, Uint32Array ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isIndirectStorageBufferAttribute = true; } diff --git a/src/renderers/common/Info.js b/src/renderers/common/Info.js index 2de51487092447..4019720cd0105a 100644 --- a/src/renderers/common/Info.js +++ b/src/renderers/common/Info.js @@ -1,12 +1,61 @@ +/** + * This renderer module provides a series of statistical information + * about the GPU memory and the rendering process. Useful for debugging + * and monitoring. + */ class Info { + /** + * Constructs a new info component. + */ constructor() { + /** + * Whether frame related metrics should automatically + * be resetted or not. This property should be set to `false` + * by apps which manage their own animation loop. They must + * then call `renderer.info.reset()` once per frame manually. + * + * @type {Boolean} + * @default true + */ this.autoReset = true; + /** + * The current frame ID. This ID is managed + * by `NodeFrame`. + * + * @type {Number} + * @readonly + * @default 0 + */ this.frame = 0; + + /** + * The number of render calls since the + * app has been started. + * + * @type {Number} + * @readonly + * @default 0 + */ this.calls = 0; + /** + * Render related metrics. + * + * @type {Object} + * @readonly + * @property {Number} calls - The number of render calls since the app has been started. + * @property {Number} frameCalls - The number of render calls of the current frame. + * @property {Number} drawCalls - The number of draw calls of the current frame. + * @property {Number} triangles - The number of rendered triangle primitives of the current frame. + * @property {Number} points - The number of rendered point primitives of the current frame. + * @property {Number} lines - The number of rendered line primitives of the current frame. + * @property {Number} previousFrameCalls - The number of render calls of the previous frame. + * @property {Number} timestamp - The timestamp of the frame when using `renderer.renderAsync()`. + * @property {Number} timestampCalls - The number of render calls using `renderer.renderAsync()`. + */ this.render = { calls: 0, frameCalls: 0, @@ -19,6 +68,17 @@ class Info { timestampCalls: 0 }; + /** + * Compute related metrics. + * + * @type {Object} + * @readonly + * @property {Number} calls - The number of compute calls since the app has been started. + * @property {Number} frameCalls - The number of compute calls of the current frame. + * @property {Number} previousFrameCalls - The number of compute calls of the previous frame. + * @property {Number} timestamp - The timestamp of the frame when using `renderer.computeAsync()`. + * @property {Number} timestampCalls - The number of render calls using `renderer.computeAsync()`. + */ this.compute = { calls: 0, frameCalls: 0, @@ -27,6 +87,14 @@ class Info { timestampCalls: 0 }; + /** + * Memory related metrics. + * + * @type {Object} + * @readonly + * @property {Number} geometries - The number of active geometries. + * @property {Number} frameCalls - The number of active textures. + */ this.memory = { geometries: 0, textures: 0 @@ -34,6 +102,13 @@ class Info { } + /** + * This method should be executed per draw call and updates the corresponding metrics. + * + * @param {Object3D} object - The 3D object that is going to be rendered. + * @param {Number} count - The vertex or index count. + * @param {Number} instanceCount - The instance count. + */ update( object, count, instanceCount ) { this.render.drawCalls ++; @@ -62,6 +137,12 @@ class Info { } + /** + * Used by async render methods to updated timestamp metrics. + * + * @param {('render'|'compute')} type - The type of render call. + * @param {Number} time - The duration of the compute/render call in milliseconds. + */ updateTimestamp( type, time ) { if ( this[ type ].timestampCalls === 0 ) { @@ -85,6 +166,9 @@ class Info { } + /** + * Resets frame related metrics. + */ reset() { const previousRenderFrameCalls = this.render.frameCalls; @@ -105,6 +189,9 @@ class Info { } + /** + * Performs a complete reset of the object. + */ dispose() { this.reset(); diff --git a/src/renderers/common/Lighting.js b/src/renderers/common/Lighting.js index 9a1d4f36f68966..8b48bf6cd24c96 100644 --- a/src/renderers/common/Lighting.js +++ b/src/renderers/common/Lighting.js @@ -2,40 +2,68 @@ import { LightsNode } from '../../nodes/Nodes.js'; import ChainMap from './ChainMap.js'; const _defaultLights = /*@__PURE__*/ new LightsNode(); - +const _chainKeys = []; + +/** + * This renderer module manages the lights nodes which are unique + * per scene and camera combination. + * + * The lights node itself is later configured in the render list + * with the actual lights from the scene. + * + * @private + * @augments ChainMap + */ class Lighting extends ChainMap { + /** + * Constructs a lighting management component. + */ constructor() { super(); } + /** + * Creates a new lights node for the given array of lights. + * + * @param {Array} lights - The render object. + * @return {Boolean} Whether if the given render object has an initialized geometry or not. + */ createNode( lights = [] ) { return new LightsNode().setLights( lights ); } + /** + * Returns a lights node for the given scene and camera. + * + * @param {Scene} scene - The scene. + * @param {Camera} camera - The camera. + * @return {LightsNode} The lights node. + */ getNode( scene, camera ) { // ignore post-processing if ( scene.isQuadMesh ) return _defaultLights; - // tiled lighting - - const keys = [ scene, camera ]; + _chainKeys[ 0 ] = scene; + _chainKeys[ 1 ] = camera; - let node = this.get( keys ); + let node = this.get( _chainKeys ); if ( node === undefined ) { node = this.createNode(); - this.set( keys, node ); + this.set( _chainKeys, node ); } + _chainKeys.length = 0; + return node; } diff --git a/src/renderers/common/Pipeline.js b/src/renderers/common/Pipeline.js index 8f0f30418f5893..a12f9f01e0cd33 100644 --- a/src/renderers/common/Pipeline.js +++ b/src/renderers/common/Pipeline.js @@ -1,9 +1,31 @@ +/** + * Abstract class for representing pipelines. + * + * @private + * @abstract + */ class Pipeline { + /** + * Constructs a new pipeline. + * + * @param {String} cacheKey - The pipeline's cache key. + */ constructor( cacheKey ) { + /** + * The pipeline's cache key. + * + * @type {String} + */ this.cacheKey = cacheKey; + /** + * How often the pipeline is currently in use. + * + * @type {Number} + * @default 0 + */ this.usedTimes = 0; } diff --git a/src/renderers/common/Pipelines.js b/src/renderers/common/Pipelines.js index 4cae37d1260006..e1b12907418498 100644 --- a/src/renderers/common/Pipelines.js +++ b/src/renderers/common/Pipelines.js @@ -3,18 +3,63 @@ import RenderPipeline from './RenderPipeline.js'; import ComputePipeline from './ComputePipeline.js'; import ProgrammableStage from './ProgrammableStage.js'; +/** + * This renderer module manages the pipelines of the renderer. + * + * @private + * @augments DataMap + */ class Pipelines extends DataMap { + /** + * Constructs a new pipeline management component. + * + * @param {Backend} backend - The renderer's backend. + * @param {Nodes} nodes - Renderer component for managing nodes related logic. + */ constructor( backend, nodes ) { super(); + /** + * The renderer's backend. + * + * @type {Backend} + */ this.backend = backend; - this.nodes = nodes; - this.bindings = null; // set by the bindings + /** + * Renderer component for managing nodes related logic. + * + * @type {Nodes} + */ + this.nodes = nodes; + /** + * A references to the bindings management component. + * This reference will be set inside the `Bindings` + * constructor. + * + * @type {Bindings?} + * @default null + */ + this.bindings = null; + + /** + * Internal cache for maintaining pipelines. + * The key of the map is a cache key, the value the pipeline. + * + * @type {Map} + */ this.caches = new Map(); + + /** + * This dictionary maintains for each shader stage type (vertex, + * fragment and compute) the programmable stage objects which + * represent the actual shader code. + * + * @type {Object} + */ this.programs = { vertex: new Map(), fragment: new Map(), @@ -23,6 +68,13 @@ class Pipelines extends DataMap { } + /** + * Returns a compute pipeline for the given compute node. + * + * @param {Node} computeNode - The compute node. + * @param {Array} bindings - The bindings. + * @return {ComputePipeline} The compute pipeline. + */ getForCompute( computeNode, bindings ) { const { backend } = this; @@ -52,7 +104,7 @@ class Pipelines extends DataMap { if ( previousPipeline && previousPipeline.computeProgram.usedTimes === 0 ) this._releaseProgram( previousPipeline.computeProgram ); - stageCompute = new ProgrammableStage( nodeBuilderState.computeShader, 'compute', nodeBuilderState.transforms, nodeBuilderState.nodeAttributes ); + stageCompute = new ProgrammableStage( nodeBuilderState.computeShader, 'compute', computeNode.name, nodeBuilderState.transforms, nodeBuilderState.nodeAttributes ); this.programs.compute.set( nodeBuilderState.computeShader, stageCompute ); backend.createProgram( stageCompute ); @@ -89,6 +141,13 @@ class Pipelines extends DataMap { } + /** + * Returns a render pipeline for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @param {Array?} [promises=null] - An array of compilation promises which is only relevant in context of `Renderer.compileAsync()`. + * @return {RenderPipeline} The render pipeline. + */ getForRender( renderObject, promises = null ) { const { backend } = this; @@ -111,6 +170,8 @@ class Pipelines extends DataMap { const nodeBuilderState = renderObject.getNodeBuilderState(); + const name = renderObject.material ? renderObject.material.name : ''; + // programmable stages let stageVertex = this.programs.vertex.get( nodeBuilderState.vertexShader ); @@ -119,7 +180,7 @@ class Pipelines extends DataMap { if ( previousPipeline && previousPipeline.vertexProgram.usedTimes === 0 ) this._releaseProgram( previousPipeline.vertexProgram ); - stageVertex = new ProgrammableStage( nodeBuilderState.vertexShader, 'vertex' ); + stageVertex = new ProgrammableStage( nodeBuilderState.vertexShader, 'vertex', name ); this.programs.vertex.set( nodeBuilderState.vertexShader, stageVertex ); backend.createProgram( stageVertex ); @@ -132,7 +193,7 @@ class Pipelines extends DataMap { if ( previousPipeline && previousPipeline.fragmentProgram.usedTimes === 0 ) this._releaseProgram( previousPipeline.fragmentProgram ); - stageFragment = new ProgrammableStage( nodeBuilderState.fragmentShader, 'fragment' ); + stageFragment = new ProgrammableStage( nodeBuilderState.fragmentShader, 'fragment', name ); this.programs.fragment.set( nodeBuilderState.fragmentShader, stageFragment ); backend.createProgram( stageFragment ); @@ -173,6 +234,12 @@ class Pipelines extends DataMap { } + /** + * Deletes the pipeline for the given render object. + * + * @param {RenderObject} object - The render object. + * @return {Object?} The deleted dictionary. + */ delete( object ) { const pipeline = this.get( object ).pipeline; @@ -209,6 +276,9 @@ class Pipelines extends DataMap { } + /** + * Frees internal resources. + */ dispose() { super.dispose(); @@ -222,12 +292,27 @@ class Pipelines extends DataMap { } + /** + * Updates the pipeline for the given render object. + * + * @param {RenderObject} renderObject - The render object. + */ updateForRender( renderObject ) { this.getForRender( renderObject ); } + /** + * Returns a compute pipeline for the given parameters. + * + * @private + * @param {Node} computeNode - The compute node. + * @param {ProgrammableStage} stageCompute - The programmable stage representing the compute shader. + * @param {String} cacheKey - The cache key. + * @param {Array} bindings - The bindings. + * @return {ComputePipeline} The compute pipeline. + */ _getComputePipeline( computeNode, stageCompute, cacheKey, bindings ) { // check for existing pipeline @@ -250,6 +335,17 @@ class Pipelines extends DataMap { } + /** + * Returns a render pipeline for the given parameters. + * + * @private + * @param {RenderObject} renderObject - The render object. + * @param {ProgrammableStage} stageVertex - The programmable stage representing the vertex shader. + * @param {ProgrammableStage} stageFragment - The programmable stage representing the fragment shader. + * @param {String} cacheKey - The cache key. + * @param {Array} promises - An array of compilation promises which is only relevant in context of `Renderer.compileAsync()`. + * @return {ComputePipeline} The compute pipeline. + */ _getRenderPipeline( renderObject, stageVertex, stageFragment, cacheKey, promises ) { // check for existing pipeline @@ -266,6 +362,10 @@ class Pipelines extends DataMap { renderObject.pipeline = pipeline; + // The `promises` array is `null` by default and only set to an empty array when + // `Renderer.compileAsync()` is used. The next call actually fills the array with + // pending promises that resolve when the render pipelines are ready for rendering. + this.backend.createRenderPipeline( renderObject, promises ); } @@ -274,24 +374,53 @@ class Pipelines extends DataMap { } + /** + * Computes a cache key representing a compute pipeline. + * + * @private + * @param {Node} computeNode - The compute node. + * @param {ProgrammableStage} stageCompute - The programmable stage representing the compute shader. + * @return {String} The cache key. + */ _getComputeCacheKey( computeNode, stageCompute ) { return computeNode.id + ',' + stageCompute.id; } + /** + * Computes a cache key representing a render pipeline. + * + * @private + * @param {RenderObject} renderObject - The render object. + * @param {ProgrammableStage} stageVertex - The programmable stage representing the vertex shader. + * @param {ProgrammableStage} stageFragment - The programmable stage representing the fragment shader. + * @return {String} The cache key. + */ _getRenderCacheKey( renderObject, stageVertex, stageFragment ) { return stageVertex.id + ',' + stageFragment.id + ',' + this.backend.getRenderCacheKey( renderObject ); } + /** + * Releases the given pipeline. + * + * @private + * @param {Pipeline} pipeline - The pipeline to release. + */ _releasePipeline( pipeline ) { this.caches.delete( pipeline.cacheKey ); } + /** + * Releases the shader program. + * + * @private + * @param {Object} program - The shader program to release. + */ _releaseProgram( program ) { const code = program.code; @@ -301,6 +430,13 @@ class Pipelines extends DataMap { } + /** + * Returns `true` if the compute pipeline for the given compute node requires an update. + * + * @private + * @param {Node} computeNode - The compute node. + * @return {Boolean} Whether the compute pipeline for the given compute node requires an update or not. + */ _needsComputeUpdate( computeNode ) { const data = this.get( computeNode ); @@ -309,6 +445,13 @@ class Pipelines extends DataMap { } + /** + * Returns `true` if the render pipeline for the given render object requires an update. + * + * @private + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether the render object for the given render object requires an update or not. + */ _needsRenderUpdate( renderObject ) { const data = this.get( renderObject ); diff --git a/src/renderers/common/PostProcessing.js b/src/renderers/common/PostProcessing.js index 3792420048329f..64310d9fb9e54a 100644 --- a/src/renderers/common/PostProcessing.js +++ b/src/renderers/common/PostProcessing.js @@ -3,27 +3,93 @@ import { vec4, renderOutput } from '../../nodes/TSL.js'; import { LinearSRGBColorSpace, NoToneMapping } from '../../constants.js'; import QuadMesh from '../../renderers/common/QuadMesh.js'; -const _material = /*@__PURE__*/ new NodeMaterial(); -const _quadMesh = /*@__PURE__*/ new QuadMesh( _material ); - +/** + * This module is responsible to manage the post processing setups in apps. + * You usually create a single instance of this class and use it to define + * the output of your post processing effect chain. + * ```js + * const postProcessing = new PostProcessing( renderer ); + * + * const scenePass = pass( scene, camera ); + * + * postProcessing.outputNode = scenePass; + * ``` + */ class PostProcessing { + /** + * Constructs a new post processing management module. + * + * @param {Renderer} renderer - A reference to the renderer. + * @param {Node} outputNode - An optional output node. + */ constructor( renderer, outputNode = vec4( 0, 0, 1, 1 ) ) { + /** + * A reference to the renderer. + * + * @type {Renderer} + */ this.renderer = renderer; + + /** + * A node which defines the final output of the post + * processing. This is usually the last node in a chain + * of effect nodes. + * + * @type {Node} + */ this.outputNode = outputNode; + /** + * Whether the default output tone mapping and color + * space transformation should be enabled or not. + * + * It is enabled by default by it must be disabled when + * effects must be executed after tone mapping and color + * space conversion. A typical example is FXAA which + * requires sRGB input. + * + * When set to `false`, the app must control the output + * transformation with `RenderOutputNode`. + * + * ```js + * const outputPass = renderOutput( scenePass ); + * ``` + * + * @type {Boolean} + */ this.outputColorTransform = true; + /** + * Must be set to `true` when the output node changes. + * + * @type {Node} + */ this.needsUpdate = true; - _material.name = 'PostProcessing'; + const material = new NodeMaterial(); + material.name = 'PostProcessing'; + + /** + * The full screen quad that is used to render + * the effects. + * + * @private + * @type {QuadMesh} + */ + this._quadMesh = new QuadMesh( material ); } + /** + * When `PostProcessing` is used to apply post processing effects, + * the application must use this version of `render()` inside + * its animation loop (not the one from the renderer). + */ render() { - this.update(); + this._update(); const renderer = this.renderer; @@ -35,7 +101,7 @@ class PostProcessing { // - _quadMesh.render( renderer ); + this._quadMesh.render( renderer ); // @@ -44,7 +110,21 @@ class PostProcessing { } - update() { + /** + * Frees internal resources. + */ + dispose() { + + this._quadMesh.material.dispose(); + + } + + /** + * Updates the state of the module. + * + * @private + */ + _update() { if ( this.needsUpdate === true ) { @@ -53,8 +133,8 @@ class PostProcessing { const toneMapping = renderer.toneMapping; const outputColorSpace = renderer.outputColorSpace; - _quadMesh.material.fragmentNode = this.outputColorTransform === true ? renderOutput( this.outputNode, toneMapping, outputColorSpace ) : this.outputNode.context( { toneMapping, outputColorSpace } ); - _quadMesh.material.needsUpdate = true; + this._quadMesh.material.fragmentNode = this.outputColorTransform === true ? renderOutput( this.outputNode, toneMapping, outputColorSpace ) : this.outputNode.context( { toneMapping, outputColorSpace } ); + this._quadMesh.material.needsUpdate = true; this.needsUpdate = false; @@ -62,9 +142,17 @@ class PostProcessing { } + /** + * When `PostProcessing` is used to apply post processing effects, + * the application must use this version of `renderAsync()` inside + * its animation loop (not the one from the renderer). + * + * @async + * @return {Promise} A Promise that resolves when the render has been finished. + */ async renderAsync() { - this.update(); + this._update(); const renderer = this.renderer; @@ -76,7 +164,7 @@ class PostProcessing { // - await _quadMesh.renderAsync( renderer ); + await this._quadMesh.renderAsync( renderer ); // diff --git a/src/renderers/common/PostProcessingUtils.js b/src/renderers/common/PostProcessingUtils.js deleted file mode 100644 index 0720c77179cf9a..00000000000000 --- a/src/renderers/common/PostProcessingUtils.js +++ /dev/null @@ -1,86 +0,0 @@ -import { Color } from '../../math/Color.js'; - -// renderer state - -export function saveRendererState( renderer, state = {} ) { - - state.toneMapping = renderer.toneMapping; - state.toneMappingExposure = renderer.toneMappingExposure; - state.outputColorSpace = renderer.outputColorSpace; - state.renderTarget = renderer.getRenderTarget(); - state.activeCubeFace = renderer.getActiveCubeFace(); - state.activeMipmapLevel = renderer.getActiveMipmapLevel(); - state.renderObjectFunction = renderer.getRenderObjectFunction(); - state.pixelRatio = renderer.getPixelRatio(); - state.mrt = renderer.getMRT(); - state.clearColor = renderer.getClearColor( state.clearColor || new Color() ); - state.clearAlpha = renderer.getClearAlpha(); - state.autoClear = renderer.autoClear; - state.scissorTest = renderer.getScissorTest(); - - return state; - -} - -export function resetRendererState( renderer, state ) { - - state = saveRendererState( renderer, state ); - - renderer.setMRT( null ); - renderer.setRenderObjectFunction( null ); - renderer.setClearColor( 0x000000, 1 ); - renderer.autoClear = true; - - return state; - -} - -export function restoreRendererState( renderer, state ) { - - renderer.toneMapping = state.toneMapping; - renderer.toneMappingExposure = state.toneMappingExposure; - renderer.outputColorSpace = state.outputColorSpace; - renderer.setRenderTarget( state.renderTarget, state.activeCubeFace, state.activeMipmapLevel ); - renderer.setRenderObjectFunction( state.renderObjectFunction ); - renderer.setPixelRatio( state.pixelRatio ); - renderer.setMRT( state.mrt ); - renderer.setClearColor( state.clearColor, state.clearAlpha ); - renderer.autoClear = state.autoClear; - renderer.setScissorTest( state.scissorTest ); - -} - -// renderer and scene state - -export function saveRendererAndSceneState( renderer, scene, state = {} ) { - - state = saveRendererState( renderer, state ); - state.background = scene.background; - state.backgroundNode = scene.backgroundNode; - state.overrideMaterial = scene.overrideMaterial; - - return state; - -} - -export function resetRendererAndSceneState( renderer, scene, state ) { - - state = saveRendererAndSceneState( renderer, scene, state ); - - scene.background = null; - scene.backgroundNode = null; - scene.overrideMaterial = null; - - return state; - -} - -export function restoreRendererAndSceneState( renderer, scene, state ) { - - restoreRendererState( renderer, state ); - - scene.background = state.background; - scene.backgroundNode = state.backgroundNode; - scene.overrideMaterial = state.overrideMaterial; - -} diff --git a/src/renderers/common/ProgrammableStage.js b/src/renderers/common/ProgrammableStage.js index c69627bf0cd9c8..502cba31e23b3e 100644 --- a/src/renderers/common/ProgrammableStage.js +++ b/src/renderers/common/ProgrammableStage.js @@ -1,16 +1,74 @@ let _id = 0; +/** + * Class for representing programmable stages which are vertex, + * fragment or compute shaders. Unlike fixed-function states (like blending), + * they represent the programmable part of a pipeline. + * + * @private + */ class ProgrammableStage { - constructor( code, type, transforms = null, attributes = null ) { + /** + * Constructs a new programmable stage. + * + * @param {String} code - The shader code. + * @param {('vertex'|'fragment'|'compute')} stage - The type of stage. + * @param {String} name - The name of the shader. + * @param {Array?} [transforms=null] - The transforms (only relevant for compute stages with WebGL 2 which uses Transform Feedback). + * @param {Array?} [attributes=null] - The attributes (only relevant for compute stages with WebGL 2 which uses Transform Feedback). + */ + constructor( code, stage, name, transforms = null, attributes = null ) { + /** + * The id of the programmable stage. + * + * @type {Number} + */ this.id = _id ++; + /** + * The shader code. + * + * @type {String} + */ this.code = code; - this.stage = type; + + /** + * The type of stage. + * + * @type {String} + */ + this.stage = stage; + + /** + * The name of the stage. + * This is used for debugging purposes. + * + * @type {String} + */ + this.name = name; + + /** + * The transforms (only relevant for compute stages with WebGL 2 which uses Transform Feedback). + * + * @type {Array?} + */ this.transforms = transforms; + + /** + * The attributes (only relevant for compute stages with WebGL 2 which uses Transform Feedback). + * + * @type {Array?} + */ this.attributes = attributes; + /** + * How often the programmable stage is currently in use. + * + * @type {Number} + * @default 0 + */ this.usedTimes = 0; } diff --git a/src/renderers/common/QuadMesh.js b/src/renderers/common/QuadMesh.js index 1274e4ba75276f..a0968c9fe975a0 100644 --- a/src/renderers/common/QuadMesh.js +++ b/src/renderers/common/QuadMesh.js @@ -3,14 +3,23 @@ import { Float32BufferAttribute } from '../../core/BufferAttribute.js'; import { Mesh } from '../../objects/Mesh.js'; import { OrthographicCamera } from '../../cameras/OrthographicCamera.js'; -// Helper for passes that need to fill the viewport with a single quad. - const _camera = /*@__PURE__*/ new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); -// https://github.com/mrdoob/three.js/pull/21358 - +/** + * The purpose of this special geometry is to fill the entire viewport with a single triangle. + * + * Reference: {@link https://github.com/mrdoob/three.js/pull/21358} + * + * @private + * @augments BufferGeometry + */ class QuadGeometry extends BufferGeometry { + /** + * Constructs a new quad geometry. + * + * @param {Boolean} [flipY=false] - Whether the uv coordinates should be flipped along the vertical axis or not. + */ constructor( flipY = false ) { super(); @@ -26,24 +35,64 @@ class QuadGeometry extends BufferGeometry { const _geometry = /*@__PURE__*/ new QuadGeometry(); + +/** + * This module is a helper for passes which need to render a full + * screen effect which is quite common in context of post processing. + * + * The intended usage is to reuse a single quad mesh for rendering + * subsequent passes by just reassigning the `material` reference. + * + * @augments BufferGeometry + */ class QuadMesh extends Mesh { + /** + * Constructs a new quad mesh. + * + * @param {Material?} [material=null] - The material to render the quad mesh with. + */ constructor( material = null ) { super( _geometry, material ); + /** + * The camera to render the quad mesh with. + * + * @type {OrthographicCamera} + * @readonly + */ this.camera = _camera; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isQuadMesh = true; } - renderAsync( renderer ) { + /** + * Async version of `render()`. + * + * @async + * @param {Renderer} renderer - The renderer. + * @return {Promise} A Promise that resolves when the render has been finished. + */ + async renderAsync( renderer ) { return renderer.renderAsync( this, _camera ); } + /** + * Renders the quad mesh + * + * @param {Renderer} renderer - The renderer. + */ render( renderer ) { renderer.render( this, _camera ); diff --git a/src/renderers/common/RenderBundle.js b/src/renderers/common/RenderBundle.js index e84c0ad0de8d5c..84598acb067dd2 100644 --- a/src/renderers/common/RenderBundle.js +++ b/src/renderers/common/RenderBundle.js @@ -1,18 +1,24 @@ +/** + * This module is used to represent render bundles inside the renderer + * for further processing. + * + * @private + */ class RenderBundle { - constructor( scene, camera ) { + /** + * Constructs a new bundle group. + * + * @param {BundleGroup} bundleGroup - The bundle group. + * @param {Camera} camera - The camera the bundle group is rendered with. + */ + constructor( bundleGroup, camera ) { - this.scene = scene; + this.bundleGroup = bundleGroup; this.camera = camera; } - clone() { - - return Object.assign( new this.constructor(), this ); - - } - } export default RenderBundle; diff --git a/src/renderers/common/RenderBundles.js b/src/renderers/common/RenderBundles.js index 66045184139de4..25f90a7261b4ab 100644 --- a/src/renderers/common/RenderBundles.js +++ b/src/renderers/common/RenderBundles.js @@ -1,35 +1,64 @@ import ChainMap from './ChainMap.js'; import RenderBundle from './RenderBundle.js'; +const _chainKeys = []; + +/** + * This renderer module manages render bundles. + * + * @private + */ class RenderBundles { + /** + * Constructs a new render bundle management component. + */ constructor() { - this.lists = new ChainMap(); + /** + * A chain map for maintaining the render bundles. + * + * @type {ChainMap} + */ + this.bundles = new ChainMap(); } - get( scene, camera ) { + /** + * Returns a render bundle for the given bundle group and camera. + * + * @param {BundleGroup} bundleGroup - The bundle group. + * @param {Camera} camera - The camera the bundle group is rendered with. + * @return {RenderBundle} The render bundle. + */ + get( bundleGroup, camera ) { + + const bundles = this.bundles; - const lists = this.lists; - const keys = [ scene, camera ]; + _chainKeys[ 0 ] = bundleGroup; + _chainKeys[ 1 ] = camera; - let list = lists.get( keys ); + let bundle = bundles.get( _chainKeys ); - if ( list === undefined ) { + if ( bundle === undefined ) { - list = new RenderBundle( scene, camera ); - lists.set( keys, list ); + bundle = new RenderBundle( bundleGroup, camera ); + bundles.set( _chainKeys, bundle ); } - return list; + _chainKeys.length = 0; + + return bundle; } + /** + * Frees all internal resources. + */ dispose() { - this.lists = new ChainMap(); + this.bundles = new ChainMap(); } diff --git a/src/renderers/common/RenderContext.js b/src/renderers/common/RenderContext.js index 1f1d543a5b1c3d..1acd7e0a5e4488 100644 --- a/src/renderers/common/RenderContext.js +++ b/src/renderers/common/RenderContext.js @@ -1,44 +1,227 @@ import { Vector4 } from '../../math/Vector4.js'; import { hashArray } from '../../nodes/core/NodeUtils.js'; -let id = 0; +let _id = 0; +/** + * Any render or compute command is executed in a specific context that defines + * the state of the renderer and its backend. Typical examples for such context + * data are the current clear values or data from the active framebuffer. This + * module is used to represent these contexts as objects. + * + * @private + */ class RenderContext { + /** + * Constructs a new render context. + */ constructor() { - this.id = id ++; + /** + * The context's ID. + * + * @type {Number} + */ + this.id = _id ++; + /** + * Whether the current active framebuffer has a color attachment. + * + * @type {Boolean} + * @default true + */ this.color = true; + + /** + * Whether the color attachment should be cleared or not. + * + * @type {Boolean} + * @default true + */ this.clearColor = true; + + /** + * The clear color value. + * + * @type {Object} + * @default true + */ this.clearColorValue = { r: 0, g: 0, b: 0, a: 1 }; + /** + * Whether the current active framebuffer has a depth attachment. + * + * @type {Boolean} + * @default true + */ this.depth = true; + + /** + * Whether the depth attachment should be cleared or not. + * + * @type {Boolean} + * @default true + */ this.clearDepth = true; + + /** + * The clear depth value. + * + * @type {Number} + * @default 1 + */ this.clearDepthValue = 1; + /** + * Whether the current active framebuffer has a stencil attachment. + * + * @type {Boolean} + * @default false + */ this.stencil = false; + + /** + * Whether the stencil attachment should be cleared or not. + * + * @type {Boolean} + * @default true + */ this.clearStencil = true; + + /** + * The clear stencil value. + * + * @type {Number} + * @default 1 + */ this.clearStencilValue = 1; + /** + * By default the viewport encloses the entire framebuffer If a smaller + * viewport is manually defined, this property is to `true` by the renderer. + * + * @type {Boolean} + * @default false + */ this.viewport = false; + + /** + * The viewport value. This value is in physical pixels meaning it incorporates + * the renderer's pixel ratio. The viewport property of render targets or + * the renderer is in logical pixels. + * + * @type {Vector4} + */ this.viewportValue = new Vector4(); + /** + * When the scissor test is active and scissor rectangle smaller than the + * framebuffers dimensions, this property is to `true` by the renderer. + * + * @type {Boolean} + * @default false + */ this.scissor = false; + + /** + * The scissor rectangle. + * + * @type {Vector4} + */ this.scissorValue = new Vector4(); + /** + * The active render target. + * + * @type {RenderTarget?} + * @default null + */ + this.renderTarget = null; + + /** + * The textures of the active render target. + * `null` when no render target is set. + * + * @type {Array?} + * @default null + */ this.textures = null; + + /** + * The depth texture of the active render target. + * `null` when no render target is set. + * + * @type {DepthTexture?} + * @default null + */ this.depthTexture = null; + + /** + * The active cube face. + * + * @type {Number} + * @default 0 + */ this.activeCubeFace = 0; + + /** + * The number of MSAA samples. This value is always `1` when + * MSAA isn't used. + * + * @type {Number} + * @default 1 + */ this.sampleCount = 1; + /** + * The active render target's width in physical pixels. + * + * @type {Number} + * @default 0 + */ this.width = 0; + + /** + * The active render target's height in physical pixels. + * + * @type {Number} + * @default 0 + */ this.height = 0; + /** + * The occlusion query count. + * + * @type {Number} + * @default 0 + */ + this.occlusionQueryCount = 0; + + /** + * The current clipping context. + * + * @type {ClippingContext?} + * @default null + */ + this.clippingContext = null; + + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isRenderContext = true; } + /** + * Returns the cache key of this render context. + * + * @return {Number} The cache key. + */ getCacheKey() { return getCacheKey( this ); @@ -47,6 +230,14 @@ class RenderContext { } +/** + * Computes a cache key for the given render context. This cache + * should identify the render target state so it is possible to + * configure the correct attachments in the respective backend. + * + * @param {RenderContext} renderContext - The render context. + * @return {Number} The cache key. + */ export function getCacheKey( renderContext ) { const { textures, activeCubeFace } = renderContext; diff --git a/src/renderers/common/RenderContexts.js b/src/renderers/common/RenderContexts.js index cdbfc8c26d8100..8a6e2467873217 100644 --- a/src/renderers/common/RenderContexts.js +++ b/src/renderers/common/RenderContexts.js @@ -1,17 +1,46 @@ import ChainMap from './ChainMap.js'; import RenderContext from './RenderContext.js'; - +import { Scene } from '../../scenes/Scene.js'; +import { Camera } from '../../cameras/Camera.js'; + +const _chainKeys = []; +const _defaultScene = /*@__PURE__*/ new Scene(); +const _defaultCamera = /*@__PURE__*/ new Camera(); + +/** + * This module manages the render contexts of the renderer. + * + * @private + */ class RenderContexts { + /** + * Constructs a new render context management component. + */ constructor() { + /** + * A dictionary that manages render contexts in chain maps + * for each attachment state. + * + * @type {Object} + */ this.chainMaps = {}; } + /** + * Returns a render context for the given scene, camera and render target. + * + * @param {Scene} scene - The scene. + * @param {Camera} camera - The camera that is used to render the scene. + * @param {RenderTarget?} [renderTarget=null] - The active render target. + * @return {RenderContext} The render context. + */ get( scene, camera, renderTarget = null ) { - const chainKey = [ scene, camera ]; + _chainKeys[ 0 ] = scene; + _chainKeys[ 1 ] = camera; let attachmentState; @@ -28,30 +57,54 @@ class RenderContexts { } - const chainMap = this.getChainMap( attachmentState ); + const chainMap = this._getChainMap( attachmentState ); - let renderState = chainMap.get( chainKey ); + let renderState = chainMap.get( _chainKeys ); if ( renderState === undefined ) { renderState = new RenderContext(); - chainMap.set( chainKey, renderState ); + chainMap.set( _chainKeys, renderState ); } + _chainKeys.length = 0; + if ( renderTarget !== null ) renderState.sampleCount = renderTarget.samples === 0 ? 1 : renderTarget.samples; return renderState; } - getChainMap( attachmentState ) { + /** + * Returns a render context intended for clear operations. + * + * @param {RenderTarget?} [renderTarget=null] - The active render target. + * @return {RenderContext} The render context. + */ + getForClear( renderTarget = null ) { + + return this.get( _defaultScene, _defaultCamera, renderTarget ); + + } + + /** + * Returns a chain map for the given attachment state. + * + * @private + * @param {String} attachmentState - The attachment state. + * @return {ChainMap} The chain map. + */ + _getChainMap( attachmentState ) { return this.chainMaps[ attachmentState ] || ( this.chainMaps[ attachmentState ] = new ChainMap() ); } + /** + * Frees internal resources. + */ dispose() { this.chainMaps = {}; diff --git a/src/renderers/common/RenderList.js b/src/renderers/common/RenderList.js index d819ee90bbb4c2..59412530bba172 100644 --- a/src/renderers/common/RenderList.js +++ b/src/renderers/common/RenderList.js @@ -1,5 +1,14 @@ import { DoubleSide } from '../../constants.js'; +/** + * Default sorting function for opaque render items. + * + * @private + * @function + * @param {Object} a - The first render item. + * @param {Object} b - The second render item. + * @return {Number} A numeric value which defines the sort order. + */ function painterSortStable( a, b ) { if ( a.groupOrder !== b.groupOrder ) { @@ -26,6 +35,15 @@ function painterSortStable( a, b ) { } +/** + * Default sorting function for transparent render items. + * + * @private + * @function + * @param {Object} a - The first render item. + * @param {Object} b - The second render item. + * @return {Number} A numeric value which defines the sort order. + */ function reversePainterSortStable( a, b ) { if ( a.groupOrder !== b.groupOrder ) { @@ -48,6 +66,14 @@ function reversePainterSortStable( a, b ) { } +/** + * Returns `true` if the given transparent material requires a double pass. + * + * @private + * @function + * @param {Material} material - The transparent material. + * @return {Boolean} Whether the given material requires a double pass or not. + */ function needsDoublePass( material ) { const hasTransmission = material.transmission > 0 || material.transmissionNode; @@ -56,28 +82,120 @@ function needsDoublePass( material ) { } +/** + * When the renderer analyzes the scene at the beginning of a render call, + * it stores 3D object for further processing in render lists. Depending on the + * properties of a 3D objects (like their transformation or material state), the + * objects are maintained in ordered lists for the actual rendering. + * + * Render lists are unique per scene and camera combination. + * + * @private + * @augments Pipeline + */ class RenderList { + /** + * Constructs a render list. + * + * @param {Lighting} lighting - The lighting management component. + * @param {Scene} scene - The scene. + * @param {Camera} camera - The camera the scene is rendered with. + */ constructor( lighting, scene, camera ) { + /** + * 3D objects are transformed into render items and stored in this array. + * + * @type {Array} + */ this.renderItems = []; + + /** + * The current render items index. + * + * @type {Number} + * @default 0 + */ this.renderItemsIndex = 0; + /** + * A list with opaque render items. + * + * @type {Array} + */ this.opaque = []; + + /** + * A list with transparent render items which require + * double pass rendering (e.g. transmissive objects). + * + * @type {Array} + */ this.transparentDoublePass = []; + + /** + * A list with transparent render items. + * + * @type {Array} + */ this.transparent = []; + + /** + * A list with transparent render bundle data. + * + * @type {Array} + */ this.bundles = []; + /** + * The render list's lights node. This node is later + * relevant for the actual analytical light nodes which + * compute the scene's lighting in the shader. + * + * @type {LightsNode} + */ this.lightsNode = lighting.getNode( scene, camera ); + + /** + * The scene's lights stored in an array. This array + * is used to setup the lights node. + * + * @type {Array} + */ this.lightsArray = []; + /** + * The scene. + * + * @type {Scene} + */ this.scene = scene; + + /** + * The camera the scene is rendered with. + * + * @type {Camera} + */ this.camera = camera; + /** + * How many objects perform occlusion query tests. + * + * @type {Number} + * @default 0 + */ this.occlusionQueryCount = 0; } + /** + * This method is called right at the beginning of a render call + * before the scene is analyzed. It prepares the internal data + * structures for the upcoming render lists generation. + * + * @return {RenderList} A reference to this render list. + */ begin() { this.renderItemsIndex = 0; @@ -95,6 +213,22 @@ class RenderList { } + /** + * Returns a render item for the giving render item state. The state is defined + * by a series of object-related parameters. + * + * The method avoids object creation by holding render items and reusing them in + * subsequent render calls (just with different property values). + * + * @param {Object3D} object - The 3D object. + * @param {BufferGeometry} geometry - The 3D object's geometry. + * @param {Material} material - The 3D object's material. + * @param {Number} groupOrder - The current group order. + * @param {Number} z - Th 3D object's depth value (z value in clip space). + * @param {Number?} group - {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`. + * @param {ClippingContext} clippingContext - The current clipping context. + * @return {Object} The render item. + */ getNextRenderItem( object, geometry, material, groupOrder, z, group, clippingContext ) { let renderItem = this.renderItems[ this.renderItemsIndex ]; @@ -135,6 +269,18 @@ class RenderList { } + /** + * Pushes the given object as a render item to the internal render lists. + * The selected lists depend on the object properties. + * + * @param {Object3D} object - The 3D object. + * @param {BufferGeometry} geometry - The 3D object's geometry. + * @param {Material} material - The 3D object's material. + * @param {Number} groupOrder - The current group order. + * @param {Number} z - Th 3D object's depth value (z value in clip space). + * @param {Number?} group - {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`. + * @param {ClippingContext} clippingContext - The current clipping context. + */ push( object, geometry, material, groupOrder, z, group, clippingContext ) { const renderItem = this.getNextRenderItem( object, geometry, material, groupOrder, z, group, clippingContext ); @@ -155,6 +301,18 @@ class RenderList { } + /** + * Inserts the given object as a render item at the start of the internal render lists. + * The selected lists depend on the object properties. + * + * @param {Object3D} object - The 3D object. + * @param {BufferGeometry} geometry - The 3D object's geometry. + * @param {Material} material - The 3D object's material. + * @param {Number} groupOrder - The current group order. + * @param {Number} z - Th 3D object's depth value (z value in clip space). + * @param {Number?} group - {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`. + * @param {ClippingContext} clippingContext - The current clipping context. + */ unshift( object, geometry, material, groupOrder, z, group, clippingContext ) { const renderItem = this.getNextRenderItem( object, geometry, material, groupOrder, z, group, clippingContext ); @@ -173,18 +331,34 @@ class RenderList { } + /** + * Pushes render bundle group data into the render list. + * + * @param {Object} group - Bundle group data. + */ pushBundle( group ) { this.bundles.push( group ); } + /** + * Pushes a light into the render list. + * + * @param {Light} light - The light. + */ pushLight( light ) { this.lightsArray.push( light ); } + /** + * Sorts the internal render lists. + * + * @param {Function} customOpaqueSort - A custom sort function for opaque objects. + * @param {Function} customTransparentSort - A custom sort function for transparent objects. + */ sort( customOpaqueSort, customTransparentSort ) { if ( this.opaque.length > 1 ) this.opaque.sort( customOpaqueSort || painterSortStable ); @@ -193,6 +367,10 @@ class RenderList { } + /** + * This method performs finalizing tasks right after the render lists + * have been generated. + */ finish() { // update lights diff --git a/src/renderers/common/RenderLists.js b/src/renderers/common/RenderLists.js index 60cb94c30f2a81..1818d25e0156a6 100644 --- a/src/renderers/common/RenderLists.js +++ b/src/renderers/common/RenderLists.js @@ -1,34 +1,71 @@ import ChainMap from './ChainMap.js'; import RenderList from './RenderList.js'; +const _chainKeys = []; + +/** + * This renderer module manages the render lists which are unique + * per scene and camera combination. + * + * @private + */ class RenderLists { + /** + * Constructs a render lists management component. + * + * @param {Lighting} lighting - The lighting management component. + */ constructor( lighting ) { + /** + * The lighting management component. + * + * @type {Lighting} + */ this.lighting = lighting; + /** + * The internal chain map which holds the render lists. + * + * @type {ChainMap} + */ this.lists = new ChainMap(); } + /** + * Returns a render list for the given scene and camera. + * + * @param {Scene} scene - The scene. + * @param {Camera} camera - The camera. + * @return {RenderList} The render list. + */ get( scene, camera ) { const lists = this.lists; - const keys = [ scene, camera ]; - let list = lists.get( keys ); + _chainKeys[ 0 ] = scene; + _chainKeys[ 1 ] = camera; + + let list = lists.get( _chainKeys ); if ( list === undefined ) { list = new RenderList( this.lighting, scene, camera ); - lists.set( keys, list ); + lists.set( _chainKeys, list ); } + _chainKeys.length = 0; + return list; } + /** + * Frees all internal resources. + */ dispose() { this.lists = new ChainMap(); diff --git a/src/renderers/common/RenderObject.js b/src/renderers/common/RenderObject.js index 50daed6be71425..a95347e88335da 100644 --- a/src/renderers/common/RenderObject.js +++ b/src/renderers/common/RenderObject.js @@ -36,49 +36,254 @@ function getKeys( obj ) { } -export default class RenderObject { - +/** + * A render object is the renderer's representation of single entity that gets drawn + * with a draw command. There is no unique mapping of render objects to 3D objects in the + * scene since render objects also depend from the used material, the current render context + * and the current scene's lighting. + * + * In general, the basic process of the renderer is: + * + * - Analyze the 3D objects in the scene and generate render lists containing render items. + * - Process the render lists by calling one or more render commands for each render item. + * - For each render command, request a render object and perform the draw. + * + * The module provides an interface to get data required for the draw command like the actual + * draw parameters or vertex buffers. It also holds a series of caching related methods since + * creating render objects should only be done when necessary. + * + * @private + */ +class RenderObject { + + /** + * Constructs a new render object. + * + * @param {Nodes} nodes - Renderer component for managing nodes related logic. + * @param {Geometries} geometries - Renderer component for managing geometries. + * @param {Renderer} renderer - The renderer. + * @param {Object3D} object - The 3D object. + * @param {Material} material - The 3D object's material. + * @param {Scene} scene - The scene the 3D object belongs to. + * @param {Camera} camera - The camera the object should be rendered with. + * @param {LightsNode} lightsNode - The lights node. + * @param {RenderContext} renderContext - The render context. + * @param {ClippingContext} clippingContext - The clipping context. + */ constructor( nodes, geometries, renderer, object, material, scene, camera, lightsNode, renderContext, clippingContext ) { + this.id = _id ++; + + /** + * Renderer component for managing nodes related logic. + * + * @type {Nodes} + * @private + */ this._nodes = nodes; - this._geometries = geometries; - this.id = _id ++; + /** + * Renderer component for managing geometries. + * + * @type {Geometries} + * @private + */ + this._geometries = geometries; + /** + * The renderer. + * + * @type {Renderer} + */ this.renderer = renderer; + + /** + * The 3D object. + * + * @type {Object3D} + */ this.object = object; + + /** + * The 3D object's material. + * + * @type {Material} + */ this.material = material; + + /** + * The scene the 3D object belongs to. + * + * @type {Scene} + */ this.scene = scene; + + /** + * The camera the 3D object should be rendered with. + * + * @type {Camera} + */ this.camera = camera; + + /** + * The lights node. + * + * @type {LightsNode} + */ this.lightsNode = lightsNode; + + /** + * The render context. + * + * @type {RenderContext} + */ this.context = renderContext; + /** + * The 3D object's geometry. + * + * @type {BufferGeometry} + */ this.geometry = object.geometry; + + /** + * The render object's version. + * + * @type {Number} + */ this.version = material.version; + /** + * The draw range of the geometry. + * + * @type {Object?} + * @default null + */ this.drawRange = null; + /** + * An array holding the buffer attributes + * of the render object. This entails attribute + * definitions on geometry and node level. + * + * @type {Array?} + * @default null + */ this.attributes = null; + + /** + * A reference to a render pipeline the render + * object is processed with. + * + * @type {RenderPipeline} + * @default null + */ this.pipeline = null; + + /** + * An array holding the vertex buffers which can + * be buffer attributes but also interleaved buffers. + * + * @type {Array?} + * @default null + */ this.vertexBuffers = null; + + /** + * The parameters for the draw command. + * + * @type {Object?} + * @default null + */ this.drawParams = null; + /** + * If this render object is used inside a render bundle, + * this property points to the respective bundle group. + * + * @type {BundleGroup?} + * @default null + */ this.bundle = null; + /** + * The clipping context. + * + * @type {ClippingContext} + */ this.clippingContext = clippingContext; + + /** + * The clipping context's cache key. + * + * @type {String} + */ this.clippingContextCacheKey = clippingContext !== null ? clippingContext.cacheKey : ''; + /** + * The initial node cache key. + * + * @type {Number} + */ this.initialNodesCacheKey = this.getDynamicCacheKey(); + + /** + * The initial cache key. + * + * @type {Number} + */ this.initialCacheKey = this.getCacheKey(); + /** + * The node builder state. + * + * @type {NodeBuilderState?} + * @private + * @default null + */ this._nodeBuilderState = null; + + /** + * An array of bindings. + * + * @type {Array?} + * @private + * @default null + */ this._bindings = null; + + /** + * Reference to the node material observer. + * + * @type {NodeMaterialObserver?} + * @private + * @default null + */ this._monitor = null; + /** + * An event listener which is defined by `RenderObjects`. It performs + * clean up tasks when `dispose()` on this render object. + * + * @method + */ this.onDispose = null; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isRenderObject = true; + /** + * An event listener which is executed when `dispose()` is called on + * the render object's material. + * + * @method + */ this.onMaterialDispose = () => { this.dispose(); @@ -89,12 +294,23 @@ export default class RenderObject { } - updateClipping( parent ) { + /** + * Updates the clipping context. + * + * @param {ClippingContext} context - The clipping context to set. + */ + updateClipping( context ) { - this.clippingContext = parent; + this.clippingContext = context; } + /** + * Whether the clipping requires an update or not. + * + * @type {Boolean} + * @readonly + */ get clippingNeedsUpdate() { if ( this.clippingContext === null || this.clippingContext.cacheKey === this.clippingContextCacheKey ) return false; @@ -105,48 +321,90 @@ export default class RenderObject { } + /** + * The number of clipping planes defined in context of hardware clipping. + * + * @type {Number} + * @readonly + */ get hardwareClippingPlanes() { return this.material.hardwareClipping === true ? this.clippingContext.unionClippingCount : 0; } + /** + * Returns the node builder state of this render object. + * + * @return {NodeBuilderState} The node builder state. + */ getNodeBuilderState() { return this._nodeBuilderState || ( this._nodeBuilderState = this._nodes.getForRender( this ) ); } + /** + * Returns the node material observer of this render object. + * + * @return {NodeMaterialObserver} The node material observer. + */ getMonitor() { return this._monitor || ( this._monitor = this.getNodeBuilderState().monitor ); } + /** + * Returns an array of bind groups of this render object. + * + * @return {Array} The bindings. + */ getBindings() { return this._bindings || ( this._bindings = this.getNodeBuilderState().createBindings() ); } + /** + * Returns the index of the render object's geometry. + * + * @return {BufferAttribute?} The index. Returns `null` for non-indexed geometries. + */ getIndex() { return this._geometries.getIndex( this ); } + /** + * Returns the indirect buffer attribute. + * + * @return {BufferAttribute?} The indirect attribute. `null` if no indirect drawing is used. + */ getIndirect() { return this._geometries.getIndirect( this ); } + /** + * Returns an array that acts as a key for identifying the render object in a chain map. + * + * @return {Array} An array with object references. + */ getChainArray() { return [ this.object, this.material, this.context, this.lightsNode ]; } + /** + * This method is used when the geometry of a 3D object has been exchanged and the + * respective render object now requires an update. + * + * @param {BufferGeometry} geometry - The geometry to set. + */ setGeometry( geometry ) { this.geometry = geometry; @@ -154,6 +412,12 @@ export default class RenderObject { } + /** + * Returns the buffer attributes of the render object. The returned array holds + * attribute definitions on geometry and node level. + * + * @return {Array} An array with buffer attributes. + */ getAttributes() { if ( this.attributes !== null ) return this.attributes; @@ -184,6 +448,11 @@ export default class RenderObject { } + /** + * Returns the vertex buffers of the render object. + * + * @return {Array} An array with buffer attribute or interleaved buffers. + */ getVertexBuffers() { if ( this.vertexBuffers === null ) this.getAttributes(); @@ -192,6 +461,11 @@ export default class RenderObject { } + /** + * Returns the draw parameters for the render object. + * + * @return {{vertexCount: Number, firstVertex: Number, instanceCount: Number, firstInstance: Number}} The draw parameters. + */ getDrawParameters() { const { object, material, geometry, group, drawRange } = this; @@ -258,6 +532,13 @@ export default class RenderObject { } + /** + * Returns the render object's geometry cache key. + * + * The geometry cache key is part of the material cache key. + * + * @return {String} The geometry cache key. + */ getGeometryCacheKey() { const { geometry } = this; @@ -287,6 +568,13 @@ export default class RenderObject { } + /** + * Returns the render object's material cache key. + * + * The material cache key is part of the render object cache key. + * + * @return {String} The material cache key. + */ getMaterialCacheKey() { const { object, material } = this; @@ -385,18 +673,46 @@ export default class RenderObject { } + /** + * Whether the geometry requires an update or not. + * + * @type {Boolean} + * @readonly + */ get needsGeometryUpdate() { return this.geometry.id !== this.object.geometry.id; } + /** + * Whether the render object requires an update or not. + * + * Note: There are two distinct places where render objects are checked for an update. + * + * 1. In `RenderObjects.get()` which is executed when the render object is request. This + * method checks the `needsUpdate` flag and recreates the render object if necessary. + * 2. In `Renderer._renderObjectDirect()` right after getting the render object via + * `RenderObjects.get()`. The render object's NodeMaterialObserver is then used to detect + * a need for a refresh due to material, geometry or object related value changes. + * + * TODO: Investigate if it's possible to merge both steps so there is only a single place + * that performs the 'needsUpdate' check. + * + * @type {Boolean} + * @readonly + */ get needsUpdate() { return /*this.object.static !== true &&*/ ( this.initialNodesCacheKey !== this.getDynamicCacheKey() || this.clippingNeedsUpdate ); } + /** + * Returns the dynamic cache key which represents a key that is computed per draw command. + * + * @return {String} The cache key. + */ getDynamicCacheKey() { // Environment Nodes Cache Key @@ -413,12 +729,20 @@ export default class RenderObject { } + /** + * Returns the render object's cache key. + * + * @return {String} The cache key. + */ getCacheKey() { return this.getMaterialCacheKey() + this.getDynamicCacheKey(); } + /** + * Frees internal resources. + */ dispose() { this.material.removeEventListener( 'dispose', this.onMaterialDispose ); @@ -428,3 +752,5 @@ export default class RenderObject { } } + +export default RenderObject; diff --git a/src/renderers/common/RenderObjects.js b/src/renderers/common/RenderObjects.js index 63c1f3a54cf8ec..b9ffe747681f2a 100644 --- a/src/renderers/common/RenderObjects.js +++ b/src/renderers/common/RenderObjects.js @@ -1,40 +1,109 @@ import ChainMap from './ChainMap.js'; import RenderObject from './RenderObject.js'; -const chainArray = []; +const _chainKeys = []; +/** + * This module manages the render objects of the renderer. + * + * @private + */ class RenderObjects { + /** + * Constructs a new render object management component. + * + * @param {Renderer} renderer - The renderer. + * @param {Nodes} nodes - Renderer component for managing nodes related logic. + * @param {Geometries} geometries - Renderer component for managing geometries. + * @param {Pipelines} pipelines - Renderer component for managing pipelines. + * @param {Bindings} bindings - Renderer component for managing bindings. + * @param {Info} info - Renderer component for managing metrics and monitoring data. + */ constructor( renderer, nodes, geometries, pipelines, bindings, info ) { + /** + * The renderer. + * + * @type {Renderer} + */ this.renderer = renderer; + + /** + * Renderer component for managing nodes related logic. + * + * @type {Nodes} + */ this.nodes = nodes; + + /** + * Renderer component for managing geometries. + * + * @type {Geometries} + */ this.geometries = geometries; + + /** + * Renderer component for managing pipelines. + * + * @type {Pipelines} + */ this.pipelines = pipelines; + + /** + * Renderer component for managing bindings. + * + * @type {Bindings} + */ this.bindings = bindings; + + /** + * Renderer component for managing metrics and monitoring data. + * + * @type {Info} + */ this.info = info; + /** + * A dictionary that manages render contexts in chain maps + * for each pass ID. + * + * @type {Object} + */ this.chainMaps = {}; } + /** + * Returns a render object for the given object and state data. + * + * @param {Object3D} object - The 3D object. + * @param {Material} material - The 3D object's material. + * @param {Scene} scene - The scene the 3D object belongs to. + * @param {Camera} camera - The camera the 3D object should be rendered with. + * @param {LightsNode} lightsNode - The lights node. + * @param {RenderContext} renderContext - The render context. + * @param {ClippingContext} clippingContext - The clipping context. + * @param {String?} passId - An optional ID for identifying the pass. + * @return {RenderObject} The render object. + */ get( object, material, scene, camera, lightsNode, renderContext, clippingContext, passId ) { const chainMap = this.getChainMap( passId ); // reuse chainArray - chainArray[ 0 ] = object; - chainArray[ 1 ] = material; - chainArray[ 2 ] = renderContext; - chainArray[ 3 ] = lightsNode; + _chainKeys[ 0 ] = object; + _chainKeys[ 1 ] = material; + _chainKeys[ 2 ] = renderContext; + _chainKeys[ 3 ] = lightsNode; - let renderObject = chainMap.get( chainArray ); + let renderObject = chainMap.get( _chainKeys ); if ( renderObject === undefined ) { renderObject = this.createRenderObject( this.nodes, this.geometries, this.renderer, object, material, scene, camera, lightsNode, renderContext, clippingContext, passId ); - chainMap.set( chainArray, renderObject ); + chainMap.set( _chainKeys, renderObject ); } else { @@ -64,22 +133,49 @@ class RenderObjects { } + _chainKeys.length = 0; + return renderObject; } + /** + * Returns a chain map for the given pass ID. + * + * @param {String} [passId='default'] - The pass ID. + * @return {ChainMap} The chain map. + */ getChainMap( passId = 'default' ) { return this.chainMaps[ passId ] || ( this.chainMaps[ passId ] = new ChainMap() ); } + /** + * Frees internal resources. + */ dispose() { this.chainMaps = {}; } + /** + * Factory method for creating render objects with the given list of parameters. + * + * @param {Nodes} nodes - Renderer component for managing nodes related logic. + * @param {Geometries} geometries - Renderer component for managing geometries. + * @param {Renderer} renderer - The renderer. + * @param {Object3D} object - The 3D object. + * @param {Material} material - The object's material. + * @param {Scene} scene - The scene the 3D object belongs to. + * @param {Camera} camera - The camera the object should be rendered with. + * @param {LightsNode} lightsNode - The lights node. + * @param {RenderContext} renderContext - The render context. + * @param {ClippingContext} clippingContext - The clipping context. + * @param {String?} passId - An optional ID for identifying the pass. + * @return {RenderObject} The render object. + */ createRenderObject( nodes, geometries, renderer, object, material, scene, camera, lightsNode, renderContext, clippingContext, passId ) { const chainMap = this.getChainMap( passId ); diff --git a/src/renderers/common/RenderPipeline.js b/src/renderers/common/RenderPipeline.js index d9aeadda798322..bcc91a22b5c2fa 100644 --- a/src/renderers/common/RenderPipeline.js +++ b/src/renderers/common/RenderPipeline.js @@ -1,12 +1,36 @@ import Pipeline from './Pipeline.js'; +/** + * Class for representing render pipelines. + * + * @private + * @augments Pipeline + */ class RenderPipeline extends Pipeline { + /** + * Constructs a new render pipeline. + * + * @param {String} cacheKey - The pipeline's cache key. + * @param {ProgrammableStage} vertexProgram - The pipeline's vertex shader. + * @param {ProgrammableStage} fragmentProgram - The pipeline's fragment shader. + */ constructor( cacheKey, vertexProgram, fragmentProgram ) { super( cacheKey ); + /** + * The pipeline's vertex shader. + * + * @type {ProgrammableStage} + */ this.vertexProgram = vertexProgram; + + /** + * The pipeline's fragment shader. + * + * @type {ProgrammableStage} + */ this.fragmentProgram = fragmentProgram; } diff --git a/src/renderers/common/Renderer.js b/src/renderers/common/Renderer.js index 140074613b420a..4ee820a607543d 100644 --- a/src/renderers/common/Renderer.js +++ b/src/renderers/common/Renderer.js @@ -27,6 +27,8 @@ import { Vector4 } from '../../math/Vector4.js'; import { RenderTarget } from '../../core/RenderTarget.js'; import { DoubleSide, BackSide, FrontSide, SRGBColorSpace, NoToneMapping, LinearFilter, LinearSRGBColorSpace, HalfFloatType, RGBAFormat, PCFShadowMap } from '../../constants.js'; +/** @module Renderer **/ + const _scene = /*@__PURE__*/ new Scene(); const _drawingBufferSize = /*@__PURE__*/ new Vector2(); const _screen = /*@__PURE__*/ new Vector4(); @@ -34,10 +36,34 @@ const _frustum = /*@__PURE__*/ new Frustum(); const _projScreenMatrix = /*@__PURE__*/ new Matrix4(); const _vector4 = /*@__PURE__*/ new Vector4(); +/** + * Base class for renderers. + */ class Renderer { + /** + * Constructs a new renderer. + * + * @param {Backend} backend - The backend the renderer is targeting (e.g. WebGPU or WebGL 2). + * @param {Object} parameters - The configuration parameter. + * @param {Boolean} [parameters.logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not. + * @param {Boolean} [parameters.alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque. + * @param {Boolean} [parameters.depth=true] - Whether the default framebuffer should have a depth buffer or not. + * @param {Boolean} [parameters.stencil=false] - Whether the default framebuffer should have a stencil buffer or not. + * @param {Boolean} [parameters.antialias=false] - Whether MSAA as the default anti-aliasing should be enabled or not. + * @param {Number} [parameters.samples=0] - When `antialias` is `true`, `4` samples are used by default. This parameter can set to any other integer value than 0 + * to overwrite the default. + * @param {Function?} [parameters.getFallback=null] - This callback function can be used to provide a fallback backend, if the primary backend can't be targeted. + */ constructor( backend, parameters = {} ) { + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isRenderer = true; // @@ -52,32 +78,142 @@ class Renderer { getFallback = null } = parameters; - // public + /** + * A reference to the canvas element the renderer is drawing to. + * This value of this property will automatically be created by + * the renderer. + * + * @type {HTMLCanvasElement|OffscreenCanvas} + */ this.domElement = backend.getDomElement(); + /** + * A reference to the current backend. + * + * @type {Backend} + */ this.backend = backend; + /** + * The number of MSAA samples. + * + * @type {Number} + * @default 0 + */ this.samples = samples || ( antialias === true ) ? 4 : 0; + /** + * Whether the renderer should automatically clear the current rendering target + * before execute a `render()` call. The target can be the canvas (default framebuffer) + * or the current bound render target (custom framebuffer). + * + * @type {Boolean} + * @default true + */ this.autoClear = true; + + /** + * When `autoClear` is set to `true`, this property defines whether the renderer + * should clear the color buffer. + * + * @type {Boolean} + * @default true + */ this.autoClearColor = true; + + /** + * When `autoClear` is set to `true`, this property defines whether the renderer + * should clear the depth buffer. + * + * @type {Boolean} + * @default true + */ this.autoClearDepth = true; + + /** + * When `autoClear` is set to `true`, this property defines whether the renderer + * should clear the stencil buffer. + * + * @type {Boolean} + * @default true + */ this.autoClearStencil = true; + /** + * Whether the default framebuffer should be transparent or opaque. + * + * @type {Boolean} + * @default true + */ this.alpha = alpha; + /** + * Whether logarithmic depth buffer is enabled or not. + * + * @type {Boolean} + * @default false + */ this.logarithmicDepthBuffer = logarithmicDepthBuffer; + /** + * Defines the output color space of the renderer. + * + * @type {String} + * @default SRGBColorSpace + */ this.outputColorSpace = SRGBColorSpace; + /** + * Defines the tone mapping of the renderer. + * + * @type {Number} + * @default NoToneMapping + */ this.toneMapping = NoToneMapping; + + /** + * Defines the tone mapping exposure. + * + * @type {Number} + * @default 1 + */ this.toneMappingExposure = 1.0; + /** + * Whether the renderer should sort its render lists or not. + * + * Note: Sorting is used to attempt to properly render objects that have some degree of transparency. + * By definition, sorting objects may not work in all cases. Depending on the needs of application, + * it may be necessary to turn off sorting and use other methods to deal with transparency rendering + * e.g. manually determining each object's rendering order. + * + * @type {Boolean} + * @default true + */ this.sortObjects = true; + /** + * Whether the default framebuffer should have a depth buffer or not. + * + * @type {Boolean} + * @default true + */ this.depth = depth; + + /** + * Whether the default framebuffer should have a stencil buffer or not. + * + * @type {Boolean} + * @default false + */ this.stencil = stencil; + /** + * Holds a series of statistical information about the GPU memory + * and the rendering process. Useful for debugging and monitoring. + * + * @type {Boolean} + */ this.info = new Info(); this.nodes = { @@ -85,82 +221,449 @@ class Renderer { modelNormalViewMatrix: null }; + /** + * The node library defines how certain library objects like materials, lights + * or tone mapping functions are mapped to node types. This is required since + * although instances of classes like `MeshBasicMaterial` or `PointLight` can + * be part of the scene graph, they are internally represented as nodes for + * further processing. + * + * @type {NodeLibrary} + */ this.library = new NodeLibrary(); + + /** + * A map-like data structure for managing lights. + * + * @type {Lighting} + */ this.lighting = new Lighting(); // internals + /** + * This callback function can be used to provide a fallback backend, if the primary backend can't be targeted. + * + * @private + * @type {Function} + */ this._getFallback = getFallback; + /** + * The renderer's pixel ration. + * + * @private + * @type {Number} + * @default 1 + */ this._pixelRatio = 1; + + /** + * The width of the renderer's default framebuffer in logical pixel unit. + * + * @private + * @type {Number} + */ this._width = this.domElement.width; + + /** + * The height of the renderer's default framebuffer in logical pixel unit. + * + * @private + * @type {Number} + */ this._height = this.domElement.height; + /** + * The viewport of the renderer in logical pixel unit. + * + * @private + * @type {Vector4} + */ this._viewport = new Vector4( 0, 0, this._width, this._height ); + + /** + * The scissor rectangle of the renderer in logical pixel unit. + * + * @private + * @type {Vector4} + */ this._scissor = new Vector4( 0, 0, this._width, this._height ); + + /** + * Whether the scissor test should be enabled or not. + * + * @private + * @type {Vector4} + */ this._scissorTest = false; + /** + * A reference to a renderer module for managing shader attributes. + * + * @private + * @type {Attributes?} + * @default null + */ this._attributes = null; + + /** + * A reference to a renderer module for managing geometries. + * + * @private + * @type {Geometries?} + * @default null + */ this._geometries = null; + + /** + * A reference to a renderer module for managing node related logic. + * + * @private + * @type {Nodes?} + * @default null + */ this._nodes = null; + + /** + * A reference to a renderer module for managing the internal animation loop. + * + * @private + * @type {Animation?} + * @default null + */ this._animation = null; + + /** + * A reference to a renderer module for managing shader program bindings. + * + * @private + * @type {Bindings?} + * @default null + */ this._bindings = null; + + /** + * A reference to a renderer module for managing render objects. + * + * @private + * @type {RenderObjects?} + * @default null + */ this._objects = null; + + /** + * A reference to a renderer module for managing render and compute pipelines. + * + * @private + * @type {Pipelines?} + * @default null + */ this._pipelines = null; + + /** + * A reference to a renderer module for managing render bundles. + * + * @private + * @type {RenderBundles?} + * @default null + */ this._bundles = null; + + /** + * A reference to a renderer module for managing render lists. + * + * @private + * @type {RenderLists?} + * @default null + */ this._renderLists = null; + + /** + * A reference to a renderer module for managing render contexts. + * + * @private + * @type {RenderContexts?} + * @default null + */ this._renderContexts = null; + + /** + * A reference to a renderer module for managing textures. + * + * @private + * @type {Textures?} + * @default null + */ this._textures = null; + + /** + * A reference to a renderer module for backgrounds. + * + * @private + * @type {Background?} + * @default null + */ this._background = null; + /** + * This fullscreen quad is used for internal render passes + * like the tone mapping and color space output pass. + * + * @private + * @type {QuadMesh} + */ this._quad = new QuadMesh( new NodeMaterial() ); - this._quad.material.type = 'Renderer_output'; - + this._quad.material.name = 'Renderer_output'; + + /** + * A reference to the current render context. + * + * @private + * @type {RenderContext?} + * @default null + */ this._currentRenderContext = null; + /** + * A custom sort function for the opaque render list. + * + * @private + * @type {Function?} + * @default null + */ this._opaqueSort = null; + + /** + * A custom sort function for the transparent render list. + * + * @private + * @type {Function?} + * @default null + */ this._transparentSort = null; + /** + * The framebuffer target. + * + * @private + * @type {RenderTarget?} + * @default null + */ this._frameBufferTarget = null; const alphaClear = this.alpha === true ? 0 : 1; + /** + * The clear color value. + * + * @private + * @type {Color4} + */ this._clearColor = new Color4( 0, 0, 0, alphaClear ); + + /** + * The clear depth value. + * + * @private + * @type {Number} + * @default 1 + */ this._clearDepth = 1; + + /** + * The clear stencil value. + * + * @private + * @type {Number} + * @default 0 + */ this._clearStencil = 0; + /** + * The current render target. + * + * @private + * @type {RenderTarget?} + * @default null + */ this._renderTarget = null; + + /** + * The active cube face. + * + * @private + * @type {Number} + * @default 0 + */ this._activeCubeFace = 0; + + /** + * The active mipmap level. + * + * @private + * @type {Number} + * @default 0 + */ this._activeMipmapLevel = 0; + /** + * The MRT setting. + * + * @private + * @type {MRTNode?} + * @default null + */ this._mrt = null; + /** + * This function defines how a render object is going + * to be rendered. + * + * @private + * @type {Function?} + * @default null + */ this._renderObjectFunction = null; + + /** + * Used to keep track of the current render object function. + * + * @private + * @type {Function?} + * @default null + */ this._currentRenderObjectFunction = null; + + /** + * Used to keep track of the current render bundle. + * + * @private + * @type {RenderBundle?} + * @default null + */ this._currentRenderBundle = null; + /** + * Next to `_renderObjectFunction()`, this function provides another hook + * for influencing the render process of a render object. It is meant for internal + * use and only relevant for `compileAsync()` right now. Instead of using + * the default logic of `_renderObjectDirect()` which actually draws the render object, + * a different function might be used which performs no draw but just the node + * and pipeline updates. + * + * @private + * @type {Function?} + * @default null + */ this._handleObjectFunction = this._renderObjectDirect; + /** + * Indicates whether the device has been lost or not. In WebGL terms, the device + * lost is considered as a context lost. When this is set to `true`, rendering + * isn't possible anymore. + * + * @private + * @type {Boolean} + * @default false + */ this._isDeviceLost = false; + + /** + * A callback function that defines what should happen when a device/context lost occurs. + * + * @type {Function} + */ this.onDeviceLost = this._onDeviceLost; + /** + * Whether the renderer has been initialized or not. + * + * @private + * @type {Boolean} + * @default false + */ this._initialized = false; + + /** + * A reference to the promise which initializes the renderer. + * + * @private + * @type {Promise?} + * @default null + */ this._initPromise = null; + /** + * An array of compilation promises which are used in `compileAsync()`. + * + * @private + * @type {Array?} + * @default null + */ this._compilationPromises = null; + /** + * Whether the renderer should render transparent render objects or not. + * + * @type {Boolean} + * @default true + */ this.transparent = true; + + /** + * Whether the renderer should render opaque render objects or not. + * + * @type {Boolean} + * @default true + */ this.opaque = true; + /** + * Shadow map configuration + * @typedef {Object} ShadowMapConfig + * @property {Boolean} enabled - Whether to globally enable shadows or not. + * @property {Number} type - The shadow map type. + */ + + /** + * The renderer's shadow configuration. + * + * @type {module:Renderer~ShadowMapConfig} + */ this.shadowMap = { enabled: false, type: PCFShadowMap }; + /** + * XR configuration. + * @typedef {Object} XRConfig + * @property {Boolean} enabled - Whether to globally enable XR or not. + */ + + /** + * The renderer's XR configuration. + * + * @type {module:Renderer~XRConfig} + */ this.xr = { enabled: false }; + /** + * Debug configuration. + * @typedef {Object} DebugConfig + * @property {Boolean} checkShaderErrors - Whether shader errors should be checked or not. + * @property {Function} onShaderError - A callback function that is executed when a shader error happens. Only supported with WebGL 2 right now. + * @property {Function} getShaderAsync - Allows the get the raw shader code for the given scene, camera and 3D object. + */ + + /** + * The renderer's debug configuration. + * + * @type {module:Renderer~DebugConfig} + */ this.debug = { checkShaderErrors: true, onShaderError: null, @@ -184,6 +687,12 @@ class Renderer { } + /** + * Initializes the renderer so it is ready for usage. + * + * @async + * @return {Promise} A Promise that resolves when the renderer has been initialized. + */ async init() { if ( this._initialized ) { @@ -259,12 +768,35 @@ class Renderer { } + /** + * The coordinate system of the renderer. The value of this property + * depends on the selected backend. Either `THREE.WebGLCoordinateSystem` or + * `THREE.WebGPUCoordinateSystem`. + * + * @readonly + * @type {Number} + */ get coordinateSystem() { return this.backend.coordinateSystem; } + /** + * Compiles all materials in the given scene. This can be useful to avoid a + * phenomenon which is called "shader compilation stutter", which occurs when + * rendering an object with a new shader for the first time. + * + * If you want to add a 3D object to an existing scene, use the third optional + * parameter for applying the target scene. Note that the (target) scene's lighting + * and environment must be configured before calling this method. + * + * @async + * @param {Object3D} scene - The scene or 3D object to precompile. + * @param {Camera} camera - The camera that is used to render the scene. + * @param {Scene} targetScene - If the first argument is a 3D object, this parameter must represent the scene the 3D object is going to be added. + * @return {Promise} A Promise that resolves when the compile has been finished. + */ async compileAsync( scene, camera, targetScene = null ) { if ( this._isDeviceLost === true ) return; @@ -361,10 +893,6 @@ class Renderer { // - this._nodes.updateScene( sceneRef ); - - // - this._background.update( sceneRef, renderList, renderContext ); // process render lists @@ -393,6 +921,14 @@ class Renderer { } + /** + * Renders the scene in an async fashion. + * + * @async + * @param {Object3D} scene - The scene or 3D object to render. + * @param {Camera} camera - The camera. + * @return {Promise} A Promise that resolves when the render has been finished. + */ async renderAsync( scene, camera ) { if ( this._initialized === false ) await this.init(); @@ -403,12 +939,25 @@ class Renderer { } + /** + * Can be used to synchronize CPU operations with GPU tasks. So when this method is called, + * the CPU waits for the GPU to complete its operation (e.g. a compute task). + * + * @async + * @return {Promise} A Promise that resolves when synchronization has been finished. + */ async waitForGPU() { await this.backend.waitForGPU(); } + /** + * Sets the given MRT configuration. + * + * @param {MRTNode} mrt - The MRT node to set. + * @return {Renderer} A reference to this renderer. + */ setMRT( mrt ) { this._mrt = mrt; @@ -417,12 +966,23 @@ class Renderer { } + /** + * Returns the MRT configuration. + * + * @return {MRTNode} The MRT configuration. + */ getMRT() { return this._mrt; } + /** + * Default implementation of the device lost callback. + * + * @private + * @param {Object} info - Information about the context lost. + */ _onDeviceLost( info ) { let errorMessage = `THREE.WebGPURenderer: ${info.api} Device Lost:\n\nMessage: ${info.message}`; @@ -439,7 +999,14 @@ class Renderer { } - + /** + * Renders the given render bundle. + * + * @private + * @param {Object} bundle - Render bundle data. + * @param {Scene} sceneRef - The scene the render bundle belongs to. + * @param {LightsNode} lightsNode - The current lights node. + */ _renderBundle( bundle, sceneRef, lightsNode ) { const { bundleGroup, camera, renderList } = bundle; @@ -511,6 +1078,18 @@ class Renderer { } + /** + * Renders the scene or 3D object with the given camera. This method can only be called + * if the renderer has been initialized. + * + * The target of the method is the default framebuffer (meaning the canvas) + * or alternatively a render target when specified via `setRenderTarget()`. + * + * @param {Object3D} scene - The scene or 3D object to render. + * @param {Camera} camera - The camera to render the scene with. + * @return {Promise?} A Promise that resolve when the scene has been rendered. + * Only returned when the renderer has not been initialized. + */ render( scene, camera ) { if ( this._initialized === false ) { @@ -525,6 +1104,14 @@ class Renderer { } + /** + * Returns an internal render target which is used when computing the output tone mapping + * and color space conversion. Unlike in `WebGLRenderer`, this is done in a separate render + * pass and not inline to achieve more correct results. + * + * @private + * @return {RenderTarget?} The render target. The method returns `null` if no output conversion should be applied. + */ _getFrameBufferTarget() { const { currentToneMapping, currentColorSpace } = this; @@ -572,6 +1159,15 @@ class Renderer { } + /** + * Renders the scene or 3D object with the given camera. + * + * @private + * @param {Object3D} scene - The scene or 3D object to render. + * @param {Camera} camera - The camera to render the scene with. + * @param {Boolean} [useFrameBufferTarget=true] - Whether to use a framebuffer target or not. + * @return {RenderContext} The current render context. + */ _renderScene( scene, camera, useFrameBufferTarget = true ) { if ( this._isDeviceLost === true ) return; @@ -737,10 +1333,6 @@ class Renderer { // - this._nodes.updateScene( sceneRef ); - - // - this._background.update( sceneRef, renderList, renderContext ); // @@ -801,24 +1393,48 @@ class Renderer { } + /** + * Returns the maximum available anisotropy for texture filtering. + * + * @return {Number} The maximum available anisotropy. + */ getMaxAnisotropy() { return this.backend.getMaxAnisotropy(); } + /** + * Returns the active cube face. + * + * @return {Number} The active cube face. + */ getActiveCubeFace() { return this._activeCubeFace; } + /** + * Returns the active mipmap level. + * + * @return {Number} The active mipmap level. + */ getActiveMipmapLevel() { return this._activeMipmapLevel; } + /** + * Applications are advised to always define the animation loop + * with this method and not manually with `requestAnimationFrame()` + * for best compatibility. + * + * @async + * @param {Function} callback - The application's animation loop. + * @return {Promise} A Promise that resolves when the set has been executed. + */ async setAnimationLoop( callback ) { if ( this._initialized === false ) await this.init(); @@ -827,36 +1443,71 @@ class Renderer { } + /** + * Can be used to transfer buffer data from a storage buffer attribute + * from the GPU to the CPU in context of compute shaders. + * + * @async + * @param {StorageBufferAttribute} attribute - The storage buffer attribute. + * @return {Promise} A promise that resolves with the buffer data when the data are ready. + */ async getArrayBufferAsync( attribute ) { return await this.backend.getArrayBufferAsync( attribute ); } + /** + * Returns the rendering context. + * + * @return {GPUCanvasContext|WebGL2RenderingContext} The rendering context. + */ getContext() { return this.backend.getContext(); } + /** + * Returns the pixel ratio. + * + * @return {Number} The pixel ratio. + */ getPixelRatio() { return this._pixelRatio; } + /** + * Returns the drawing buffer size in physical pixels. This method honors the pixel ratio. + * + * @param {Vector2} target - The method writes the result in this target object. + * @return {Vector2} The drawing buffer size. + */ getDrawingBufferSize( target ) { return target.set( this._width * this._pixelRatio, this._height * this._pixelRatio ).floor(); } + /** + * Returns the renderer's size in logical pixels. This method does not honor the pixel ratio. + * + * @param {Vector2} target - The method writes the result in this target object. + * @return {Vector2} The drawing buffer size. + */ getSize( target ) { return target.set( this._width, this._height ); } + /** + * Sets the given pixel ration and resizes the canvas if necessary. + * + * @param {Number} [value=1] - The pixel ratio. + */ setPixelRatio( value = 1 ) { if ( this._pixelRatio === value ) return; @@ -867,6 +1518,19 @@ class Renderer { } + /** + * This method allows to define the drawing buffer size by specifying + * width, height and pixel ratio all at once. The size of the drawing + * buffer is computed with this formula: + * ```` + * size.x = width * pixelRatio; + * size.y = height * pixelRatio; + *``` + * + * @param {Number} width - The width in logical pixels. + * @param {Number} height - The height in logical pixels. + * @param {Number} pixelRatio - The pixel ratio. + */ setDrawingBufferSize( width, height, pixelRatio ) { this._width = width; @@ -883,6 +1547,13 @@ class Renderer { } + /** + * Sets the size of the renderer. + * + * @param {Number} width - The width in logical pixels. + * @param {Number} height - The height in logical pixels. + * @param {Boolean} [updateStyle=true] - Whether to update the `style` attribute of the canvas or not. + */ setSize( width, height, updateStyle = true ) { this._width = width; @@ -904,18 +1575,36 @@ class Renderer { } + /** + * Defines a manual sort function for the opaque render list. + * Pass `null` to use the default sort. + * + * @param {Function} method - The sort function. + */ setOpaqueSort( method ) { this._opaqueSort = method; } + /** + * Defines a manual sort function for the transparent render list. + * Pass `null` to use the default sort. + * + * @param {Function} method - The sort function. + */ setTransparentSort( method ) { this._transparentSort = method; } + /** + * Returns the scissor rectangle. + * + * @param {Vector4} target - The method writes the result in this target object. + * @return {Vector4} The scissor rectangle. + */ getScissor( target ) { const scissor = this._scissor; @@ -929,6 +1618,15 @@ class Renderer { } + /** + * Defines the scissor rectangle. + * + * @param {Number | Vector4} x - The horizontal coordinate for the lower left corner of the box in logical pixel unit. + * Instead of passing four arguments, the method also works with a single four-dimensional vector. + * @param {Number} y - The vertical coordinate for the lower left corner of the box in logical pixel unit. + * @param {Number} width - The width of the scissor box in logical pixel unit. + * @param {Number} height - The height of the scissor box in logical pixel unit. + */ setScissor( x, y, width, height ) { const scissor = this._scissor; @@ -945,12 +1643,22 @@ class Renderer { } + /** + * Returns the scissor test value. + * + * @return {Boolean} Whether the scissor test should be enabled or not. + */ getScissorTest() { return this._scissorTest; } + /** + * Defines the scissor test. + * + * @param {Boolean} boolean - Whether the scissor test should be enabled or not. + */ setScissorTest( boolean ) { this._scissorTest = boolean; @@ -959,12 +1667,28 @@ class Renderer { } + /** + * Returns the viewport definition. + * + * @param {Vector4} target - The method writes the result in this target object. + * @return {Vector4} The viewport definition. + */ getViewport( target ) { return target.copy( this._viewport ); } + /** + * Defines the viewport. + * + * @param {Number | Vector4} x - The horizontal coordinate for the lower left corner of the viewport origin in logical pixel unit. + * @param {Number} y - The vertical coordinate for the lower left corner of the viewport origin in logical pixel unit. + * @param {Number} width - The width of the viewport in logical pixel unit. + * @param {Number} height - The height of the viewport in logical pixel unit. + * @param {Number} minDepth - The minimum depth value of the viewport. WebGPU only. + * @param {Number} maxDepth - The maximum depth value of the viewport. WebGPU only. + */ setViewport( x, y, width, height, minDepth = 0, maxDepth = 1 ) { const viewport = this._viewport; @@ -984,12 +1708,24 @@ class Renderer { } + /** + * Returns the clear color. + * + * @param {Color} target - The method writes the result in this target object. + * @return {Color} The clear color. + */ getClearColor( target ) { return target.copy( this._clearColor ); } + /** + * Defines the clear color and optionally the clear alpha. + * + * @param {Color} color - The clear color. + * @param {Number} [alpha=1] - The clear alpha. + */ setClearColor( color, alpha = 1 ) { this._clearColor.set( color ); @@ -997,42 +1733,80 @@ class Renderer { } + /** + * Returns the clear alpha. + * + * @return {Number} The clear alpha. + */ getClearAlpha() { return this._clearColor.a; } + /** + * Defines the clear alpha. + * + * @param {Number} alpha - The clear alpha. + */ setClearAlpha( alpha ) { this._clearColor.a = alpha; } + /** + * Returns the clear depth. + * + * @return {Number} The clear depth. + */ getClearDepth() { return this._clearDepth; } + /** + * Defines the clear depth. + * + * @param {Number} depth - The clear depth. + */ setClearDepth( depth ) { this._clearDepth = depth; } + /** + * Returns the clear stencil. + * + * @return {Number} The clear stencil. + */ getClearStencil() { return this._clearStencil; } + /** + * Defines the clear stencil. + * + * @param {Number} stencil - The clear stencil. + */ setClearStencil( stencil ) { this._clearStencil = stencil; } + /** + * This method performs an occlusion query for the given 3D object. + * It returns `true` if the given 3D object is fully occluded by other + * 3D objects in the scene. + * + * @param {Object3D} object - The 3D object to test. + * @return {Boolean} Whether the 3D object is fully occluded or not. + */ isOccluded( object ) { const renderContext = this._currentRenderContext; @@ -1041,6 +1815,15 @@ class Renderer { } + /** + * Performs a manual clear operation. This method ignores `autoClear` properties. + * + * @param {Boolean} [color=true] - Whether the color buffer should be cleared or not. + * @param {Boolean} [depth=true] - Whether the depth buffer should be cleared or not. + * @param {Boolean} [stencil=true] - Whether the stencil buffer should be cleared or not. + * @return {Promise} A Promise that resolves when the clear operation has been executed. + * Only returned when the renderer has not been initialized. + */ clear( color = true, depth = true, stencil = true ) { if ( this._initialized === false ) { @@ -1053,17 +1836,26 @@ class Renderer { const renderTarget = this._renderTarget || this._getFrameBufferTarget(); - let renderTargetData = null; + let renderContext = null; if ( renderTarget !== null ) { this._textures.updateRenderTarget( renderTarget ); - renderTargetData = this._textures.get( renderTarget ); + const renderTargetData = this._textures.get( renderTarget ); + + renderContext = this._renderContexts.getForClear( renderTarget ); + renderContext.textures = renderTargetData.textures; + renderContext.depthTexture = renderTargetData.depthTexture; + renderContext.width = renderTargetData.width; + renderContext.height = renderTargetData.height; + renderContext.renderTarget = renderTarget; + renderContext.depth = renderTarget.depthBuffer; + renderContext.stencil = renderTarget.stencilBuffer; } - this.backend.clear( color, depth, stencil, renderTargetData ); + this.backend.clear( color, depth, stencil, renderContext ); if ( renderTarget !== null && this._renderTarget === null ) { @@ -1085,24 +1877,51 @@ class Renderer { } + /** + * Performs a manual clear operation of the color buffer. This method ignores `autoClear` properties. + * + * @return {Promise} A Promise that resolves when the clear operation has been executed. + * Only returned when the renderer has not been initialized. + */ clearColor() { return this.clear( true, false, false ); } + /** + * Performs a manual clear operation of the depth buffer. This method ignores `autoClear` properties. + * + * @return {Promise} A Promise that resolves when the clear operation has been executed. + * Only returned when the renderer has not been initialized. + */ clearDepth() { return this.clear( false, true, false ); } + /** + * Performs a manual clear operation of the stencil buffer. This method ignores `autoClear` properties. + * + * @return {Promise} A Promise that resolves when the clear operation has been executed. + * Only returned when the renderer has not been initialized. + */ clearStencil() { return this.clear( false, false, true ); } + /** + * Async version of {@link module:Renderer~Renderer#clear}. + * + * @async + * @param {Boolean} [color=true] - Whether the color buffer should be cleared or not. + * @param {Boolean} [depth=true] - Whether the depth buffer should be cleared or not. + * @param {Boolean} [stencil=true] - Whether the stencil buffer should be cleared or not. + * @return {Promise} A Promise that resolves when the clear operation has been executed. + */ async clearAsync( color = true, depth = true, stencil = true ) { if ( this._initialized === false ) await this.init(); @@ -1111,36 +1930,70 @@ class Renderer { } - clearColorAsync() { + /** + * Async version of {@link module:Renderer~Renderer#clearColor}. + * + * @async + * @return {Promise} A Promise that resolves when the clear operation has been executed. + */ + async clearColorAsync() { - return this.clearAsync( true, false, false ); + this.clearAsync( true, false, false ); } - clearDepthAsync() { + /** + * Async version of {@link module:Renderer~Renderer#clearDepth}. + * + * @async + * @return {Promise} A Promise that resolves when the clear operation has been executed. + */ + async clearDepthAsync() { - return this.clearAsync( false, true, false ); + this.clearAsync( false, true, false ); } - clearStencilAsync() { + /** + * Async version of {@link module:Renderer~Renderer#clearStencil}. + * + * @async + * @return {Promise} A Promise that resolves when the clear operation has been executed. + */ + async clearStencilAsync() { - return this.clearAsync( false, false, true ); + this.clearAsync( false, false, true ); } + /** + * The current output tone mapping of the renderer. When a render target is set, + * the output tone mapping is always `NoToneMapping`. + * + * @type {Number} + */ get currentToneMapping() { return this._renderTarget !== null ? NoToneMapping : this.toneMapping; } + /** + * The current output color space of the renderer. When a render target is set, + * the output color space is always `LinearSRGBColorSpace`. + * + * @type {String} + */ get currentColorSpace() { return this._renderTarget !== null ? LinearSRGBColorSpace : this.outputColorSpace; } + /** + * Frees all internal resources of the renderer. Call this method if the renderer + * is no longer in use by your app. + */ dispose() { this.info.dispose(); @@ -1160,6 +2013,15 @@ class Renderer { } + /** + * Sets the given render target. Calling this method means the renderer does not + * target the default framebuffer (meaning the canvas) anymore but a custom framebuffer. + * Use `null` as the first argument to reset the state. + * + * @param {RenderTarget?} renderTarget - The render target to set. + * @param {Number} [activeCubeFace=0] - The active cube face. + * @param {Number} [activeMipmapLevel=0] - The active mipmap level. + */ setRenderTarget( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) { this._renderTarget = renderTarget; @@ -1168,24 +2030,67 @@ class Renderer { } + /** + * Returns the current render target. + * + * @return {RenderTarget?} The render target. Returns `null` if no render target is set. + */ getRenderTarget() { return this._renderTarget; } + /** + * Callback for {@link module:Renderer~Renderer#setRenderObjectFunction}. + * + * @callback renderObjectFunction + * @param {Object3D} object - The 3D object. + * @param {Scene} scene - The scene the 3D object belongs to. + * @param {Camera} camera - The camera the object should be rendered with. + * @param {BufferGeometry} geometry - The object's geometry. + * @param {Material} material - The object's material. + * @param {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`. + * @param {LightsNode} lightsNode - The current lights node. + * @param {ClippingContext} clippingContext - The clipping context. + * @param {String?} [passId=null] - An optional ID for identifying the pass. + */ + + /** + * Sets the given render object function. Calling this method overwrites the default implementation + * which is {@link module:Renderer~Renderer#renderObject}. Defining a custom function can be useful + * if you want to modify the way objects are rendered. For example you can define things like "every + * object that has material of a certain type should perform a pre-pass with a special overwrite material". + * The custom function must always call `renderObject()` in its implementation. + * + * Use `null` as the first argument to reset the state. + * + * @param {module:Renderer~renderObjectFunction?} renderObjectFunction - The render object function. + */ setRenderObjectFunction( renderObjectFunction ) { this._renderObjectFunction = renderObjectFunction; } + /** + * Returns the current render object function. + * + * @return {Function?} The current render object function. Returns `null` if no function is set. + */ getRenderObjectFunction() { return this._renderObjectFunction; } + /** + * Execute a single or an array of compute nodes. This method can only be called + * if the renderer has been initialized. + * + * @param {Node|Array} computeNodes - The compute node(s). + * @return {Promise?} A Promise that resolve when the compute has finished. Only returned when the renderer has not been initialized. + */ compute( computeNodes ) { if ( this.isDeviceLost === true ) return; @@ -1277,6 +2182,13 @@ class Renderer { } + /** + * Execute a single or an array of compute nodes. + * + * @async + * @param {Node|Array} computeNodes - The compute node(s). + * @return {Promise?} A Promise that resolve when the compute has finished. + */ async computeAsync( computeNodes ) { if ( this._initialized === false ) await this.init(); @@ -1287,6 +2199,13 @@ class Renderer { } + /** + * Checks if the given feature is supported by the selected backend. + * + * @async + * @param {String} name - The feature's name. + * @return {Promise} A Promise that resolves with a bool that indicates whether the feature is supported or not. + */ async hasFeatureAsync( name ) { if ( this._initialized === false ) await this.init(); @@ -1295,6 +2214,13 @@ class Renderer { } + /** + * Checks if the given feature is supported by the selected backend. If the + * renderer has not been initialized, this method always returns `false`. + * + * @param {String} name - The feature's name. + * @return {Boolean} Whether the feature is supported or not. + */ hasFeature( name ) { if ( this._initialized === false ) { @@ -1309,12 +2235,25 @@ class Renderer { } + /** + * Returns `true` when the renderer has been initialized. + * + * @return {Boolean} Whether the renderer has been initialized or not. + */ hasInitialized() { return this._initialized; } + /** + * Initializes the given textures. Useful for preloading a texture rather than waiting until first render + * (which can cause noticeable lags due to decode and GPU upload overhead). + * + * @async + * @param {Texture} texture - The texture. + * @return {Promise} A Promise that resolves when the texture has been initialized. + */ async initTextureAsync( texture ) { if ( this._initialized === false ) await this.init(); @@ -1323,20 +2262,32 @@ class Renderer { } + /** + * Initializes the given textures. Useful for preloading a texture rather than waiting until first render + * (which can cause noticeable lags due to decode and GPU upload overhead). + * + * This method can only be used if the renderer has been initialized. + * + * @param {Texture} texture - The texture. + */ initTexture( texture ) { if ( this._initialized === false ) { console.warn( 'THREE.Renderer: .initTexture() called before the backend is initialized. Try using .initTextureAsync() instead.' ); - return false; - } this._textures.updateTexture( texture ); } + /** + * Copies the current bound framebuffer into the given texture. + * + * @param {FramebufferTexture} framebufferTexture - The texture. + * @param {Vector2|Vector4} rectangle - A two or four dimensional vector that defines the rectangular portion of the framebuffer that should be copied. + */ copyFramebufferToTexture( framebufferTexture, rectangle = null ) { if ( rectangle !== null ) { @@ -1394,6 +2345,15 @@ class Renderer { } + /** + * Copies data of source texture into a destination texture. + * + * @param {Texture} srcTexture - The source texture. + * @param {Texture} dstTexture - The destination texture. + * @param {Box2|Box3} [srcRegion=null] - A bounding box which describes the source region. Can be two or three-dimensional. + * @param {Vector2|Vector3} [dstPosition=null] - A vector that represents the origin of the destination region. Can be two or three-dimensional. + * @param {Number} level - The mipmap level to copy. + */ copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { this._textures.updateTexture( srcTexture ); @@ -1403,12 +2363,35 @@ class Renderer { } - readRenderTargetPixelsAsync( renderTarget, x, y, width, height, index = 0, faceIndex = 0 ) { - - return this.backend.copyTextureToBuffer( renderTarget.textures[ index ], x, y, width, height, faceIndex ); - - } - + /** + * Reads pixel data from the given render target. + * + * @async + * @param {RenderTarget} renderTarget - The render target to read from. + * @param {Number} x - The `x` coordinate of the copy region's origin. + * @param {Number} y - The `y` coordinate of the copy region's origin. + * @param {Number} width - The width of the copy region. + * @param {Number} height - The height of the copy region. + * @param {Number} [textureIndex=0] - The texture index of a MRT render target. + * @param {Number} [faceIndex=0] - The active cube face index. + * @return {Promise} A Promise that resolves when the read has been finished. The resolve provides the read data as a typed array. + */ + async readRenderTargetPixelsAsync( renderTarget, x, y, width, height, textureIndex = 0, faceIndex = 0 ) { + + return this.backend.copyTextureToBuffer( renderTarget.textures[ textureIndex ], x, y, width, height, faceIndex ); + + } + + /** + * Analyzes the given 3D object's hierarchy and builds render lists from the + * processed hierarchy. + * + * @param {Object3D} object - The 3D object to process (usually a scene). + * @param {Camera} camera - The camera the object is rendered with. + * @param {Number} groupOrder - The group order is derived from the `renderOrder` of groups and is used to group 3D objects within groups. + * @param {RenderList} renderList - The current render list. + * @param {ClippingContext} clippingContext - The current clipping context. + */ _projectObject( object, camera, groupOrder, renderList, clippingContext ) { if ( object.visible === false ) return; @@ -1530,6 +2513,14 @@ class Renderer { } + /** + * Renders the given render bundles. + * + * @private + * @param {Array} bundles - Array with render bundle data. + * @param {Scene} sceneRef - The scene the render bundles belong to. + * @param {LightsNode} lightsNode - The current lights node. + */ _renderBundles( bundles, sceneRef, lightsNode ) { for ( const bundle of bundles ) { @@ -1540,6 +2531,16 @@ class Renderer { } + /** + * Renders the transparent objects from the given render lists. + * + * @private + * @param {Array} renderList - The transparent render list. + * @param {Array} doublePassList - The list of transparent objects which require a double pass (e.g. because of transmission). + * @param {Camera} camera - The camera the render list should be rendered with. + * @param {Scene} scene - The scene the render list belongs to. + * @param {LightsNode} lightsNode - The current lights node. + */ _renderTransparents( renderList, doublePassList, camera, scene, lightsNode ) { if ( doublePassList.length > 0 ) { @@ -1580,6 +2581,16 @@ class Renderer { } + /** + * Renders the objects from the given render list. + * + * @private + * @param {Array} renderList - The render list. + * @param {Camera} camera - The camera the render list should be rendered with. + * @param {Scene} scene - The scene the render list belongs to. + * @param {LightsNode} lightsNode - The current lights node. + * @param {String?} [passId=null] - An optional ID for identifying the pass. + */ _renderObjects( renderList, camera, scene, lightsNode, passId = null ) { // process renderable objects @@ -1630,6 +2641,20 @@ class Renderer { } + /** + * This method represents the default render object function that manages the render lifecycle + * of the object. + * + * @param {Object3D} object - The 3D object. + * @param {Scene} scene - The scene the 3D object belongs to. + * @param {Camera} camera - The camera the object should be rendered with. + * @param {BufferGeometry} geometry - The object's geometry. + * @param {Material} material - The object's material. + * @param {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`. + * @param {LightsNode} lightsNode - The current lights node. + * @param {ClippingContext} clippingContext - The clipping context. + * @param {String?} [passId=null] - An optional ID for identifying the pass. + */ renderObject( object, scene, camera, geometry, material, group, lightsNode, clippingContext = null, passId = null ) { let overridePositionNode; @@ -1725,6 +2750,20 @@ class Renderer { } + /** + * This method represents the default `_handleObjectFunction` implementation which creates + * a render object from the given data and performs the draw command with the selected backend. + * + * @private + * @param {Object3D} object - The 3D object. + * @param {Material} material - The object's material. + * @param {Scene} scene - The scene the 3D object belongs to. + * @param {Camera} camera - The camera the object should be rendered with. + * @param {LightsNode} lightsNode - The current lights node. + * @param {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`. + * @param {ClippingContext} clippingContext - The clipping context. + * @param {String?} [passId=null] - An optional ID for identifying the pass. + */ _renderObjectDirect( object, material, scene, camera, lightsNode, group, clippingContext, passId ) { const renderObject = this._objects.get( object, material, scene, camera, lightsNode, this._currentRenderContext, clippingContext, passId ); @@ -1756,7 +2795,7 @@ class Renderer { renderBundleData.renderObjects.push( renderObject ); - renderObject.bundle = this._currentRenderBundle.scene; + renderObject.bundle = this._currentRenderBundle.bundleGroup; } @@ -1766,6 +2805,20 @@ class Renderer { } + /** + * A different implementation for `_handleObjectFunction` which only makes sure the object is ready for rendering. + * Used in `compileAsync()`. + * + * @private + * @param {Object3D} object - The 3D object. + * @param {Material} material - The object's material. + * @param {Scene} scene - The scene the 3D object belongs to. + * @param {Camera} camera - The camera the object should be rendered with. + * @param {LightsNode} lightsNode - The current lights node. + * @param {Object?} group - Only relevant for objects using multiple materials. This represents a group entry from the respective `BufferGeometry`. + * @param {ClippingContext} clippingContext - The clipping context. + * @param {String?} [passId=null] - An optional ID for identifying the pass. + */ _createObjectPipeline( object, material, scene, camera, lightsNode, group, clippingContext, passId ) { const renderObject = this._objects.get( object, material, scene, camera, lightsNode, this._currentRenderContext, clippingContext, passId ); @@ -1787,6 +2840,15 @@ class Renderer { } + /** + * Alias for `compileAsync()`. + * + * @method + * @param {Object3D} scene - The scene or 3D object to precompile. + * @param {Camera} camera - The camera that is used to render the scene. + * @param {Scene} targetScene - If the first argument is a 3D object, this parameter must represent the scene the 3D object is going to be added. + * @return {Promise} A Promise that resolves when the compile has been finished. + */ get compile() { return this.compileAsync; diff --git a/src/renderers/common/RendererUtils.js b/src/renderers/common/RendererUtils.js new file mode 100644 index 00000000000000..7de30175de4428 --- /dev/null +++ b/src/renderers/common/RendererUtils.js @@ -0,0 +1,193 @@ +import { Color } from '../../math/Color.js'; + +/** @module RendererUtils **/ + +/** + * Saves the state of the given renderer and stores it into the given state object. + * + * If not state object is provided, the function creates one. + * + * @function + * @param {Renderer} renderer - The renderer. + * @param {Object} [state={}] - The state. + * @return {Object} The state. + */ +export function saveRendererState( renderer, state = {} ) { + + state.toneMapping = renderer.toneMapping; + state.toneMappingExposure = renderer.toneMappingExposure; + state.outputColorSpace = renderer.outputColorSpace; + state.renderTarget = renderer.getRenderTarget(); + state.activeCubeFace = renderer.getActiveCubeFace(); + state.activeMipmapLevel = renderer.getActiveMipmapLevel(); + state.renderObjectFunction = renderer.getRenderObjectFunction(); + state.pixelRatio = renderer.getPixelRatio(); + state.mrt = renderer.getMRT(); + state.clearColor = renderer.getClearColor( state.clearColor || new Color() ); + state.clearAlpha = renderer.getClearAlpha(); + state.autoClear = renderer.autoClear; + state.scissorTest = renderer.getScissorTest(); + + return state; + +} + +/** + * Saves the state of the given renderer and stores it into the given state object. + * Besides, the function also resets the state of the renderer to its default values. + * + * If not state object is provided, the function creates one. + * + * @function + * @param {Renderer} renderer - The renderer. + * @param {Object} [state={}] - The state. + * @return {Object} The state. + */ +export function resetRendererState( renderer, state ) { + + state = saveRendererState( renderer, state ); + + renderer.setMRT( null ); + renderer.setRenderObjectFunction( null ); + renderer.setClearColor( 0x000000, 1 ); + renderer.autoClear = true; + + return state; + +} + +/** + * Restores the state of the given renderer from the given state object. + * + * @function + * @param {Renderer} renderer - The renderer. + * @param {Object} state - The state to restore. + */ +export function restoreRendererState( renderer, state ) { + + renderer.toneMapping = state.toneMapping; + renderer.toneMappingExposure = state.toneMappingExposure; + renderer.outputColorSpace = state.outputColorSpace; + renderer.setRenderTarget( state.renderTarget, state.activeCubeFace, state.activeMipmapLevel ); + renderer.setRenderObjectFunction( state.renderObjectFunction ); + renderer.setPixelRatio( state.pixelRatio ); + renderer.setMRT( state.mrt ); + renderer.setClearColor( state.clearColor, state.clearAlpha ); + renderer.autoClear = state.autoClear; + renderer.setScissorTest( state.scissorTest ); + +} + +/** + * Saves the state of the given scene and stores it into the given state object. + * + * If not state object is provided, the function creates one. + * + * @function + * @param {Scene} scene - The scene. + * @param {Object} [state={}] - The state. + * @return {Object} The state. + */ +export function saveSceneState( scene, state = {} ) { + + state.background = scene.background; + state.backgroundNode = scene.backgroundNode; + state.overrideMaterial = scene.overrideMaterial; + + return state; + +} + +/** + * Saves the state of the given scene and stores it into the given state object. + * Besides, the function also resets the state of the scene to its default values. + * + * If not state object is provided, the function creates one. + * + * @function + * @param {Scene} scene - The scene. + * @param {Object} [state={}] - The state. + * @return {Object} The state. + */ +export function resetSceneState( scene, state ) { + + state = saveSceneState( scene, state ); + + scene.background = null; + scene.backgroundNode = null; + scene.overrideMaterial = null; + + return state; + +} + +/** + * Restores the state of the given scene from the given state object. + * + * @function + * @param {Scene} scene - The scene. + * @param {Object} state - The state to restore. + */ +export function restoreSceneState( scene, state ) { + + scene.background = state.background; + scene.backgroundNode = state.backgroundNode; + scene.overrideMaterial = state.overrideMaterial; + +} + +/** + * Saves the state of the given renderer and scene and stores it into the given state object. + * + * If not state object is provided, the function creates one. + * + * @function + * @param {Renderer} renderer - The renderer. + * @param {Scene} scene - The scene. + * @param {Object} [state={}] - The state. + * @return {Object} The state. + */ +export function saveRendererAndSceneState( renderer, scene, state = {} ) { + + state = saveRendererState( renderer, state ); + state = saveSceneState( scene, state ); + + return state; + +} + +/** + * Saves the state of the given renderer and scene and stores it into the given state object. + * Besides, the function also resets the state of the renderer and scene to its default values. + * + * If not state object is provided, the function creates one. + * + * @function + * @param {Renderer} renderer - The renderer. + * @param {Scene} scene - The scene. + * @param {Object} [state={}] - The state. + * @return {Object} The state. + */ +export function resetRendererAndSceneState( renderer, scene, state ) { + + state = resetRendererState( renderer, state ); + state = resetSceneState( scene, state ); + + return state; + +} + +/** + * Restores the state of the given renderer and scene from the given state object. + * + * @function + * @param {Renderer} renderer - The renderer. + * @param {Scene} scene - The scene. + * @param {Object} state - The state to restore. + */ +export function restoreRendererAndSceneState( renderer, scene, state ) { + + restoreRendererState( renderer, state ); + restoreSceneState( scene, state ); + +} diff --git a/src/renderers/common/SampledTexture.js b/src/renderers/common/SampledTexture.js index 6e4ff0c92201e9..dd208ae4e2ed94 100644 --- a/src/renderers/common/SampledTexture.js +++ b/src/renderers/common/SampledTexture.js @@ -2,23 +2,80 @@ import Binding from './Binding.js'; let _id = 0; +/** + * Represents a sampled texture binding type. + * + * @private + * @augments Binding + */ class SampledTexture extends Binding { + /** + * Constructs a new sampled texture. + * + * @param {String} name - The sampled texture's name. + * @param {Texture?} texture - The texture this binding is referring to. + */ constructor( name, texture ) { super( name ); + /** + * This identifier. + * + * @type {Number} + */ this.id = _id ++; + /** + * The texture this binding is referring to. + * + * @type {Texture?} + */ this.texture = texture; + + /** + * The binding's version. + * + * @type {Number} + */ this.version = texture ? texture.version : 0; + + /** + * Whether the texture is a storage texture or not. + * + * @type {Boolean} + * @default false + */ this.store = false; + + /** + * The binding's generation which is an additional version + * qualifier. + * + * @type {Number?} + * @default null + */ this.generation = null; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isSampledTexture = true; } + /** + * Returns `true` whether this binding requires an update for the + * given generation. + * + * @param {Number} generation - The generation. + * @return {Boolean} Whether an update is required or not. + */ needsBindingsUpdate( generation ) { const { texture } = this; @@ -35,6 +92,13 @@ class SampledTexture extends Binding { } + /** + * Updates the binding. + * + * @param {Number} generation - The generation. + * @return {Boolean} Whether the texture has been updated and must be + * uploaded to the GPU. + */ update() { const { texture, version } = this; @@ -53,36 +117,93 @@ class SampledTexture extends Binding { } +/** + * Represents a sampled array texture binding type. + * + * @private + * @augments SampledTexture + */ class SampledArrayTexture extends SampledTexture { + /** + * Constructs a new sampled array texture. + * + * @param {String} name - The sampled array texture's name. + * @param {(DataArrayTexture|CompressedArrayTexture)?} texture - The texture this binding is referring to. + */ constructor( name, texture ) { super( name, texture ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isSampledArrayTexture = true; } } +/** + * Represents a sampled 3D texture binding type. + * + * @private + * @augments SampledTexture + */ class Sampled3DTexture extends SampledTexture { + /** + * Constructs a new sampled 3D texture. + * + * @param {String} name - The sampled 3D texture's name. + * @param {Data3DTexture?} texture - The texture this binding is referring to. + */ constructor( name, texture ) { super( name, texture ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isSampled3DTexture = true; } } +/** + * Represents a sampled cube texture binding type. + * + * @private + * @augments SampledTexture + */ class SampledCubeTexture extends SampledTexture { + /** + * Constructs a new sampled cube texture. + * + * @param {String} name - The sampled cube texture's name. + * @param {(CubeTexture|CompressedCubeTexture)?} texture - The texture this binding is referring to. + */ constructor( name, texture ) { super( name, texture ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isSampledCubeTexture = true; } diff --git a/src/renderers/common/Sampler.js b/src/renderers/common/Sampler.js index ccbdd0e5544bd2..82e86ae3daef8c 100644 --- a/src/renderers/common/Sampler.js +++ b/src/renderers/common/Sampler.js @@ -1,14 +1,44 @@ import Binding from './Binding.js'; +/** + * Represents a sampler binding type. + * + * @private + * @augments Binding + */ class Sampler extends Binding { + /** + * Constructs a new sampler. + * + * @param {String} name - The samplers's name. + * @param {Texture?} texture - The texture this binding is referring to. + */ constructor( name, texture ) { super( name ); + /** + * The texture the sampler is referring to. + * + * @type {Texture?} + */ this.texture = texture; + + /** + * The binding's version. + * + * @type {Number} + */ this.version = texture ? texture.version : 0; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isSampler = true; } diff --git a/src/renderers/common/StorageBuffer.js b/src/renderers/common/StorageBuffer.js index 8c353e78a4fefd..1411c15941912a 100644 --- a/src/renderers/common/StorageBuffer.js +++ b/src/renderers/common/StorageBuffer.js @@ -1,13 +1,37 @@ import Buffer from './Buffer.js'; +/** + * Represents a storage buffer binding type. + * + * @private + * @augments Buffer + */ class StorageBuffer extends Buffer { + /** + * Constructs a new uniform buffer. + * + * @param {String} name - The buffer's name. + * @param {BufferAttribute} attribute - The buffer attribute. + */ constructor( name, attribute ) { super( name, attribute ? attribute.array : null ); + /** + * This flag can be used for type testing. + * + * @type {BufferAttribute} + */ this.attribute = attribute; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isStorageBuffer = true; } diff --git a/src/renderers/common/StorageBufferAttribute.js b/src/renderers/common/StorageBufferAttribute.js index 0ce8fb0485c5fc..f978041afbdb5c 100644 --- a/src/renderers/common/StorageBufferAttribute.js +++ b/src/renderers/common/StorageBufferAttribute.js @@ -1,13 +1,42 @@ import { BufferAttribute } from '../../core/BufferAttribute.js'; +/** + * This special type of buffer attribute is intended for compute shaders. + * In earlier three.js versions it was only possible to update attribute data + * on the CPU via JavaScript and then upload the data to the GPU. With the + * new material system and renderer it is now possible to use compute shaders + * to compute the data for an attribute more efficiently on the GPU. + * + * The idea is to create an instance of this class and provide it as an input + * to {@link module:StorageBufferNode}. + * + * Note: This type of buffer attribute can only be used with `WebGPURenderer`. + * + * @augments BufferAttribute + */ class StorageBufferAttribute extends BufferAttribute { - constructor( array, itemSize, typeClass = Float32Array ) { + /** + * Constructs a new storage buffer attribute. + * + * @param {Number|TypedArray} count - The item count. It is also valid to pass a typed array as an argument. + * The subsequent parameters are then obsolete. + * @param {Number} itemSize - The item size. + * @param {TypedArray.constructor} [typeClass=Float32Array] - A typed array constructor. + */ + constructor( count, itemSize, typeClass = Float32Array ) { - if ( ArrayBuffer.isView( array ) === false ) array = new typeClass( array * itemSize ); + const array = ArrayBuffer.isView( count ) ? count : new typeClass( count * itemSize ); super( array, itemSize ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isStorageBufferAttribute = true; } diff --git a/src/renderers/common/StorageInstancedBufferAttribute.js b/src/renderers/common/StorageInstancedBufferAttribute.js index 8ccbaae56274ac..b3e484ddaadc46 100644 --- a/src/renderers/common/StorageInstancedBufferAttribute.js +++ b/src/renderers/common/StorageInstancedBufferAttribute.js @@ -1,13 +1,42 @@ import { InstancedBufferAttribute } from '../../core/InstancedBufferAttribute.js'; +/** + * This special type of instanced buffer attribute is intended for compute shaders. + * In earlier three.js versions it was only possible to update attribute data + * on the CPU via JavaScript and then upload the data to the GPU. With the + * new material system and renderer it is now possible to use compute shaders + * to compute the data for an attribute more efficiently on the GPU. + * + * The idea is to create an instance of this class and provide it as an input + * to {@link module:StorageBufferNode}. + * + * Note: This type of buffer attribute can only be used with `WebGPURenderer`. + * + * @augments InstancedBufferAttribute + */ class StorageInstancedBufferAttribute extends InstancedBufferAttribute { - constructor( array, itemSize, typeClass = Float32Array ) { + /** + * Constructs a new storage instanced buffer attribute. + * + * @param {Number|TypedArray} count - The item count. It is also valid to pass a typed array as an argument. + * The subsequent parameters are then obsolete. + * @param {Number} itemSize - The item size. + * @param {TypedArray.constructor} [typeClass=Float32Array] - A typed array constructor. + */ + constructor( count, itemSize, typeClass = Float32Array ) { - if ( ArrayBuffer.isView( array ) === false ) array = new typeClass( array * itemSize ); + const array = ArrayBuffer.isView( count ) ? count : new typeClass( count * itemSize ); super( array, itemSize ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isStorageInstancedBufferAttribute = true; } diff --git a/src/renderers/common/StorageTexture.js b/src/renderers/common/StorageTexture.js index d5a2742c99e0c8..9f959eca0f6e68 100644 --- a/src/renderers/common/StorageTexture.js +++ b/src/renderers/common/StorageTexture.js @@ -1,17 +1,55 @@ import { Texture } from '../../textures/Texture.js'; import { LinearFilter } from '../../constants.js'; +/** + * This special type of texture is intended for compute shaders. + * It can be used to compute the data of a texture with a compute shader. + * + * Note: This type of texture can only be used with `WebGPURenderer` + * and a WebGPU backend. + * + * @augments Texture + */ class StorageTexture extends Texture { + /** + * Constructs a new storage texture. + * + * @param {Number} [width=1] - The storage texture's width. + * @param {Number} [height=1] - The storage texture's height. + */ constructor( width = 1, height = 1 ) { super(); + /** + * The image object which just represents the texture's dimension. + * + * @type {{width: Number, height:Number}} + */ this.image = { width, height }; + /** + * The default `magFilter` for storage textures is `THREE.LinearFilter`. + * + * @type {Number} + */ this.magFilter = LinearFilter; + + /** + * The default `minFilter` for storage textures is `THREE.LinearFilter`. + * + * @type {Number} + */ this.minFilter = LinearFilter; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isStorageTexture = true; } diff --git a/src/renderers/common/Textures.js b/src/renderers/common/Textures.js index 84635f0f95abfe..907c9c325bf940 100644 --- a/src/renderers/common/Textures.js +++ b/src/renderers/common/Textures.js @@ -6,18 +6,55 @@ import { DepthStencilFormat, DepthFormat, UnsignedIntType, UnsignedInt248Type, E const _size = /*@__PURE__*/ new Vector3(); +/** + * This module manages the textures of the renderer. + * + * @private + * @augments DataMap + */ class Textures extends DataMap { + /** + * Constructs a new texture management component. + * + * @param {Renderer} renderer - The renderer. + * @param {Backend} backend - The renderer's backend. + * @param {Info} info - Renderer component for managing metrics and monitoring data. + */ constructor( renderer, backend, info ) { super(); + /** + * The renderer. + * + * @type {Renderer} + */ this.renderer = renderer; + + /** + * The backend. + * + * @type {Backend} + */ this.backend = backend; + + /** + * Renderer component for managing metrics and monitoring data. + * + * @type {Info} + */ this.info = info; } + /** + * Updates the given render target. Based on the given render target configuration, + * it updates the texture states representing the attachments of the framebuffer. + * + * @param {RenderTarget} renderTarget - The render target to update. + * @param {Number} [activeMipmapLevel=0] - The active mipmap level. + */ updateRenderTarget( renderTarget, activeMipmapLevel = 0 ) { const renderTargetData = this.get( renderTarget ); @@ -139,6 +176,14 @@ class Textures extends DataMap { } + /** + * Updates the given texture. Depending on the texture state, this method + * triggers the upload of texture data to the GPU memory. If the texture data are + * not yet ready for the upload, it uses default texture data for as a placeholder. + * + * @param {Texture} texture - The texture to update. + * @param {Object} [options={}] - The options. + */ updateTexture( texture, options = {} ) { const textureData = this.get( texture ); @@ -292,6 +337,18 @@ class Textures extends DataMap { } + /** + * Computes the size of the given texture and writes the result + * into the target vector. This vector is also returned by the + * method. + * + * If no texture data are available for the compute yet, the method + * returns default size values. + * + * @param {Texture} texture - The texture to compute the size for. + * @param {Vector3} target - The target vector. + * @return {Vector3} The target vector. + */ getSize( texture, target = _size ) { let image = texture.images ? texture.images[ 0 ] : texture.image; @@ -314,6 +371,14 @@ class Textures extends DataMap { } + /** + * Computes the number of mipmap levels for the given texture. + * + * @param {Texture} texture - The texture. + * @param {Number} width - The texture's width. + * @param {Number} height - The texture's height. + * @return {Number} The number of mipmap levels. + */ getMipLevels( texture, width, height ) { let mipLevelCount; @@ -340,12 +405,24 @@ class Textures extends DataMap { } + /** + * Returns `true` if the given texture requires mipmaps. + * + * @param {Texture} texture - The texture. + * @return {Boolean} Whether mipmaps are required or not. + */ needsMipmaps( texture ) { return this.isEnvironmentTexture( texture ) || texture.isCompressedTexture === true || texture.generateMipmaps; } + /** + * Returns `true` if the given texture is an environment map. + * + * @param {Texture} texture - The texture. + * @return {Boolean} Whether the given texture is an environment map or not. + */ isEnvironmentTexture( texture ) { const mapping = texture.mapping; @@ -354,6 +431,12 @@ class Textures extends DataMap { } + /** + * Frees internal resource when the given texture isn't + * required anymore. + * + * @param {Texture} texture - The texture to destroy. + */ _destroyTexture( texture ) { this.backend.destroySampler( texture ); diff --git a/src/renderers/common/Uniform.js b/src/renderers/common/Uniform.js index cff9e684eae977..3a6229c15a0259 100644 --- a/src/renderers/common/Uniform.js +++ b/src/renderers/common/Uniform.js @@ -5,26 +5,79 @@ import { Vector2 } from '../../math/Vector2.js'; import { Vector3 } from '../../math/Vector3.js'; import { Vector4 } from '../../math/Vector4.js'; +/** + * Abstract base class for uniforms. + * + * @abstract + * @private + */ class Uniform { + /** + * Constructs a new uniform. + * + * @param {String} name - The uniform's name. + * @param {Any} value - The uniform's value. + */ constructor( name, value ) { + /** + * The uniform's name. + * + * @type {String} + */ this.name = name; + + /** + * The uniform's value. + * + * @type {Any} + */ this.value = value; - this.boundary = 0; // used to build the uniform buffer according to the STD140 layout + /** + * Used to build the uniform buffer according to the STD140 layout. + * Derived uniforms will set this property to a data type specific + * value. + * + * @type {Number} + */ + this.boundary = 0; + + /** + * The item size. Derived uniforms will set this property to a data + * type specific value. + * + * @type {Number} + */ this.itemSize = 0; - this.offset = 0; // this property is set by WebGPUUniformsGroup and marks the start position in the uniform buffer + /** + * This property is set by {@link UniformsGroup} and marks + * the start position in the uniform buffer. + * + * @type {Number} + */ + this.offset = 0; } + /** + * Sets the uniform's value. + * + * @param {Any} value - The value to set. + */ setValue( value ) { this.value = value; } + /** + * Returns the uniform's value. + * + * @return {Any} The value. + */ getValue() { return this.value; @@ -33,12 +86,31 @@ class Uniform { } +/** + * Represents a Number uniform. + * + * @private + * @augments Uniform + */ class NumberUniform extends Uniform { + /** + * Constructs a new Number uniform. + * + * @param {String} name - The uniform's name. + * @param {Number} value - The uniform's value. + */ constructor( name, value = 0 ) { super( name, value ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isNumberUniform = true; this.boundary = 4; @@ -48,12 +120,31 @@ class NumberUniform extends Uniform { } +/** + * Represents a Vector2 uniform. + * + * @private + * @augments Uniform + */ class Vector2Uniform extends Uniform { + /** + * Constructs a new Number uniform. + * + * @param {String} name - The uniform's name. + * @param {Vector2} value - The uniform's value. + */ constructor( name, value = new Vector2() ) { super( name, value ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isVector2Uniform = true; this.boundary = 8; @@ -63,12 +154,31 @@ class Vector2Uniform extends Uniform { } +/** + * Represents a Vector3 uniform. + * + * @private + * @augments Uniform + */ class Vector3Uniform extends Uniform { + /** + * Constructs a new Number uniform. + * + * @param {String} name - The uniform's name. + * @param {Vector3} value - The uniform's value. + */ constructor( name, value = new Vector3() ) { super( name, value ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isVector3Uniform = true; this.boundary = 16; @@ -78,12 +188,31 @@ class Vector3Uniform extends Uniform { } +/** + * Represents a Vector4 uniform. + * + * @private + * @augments Uniform + */ class Vector4Uniform extends Uniform { + /** + * Constructs a new Number uniform. + * + * @param {String} name - The uniform's name. + * @param {Vector4} value - The uniform's value. + */ constructor( name, value = new Vector4() ) { super( name, value ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isVector4Uniform = true; this.boundary = 16; @@ -93,12 +222,31 @@ class Vector4Uniform extends Uniform { } +/** + * Represents a Color uniform. + * + * @private + * @augments Uniform + */ class ColorUniform extends Uniform { + /** + * Constructs a new Number uniform. + * + * @param {String} name - The uniform's name. + * @param {Color} value - The uniform's value. + */ constructor( name, value = new Color() ) { super( name, value ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isColorUniform = true; this.boundary = 16; @@ -108,12 +256,31 @@ class ColorUniform extends Uniform { } +/** + * Represents a Matrix3 uniform. + * + * @private + * @augments Uniform + */ class Matrix3Uniform extends Uniform { + /** + * Constructs a new Number uniform. + * + * @param {String} name - The uniform's name. + * @param {Matrix3} value - The uniform's value. + */ constructor( name, value = new Matrix3() ) { super( name, value ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMatrix3Uniform = true; this.boundary = 48; @@ -123,12 +290,31 @@ class Matrix3Uniform extends Uniform { } +/** + * Represents a Matrix4 uniform. + * + * @private + * @augments Uniform + */ class Matrix4Uniform extends Uniform { + /** + * Constructs a new Number uniform. + * + * @param {String} name - The uniform's name. + * @param {Matrix4} value - The uniform's value. + */ constructor( name, value = new Matrix4() ) { super( name, value ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isMatrix4Uniform = true; this.boundary = 64; diff --git a/src/renderers/common/UniformBuffer.js b/src/renderers/common/UniformBuffer.js index 4edd9f8f8e6be4..4262c774743823 100644 --- a/src/renderers/common/UniformBuffer.js +++ b/src/renderers/common/UniformBuffer.js @@ -1,11 +1,30 @@ import Buffer from './Buffer.js'; +/** + * Represents a uniform buffer binding type. + * + * @private + * @augments Buffer + */ class UniformBuffer extends Buffer { + /** + * Constructs a new uniform buffer. + * + * @param {String} name - The buffer's name. + * @param {TypedArray} [buffer=null] - The buffer. + */ constructor( name, buffer = null ) { super( name, buffer ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isUniformBuffer = true; } diff --git a/src/renderers/common/UniformsGroup.js b/src/renderers/common/UniformsGroup.js index 10d7466da375d8..70a973d9d0316a 100644 --- a/src/renderers/common/UniformsGroup.js +++ b/src/renderers/common/UniformsGroup.js @@ -1,22 +1,59 @@ import UniformBuffer from './UniformBuffer.js'; import { GPU_CHUNK_BYTES } from './Constants.js'; +/** + * This class represents a uniform buffer binding but with + * an API that allows to maintain individual uniform objects. + * + * @private + * @augments UniformBuffer + */ class UniformsGroup extends UniformBuffer { + /** + * Constructs a new uniforms group. + * + * @param {String} name - The group's name. + */ constructor( name ) { super( name ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isUniformsGroup = true; + /** + * An array with the raw uniform values. + * + * @private + * @type {Array?} + * @default null + */ this._values = null; - // the order of uniforms in this array must match the order of uniforms in the shader - + /** + * An array of uniform objects. + * + * The order of uniforms in this array must match the order of uniforms in the shader. + * + * @type {Array} + */ this.uniforms = []; } + /** + * Adds a uniform to this group. + * + * @param {Uniform} uniform - The uniform to add. + * @return {UniformsGroup} A reference to this group. + */ addUniform( uniform ) { this.uniforms.push( uniform ); @@ -25,6 +62,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Removes a uniform from this group. + * + * @param {Uniform} uniform - The uniform to remove. + * @return {UniformsGroup} A reference to this group. + */ removeUniform( uniform ) { const index = this.uniforms.indexOf( uniform ); @@ -39,6 +82,11 @@ class UniformsGroup extends UniformBuffer { } + /** + * An array with the raw uniform values. + * + * @type {Array} + */ get values() { if ( this._values === null ) { @@ -51,6 +99,11 @@ class UniformsGroup extends UniformBuffer { } + /** + * A Float32 array buffer with the uniform values. + * + * @type {Float32Array} + */ get buffer() { let buffer = this._buffer; @@ -69,6 +122,11 @@ class UniformsGroup extends UniformBuffer { } + /** + * The byte length of the buffer with correct buffer alignment. + * + * @type {Number} + */ get byteLength() { let offset = 0; // global buffer offset in bytes @@ -110,6 +168,15 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates this group by updating each uniform object of + * the internal uniform list. The uniform objects check if their + * values has actually changed so this method only returns + * `true` if there is a real value change. + * + * @return {Boolean} Whether the uniforms have been updated and + * must be uploaded to the GPU. + */ update() { let updated = false; @@ -128,6 +195,13 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given uniform by calling an update method matching + * the uniforms type. + * + * @param {Uniform} uniform - The uniform to update. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateByType( uniform ) { if ( uniform.isNumberUniform ) return this.updateNumber( uniform ); @@ -142,6 +216,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given Number uniform. + * + * @param {NumberUniform} uniform - The Number uniform. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateNumber( uniform ) { let updated = false; @@ -164,6 +244,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given Vector2 uniform. + * + * @param {Vector2Uniform} uniform - The Vector2 uniform. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateVector2( uniform ) { let updated = false; @@ -188,6 +274,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given Vector3 uniform. + * + * @param {Vector3Uniform} uniform - The Vector3 uniform. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateVector3( uniform ) { let updated = false; @@ -213,6 +305,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given Vector4 uniform. + * + * @param {Vector4Uniform} uniform - The Vector4 uniform. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateVector4( uniform ) { let updated = false; @@ -239,6 +337,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given Color uniform. + * + * @param {ColorUniform} uniform - The Color uniform. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateColor( uniform ) { let updated = false; @@ -263,6 +367,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given Matrix3 uniform. + * + * @param {Matrix3Uniform} uniform - The Matrix3 uniform. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateMatrix3( uniform ) { let updated = false; @@ -295,6 +405,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Updates a given Matrix4 uniform. + * + * @param {Matrix4Uniform} uniform - The Matrix4 uniform. + * @return {Boolean} Whether the uniform has been updated or not. + */ updateMatrix4( uniform ) { let updated = false; @@ -316,6 +432,12 @@ class UniformsGroup extends UniformBuffer { } + /** + * Returns a typed array that matches the given data type. + * + * @param {String} type - The data type. + * @return {TypedArray} The typed array. + */ _getBufferForType( type ) { if ( type === 'int' || type === 'ivec2' || type === 'ivec3' || type === 'ivec4' ) return new Int32Array( this.buffer.buffer ); @@ -326,6 +448,14 @@ class UniformsGroup extends UniformBuffer { } +/** + * Sets the values of the second array to the first array. + * + * @private + * @param {TypedArray} a - The first array. + * @param {TypedArray} b - The second array. + * @param {Number} offset - An index offset for the first array. + */ function setArray( a, b, offset ) { for ( let i = 0, l = b.length; i < l; i ++ ) { @@ -336,6 +466,15 @@ function setArray( a, b, offset ) { } +/** + * Returns `true` if the given arrays are equal. + * + * @private + * @param {TypedArray} a - The first array. + * @param {TypedArray} b - The second array. + * @param {Number} offset - An index offset for the first array. + * @return {Boolean} Whether the given arrays are equal or not. + */ function arraysEqual( a, b, offset ) { for ( let i = 0, l = b.length; i < l; i ++ ) { diff --git a/src/renderers/common/nodes/NodeBuilderState.js b/src/renderers/common/nodes/NodeBuilderState.js index dcdc2aaffda631..e6c1ef8441999e 100644 --- a/src/renderers/common/nodes/NodeBuilderState.js +++ b/src/renderers/common/nodes/NodeBuilderState.js @@ -1,34 +1,128 @@ import BindGroup from '../BindGroup.js'; +/** + * This module represents the state of a node builder after it was + * used to build the nodes for a render object. The state holds the + * results of the build for further processing in the renderer. + * + * Render objects with identical cache keys share the same node builder state. + * + * @private + */ class NodeBuilderState { + /** + * Constructs a new node builder state. + * + * @param {String?} vertexShader - The native vertex shader code. + * @param {String?} fragmentShader - The native fragment shader code. + * @param {String?} computeShader - The native compute shader code. + * @param {Array} nodeAttributes - An array of node attributes. + * @param {Array} bindings - An array of bind groups. + * @param {Array} updateNodes - An array of nodes that implement their `update()` method. + * @param {Array} updateBeforeNodes - An array of nodes that implement their `updateBefore()` method. + * @param {Array} updateAfterNodes - An array of nodes that implement their `updateAfter()` method. + * @param {NodeMaterialObserver} monitor - A node material observer. + * @param {Array} transforms - An array with transform attribute objects. Only relevant when using compute shaders with WebGL 2. + */ constructor( vertexShader, fragmentShader, computeShader, nodeAttributes, bindings, updateNodes, updateBeforeNodes, updateAfterNodes, monitor, transforms = [] ) { + /** + * The native vertex shader code. + * + * @type {String} + */ this.vertexShader = vertexShader; + + /** + * The native fragment shader code. + * + * @type {String} + */ this.fragmentShader = fragmentShader; + + /** + * The native compute shader code. + * + * @type {String} + */ this.computeShader = computeShader; + + /** + * An array with transform attribute objects. + * Only relevant when using compute shaders with WebGL 2. + * + * @type {Array} + */ this.transforms = transforms; + /** + * An array of node attributes representing + * the attributes of the shaders. + * + * @type {Array} + */ this.nodeAttributes = nodeAttributes; + + /** + * An array of bind groups representing the uniform or storage + * buffers, texture or samplers of the shader. + * + * @type {Array} + */ this.bindings = bindings; + /** + * An array of nodes that implement their `update()` method. + * + * @type {Array} + */ this.updateNodes = updateNodes; + + /** + * An array of nodes that implement their `updateBefore()` method. + * + * @type {Array} + */ this.updateBeforeNodes = updateBeforeNodes; + + /** + * An array of nodes that implement their `updateAfter()` method. + * + * @type {Array} + */ this.updateAfterNodes = updateAfterNodes; + /** + * A node material observer. + * + * @type {NodeMaterialObserver} + */ this.monitor = monitor; + /** + * How often this state is used by render objects. + * + * @type {Number} + */ this.usedTimes = 0; } + /** + * This method is used to create a array of bind groups based + * on the existing bind groups of this state. Shared groups are + * not cloned. + * + * @return {Array} A array of bind groups. + */ createBindings() { const bindings = []; for ( const instanceGroup of this.bindings ) { - const shared = instanceGroup.bindings[ 0 ].groupNode.shared; + const shared = instanceGroup.bindings[ 0 ].groupNode.shared; // TODO: Is it safe to always check the first binding in the group? if ( shared !== true ) { diff --git a/src/renderers/common/nodes/NodeLibrary.js b/src/renderers/common/nodes/NodeLibrary.js index eb1e7281b1fc7f..158aaa8e8cffcc 100644 --- a/src/renderers/common/nodes/NodeLibrary.js +++ b/src/renderers/common/nodes/NodeLibrary.js @@ -1,13 +1,52 @@ +/** + * The purpose of a node library is to assign node implementations + * to existing library features. In `WebGPURenderer` lights, materials + * which are not based on `NodeMaterial` as well as tone mapping techniques + * are implemented with node-based modules. + * + * @private + */ class NodeLibrary { + /** + * Constructs a new node library. + */ constructor() { + /** + * A weak map that maps lights to light nodes. + * + * @type {WeakMap} + */ this.lightNodes = new WeakMap(); + + /** + * A map that maps materials to node materials. + * + * @type {WeakMap} + */ this.materialNodes = new Map(); + + /** + * A map that maps tone mapping techniques (constants) + * to tone mapping node functions. + * + * @type {WeakMap} + */ this.toneMappingNodes = new Map(); } + /** + * Returns a matching node material instance for the given material object. + * + * This method also assigns/copies the properties of the given material object + * to the node material. This is done to make sure the current material + * configuration carries over to the node version. + * + * @param {Material} material - A material. + * @return {NodeMaterial} The corresponding node material. + */ fromMaterial( material ) { if ( material.isNodeMaterial ) return material; @@ -32,42 +71,85 @@ class NodeLibrary { } + /** + * Adds a tone mapping node function for a tone mapping technique (constant). + * + * @param {Function} toneMappingNode - The tone mapping node function. + * @param {Number} toneMapping - The tone mapping. + */ addToneMapping( toneMappingNode, toneMapping ) { this.addType( toneMappingNode, toneMapping, this.toneMappingNodes ); } + /** + * Returns a tone mapping node function for a tone mapping technique (constant). + * + * @param {Number} toneMapping - The tone mapping. + * @return {Function?} The tone mapping node function. Returns `null` if no node function is found. + */ getToneMappingFunction( toneMapping ) { return this.toneMappingNodes.get( toneMapping ) || null; } + /** + * Returns a node material class definition for a material type. + * + * @param {String} materialType - The material type. + * @return {NodeMaterial.constructor?} The node material class definition. Returns `null` if no node material is found. + */ getMaterialNodeClass( materialType ) { return this.materialNodes.get( materialType ) || null; } + /** + * Adds a node material class definition for a given material type. + * + * @param {NodeMaterial.constructor} materialNodeClass - The node material class definition. + * @param {String} materialClassType - The material type. + */ addMaterial( materialNodeClass, materialClassType ) { this.addType( materialNodeClass, materialClassType, this.materialNodes ); } + /** + * Returns a light node class definition for a light class definition. + * + * @param {Light.constructor} light - The light class definition. + * @return {AnalyticLightNode.constructor?} The light node class definition. Returns `null` if no light node is found. + */ getLightNodeClass( light ) { return this.lightNodes.get( light ) || null; } + /** + * Adds a light node class definition for a given light class definition. + * + * @param {AnalyticLightNode.constructor} lightNodeClass - The light node class definition. + * @param {Light.constructor} lightClass - The light class definition. + */ addLight( lightNodeClass, lightClass ) { this.addClass( lightNodeClass, lightClass, this.lightNodes ); } + /** + * Adds a node class definition for the given type to the provided type library. + * + * @param {Any} nodeClass - The node class definition. + * @param {String} type - The object type. + * @param {Map} library - The type library. + */ addType( nodeClass, type, library ) { if ( library.has( type ) ) { @@ -84,6 +166,13 @@ class NodeLibrary { } + /** + * Adds a node class definition for the given class definition to the provided type library. + * + * @param {Any} nodeClass - The node class definition. + * @param {Any} baseClass - The class definition. + * @param {WeakMap} library - The type library. + */ addClass( nodeClass, baseClass, library ) { if ( library.has( baseClass ) ) { diff --git a/src/renderers/common/nodes/NodeSampledTexture.js b/src/renderers/common/nodes/NodeSampledTexture.js index b23b165d00b928..0e9e915b920145 100644 --- a/src/renderers/common/nodes/NodeSampledTexture.js +++ b/src/renderers/common/nodes/NodeSampledTexture.js @@ -1,24 +1,69 @@ import { SampledTexture } from '../SampledTexture.js'; +/** + * A special form of sampled texture binding type. + * It's texture value is managed by a node object. + * + * @private + * @augments SampledTexture + */ class NodeSampledTexture extends SampledTexture { + /** + * Constructs a new node-based sampled texture. + * + * @param {String} name - The textures's name. + * @param {TextureNode} textureNode - The texture node. + * @param {UniformGroupNode} groupNode - The uniform group node. + * @param {String?} [access=null] - The access type. + */ constructor( name, textureNode, groupNode, access = null ) { super( name, textureNode ? textureNode.value : null ); + /** + * The texture node. + * + * @type {TextureNode} + */ this.textureNode = textureNode; + + /** + * The uniform group node. + * + * @type {UniformGroupNode} + */ this.groupNode = groupNode; + /** + * The access type. + * + * @type {String?} + * @default null + */ this.access = access; } + /** + * Overwrites the default to additionally check if the node value has changed. + * + * @param {Number} generation - The generation. + * @return {Boolean} Whether an update is required or not. + */ needsBindingsUpdate( generation ) { return this.textureNode.value !== this.texture || super.needsBindingsUpdate( generation ); } + /** + * Updates the binding. + * + * @param {Number} generation - The generation. + * @return {Boolean} Whether the texture has been updated and must be + * uploaded to the GPU. + */ update() { const { textureNode } = this; @@ -37,24 +82,68 @@ class NodeSampledTexture extends SampledTexture { } +/** + * A special form of sampled cube texture binding type. + * It's texture value is managed by a node object. + * + * @private + * @augments NodeSampledTexture + */ class NodeSampledCubeTexture extends NodeSampledTexture { - constructor( name, textureNode, groupNode, access ) { + /** + * Constructs a new node-based sampled cube texture. + * + * @param {String} name - The textures's name. + * @param {TextureNode} textureNode - The texture node. + * @param {UniformGroupNode} groupNode - The uniform group node. + * @param {String?} [access=null] - The access type. + */ + constructor( name, textureNode, groupNode, access = null ) { super( name, textureNode, groupNode, access ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isSampledCubeTexture = true; } } +/** + * A special form of sampled 3D texture binding type. + * It's texture value is managed by a node object. + * + * @private + * @augments NodeSampledTexture + */ class NodeSampledTexture3D extends NodeSampledTexture { - constructor( name, textureNode, groupNode, access ) { + /** + * Constructs a new node-based sampled 3D texture. + * + * @param {String} name - The textures's name. + * @param {TextureNode} textureNode - The texture node. + * @param {UniformGroupNode} groupNode - The uniform group node. + * @param {String?} [access=null] - The access type. + */ + constructor( name, textureNode, groupNode, access = null ) { super( name, textureNode, groupNode, access ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isSampledTexture3D = true; } diff --git a/src/renderers/common/nodes/NodeSampler.js b/src/renderers/common/nodes/NodeSampler.js index 7c4dbf3202388f..2a2f11ee38ce5f 100644 --- a/src/renderers/common/nodes/NodeSampler.js +++ b/src/renderers/common/nodes/NodeSampler.js @@ -1,16 +1,44 @@ import Sampler from '../Sampler.js'; +/** + * A special form of sampler binding type. + * It's texture value is managed by a node object. + * + * @private + * @augments Sampler + */ class NodeSampler extends Sampler { + /** + * Constructs a new node-based sampler. + * + * @param {String} name - The samplers's name. + * @param {TextureNode} textureNode - The texture node. + * @param {UniformGroupNode} groupNode - The uniform group node. + */ constructor( name, textureNode, groupNode ) { super( name, textureNode ? textureNode.value : null ); + /** + * The texture node. + * + * @type {TextureNode} + */ this.textureNode = textureNode; + + /** + * The uniform group node. + * + * @type {UniformGroupNode} + */ this.groupNode = groupNode; } + /** + * Updates the texture value of this sampler. + */ update() { this.texture = this.textureNode.value; diff --git a/src/renderers/common/nodes/NodeStorageBuffer.js b/src/renderers/common/nodes/NodeStorageBuffer.js index 0a5da2607d8f1d..daf82a1ed0123c 100644 --- a/src/renderers/common/nodes/NodeStorageBuffer.js +++ b/src/renderers/common/nodes/NodeStorageBuffer.js @@ -3,18 +3,53 @@ import { NodeAccess } from '../../../nodes/core/constants.js'; let _id = 0; +/** + * A special form of storage buffer binding type. + * It's buffer value is managed by a node object. + * + * @private + * @augments StorageBuffer + */ class NodeStorageBuffer extends StorageBuffer { + /** + * Constructs a new node-based storage buffer. + * + * @param {StorageBufferNode} nodeUniform - The storage buffer node. + * @param {UniformGroupNode} groupNode - The uniform group node. + */ constructor( nodeUniform, groupNode ) { super( 'StorageBuffer_' + _id ++, nodeUniform ? nodeUniform.value : null ); + /** + * The node uniform. + * + * @type {StorageBufferNode} + */ this.nodeUniform = nodeUniform; + + /** + * The access type. + * + * @type {String} + */ this.access = nodeUniform ? nodeUniform.access : NodeAccess.READ_WRITE; + + /** + * The uniform group node. + * + * @type {UniformGroupNode} + */ this.groupNode = groupNode; } + /** + * The storage buffer. + * + * @type {BufferAttribute} + */ get buffer() { return this.nodeUniform.value; diff --git a/src/renderers/common/nodes/NodeUniform.js b/src/renderers/common/nodes/NodeUniform.js index 384d4335f50437..9043e539f309a1 100644 --- a/src/renderers/common/nodes/NodeUniform.js +++ b/src/renderers/common/nodes/NodeUniform.js @@ -3,22 +3,49 @@ import { ColorUniform, Matrix3Uniform, Matrix4Uniform } from '../Uniform.js'; +/** + * A special form of Number uniform binding type. + * It's value is managed by a node object. + * + * @private + * @augments NumberUniform + */ class NumberNodeUniform extends NumberUniform { + /** + * Constructs a new node-based Number uniform. + * + * @param {NodeUniform} nodeUniform - The node uniform. + */ constructor( nodeUniform ) { super( nodeUniform.name, nodeUniform.value ); + /** + * The node uniform. + * + * @type {NodeUniform} + */ this.nodeUniform = nodeUniform; } + /** + * Overwritten to return the value of the node uniform. + * + * @return {Number} The value. + */ getValue() { return this.nodeUniform.value; } + /** + * Returns the node uniform data type. + * + * @return {String} The data type. + */ getType() { return this.nodeUniform.type; @@ -27,22 +54,49 @@ class NumberNodeUniform extends NumberUniform { } +/** + * A special form of Vector2 uniform binding type. + * It's value is managed by a node object. + * + * @private + * @augments Vector2Uniform + */ class Vector2NodeUniform extends Vector2Uniform { + /** + * Constructs a new node-based Vector2 uniform. + * + * @param {NodeUniform} nodeUniform - The node uniform. + */ constructor( nodeUniform ) { super( nodeUniform.name, nodeUniform.value ); + /** + * The node uniform. + * + * @type {NodeUniform} + */ this.nodeUniform = nodeUniform; } + /** + * Overwritten to return the value of the node uniform. + * + * @return {Vector2} The value. + */ getValue() { return this.nodeUniform.value; } + /** + * Returns the node uniform data type. + * + * @return {String} The data type. + */ getType() { return this.nodeUniform.type; @@ -51,22 +105,49 @@ class Vector2NodeUniform extends Vector2Uniform { } +/** + * A special form of Vector3 uniform binding type. + * It's value is managed by a node object. + * + * @private + * @augments Vector3Uniform + */ class Vector3NodeUniform extends Vector3Uniform { + /** + * Constructs a new node-based Vector3 uniform. + * + * @param {NodeUniform} nodeUniform - The node uniform. + */ constructor( nodeUniform ) { super( nodeUniform.name, nodeUniform.value ); + /** + * The node uniform. + * + * @type {NodeUniform} + */ this.nodeUniform = nodeUniform; } + /** + * Overwritten to return the value of the node uniform. + * + * @return {Vector3} The value. + */ getValue() { return this.nodeUniform.value; } + /** + * Returns the node uniform data type. + * + * @return {String} The data type. + */ getType() { return this.nodeUniform.type; @@ -75,22 +156,49 @@ class Vector3NodeUniform extends Vector3Uniform { } +/** + * A special form of Vector4 uniform binding type. + * It's value is managed by a node object. + * + * @private + * @augments Vector4Uniform + */ class Vector4NodeUniform extends Vector4Uniform { + /** + * Constructs a new node-based Vector4 uniform. + * + * @param {NodeUniform} nodeUniform - The node uniform. + */ constructor( nodeUniform ) { super( nodeUniform.name, nodeUniform.value ); + /** + * The node uniform. + * + * @type {NodeUniform} + */ this.nodeUniform = nodeUniform; } + /** + * Overwritten to return the value of the node uniform. + * + * @return {Vector4} The value. + */ getValue() { return this.nodeUniform.value; } + /** + * Returns the node uniform data type. + * + * @return {String} The data type. + */ getType() { return this.nodeUniform.type; @@ -99,22 +207,49 @@ class Vector4NodeUniform extends Vector4Uniform { } +/** + * A special form of Color uniform binding type. + * It's value is managed by a node object. + * + * @private + * @augments ColorUniform + */ class ColorNodeUniform extends ColorUniform { + /** + * Constructs a new node-based Color uniform. + * + * @param {NodeUniform} nodeUniform - The node uniform. + */ constructor( nodeUniform ) { super( nodeUniform.name, nodeUniform.value ); + /** + * The node uniform. + * + * @type {NodeUniform} + */ this.nodeUniform = nodeUniform; } + /** + * Overwritten to return the value of the node uniform. + * + * @return {Color} The value. + */ getValue() { return this.nodeUniform.value; } + /** + * Returns the node uniform data type. + * + * @return {String} The data type. + */ getType() { return this.nodeUniform.type; @@ -123,22 +258,49 @@ class ColorNodeUniform extends ColorUniform { } +/** + * A special form of Matrix3 uniform binding type. + * It's value is managed by a node object. + * + * @private + * @augments Matrix3Uniform + */ class Matrix3NodeUniform extends Matrix3Uniform { + /** + * Constructs a new node-based Matrix3 uniform. + * + * @param {NodeUniform} nodeUniform - The node uniform. + */ constructor( nodeUniform ) { super( nodeUniform.name, nodeUniform.value ); + /** + * The node uniform. + * + * @type {NodeUniform} + */ this.nodeUniform = nodeUniform; } + /** + * Overwritten to return the value of the node uniform. + * + * @return {Matrix3} The value. + */ getValue() { return this.nodeUniform.value; } + /** + * Returns the node uniform data type. + * + * @return {String} The data type. + */ getType() { return this.nodeUniform.type; @@ -147,22 +309,49 @@ class Matrix3NodeUniform extends Matrix3Uniform { } +/** + * A special form of Matrix4 uniform binding type. + * It's value is managed by a node object. + * + * @private + * @augments Matrix4Uniform + */ class Matrix4NodeUniform extends Matrix4Uniform { + /** + * Constructs a new node-based Matrix4 uniform. + * + * @param {NodeUniform} nodeUniform - The node uniform. + */ constructor( nodeUniform ) { super( nodeUniform.name, nodeUniform.value ); + /** + * The node uniform. + * + * @type {NodeUniform} + */ this.nodeUniform = nodeUniform; } + /** + * Overwritten to return the value of the node uniform. + * + * @return {Matrix4} The value. + */ getValue() { return this.nodeUniform.value; } + /** + * Returns the node uniform data type. + * + * @return {String} The data type. + */ getType() { return this.nodeUniform.type; diff --git a/src/renderers/common/nodes/NodeUniformBuffer.js b/src/renderers/common/nodes/NodeUniformBuffer.js index a323bb1c71fb90..d33c6f885c276e 100644 --- a/src/renderers/common/nodes/NodeUniformBuffer.js +++ b/src/renderers/common/nodes/NodeUniformBuffer.js @@ -2,17 +2,46 @@ import UniformBuffer from '../UniformBuffer.js'; let _id = 0; +/** + * A special form of uniform buffer binding type. + * It's buffer value is managed by a node object. + * + * @private + * @augments UniformBuffer + */ class NodeUniformBuffer extends UniformBuffer { + /** + * Constructs a new node-based uniform buffer. + * + * @param {BufferNode} nodeUniform - The uniform buffer node. + * @param {UniformGroupNode} groupNode - The uniform group node. + */ constructor( nodeUniform, groupNode ) { super( 'UniformBuffer_' + _id ++, nodeUniform ? nodeUniform.value : null ); + /** + * The uniform buffer node. + * + * @type {BufferNode} + */ this.nodeUniform = nodeUniform; + + /** + * The uniform group node. + * + * @type {UniformGroupNode} + */ this.groupNode = groupNode; } + /** + * The uniform buffer. + * + * @type {Float32Array} + */ get buffer() { return this.nodeUniform.value; diff --git a/src/renderers/common/nodes/NodeUniformsGroup.js b/src/renderers/common/nodes/NodeUniformsGroup.js index be2b7839f95ed0..cbdea97b97b636 100644 --- a/src/renderers/common/nodes/NodeUniformsGroup.js +++ b/src/renderers/common/nodes/NodeUniformsGroup.js @@ -2,37 +2,50 @@ import UniformsGroup from '../UniformsGroup.js'; let _id = 0; +/** + * A special form of uniforms group that represents + * the individual uniforms as node-based uniforms. + * + * @private + * @augments UniformsGroup + */ class NodeUniformsGroup extends UniformsGroup { + /** + * Constructs a new node-based uniforms group. + * + * @param {String} name - The group's name. + * @param {UniformGroupNode} groupNode - The uniform group node. + */ constructor( name, groupNode ) { super( name ); + /** + * The group's ID. + * + * @type {Number} + */ this.id = _id ++; + + /** + * The uniform group node. + * + * @type {UniformGroupNode} + */ this.groupNode = groupNode; + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isNodeUniformsGroup = true; } - getNodes() { - - const nodes = []; - - for ( const uniform of this.uniforms ) { - - const node = uniform.nodeUniform.node; - - if ( ! node ) throw new Error( 'NodeUniformsGroup: Uniform has no node.' ); - - nodes.push( node ); - - } - - return nodes; - - } - } export default NodeUniformsGroup; diff --git a/src/renderers/common/nodes/Nodes.js b/src/renderers/common/nodes/Nodes.js index a061ad9d700584..acdcc0d23304da 100644 --- a/src/renderers/common/nodes/Nodes.js +++ b/src/renderers/common/nodes/Nodes.js @@ -8,29 +8,93 @@ import { objectGroup, renderGroup, frameGroup, cubeTexture, texture, fog, rangeF import { CubeUVReflectionMapping, EquirectangularReflectionMapping, EquirectangularRefractionMapping } from '../../../constants.js'; import { hashArray } from '../../../nodes/core/NodeUtils.js'; -const outputNodeMap = new WeakMap(); - +const _outputNodeMap = new WeakMap(); +const _chainKeys = []; +const _cacheKeyValues = []; + +/** + * This renderer module manages node-related objects and is the + * primary interface between the renderer and the node system. + * + * @private + * @augments DataMap + */ class Nodes extends DataMap { + /** + * Constructs a new nodes management component. + * + * @param {Renderer} renderer - The renderer. + * @param {Backend} backend - The renderer's backend. + */ constructor( renderer, backend ) { super(); + /** + * The renderer. + * + * @type {Renderer} + */ this.renderer = renderer; + + /** + * The renderer's backend. + * + * @type {Backend} + */ this.backend = backend; + + /** + * The node frame. + * + * @type {Renderer} + */ this.nodeFrame = new NodeFrame(); + + /** + * A cache for managing node builder states. + * + * @type {Map} + */ this.nodeBuilderCache = new Map(); + + /** + * A cache for managing data cache key data. + * + * @type {ChainMap} + */ this.callHashCache = new ChainMap(); + + /** + * A cache for managing node uniforms group data. + * + * @type {ChainMap} + */ this.groupsData = new ChainMap(); + /** + * A cache for managing node objects of + * scene properties like fog or environments. + * + * @type {Object} + */ + this.cacheLib = {}; + } + /** + * Returns `true` if the given node uniforms group must be updated or not. + * + * @param {NodeUniformsGroup} nodeUniformsGroup - The node uniforms group. + * @return {Boolean} Whether the node uniforms group requires an update or not. + */ updateGroup( nodeUniformsGroup ) { const groupNode = nodeUniformsGroup.groupNode; const name = groupNode.name; - // objectGroup is every updated + // objectGroup is always updated if ( name === objectGroup.name ) return true; @@ -74,10 +138,13 @@ class Nodes extends DataMap { // other groups are updated just when groupNode.needsUpdate is true - const groupChain = [ groupNode, nodeUniformsGroup ]; + _chainKeys[ 0 ] = groupNode; + _chainKeys[ 1 ] = nodeUniformsGroup; - let groupData = this.groupsData.get( groupChain ); - if ( groupData === undefined ) this.groupsData.set( groupChain, groupData = {} ); + let groupData = this.groupsData.get( _chainKeys ); + if ( groupData === undefined ) this.groupsData.set( _chainKeys, groupData = {} ); + + _chainKeys.length = 0; if ( groupData.version !== groupNode.version ) { @@ -91,12 +158,24 @@ class Nodes extends DataMap { } + /** + * Returns the cache key for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @return {Number} The cache key. + */ getForRenderCacheKey( renderObject ) { return renderObject.initialCacheKey; } + /** + * Returns a node builder state for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @return {NodeBuilderState} The node builder state. + */ getForRender( renderObject ) { const renderObjectData = this.get( renderObject ); @@ -140,6 +219,12 @@ class Nodes extends DataMap { } + /** + * Deletes the given object from the internal data map + * + * @param {Any} object - The object to delete. + * @return {Object?} The deleted dictionary. + */ delete( object ) { if ( object.isRenderObject ) { @@ -159,6 +244,12 @@ class Nodes extends DataMap { } + /** + * Returns a node builder state for the given compute node. + * + * @param {Node} computeNode - The compute node. + * @return {NodeBuilderState} The node builder state. + */ getForCompute( computeNode ) { const computeData = this.get( computeNode ); @@ -180,6 +271,13 @@ class Nodes extends DataMap { } + /** + * Creates a node builder state for the given node builder. + * + * @private + * @param {NodeBuilder} nodeBuilder - The node builder. + * @return {NodeBuilderState} The node builder state. + */ _createNodeBuilderState( nodeBuilder ) { return new NodeBuilderState( @@ -197,71 +295,149 @@ class Nodes extends DataMap { } + /** + * Returns an environment node for the current configured + * scene environment. + * + * @param {Scene} scene - The scene. + * @return {Node} A node representing the current scene environment. + */ getEnvironmentNode( scene ) { - return scene.environmentNode || this.get( scene ).environmentNode || null; + this.updateEnvironment( scene ); + + let environmentNode = null; + + if ( scene.environmentNode && scene.environmentNode.isNode ) { + + environmentNode = scene.environmentNode; + + } else { + + const sceneData = this.get( scene ); + + if ( sceneData.environmentNode ) { + + environmentNode = sceneData.environmentNode; + + } + + } + + return environmentNode; } + /** + * Returns a background node for the current configured + * scene background. + * + * @param {Scene} scene - The scene. + * @return {Node} A node representing the current scene background. + */ getBackgroundNode( scene ) { - return scene.backgroundNode || this.get( scene ).backgroundNode || null; + this.updateBackground( scene ); + + let backgroundNode = null; + + if ( scene.backgroundNode && scene.backgroundNode.isNode ) { + + backgroundNode = scene.backgroundNode; + + } else { + + const sceneData = this.get( scene ); + + if ( sceneData.backgroundNode ) { + + backgroundNode = sceneData.backgroundNode; + + } + + } + + return backgroundNode; } + /** + * Returns a fog node for the current configured scene fog. + * + * @param {Scene} scene - The scene. + * @return {Node} A node representing the current scene fog. + */ getFogNode( scene ) { + this.updateFog( scene ); + return scene.fogNode || this.get( scene ).fogNode || null; } + /** + * Returns a cache key for the given scene and lights node. + * This key is used by `RenderObject` as a part of the dynamic + * cache key (a key that must be checked every time the render + * objects is drawn). + * + * @param {Scene} scene - The scene. + * @param {LightsNode} lightsNode - The lights node. + * @return {Number} The cache key. + */ getCacheKey( scene, lightsNode ) { - const chain = [ scene, lightsNode ]; + _chainKeys[ 0 ] = scene; + _chainKeys[ 1 ] = lightsNode; + const callId = this.renderer.info.calls; - let cacheKeyData = this.callHashCache.get( chain ); + const cacheKeyData = this.callHashCache.get( _chainKeys ) || {}; - if ( cacheKeyData === undefined || cacheKeyData.callId !== callId ) { + if ( cacheKeyData.callId !== callId ) { const environmentNode = this.getEnvironmentNode( scene ); const fogNode = this.getFogNode( scene ); - const values = []; + if ( lightsNode ) _cacheKeyValues.push( lightsNode.getCacheKey( true ) ); + if ( environmentNode ) _cacheKeyValues.push( environmentNode.getCacheKey() ); + if ( fogNode ) _cacheKeyValues.push( fogNode.getCacheKey() ); - if ( lightsNode ) values.push( lightsNode.getCacheKey( true ) ); - if ( environmentNode ) values.push( environmentNode.getCacheKey() ); - if ( fogNode ) values.push( fogNode.getCacheKey() ); + _cacheKeyValues.push( this.renderer.shadowMap.enabled ? 1 : 0 ); - values.push( this.renderer.shadowMap.enabled ? 1 : 0 ); + cacheKeyData.callId = callId; + cacheKeyData.cacheKey = hashArray( _cacheKeyValues ); - cacheKeyData = { - callId, - cacheKey: hashArray( values ) - }; + this.callHashCache.set( _chainKeys, cacheKeyData ); - this.callHashCache.set( chain, cacheKeyData ); + _cacheKeyValues.length = 0; } - return cacheKeyData.cacheKey; + _chainKeys.length = 0; - } - - updateScene( scene ) { - - this.updateEnvironment( scene ); - this.updateFog( scene ); - this.updateBackground( scene ); + return cacheKeyData.cacheKey; } + /** + * A boolean that indicates whether tone mapping should be enabled + * or not. + * + * @type {Boolean} + */ get isToneMappingState() { return this.renderer.getRenderTarget() ? false : true; } + /** + * If a scene background is configured, this method makes sure to + * represent the background with a corresponding node-based implementation. + * + * @param {Scene} scene - The scene. + */ updateBackground( scene ) { const sceneData = this.get( scene ); @@ -273,41 +449,43 @@ class Nodes extends DataMap { if ( sceneData.background !== background || forceUpdate ) { - let backgroundNode = null; + const backgroundNode = this.getCacheNode( 'background', background, () => { - if ( background.isCubeTexture === true || ( background.mapping === EquirectangularReflectionMapping || background.mapping === EquirectangularRefractionMapping || background.mapping === CubeUVReflectionMapping ) ) { + if ( background.isCubeTexture === true || ( background.mapping === EquirectangularReflectionMapping || background.mapping === EquirectangularRefractionMapping || background.mapping === CubeUVReflectionMapping ) ) { - if ( scene.backgroundBlurriness > 0 || background.mapping === CubeUVReflectionMapping ) { + if ( scene.backgroundBlurriness > 0 || background.mapping === CubeUVReflectionMapping ) { - backgroundNode = pmremTexture( background ); + return pmremTexture( background ); - } else { + } else { - let envMap; + let envMap; - if ( background.isCubeTexture === true ) { + if ( background.isCubeTexture === true ) { - envMap = cubeTexture( background ); + envMap = cubeTexture( background ); - } else { + } else { - envMap = texture( background ); + envMap = texture( background ); - } + } - backgroundNode = cubeMapNode( envMap ); + return cubeMapNode( envMap ); - } + } - } else if ( background.isTexture === true ) { + } else if ( background.isTexture === true ) { - backgroundNode = texture( background, screenUV.flipY() ).setUpdateMatrix( true ); + return texture( background, screenUV.flipY() ).setUpdateMatrix( true ); - } else if ( background.isColor !== true ) { + } else if ( background.isColor !== true ) { - console.error( 'WebGPUNodes: Unsupported background configuration.', background ); + console.error( 'WebGPUNodes: Unsupported background configuration.', background ); - } + } + + }, forceUpdate ); sceneData.backgroundNode = backgroundNode; sceneData.background = background; @@ -324,6 +502,39 @@ class Nodes extends DataMap { } + /** + * This method is part of the caching of nodes which are used to represents the + * scene's background, fog or environment. + * + * @param {String} type - The type of object to cache. + * @param {Object} object - The object. + * @param {Function} callback - A callback that produces a node representation for the given object. + * @param {Boolean} [forceUpdate=false] - Whether an update should be enforced or not. + * @return {Node} The node representation. + */ + getCacheNode( type, object, callback, forceUpdate = false ) { + + const nodeCache = this.cacheLib[ type ] || ( this.cacheLib[ type ] = new WeakMap() ); + + let node = nodeCache.get( object ); + + if ( node === undefined || forceUpdate ) { + + node = callback(); + nodeCache.set( object, node ); + + } + + return node; + + } + + /** + * If a scene fog is configured, this method makes sure to + * represent the fog with a corresponding node-based implementation. + * + * @param {Scene} scene - The scene. + */ updateFog( scene ) { const sceneData = this.get( scene ); @@ -333,28 +544,30 @@ class Nodes extends DataMap { if ( sceneData.fog !== sceneFog ) { - let fogNode = null; + const fogNode = this.getCacheNode( 'fog', sceneFog, () => { - if ( sceneFog.isFogExp2 ) { + if ( sceneFog.isFogExp2 ) { - const color = reference( 'color', 'color', sceneFog ).setGroup( renderGroup ); - const density = reference( 'density', 'float', sceneFog ).setGroup( renderGroup ); + const color = reference( 'color', 'color', sceneFog ).setGroup( renderGroup ); + const density = reference( 'density', 'float', sceneFog ).setGroup( renderGroup ); - fogNode = fog( color, densityFogFactor( density ) ); + return fog( color, densityFogFactor( density ) ); - } else if ( sceneFog.isFog ) { + } else if ( sceneFog.isFog ) { - const color = reference( 'color', 'color', sceneFog ).setGroup( renderGroup ); - const near = reference( 'near', 'float', sceneFog ).setGroup( renderGroup ); - const far = reference( 'far', 'float', sceneFog ).setGroup( renderGroup ); + const color = reference( 'color', 'color', sceneFog ).setGroup( renderGroup ); + const near = reference( 'near', 'float', sceneFog ).setGroup( renderGroup ); + const far = reference( 'far', 'float', sceneFog ).setGroup( renderGroup ); - fogNode = fog( color, rangeFogFactor( near, far ) ); + return fog( color, rangeFogFactor( near, far ) ); + + } else { - } else { + console.error( 'THREE.Renderer: Unsupported fog configuration.', sceneFog ); - console.error( 'WebGPUNodes: Unsupported fog configuration.', sceneFog ); + } - } + } ); sceneData.fogNode = fogNode; sceneData.fog = sceneFog; @@ -370,6 +583,12 @@ class Nodes extends DataMap { } + /** + * If a scene environment is configured, this method makes sure to + * represent the environment with a corresponding node-based implementation. + * + * @param {Scene} scene - The scene. + */ updateEnvironment( scene ) { const sceneData = this.get( scene ); @@ -379,21 +598,23 @@ class Nodes extends DataMap { if ( sceneData.environment !== environment ) { - let environmentNode = null; + const environmentNode = this.getCacheNode( 'environment', environment, () => { + + if ( environment.isCubeTexture === true ) { - if ( environment.isCubeTexture === true ) { + return cubeTexture( environment ); - environmentNode = cubeTexture( environment ); + } else if ( environment.isTexture === true ) { - } else if ( environment.isTexture === true ) { + return texture( environment ); - environmentNode = texture( environment ); + } else { - } else { + console.error( 'Nodes: Unsupported environment configuration.', environment ); - console.error( 'Nodes: Unsupported environment configuration.', environment ); + } - } + } ); sceneData.environmentNode = environmentNode; sceneData.environment = environment; @@ -428,6 +649,11 @@ class Nodes extends DataMap { } + /** + * Returns the current output cache key. + * + * @return {String} The output cache key. + */ getOutputCacheKey() { const renderer = this.renderer; @@ -436,27 +662,47 @@ class Nodes extends DataMap { } + /** + * Checks if the output configuration (tone mapping and color space) for + * the given target has changed. + * + * @param {Texture} outputTarget - The output target. + * @return {Boolean} Whether the output configuration has changed or not. + */ hasOutputChange( outputTarget ) { - const cacheKey = outputNodeMap.get( outputTarget ); + const cacheKey = _outputNodeMap.get( outputTarget ); return cacheKey !== this.getOutputCacheKey(); } - getOutputNode( outputTexture ) { + /** + * Returns a node that represents the output configuration (tone mapping and + * color space) for the current target. + * + * @param {Texture} outputTarget - The output target. + * @return {Node} The output node. + */ + getOutputNode( outputTarget ) { const renderer = this.renderer; const cacheKey = this.getOutputCacheKey(); - const output = texture( outputTexture, screenUV ).renderOutput( renderer.toneMapping, renderer.currentColorSpace ); + const output = texture( outputTarget, screenUV ).renderOutput( renderer.toneMapping, renderer.currentColorSpace ); - outputNodeMap.set( outputTexture, cacheKey ); + _outputNodeMap.set( outputTarget, cacheKey ); return output; } + /** + * Triggers the call of `updateBefore()` methods + * for all nodes of the given render object. + * + * @param {RenderObject} renderObject - The render object. + */ updateBefore( renderObject ) { const nodeBuilder = renderObject.getNodeBuilderState(); @@ -471,6 +717,12 @@ class Nodes extends DataMap { } + /** + * Triggers the call of `updateAfter()` methods + * for all nodes of the given render object. + * + * @param {RenderObject} renderObject - The render object. + */ updateAfter( renderObject ) { const nodeBuilder = renderObject.getNodeBuilderState(); @@ -485,6 +737,12 @@ class Nodes extends DataMap { } + /** + * Triggers the call of `update()` methods + * for all nodes of the given compute node. + * + * @param {Node} computeNode - The compute node. + */ updateForCompute( computeNode ) { const nodeFrame = this.getNodeFrame(); @@ -498,6 +756,12 @@ class Nodes extends DataMap { } + /** + * Triggers the call of `update()` methods + * for all nodes of the given compute node. + * + * @param {RenderObject} renderObject - The render object. + */ updateForRender( renderObject ) { const nodeFrame = this.getNodeFrameForRender( renderObject ); @@ -511,6 +775,12 @@ class Nodes extends DataMap { } + /** + * Returns `true` if the given render object requires a refresh. + * + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether the given render object requires a refresh or not. + */ needsRefresh( renderObject ) { const nodeFrame = this.getNodeFrameForRender( renderObject ); @@ -520,12 +790,16 @@ class Nodes extends DataMap { } + /** + * Frees the internal resources. + */ dispose() { super.dispose(); this.nodeFrame = new NodeFrame(); this.nodeBuilderCache = new Map(); + this.cacheLib = {}; } diff --git a/src/renderers/webgl-fallback/WebGLBackend.js b/src/renderers/webgl-fallback/WebGLBackend.js index a7e775991f1ca2..53924bc581f7e2 100644 --- a/src/renderers/webgl-fallback/WebGLBackend.js +++ b/src/renderers/webgl-fallback/WebGLBackend.js @@ -14,18 +14,184 @@ import { WebGLBufferRenderer } from './WebGLBufferRenderer.js'; import { warnOnce } from '../../utils.js'; import { WebGLCoordinateSystem } from '../../constants.js'; -// - +/** + * A backend implementation targeting WebGL 2. + * + * @private + * @augments Backend + */ class WebGLBackend extends Backend { + /** + * Constructs a new WebGPU backend. + * + * @param {Object} parameters - The configuration parameter. + * @param {Boolean} [parameters.logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not. + * @param {Boolean} [parameters.alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque. + * @param {Boolean} [parameters.depth=true] - Whether the default framebuffer should have a depth buffer or not. + * @param {Boolean} [parameters.stencil=false] - Whether the default framebuffer should have a stencil buffer or not. + * @param {Boolean} [parameters.antialias=false] - Whether MSAA as the default anti-aliasing should be enabled or not. + * @param {Number} [parameters.samples=0] - When `antialias` is `true`, `4` samples are used by default. Set this parameter to any other integer value than 0 to overwrite the default. + * @param {Boolean} [parameters.forceWebGL=false] - If set to `true`, the renderer uses a WebGL 2 backend no matter if WebGPU is supported or not. + * @param {WebGL2RenderingContext} [parameters.context=undefined] - A WebGL 2 rendering context. + */ constructor( parameters = {} ) { super( parameters ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isWebGLBackend = true; + /** + * A reference to a backend module holding shader attribute-related + * utility functions. + * + * @type {WebGLAttributeUtils?} + * @default null + */ + this.attributeUtils = null; + + /** + * A reference to a backend module holding extension-related + * utility functions. + * + * @type {WebGLExtensions?} + * @default null + */ + this.extensions = null; + + /** + * A reference to a backend module holding capability-related + * utility functions. + * + * @type {WebGLCapabilities?} + * @default null + */ + this.capabilities = null; + + /** + * A reference to a backend module holding texture-related + * utility functions. + * + * @type {WebGLTextureUtils?} + * @default null + */ + this.textureUtils = null; + + /** + * A reference to a backend module holding renderer-related + * utility functions. + * + * @type {WebGLBufferRenderer?} + * @default null + */ + this.bufferRenderer = null; + + /** + * A reference to the rendering context. + * + * @type {WebGL2RenderingContext?} + * @default null + */ + this.gl = null; + + /** + * A reference to a backend module holding state-related + * utility functions. + * + * @type {WebGLState?} + * @default null + */ + this.state = null; + + /** + * A reference to a backend module holding common + * utility functions. + * + * @type {WebGLUtils?} + * @default null + */ + this.utils = null; + + /** + * Dictionary for caching VAOs. + * + * @type {Object} + */ + this.vaoCache = {}; + + /** + * Dictionary for caching transform feedback objects. + * + * @type {Object} + */ + this.transformFeedbackCache = {}; + + /** + * Controls if `gl.RASTERIZER_DISCARD` should be enabled or not. + * Only relevant when using compute shaders. + * + * @type {Boolean} + * @default false + */ + this.discard = false; + + /** + * A reference to the `EXT_disjoint_timer_query_webgl2` extension. `null` if the + * device does not support the extension. + * + * @type {EXTDisjointTimerQueryWebGL2?} + * @default null + */ + this.disjoint = null; + + /** + * A reference to the `KHR_parallel_shader_compile` extension. `null` if the + * device does not support the extension. + * + * @type {KHRParallelShaderCompile?} + * @default null + */ + this.parallel = null; + + /** + * Whether to track timestamps with a Timestamp Query API or not. + * + * @type {Boolean} + * @default false + */ + this.trackTimestamp = ( parameters.trackTimestamp === true ); + + /** + * A reference to the current render context. + * + * @private + * @type {RenderContext} + * @default null + */ + this._currentContext = null; + + /** + * A unique collection of bindings. + * + * @private + * @type {WeakSet} + */ + this._knownBindings = new WeakSet(); + } + /** + * Initializes the backend so it is ready for usage. + * + * @param {Renderer} renderer - The renderer. + */ init( renderer ) { super.init( renderer ); @@ -66,11 +232,6 @@ class WebGLBackend extends Backend { this.state = new WebGLState( this ); this.utils = new WebGLUtils( this ); - this.vaoCache = {}; - this.transformFeedbackCache = {}; - this.discard = false; - this.trackTimestamp = ( parameters.trackTimestamp === true ); - this.extensions.get( 'EXT_color_buffer_float' ); this.extensions.get( 'WEBGL_clip_cull_distance' ); this.extensions.get( 'OES_texture_float_linear' ); @@ -82,30 +243,52 @@ class WebGLBackend extends Backend { this.disjoint = this.extensions.get( 'EXT_disjoint_timer_query_webgl2' ); this.parallel = this.extensions.get( 'KHR_parallel_shader_compile' ); - this._knownBindings = new WeakSet(); - - this._currentContext = null; - } + /** + * The coordinate system of the backend. + * + * @type {Number} + * @readonly + */ get coordinateSystem() { return WebGLCoordinateSystem; } + /** + * This method performs a readback operation by moving buffer data from + * a storage buffer attribute from the GPU to the CPU. + * + * @async + * @param {StorageBufferAttribute} attribute - The storage buffer attribute. + * @return {Promise} A promise that resolves with the buffer data when the data are ready. + */ async getArrayBufferAsync( attribute ) { return await this.attributeUtils.getArrayBufferAsync( attribute ); } + /** + * Can be used to synchronize CPU operations with GPU tasks. So when this method is called, + * the CPU waits for the GPU to complete its operation (e.g. a compute task). + * + * @async + * @return {Promise} A Promise that resolves when synchronization has been finished. + */ async waitForGPU() { await this.utils._clientWaitAsync(); } + /** + * Inits a time stamp query for the given render context. + * + * @param {RenderContext} renderContext - The render context. + */ initTimestampQuery( renderContext ) { if ( ! this.disjoint || ! this.trackTimestamp ) return; @@ -140,6 +323,11 @@ class WebGLBackend extends Backend { // timestamp utils + /** + * Prepares the timestamp buffer. + * + * @param {RenderContext} renderContext - The render context. + */ prepareTimestampBuffer( renderContext ) { if ( ! this.disjoint || ! this.trackTimestamp ) return; @@ -166,6 +354,14 @@ class WebGLBackend extends Backend { } + /** + * Resolves the time stamp for the given render context and type. + * + * @async + * @param {RenderContext} renderContext - The render context. + * @param {String} type - The render context. + * @return {Promise} A Promise that resolves when the time stamp has been computed. + */ async resolveTimestampAsync( renderContext, type = 'render' ) { if ( ! this.disjoint || ! this.trackTimestamp ) return; @@ -195,12 +391,23 @@ class WebGLBackend extends Backend { } + /** + * Returns the backend's rendering context. + * + * @return {WebGL2RenderingContext} The rendering context. + */ getContext() { return this.gl; } + /** + * This method is executed at the beginning of a render call and prepares + * the WebGL state for upcoming render calls + * + * @param {RenderContext} renderContext - The render context. + */ beginRender( renderContext ) { const { gl } = this; @@ -256,6 +463,12 @@ class WebGLBackend extends Backend { } + /** + * This method is executed at the end of a render call and finalizes work + * after draw calls. + * + * @param {RenderContext} renderContext - The render context. + */ finishRender( renderContext ) { const { gl, state } = this; @@ -362,6 +575,13 @@ class WebGLBackend extends Backend { } + /** + * This method processes the result of occlusion queries and writes it + * into render context data. + * + * @async + * @param {RenderContext} renderContext - The render context. + */ resolveOccludedAsync( renderContext ) { const renderContextData = this.get( renderContext ); @@ -391,7 +611,7 @@ class WebGLBackend extends Backend { if ( gl.getQueryParameter( query, gl.QUERY_RESULT_AVAILABLE ) ) { - if ( gl.getQueryParameter( query, gl.QUERY_RESULT ) > 0 ) occluded.add( currentOcclusionQueryObjects[ i ] ); + if ( gl.getQueryParameter( query, gl.QUERY_RESULT ) === 0 ) occluded.add( currentOcclusionQueryObjects[ i ] ); currentOcclusionQueries[ i ] = null; gl.deleteQuery( query ); @@ -420,6 +640,14 @@ class WebGLBackend extends Backend { } + /** + * Returns `true` if the given 3D object is fully occluded by other + * 3D objects in the scene. + * + * @param {RenderContext} renderContext - The render context. + * @param {Object3D} object - The 3D object to test. + * @return {Boolean} Whether the 3D object is fully occluded or not. + */ isOccluded( renderContext, object ) { const renderContextData = this.get( renderContext ); @@ -428,6 +656,11 @@ class WebGLBackend extends Backend { } + /** + * Updates the viewport with the values from the given render context. + * + * @param {RenderContext} renderContext - The render context. + */ updateViewport( renderContext ) { const gl = this.gl; @@ -437,6 +670,11 @@ class WebGLBackend extends Backend { } + /** + * Defines the scissor test. + * + * @param {Boolean} boolean - Whether the scissor test should be enabled or not. + */ setScissorTest( boolean ) { const gl = this.gl; @@ -453,6 +691,15 @@ class WebGLBackend extends Backend { } + /** + * Performs a clear operation. + * + * @param {Boolean} color - Whether the color buffer should be cleared or not. + * @param {Boolean} depth - Whether the depth buffer should be cleared or not. + * @param {Boolean} stencil - Whether the stencil buffer should be cleared or not. + * @param {Object?} [descriptor=null] - The render context of the current set render target. + * @param {Boolean} [setFrameBuffer=true] - TODO. + */ clear( color, depth, stencil, descriptor = null, setFrameBuffer = true ) { const { gl } = this; @@ -543,6 +790,12 @@ class WebGLBackend extends Backend { } + /** + * This method is executed at the beginning of a compute call and + * prepares the state for upcoming compute tasks. + * + * @param {Node|Array} computeGroup - The compute node(s). + */ beginCompute( computeGroup ) { const { state, gl } = this; @@ -552,11 +805,19 @@ class WebGLBackend extends Backend { } + /** + * Executes a compute command for the given compute node. + * + * @param {Node|Array} computeGroup - The group of compute nodes of a compute call. Can be a single compute node. + * @param {Node} computeNode - The compute node. + * @param {Array} bindings - The bindings. + * @param {ComputePipeline} pipeline - The compute pipeline. + */ compute( computeGroup, computeNode, bindings, pipeline ) { const { state, gl } = this; - if ( ! this.discard ) { + if ( this.discard === false ) { // required here to handle async behaviour of render.compute() gl.enable( gl.RASTERIZER_DISCARD ); @@ -621,6 +882,12 @@ class WebGLBackend extends Backend { } + /** + * This method is executed at the end of a compute call and + * finalizes work after compute tasks. + * + * @param {Node|Array} computeGroup - The compute node(s). + */ finishCompute( computeGroup ) { const gl = this.gl; @@ -639,6 +906,12 @@ class WebGLBackend extends Backend { } + /** + * Executes a draw command for the given render object. + * + * @param {RenderObject} renderObject - The render object to draw. + * @param {Info} info - Holds a series of statistical information about the GPU memory and the rendering process. + */ draw( renderObject/*, info*/ ) { const { object, pipeline, material, context, hardwareClippingPlanes } = renderObject; @@ -801,12 +1074,24 @@ class WebGLBackend extends Backend { } + /** + * Explain why always null is returned. + * + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether the render pipeline requires an update or not. + */ needsRenderUpdate( /*renderObject*/ ) { return false; } + /** + * Explain why no cache key is computed. + * + * @param {RenderObject} renderObject - The render object. + * @return {String} The cache key. + */ getRenderCacheKey( /*renderObject*/ ) { return ''; @@ -815,53 +1100,109 @@ class WebGLBackend extends Backend { // textures + /** + * Creates a default texture for the given texture that can be used + * as a placeholder until the actual texture is ready for usage. + * + * @param {Texture} texture - The texture to create a default texture for. + */ createDefaultTexture( texture ) { this.textureUtils.createDefaultTexture( texture ); } + /** + * Defines a texture on the GPU for the given texture object. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ createTexture( texture, options ) { this.textureUtils.createTexture( texture, options ); } + /** + * Uploads the updated texture data to the GPU. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ updateTexture( texture, options ) { this.textureUtils.updateTexture( texture, options ); } + /** + * Generates mipmaps for the given texture. + * + * @param {Texture} texture - The texture. + */ generateMipmaps( texture ) { this.textureUtils.generateMipmaps( texture ); } - + /** + * Destroys the GPU data for the given texture object. + * + * @param {Texture} texture - The texture. + */ destroyTexture( texture ) { this.textureUtils.destroyTexture( texture ); } - copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { + /** + * Returns texture data as a typed array. + * + * @async + * @param {Texture} texture - The texture to copy. + * @param {Number} x - The x coordinate of the copy origin. + * @param {Number} y - The y coordinate of the copy origin. + * @param {Number} width - The width of the copy. + * @param {Number} height - The height of the copy. + * @param {Number} faceIndex - The face index. + * @return {Promise} A Promise that resolves with a typed array when the copy operation has finished. + */ + async copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { return this.textureUtils.copyTextureToBuffer( texture, x, y, width, height, faceIndex ); } + /** + * This method does nothing since WebGL 2 has no concept of samplers. + * + * @param {Texture} texture - The texture to create the sampler for. + */ createSampler( /*texture*/ ) { //console.warn( 'Abstract class.' ); } - destroySampler() {} + /** + * This method does nothing since WebGL 2 has no concept of samplers. + * + * @param {Texture} texture - The texture to destroy the sampler for. + */ + destroySampler( /*texture*/ ) {} // node builder + /** + * Returns a node builder for the given render object. + * + * @param {RenderObject} object - The render object. + * @param {Renderer} renderer - The renderer. + * @return {GLSLNodeBuilder} The node builder. + */ createNodeBuilder( object, renderer ) { return new GLSLNodeBuilder( object, renderer ); @@ -870,6 +1211,11 @@ class WebGLBackend extends Backend { // program + /** + * Creates a shader program from the given programmable stage. + * + * @param {ProgrammableStage} program - The programmable stage. + */ createProgram( program ) { const gl = this.gl; @@ -886,12 +1232,23 @@ class WebGLBackend extends Backend { } - destroyProgram( /*program*/ ) { + /** + * Destroys the shader program of the given programmable stage. + * + * @param {ProgrammableStage} program - The programmable stage. + */ + destroyProgram( program ) { - console.warn( 'Abstract class.' ); + this.delete( program ); } + /** + * Creates a render pipeline for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @param {Array} promises - An array of compilation promises which are used in `compileAsync()`. + */ createRenderPipeline( renderObject, promises ) { const gl = this.gl; @@ -950,6 +1307,14 @@ class WebGLBackend extends Backend { } + /** + * Formats the source code of error messages. + * + * @private + * @param {String} string - The code. + * @param {Number} errorLine - The error line. + * @return {String} The formatted code. + */ _handleSource( string, errorLine ) { const lines = string.split( '\n' ); @@ -969,6 +1334,15 @@ class WebGLBackend extends Backend { } + /** + * Gets the shader compilation errors from the info log. + * + * @private + * @param {WebGL2RenderingContext} gl - The rendering context. + * @param {WebGLShader} shader - The WebGL shader object. + * @param {String} type - The shader type. + * @return {String} The shader errors. + */ _getShaderErrors( gl, shader, type ) { const status = gl.getShaderParameter( shader, gl.COMPILE_STATUS ); @@ -990,6 +1364,14 @@ class WebGLBackend extends Backend { } + /** + * Logs shader compilation errors. + * + * @private + * @param {WebGLProgram} programGPU - The WebGL program. + * @param {WebGLShader} glFragmentShader - The fragment shader as a native WebGL shader object. + * @param {WebGLShader} glVertexShader - The vertex shader as a native WebGL shader object. + */ _logProgramError( programGPU, glFragmentShader, glVertexShader ) { if ( this.renderer.debug.checkShaderErrors ) { @@ -1032,6 +1414,13 @@ class WebGLBackend extends Backend { } + /** + * Completes the shader program setup for the given render object. + * + * @private + * @param {RenderObject} renderObject - The render object. + * @param {RenderPipeline} pipeline - The render pipeline. + */ _completeCompile( renderObject, pipeline ) { const { state, gl } = this; @@ -1060,6 +1449,12 @@ class WebGLBackend extends Backend { } + /** + * Creates a compute pipeline for the given compute node. + * + * @param {ComputePipeline} computePipeline - The compute pipeline. + * @param {Array} bindings - The bindings. + */ createComputePipeline( computePipeline, bindings ) { const { state, gl } = this; @@ -1154,7 +1549,15 @@ class WebGLBackend extends Backend { } - createBindings( bindGroup, bindings ) { + /** + * Creates bindings from the given bind group definition. + * + * @param {BindGroup} bindGroup - The bind group. + * @param {Array} bindings - Array of bind groups. + * @param {Number} cacheIndex - The cache index. + * @param {Number} version - The version. + */ + createBindings( bindGroup, bindings /*, cacheIndex, version*/ ) { if ( this._knownBindings.has( bindings ) === false ) { @@ -1185,7 +1588,15 @@ class WebGLBackend extends Backend { } - updateBindings( bindGroup /*, bindings*/ ) { + /** + * Updates the given bind group definition. + * + * @param {BindGroup} bindGroup - The bind group. + * @param {Array} bindings - Array of bind groups. + * @param {Number} cacheIndex - The cache index. + * @param {Number} version - The version. + */ + updateBindings( bindGroup /*, bindings, cacheIndex, version*/ ) { const { gl } = this; @@ -1225,6 +1636,11 @@ class WebGLBackend extends Backend { } + /** + * Updates a buffer binding. + * + * @param {Buffer} binding - The buffer binding to update. + */ updateBinding( binding ) { const gl = this.gl; @@ -1244,6 +1660,11 @@ class WebGLBackend extends Backend { // attributes + /** + * Creates the GPU buffer of an indexed shader attribute. + * + * @param {BufferAttribute} attribute - The indexed buffer attribute. + */ createIndexAttribute( attribute ) { const gl = this.gl; @@ -1252,6 +1673,11 @@ class WebGLBackend extends Backend { } + /** + * Creates the GPU buffer of a shader attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ createAttribute( attribute ) { if ( this.has( attribute ) ) return; @@ -1262,6 +1688,11 @@ class WebGLBackend extends Backend { } + /** + * Creates the GPU buffer of a storage attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ createStorageAttribute( attribute ) { if ( this.has( attribute ) ) return; @@ -1272,24 +1703,34 @@ class WebGLBackend extends Backend { } + /** + * Updates the GPU buffer of a shader attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute to update. + */ updateAttribute( attribute ) { this.attributeUtils.updateAttribute( attribute ); } + /** + * Destroys the GPU buffer of a shader attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute to destroy. + */ destroyAttribute( attribute ) { this.attributeUtils.destroyAttribute( attribute ); } - updateSize() { - - //console.warn( 'Abstract class.' ); - - } - + /** + * Checks if the given feature is supported by the backend. + * + * @param {String} name - The feature's name. + * @return {Boolean} Whether the feature is supported or not. + */ hasFeature( name ) { const keysMatching = Object.keys( GLFeatureName ).filter( key => GLFeatureName[ key ] === name ); @@ -1306,24 +1747,51 @@ class WebGLBackend extends Backend { } + /** + * Returns the maximum anisotropy texture filtering value. + * + * @return {Number} The maximum anisotropy texture filtering value. + */ getMaxAnisotropy() { return this.capabilities.getMaxAnisotropy(); } - copyTextureToTexture( srcTexture, dstTexture, srcRegion, dstPosition, level ) { + /** + * Copies data of the given source texture to the given destination texture. + * + * @param {Texture} srcTexture - The source texture. + * @param {Texture} dstTexture - The destination texture. + * @param {Vector4?} [srcRegion=null] - The region of the source texture to copy. + * @param {(Vector2|Vector3)?} [dstPosition=null] - The destination position of the copy. + * @param {Number} [level=0] - The mip level to copy. + */ + copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { this.textureUtils.copyTextureToTexture( srcTexture, dstTexture, srcRegion, dstPosition, level ); } + /** + * Copies the current bound framebuffer to the given texture. + * + * @param {Texture} texture - The destination texture. + * @param {RenderContext} renderContext - The render context. + * @param {Vector4} rectangle - A four dimensional vector defining the origin and dimension of the copy. + */ copyFramebufferToTexture( texture, renderContext, rectangle ) { this.textureUtils.copyFramebufferToTexture( texture, renderContext, rectangle ); } + /** + * Configures the active framebuffer from the given render context. + * + * @private + * @param {RenderContext} descriptor - The render context. + */ _setFramebuffer( descriptor ) { const { gl, state } = this; @@ -1337,6 +1805,8 @@ class WebGLBackend extends Backend { const { samples, depthBuffer, stencilBuffer } = renderTarget; const isCube = renderTarget.isWebGLCubeRenderTarget === true; + const isRenderTarget3D = renderTarget.isRenderTarget3D === true; + const isRenderTargetArray = renderTarget.isRenderTargetArray === true; let msaaFb = renderTargetContextData.msaaFrameBuffer; let depthRenderbuffer = renderTargetContextData.depthRenderbuffer; @@ -1390,7 +1860,19 @@ class WebGLBackend extends Backend { const attachment = gl.COLOR_ATTACHMENT0 + i; - gl.framebufferTexture2D( gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureData.textureGPU, 0 ); + if ( isRenderTarget3D || isRenderTargetArray ) { + + const layer = this.renderer._activeCubeFace; + + gl.framebufferTextureLayer( gl.FRAMEBUFFER, attachment, textureData.textureGPU, 0, layer ); + + } else { + + gl.framebufferTexture2D( gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureData.textureGPU, 0 ); + + } + + } @@ -1482,10 +1964,17 @@ class WebGLBackend extends Backend { } - + /** + * Computes the VAO key for the given index and attributes. + * + * @private + * @param {BufferAttribute?} index - The index. `null` for non-indexed geometries. + * @param {Array} attributes - An array of buffer attributes. + * @return {String} The VAO key. + */ _getVaoKey( index, attributes ) { - let key = []; + let key = ''; if ( index !== null ) { @@ -1507,6 +1996,14 @@ class WebGLBackend extends Backend { } + /** + * Creates a VAO from the index and attributes. + * + * @private + * @param {BufferAttribute?} index - The index. `null` for non-indexed geometries. + * @param {Array} attributes - An array of buffer attributes. + * @return {Object} The VAO data. + */ _createVao( index, attributes ) { const { gl } = this; @@ -1584,6 +2081,13 @@ class WebGLBackend extends Backend { } + /** + * Creates a transform feedback from the given transform buffers. + * + * @private + * @param {Array} transformBuffers - The transform buffers. + * @return {WebGLTransformFeedback} The transform feedback. + */ _getTransformFeedback( transformBuffers ) { let key = ''; @@ -1624,7 +2128,13 @@ class WebGLBackend extends Backend { } - + /** + * Setups the given bindings. + * + * @private + * @param {Array} bindings - The bindings. + * @param {WebGLProgram} programGPU - The WebGL program. + */ _setupBindings( bindings, programGPU ) { const gl = this.gl; @@ -1654,6 +2164,12 @@ class WebGLBackend extends Backend { } + /** + * Binds the given uniforms. + * + * @private + * @param {Array} bindings - The bindings. + */ _bindUniforms( bindings ) { const { gl, state } = this; @@ -1682,6 +2198,9 @@ class WebGLBackend extends Backend { } + /** + * Frees internal resources. + */ dispose() { this.renderer.domElement.removeEventListener( 'webglcontextlost', this._onContextLost ); diff --git a/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js b/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js index 2ecc37a606a12b..597a3be33e4f3f 100644 --- a/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +++ b/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js @@ -45,39 +45,109 @@ precision highp isampler2DArray; precision lowp sampler2DShadow; `; +/** + * A node builder targeting GLSL. + * + * This module generates GLSL shader code from node materials and also + * generates the respective bindings and vertex buffer definitions. These + * data are later used by the renderer to create render and compute pipelines + * for render objects. + * + * @augments NodeBuilder + */ class GLSLNodeBuilder extends NodeBuilder { + /** + * Constructs a new GLSL node builder renderer. + * + * @param {Object3D} object - The 3D object. + * @param {Renderer} renderer - The renderer. + */ constructor( object, renderer ) { super( object, renderer, new GLSLNodeParser() ); + /** + * A dictionary holds for each shader stage ('vertex', 'fragment', 'compute') + * another dictionary which manages UBOs per group ('render','frame','object'). + * + * @type {Object>} + */ this.uniformGroups = {}; + + /** + * An array that holds objects defining the varying and attribute data in + * context of Transform Feedback. + * + * @type {Object>} + */ this.transforms = []; + + /** + * A dictionary that holds for each shader stage a Map of used extensions. + * + * @type {Object>} + */ this.extensions = {}; + + /** + * A dictionary that holds for each shader stage an Array of used builtins. + * + * @type {Object>} + */ this.builtins = { vertex: [], fragment: [], compute: [] }; + /** + * Whether comparison in shader code are generated with methods or not. + * + * @type {Boolean} + * @default true + */ this.useComparisonMethod = true; } + /** + * Checks if the given texture requires a manual conversion to the working color space. + * + * @param {Texture} texture - The texture to check. + * @return {Boolean} Whether the given texture requires a conversion to working color space or not. + */ needsToWorkingColorSpace( texture ) { return texture.isVideoTexture === true && texture.colorSpace !== NoColorSpace; } + /** + * Returns the native shader method name for a given generic name. + * + * @param {String} method - The method name to resolve. + * @return {String} The resolved GLSL method name. + */ getMethod( method ) { return glslMethods[ method ] || method; } + /** + * Returns the output struct name. Not relevant for GLSL. + * + * @return {String} + */ getOutputStructName() { return ''; } + /** + * Builds the given shader node. + * + * @param {ShaderNodeInternal} shaderNode - The shader node. + * @return {String} The GLSL function code. + */ buildFunctionCode( shaderNode ) { const layout = shaderNode.layout; @@ -108,6 +178,12 @@ ${ flowData.code } } + /** + * Setups the Pixel Buffer Object (PBO) for the given storage + * buffer node. + * + * @param {StorageBufferNode} storageBufferNode - The storage buffer node. + */ setupPBO( storageBufferNode ) { const attribute = storageBufferNode.value; @@ -176,6 +252,13 @@ ${ flowData.code } } + /** + * Returns a GLSL snippet that represents the property name of the given node. + * + * @param {Node} node - The node. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The property name. + */ getPropertyName( node, shaderStage = this.shaderStage ) { if ( node.isNodeUniform && node.node.isTextureNode !== true && node.node.isBufferNode !== true ) { @@ -188,6 +271,13 @@ ${ flowData.code } } + /** + * Setups the Pixel Buffer Object (PBO) for the given storage + * buffer node. + * + * @param {StorageArrayElementNode} storageArrayElementNode - The storage array element node. + * @return {String} The property name. + */ generatePBO( storageArrayElementNode ) { const { node, indexNode } = storageArrayElementNode; @@ -270,6 +360,16 @@ ${ flowData.code } } + /** + * Generates the GLSL snippet that reads a single texel from a texture without sampling or filtering. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvIndexSnippet - A GLSL snippet that represents texture coordinates used for sampling. + * @param {String?} depthSnippet - A GLSL snippet that represents the 0-based texture array index to sample. + * @param {String} [levelSnippet='0u'] - A GLSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @return {String} The GLSL snippet. + */ generateTextureLoad( texture, textureProperty, uvIndexSnippet, depthSnippet, levelSnippet = '0' ) { if ( depthSnippet ) { @@ -284,6 +384,15 @@ ${ flowData.code } } + /** + * Generates the GLSL snippet for sampling/loading the given texture. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A GLSL snippet that represents texture coordinates used for sampling. + * @param {String?} depthSnippet - A GLSL snippet that represents the 0-based texture array index to sample. + * @return {String} The GLSL snippet. + */ generateTexture( texture, textureProperty, uvSnippet, depthSnippet ) { if ( texture.isDepthTexture ) { @@ -300,24 +409,63 @@ ${ flowData.code } } + /** + * Generates the GLSL snippet when sampling textures with explicit mip level. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A GLSL snippet that represents texture coordinates used for sampling. + * @param {String} levelSnippet - A GLSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @return {String} The GLSL snippet. + */ generateTextureLevel( texture, textureProperty, uvSnippet, levelSnippet ) { return `textureLod( ${ textureProperty }, ${ uvSnippet }, ${ levelSnippet } )`; } + /** + * Generates the GLSL snippet when sampling textures with a bias to the mip level. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A GLSL snippet that represents texture coordinates used for sampling. + * @param {String} biasSnippet - A GLSL snippet that represents the bias to apply to the mip level before sampling. + * @return {String} The GLSL snippet. + */ generateTextureBias( texture, textureProperty, uvSnippet, biasSnippet ) { return `texture( ${ textureProperty }, ${ uvSnippet }, ${ biasSnippet } )`; } + /** + * Generates the GLSL snippet for sampling/loading the given texture using explicit gradients. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A GLSL snippet that represents texture coordinates used for sampling. + * @param {Array} gradSnippet - An array holding both gradient GLSL snippets. + * @return {String} The GLSL snippet. + */ generateTextureGrad( texture, textureProperty, uvSnippet, gradSnippet ) { return `textureGrad( ${ textureProperty }, ${ uvSnippet }, ${ gradSnippet[ 0 ] }, ${ gradSnippet[ 1 ] } )`; } + /** + * Generates the GLSL snippet for sampling a depth texture and comparing the sampled depth values + * against a reference value. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A GLSL snippet that represents texture coordinates used for sampling. + * @param {String} compareSnippet - A GLSL snippet that represents the reference value. + * @param {String?} depthSnippet - A GLSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The GLSL snippet. + */ generateTextureCompare( texture, textureProperty, uvSnippet, compareSnippet, depthSnippet, shaderStage = this.shaderStage ) { if ( shaderStage === 'fragment' ) { @@ -332,6 +480,12 @@ ${ flowData.code } } + /** + * Returns the variables of the given shader stage as a GLSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The GLSL snippet that defines the variables. + */ getVars( shaderStage ) { const snippets = []; @@ -352,6 +506,12 @@ ${ flowData.code } } + /** + * Returns the uniforms of the given shader stage as a GLSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The GLSL snippet that defines the uniforms. + */ getUniforms( shaderStage ) { const uniforms = this.uniforms[ shaderStage ]; @@ -469,6 +629,12 @@ ${ flowData.code } } + /** + * Returns the type for a given buffer attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + * @return {String} The type. + */ getTypeFromAttribute( attribute ) { let nodeType = super.getTypeFromAttribute( attribute ); @@ -493,6 +659,12 @@ ${ flowData.code } } + /** + * Returns the shader attributes of the given shader stage as a GLSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The GLSL snippet that defines the shader attributes. + */ getAttributes( shaderStage ) { let snippet = ''; @@ -515,6 +687,12 @@ ${ flowData.code } } + /** + * Returns the members of the given struct type node as a GLSL string. + * + * @param {StructTypeNode} struct - The struct type node. + * @return {String} The GLSL snippet that defines the struct members. + */ getStructMembers( struct ) { const snippets = []; @@ -531,6 +709,12 @@ ${ flowData.code } } + /** + * Returns the structs of the given shader stage as a GLSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The GLSL snippet that defines the structs. + */ getStructs( shaderStage ) { const snippets = []; @@ -558,6 +742,12 @@ ${ flowData.code } } + /** + * Returns the varyings of the given shader stage as a GLSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The GLSL snippet that defines the varyings. + */ getVaryings( shaderStage ) { let snippet = ''; @@ -603,18 +793,33 @@ ${ flowData.code } } + /** + * Returns the vertex index builtin. + * + * @return {String} The vertex index. + */ getVertexIndex() { return 'uint( gl_VertexID )'; } + /** + * Returns the instance index builtin. + * + * @return {String} The instance index. + */ getInstanceIndex() { return 'uint( gl_InstanceID )'; } + /** + * Returns the invocation local index builtin. + * + * @return {String} The invocation local index. + */ getInvocationLocalIndex() { const workgroupSize = this.object.workgroupSize; @@ -625,6 +830,11 @@ ${ flowData.code } } + /** + * Returns the draw index builtin. + * + * @return {String?} The drawIndex shader string. Returns `null` if `WEBGL_multi_draw` isn't supported by the device. + */ getDrawIndex() { const extensions = this.renderer.backend.extensions; @@ -639,24 +849,46 @@ ${ flowData.code } } + /** + * Returns the front facing builtin. + * + * @return {String} The front facing builtin. + */ getFrontFacing() { return 'gl_FrontFacing'; } + /** + * Returns the frag coord builtin. + * + * @return {String} The frag coord builtin. + */ getFragCoord() { return 'gl_FragCoord.xy'; } + /** + * Returns the frag depth builtin. + * + * @return {String} The frag depth builtin. + */ getFragDepth() { return 'gl_FragDepth'; } + /** + * Enables the given extension. + * + * @param {String} name - The extension name. + * @param {String} behavior - The extension behavior. + * @param {String} [shaderStage=this.shaderStage] - The shader stage. + */ enableExtension( name, behavior, shaderStage = this.shaderStage ) { const map = this.extensions[ shaderStage ] || ( this.extensions[ shaderStage ] = new Map() ); @@ -672,6 +904,12 @@ ${ flowData.code } } + /** + * Returns the enabled extensions of the given shader stage as a GLSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The GLSL snippet that defines the enabled extensions. + */ getExtensions( shaderStage ) { const snippets = []; @@ -705,12 +943,23 @@ ${ flowData.code } } + /** + * Returns the clip distances builtin. + * + * @return {String} The clip distances builtin. + */ getClipDistance() { return 'gl_ClipDistance'; } + /** + * Whether the requested feature is available or not. + * + * @param {String} name - The requested feature. + * @return {Boolean} Whether the requested feature is supported or not. + */ isAvailable( name ) { let result = supports[ name ]; @@ -754,12 +1003,22 @@ ${ flowData.code } } + /** + * Whether to flip texture data along its vertical axis or not. + * + * @return {Boolean} Returns always `true` in context of GLSL. + */ isFlipY() { return true; } + /** + * Enables hardware clipping. + * + * @param {String} planeCount - The clipping plane count. + */ enableHardwareClipping( planeCount ) { this.enableExtension( 'GL_ANGLE_clip_cull_distance', 'require' ); @@ -768,12 +1027,24 @@ ${ flowData.code } } + /** + * Registers a transform in context of Transform Feedback. + * + * @param {String} varyingName - The varying name. + * @param {AttributeNode} attributeNode - The attribute node. + */ registerTransform( varyingName, attributeNode ) { this.transforms.push( { varyingName, attributeNode } ); } + /** + * Returns the transforms of the given shader stage as a GLSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The GLSL snippet that defines the transforms. + */ getTransforms( /* shaderStage */ ) { const transforms = this.transforms; @@ -794,6 +1065,14 @@ ${ flowData.code } } + /** + * Returns a GLSL struct based on the given name and variables. + * + * @private + * @param {String} name - The struct name. + * @param {String} vars - The struct variables. + * @return {String} The GLSL snippet representing a struct. + */ _getGLSLUniformStruct( name, vars ) { return ` @@ -803,6 +1082,13 @@ ${vars} } + /** + * Returns a GLSL vertex shader based on the given shader data. + * + * @private + * @param {Object} shaderData - The shader data. + * @return {String} The vertex shader. + */ _getGLSLVertexCode( shaderData ) { return `#version 300 es @@ -845,6 +1131,13 @@ void main() { } + /** + * Returns a GLSL fragment shader based on the given shader data. + * + * @private + * @param {Object} shaderData - The shader data. + * @return {String} The vertex shader. + */ _getGLSLFragmentCode( shaderData ) { return `#version 300 es @@ -878,6 +1171,9 @@ void main() { } + /** + * Controls the code build of the shader stages. + */ buildCode() { const shadersData = this.material !== null ? { fragment: {}, vertex: {} } : { compute: {} }; @@ -958,6 +1254,19 @@ void main() { } + /** + * This method is one of the more important ones since it's responsible + * for generating a matching binding instance for the given uniform node. + * + * These bindings are later used in the renderer to create bind groups + * and layouts. + * + * @param {UniformNode} node - The uniform node. + * @param {String} type - The node data type. + * @param {String} shaderStage - The shader stage. + * @param {String?} [name=null] - An optional uniform name. + * @return {NodeUniform} The node uniform object. + */ getUniformFromNode( node, type, shaderStage, name = null ) { const uniformNode = super.getUniformFromNode( node, type, shaderStage, name ); diff --git a/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js b/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js index d1ef9c24fd8662..4082a9d5aefb44 100644 --- a/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js +++ b/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js @@ -2,6 +2,14 @@ import { IntType } from '../../../constants.js'; let _id = 0; +/** + * This module is internally used in context of compute shaders. + * This type of shader is not natively supported in WebGL 2 and + * thus implemented via Transform Feedback. `DualAttributeData` + * manages the related data. + * + * @private + */ class DualAttributeData { constructor( attributeData, dualBuffer ) { @@ -46,14 +54,35 @@ class DualAttributeData { } +/** + * A WebGL 2 backend utility module for managing shader attributes. + * + * @private + */ class WebGLAttributeUtils { + /** + * Constructs a new utility object. + * + * @param {WebGLBackend} backend - The WebGL 2 backend. + */ constructor( backend ) { + /** + * A reference to the WebGL 2 backend. + * + * @type {WebGLBackend} + */ this.backend = backend; } + /** + * Creates the GPU buffer for the given buffer attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + * @param {GLenum } bufferType - A flag that indicates the buffer type and thus binding point target. + */ createAttribute( attribute, bufferType ) { const backend = this.backend; @@ -151,6 +180,11 @@ class WebGLAttributeUtils { } + /** + * Updates the GPU buffer of the given buffer attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ updateAttribute( attribute ) { const backend = this.backend; @@ -190,6 +224,11 @@ class WebGLAttributeUtils { } + /** + * Destroys the GPU buffer of the given buffer attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ destroyAttribute( attribute ) { const backend = this.backend; @@ -209,6 +248,14 @@ class WebGLAttributeUtils { } + /** + * This method performs a readback operation by moving buffer data from + * a storage buffer attribute from the GPU to the CPU. + * + * @async + * @param {StorageBufferAttribute} attribute - The storage buffer attribute. + * @return {Promise} A promise that resolves with the buffer data when the data are ready. + */ async getArrayBufferAsync( attribute ) { const backend = this.backend; @@ -247,6 +294,16 @@ class WebGLAttributeUtils { } + /** + * Creates a WebGL buffer with the given data. + * + * @private + * @param {WebGL2RenderingContext} gl - The rendering context. + * @param {GLenum } bufferType - A flag that indicates the buffer type and thus binding point target. + * @param {TypedArray} array - The array of the buffer attribute. + * @param {GLenum} usage - The usage. + * @return {WebGLBuffer} The WebGL buffer. + */ _createBuffer( gl, bufferType, array, usage ) { const bufferGPU = gl.createBuffer(); diff --git a/src/renderers/webgl-fallback/utils/WebGLCapabilities.js b/src/renderers/webgl-fallback/utils/WebGLCapabilities.js index 52f0df44684050..8aff47cd3654ea 100644 --- a/src/renderers/webgl-fallback/utils/WebGLCapabilities.js +++ b/src/renderers/webgl-fallback/utils/WebGLCapabilities.js @@ -1,13 +1,41 @@ +/** + * A WebGL 2 backend utility module for managing the device's capabilities. + * + * @private + */ class WebGLCapabilities { + /** + * Constructs a new utility object. + * + * @param {WebGLBackend} backend - The WebGL 2 backend. + */ constructor( backend ) { + /** + * A reference to the WebGL 2 backend. + * + * @type {WebGLBackend} + */ this.backend = backend; + /** + * This value holds the cached max anisotropy value. + * + * @type {Number?} + * @default null + */ this.maxAnisotropy = null; } + /** + * Returns the maximum anisotropy texture filtering value. This value + * depends on the device and is reported by the `EXT_texture_filter_anisotropic` + * WebGL extension. + * + * @return {Number} The maximum anisotropy texture filtering value. + */ getMaxAnisotropy() { if ( this.maxAnisotropy !== null ) return this.maxAnisotropy; diff --git a/src/renderers/webgl-fallback/utils/WebGLExtensions.js b/src/renderers/webgl-fallback/utils/WebGLExtensions.js index dfb0e5740f9043..ee5d2a33898a2c 100644 --- a/src/renderers/webgl-fallback/utils/WebGLExtensions.js +++ b/src/renderers/webgl-fallback/utils/WebGLExtensions.js @@ -1,16 +1,55 @@ +/** + * A WebGL 2 backend utility module for managing extensions. + * + * @private + */ class WebGLExtensions { + /** + * Constructs a new utility object. + * + * @param {WebGLBackend} backend - The WebGL 2 backend. + */ constructor( backend ) { + /** + * A reference to the WebGL 2 backend. + * + * @type {WebGLBackend} + */ this.backend = backend; + /** + * A reference to the rendering context. + * + * @type {WebGL2RenderingContext} + */ this.gl = this.backend.gl; + + /** + * A list with all the supported WebGL extensions. + * + * @type {Array} + */ this.availableExtensions = this.gl.getSupportedExtensions(); + /** + * A dictionary with requested WebGL extensions. + * The key is the name of the extension, the value + * the requested extension object. + * + * @type {Object} + */ this.extensions = {}; } + /** + * Returns the extension object for the given extension name. + * + * @param {String} name - The extension name. + * @return {Object} The extension object. + */ get( name ) { let extension = this.extensions[ name ]; @@ -27,6 +66,12 @@ class WebGLExtensions { } + /** + * Returns `true` if the requested extension is available. + * + * @param {String} name - The extension name. + * @return {Boolean} Whether the given extension is available or not. + */ has( name ) { return this.availableExtensions.includes( name ); diff --git a/src/renderers/webgl-fallback/utils/WebGLState.js b/src/renderers/webgl-fallback/utils/WebGLState.js index 3e0569eca35e44..c623c82c072e04 100644 --- a/src/renderers/webgl-fallback/utils/WebGLState.js +++ b/src/renderers/webgl-fallback/utils/WebGLState.js @@ -9,14 +9,43 @@ import { let initialized = false, equationToGL, factorToGL; +/** + * A WebGL 2 backend utility module for managing the WebGL state. + * + * The major goal of this module is to reduce the number of state changes + * by caching the WEbGL state with a series of variables. In this way, the + * renderer only executes state change commands when necessary which + * improves the overall performance. + * + * @private + */ class WebGLState { + /** + * Constructs a new utility object. + * + * @param {WebGLBackend} backend - The WebGL 2 backend. + */ constructor( backend ) { + /** + * A reference to the WebGL 2 backend. + * + * @type {WebGLBackend} + */ this.backend = backend; + /** + * A reference to the rendering context. + * + * @type {WebGL2RenderingContext} + */ this.gl = this.backend.gl; + // Below properties are intended to cache + // the WebGL state and are not explicitly + // documented for convenience reasons. + this.enabled = {}; this.currentFlipSided = null; this.currentCullFace = null; @@ -53,7 +82,7 @@ class WebGLState { if ( initialized === false ) { - this._init( this.gl ); + this._init(); initialized = true; @@ -61,7 +90,14 @@ class WebGLState { } - _init( gl ) { + /** + * Inits the state of the utility. + * + * @private + */ + _init() { + + const gl = this.gl; // Store only WebGL constants here. @@ -87,6 +123,14 @@ class WebGLState { } + /** + * Enables the given WebGL capability. + * + * This method caches the capability state so + * `gl.enable()` is only called when necessary. + * + * @param {GLenum} id - The capability to enable. + */ enable( id ) { const { enabled } = this; @@ -100,6 +144,14 @@ class WebGLState { } + /** + * Disables the given WebGL capability. + * + * This method caches the capability state so + * `gl.disable()` is only called when necessary. + * + * @param {GLenum} id - The capability to enable. + */ disable( id ) { const { enabled } = this; @@ -113,6 +165,15 @@ class WebGLState { } + /** + * Specifies whether polygons are front- or back-facing + * by setting the winding orientation. + * + * This method caches the state so `gl.frontFace()` is only + * called when necessary. + * + * @param {Boolean} flipSided - Whether triangles flipped their sides or not. + */ setFlipSided( flipSided ) { if ( this.currentFlipSided !== flipSided ) { @@ -135,6 +196,15 @@ class WebGLState { } + /** + * Specifies whether or not front- and/or back-facing + * polygons can be culled. + * + * This method caches the state so `gl.cullFace()` is only + * called when necessary. + * + * @param {Number} cullFace - Defines which polygons are candidates for culling. + */ setCullFace( cullFace ) { const { gl } = this; @@ -171,6 +241,14 @@ class WebGLState { } + /** + * Specifies the width of line primitives. + * + * This method caches the state so `gl.lineWidth()` is only + * called when necessary. + * + * @param {Number} width - The line width. + */ setLineWidth( width ) { const { currentLineWidth, gl } = this; @@ -185,7 +263,21 @@ class WebGLState { } - + /** + * Defines the blending. + * + * This method caches the state so `gl.blendEquation()`, `gl.blendEquationSeparate()`, + * `gl.blendFunc()` and `gl.blendFuncSeparate()` are only called when necessary. + * + * @param {Number} blending - The blending type. + * @param {Number} blendEquation - The blending equation. + * @param {Number} blendSrc - Only relevant for custom blending. The RGB source blending factor. + * @param {Number} blendDst - Only relevant for custom blending. The RGB destination blending factor. + * @param {Number} blendEquationAlpha - Only relevant for custom blending. The blending equation for alpha. + * @param {Number} blendSrcAlpha - Only relevant for custom blending. The alpha source blending factor. + * @param {Number} blendDstAlpha - Only relevant for custom blending. The alpha destination blending factor. + * @param {Boolean} premultipliedAlpha - Whether premultiplied alpha is enabled or not. + */ setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) { const { gl } = this; @@ -322,6 +414,15 @@ class WebGLState { } + /** + * Specifies whether colors can be written when rendering + * into a framebuffer or not. + * + * This method caches the state so `gl.colorMask()` is only + * called when necessary. + * + * @param {Boolean} colorMask - The color mask. + */ setColorMask( colorMask ) { if ( this.currentColorMask !== colorMask ) { @@ -333,6 +434,11 @@ class WebGLState { } + /** + * Specifies whether the depth test is enabled or not. + * + * @param {Boolean} depthTest - Whether the depth test is enabled or not. + */ setDepthTest( depthTest ) { const { gl } = this; @@ -349,6 +455,15 @@ class WebGLState { } + /** + * Specifies whether depth values can be written when rendering + * into a framebuffer or not. + * + * This method caches the state so `gl.depthMask()` is only + * called when necessary. + * + * @param {Boolean} depthMask - The depth mask. + */ setDepthMask( depthMask ) { if ( this.currentDepthMask !== depthMask ) { @@ -360,6 +475,14 @@ class WebGLState { } + /** + * Specifies the depth compare function. + * + * This method caches the state so `gl.depthFunc()` is only + * called when necessary. + * + * @param {Number} depthFunc - The depth compare function. + */ setDepthFunc( depthFunc ) { if ( this.currentDepthFunc !== depthFunc ) { @@ -420,6 +543,11 @@ class WebGLState { } + /** + * Specifies whether the stencil test is enabled or not. + * + * @param {Boolean} stencilTest - Whether the stencil test is enabled or not. + */ setStencilTest( stencilTest ) { const { gl } = this; @@ -436,6 +564,15 @@ class WebGLState { } + /** + * Specifies whether stencil values can be written when rendering + * into a framebuffer or not. + * + * This method caches the state so `gl.stencilMask()` is only + * called when necessary. + * + * @param {Boolean} stencilMask - The stencil mask. + */ setStencilMask( stencilMask ) { if ( this.currentStencilMask !== stencilMask ) { @@ -447,6 +584,16 @@ class WebGLState { } + /** + * Specifies whether the stencil test functions. + * + * This method caches the state so `gl.stencilFunc()` is only + * called when necessary. + * + * @param {Number} stencilFunc - The stencil compare function. + * @param {Number} stencilRef - The reference value for the stencil test. + * @param {Number} stencilMask - A bit-wise mask that is used to AND the reference value and the stored stencil value when the test is done. + */ setStencilFunc( stencilFunc, stencilRef, stencilMask ) { if ( this.currentStencilFunc !== stencilFunc || @@ -463,6 +610,17 @@ class WebGLState { } + /** + * Specifies whether the stencil test operation. + * + * This method caches the state so `gl.stencilOp()` is only + * called when necessary. + * + * @param {Number} stencilFail - The function to use when the stencil test fails. + * @param {Number} stencilZFail - The function to use when the stencil test passes, but the depth test fail. + * @param {Number} stencilZPass - The function to use when both the stencil test and the depth test pass, + * or when the stencil test passes and there is no depth buffer or depth testing is disabled. + */ setStencilOp( stencilFail, stencilZFail, stencilZPass ) { if ( this.currentStencilFail !== stencilFail || @@ -479,6 +637,13 @@ class WebGLState { } + /** + * Configures the WebGL state for the given material. + * + * @param {Material} material - The material to configure the state for. + * @param {Number} frontFaceCW - Whether the front faces are counter-clockwise or not. + * @param {Number} hardwareClippingPlanes - The number of hardware clipping planes. + */ setMaterial( material, frontFaceCW, hardwareClippingPlanes ) { const { gl } = this; @@ -543,6 +708,16 @@ class WebGLState { } + /** + * Specifies the polygon offset. + * + * This method caches the state so `gl.polygonOffset()` is only + * called when necessary. + * + * @param {Boolean} polygonOffset - Whether polygon offset is enabled or not. + * @param {Number} factor - The scale factor for the variable depth offset for each polygon. + * @param {Number} units - The multiplier by which an implementation-specific value is multiplied with to create a constant depth offset. + */ setPolygonOffset( polygonOffset, factor, units ) { const { gl } = this; @@ -568,6 +743,15 @@ class WebGLState { } + /** + * Defines the usage of the given WebGL program. + * + * This method caches the state so `gl.useProgram()` is only + * called when necessary. + * + * @param {WebGLProgram} program - The WebGL program to use. + * @return {Boolean} Whether a program change has been executed or not. + */ useProgram( program ) { if ( this.currentProgram !== program ) { @@ -587,6 +771,16 @@ class WebGLState { // framebuffer + /** + * Binds the given framebuffer. + * + * This method caches the state so `gl.bindFramebuffer()` is only + * called when necessary. + * + * @param {Number} target - The binding point (target). + * @param {WebGLFramebuffer} framebuffer - The WebGL framebuffer to bind. + * @return {Boolean} Whether a bind has been executed or not. + */ bindFramebuffer( target, framebuffer ) { const { gl, currentBoundFramebuffers } = this; @@ -619,6 +813,16 @@ class WebGLState { } + /** + * Defines draw buffers to which fragment colors are written into. + * Configures the MRT setup of custom framebuffers. + * + * This method caches the state so `gl.drawBuffers()` is only + * called when necessary. + * + * @param {RenderContext} renderContext - The render context. + * @param {WebGLFramebuffer} framebuffer - The WebGL framebuffer. + */ drawBuffers( renderContext, framebuffer ) { const { gl } = this; @@ -679,6 +883,14 @@ class WebGLState { // texture + /** + * Makes the given texture unit active. + * + * This method caches the state so `gl.activeTexture()` is only + * called when necessary. + * + * @param {Number} webglSlot - The texture unit to make active. + */ activeTexture( webglSlot ) { const { gl, currentTextureSlot, maxTextures } = this; @@ -694,6 +906,16 @@ class WebGLState { } + /** + * Binds the given WebGL texture to a target. + * + * This method caches the state so `gl.bindTexture()` is only + * called when necessary. + * + * @param {Number} webglType - The binding point (target). + * @param {WebGLTexture} webglTexture - The WebGL texture to bind. + * @param {Number} webglSlot - The texture. + */ bindTexture( webglType, webglTexture, webglSlot ) { const { gl, currentTextureSlot, currentBoundTextures, maxTextures } = this; @@ -739,6 +961,17 @@ class WebGLState { } + /** + * Binds a given WebGL buffer to a given binding point (target) at a given index. + * + * This method caches the state so `gl.bindBufferBase()` is only + * called when necessary. + * + * @param {Number} target - The target for the bind operation. + * @param {Number} index - The index of the target. + * @param {WebGLBuffer} buffer - The WebGL buffer. + * @return {Boolean} Whether a bind has been executed or not. + */ bindBufferBase( target, index, buffer ) { const { gl } = this; @@ -759,6 +992,12 @@ class WebGLState { } + /** + * Unbinds the current bound texture. + * + * This method caches the state so `gl.bindTexture()` is only + * called when necessary. + */ unbindTexture() { const { gl, currentTextureSlot, currentBoundTextures } = this; diff --git a/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js b/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js index c20a4a733ae6c1..85c8f75921722e 100644 --- a/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +++ b/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js @@ -2,19 +2,53 @@ import { LinearFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, Near let initialized = false, wrappingToGL, filterToGL, compareToGL; +/** + * A WebGL 2 backend utility module for managing textures. + * + * @private + */ class WebGLTextureUtils { + /** + * Constructs a new utility object. + * + * @param {WebGLBackend} backend - The WebGL 2 backend. + */ constructor( backend ) { + /** + * A reference to the WebGL 2 backend. + * + * @type {WebGLBackend} + */ this.backend = backend; + /** + * A reference to the rendering context. + * + * @type {WebGL2RenderingContext} + */ this.gl = backend.gl; + + /** + * A reference to a backend module holding extension-related + * utility functions. + * + * @type {WebGLExtensions} + */ this.extensions = backend.extensions; + + /** + * A dictionary for managing default textures. The key + * is the binding point (target), the value the WEbGL texture object. + * + * @type {Object} + */ this.defaultTextures = {}; if ( initialized === false ) { - this._init( this.gl ); + this._init(); initialized = true; @@ -22,7 +56,14 @@ class WebGLTextureUtils { } - _init( gl ) { + /** + * Inits the state of the utility. + * + * @private + */ + _init() { + + const gl = this.gl; // Store only WebGL constants here. @@ -55,20 +96,12 @@ class WebGLTextureUtils { } - filterFallback( f ) { - - const { gl } = this; - - if ( f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter ) { - - return gl.NEAREST; - - } - - return gl.LINEAR; - - } - + /** + * Returns the native texture type for the given texture. + * + * @param {Texture} texture - The texture. + * @return {GLenum} The native texture type. + */ getGLTextureType( texture ) { const { gl } = this; @@ -98,6 +131,16 @@ class WebGLTextureUtils { } + /** + * Returns the native texture type for the given texture. + * + * @param {String?} internalFormatName - The internal format name. When `null`, the internal format is derived from the subsequent parameters. + * @param {GLenum} glFormat - The WebGL format. + * @param {GLenum} glType - The WebGL type. + * @param {String} colorSpace - The texture's color space. + * @param {Boolean} [forceLinearTransfer=false] - Whether to force a linear transfer or not. + * @return {GLenum} The internal format. + */ getInternalFormat( internalFormatName, glFormat, glType, colorSpace, forceLinearTransfer = false ) { const { gl, extensions } = this; @@ -241,6 +284,12 @@ class WebGLTextureUtils { } + /** + * Sets the texture parameters for the given texture. + * + * @param {GLenum} textureType - The texture type. + * @param {Texture} texture - The texture. + */ setTextureParameters( textureType, texture ) { const { gl, extensions, backend } = this; @@ -294,6 +343,12 @@ class WebGLTextureUtils { } + /** + * Creates a default texture for the given texture that can be used + * as a placeholder until the actual texture is ready for usage. + * + * @param {Texture} texture - The texture to create a default texture for. + */ createDefaultTexture( texture ) { const { gl, backend, defaultTextures } = this; @@ -325,6 +380,13 @@ class WebGLTextureUtils { } + /** + * Defines a texture on the GPU for the given texture object. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + * @return {undefined} + */ createTexture( texture, options ) { const { gl, backend } = this; @@ -365,6 +427,12 @@ class WebGLTextureUtils { } + /** + * Uploads texture buffer data to the GPU memory. + * + * @param {WebGLBuffer} buffer - The buffer data. + * @param {Texture} texture - The texture, + */ copyBufferToTexture( buffer, texture ) { const { gl, backend } = this; @@ -400,6 +468,12 @@ class WebGLTextureUtils { } + /** + * Uploads the updated texture data to the GPU. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ updateTexture( texture, options ) { const { gl } = this; @@ -520,6 +594,11 @@ class WebGLTextureUtils { } + /** + * Generates mipmaps for the given texture. + * + * @param {Texture} texture - The texture. + */ generateMipmaps( texture ) { const { gl, backend } = this; @@ -530,6 +609,11 @@ class WebGLTextureUtils { } + /** + * Deallocates the render buffers of the given render target. + * + * @param {RenderTarget} renderTarget - The render target. + */ deallocateRenderBuffers( renderTarget ) { const { gl, backend } = this; @@ -590,6 +674,11 @@ class WebGLTextureUtils { } + /** + * Destroys the GPU data for the given texture object. + * + * @param {Texture} texture - The texture. + */ destroyTexture( texture ) { const { gl, backend } = this; @@ -602,6 +691,15 @@ class WebGLTextureUtils { } + /** + * Copies data of the given source texture to the given destination texture. + * + * @param {Texture} srcTexture - The source texture. + * @param {Texture} dstTexture - The destination texture. + * @param {Vector4?} [srcRegion=null] - The region of the source texture to copy. + * @param {(Vector2|Vector3)?} [dstPosition=null] - The destination position of the copy. + * @param {Number} [level=0] - The mip level to copy. + */ copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { const { gl, backend } = this; @@ -720,6 +818,13 @@ class WebGLTextureUtils { } + /** + * Copies the current bound framebuffer to the given texture. + * + * @param {Texture} texture - The destination texture. + * @param {RenderContext} renderContext - The render context. + * @param {Vector4} rectangle - A four dimensional vector defining the origin and dimension of the copy. + */ copyFramebufferToTexture( texture, renderContext, rectangle ) { const { gl } = this; @@ -731,7 +836,7 @@ class WebGLTextureUtils { const requireDrawFrameBuffer = texture.isDepthTexture === true || ( renderContext.renderTarget && renderContext.renderTarget.samples > 0 ); - const srcHeight = renderContext.renderTarget ? renderContext.renderTarget.height : this.backend.gerDrawingBufferSize().y; + const srcHeight = renderContext.renderTarget ? renderContext.renderTarget.height : this.backend.getDrawingBufferSize().y; if ( requireDrawFrameBuffer ) { @@ -807,7 +912,12 @@ class WebGLTextureUtils { } - // Setup storage for internal depth/stencil buffers and bind to correct framebuffer + /** + * SetupS storage for internal depth/stencil buffers and bind to correct framebuffer. + * + * @param {WebGLRenderbuffer} renderbuffer - The render buffer. + * @param {RenderContext} renderContext - The render context. + */ setupRenderBufferStorage( renderbuffer, renderContext ) { const { gl } = this; @@ -862,6 +972,18 @@ class WebGLTextureUtils { } + /** + * Returns texture data as a typed array. + * + * @async + * @param {Texture} texture - The texture to copy. + * @param {Number} x - The x coordinate of the copy origin. + * @param {Number} y - The y coordinate of the copy origin. + * @param {Number} width - The width of the copy. + * @param {Number} height - The height of the copy. + * @param {Number} faceIndex - The face index. + * @return {Promise} A Promise that resolves with a typed array when the copy operation has finished. + */ async copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { const { backend, gl } = this; @@ -903,6 +1025,13 @@ class WebGLTextureUtils { } + /** + * Returns the corresponding typed array type for the given WebGL data type. + * + * @private + * @param {GLenum} glType - The WebGL data type. + * @return {TypedArray.constructor} The typed array type. + */ _getTypedArrayType( glType ) { const { gl } = this; @@ -922,6 +1051,14 @@ class WebGLTextureUtils { } + /** + * Returns the bytes-per-texel value for the given WebGL data type and texture format. + * + * @private + * @param {GLenum} glType - The WebGL data type. + * @param {GLenum} glFormat - The WebGL texture format. + * @return {Number} The bytes-per-texel. + */ _getBytesPerTexel( glType, glFormat ) { const { gl } = this; diff --git a/src/renderers/webgl-fallback/utils/WebGLUtils.js b/src/renderers/webgl-fallback/utils/WebGLUtils.js index 170fdd00977647..16c9589ffb9d05 100644 --- a/src/renderers/webgl-fallback/utils/WebGLUtils.js +++ b/src/renderers/webgl-fallback/utils/WebGLUtils.js @@ -1,16 +1,52 @@ import { RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT5_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT1_Format, RGB_S3TC_DXT1_Format, DepthFormat, DepthStencilFormat, LuminanceAlphaFormat, LuminanceFormat, RedFormat, RGBFormat, RGBAFormat, AlphaFormat, RedIntegerFormat, RGFormat, RGIntegerFormat, RGBAIntegerFormat, HalfFloatType, FloatType, UnsignedIntType, IntType, UnsignedShortType, ShortType, ByteType, UnsignedInt248Type, UnsignedInt5999Type, UnsignedShort5551Type, UnsignedShort4444Type, UnsignedByteType, RGBA_BPTC_Format, RED_RGTC1_Format, SIGNED_RED_RGTC1_Format, RED_GREEN_RGTC2_Format, SIGNED_RED_GREEN_RGTC2_Format, SRGBColorSpace, NoColorSpace } from '../../../constants.js'; +/** + * A WebGL 2 backend utility module with common helpers. + * + * @private + */ class WebGLUtils { + /** + * Constructs a new utility object. + * + * @param {WebGLBackend} backend - The WebGL 2 backend. + */ constructor( backend ) { + /** + * A reference to the WebGL 2 backend. + * + * @type {WebGLBackend} + */ this.backend = backend; + /** + * A reference to the rendering context. + * + * @type {WebGL2RenderingContext} + */ this.gl = this.backend.gl; + + /** + * A reference to a backend module holding extension-related + * utility functions. + * + * @type {WebGLExtensions} + */ this.extensions = backend.extensions; } + /** + * Converts the given three.js constant into a WebGL constant. + * The method currently supports the conversion of texture formats + * and types. + * + * @param {Number} p - The three.js constant. + * @param {String} [colorSpace=NoColorSpace] - The color space. + * @return {Number} The corresponding WebGL constant. + */ convert( p, colorSpace = NoColorSpace ) { const { gl, extensions } = this; @@ -221,6 +257,13 @@ class WebGLUtils { } + /** + * This method can be used to synchronize the CPU with the GPU by waiting until + * ongoing GPU commands have been completed. + * + * @private + * @return {Promise} A promise that resolves when all ongoing GPU commands have been completed. + */ _clientWaitAsync() { const { gl } = this; diff --git a/src/renderers/webgl/WebGLBackground.js b/src/renderers/webgl/WebGLBackground.js index 1344ac8ac4f8db..9abfdb09a4a155 100644 --- a/src/renderers/webgl/WebGLBackground.js +++ b/src/renderers/webgl/WebGLBackground.js @@ -249,6 +249,8 @@ function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, boxMesh.geometry.dispose(); boxMesh.material.dispose(); + boxMesh = undefined; + } if ( planeMesh !== undefined ) { @@ -256,6 +258,8 @@ function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, planeMesh.geometry.dispose(); planeMesh.material.dispose(); + planeMesh = undefined; + } } diff --git a/src/renderers/webgpu/WebGPUBackend.js b/src/renderers/webgpu/WebGPUBackend.js index 795d4717c10d0f..4d7d50af34cbdc 100644 --- a/src/renderers/webgpu/WebGPUBackend.js +++ b/src/renderers/webgpu/WebGPUBackend.js @@ -15,14 +15,41 @@ import WebGPUTextureUtils from './utils/WebGPUTextureUtils.js'; import { WebGPUCoordinateSystem } from '../../constants.js'; -// - +/** + * A backend implementation targeting WebGPU. + * + * @private + * @augments Backend + */ class WebGPUBackend extends Backend { + /** + * Constructs a new WebGPU backend. + * + * @param {Object} parameters - The configuration parameter. + * @param {Boolean} [parameters.logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not. + * @param {Boolean} [parameters.alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque. + * @param {Boolean} [parameters.depth=true] - Whether the default framebuffer should have a depth buffer or not. + * @param {Boolean} [parameters.stencil=false] - Whether the default framebuffer should have a stencil buffer or not. + * @param {Boolean} [parameters.antialias=false] - Whether MSAA as the default anti-aliasing should be enabled or not. + * @param {Number} [parameters.samples=0] - When `antialias` is `true`, `4` samples are used by default. Set this parameter to any other integer value than 0 to overwrite the default. + * @param {Boolean} [parameters.forceWebGL=false] - If set to `true`, the renderer uses a WebGL 2 backend no matter if WebGPU is supported or not. + * @param {Boolean} [parameters.trackTimestamp=false] - Whether to track timestamps with a Timestamp Query API or not. + * @param {String} [parameters.powerPreference=undefined] - The power preference. + * @param {Object} [parameters.requiredLimits=undefined] - Specifies the limits that are required by the device request. The request will fail if the adapter cannot provide these limits. + * @param {GPUDevice} [parameters.device=undefined] - If there is an existing GPU device on app level, it can be passed to the renderer as a parameter. + */ constructor( parameters = {} ) { super( parameters ); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isWebGPUBackend = true; // some parameters require default values other than "undefined" @@ -30,22 +57,101 @@ class WebGPUBackend extends Backend { this.parameters.requiredLimits = ( parameters.requiredLimits === undefined ) ? {} : parameters.requiredLimits; + /** + * Whether to track timestamps with a Timestamp Query API or not. + * + * @type {Boolean} + * @default false + */ this.trackTimestamp = ( parameters.trackTimestamp === true ); + /** + * A reference to the device. + * + * @type {GPUDevice?} + * @default null + */ this.device = null; + + /** + * A reference to the context. + * + * @type {GPUCanvasContext?} + * @default null + */ this.context = null; + + /** + * A reference to the color attachment of the default framebuffer. + * + * @type {GPUTexture?} + * @default null + */ this.colorBuffer = null; + + /** + * A reference to the default render pass descriptor. + * + * @type {Object?} + * @default null + */ this.defaultRenderPassdescriptor = null; + /** + * A reference to a backend module holding common utility functions. + * + * @type {WebGPUUtils} + */ this.utils = new WebGPUUtils( this ); + + /** + * A reference to a backend module holding shader attribute-related + * utility functions. + * + * @type {WebGPUAttributeUtils} + */ this.attributeUtils = new WebGPUAttributeUtils( this ); + + /** + * A reference to a backend module holding shader binding-related + * utility functions. + * + * @type {WebGPUBindingUtils} + */ this.bindingUtils = new WebGPUBindingUtils( this ); + + /** + * A reference to a backend module holding shader pipeline-related + * utility functions. + * + * @type {WebGPUPipelineUtils} + */ this.pipelineUtils = new WebGPUPipelineUtils( this ); + + /** + * A reference to a backend module holding shader texture-related + * utility functions. + * + * @type {WebGPUTextureUtils} + */ this.textureUtils = new WebGPUTextureUtils( this ); + + /** + * A map that manages the resolve buffers for occlusion queries. + * + * @type {Map} + */ this.occludedResolveCache = new Map(); } + /** + * Initializes the backend so it is ready for usage. + * + * @async + * @param {Renderer} renderer - The renderer. + * @return {Promise} A Promise that resolves when the backend has been initialized. + */ async init( renderer ) { await super.init( renderer ); @@ -134,24 +240,53 @@ class WebGPUBackend extends Backend { } + /** + * The coordinate system of the backend. + * + * @type {Number} + * @readonly + */ get coordinateSystem() { return WebGPUCoordinateSystem; } + /** + * This method performs a readback operation by moving buffer data from + * a storage buffer attribute from the GPU to the CPU. + * + * @async + * @param {StorageBufferAttribute} attribute - The storage buffer attribute. + * @return {Promise} A promise that resolves with the buffer data when the data are ready. + */ async getArrayBufferAsync( attribute ) { return await this.attributeUtils.getArrayBufferAsync( attribute ); } + /** + * Returns the backend's rendering context. + * + * @return {GPUCanvasContext} The rendering context. + */ getContext() { return this.context; } + /** + * Returns the default render pass descriptor. + * + * In WebGPU, the default framebuffer must be configured + * like custom framebuffers so the backend needs a render + * pass descriptor even when rendering directly to screen. + * + * @private + * @return {Object} The render pass descriptor. + */ _getDefaultRenderPassDescriptor() { let descriptor = this.defaultRenderPassdescriptor; @@ -206,7 +341,15 @@ class WebGPUBackend extends Backend { } - _getRenderPassDescriptor( renderContext ) { + /** + * Returns the render pass descriptor for the given render context. + * + * @private + * @param {RenderContext} renderContext - The render context. + * @param {Object} colorAttachmentsConfig - Configuration object for the color attachments. + * @return {Object} The render pass descriptor. + */ + _getRenderPassDescriptor( renderContext, colorAttachmentsConfig = {} ) { const renderTarget = renderContext.renderTarget; const renderTargetData = this.get( renderTarget ); @@ -216,8 +359,11 @@ class WebGPUBackend extends Backend { if ( descriptors === undefined || renderTargetData.width !== renderTarget.width || renderTargetData.height !== renderTarget.height || + renderTargetData.dimensions !== renderTarget.dimensions || renderTargetData.activeMipmapLevel !== renderTarget.activeMipmapLevel || - renderTargetData.samples !== renderTarget.samples + renderTargetData.activeCubeFace !== renderContext.activeCubeFace || + renderTargetData.samples !== renderTarget.samples || + renderTargetData.loadOp !== colorAttachmentsConfig.loadOp ) { descriptors = {}; @@ -247,16 +393,37 @@ class WebGPUBackend extends Backend { const textures = renderContext.textures; const colorAttachments = []; + let sliceIndex; + for ( let i = 0; i < textures.length; i ++ ) { const textureData = this.get( textures[ i ] ); - const textureView = textureData.texture.createView( { + const viewDescriptor = { + label: `colorAttachment_${ i }`, baseMipLevel: renderContext.activeMipmapLevel, mipLevelCount: 1, baseArrayLayer: renderContext.activeCubeFace, + arrayLayerCount: 1, dimension: GPUTextureViewDimension.TwoD - } ); + }; + + if ( renderTarget.isRenderTarget3D ) { + + sliceIndex = renderContext.activeCubeFace; + + viewDescriptor.baseArrayLayer = 0; + viewDescriptor.dimension = GPUTextureViewDimension.ThreeD; + viewDescriptor.depthOrArrayLayers = textures[ i ].image.depth; + + } else if ( renderTarget.isRenderTargetArray ) { + + viewDescriptor.dimension = GPUTextureViewDimension.TwoDArray; + viewDescriptor.depthOrArrayLayers = textures[ i ].image.depth; + + } + + const textureView = textureData.texture.createView( viewDescriptor ); let view, resolveTarget; @@ -274,9 +441,11 @@ class WebGPUBackend extends Backend { colorAttachments.push( { view, + depthSlice: sliceIndex, resolveTarget, loadOp: GPULoadOp.Load, - storeOp: GPUStoreOp.Store + storeOp: GPUStoreOp.Store, + ...colorAttachmentsConfig } ); } @@ -302,7 +471,11 @@ class WebGPUBackend extends Backend { renderTargetData.width = renderTarget.width; renderTargetData.height = renderTarget.height; renderTargetData.samples = renderTarget.samples; - renderTargetData.activeMipmapLevel = renderTarget.activeMipmapLevel; + renderTargetData.activeMipmapLevel = renderContext.activeMipmapLevel; + renderTargetData.activeCubeFace = renderContext.activeCubeFace; + renderTargetData.dimensions = renderTarget.dimensions; + renderTargetData.depthSlice = sliceIndex; + renderTargetData.loadOp = colorAttachments[ 0 ].loadOp; } @@ -310,6 +483,12 @@ class WebGPUBackend extends Backend { } + /** + * This method is executed at the beginning of a render call and prepares + * the WebGPU state for upcoming render calls + * + * @param {RenderContext} renderContext - The render context. + */ beginRender( renderContext ) { const renderContextData = this.get( renderContext ); @@ -350,7 +529,7 @@ class WebGPUBackend extends Backend { } else { - descriptor = this._getRenderPassDescriptor( renderContext ); + descriptor = this._getRenderPassDescriptor( renderContext, { loadOp: GPULoadOp.Load } ); } @@ -469,6 +648,12 @@ class WebGPUBackend extends Backend { } + /** + * This method is executed at the end of a render call and finalizes work + * after draw calls. + * + * @param {RenderContext} renderContext - The render context. + */ finishRender( renderContext ) { const renderContextData = this.get( renderContext ); @@ -557,6 +742,14 @@ class WebGPUBackend extends Backend { } + /** + * Returns `true` if the given 3D object is fully occluded by other + * 3D objects in the scene. + * + * @param {RenderContext} renderContext - The render context. + * @param {Object3D} object - The 3D object to test. + * @return {Boolean} Whether the 3D object is fully occluded or not. + */ isOccluded( renderContext, object ) { const renderContextData = this.get( renderContext ); @@ -565,6 +758,13 @@ class WebGPUBackend extends Backend { } + /** + * This method processes the result of occlusion queries and writes it + * into render context data. + * + * @async + * @param {RenderContext} renderContext - The render context. + */ async resolveOccludedAsync( renderContext ) { const renderContextData = this.get( renderContext ); @@ -587,7 +787,7 @@ class WebGPUBackend extends Backend { for ( let i = 0; i < currentOcclusionQueryObjects.length; i ++ ) { - if ( results[ i ] !== BigInt( 0 ) ) { + if ( results[ i ] === BigInt( 0 ) ) { occluded.add( currentOcclusionQueryObjects[ i ] ); @@ -603,6 +803,11 @@ class WebGPUBackend extends Backend { } + /** + * Updates the viewport with the values from the given render context. + * + * @param {RenderContext} renderContext - The render context. + */ updateViewport( renderContext ) { const { currentPass } = this.get( renderContext ); @@ -612,7 +817,15 @@ class WebGPUBackend extends Backend { } - clear( color, depth, stencil, renderTargetData = null ) { + /** + * Performs a clear operation. + * + * @param {Boolean} color - Whether the color buffer should be cleared or not. + * @param {Boolean} depth - Whether the depth buffer should be cleared or not. + * @param {Boolean} stencil - Whether the stencil buffer should be cleared or not. + * @param {RenderContext?} [renderTargetContext=null] - The render context of the current set render target. + */ + clear( color, depth, stencil, renderTargetContext = null ) { const device = this.device; const renderer = this.renderer; @@ -645,7 +858,7 @@ class WebGPUBackend extends Backend { } - if ( renderTargetData === null ) { + if ( renderTargetContext === null ) { supportsDepth = renderer.depth; supportsStencil = renderer.stencil; @@ -672,45 +885,20 @@ class WebGPUBackend extends Backend { } else { - supportsDepth = renderTargetData.depth; - supportsStencil = renderTargetData.stencil; + supportsDepth = renderTargetContext.depth; + supportsStencil = renderTargetContext.stencil; if ( color ) { - for ( const texture of renderTargetData.textures ) { - - const textureData = this.get( texture ); - const textureView = textureData.texture.createView(); - - let view, resolveTarget; - - if ( textureData.msaaTexture !== undefined ) { - - view = textureData.msaaTexture.createView(); - resolveTarget = textureView; - - } else { - - view = textureView; - resolveTarget = undefined; + const descriptor = this._getRenderPassDescriptor( renderTargetContext, { loadOp: GPULoadOp.Clear } ); - } - - colorAttachments.push( { - view, - resolveTarget, - clearValue, - loadOp: GPULoadOp.Clear, - storeOp: GPUStoreOp.Store - } ); - - } + colorAttachments = descriptor.colorAttachments; } if ( supportsDepth || supportsStencil ) { - const depthTextureData = this.get( renderTargetData.depthTexture ); + const depthTextureData = this.get( renderTargetContext.depthTexture ); depthStencilAttachment = { view: depthTextureData.texture.createView() @@ -760,7 +948,7 @@ class WebGPUBackend extends Backend { // - const encoder = device.createCommandEncoder( {} ); + const encoder = device.createCommandEncoder( { label: 'clear' } ); const currentPass = encoder.beginRenderPass( { colorAttachments, depthStencilAttachment @@ -774,21 +962,37 @@ class WebGPUBackend extends Backend { // compute + /** + * This method is executed at the beginning of a compute call and + * prepares the state for upcoming compute tasks. + * + * @param {Node|Array} computeGroup - The compute node(s). + */ beginCompute( computeGroup ) { const groupGPU = this.get( computeGroup ); - const descriptor = {}; + const descriptor = { + label: 'computeGroup_' + computeGroup.id + }; this.initTimestampQuery( computeGroup, descriptor ); - groupGPU.cmdEncoderGPU = this.device.createCommandEncoder(); + groupGPU.cmdEncoderGPU = this.device.createCommandEncoder( { label: 'computeGroup_' + computeGroup.id } ); groupGPU.passEncoderGPU = groupGPU.cmdEncoderGPU.beginComputePass( descriptor ); } + /** + * Executes a compute command for the given compute node. + * + * @param {Node|Array} computeGroup - The group of compute nodes of a compute call. Can be a single compute node. + * @param {Node} computeNode - The compute node. + * @param {Array} bindings - The bindings. + * @param {ComputePipeline} pipeline - The compute pipeline. + */ compute( computeGroup, computeNode, bindings, pipeline ) { const { passEncoderGPU } = this.get( computeGroup ); @@ -836,6 +1040,12 @@ class WebGPUBackend extends Backend { } + /** + * This method is executed at the end of a compute call and + * finalizes work after compute tasks. + * + * @param {Node|Array} computeGroup - The compute node(s). + */ finishCompute( computeGroup ) { const groupData = this.get( computeGroup ); @@ -848,6 +1058,13 @@ class WebGPUBackend extends Backend { } + /** + * Can be used to synchronize CPU operations with GPU tasks. So when this method is called, + * the CPU waits for the GPU to complete its operation (e.g. a compute task). + * + * @async + * @return {Promise} A Promise that resolves when synchronization has been finished. + */ async waitForGPU() { await this.device.queue.onSubmittedWorkDone(); @@ -856,6 +1073,12 @@ class WebGPUBackend extends Backend { // render object + /** + * Executes a draw command for the given render object. + * + * @param {RenderObject} renderObject - The render object to draw. + * @param {Info} info - Holds a series of statistical information about the GPU memory and the rendering process. + */ draw( renderObject, info ) { const { object, context, pipeline } = renderObject; @@ -1039,6 +1262,12 @@ class WebGPUBackend extends Backend { // cache key + /** + * Returns `true` if the render pipeline requires an update. + * + * @param {RenderObject} renderObject - The render object. + * @return {Boolean} Whether the render pipeline requires an update or not. + */ needsRenderUpdate( renderObject ) { const data = this.get( renderObject ); @@ -1095,6 +1324,12 @@ class WebGPUBackend extends Backend { } + /** + * Returns a cache key that is used to identify render pipelines. + * + * @param {RenderObject} renderObject - The render object. + * @return {String} The cache key. + */ getRenderCacheKey( renderObject ) { const { object, material } = renderObject; @@ -1123,83 +1358,142 @@ class WebGPUBackend extends Backend { // textures + /** + * Creates a GPU sampler for the given texture. + * + * @param {Texture} texture - The texture to create the sampler for. + */ createSampler( texture ) { this.textureUtils.createSampler( texture ); } + /** + * Destroys the GPU sampler for the given texture. + * + * @param {Texture} texture - The texture to destroy the sampler for. + */ destroySampler( texture ) { this.textureUtils.destroySampler( texture ); } + /** + * Creates a default texture for the given texture that can be used + * as a placeholder until the actual texture is ready for usage. + * + * @param {Texture} texture - The texture to create a default texture for. + */ createDefaultTexture( texture ) { this.textureUtils.createDefaultTexture( texture ); } + /** + * Defines a texture on the GPU for the given texture object. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ createTexture( texture, options ) { this.textureUtils.createTexture( texture, options ); } + /** + * Uploads the updated texture data to the GPU. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ updateTexture( texture, options ) { this.textureUtils.updateTexture( texture, options ); } + /** + * Generates mipmaps for the given texture. + * + * @param {Texture} texture - The texture. + */ generateMipmaps( texture ) { this.textureUtils.generateMipmaps( texture ); } + /** + * Destroys the GPU data for the given texture object. + * + * @param {Texture} texture - The texture. + */ destroyTexture( texture ) { this.textureUtils.destroyTexture( texture ); } - copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { + /** + * Returns texture data as a typed array. + * + * @async + * @param {Texture} texture - The texture to copy. + * @param {Number} x - The x coordinate of the copy origin. + * @param {Number} y - The y coordinate of the copy origin. + * @param {Number} width - The width of the copy. + * @param {Number} height - The height of the copy. + * @param {Number} faceIndex - The face index. + * @return {Promise} A Promise that resolves with a typed array when the copy operation has finished. + */ + async copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { return this.textureUtils.copyTextureToBuffer( texture, x, y, width, height, faceIndex ); } - + /** + * Inits a time stamp query for the given render context. + * + * @param {RenderContext} renderContext - The render context. + * @param {Object} descriptor - The query descriptor. + */ initTimestampQuery( renderContext, descriptor ) { if ( ! this.trackTimestamp ) return; const renderContextData = this.get( renderContext ); - if ( ! renderContextData.timeStampQuerySet ) { + if ( ! renderContextData.timestampQuerySet ) { const type = renderContext.isComputeNode ? 'compute' : 'render'; - const timeStampQuerySet = this.device.createQuerySet( { type: 'timestamp', count: 2, label: `timestamp_${type}_${renderContext.id}` } ); + const timestampQuerySet = this.device.createQuerySet( { type: 'timestamp', count: 2, label: `timestamp_${type}_${renderContext.id}` } ); const timestampWrites = { - querySet: timeStampQuerySet, + querySet: timestampQuerySet, beginningOfPassWriteIndex: 0, // Write timestamp in index 0 when pass begins. endOfPassWriteIndex: 1, // Write timestamp in index 1 when pass ends. }; Object.assign( descriptor, { timestampWrites } ); - renderContextData.timeStampQuerySet = timeStampQuerySet; + renderContextData.timestampQuerySet = timestampQuerySet; } } - // timestamp utils - + /** + * Prepares the timestamp buffer. + * + * @param {RenderContext} renderContext - The render context. + * @param {GPUCommandEncoder} encoder - The command encoder. + */ prepareTimestampBuffer( renderContext, encoder ) { if ( ! this.trackTimestamp ) return; @@ -1207,7 +1501,7 @@ class WebGPUBackend extends Backend { const renderContextData = this.get( renderContext ); - const size = 2 * BigInt64Array.BYTES_PER_ELEMENT; + const size = 2 * BigUint64Array.BYTES_PER_ELEMENT; if ( renderContextData.currentTimestampQueryBuffers === undefined ) { @@ -1229,7 +1523,7 @@ class WebGPUBackend extends Backend { const { resolveBuffer, resultBuffer } = renderContextData.currentTimestampQueryBuffers; - encoder.resolveQuerySet( renderContextData.timeStampQuerySet, 0, 2, resolveBuffer, 0 ); + encoder.resolveQuerySet( renderContextData.timestampQuerySet, 0, 2, resolveBuffer, 0 ); if ( resultBuffer.mapState === 'unmapped' ) { @@ -1239,6 +1533,14 @@ class WebGPUBackend extends Backend { } + /** + * Resolves the time stamp for the given render context and type. + * + * @async + * @param {RenderContext} renderContext - The render context. + * @param {String} type - The render context. + * @return {Promise} A Promise that resolves when the time stamp has been computed. + */ async resolveTimestampAsync( renderContext, type = 'render' ) { if ( ! this.trackTimestamp ) return; @@ -1270,6 +1572,13 @@ class WebGPUBackend extends Backend { // node builder + /** + * Returns a node builder for the given render object. + * + * @param {RenderObject} object - The render object. + * @param {Renderer} renderer - The renderer. + * @return {WGSLNodeBuilder} The node builder. + */ createNodeBuilder( object, renderer ) { return new WGSLNodeBuilder( object, renderer ); @@ -1278,17 +1587,27 @@ class WebGPUBackend extends Backend { // program + /** + * Creates a shader program from the given programmable stage. + * + * @param {ProgrammableStage} program - The programmable stage. + */ createProgram( program ) { const programGPU = this.get( program ); programGPU.module = { - module: this.device.createShaderModule( { code: program.code, label: program.stage } ), + module: this.device.createShaderModule( { code: program.code, label: program.stage + ( program.name !== '' ? `_${ program.name }` : '' ) } ), entryPoint: 'main' }; } + /** + * Destroys the shader program of the given programmable stage. + * + * @param {ProgrammableStage} program - The programmable stage. + */ destroyProgram( program ) { this.delete( program ); @@ -1297,18 +1616,35 @@ class WebGPUBackend extends Backend { // pipelines + /** + * Creates a render pipeline for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @param {Array} promises - An array of compilation promises which are used in `compileAsync()`. + */ createRenderPipeline( renderObject, promises ) { this.pipelineUtils.createRenderPipeline( renderObject, promises ); } + /** + * Creates a compute pipeline for the given compute node. + * + * @param {ComputePipeline} computePipeline - The compute pipeline. + * @param {Array} bindings - The bindings. + */ createComputePipeline( computePipeline, bindings ) { this.pipelineUtils.createComputePipeline( computePipeline, bindings ); } + /** + * Prepares the state for encoding render bundles. + * + * @param {RenderContext} renderContext - The render context. + */ beginBundle( renderContext ) { const renderContextData = this.get( renderContext ); @@ -1321,6 +1657,12 @@ class WebGPUBackend extends Backend { } + /** + * After processing render bundles this method finalizes related work. + * + * @param {RenderContext} renderContext - The render context. + * @param {RenderBundle} bundle - The render bundle. + */ finishBundle( renderContext, bundle ) { const renderContextData = this.get( renderContext ); @@ -1337,6 +1679,12 @@ class WebGPUBackend extends Backend { } + /** + * Adds a render bundle to the render context data. + * + * @param {RenderContext} renderContext - The render context. + * @param {RenderBundle} bundle - The render bundle to add. + */ addBundle( renderContext, bundle ) { const renderContextData = this.get( renderContext ); @@ -1347,18 +1695,39 @@ class WebGPUBackend extends Backend { // bindings + /** + * Creates bindings from the given bind group definition. + * + * @param {BindGroup} bindGroup - The bind group. + * @param {Array} bindings - Array of bind groups. + * @param {Number} cacheIndex - The cache index. + * @param {Number} version - The version. + */ createBindings( bindGroup, bindings, cacheIndex, version ) { this.bindingUtils.createBindings( bindGroup, bindings, cacheIndex, version ); } + /** + * Updates the given bind group definition. + * + * @param {BindGroup} bindGroup - The bind group. + * @param {Array} bindings - Array of bind groups. + * @param {Number} cacheIndex - The cache index. + * @param {Number} version - The version. + */ updateBindings( bindGroup, bindings, cacheIndex, version ) { this.bindingUtils.createBindings( bindGroup, bindings, cacheIndex, version ); } + /** + * Updates a buffer binding. + * + * @param {Buffer} binding - The buffer binding to update. + */ updateBinding( binding ) { this.bindingUtils.updateBinding( binding ); @@ -1367,36 +1736,66 @@ class WebGPUBackend extends Backend { // attributes + /** + * Creates the buffer of an indexed shader attribute. + * + * @param {BufferAttribute} attribute - The indexed buffer attribute. + */ createIndexAttribute( attribute ) { this.attributeUtils.createAttribute( attribute, GPUBufferUsage.INDEX | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST ); } + /** + * Creates the GPU buffer of a shader attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ createAttribute( attribute ) { this.attributeUtils.createAttribute( attribute, GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST ); } + /** + * Creates the GPU buffer of a storage attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ createStorageAttribute( attribute ) { this.attributeUtils.createAttribute( attribute, GPUBufferUsage.STORAGE | GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST ); } + /** + * Creates the GPU buffer of an indirect storage attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ createIndirectStorageAttribute( attribute ) { this.attributeUtils.createAttribute( attribute, GPUBufferUsage.STORAGE | GPUBufferUsage.INDIRECT | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST ); } + /** + * Updates the GPU buffer of a shader attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute to update. + */ updateAttribute( attribute ) { this.attributeUtils.updateAttribute( attribute ); } + /** + * Destroys the GPU buffer of a shader attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute to destroy. + */ destroyAttribute( attribute ) { this.attributeUtils.destroyAttribute( attribute ); @@ -1405,6 +1804,9 @@ class WebGPUBackend extends Backend { // canvas + /** + * Triggers an update of the default render pass descriptor. + */ updateSize() { this.colorBuffer = this.textureUtils.getColorBuffer(); @@ -1414,18 +1816,38 @@ class WebGPUBackend extends Backend { // utils public + /** + * Returns the maximum anisotropy texture filtering value. + * + * @return {Number} The maximum anisotropy texture filtering value. + */ getMaxAnisotropy() { return 16; } + /** + * Checks if the given feature is supported by the backend. + * + * @param {String} name - The feature's name. + * @return {Boolean} Whether the feature is supported or not. + */ hasFeature( name ) { return this.device.features.has( name ); } + /** + * Copies data of the given source texture to the given destination texture. + * + * @param {Texture} srcTexture - The source texture. + * @param {Texture} dstTexture - The destination texture. + * @param {Vector4?} [srcRegion=null] - The region of the source texture to copy. + * @param {(Vector2|Vector3)?} [dstPosition=null] - The destination position of the copy. + * @param {Number} [level=0] - The mip level to copy. + */ copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { let dstX = 0; @@ -1484,6 +1906,13 @@ class WebGPUBackend extends Backend { } + /** + * Copies the current bound framebuffer to the given texture. + * + * @param {Texture} texture - The destination texture. + * @param {RenderContext} renderContext - The render context. + * @param {Vector4} rectangle - A four dimensional vector defining the origin and dimension of the copy. + */ copyFramebufferToTexture( texture, renderContext, rectangle ) { const renderContextData = this.get( renderContext ); diff --git a/src/renderers/webgpu/WebGPURenderer.Nodes.js b/src/renderers/webgpu/WebGPURenderer.Nodes.js index 2f2dae57f561af..d5c7c18a69e499 100644 --- a/src/renderers/webgpu/WebGPURenderer.Nodes.js +++ b/src/renderers/webgpu/WebGPURenderer.Nodes.js @@ -3,8 +3,28 @@ import WebGLBackend from '../webgl-fallback/WebGLBackend.js'; import WebGPUBackend from './WebGPUBackend.js'; import BasicNodeLibrary from './nodes/BasicNodeLibrary.js'; +/** + * This alternative version of {@link WebGPURenderer} only supports node materials. + * So classes like `MeshBasicMaterial` are not compatible. + * + * @augments module:Renderer~Renderer + */ class WebGPURenderer extends Renderer { + /** + * Constructs a new WebGPU renderer. + * + * @param {Object} parameters - The configuration parameter. + * @param {Boolean} [parameters.logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not. + * @param {Boolean} [parameters.alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque. + * @param {Boolean} [parameters.depth=true] - Whether the default framebuffer should have a depth buffer or not. + * @param {Boolean} [parameters.stencil=false] - Whether the default framebuffer should have a stencil buffer or not. + * @param {Boolean} [parameters.antialias=false] - Whether MSAA as the default anti-aliasing should be enabled or not. + * @param {Number} [parameters.samples=0] - When `antialias` is `true`, `4` samples are used by default. Set this parameter to any other integer value than 0 + * to overwrite the default. + * @param {Boolean} [parameters.forceWebGL=false] - If set to `true`, the renderer uses it + * WebGL 2 backend no matter if WebGPU is supported or not. + */ constructor( parameters = {} ) { let BackendClass; @@ -31,8 +51,22 @@ class WebGPURenderer extends Renderer { super( backend, parameters ); + /** + * The generic default value is overwritten with the + * standard node library for type mapping. Material + * mapping is not supported with this version. + * + * @type {BasicNodeLibrary} + */ this.library = new BasicNodeLibrary(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isWebGPURenderer = true; } diff --git a/src/renderers/webgpu/WebGPURenderer.js b/src/renderers/webgpu/WebGPURenderer.js index c8ddb67cf638be..37e8958a546aac 100644 --- a/src/renderers/webgpu/WebGPURenderer.js +++ b/src/renderers/webgpu/WebGPURenderer.js @@ -16,8 +16,28 @@ const debugHandler = { }; */ + +/** + * This renderer is the new alternative of `WebGLRenderer`. `WebGPURenderer` has the ability + * to target different backends. By default, the renderer tries to use a WebGPU backend if the + * browser supports WebGPU. If not, `WebGPURenderer` falls backs to a WebGL 2 backend. + * + * @augments module:Renderer~Renderer + */ class WebGPURenderer extends Renderer { + /** + * Constructs a new WebGPU renderer. + * + * @param {Object} parameters - The configuration parameter. + * @param {Boolean} [parameters.logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not. + * @param {Boolean} [parameters.alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque. + * @param {Boolean} [parameters.depth=true] - Whether the default framebuffer should have a depth buffer or not. + * @param {Boolean} [parameters.stencil=false] - Whether the default framebuffer should have a stencil buffer or not. + * @param {Boolean} [parameters.antialias=false] - Whether MSAA as the default anti-aliasing should be enabled or not. + * @param {Number} [parameters.samples=0] - When `antialias` is `true`, `4` samples are used by default. Set this parameter to any other integer value than 0 to overwrite the default. + * @param {Boolean} [parameters.forceWebGL=false] - If set to `true`, the renderer uses a WebGL 2 backend no matter if WebGPU is supported or not. + */ constructor( parameters = {} ) { let BackendClass; @@ -45,8 +65,21 @@ class WebGPURenderer extends Renderer { //super( new Proxy( backend, debugHandler ) ); super( backend, parameters ); + /** + * The generic default value is overwritten with the + * standard node library for type mapping. + * + * @type {StandardNodeLibrary} + */ this.library = new StandardNodeLibrary(); + /** + * This flag can be used for type testing. + * + * @type {Boolean} + * @readonly + * @default true + */ this.isWebGPURenderer = true; } diff --git a/src/renderers/webgpu/nodes/BasicNodeLibrary.js b/src/renderers/webgpu/nodes/BasicNodeLibrary.js index a6a9d919190f4f..3ab241fa9ed829 100644 --- a/src/renderers/webgpu/nodes/BasicNodeLibrary.js +++ b/src/renderers/webgpu/nodes/BasicNodeLibrary.js @@ -24,8 +24,18 @@ import { import { LinearToneMapping, ReinhardToneMapping, CineonToneMapping, ACESFilmicToneMapping, AgXToneMapping, NeutralToneMapping } from '../../../constants.js'; import { linearToneMapping, reinhardToneMapping, cineonToneMapping, acesFilmicToneMapping, agxToneMapping, neutralToneMapping } from '../../../nodes/display/ToneMappingFunctions.js'; +/** + * This version of a node library represents a basic version + * just focusing on lights and tone mapping techniques. + * + * @private + * @augments NodeLibrary + */ class BasicNodeLibrary extends NodeLibrary { + /** + * Constructs a new basic node library. + */ constructor() { super(); diff --git a/src/renderers/webgpu/nodes/StandardNodeLibrary.js b/src/renderers/webgpu/nodes/StandardNodeLibrary.js index 9f9f1558707972..b5efe8d3927bd1 100644 --- a/src/renderers/webgpu/nodes/StandardNodeLibrary.js +++ b/src/renderers/webgpu/nodes/StandardNodeLibrary.js @@ -43,8 +43,19 @@ import { import { LinearToneMapping, ReinhardToneMapping, CineonToneMapping, ACESFilmicToneMapping, AgXToneMapping, NeutralToneMapping } from '../../../constants.js'; import { linearToneMapping, reinhardToneMapping, cineonToneMapping, acesFilmicToneMapping, agxToneMapping, neutralToneMapping } from '../../../nodes/display/ToneMappingFunctions.js'; +/** + * This version of a node library represents the standard version + * used in {@link WebGPURenderer}. It maps lights, tone mapping + * techniques and materials to node-based implementations. + * + * @private + * @augments NodeLibrary + */ class StandardNodeLibrary extends NodeLibrary { + /** + * Constructs a new standard node library. + */ constructor() { super(); diff --git a/src/renderers/webgpu/nodes/WGSLNodeBuilder.js b/src/renderers/webgpu/nodes/WGSLNodeBuilder.js index 497499f2d918be..4fb6d3873f18c5 100644 --- a/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +++ b/src/renderers/webgpu/nodes/WGSLNodeBuilder.js @@ -157,30 +157,83 @@ if ( ( typeof navigator !== 'undefined' && /Firefox|Deno/g.test( navigator.userA } -// - +/** + * A node builder targeting WGSL. + * + * This module generates WGSL shader code from node materials and also + * generates the respective bindings and vertex buffer definitions. These + * data are later used by the renderer to create render and compute pipelines + * for render objects. + * + * @augments NodeBuilder + */ class WGSLNodeBuilder extends NodeBuilder { + /** + * Constructs a new WGSL node builder renderer. + * + * @param {Object3D} object - The 3D object. + * @param {Renderer} renderer - The renderer. + */ constructor( object, renderer ) { super( object, renderer, new WGSLNodeParser() ); + /** + * A dictionary that holds for each shader stage ('vertex', 'fragment', 'compute') + * another dictionary which manages UBOs per group ('render','frame','object'). + * + * @type {Object>} + */ this.uniformGroups = {}; + /** + * A dictionary that holds for each shader stage a Map of builtins. + * + * @type {Object>} + */ this.builtins = {}; + /** + * A dictionary that holds for each shader stage a Set of directives. + * + * @type {Object>} + */ this.directives = {}; + /** + * A map for managing scope arrays. Only relevant for when using + * {@link module:WorkgroupInfoNode} in context of compute shaders. + * + * @type {Map} + */ this.scopedArrays = new Map(); } + /** + * Checks if the given texture requires a manual conversion to the working color space. + * + * @param {Texture} texture - The texture to check. + * @return {Boolean} Whether the given texture requires a conversion to working color space or not. + */ needsToWorkingColorSpace( texture ) { return texture.isVideoTexture === true && texture.colorSpace !== NoColorSpace; } + /** + * Generates the WGSL snippet for sampled textures. + * + * @private + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ _generateTextureSample( texture, textureProperty, uvSnippet, depthSnippet, shaderStage = this.shaderStage ) { if ( shaderStage === 'fragment' ) { @@ -207,6 +260,15 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet when sampling video textures. + * + * @private + * @param {String} textureProperty - The name of the video texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ _generateVideoSample( textureProperty, uvSnippet, shaderStage = this.shaderStage ) { if ( shaderStage === 'fragment' ) { @@ -221,6 +283,18 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet when sampling textures with explicit mip level. + * + * @private + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String} levelSnippet - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ _generateTextureSampleLevel( texture, textureProperty, uvSnippet, levelSnippet, depthSnippet, shaderStage = this.shaderStage ) { if ( ( shaderStage === 'fragment' || shaderStage === 'compute' ) && this.isUnfilterable( texture ) === false ) { @@ -239,9 +313,15 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates a wrap function used in context of textures. + * + * @param {Texture} texture - The texture to generate the function for. + * @return {String} The name of the generated function. + */ generateWrapFunction( texture ) { - const functionName = `tsl_coord_${ wrapNames[ texture.wrapS ] }S_${ wrapNames[ texture.wrapT ] }T`; + const functionName = `tsl_coord_${ wrapNames[ texture.wrapS ] }S_${ wrapNames[ texture.wrapT ] }_${texture.isData3DTexture ? '3d' : '2d'}T`; let nodeCode = wgslCodeCache[ functionName ]; @@ -249,7 +329,9 @@ class WGSLNodeBuilder extends NodeBuilder { const includes = []; - let code = `fn ${ functionName }( coord : vec2f ) -> vec2f {\n\n\treturn vec2f(\n`; + // For 3D textures, use vec3f; for texture arrays, keep vec2f since array index is separate + const coordType = texture.isData3DTexture ? 'vec3f' : 'vec2f'; + let code = `fn ${functionName}( coord : ${coordType} ) -> ${coordType} {\n\n\treturn ${coordType}(\n`; const addWrapSnippet = ( wrap, axis ) => { @@ -287,6 +369,13 @@ class WGSLNodeBuilder extends NodeBuilder { addWrapSnippet( texture.wrapT, 'y' ); + if ( texture.isData3DTexture ) { + + code += ',\n'; + addWrapSnippet( texture.wrapR, 'z' ); + + } + code += '\n\t);\n\n}\n'; wgslCodeCache[ functionName ] = nodeCode = new CodeNode( code, includes ); @@ -299,6 +388,16 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates a WGSL variable that holds the texture dimension of the given texture. + * It also returns information about the the number of layers (elements) of an arrayed + * texture as well as the cube face count of cube textures. + * + * @param {Texture} texture - The texture to generate the function for. + * @param {String} textureProperty - The name of the video texture uniform in the shader. + * @param {String} levelSnippet - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @return {String} The name of the dimension variable. + */ generateTextureDimension( texture, textureProperty, levelSnippet ) { const textureData = this.getDataFromNode( texture, this.shaderStage, this.globalCache ); @@ -310,29 +409,72 @@ class WGSLNodeBuilder extends NodeBuilder { if ( textureData.dimensionsSnippet[ levelSnippet ] === undefined ) { let textureDimensionsParams; + let dimensionType; const { primarySamples } = this.renderer.backend.utils.getTextureSampleData( texture ); + const isMultisampled = primarySamples > 1; - if ( primarySamples > 1 ) { + if ( texture.isData3DTexture ) { + + dimensionType = 'vec3'; + + } else { + + // Regular 2D textures, depth textures, etc. + dimensionType = 'vec2'; + + } + + // Build parameters string based on texture type and multisampling + if ( isMultisampled || texture.isVideoTexture || texture.isStorageTexture ) { textureDimensionsParams = textureProperty; } else { - textureDimensionsParams = `${ textureProperty }, u32( ${ levelSnippet } )`; + textureDimensionsParams = `${textureProperty}${levelSnippet ? `, u32( ${ levelSnippet } )` : ''}`; } - textureDimensionNode = new VarNode( new ExpressionNode( `textureDimensions( ${ textureDimensionsParams } )`, 'uvec2' ) ); + textureDimensionNode = new VarNode( new ExpressionNode( `textureDimensions( ${ textureDimensionsParams } )`, dimensionType ) ); textureData.dimensionsSnippet[ levelSnippet ] = textureDimensionNode; + if ( texture.isDataArrayTexture || texture.isData3DTexture ) { + + textureData.arrayLayerCount = new VarNode( + new ExpressionNode( + `textureNumLayers(${textureProperty})`, + 'u32' + ) + ); + + } + + // For cube textures, we know it's always 6 faces + if ( texture.isTextureCube ) { + + textureData.cubeFaceCount = new VarNode( + new ExpressionNode( '6u', 'u32' ) + ); + + } + } return textureDimensionNode.build( this ); } + /** + * Generates the WGSL snippet for a manual filtered texture. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String} levelSnippet - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @return {String} The WGSL snippet. + */ generateFilteredTexture( texture, textureProperty, uvSnippet, levelSnippet = '0u' ) { this._include( 'biquadraticTexture' ); @@ -344,17 +486,39 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet for a texture lookup with explicit level-of-detail. + * Since it's a lookup, no sampling or filtering is applied. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [levelSnippet='0u'] - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @return {String} The WGSL snippet. + */ generateTextureLod( texture, textureProperty, uvSnippet, depthSnippet, levelSnippet = '0u' ) { const wrapFunction = this.generateWrapFunction( texture ); const textureDimension = this.generateTextureDimension( texture, textureProperty, levelSnippet ); - const coordSnippet = `vec2u( ${ wrapFunction }( ${ uvSnippet } ) * vec2f( ${ textureDimension } ) )`; + const vecType = texture.isData3DTexture ? 'vec3' : 'vec2'; + const coordSnippet = `${vecType}(${wrapFunction}(${uvSnippet}) * ${vecType}(${textureDimension}))`; return this.generateTextureLoad( texture, textureProperty, coordSnippet, depthSnippet, levelSnippet ); } + /** + * Generates the WGSL snippet that reads a single texel from a texture without sampling or filtering. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvIndexSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [levelSnippet='0u'] - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @return {String} The WGSL snippet. + */ generateTextureLoad( texture, textureProperty, uvIndexSnippet, depthSnippet, levelSnippet = '0u' ) { if ( texture.isVideoTexture === true || texture.isStorageTexture === true ) { @@ -373,18 +537,39 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet that writes a single texel to a texture. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvIndexSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String} valueSnippet - A WGSL snippet that represent the new texel value. + * @return {String} The WGSL snippet. + */ generateTextureStore( texture, textureProperty, uvIndexSnippet, valueSnippet ) { return `textureStore( ${ textureProperty }, ${ uvIndexSnippet }, ${ valueSnippet } )`; } + /** + * Returns `true` if the sampled values of the given texture should be compared against a reference value. + * + * @param {Texture} texture - The texture. + * @return {Boolean} Whether the sampled values of the given texture should be compared against a reference value or not. + */ isSampleCompare( texture ) { return texture.isDepthTexture === true && texture.compareFunction !== null; } + /** + * Returns `true` if the given texture is unfilterable. + * + * @param {Texture} texture - The texture. + * @return {Boolean} Whether the given texture is unfilterable or not. + */ isUnfilterable( texture ) { return this.getComponentTypeFromTexture( texture ) !== 'float' || @@ -394,6 +579,16 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet for sampling/loading the given texture. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ generateTexture( texture, textureProperty, uvSnippet, depthSnippet, shaderStage = this.shaderStage ) { let snippet = null; @@ -416,6 +611,17 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet for sampling/loading the given texture using explicit gradients. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {Array} gradSnippet - An array holding both gradient WGSL snippets. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ generateTextureGrad( texture, textureProperty, uvSnippet, gradSnippet, depthSnippet, shaderStage = this.shaderStage ) { if ( shaderStage === 'fragment' ) { @@ -431,6 +637,18 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet for sampling a depth texture and comparing the sampled depth values + * against a reference value. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String} compareSnippet - A WGSL snippet that represents the reference value. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ generateTextureCompare( texture, textureProperty, uvSnippet, compareSnippet, depthSnippet, shaderStage = this.shaderStage ) { if ( shaderStage === 'fragment' ) { @@ -445,6 +663,17 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet when sampling textures with explicit mip level. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String} levelSnippet - A WGSL snippet that represents the mip level, with level 0 containing a full size version of the texture. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ generateTextureLevel( texture, textureProperty, uvSnippet, levelSnippet, depthSnippet, shaderStage = this.shaderStage ) { let snippet = null; @@ -463,6 +692,17 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Generates the WGSL snippet when sampling textures with a bias to the mip level. + * + * @param {Texture} texture - The texture. + * @param {String} textureProperty - The name of the texture uniform in the shader. + * @param {String} uvSnippet - A WGSL snippet that represents texture coordinates used for sampling. + * @param {String} biasSnippet - A WGSL snippet that represents the bias to apply to the mip level before sampling. + * @param {String?} depthSnippet - A WGSL snippet that represents 0-based texture array index to sample. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The WGSL snippet. + */ generateTextureBias( texture, textureProperty, uvSnippet, biasSnippet, depthSnippet, shaderStage = this.shaderStage ) { if ( shaderStage === 'fragment' ) { @@ -477,6 +717,13 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Returns a WGSL snippet that represents the property name of the given node. + * + * @param {Node} node - The node. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The property name. + */ getPropertyName( node, shaderStage = this.shaderStage ) { if ( node.isNodeVarying === true && node.needsInterpolation === true ) { @@ -512,18 +759,36 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Returns the output struct name. + * + * @return {String} The name of the output struct. + */ getOutputStructName() { return 'output'; } + /** + * Returns uniforms group count for the given shader stage. + * + * @private + * @param {String} shaderStage - The shader stage. + * @return {Number} The uniforms group count for the given shader stage. + */ _getUniformGroupCount( shaderStage ) { return Object.keys( this.uniforms[ shaderStage ] ).length; } + /** + * Returns the native shader operator name for a given generic name. + * + * @param {String} op - The operator name to resolve. + * @return {String} The resolved operator name. + */ getFunctionOperator( op ) { const fnOp = wgslFnOpLib[ op ]; @@ -540,6 +805,13 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Returns the node access for the given node and shader stage. + * + * @param {StorageTextureNode|StorageBufferNode} node - The storage node. + * @param {String} shaderStage - The shader stage. + * @return {String} The node access. + */ getNodeAccess( node, shaderStage ) { if ( shaderStage !== 'compute' ) @@ -549,12 +821,32 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Returns A WGSL snippet representing the storage access. + * + * @param {StorageTextureNode|StorageBufferNode} node - The storage node. + * @param {String} shaderStage - The shader stage. + * @return {String} The WGSL snippet representing the storage access. + */ getStorageAccess( node, shaderStage ) { return accessNames[ this.getNodeAccess( node, shaderStage ) ]; } + /** + * This method is one of the more important ones since it's responsible + * for generating a matching binding instance for the given uniform node. + * + * These bindings are later used in the renderer to create bind groups + * and layouts. + * + * @param {UniformNode} node - The uniform node. + * @param {String} type - The node data type. + * @param {String} shaderStage - The shader stage. + * @param {String?} [name=null] - An optional uniform name. + * @return {NodeUniform} The node uniform object. + */ getUniformFromNode( node, type, shaderStage, name = null ) { const uniformNode = super.getUniformFromNode( node, type, shaderStage, name ); @@ -651,6 +943,17 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * This method should be used whenever builtins are required in nodes. + * The internal builtins data structure will make sure builtins are + * defined in the WGSL source. + * + * @param {String} name - The builtin name. + * @param {String} property - The property name. + * @param {String} type - The node data type. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} The property name. + */ getBuiltin( name, property, type, shaderStage = this.shaderStage ) { const map = this.builtins[ shaderStage ] || ( this.builtins[ shaderStage ] = new Map() ); @@ -669,12 +972,24 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Returns `true` if the given builtin is defined in the given shader stage. + * + * @param {String} name - The builtin name. + * @param {String} [shaderStage=this.shaderStage] - The shader stage this code snippet is generated for. + * @return {String} Whether the given builtin is defined in the given shader stage or not. + */ hasBuiltin( name, shaderStage = this.shaderStage ) { return ( this.builtins[ shaderStage ] !== undefined && this.builtins[ shaderStage ].has( name ) ); } + /** + * Returns the vertex index builtin. + * + * @return {String} The vertex index. + */ getVertexIndex() { if ( this.shaderStage === 'vertex' ) { @@ -687,6 +1002,12 @@ class WGSLNodeBuilder extends NodeBuilder { } + /** + * Builds the given shader node. + * + * @param {ShaderNodeInternal} shaderNode - The shader node. + * @return {String} The WGSL function code. + */ buildFunctionCode( shaderNode ) { const layout = shaderNode.layout; @@ -721,6 +1042,11 @@ ${ flowData.code } } + /** + * Returns the instance index builtin. + * + * @return {String} The instance index. + */ getInstanceIndex() { if ( this.shaderStage === 'vertex' ) { @@ -733,12 +1059,22 @@ ${ flowData.code } } + /** + * Returns the invocation local index builtin. + * + * @return {String} The invocation local index. + */ getInvocationLocalIndex() { return this.getBuiltin( 'local_invocation_index', 'invocationLocalIndex', 'u32', 'attribute' ); } + /** + * Returns the subgroup size builtin. + * + * @return {String} The subgroup size. + */ getSubgroupSize() { this.enableSubGroups(); @@ -747,6 +1083,11 @@ ${ flowData.code } } + /** + * Returns the invocation subgroup index builtin. + * + * @return {String} The invocation subgroup index. + */ getInvocationSubgroupIndex() { this.enableSubGroups(); @@ -755,6 +1096,11 @@ ${ flowData.code } } + /** + * Returns the subgroup index builtin. + * + * @return {String} The subgroup index. + */ getSubgroupIndex() { this.enableSubGroups(); @@ -763,42 +1109,78 @@ ${ flowData.code } } + /** + * Overwritten as a NOP since this method is intended for the WebGL 2 backend. + * + * @return {null} Null. + */ getDrawIndex() { return null; } + /** + * Returns the front facing builtin. + * + * @return {String} The front facing builtin. + */ getFrontFacing() { return this.getBuiltin( 'front_facing', 'isFront', 'bool' ); } + /** + * Returns the frag coord builtin. + * + * @return {String} The frag coord builtin. + */ getFragCoord() { return this.getBuiltin( 'position', 'fragCoord', 'vec4' ) + '.xy'; } + /** + * Returns the frag depth builtin. + * + * @return {String} The frag depth builtin. + */ getFragDepth() { return 'output.' + this.getBuiltin( 'frag_depth', 'depth', 'f32', 'output' ); } + /** + * Returns the clip distances builtin. + * + * @return {String} The clip distances builtin. + */ getClipDistance() { return 'varyings.hw_clip_distances'; } + /** + * Whether to flip texture data along its vertical axis or not. + * + * @return {Boolean} Returns always `false` in context of WGSL. + */ isFlipY() { return false; } + /** + * Enables the given directive for the given shader stage. + * + * @param {String} name - The directive name. + * @param {String} [shaderStage=this.shaderStage] - The shader stage to enable the directive for. + */ enableDirective( name, shaderStage = this.shaderStage ) { const stage = this.directives[ shaderStage ] || ( this.directives[ shaderStage ] = new Set() ); @@ -806,6 +1188,12 @@ ${ flowData.code } } + /** + * Returns the directives of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} A WGSL snippet that enables the directives of the given stage. + */ getDirectives( shaderStage ) { const snippets = []; @@ -825,36 +1213,56 @@ ${ flowData.code } } + /** + * Enables the 'subgroups' directive. + */ enableSubGroups() { this.enableDirective( 'subgroups' ); } + /** + * Enables the 'subgroups-f16' directive. + */ enableSubgroupsF16() { this.enableDirective( 'subgroups-f16' ); } + /** + * Enables the 'clip_distances' directive. + */ enableClipDistances() { this.enableDirective( 'clip_distances' ); } + /** + * Enables the 'f16' directive. + */ enableShaderF16() { this.enableDirective( 'f16' ); } + /** + * Enables the 'dual_source_blending' directive. + */ enableDualSourceBlending() { this.enableDirective( 'dual_source_blending' ); } + /** + * Enables hardware clipping. + * + * @param {String} planeCount - The clipping plane count. + */ enableHardwareClipping( planeCount ) { this.enableClipDistances(); @@ -862,6 +1270,12 @@ ${ flowData.code } } + /** + * Returns the builtins of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} A WGSL snippet that represents the builtins of the given stage. + */ getBuiltins( shaderStage ) { const snippets = []; @@ -881,6 +1295,17 @@ ${ flowData.code } } + /** + * This method should be used when a new scoped buffer is used in context of + * compute shaders. It adds the array to the internal data structure which is + * later used to generate the respective WGSL. + * + * @param {String} name - The array name. + * @param {String} scope - The scope. + * @param {String} bufferType - The buffer type. + * @param {String} bufferCount - The buffer count. + * @return {String} The array name. + */ getScopedArray( name, scope, bufferType, bufferCount ) { if ( this.scopedArrays.has( name ) === false ) { @@ -898,6 +1323,13 @@ ${ flowData.code } } + /** + * Returns the scoped arrays of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String|undefined} The WGSL snippet that defines the scoped arrays. + * Returns `undefined` when used in the vertex or fragment stage. + */ getScopedArrays( shaderStage ) { if ( shaderStage !== 'compute' ) { @@ -920,13 +1352,19 @@ ${ flowData.code } } + /** + * Returns the shader attributes of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The WGSL snippet that defines the shader attributes. + */ getAttributes( shaderStage ) { const snippets = []; if ( shaderStage === 'compute' ) { - this.getBuiltin( 'global_invocation_id', 'id', 'vec3', 'attribute' ); + this.getBuiltin( 'global_invocation_id', 'globalId', 'vec3', 'attribute' ); this.getBuiltin( 'workgroup_id', 'workgroupId', 'vec3', 'attribute' ); this.getBuiltin( 'local_invocation_id', 'localId', 'vec3', 'attribute' ); this.getBuiltin( 'num_workgroups', 'numWorkgroups', 'vec3', 'attribute' ); @@ -964,6 +1402,12 @@ ${ flowData.code } } + /** + * Returns the members of the given struct type node as a WGSL string. + * + * @param {StructTypeNode} struct - The struct type node. + * @return {String} The WGSL snippet that defines the struct members. + */ getStructMembers( struct ) { const snippets = []; @@ -984,6 +1428,12 @@ ${ flowData.code } } + /** + * Returns the structs of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The WGSL snippet that defines the structs. + */ getStructs( shaderStage ) { const snippets = []; @@ -1009,12 +1459,25 @@ ${ flowData.code } } + /** + * Returns a WGSL string representing a variable. + * + * @param {String} type - The variable's type. + * @param {String} name - The variable's name. + * @return {String} The WGSL snippet that defines a variable. + */ getVar( type, name ) { return `var ${ name } : ${ this.getType( type ) }`; } + /** + * Returns the variables of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The WGSL snippet that defines the variables. + */ getVars( shaderStage ) { const snippets = []; @@ -1034,6 +1497,12 @@ ${ flowData.code } } + /** + * Returns the varyings of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The WGSL snippet that defines the varyings. + */ getVaryings( shaderStage ) { const snippets = []; @@ -1086,6 +1555,12 @@ ${ flowData.code } } + /** + * Returns the uniforms of the given shader stage as a WGSL string. + * + * @param {String} shaderStage - The shader stage. + * @return {String} The WGSL snippet that defines the uniforms. + */ getUniforms( shaderStage ) { const uniforms = this.uniforms[ shaderStage ]; @@ -1213,6 +1688,9 @@ ${ flowData.code } } + /** + * Controls the code build of the shader stages. + */ buildCode() { const shadersData = this.material !== null ? { fragment: {}, vertex: {} } : { compute: {} }; @@ -1251,7 +1729,7 @@ ${ flowData.code } if ( flow.length > 0 ) flow += '\n'; - flow += `\t// flow -> ${ slotName }\n\t`; + flow += `\t// flow -> ${ slotName }\n`; } @@ -1313,6 +1791,13 @@ ${ flowData.code } } + /** + * Returns the native shader method name for a given generic name. + * + * @param {String} method - The method name to resolve. + * @param {String} [output=null] - An optional output. + * @return {String} The resolved WGSL method name. + */ getMethod( method, output = null ) { let wgslMethod; @@ -1333,12 +1818,24 @@ ${ flowData.code } } + /** + * Returns the WGSL type of the given node data type. + * + * @param {String} type - The node data type. + * @return {String} The WGSL type. + */ getType( type ) { return wgslTypeLib[ type ] || type; } + /** + * Whether the requested feature is available or not. + * + * @param {String} name - The requested feature. + * @return {Boolean} Whether the requested feature is supported or not. + */ isAvailable( name ) { let result = supports[ name ]; @@ -1363,6 +1860,13 @@ ${ flowData.code } } + /** + * Returns the native shader method name for a given generic name. + * + * @private + * @param {String} method - The method name to resolve. + * @return {String} The resolved WGSL method name. + */ _getWGSLMethod( method ) { if ( wgslPolyfill[ method ] !== undefined ) { @@ -1375,6 +1879,14 @@ ${ flowData.code } } + /** + * Includes the given method name into the current + * function node. + * + * @private + * @param {String} name - The method name to include. + * @return {CodeNode} The respective code node. + */ _include( name ) { const codeNode = wgslPolyfill[ name ]; @@ -1390,6 +1902,13 @@ ${ flowData.code } } + /** + * Returns a WGSL vertex shader based on the given shader data. + * + * @private + * @param {Object} shaderData - The shader data. + * @return {String} The vertex shader. + */ _getWGSLVertexCode( shaderData ) { return `${ this.getSignature() } @@ -1422,6 +1941,13 @@ fn main( ${shaderData.attributes} ) -> VaryingsStruct { } + /** + * Returns a WGSL fragment shader based on the given shader data. + * + * @private + * @param {Object} shaderData - The shader data. + * @return {String} The vertex shader. + */ _getWGSLFragmentCode( shaderData ) { return `${ this.getSignature() } @@ -1451,6 +1977,14 @@ fn main( ${shaderData.varyings} ) -> ${shaderData.returnType} { } + /** + * Returns a WGSL compute shader based on the given shader data. + * + * @private + * @param {Object} shaderData - The shader data. + * @param {String} workgroupSize - The workgroup size. + * @return {String} The vertex shader. + */ _getWGSLComputeCode( shaderData, workgroupSize ) { return `${ this.getSignature() } @@ -1473,7 +2007,7 @@ ${shaderData.codes} fn main( ${shaderData.attributes} ) { // system - instanceIndex = id.x + id.y * numWorkgroups.x * u32(${workgroupSize}) + id.z * numWorkgroups.x * numWorkgroups.y * u32(${workgroupSize}); + instanceIndex = globalId.x + globalId.y * numWorkgroups.x * u32(${workgroupSize}) + globalId.z * numWorkgroups.x * numWorkgroups.y * u32(${workgroupSize}); // vars ${shaderData.vars} @@ -1486,6 +2020,14 @@ fn main( ${shaderData.attributes} ) { } + /** + * Returns a WGSL struct based on the given name and variables. + * + * @private + * @param {String} name - The struct name. + * @param {String} vars - The struct variables. + * @return {String} The WGSL snippet representing a struct. + */ _getWGSLStruct( name, vars ) { return ` @@ -1495,6 +2037,17 @@ ${vars} } + /** + * Returns a WGSL struct binding. + * + * @private + * @param {String} name - The struct name. + * @param {String} vars - The struct variables. + * @param {String} access - The access. + * @param {Number} [binding=0] - The binding index. + * @param {Number} [group=0] - The group index. + * @return {String} The WGSL snippet representing a struct binding. + */ _getWGSLStructBinding( name, vars, access, binding = 0, group = 0 ) { const structName = name + 'Struct'; diff --git a/src/renderers/webgpu/utils/WebGPUAttributeUtils.js b/src/renderers/webgpu/utils/WebGPUAttributeUtils.js index 7ed75a05ec8b2e..f98f4e9a3b9872 100644 --- a/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +++ b/src/renderers/webgpu/utils/WebGPUAttributeUtils.js @@ -24,14 +24,35 @@ const typeArraysToVertexFormatPrefixForItemSize1 = new Map( [ [ Float32Array, 'float32' ] ] ); +/** + * A WebGPU backend utility module for managing shader attributes. + * + * @private + */ class WebGPUAttributeUtils { + /** + * Constructs a new utility object. + * + * @param {WebGPUBackend} backend - The WebGPU backend. + */ constructor( backend ) { + /** + * A reference to the WebGPU backend. + * + * @type {WebGPUBackend} + */ this.backend = backend; } + /** + * Creates the GPU buffer for the given buffer attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + * @param {GPUBufferUsage} usage - A flag that indicates how the buffer may be used after its creation. + */ createAttribute( attribute, usage ) { const bufferAttribute = this._getBufferAttribute( attribute ); @@ -48,16 +69,27 @@ class WebGPUAttributeUtils { let array = bufferAttribute.array; // patch for INT16 and UINT16 - if ( attribute.normalized === false && ( array.constructor === Int16Array || array.constructor === Uint16Array ) ) { + if ( attribute.normalized === false ) { - const tempArray = new Uint32Array( array.length ); - for ( let i = 0; i < array.length; i ++ ) { + if ( array.constructor === Int16Array ) { - tempArray[ i ] = array[ i ]; + array = new Int32Array( array ); - } + } else if ( array.constructor === Uint16Array ) { + + array = new Uint32Array( array ); + + if ( usage & GPUBufferUsage.INDEX ) { + + for ( let i = 0; i < array.length; i ++ ) { - array = tempArray; + if ( array[ i ] === 0xffff ) array[ i ] = 0xffffffff; // use correct primitive restart index + + } + + } + + } } @@ -98,6 +130,11 @@ class WebGPUAttributeUtils { } + /** + * Updates the GPU buffer of the given buffer attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ updateAttribute( attribute ) { const bufferAttribute = this._getBufferAttribute( attribute ); @@ -149,6 +186,13 @@ class WebGPUAttributeUtils { } + /** + * This method creates the vertex buffer layout data which are + * require when creating a render pipeline for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @return {Array} An array holding objects which describe the vertex buffer layout. + */ createShaderVertexBuffers( renderObject ) { const attributes = renderObject.getAttributes(); @@ -210,6 +254,11 @@ class WebGPUAttributeUtils { } + /** + * Destroys the GPU buffer of the given buffer attribute. + * + * @param {BufferAttribute} attribute - The buffer attribute. + */ destroyAttribute( attribute ) { const backend = this.backend; @@ -221,6 +270,14 @@ class WebGPUAttributeUtils { } + /** + * This method performs a readback operation by moving buffer data from + * a storage buffer attribute from the GPU to the CPU. + * + * @async + * @param {StorageBufferAttribute} attribute - The storage buffer attribute. + * @return {Promise} A promise that resolves with the buffer data when the data are ready. + */ async getArrayBufferAsync( attribute ) { const backend = this.backend; @@ -263,6 +320,13 @@ class WebGPUAttributeUtils { } + /** + * Returns the vertex format of the given buffer attribute. + * + * @private + * @param {BufferAttribute} geometryAttribute - The buffer attribute. + * @return {String} The vertex format (e.g. 'float32x3'). + */ _getVertexFormat( geometryAttribute ) { const { itemSize, normalized } = geometryAttribute; @@ -308,12 +372,27 @@ class WebGPUAttributeUtils { } + /** + * Returns `true` if the given array is a typed array. + * + * @private + * @param {Any} array - The array. + * @return {Boolean} Whether the given array is a typed array or not. + */ _isTypedArray( array ) { return ArrayBuffer.isView( array ) && ! ( array instanceof DataView ); } + /** + * Utility method for handling interleaved buffer attributes correctly. + * To process them, their `InterleavedBuffer` is returned. + * + * @private + * @param {BufferAttribute} attribute - The attribute. + * @return {BufferAttribute|InterleavedBuffer} + */ _getBufferAttribute( attribute ) { if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; diff --git a/src/renderers/webgpu/utils/WebGPUBindingUtils.js b/src/renderers/webgpu/utils/WebGPUBindingUtils.js index ba349d46592520..73e22f249f1c5a 100644 --- a/src/renderers/webgpu/utils/WebGPUBindingUtils.js +++ b/src/renderers/webgpu/utils/WebGPUBindingUtils.js @@ -5,15 +5,47 @@ import { import { FloatType, IntType, UnsignedIntType } from '../../../constants.js'; import { NodeAccess } from '../../../nodes/core/constants.js'; +/** + * A WebGPU backend utility module for managing bindings. + * + * When reading the documentation it's helpful to keep in mind that + * all class definitions starting with 'GPU*' are modules from the + * WebGPU API. So for example `BindGroup` is a class from the engine + * whereas `GPUBindGroup` is a class from WebGPU. + * + * @private + */ class WebGPUBindingUtils { + /** + * Constructs a new utility object. + * + * @param {WebGPUBackend} backend - The WebGPU backend. + */ constructor( backend ) { + /** + * A reference to the WebGPU backend. + * + * @type {WebGPUBackend} + */ this.backend = backend; + + /** + * A cache for managing bind group layouts. + * + * @type {WeakMap,GPUBindGroupLayout>} + */ this.bindGroupLayoutCache = new WeakMap(); } + /** + * Creates a GPU bind group layout for the given bind group. + * + * @param {BindGroup} bindGroup - The bind group. + * @return {GPUBindGroupLayout} The GPU bind group layout. + */ createBindingsLayout( bindGroup ) { const backend = this.backend; @@ -183,6 +215,14 @@ class WebGPUBindingUtils { } + /** + * Creates bindings from the given bind group definition. + * + * @param {BindGroup} bindGroup - The bind group. + * @param {Array} bindings - Array of bind groups. + * @param {Number} cacheIndex - The cache index. + * @param {Number} version - The version. + */ createBindings( bindGroup, bindings, cacheIndex, version = 0 ) { const { backend, bindGroupLayoutCache } = this; @@ -236,6 +276,11 @@ class WebGPUBindingUtils { } + /** + * Updates a buffer binding. + * + * @param {Buffer} binding - The buffer binding to update. + */ updateBinding( binding ) { const backend = this.backend; @@ -248,6 +293,13 @@ class WebGPUBindingUtils { } + /** + * Creates a GPU bind group for the given bind group and GPU layout. + * + * @param {BindGroup} bindGroup - The bind group. + * @param {GPUBindGroupLayout} layoutGPU - The GPU bind group layout. + * @return {GPUBindGroup} The GPU bind group. + */ createBindGroup( bindGroup, layoutGPU ) { const backend = this.backend; diff --git a/src/renderers/webgpu/utils/WebGPUPipelineUtils.js b/src/renderers/webgpu/utils/WebGPUPipelineUtils.js index c0a20faee05f91..5292bed51d8b1e 100644 --- a/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +++ b/src/renderers/webgpu/utils/WebGPUPipelineUtils.js @@ -15,20 +15,48 @@ import { NeverStencilFunc, AlwaysStencilFunc, LessStencilFunc, LessEqualStencilFunc, EqualStencilFunc, GreaterEqualStencilFunc, GreaterStencilFunc, NotEqualStencilFunc } from '../../../constants.js'; +/** + * A WebGPU backend utility module for managing pipelines. + * + * @private + */ class WebGPUPipelineUtils { + /** + * Constructs a new utility object. + * + * @param {WebGPUBackend} backend - The WebGPU backend. + */ constructor( backend ) { + /** + * A reference to the WebGPU backend. + * + * @type {WebGPUBackend} + */ this.backend = backend; } - _getSampleCount( renderObjectContext ) { + /** + * Returns the sample count derived from the given render context. + * + * @private + * @param {RenderContext} renderContext - The render context. + * @return {Number} The sample count. + */ + _getSampleCount( renderContext ) { - return this.backend.utils.getSampleCountRenderContext( renderObjectContext ); + return this.backend.utils.getSampleCountRenderContext( renderContext ); } + /** + * Creates a render pipeline for the given render object. + * + * @param {RenderObject} renderObject - The render object. + * @param {Array} promises - An array of compilation promises which are used in `compileAsync()`. + */ createRenderPipeline( renderObject, promises ) { const { object, material, geometry, pipeline } = renderObject; @@ -188,6 +216,12 @@ class WebGPUPipelineUtils { } + /** + * Creates GPU render bundle encoder for the given render context. + * + * @param {RenderContext} renderContext - The render context. + * @return {GPURenderBundleEncoder} The GPU render bundle encoder. + */ createBundleEncoder( renderContext ) { const backend = this.backend; @@ -208,6 +242,12 @@ class WebGPUPipelineUtils { } + /** + * Creates a compute pipeline for the given compute node. + * + * @param {ComputePipeline} pipeline - The compute pipeline. + * @param {Array} bindings - The bindings. + */ createComputePipeline( pipeline, bindings ) { const backend = this.backend; @@ -238,6 +278,14 @@ class WebGPUPipelineUtils { } + /** + * Returns the blending state as a descriptor object required + * for the pipeline creation. + * + * @private + * @param {Material} material - The material. + * @return {Object} The blending state. + */ _getBlending( material ) { let color, alpha; @@ -345,7 +393,13 @@ class WebGPUPipelineUtils { } } - + /** + * Returns the GPU blend factor which is required for the pipeline creation. + * + * @private + * @param {Number} blend - The blend factor as a three.js constant. + * @return {String} The GPU blend factor. + */ _getBlendFactor( blend ) { let blendFactor; @@ -413,6 +467,13 @@ class WebGPUPipelineUtils { } + /** + * Returns the GPU stencil compare function which is required for the pipeline creation. + * + * @private + * @param {Material} material - The material. + * @return {String} The GPU stencil compare function. + */ _getStencilCompare( material ) { let stencilCompare; @@ -462,6 +523,13 @@ class WebGPUPipelineUtils { } + /** + * Returns the GPU stencil operation which is required for the pipeline creation. + * + * @private + * @param {Number} op - A three.js constant defining the stencil operation. + * @return {String} The GPU stencil operation. + */ _getStencilOperation( op ) { let stencilOperation; @@ -509,6 +577,13 @@ class WebGPUPipelineUtils { } + /** + * Returns the GPU blend operation which is required for the pipeline creation. + * + * @private + * @param {Number} blendEquation - A three.js constant defining the blend equation. + * @return {String} The GPU blend operation. + */ _getBlendOperation( blendEquation ) { let blendOperation; @@ -544,6 +619,16 @@ class WebGPUPipelineUtils { } + /** + * Returns the primitive state as a descriptor object required + * for the pipeline creation. + * + * @private + * @param {Object3D} object - The 3D object. + * @param {BufferGeometry} geometry - The geometry. + * @param {Material} material - The material. + * @return {Object} The primitive state. + */ _getPrimitiveState( object, geometry, material ) { const descriptor = {}; @@ -584,12 +669,26 @@ class WebGPUPipelineUtils { } + /** + * Returns the GPU color write mask which is required for the pipeline creation. + * + * @private + * @param {Material} material - The material. + * @return {String} The GPU color write mask. + */ _getColorWriteMask( material ) { return ( material.colorWrite === true ) ? GPUColorWriteFlags.All : GPUColorWriteFlags.None; } + /** + * Returns the GPU depth compare function which is required for the pipeline creation. + * + * @private + * @param {Material} material - The material. + * @return {String} The GPU depth compare function. + */ _getDepthCompare( material ) { let depthCompare; diff --git a/src/renderers/webgpu/utils/WebGPUTexturePassUtils.js b/src/renderers/webgpu/utils/WebGPUTexturePassUtils.js index 913854e7a84423..33e63ca963c527 100644 --- a/src/renderers/webgpu/utils/WebGPUTexturePassUtils.js +++ b/src/renderers/webgpu/utils/WebGPUTexturePassUtils.js @@ -1,12 +1,27 @@ import DataMap from '../../common/DataMap.js'; import { GPUTextureViewDimension, GPUIndexFormat, GPUFilterMode, GPUPrimitiveTopology, GPULoadOp, GPUStoreOp } from './WebGPUConstants.js'; +/** + * A WebGPU backend utility module used by {@link WebGPUTextureUtils}. + * + * @private + */ class WebGPUTexturePassUtils extends DataMap { + /** + * Constructs a new utility object. + * + * @param {GPUDevice} device - The WebGPU device. + */ constructor( device ) { super(); + /** + * The WebGPU device. + * + * @type {GPUDevice} + */ this.device = device; const mipmapVertexSource = ` @@ -71,23 +86,62 @@ fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { } `; + + /** + * The mipmap GPU sampler. + * + * @type {GPUSampler} + */ this.mipmapSampler = device.createSampler( { minFilter: GPUFilterMode.Linear } ); + + /** + * The flipY GPU sampler. + * + * @type {GPUSampler} + */ this.flipYSampler = device.createSampler( { minFilter: GPUFilterMode.Nearest } ); //@TODO?: Consider using textureLoad() - // We'll need a new pipeline for every texture format used. + /** + * A cache for GPU render pipelines used for copy/transfer passes. + * Every texture format requires a unique pipeline. + * + * @type {Object} + */ this.transferPipelines = {}; + + /** + * A cache for GPU render pipelines used for flipY passes. + * Every texture format requires a unique pipeline. + * + * @type {Object} + */ this.flipYPipelines = {}; + /** + * The mipmap vertex shader module. + * + * @type {GPUShaderModule} + */ this.mipmapVertexShaderModule = device.createShaderModule( { label: 'mipmapVertex', code: mipmapVertexSource } ); + /** + * The mipmap fragment shader module. + * + * @type {GPUShaderModule} + */ this.mipmapFragmentShaderModule = device.createShaderModule( { label: 'mipmapFragment', code: mipmapFragmentSource } ); + /** + * The flipY fragment shader module. + * + * @type {GPUShaderModule} + */ this.flipYFragmentShaderModule = device.createShaderModule( { label: 'flipYFragment', code: flipYFragmentSource @@ -95,6 +149,13 @@ fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { } + /** + * Returns a render pipeline for the internal copy render pass. The pass + * requires a unique render pipeline for each texture format. + * + * @param {String} format - The GPU texture format + * @return {GPURenderPipeline} The GPU render pipeline. + */ getTransferPipeline( format ) { let pipeline = this.transferPipelines[ format ]; @@ -127,6 +188,13 @@ fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { } + /** + * Returns a render pipeline for the flipY render pass. The pass + * requires a unique render pipeline for each texture format. + * + * @param {String} format - The GPU texture format + * @return {GPURenderPipeline} The GPU render pipeline. + */ getFlipYPipeline( format ) { let pipeline = this.flipYPipelines[ format ]; @@ -159,6 +227,13 @@ fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { } + /** + * Flip the contents of the given GPU texture along its vertical axis. + * + * @param {GPUTexture} textureGPU - The GPU texture object. + * @param {Object} textureGPUDescriptor - The texture descriptor. + * @param {Number} [baseArrayLayer=0] - The index of the first array layer accessible to the texture view. + */ flipY( textureGPU, textureGPUDescriptor, baseArrayLayer = 0 ) { const format = textureGPUDescriptor.format; @@ -229,6 +304,13 @@ fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { } + /** + * Generates mipmaps for the given GPU texture. + * + * @param {GPUTexture} textureGPU - The GPU texture object. + * @param {Object} textureGPUDescriptor - The texture descriptor. + * @param {Number} [baseArrayLayer=0] - The index of the first array layer accessible to the texture view. + */ generateMipmaps( textureGPU, textureGPUDescriptor, baseArrayLayer = 0 ) { const textureData = this.get( textureGPU ); @@ -254,6 +336,15 @@ fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { } + /** + * Since multiple copy render passes are required to generate mipmaps, the passes + * are managed as render bundles to improve performance. + * + * @param {GPUTexture} textureGPU - The GPU texture object. + * @param {Object} textureGPUDescriptor - The texture descriptor. + * @param {Number} baseArrayLayer - The index of the first array layer accessible to the texture view. + * @return {Array} An array of render bundles. + */ _mipmapCreateBundles( textureGPU, textureGPUDescriptor, baseArrayLayer ) { const pipeline = this.getTransferPipeline( textureGPUDescriptor.format ); @@ -319,6 +410,12 @@ fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { } + /** + * Executes the render bundles. + * + * @param {GPUCommandEncoder} commandEncoder - The GPU command encoder. + * @param {Array} passes - An array of render bundles. + */ _mipmapRunBundles( commandEncoder, passes ) { const levels = passes.length; diff --git a/src/renderers/webgpu/utils/WebGPUTextureUtils.js b/src/renderers/webgpu/utils/WebGPUTextureUtils.js index 476c86784b8338..694e54aa6a59d4 100644 --- a/src/renderers/webgpu/utils/WebGPUTextureUtils.js +++ b/src/renderers/webgpu/utils/WebGPUTextureUtils.js @@ -32,25 +32,82 @@ const _compareToWebGPU = { const _flipMap = [ 0, 1, 3, 2, 4, 5 ]; +/** + * A WebGPU backend utility module for managing textures. + * + * @private + */ class WebGPUTextureUtils { + /** + * Constructs a new utility object. + * + * @param {WebGPUBackend} backend - The WebGPU backend. + */ constructor( backend ) { + /** + * A reference to the WebGPU backend. + * + * @type {WebGPUBackend} + */ this.backend = backend; + /** + * A reference to the pass utils. + * + * @type {WebGPUTexturePassUtils?} + * @default null + */ this._passUtils = null; + /** + * A dictionary for managing default textures. The key + * is the texture format, the value the texture object. + * + * @type {Object} + */ this.defaultTexture = {}; + + /** + * A dictionary for managing default cube textures. The key + * is the texture format, the value the texture object. + * + * @type {Object} + */ this.defaultCubeTexture = {}; + + /** + * A default video frame. + * + * @type {VideoFrame?} + * @default null + */ this.defaultVideoFrame = null; + /** + * Represents the color attachment of the default framebuffer. + * + * @type {GPUTexture?} + * @default null + */ this.colorBuffer = null; + /** + * Represents the depth attachment of the default framebuffer. + * + * @type {DepthTexture} + */ this.depthTexture = new DepthTexture(); this.depthTexture.name = 'depthBuffer'; } + /** + * Creates a GPU sampler for the given texture. + * + * @param {Texture} texture - The texture to create the sampler for. + */ createSampler( texture ) { const backend = this.backend; @@ -86,6 +143,12 @@ class WebGPUTextureUtils { } + /** + * Creates a default texture for the given texture that can be used + * as a placeholder until the actual texture is ready for usage. + * + * @param {Texture} texture - The texture to create a default texture for. + */ createDefaultTexture( texture ) { let textureGPU; @@ -110,6 +173,13 @@ class WebGPUTextureUtils { } + /** + * Defines a texture on the GPU for the given texture object. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + * @return {undefined} + */ createTexture( texture, options = {} ) { const backend = this.backend; @@ -221,6 +291,11 @@ class WebGPUTextureUtils { } + /** + * Destroys the GPU data for the given texture object. + * + * @param {Texture} texture - The texture. + */ destroyTexture( texture ) { const backend = this.backend; @@ -234,6 +309,11 @@ class WebGPUTextureUtils { } + /** + * Destroys the GPU sampler for the given texture. + * + * @param {Texture} texture - The texture to destroy the sampler for. + */ destroySampler( texture ) { const backend = this.backend; @@ -243,6 +323,11 @@ class WebGPUTextureUtils { } + /** + * Generates mipmaps for the given texture. + * + * @param {Texture} texture - The texture. + */ generateMipmaps( texture ) { const textureData = this.backend.get( texture ); @@ -269,6 +354,12 @@ class WebGPUTextureUtils { } + /** + * Returns the color buffer representing the color + * attachment of the default framebuffer. + * + * @return {GPUTexture} The color buffer. + */ getColorBuffer() { if ( this.colorBuffer ) this.colorBuffer.destroy(); @@ -292,6 +383,14 @@ class WebGPUTextureUtils { } + /** + * Returns the depth buffer representing the depth + * attachment of the default framebuffer. + * + * @param {Boolean} [depth=true] - Whether depth is enabled or not. + * @param {Boolean} [stencil=false] - Whether stencil is enabled or not. + * @return {GPUTexture} The depth buffer. + */ getDepthBuffer( depth = true, stencil = false ) { const backend = this.backend; @@ -338,6 +437,12 @@ class WebGPUTextureUtils { } + /** + * Uploads the updated texture data to the GPU. + * + * @param {Texture} texture - The texture. + * @param {Object} [options={}] - Optional configuration parameter. + */ updateTexture( texture, options ) { const textureData = this.backend.get( texture ); @@ -389,6 +494,18 @@ class WebGPUTextureUtils { } + /** + * Returns texture data as a typed array. + * + * @async + * @param {Texture} texture - The texture to copy. + * @param {Number} x - The x coordinate of the copy origin. + * @param {Number} y - The y coordinate of the copy origin. + * @param {Number} width - The width of the copy. + * @param {Number} height - The height of the copy. + * @param {Number} faceIndex - The face index. + * @return {Promise} A Promise that resolves with a typed array when the copy operation has finished. + */ async copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { const device = this.backend.device; @@ -438,6 +555,13 @@ class WebGPUTextureUtils { } + /** + * Returns `true` if the given texture is an environment map. + * + * @private + * @param {Texture} texture - The texture. + * @return {Boolean} Whether the given texture is an environment map or not. + */ _isEnvironmentTexture( texture ) { const mapping = texture.mapping; @@ -446,6 +570,13 @@ class WebGPUTextureUtils { } + /** + * Returns the default GPU texture for the given format. + * + * @private + * @param {String} format - The GPU format. + * @return {GPUTexture} The GPU texture. + */ _getDefaultTextureGPU( format ) { let defaultTexture = this.defaultTexture[ format ]; @@ -466,6 +597,13 @@ class WebGPUTextureUtils { } + /** + * Returns the default GPU cube texture for the given format. + * + * @private + * @param {String} format - The GPU format. + * @return {GPUTexture} The GPU texture. + */ _getDefaultCubeTextureGPU( format ) { let defaultCubeTexture = this.defaultTexture[ format ]; @@ -486,6 +624,12 @@ class WebGPUTextureUtils { } + /** + * Returns the default video frame used as default data in context of video textures. + * + * @private + * @return {VideoFrame} The video frame. + */ _getDefaultVideoFrame() { let defaultVideoFrame = this.defaultVideoFrame; @@ -507,6 +651,15 @@ class WebGPUTextureUtils { } + /** + * Uploads cube texture image data to the GPU memory. + * + * @private + * @param {Array} images - The cube image data. + * @param {GPUTexture} textureGPU - The GPU texture. + * @param {Object} textureDescriptorGPU - The GPU texture descriptor. + * @param {Boolean} flipY - Whether to flip texture data along their vertical axis or not. + */ _copyCubeMapToTexture( images, textureGPU, textureDescriptorGPU, flipY ) { for ( let i = 0; i < 6; i ++ ) { @@ -529,13 +682,24 @@ class WebGPUTextureUtils { } + /** + * Uploads texture image data to the GPU memory. + * + * @private + * @param {HTMLImageElement|ImageBitmap|HTMLCanvasElement} image - The image data. + * @param {GPUTexture} textureGPU - The GPU texture. + * @param {Object} textureDescriptorGPU - The GPU texture descriptor. + * @param {Number} originDepth - The origin depth. + * @param {Boolean} flipY - Whether to flip texture data along their vertical axis or not. + */ _copyImageToTexture( image, textureGPU, textureDescriptorGPU, originDepth, flipY ) { const device = this.backend.device; device.queue.copyExternalImageToTexture( { - source: image + source: image, + flipY: flipY }, { texture: textureGPU, mipLevel: 0, @@ -547,14 +711,14 @@ class WebGPUTextureUtils { } ); - if ( flipY === true ) { - - this._flipY( textureGPU, textureDescriptorGPU, originDepth ); - - } - } + /** + * Returns the pass utils singleton. + * + * @private + * @return {WebGPUTexturePassUtils} The utils instance. + */ _getPassUtils() { let passUtils = this._passUtils; @@ -569,18 +733,45 @@ class WebGPUTextureUtils { } + /** + * Generates mipmaps for the given GPU texture. + * + * @private + * @param {GPUTexture} textureGPU - The GPU texture object. + * @param {Object} textureDescriptorGPU - The texture descriptor. + * @param {Number} [baseArrayLayer=0] - The index of the first array layer accessible to the texture view. + */ _generateMipmaps( textureGPU, textureDescriptorGPU, baseArrayLayer = 0 ) { this._getPassUtils().generateMipmaps( textureGPU, textureDescriptorGPU, baseArrayLayer ); } + /** + * Flip the contents of the given GPU texture along its vertical axis. + * + * @private + * @param {GPUTexture} textureGPU - The GPU texture object. + * @param {Object} textureDescriptorGPU - The texture descriptor. + * @param {Number} [originDepth=0] - The origin depth. + */ _flipY( textureGPU, textureDescriptorGPU, originDepth = 0 ) { this._getPassUtils().flipY( textureGPU, textureDescriptorGPU, originDepth ); } + /** + * Uploads texture buffer data to the GPU memory. + * + * @private + * @param {Object} image - An object defining the image buffer data. + * @param {GPUTexture} textureGPU - The GPU texture. + * @param {Object} textureDescriptorGPU - The GPU texture descriptor. + * @param {Number} originDepth - The origin depth. + * @param {Boolean} flipY - Whether to flip texture data along their vertical axis or not. + * @param {Number} [depth=0] - TODO. + */ _copyBufferToTexture( image, textureGPU, textureDescriptorGPU, originDepth, flipY, depth = 0 ) { // @TODO: Consider to use GPUCommandEncoder.copyBufferToTexture() @@ -618,6 +809,14 @@ class WebGPUTextureUtils { } + /** + * Uploads compressed texture data to the GPU memory. + * + * @private + * @param {Array} mipmaps - An array with mipmap data. + * @param {GPUTexture} textureGPU - The GPU texture. + * @param {Object} textureDescriptorGPU - The GPU texture descriptor. + */ _copyCompressedBufferToTexture( mipmaps, textureGPU, textureDescriptorGPU ) { // @TODO: Consider to use GPUCommandEncoder.copyBufferToTexture() @@ -665,10 +864,16 @@ class WebGPUTextureUtils { } + /** + * This method is only relevant for compressed texture formats. It returns a block + * data descriptor for the given GPU compressed texture format. + * + * @private + * @param {String} format - The GPU compressed texture format. + * @return {Object} The block data descriptor. + */ _getBlockData( format ) { - // this method is only relevant for compressed texture formats - if ( format === GPUTextureFormat.BC1RGBAUnorm || format === GPUTextureFormat.BC1RGBAUnormSRGB ) return { byteLength: 8, width: 4, height: 4 }; // DXT1 if ( format === GPUTextureFormat.BC2RGBAUnorm || format === GPUTextureFormat.BC2RGBAUnormSRGB ) return { byteLength: 16, width: 4, height: 4 }; // DXT3 if ( format === GPUTextureFormat.BC3RGBAUnorm || format === GPUTextureFormat.BC3RGBAUnormSRGB ) return { byteLength: 16, width: 4, height: 4 }; // DXT5 @@ -702,6 +907,13 @@ class WebGPUTextureUtils { } + /** + * Converts the three.js uv wrapping constants to GPU address mode constants. + * + * @private + * @param {Number} value - The three.js constant defining a uv wrapping mode. + * @return {String} The GPU address mode. + */ _convertAddressMode( value ) { let addressMode = GPUAddressMode.ClampToEdge; @@ -720,6 +932,13 @@ class WebGPUTextureUtils { } + /** + * Converts the three.js filter constants to GPU filter constants. + * + * @private + * @param {Number} value - The three.js constant defining a filter mode. + * @return {String} The GPU filter mode. + */ _convertFilterMode( value ) { let filterMode = GPUFilterMode.Linear; @@ -734,6 +953,13 @@ class WebGPUTextureUtils { } + /** + * Returns the bytes-per-texel value for the given GPU texture format. + * + * @private + * @param {String} format - The GPU texture format. + * @return {Number} The bytes-per-texel. + */ _getBytesPerTexel( format ) { // 8-bit formats @@ -790,6 +1016,13 @@ class WebGPUTextureUtils { } + /** + * Returns the corresponding typed array type for the given GPU texture format. + * + * @private + * @param {String} format - The GPU texture format. + * @return {TypedArray.constructor} The typed array type. + */ _getTypedArrayType( format ) { if ( format === GPUTextureFormat.R8Uint ) return Uint8Array; @@ -840,6 +1073,13 @@ class WebGPUTextureUtils { } + /** + * Returns the GPU dimensions for the given texture. + * + * @private + * @param {Texture} texture - The texture. + * @return {String} The GPU dimension. + */ _getDimension( texture ) { let dimension; @@ -860,6 +1100,14 @@ class WebGPUTextureUtils { } +/** + * Returns the GPU format for the given texture. + * + * @param {Texture} texture - The texture. + * @param {GPUDevice?} [device=null] - The GPU device which is used for feature detection. + * It is not necessary to apply the device for most formats. + * @return {String} The GPU format. + */ export function getFormat( texture, device = null ) { const format = texture.format; diff --git a/src/renderers/webgpu/utils/WebGPUUtils.js b/src/renderers/webgpu/utils/WebGPUUtils.js index a055059c6e15fc..8904ea29892793 100644 --- a/src/renderers/webgpu/utils/WebGPUUtils.js +++ b/src/renderers/webgpu/utils/WebGPUUtils.js @@ -1,13 +1,34 @@ import { GPUPrimitiveTopology, GPUTextureFormat } from './WebGPUConstants.js'; +/** + * A WebGPU backend utility module with common helpers. + * + * @private + */ class WebGPUUtils { + /** + * Constructs a new utility object. + * + * @param {WebGPUBackend} backend - The WebGPU backend. + */ constructor( backend ) { + /** + * A reference to the WebGPU backend. + * + * @type {WebGPUBackend} + */ this.backend = backend; } + /** + * Returns the depth/stencil GPU format for the given render context. + * + * @param {RenderContext} renderContext - The render context. + * @return {String} The depth/stencil GPU texture format. + */ getCurrentDepthStencilFormat( renderContext ) { let format; @@ -30,12 +51,24 @@ class WebGPUUtils { } + /** + * Returns the GPU format for the given texture. + * + * @param {Texture} texture - The texture. + * @return {String} The GPU texture format. + */ getTextureFormatGPU( texture ) { return this.backend.get( texture ).format; } + /** + * Returns an object that defines the multi-sampling state of the given texture. + * + * @param {Texture} texture - The texture. + * @return {Object} The multi-sampling state. + */ getTextureSampleData( texture ) { let samples; @@ -66,6 +99,12 @@ class WebGPUUtils { } + /** + * Returns the default color attachment's GPU format of the current render context. + * + * @param {RenderContext} renderContext - The render context. + * @return {String} The GPU texture format of the default color attachment. + */ getCurrentColorFormat( renderContext ) { let format; @@ -84,6 +123,12 @@ class WebGPUUtils { } + /** + * Returns the output color space of the current render context. + * + * @param {RenderContext} renderContext - The render context. + * @return {String} The output color space. + */ getCurrentColorSpace( renderContext ) { if ( renderContext.textures !== null ) { @@ -96,6 +141,13 @@ class WebGPUUtils { } + /** + * Returns GPU primitive topology for the given object and material. + * + * @param {Object3D} object - The 3D object. + * @param {Material} material - The material. + * @return {String} The GPU primitive topology. + */ getPrimitiveTopology( object, material ) { if ( object.isPoints ) return GPUPrimitiveTopology.PointList; @@ -105,6 +157,14 @@ class WebGPUUtils { } + /** + * Returns a modified sample count from the given sample count value. + * + * That is required since WebGPU does not support arbitrary sample counts. + * + * @param {Number} sampleCount - The input sample count. + * @return {Number} The (potentially updated) output sample count. + */ getSampleCount( sampleCount ) { let count = 1; @@ -126,6 +186,12 @@ class WebGPUUtils { } + /** + * Returns the sample count of the given render context. + * + * @param {RenderContext} renderContext - The render context. + * @return {Number} The sample count. + */ getSampleCountRenderContext( renderContext ) { if ( renderContext.textures !== null ) { @@ -138,6 +204,14 @@ class WebGPUUtils { } + /** + * Returns the preferred canvas format. + * + * There is a separate method for this so it's possible to + * honor edge cases for specific devices. + * + * @return {String} The GPU texture format of the canvas. + */ getPreferredCanvasFormat() { // TODO: Remove this check when Quest 34.5 is out diff --git a/src/renderers/webxr/WebXRManager.js b/src/renderers/webxr/WebXRManager.js index 529c7154474784..509b663f637949 100644 --- a/src/renderers/webxr/WebXRManager.js +++ b/src/renderers/webxr/WebXRManager.js @@ -784,8 +784,11 @@ class WebXRManager extends EventDispatcher { // const enabledFeatures = session.enabledFeatures; + const gpuDepthSensingEnabled = enabledFeatures && + enabledFeatures.includes( 'depth-sensing' ) && + session.depthUsage == 'gpu-optimized'; - if ( enabledFeatures && enabledFeatures.includes( 'depth-sensing' ) ) { + if ( gpuDepthSensingEnabled && glBinding ) { const depthData = glBinding.getDepthInformation( views[ 0 ] ); diff --git a/src/textures/Data3DTexture.js b/src/textures/Data3DTexture.js index 36348cc1f04a12..e6e99a4f08948a 100644 --- a/src/textures/Data3DTexture.js +++ b/src/textures/Data3DTexture.js @@ -6,9 +6,9 @@ class Data3DTexture extends Texture { constructor( data = null, width = 1, height = 1, depth = 1 ) { // We're going to add .setXXX() methods for setting properties later. - // Users can still set in DataTexture3D directly. + // Users can still set in Data3DTexture directly. // - // const texture = new THREE.DataTexture3D( data, width, height, depth ); + // const texture = new THREE.Data3DTexture( data, width, height, depth ); // texture.anisotropy = 16; // // See #14839 diff --git a/src/textures/VideoFrameTexture.js b/src/textures/VideoFrameTexture.js new file mode 100644 index 00000000000000..b58cf6e96069ce --- /dev/null +++ b/src/textures/VideoFrameTexture.js @@ -0,0 +1,33 @@ +import { VideoTexture } from './VideoTexture.js'; + +class VideoFrameTexture extends VideoTexture { + + constructor( mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { + + super( {}, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); + + } + + update() { + + // overwrites `VideoTexture.update()` with an empty method since + // this type of texture is updated via `setFrame()`. + + } + + clone() { + + return new this.constructor().copy( this ); // restoring Texture.clone() + + } + + setFrame( frame ) { + + this.image = frame; + this.needsUpdate = true; + + } + +} + +export { VideoFrameTexture }; diff --git a/test/e2e/puppeteer.js b/test/e2e/puppeteer.js index 9927554dceb5b7..ea122bf0b175f6 100644 --- a/test/e2e/puppeteer.js +++ b/test/e2e/puppeteer.js @@ -47,6 +47,7 @@ const exceptionList = [ 'webgl_materials_video', 'webgl_video_kinect', 'webgl_video_panorama_equirectangular', + 'webgpu_video_frame', 'webaudio_visualizer', // audio can't be analyzed without proper audio hook @@ -156,6 +157,8 @@ const exceptionList = [ 'webgpu_tsl_vfx_linkedparticles', 'webgpu_tsl_vfx_tornado', 'webgpu_textures_anisotropy', + 'webgpu_textures_2d-array_compressed', + 'webgpu_rendertarget_2d-array_3d', 'webgpu_materials_envmaps_bpcem', 'webgpu_postprocessing_ssr', 'webgpu_postprocessing_sobel', diff --git a/utils/build/rollup.config.js b/utils/build/rollup.config.js index 0d74075e53854d..2385b25c560cc8 100644 --- a/utils/build/rollup.config.js +++ b/utils/build/rollup.config.js @@ -45,7 +45,7 @@ function header() { code.prepend( `/** * @license - * Copyright 2010-2024 Three.js Authors + * Copyright 2010-2025 Three.js Authors * SPDX-License-Identifier: MIT */\n` ); diff --git a/utils/docs/jsdoc.config.json b/utils/docs/jsdoc.config.json index 233b21e6082545..040ce014759bd4 100644 --- a/utils/docs/jsdoc.config.json +++ b/utils/docs/jsdoc.config.json @@ -4,10 +4,24 @@ "encoding": "utf8", "package": "package.json", "recurse": true, - "template": "node_modules/clean-jsdoc-theme" + "template": "node_modules/clean-jsdoc-theme", + "theme_opts": { + "homepageTitle": "three.js docs" + } }, "plugins": [ "plugins/markdown" ], "source": { - "include": [ "src/nodes", "src/loaders/nodes", "src/materials/nodes", "examples/jsm/tsl" ] + "include": [ + "examples/jsm/tsl", + "src/loaders/nodes", + "src/materials/nodes", + "src/nodes", + "src/renderers/common", + "src/renderers/webgpu" + ] + }, + "markdown": { + "hardwrap": false, + "idInHeadings": true } }