You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

three

Package Overview
Dependencies
Maintainers
2
Versions
299
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

three - npm Package Compare versions

Comparing version

to
0.175.0

examples/jsm/geometries/ParametricFunctions.js

6

build/three.tsl.js

@@ -124,2 +124,3 @@ /**

const compute = TSL.compute;
const computeSkinning = TSL.computeSkinning;
const cond = TSL.cond;

@@ -137,2 +138,3 @@ const Const = TSL.Const;

const dashSize = TSL.dashSize;
const debug = TSL.debug;
const defaultBuildStages = TSL.defaultBuildStages;

@@ -417,2 +419,3 @@ const defaultShaderStages = TSL.defaultShaderStages;

const sampler = TSL.sampler;
const samplerComparison = TSL.samplerComparison;
const saturate = TSL.saturate;

@@ -443,3 +446,2 @@ const saturation = TSL.saturation;

const skinning = TSL.skinning;
const skinningReference = TSL.skinningReference;
const smoothstep = TSL.smoothstep;

@@ -554,2 +556,2 @@ const smoothstepElement = TSL.smoothstepElement;

export { BRDF_GGX, BRDF_Lambert, BasicShadowFilter, Break, Const, Continue, DFGApprox, D_GGX, Discard, EPSILON, F_Schlick, Fn, INFINITY, If, Loop, NodeAccess, NodeShaderStage, NodeType, NodeUpdateType, PCFShadowFilter, PCFSoftShadowFilter, PI, PI2, Return, Schlick_to_F0, ScriptableNodeResources, ShaderNode, TBNViewMatrix, VSMShadowFilter, V_GGX_SmithCorrelated, Var, abs, acesFilmicToneMapping, acos, add, addNodeElement, agxToneMapping, all, alphaT, and, anisotropy, anisotropyB, anisotropyT, any, append, array, arrayBuffer, asin, assign, atan, atan2, atomicAdd, atomicAnd, atomicFunc, atomicLoad, atomicMax, atomicMin, atomicOr, atomicStore, atomicSub, atomicXor, attenuationColor, attenuationDistance, attribute, attributeArray, backgroundBlurriness, backgroundIntensity, backgroundRotation, batch, billboarding, bitAnd, bitNot, bitOr, bitXor, bitangentGeometry, bitangentLocal, bitangentView, bitangentWorld, bitcast, blendBurn, blendColor, blendDodge, blendOverlay, blendScreen, blur, bool, buffer, bufferAttribute, bumpMap, burn, bvec2, bvec3, bvec4, bypass, cache, call, cameraFar, cameraIndex, cameraNear, cameraNormalMatrix, cameraPosition, cameraProjectionMatrix, cameraProjectionMatrixInverse, cameraViewMatrix, cameraWorldMatrix, cbrt, cdl, ceil, checker, cineonToneMapping, clamp, clearcoat, clearcoatRoughness, code, color, colorSpaceToWorking, colorToDirection, compute, cond, context, convert, convertColorSpace, convertToTexture, cos, cross, cubeTexture, dFdx, dFdy, dashSize, defaultBuildStages, defaultShaderStages, defined, degrees, deltaTime, densityFog, densityFogFactor, depth, depthPass, difference, diffuseColor, directPointLight, directionToColor, dispersion, distance, div, dodge, dot, drawIndex, dynamicBufferAttribute, element, emissive, equal, equals, equirectUV, exp, exp2, expression, faceDirection, faceForward, faceforward, float, floor, fog, fract, frameGroup, frameId, frontFacing, fwidth, gain, gapSize, getConstNodeType, getCurrentStack, getDirection, getDistanceAttenuation, getGeometryRoughness, getNormalFromDepth, getParallaxCorrectNormal, getRoughness, getScreenPosition, getShIrradianceAt, getTextureIndex, getViewPosition, globalId, glsl, glslFn, grayscale, greaterThan, greaterThanEqual, hash, highpModelNormalViewMatrix, highpModelViewMatrix, hue, instance, instanceIndex, instancedArray, instancedBufferAttribute, instancedDynamicBufferAttribute, instancedMesh, int, inverseSqrt, inversesqrt, invocationLocalIndex, invocationSubgroupIndex, ior, iridescence, iridescenceIOR, iridescenceThickness, ivec2, ivec3, ivec4, js, label, length, lengthSq, lessThan, lessThanEqual, lightPosition, lightProjectionUV, lightTargetDirection, lightTargetPosition, lightViewPosition, lightingContext, lights, linearDepth, linearToneMapping, localId, log, log2, logarithmicDepthToViewZ, loop, luminance, mat2, mat3, mat4, matcapUV, materialAO, materialAlphaTest, materialAnisotropy, materialAnisotropyVector, materialAttenuationColor, materialAttenuationDistance, materialClearcoat, materialClearcoatNormal, materialClearcoatRoughness, materialColor, materialDispersion, materialEmissive, materialIOR, materialIridescence, materialIridescenceIOR, materialIridescenceThickness, materialLightMap, materialLineDashOffset, materialLineDashSize, materialLineGapSize, materialLineScale, materialLineWidth, materialMetalness, materialNormal, materialOpacity, materialPointSize, materialReference, materialReflectivity, materialRefractionRatio, materialRotation, materialRoughness, materialSheen, materialSheenRoughness, materialShininess, materialSpecular, materialSpecularColor, materialSpecularIntensity, materialSpecularStrength, materialThickness, materialTransmission, max, maxMipLevel, mediumpModelViewMatrix, metalness, min, mix, mixElement, mod, modInt, modelDirection, modelNormalMatrix, modelPosition, modelRadius, modelScale, modelViewMatrix, modelViewPosition, modelViewProjection, modelWorldMatrix, modelWorldMatrixInverse, morphReference, mrt, mul, mx_aastep, mx_cell_noise_float, mx_contrast, mx_fractal_noise_float, mx_fractal_noise_vec2, mx_fractal_noise_vec3, mx_fractal_noise_vec4, mx_hsvtorgb, mx_noise_float, mx_noise_vec3, mx_noise_vec4, mx_ramplr, mx_ramptb, mx_rgbtohsv, mx_safepower, mx_splitlr, mx_splittb, mx_srgb_texture_to_lin_rec709, mx_transform_uv, mx_worley_noise_float, mx_worley_noise_vec2, mx_worley_noise_vec3, negate, neutralToneMapping, nodeArray, nodeImmutable, nodeObject, nodeObjects, nodeProxy, normalFlat, normalGeometry, normalLocal, normalMap, normalView, normalWorld, normalize, not, notEqual, numWorkgroups, objectDirection, objectGroup, objectPosition, objectRadius, objectScale, objectViewPosition, objectWorldMatrix, oneMinus, or, orthographicDepthToViewZ, oscSawtooth, oscSine, oscSquare, oscTriangle, output, outputStruct, overlay, overloadingFn, parabola, parallaxDirection, parallaxUV, parameter, pass, passTexture, pcurve, perspectiveDepthToViewZ, pmremTexture, pointShadow, pointUV, pointWidth, positionGeometry, positionLocal, positionPrevious, positionView, positionViewDirection, positionWorld, positionWorldDirection, posterize, pow, pow2, pow3, pow4, property, radians, rand, range, rangeFog, rangeFogFactor, reciprocal, reference, referenceBuffer, reflect, reflectVector, reflectView, reflector, refract, refractVector, refractView, reinhardToneMapping, remainder, remap, remapClamp, renderGroup, renderOutput, rendererReference, rotate, rotateUV, roughness, round, rtt, sRGBTransferEOTF, sRGBTransferOETF, sampler, saturate, saturation, screen, screenCoordinate, screenSize, screenUV, scriptable, scriptableValue, select, setCurrentStack, shaderStages, shadow, shadowPositionWorld, shapeCircle, sharedUniformGroup, sheen, sheenRoughness, shiftLeft, shiftRight, shininess, sign, sin, sinc, skinning, skinningReference, smoothstep, smoothstepElement, specularColor, specularF90, spherizeUV, split, spritesheetUV, sqrt, stack, step, storage, storageBarrier, storageObject, storageTexture, string, struct, sub, subgroupIndex, subgroupSize, tan, tangentGeometry, tangentLocal, tangentView, tangentWorld, temp, texture, texture3D, textureBarrier, textureBicubic, textureCubeUV, textureLoad, textureSize, textureStore, thickness, threshold, time, timerDelta, timerGlobal, timerLocal, toOutputColorSpace, toWorkingColorSpace, toneMapping, toneMappingExposure, toonOutlinePass, transformDirection, transformNormal, transformNormalToView, transformedBentNormalView, transformedBitangentView, transformedBitangentWorld, transformedClearcoatNormalView, transformedNormalView, transformedNormalWorld, transformedTangentView, transformedTangentWorld, transmission, transpose, tri, tri3, triNoise3D, triplanarTexture, triplanarTextures, trunc, tslFn, uint, uniform, uniformArray, uniformGroup, uniforms, userData, uv, uvec2, uvec3, uvec4, varying, varyingProperty, vec2, vec3, vec4, vectorComponents, velocity, vertexColor, vertexIndex, vibrance, viewZToLogarithmicDepth, viewZToOrthographicDepth, viewZToPerspectiveDepth, viewport, viewportBottomLeft, viewportCoordinate, viewportDepthTexture, viewportLinearDepth, viewportMipTexture, viewportResolution, viewportSafeUV, viewportSharedTexture, viewportSize, viewportTexture, viewportTopLeft, viewportUV, wgsl, wgslFn, workgroupArray, workgroupBarrier, workgroupId, workingToColorSpace, xor };
export { BRDF_GGX, BRDF_Lambert, BasicShadowFilter, Break, Const, Continue, DFGApprox, D_GGX, Discard, EPSILON, F_Schlick, Fn, INFINITY, If, Loop, NodeAccess, NodeShaderStage, NodeType, NodeUpdateType, PCFShadowFilter, PCFSoftShadowFilter, PI, PI2, Return, Schlick_to_F0, ScriptableNodeResources, ShaderNode, TBNViewMatrix, VSMShadowFilter, V_GGX_SmithCorrelated, Var, abs, acesFilmicToneMapping, acos, add, addNodeElement, agxToneMapping, all, alphaT, and, anisotropy, anisotropyB, anisotropyT, any, append, array, arrayBuffer, asin, assign, atan, atan2, atomicAdd, atomicAnd, atomicFunc, atomicLoad, atomicMax, atomicMin, atomicOr, atomicStore, atomicSub, atomicXor, attenuationColor, attenuationDistance, attribute, attributeArray, backgroundBlurriness, backgroundIntensity, backgroundRotation, batch, billboarding, bitAnd, bitNot, bitOr, bitXor, bitangentGeometry, bitangentLocal, bitangentView, bitangentWorld, bitcast, blendBurn, blendColor, blendDodge, blendOverlay, blendScreen, blur, bool, buffer, bufferAttribute, bumpMap, burn, bvec2, bvec3, bvec4, bypass, cache, call, cameraFar, cameraIndex, cameraNear, cameraNormalMatrix, cameraPosition, cameraProjectionMatrix, cameraProjectionMatrixInverse, cameraViewMatrix, cameraWorldMatrix, cbrt, cdl, ceil, checker, cineonToneMapping, clamp, clearcoat, clearcoatRoughness, code, color, colorSpaceToWorking, colorToDirection, compute, computeSkinning, cond, context, convert, convertColorSpace, convertToTexture, cos, cross, cubeTexture, dFdx, dFdy, dashSize, debug, defaultBuildStages, defaultShaderStages, defined, degrees, deltaTime, densityFog, densityFogFactor, depth, depthPass, difference, diffuseColor, directPointLight, directionToColor, dispersion, distance, div, dodge, dot, drawIndex, dynamicBufferAttribute, element, emissive, equal, equals, equirectUV, exp, exp2, expression, faceDirection, faceForward, faceforward, float, floor, fog, fract, frameGroup, frameId, frontFacing, fwidth, gain, gapSize, getConstNodeType, getCurrentStack, getDirection, getDistanceAttenuation, getGeometryRoughness, getNormalFromDepth, getParallaxCorrectNormal, getRoughness, getScreenPosition, getShIrradianceAt, getTextureIndex, getViewPosition, globalId, glsl, glslFn, grayscale, greaterThan, greaterThanEqual, hash, highpModelNormalViewMatrix, highpModelViewMatrix, hue, instance, instanceIndex, instancedArray, instancedBufferAttribute, instancedDynamicBufferAttribute, instancedMesh, int, inverseSqrt, inversesqrt, invocationLocalIndex, invocationSubgroupIndex, ior, iridescence, iridescenceIOR, iridescenceThickness, ivec2, ivec3, ivec4, js, label, length, lengthSq, lessThan, lessThanEqual, lightPosition, lightProjectionUV, lightTargetDirection, lightTargetPosition, lightViewPosition, lightingContext, lights, linearDepth, linearToneMapping, localId, log, log2, logarithmicDepthToViewZ, loop, luminance, mat2, mat3, mat4, matcapUV, materialAO, materialAlphaTest, materialAnisotropy, materialAnisotropyVector, materialAttenuationColor, materialAttenuationDistance, materialClearcoat, materialClearcoatNormal, materialClearcoatRoughness, materialColor, materialDispersion, materialEmissive, materialIOR, materialIridescence, materialIridescenceIOR, materialIridescenceThickness, materialLightMap, materialLineDashOffset, materialLineDashSize, materialLineGapSize, materialLineScale, materialLineWidth, materialMetalness, materialNormal, materialOpacity, materialPointSize, materialReference, materialReflectivity, materialRefractionRatio, materialRotation, materialRoughness, materialSheen, materialSheenRoughness, materialShininess, materialSpecular, materialSpecularColor, materialSpecularIntensity, materialSpecularStrength, materialThickness, materialTransmission, max, maxMipLevel, mediumpModelViewMatrix, metalness, min, mix, mixElement, mod, modInt, modelDirection, modelNormalMatrix, modelPosition, modelRadius, modelScale, modelViewMatrix, modelViewPosition, modelViewProjection, modelWorldMatrix, modelWorldMatrixInverse, morphReference, mrt, mul, mx_aastep, mx_cell_noise_float, mx_contrast, mx_fractal_noise_float, mx_fractal_noise_vec2, mx_fractal_noise_vec3, mx_fractal_noise_vec4, mx_hsvtorgb, mx_noise_float, mx_noise_vec3, mx_noise_vec4, mx_ramplr, mx_ramptb, mx_rgbtohsv, mx_safepower, mx_splitlr, mx_splittb, mx_srgb_texture_to_lin_rec709, mx_transform_uv, mx_worley_noise_float, mx_worley_noise_vec2, mx_worley_noise_vec3, negate, neutralToneMapping, nodeArray, nodeImmutable, nodeObject, nodeObjects, nodeProxy, normalFlat, normalGeometry, normalLocal, normalMap, normalView, normalWorld, normalize, not, notEqual, numWorkgroups, objectDirection, objectGroup, objectPosition, objectRadius, objectScale, objectViewPosition, objectWorldMatrix, oneMinus, or, orthographicDepthToViewZ, oscSawtooth, oscSine, oscSquare, oscTriangle, output, outputStruct, overlay, overloadingFn, parabola, parallaxDirection, parallaxUV, parameter, pass, passTexture, pcurve, perspectiveDepthToViewZ, pmremTexture, pointShadow, pointUV, pointWidth, positionGeometry, positionLocal, positionPrevious, positionView, positionViewDirection, positionWorld, positionWorldDirection, posterize, pow, pow2, pow3, pow4, property, radians, rand, range, rangeFog, rangeFogFactor, reciprocal, reference, referenceBuffer, reflect, reflectVector, reflectView, reflector, refract, refractVector, refractView, reinhardToneMapping, remainder, remap, remapClamp, renderGroup, renderOutput, rendererReference, rotate, rotateUV, roughness, round, rtt, sRGBTransferEOTF, sRGBTransferOETF, sampler, samplerComparison, saturate, saturation, screen, screenCoordinate, screenSize, screenUV, scriptable, scriptableValue, select, setCurrentStack, shaderStages, shadow, shadowPositionWorld, shapeCircle, sharedUniformGroup, sheen, sheenRoughness, shiftLeft, shiftRight, shininess, sign, sin, sinc, skinning, smoothstep, smoothstepElement, specularColor, specularF90, spherizeUV, split, spritesheetUV, sqrt, stack, step, storage, storageBarrier, storageObject, storageTexture, string, struct, sub, subgroupIndex, subgroupSize, tan, tangentGeometry, tangentLocal, tangentView, tangentWorld, temp, texture, texture3D, textureBarrier, textureBicubic, textureCubeUV, textureLoad, textureSize, textureStore, thickness, threshold, time, timerDelta, timerGlobal, timerLocal, toOutputColorSpace, toWorkingColorSpace, toneMapping, toneMappingExposure, toonOutlinePass, transformDirection, transformNormal, transformNormalToView, transformedBentNormalView, transformedBitangentView, transformedBitangentWorld, transformedClearcoatNormalView, transformedNormalView, transformedNormalWorld, transformedTangentView, transformedTangentWorld, transmission, transpose, tri, tri3, triNoise3D, triplanarTexture, triplanarTextures, trunc, tslFn, uint, uniform, uniformArray, uniformGroup, uniforms, userData, uv, uvec2, uvec3, uvec4, varying, varyingProperty, vec2, vec3, vec4, vectorComponents, velocity, vertexColor, vertexIndex, vibrance, viewZToLogarithmicDepth, viewZToOrthographicDepth, viewZToPerspectiveDepth, viewport, viewportBottomLeft, viewportCoordinate, viewportDepthTexture, viewportLinearDepth, viewportMipTexture, viewportResolution, viewportSafeUV, viewportSharedTexture, viewportSize, viewportTexture, viewportTopLeft, viewportUV, wgsl, wgslFn, workgroupArray, workgroupBarrier, workgroupId, workingToColorSpace, xor };

@@ -6,2 +6,2 @@ /**

*/
import{TSL as e}from"three/webgpu";const t=e.BRDF_GGX,r=e.BRDF_Lambert,a=e.BasicShadowFilter,o=e.Break,i=e.Continue,n=e.DFGApprox,s=e.D_GGX,l=e.Discard,c=e.EPSILON,m=e.F_Schlick,p=e.Fn,d=e.INFINITY,u=e.If,g=e.Loop,h=e.NodeShaderStage,f=e.NodeType,x=e.NodeUpdateType,b=e.NodeAccess,w=e.PCFShadowFilter,v=e.PCFSoftShadowFilter,S=e.PI,T=e.PI2,_=e.Return,V=e.Schlick_to_F0,y=e.ScriptableNodeResources,D=e.ShaderNode,M=e.TBNViewMatrix,F=e.VSMShadowFilter,C=e.V_GGX_SmithCorrelated,I=e.abs,P=e.acesFilmicToneMapping,R=e.acos,N=e.add,B=e.addNodeElement,L=e.agxToneMapping,k=e.all,A=e.alphaT,G=e.and,O=e.anisotropy,W=e.anisotropyB,j=e.anisotropyT,U=e.any,z=e.append,q=e.array,E=e.arrayBuffer,Z=e.asin,X=e.assign,Y=e.atan,H=e.atan2,J=e.atomicAdd,K=e.atomicAnd,Q=e.atomicFunc,$=e.atomicMax,ee=e.atomicMin,te=e.atomicOr,re=e.atomicStore,ae=e.atomicSub,oe=e.atomicXor,ie=e.atomicLoad,ne=e.attenuationColor,se=e.attenuationDistance,le=e.attribute,ce=e.attributeArray,me=e.backgroundBlurriness,pe=e.backgroundIntensity,de=e.backgroundRotation,ue=e.batch,ge=e.billboarding,he=e.bitAnd,fe=e.bitNot,xe=e.bitOr,be=e.bitXor,we=e.bitangentGeometry,ve=e.bitangentLocal,Se=e.bitangentView,Te=e.bitangentWorld,_e=e.bitcast,Ve=e.blendBurn,ye=e.blendColor,De=e.blendDodge,Me=e.blendOverlay,Fe=e.blendScreen,Ce=e.blur,Ie=e.bool,Pe=e.buffer,Re=e.bufferAttribute,Ne=e.bumpMap,Be=e.burn,Le=e.bvec2,ke=e.bvec3,Ae=e.bvec4,Ge=e.bypass,Oe=e.cache,We=e.call,je=e.cameraFar,Ue=e.cameraIndex,ze=e.cameraNear,qe=e.cameraNormalMatrix,Ee=e.cameraPosition,Ze=e.cameraProjectionMatrix,Xe=e.cameraProjectionMatrixInverse,Ye=e.cameraViewMatrix,He=e.cameraWorldMatrix,Je=e.cbrt,Ke=e.cdl,Qe=e.ceil,$e=e.checker,et=e.cineonToneMapping,tt=e.clamp,rt=e.clearcoat,at=e.clearcoatRoughness,ot=e.code,it=e.color,nt=e.colorSpaceToWorking,st=e.colorToDirection,lt=e.compute,ct=e.cond,mt=e.Const,pt=e.context,dt=e.convert,ut=e.convertColorSpace,gt=e.convertToTexture,ht=e.cos,ft=e.cross,xt=e.cubeTexture,bt=e.dFdx,wt=e.dFdy,vt=e.dashSize,St=e.defaultBuildStages,Tt=e.defaultShaderStages,_t=e.defined,Vt=e.degrees,yt=e.deltaTime,Dt=e.densityFog,Mt=e.densityFogFactor,Ft=e.depth,Ct=e.depthPass,It=e.difference,Pt=e.diffuseColor,Rt=e.directPointLight,Nt=e.directionToColor,Bt=e.dispersion,Lt=e.distance,kt=e.div,At=e.dodge,Gt=e.dot,Ot=e.drawIndex,Wt=e.dynamicBufferAttribute,jt=e.element,Ut=e.emissive,zt=e.equal,qt=e.equals,Et=e.equirectUV,Zt=e.exp,Xt=e.exp2,Yt=e.expression,Ht=e.faceDirection,Jt=e.faceForward,Kt=e.faceforward,Qt=e.float,$t=e.floor,er=e.fog,tr=e.fract,rr=e.frameGroup,ar=e.frameId,or=e.frontFacing,ir=e.fwidth,nr=e.gain,sr=e.gapSize,lr=e.getConstNodeType,cr=e.getCurrentStack,mr=e.getDirection,pr=e.getDistanceAttenuation,dr=e.getGeometryRoughness,ur=e.getNormalFromDepth,gr=e.getParallaxCorrectNormal,hr=e.getRoughness,fr=e.getScreenPosition,xr=e.getShIrradianceAt,br=e.getTextureIndex,wr=e.getViewPosition,vr=e.glsl,Sr=e.glslFn,Tr=e.grayscale,_r=e.greaterThan,Vr=e.greaterThanEqual,yr=e.hash,Dr=e.highpModelNormalViewMatrix,Mr=e.highpModelViewMatrix,Fr=e.hue,Cr=e.instance,Ir=e.instanceIndex,Pr=e.instancedArray,Rr=e.instancedBufferAttribute,Nr=e.instancedDynamicBufferAttribute,Br=e.instancedMesh,Lr=e.int,kr=e.inverseSqrt,Ar=e.inversesqrt,Gr=e.invocationLocalIndex,Or=e.invocationSubgroupIndex,Wr=e.ior,jr=e.iridescence,Ur=e.iridescenceIOR,zr=e.iridescenceThickness,qr=e.ivec2,Er=e.ivec3,Zr=e.ivec4,Xr=e.js,Yr=e.label,Hr=e.length,Jr=e.lengthSq,Kr=e.lessThan,Qr=e.lessThanEqual,$r=e.lightPosition,ea=e.lightTargetDirection,ta=e.lightTargetPosition,ra=e.lightViewPosition,aa=e.lightingContext,oa=e.lights,ia=e.linearDepth,na=e.linearToneMapping,sa=e.localId,la=e.globalId,ca=e.log,ma=e.log2,pa=e.logarithmicDepthToViewZ,da=e.loop,ua=e.luminance,ga=e.mediumpModelViewMatrix,ha=e.mat2,fa=e.mat3,xa=e.mat4,ba=e.matcapUV,wa=e.materialAO,va=e.materialAlphaTest,Sa=e.materialAnisotropy,Ta=e.materialAnisotropyVector,_a=e.materialAttenuationColor,Va=e.materialAttenuationDistance,ya=e.materialClearcoat,Da=e.materialClearcoatNormal,Ma=e.materialClearcoatRoughness,Fa=e.materialColor,Ca=e.materialDispersion,Ia=e.materialEmissive,Pa=e.materialIOR,Ra=e.materialIridescence,Na=e.materialIridescenceIOR,Ba=e.materialIridescenceThickness,La=e.materialLightMap,ka=e.materialLineDashOffset,Aa=e.materialLineDashSize,Ga=e.materialLineGapSize,Oa=e.materialLineScale,Wa=e.materialLineWidth,ja=e.materialMetalness,Ua=e.materialNormal,za=e.materialOpacity,qa=e.materialPointSize,Ea=e.materialReference,Za=e.materialReflectivity,Xa=e.materialRefractionRatio,Ya=e.materialRotation,Ha=e.materialRoughness,Ja=e.materialSheen,Ka=e.materialSheenRoughness,Qa=e.materialShininess,$a=e.materialSpecular,eo=e.materialSpecularColor,to=e.materialSpecularIntensity,ro=e.materialSpecularStrength,ao=e.materialThickness,oo=e.materialTransmission,io=e.max,no=e.maxMipLevel,so=e.metalness,lo=e.min,co=e.mix,mo=e.mixElement,po=e.mod,uo=e.modInt,go=e.modelDirection,ho=e.modelNormalMatrix,fo=e.modelPosition,xo=e.modelRadius,bo=e.modelScale,wo=e.modelViewMatrix,vo=e.modelViewPosition,So=e.modelViewProjection,To=e.modelWorldMatrix,_o=e.modelWorldMatrixInverse,Vo=e.morphReference,yo=e.mrt,Do=e.mul,Mo=e.mx_aastep,Fo=e.mx_cell_noise_float,Co=e.mx_contrast,Io=e.mx_fractal_noise_float,Po=e.mx_fractal_noise_vec2,Ro=e.mx_fractal_noise_vec3,No=e.mx_fractal_noise_vec4,Bo=e.mx_hsvtorgb,Lo=e.mx_noise_float,ko=e.mx_noise_vec3,Ao=e.mx_noise_vec4,Go=e.mx_ramplr,Oo=e.mx_ramptb,Wo=e.mx_rgbtohsv,jo=e.mx_safepower,Uo=e.mx_splitlr,zo=e.mx_splittb,qo=e.mx_srgb_texture_to_lin_rec709,Eo=e.mx_transform_uv,Zo=e.mx_worley_noise_float,Xo=e.mx_worley_noise_vec2,Yo=e.mx_worley_noise_vec3,Ho=e.negate,Jo=e.neutralToneMapping,Ko=e.nodeArray,Qo=e.nodeImmutable,$o=e.nodeObject,ei=e.nodeObjects,ti=e.nodeProxy,ri=e.normalFlat,ai=e.normalGeometry,oi=e.normalLocal,ii=e.normalMap,ni=e.normalView,si=e.normalWorld,li=e.normalize,ci=e.not,mi=e.notEqual,pi=e.numWorkgroups,di=e.objectDirection,ui=e.objectGroup,gi=e.objectPosition,hi=e.objectRadius,fi=e.objectScale,xi=e.objectViewPosition,bi=e.objectWorldMatrix,wi=e.oneMinus,vi=e.or,Si=e.orthographicDepthToViewZ,Ti=e.oscSawtooth,_i=e.oscSine,Vi=e.oscSquare,yi=e.oscTriangle,Di=e.output,Mi=e.outputStruct,Fi=e.overlay,Ci=e.overloadingFn,Ii=e.parabola,Pi=e.parallaxDirection,Ri=e.parallaxUV,Ni=e.parameter,Bi=e.pass,Li=e.passTexture,ki=e.pcurve,Ai=e.perspectiveDepthToViewZ,Gi=e.pmremTexture,Oi=e.pointUV,Wi=e.pointWidth,ji=e.positionGeometry,Ui=e.positionLocal,zi=e.positionPrevious,qi=e.positionView,Ei=e.positionViewDirection,Zi=e.positionWorld,Xi=e.positionWorldDirection,Yi=e.posterize,Hi=e.pow,Ji=e.pow2,Ki=e.pow3,Qi=e.pow4,$i=e.property,en=e.radians,tn=e.rand,rn=e.range,an=e.rangeFog,on=e.rangeFogFactor,nn=e.reciprocal,sn=e.lightProjectionUV,ln=e.reference,cn=e.referenceBuffer,mn=e.reflect,pn=e.reflectVector,dn=e.reflectView,un=e.reflector,gn=e.refract,hn=e.refractVector,fn=e.refractView,xn=e.reinhardToneMapping,bn=e.remainder,wn=e.remap,vn=e.remapClamp,Sn=e.renderGroup,Tn=e.renderOutput,_n=e.rendererReference,Vn=e.rotate,yn=e.rotateUV,Dn=e.roughness,Mn=e.round,Fn=e.rtt,Cn=e.sRGBTransferEOTF,In=e.sRGBTransferOETF,Pn=e.sampler,Rn=e.saturate,Nn=e.saturation,Bn=e.screen,Ln=e.screenCoordinate,kn=e.screenSize,An=e.screenUV,Gn=e.scriptable,On=e.scriptableValue,Wn=e.select,jn=e.setCurrentStack,Un=e.shaderStages,zn=e.shadow,qn=e.pointShadow,En=e.shadowPositionWorld,Zn=e.sharedUniformGroup,Xn=e.shapeCircle,Yn=e.sheen,Hn=e.sheenRoughness,Jn=e.shiftLeft,Kn=e.shiftRight,Qn=e.shininess,$n=e.sign,es=e.sin,ts=e.sinc,rs=e.skinning,as=e.skinningReference,os=e.smoothstep,is=e.smoothstepElement,ns=e.specularColor,ss=e.specularF90,ls=e.spherizeUV,cs=e.split,ms=e.spritesheetUV,ps=e.sqrt,ds=e.stack,us=e.step,gs=e.storage,hs=e.storageBarrier,fs=e.storageObject,xs=e.storageTexture,bs=e.string,ws=e.struct,vs=e.sub,Ss=e.subgroupIndex,Ts=e.subgroupSize,_s=e.tan,Vs=e.tangentGeometry,ys=e.tangentLocal,Ds=e.tangentView,Ms=e.tangentWorld,Fs=e.temp,Cs=e.texture,Is=e.texture3D,Ps=e.textureBarrier,Rs=e.textureBicubic,Ns=e.textureCubeUV,Bs=e.textureLoad,Ls=e.textureSize,ks=e.textureStore,As=e.thickness,Gs=e.threshold,Os=e.time,Ws=e.timerDelta,js=e.timerGlobal,Us=e.timerLocal,zs=e.toOutputColorSpace,qs=e.toWorkingColorSpace,Es=e.toneMapping,Zs=e.toneMappingExposure,Xs=e.toonOutlinePass,Ys=e.transformDirection,Hs=e.transformNormal,Js=e.transformNormalToView,Ks=e.transformedBentNormalView,Qs=e.transformedBitangentView,$s=e.transformedBitangentWorld,el=e.transformedClearcoatNormalView,tl=e.transformedNormalView,rl=e.transformedNormalWorld,al=e.transformedTangentView,ol=e.transformedTangentWorld,il=e.transmission,nl=e.transpose,sl=e.tri,ll=e.tri3,cl=e.triNoise3D,ml=e.triplanarTexture,pl=e.triplanarTextures,dl=e.trunc,ul=e.tslFn,gl=e.uint,hl=e.uniform,fl=e.uniformArray,xl=e.uniformGroup,bl=e.uniforms,wl=e.userData,vl=e.uv,Sl=e.uvec2,Tl=e.uvec3,_l=e.uvec4,Vl=e.Var,yl=e.varying,Dl=e.varyingProperty,Ml=e.vec2,Fl=e.vec3,Cl=e.vec4,Il=e.vectorComponents,Pl=e.velocity,Rl=e.vertexColor,Nl=e.vertexIndex,Bl=e.vibrance,Ll=e.viewZToLogarithmicDepth,kl=e.viewZToOrthographicDepth,Al=e.viewZToPerspectiveDepth,Gl=e.viewport,Ol=e.viewportBottomLeft,Wl=e.viewportCoordinate,jl=e.viewportDepthTexture,Ul=e.viewportLinearDepth,zl=e.viewportMipTexture,ql=e.viewportResolution,El=e.viewportSafeUV,Zl=e.viewportSharedTexture,Xl=e.viewportSize,Yl=e.viewportTexture,Hl=e.viewportTopLeft,Jl=e.viewportUV,Kl=e.wgsl,Ql=e.wgslFn,$l=e.workgroupArray,ec=e.workgroupBarrier,tc=e.workgroupId,rc=e.workingToColorSpace,ac=e.xor;export{t as BRDF_GGX,r as BRDF_Lambert,a as BasicShadowFilter,o as Break,mt as Const,i as Continue,n as DFGApprox,s as D_GGX,l as Discard,c as EPSILON,m as F_Schlick,p as Fn,d as INFINITY,u as If,g as Loop,b as NodeAccess,h as NodeShaderStage,f as NodeType,x as NodeUpdateType,w as PCFShadowFilter,v as PCFSoftShadowFilter,S as PI,T as PI2,_ as Return,V as Schlick_to_F0,y as ScriptableNodeResources,D as ShaderNode,M as TBNViewMatrix,F as VSMShadowFilter,C as V_GGX_SmithCorrelated,Vl as Var,I as abs,P as acesFilmicToneMapping,R as acos,N as add,B as addNodeElement,L as agxToneMapping,k as all,A as alphaT,G as and,O as anisotropy,W as anisotropyB,j as anisotropyT,U as any,z as append,q as array,E as arrayBuffer,Z as asin,X as assign,Y as atan,H as atan2,J as atomicAdd,K as atomicAnd,Q as atomicFunc,ie as atomicLoad,$ as atomicMax,ee as atomicMin,te as atomicOr,re as atomicStore,ae as atomicSub,oe as atomicXor,ne as attenuationColor,se as attenuationDistance,le as attribute,ce as attributeArray,me as backgroundBlurriness,pe as backgroundIntensity,de as backgroundRotation,ue as batch,ge as billboarding,he as bitAnd,fe as bitNot,xe as bitOr,be as bitXor,we as bitangentGeometry,ve as bitangentLocal,Se as bitangentView,Te as bitangentWorld,_e as bitcast,Ve as blendBurn,ye as blendColor,De as blendDodge,Me as blendOverlay,Fe as blendScreen,Ce as blur,Ie as bool,Pe as buffer,Re as bufferAttribute,Ne as bumpMap,Be as burn,Le as bvec2,ke as bvec3,Ae as bvec4,Ge as bypass,Oe as cache,We as call,je as cameraFar,Ue as cameraIndex,ze as cameraNear,qe as cameraNormalMatrix,Ee as cameraPosition,Ze as cameraProjectionMatrix,Xe as cameraProjectionMatrixInverse,Ye as cameraViewMatrix,He as cameraWorldMatrix,Je as cbrt,Ke as cdl,Qe as ceil,$e as checker,et as cineonToneMapping,tt as clamp,rt as clearcoat,at as clearcoatRoughness,ot as code,it as color,nt as colorSpaceToWorking,st as colorToDirection,lt as compute,ct as cond,pt as context,dt as convert,ut as convertColorSpace,gt as convertToTexture,ht as cos,ft as cross,xt as cubeTexture,bt as dFdx,wt as dFdy,vt as dashSize,St as defaultBuildStages,Tt as defaultShaderStages,_t as defined,Vt as degrees,yt as deltaTime,Dt as densityFog,Mt as densityFogFactor,Ft as depth,Ct as depthPass,It as difference,Pt as diffuseColor,Rt as directPointLight,Nt as directionToColor,Bt as dispersion,Lt as distance,kt as div,At as dodge,Gt as dot,Ot as drawIndex,Wt as dynamicBufferAttribute,jt as element,Ut as emissive,zt as equal,qt as equals,Et as equirectUV,Zt as exp,Xt as exp2,Yt as expression,Ht as faceDirection,Jt as faceForward,Kt as faceforward,Qt as float,$t as floor,er as fog,tr as fract,rr as frameGroup,ar as frameId,or as frontFacing,ir as fwidth,nr as gain,sr as gapSize,lr as getConstNodeType,cr as getCurrentStack,mr as getDirection,pr as getDistanceAttenuation,dr as getGeometryRoughness,ur as getNormalFromDepth,gr as getParallaxCorrectNormal,hr as getRoughness,fr as getScreenPosition,xr as getShIrradianceAt,br as getTextureIndex,wr as getViewPosition,la as globalId,vr as glsl,Sr as glslFn,Tr as grayscale,_r as greaterThan,Vr as greaterThanEqual,yr as hash,Dr as highpModelNormalViewMatrix,Mr as highpModelViewMatrix,Fr as hue,Cr as instance,Ir as instanceIndex,Pr as instancedArray,Rr as instancedBufferAttribute,Nr as instancedDynamicBufferAttribute,Br as instancedMesh,Lr as int,kr as inverseSqrt,Ar as inversesqrt,Gr as invocationLocalIndex,Or as invocationSubgroupIndex,Wr as ior,jr as iridescence,Ur as iridescenceIOR,zr as iridescenceThickness,qr as ivec2,Er as ivec3,Zr as ivec4,Xr as js,Yr as label,Hr as length,Jr as lengthSq,Kr as lessThan,Qr as lessThanEqual,$r as lightPosition,sn as lightProjectionUV,ea as lightTargetDirection,ta as lightTargetPosition,ra as lightViewPosition,aa as lightingContext,oa as lights,ia as linearDepth,na as linearToneMapping,sa as localId,ca as log,ma as log2,pa as logarithmicDepthToViewZ,da as loop,ua as luminance,ha as mat2,fa as mat3,xa as mat4,ba as matcapUV,wa as materialAO,va as materialAlphaTest,Sa as materialAnisotropy,Ta as materialAnisotropyVector,_a as materialAttenuationColor,Va as materialAttenuationDistance,ya as materialClearcoat,Da as materialClearcoatNormal,Ma as materialClearcoatRoughness,Fa as materialColor,Ca as materialDispersion,Ia as materialEmissive,Pa as materialIOR,Ra as materialIridescence,Na as materialIridescenceIOR,Ba as materialIridescenceThickness,La as materialLightMap,ka as materialLineDashOffset,Aa as materialLineDashSize,Ga as materialLineGapSize,Oa as materialLineScale,Wa as materialLineWidth,ja as materialMetalness,Ua as materialNormal,za as materialOpacity,qa as materialPointSize,Ea as materialReference,Za as materialReflectivity,Xa as materialRefractionRatio,Ya as materialRotation,Ha as materialRoughness,Ja as materialSheen,Ka as materialSheenRoughness,Qa as materialShininess,$a as materialSpecular,eo as materialSpecularColor,to as materialSpecularIntensity,ro as materialSpecularStrength,ao as materialThickness,oo as materialTransmission,io as max,no as maxMipLevel,ga as mediumpModelViewMatrix,so as metalness,lo as min,co as mix,mo as mixElement,po as mod,uo as modInt,go as modelDirection,ho as modelNormalMatrix,fo as modelPosition,xo as modelRadius,bo as modelScale,wo as modelViewMatrix,vo as modelViewPosition,So as modelViewProjection,To as modelWorldMatrix,_o as modelWorldMatrixInverse,Vo as morphReference,yo as mrt,Do as mul,Mo as mx_aastep,Fo as mx_cell_noise_float,Co as mx_contrast,Io as mx_fractal_noise_float,Po as mx_fractal_noise_vec2,Ro as mx_fractal_noise_vec3,No as mx_fractal_noise_vec4,Bo as mx_hsvtorgb,Lo as mx_noise_float,ko as mx_noise_vec3,Ao as mx_noise_vec4,Go as mx_ramplr,Oo as mx_ramptb,Wo as mx_rgbtohsv,jo as mx_safepower,Uo as mx_splitlr,zo as mx_splittb,qo as mx_srgb_texture_to_lin_rec709,Eo as mx_transform_uv,Zo as mx_worley_noise_float,Xo as mx_worley_noise_vec2,Yo as mx_worley_noise_vec3,Ho as negate,Jo as neutralToneMapping,Ko as nodeArray,Qo as nodeImmutable,$o as nodeObject,ei as nodeObjects,ti as nodeProxy,ri as normalFlat,ai as normalGeometry,oi as normalLocal,ii as normalMap,ni as normalView,si as normalWorld,li as normalize,ci as not,mi as notEqual,pi as numWorkgroups,di as objectDirection,ui as objectGroup,gi as objectPosition,hi as objectRadius,fi as objectScale,xi as objectViewPosition,bi as objectWorldMatrix,wi as oneMinus,vi as or,Si as orthographicDepthToViewZ,Ti as oscSawtooth,_i as oscSine,Vi as oscSquare,yi as oscTriangle,Di as output,Mi as outputStruct,Fi as overlay,Ci as overloadingFn,Ii as parabola,Pi as parallaxDirection,Ri as parallaxUV,Ni as parameter,Bi as pass,Li as passTexture,ki as pcurve,Ai as perspectiveDepthToViewZ,Gi as pmremTexture,qn as pointShadow,Oi as pointUV,Wi as pointWidth,ji as positionGeometry,Ui as positionLocal,zi as positionPrevious,qi as positionView,Ei as positionViewDirection,Zi as positionWorld,Xi as positionWorldDirection,Yi as posterize,Hi as pow,Ji as pow2,Ki as pow3,Qi as pow4,$i as property,en as radians,tn as rand,rn as range,an as rangeFog,on as rangeFogFactor,nn as reciprocal,ln as reference,cn as referenceBuffer,mn as reflect,pn as reflectVector,dn as reflectView,un as reflector,gn as refract,hn as refractVector,fn as refractView,xn as reinhardToneMapping,bn as remainder,wn as remap,vn as remapClamp,Sn as renderGroup,Tn as renderOutput,_n as rendererReference,Vn as rotate,yn as rotateUV,Dn as roughness,Mn as round,Fn as rtt,Cn as sRGBTransferEOTF,In as sRGBTransferOETF,Pn as sampler,Rn as saturate,Nn as saturation,Bn as screen,Ln as screenCoordinate,kn as screenSize,An as screenUV,Gn as scriptable,On as scriptableValue,Wn as select,jn as setCurrentStack,Un as shaderStages,zn as shadow,En as shadowPositionWorld,Xn as shapeCircle,Zn as sharedUniformGroup,Yn as sheen,Hn as sheenRoughness,Jn as shiftLeft,Kn as shiftRight,Qn as shininess,$n as sign,es as sin,ts as sinc,rs as skinning,as as skinningReference,os as smoothstep,is as smoothstepElement,ns as specularColor,ss as specularF90,ls as spherizeUV,cs as split,ms as spritesheetUV,ps as sqrt,ds as stack,us as step,gs as storage,hs as storageBarrier,fs as storageObject,xs as storageTexture,bs as string,ws as struct,vs as sub,Ss as subgroupIndex,Ts as subgroupSize,_s as tan,Vs as tangentGeometry,ys as tangentLocal,Ds as tangentView,Ms as tangentWorld,Fs as temp,Cs as texture,Is as texture3D,Ps as textureBarrier,Rs as textureBicubic,Ns as textureCubeUV,Bs as textureLoad,Ls as textureSize,ks as textureStore,As as thickness,Gs as threshold,Os as time,Ws as timerDelta,js as timerGlobal,Us as timerLocal,zs as toOutputColorSpace,qs as toWorkingColorSpace,Es as toneMapping,Zs as toneMappingExposure,Xs as toonOutlinePass,Ys as transformDirection,Hs as transformNormal,Js as transformNormalToView,Ks as transformedBentNormalView,Qs as transformedBitangentView,$s as transformedBitangentWorld,el as transformedClearcoatNormalView,tl as transformedNormalView,rl as transformedNormalWorld,al as transformedTangentView,ol as transformedTangentWorld,il as transmission,nl as transpose,sl as tri,ll as tri3,cl as triNoise3D,ml as triplanarTexture,pl as triplanarTextures,dl as trunc,ul as tslFn,gl as uint,hl as uniform,fl as uniformArray,xl as uniformGroup,bl as uniforms,wl as userData,vl as uv,Sl as uvec2,Tl as uvec3,_l as uvec4,yl as varying,Dl as varyingProperty,Ml as vec2,Fl as vec3,Cl as vec4,Il as vectorComponents,Pl as velocity,Rl as vertexColor,Nl as vertexIndex,Bl as vibrance,Ll as viewZToLogarithmicDepth,kl as viewZToOrthographicDepth,Al as viewZToPerspectiveDepth,Gl as viewport,Ol as viewportBottomLeft,Wl as viewportCoordinate,jl as viewportDepthTexture,Ul as viewportLinearDepth,zl as viewportMipTexture,ql as viewportResolution,El as viewportSafeUV,Zl as viewportSharedTexture,Xl as viewportSize,Yl as viewportTexture,Hl as viewportTopLeft,Jl as viewportUV,Kl as wgsl,Ql as wgslFn,$l as workgroupArray,ec as workgroupBarrier,tc as workgroupId,rc as workingToColorSpace,ac as xor};
import{TSL as e}from"three/webgpu";const t=e.BRDF_GGX,r=e.BRDF_Lambert,a=e.BasicShadowFilter,o=e.Break,i=e.Continue,n=e.DFGApprox,s=e.D_GGX,l=e.Discard,c=e.EPSILON,m=e.F_Schlick,p=e.Fn,d=e.INFINITY,u=e.If,g=e.Loop,h=e.NodeShaderStage,x=e.NodeType,f=e.NodeUpdateType,b=e.NodeAccess,w=e.PCFShadowFilter,v=e.PCFSoftShadowFilter,S=e.PI,T=e.PI2,_=e.Return,V=e.Schlick_to_F0,y=e.ScriptableNodeResources,D=e.ShaderNode,M=e.TBNViewMatrix,F=e.VSMShadowFilter,C=e.V_GGX_SmithCorrelated,I=e.abs,P=e.acesFilmicToneMapping,N=e.acos,R=e.add,B=e.addNodeElement,L=e.agxToneMapping,k=e.all,A=e.alphaT,G=e.and,O=e.anisotropy,W=e.anisotropyB,j=e.anisotropyT,U=e.any,z=e.append,q=e.array,E=e.arrayBuffer,Z=e.asin,X=e.assign,Y=e.atan,H=e.atan2,J=e.atomicAdd,K=e.atomicAnd,Q=e.atomicFunc,$=e.atomicMax,ee=e.atomicMin,te=e.atomicOr,re=e.atomicStore,ae=e.atomicSub,oe=e.atomicXor,ie=e.atomicLoad,ne=e.attenuationColor,se=e.attenuationDistance,le=e.attribute,ce=e.attributeArray,me=e.backgroundBlurriness,pe=e.backgroundIntensity,de=e.backgroundRotation,ue=e.batch,ge=e.billboarding,he=e.bitAnd,xe=e.bitNot,fe=e.bitOr,be=e.bitXor,we=e.bitangentGeometry,ve=e.bitangentLocal,Se=e.bitangentView,Te=e.bitangentWorld,_e=e.bitcast,Ve=e.blendBurn,ye=e.blendColor,De=e.blendDodge,Me=e.blendOverlay,Fe=e.blendScreen,Ce=e.blur,Ie=e.bool,Pe=e.buffer,Ne=e.bufferAttribute,Re=e.bumpMap,Be=e.burn,Le=e.bvec2,ke=e.bvec3,Ae=e.bvec4,Ge=e.bypass,Oe=e.cache,We=e.call,je=e.cameraFar,Ue=e.cameraIndex,ze=e.cameraNear,qe=e.cameraNormalMatrix,Ee=e.cameraPosition,Ze=e.cameraProjectionMatrix,Xe=e.cameraProjectionMatrixInverse,Ye=e.cameraViewMatrix,He=e.cameraWorldMatrix,Je=e.cbrt,Ke=e.cdl,Qe=e.ceil,$e=e.checker,et=e.cineonToneMapping,tt=e.clamp,rt=e.clearcoat,at=e.clearcoatRoughness,ot=e.code,it=e.color,nt=e.colorSpaceToWorking,st=e.colorToDirection,lt=e.compute,ct=e.computeSkinning,mt=e.cond,pt=e.Const,dt=e.context,ut=e.convert,gt=e.convertColorSpace,ht=e.convertToTexture,xt=e.cos,ft=e.cross,bt=e.cubeTexture,wt=e.dFdx,vt=e.dFdy,St=e.dashSize,Tt=e.debug,_t=e.defaultBuildStages,Vt=e.defaultShaderStages,yt=e.defined,Dt=e.degrees,Mt=e.deltaTime,Ft=e.densityFog,Ct=e.densityFogFactor,It=e.depth,Pt=e.depthPass,Nt=e.difference,Rt=e.diffuseColor,Bt=e.directPointLight,Lt=e.directionToColor,kt=e.dispersion,At=e.distance,Gt=e.div,Ot=e.dodge,Wt=e.dot,jt=e.drawIndex,Ut=e.dynamicBufferAttribute,zt=e.element,qt=e.emissive,Et=e.equal,Zt=e.equals,Xt=e.equirectUV,Yt=e.exp,Ht=e.exp2,Jt=e.expression,Kt=e.faceDirection,Qt=e.faceForward,$t=e.faceforward,er=e.float,tr=e.floor,rr=e.fog,ar=e.fract,or=e.frameGroup,ir=e.frameId,nr=e.frontFacing,sr=e.fwidth,lr=e.gain,cr=e.gapSize,mr=e.getConstNodeType,pr=e.getCurrentStack,dr=e.getDirection,ur=e.getDistanceAttenuation,gr=e.getGeometryRoughness,hr=e.getNormalFromDepth,xr=e.getParallaxCorrectNormal,fr=e.getRoughness,br=e.getScreenPosition,wr=e.getShIrradianceAt,vr=e.getTextureIndex,Sr=e.getViewPosition,Tr=e.glsl,_r=e.glslFn,Vr=e.grayscale,yr=e.greaterThan,Dr=e.greaterThanEqual,Mr=e.hash,Fr=e.highpModelNormalViewMatrix,Cr=e.highpModelViewMatrix,Ir=e.hue,Pr=e.instance,Nr=e.instanceIndex,Rr=e.instancedArray,Br=e.instancedBufferAttribute,Lr=e.instancedDynamicBufferAttribute,kr=e.instancedMesh,Ar=e.int,Gr=e.inverseSqrt,Or=e.inversesqrt,Wr=e.invocationLocalIndex,jr=e.invocationSubgroupIndex,Ur=e.ior,zr=e.iridescence,qr=e.iridescenceIOR,Er=e.iridescenceThickness,Zr=e.ivec2,Xr=e.ivec3,Yr=e.ivec4,Hr=e.js,Jr=e.label,Kr=e.length,Qr=e.lengthSq,$r=e.lessThan,ea=e.lessThanEqual,ta=e.lightPosition,ra=e.lightTargetDirection,aa=e.lightTargetPosition,oa=e.lightViewPosition,ia=e.lightingContext,na=e.lights,sa=e.linearDepth,la=e.linearToneMapping,ca=e.localId,ma=e.globalId,pa=e.log,da=e.log2,ua=e.logarithmicDepthToViewZ,ga=e.loop,ha=e.luminance,xa=e.mediumpModelViewMatrix,fa=e.mat2,ba=e.mat3,wa=e.mat4,va=e.matcapUV,Sa=e.materialAO,Ta=e.materialAlphaTest,_a=e.materialAnisotropy,Va=e.materialAnisotropyVector,ya=e.materialAttenuationColor,Da=e.materialAttenuationDistance,Ma=e.materialClearcoat,Fa=e.materialClearcoatNormal,Ca=e.materialClearcoatRoughness,Ia=e.materialColor,Pa=e.materialDispersion,Na=e.materialEmissive,Ra=e.materialIOR,Ba=e.materialIridescence,La=e.materialIridescenceIOR,ka=e.materialIridescenceThickness,Aa=e.materialLightMap,Ga=e.materialLineDashOffset,Oa=e.materialLineDashSize,Wa=e.materialLineGapSize,ja=e.materialLineScale,Ua=e.materialLineWidth,za=e.materialMetalness,qa=e.materialNormal,Ea=e.materialOpacity,Za=e.materialPointSize,Xa=e.materialReference,Ya=e.materialReflectivity,Ha=e.materialRefractionRatio,Ja=e.materialRotation,Ka=e.materialRoughness,Qa=e.materialSheen,$a=e.materialSheenRoughness,eo=e.materialShininess,to=e.materialSpecular,ro=e.materialSpecularColor,ao=e.materialSpecularIntensity,oo=e.materialSpecularStrength,io=e.materialThickness,no=e.materialTransmission,so=e.max,lo=e.maxMipLevel,co=e.metalness,mo=e.min,po=e.mix,uo=e.mixElement,go=e.mod,ho=e.modInt,xo=e.modelDirection,fo=e.modelNormalMatrix,bo=e.modelPosition,wo=e.modelRadius,vo=e.modelScale,So=e.modelViewMatrix,To=e.modelViewPosition,_o=e.modelViewProjection,Vo=e.modelWorldMatrix,yo=e.modelWorldMatrixInverse,Do=e.morphReference,Mo=e.mrt,Fo=e.mul,Co=e.mx_aastep,Io=e.mx_cell_noise_float,Po=e.mx_contrast,No=e.mx_fractal_noise_float,Ro=e.mx_fractal_noise_vec2,Bo=e.mx_fractal_noise_vec3,Lo=e.mx_fractal_noise_vec4,ko=e.mx_hsvtorgb,Ao=e.mx_noise_float,Go=e.mx_noise_vec3,Oo=e.mx_noise_vec4,Wo=e.mx_ramplr,jo=e.mx_ramptb,Uo=e.mx_rgbtohsv,zo=e.mx_safepower,qo=e.mx_splitlr,Eo=e.mx_splittb,Zo=e.mx_srgb_texture_to_lin_rec709,Xo=e.mx_transform_uv,Yo=e.mx_worley_noise_float,Ho=e.mx_worley_noise_vec2,Jo=e.mx_worley_noise_vec3,Ko=e.negate,Qo=e.neutralToneMapping,$o=e.nodeArray,ei=e.nodeImmutable,ti=e.nodeObject,ri=e.nodeObjects,ai=e.nodeProxy,oi=e.normalFlat,ii=e.normalGeometry,ni=e.normalLocal,si=e.normalMap,li=e.normalView,ci=e.normalWorld,mi=e.normalize,pi=e.not,di=e.notEqual,ui=e.numWorkgroups,gi=e.objectDirection,hi=e.objectGroup,xi=e.objectPosition,fi=e.objectRadius,bi=e.objectScale,wi=e.objectViewPosition,vi=e.objectWorldMatrix,Si=e.oneMinus,Ti=e.or,_i=e.orthographicDepthToViewZ,Vi=e.oscSawtooth,yi=e.oscSine,Di=e.oscSquare,Mi=e.oscTriangle,Fi=e.output,Ci=e.outputStruct,Ii=e.overlay,Pi=e.overloadingFn,Ni=e.parabola,Ri=e.parallaxDirection,Bi=e.parallaxUV,Li=e.parameter,ki=e.pass,Ai=e.passTexture,Gi=e.pcurve,Oi=e.perspectiveDepthToViewZ,Wi=e.pmremTexture,ji=e.pointUV,Ui=e.pointWidth,zi=e.positionGeometry,qi=e.positionLocal,Ei=e.positionPrevious,Zi=e.positionView,Xi=e.positionViewDirection,Yi=e.positionWorld,Hi=e.positionWorldDirection,Ji=e.posterize,Ki=e.pow,Qi=e.pow2,$i=e.pow3,en=e.pow4,tn=e.property,rn=e.radians,an=e.rand,on=e.range,nn=e.rangeFog,sn=e.rangeFogFactor,ln=e.reciprocal,cn=e.lightProjectionUV,mn=e.reference,pn=e.referenceBuffer,dn=e.reflect,un=e.reflectVector,gn=e.reflectView,hn=e.reflector,xn=e.refract,fn=e.refractVector,bn=e.refractView,wn=e.reinhardToneMapping,vn=e.remainder,Sn=e.remap,Tn=e.remapClamp,_n=e.renderGroup,Vn=e.renderOutput,yn=e.rendererReference,Dn=e.rotate,Mn=e.rotateUV,Fn=e.roughness,Cn=e.round,In=e.rtt,Pn=e.sRGBTransferEOTF,Nn=e.sRGBTransferOETF,Rn=e.sampler,Bn=e.samplerComparison,Ln=e.saturate,kn=e.saturation,An=e.screen,Gn=e.screenCoordinate,On=e.screenSize,Wn=e.screenUV,jn=e.scriptable,Un=e.scriptableValue,zn=e.select,qn=e.setCurrentStack,En=e.shaderStages,Zn=e.shadow,Xn=e.pointShadow,Yn=e.shadowPositionWorld,Hn=e.sharedUniformGroup,Jn=e.shapeCircle,Kn=e.sheen,Qn=e.sheenRoughness,$n=e.shiftLeft,es=e.shiftRight,ts=e.shininess,rs=e.sign,as=e.sin,os=e.sinc,is=e.skinning,ns=e.smoothstep,ss=e.smoothstepElement,ls=e.specularColor,cs=e.specularF90,ms=e.spherizeUV,ps=e.split,ds=e.spritesheetUV,us=e.sqrt,gs=e.stack,hs=e.step,xs=e.storage,fs=e.storageBarrier,bs=e.storageObject,ws=e.storageTexture,vs=e.string,Ss=e.struct,Ts=e.sub,_s=e.subgroupIndex,Vs=e.subgroupSize,ys=e.tan,Ds=e.tangentGeometry,Ms=e.tangentLocal,Fs=e.tangentView,Cs=e.tangentWorld,Is=e.temp,Ps=e.texture,Ns=e.texture3D,Rs=e.textureBarrier,Bs=e.textureBicubic,Ls=e.textureCubeUV,ks=e.textureLoad,As=e.textureSize,Gs=e.textureStore,Os=e.thickness,Ws=e.threshold,js=e.time,Us=e.timerDelta,zs=e.timerGlobal,qs=e.timerLocal,Es=e.toOutputColorSpace,Zs=e.toWorkingColorSpace,Xs=e.toneMapping,Ys=e.toneMappingExposure,Hs=e.toonOutlinePass,Js=e.transformDirection,Ks=e.transformNormal,Qs=e.transformNormalToView,$s=e.transformedBentNormalView,el=e.transformedBitangentView,tl=e.transformedBitangentWorld,rl=e.transformedClearcoatNormalView,al=e.transformedNormalView,ol=e.transformedNormalWorld,il=e.transformedTangentView,nl=e.transformedTangentWorld,sl=e.transmission,ll=e.transpose,cl=e.tri,ml=e.tri3,pl=e.triNoise3D,dl=e.triplanarTexture,ul=e.triplanarTextures,gl=e.trunc,hl=e.tslFn,xl=e.uint,fl=e.uniform,bl=e.uniformArray,wl=e.uniformGroup,vl=e.uniforms,Sl=e.userData,Tl=e.uv,_l=e.uvec2,Vl=e.uvec3,yl=e.uvec4,Dl=e.Var,Ml=e.varying,Fl=e.varyingProperty,Cl=e.vec2,Il=e.vec3,Pl=e.vec4,Nl=e.vectorComponents,Rl=e.velocity,Bl=e.vertexColor,Ll=e.vertexIndex,kl=e.vibrance,Al=e.viewZToLogarithmicDepth,Gl=e.viewZToOrthographicDepth,Ol=e.viewZToPerspectiveDepth,Wl=e.viewport,jl=e.viewportBottomLeft,Ul=e.viewportCoordinate,zl=e.viewportDepthTexture,ql=e.viewportLinearDepth,El=e.viewportMipTexture,Zl=e.viewportResolution,Xl=e.viewportSafeUV,Yl=e.viewportSharedTexture,Hl=e.viewportSize,Jl=e.viewportTexture,Kl=e.viewportTopLeft,Ql=e.viewportUV,$l=e.wgsl,ec=e.wgslFn,tc=e.workgroupArray,rc=e.workgroupBarrier,ac=e.workgroupId,oc=e.workingToColorSpace,ic=e.xor;export{t as BRDF_GGX,r as BRDF_Lambert,a as BasicShadowFilter,o as Break,pt as Const,i as Continue,n as DFGApprox,s as D_GGX,l as Discard,c as EPSILON,m as F_Schlick,p as Fn,d as INFINITY,u as If,g as Loop,b as NodeAccess,h as NodeShaderStage,x as NodeType,f as NodeUpdateType,w as PCFShadowFilter,v as PCFSoftShadowFilter,S as PI,T as PI2,_ as Return,V as Schlick_to_F0,y as ScriptableNodeResources,D as ShaderNode,M as TBNViewMatrix,F as VSMShadowFilter,C as V_GGX_SmithCorrelated,Dl as Var,I as abs,P as acesFilmicToneMapping,N as acos,R as add,B as addNodeElement,L as agxToneMapping,k as all,A as alphaT,G as and,O as anisotropy,W as anisotropyB,j as anisotropyT,U as any,z as append,q as array,E as arrayBuffer,Z as asin,X as assign,Y as atan,H as atan2,J as atomicAdd,K as atomicAnd,Q as atomicFunc,ie as atomicLoad,$ as atomicMax,ee as atomicMin,te as atomicOr,re as atomicStore,ae as atomicSub,oe as atomicXor,ne as attenuationColor,se as attenuationDistance,le as attribute,ce as attributeArray,me as backgroundBlurriness,pe as backgroundIntensity,de as backgroundRotation,ue as batch,ge as billboarding,he as bitAnd,xe as bitNot,fe as bitOr,be as bitXor,we as bitangentGeometry,ve as bitangentLocal,Se as bitangentView,Te as bitangentWorld,_e as bitcast,Ve as blendBurn,ye as blendColor,De as blendDodge,Me as blendOverlay,Fe as blendScreen,Ce as blur,Ie as bool,Pe as buffer,Ne as bufferAttribute,Re as bumpMap,Be as burn,Le as bvec2,ke as bvec3,Ae as bvec4,Ge as bypass,Oe as cache,We as call,je as cameraFar,Ue as cameraIndex,ze as cameraNear,qe as cameraNormalMatrix,Ee as cameraPosition,Ze as cameraProjectionMatrix,Xe as cameraProjectionMatrixInverse,Ye as cameraViewMatrix,He as cameraWorldMatrix,Je as cbrt,Ke as cdl,Qe as ceil,$e as checker,et as cineonToneMapping,tt as clamp,rt as clearcoat,at as clearcoatRoughness,ot as code,it as color,nt as colorSpaceToWorking,st as colorToDirection,lt as compute,ct as computeSkinning,mt as cond,dt as context,ut as convert,gt as convertColorSpace,ht as convertToTexture,xt as cos,ft as cross,bt as cubeTexture,wt as dFdx,vt as dFdy,St as dashSize,Tt as debug,_t as defaultBuildStages,Vt as defaultShaderStages,yt as defined,Dt as degrees,Mt as deltaTime,Ft as densityFog,Ct as densityFogFactor,It as depth,Pt as depthPass,Nt as difference,Rt as diffuseColor,Bt as directPointLight,Lt as directionToColor,kt as dispersion,At as distance,Gt as div,Ot as dodge,Wt as dot,jt as drawIndex,Ut as dynamicBufferAttribute,zt as element,qt as emissive,Et as equal,Zt as equals,Xt as equirectUV,Yt as exp,Ht as exp2,Jt as expression,Kt as faceDirection,Qt as faceForward,$t as faceforward,er as float,tr as floor,rr as fog,ar as fract,or as frameGroup,ir as frameId,nr as frontFacing,sr as fwidth,lr as gain,cr as gapSize,mr as getConstNodeType,pr as getCurrentStack,dr as getDirection,ur as getDistanceAttenuation,gr as getGeometryRoughness,hr as getNormalFromDepth,xr as getParallaxCorrectNormal,fr as getRoughness,br as getScreenPosition,wr as getShIrradianceAt,vr as getTextureIndex,Sr as getViewPosition,ma as globalId,Tr as glsl,_r as glslFn,Vr as grayscale,yr as greaterThan,Dr as greaterThanEqual,Mr as hash,Fr as highpModelNormalViewMatrix,Cr as highpModelViewMatrix,Ir as hue,Pr as instance,Nr as instanceIndex,Rr as instancedArray,Br as instancedBufferAttribute,Lr as instancedDynamicBufferAttribute,kr as instancedMesh,Ar as int,Gr as inverseSqrt,Or as inversesqrt,Wr as invocationLocalIndex,jr as invocationSubgroupIndex,Ur as ior,zr as iridescence,qr as iridescenceIOR,Er as iridescenceThickness,Zr as ivec2,Xr as ivec3,Yr as ivec4,Hr as js,Jr as label,Kr as length,Qr as lengthSq,$r as lessThan,ea as lessThanEqual,ta as lightPosition,cn as lightProjectionUV,ra as lightTargetDirection,aa as lightTargetPosition,oa as lightViewPosition,ia as lightingContext,na as lights,sa as linearDepth,la as linearToneMapping,ca as localId,pa as log,da as log2,ua as logarithmicDepthToViewZ,ga as loop,ha as luminance,fa as mat2,ba as mat3,wa as mat4,va as matcapUV,Sa as materialAO,Ta as materialAlphaTest,_a as materialAnisotropy,Va as materialAnisotropyVector,ya as materialAttenuationColor,Da as materialAttenuationDistance,Ma as materialClearcoat,Fa as materialClearcoatNormal,Ca as materialClearcoatRoughness,Ia as materialColor,Pa as materialDispersion,Na as materialEmissive,Ra as materialIOR,Ba as materialIridescence,La as materialIridescenceIOR,ka as materialIridescenceThickness,Aa as materialLightMap,Ga as materialLineDashOffset,Oa as materialLineDashSize,Wa as materialLineGapSize,ja as materialLineScale,Ua as materialLineWidth,za as materialMetalness,qa as materialNormal,Ea as materialOpacity,Za as materialPointSize,Xa as materialReference,Ya as materialReflectivity,Ha as materialRefractionRatio,Ja as materialRotation,Ka as materialRoughness,Qa as materialSheen,$a as materialSheenRoughness,eo as materialShininess,to as materialSpecular,ro as materialSpecularColor,ao as materialSpecularIntensity,oo as materialSpecularStrength,io as materialThickness,no as materialTransmission,so as max,lo as maxMipLevel,xa as mediumpModelViewMatrix,co as metalness,mo as min,po as mix,uo as mixElement,go as mod,ho as modInt,xo as modelDirection,fo as modelNormalMatrix,bo as modelPosition,wo as modelRadius,vo as modelScale,So as modelViewMatrix,To as modelViewPosition,_o as modelViewProjection,Vo as modelWorldMatrix,yo as modelWorldMatrixInverse,Do as morphReference,Mo as mrt,Fo as mul,Co as mx_aastep,Io as mx_cell_noise_float,Po as mx_contrast,No as mx_fractal_noise_float,Ro as mx_fractal_noise_vec2,Bo as mx_fractal_noise_vec3,Lo as mx_fractal_noise_vec4,ko as mx_hsvtorgb,Ao as mx_noise_float,Go as mx_noise_vec3,Oo as mx_noise_vec4,Wo as mx_ramplr,jo as mx_ramptb,Uo as mx_rgbtohsv,zo as mx_safepower,qo as mx_splitlr,Eo as mx_splittb,Zo as mx_srgb_texture_to_lin_rec709,Xo as mx_transform_uv,Yo as mx_worley_noise_float,Ho as mx_worley_noise_vec2,Jo as mx_worley_noise_vec3,Ko as negate,Qo as neutralToneMapping,$o as nodeArray,ei as nodeImmutable,ti as nodeObject,ri as nodeObjects,ai as nodeProxy,oi as normalFlat,ii as normalGeometry,ni as normalLocal,si as normalMap,li as normalView,ci as normalWorld,mi as normalize,pi as not,di as notEqual,ui as numWorkgroups,gi as objectDirection,hi as objectGroup,xi as objectPosition,fi as objectRadius,bi as objectScale,wi as objectViewPosition,vi as objectWorldMatrix,Si as oneMinus,Ti as or,_i as orthographicDepthToViewZ,Vi as oscSawtooth,yi as oscSine,Di as oscSquare,Mi as oscTriangle,Fi as output,Ci as outputStruct,Ii as overlay,Pi as overloadingFn,Ni as parabola,Ri as parallaxDirection,Bi as parallaxUV,Li as parameter,ki as pass,Ai as passTexture,Gi as pcurve,Oi as perspectiveDepthToViewZ,Wi as pmremTexture,Xn as pointShadow,ji as pointUV,Ui as pointWidth,zi as positionGeometry,qi as positionLocal,Ei as positionPrevious,Zi as positionView,Xi as positionViewDirection,Yi as positionWorld,Hi as positionWorldDirection,Ji as posterize,Ki as pow,Qi as pow2,$i as pow3,en as pow4,tn as property,rn as radians,an as rand,on as range,nn as rangeFog,sn as rangeFogFactor,ln as reciprocal,mn as reference,pn as referenceBuffer,dn as reflect,un as reflectVector,gn as reflectView,hn as reflector,xn as refract,fn as refractVector,bn as refractView,wn as reinhardToneMapping,vn as remainder,Sn as remap,Tn as remapClamp,_n as renderGroup,Vn as renderOutput,yn as rendererReference,Dn as rotate,Mn as rotateUV,Fn as roughness,Cn as round,In as rtt,Pn as sRGBTransferEOTF,Nn as sRGBTransferOETF,Rn as sampler,Bn as samplerComparison,Ln as saturate,kn as saturation,An as screen,Gn as screenCoordinate,On as screenSize,Wn as screenUV,jn as scriptable,Un as scriptableValue,zn as select,qn as setCurrentStack,En as shaderStages,Zn as shadow,Yn as shadowPositionWorld,Jn as shapeCircle,Hn as sharedUniformGroup,Kn as sheen,Qn as sheenRoughness,$n as shiftLeft,es as shiftRight,ts as shininess,rs as sign,as as sin,os as sinc,is as skinning,ns as smoothstep,ss as smoothstepElement,ls as specularColor,cs as specularF90,ms as spherizeUV,ps as split,ds as spritesheetUV,us as sqrt,gs as stack,hs as step,xs as storage,fs as storageBarrier,bs as storageObject,ws as storageTexture,vs as string,Ss as struct,Ts as sub,_s as subgroupIndex,Vs as subgroupSize,ys as tan,Ds as tangentGeometry,Ms as tangentLocal,Fs as tangentView,Cs as tangentWorld,Is as temp,Ps as texture,Ns as texture3D,Rs as textureBarrier,Bs as textureBicubic,Ls as textureCubeUV,ks as textureLoad,As as textureSize,Gs as textureStore,Os as thickness,Ws as threshold,js as time,Us as timerDelta,zs as timerGlobal,qs as timerLocal,Es as toOutputColorSpace,Zs as toWorkingColorSpace,Xs as toneMapping,Ys as toneMappingExposure,Hs as toonOutlinePass,Js as transformDirection,Ks as transformNormal,Qs as transformNormalToView,$s as transformedBentNormalView,el as transformedBitangentView,tl as transformedBitangentWorld,rl as transformedClearcoatNormalView,al as transformedNormalView,ol as transformedNormalWorld,il as transformedTangentView,nl as transformedTangentWorld,sl as transmission,ll as transpose,cl as tri,ml as tri3,pl as triNoise3D,dl as triplanarTexture,ul as triplanarTextures,gl as trunc,hl as tslFn,xl as uint,fl as uniform,bl as uniformArray,wl as uniformGroup,vl as uniforms,Sl as userData,Tl as uv,_l as uvec2,Vl as uvec3,yl as uvec4,Ml as varying,Fl as varyingProperty,Cl as vec2,Il as vec3,Pl as vec4,Nl as vectorComponents,Rl as velocity,Bl as vertexColor,Ll as vertexIndex,kl as vibrance,Al as viewZToLogarithmicDepth,Gl as viewZToOrthographicDepth,Ol as viewZToPerspectiveDepth,Wl as viewport,jl as viewportBottomLeft,Ul as viewportCoordinate,zl as viewportDepthTexture,ql as viewportLinearDepth,El as viewportMipTexture,Zl as viewportResolution,Xl as viewportSafeUV,Yl as viewportSharedTexture,Hl as viewportSize,Jl as viewportTexture,Kl as viewportTopLeft,Ql as viewportUV,$l as wgsl,ec as wgslFn,tc as workgroupArray,rc as workgroupBarrier,ac as workgroupId,oc as workingToColorSpace,ic as xor};

@@ -49,3 +49,3 @@ export * from './animation/AnimationClipCreator.js';

export * from './geometries/DecalGeometry.js';
export * from './geometries/ParametricGeometries.js';
export * from './geometries/ParametricFunctions.js';
export * from './geometries/ParametricGeometry.js';

@@ -52,0 +52,0 @@ export * from './geometries/RoundedBoxGeometry.js';

@@ -10,4 +10,17 @@ import {

/**
* A utility class with factory methods for creating basic animation clips.
*
* @hideconstructor
*/
class AnimationClipCreator {
/**
* Creates an animation clip that rotates a 3D object 360 degrees
* in the given period of time around the given axis.
*
* @param {number} period - The duration of the animation.
* @param {('x'|'y'|'z')} [axis='x'] - The axis of rotation.
* @return {AnimationClip} The created animation clip.
*/
static CreateRotationAnimation( period, axis = 'x' ) {

@@ -21,6 +34,14 @@

return new AnimationClip( null, period, [ track ] );
return new AnimationClip( '', period, [ track ] );
}
/**
* Creates an animation clip that scales a 3D object from `0` to `1`
* in the given period of time along the given axis.
*
* @param {number} period - The duration of the animation.
* @param {('x'|'y'|'z')} [axis='x'] - The axis to scale the 3D object along.
* @return {AnimationClip} The created animation clip.
*/
static CreateScaleAxisAnimation( period, axis = 'x' ) {

@@ -34,6 +55,14 @@

return new AnimationClip( null, period, [ track ] );
return new AnimationClip( '', period, [ track ] );
}
/**
* Creates an animation clip that translates a 3D object in a shake pattern
* in the given period.
*
* @param {number} duration - The duration of the animation.
* @param {Vector3} shakeScale - The scale of the shake.
* @return {AnimationClip} The created animation clip.
*/
static CreateShakeAnimation( duration, shakeScale ) {

@@ -57,6 +86,14 @@

return new AnimationClip( null, duration, [ track ] );
return new AnimationClip( '', duration, [ track ] );
}
/**
* Creates an animation clip that scales a 3D object in a pulse pattern
* in the given period.
*
* @param {number} duration - The duration of the animation.
* @param {number} pulseScale - The scale of the pulse.
* @return {AnimationClip} The created animation clip.
*/
static CreatePulsationAnimation( duration, pulseScale ) {

@@ -80,6 +117,12 @@

return new AnimationClip( null, duration, [ track ] );
return new AnimationClip( '', duration, [ track ] );
}
/**
* Creates an animation clip that toggles the visibility of a 3D object.
*
* @param {number} duration - The duration of the animation.
* @return {AnimationClip} The created animation clip.
*/
static CreateVisibilityAnimation( duration ) {

@@ -93,6 +136,14 @@

return new AnimationClip( null, duration, [ track ] );
return new AnimationClip( '', duration, [ track ] );
}
/**
* Creates an animation clip that animates the `color` property of a 3D object's
* material.
*
* @param {number} duration - The duration of the animation.
* @param {Array<Color>} colors - An array of colors that should be sequentially animated.
* @return {AnimationClip} The created animation clip.
*/
static CreateMaterialColorAnimation( duration, colors ) {

@@ -116,3 +167,3 @@

return new AnimationClip( null, duration, [ track ] );
return new AnimationClip( '', duration, [ track ] );

@@ -119,0 +170,0 @@ }

@@ -28,32 +28,27 @@ import {

/**
* CCD Algorithm
* - https://web.archive.org/web/20221206080850/https://sites.google.com/site/auraliusproject/ccd-algorithm
* This class solves the Inverse Kinematics Problem with a [CCD Algorithm]{@link https://web.archive.org/web/20221206080850/https://sites.google.com/site/auraliusproject/ccd-algorithm}.
*
* // ik parameter example
* //
* // target, effector, index in links are bone index in skeleton.bones.
* // the bones relation should be
* // <-- parent child -->
* // links[ n ], links[ n - 1 ], ..., links[ 0 ], effector
* iks = [ {
* target: 1,
* effector: 2,
* links: [ { index: 5, limitation: new Vector3( 1, 0, 0 ) }, { index: 4, enabled: false }, { index : 3 } ],
* iteration: 10,
* minAngle: 0.0,
* maxAngle: 1.0,
* } ];
* `CCDIKSolver` is designed to work with instances of {@link SkinnedMesh}.
*/
class CCDIKSolver {
/**
* @param {THREE.SkinnedMesh} mesh
* @param {Array<Object>} iks
* @param {SkinnedMesh} mesh - The skinned mesh.
* @param {Array<CCDIKSolver~IK>} [iks=[]] - The IK objects.
*/
constructor( mesh, iks = [] ) {
/**
* The skinned mesh.
*
* @type {SkinnedMesh}
*/
this.mesh = mesh;
/**
* The IK objects.
*
* @type {SkinnedMesh}
*/
this.iks = iks;

@@ -82,6 +77,6 @@

/**
* Update all IK bones.
* Updates all IK bones by solving the CCD algorithm.
*
* @param {number} [globalBlendFactor=1.0] - Blend factor applied if an IK chain doesn't have its own .blendFactor.
* @return {CCDIKSolver}
* @return {CCDIKSolver} A reference to this instance.
*/

@@ -103,7 +98,7 @@ update( globalBlendFactor = 1.0 ) {

/**
* Update one IK bone
* Updates one IK bone solving the CCD algorithm.
*
* @param {Object} ik parameter
* @param {number} [overrideBlend=1.0] - If the ik object does not define .blendFactor, this value is used.
* @return {CCDIKSolver}
* @param {CCDIKSolver~IK} ik - The IK to update.
* @param {number} [overrideBlend=1.0] - If the IK object does not define `blendFactor`, this value is used.
* @return {CCDIKSolver} A reference to this instance.
*/

@@ -264,6 +259,6 @@ updateOne( ik, overrideBlend = 1.0 ) {

/**
* Creates Helper
* Creates a helper for visualizing the CCDIK.
*
* @param {number} sphereSize
* @return {CCDIKHelper}
* @param {number} sphereSize - The sphere size.
* @return {CCDIKHelper} The created helper.
*/

@@ -331,3 +326,5 @@ createHelper( sphereSize ) {

/**
* Visualize IK bones
* Helper for visualizing IK bones.
*
* @augments Object3D
*/

@@ -337,5 +334,5 @@ class CCDIKHelper extends Object3D {

/**
* @param {SkinnedMesh} mesh
* @param {Array<Object>} [iks=[]]
* @param {number} [sphereSize=0.25]
* @param {SkinnedMesh} mesh - The skinned mesh.
* @param {Array<CCDIKSolver~IK>} [iks=[]] - The IK objects.
* @param {number} [sphereSize=0.25] - The sphere size.
*/

@@ -346,3 +343,14 @@ constructor( mesh, iks = [], sphereSize = 0.25 ) {

/**
* The skinned mesh this helper refers to.
*
* @type {SkinnedMesh}
*/
this.root = mesh;
/**
* The IK objects.
*
* @type {Array<CCDIKSolver~IK>}
*/
this.iks = iks;

@@ -353,4 +361,14 @@

/**
* The helpers sphere geometry.
*
* @type {SkinnedMesh}
*/
this.sphereGeometry = new SphereGeometry( sphereSize, 16, 8 );
/**
* The material for the target spheres.
*
* @type {MeshBasicMaterial}
*/
this.targetSphereMaterial = new MeshBasicMaterial( {

@@ -363,2 +381,7 @@ color: new Color( 0xff8888 ),

/**
* The material for the effector spheres.
*
* @type {MeshBasicMaterial}
*/
this.effectorSphereMaterial = new MeshBasicMaterial( {

@@ -371,2 +394,7 @@ color: new Color( 0x88ff88 ),

/**
* The material for the link spheres.
*
* @type {MeshBasicMaterial}
*/
this.linkSphereMaterial = new MeshBasicMaterial( {

@@ -379,2 +407,7 @@ color: new Color( 0x8888ff ),

/**
* A global line material.
*
* @type {LineBasicMaterial}
*/
this.lineMaterial = new LineBasicMaterial( {

@@ -391,7 +424,2 @@ color: new Color( 0xff0000 ),

/**
* Updates IK bones visualization.
*
* @param {boolean} force
*/
updateMatrixWorld( force ) {

@@ -461,3 +489,4 @@

/**
* Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app.
* Frees the GPU-related resources allocated by this instance.
* Call this method whenever this instance is no longer used in your app.
*/

@@ -547,2 +576,27 @@ dispose() {

/**
* This type represents IK configuration objects.
*
* @typedef {Object} CCDIKSolver~IK
* @property {number} target - The target bone index which refers to a bone in the `Skeleton.bones` array.
* @property {number} effector - The effector bone index which refers to a bone in the `Skeleton.bones` array.
* @property {Array<CCDIKSolver~BoneLink>} links - An array of bone links.
* @property {number} [iteration=1] - Iteration number of calculation. Smaller is faster but less precise.
* @property {number} [minAngle] - Minimum rotation angle in a step in radians.
* @property {number} [maxAngle] - Minimum rotation angle in a step in radians.
* @property {number} [blendFactor] - The blend factor.
**/
/**
* This type represents bone links.
*
* @typedef {Object} CCDIKSolver~BoneLink
* @property {number} index - The index of a linked bone which refers to a bone in the `Skeleton.bones` array.
* @property {number} [limitation] - Rotation axis.
* @property {number} [rotationMin] - Rotation minimum limit.
* @property {number} [rotationMax] - Rotation maximum limit.
* @property {boolean} [enabled=true] - Whether the link is enabled or not.
**/
export { CCDIKSolver, CCDIKHelper };

@@ -0,3 +1,13 @@

/**
* A utility module with basic WebGL 2 capability testing.
*
* @hideconstructor
*/
class WebGL {
/**
* Returns `true` if WebGL 2 is available.
*
* @return {boolean} Whether WebGL 2 is available or not.
*/
static isWebGL2Available() {

@@ -18,2 +28,9 @@

/**
* Returns `true` if the given color space is available. This method can only be used
* if WebGL 2 is supported.
*
* @param {string} colorSpace - The color space to test.
* @return {boolean} Whether the given color space is available or not.
*/
static isColorSpaceAvailable( colorSpace ) {

@@ -36,10 +53,18 @@

/**
* Returns a `div` element representing a formatted error message that can be appended in
* web sites if WebGL 2 isn't supported.
*
* @return {HTMLDivElement} A `div` element representing a formatted error message that WebGL 2 isn't supported.
*/
static getWebGL2ErrorMessage() {
return this.getErrorMessage( 2 );
return this._getErrorMessage( 2 );
}
static getErrorMessage( version ) {
// private
static _getErrorMessage( version ) {
const names = {

@@ -110,3 +135,3 @@ 1: 'WebGL',

return this.getErrorMessage( 1 );
return this._getErrorMessage( 1 );

@@ -113,0 +138,0 @@ }

@@ -9,4 +9,14 @@ let isAvailable = ( typeof navigator !== 'undefined' && navigator.gpu !== undefined );

/**
* A utility module with basic WebGPU capability testing.
*
* @hideconstructor
*/
class WebGPU {
/**
* Returns `true` if WebGPU is available.
*
* @return {boolean} Whether WebGPU is available or not.
*/
static isAvailable() {

@@ -18,8 +28,8 @@

static getStaticAdapter() {
return isAvailable;
}
/**
* Returns a `div` element representing a formatted error message that can be appended in
* web sites if WebGPU isn't supported.
*
* @return {HTMLDivElement} A `div` element representing a formatted error message that WebGPU isn't supported.
*/
static getErrorMessage() {

@@ -26,0 +36,0 @@

@@ -34,4 +34,33 @@ import {

/**
* This class can be used to provide a drag'n'drop interaction.
*
* ```js
* const controls = new DragControls( objects, camera, renderer.domElement );
*
* // add event listener to highlight dragged objects
* controls.addEventListener( 'dragstart', function ( event ) {
*
* event.object.material.emissive.set( 0xaaaaaa );
*
* } );
*
* controls.addEventListener( 'dragend', function ( event ) {
*
* event.object.material.emissive.set( 0x000000 );
*
* } );
* ```
*
* @augments Controls
*/
class DragControls extends Controls {
/**
* Constructs a new controls instance.
*
* @param {Array<Object3D>} objects - An array of draggable 3D objects.
* @param {Camera} camera - The camera of the rendered scene.
* @param {?HTMLDOMElement} [domElement=null] - The HTML DOM element used for event listeners.
*/
constructor( objects, camera, domElement = null ) {

@@ -41,8 +70,40 @@

/**
* An array of draggable 3D objects.
*
* @type {Array<Object3D>}
*/
this.objects = objects;
/**
* Whether children of draggable objects can be dragged independently from their parent.
*
* @type {boolean}
* @default true
*/
this.recursive = true;
/**
* This option only works if the `objects` array contains a single draggable group object.
* If set to `true`, the controls does not transform individual objects but the entire group.
*
* @type {boolean}
* @default false
*/
this.transformGroup = false;
/**
* The speed at which the object will rotate when dragged in `rotate` mode.
* The higher the number the faster the rotation.
*
* @type {number}
* @default 1
*/
this.rotateSpeed = 1;
/**
* The raycaster used for detecting 3D objects.
*
* @type {Raycaster}
*/
this.raycaster = new Raycaster();

@@ -66,3 +127,3 @@

this.connect();
this.connect( domElement );

@@ -73,4 +134,6 @@ }

connect() {
connect( element ) {
super.connect( element );
this.domElement.addEventListener( 'pointermove', this._onPointerMove );

@@ -414,2 +477,30 @@ this.domElement.addEventListener( 'pointerdown', this._onPointerDown );

/**
* Fires when the user drags a 3D object.
*
* @event DragControls#drag
* @type {Object}
*/
/**
* Fires when the user has finished dragging a 3D object.
*
* @event DragControls#dragend
* @type {Object}
*/
/**
* Fires when the pointer is moved onto a 3D object, or onto one of its children.
*
* @event DragControls#hoveron
* @type {Object}
*/
/**
* Fires when the pointer is moved out of a 3D object.
*
* @event DragControls#hoveroff
* @type {Object}
*/
export { DragControls };

@@ -13,4 +13,15 @@ import {

/**
* This class is an alternative implementation of {@link FlyControls}.
*
* @augments Controls
*/
class FirstPersonControls extends Controls {
/**
* Constructs a new controls instance.
*
* @param {Object3D} object - The object that is managed by the controls.
* @param {?HTMLDOMElement} domElement - The HTML element used for event listeners.
*/
constructor( object, domElement = null ) {

@@ -20,21 +31,106 @@

// API
/**
* The movement speed.
*
* @type {number}
* @default 1
*/
this.movementSpeed = 1.0;
this.movementSpeed = 1.0;
/**
* The look around speed.
*
* @type {number}
* @default 0.005
*/
this.lookSpeed = 0.005;
/**
* Whether it's possible to vertically look around or not.
*
* @type {boolean}
* @default true
*/
this.lookVertical = true;
/**
* Whether the camera is automatically moved forward or not.
*
* @type {boolean}
* @default false
*/
this.autoForward = false;
/**
* Whether it's possible to look around or not.
*
* @type {boolean}
* @default true
*/
this.activeLook = true;
/**
* Whether or not the camera's height influences the forward movement speed.
* Use the properties `heightCoef`, `heightMin` and `heightMax` for configuration.
*
* @type {boolean}
* @default false
*/
this.heightSpeed = false;
/**
* Determines how much faster the camera moves when it's y-component is near `heightMax`.
*
* @type {number}
* @default 1
*/
this.heightCoef = 1.0;
/**
* Lower camera height limit used for movement speed adjustment.
*
* @type {number}
* @default 0
*/
this.heightMin = 0.0;
/**
* Upper camera height limit used for movement speed adjustment.
*
* @type {number}
* @default 1
*/
this.heightMax = 1.0;
/**
* Whether or not looking around is vertically constrained by `verticalMin` and `verticalMax`.
*
* @type {boolean}
* @default false
*/
this.constrainVertical = false;
/**
* How far you can vertically look around, lower limit. Range is `0` to `Math.PI` in radians.
*
* @type {number}
* @default 0
*/
this.verticalMin = 0;
/**
* How far you can vertically look around, upper limit. Range is `0` to `Math.PI` in radians.
*
* @type {number}
* @default 0
*/
this.verticalMax = Math.PI;
/**
* Whether the mouse is pressed down or not.
*
* @type {boolean}
* @readonly
* @default false
*/
this.mouseDragOn = false;

@@ -73,3 +169,3 @@

this.connect();
this.connect( domElement );

@@ -84,4 +180,6 @@ this.handleResize();

connect() {
connect( element ) {
super.connect( element );
window.addEventListener( 'keydown', this._onKeyDown );

@@ -115,2 +213,5 @@ window.addEventListener( 'keyup', this._onKeyUp );

/**
* Must be called if the application window is resized.
*/
handleResize() {

@@ -132,2 +233,10 @@

/**
* Rotates the camera towards the defined target position.
*
* @param {number|Vector3} x - The x coordinate of the target position or alternatively a vector representing the target position.
* @param {number} y - The y coordinate of the target position.
* @param {number} z - The z coordinate of the target position.
* @return {FirstPersonControls} A reference to this controls.
*/
lookAt( x, y, z ) {

@@ -134,0 +243,0 @@

@@ -7,2 +7,8 @@ import {

/**
* Fires when the camera has been transformed by the controls.
*
* @event FlyControls#change
* @type {Object}
*/
const _changeEvent = { type: 'change' };

@@ -13,4 +19,17 @@

/**
* This class enables a navigation similar to fly modes in DCC tools like Blender.
* You can arbitrarily transform the camera in 3D space without any limitations
* (e.g. focus on a specific target).
*
* @augments Controls
*/
class FlyControls extends Controls {
/**
* Constructs a new controls instance.
*
* @param {Object3D} object - The object that is managed by the controls.
* @param {?HTMLDOMElement} domElement - The HTML element used for event listeners.
*/
constructor( object, domElement = null ) {

@@ -20,6 +39,32 @@

/**
* The movement speed.
*
* @type {number}
* @default 1
*/
this.movementSpeed = 1.0;
/**
* The rotation speed.
*
* @type {number}
* @default 0.005
*/
this.rollSpeed = 0.005;
/**
* If set to `true`, you can only look around by performing a drag interaction.
*
* @type {boolean}
* @default false
*/
this.dragToLook = false;
/**
* If set to `true`, the camera automatically moves forward (and does not stop) when initially translated.
*
* @type {boolean}
* @default false
*/
this.autoForward = false;

@@ -50,3 +95,3 @@

this.connect();
this.connect( domElement );

@@ -57,4 +102,6 @@ }

connect() {
connect( element ) {
super.connect( element );
window.addEventListener( 'keydown', this._onKeyDown );

@@ -61,0 +108,0 @@ window.addEventListener( 'keyup', this._onKeyUp );

@@ -5,9 +5,13 @@ import { MOUSE, TOUCH } from 'three';

// MapControls performs orbiting, dollying (zooming), and panning.
// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default).
//
// Orbit - right mouse, or left mouse + ctrl/meta/shiftKey / touch: two-finger rotate
// Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish
// Pan - left mouse, or arrow keys / touch: one-finger move
/**
* This class is intended for transforming a camera over a map from bird's eye perspective.
* The class shares its implementation with {@link OrbitControls} but uses a specific preset
* for mouse/touch interaction and disables screen space panning by default.
*
* - Orbit: Right mouse, or left mouse + ctrl/meta/shiftKey / touch: two-finger rotate.
* - Zoom: Middle mouse, or mousewheel / touch: two-finger spread or squish.
* - Pan: Left mouse, or arrow keys / touch: one-finger move.
*
* @augments OrbitControls
*/
class MapControls extends OrbitControls {

@@ -19,6 +23,35 @@

this.screenSpacePanning = false; // pan orthogonal to world-space direction camera.up
/**
* Overwritten and set to `false` to pan orthogonal to world-space direction `camera.up`.
*
* @type {boolean}
* @default false
*/
this.screenSpacePanning = false;
/**
* This object contains references to the mouse actions used by the controls.
*
* ```js
* controls.mouseButtons = {
* LEFT: THREE.MOUSE.PAN,
* MIDDLE: THREE.MOUSE.DOLLY,
* RIGHT: THREE.MOUSE.ROTATE
* }
* ```
* @type {Object}
*/
this.mouseButtons = { LEFT: MOUSE.PAN, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.ROTATE };
/**
* This object contains references to the touch actions used by the controls.
*
* ```js
* controls.mouseButtons = {
* ONE: THREE.TOUCH.PAN,
* TWO: THREE.TOUCH.DOLLY_ROTATE
* }
* ```
* @type {Object}
*/
this.touches = { ONE: TOUCH.PAN, TWO: TOUCH.DOLLY_ROTATE };

@@ -25,0 +58,0 @@

@@ -14,12 +14,26 @@ import {

// OrbitControls performs orbiting, dollying (zooming), and panning.
// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default).
//
// Orbit - left mouse / touch: one-finger move
// Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish
// Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move
/**
* Fires when the camera has been transformed by the controls.
*
* @event OrbitControls#change
* @type {Object}
*/
const _changeEvent = { type: 'change' };
const _changeEvent = { type: 'change' };
/**
* Fires when an interaction was initiated.
*
* @event OrbitControls#start
* @type {Object}
*/
const _startEvent = { type: 'start' };
/**
* Fires when an interaction has finished.
*
* @event OrbitControls#end
* @type {Object}
*/
const _endEvent = { type: 'end' };
const _ray = new Ray();

@@ -44,4 +58,40 @@ const _plane = new Plane();

/**
* Orbit controls allow the camera to orbit around a target.
*
* OrbitControls performs orbiting, dollying (zooming), and panning. Unlike {@link TrackballControls},
* it maintains the "up" direction `object.up` (+Y by default).
*
* - Orbit: Left mouse / touch: one-finger move.
* - Zoom: Middle mouse, or mousewheel / touch: two-finger spread or squish.
* - Pan: Right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move.
*
* ```js
* const controls = new OrbitControls( camera, renderer.domElement );
*
* // controls.update() must be called after any manual changes to the camera's transform
* camera.position.set( 0, 20, 100 );
* controls.update();
*
* function animate() {
*
* // required if controls.enableDamping or controls.autoRotate are set to true
* controls.update();
*
* renderer.render( scene, camera );
*
* }
* ```
*
* @augments Controls
*/
class OrbitControls extends Controls {
/**
* Constructs a new controls instance.
*
* @param {Object3D} object - The object that is managed by the controls.
* @param {?HTMLDOMElement} domElement - The HTML element used for event listeners.
*/
constructor( object, domElement = null ) {

@@ -53,72 +103,292 @@

// Set to false to disable this control
this.enabled = true;
// "target" sets the location of focus, where the object orbits around
/**
* The focus point of the controls, the `object` orbits around this.
* It can be updated manually at any point to change the focus of the controls.
*
* @type {Vector3}
*/
this.target = new Vector3();
// Sets the 3D cursor (similar to Blender), from which the maxTargetRadius takes effect
/**
* The focus point of the `minTargetRadius` and `maxTargetRadius` limits.
* It can be updated manually at any point to change the center of interest
* for the `target`.
*
* @type {Vector3}
*/
this.cursor = new Vector3();
// How far you can dolly in and out ( PerspectiveCamera only )
/**
* How far you can dolly in (perspective camera only).
*
* @type {number}
* @default 0
*/
this.minDistance = 0;
/**
* How far you can dolly out (perspective camera only).
*
* @type {number}
* @default Infinity
*/
this.maxDistance = Infinity;
// How far you can zoom in and out ( OrthographicCamera only )
/**
* How far you can zoom in (orthographic camera only).
*
* @type {number}
* @default 0
*/
this.minZoom = 0;
/**
* How far you can zoom out (orthographic camera only).
*
* @type {number}
* @default Infinity
*/
this.maxZoom = Infinity;
// Limit camera target within a spherical area around the cursor
/**
* How close you can get the target to the 3D `cursor`.
*
* @type {number}
* @default 0
*/
this.minTargetRadius = 0;
/**
* How far you can move the target from the 3D `cursor`.
*
* @type {number}
* @default Infinity
*/
this.maxTargetRadius = Infinity;
// How far you can orbit vertically, upper and lower limits.
// Range is 0 to Math.PI radians.
this.minPolarAngle = 0; // radians
this.maxPolarAngle = Math.PI; // radians
/**
* How far you can orbit vertically, lower limit. Range is `[0, Math.PI]` radians.
*
* @type {number}
* @default 0
*/
this.minPolarAngle = 0;
// How far you can orbit horizontally, upper and lower limits.
// If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI )
this.minAzimuthAngle = - Infinity; // radians
this.maxAzimuthAngle = Infinity; // radians
/**
* How far you can orbit vertically, upper limit. Range is `[0, Math.PI]` radians.
*
* @type {number}
* @default Math.PI
*/
this.maxPolarAngle = Math.PI;
// Set to true to enable damping (inertia)
// If damping is enabled, you must call controls.update() in your animation loop
/**
* How far you can orbit horizontally, lower limit. If set, the interval `[ min, max ]`
* must be a sub-interval of `[ - 2 PI, 2 PI ]`, with `( max - min < 2 PI )`.
*
* @type {number}
* @default -Infinity
*/
this.minAzimuthAngle = - Infinity;
/**
* How far you can orbit horizontally, upper limit. If set, the interval `[ min, max ]`
* must be a sub-interval of `[ - 2 PI, 2 PI ]`, with `( max - min < 2 PI )`.
*
* @type {number}
* @default -Infinity
*/
this.maxAzimuthAngle = Infinity;
/**
* Set to `true` to enable damping (inertia), which can be used to give a sense of weight
* to the controls. Note that if this is enabled, you must call `update()` in your animation
* loop.
*
* @type {boolean}
* @default false
*/
this.enableDamping = false;
/**
* The damping inertia used if `enableDamping` is set to `true`.
*
* Note that for this to work, you must call `update()` in your animation loop.
*
* @type {number}
* @default 0.05
*/
this.dampingFactor = 0.05;
// This option actually enables dollying in and out; left as "zoom" for backwards compatibility.
// Set to false to disable zooming
/**
* Enable or disable zooming (dollying) of the camera.
*
* @type {boolean}
* @default true
*/
this.enableZoom = true;
/**
* Speed of zooming / dollying.
*
* @type {number}
* @default 1
*/
this.zoomSpeed = 1.0;
// Set to false to disable rotating
/**
* Enable or disable horizontal and vertical rotation of the camera.
*
* Note that it is possible to disable a single axis by setting the min and max of the
* `minPolarAngle` or `minAzimuthAngle` to the same value, which will cause the vertical
* or horizontal rotation to be fixed at that value.
*
* @type {boolean}
* @default true
*/
this.enableRotate = true;
/**
* Speed of rotation.
*
* @type {number}
* @default 1
*/
this.rotateSpeed = 1.0;
/**
* How fast to rotate the camera when the keyboard is used.
*
* @type {number}
* @default 1
*/
this.keyRotateSpeed = 1.0;
// Set to false to disable panning
/**
* Enable or disable camera panning.
*
* @type {boolean}
* @default true
*/
this.enablePan = true;
/**
* Speed of panning.
*
* @type {number}
* @default 1
*/
this.panSpeed = 1.0;
this.screenSpacePanning = true; // if false, pan orthogonal to world-space direction camera.up
this.keyPanSpeed = 7.0; // pixels moved per arrow key push
/**
* Defines how the camera's position is translated when panning. If `true`, the camera pans
* in screen space. Otherwise, the camera pans in the plane orthogonal to the camera's up
* direction.
*
* @type {boolean}
* @default true
*/
this.screenSpacePanning = true;
/**
* How fast to pan the camera when the keyboard is used in
* pixels per keypress.
*
* @type {number}
* @default 7
*/
this.keyPanSpeed = 7.0;
/**
* Setting this property to `true` allows to zoom to the cursor's position.
*
* @type {boolean}
* @default false
*/
this.zoomToCursor = false;
// Set to true to automatically rotate around the target
// If auto-rotate is enabled, you must call controls.update() in your animation loop
/**
* Set to true to automatically rotate around the target
*
* Note that if this is enabled, you must call `update()` in your animation loop.
* If you want the auto-rotate speed to be independent of the frame rate (the refresh
* rate of the display), you must pass the time `deltaTime`, in seconds, to `update()`.
*
* @type {boolean}
* @default false
*/
this.autoRotate = false;
this.autoRotateSpeed = 2.0; // 30 seconds per orbit when fps is 60
// The four arrow keys
/**
* How fast to rotate around the target if `autoRotate` is `true`. The default equates to 30 seconds
* per orbit at 60fps.
*
* Note that if `autoRotate` is enabled, you must call `update()` in your animation loop.
*
* @type {number}
* @default 2
*/
this.autoRotateSpeed = 2.0;
/**
* This object contains references to the keycodes for controlling camera panning.
*
* ```js
* controls.keys = {
* LEFT: 'ArrowLeft', //left arrow
* UP: 'ArrowUp', // up arrow
* RIGHT: 'ArrowRight', // right arrow
* BOTTOM: 'ArrowDown' // down arrow
* }
* ```
* @type {Object}
*/
this.keys = { LEFT: 'ArrowLeft', UP: 'ArrowUp', RIGHT: 'ArrowRight', BOTTOM: 'ArrowDown' };
// Mouse buttons
/**
* This object contains references to the mouse actions used by the controls.
*
* ```js
* controls.mouseButtons = {
* LEFT: THREE.MOUSE.ROTATE,
* MIDDLE: THREE.MOUSE.DOLLY,
* RIGHT: THREE.MOUSE.PAN
* }
* ```
* @type {Object}
*/
this.mouseButtons = { LEFT: MOUSE.ROTATE, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.PAN };
// Touch fingers
/**
* This object contains references to the touch actions used by the controls.
*
* ```js
* controls.mouseButtons = {
* ONE: THREE.TOUCH.ROTATE,
* TWO: THREE.TOUCH.DOLLY_PAN
* }
* ```
* @type {Object}
*/
this.touches = { ONE: TOUCH.ROTATE, TWO: TOUCH.DOLLY_PAN };
// for reset
/**
* Used internally by `saveState()` and `reset()`.
*
* @type {Vector3}
*/
this.target0 = this.target.clone();
/**
* Used internally by `saveState()` and `reset()`.
*
* @type {Vector3}
*/
this.position0 = this.object.position.clone();
/**
* Used internally by `saveState()` and `reset()`.
*
* @type {number}
*/
this.zoom0 = this.object.zoom;

@@ -189,3 +459,3 @@

this.connect();
this.connect( this.domElement );

@@ -198,4 +468,6 @@ }

connect() {
connect( element ) {
super.connect( element );
this.domElement.addEventListener( 'pointerdown', this._onPointerDown );

@@ -239,2 +511,7 @@ this.domElement.addEventListener( 'pointercancel', this._onPointerUp );

/**
* Get the current vertical rotation, in radians.
*
* @return {number} The current vertical rotation, in radians.
*/
getPolarAngle() {

@@ -246,2 +523,7 @@

/**
* Get the current horizontal rotation, in radians.
*
* @return {number} The current horizontal rotation, in radians.
*/
getAzimuthalAngle() {

@@ -253,2 +535,7 @@

/**
* Returns the distance from the camera to the target.
*
* @return {number} The distance from the camera to the target.
*/
getDistance() {

@@ -260,2 +547,8 @@

/**
* Adds key event listeners to the given DOM element.
* `window` is a recommended argument for using this method.
*
* @param {HTMLDOMElement} domElement - The DOM element
*/
listenToKeyEvents( domElement ) {

@@ -268,2 +561,5 @@

/**
* Removes the key event listener previously defined with `listenToKeyEvents()`.
*/
stopListenToKeyEvents() {

@@ -280,2 +576,5 @@

/**
* Save the current state of the controls. This can later be recovered with `reset()`.
*/
saveState() {

@@ -289,2 +588,6 @@

/**
* Reset the controls to their state from either the last time the `saveState()`
* was called, or the initial state.
*/
reset() {

@@ -291,0 +594,0 @@

@@ -10,4 +10,24 @@ import {

/**
* Fires when the user moves the mouse.
*
* @event PointerLockControls#change
* @type {Object}
*/
const _changeEvent = { type: 'change' };
/**
* Fires when the pointer lock status is "locked" (in other words: the mouse is captured).
*
* @event PointerLockControls#lock
* @type {Object}
*/
const _lockEvent = { type: 'lock' };
/**
* Fires when the pointer lock status is "unlocked" (in other words: the mouse is not captured anymore).
*
* @event PointerLockControls#unlock
* @type {Object}
*/
const _unlockEvent = { type: 'unlock' };

@@ -17,4 +37,33 @@

/**
* The implementation of this class is based on the [Pointer Lock API]{@link https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API}.
* `PointerLockControls` is a perfect choice for first person 3D games.
*
* ```js
* const controls = new PointerLockControls( camera, document.body );
*
* // add event listener to show/hide a UI (e.g. the game's menu)
* controls.addEventListener( 'lock', function () {
*
* menu.style.display = 'none';
*
* } );
*
* controls.addEventListener( 'unlock', function () {
*
* menu.style.display = 'block';
*
* } );
* ```
*
* @augments Controls
*/
class PointerLockControls extends Controls {
/**
* Constructs a new controls instance.
*
* @param {Camera} camera - The camera that is managed by the controls.
* @param {?HTMLDOMElement} domElement - The HTML element used for event listeners.
*/
constructor( camera, domElement = null ) {

@@ -24,9 +73,33 @@

/**
* Whether the controls are locked or not.
*
* @type {boolean}
* @readonly
* @default false
*/
this.isLocked = false;
// Set to constrain the pitch of the camera
// Range is 0 to Math.PI radians
this.minPolarAngle = 0; // radians
this.maxPolarAngle = Math.PI; // radians
/**
* Camera pitch, lower limit. Range is '[0, Math.PI]' in radians.
*
* @type {number}
* @default 0
*/
this.minPolarAngle = 0;
/**
* Camera pitch, upper limit. Range is '[0, Math.PI]' in radians.
*
* @type {number}
* @default Math.PI
*/
this.maxPolarAngle = Math.PI;
/**
* Multiplier for how much the pointer movement influences the camera rotation.
*
* @type {number}
* @default 1
*/
this.pointerSpeed = 1.0;

@@ -42,3 +115,3 @@

this.connect();
this.connect( this.domElement );

@@ -49,4 +122,6 @@ }

connect() {
connect( element ) {
super.connect( element );
this.domElement.ownerDocument.addEventListener( 'mousemove', this._onMouseMove );

@@ -80,2 +155,8 @@ this.domElement.ownerDocument.addEventListener( 'pointerlockchange', this._onPointerlockChange );

/**
* Returns the look direction of the camera.
*
* @param {Vector3} v - The target vector that is used to store the method's result.
* @return {Vector3} The normalized direction vector.
*/
getDirection( v ) {

@@ -87,2 +168,7 @@

/**
* Moves the camera forward parallel to the xz-plane. Assumes camera.up is y-up.
*
* @param {number} distance - The signed distance.
*/
moveForward( distance ) {

@@ -105,2 +191,7 @@

/**
* Moves the camera sidewards parallel to the xz-plane.
*
* @param {number} distance - The signed distance.
*/
moveRight( distance ) {

@@ -118,8 +209,19 @@

lock() {
/**
* Activates the pointer lock.
*
* @param {boolean} [unadjustedMovement=false] - Disables OS-level adjustment for mouse acceleration, and accesses raw mouse input instead.
* Setting it to true will disable mouse acceleration.
*/
lock( unadjustedMovement = false ) {
this.domElement.requestPointerLock();
this.domElement.requestPointerLock( {
unadjustedMovement
} );
}
/**
* Exits the pointer lock.
*/
unlock() {

@@ -126,0 +228,0 @@

@@ -10,4 +10,24 @@ import {

/**
* Fires when the camera has been transformed by the controls.
*
* @event TrackballControls#change
* @type {Object}
*/
const _changeEvent = { type: 'change' };
/**
* Fires when an interaction was initiated.
*
* @event TrackballControls#start
* @type {Object}
*/
const _startEvent = { type: 'start' };
/**
* Fires when an interaction has finished.
*
* @event TrackballControls#end
* @type {Object}
*/
const _endEvent = { type: 'end' };

@@ -29,4 +49,17 @@

/**
* This class is similar to {@link OrbitControls}. However, it does not maintain a constant camera
* `up` vector. That means if the camera orbits over the “north” and “south” poles, it does not flip
* to stay "right side up".
*
* @augments Controls
*/
class TrackballControls extends Controls {
/**
* Constructs a new controls instance.
*
* @param {Object3D} object - The object that is managed by the controls.
* @param {?HTMLDOMElement} domElement - The HTML element used for event listeners.
*/
constructor( object, domElement = null ) {

@@ -36,31 +69,138 @@

// API
this.enabled = true;
/**
* Represents the properties of the screen. Automatically set when `handleResize()` is called.
*
* @type {Object}
* @readonly
*/
this.screen = { left: 0, top: 0, width: 0, height: 0 };
/**
* The rotation speed.
*
* @type {number}
* @default 1
*/
this.rotateSpeed = 1.0;
/**
* The zoom speed.
*
* @type {number}
* @default 1.2
*/
this.zoomSpeed = 1.2;
/**
* The pan speed.
*
* @type {number}
* @default 0.3
*/
this.panSpeed = 0.3;
/**
* Whether rotation is disabled or not.
*
* @type {boolean}
* @default false
*/
this.noRotate = false;
/**
* Whether zooming is disabled or not.
*
* @type {boolean}
* @default false
*/
this.noZoom = false;
/**
* Whether panning is disabled or not.
*
* @type {boolean}
* @default false
*/
this.noPan = false;
/**
* Whether damping is disabled or not.
*
* @type {boolean}
* @default false
*/
this.staticMoving = false;
/**
* Defines the intensity of damping. Only considered if `staticMoving` is set to `false`.
*
* @type {number}
* @default 0.2
*/
this.dynamicDampingFactor = 0.2;
/**
* How far you can dolly in (perspective camera only).
*
* @type {number}
* @default 0
*/
this.minDistance = 0;
/**
* How far you can dolly out (perspective camera only).
*
* @type {number}
* @default Infinity
*/
this.maxDistance = Infinity;
/**
* How far you can zoom in (orthographic camera only).
*
* @type {number}
* @default 0
*/
this.minZoom = 0;
/**
* How far you can zoom out (orthographic camera only).
*
* @type {number}
* @default Infinity
*/
this.maxZoom = Infinity;
/**
* This array holds keycodes for controlling interactions.
*
* - When the first defined key is pressed, all mouse interactions (left, middle, right) performs orbiting.
* - When the second defined key is pressed, all mouse interactions (left, middle, right) performs zooming.
* - When the third defined key is pressed, all mouse interactions (left, middle, right) performs panning.
*
* Default is *KeyA, KeyS, KeyD* which represents A, S, D.
*
* @type {Array<string>}
*/
this.keys = [ 'KeyA' /*A*/, 'KeyS' /*S*/, 'KeyD' /*D*/ ];
/**
* This object contains references to the mouse actions used by the controls.
*
* ```js
* controls.mouseButtons = {
* LEFT: THREE.MOUSE.ROTATE,
* MIDDLE: THREE.MOUSE.DOLLY,
* RIGHT: THREE.MOUSE.PAN
* }
* ```
* @type {Object}
*/
this.mouseButtons = { LEFT: MOUSE.ROTATE, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.PAN };
this.state = _STATE.NONE;
this.keyState = _STATE.NONE;
/**
* The focus point of the controls.
*
* @type {Vector3}
*/
this.target = new Vector3();

@@ -70,2 +210,5 @@

this.state = _STATE.NONE;
this.keyState = _STATE.NONE;
this._lastPosition = new Vector3();

@@ -121,3 +264,3 @@ this._lastZoom = 1;

this.connect();
this.connect( domElement );

@@ -133,4 +276,6 @@ this.handleResize();

connect() {
connect( element ) {
super.connect( element );
window.addEventListener( 'keydown', this._onKeyDown );

@@ -170,2 +315,5 @@ window.addEventListener( 'keyup', this._onKeyUp );

/**
* Must be called if the application window is resized.
*/
handleResize() {

@@ -243,2 +391,5 @@

/**
* Resets the controls to its initial state.
*/
reset() {

@@ -245,0 +396,0 @@

@@ -35,9 +35,51 @@ import {

/**
* Fires if any type of change (object or property change) is performed. Property changes
* are separate events you can add event listeners to. The event type is "propertyname-changed".
*
* @event TransformControls#change
* @type {Object}
*/
const _changeEvent = { type: 'change' };
/**
* Fires if a pointer (mouse/touch) becomes active.
*
* @event TransformControls#mouseDown
* @type {Object}
*/
const _mouseDownEvent = { type: 'mouseDown', mode: null };
/**
* Fires if a pointer (mouse/touch) is no longer active.
*
* @event TransformControls#mouseUp
* @type {Object}
*/
const _mouseUpEvent = { type: 'mouseUp', mode: null };
/**
* Fires if the controlled 3D object is changed.
*
* @event TransformControls#objectChange
* @type {Object}
*/
const _objectChangeEvent = { type: 'objectChange' };
/**
* This class can be used to transform objects in 3D space by adapting a similar interaction model
* of DCC tools like Blender. Unlike other controls, it is not intended to transform the scene's camera.
*
* `TransformControls` expects that its attached 3D object is part of the scene graph.
*
* @augments Controls
*/
class TransformControls extends Controls {
/**
* Constructs a new controls instance.
*
* @param {Camera} camera - The camera of the rendered scene.
* @param {?HTMLDOMElement} domElement - The HTML element used for event listeners.
*/
constructor( camera, domElement = null ) {

@@ -100,21 +142,166 @@

/**
* The camera of the rendered scene.
*
* @name TransformControls#camera
* @type {Camera}
*/
defineProperty( 'camera', camera );
defineProperty( 'object', undefined );
defineProperty( 'enabled', true );
/**
* The current transformation axis.
*
* @name TransformControls#axis
* @type {string}
*/
defineProperty( 'axis', null );
/**
* The current transformation axis.
*
* @name TransformControls#mode
* @type {('translate'|'rotate'|'scale')}
* @default 'translate'
*/
defineProperty( 'mode', 'translate' );
/**
* By default, 3D objects are continuously translated. If you set this property to a numeric
* value (world units), you can define in which steps the 3D object should be translated.
*
* @name TransformControls#translationSnap
* @type {?number}
* @default null
*/
defineProperty( 'translationSnap', null );
/**
* By default, 3D objects are continuously rotated. If you set this property to a numeric
* value (radians), you can define in which steps the 3D object should be rotated.
*
* @name TransformControls#rotationSnap
* @type {?number}
* @default null
*/
defineProperty( 'rotationSnap', null );
/**
* By default, 3D objects are continuously scaled. If you set this property to a numeric
* value, you can define in which steps the 3D object should be scaled.
*
* @name TransformControls#scaleSnap
* @type {?number}
* @default null
*/
defineProperty( 'scaleSnap', null );
/**
* Defines in which coordinate space transformations should be performed.
*
* @name TransformControls#space
* @type {('world'|'local')}
* @default 'world'
*/
defineProperty( 'space', 'world' );
/**
* The size of the helper UI (axes/planes).
*
* @name TransformControls#size
* @type {number}
* @default 1
*/
defineProperty( 'size', 1 );
/**
* Whether dragging is currently performed or not.
*
* @name TransformControls#dragging
* @type {boolean}
* @readonly
* @default false
*/
defineProperty( 'dragging', false );
/**
* Whether the x-axis helper should be visible or not.
*
* @name TransformControls#showX
* @type {boolean}
* @default true
*/
defineProperty( 'showX', true );
/**
* Whether the y-axis helper should be visible or not.
*
* @name TransformControls#showY
* @type {boolean}
* @default true
*/
defineProperty( 'showY', true );
/**
* Whether the z-axis helper should be visible or not.
*
* @name TransformControls#showZ
* @type {boolean}
* @default true
*/
defineProperty( 'showZ', true );
/**
* The minimum allowed X position during translation.
*
* @name TransformControls#minX
* @type {number}
* @default -Infinity
*/
defineProperty( 'minX', - Infinity );
/**
* The maximum allowed X position during translation.
*
* @name TransformControls#maxX
* @type {number}
* @default Infinity
*/
defineProperty( 'maxX', Infinity );
/**
* The minimum allowed y position during translation.
*
* @name TransformControls#minY
* @type {number}
* @default -Infinity
*/
defineProperty( 'minY', - Infinity );
/**
* The maximum allowed Y position during translation.
*
* @name TransformControls#maxY
* @type {number}
* @default Infinity
*/
defineProperty( 'maxY', Infinity );
/**
* The minimum allowed z position during translation.
*
* @name TransformControls#minZ
* @type {number}
* @default -Infinity
*/
defineProperty( 'minZ', - Infinity );
/**
* The maximum allowed Z position during translation.
*
* @name TransformControls#maxZ
* @type {number}
* @default Infinity
*/
defineProperty( 'maxZ', Infinity );

@@ -176,3 +363,3 @@

this.connect();
this.connect( domElement );

@@ -183,4 +370,6 @@ }

connect() {
connect( element ) {
super.connect( element );
this.domElement.addEventListener( 'pointerdown', this._onPointerDown );

@@ -205,2 +394,8 @@ this.domElement.addEventListener( 'pointermove', this._onPointerHover );

/**
* Returns the visual representation of the controls. Add the helper to your scene to
* visually transform the attached 3D object.
*
* @return {TransformControlsRoot} The helper.
*/
getHelper() {

@@ -558,3 +753,8 @@

// Set current object
/**
* Sets the 3D object that should be transformed and ensures the controls UI is visible.
*
* @param {Object3D} object - The 3D object that should be transformed.
* @return {TransformControls} A reference to this controls.
*/
attach( object ) {

@@ -569,3 +769,7 @@

// Detach from object
/**
* Removes the current 3D object from the controls and makes the helper UI invisible.
*
* @return {TransformControls} A reference to this controls.
*/
detach() {

@@ -582,2 +786,5 @@

/**
* Resets the object's position, rotation and scale to when the current transform began.
*/
reset() {

@@ -602,2 +809,8 @@

/**
* Returns the raycaster that is used for user interaction. This object is shared between all
* instances of `TransformControls`.
*
* @returns {Raycaster} The internal raycaster.
*/
getRaycaster() {

@@ -609,4 +822,7 @@

// TODO: deprecate
/**
* Returns the transformation mode.
*
* @returns {'translate'|'rotate'|'scale'} The transformation mode.
*/
getMode() {

@@ -618,2 +834,7 @@

/**
* Sets the given transformation mode.
*
* @param {'translate'|'rotate'|'scale'} mode - The transformation mode to set.
*/
setMode( mode ) {

@@ -625,2 +846,7 @@

/**
* Sets the translation snap.
*
* @param {?number} translationSnap - The translation snap to set.
*/
setTranslationSnap( translationSnap ) {

@@ -632,2 +858,7 @@

/**
* Sets the rotation snap.
*
* @param {?number} rotationSnap - The rotation snap to set.
*/
setRotationSnap( rotationSnap ) {

@@ -639,2 +870,7 @@

/**
* Sets the scale snap.
*
* @param {?number} scaleSnap - The scale snap to set.
*/
setScaleSnap( scaleSnap ) {

@@ -646,2 +882,7 @@

/**
* Sets the size of the helper UI.
*
* @param {number} size - The size to set.
*/
setSize( size ) {

@@ -653,2 +894,7 @@

/**
* Sets the coordinate space in which transformations are applied.
*
* @param {'world'|'local'} space - The space to set.
*/
setSpace( space ) {

@@ -655,0 +901,0 @@

@@ -23,34 +23,175 @@ import {

/**
* An implementation of Cascade Shadow Maps (CSM).
*
* This module can only be used with {@link WebGLRenderer}. When using {@link WebGPURenderer},
* use {@link CSMShadowNode} instead.
*/
export class CSM {
/**
* Constructs a new CSM instance.
*
* @param {CSM~Data} data - The CSM data.
*/
constructor( data ) {
/**
* The scene's camera.
*
* @type {Camera}
*/
this.camera = data.camera;
/**
* The parent object, usually the scene.
*
* @type {Object3D}
*/
this.parent = data.parent;
/**
* The number of cascades.
*
* @type {number}
* @default 3
*/
this.cascades = data.cascades || 3;
/**
* The maximum far value.
*
* @type {number}
* @default 100000
*/
this.maxFar = data.maxFar || 100000;
/**
* The frustum split mode.
*
* @type {('practical'|'uniform'|'logarithmic'|'custom')}
* @default 'practical'
*/
this.mode = data.mode || 'practical';
/**
* The shadow map size.
*
* @type {number}
* @default 2048
*/
this.shadowMapSize = data.shadowMapSize || 2048;
/**
* The shadow bias.
*
* @type {number}
* @default 0.000001
*/
this.shadowBias = data.shadowBias || 0.000001;
/**
* The light direction.
*
* @type {Vector3}
*/
this.lightDirection = data.lightDirection || new Vector3( 1, - 1, 1 ).normalize();
/**
* The light intensity.
*
* @type {number}
* @default 3
*/
this.lightIntensity = data.lightIntensity || 3;
/**
* The light near value.
*
* @type {number}
* @default 1
*/
this.lightNear = data.lightNear || 1;
/**
* The light far value.
*
* @type {number}
* @default 2000
*/
this.lightFar = data.lightFar || 2000;
/**
* The light margin.
*
* @type {number}
* @default 200
*/
this.lightMargin = data.lightMargin || 200;
/**
* Custom split callback when using `mode='custom'`.
*
* @type {Function}
*/
this.customSplitsCallback = data.customSplitsCallback;
/**
* Whether to fade between cascades or not.
*
* @type {boolean}
* @default false
*/
this.fade = false;
/**
* The main frustum.
*
* @type {CSMFrustum}
*/
this.mainFrustum = new CSMFrustum( { webGL: true } );
/**
* An array of frustums representing the cascades.
*
* @type {Array<CSMFrustum>}
*/
this.frustums = [];
/**
* An array of numbers in the range `[0,1]` the defines how the
* mainCSM frustum should be split up.
*
* @type {Array<number>}
*/
this.breaks = [];
/**
* An array of directional lights which cast the shadows for
* the different cascades. There is one directional light for each
* cascade.
*
* @type {Array<DirectionalLight>}
*/
this.lights = [];
/**
* A Map holding enhanced material shaders.
*
* @type {Map<Material,Object>}
*/
this.shaders = new Map();
this.createLights();
this._createLights();
this.updateFrustums();
this.injectInclude();
this._injectInclude();
}
createLights() {
/**
* Creates the directional lights of this CSM instance.
*
* @private
*/
_createLights() {

@@ -76,3 +217,8 @@ for ( let i = 0; i < this.cascades; i ++ ) {

initCascades() {
/**
* Inits the cascades according to the scene's camera and breaks configuration.
*
* @private
*/
_initCascades() {

@@ -86,3 +232,8 @@ const camera = this.camera;

updateShadowBounds() {
/**
* Updates the shadow bounds of this CSM instance.
*
* @private
*/
_updateShadowBounds() {

@@ -136,3 +287,9 @@ const frustums = this.frustums;

getBreaks() {
/**
* Computes the breaks of this CSM instance based on the scene's camera, number of cascades
* and the selected split mode.
*
* @private
*/
_getBreaks() {

@@ -204,2 +361,6 @@ const camera = this.camera;

/**
* Updates the CSM. This method must be called in your animation loop before
* calling `renderer.render()`.
*/
update() {

@@ -251,3 +412,8 @@

injectInclude() {
/**
* Injects the CSM shader enhancements into the built-in materials.
*
* @private
*/
_injectInclude() {

@@ -259,2 +425,7 @@ ShaderChunk.lights_fragment_begin = CSMShader.lights_fragment_begin;

/**
* Applications must call this method for all materials that should be affected by CSM.
*
* @param {Material} material - The material to setup for CSM support.
*/
setupMaterial( material ) {

@@ -279,3 +450,3 @@

const far = Math.min( scope.camera.far, scope.maxFar );
scope.getExtendedBreaks( breaksVec2 );
scope._getExtendedBreaks( breaksVec2 );

@@ -294,3 +465,8 @@ shader.uniforms.CSM_cascades = { value: breaksVec2 };

updateUniforms() {
/**
* Updates the CSM uniforms.
*
* @private
*/
_updateUniforms() {

@@ -305,3 +481,3 @@ const far = Math.min( this.camera.far, this.maxFar );

const uniforms = shader.uniforms;
this.getExtendedBreaks( uniforms.CSM_cascades.value );
this._getExtendedBreaks( uniforms.CSM_cascades.value );
uniforms.cameraNear.value = this.camera.near;

@@ -328,3 +504,9 @@ uniforms.shadowFar.value = far;

getExtendedBreaks( target ) {
/**
* Computes the extended breaks for the CSM uniforms.
*
* @private
* @param {Array<Vector2>} target - The target array that holds the extended breaks.
*/
_getExtendedBreaks( target ) {

@@ -350,11 +532,17 @@ while ( target.length < this.breaks.length ) {

/**
* Applications must call this method every time they change camera or CSM settings.
*/
updateFrustums() {
this.getBreaks();
this.initCascades();
this.updateShadowBounds();
this.updateUniforms();
this._getBreaks();
this._initCascades();
this._updateShadowBounds();
this._updateUniforms();
}
/**
* Applications must call this method when they remove the CSM usage from their scene.
*/
remove() {

@@ -371,2 +559,6 @@

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*/
dispose() {

@@ -398,1 +590,20 @@

}
/**
* Constructor data of `CSM`.
*
* @typedef {Object} CSM~Data
* @property {Camera} camera - The scene's camera.
* @property {Object3D} parent - The parent object, usually the scene.
* @property {number} [cascades=3] - The number of cascades.
* @property {number} [maxFar=100000] - The maximum far value.
* @property {('practical'|'uniform'|'logarithmic'|'custom')} [mode='practical'] - The frustum split mode.
* @property {Function} [customSplitsCallback] - Custom split callback when using `mode='custom'`.
* @property {number} [shadowMapSize=2048] - The shadow map size.
* @property {number} [shadowBias=0.000001] - The shadow bias.
* @property {Vector3} [lightDirection] - The light direction.
* @property {number} [lightIntensity=3] - The light intensity.
* @property {number} [lightNear=1] - The light near value.
* @property {number} [lightNear=2000] - The light far value.
* @property {number} [lightMargin=200] - The light margin.
**/

@@ -5,4 +5,12 @@ import { Vector3, Matrix4 } from 'three';

/**
* Represents the frustum of a CSM instance.
*/
class CSMFrustum {
/**
* Constructs a new CSM frustum.
*
* @param {CSMFrustum~Data} [data] - The CSM data.
*/
constructor( data ) {

@@ -12,4 +20,17 @@

/**
* The zNear value. This value depends on whether the CSM
* is used with WebGL or WebGPU. Both API use different
* conventions for their projection matrices.
*
* @type {number}
*/
this.zNear = data.webGL === true ? - 1 : 0;
/**
* An object representing the vertices of the near and
* far plane in view space.
*
* @type {Object}
*/
this.vertices = {

@@ -38,2 +59,9 @@ near: [

/**
* Setups this CSM frustum from the given projection matrix and max far value.
*
* @param {Matrix4} projectionMatrix - The projection matrix, usually of the scene's camera.
* @param {number} maxFar - The maximum far value.
* @returns {Object} An object representing the vertices of the near and far plane in view space.
*/
setFromProjectionMatrix( projectionMatrix, maxFar ) {

@@ -86,2 +114,10 @@

/**
* Splits the CSM frustum by the given array. The new CSM frustum are pushed into the given
* target array.
*
* @param {Array<number>} breaks - An array of numbers in the range `[0,1]` the defines how the
* CSM frustum should be split up.
* @param {Array<CSMFrustum>} target - The target array that holds the new CSM frustums.
*/
split( breaks, target ) {

@@ -141,2 +177,9 @@

/**
* Transforms the given target CSM frustum into the different coordinate system defined by the
* given camera matrix.
*
* @param {Matrix4} cameraMatrix - The matrix that defines the new coordinate system.
* @param {CSMFrustum} target - The CSM to convert.
*/
toSpace( cameraMatrix, target ) {

@@ -160,2 +203,11 @@

/**
* Constructor data of `CSMFrustum`.
*
* @typedef {Object} CSMFrustum~Data
* @property {boolean} [webGL] - Whether this CSM frustum is used with WebGL or WebGPU.
* @property {Matrix4} [projectionMatrix] - A projection matrix usually of the scene's camera.
* @property {number} [maxFar] - The maximum far value.
**/
export { CSMFrustum };

@@ -15,10 +15,47 @@ import {

/**
* A helper for visualizing the cascades of a CSM instance.
*
* @augments Group
*/
class CSMHelper extends Group {
/**
* Constructs a new CSM helper.
*
* @param {CSM|CSMShadowNode} csm - The CSM instance to visualize.
*/
constructor( csm ) {
super();
/**
* The CSM instance to visualize.
*
* @type {CSM|CSMShadowNode}
*/
this.csm = csm;
/**
* Whether to display the CSM frustum or not.
*
* @type {boolean}
* @default true
*/
this.displayFrustum = true;
/**
* Whether to display the cascade planes or not.
*
* @type {boolean}
* @default true
*/
this.displayPlanes = true;
/**
* Whether to display the shadow bounds or not.
*
* @type {boolean}
* @default true
*/
this.displayShadowBounds = true;

@@ -41,2 +78,5 @@

/**
* This method must be called if one of the `display*` properties is changed at runtime.
*/
updateVisibility() {

@@ -68,2 +108,5 @@

/**
* Updates the helper. This method should be called in the app's animation loop.
*/
update() {

@@ -166,2 +209,6 @@

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*/
dispose() {

@@ -168,0 +215,0 @@

import { ShaderChunk } from 'three';
/** @module CSMShader */
/**
* The object that holds the GLSL enhancements to enable CSM. This
* code is injected into the built-in material shaders by {@link CSM}.
*
* @type {Object}
*/
const CSMShader = {

@@ -49,3 +57,4 @@ lights_fragment_begin: /* glsl */`

pointLightShadow = pointLightShadows[ i ];
directLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;
directLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowIntensity, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;
#endif

@@ -52,0 +61,0 @@

@@ -38,4 +38,18 @@ import {

/**
* An implementation of Cascade Shadow Maps (CSM).
*
* This module can only be used with {@link WebGPURenderer}. When using {@link WebGLRenderer},
* use {@link CSM} instead.
*
* @augments ShadowBaseNode
*/
class CSMShadowNode extends ShadowBaseNode {
/**
* Constructs a new CSM shadow node.
*
* @param {DirectionalLight} light - The CSM light.
* @param {CSMShadowNode~Data} [data={}] - The CSM data.
*/
constructor( light, data = {} ) {

@@ -45,17 +59,89 @@

/**
* The scene's camera.
*
* @type {?Camera}
* @default null
*/
this.camera = null;
/**
* The number of cascades.
*
* @type {number}
* @default 3
*/
this.cascades = data.cascades || 3;
/**
* The maximum far value.
*
* @type {number}
* @default 100000
*/
this.maxFar = data.maxFar || 100000;
/**
* The frustum split mode.
*
* @type {('practical'|'uniform'|'logarithmic'|'custom')}
* @default 'practical'
*/
this.mode = data.mode || 'practical';
/**
* The light margin.
*
* @type {number}
* @default 200
*/
this.lightMargin = data.lightMargin || 200;
/**
* Custom split callback when using `mode='custom'`.
*
* @type {Function}
*/
this.customSplitsCallback = data.customSplitsCallback;
/**
* Whether to fade between cascades or not.
*
* @type {boolean}
* @default false
*/
this.fade = false;
/**
* An array of numbers in the range `[0,1]` the defines how the
* mainCSM frustum should be split up.
*
* @type {Array<number>}
*/
this.breaks = [];
this._cascades = [];
/**
* The main frustum.
*
* @type {?CSMFrustum}
* @default null
*/
this.mainFrustum = null;
/**
* An array of frustums representing the cascades.
*
* @type {Array<CSMFrustum>}
*/
this.frustums = [];
/**
* An array of directional lights which cast the shadows for
* the different cascades. There is one directional light for each
* cascade.
*
* @type {Array<DirectionalLight>}
*/
this.lights = [];

@@ -67,3 +153,9 @@

init( { camera, renderer } ) {
/**
* Inits the CSM shadow node.
*
* @private
* @param {NodeBuilder} builder - The node builder.
*/
_init( { camera, renderer } ) {

@@ -103,3 +195,8 @@ this.camera = camera;

initCascades() {
/**
* Inits the cascades according to the scene's camera and breaks configuration.
*
* @private
*/
_initCascades() {

@@ -114,3 +211,9 @@ const camera = this.camera;

getBreaks() {
/**
* Computes the breaks of this CSM instance based on the scene's camera, number of cascades
* and the selected split mode.
*
* @private
*/
_getBreaks() {

@@ -186,3 +289,8 @@ const camera = this.camera;

setLightBreaks() {
/**
* Sets the light breaks.
*
* @private
*/
_setLightBreaks() {

@@ -200,3 +308,8 @@ for ( let i = 0, l = this.cascades; i < l; i ++ ) {

updateShadowBounds() {
/**
* Updates the shadow bounds of this CSM instance.
*
* @private
*/
_updateShadowBounds() {

@@ -253,12 +366,21 @@ const frustums = this.frustums;

/**
* Applications must call this method every time they change camera or CSM settings.
*/
updateFrustums() {
this.getBreaks();
this.initCascades();
this.updateShadowBounds();
this.setLightBreaks();
this._getBreaks();
this._initCascades();
this._updateShadowBounds();
this._setLightBreaks();
}
setupFade() {
/**
* Setups the TSL when using fading.
*
* @private
* @return {ShaderCallNodeInternal}
*/
_setupFade() {

@@ -339,3 +461,9 @@ const cameraNear = reference( 'camera.near', 'float', this ).setGroup( renderGroup );

setupStandard() {
/**
* Setups the TSL when no fading (default).
*
* @private
* @return {ShaderCallNodeInternal}
*/
_setupStandard() {

@@ -377,5 +505,5 @@ const cameraNear = reference( 'camera.near', 'float', this ).setGroup( renderGroup );

if ( this.camera === null ) this.init( builder );
if ( this.camera === null ) this._init( builder );
return this.fade === true ? this.setupFade() : this.setupStandard();
return this.fade === true ? this._setupFade() : this._setupStandard();

@@ -434,2 +562,6 @@ }

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*/
dispose() {

@@ -453,2 +585,13 @@

/**
* Constructor data of `CSMShadowNode`.
*
* @typedef {Object} CSMShadowNode~Data
* @property {number} [cascades=3] - The number of cascades.
* @property {number} [maxFar=100000] - The maximum far value.
* @property {('practical'|'uniform'|'logarithmic'|'custom')} [mode='practical'] - The frustum split mode.
* @property {Function} [customSplitsCallback] - Custom split callback when using `mode='custom'`.
* @property {number} [lightMargin=200] - The light margin.
**/
export { CSMShadowNode };

@@ -16,6 +16,16 @@ import {

// GrannyKnot
/**
* A Granny Knot curve.
*
* @augments Curve
*/
class GrannyKnot extends Curve {
/**
* This method returns a vector in 3D space for the given interpolation factor.
*
* @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
* @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
* @return {Vector3} The position on the curve.
*/
getPoint( t, optionalTarget = new Vector3() ) {

@@ -37,6 +47,14 @@

// HeartCurve
/**
* A heart curve.
*
* @augments Curve
*/
class HeartCurve extends Curve {
/**
* Constructs a new heart curve.
*
* @param {number} [scale=5] - The curve's scale.
*/
constructor( scale = 5 ) {

@@ -46,2 +64,8 @@

/**
* The curve's scale.
*
* @type {number}
* @default 5
*/
this.scale = scale;

@@ -51,2 +75,9 @@

/**
* This method returns a vector in 3D space for the given interpolation factor.
*
* @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
* @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
* @return {Vector3} The position on the curve.
*/
getPoint( t, optionalTarget = new Vector3() ) {

@@ -68,6 +99,14 @@

// Viviani's Curve
/**
* A Viviani curve.
*
* @augments Curve
*/
class VivianiCurve extends Curve {
/**
* Constructs a new Viviani curve.
*
* @param {number} [scale=70] - The curve's scale.
*/
constructor( scale = 70 ) {

@@ -77,2 +116,8 @@

/**
* The curve's scale.
*
* @type {number}
* @default 70
*/
this.scale = scale;

@@ -82,2 +127,9 @@

/**
* This method returns a vector in 3D space for the given interpolation factor.
*
* @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
* @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
* @return {Vector3} The position on the curve.
*/
getPoint( t, optionalTarget = new Vector3() ) {

@@ -100,6 +152,16 @@

// KnotCurve
/**
* A knot curve.
*
* @augments Curve
*/
class KnotCurve extends Curve {
/**
* This method returns a vector in 3D space for the given interpolation factor.
*
* @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
* @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
* @return {Vector3} The position on the curve.
*/
getPoint( t, optionalTarget = new Vector3() ) {

@@ -124,7 +186,16 @@

// HelixCurve
/**
* A helix curve.
*
* @augments Curve
*/
class HelixCurve extends Curve {
/**
* This method returns a vector in 3D space for the given interpolation factor.
*
* @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
* @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
* @return {Vector3} The position on the curve.
*/
getPoint( t, optionalTarget = new Vector3() ) {

@@ -149,6 +220,14 @@

// TrefoilKnot
/**
* A Trefoil Knot.
*
* @augments Curve
*/
class TrefoilKnot extends Curve {
/**
* Constructs a new Trefoil Knot.
*
* @param {number} [scale=10] - The curve's scale.
*/
constructor( scale = 10 ) {

@@ -158,2 +237,8 @@

/**
* The curve's scale.
*
* @type {number}
* @default 10
*/
this.scale = scale;

@@ -163,2 +248,9 @@

/**
* This method returns a vector in 3D space for the given interpolation factor.
*
* @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
* @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
* @return {Vector3} The position on the curve.
*/
getPoint( t, optionalTarget = new Vector3() ) {

@@ -180,6 +272,14 @@

// TorusKnot
/**
* A torus knot.
*
* @augments Curve
*/
class TorusKnot extends Curve {
/**
* Constructs a new torus knot.
*
* @param {number} [scale=10] - The curve's scale.
*/
constructor( scale = 10 ) {

@@ -189,2 +289,8 @@

/**
* The curve's scale.
*
* @type {number}
* @default 10
*/
this.scale = scale;

@@ -194,2 +300,9 @@

/**
* This method returns a vector in 3D space for the given interpolation factor.
*
* @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
* @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
* @return {Vector3} The position on the curve.
*/
getPoint( t, optionalTarget = new Vector3() ) {

@@ -214,6 +327,14 @@

// CinquefoilKnot
/**
* A Cinquefoil Knot.
*
* @augments Curve
*/
class CinquefoilKnot extends Curve {
/**
* Constructs a new Cinquefoil Knot.
*
* @param {number} [scale=10] - The curve's scale.
*/
constructor( scale = 10 ) {

@@ -223,2 +344,8 @@

/**
* The curve's scale.
*
* @type {number}
* @default 10
*/
this.scale = scale;

@@ -228,2 +355,9 @@

/**
* This method returns a vector in 3D space for the given interpolation factor.
*
* @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
* @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
* @return {Vector3} The position on the curve.
*/
getPoint( t, optionalTarget = new Vector3() ) {

@@ -248,7 +382,14 @@

// TrefoilPolynomialKnot
/**
* A Trefoil Polynomial Knot.
*
* @augments Curve
*/
class TrefoilPolynomialKnot extends Curve {
/**
* Constructs a new Trefoil Polynomial Knot.
*
* @param {number} [scale=10] - The curve's scale.
*/
constructor( scale = 10 ) {

@@ -258,2 +399,8 @@

/**
* The curve's scale.
*
* @type {number}
* @default 10
*/
this.scale = scale;

@@ -263,2 +410,9 @@

/**
* This method returns a vector in 3D space for the given interpolation factor.
*
* @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
* @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
* @return {Vector3} The position on the curve.
*/
getPoint( t, optionalTarget = new Vector3() ) {

@@ -287,6 +441,14 @@

// FigureEightPolynomialKnot
/**
* A Figure Eight Polynomial Knot.
*
* @augments Curve
*/
class FigureEightPolynomialKnot extends Curve {
/**
* Constructs a new Figure Eight Polynomial Knot.
*
* @param {number} [scale=1] - The curve's scale.
*/
constructor( scale = 1 ) {

@@ -296,2 +458,8 @@

/**
* The curve's scale.
*
* @type {number}
* @default 1
*/
this.scale = scale;

@@ -301,2 +469,9 @@

/**
* This method returns a vector in 3D space for the given interpolation factor.
*
* @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
* @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
* @return {Vector3} The position on the curve.
*/
getPoint( t, optionalTarget = new Vector3() ) {

@@ -318,6 +493,14 @@

// DecoratedTorusKnot4a
/**
* A Decorated Torus Knot 4a.
*
* @augments Curve
*/
class DecoratedTorusKnot4a extends Curve {
/**
* Constructs a new Decorated Torus Knot 4a.
*
* @param {number} [scale=1] - The curve's scale.
*/
constructor( scale = 40 ) {

@@ -327,2 +510,8 @@

/**
* The curve's scale.
*
* @type {number}
* @default 40
*/
this.scale = scale;

@@ -332,2 +521,9 @@

/**
* This method returns a vector in 3D space for the given interpolation factor.
*
* @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
* @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
* @return {Vector3} The position on the curve.
*/
getPoint( t, optionalTarget = new Vector3() ) {

@@ -349,6 +545,14 @@

// DecoratedTorusKnot4b
/**
* A Decorated Torus Knot 4b.
*
* @augments Curve
*/
class DecoratedTorusKnot4b extends Curve {
/**
* Constructs a new Decorated Torus Knot 4b.
*
* @param {number} [scale=1] - The curve's scale.
*/
constructor( scale = 40 ) {

@@ -358,2 +562,8 @@

/**
* The curve's scale.
*
* @type {number}
* @default 40
*/
this.scale = scale;

@@ -363,2 +573,9 @@

/**
* This method returns a vector in 3D space for the given interpolation factor.
*
* @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
* @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
* @return {Vector3} The position on the curve.
*/
getPoint( t, optionalTarget = new Vector3() ) {

@@ -380,7 +597,14 @@

// DecoratedTorusKnot5a
/**
* A Decorated Torus Knot 5a.
*
* @augments Curve
*/
class DecoratedTorusKnot5a extends Curve {
/**
* Constructs a new Decorated Torus Knot 5a.
*
* @param {number} [scale=1] - The curve's scale.
*/
constructor( scale = 40 ) {

@@ -390,2 +614,8 @@

/**
* The curve's scale.
*
* @type {number}
* @default 40
*/
this.scale = scale;

@@ -395,2 +625,9 @@

/**
* This method returns a vector in 3D space for the given interpolation factor.
*
* @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
* @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
* @return {Vector3} The position on the curve.
*/
getPoint( t, optionalTarget = new Vector3() ) {

@@ -412,6 +649,14 @@

// DecoratedTorusKnot5c
/**
* A Decorated Torus Knot 5c.
*
* @augments Curve
*/
class DecoratedTorusKnot5c extends Curve {
/**
* Constructs a new Decorated Torus Knot 5c.
*
* @param {number} [scale=1] - The curve's scale.
*/
constructor( scale = 40 ) {

@@ -421,2 +666,8 @@

/**
* The curve's scale.
*
* @type {number}
* @default 40
*/
this.scale = scale;

@@ -426,2 +677,9 @@

/**
* This method returns a vector in 3D space for the given interpolation factor.
*
* @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
* @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
* @return {Vector3} The position on the curve.
*/
getPoint( t, optionalTarget = new Vector3() ) {

@@ -428,0 +686,0 @@

@@ -9,19 +9,20 @@ import {

/**
* NURBS curve object
* This class represents a NURBS curve.
*
* Derives from Curve, overriding getPoint and getTangent.
* Implementation is based on `(x, y [, z=0 [, w=1]])` control points with `w=weight`.
*
* Implementation is based on (x, y [, z=0 [, w=1]]) control points with w=weight.
*
**/
* @augments Curve
*/
class NURBSCurve extends Curve {
constructor(
degree,
knots /* array of reals */,
controlPoints /* array of Vector(2|3|4) */,
startKnot /* index in knots */,
endKnot /* index in knots */
) {
/**
* Constructs a new NURBS curve.
*
* @param {number} degree - The NURBS degree.
* @param {Array<number>} knots - The knots as a flat array of numbers.
* @param {Array<Vector2|Vector3|Vector4>} controlPoints - An array holding control points.
* @param {number} [startKnot] - Index of the start knot into the `knots` array.
* @param {number} [endKnot] - Index of the end knot into the `knots` array.
*/
constructor( degree, knots, controlPoints, startKnot, endKnot ) {

@@ -33,7 +34,35 @@ super();

/**
* The NURBS degree.
*
* @type {number}
*/
this.degree = degree;
/**
* The knots as a flat array of numbers.
*
* @type {Array<number>}
*/
this.knots = knots;
/**
* An array of control points.
*
* @type {Array<Vector4>}
*/
this.controlPoints = [];
// Used by periodic NURBS to remove hidden spans
/**
* Index of the start knot into the `knots` array.
*
* @type {number}
*/
this.startKnot = startKnot || 0;
/**
* Index of the end knot into the `knots` array.
*
* @type {number}
*/
this.endKnot = endKnot || knotsLength;

@@ -51,2 +80,9 @@

/**
* This method returns a vector in 3D space for the given interpolation factor.
*
* @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
* @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
* @return {Vector3} The position on the curve.
*/
getPoint( t, optionalTarget = new Vector3() ) {

@@ -72,2 +108,9 @@

/**
* Returns a unit vector tangent for the given interpolation factor.
*
* @param {number} t - The interpolation factor.
* @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
* @return {Vector3} The tangent vector.
*/
getTangent( t, optionalTarget = new Vector3() ) {

@@ -74,0 +117,0 @@

@@ -7,15 +7,52 @@ import {

/**
* NURBS surface object
* This class represents a NURBS surface.
*
* Implementation is based on (x, y [, z=0 [, w=1]]) control points with w=weight.
**/
* Implementation is based on `(x, y [, z=0 [, w=1]])` control points with `w=weight`.
*/
class NURBSSurface {
constructor( degree1, degree2, knots1, knots2 /* arrays of reals */, controlPoints /* array^2 of Vector(2|3|4) */ ) {
/**
* Constructs a new NURBS surface.
*
* @param {number} degree1 - The first NURBS degree.
* @param {number} degree2 - The second NURBS degree.
* @param {Array<number>} knots1 - The first knots as a flat array of numbers.
* @param {Array<number>} knots2 - The second knots as a flat array of numbers.
* @param {Array<Array<Vector2|Vector3|Vector4>>} controlPoints - An array^2 holding control points.
*/
constructor( degree1, degree2, knots1, knots2, controlPoints ) {
/**
* The first NURBS degree.
*
* @type {number}
*/
this.degree1 = degree1;
/**
* The second NURBS degree.
*
* @type {number}
*/
this.degree2 = degree2;
/**
* The first knots as a flat array of numbers.
*
* @type {Array<number>}
*/
this.knots1 = knots1;
/**
* The second knots as a flat array of numbers.
*
* @type {Array<number>}
*/
this.knots2 = knots2;
/**
* An array holding arrays of control points.
*
* @type {Array<Array<Vector2|Vector3|Vector4>>}
*/
this.controlPoints = [];

@@ -42,2 +79,9 @@

/**
* This method returns a vector in 3D space for the given interpolation factor. This vector lies on the NURBS surface.
*
* @param {number} t1 - The first interpolation factor representing the `u` position on the surface. Must be in the range `[0,1]`.
* @param {number} t2 - The second interpolation factor representing the `v` position on the surface. Must be in the range `[0,1]`.
* @param {Vector3} target - The target vector the result is written to.
*/
getPoint( t1, t2, target ) {

@@ -44,0 +88,0 @@

@@ -6,22 +6,12 @@ import {

/** @module NURBSUtils */
/**
* NURBS utils
* Finds knot vector span.
*
* See NURBSCurve and NURBSSurface.
**/
/**************************************************************
* NURBS Utils
**************************************************************/
/*
Finds knot vector span.
p : degree
u : parametric value
U : knot vector
returns the span
*/
* @param {number} p - The degree.
* @param {number} u - The parametric value.
* @param {Array<number>} U - The knot vector.
* @return {number} The span.
*/
function findSpan( p, u, U ) {

@@ -67,13 +57,11 @@

/*
Calculate basis functions. See The NURBS Book, page 70, algorithm A2.2
span : span in which u lies
u : parametric point
p : degree
U : knot vector
returns array[p+1] with basis functions values.
*/
/**
* Calculates basis functions. See The NURBS Book, page 70, algorithm A2.2.
*
* @param {number} span - The span in which `u` lies.
* @param {number} u - The parametric value.
* @param {number} p - The degree.
* @param {Array<number>} U - The knot vector.
* @return {Array<number>} Array[p+1] with basis functions values.
*/
function calcBasisFunctions( span, u, p, U ) {

@@ -111,13 +99,11 @@

/*
Calculate B-Spline curve points. See The NURBS Book, page 82, algorithm A3.1.
p : degree of B-Spline
U : knot vector
P : control points (x, y, z, w)
u : parametric point
returns point for given u
*/
/**
* Calculates B-Spline curve points. See The NURBS Book, page 82, algorithm A3.1.
*
* @param {number} p - The degree of the B-Spline.
* @param {Array<number>} U - The knot vector.
* @param {Array<Vector4>} P - The control points
* @param {number} u - The parametric point.
* @return {Vector4} The point for given `u`.
*/
function calcBSplinePoint( p, U, P, u ) {

@@ -145,14 +131,12 @@

/*
Calculate basis functions derivatives. See The NURBS Book, page 72, algorithm A2.3.
span : span in which u lies
u : parametric point
p : degree
n : number of derivatives to calculate
U : knot vector
returns array[n+1][p+1] with basis functions derivatives
*/
/**
* Calculates basis functions derivatives. See The NURBS Book, page 72, algorithm A2.3.
*
* @param {number} span - The span in which `u` lies.
* @param {number} u - The parametric point.
* @param {number} p - The degree.
* @param {number} n - number of derivatives to calculate
* @param {Array<number>} U - The knot vector.
* @return {Array<Array<number>>} An array[n+1][p+1] with basis functions derivatives.
*/
function calcBasisFunctionDerivatives( span, u, p, n, U ) {

@@ -280,14 +264,12 @@

/*
Calculate derivatives of a B-Spline. See The NURBS Book, page 93, algorithm A3.2.
p : degree
U : knot vector
P : control points
u : Parametric points
nd : number of derivatives
returns array[d+1] with derivatives
*/
/**
* Calculates derivatives of a B-Spline. See The NURBS Book, page 93, algorithm A3.2.
*
* @param {number} p - The degree.
* @param {Array<number>} U - The knot vector.
* @param {Array<Vector4>} P - The control points
* @param {number} u - The parametric point.
* @param {number} nd - The number of derivatives.
* @return {Array<Vector4>} An array[d+1] with derivatives.
*/
function calcBSplineDerivatives( p, U, P, u, nd ) {

@@ -338,8 +320,9 @@

/*
Calculate "K over I"
returns k!/(i!(k-i)!)
*/
/**
* Calculates "K over I".
*
* @param {number} k - The K value.
* @param {number} i - The I value.
* @return {number} k!/(i!(k-i)!)
*/
function calcKoverI( k, i ) {

@@ -373,10 +356,8 @@

/*
Calculate derivatives (0-nd) of rational curve. See The NURBS Book, page 127, algorithm A4.2.
Pders : result of function calcBSplineDerivatives
returns array with derivatives for rational curve.
*/
/**
* Calculates derivatives (0-nd) of rational curve. See The NURBS Book, page 127, algorithm A4.2.
*
* @param {Array<Vector4>} Pders - Array with derivatives.
* @return {Array<Vector3>} An array with derivatives for rational curve.
*/
function calcRationalCurveDerivatives( Pders ) {

@@ -416,14 +397,12 @@

/*
Calculate NURBS curve derivatives. See The NURBS Book, page 127, algorithm A4.2.
p : degree
U : knot vector
P : control points in homogeneous space
u : parametric points
nd : number of derivatives
returns array with derivatives.
*/
/**
* Calculates NURBS curve derivatives. See The NURBS Book, page 127, algorithm A4.2.
*
* @param {number} p - The degree.
* @param {Array<number>} U - The knot vector.
* @param {Array<Vector4>} P - The control points in homogeneous space.
* @param {number} u - The parametric point.
* @param {number} nd - The number of derivatives.
* @return {Array<Vector3>} array with derivatives for rational curve.
*/
function calcNURBSDerivatives( p, U, P, u, nd ) {

@@ -436,13 +415,14 @@

/*
Calculate rational B-Spline surface point. See The NURBS Book, page 134, algorithm A4.3.
p, q : degrees of B-Spline surface
U, V : knot vectors
P : control points (x, y, z, w)
u, v : parametric values
returns point for given (u, v)
*/
/**
* Calculates a rational B-Spline surface point. See The NURBS Book, page 134, algorithm A4.3.
*
* @param {number} p - The first degree of B-Spline surface.
* @param {number} q - The second degree of B-Spline surface.
* @param {Array<number>} U - The first knot vector.
* @param {Array<number>} V - The second knot vector.
* @param {Array<Array<Vector4>>} P - The control points in homogeneous space.
* @param {number} u - The first parametric point.
* @param {number} v - The second parametric point.
* @param {Vector3} target - The target vector.
*/
function calcSurfacePoint( p, q, U, V, P, u, v, target ) {

@@ -484,12 +464,17 @@

/*
Calculate rational B-Spline volume point. See The NURBS Book, page 134, algorithm A4.3.
p, q, r : degrees of B-Splinevolume
U, V, W : knot vectors
P : control points (x, y, z, w)
u, v, w : parametric values
returns point for given (u, v, w)
*/
/**
* Calculates a rational B-Spline volume point. See The NURBS Book, page 134, algorithm A4.3.
*
* @param {number} p - The first degree of B-Spline surface.
* @param {number} q - The second degree of B-Spline surface.
* @param {number} r - The third degree of B-Spline surface.
* @param {Array<number>} U - The first knot vector.
* @param {Array<number>} V - The second knot vector.
* @param {Array<number>} W - The third knot vector.
* @param {Array<Array<Array<Vector4>>>} P - The control points in homogeneous space.
* @param {number} u - The first parametric point.
* @param {number} v - The second parametric point.
* @param {number} w - The third parametric point.
* @param {Vector3} target - The target vector.
*/
function calcVolumePoint( p, q, r, U, V, W, P, u, v, w, target ) {

@@ -543,3 +528,2 @@

export {

@@ -546,0 +530,0 @@ findSpan,

@@ -7,9 +7,19 @@ import {

/**
* NURBS volume object
* This class represents a NURBS volume.
*
* Implementation is based on (x, y, z [, w=1]]) control points with w=weight.
**/
* Implementation is based on `(x, y [, z=0 [, w=1]])` control points with `w=weight`.
*/
class NURBSVolume {
/**
* Constructs a new NURBS surface.
*
* @param {number} degree1 - The first NURBS degree.
* @param {number} degree2 - The second NURBS degree.
* @param {number} degree3 - The third NURBS degree.
* @param {Array<number>} knots1 - The first knots as a flat array of numbers.
* @param {Array<number>} knots2 - The second knots as a flat array of numbers.
* @param {Array<number>} knots3 - The third knots as a flat array of numbers.
* @param {Array<Array<Array<Vector2|Vector3|Vector4>>>} controlPoints - An array^3 holding control points.
*/
constructor( degree1, degree2, degree3, knots1, knots2, knots3 /* arrays of reals */, controlPoints /* array^3 of Vector(2|3|4) */ ) {

@@ -51,2 +61,10 @@

/**
* This method returns a vector in 3D space for the given interpolation factor. This vector lies within the NURBS volume.
*
* @param {number} t1 - The first interpolation factor representing the `u` position within the volume. Must be in the range `[0,1]`.
* @param {number} t2 - The second interpolation factor representing the `v` position within the volume. Must be in the range `[0,1]`.
* @param {number} t3 - The third interpolation factor representing the `w` position within the volume. Must be in the range `[0,1]`.
* @param {Vector3} target - The target vector the result is written to.
*/
getPoint( t1, t2, t3, target ) {

@@ -53,0 +71,0 @@

@@ -12,4 +12,17 @@ import {

/**
* A class that creates an anaglyph effect.
*
* Note that this class can only be used with {@link WebGLRenderer}.
* When using {@link WebGPURenderer}, use {@link AnaglyphPassNode}.
*/
class AnaglyphEffect {
/**
* Constructs a new anaglyph effect.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {number} width - The width of the effect in physical pixels.
* @param {number} height - The height of the effect in physical pixels.
*/
constructor( renderer, width = 512, height = 512 ) {

@@ -98,2 +111,8 @@

/**
* Resizes the effect.
*
* @param {number} width - The width of the effect in logical pixels.
* @param {number} height - The height of the effect in logical pixels.
*/
this.setSize = function ( width, height ) {

@@ -110,2 +129,9 @@

/**
* When using this effect, this method should be called instead of the
* default {@link WebGLRenderer#render}.
*
* @param {Object3D} scene - The scene to render.
* @param {Camera} camera - The camera.
*/
this.render = function ( scene, camera ) {

@@ -136,2 +162,6 @@

/**
* Frees internal resources. This method should be called
* when the effect is no longer required.
*/
this.dispose = function () {

@@ -138,0 +168,0 @@

/**
* Ascii generation is based on https://github.com/hassadee/jsascii/blob/master/jsascii.js
* A class that creates an ASCII effect.
*
* 16 April 2012 - @blurspline
* The ASCII generation is based on [jsascii]{@link https://github.com/hassadee/jsascii/blob/master/jsascii.js}.
*/
class AsciiEffect {
/**
* Constructs a new ASCII effect.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {string} [charSet=' .:-=+*#%@'] - The char set.
* @param {AsciiEffect~Options} [options] - The configuration parameter.
*/
constructor( renderer, charSet = ' .:-=+*#%@', options = {} ) {

@@ -17,8 +23,8 @@

const fResolution = options[ 'resolution' ] || 0.15; // Higher for more details
const fResolution = options[ 'resolution' ] || 0.15;
const iScale = options[ 'scale' ] || 1;
const bColor = options[ 'color' ] || false; // nice but slows down rendering!
const bAlpha = options[ 'alpha' ] || false; // Transparency
const bBlock = options[ 'block' ] || false; // blocked characters. like good O dos
const bInvert = options[ 'invert' ] || false; // black is white, white is black
const bColor = options[ 'color' ] || false;
const bAlpha = options[ 'alpha' ] || false;
const bBlock = options[ 'block' ] || false;
const bInvert = options[ 'invert' ] || false;
const strResolution = options[ 'strResolution' ] || 'low';

@@ -37,2 +43,8 @@

/**
* Resizes the effect.
*
* @param {number} w - The width of the effect in logical pixels.
* @param {number} h - The height of the effect in logical pixels.
*/
this.setSize = function ( w, h ) {

@@ -49,3 +61,9 @@

/**
* When using this effect, this method should be called instead of the
* default {@link WebGLRenderer#render}.
*
* @param {Object3D} scene - The scene to render.
* @param {Camera} camera - The camera.
*/
this.render = function ( scene, camera ) {

@@ -58,2 +76,8 @@

/**
* The DOM element of the effect. This element must be used instead of the
* default {@link WebGLRenderer#domElement}.
*
* @type {HTMLDivElement}
*/
this.domElement = domElement;

@@ -84,4 +108,4 @@

oAscii.cellSpacing = 0;
oAscii.cellPadding = 0;
oAscii.cellSpacing = '0';
oAscii.cellPadding = '0';

@@ -102,4 +126,2 @@ const oStyle = oAscii.style;

const aDefaultCharList = ( ' .,:;i1tfLCG08@' ).split( '' );
const aDefaultColorCharList = ( ' CGO08@' ).split( '' );
const strFont = 'courier new, monospace';

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

let aCharList = ( bColor ? aDefaultColorCharList : aDefaultCharList );
let aCharList;
if ( charSet ) {
if ( charSet ) aCharList = charSet;
aCharList = ( charSet ).split( '' );
} else {
const aDefaultCharList = ( ' .,:;i1tfLCG08@' ).split( '' );
const aDefaultColorCharList = ( ' CGO08@' ).split( '' );
aCharList = ( bColor ? aDefaultColorCharList : aDefaultCharList );
}
// Setup dom

@@ -270,2 +302,15 @@

/**
* This type represents configuration settings of `AsciiEffect`.
*
* @typedef {Object} AsciiEffect~Options
* @property {number} [resolution=0.15] - A higher value leads to more details.
* @property {number} [scale=1] - The scale of the effect.
* @property {boolean} [color=false] - Whether colors should be enabled or not. Better quality but slows down rendering.
* @property {boolean} [alpha=false] - Whether transparency should be enabled or not.
* @property {boolean} [block=false] - Whether blocked characters should be enabled or not.
* @property {boolean} [invert=false] - Whether colors should be inverted or not.
* @property {('low'|'medium'|'high')} [strResolution='low'] - The string resolution.
**/
export { AsciiEffect };

@@ -10,8 +10,8 @@ import {

/**
* Reference: https://en.wikipedia.org/wiki/Cel_shading
* An outline effect for toon shaders.
*
* API
* Note that this class can only be used with {@link WebGLRenderer}.
* When using {@link WebGPURenderer}, use {@link ToonOutlinePassNode}.
*
* 1. Traditional
*
* ```js
* const effect = new OutlineEffect( renderer );

@@ -24,46 +24,12 @@ *

* }
*
* 2. VR compatible
*
* const effect = new OutlineEffect( renderer );
* let renderingOutline = false;
*
* scene.onAfterRender = function () {
*
* if ( renderingOutline ) return;
*
* renderingOutline = true;
*
* effect.renderOutline( scene, camera );
*
* renderingOutline = false;
*
* };
*
* function render() {
*
* renderer.render( scene, camera );
*
* }
*
* // How to set default outline parameters
* new OutlineEffect( renderer, {
* defaultThickness: 0.01,
* defaultColor: [ 0, 0, 0 ],
* defaultAlpha: 0.8,
* defaultKeepAlive: true // keeps outline material in cache even if material is removed from scene
* } );
*
* // How to set outline parameters for each material
* material.userData.outlineParameters = {
* thickness: 0.01,
* color: [ 0, 0, 0 ],
* alpha: 0.8,
* visible: true,
* keepAlive: true
* };
* ```
*/
class OutlineEffect {
/**
* Constructs a new outline effect.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {OutlineEffect~Options} [parameters] - The configuration parameter.
*/
constructor( renderer, parameters = {} ) {

@@ -418,2 +384,9 @@

/**
* When using this effect, this method should be called instead of the
* default {@link WebGLRenderer#render}.
*
* @param {Object3D} scene - The scene to render.
* @param {Camera} camera - The camera.
*/
this.render = function ( scene, camera ) {

@@ -439,2 +412,26 @@

/**
* This method can be used to render outlines in VR.
*
* ```js
* const effect = new OutlineEffect( renderer );
* let renderingOutline = false;
*
* scene.onAfterRender = function () {
*
* if ( renderingOutline ) return;
*
* renderingOutline = true;
* effect.renderOutline( scene, camera );
* renderingOutline = false;
* };
*
* function render() {
* renderer.render( scene, camera );
* }
* ```
*
* @param {Object3D} scene - The scene to render.
* @param {Camera} camera - The camera.
*/
this.renderOutline = function ( scene, camera ) {

@@ -467,78 +464,29 @@

/*
* See #9918
/**
* Resizes the effect.
*
* The following property copies and wrapper methods enable
* OutlineEffect to be called from other *Effect, like
*
* effect = new StereoEffect( new OutlineEffect( renderer ) );
*
* function render () {
*
* effect.render( scene, camera );
*
* }
* @param {number} width - The width of the effect in logical pixels.
* @param {number} height - The height of the effect in logical pixels.
*/
this.autoClear = renderer.autoClear;
this.domElement = renderer.domElement;
this.shadowMap = renderer.shadowMap;
this.setSize = function ( width, height ) {
this.clear = function ( color, depth, stencil ) {
renderer.setSize( width, height );
renderer.clear( color, depth, stencil );
};
this.getPixelRatio = function () {
}
return renderer.getPixelRatio();
}
};
/**
* This type represents configuration settings of `OutlineEffect`.
*
* @typedef {Object} OutlineEffect~Options
* @property {number} [defaultThickness=0.003] - The outline thickness.
* @property {Array<number>} [defaultColor=[0,0,0]] - The outline color.
* @property {number} [defaultAlpha=1] - The outline alpha value.
* @property {boolean} [defaultKeepAlive=false] - Whether to keep alive cached internal materials or not.
**/
this.setPixelRatio = function ( value ) {
renderer.setPixelRatio( value );
};
this.getSize = function ( target ) {
return renderer.getSize( target );
};
this.setSize = function ( width, height, updateStyle ) {
renderer.setSize( width, height, updateStyle );
};
this.setViewport = function ( x, y, width, height ) {
renderer.setViewport( x, y, width, height );
};
this.setScissor = function ( x, y, width, height ) {
renderer.setScissor( x, y, width, height );
};
this.setScissorTest = function ( boolean ) {
renderer.setScissorTest( boolean );
};
this.setRenderTarget = function ( renderTarget ) {
renderer.setRenderTarget( renderTarget );
};
}
}
export { OutlineEffect };

@@ -11,4 +11,15 @@ import {

/**
* A class that creates an parallax barrier effect.
*
* Note that this class can only be used with {@link WebGLRenderer}.
* When using {@link WebGPURenderer}, use {@link ParallaxBarrierPassNode}.
*/
class ParallaxBarrierEffect {
/**
* Constructs a new parallax barrier effect.
*
* @param {WebGLRenderer} renderer - The renderer.
*/
constructor( renderer ) {

@@ -76,2 +87,8 @@

/**
* Resizes the effect.
*
* @param {number} width - The width of the effect in logical pixels.
* @param {number} height - The height of the effect in logical pixels.
*/
this.setSize = function ( width, height ) {

@@ -88,2 +105,9 @@

/**
* When using this effect, this method should be called instead of the
* default {@link WebGLRenderer#render}.
*
* @param {Object3D} scene - The scene to render.
* @param {Camera} camera - The camera.
*/
this.render = function ( scene, camera ) {

@@ -114,2 +138,6 @@

/**
* Frees internal resources. This method should be called
* when the effect is no longer required.
*/
this.dispose = function () {

@@ -116,0 +144,0 @@

@@ -8,7 +8,13 @@ import {

/**
* peppers ghost effect based on http://www.instructables.com/id/Reflective-Prism/?ALLSTEPS
* A class that implements a peppers ghost effect.
*
* Reference: [Reflective Prism]{@link http://www.instructables.com/id/Reflective-Prism/?ALLSTEPS}
*/
class PeppersGhostEffect {
/**
* Constructs a new peppers ghost effect.
*
* @param {(WebGPURenderer|WebGLRenderer)} renderer - The renderer.
*/
constructor( renderer ) {

@@ -36,2 +42,8 @@

/**
* Resizes the effect.
*
* @param {number} width - The width of the effect in logical pixels.
* @param {number} height - The height of the effect in logical pixels.
*/
this.setSize = function ( width, height ) {

@@ -56,2 +68,9 @@

/**
* When using this effect, this method should be called instead of the
* default {@link WebGLRenderer#render}.
*
* @param {Object3D} scene - The scene to render.
* @param {Camera} camera - The camera.
*/
this.render = function ( scene, camera ) {

@@ -58,0 +77,0 @@

@@ -6,4 +6,15 @@ import {

/**
* A class that creates an stereo effect.
*
* Note that this class can only be used with {@link WebGLRenderer}.
* When using {@link WebGPURenderer}, use {@link StereoPassNode}.
*/
class StereoEffect {
/**
* Constructs a new stereo effect.
*
* @param {WebGLRenderer} renderer - The renderer.
*/
constructor( renderer ) {

@@ -15,2 +26,7 @@

/**
* Sets the given eye separation.
*
* @param {number} eyeSep - The eye separation to set.
*/
this.setEyeSeparation = function ( eyeSep ) {

@@ -22,2 +38,8 @@

/**
* Resizes the effect.
*
* @param {number} width - The width of the effect in logical pixels.
* @param {number} height - The height of the effect in logical pixels.
*/
this.setSize = function ( width, height ) {

@@ -29,2 +51,9 @@

/**
* When using this effect, this method should be called instead of the
* default {@link WebGLRenderer#render}.
*
* @param {Object3D} scene - The scene to render.
* @param {Camera} camera - The camera.
*/
this.render = function ( scene, camera ) {

@@ -31,0 +60,0 @@

@@ -11,4 +11,26 @@ import {

/**
* This class represents a scene with a very basic room setup that can be used as
* input for {@link PMREMGenerator#fromScene}. The resulting PMREM represents the room's
* lighting and can be used for Image Based Lighting by assigning it to {@link Scene#environment}
* or directly as an environment map to PBR materials.
*
* This class uses a simple room setup and should only be used for development purposes.
* A more appropriate setup for production is {@link RoomEnvironment}.
*
* ```js
* const environment = new DebugEnvironment();
* const pmremGenerator = new THREE.PMREMGenerator( renderer );
*
* const envMap = pmremGenerator.fromScene( environment ).texture;
* scene.environment = envMap;
* ```
*
* @augments Scene
*/
class DebugEnvironment extends Scene {
/**
* Constructs a new debug environment.
*/
constructor() {

@@ -51,4 +73,31 @@

/**
* Frees internal resources. This method should be called
* when the environment is no longer required.
*/
dispose() {
const resources = new Set();
this.traverse( ( object ) => {
if ( object.isMesh ) {
resources.add( object.geometry );
resources.add( object.material );
}
} );
for ( const resource of resources ) {
resource.dispose();
}
}
}
export { DebugEnvironment };

@@ -1,5 +0,1 @@

/**
* https://github.com/google/model-viewer/blob/master/packages/model-viewer/src/three-components/EnvironmentScene.ts
*/
import {

@@ -15,2 +11,21 @@ BackSide,

/**
* This class represents a scene with a basic room setup that can be used as
* input for {@link PMREMGenerator#fromScene}. The resulting PMREM represents the room's
* lighting and can be used for Image Based Lighting by assigning it to {@link Scene#environment}
* or directly as an environment map to PBR materials.
*
* The implementation is based on the [EnvironmentScene](https://github.com/google/model-viewer/blob/master/packages/model-viewer/src/three-components/EnvironmentScene.ts)
* component from the `model-viewer` project.
*
* ```js
* const environment = new RoomEnvironment();
* const pmremGenerator = new THREE.PMREMGenerator( renderer );
*
* const envMap = pmremGenerator.fromScene( environment ).texture;
* scene.environment = envMap;
* ```
*
* @augments Scene
*/
class RoomEnvironment extends Scene {

@@ -112,2 +127,6 @@

/**
* Frees internal resources. This method should be called
* when the environment is no longer required.
*/
dispose() {

@@ -114,0 +133,0 @@

import { Color, ColorManagement, SRGBColorSpace } from 'three';
/* global DracoEncoderModule */
/**
* Export draco compressed files from threejs geometry objects.
* An exporter to compress geometry with the Draco library.
*
* Draco files are compressed and usually are smaller than conventional 3D file formats.
* [Draco]{@link https://google.github.io/draco/} is an open source library for compressing and
* decompressing 3D meshes and point clouds. Compressed geometry can be significantly smaller,
* at the cost of additional decoding time on the client device.
*
* The exporter receives a options object containing
* - decodeSpeed, indicates how to tune the encoder regarding decode speed (0 gives better speed but worst quality)
* - encodeSpeed, indicates how to tune the encoder parameters (0 gives better speed but worst quality)
* - encoderMethod
* - quantization, indicates the presision of each type of data stored in the draco file in the order (POSITION, NORMAL, COLOR, TEX_COORD, GENERIC)
* - exportUvs
* - exportNormals
* - exportColor
* Standalone Draco files have a `.drc` extension, and contain vertex positions,
* normals, colors, and other attributes. Draco files *do not* contain materials,
* textures, animation, or node hierarchies – to use these features, embed Draco geometry
* inside of a glTF file. A normal glTF file can be converted to a Draco-compressed glTF file
* using [glTF-Pipeline]{@link https://github.com/AnalyticalGraphicsInc/gltf-pipeline}.
*
* ```js
* const exporter = new DRACOExporter();
* const data = exporter.parse( mesh, options );
* ```
*/
/* global DracoEncoderModule */
class DRACOExporter {
/**
* Parses the given mesh or point cloud and generates the Draco output.
*
* @param {(Mesh|Points)} object - The mesh or point cloud to export.
* @param {DRACOExporter~Options} options - The export options.
* @return {ArrayBuffer} The exported Draco.
*/
parse( object, options = {} ) {

@@ -252,3 +262,20 @@

/**
* Edgebreaker encoding.
*
* @static
* @constant
* @type {number}
* @default 1
*/
DRACOExporter.MESH_EDGEBREAKER_ENCODING = 1;
/**
* Sequential encoding.
*
* @static
* @constant
* @type {number}
* @default 0
*/
DRACOExporter.MESH_SEQUENTIAL_ENCODING = 0;

@@ -270,2 +297,15 @@

/**
* Export options of `DRACOExporter`.
*
* @typedef {Object} DRACOExporter~Options
* @property {number} [decodeSpeed=5] - Indicates how to tune the encoder regarding decode speed (0 gives better speed but worst quality).
* @property {number} [encodeSpeed=5] - Indicates how to tune the encoder parameters (0 gives better speed but worst quality).
* @property {number} [encoderMethod=1] - Either sequential (very little compression) or Edgebreaker. Edgebreaker traverses the triangles of the mesh in a deterministic, spiral-like way which provides most of the benefits of this data format.
* @property {Array<number>} [quantization=[ 16, 8, 8, 8, 8 ]] - Indicates the precision of each type of data stored in the draco file in the order (POSITION, NORMAL, COLOR, TEX_COORD, GENERIC).
* @property {boolean} [exportUvs=true] - Whether to export UVs or not.
* @property {boolean} [exportNormals=true] - Whether to export normals or not.
* @property {boolean} [exportColor=false] - Whether to export colors or not.
**/
export { DRACOExporter };

@@ -1,8 +0,1 @@

/**
* @author sciecode / https://github.com/sciecode
*
* EXR format references:
* https://www.openexr.com/documentation/openexrfilelayout.pdf
*/
import {

@@ -22,4 +15,32 @@ FloatType,

/**
* An exporter for EXR.
*
* EXR ( Extended Dynamic Range) is an [open format specification]{@link https://github.com/AcademySoftwareFoundation/openexr}
* for professional-grade image storage format of the motion picture industry. The purpose of
* format is to accurately and efficiently represent high-dynamic-range scene-linear image data
* and associated metadata. The library is widely used in host application software where accuracy
* is critical, such as photorealistic rendering, texture access, image compositing, deep compositing,
* and DI.
*
* ```js
* const exporter = new EXRExporter();
* const result = await exporter.parse( renderer, options );
* ```
*/
class EXRExporter {
/**
* This method has two variants.
*
* - When exporting a data texture, it receives two parameters. The texture and the exporter options.
* - When exporting a render target (e.g. a PMREM), it receives three parameters. The renderer, the
* render target and the exporter options.
*
* @async
* @param {(DataTexture|WebGPURenderer|WebGLRenderer)} arg1 - The data texture to export or a renderer.
* @param {(EXRExporter~Options|RenderTarget)} arg2 - The exporter options or a render target.
* @param {EXRExporter~Options} [arg3] - The exporter options.
* @return {Promise<Uint8Array>} A Promise that resolves with the exported EXR.
*/
async parse( arg1, arg2, arg3 ) {

@@ -29,3 +50,3 @@

throw Error( 'EXRExporter.parse: Unsupported first parameter, expected instance of WebGLRenderer or DataTexture.' );
throw Error( 'EXRExporter.parse: Unsupported first parameter, expected instance of WebGLRenderer, WebGPURenderer or DataTexture.' );

@@ -589,2 +610,10 @@ } else if ( arg1.isWebGLRenderer || arg1.isWebGPURenderer ) {

/**
* Export options of `EXRExporter`.
*
* @typedef {Object} EXRExporter~Options
* @property {(HalfFloatType|FloatType)} [type=HalfFloatType] - Output data type.
* @property {(NO_COMPRESSION|ZIP_COMPRESSION|ZIPS_COMPRESSION)} [type=ZIP_COMPRESSION] - The compression algorithm.
**/
export { EXRExporter, NO_COMPRESSION, ZIP_COMPRESSION, ZIPS_COMPRESSION };

@@ -130,4 +130,24 @@ import {

/**
* An exporter for KTX2.
*
* ```js
* const exporter = new KTX2Exporter();
* const result = await exporter.parse( dataTexture );
* ```
*/
export class KTX2Exporter {
/**
* This method has two variants.
*
* - When exporting a data texture, it receives one parameter. The data or 3D data texture.
* - When exporting a render target (e.g. a PMREM), it receives two parameters. The renderer and the
* render target.
*
* @async
* @param {(DataTexture|Data3DTexture|WebGPURenderer|WebGLRenderer)} arg1 - The data texture to export or a renderer.
* @param {RenderTarget} [arg2] - The render target that should be exported
* @return {Promise<Uint8Array>} A Promise that resolves with the exported KTX2.
*/
async parse( arg1, arg2 ) {

@@ -134,0 +154,0 @@

@@ -10,4 +10,22 @@ import {

/**
* An exporter for OBJ.
*
* `OBJExporter` is not able to export material data into MTL files so only geometry data are supported.
*
* ```js
* const exporter = new OBJExporter();
* const data = exporter.parse( scene );
* ```
*/
class OBJExporter {
/**
* Parses the given 3D object and generates the OBJ output.
*
* If the 3D object is composed of multiple children and geometry, they are merged into a single mesh in the file.
*
* @param {Object3D} object - The 3D object to export.
* @return {string} The exported OBJ.
*/
parse( object ) {

@@ -14,0 +32,0 @@

@@ -10,18 +10,30 @@ import {

/**
* https://github.com/gkjohnson/ply-exporter-js
* An exporter for PLY.
*
* Usage:
* const exporter = new PLYExporter();
* PLY (Polygon or Stanford Triangle Format) is a file format for efficient delivery and
* loading of simple, static 3D content in a dense format. Both binary and ascii formats are
* supported. PLY can store vertex positions, colors, normals and uv coordinates. No textures
* or texture references are saved.
*
* // second argument is a list of options
* exporter.parse(mesh, data => console.log(data), { binary: true, excludeAttributes: [ 'color' ], littleEndian: true });
*
* Format Definition:
* http://paulbourke.net/dataformats/ply/
* ```js
* const exporter = new PLYExporter();
* const data = exporter.parse( scene, options );
* ```
*/
class PLYExporter {
/**
* Parses the given 3D object and generates the PLY output.
*
* If the 3D object is composed of multiple children and geometry, they are merged into a single mesh in the file.
*
* @param {Object3D} object - The 3D object to export.
* @param {PLYExporter~OnDone} onDone - A callback function that is executed when the export has finished.
* @param {PLYExporter~Options} options - The export options.
* @return {?string|ArrayBuffer} The exported PLY.
*/
parse( object, onDone, options = {} ) {
// reference https://github.com/gkjohnson/ply-exporter-js
// Iterate over the valid meshes in the object

@@ -531,2 +543,20 @@ function traverseMeshes( cb ) {

/**
* Export options of `PLYExporter`.
*
* @typedef {Object} PLYExporter~Options
* @property {boolean} [binary=false] - Whether to export in binary format or ASCII.
* @property {Array<string>} [excludeAttributes] - Which properties to explicitly exclude from
* the exported PLY file. Valid values are `'color'`, `'normal'`, `'uv'`, and `'index'`. If triangle
* indices are excluded, then a point cloud is exported.
* @property {boolean} [littleEndian=false] - Whether the binary export uses little or big endian.
**/
/**
* onDone callback of `PLYExporter`.
*
* @callback PLYExporter~OnDone
* @param {string|ArrayBuffer} result - The generated PLY ascii or binary.
*/
export { PLYExporter };
import { Vector3 } from 'three';
/**
* Usage:
* const exporter = new STLExporter();
* An exporter for STL.
*
* // second argument is a list of options
* const data = exporter.parse( mesh, { binary: true } );
* STL files describe only the surface geometry of a three-dimensional object without
* any representation of color, texture or other common model attributes. The STL format
* specifies both ASCII and binary representations, with binary being more compact.
* STL files contain no scale information or indexes, and the units are arbitrary.
*
* ```js
* const exporter = new STLExporter();
* const data = exporter.parse( mesh, { binary: true } );
* ```
*/
class STLExporter {
/**
* Parses the given 3D object and generates the STL output.
*
* If the 3D object is composed of multiple children and geometry, they are merged into a single mesh in the file.
*
* @param {Object3D} scene - A scene, mesh or any other 3D object containing meshes to encode.
* @param {STLExporter~Options} options - The export options.
* @return {string|ArrayBuffer} The exported STL.
*/
parse( scene, options = {} ) {

@@ -199,2 +212,9 @@

/**
* Export options of `STLExporter`.
*
* @typedef {Object} STLExporter~Options
* @property {boolean} [binary=false] - Whether to export in binary format or ASCII.
**/
export { STLExporter };

@@ -12,6 +12,23 @@ import {

/**
* An exporter for USDZ.
*
* ```js
* const exporter = new USDZExporter();
* const arraybuffer = await exporter.parseAsync( scene );
* ```
*/
class USDZExporter {
/**
* Constructs a new USDZ exporter.
*/
constructor() {
/**
* A reference to a texture utils module.
*
* @type {?(WebGLTextureUtils|WebGPUTextureUtils)}
* @default null
*/
this.textureUtils = null;

@@ -21,2 +38,10 @@

/**
* Sets the texture utils for this exporter. Only relevant when compressed textures have to be exported.
*
* Depending on whether you use {@link WebGLRenderer} or {@link WebGPURenderer}, you must inject the
* corresponding texture utils {@link WebGLTextureUtils} or {@link WebGPUTextureUtils}.
*
* @param {WebGLTextureUtils|WebGPUTextureUtils} utils - The texture utils.
*/
setTextureUtils( utils ) {

@@ -28,2 +53,10 @@

/**
* Parse the given 3D object and generates the USDZ output.
*
* @param {Object3D} scene - The 3D object to export.
* @param {USDZExporter~OnDone} onDone - A callback function that is executed when the export has finished.
* @param {USDZExporter~OnError} onError - A callback function that is executed when an error happens.
* @param {USDZExporter~Options} options - The export options.
*/
parse( scene, onDone, onError, options ) {

@@ -35,2 +68,10 @@

/**
* Async version of {@link USDZExporter#parse}.
*
* @async
* @param {Object3D} scene - The 3D object to export.
* @param {USDZExporter~Options} options - The export options.
* @return {Promise<ArrayBuffer>} A Promise that resolved with the exported USDZ data.
*/
async parseAsync( scene, options = {} ) {

@@ -85,3 +126,3 @@

output += buildXform( object, geometry, material );
output += buildXform( object, geometry, materials[ material.uuid ] );

@@ -763,3 +804,3 @@ } else {

}
`;

@@ -781,3 +822,3 @@

}
`;

@@ -789,2 +830,28 @@

/**
* Export options of `USDZExporter`.
*
* @typedef {Object} USDZExporter~Options
* @property {number} [maxTextureSize=1024] - The maximum texture size that is going to be exported.
* @property {boolean} [includeAnchoringProperties=false] - Whether to include anchoring properties or not.
* @property {Object} [ar] - If `includeAnchoringProperties` is set to `true`, the anchoring type and alignment
* can be configured via `ar.anchoring.type` and `ar.planeAnchoring.alignment`.
* @property {boolean} [quickLookCompatible=false] - Whether to make the exported USDZ compatible to QuickLook
* which means the asset is modified to accommodate the bugs FB10036297 and FB11442287 (Apple Feedback).
**/
/**
* onDone callback of `USDZExporter`.
*
* @callback USDZExporter~OnDone
* @param {ArrayBuffer} result - The generated USDZ.
*/
/**
* onError callback of `USDZExporter`.
*
* @callback USDZExporter~OnError
* @param {Error} error - The error object.
*/
export { USDZExporter };

@@ -6,4 +6,26 @@ import {

/**
* A special type of box geometry intended for {@link LineSegments}.
*
* ```js
* const geometry = new THREE.BoxLineGeometry();
* const material = new THREE.LineBasicMaterial( { color: 0x00ff00 } );
* const lines = new THREE.LineSegments( geometry, material );
* scene.add( lines );
* ```
*
* @augments BufferGeometry
*/
class BoxLineGeometry extends BufferGeometry {
/**
* Constructs a new box line geometry.
*
* @param {number} [width=1] - The width. That is, the length of the edges parallel to the X axis.
* @param {number} [height=1] - The height. That is, the length of the edges parallel to the Y axis.
* @param {number} [depth=1] - The depth. That is, the length of the edges parallel to the Z axis.
* @param {number} [widthSegments=1] - Number of segmented rectangular sections along the width of the sides.
* @param {number} [heightSegments=1] - Number of segmented rectangular sections along the height of the sides.
* @param {number} [depthSegments=1] - Number of segmented rectangular sections along the depth of the sides.
*/
constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) {

@@ -10,0 +32,0 @@

@@ -7,4 +7,22 @@ import {

/**
* This class can be used to generate a convex hull for a given array of 3D points.
* The average time complexity for this task is considered to be O(nlog(n)).
*
* ```js
* const geometry = new ConvexGeometry( points );
* const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
* const mesh = new THREE.Mesh( geometry, material );
* scene.add( mesh );
* ```
*
* @augments BufferGeometry
*/
class ConvexGeometry extends BufferGeometry {
/**
* Constructs a new convex geometry.
*
* @param {Array<Vector3>} points - An array of points in 3D space which should be enclosed by the convex hull.
*/
constructor( points = [] ) {

@@ -11,0 +29,0 @@

@@ -12,18 +12,29 @@ import {

/**
* You can use this geometry to create a decal mesh, that serves different kinds of purposes.
* e.g. adding unique details to models, performing dynamic visual environmental changes or covering seams.
* This class can be used to create a decal mesh that serves different kinds of purposes e.g.
* adding unique details to models, performing dynamic visual environmental changes or covering seams.
*
* Constructor parameter:
* Please not that decal projections can be distorted when used around corners. More information at
* this GitHub issue: [Decal projections without distortions]{@link https://github.com/mrdoob/three.js/issues/21187}.
*
* mesh — Any mesh object
* position — Position of the decal projector
* orientation — Orientation of the decal projector
* size — Size of the decal projector
* Reference: [How to project decals]{@link http://blog.wolfire.com/2009/06/how-to-project-decals/}
*
* reference: http://blog.wolfire.com/2009/06/how-to-project-decals/
* ```js
* const geometry = new DecalGeometry( mesh, position, orientation, size );
* const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
* const mesh = new THREE.Mesh( geometry, material );
* scene.add( mesh );
* ```
*
* @augments BufferGeometry
*/
class DecalGeometry extends BufferGeometry {
/**
* Constructs a new decal geometry.
*
* @param {Mesh} [mesh] - The base mesh the decal should be projected on.
* @param {Vector3} [position] - The position of the decal projector.
* @param {Euler} [orientation] - The orientation of the decal projector.
* @param {Vector3} [size] - Tje scale of the decal projector.
*/
constructor( mesh = new Mesh(), position = new Vector3(), orientation = new Euler(), size = new Vector3( 1, 1, 1 ) ) {

@@ -30,0 +41,0 @@

@@ -1,6 +0,1 @@

/**
* Parametric Surfaces Geometry
* based on the brilliant article by @prideout https://prideout.net/blog/old/blog/index.html@p=44.html
*/
import {

@@ -12,4 +7,25 @@ BufferGeometry,

/**
* This class can be used to generate a geometry based on a parametric surface.
*
* Reference: [Mesh Generation with Python]{@link https://prideout.net/blog/old/blog/index.html@p=44.html}
*
* ```js
* const geometry = new THREE.ParametricGeometry( klein, 25, 25 );
* const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
* const klein = new THREE.Mesh( geometry, material );
* scene.add( klein );
* ```
*
* @augments BufferGeometry
*/
class ParametricGeometry extends BufferGeometry {
/**
* Constructs a new parametric geometry.
*
* @param {ParametricGeometry~Func} func - The parametric function. Default is a function that generates a curved plane surface.
* @param {number} [slices=8] - The number of slices to use for the parametric function.
* @param {number} [stacks=8] - The stacks of slices to use for the parametric function.
*/
constructor( func = ( u, v, target ) => target.set( u, v, Math.cos( u ) * Math.sin( v ) ), slices = 8, stacks = 8 ) {

@@ -21,2 +37,9 @@

/**
* Holds the constructor parameters that have been
* used to generate the geometry. Any modification
* after instantiation does not change the geometry.
*
* @type {Object}
*/
this.parameters = {

@@ -141,2 +164,11 @@ func: func,

/**
* Parametric function definition of `ParametricGeometry`.
*
* @callback ParametricGeometry~Func
* @param {number} u - The `u` coordinate on the surface in the range `[0,1]`.
* @param {number} v - The `v` coordinate on the surface in the range `[0,1]`.
* @param {Vector3} target - The target vector that is used to store the method's result.
*/
export { ParametricGeometry };

@@ -41,4 +41,25 @@ import {

/**
* A special type of box geometry with rounded corners and edges.
*
* ```js
* const geometry = new THREE.RoundedBoxGeometry();
* const material = new THREE.MeshStandardMaterial( { color: 0x00ff00 } );
* const cube = new THREE.Mesh( geometry, material );
* scene.add( cube );
* ```
*
* @augments BoxGeometry
*/
class RoundedBoxGeometry extends BoxGeometry {
/**
* Constructs a new rounded box geometry.
*
* @param {number} [width=1] - The width. That is, the length of the edges parallel to the X axis.
* @param {number} [height=1] - The height. That is, the length of the edges parallel to the Y axis.
* @param {number} [depth=1] - The depth. That is, the length of the edges parallel to the Z axis.
* @param {number} [segments=2] - Number of segmented that form the rounded corners.
* @param {number} [radius=0.1] - The radius of the rounded corners.
*/
constructor( width = 1, height = 1, depth = 1, segments = 2, radius = 0.1 ) {

@@ -45,0 +66,0 @@

@@ -12,49 +12,33 @@ import {

*
* Parameters: size = 50, segments = 10, bottom = true, lid = true, body = true,
* fitLid = true, blinn = true
*
* size is a relative scale: I've scaled the teapot to fit vertically between -1 and 1.
* Think of it as a "radius".
* segments - number of line segments to subdivide each patch edge;
* 1 is possible but gives degenerates, so two is the real minimum.
* bottom - boolean, if true (default) then the bottom patches are added. Some consider
* adding the bottom heresy, so set this to "false" to adhere to the One True Way.
* lid - to remove the lid and look inside, set to true.
* body - to remove the body and leave the lid, set this and "bottom" to false.
* fitLid - the lid is a tad small in the original. This stretches it a bit so you can't
* see the teapot's insides through the gap.
* blinn - Jim Blinn scaled the original data vertically by dividing by about 1.3 to look
* nicer. If you want to see the original teapot, similar to the real-world model, set
* this to false. True by default.
* See http://en.wikipedia.org/wiki/File:Original_Utah_Teapot.jpg for the original
* real-world teapot (from http://en.wikipedia.org/wiki/Utah_teapot).
*
* Note that the bottom (the last four patches) is not flat - blame Frank Crow, not me.
*
* The teapot should normally be rendered as a double sided object, since for some
* patches both sides can be seen, e.g., the gap around the lid and inside the spout.
*
* Segments 'n' determines the number of triangles output.
* Total triangles = 32*2*n*n - 8*n [degenerates at the top and bottom cusps are deleted]
* Segments 'n' determines the number of triangles output. Total triangles = 32*2*n*n - 8*n
* (degenerates at the top and bottom cusps are deleted).
*
* size_factor # triangles
* 1 56
* 2 240
* 3 552
* 4 992
* Code based on [SPD software]{@link http://tog.acm.org/resources/SPD/}
* Created for the Udacity course [Interactive Rendering]{@link http://bit.ly/ericity}
*
* 10 6320
* 20 25440
* 30 57360
* ```js
* const geometry = new TeapotGeometry( 50, 18 );
* const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
* const teapot = new THREE.Mesh( geometry, material );
* scene.add( teapot );
* ```
*
* Code converted from my ancient SPD software, http://tog.acm.org/resources/SPD/
* Created for the Udacity course "Interactive Rendering", http://bit.ly/ericity
* YouTube video on teapot history: https://www.youtube.com/watch?v=DxMfblPzFNc
*
* See https://en.wikipedia.org/wiki/Utah_teapot for the history of the teapot
*
* @augments BufferGeometry
*/
class TeapotGeometry extends BufferGeometry {
/**
* Constructs a new teapot geometry.
*
* @param {number} [size=50] - Relative scale of the teapot.
* @param {number} [segments=10] - Number of line segments to subdivide each patch edge.
* @param {boolean} [bottom=true] - Whether the bottom of the teapot is generated or not.
* @param {boolean} [lid=true] - Whether the lid is generated or not.
* @param {boolean} [body=true] - Whether the body is generated or not.
* @param {boolean} [fitLid=true] - Whether the lid is slightly stretched to prevent gaps between the body and lid or not.
* @param {boolean} [blinn=true] - Whether the teapot is scaled vertically for better aesthetics or not.
*/
constructor( size = 50, segments = 10, bottom = true, lid = true, body = true, fitLid = true, blinn = true ) {

@@ -61,0 +45,0 @@

@@ -0,24 +1,35 @@

import {
ExtrudeGeometry
} from 'three';
/**
* Text = 3D Text
* A class for generating text as a single geometry. It is constructed by providing a string of text, and a set of
* parameters consisting of a loaded font and extrude settings.
*
* parameters = {
* font: <THREE.Font>, // font
* See the {@link FontLoader} page for additional details.
*
* size: <float>, // size of the text
* depth: <float>, // thickness to extrude text
* curveSegments: <int>, // number of points on the curves
* `TextGeometry` uses [typeface.json]{@link http://gero3.github.io/facetype.js/} generated fonts.
* Some existing fonts can be found located in `/examples/fonts`.
*
* bevelEnabled: <bool>, // turn on bevel
* bevelThickness: <float>, // how deep into text bevel goes
* bevelSize: <float>, // how far from text outline (including bevelOffset) is bevel
* bevelOffset: <float> // how far from text outline does bevel start
* }
* ```js
* const loader = new FontLoader();
* const font = await loader.loadAsync( 'fonts/helvetiker_regular.typeface.json' );
* const geometry = new TextGeometry( 'Hello three.js!', {
* font: font,
* size: 80,
* depth: 5,
* curveSegments: 12
* } );
* ```
*
* @augments ExtrudeGeometry
*/
import {
ExtrudeGeometry
} from 'three';
class TextGeometry extends ExtrudeGeometry {
/**
* Constructs a new text geometry.
*
* @param {string} text - The text that should be transformed into a geometry.
* @param {TextGeometry~Options} [parameters] - The text settings.
*/
constructor( text, parameters = {} ) {

@@ -53,3 +64,20 @@

/**
* Represents the `options` type of the geometry's constructor.
*
* @typedef {Object} TextGeometry~Options
* @property {Font} [font] - The font.
* @property {number} [size=100] - The text size.
* @property {number} [depth=50] - Depth to extrude the shape.
* @property {number} [curveSegments=12] - Number of points on the curves.
* @property {number} [steps=1] - Number of points used for subdividing segments along the depth of the extruded spline.
* @property {boolean} [bevelEnabled=false] - Whether to beveling to the shape or not.
* @property {number} [bevelThickness=10] - How deep into the original shape the bevel goes.
* @property {number} [bevelSize=8] - Distance from the shape outline that the bevel extends.
* @property {number} [bevelOffset=0] - Distance from the shape outline that the bevel starts.
* @property {number} [bevelSegments=3] - Number of bevel layers.
* @property {?Curve} [extrudePath=null] - A 3D spline path along which the shape should be extruded. Bevels not supported for path extrusion.
* @property {Object} [UVGenerator] - An object that provides UV generator functions for custom UV generation.
**/
export { TextGeometry };

@@ -7,4 +7,23 @@ import {

/**
* Renders a sphere to visualize a light probe in the scene.
*
* This helper can only be used with {@link WebGLRenderer}.
* When using {@link WebGPURenderer}, import from `LightProbeHelperGPU.js`.
*
* ```js
* const helper = new LightProbeHelper( lightProbe );
* scene.add( helper );
* ```
*
* @augments Mesh
*/
class LightProbeHelper extends Mesh {
/**
* Constructs a new light probe helper.
*
* @param {LightProbe} lightProbe - The light probe to visualize.
* @param {number} [size=1] - The size of the helper.
*/
constructor( lightProbe, size = 1 ) {

@@ -103,3 +122,15 @@

/**
* The light probe to visualize.
*
* @type {LightProbe}
*/
this.lightProbe = lightProbe;
/**
* The size of the helper.
*
* @type {number}
* @default 1
*/
this.size = size;

@@ -112,2 +143,6 @@ this.type = 'LightProbeHelper';

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*/
dispose() {

@@ -114,0 +149,0 @@

@@ -8,4 +8,24 @@ import {

/**
* Renders a sphere to visualize a light probe in the scene.
*
* This helper can only be used with {@link WebGPURenderer}.
* When using {@link WebGLRenderer}, import from `LightProbeHelper.js`.
*
* ```js
* const helper = new LightProbeHelper( lightProbe );
* scene.add( helper );
* ```
*
* @private
* @augments Mesh
*/
class LightProbeHelper extends Mesh {
/**
* Constructs a new light probe helper.
*
* @param {LightProbe} lightProbe - The light probe to visualize.
* @param {number} [size=1] - The size of the helper.
*/
constructor( lightProbe, size = 1 ) {

@@ -35,3 +55,15 @@

/**
* The light probe to visualize.
*
* @type {LightProbe}
*/
this.lightProbe = lightProbe;
/**
* The size of the helper.
*
* @type {number}
* @default 1
*/
this.size = size;

@@ -47,2 +79,6 @@ this.type = 'LightProbeHelper';

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*/
dispose() {

@@ -49,0 +85,0 @@

@@ -8,4 +8,20 @@ import {

/**
* A helper for visualizing an Octree.
*
* ```js
* const helper = new OctreeHelper( octree );
* scene.add( helper );
* ```
*
* @augments LineSegments
*/
class OctreeHelper extends LineSegments {
/**
* Constructs a new Octree helper.
*
* @param {Octree} octree - The octree to visualize.
* @param {number|Color|string} [color=0xffff00] - The helper's color.
*/
constructor( octree, color = 0xffff00 ) {

@@ -15,3 +31,14 @@

/**
* The octree to visualize.
*
* @type {Octree}
*/
this.octree = octree;
/**
* The helper's color.
*
* @type {number|Color|string}
*/
this.color = color;

@@ -25,2 +52,6 @@

/**
* Updates the helper. This method must be called whenever the Octree's
* structure is changed.
*/
update() {

@@ -67,2 +98,6 @@

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*/
dispose() {

@@ -69,0 +104,0 @@

@@ -9,4 +9,28 @@ import {

/**
* This helper displays the directional cone of a positional audio.
*
* `PositionalAudioHelper` must be added as a child of the positional audio.
*
* ```js
* const positionalAudio = new THREE.PositionalAudio( listener );
* positionalAudio.setDirectionalCone( 180, 230, 0.1 );
* scene.add( positionalAudio );
*
* const helper = new PositionalAudioHelper( positionalAudio );
* positionalAudio.add( helper );
* ```
*
* @augments Line
*/
class PositionalAudioHelper extends Line {
/**
* Constructs a new positional audio helper.
*
* @param {PositionalAudio} audio - The audio to visualize.
* @param {number} [range=1] - The range of the directional cone.
* @param {number} [divisionsInnerAngle=16] - The number of divisions of the inner part of the directional cone.
* @param {number} [divisionsOuterAngle=2] The number of divisions of the outer part of the directional cone.
*/
constructor( audio, range = 1, divisionsInnerAngle = 16, divisionsOuterAngle = 2 ) {

@@ -24,6 +48,33 @@

/**
* The audio to visualize.
*
* @type {PositionalAudio}
*/
this.audio = audio;
/**
* The range of the directional cone.
*
* @type {number}
* @default 1
*/
this.range = range;
/**
* The number of divisions of the inner part of the directional cone.
*
* @type {number}
* @default 16
*/
this.divisionsInnerAngle = divisionsInnerAngle;
/**
* The number of divisions of the outer part of the directional cone.
*
* @type {number}
* @default 2
*/
this.divisionsOuterAngle = divisionsOuterAngle;
this.type = 'PositionalAudioHelper';

@@ -35,2 +86,6 @@

/**
* Updates the helper. This method must be called whenever the directional cone
* of the positional audio is changed.
*/
update() {

@@ -101,2 +156,6 @@

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*/
dispose() {

@@ -103,0 +162,0 @@

@@ -12,7 +12,23 @@ import {

/**
* This helper must be added as a child of the light
* Creates a visual aid for rect area lights.
*
* `RectAreaLightHelper` must be added as a child of the light.
*
* ```js
* const light = new THREE.RectAreaLight( 0xffffbb, 1.0, 5, 5 );
* const helper = new RectAreaLightHelper( light );
* light.add( helper );
* ```
*
* @augments Line
*/
class RectAreaLightHelper extends Line {
/**
* Constructs a new rect area light helper.
*
* @param {RectAreaLight} light - The light to visualize.
* @param {number|Color|string} [color] - The helper's color.
* If this is not the set, the helper will take the color of the light.
*/
constructor( light, color ) {

@@ -30,4 +46,16 @@

/**
* The light to visualize.
*
* @type {RectAreaLight}
*/
this.light = light;
this.color = color; // optional hardwired color for the helper
/**
* The helper's color. If `undefined`, the helper will take the color of the light.
*
* @type {number|Color|string|undefined}
*/
this.color = color;
this.type = 'RectAreaLightHelper';

@@ -76,2 +104,6 @@

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*/
dispose() {

@@ -78,0 +110,0 @@

@@ -12,4 +12,22 @@ import {

/**
* A helper that can be used to display any type of texture for
* debugging purposes. Depending on the type of texture (2D, 3D, Array),
* the helper becomes a plane or box mesh.
*
* This helper can only be used with {@link WebGLRenderer}.
* When using {@link WebGPURenderer}, import from `TextureHelperGPU.js`.
*
* @augments Mesh
*/
class TextureHelper extends Mesh {
/**
* Constructs a new texture helper.
*
* @param {Texture} texture - The texture to visualize.
* @param {number} [width=1] - The helper's width.
* @param {number} [height=1] - The helper's height.
* @param {number} [depth=1] - The helper's depth.
*/
constructor( texture, width = 1, height = 1, depth = 1 ) {

@@ -85,2 +103,7 @@

/**
* The texture to visualize.
*
* @type {Texture}
*/
this.texture = texture;

@@ -91,2 +114,6 @@ this.type = 'TextureHelper';

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*/
dispose() {

@@ -93,0 +120,0 @@

@@ -13,4 +13,23 @@ import {

/**
* A helper that can be used to display any type of texture for
* debugging purposes. Depending on the type of texture (2D, 3D, Array),
* the helper becomes a plane or box mesh.
*
* This helper can only be used with {@link WebGPURenderer}.
* When using {@link WebGLRenderer}, import from `TextureHelper.js`.
*
* @private
* @augments Mesh
*/
class TextureHelper extends Mesh {
/**
* Constructs a new texture helper.
*
* @param {Texture} texture - The texture to visualize.
* @param {number} [width=1] - The helper's width.
* @param {number} [height=1] - The helper's height.
* @param {number} [depth=1] - The helper's depth.
*/
constructor( texture, width = 1, height = 1, depth = 1 ) {

@@ -55,2 +74,7 @@

/**
* The texture to visualize.
*
* @type {Texture}
*/
this.texture = texture;

@@ -61,2 +85,6 @@ this.type = 'TextureHelper';

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*/
dispose() {

@@ -63,0 +91,0 @@

@@ -14,4 +14,28 @@ import {

/**
* Visualizes an object's vertex normals.
*
* Requires that normals have been specified in the geometry as a buffer attribute or
* have been calculated using {@link BufferGeometry#computeVertexNormals}.
* ```js
* const geometry = new THREE.BoxGeometry( 10, 10, 10, 2, 2, 2 );
* const material = new THREE.MeshStandardMaterial();
* const mesh = new THREE.Mesh( geometry, material );
* scene.add( mesh );
*
* const helper = new VertexNormalsHelper( mesh, 1, 0xff0000 );
* scene.add( helper );
* ```
*
* @augments LineSegments
*/
class VertexNormalsHelper extends LineSegments {
/**
* Constructs a new vertex normals helper.
*
* @param {Object3D} object - The object for which to visualize vertex normals.
* @param {number} [size=1] - The helper's size.
* @param {number|Color|string} [color=0xff0000] - The helper's color.
*/
constructor( object, size = 1, color = 0xff0000 ) {

@@ -28,10 +52,35 @@

/**
* The object for which to visualize vertex normals.
*
* @type {Object3D}
*/
this.object = object;
/**
* The helper's size.
*
* @type {number}
* @default 1
*/
this.size = size;
this.type = 'VertexNormalsHelper';
//
/**
* Overwritten and set to `false` since the object's world transformation
* is encoded in the helper's geometry data.
*
* @type {boolean}
* @default false
*/
this.matrixAutoUpdate = false;
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isVertexNormalsHelper = true;

@@ -43,2 +92,5 @@

/**
* Updates the vertex normals preview based on the object's world transform.
*/
update() {

@@ -92,2 +144,6 @@

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*/
dispose() {

@@ -94,0 +150,0 @@

@@ -12,4 +12,23 @@ import {

/**
* Visualizes an object's vertex tangents.
*
* Requires that tangents have been specified in the geometry as a buffer attribute or
* have been calculated using {@link BufferGeometry#computeTangents}.
* ```js
* const helper = new VertexTangentsHelper( mesh, 1, 0xff0000 );
* scene.add( helper );
* ```
*
* @augments LineSegments
*/
class VertexTangentsHelper extends LineSegments {
/**
* Constructs a new vertex tangents helper.
*
* @param {Object3D} object - The object for which to visualize vertex tangents.
* @param {number} [size=1] - The helper's size.
* @param {number|Color|string} [color=0xff0000] - The helper's color.
*/
constructor( object, size = 1, color = 0x00ffff ) {

@@ -26,8 +45,26 @@

/**
* The object for which to visualize vertex tangents.
*
* @type {Object3D}
*/
this.object = object;
/**
* The helper's size.
*
* @type {number}
* @default 1
*/
this.size = size;
this.type = 'VertexTangentsHelper';
//
/**
* Overwritten and set to `false` since the object's world transformation
* is encoded in the helper's geometry data.
*
* @type {boolean}
* @default false
*/
this.matrixAutoUpdate = false;

@@ -39,2 +76,5 @@

/**
* Updates the vertex normals preview based on the object's world transform.
*/
update() {

@@ -82,2 +122,6 @@

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*/
dispose() {

@@ -84,0 +128,0 @@

@@ -20,4 +20,20 @@ import {

/**
* A special type of helper that visualizes the camera's transformation
* in a small viewport area as an axes helper. Such a helper is often wanted
* in 3D modeling tools or scene editors like the [three.js editor]{@link https://threejs.org/editor}.
*
* The helper allows to click on the X, Y and Z axes which animates the camera
* so it looks along the selected axis.
*
* @augments Object3D
*/
class ViewHelper extends Object3D {
/**
* Constructs a new view helper.
*
* @param {Camera} camera - The camera whose transformation should be visualized.
* @param {HTMLDOMElement} [domElement] - The DOM element that is used to render the view.
*/
constructor( camera, domElement ) {

@@ -27,5 +43,25 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isViewHelper = true;
/**
* Whether the helper is currently animating or not.
*
* @type {boolean}
* @readonly
* @default false
*/
this.animating = false;
/**
* The helper's center point.
*
* @type {Vector3}
*/
this.center = new Vector3();

@@ -109,2 +145,8 @@

/**
* Renders the helper in a separate view in the bottom-right corner
* of the viewport.
*
* @param {WebGLRenderer|WebGPURenderer} renderer - The renderer.
*/
this.render = function ( renderer ) {

@@ -121,2 +163,3 @@

const x = domElement.offsetWidth - dim;
const y = renderer.isWebGPURenderer ? domElement.offsetHeight - dim : 0;

@@ -126,3 +169,3 @@ renderer.clearDepth();

renderer.getViewport( viewport );
renderer.setViewport( x, 0, dim, dim );
renderer.setViewport( x, y, dim, dim );

@@ -143,2 +186,9 @@ renderer.render( this, orthoCamera );

/**
* This method should be called when a click or pointer event
* has happened in the app.
*
* @param {PointerEvent} event - The event to process.
* @return {boolean} Whether an intersection with the helper has been detected or not.
*/
this.handleClick = function ( event ) {

@@ -177,2 +227,9 @@

/**
* Sets labels for each axis. By default, they are unlabeled.
*
* @param {string|undefined} labelX - The label for the x-axis.
* @param {string|undefined} labelY - The label for the y-axis.
* @param {string|undefined} labelZ - The label for the z-axis.
*/
this.setLabels = function ( labelX, labelY, labelZ ) {

@@ -188,2 +245,9 @@

/**
* Sets the label style. Has no effect when the axes are unlabeled.
*
* @param {string} [font='24px Arial'] - The label font.
* @param {string} [color='#000000'] - The label color.
* @param {number} [radius=14] - The label radius.
*/
this.setLabelStyle = function ( font, color, radius ) {

@@ -199,2 +263,8 @@

/**
* Updates the helper. This method should be called in the app's animation
* loop.
*
* @param {number} delta - The delta time in seconds.
*/
this.update = function ( delta ) {

@@ -221,2 +291,6 @@

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*/
this.dispose = function () {

@@ -223,0 +297,0 @@

@@ -11,4 +11,25 @@ import {

/**
* This class can be used to render a DOM element onto a canvas and use it as a texture
* for a plane mesh.
*
* A typical use case for this class is to render the GUI of `lil-gui` as a texture so it
* is compatible for VR.
*
* ```js
* const gui = new GUI( { width: 300 } ); // create lil-gui instance
*
* const mesh = new HTMLMesh( gui.domElement );
* scene.add( mesh );
* ```
*
* @augments Mesh
*/
class HTMLMesh extends Mesh {
/**
* Constructs a new HTML mesh.
*
* @param {HTMLElement} dom - The DOM element to display as a plane mesh.
*/
constructor( dom ) {

@@ -34,2 +55,6 @@

/**
* Frees the GPU-related resources allocated by this instance and removes all event listeners.
* Call this method whenever this instance is no longer used in your app.
*/
this.dispose = function () {

@@ -36,0 +61,0 @@

@@ -10,7 +10,3 @@ import {

// TODO: Dispatch pointerevents too
/**
* The XR events that are mapped to "standard" pointer events
*/
// The XR events that are mapped to "standard" pointer events.
const _events = {

@@ -25,2 +21,20 @@ 'move': 'mousemove',

/**
* This class can be used to group 3D objects in an interactive group.
* The group itself can listen to Pointer, Mouse or XR controller events to
* detect selections of descendant 3D objects. If a 3D object is selected,
* the respective event is going to dispatched to it.
*
* ```js
* const group = new InteractiveGroup();
* group.listenToPointerEvents( renderer, camera );
* group.listenToXRControllerEvents( controller1 );
* group.listenToXRControllerEvents( controller2 );
* scene.add( group );
*
* // now add objects that should be interactive
* group.add( mesh1, mesh2, mesh3 );
* ```
* @augments Group
*/
class InteractiveGroup extends Group {

@@ -32,7 +46,30 @@

/**
* The internal raycaster.
*
* @type {Raycaster}
*/
this.raycaster = new Raycaster();
/**
* The internal raycaster.
*
* @type {?HTMLDOMElement}
* @default null
*/
this.element = null;
/**
* The camera used for raycasting.
*
* @type {?Camera}
* @default null
*/
this.camera = null;
/**
* An array of XR controllers.
*
* @type {Array<Group>}
*/
this.controllers = [];

@@ -98,2 +135,10 @@

/**
* Calling this method makes sure the interactive group listens to Pointer and Mouse events.
* The target is the `domElement` of the given renderer. The camera is required for the internal
* raycasting so 3D objects can be detected based on the events.
*
* @param {(WebGPURenderer|WebGLRenderer)} renderer - The renderer.
* @param {Camera} camera - The camera.
*/
listenToPointerEvents( renderer, camera ) {

@@ -114,2 +159,5 @@

/**
* Disconnects this interactive group from all Pointer and Mouse Events.
*/
disconnectionPointerEvents() {

@@ -131,2 +179,8 @@

/**
* Calling this method makes sure the interactive group listens to events of
* the given XR controller.
*
* @param {Group} controller - The XR controller.
*/
listenToXRControllerEvents( controller ) {

@@ -142,2 +196,5 @@

/**
* Disconnects this interactive group from all XR controllers.
*/
disconnectXrControllerEvents() {

@@ -156,2 +213,5 @@

/**
* Disconnects this interactive group from the DOM and all XR controllers.
*/
disconnect() {

@@ -158,0 +218,0 @@

@@ -8,6 +8,2 @@ import {

/**
* This is a class to check whether objects are in a selection area in 3D space
*/
const _frustum = new Frustum();

@@ -37,12 +33,70 @@ const _center = new Vector3();

/**
* This class can be used to select 3D objects in a scene with a selection box.
* It is recommended to visualize the selected area with the help of {@link SelectionHelper}.
*
* ```js
* const selectionBox = new SelectionBox( camera, scene );
* const selectedObjects = selectionBox.select( startPoint, endPoint );
* ```
*/
class SelectionBox {
/**
* Constructs a new selection box.
*
* @param {Camera} camera - The camera the scene is rendered with.
* @param {Scene} scene - The scene.
* @param {number} [deep=Number.MAX_VALUE] - How deep the selection frustum of perspective cameras should extend.
*/
constructor( camera, scene, deep = Number.MAX_VALUE ) {
/**
* The camera the scene is rendered with.
*
* @type {Camera}
*/
this.camera = camera;
/**
* The camera the scene is rendered with.
*
* @type {Scene}
*/
this.scene = scene;
/**
* The start point of the selection.
*
* @type {Vector3}
*/
this.startPoint = new Vector3();
/**
* The end point of the selection.
*
* @type {Vector3}
*/
this.endPoint = new Vector3();
/**
* The selected 3D objects.
*
* @type {Array<Object3D>}
*/
this.collection = [];
/**
* The selected instance IDs of instanced meshes.
*
* @type {Object}
*/
this.instances = {};
/**
* How deep the selection frustum of perspective cameras should extend.
*
* @type {number}
* @default Number.MAX_VALUE
*/
this.deep = deep;

@@ -52,2 +106,11 @@

/**
* This method selects 3D objects in the scene based on the given start
* and end point. If no parameters are provided, the method uses the start
* and end values of the respective members.
*
* @param {Vector3} [startPoint] - The start point.
* @param {Vector3} [endPoint] - The end point.
* @return {Array<Object3D>} The selected 3D objects.
*/
select( startPoint, endPoint ) {

@@ -59,4 +122,4 @@

this.updateFrustum( this.startPoint, this.endPoint );
this.searchChildInFrustum( _frustum, this.scene );
this._updateFrustum( this.startPoint, this.endPoint );
this._searchChildInFrustum( _frustum, this.scene );

@@ -67,4 +130,6 @@ return this.collection;

updateFrustum( startPoint, endPoint ) {
// private
_updateFrustum( startPoint, endPoint ) {
startPoint = startPoint || this.startPoint;

@@ -178,3 +243,3 @@ endPoint = endPoint || this.endPoint;

searchChildInFrustum( frustum, object ) {
_searchChildInFrustum( frustum, object ) {

@@ -223,3 +288,3 @@ if ( object.isMesh || object.isLine || object.isPoints ) {

this.searchChildInFrustum( frustum, object.children[ x ] );
this._searchChildInFrustum( frustum, object.children[ x ] );

@@ -226,0 +291,0 @@ }

import { Vector2 } from 'three';
/**
* A helper for {@link SelectionBox}.
*
* It visualizes the current selection box with a `div` container element.
*/
class SelectionHelper {
/**
* Constructs a new selection helper.
*
* @param {(WebGPURenderer|WebGLRenderer)} renderer - The renderer.
* @param {string} cssClassName - The CSS class name of the `div`.
*/
constructor( renderer, cssClassName ) {
/**
* The visualization of the selection box.
*
* @type {HTMLDivElement}
*/
this.element = document.createElement( 'div' );

@@ -11,21 +27,41 @@ this.element.classList.add( cssClassName );

/**
* A reference to the renderer.
*
* @type {(WebGPURenderer|WebGLRenderer)}
*/
this.renderer = renderer;
this.startPoint = new Vector2();
this.pointTopLeft = new Vector2();
this.pointBottomRight = new Vector2();
/**
* Whether the mouse or pointer is pressed down.
*
* @type {boolean}
* @default false
*/
this.isDown = false;
this.isDown = false;
/**
* Whether helper is enabled or not.
*
* @type {boolean}
* @default true
*/
this.enabled = true;
this.onPointerDown = function ( event ) {
// private
this._startPoint = new Vector2();
this._pointTopLeft = new Vector2();
this._pointBottomRight = new Vector2();
this._onPointerDown = function ( event ) {
if ( this.enabled === false ) return;
this.isDown = true;
this.onSelectStart( event );
this._onSelectStart( event );
}.bind( this );
this.onPointerMove = function ( event ) {
this._onPointerMove = function ( event ) {

@@ -36,3 +72,3 @@ if ( this.enabled === false ) return;

this.onSelectMove( event );
this._onSelectMove( event );

@@ -43,3 +79,3 @@ }

this.onPointerUp = function ( ) {
this._onPointerUp = function ( ) {

@@ -49,17 +85,21 @@ if ( this.enabled === false ) return;

this.isDown = false;
this.onSelectOver();
this._onSelectOver();
}.bind( this );
this.renderer.domElement.addEventListener( 'pointerdown', this.onPointerDown );
this.renderer.domElement.addEventListener( 'pointermove', this.onPointerMove );
this.renderer.domElement.addEventListener( 'pointerup', this.onPointerUp );
this.renderer.domElement.addEventListener( 'pointerdown', this._onPointerDown );
this.renderer.domElement.addEventListener( 'pointermove', this._onPointerMove );
this.renderer.domElement.addEventListener( 'pointerup', this._onPointerUp );
}
/**
* Call this method if you no longer want use to the controls. It frees all internal
* resources and removes all event listeners.
*/
dispose() {
this.renderer.domElement.removeEventListener( 'pointerdown', this.onPointerDown );
this.renderer.domElement.removeEventListener( 'pointermove', this.onPointerMove );
this.renderer.domElement.removeEventListener( 'pointerup', this.onPointerUp );
this.renderer.domElement.removeEventListener( 'pointerdown', this._onPointerDown );
this.renderer.domElement.removeEventListener( 'pointermove', this._onPointerMove );
this.renderer.domElement.removeEventListener( 'pointerup', this._onPointerUp );

@@ -70,4 +110,6 @@ this.element.remove(); // in case disposal happens while dragging

onSelectStart( event ) {
// private
_onSelectStart( event ) {
this.element.style.display = 'none';

@@ -82,24 +124,24 @@

this.startPoint.x = event.clientX;
this.startPoint.y = event.clientY;
this._startPoint.x = event.clientX;
this._startPoint.y = event.clientY;
}
onSelectMove( event ) {
_onSelectMove( event ) {
this.element.style.display = 'block';
this.pointBottomRight.x = Math.max( this.startPoint.x, event.clientX );
this.pointBottomRight.y = Math.max( this.startPoint.y, event.clientY );
this.pointTopLeft.x = Math.min( this.startPoint.x, event.clientX );
this.pointTopLeft.y = Math.min( this.startPoint.y, event.clientY );
this._pointBottomRight.x = Math.max( this._startPoint.x, event.clientX );
this._pointBottomRight.y = Math.max( this._startPoint.y, event.clientY );
this._pointTopLeft.x = Math.min( this._startPoint.x, event.clientX );
this._pointTopLeft.y = Math.min( this._startPoint.y, event.clientY );
this.element.style.left = this.pointTopLeft.x + 'px';
this.element.style.top = this.pointTopLeft.y + 'px';
this.element.style.width = ( this.pointBottomRight.x - this.pointTopLeft.x ) + 'px';
this.element.style.height = ( this.pointBottomRight.y - this.pointTopLeft.y ) + 'px';
this.element.style.left = this._pointTopLeft.x + 'px';
this.element.style.top = this._pointTopLeft.y + 'px';
this.element.style.width = ( this._pointBottomRight.x - this._pointTopLeft.x ) + 'px';
this.element.style.height = ( this._pointBottomRight.y - this._pointTopLeft.y ) + 'px';
}
onSelectOver() {
_onSelectOver() {

@@ -106,0 +148,0 @@ this.element.remove();

@@ -341,3 +341,3 @@ /**

* @param {Object} profile - The best matched profile description for the supplied xrInputSource
* @param {Object} assetUrl
* @param {string} assetUrl
*/

@@ -344,0 +344,0 @@ constructor(xrInputSource, profile, assetUrl) {

import { Lighting } from 'three/webgpu';
import { tiledLights } from '../tsl/lighting/TiledLightsNode.js';
/**
* A custom lighting implementation based on Tiled-Lighting that overwrites the default
* implementation in {@link WebGPURenderer}.
*
* ```js
* const lighting = new TiledLighting();
* renderer.lighting = lighting; // set lighting system
* ```
*
* @augments Lighting
*/
export class TiledLighting extends Lighting {
/**
* Constructs a new lighting system.
*/
constructor() {

@@ -12,2 +26,11 @@

/**
* Creates a new tiled lights node for the given array of lights.
*
* This method is called internally by the renderer and must be overwritten by
* all custom lighting implementations.
*
* @param {Array<Light>} lights - The render object.
* @return {TiledLightsNode} The tiled lights node.
*/
createNode( lights = [] ) {

@@ -14,0 +37,0 @@

@@ -14,7 +14,20 @@ import {

/**
* Utility class for creating instances of {@link LightProbe}.
*
* @hideconstructor
*/
class LightProbeGenerator {
// https://www.ppsloan.org/publications/StupidSH36.pdf
/**
* Creates a light probe from the given (radiance) environment map.
* The method expects that the environment map is represented as a cube texture.
*
* @param {CubeTexture} cubeTexture - The environment map.
* @return {LightProbe} The created light probe.
*/
static fromCubeTexture( cubeTexture ) {
// https://www.ppsloan.org/publications/StupidSH36.pdf
let totalWeight = 0;

@@ -131,2 +144,14 @@

/**
* Creates a light probe from the given (radiance) environment map.
* The method expects that the environment map is represented as a cube render target.
*
* The cube render target must be in RGBA so `cubeRenderTarget.texture.format` must be
* set to {@link RGBAFormat}.
*
* @async
* @param {WebGPURenderer|WebGLRenderer} renderer - The renderer.
* @param {CubeRenderTarget|WebGLCubeRenderTarget} cubeRenderTarget - The environment map.
* @return {Promise<LightProbe>} A Promise that resolves with the created light probe.
*/
static async fromCubeRenderTarget( renderer, cubeRenderTarget ) {

@@ -133,0 +158,0 @@

import { UniformsLib } from 'three';
import { RectAreaLightTexturesLib } from './RectAreaLightTexturesLib.js';
/**
* This class is only relevant when using {@link RectAreaLight} with {@link WebGLRenderer}.
*
* Before rect area lights can be used, the internal uniform library of the renderer must be
* enhanced with the following code.
*
* ```js
* RectAreaLightUniformsLib.init();
* ```
*
* @hideconstructor
*/
class RectAreaLightUniformsLib {
/**
* Inits the uniform library required when using rect area lights.
*/
static init() {

@@ -7,0 +22,0 @@

@@ -5,4 +5,33 @@ import { LineSegments2 } from '../lines/LineSegments2.js';

/**
* A polyline drawn between vertices.
*
* This adds functionality beyond {@link Line}, like arbitrary line width and changing width to
* be in world units.It extends {@link LineSegments2}, simplifying constructing segments from a
* chain of points.
*
* This module can only be used with {@link WebGLRenderer}. When using {@link WebGPURenderer},
* import the class from `lines/webgpu/Line2.js`.
*
* ```js
* const geometry = new LineGeometry();
* geometry.setPositions( positions );
* geometry.setColors( colors );
*
* const material = new LineMaterial( { linewidth: 5, vertexColors: true } };
*
* const line = new Line2( geometry, material );
* scene.add( line );
* ```
*
* @augments LineSegments2
*/
class Line2 extends LineSegments2 {
/**
* Constructs a new wide line.
*
* @param {LineGeometry} [geometry] - The line geometry.
* @param {LineMaterial} [material] - The line material.
*/
constructor( geometry = new LineGeometry(), material = new LineMaterial( { color: Math.random() * 0xffffff } ) ) {

@@ -12,2 +41,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isLine2 = true;

@@ -14,0 +50,0 @@

import { LineSegmentsGeometry } from '../lines/LineSegmentsGeometry.js';
/**
* A chain of vertices, forming a polyline.
*
* This is used in {@link Line2} to describe the shape.
*
* ```js
* const points = [
* new THREE.Vector3( - 10, 0, 0 ),
* new THREE.Vector3( 0, 5, 0 ),
* new THREE.Vector3( 10, 0, 0 ),
* ];
*
* const geometry = new LineGeometry();
* geometry.setFromPoints( points );
* ```
*
* @augments LineSegmentsGeometry
*/
class LineGeometry extends LineSegmentsGeometry {
/**
* Constructs a new line geometry.
*/
constructor() {

@@ -9,2 +30,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isLineGeometry = true;

@@ -16,2 +44,8 @@

/**
* Sets the given line positions for this geometry.
*
* @param {Float32Array|Array<number>} array - The position data to set.
* @return {LineGeometry} A reference to this geometry.
*/
setPositions( array ) {

@@ -42,2 +76,8 @@

/**
* Sets the given line colors for this geometry.
*
* @param {Float32Array|Array<number>} array - The position data to set.
* @return {LineGeometry} A reference to this geometry.
*/
setColors( array ) {

@@ -68,2 +108,8 @@

/**
* Setups this line segments geometry from the given sequence of points.
*
* @param {Array<Vector3|Vector2>} points - An array of points in 2D or 3D space.
* @return {LineGeometry} A reference to this geometry.
*/
setFromPoints( points ) {

@@ -94,2 +140,8 @@

/**
* Setups this line segments geometry from the given line.
*
* @param {Line} line - The line that should be used as a data source for this geometry.
* @return {LineGeometry} A reference to this geometry.
*/
fromLine( line ) {

@@ -96,0 +148,0 @@

@@ -406,4 +406,24 @@ import {

/**
* A material for drawing wireframe-style geometries.
*
* Unlike {@link LineBasicMaterial}, it supports arbitrary line widths and allows using world units
* instead of screen space units. This material is used with {@link LineSegments2} and {@link Line2}.
*
* This module can only be used with {@link WebGLRenderer}. When using {@link WebGPURenderer},
* use {@link Line2NodeMaterial}.
*
* @augments ShaderMaterial
*/
class LineMaterial extends ShaderMaterial {
/**
* Constructs a new line segments geometry.
*
* @param {Object} [parameters] - An object with one or more properties
* defining the material's appearance. Any property of the material
* (including any property from inherited materials) can be passed
* in here. Color values can be passed any type of value accepted
* by {@link Color#set}.
*/
constructor( parameters ) {

@@ -423,2 +443,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isLineMaterial = true;

@@ -430,2 +457,8 @@

/**
* The material's color.
*
* @type {Color}
* @default (1,1,1)
*/
get color() {

@@ -443,2 +476,8 @@

/**
* Whether the material's sizes (width, dash gaps) are in world units.
*
* @type {boolean}
* @default false
*/
get worldUnits() {

@@ -464,2 +503,9 @@

/**
* Controls line thickness in CSS pixel units when `worldUnits` is `false` (default),
* or in world units when `worldUnits` is `true`.
*
* @type {number}
* @default 1
*/
get linewidth() {

@@ -478,2 +524,8 @@

/**
* Whether the line is dashed, or solid.
*
* @type {boolean}
* @default false
*/
get dashed() {

@@ -505,2 +557,8 @@

/**
* The scale of the dashes and gaps.
*
* @type {number}
* @default 1
*/
get dashScale() {

@@ -518,2 +576,8 @@

/**
* The size of the dash.
*
* @type {number}
* @default 1
*/
get dashSize() {

@@ -531,2 +595,8 @@

/**
* Where in the dash cycle the dash starts.
*
* @type {number}
* @default 0
*/
get dashOffset() {

@@ -544,2 +614,8 @@

/**
* The size of the gap.
*
* @type {number}
* @default 0
*/
get gapSize() {

@@ -557,2 +633,8 @@

/**
* The opacity.
*
* @type {number}
* @default 1
*/
get opacity() {

@@ -571,2 +653,9 @@

/**
* The size of the viewport, in screen pixels. This must be kept updated to make
* screen-space rendering accurate.The `LineSegments2.onBeforeRender` callback
* performs the update for visible objects.
*
* @type {Vector2}
*/
get resolution() {

@@ -584,2 +673,8 @@

/**
* Whether to use alphaToCoverage or not. When enabled, this can improve the
* anti-aliasing of line edges when using MSAA.
*
* @type {boolean}
*/
get alphaToCoverage() {

@@ -586,0 +681,0 @@

@@ -227,4 +227,33 @@ import {

/**
* A series of lines drawn between pairs of vertices.
*
* This adds functionality beyond {@link LineSegments}, like arbitrary line width and changing width
* to be in world units. {@link Line2} extends this object, forming a polyline instead of individual
* segments.
*
* This module can only be used with {@link WebGLRenderer}. When using {@link WebGPURenderer},
* import the class from `lines/webgpu/LineSegments2.js`.
*
* ```js
* const geometry = new LineSegmentsGeometry();
* geometry.setPositions( positions );
* geometry.setColors( colors );
*
* const material = new LineMaterial( { linewidth: 5, vertexColors: true } };
*
* const lineSegments = new LineSegments2( geometry, material );
* scene.add( lineSegments );
* ```
*
* @augments Mesh
*/
class LineSegments2 extends Mesh {
/**
* Constructs a new wide line.
*
* @param {LineSegmentsGeometry} [geometry] - The line geometry.
* @param {LineMaterial} [material] - The line material.
*/
constructor( geometry = new LineSegmentsGeometry(), material = new LineMaterial( { color: Math.random() * 0xffffff } ) ) {

@@ -234,2 +263,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isLineSegments2 = true;

@@ -241,6 +277,13 @@

// for backwards-compatibility, but could be a method of LineSegmentsGeometry...
/**
* Computes an array of distance values which are necessary for rendering dashed lines.
* For each vertex in the geometry, the method calculates the cumulative length from the
* current point to the very beginning of the line.
*
* @return {LineSegments2} A reference to this instance.
*/
computeLineDistances() {
// for backwards-compatibility, but could be a method of LineSegmentsGeometry...
const geometry = this.geometry;

@@ -271,2 +314,8 @@

/**
* Computes intersection points between a casted ray and this instance.
*
* @param {Raycaster} raycaster - The raycaster.
* @param {Array<Object>} intersects - The target array that holds the intersection points.
*/
raycast( raycaster, intersects ) {

@@ -273,0 +322,0 @@

@@ -15,4 +15,14 @@ import {

/**
* A series of vertex pairs, forming line segments.
*
* This is used in {@link LineSegments2} to describe the shape.
*
* @augments InstancedBufferGeometry
*/
class LineSegmentsGeometry extends InstancedBufferGeometry {
/**
* Constructs a new line segments geometry.
*/
constructor() {

@@ -22,2 +32,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isLineSegmentsGeometry = true;

@@ -37,2 +54,8 @@

/**
* Applies the given 4x4 transformation matrix to the geometry.
*
* @param {Matrix4} matrix - The matrix to apply.
* @return {LineSegmentsGeometry} A reference to this instance.
*/
applyMatrix4( matrix ) {

@@ -69,2 +92,9 @@

/**
* Sets the given line positions for this geometry. The length must be a multiple of six since
* each line segment is defined by a start end vertex in the pattern `(xyz xyz)`.
*
* @param {Float32Array|Array<number>} array - The position data to set.
* @return {LineSegmentsGeometry} A reference to this geometry.
*/
setPositions( array ) {

@@ -100,2 +130,9 @@

/**
* Sets the given line colors for this geometry. The length must be a multiple of six since
* each line segment is defined by a start end color in the pattern `(rgb rgb)`.
*
* @param {Float32Array|Array<number>} array - The position data to set.
* @return {LineSegmentsGeometry} A reference to this geometry.
*/
setColors( array ) {

@@ -124,2 +161,8 @@

/**
* Setups this line segments geometry from the given wireframe geometry.
*
* @param {WireframeGeometry} geometry - The geometry that should be used as a data source for this geometry.
* @return {LineSegmentsGeometry} A reference to this geometry.
*/
fromWireframeGeometry( geometry ) {

@@ -133,2 +176,8 @@

/**
* Setups this line segments geometry from the given edges geometry.
*
* @param {EdgesGeometry} geometry - The geometry that should be used as a data source for this geometry.
* @return {LineSegmentsGeometry} A reference to this geometry.
*/
fromEdgesGeometry( geometry ) {

@@ -142,2 +191,8 @@

/**
* Setups this line segments geometry from the given mesh.
*
* @param {Mesh} mesh - The mesh geometry that should be used as a data source for this geometry.
* @return {LineSegmentsGeometry} A reference to this geometry.
*/
fromMesh( mesh ) {

@@ -153,2 +208,9 @@

/**
* Setups this line segments geometry from the given line segments.
*
* @param {LineSegments} lineSegments - The line segments that should be used as a data source for this geometry.
* Assumes the source geometry is not using indices.
* @return {LineSegmentsGeometry} A reference to this geometry.
*/
fromLineSegments( lineSegments ) {

@@ -242,12 +304,4 @@

applyMatrix( matrix ) {
console.warn( 'THREE.LineSegmentsGeometry: applyMatrix() has been renamed to applyMatrix4().' );
return this.applyMatrix4( matrix );
}
}
export { LineSegmentsGeometry };

@@ -6,5 +6,22 @@ import { Line2NodeMaterial } from 'three/webgpu';

/**
* A polyline drawn between vertices.
*
* This adds functionality beyond {@link Line}, like arbitrary line width and changing width to
* be in world units.It extends {@link LineSegments2}, simplifying constructing segments from a
* chain of points.
*
* This module can only be used with {@link WebGPURenderer}. When using {@link WebGLRenderer},
* import the class from `lines/Line2.js`.
*
* @augments LineSegments2
*/
class Line2 extends LineSegments2 {
/**
* Constructs a new wide line.
*
* @param {LineGeometry} [geometry] - The line geometry.
* @param {Line2NodeMaterial} [material] - The line material.
*/
constructor( geometry = new LineGeometry(), material = new Line2NodeMaterial( { color: Math.random() * 0xffffff } ) ) {

@@ -14,2 +31,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isLine2 = true;

@@ -16,0 +40,0 @@

@@ -226,4 +226,22 @@ import {

/**
* A series of lines drawn between pairs of vertices.
*
* This adds functionality beyond {@link LineSegments}, like arbitrary line width and changing width
* to be in world units. {@link Line2} extends this object, forming a polyline instead of individual
* segments.
*
* This module can only be used with {@link WebGPURenderer}. When using {@link WebGLRenderer},
* import the class from `lines/LineSegments2.js`.
*
* @augments Mesh
*/
class LineSegments2 extends Mesh {
/**
* Constructs a new wide line.
*
* @param {LineSegmentsGeometry} [geometry] - The line geometry.
* @param {Line2NodeMaterial} [material] - The line material.
*/
constructor( geometry = new LineSegmentsGeometry(), material = new Line2NodeMaterial( { color: Math.random() * 0xffffff } ) ) {

@@ -233,2 +251,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isLineSegments2 = true;

@@ -238,10 +263,17 @@

this.resolution = new Vector2();
this._resolution = new Vector2();
}
// for backwards-compatibility, but could be a method of LineSegmentsGeometry...
/**
* Computes an array of distance values which are necessary for rendering dashed lines.
* For each vertex in the geometry, the method calculates the cumulative length from the
* current point to the very beginning of the line.
*
* @return {LineSegments2} A reference to this instance.
*/
computeLineDistances() {
// for backwards-compatibility, but could be a method of LineSegmentsGeometry...
const geometry = this.geometry;

@@ -275,6 +307,12 @@

renderer.getViewport( _viewport );
this.resolution.set( _viewport.z, _viewport.w );
this._resolution.set( _viewport.z, _viewport.w );
}
/**
* Computes intersection points between a casted ray and this instance.
*
* @param {Raycaster} raycaster - The raycaster.
* @param {Array<Object>} intersects - The target array that holds the intersection points.
*/
raycast( raycaster, intersects ) {

@@ -319,3 +357,3 @@

const distanceToSphere = Math.max( camera.near, _sphere.distanceToPoint( _ray.origin ) );
sphereMargin = getWorldSpaceHalfWidth( camera, distanceToSphere, this.resolution );
sphereMargin = getWorldSpaceHalfWidth( camera, distanceToSphere, this._resolution );

@@ -350,3 +388,3 @@ }

const distanceToBox = Math.max( camera.near, _box.distanceToPoint( _ray.origin ) );
boxMargin = getWorldSpaceHalfWidth( camera, distanceToBox, this.resolution );
boxMargin = getWorldSpaceHalfWidth( camera, distanceToBox, this._resolution );

@@ -353,0 +391,0 @@ }

@@ -14,4 +14,18 @@ import {

/**
* A class for creating wireframes based on wide lines.
*
* This module can only be used with {@link WebGPURenderer}. When using {@link WebGLRenderer},
* import the class from `lines/Wireframe.js`.
*
* @augments Mesh
*/
class Wireframe extends Mesh {
/**
* Constructs a new wireframe.
*
* @param {LineSegmentsGeometry} [geometry] - The line geometry.
* @param {Line2NodeMaterial} [material] - The line material.
*/
constructor( geometry = new LineSegmentsGeometry(), material = new Line2NodeMaterial( { color: Math.random() * 0xffffff } ) ) {

@@ -21,2 +35,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isWireframe = true;

@@ -28,6 +49,13 @@

// for backwards-compatibility, but could be a method of LineSegmentsGeometry...
/**
* Computes an array of distance values which are necessary for rendering dashed lines.
* For each vertex in the geometry, the method calculates the cumulative length from the
* current point to the very beginning of the line.
*
* @return {Wireframe} A reference to this instance.
*/
computeLineDistances() {
// for backwards-compatibility, but could be a method of LineSegmentsGeometry...
const geometry = this.geometry;

@@ -34,0 +62,0 @@

@@ -15,4 +15,26 @@ import {

/**
* A class for creating wireframes based on wide lines.
*
* This module can only be used with {@link WebGLRenderer}. When using {@link WebGPURenderer},
* import the class from `lines/webgpu/Wireframe.js`.
*
* ```js
* const geometry = new THREE.IcosahedronGeometry();
* const wireframeGeometry = new WireframeGeometry2( geo );
*
* const wireframe = new Wireframe( wireframeGeometry, material );
* scene.add( wireframe );
* ```
*
* @augments Mesh
*/
class Wireframe extends Mesh {
/**
* Constructs a new wireframe.
*
* @param {LineSegmentsGeometry} [geometry] - The line geometry.
* @param {LineMaterial} [material] - The line material.
*/
constructor( geometry = new LineSegmentsGeometry(), material = new LineMaterial( { color: Math.random() * 0xffffff } ) ) {

@@ -22,2 +44,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isWireframe = true;

@@ -29,6 +58,13 @@

// for backwards-compatibility, but could be a method of LineSegmentsGeometry...
/**
* Computes an array of distance values which are necessary for rendering dashed lines.
* For each vertex in the geometry, the method calculates the cumulative length from the
* current point to the very beginning of the line.
*
* @return {Wireframe} A reference to this instance.
*/
computeLineDistances() {
// for backwards-compatibility, but could be a method of LineSegmentsGeometry...
const geometry = this.geometry;

@@ -35,0 +71,0 @@

@@ -6,4 +6,21 @@ import {

/**
* A special type of line segments geometry intended for wireframe rendering.
*
* This is used in {@link Wireframe} to describe the shape.
*
* ```js
* const geometry = new THREE.IcosahedronGeometry();
* const wireframeGeometry = new WireframeGeometry2( geo );
* ```
*
* @augments LineSegmentsGeometry
*/
class WireframeGeometry2 extends LineSegmentsGeometry {
/**
* Constructs a new wireframe geometry.
*
* @param {BufferGeometry} [geometry] - The geometry to render the wireframe for.
*/
constructor( geometry ) {

@@ -13,2 +30,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isWireframeGeometry2 = true;

@@ -15,0 +39,0 @@

@@ -33,4 +33,28 @@ import {

/**
* A loader for Rhinoceros 3D files and objects.
*
* Rhinoceros is a 3D modeler used to create, edit, analyze, document, render,
* animate, and translate NURBS curves, surfaces, breps, extrusions, point clouds,
* as well as polygon meshes and SubD objects. `rhino3dm.js` is compiled to WebAssembly
* from the open source geometry library `openNURBS`. The loader currently uses
* `rhino3dm.js 8.4.0`.
*
* ```js
* const loader = new Rhino3dmLoader();
* loader.setLibraryPath( 'https://cdn.jsdelivr.net/npm/rhino3dm@8.0.1' );
*
* const object = await loader.loadAsync( 'models/3dm/Rhino_Logo.3dm' );
* scene.add( object );
* ```
*
* @augments Loader
*/
class Rhino3dmLoader extends Loader {
/**
* Constructs a new Rhino 3DM loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -40,2 +64,4 @@

// internals
this.libraryPath = '';

@@ -59,2 +85,8 @@ this.libraryPending = null;

/**
* Path to a folder containing the JS and WASM libraries.
*
* @param {string} path - The library path to set.
* @return {Rhino3dmLoader} A reference to this loader.
*/
setLibraryPath( path ) {

@@ -68,2 +100,10 @@

/**
* Sets the maximum number of Web Workers to be used during decoding.
* A lower limit may be preferable if workers are also for other
* tasks in the application.
*
* @param {number} workerLimit - The worker limit.
* @return {Rhino3dmLoader} A reference to this loader.
*/
setWorkerLimit( workerLimit ) {

@@ -77,2 +117,11 @@

/**
* Starts loading from the given URL and passes the loaded 3DM asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(Object3D)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -113,2 +162,5 @@

/**
* Prints debug messages to the browser console.
*/
debug() {

@@ -120,2 +172,9 @@

/**
* Decodes the 3DM asset data with a Web Worker.
*
* @param {ArrayBuffer} buffer - The raw 3DM asset data as an array buffer.
* @param {string} url - The asset URL.
* @return {Promise<Object3D>} A Promise that resolved with the decoded 3D object.
*/
decodeObjects( buffer, url ) {

@@ -180,2 +239,10 @@

/**
* Parses the given 3DM data and passes the loaded 3DM asset
* to the `onLoad()` callback.
*
* @param {ArrayBuffer} data - The raw 3DM asset data as an array buffer.
* @param {function(Object3D)} onLoad - Executed when the loading process has been finished.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
parse( data, onLoad, onError ) {

@@ -973,2 +1040,6 @@

/**
* Frees internal resources. This method should be called
* when the loader is no longer required.
*/
dispose() {

@@ -984,4 +1055,2 @@

return this;
}

@@ -988,0 +1057,0 @@

@@ -27,5 +27,4 @@ import {

/**
* A loader for the [3D Manufacturing Format (3MF)]{@link https://3mf.io/specification/} format.
*
* 3D Manufacturing Format (3MF) specification: https://3mf.io/specification/
*
* The following features from the core specification are supported:

@@ -43,6 +42,20 @@ *

* - Metallic Display Properties (PBR)
*
* ```js
* const loader = new ThreeMFLoader();
*
* const object = await loader.loadAsync( './models/3mf/truck.3mf' );
* object.rotation.set( - Math.PI / 2, 0, 0 ); // z-up conversion
* scene.add( object );
* ```
*
* @augments Loader
*/
class ThreeMFLoader extends Loader {
/**
* Constructs a new 3MF loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -52,2 +65,7 @@

/**
* An array of available extensions.
*
* @type {Array<Object>}
*/
this.availableExtensions = [];

@@ -57,2 +75,11 @@

/**
* Starts loading from the given URL and passes the loaded 3MF asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(Group)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -92,2 +119,8 @@

/**
* Parses the given 3MF data and returns the resulting group.
*
* @param {ArrayBuffer} data - The raw 3MF asset data as an array buffer.
* @return {Group} A group representing the parsed asset.
*/
parse( data ) {

@@ -1579,2 +1612,7 @@

/**
* Adds a 3MF extension.
*
* @param {Object} extension - The extension to add.
*/
addExtension( extension ) {

@@ -1581,0 +1619,0 @@

@@ -14,19 +14,23 @@ import {

/**
* Description: Early release of an AMF Loader following the pattern of the
* example loaders in the three.js project.
* A loader for the AMF format.
*
* Usage:
* const loader = new AMFLoader();
* loader.load('/path/to/project.amf', function(objecttree) {
* scene.add(objecttree);
* });
* The loader supports materials, color and ZIP compressed files.
* No constellation support (yet).
*
* Materials now supported, material colors supported
* Zip support, requires fflate
* No constellation support (yet)!
* ```js
* const loader = new AMFLoader();
*
* const object = await loader.loadAsync( './models/amf/rook.amf' );
* scene.add( object );
* ```
*
* @augments Loader
*/
class AMFLoader extends Loader {
/**
* Constructs a new AMF loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -38,2 +42,11 @@

/**
* Starts loading from the given URL and passes the loaded AMF asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(Group)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -74,2 +87,8 @@

/**
* Parses the given AMF data and returns the resulting group.
*
* @param {ArrayBuffer} data - The raw AMF asset data as an array buffer.
* @return {Group} A group representing the parsed asset.
*/
parse( data ) {

@@ -242,3 +261,3 @@

const volume = { name: '', triangles: [], materialid: null };
const volume = { name: '', triangles: [], materialId: null };

@@ -245,0 +264,0 @@ let currVolumeNode = node.firstElementChild;

@@ -14,10 +14,30 @@ import {

/**
* Description: reads BVH files and outputs a single Skeleton and an AnimationClip
* A loader for the BVH format.
*
* Currently only supports bvh files containing a single root.
* Imports BVH files and outputs a single {@link Skeleton} and {@link AnimationClip}.
* The loader only supports BVH files containing a single root right now.
*
* ```js
* const loader = new BVHLoader();
* const result = await loader.loadAsync( 'models/bvh/pirouette.bvh' );
*
* // visualize skeleton
* const skeletonHelper = new THREE.SkeletonHelper( result.skeleton.bones[ 0 ] );
* scene.add( result.skeleton.bones[ 0 ] );
* scene.add( skeletonHelper );
*
* // play animation clip
* mixer = new THREE.AnimationMixer( result.skeleton.bones[ 0 ] );
* mixer.clipAction( result.clip ).play();
* ```
*
* @augments Loader
*/
class BVHLoader extends Loader {
/**
* Constructs a new BVH loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -27,3 +47,16 @@

/**
* Whether to animate bone positions or not.
*
* @type {boolean}
* @default true
*/
this.animateBonePositions = true;
/**
* Whether to animate bone rotations or not.
*
* @type {boolean}
* @default true
*/
this.animateBoneRotations = true;

@@ -33,2 +66,11 @@

/**
* Starts loading from the given URL and passes the loaded BVH asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function({skeleton:Skeleton,clip:AnimationClip})} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -68,11 +110,15 @@

/**
* Parses the given BVH data and returns the resulting data.
*
* @param {string} text - The raw BVH data as a string.
* @return {{skeleton:Skeleton,clip:AnimationClip}} An object representing the parsed asset.
*/
parse( text ) {
/*
reads a string array (lines) from a BVH file
and outputs a skeleton structure including motion data
// reads a string array (lines) from a BVH file
// and outputs a skeleton structure including motion data
returns thee root node:
{ name: '', channels: [], children: [] }
*/
// returns thee root node:
// { name: '', channels: [], children: [] }
function readBvh( lines ) {

@@ -345,7 +391,7 @@

/*
builds a AnimationClip from the keyframe data saved in each bone.
builds an AnimationClip from the keyframe data saved in each bone.
bone: bvh root node
returns: a AnimationClip containing position and quaternion tracks
returns: an AnimationClip containing position and quaternion tracks
*/

@@ -352,0 +398,0 @@ function toTHREEAnimation( bones ) {

@@ -12,4 +12,21 @@ import {

/**
* A loader for the S3TC texture compression format.
*
* ```js
* const loader = new DDSLoader();
*
* const map = loader.load( 'textures/compressed/disturb_dxt1_nomip.dds' );
* map.colorSpace = THREE.SRGBColorSpace; // only for color textures
* ```
*
* @augments CompressedTextureLoader
*/
class DDSLoader extends CompressedTextureLoader {
/**
* Constructs a new DDS loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -21,2 +38,9 @@

/**
* Parses the given S3TC texture data.
*
* @param {ArrayBuffer} buffer - The raw texture data.
* @param {boolean} loadMipmaps - Whether to load mipmaps or not.
* @return {CompressedTextureLoader~TexData} An object representing the parsed texture data.
*/
parse( buffer, loadMipmaps ) {

@@ -23,0 +47,0 @@

@@ -14,4 +14,40 @@ import {

/**
* A loader for the Draco format.
*
* [Draco]{@link https://google.github.io/draco/} is an open source library for compressing
* and decompressing 3D meshes and point clouds. Compressed geometry can be significantly smaller,
* at the cost of additional decoding time on the client device.
*
* Standalone Draco files have a `.drc` extension, and contain vertex positions, normals, colors,
* and other attributes. Draco files do not contain materials, textures, animation, or node hierarchies –
* to use these features, embed Draco geometry inside of a glTF file. A normal glTF file can be converted
* to a Draco-compressed glTF file using [glTF-Pipeline]{@link https://github.com/CesiumGS/gltf-pipeline}.
* When using Draco with glTF, an instance of `DRACOLoader` will be used internally by {@link GLTFLoader}.
*
* It is recommended to create one DRACOLoader instance and reuse it to avoid loading and creating
* multiple decoder instances.
*
* `DRACOLoader` will automatically use either the JS or the WASM decoding library, based on
* browser capabilities.
*
* ```js
* const loader = new DRACOLoader();
* loader.setDecoderPath( '/examples/jsm/libs/draco/' );
*
* const geometry = await dracoLoader.loadAsync( 'models/draco/bunny.drc' );
* geometry.computeVertexNormals(); // optional
*
* dracoLoader.dispose();
* ```
*
* @augments Loader
*/
class DRACOLoader extends Loader {
/**
* Constructs a new Draco loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -46,2 +82,8 @@

/**
* Provides configuration for the decoder libraries. Configuration cannot be changed after decoding begins.
*
* @param {string} path - The decoder path.
* @return {DRACOLoader} A reference to this loader.
*/
setDecoderPath( path ) {

@@ -55,2 +97,8 @@

/**
* Provides configuration for the decoder libraries. Configuration cannot be changed after decoding begins.
*
* @param {{type:('js'|'wasm')}} config - The decoder config.
* @return {DRACOLoader} A reference to this loader.
*/
setDecoderConfig( config ) {

@@ -64,2 +112,9 @@

/**
* Sets the maximum number of Web Workers to be used during decoding.
* A lower limit may be preferable if workers are also for other tasks in the application.
*
* @param {number} workerLimit - The worker limit.
* @return {DRACOLoader} A reference to this loader.
*/
setWorkerLimit( workerLimit ) {

@@ -73,2 +128,11 @@

/**
* Starts loading from the given URL and passes the loaded Draco asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(BufferGeometry)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -91,3 +155,9 @@

/**
* Parses the given Draco data.
*
* @param {ArrayBuffer} buffer - The raw Draco data as an array buffer.
* @param {function(BufferGeometry)} onLoad - Executed when the loading/parsing process has been finished.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
parse( buffer, onLoad, onError = ()=>{} ) {

@@ -99,2 +169,4 @@

//
decodeDracoFile( buffer, callback, attributeIDs, attributeTypes, vertexColorSpace = LinearSRGBColorSpace, onError = () => {} ) {

@@ -101,0 +173,0 @@

@@ -14,9 +14,4 @@ import {

/**
* OpenEXR loader currently supports uncompressed, ZIP(S), RLE, PIZ and DWA/B compression.
* Supports reading as UnsignedByte, HalfFloat and Float type data texture.
*
* Referred to the original Industrial Light & Magic OpenEXR implementation and the TinyEXR / Syoyo Fujita
* implementation, so I have preserved their copyright notices.
*/
// Referred to the original Industrial Light & Magic OpenEXR implementation and the TinyEXR / Syoyo Fujita
// implementation, so I have preserved their copyright notices.

@@ -88,4 +83,23 @@ // /*

/**
* A loader for the OpenEXR texture format.
*
* `EXRLoader` currently supports uncompressed, ZIP(S), RLE, PIZ and DWA/B compression.
* Supports reading as UnsignedByte, HalfFloat and Float type data texture.
*
* ```js
* const loader = new EXRLoader();
* const texture = await loader.loadAsync( 'textures/memorial.exr' );
* ```
*
* @augments DataTextureLoader
*/
class EXRLoader extends DataTextureLoader {
/**
* Constructs a new EXR loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -95,2 +109,8 @@

/**
* The texture type.
*
* @type {(HalfFloatType|FloatType)}
* @default HalfFloatType
*/
this.type = HalfFloatType;

@@ -100,2 +120,8 @@

/**
* Parses the given EXR texture data.
*
* @param {ArrayBuffer} buffer - The raw texture data.
* @return {DataTextureLoader~TexData} An object representing the parsed texture data.
*/
parse( buffer ) {

@@ -2236,3 +2262,3 @@

if ( attributeName == 0 ) {
if ( attributeName === '' ) {

@@ -2541,2 +2567,8 @@ keepReading = false;

/**
* Sets the texture type.
*
* @param {(HalfFloatType|FloatType)} value - The texture type to set.
* @return {RGBMLoader} A reference to this loader.
*/
setDataType( value ) {

@@ -2543,0 +2575,0 @@

@@ -7,4 +7,21 @@ import {

/**
* A loader for loading fonts.
*
* You can convert fonts online using [facetype.js]{@link https://gero3.github.io/facetype.js/}.
*
* ```js
* const loader = new FontLoader();
* const font = await loader.loadAsync( 'fonts/helvetiker_regular.typeface.json' );
* ```
*
* @augments Loader
*/
class FontLoader extends Loader {
/**
* Constructs a new font loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -16,2 +33,11 @@

/**
* Starts loading from the given URL and passes the loaded font
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(Font)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -35,2 +61,8 @@

/**
* Parses the given font data and returns the resulting font.
*
* @param {Object} json - The raw font data as a JSON object.
* @return {Font} The font.
*/
parse( json ) {

@@ -44,8 +76,21 @@

//
/**
* Class representing a font.
*/
class Font {
/**
* Constructs a new font.
*
* @param {Object} data - The font data as JSON.
*/
constructor( data ) {
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isFont = true;

@@ -55,2 +100,7 @@

/**
* The font data as JSON.
*
* @type {Object}
*/
this.data = data;

@@ -60,2 +110,10 @@

/**
* Generates geometry shapes from the given text and size. The result of this method
* should be used with {@link ShapeGeometry} to generate the actual geometry data.
*
* @param {string} text - The text.
* @param {number} [size=100] - The text size.
* @return {Array<Shape>} An array of shapes representing the text.
*/
generateShapes( text, size = 100 ) {

@@ -62,0 +120,0 @@

@@ -12,13 +12,20 @@ import {

/**
* GCodeLoader is used to load gcode files usually used for 3D printing or CNC applications.
* A loader for the GCode format.
*
* Gcode files are composed by commands used by machines to create objects.
* GCode files are usually used for 3D printing or CNC applications.
*
* @class GCodeLoader
* ```js
* const loader = new GCodeLoader();
* const object = await loader.loadAsync( 'models/gcode/benchy.gcode' );
* scene.add( object );
* ```
*
* @augments Loader
*/
class GCodeLoader extends Loader {
/**
* @param {Manager} manager Loading manager.
* Constructs a new GCode loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/

@@ -29,2 +36,8 @@ constructor( manager ) {

/**
* Whether to split layers or not.
*
* @type {boolean}
* @default false
*/
this.splitLayer = false;

@@ -34,2 +47,11 @@

/**
* Starts loading from the given URL and passes the loaded GCode asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(Group)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -69,2 +91,8 @@

/**
* Parses the given GCode data and returns a group with lines.
*
* @param {string} data - The raw Gcode data as a string.
* @return {Group} The parsed GCode asset.
*/
parse( data ) {

@@ -71,0 +99,0 @@

@@ -13,4 +13,23 @@ import {

/**
* A loader for loading HDR cube textures.
*
* ```js
* const loader = new HDRCubeTextureLoader();
* loader.setPath( 'textures/cube/pisaHDR/' );
* const cubeTexture = await loader.loadAsync( [ 'px.hdr', 'nx.hdr', 'py.hdr', 'ny.hdr', 'pz.hdr', 'nz.hdr' ] );
*
* scene.background = cubeTexture;
* scene.environment = cubeTexture;
* ```
*
* @augments Loader
*/
class HDRCubeTextureLoader extends Loader {
/**
* Constructs a new HDR cube texture loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -20,3 +39,16 @@

/**
* The internal HDR loader that loads the
* individual textures for each cube face.
*
* @type {RGBELoader}
*/
this.hdrLoader = new RGBELoader();
/**
* The texture type.
*
* @type {(HalfFloatType|FloatType)}
* @default HalfFloatType
*/
this.type = HalfFloatType;

@@ -26,2 +58,12 @@

/**
* Starts loading from the given URLs and passes the loaded HDR cube texture
* to the `onLoad()` callback.
*
* @param {Array<string>} urls - The paths/URLs of the files to be loaded. This can also be a data URIs.
* @param {function(CubeTexture)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
* @return {CubeTexture} The HDR cube texture.
*/
load( urls, onLoad, onProgress, onError ) {

@@ -107,2 +149,8 @@

/**
* Sets the texture type.
*
* @param {(HalfFloatType|FloatType)} value - The texture type to set.
* @return {RGBELoader} A reference to this loader.
*/
setDataType( value ) {

@@ -109,0 +157,0 @@

@@ -14,4 +14,24 @@ import {

/**
* A loader for the IES format.
*
* The loaded texture should be assigned to {@link IESSpotLight#map}.
*
* ```js
* const loader = new IESLoader();
* const texture = await loader.loadAsync( 'ies/007cfb11e343e2f42e3b476be4ab684e.ies' );
*
* const spotLight = new THREE.IESSpotLight( 0xff0000, 500 );
* spotLight.iesMap = texture;
* ```
*
* @augments Loader
*/
class IESLoader extends Loader {
/**
* Constructs a new IES loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -21,2 +41,8 @@

/**
* The texture type.
*
* @type {(HalfFloatType|FloatType)}
* @default HalfFloatType
*/
this.type = HalfFloatType;

@@ -117,2 +143,11 @@

/**
* Starts loading from the given URL and passes the loaded IES texture
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(DataTexture)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -135,2 +170,8 @@

/**
* Parses the given IES data.
*
* @param {string} text - The raw IES data.
* @return {DataTexture} THE IES data as a texture.
*/
parse( text ) {

@@ -137,0 +178,0 @@

@@ -10,4 +10,21 @@ import {

/**
* A loader for the KMZ format.
*
* ```js
* const loader = new KMZLoader();
* const kmz = await loader.loadAsync( './models/kmz/Box.kmz' );
*
* scene.add( kmz.scene );
* ```
*
* @augments Loader
*/
class KMZLoader extends Loader {
/**
* Constructs a new KMZ loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -19,2 +36,11 @@

/**
* Starts loading from the given URL and passes the loaded KMZ asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function({scene:Group})} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -55,2 +81,8 @@

/**
* Parses the given KMZ data and returns an object holding the scene.
*
* @param {ArrayBuffer} data - The raw KMZ data as an array buffer.
* @return {{scene:Group}} The parsed KMZ asset.
*/
parse( data ) {

@@ -57,0 +89,0 @@

@@ -1,15 +0,1 @@

/**
* Loader for KTX 2.0 GPU Texture containers.
*
* KTX 2.0 is a container format for various GPU texture formats. The loader
* supports Basis Universal GPU textures, which can be quickly transcoded to
* a wide variety of GPU texture compression formats, as well as some
* uncompressed DataTexture and Data3DTexture formats.
*
* References:
* - KTX: http://github.khronos.org/KTX-Specification/
* - DFD: https://www.khronos.org/registry/DataFormat/specs/1.3/dataformat.1.3.html#basicdescriptor
* - BasisU HDR: https://github.com/BinomialLLC/basis_universal/wiki/UASTC-HDR-Texture-Specification-v1.0
*/
import {

@@ -82,4 +68,35 @@ CompressedTexture,

/**
* A loader for KTX 2.0 GPU Texture containers.
*
* KTX 2.0 is a container format for various GPU texture formats. The loader supports Basis Universal GPU textures,
* which can be quickly transcoded to a wide variety of GPU texture compression formats. While KTX 2.0 also allows
* other hardware-specific formats, this loader does not yet parse them.
*
* This loader parses the KTX 2.0 container and transcodes to a supported GPU compressed texture format.
* The required WASM transcoder and JS wrapper are available from the `examples/jsm/libs/basis` directory.
*
* This loader relies on Web Assembly which is not supported in older browsers.
*
* References:
* - [KTX specification]{@link http://github.khronos.org/KTX-Specification/}
* - [DFD]{@link https://www.khronos.org/registry/DataFormat/specs/1.3/dataformat.1.3.html#basicdescriptor}
* - [BasisU HDR]{@link https://github.com/BinomialLLC/basis_universal/wiki/UASTC-HDR-Texture-Specification-v1.0}
*
* ```js
* const loader = new KTX2Loader();
* loader.setTranscoderPath( 'examples/jsm/libs/basis/' );
* loader.detectSupport( renderer );
* const texture = loader.loadAsync( 'diffuse.ktx2' );
* ```
*
* @augments Loader
*/
class KTX2Loader extends Loader {
/**
* Constructs a new KTX2 loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -110,2 +127,10 @@

/**
* Sets the transcoder path.
*
* The WASM transcoder and JS wrapper are available from the `examples/jsm/libs/basis` directory.
*
* @param {string} path - The transcoder path to set.
* @return {KTX2Loader} A reference to this loader.
*/
setTranscoderPath( path ) {

@@ -119,5 +144,11 @@

setWorkerLimit( num ) {
/**
* Sets the maximum number of Web Workers to be allocated by this instance.
*
* @param {number} workerLimit - The worker limit.
* @return {KTX2Loader} A reference to this loader.
*/
setWorkerLimit( workerLimit ) {
this.workerPool.setWorkerLimit( num );
this.workerPool.setWorkerLimit( workerLimit );

@@ -128,2 +159,10 @@ return this;

/**
* Async version of {@link KTX2Loader#detectSupport}.
*
* @async
* @param {WebGPURenderer|WebGLRenderer} renderer - The renderer.
* @return {Promise} A Promise that resolves when the support has been detected.
*/
async detectSupportAsync( renderer ) {

@@ -145,2 +184,9 @@

/**
* Detects hardware support for available compressed texture formats, to determine
* the output format for the transcoder. Must be called before loading a texture.
*
* @param {WebGPURenderer|WebGLRenderer} renderer - The renderer.
* @return {KTX2Loader} A reference to this loader.
*/
detectSupport( renderer ) {

@@ -180,2 +226,4 @@

// TODO: Make this method private
init() {

@@ -252,2 +300,11 @@

/**
* Starts loading from the given URL and passes the loaded KTX2 texture
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(CompressedTexture)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -274,2 +331,10 @@

/**
* Parses the given KTX2 data.
*
* @param {ArrayBuffer} buffer - The raw KTX2 data as an array buffer.
* @param {function(CompressedTexture)} onLoad - Executed when the loading/parsing process has been finished.
* @param {onErrorCallback} onError - Executed when errors occur.
* @returns {Promise} A Promise that resolves when the parsing has been finished.
*/
parse( buffer, onLoad, onError ) {

@@ -334,2 +399,3 @@

/**
* @private
* @param {ArrayBuffer} buffer

@@ -376,2 +442,6 @@ * @param {?Object} config

/**
* Frees internal resources. This method should be called
* when the loader is no longer required.
*/
dispose() {

@@ -384,4 +454,2 @@

return this;
}

@@ -388,0 +456,0 @@

@@ -6,11 +6,24 @@ import {

/**
* for description see https://www.khronos.org/opengles/sdk/tools/KTX/
* for file layout see https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/
* A loader for the KTX texture compression format.
*
* ported from https://github.com/BabylonJS/Babylon.js/blob/master/src/Misc/khronosTextureContainer.ts
* References:
* - [The KTX File Format and Tools]{@link https://www.khronos.org/opengles/sdk/tools/KTX/}
* - [Babylon.JS khronosTextureContainer.ts]{@link https://github.com/BabylonJS/Babylon.js/blob/master/src/Misc/khronosTextureContainer.ts}
*
* ```js
* const loader = new KTXLoader();
*
* const map = loader.load( 'textures/compressed/lensflare_ASTC8x8.ktx' )
* map.colorSpace = THREE.SRGBColorSpace; // only for color textures
* ```
*
* @augments CompressedTextureLoader
*/
class KTXLoader extends CompressedTextureLoader {
/**
* Constructs a new KTX loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -22,2 +35,9 @@

/**
* Parses the given KTX texture data.
*
* @param {ArrayBuffer} buffer - The raw texture data.
* @param {boolean} loadMipmaps - Whether to load mipmaps or not.
* @return {CompressedTextureLoader~TexData} An object representing the parsed texture data.
*/
parse( buffer, loadMipmaps ) {

@@ -40,3 +60,2 @@

const HEADER_LEN = 12 + ( 13 * 4 ); // identifier + header elements (not including key value meta-data pairs)

@@ -52,2 +71,3 @@ // load types

/**
* @private
* @param {ArrayBuffer} arrayBuffer - contents of the KTX container file

@@ -54,0 +74,0 @@ * @param {number} facesExpected - should be either 1 or 6, based whether a cube texture or or

@@ -1749,6 +1749,40 @@ import {

//
/**
* A loader for the LDraw format.
*
* [LDraw]{@link https://ldraw.org/} (LEGO Draw) is an [open format specification]{@link https://ldraw.org/article/218.html}
* for describing LEGO and other construction set 3D models.
*
* An LDraw asset (a text file usually with extension .ldr, .dat or .txt) can describe just a single construction
* piece, or an entire model. In the case of a model the LDraw file can reference other LDraw files, which are
* loaded from a library path set with `setPartsLibraryPath`. You usually download the LDraw official parts library,
* extract to a folder and point setPartsLibraryPath to it.
*
* Library parts will be loaded by trial and error in subfolders 'parts', 'p' and 'models'. These file accesses
* are not optimal for web environment, so a script tool has been made to pack an LDraw file with all its dependencies
* into a single file, which loads much faster. See section 'Packing LDraw models'. The LDrawLoader example loads
* several packed files. The official parts library is not included due to its large size.
*
* `LDrawLoader` supports the following extensions:
* - !COLOUR: Color and surface finish declarations.
* - BFC: Back Face Culling specification.
* - !CATEGORY: Model/part category declarations.
* - !KEYWORDS: Model/part keywords declarations.
*
* ```js
* const loader = new LDrawLoader();
* loader.setConditionalLineMaterial( LDrawConditionalLineMaterial ); // the type of line material depends on the used renderer
* const object = await loader.loadAsync( 'models/ldraw/officialLibrary/models/car.ldr_Packed.mpd' );
* scene.add( object );
* ```
*
* @augments Loader
*/
class LDrawLoader extends Loader {
/**
* Constructs a new LDraw loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -1788,2 +1822,10 @@

/**
* This method must be called prior to `load()` unless the model to load does not reference
* library parts (usually it will be a model with all its parts packed in a single file).
*
* @param {string} path - Path to library parts files to load referenced parts from.
* This is different from Loader.setPath, which indicates the path to load the main asset from.
* @return {LDrawLoader} A reference to this loader.
*/
setPartsLibraryPath( path ) {

@@ -1796,2 +1838,10 @@

/**
* Sets the conditional line material type which depends on the used renderer.
* Use {@link LDrawConditionalLineMaterial} when using `WebGLRenderer` and
* {@link LDrawConditionalLineNodeMaterial} when using `WebGPURenderer`.
*
* @param {(LDrawConditionalLineMaterial.constructor|LDrawConditionalLineNodeMaterial.constructor)} type - The conditional line material type.
* @return {LDrawLoader} A reference to this loader.
*/
setConditionalLineMaterial( type ) {

@@ -1805,2 +1855,13 @@

/**
* This async method preloads materials from a single LDraw file. In the official
* parts library there is a special file which is loaded always the first (LDConfig.ldr)
* and contains all the standard color codes. This method is intended to be used with
* not packed files, for example in an editor where materials are preloaded and parts
* are loaded on demand.
*
* @async
* @param {string} url - Path of the LDraw materials asset.
* @return {Promise} A Promise that resolves when the preload has finished.
*/
async preloadMaterials( url ) {

@@ -1834,2 +1895,11 @@

/**
* Starts loading from the given URL and passes the loaded LDraw asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(Group)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -1847,3 +1917,3 @@

this.partsCache
.parseModel( text, this.materialLibrary )
.parseModel( text )
.then( group => {

@@ -1863,6 +1933,13 @@

/**
* Parses the given LDraw data and returns the resulting group.
*
* @param {string} text - The raw VRML data as a string.
* @param {function(Group)} onLoad - Executed when the loading/parsing process has been finished.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
parse( text, onLoad, onError ) {
this.partsCache
.parseModel( text, this.materialLibrary )
.parseModel( text )
.then( group => {

@@ -1898,2 +1975,10 @@

/**
* Sets a map which maps referenced library filenames to new filenames.
* If a fileMap is not specified (the default), library parts will be accessed by trial and
* error in subfolders 'parts', 'p' and 'models'.
*
* @param {Object<string,string>} fileMap - The file map to set.
* @return {LDrawLoader} A reference to this loader.
*/
setFileMap( fileMap ) {

@@ -1923,2 +2008,8 @@

/**
* Returns a material for the given color code.
*
* @param {string} colorCode - The color code.
* @return {?Material} The material. Returns `null` if no material has been found.
*/
getMaterial( colorCode ) {

@@ -2039,2 +2130,16 @@

/**
* Returns the Material for the main LDraw color.
*
* For an already loaded LDraw asset, returns the Material associated with the main color code.
* This method can be useful to modify the main material of a model or part that exposes it.
*
* The main color code is the standard way to color an LDraw part. It is '16' for triangles and
* '24' for edges. Usually a complete model will not expose the main color (that is, no part
* uses the code '16' at the top level, because they are assigned other specific colors) An LDraw
* part file on the other hand will expose the code '16' to be colored, and can have additional
* fixed colors.
*
* @return {?Material} The material. Returns `null` if no material has been found.
*/
getMainMaterial() {

@@ -2046,2 +2151,7 @@

/**
* Returns the material for the edges main LDraw color.
*
* @return {?Material} The material. Returns `null` if no material has been found.
*/
getMainEdgeMaterial() {

@@ -2165,3 +2275,3 @@

throw new Error( 'LDrawLoader: Invalid luminance value in material definition' + LineParser.getLineNumberString() + '.' );
throw new Error( 'LDrawLoader: Invalid luminance value in material definition' + lineParser.getLineNumberString() + '.' );

@@ -2168,0 +2278,0 @@ }

@@ -11,4 +11,31 @@ import {

/**
* A loader for the Lottie texture animation format.
*
* The loader returns an instance of {@link CanvasTexture} to represent
* the animated texture. Two additional properties are added to each texture:
* - `animation`: The return value of `lottie.loadAnimation()` which is an object
* with an API for controlling the animation's playback.
* - `image`: The image container.
*
* ```js
* const loader = new LottieLoader();
* loader.setQuality( 2 );
* const texture = await loader.loadAsync( 'textures/lottie/24017-lottie-logo-animation.json' );
*
* const geometry = new THREE.BoxGeometry();
* const material = new THREE.MeshBasicMaterial( { map: texture } );
* const mesh = new THREE.Mesh( geometry, material );
* scene.add( mesh );
* ```
*
* @augments Loader
*/
class LottieLoader extends Loader {
/**
* Sets the texture quality.
*
* @param {number} value - The texture quality.
*/
setQuality( value ) {

@@ -20,2 +47,12 @@

/**
* Starts loading from the given URL and passes the loaded Lottie asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(CanvasTexture)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
* @returns {CanvasTexture} The Lottie texture.
*/
load( url, onLoad, onProgress, onError ) {

@@ -22,0 +59,0 @@

@@ -1,4 +0,1 @@

// http://download.autodesk.com/us/systemdocs/help/2011/lustre/index.html?url=./files/WSc4e151a45a3b785a24c3d9a411df9298473-7ffd.htm,topicNumber=d0e9492
// https://community.foundry.com/discuss/topic/103636/format-spec-for-3dl?mode=Post&postID=895258
import {

@@ -8,3 +5,2 @@ ClampToEdgeWrapping,

FileLoader,
FloatType,
LinearFilter,

@@ -16,4 +12,23 @@ Loader,

/**
* A loader for the 3DL LUT format.
*
* References:
* - [3D LUTs]{@link http://download.autodesk.com/us/systemdocs/help/2011/lustre/index.html?url=./files/WSc4e151a45a3b785a24c3d9a411df9298473-7ffd.htm,topicNumber=d0e9492}
* - [Format Spec for .3dl]{@link https://community.foundry.com/discuss/topic/103636/format-spec-for-3dl?mode=Post&postID=895258}
*
* ```js
* const loader = new LUT3dlLoader();
* const map = loader.loadAsync( 'luts/Presetpro-Cinematic.3dl' );
* ```
*
* @augments Loader
*/
export class LUT3dlLoader extends Loader {
/**
* Constructs a new 3DL LUT loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -23,2 +38,8 @@

/**
* The texture type.
*
* @type {(UnsignedByteType|FloatType)}
* @default UnsignedByteType
*/
this.type = UnsignedByteType;

@@ -28,10 +49,10 @@

/**
* Sets the texture type.
*
* @param {(UnsignedByteType|FloatType)} type - The texture type to set.
* @return {LUT3dlLoader} A reference to this loader.
*/
setType( type ) {
if ( type !== UnsignedByteType && type !== FloatType ) {
throw new Error( 'LUT3dlLoader: Unsupported type' );
}
this.type = type;

@@ -43,2 +64,11 @@

/**
* Starts loading from the given URL and passes the loaded 3DL LUT asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function({size:number,texture3D:Data3DTexture})} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -75,2 +105,8 @@

/**
* Parses the given 3DL LUT data and returns the resulting 3D data texture.
*
* @param {string} input - The raw 3DL LUT data as a string.
* @return {{size:number,texture3D:Data3DTexture}} The parsed 3DL LUT.
*/
parse( input ) {

@@ -77,0 +113,0 @@

@@ -1,3 +0,1 @@

// https://wwwimages2.adobe.com/content/dam/acom/en/products/speedgrade/cc/pdfs/cube-lut-specification-1.0.pdf
import {

@@ -7,3 +5,2 @@ ClampToEdgeWrapping,

FileLoader,
FloatType,
LinearFilter,

@@ -15,4 +12,22 @@ Loader,

/**
* A loader for the Cube LUT format.
*
* References:
* - [Cube LUT Specification]{@link https://web.archive.org/web/20220220033515/https://wwwimages2.adobe.com/content/dam/acom/en/products/speedgrade/cc/pdfs/cube-lut-specification-1.0.pdf}
*
* ```js
* const loader = new LUTCubeLoader();
* const map = loader.loadAsync( 'luts/Bourbon 64.CUBE' );
* ```
*
* @augments Loader
*/
export class LUTCubeLoader extends Loader {
/**
* Constructs a new Cube LUT loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -22,2 +37,8 @@

/**
* The texture type.
*
* @type {(UnsignedByteType|FloatType)}
* @default UnsignedByteType
*/
this.type = UnsignedByteType;

@@ -27,10 +48,10 @@

/**
* Sets the texture type.
*
* @param {(UnsignedByteType|FloatType)} type - The texture type to set.
* @return {LUTCubeLoader} A reference to this loader.
*/
setType( type ) {
if ( type !== UnsignedByteType && type !== FloatType ) {
throw new Error( 'LUTCubeLoader: Unsupported type' );
}
this.type = type;

@@ -42,2 +63,11 @@

/**
* Starts loading from the given URL and passes the loaded Cube LUT asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function({title:string,size:number,domainMin:Vector3,domainMax:Vector3,texture3D:Data3DTexture})} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -74,2 +104,8 @@

/**
* Parses the given Cube LUT data and returns the resulting 3D data texture.
*
* @param {string} input - The raw Cube LUT data as a string.
* @return {{title:string,size:number,domainMin:Vector3,domainMax:Vector3,texture3D:Data3DTexture}} The parsed Cube LUT.
*/
parse( input ) {

@@ -76,0 +112,0 @@

@@ -11,15 +11,46 @@ import {

/**
* A loader for loading LUT images.
*
* ```js
* const loader = new LUTImageLoader();
* const map = loader.loadAsync( 'luts/NeutralLUT.png' );
* ```
*
* @augments Loader
*/
export class LUTImageLoader extends Loader {
constructor( flipVertical = false ) {
/**
* Constructs a new LUT loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {
//The NeutralLUT.png has green at the bottom for Unreal ang green at the top for Unity URP Color Lookup
//post-processing. If you're using lut image strips from a Unity pipeline then pass true to the constructor
super( manager );
super();
/**
* Whether to vertically flip the LUT or not.
*
* Depending on the LUT's origin, the texture has green at the bottom (e.g. for Unreal)
* or green at the top (e.g. for Unity URP Color Lookup). If you're using lut image strips
* from a Unity pipeline, then set this property to `true`.
*
* @type {boolean}
* @default false
*/
this.flip = false;
this.flip = flipVertical;
}
/**
* Starts loading from the given URL and passes the loaded LUT
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function({size:number,texture3D:Data3DTexture})} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -40,7 +71,7 @@

imageData = this.getImageData( texture );
imageData = this._getImageData( texture );
} else {
imageData = this.horz2Vert( texture );
imageData = this._horz2Vert( texture );

@@ -71,4 +102,39 @@ }

getImageData( texture ) {
/**
* Parses the given LUT data and returns the resulting 3D data texture.
*
* @param {Uint8ClampedArray} dataArray - The raw LUT data.
* @param {number} size - The LUT size.
* @return {{size:number,texture3D:Data3DTexture}} An object representing the parsed LUT.
*/
parse( dataArray, size ) {
const data = new Uint8Array( dataArray );
const texture3D = new Data3DTexture();
texture3D.image.data = data;
texture3D.image.width = size;
texture3D.image.height = size;
texture3D.image.depth = size;
texture3D.format = RGBAFormat;
texture3D.type = UnsignedByteType;
texture3D.magFilter = LinearFilter;
texture3D.minFilter = LinearFilter;
texture3D.wrapS = ClampToEdgeWrapping;
texture3D.wrapT = ClampToEdgeWrapping;
texture3D.wrapR = ClampToEdgeWrapping;
texture3D.generateMipmaps = false;
texture3D.needsUpdate = true;
return {
size,
texture3D,
};
}
// internal
_getImageData( texture ) {
const width = texture.image.width;

@@ -96,3 +162,3 @@ const height = texture.image.height;

horz2Vert( texture ) {
_horz2Vert( texture ) {

@@ -127,28 +193,2 @@ const width = texture.image.height;

parse( dataArray, size ) {
const data = new Uint8Array( dataArray );
const texture3D = new Data3DTexture();
texture3D.image.data = data;
texture3D.image.width = size;
texture3D.image.height = size;
texture3D.image.depth = size;
texture3D.format = RGBAFormat;
texture3D.type = UnsignedByteType;
texture3D.magFilter = LinearFilter;
texture3D.minFilter = LinearFilter;
texture3D.wrapS = ClampToEdgeWrapping;
texture3D.wrapT = ClampToEdgeWrapping;
texture3D.wrapR = ClampToEdgeWrapping;
texture3D.generateMipmaps = false;
texture3D.needsUpdate = true;
return {
size,
texture3D,
};
}
}

@@ -46,12 +46,43 @@ /**

/**
* A loader for the LWO format.
*
* LWO3 and LWO2 formats are supported.
*
* References:
* - [LWO3 format specification]{@link https://static.lightwave3d.com/sdk/2019/html/filefmts/lwo3.html}
* - [LWO2 format specification]{@link https://static.lightwave3d.com/sdk/2019/html/filefmts/lwo2.html}
*
* ```js
* const loader = new LWOLoader();
* const lwoData = await loader.loadAsync( 'models/lwo/Objects/LWO3/Demo.lwo' );
*
* const mesh = object.meshes[ 0 ];
* scene.add( mesh );
* ```
*
* @augments Loader
*/
class LWOLoader extends Loader {
constructor( manager, parameters = {} ) {
/**
* Constructs a new LWO loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {
super( manager );
this.resourcePath = ( parameters.resourcePath !== undefined ) ? parameters.resourcePath : '';
}
/**
* Starts loading from the given URL and passes the loaded LWO asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function({meshes:Array<Mesh>,materials:Array<Material>})} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -100,2 +131,10 @@

/**
* Parses the given LWO data and returns the resulting meshes and materials.
*
* @param {ArrayBuffer} iffBuffer - The raw LWO data as an array buffer.
* @param {string} path - The URL base path.
* @param {string} modelName - The model name.
* @return {{meshes:Array<Mesh>,materials:Array<Material>}} An object holding the parse meshes and materials.
*/
parse( iffBuffer, path, modelName ) {

@@ -317,3 +356,3 @@

this.parseAttributeImageMaps( connections.attributes, textures, maps, materialData.maps );
this.parseAttributeImageMaps( connections.attributes, textures, maps );

@@ -502,3 +541,3 @@ const attributes = this.parseAttributes( connections.attributes, maps );

const path = this.getTexturePathByIndex( mapData.imageIndex, textures );
const path = this.getTexturePathByIndex( mapData.imageIndex );
if ( ! path ) return;

@@ -790,4 +829,4 @@

this.parseUVs( geometry, layer, indices );
this.parseMorphTargets( geometry, layer, indices );
this.parseUVs( geometry, layer );
this.parseMorphTargets( geometry, layer );

@@ -794,0 +833,0 @@ // TODO: z may need to be reversed to account for coordinate system change

@@ -148,4 +148,21 @@ import { FileLoader, Loader, TextureLoader, RepeatWrapping, MeshBasicNodeMaterial, MeshPhysicalNodeMaterial } from 'three/webgpu';

/**
* A loader for the MaterialX format.
*
* The node materials loaded with this loader can only be used with {@link WebGPURenderer}.
*
* ```js
* const loader = new MaterialXLoader().setPath( SAMPLE_PATH );
* const materials = await loader.loadAsync( 'standard_surface_brass_tiled.mtlx' );
* ```
*
* @augments Loader
*/
class MaterialXLoader extends Loader {
/**
* Constructs a new MaterialX loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -157,2 +174,12 @@

/**
* Starts loading from the given URL and passes the loaded MaterialX asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(Object<string,NodeMaterial>)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
* @return {MaterialXLoader} A reference to this loader.
*/
load( url, onLoad, onProgress, onError ) {

@@ -194,2 +221,8 @@

/**
* Parses the given MaterialX data and returns the resulting materials.
*
* @param {string} text - The raw MaterialX data as a string.
* @return {Object<string,NodeMaterial>} A dictionary holding the parse node materials.
*/
parse( text ) {

@@ -196,0 +229,0 @@

@@ -94,4 +94,24 @@ import {

/**
* A loader for the MD2 format.
*
* The loader represents the animations of the MD2 asset as an array of animation
* clips and stores them in the `animations` property of the geometry.
*
* ```js
* const loader = new MD2Loader();
* const geometry = await loader.loadAsync( './models/md2/ogro/ogro.md2' );
*
* const animations = geometry.animations;
* ```
*
* @augments Loader
*/
class MD2Loader extends Loader {
/**
* Constructs a new MD2 loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -103,2 +123,11 @@

/**
* Starts loading from the given URL and passes the loaded MD2 asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(BufferGeometry)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} [onProgress] - Executed while the loading is in progress.
* @param {onErrorCallback} [onError] - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -139,2 +168,8 @@

/**
* Parses the given MD2 data and returns a geometry.
*
* @param {ArrayBuffer} buffer - The raw MD2 data as an array buffer.
* @return {BufferGeometry} The parsed geometry data.
*/
parse( buffer ) {

@@ -394,3 +429,3 @@

geometry.animations = AnimationClip.CreateClipsFromMorphTargetSequences( frames, 10 );
geometry.animations = AnimationClip.CreateClipsFromMorphTargetSequences( frames, 10, false );

@@ -397,0 +432,0 @@ return geometry;

@@ -1,13 +0,1 @@

/**
* MDD is a special format that stores a position for every vertex in a model for every frame in an animation.
* Similar to BVH, it can be used to transfer animation data between different 3D applications or engines.
*
* MDD stores its data in binary format (big endian) in the following way:
*
* number of frames (a single uint32)
* number of vertices (a single uint32)
* time values for each frame (sequence of float32)
* vertex data for each frame (sequence of float32)
*/
import {

@@ -21,4 +9,44 @@ AnimationClip,

/**
* A loader for the MDD format.
*
* MDD stores a position for every vertex in a model for every frame in an animation.
* Similar to BVH, it can be used to transfer animation data between different 3D applications or engines.
*
* MDD stores its data in binary format (big endian) in the following way:
*
* - number of frames (a single uint32)
* - number of vertices (a single uint32)
* - time values for each frame (sequence of float32)
* - vertex data for each frame (sequence of float32)
*
* ```js
* const loader = new MDDLoader();
* const result = await loader.loadAsync( 'models/mdd/cube.mdd' );
*
* const morphTargets = result.morphTargets;
* const clip = result.clip;
* // clip.optimize(); // optional
*
* const geometry = new THREE.BoxGeometry();
* geometry.morphAttributes.position = morphTargets; // apply morph targets (vertex data must match)
*
* const material = new THREE.MeshBasicMaterial();
*
* const mesh = new THREE.Mesh( geometry, material );
* scene.add( mesh );
*
* const mixer = new THREE.AnimationMixer( mesh );
* mixer.clipAction( clip ).play();
* ```
*
* @augments Loader
*/
class MDDLoader extends Loader {
/**
* Constructs a new MDD loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -30,2 +58,11 @@

/**
* Starts loading from the given URL and passes the loaded MDD asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function({clip:AnimationClip, morphTargets:Array<BufferAttribute>})} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -46,2 +83,9 @@

/**
* Parses the given MDD data and returns an object holding the animation clip and the respective
* morph targets.
*
* @param {ArrayBuffer} data - The raw XYZ data as an array buffer.
* @return {{clip:AnimationClip, morphTargets:Array<BufferAttribute>}} The result object.
*/
parse( data ) {

@@ -48,0 +92,0 @@

@@ -17,5 +17,18 @@ import {

/**
* Loads a Wavefront .mtl file specifying materials
* A loader for the MTL format.
*
* The Material Template Library format (MTL) or .MTL File Format is a companion file format
* to OBJ that describes surface shading (material) properties of objects within one or more
* OBJ files.
*
* ```js
* const loader = new MTLLoader();
* const materials = await loader.loadAsync( 'models/obj/male02/male02.mtl' );
*
* const objLoader = new OBJLoader();
* objLoader.setMaterials( materials );
* ```
*
* @augments Loader
*/
class MTLLoader extends Loader {

@@ -30,13 +43,9 @@

/**
* Loads and parses a MTL asset from a URL.
* Starts loading from the given URL and passes the loaded MTL asset
* to the `onLoad()` callback.
*
* @param {string} url - URL to the MTL file.
* @param {Function} [onLoad] - Callback invoked with the loaded object.
* @param {Function} [onProgress] - Callback for download progress.
* @param {Function} [onError] - Callback for download errors.
*
* @see {@link FileLoader#setPath} {@link FileLoader#setResourcePath}
*
* @note In order for relative texture references to resolve correctly
* you must call setResourcePath() explicitly prior to load.
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(MaterialCreator)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/

@@ -79,2 +88,8 @@ load( url, onLoad, onProgress, onError ) {

/**
* Sets the material options.
*
* @param {MTLLoader~MaterialOptions} value - The material options.
* @return {MTLLoader} A reference to this loader.
*/
setMaterialOptions( value ) {

@@ -88,12 +103,7 @@

/**
* Parses a MTL file.
* Parses the given MTL data and returns the resulting material creator.
*
* @param {string} text - Content of MTL file
* @param {string} path
* @return {MaterialCreator}
*
* @see {@link FileLoader#setPath} {@link FileLoader#setResourcePath}
*
* @note In order for relative texture references to resolve correctly
* you must call setResourcePath() explicitly prior to parse.
* @param {string} text - The raw MTL data as a string.
* @param {string} path - The URL base path.
* @return {MaterialCreator} The material creator.
*/

@@ -162,14 +172,9 @@ parse( text, path ) {

/**
* Create a new MTLLoader.MaterialCreator
* @param baseUrl - Url relative to which textures are loaded
* @param options - Set of options on how to construct the materials
* side: Which side to apply the material
* FrontSide (default), THREE.BackSide, THREE.DoubleSide
* wrap: What type of wrapping to apply for textures
* RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping
* normalizeRGB: RGBs need to be normalized to 0-1 from 0-255
* Default: false, assumed to be already normalized
* ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's
* Default: false
* @constructor
* Material options of `MTLLoader`.
*
* @typedef {Object} MTLLoader~MaterialOptions
* @property {(FrontSide|BackSide|DoubleSide)} [side=FrontSide] - Which side to apply the material.
* @property {(RepeatWrapping|ClampToEdgeWrapping|MirroredRepeatWrapping)} [wrap=RepeatWrapping] - What type of wrapping to apply for textures.
* @property {boolean} [normalizeRGB=false] - Whether RGB colors should be normalized to `0-1` from `0-255`.
* @property {boolean} [ignoreZeroRGBs=false] - Ignore values of RGBs (Ka,Kd,Ks) that are all 0's.
*/

@@ -176,0 +181,0 @@

@@ -10,4 +10,19 @@ import {

/**
* A loader for the NRRD format.
*
* ```js
* const loader = new NRRDLoader();
* const volume = await loader.loadAsync( 'models/nrrd/I.nrrd' );
* ```
*
* @augments Loader
*/
class NRRDLoader extends Loader {
/**
* Constructs a new NRRD loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -19,2 +34,11 @@

/**
* Starts loading from the given URL and passes the loaded NRRD asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(Volume)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -56,11 +80,18 @@

/**
* Toggles the segmentation mode.
*
* @param {boolean} segmentation is a option for user to choose
*/
* @param {boolean} segmentation - Whether to use segmentation mode or not.
*/
setSegmentation( segmentation ) {
this.segmentation = segmentation;
this.segmentation = segmentation;
}
/**
* Parses the given NRRD data and returns the resulting volume data.
*
* @param {ArrayBuffer} data - The raw NRRD data as an array buffer.
* @return {Volume} The parsed volume.
*/
parse( data ) {

@@ -313,3 +344,3 @@

// now we know what the header is
_header = this.parseChars( _bytes, 0, i - 2 );
_header = this._parseChars( _bytes, 0, i - 2 );
// this is were the data starts

@@ -492,3 +523,3 @@ _data_start = i + 1;

parseChars( array, start, end ) {
_parseChars( array, start, end ) {

@@ -495,0 +526,0 @@ // without borders, use the whole array

@@ -435,6 +435,26 @@ import {

//
/**
* A loader for the OBJ format.
*
* The [OBJ format]{@link https://en.wikipedia.org/wiki/Wavefront_.obj_file} is a simple data-format that
* represents 3D geometry in a human readable format as the position of each vertex, the UV position of
* each texture coordinate vertex, vertex normals, and the faces that make each polygon defined as a list
* of vertices, and texture vertices.
*
* ```js
* const loader = new OBJLoader();
* const object = await loader.loadAsync( 'models/monster.obj' );
* scene.add( object );
* ```
*
* @augments Loader
*/
class OBJLoader extends Loader {
/**
* Constructs a new OBJ loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -444,2 +464,8 @@

/**
* A reference to a material creator.
*
* @type {?MaterialCreator}
* @default null
*/
this.materials = null;

@@ -449,2 +475,11 @@

/**
* Starts loading from the given URL and passes the loaded OBJ asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(Group)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -484,2 +519,8 @@

/**
* Sets the material creator for this OBJ. This object is loaded via {@link MTLLoader}.
*
* @param {MaterialCreator} materials - An object that creates the materials for this OBJ.
* @return {OBJLoader} A reference to this loader.
*/
setMaterials( materials ) {

@@ -493,2 +534,8 @@

/**
* Parses the given OBJ data and returns the resulting group.
*
* @param {string} text - The raw OBJ data as a string.
* @return {Group} The parsed OBJ.
*/
parse( text ) {

@@ -495,0 +542,0 @@

@@ -13,4 +13,30 @@ import {

/**
* A loader for the Point Cloud Data (PCD) format.
*
* PCDLoader supports ASCII and (compressed) binary files as well as the following PCD fields:
* - x y z
* - rgb
* - normal_x normal_y normal_z
* - intensity
* - label
*
* ```js
* const loader = new PCDLoader();
*
* const points = await loader.loadAsync( './models/pcd/binary/Zaghetto.pcd' );
* points.geometry.center(); // optional
* points.geometry.rotateX( Math.PI ); // optional
* scene.add( points );
* ```
*
* @augments Loader
*/
class PCDLoader extends Loader {
/**
* Constructs a new PCD loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -20,2 +46,8 @@

/**
* Whether to use little Endian or not.
*
* @type {boolean}
* @default true
*/
this.littleEndian = true;

@@ -25,2 +57,11 @@

/**
* Starts loading from the given URL and passes the loaded PCD asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(Points)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -61,2 +102,8 @@

/**
* Parses the given PCD data and returns a point cloud.
*
* @param {ArrayBuffer} data - The raw PCD data as an array buffer.
* @return {Points} The parsed point cloud.
*/
parse( data ) {

@@ -63,0 +110,0 @@

@@ -10,4 +10,26 @@ import {

/**
* A loader for the PDB format.
*
* The [Protein Data Bank]{@link https://en.wikipedia.org/wiki/Protein_Data_Bank_(file_format)}
* file format is a textual file describing the three-dimensional structures of molecules.
*
* ```js
* const loader = new PDBLoader();
* const pdb = await loader.loadAsync( 'models/pdb/ethanol.pdb' );
*
* const geometryAtoms = pdb.geometryAtoms;
* const geometryBonds = pdb.geometryBonds;
* const json = pdb.json;
* ```
*
* @augments Loader
*/
class PDBLoader extends Loader {
/**
* Constructs a new PDB loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -19,2 +41,11 @@

/**
* Starts loading from the given URL and passes the loaded PDB asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(Object)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -54,6 +85,13 @@

// Based on CanvasMol PDB parser
/**
* Parses the given PDB data and returns an object holding the atoms and
* bond geometries as well as the raw atom data as JSON.
*
* @param {string} text - The raw PDB data as a string.
* @return {Object} The result object.
*/
parse( text ) {
// Based on CanvasMol PDB parser
function trim( text ) {

@@ -60,0 +98,0 @@

@@ -10,42 +10,26 @@ import {

const _color = new Color();
/**
* Description: A THREE loader for PLY ASCII files (known as the Polygon
* A loader for PLY the PLY format (known as the Polygon
* File Format or the Stanford Triangle Format).
*
* Limitations: ASCII decoding assumes file is UTF-8.
* Limitations:
* - ASCII decoding assumes file is UTF-8.
*
* Usage:
* const loader = new PLYLoader();
* loader.load('./models/ply/ascii/dolphins.ply', function (geometry) {
* ```js
* const loader = new PLYLoader();
* const geometry = await loader.loadAsync( './models/ply/ascii/dolphins.ply' );
* scene.add( new THREE.Mesh( geometry ) );
* ```
*
* scene.add( new THREE.Mesh( geometry ) );
*
* } );
*
* If the PLY file uses non standard property names, they can be mapped while
* loading. For example, the following maps the properties
* “diffuse_(red|green|blue)” in the file to standard color names.
*
* loader.setPropertyNameMapping( {
* diffuse_red: 'red',
* diffuse_green: 'green',
* diffuse_blue: 'blue'
* } );
*
* Custom properties outside of the defaults for position, uv, normal
* and color attributes can be added using the setCustomPropertyNameMapping method.
* For example, the following maps the element properties “custom_property_a”
* and “custom_property_b” to an attribute “customAttribute” with an item size of 2.
* Attribute item sizes are set from the number of element properties in the property array.
*
* loader.setCustomPropertyNameMapping( {
* customAttribute: ['custom_property_a', 'custom_property_b'],
* } );
*
* @augments Loader
*/
const _color = new Color();
class PLYLoader extends Loader {
/**
* Constructs a new PLY loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -55,2 +39,4 @@

// internals
this.propertyNameMapping = {};

@@ -61,2 +47,11 @@ this.customPropertyMapping = {};

/**
* Starts loading from the given URL and passes the loaded PLY asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(BufferGeometry)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -97,2 +92,17 @@

/**
* Sets a property name mapping that maps default property names
* to custom ones. For example, the following maps the properties
* “diffuse_(red|green|blue)” in the file to standard color names.
*
* ```js
* loader.setPropertyNameMapping( {
* diffuse_red: 'red',
* diffuse_green: 'green',
* diffuse_blue: 'blue'
* } );
* ```
*
* @param {Object} mapping - The mapping dictionary.
*/
setPropertyNameMapping( mapping ) {

@@ -104,2 +114,16 @@

/**
* Custom properties outside of the defaults for position, uv, normal
* and color attributes can be added using the setCustomPropertyNameMapping method.
* For example, the following maps the element properties “custom_property_a”
* and “custom_property_b” to an attribute “customAttribute” with an item size of 2.
* Attribute item sizes are set from the number of element properties in the property array.
*
* ```js
* loader.setCustomPropertyNameMapping( {
* customAttribute: ['custom_property_a', 'custom_property_b'],
* } );
* ```
* @param {Object} mapping - The mapping dictionary.
*/
setCustomPropertyNameMapping( mapping ) {

@@ -111,2 +135,8 @@

/**
* Parses the given PLY data and returns the resulting geometry.
*
* @param {ArrayBuffer} data - The raw PLY data as an array buffer.
* @return {BufferGeometry} The parsed geometry.
*/
parse( data ) {

@@ -113,0 +143,0 @@

@@ -9,10 +9,21 @@ import {

/*
* PVR v2 (legacy) parser
* TODO : Add Support for PVR v3 format
* TODO : implement loadMipmaps option
/**
* A loader for the PVRTC texture compression format.
*
* ```js
* const loader = new PVRLoader();
*
* const map = loader.load( 'textures/compressed/disturb_4bpp_rgb.pvr' );
* map.colorSpace = THREE.SRGBColorSpace; // only for color textures
* ```
*
* @augments CompressedTextureLoader
*/
class PVRLoader extends CompressedTextureLoader {
/**
* Constructs a new PVR loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -24,2 +35,9 @@

/**
* Parses the given PVRTC texture data.
*
* @param {ArrayBuffer} buffer - The raw texture data.
* @param {boolean} loadMipmaps - Whether to load mipmaps or not. This option is not yet supported by the loader.
* @return {CompressedTextureLoader~TexData} An object representing the parsed texture data.
*/
parse( buffer, loadMipmaps ) {

@@ -26,0 +44,0 @@

@@ -10,7 +10,22 @@ import {

// https://github.com/mrdoob/three.js/issues/5552
// http://en.wikipedia.org/wiki/RGBE_image_format
/**
* A loader for the RGBE HDR texture format.
*
* ```js
* const loader = new RGBELoader();
* const envMap = await loader.loadAsync( 'textures/equirectangular/blouberg_sunrise_2_1k.hdr' );
* envMap.mapping = THREE.EquirectangularReflectionMapping;
*
* scene.environment = envMap;
* ```
*
* @augments DataTextureLoader
*/
class RGBELoader extends DataTextureLoader {
/**
* Constructs a new RGBE loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -20,2 +35,8 @@

/**
* The texture type.
*
* @type {(HalfFloatType|FloatType)}
* @default HalfFloatType
*/
this.type = HalfFloatType;

@@ -25,6 +46,12 @@

// adapted from http://www.graphics.cornell.edu/~bjw/rgbe.html
/**
* Parses the given RGBE texture data.
*
* @param {ArrayBuffer} buffer - The raw texture data.
* @return {DataTextureLoader~TexData} An object representing the parsed texture data.
*/
parse( buffer ) {
// adapted from http://www.graphics.cornell.edu/~bjw/rgbe.html
const

@@ -417,2 +444,8 @@ /* default error routine. change this to change error handling */

/**
* Sets the texture type.
*
* @param {(HalfFloatType|FloatType)} value - The texture type to set.
* @return {RGBELoader} A reference to this loader.
*/
setDataType( value ) {

@@ -419,0 +452,0 @@

@@ -10,4 +10,21 @@ import {

/**
* A loader for the RGBM HDR texture format.
*
* ```js
* const loader = new RGBMLoader();
* loader.setMaxRange( 16 );
*
* const texture = await loader.loadAsync( 'textures/memorial.png' );
* ```
*
* @augments DataTextureLoader
*/
class RGBMLoader extends DataTextureLoader {
/**
* Constructs a new RGBM loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -17,7 +34,26 @@

/**
* The texture type.
*
* @type {(HalfFloatType|FloatType)}
* @default HalfFloatType
*/
this.type = HalfFloatType;
this.maxRange = 7; // more information about this property at https://iwasbeingirony.blogspot.com/2010/06/difference-between-rgbm-and-rgbd.html
/**
* More information about this property at [The difference between RGBM and RGBD]{@link https://iwasbeingirony.blogspot.com/2010/06/difference-between-rgbm-and-rgbd.html}
*
* @type {(7|16)}
* @default 7
*/
this.maxRange = 7;
}
/**
* Sets the texture type.
*
* @param {(HalfFloatType|FloatType)} value - The texture type to set.
* @return {RGBMLoader} A reference to this loader.
*/
setDataType( value ) {

@@ -30,2 +66,8 @@

/**
* Sets the maximum range.
*
* @param {(7|16)} value - The maximum range to set.
* @return {RGBMLoader} A reference to this loader.
*/
setMaxRange( value ) {

@@ -38,2 +80,12 @@

/**
* Starts loading from the given URLs and passes the loaded RGBM cube map
* to the `onLoad()` callback.
*
* @param {Array<string>} urls - The paths/URLs of the files to be loaded. This can also be a data URIs.
* @param {function(CubeTexture)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
* @return {CubeTexture} The cube texture.
*/
loadCubemap( urls, onLoad, onProgress, onError ) {

@@ -88,2 +140,10 @@

/**
* Async version of {@link RGBMLoader#loadCubemap}.
*
* @async
* @param {Array<string>} urls - The paths/URLs of the files to be loaded. This can also be a data URIs.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @return {Promise<CubeTexture>} A Promise that resolves with the loaded cube map.
*/
loadCubemapAsync( urls, onProgress ) {

@@ -99,2 +159,8 @@

/**
* Parses the given RGBM texture data.
*
* @param {ArrayBuffer} buffer - The raw texture data.
* @return {DataTextureLoader~TexData} An object representing the parsed texture data.
*/
parse( buffer ) {

@@ -101,0 +167,0 @@

@@ -13,26 +13,24 @@ import {

/**
* Description: A THREE loader for STL ASCII files, as created by Solidworks and other CAD programs.
* A loader for the STL format, as created by Solidworks and other CAD programs.
*
* Supports both binary and ASCII encoded files, with automatic detection of type.
* Supports both binary and ASCII encoded files. The loader returns a non-indexed buffer geometry.
*
* The loader returns a non-indexed buffer geometry.
*
* Limitations:
* Binary decoding supports "Magics" color format (http://en.wikipedia.org/wiki/STL_(file_format)#Color_in_binary_STL).
* There is perhaps some question as to how valid it is to always assume little-endian-ness.
* ASCII decoding assumes file is UTF-8.
* - Binary decoding supports "Magics" color format (http://en.wikipedia.org/wiki/STL_(file_format)#Color_in_binary_STL).
* - There is perhaps some question as to how valid it is to always assume little-endian-ness.
* - ASCII decoding assumes file is UTF-8.
*
* Usage:
* const loader = new STLLoader();
* loader.load( './models/stl/slotted_disk.stl', function ( geometry ) {
* scene.add( new THREE.Mesh( geometry ) );
* });
*
* ```js
* const loader = new STLLoader();
* const geometry = await loader.loadAsync( './models/stl/slotted_disk.stl' )
* scene.add( new THREE.Mesh( geometry ) );
* ```
* For binary STLs geometry might contain colors for vertices. To use it:
* // use the same code to load STL as above
* if (geometry.hasColors) {
* material = new THREE.MeshPhongMaterial({ opacity: geometry.alpha, vertexColors: true });
* } else { .... }
* const mesh = new THREE.Mesh( geometry, material );
*
* ```js
* // use the same code to load STL as above
* if ( geometry.hasColors ) {
* material = new THREE.MeshPhongMaterial( { opacity: geometry.alpha, vertexColors: true } );
* }
* const mesh = new THREE.Mesh( geometry, material );
* ```
* For ASCII STLs containing multiple solids, each solid is assigned to a different group.

@@ -42,27 +40,23 @@ * Groups can be used to assign a different color by defining an array of materials with the same length of

*
* const mesh = new THREE.Mesh( geometry, material );
* ```js
* const materials = [];
* const nGeometryGroups = geometry.groups.length;
*
* For example:
* for ( let i = 0; i < nGeometryGroups; i ++ ) {
* const material = new THREE.MeshPhongMaterial( { color: colorMap[ i ], wireframe: false } );
* materials.push( material );
* }
*
* const materials = [];
* const nGeometryGroups = geometry.groups.length;
* const mesh = new THREE.Mesh(geometry, materials);
* ```
*
* const colorMap = ...; // Some logic to index colors.
*
* for (let i = 0; i < nGeometryGroups; i++) {
*
* const material = new THREE.MeshPhongMaterial({
* color: colorMap[i],
* wireframe: false
* });
*
* }
*
* materials.push(material);
* const mesh = new THREE.Mesh(geometry, materials);
* @augments Loader
*/
class STLLoader extends Loader {
/**
* Constructs a new STL loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -74,2 +68,11 @@

/**
* Starts loading from the given URL and passes the loaded STL asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(BufferGeometry)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -111,2 +114,8 @@

/**
* Parses the given STL data and returns the resulting geometry.
*
* @param {ArrayBuffer} data - The raw STL data as an array buffer.
* @return {BufferGeometry} The parsed geometry.
*/
parse( data ) {

@@ -113,0 +122,0 @@

@@ -18,11 +18,21 @@ import {

/**
* Autodesk 3DS three.js file loader, based on lib3ds.
* A loader for the 3DS format, based on lib3ds.
*
* Loads geometry with uv and materials basic properties with texture support.
*
* @class TDSLoader
* ```js
* const loader = new TDSLoader();
* loader.setResourcePath( 'models/3ds/portalgun/textures/' );
* const object = await loader.loadAsync( 'models/3ds/portalgun/portalgun.3ds' );
* scene.add( object );
*
* @augments Loader
*/
class TDSLoader extends Loader {
/**
* Constructs a new 3DS loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -32,4 +42,12 @@

/**
* Whether debug mode should be enabled or not.
*
* @type {boolean}
* @default false
*/
this.debug = false;
// internals
this.group = null;

@@ -43,9 +61,9 @@

/**
* Load 3ds file from url.
* Starts loading from the given URL and passes the loaded 3DS asset
* to the `onLoad()` callback.
*
* @method load
* @param {string} url URL for the file.
* @param {Function} onLoad onLoad callback, receives group Object3D as argument.
* @param {Function} onProgress onProgress callback.
* @param {Function} onError onError callback.
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(Group)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/

@@ -91,8 +109,7 @@ load( url, onLoad, onProgress, onError ) {

/**
* Parse arraybuffer data and load 3ds file.
* Parses the given 3DS data and returns the resulting data.
*
* @method parse
* @param {ArrayBuffer} arraybuffer Arraybuffer data to be loaded.
* @param {string} path Path for external resources.
* @return {Group} Group loaded from 3ds file.
* @param {ArrayBuffer} arraybuffer - The raw 3DS data as an array buffer.
* @param {string} path - The asset path.
* @return {Group} The parsed asset represented as a group.
*/

@@ -120,5 +137,5 @@ parse( arraybuffer, path ) {

*
* @method readFile
* @param {ArrayBuffer} arraybuffer Arraybuffer data to be loaded.
* @param {string} path Path for external resources.
* @private
* @param {ArrayBuffer} arraybuffer - Arraybuffer data to be loaded.
* @param {string} path - Path for external resources.
*/

@@ -164,5 +181,5 @@ readFile( arraybuffer, path ) {

*
* @method readMeshData
* @param {Chunk} chunk to read mesh from
* @param {string} path Path for external resources.
* @private
* @param {Chunk} chunk - to read mesh from
* @param {string} path - Path for external resources.
*/

@@ -211,4 +228,4 @@ readMeshData( chunk, path ) {

*
* @method readNamedObject
* @param {Chunk} chunk Chunk in use.
* @private
* @param {Chunk} chunk - Chunk in use.
*/

@@ -243,5 +260,5 @@ readNamedObject( chunk ) {

*
* @method readMaterialEntry
* @param {Chunk} chunk Chunk in use.
* @param {string} path Path for external resources.
* @private
* @param {Chunk} chunk - Chunk in use.
* @param {string} path - Path for external resources.
*/

@@ -346,5 +363,5 @@ readMaterialEntry( chunk, path ) {

*
* @method readMesh
* @param {Chunk} chunk Chunk in use.
* @return {Mesh} The parsed mesh.
* @private
* @param {Chunk} chunk - Chunk in use.
* @return {Mesh} - The parsed mesh.
*/

@@ -471,5 +488,5 @@ readMesh( chunk ) {

*
* @method readFaceArray
* @param {Chunk} chunk Chunk in use.
* @param {Mesh} mesh Mesh to be filled with the data read.
* @private
* @param {Chunk} chunk - Chunk in use.
* @param {Mesh} mesh - Mesh to be filled with the data read.
*/

@@ -540,5 +557,5 @@ readFaceArray( chunk, mesh ) {

*
* @method readMap
* @param {Chunk} chunk Chunk in use.
* @param {string} path Path for external resources.
* @private
* @param {Chunk} chunk - Chunk in use.
* @param {string} path - Path for external resources.
* @return {Texture} Texture read from this data chunk.

@@ -600,4 +617,4 @@ */

*
* @method readMaterialGroup
* @param {Chunk} chunk Chunk in use.
* @private
* @param {Chunk} chunk - Chunk in use.
* @return {Object} Object with name and index of the object.

@@ -627,5 +644,5 @@ */

*
* @method readColor
* @param {Chunk} chunk Chunk.
* @return {Color} Color value read..
* @private
* @param {Chunk} chunk - Chunk.
* @return {Color} Color value read.
*/

@@ -670,4 +687,4 @@ readColor( chunk ) {

*
* @method readPercentage
* @param {Chunk} chunk Chunk to read data from.
* @private
* @param {Chunk} chunk - Chunk to read data from.
* @return {number} Data read from the dataview.

@@ -702,4 +719,4 @@ */

*
* @method debugMessage
* @param {Object} message Debug message to print to the console.
* @private
* @param {Object} message - Debug message to print to the console.
*/

@@ -718,4 +735,7 @@ debugMessage( message ) {

/** Read data/sub-chunks from chunk */
/**
* Read data/sub-chunks from chunk.
*
* @private
*/
class Chunk {

@@ -726,6 +746,6 @@

*
* @class Chunk
* @param {DataView} data DataView to read from.
* @param {number} position in data.
* @param {Function} debugMessage logging callback.
* @private
* @param {DataView} data - DataView to read from.
* @param {number} position - In data.
* @param {Function} debugMessage - Logging callback.
*/

@@ -760,6 +780,6 @@ constructor( data, position, debugMessage ) {

/**
* read a sub cchunk.
* Reads a sub cchunk.
*
* @method readChunk
* @return {Chunk | null} next sub chunk
* @private
* @return {Chunk | null} next sub chunk.
*/

@@ -790,5 +810,5 @@ readChunk() {

/**
* return the ID of this chunk as Hex
* Returns the ID of this chunk as Hex
*
* @method idToString
* @private
* @return {string} hex-string of id

@@ -811,3 +831,3 @@ */

*
* @method readByte
* @private
* @return {number} Data read from the dataview.

@@ -826,3 +846,3 @@ */

*
* @method readFloat
* @private
* @return {number} Data read from the dataview.

@@ -850,3 +870,3 @@ */

*
* @method readInt
* @private
* @return {number} Data read from the dataview.

@@ -865,3 +885,3 @@ */

*
* @method readShort
* @private
* @return {number} Data read from the dataview.

@@ -880,3 +900,3 @@ */

*
* @method readDWord
* @private
* @return {number} Data read from the dataview.

@@ -895,3 +915,3 @@ */

*
* @method readWord
* @private
* @return {number} Data read from the dataview.

@@ -910,3 +930,3 @@ */

*
* @method readString
* @private
* @return {string} Data read from the dataview.

@@ -913,0 +933,0 @@ */

@@ -6,4 +6,20 @@ import {

/**
* A loader for the TGA texture format.
*
* ```js
* const loader = new TGALoader();
* const texture = await loader.loadAsync( 'textures/crate_color8.tga' );
* texture.colorSpace = THREE.SRGBColorSpace; // only for color textures
* ```
*
* @augments DataTextureLoader
*/
class TGALoader extends DataTextureLoader {
/**
* Constructs a new TGA loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -15,2 +31,8 @@

/**
* Parses the given TGA texture data.
*
* @param {ArrayBuffer} buffer - The raw texture data.
* @return {DataTextureLoader~TexData} An object representing the parsed texture data.
*/
parse( buffer ) {

@@ -17,0 +39,0 @@

@@ -9,4 +9,20 @@ import {

/**
* A loader for the TIFF texture format.
*
* ```js
* const loader = new TIFFLoader();
* const texture = await loader.loadAsync( 'textures/tiff/crate_lzw.tif' );
* texture.colorSpace = THREE.SRGBColorSpace;
* ```
*
* @augments DataTextureLoader
*/
class TIFFLoader extends DataTextureLoader {
/**
* Constructs a new TIFF loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -18,2 +34,8 @@

/**
* Parses the given TIFF texture data.
*
* @param {ArrayBuffer} buffer - The raw texture data.
* @return {DataTextureLoader~TexData} An object representing the parsed texture data.
*/
parse( buffer ) {

@@ -20,0 +42,0 @@

@@ -8,9 +8,22 @@ import {

/**
* Requires opentype.js to be included in the project.
* A loader for the TTF format.
*
* Loads TTF files and converts them into typeface JSON that can be used directly
* to create THREE.Font objects.
*
* ```js
* const loader = new TTFLoader();
* const json = await loader.loadAsync( 'fonts/ttf/kenpixel.ttf' );
* const font = new Font( json );
* ```
*
* @augments Loader
*/
class TTFLoader extends Loader {
/**
* Constructs a new TTF loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -20,2 +33,8 @@

/**
* Whether the TTF commands should be reversed or not.
*
* @type {boolean}
* @default false
*/
this.reversed = false;

@@ -25,2 +44,11 @@

/**
* Starts loading from the given URL and passes the loaded TTF asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(Object)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -61,2 +89,8 @@

/**
* Parses the given TTF data and returns a JSON for creating a font.
*
* @param {ArrayBuffer} arraybuffer - The raw TTF data as an array buffer.
* @return {Object} The result JSON.
*/
parse( arraybuffer ) {

@@ -63,0 +97,0 @@

@@ -15,6 +15,4 @@ import {

// UltraHDR Image Format - https://developer.android.com/media/platform/hdr-image-format
// HDR/EXR to UltraHDR Converter - https://gainmap-creator.monogrid.com/
/**
* UltraHDR Image Format - https://developer.android.com/media/platform/hdr-image-format
*

@@ -34,7 +32,19 @@ * Short format brief:

// Calculating this SRGB powers is extremely slow for 4K images and can be sufficiently precalculated for a 3-4x speed boost
const SRGB_TO_LINEAR = Array( 1024 )
.fill( 0 )
.map( ( _, value ) =>
Math.pow( ( value / 255 ) * 0.9478672986 + 0.0521327014, 2.4 )
);
/**
* A loader for the Ultra HDR Image Format.
*
* Existing HDR or EXR textures can be converted to Ultra HDR with this [tool]{@link https://gainmap-creator.monogrid.com/}.
*
* Current feature set:
* - JPEG headers (required)
* - XMP metadata (required)
* - XMP validation (not implemented)
* - XMP validation (not implemented)
* - EXIF profile (not implemented)

@@ -46,13 +56,21 @@ * - ICC profile (not implemented)

* - Primary image as an HDR image (not implemented)
*
* ```js
* const loader = new UltraHDRLoader();
* const texture = await loader.loadAsync( 'textures/equirectangular/ice_planet_close.jpg' );
* texture.mapping = THREE.EquirectangularReflectionMapping;
*
* scene.background = texture;
* scene.environment = texture;
* ```
*
* @augments Loader
*/
/* Calculating this SRGB powers is extremely slow for 4K images and can be sufficiently precalculated for a 3-4x speed boost */
const SRGB_TO_LINEAR = Array( 1024 )
.fill( 0 )
.map( ( _, value ) =>
Math.pow( ( value / 255 ) * 0.9478672986 + 0.0521327014, 2.4 )
);
class UltraHDRLoader extends Loader {
/**
* Constructs a new Ultra HDR loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -62,2 +80,8 @@

/**
* The texture type.
*
* @type {(HalfFloatType|FloatType)}
* @default HalfFloatType
*/
this.type = HalfFloatType;

@@ -67,2 +91,8 @@

/**
* Sets the texture type.
*
* @param {(HalfFloatType|FloatType)} value - The texture type to set.
* @return {RGBELoader} A reference to this loader.
*/
setDataType( value ) {

@@ -76,2 +106,8 @@

/**
* Parses the given Ultra HDR texture data.
*
* @param {ArrayBuffer} buffer - The raw texture data.
* @param {Function} onLoad - The `onLoad` callback.
*/
parse( buffer, onLoad ) {

@@ -271,2 +307,12 @@

/**
* Starts loading from the given URL and passes the loaded Ultra HDR texture
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the files to be loaded. This can also be a data URI.
* @param {function(DataTexture, Object)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
* @return {DataTexture} The Ultra HDR texture.
*/
load( url, onLoad, onProgress, onError ) {

@@ -273,0 +319,0 @@

@@ -119,4 +119,22 @@ import {

/**
* A loader for the USDZ format.
*
* USDZ files that use USDC internally are not yet supported, only USDA.
*
* ```js
* const loader = new USDZLoader();
* const model = await loader.loadAsync( 'saeukkang.usdz' );
* scene.add( model );
* ```
*
* @augments Loader
*/
class USDZLoader extends Loader {
/**
* Constructs a new USDZ loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -128,2 +146,11 @@

/**
* Starts loading from the given URL and passes the loaded USDZ asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(Group)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -164,2 +191,8 @@

/**
* Parses the given USDZ data and returns the resulting group.
*
* @param {ArrayBuffer} buffer - The raw USDZ data as an array buffer.
* @return {Group} The parsed asset as a group.
*/
parse( buffer ) {

@@ -179,3 +212,3 @@

const blob = new Blob( [ zip[ filename ] ], { type: { type: 'image/png' } } );
const blob = new Blob( [ zip[ filename ] ], { type: 'image/png' } );
data[ filename ] = URL.createObjectURL( blob );

@@ -182,0 +215,0 @@

@@ -16,4 +16,31 @@ import {

/**
* A loader for the VOX format.
*
* ```js
* const loader = new VOXLoader();
* const chunks = await loader.loadAsync( 'models/vox/monu10.vox' );
*
* for ( let i = 0; i < chunks.length; i ++ ) {
*
* const chunk = chunks[ i ];
* const mesh = new VOXMesh( chunk );
* mesh.scale.setScalar( 0.0015 );
* scene.add( mesh );
*
* }
* ```
* @augments Loader
*/
class VOXLoader extends Loader {
/**
* Starts loading from the given URL and passes the loaded VOX asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(Array<Object>)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -53,2 +80,8 @@

/**
* Parses the given VOX data and returns the resulting chunks.
*
* @param {ArrayBuffer} buffer - The raw VOX data as an array buffer.
* @return {Array<Object>} The parsed chunks.
*/
parse( buffer ) {

@@ -178,4 +211,16 @@

/**
* A VOX mesh.
*
* Instances of this class are created from the loaded chunks of {@link VOXLoader}.
*
* @augments Mesh
*/
class VOXMesh extends Mesh {
/**
* Constructs a new VOX mesh.
*
* @param {Object} chunk - A VOX chunk loaded via {@link VOXLoader}.
*/
constructor( chunk ) {

@@ -285,4 +330,16 @@

/**
* A VOX 3D texture.
*
* Instances of this class are created from the loaded chunks of {@link VOXLoader}.
*
* @augments Data3DTexture
*/
class VOXData3DTexture extends Data3DTexture {
/**
* Constructs a new VOX 3D texture.
*
* @param {Object} chunk - A VOX chunk loaded via {@link VOXLoader}.
*/
constructor( chunk ) {

@@ -289,0 +346,0 @@

@@ -12,4 +12,27 @@ import {

/**
* A loader for the VTK format.
*
* This loader only supports the `POLYDATA` dataset format so far. Other formats
* (structured points, structured grid, rectilinear grid, unstructured grid, appended)
* are not supported.
*
* ```js
* const loader = new VTKLoader();
* const geometry = await loader.loadAsync( 'models/vtk/liver.vtk' );
* geometry.computeVertexNormals();
*
* const mesh = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial() );
* scene.add( mesh );
* ```
*
* @augments Loader
*/
class VTKLoader extends Loader {
/**
* Constructs a new VTK loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -21,2 +44,11 @@

/**
* Starts loading from the given URL and passes the loaded VRML asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(BufferGeometry)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -57,2 +89,8 @@

/**
* Parses the given VTK data and returns the resulting geometry.
*
* @param {ArrayBuffer} data - The raw VTK data as an array buffer
* @return {BufferGeometry} The parsed geometry.
*/
parse( data ) {

@@ -59,0 +97,0 @@

@@ -10,4 +10,33 @@ import {

/**
* A loader for the XYZ format.
*
* XYZ is a very simple format for storing point clouds. The layouts
* `XYZ` (points) and `XYZRGB` (points + colors) are supported.
*
* ```js
* const loader = new XYZLoader();
* const geometry = await loader.loadAsync( 'models/xyz/helix_201.xyz' );
* geometry.center();
*
* const vertexColors = ( geometry.hasAttribute( 'color' ) === true );
* const material = new THREE.PointsMaterial( { size: 0.1, vertexColors: vertexColors } );
*
* const points = new THREE.Points( geometry, material );
* scene.add( points );
* ```
*
* @augments Loader
*/
class XYZLoader extends Loader {
/**
* Starts loading from the given URL and passes the loaded XYZ asset
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(BufferGeometry)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -47,2 +76,8 @@

/**
* Parses the given XYZ data and returns the resulting geometry.
*
* @param {string} text - The raw XYZ data as a string.
* @return {BufferGeometry} The geometry representing the point cloud.
*/
parse( text ) {

@@ -49,0 +84,0 @@

@@ -8,2 +8,10 @@ import {

/**
* A special line material for meshes loaded via {@link LDrawLoader}.
*
* This module can only be used with {@link WebGLRenderer}. When using {@link WebGPURenderer},
* import the class from `LDrawConditionalLineNodeMaterial.js`.
*
* @augments ShaderMaterial
*/
class LDrawConditionalLineMaterial extends ShaderMaterial {

@@ -17,2 +25,11 @@

/**
* Constructs a new conditional line material.
*
* @param {Object} [parameters] - An object with one or more properties
* defining the material's appearance. Any property of the material
* (including any property from inherited materials) can be passed
* in here. Color values can be passed any type of value accepted
* by {@link Color#set}.
*/
constructor( parameters ) {

@@ -114,2 +131,9 @@

/**
* The material's opacity.
*
* @name LDrawConditionalLineMaterial#opacity
* @type {number}
* @default 1
*/
opacity: {

@@ -129,2 +153,9 @@ get: function () {

/**
* The material's color.
*
* @name LDrawConditionalLineMaterial#color
* @type {Color}
* @default (1,1,1)
*/
color: {

@@ -141,2 +172,10 @@ get: function () {

this.setValues( parameters );
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isLDrawConditionalLineMaterial = true;

@@ -143,0 +182,0 @@

import { Color } from 'three';
import { attribute, cameraProjectionMatrix, dot, float, Fn, modelViewMatrix, modelViewProjection, NodeMaterial, normalize, positionGeometry, sign, uniform, varyingProperty, vec2, vec4 } from 'three/tsl';
/**
* A special line material for meshes loaded via {@link LDrawLoader}.
*
* This module can only be used with {@link WebGPURenderer}. When using {@link WebGLRenderer},
* import the class from `LDrawConditionalLineMaterial.js`.
*
* @augments NodeMaterial
*/
class LDrawConditionalLineMaterial extends NodeMaterial {

@@ -12,2 +20,11 @@

/**
* Constructs a new conditional line material.
*
* @param {Object} [parameters] - An object with one or more properties
* defining the material's appearance. Any property of the material
* (including any property from inherited materials) can be passed
* in here. Color values can be passed any type of value accepted
* by {@link Color#set}.
*/
constructor( parameters ) {

@@ -78,2 +95,9 @@

/**
* The material's opacity.
*
* @name LDrawConditionalLineMaterial#opacity
* @type {number}
* @default 1
*/
opacity: {

@@ -93,2 +117,9 @@ get: function () {

/**
* The material's color.
*
* @name LDrawConditionalLineMaterial#color
* @type {Color}
* @default (1,1,1)
*/
color: {

@@ -111,2 +142,10 @@ get: function () {

this.setValues( parameters );
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isLDrawConditionalLineMaterial = true;

@@ -113,0 +152,0 @@

@@ -24,6 +24,16 @@ import { MeshPhysicalMaterial } from 'three';

* This would then create the possibility of SSR and IR depending on material properties such as `roughness`, `metalness` and `reflectivity`.
**/
*
* @augments MeshPhysicalMaterial
*/
class MeshPostProcessingMaterial extends MeshPhysicalMaterial {
/**
* Constructs a new conditional line material.
*
* @param {Object} [parameters] - An object with one or more properties
* defining the material's appearance. Any property of the material
* (including any property from inherited materials) can be passed
* in here. Color values can be passed any type of value accepted
* by {@link Color#set}.
*/
constructor( parameters ) {

@@ -41,2 +51,9 @@

this._aoPassMap = aoPassMap;
/**
* The scale of the AO pass.
*
* @type {number}
* @default 1
*/
this.aoPassMapScale = aoPassMapScale;

@@ -47,2 +64,7 @@ this._shader = null;

/**
* A texture representing the AO pass.
*
* @type {Texture}
*/
get aoPassMap() {

@@ -49,0 +71,0 @@

@@ -5,8 +5,39 @@ import {

/**
* A capsule is essentially a cylinder with hemispherical caps at both ends.
* It can be thought of as a swept sphere, where a sphere is moved along a line segment.
*
* Capsules are often used as bounding volumes (next to AABBs and bounding spheres).
*/
class Capsule {
/**
* Constructs a new capsule.
*
* @param {Vector3} [start] - The start vector.
* @param {Vector3} [end] - The end vector.
* @param {number} [radius=1] - The capsule's radius.
*/
constructor( start = new Vector3( 0, 0, 0 ), end = new Vector3( 0, 1, 0 ), radius = 1 ) {
/**
* The start vector.
*
* @type {Vector3}
*/
this.start = start;
/**
* The end vector.
*
* @type {Vector3}
*/
this.end = end;
/**
* The capsule's radius.
*
* @type {number}
* @default 1
*/
this.radius = radius;

@@ -16,8 +47,22 @@

/**
* Returns a new capsule with copied values from this instance.
*
* @return {Capsule} A clone of this instance.
*/
clone() {
return new Capsule( this.start.clone(), this.end.clone(), this.radius );
return new this.constructor().copy( this );
}
/**
* Sets the capsule components to the given values.
* Please note that this method only copies the values from the given objects.
*
* @param {Vector3} start - The start vector.
* @param {Vector3} end - The end vector
* @param {number} radius - The capsule's radius.
* @return {Capsule} A reference to this capsule.
*/
set( start, end, radius ) {

@@ -29,4 +74,12 @@

return this;
}
/**
* Copies the values of the given capsule to this instance.
*
* @param {Capsule} capsule - The capsule to copy.
* @return {Capsule} A reference to this capsule.
*/
copy( capsule ) {

@@ -38,4 +91,12 @@

return this;
}
/**
* Returns the center point of this capsule.
*
* @param {Vector3} target - The target vector that is used to store the method's result.
* @return {Vector3} The center point.
*/
getCenter( target ) {

@@ -47,2 +108,8 @@

/**
* Adds the given offset to this capsule, effectively moving it in 3D space.
*
* @param {Vector3} v - The offset that should be used to translate the capsule.
* @return {Capsule} A reference to this capsule.
*/
translate( v ) {

@@ -53,27 +120,24 @@

}
return this;
checkAABBAxis( p1x, p1y, p2x, p2y, minx, maxx, miny, maxy, radius ) {
return (
( minx - p1x < radius || minx - p2x < radius ) &&
( p1x - maxx < radius || p2x - maxx < radius ) &&
( miny - p1y < radius || miny - p2y < radius ) &&
( p1y - maxy < radius || p2y - maxy < radius )
);
}
/**
* Returns `true` if the given bounding box intersects with this capsule.
*
* @param {Box3} box - The bounding box to test.
* @return {boolean} Whether the given bounding box intersects with this capsule.
*/
intersectsBox( box ) {
return (
this.checkAABBAxis(
checkAABBAxis(
this.start.x, this.start.y, this.end.x, this.end.y,
box.min.x, box.max.x, box.min.y, box.max.y,
this.radius ) &&
this.checkAABBAxis(
checkAABBAxis(
this.start.x, this.start.z, this.end.x, this.end.z,
box.min.x, box.max.x, box.min.z, box.max.z,
this.radius ) &&
this.checkAABBAxis(
checkAABBAxis(
this.start.y, this.start.z, this.end.y, this.end.z,

@@ -88,2 +152,13 @@ box.min.y, box.max.y, box.min.z, box.max.z,

function checkAABBAxis( p1x, p1y, p2x, p2y, minx, maxx, miny, maxy, radius ) {
return (
( minx - p1x < radius || minx - p2x < radius ) &&
( p1x - maxx < radius || p2x - maxx < radius ) &&
( miny - p1y < radius || miny - p2y < radius ) &&
( p1y - maxy < radius || p2y - maxy < radius )
);
}
export { Capsule };

@@ -5,4 +5,18 @@ import { MathUtils } from 'three';

/**
* A utility class with helper functions for color conversion.
*
* @hideconstructor
*/
class ColorConverter {
/**
* Sets the given HSV color definition to the given color object.
*
* @param {Color} color - The color to set.
* @param {number} h - The hue.
* @param {number} s - The saturation.
* @param {number} v - The value.
* @return {Color} The update color.
*/
static setHSV( color, h, s, v ) {

@@ -20,2 +34,9 @@

/**
* Returns a HSV color representation of the given color object.
*
* @param {Color} color - The color to get HSV values from.
* @param {{h:number,s:number,v:number}} target - The target object that is used to store the method's result.
* @return {{h:number,s:number,v:number}} The HSV color.
*/
static getHSV( color, target ) {

@@ -22,0 +43,0 @@

import { LinearTransfer, Matrix3, SRGBTransfer } from 'three';
/** @module ColorSpaces */
// Reference: http://www.russellcottrell.com/photo/matrixCalculator.htm

@@ -27,5 +29,24 @@

/**
* Display-P3 color space.
*
* @type {string}
* @constant
*/
export const DisplayP3ColorSpace = 'display-p3';
/**
* Display-P3-Linear color space.
*
* @type {string}
* @constant
*/
export const LinearDisplayP3ColorSpace = 'display-p3-linear';
/**
* Implementation object for the Display-P3 color space.
*
* @type {module:ColorSpaces~ColorSpaceImpl}
* @constant
*/
export const DisplayP3ColorSpaceImpl = {

@@ -41,2 +62,8 @@ primaries: P3_PRIMARIES,

/**
* Implementation object for the Display-P3-Linear color space.
*
* @type {module:ColorSpaces~ColorSpaceImpl}
* @constant
*/
export const LinearDisplayP3ColorSpaceImpl = {

@@ -69,4 +96,16 @@ primaries: P3_PRIMARIES,

/**
* Rec2020-Linear color space.
*
* @type {string}
* @constant
*/
export const LinearRec2020ColorSpace = 'rec2020-linear';
/**
* Implementation object for the Rec2020-Linear color space.
*
* @type {module:ColorSpaces~ColorSpaceImpl}
* @constant
*/
export const LinearRec2020ColorSpaceImpl = {

@@ -80,1 +119,15 @@ primaries: REC2020_PRIMARIES,

};
/**
* An object holding the color space implementation.
*
* @typedef {Object} module:ColorSpaces~ColorSpaceImpl
* @property {Array<number>} primaries - The primaries.
* @property {Array<number>} whitePoint - The white point.
* @property {Matrix3} toXYZ - A color space conversion matrix, converting to CIE XYZ.
* @property {Matrix3} fromXYZ - A color space conversion matrix, converting from CIE XYZ.
* @property {Array<number>} luminanceCoefficients - The luminance coefficients.
* @property {{unpackColorSpace:string}} [workingColorSpaceConfig] - The working color space config.
* @property {{drawingBufferColorSpace:string}} [outputColorSpaceConfig] - The drawing buffer color space config.
**/

@@ -8,6 +8,2 @@ import {

/**
* Ported from: https://github.com/maurizzzio/quickhull3d/ by Mauricio Poppe (https://github.com/maurizzzio)
*/
const Visible = 0;

@@ -22,4 +18,14 @@ const Deleted = 1;

/**
* Can be used to compute the convex hull in 3D space for a given set of points. It
* is primarily intended for {@link ConvexGeometry}.
*
* This Quickhull 3D implementation is a port of [quickhull3d]{@link https://github.com/maurizzzio/quickhull3d/}
* by Mauricio Poppe.
*/
class ConvexHull {
/**
* Constructs a new convex hull.
*/
constructor() {

@@ -45,6 +51,12 @@

this.vertices = []; // vertices of the hull (internal representation of given geometry data)
this.vertices = []; // vertices of the hull (internal representation of given geometry data)
}
/**
* Computes to convex hull for the given array of points.
*
* @param {Array<Vector3>} points - The array of points in 3D space.
* @return {ConvexHull} A reference to this convex hull.
*/
setFromPoints( points ) {

@@ -64,3 +76,3 @@

this.compute();
this._compute();

@@ -73,2 +85,9 @@ }

/**
* Computes the convex hull of the given 3D object (including its descendants),
* accounting for the world transforms of both the 3D object and its descendants.
*
* @param {Object3D} object - The 3D object to compute the convex hull for.
* @return {ConvexHull} A reference to this convex hull.
*/
setFromObject( object ) {

@@ -110,2 +129,8 @@

/**
* Returns `true` if the given point lies in the convex hull.
*
* @param {Vector3} point - The point to test.
* @return {boolean} Whether the given point lies in the convex hull or not.
*/
containsPoint( point ) {

@@ -129,2 +154,9 @@

/**
* Computes the intersections point of the given ray and this convex hull.
*
* @param {Ray} ray - The ray to test.
* @param {Vector3} target - The target vector that is used to store the method's result.
* @return {Vector3|null} The intersection point. Returns `null` if not intersection was detected.
*/
intersectRay( ray, target ) {

@@ -206,2 +238,8 @@

/**
* Returns `true` if the given ray intersects with this convex hull.
*
* @param {Ray} ray - The ray to test.
* @return {boolean} Whether the given ray intersects with this convex hull or not.
*/
intersectsRay( ray ) {

@@ -213,2 +251,7 @@

/**
* Makes the convex hull empty.
*
* @return {ConvexHull} A reference to this convex hull.
*/
makeEmpty() {

@@ -223,5 +266,13 @@

// Adds a vertex to the 'assigned' list of vertices and assigns it to the given face
// private
addVertexToFace( vertex, face ) {
/**
* Adds a vertex to the 'assigned' list of vertices and assigns it to the given face.
*
* @private
* @param {VertexNode} vertex - The vertex to add.
* @param {Face} face - The target face.
* @return {ConvexHull} A reference to this convex hull.
*/
_addVertexToFace( vertex, face ) {

@@ -246,6 +297,14 @@ vertex.face = face;

// Removes a vertex from the 'assigned' list of vertices and from the given face
/**
* Removes a vertex from the 'assigned' list of vertices and from the given face.
* It also makes sure that the link from 'face' to the first vertex it sees in 'assigned'
* is linked correctly after the removal.
*
* @private
* @param {VertexNode} vertex - The vertex to remove.
* @param {Face} face - The target face.
* @return {ConvexHull} A reference to this convex hull.
*/
_removeVertexFromFace( vertex, face ) {
removeVertexFromFace( vertex, face ) {
if ( vertex === face.outside ) {

@@ -277,6 +336,12 @@

// Removes all the visible vertices that a given face is able to see which are stored in the 'assigned' vertex list
/**
* Removes all the visible vertices that a given face is able to see which are stored in
* the 'assigned' vertex list.
*
* @private
* @param {Face} face - The target face.
* @return {VertexNode|undefined} A reference to this convex hull.
*/
_removeAllVerticesFromFace( face ) {
removeAllVerticesFromFace( face ) {
if ( face.outside !== null ) {

@@ -308,8 +373,18 @@

// Removes all the visible vertices that 'face' is able to see
/**
* Removes all the visible vertices that `face` is able to see.
*
* - If `absorbingFace` doesn't exist, then all the removed vertices will be added to the 'unassigned' vertex list.
* - If `absorbingFace` exists, then this method will assign all the vertices of 'face' that can see 'absorbingFace'.
* - If a vertex cannot see `absorbingFace`, it's added to the 'unassigned' vertex list.
*
* @private
* @param {Face} face - The given face.
* @param {Face} [absorbingFace] - An optional face that tries to absorb the vertices of the first face.
* @return {ConvexHull} A reference to this convex hull.
*/
_deleteFaceVertices( face, absorbingFace ) {
deleteFaceVertices( face, absorbingFace ) {
const faceVertices = this._removeAllVerticesFromFace( face );
const faceVertices = this.removeAllVerticesFromFace( face );
if ( faceVertices !== undefined ) {

@@ -343,3 +418,3 @@

this.addVertexToFace( vertex, absorbingFace );
this._addVertexToFace( vertex, absorbingFace );

@@ -366,6 +441,11 @@ } else {

// Reassigns as many vertices as possible from the unassigned list to the new faces
/**
* Reassigns as many vertices as possible from the unassigned list to the new faces.
*
* @private
* @param {Array<Face>} newFaces - The new faces.
* @return {ConvexHull} A reference to this convex hull.
*/
_resolveUnassignedPoints( newFaces ) {
resolveUnassignedPoints( newFaces ) {
if ( this.unassigned.isEmpty() === false ) {

@@ -377,3 +457,3 @@

// buffer 'next' reference, see .deleteFaceVertices()
// buffer 'next' reference, see ._deleteFaceVertices()

@@ -411,3 +491,3 @@ const nextVertex = vertex.next;

this.addVertexToFace( vertex, maxFace );
this._addVertexToFace( vertex, maxFace );

@@ -426,6 +506,11 @@ }

// Computes the extremes of a simplex which will be the initial hull
/**
* Computes the extremes values (min/max vectors) which will be used to
* compute the initial hull.
*
* @private
* @return {Object} The extremes.
*/
_computeExtremes() {
computeExtremes() {
const min = new Vector3();

@@ -495,9 +580,13 @@ const max = new Vector3();

// Computes the initial simplex assigning to its faces all the points
// that are candidates to form part of the hull
/**
* Computes the initial simplex assigning to its faces all the points that are
* candidates to form part of the hull.
*
* @private
* @return {ConvexHull} A reference to this convex hull.
*/
_computeInitialHull() {
computeInitialHull() {
const vertices = this.vertices;
const extremes = this.computeExtremes();
const extremes = this._computeExtremes();
const min = extremes.min;

@@ -674,3 +763,3 @@ const max = extremes.max;

this.addVertexToFace( vertex, maxFace );
this._addVertexToFace( vertex, maxFace );

@@ -687,6 +776,10 @@ }

// Removes inactive faces
/**
* Removes inactive (e.g. deleted) faces from the internal face list.
*
* @private
* @return {ConvexHull} A reference to this convex hull.
*/
_reindexFaces() {
reindexFaces() {
const activeFaces = [];

@@ -712,6 +805,14 @@

// Finds the next vertex to create faces with the current hull
/**
* Finds the next vertex to create faces with the current hull.
*
* - Let the initial face be the first face existing in the 'assigned' vertex list.
* - If a face doesn't exist then return since there're no vertices left.
* - Otherwise for each vertex that face sees find the one furthest away from it.
*
* @private
* @return {?VertexNode} The next vertex to add.
*/
_nextVertexToAdd() {
nextVertexToAdd() {
// if the 'assigned' list of vertices is empty, no vertices are left. return with 'undefined'

@@ -751,11 +852,19 @@

// Computes a chain of half edges in CCW order called the 'horizon'.
// For an edge to be part of the horizon it must join a face that can see
// 'eyePoint' and a face that cannot see 'eyePoint'.
/**
* Computes a chain of half edges in CCW order called the 'horizon'. For an edge
* to be part of the horizon it must join a face that can see 'eyePoint' and a face
* that cannot see 'eyePoint'.
*
* @private
* @param {Vector3} eyePoint - The 3D-coordinates of a point.
* @param {HalfEdge} crossEdge - The edge used to jump to the current face.
* @param {Face} face - The current face being tested.
* @param {Array<HalfEdge>} horizon - The edges that form part of the horizon in CCW order.
* @return {ConvexHull} A reference to this convex hull.
*/
_computeHorizon( eyePoint, crossEdge, face, horizon ) {
computeHorizon( eyePoint, crossEdge, face, horizon ) {
// moves face's vertices to the 'unassigned' vertex list
this.deleteFaceVertices( face );
this._deleteFaceVertices( face );

@@ -790,3 +899,3 @@ face.mark = Deleted;

this.computeHorizon( eyePoint, twinEdge, oppositeFace, horizon );
this._computeHorizon( eyePoint, twinEdge, oppositeFace, horizon );

@@ -811,6 +920,14 @@ } else {

// Creates a face with the vertices 'eyeVertex.point', 'horizonEdge.tail' and 'horizonEdge.head' in CCW order
/**
* Creates a face with the vertices 'eyeVertex.point', 'horizonEdge.tail' and 'horizonEdge.head'
* in CCW order. All the half edges are created in CCW order thus the face is always pointing
* outside the hull.
*
* @private
* @param {VertexNode} eyeVertex - The vertex that is added to the hull.
* @param {HalfEdge} horizonEdge - A single edge of the horizon.
* @return {HalfEdge} The half edge whose vertex is the eyeVertex.
*/
_addAdjoiningFace( eyeVertex, horizonEdge ) {
addAdjoiningFace( eyeVertex, horizonEdge ) {
// all the half edges are created in ccw order thus the face is always pointing outside the hull

@@ -831,7 +948,13 @@

// Adds 'horizon.length' faces to the hull, each face will be linked with the
// horizon opposite face and the face on the left/right
/**
* Adds 'horizon.length' faces to the hull, each face will be linked with the horizon
* opposite face and the face on the left/right.
*
* @private
* @param {VertexNode} eyeVertex - The vertex that is added to the hull.
* @param {Array<HalfEdge>} horizon - The horizon.
* @return {ConvexHull} A reference to this convex hull.
*/
_addNewFaces( eyeVertex, horizon ) {
addNewFaces( eyeVertex, horizon ) {
this.newFaces = [];

@@ -848,3 +971,3 @@

const sideEdge = this.addAdjoiningFace( eyeVertex, horizonEdge );
const sideEdge = this._addAdjoiningFace( eyeVertex, horizonEdge );

@@ -876,6 +999,18 @@ if ( firstSideEdge === null ) {

// Adds a vertex to the hull
/**
* Adds a vertex to the hull with the following algorithm:
*
* - Compute the 'horizon' which is a chain of half edges. For an edge to belong to this group
* it must be the edge connecting a face that can see 'eyeVertex' and a face which cannot see 'eyeVertex'.
* - All the faces that can see 'eyeVertex' have its visible vertices removed from the assigned vertex list.
* - A new set of faces is created with each edge of the 'horizon' and 'eyeVertex'. Each face is connected
* with the opposite horizon face and the face on the left/right.
* - The vertices removed from all the visible faces are assigned to the new faces if possible.
*
* @private
* @param {VertexNode} eyeVertex - The vertex to add.
* @return {ConvexHull} A reference to this convex hull.
*/
_addVertexToHull( eyeVertex ) {
addVertexToHull( eyeVertex ) {
const horizon = [];

@@ -887,11 +1022,11 @@

this.removeVertexFromFace( eyeVertex, eyeVertex.face );
this._removeVertexFromFace( eyeVertex, eyeVertex.face );
this.computeHorizon( eyeVertex.point, null, eyeVertex.face, horizon );
this._computeHorizon( eyeVertex.point, null, eyeVertex.face, horizon );
this.addNewFaces( eyeVertex, horizon );
this._addNewFaces( eyeVertex, horizon );
// reassign 'unassigned' vertices to the new faces
this.resolveUnassignedPoints( this.newFaces );
this._resolveUnassignedPoints( this.newFaces );

@@ -902,3 +1037,9 @@ return this;

cleanup() {
/**
* Cleans up internal properties after computing the convex hull.
*
* @private
* @return {ConvexHull} A reference to this convex hull.
*/
_cleanup() {

@@ -913,19 +1054,25 @@ this.assigned.clear();

compute() {
/**
* Starts the execution of the quick hull algorithm.
*
* @private
* @return {ConvexHull} A reference to this convex hull.
*/
_compute() {
let vertex;
this.computeInitialHull();
this._computeInitialHull();
// add all available vertices gradually to the hull
while ( ( vertex = this.nextVertexToAdd() ) !== undefined ) {
while ( ( vertex = this._nextVertexToAdd() ) !== undefined ) {
this.addVertexToHull( vertex );
this._addVertexToHull( vertex );
}
this.reindexFaces();
this._reindexFaces();
this.cleanup();
this._cleanup();

@@ -938,15 +1085,67 @@ return this;

//
/**
* Represents a section bounded by a specific amount of half-edges.
* The current implementation assumes that a face always consist of three edges.
*
* @private
*/
class Face {
/**
* Constructs a new face.
*/
constructor() {
/**
* The normal vector of the face.
*
* @private
* @type {Vector3}
*/
this.normal = new Vector3();
/**
* The midpoint or centroid of the face.
*
* @private
* @type {Vector3}
*/
this.midpoint = new Vector3();
/**
* The area of the face.
*
* @private
* @type {number}
* @default 0
*/
this.area = 0;
this.constant = 0; // signed distance from face to the origin
/**
* Signed distance from face to the origin.
*
* @private
* @type {number}
* @default 0
*/
this.constant = 0;
/**
* Reference to a vertex in a vertex list this face can see.
*
* @private
* @type {?VertexNode}
* @default null
*/
this.outside = null; // reference to a vertex in a vertex list this face can see
this.mark = Visible;
/**
* Reference to the base edge of a face. To retrieve all edges, you can use the
* `next` reference of the current edge.
*
* @private
* @type {?HalfEdge}
* @default null
*/
this.edge = null;

@@ -956,2 +1155,11 @@

/**
* Creates a face from the given vertex nodes.
*
* @private
* @param {VertexNode} a - The first vertex node.
* @param {VertexNode} b - The second vertex node.
* @param {VertexNode} c - The third vertex node.
* @return {Face} The created face.
*/
static create( a, b, c ) {

@@ -979,2 +1187,9 @@

/**
* Returns an edge by the given index.
*
* @private
* @param {number} i - The edge index.
* @return {HalfEdge} The edge.
*/
getEdge( i ) {

@@ -1002,2 +1217,8 @@

/**
* Computes all properties of the face.
*
* @private
* @return {Face} A reference to this face.
*/
compute() {

@@ -1021,2 +1242,9 @@

/**
* Returns the signed distance from a given point to the plane representation of this face.
*
* @private
* @param {Vector3} point - The point to compute the distance to.
* @return {number} The distance.
*/
distanceToPoint( point ) {

@@ -1030,13 +1258,59 @@

// Entity for a Doubly-Connected Edge List (DCEL).
/**
* The basis for a half-edge data structure, also known as doubly
* connected edge list (DCEL).
*
* @private
*/
class HalfEdge {
/**
* Constructs a new half edge.
*
* @param {VertexNode} vertex - A reference to its destination vertex.
* @param {Face} face - A reference to its face.
*/
constructor( vertex, face ) {
/**
* A reference to its destination vertex.
*
* @private
* @type {VertexNode}
*/
this.vertex = vertex;
/**
* Reference to the previous half-edge of the same face.
*
* @private
* @type {?HalfEdge}
* @default null
*/
this.prev = null;
/**
* Reference to the next half-edge of the same face.
*
* @private
* @type {?HalfEdge}
* @default null
*/
this.next = null;
/**
* Reference to the twin half-edge to reach the opposite face.
*
* @private
* @type {?HalfEdge}
* @default null
*/
this.twin = null;
/**
* A reference to its face.
*
* @private
* @type {Face}
*/
this.face = face;

@@ -1046,2 +1320,8 @@

/**
* Returns the destination vertex.
*
* @private
* @return {VertexNode} The destination vertex.
*/
head() {

@@ -1053,2 +1333,8 @@

/**
* Returns the origin vertex.
*
* @private
* @return {VertexNode} The destination vertex.
*/
tail() {

@@ -1060,2 +1346,8 @@

/**
* Returns the Euclidean length (straight-line length) of the edge.
*
* @private
* @return {number} The edge's length.
*/
length() {

@@ -1076,2 +1368,8 @@

/**
* Returns the square of the Euclidean length (straight-line length) of the edge.
*
* @private
* @return {number} The square of the edge's length.
*/
lengthSquared() {

@@ -1092,2 +1390,10 @@

/**
* Sets the twin edge of this half-edge. It also ensures that the twin reference
* of the given half-edge is correctly set.
*
* @private
* @param {HalfEdge} edge - The twin edge to set.
* @return {HalfEdge} A reference to this edge.
*/
setTwin( edge ) {

@@ -1104,13 +1410,51 @@

// A vertex as a double linked list node.
/**
* A vertex as a double linked list node.
*
* @private
*/
class VertexNode {
/**
* Constructs a new vertex node.
*
* @param {Vector3} point - A point in 3D space.
*/
constructor( point ) {
/**
* A point in 3D space.
*
* @private
* @type {Vector3}
*/
this.point = point;
/**
* Reference to the previous vertex in the double linked list.
*
* @private
* @type {?VertexNode}
* @default null
*/
this.prev = null;
/**
* Reference to the next vertex in the double linked list.
*
* @private
* @type {?VertexNode}
* @default null
*/
this.next = null;
this.face = null; // the face that is able to see this vertex
/**
* Reference to the face that is able to see this vertex.
*
* @private
* @type {?Face}
* @default null
*/
this.face = null;
}

@@ -1120,9 +1464,30 @@

// A double linked list that contains vertex nodes.
/**
* A doubly linked list of vertices.
*
* @private
*/
class VertexList {
/**
* Constructs a new vertex list.
*/
constructor() {
/**
* Reference to the first vertex of the linked list.
*
* @private
* @type {?VertexNode}
* @default null
*/
this.head = null;
/**
* Reference to the last vertex of the linked list.
*
* @private
* @type {?VertexNode}
* @default null
*/
this.tail = null;

@@ -1132,2 +1497,8 @@

/**
* Returns the head reference.
*
* @private
* @return {VertexNode} The head reference.
*/
first() {

@@ -1139,2 +1510,8 @@

/**
* Returns the tail reference.
*
* @private
* @return {VertexNode} The tail reference.
*/
last() {

@@ -1146,2 +1523,8 @@

/**
* Clears the linked list.
*
* @private
* @return {VertexList} A reference to this vertex list.
*/
clear() {

@@ -1155,4 +1538,10 @@

// Inserts a vertex before the target vertex
/**
* Inserts a vertex before a target vertex.
*
* @private
* @param {VertexNode} target - The target.
* @param {VertexNode} vertex - The vertex to insert.
* @return {VertexList} A reference to this vertex list.
*/
insertBefore( target, vertex ) {

@@ -1179,4 +1568,10 @@

// Inserts a vertex after the target vertex
/**
* Inserts a vertex after a target vertex.
*
* @private
* @param {VertexNode} target - The target.
* @param {VertexNode} vertex - The vertex to insert.
* @return {VertexList} A reference to this vertex list.
*/
insertAfter( target, vertex ) {

@@ -1203,4 +1598,9 @@

// Appends a vertex to the end of the linked list
/**
* Appends a vertex to this vertex list.
*
* @private
* @param {VertexNode} vertex - The vertex to append.
* @return {VertexList} A reference to this vertex list.
*/
append( vertex ) {

@@ -1227,4 +1627,9 @@

// Appends a chain of vertices where 'vertex' is the head.
/**
* Appends a chain of vertices where the given vertex is the head.
*
* @private
* @param {VertexNode} vertex - The head vertex of a chain of vertices.
* @return {VertexList} A reference to this vertex list.
*/
appendChain( vertex ) {

@@ -1258,4 +1663,9 @@

// Removes a vertex from the linked list
/**
* Removes a vertex from the linked list.
*
* @private
* @param {VertexNode} vertex - The vertex to remove.
* @return {VertexList} A reference to this vertex list.
*/
remove( vertex ) {

@@ -1287,4 +1697,10 @@

// Removes a list of vertices whose 'head' is 'a' and whose 'tail' is b
/**
* Removes a sublist of vertices from the linked list.
*
* @private
* @param {VertexNode} a - The head of the sublist.
* @param {VertexNode} b - The tail of the sublist.
* @return {VertexList} A reference to this vertex list.
*/
removeSubList( a, b ) {

@@ -1316,2 +1732,8 @@

/**
* Returns `true` if the linked list is empty.
*
* @private
* @return {boolean} Whether the linked list is empty or not.
*/
isEmpty() {

@@ -1318,0 +1740,0 @@

@@ -1,3 +0,1 @@

// https://cs.nyu.edu/~perlin/noise/
const _p = [ 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10,

@@ -40,4 +38,18 @@ 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87,

/**
* A utility class providing a 3D noise function.
*
* The code is based on [IMPROVED NOISE]{@link https://cs.nyu.edu/~perlin/noise/}
* by Ken Perlin, 2002.
*/
class ImprovedNoise {
/**
* Returns a noise value for the given parameters.
*
* @param {number} x - The x coordinate.
* @param {number} y - The y coordinate.
* @param {number} z - The z coordinate.
* @return {number} The noise value.
*/
noise( x, y, z ) {

@@ -44,0 +56,0 @@

@@ -7,12 +7,67 @@ import {

/**
* Represents a lookup table for colormaps. It is used to determine the color
* values from a range of data values.
*
* ```js
* const lut = new Lut( 'rainbow', 512 );
* const color = lut.getColor( 0.5 );
* ```
*/
class Lut {
/**
* Constructs a new Lut.
*
* @param {('rainbow'|'cooltowarm'|'blackbody'|'grayscale')} [colormap='rainbow'] - Sets a colormap from predefined list of colormaps.
* @param {number} [count=32] - Sets the number of colors used to represent the data array.
*/
constructor( colormap, count = 32 ) {
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isLut = true;
/**
* The lookup table for the selected color map
*
* @type {Array<Color>}
*/
this.lut = [];
/**
* The currently selected color map.
*
* @type {Array}
*/
this.map = [];
/**
* The number of colors of the current selected color map.
*
* @type {number}
* @default 32
*/
this.n = 0;
/**
* The minimum value to be represented with the lookup table.
*
* @type {number}
* @default 0
*/
this.minV = 0;
/**
* The maximum value to be represented with the lookup table.
*
* @type {number}
* @default 1
*/
this.maxV = 1;

@@ -24,2 +79,8 @@

/**
* Sets the given LUT.
*
* @param {Lut} value - The LUT to set.
* @return {Lut} A reference to this LUT.
*/
set( value ) {

@@ -37,2 +98,8 @@

/**
* Sets the minimum value to be represented with this LUT.
*
* @param {number} min - The minimum value to be represented with the lookup table.
* @return {Lut} A reference to this LUT.
*/
setMin( min ) {

@@ -46,2 +113,8 @@

/**
* Sets the maximum value to be represented with this LUT.
*
* @param {number} max - The maximum value to be represented with the lookup table.
* @return {Lut} A reference to this LUT.
*/
setMax( max ) {

@@ -55,2 +128,9 @@

/**
* Configure the lookup table for the given color map and number of colors.
*
* @param {string} colormap - The name of the color map.
* @param {number} [count=32] - The number of colors.
* @return {Lut} A reference to this LUT.
*/
setColorMap( colormap, count = 32 ) {

@@ -105,2 +185,8 @@

/**
* Copies the given lut.
*
* @param {Lut} lut - The LUT to copy.
* @return {Lut} A reference to this LUT.
*/
copy( lut ) {

@@ -118,2 +204,8 @@

/**
* Returns an instance of Color for the given data value.
*
* @param {number} alpha - The value to lookup.
* @return {Color} The color from the LUT.
*/
getColor( alpha ) {

@@ -131,2 +223,10 @@

/**
* Adds a color map to this Lut instance.
*
* @param {string} name - The name of the color map.
* @param {Array} arrayOfColors - An array of color values. Each value is an array
* holding a threshold and the actual color value as a hexadecimal number.
* @return {Lut} A reference to this LUT.
*/
addColorMap( name, arrayOfColors ) {

@@ -140,2 +240,7 @@

/**
* Creates a canvas in order to visualize the lookup table as a texture.
*
* @return {HTMLCanvasElement} The created canvas.
*/
createCanvas() {

@@ -153,2 +258,8 @@

/**
* Updates the given canvas with the Lut's data.
*
* @param {HTMLCanvasElement} canvas - The canvas to update.
* @return {HTMLCanvasElement} The updated canvas.
*/
updateCanvas( canvas ) {

@@ -155,0 +266,0 @@

@@ -7,2 +7,6 @@ import {

const _face = new Triangle();
const _color = new Vector3();
const _uva = new Vector2(), _uvb = new Vector2(), _uvc = new Vector2();
/**

@@ -15,12 +19,35 @@ * Utility class for sampling weighted random points on the surface of a mesh.

* References:
* - http://www.joesfer.com/?p=84
* - https://stackoverflow.com/a/4322940/1314762
* - {@link http://www.joesfer.com/?p=84}
* - {@link https://stackoverflow.com/a/4322940/1314762}
*
* ```js
* const sampler = new MeshSurfaceSampler( surfaceMesh )
* .setWeightAttribute( 'color' )
* .build();
*
* const mesh = new THREE.InstancedMesh( sampleGeometry, sampleMaterial, 100 );
*
* const position = new THREE.Vector3();
* const matrix = new THREE.Matrix4();
*
* // Sample randomly from the surface, creating an instance of the sample geometry at each sample point.
*
* for ( let i = 0; i < 100; i ++ ) {
*
* sampler.sample( position );
* matrix.makeTranslation( position.x, position.y, position.z );
* mesh.setMatrixAt( i, matrix );
*
* }
*
* scene.add( mesh );
* ```
*/
const _face = new Triangle();
const _color = new Vector3();
const _uva = new Vector2(), _uvb = new Vector2(), _uvc = new Vector2();
class MeshSurfaceSampler {
/**
* Constructs a mesh surface sampler.
*
* @param {Mesh} mesh - Surface mesh from which to sample.
*/
constructor( mesh ) {

@@ -42,2 +69,12 @@

/**
* Specifies a vertex attribute to be used as a weight when sampling from the surface.
* Faces with higher weights are more likely to be sampled, and those with weights of
* zero will not be sampled at all. For vector attributes, only .x is used in sampling.
*
* If no weight attribute is selected, sampling is randomly distributed by area.
*
* @param {string} name - The attribute name.
* @return {MeshSurfaceSampler} A reference to this sampler.
*/
setWeightAttribute( name ) {

@@ -51,2 +88,9 @@

/**
* Processes the input geometry and prepares to return samples. Any configuration of the
* geometry or sampler must occur before this method is called. Time complexity is O(n)
* for a surface with n faces.
*
* @return {MeshSurfaceSampler} A reference to this sampler.
*/
build() {

@@ -114,2 +158,8 @@

/**
* Allows to set a custom random number generator. Default is `Math.random()`.
*
* @param {Function} randomFunction - A random number generator.
* @return {MeshSurfaceSampler} A reference to this sampler.
*/
setRandomGenerator( randomFunction ) {

@@ -122,17 +172,30 @@

/**
* Selects a random point on the surface of the input geometry, returning the
* position and optionally the normal vector, color and UV Coordinate at that point.
* Time complexity is O(log n) for a surface with n faces.
*
* @param {Vector3} targetPosition - The target object holding the sampled position.
* @param {Vector3} targetNormal - The target object holding the sampled normal.
* @param {Color} targetColor - The target object holding the sampled color.
* @param {Vector2} targetUV - The target object holding the sampled uv coordinates.
* @return {MeshSurfaceSampler} A reference to this sampler.
*/
sample( targetPosition, targetNormal, targetColor, targetUV ) {
const faceIndex = this.sampleFaceIndex();
return this.sampleFace( faceIndex, targetPosition, targetNormal, targetColor, targetUV );
const faceIndex = this._sampleFaceIndex();
return this._sampleFace( faceIndex, targetPosition, targetNormal, targetColor, targetUV );
}
sampleFaceIndex() {
// private
_sampleFaceIndex() {
const cumulativeTotal = this.distribution[ this.distribution.length - 1 ];
return this.binarySearch( this.randomFunction() * cumulativeTotal );
return this._binarySearch( this.randomFunction() * cumulativeTotal );
}
binarySearch( x ) {
_binarySearch( x ) {

@@ -171,3 +234,3 @@ const dist = this.distribution;

sampleFace( faceIndex, targetPosition, targetNormal, targetColor, targetUV ) {
_sampleFace( faceIndex, targetPosition, targetNormal, targetColor, targetUV ) {

@@ -174,0 +237,0 @@ let u = this.randomFunction();

@@ -40,10 +40,35 @@ import {

// OBB
/**
* Represents an oriented bounding box (OBB) in 3D space.
*/
class OBB {
/**
* Constructs a new OBB.
*
* @param {Vector3} [center] - The center of the OBB.
* @param {Vector3} [halfSize] - Positive halfwidth extents of the OBB along each axis.
* @param {Matrix3} [rotation] - The rotation of the OBB.
*/
constructor( center = new Vector3(), halfSize = new Vector3(), rotation = new Matrix3() ) {
/**
* The center of the OBB.
*
* @type {Vector3}
*/
this.center = center;
/**
* Positive halfwidth extents of the OBB along each axis.
*
* @type {Vector3}
*/
this.halfSize = halfSize;
/**
* The rotation of the OBB.
*
* @type {Matrix3}
*/
this.rotation = rotation;

@@ -53,2 +78,10 @@

/**
* Sets the OBBs components to the given values.
*
* @param {Vector3} [center] - The center of the OBB.
* @param {Vector3} [halfSize] - Positive halfwidth extents of the OBB along each axis.
* @param {Matrix3} [rotation] - The rotation of the OBB.
* @return {OBB} A reference to this OBB.
*/
set( center, halfSize, rotation ) {

@@ -64,2 +97,8 @@

/**
* Copies the values of the given OBB to this instance.
*
* @param {OBB} obb - The OBB to copy.
* @return {OBB} A reference to this OBB.
*/
copy( obb ) {

@@ -75,2 +114,7 @@

/**
* Returns a new OBB with copied values from this instance.
*
* @return {OBB} A clone of this instance.
*/
clone() {

@@ -82,5 +126,11 @@

getSize( result ) {
/**
* Returns the size of this OBB.
*
* @param {Vector3} target - The target vector that is used to store the method's result.
* @return {Vector3} The size.
*/
getSize( target ) {
return result.copy( this.halfSize ).multiplyScalar( 2 );
return target.copy( this.halfSize ).multiplyScalar( 2 );

@@ -90,11 +140,13 @@ }

/**
* Reference: Closest Point on OBB to Point in Real-Time Collision Detection
* by Christer Ericson (chapter 5.1.4)
*
* @param {Vector3} point
* @param {Vector3} result
* @returns {Vector3}
*/
clampPoint( point, result ) {
* Clamps the given point within the bounds of this OBB.
*
* @param {Vector3} point - The point that should be clamped within the bounds of this OBB.
* @param {Vector3} target - The target vector that is used to store the method's result.
* @returns {Vector3} - The clamped point.
*/
clampPoint( point, target ) {
// Reference: Closest Point on OBB to Point in Real-Time Collision Detection
// by Christer Ericson (chapter 5.1.4)
const halfSize = this.halfSize;

@@ -107,3 +159,3 @@

result.copy( this.center );
target.copy( this.center );

@@ -113,14 +165,20 @@ // project the target onto the OBB axes and walk towards that point

const x = MathUtils.clamp( v1.dot( xAxis ), - halfSize.x, halfSize.x );
result.add( xAxis.multiplyScalar( x ) );
target.add( xAxis.multiplyScalar( x ) );
const y = MathUtils.clamp( v1.dot( yAxis ), - halfSize.y, halfSize.y );
result.add( yAxis.multiplyScalar( y ) );
target.add( yAxis.multiplyScalar( y ) );
const z = MathUtils.clamp( v1.dot( zAxis ), - halfSize.z, halfSize.z );
result.add( zAxis.multiplyScalar( z ) );
target.add( zAxis.multiplyScalar( z ) );
return result;
return target;
}
/**
* Returns `true` if the given point lies within this OBB.
*
* @param {Vector3} point - The point to test.
* @returns {boolean} - Whether the given point lies within this OBB or not.
*/
containsPoint( point ) {

@@ -139,2 +197,8 @@

/**
* Returns `true` if the given AABB intersects this OBB.
*
* @param {Box3} box3 - The AABB to test.
* @returns {boolean} - Whether the given AABB intersects this OBB or not.
*/
intersectsBox3( box3 ) {

@@ -146,2 +210,8 @@

/**
* Returns `true` if the given bounding sphere intersects this OBB.
*
* @param {Sphere} sphere - The bounding sphere to test.
* @returns {boolean} - Whether the given bounding sphere intersects this OBB or not.
*/
intersectsSphere( sphere ) {

@@ -160,11 +230,13 @@

/**
* Reference: OBB-OBB Intersection in Real-Time Collision Detection
* by Christer Ericson (chapter 4.4.1)
*
* @param {OBB} obb
* @param {number} [epsilon=Number.EPSILON] - A small value to prevent arithmetic errors
* @returns {boolean}
*/
* Returns `true` if the given OBB intersects this OBB.
*
* @param {OBB} obb - The OBB to test.
* @param {number} [epsilon=Number.EPSILON] - A small value to prevent arithmetic errors.
* @returns {boolean} - Whether the given OBB intersects this OBB or not.
*/
intersectsOBB( obb, epsilon = Number.EPSILON ) {
// Reference: OBB-OBB Intersection in Real-Time Collision Detection
// by Christer Ericson (chapter 4.4.1)
// prepare data structures (the code uses the same nomenclature like the reference)

@@ -304,10 +376,12 @@

/**
* Reference: Testing Box Against Plane in Real-Time Collision Detection
* by Christer Ericson (chapter 5.2.3)
*
* @param {Plane} plane
* @returns {boolean}
*/
* Returns `true` if the given plane intersects this OBB.
*
* @param {Plane} plane - The plane to test.
* @returns {boolean} Whether the given plane intersects this OBB or not.
*/
intersectsPlane( plane ) {
// Reference: Testing Box Against Plane in Real-Time Collision Detection
// by Christer Ericson (chapter 5.2.3)
this.rotation.extractBasis( xAxis, yAxis, zAxis );

@@ -332,10 +406,10 @@

/**
* Performs a ray/OBB intersection test and stores the intersection point
* to the given 3D vector. If no intersection is detected, *null* is returned.
*
* @param {Ray} ray
* @param {Vector3} result
* @return {?Vector3}
*/
intersectRay( ray, result ) {
* Performs a ray/OBB intersection test and stores the intersection point
* in the given 3D vector.
*
* @param {Ray} ray - The ray to test.
* @param {Vector3} target - The target vector that is used to store the method's result.
* @return {?Vector3} The intersection point. If no intersection is detected, `null` is returned.
*/
intersectRay( ray, target ) {

@@ -360,7 +434,7 @@ // the idea is to perform the intersection test in the local space

if ( localRay.intersectBox( aabb, result ) ) {
if ( localRay.intersectBox( aabb, target ) ) {
// transform the intersection point back to world space
return result.applyMatrix4( matrix );
return target.applyMatrix4( matrix );

@@ -376,8 +450,7 @@ } else {

/**
* Performs a ray/OBB intersection test. Returns either true or false if
* there is a intersection or not.
*
* @param {Ray} ray
* @returns {boolean}
*/
* Returns `true` if the given ray intersects this OBB.
*
* @param {Ray} ray - The ray to test.
* @returns {boolean} Whether the given ray intersects this OBB or not.
*/
intersectsRay( ray ) {

@@ -389,2 +462,8 @@

/**
* Defines an OBB based on the given AABB.
*
* @param {Box3} box3 - The AABB to setup the OBB from.
* @return {OBB} A reference of this OBB.
*/
fromBox3( box3 ) {

@@ -402,2 +481,8 @@

/**
* Returns `true` if the given OBB is equal to this OBB.
*
* @param {OBB} obb - The OBB to test.
* @returns {boolean} Whether the given OBB is equal to this OBB or not.
*/
equals( obb ) {

@@ -411,2 +496,10 @@

/**
* Applies the given transformation matrix to this OBB. This method can be
* used to transform the bounding volume with the world matrix of a 3D object
* in order to keep both entities in sync.
*
* @param {Matrix4} matrix - The matrix to apply.
* @return {OBB} A reference of this OBB.
*/
applyMatrix4( matrix ) {

@@ -413,0 +506,0 @@

@@ -84,15 +84,63 @@ import {

/**
* An octree is a hierarchical tree data structure used to partition a three-dimensional
* space by recursively subdividing it into eight octants.
*
* This particular implementation can have up to sixteen levels and stores up to eight triangles
* in leaf nodes.
*
* `Octree` can be used in games to compute collision between the game world and colliders from
* the player or other dynamic 3D objects.
*
*
* ```js
* const octree = new Octree().fromGraphNode( scene );
* const result = octree.capsuleIntersect( playerCollider ); // collision detection
* ```
*/
class Octree {
/**
* Constructs a new Octree.
*
* @param {Box3} [box] - The base box with enclose the entire Octree.
*/
constructor( box ) {
/**
* The base box with enclose the entire Octree.
*
* @type {Box3}
*/
this.box = box;
/**
* The bounds of the Octree. Compared to {@link Octree#box}, no
* margin is applied.
*
* @type {Box3}
*/
this.bounds = new Box3();
/**
* Can by used for layers configuration for refine testing.
*
* @type {Layers}
*/
this.layers = new Layers();
// private
this.subTrees = [];
this.triangles = [];
this.layers = new Layers();
}
/**
* Adds the given triangle to the Octree. The triangle vertices are clamped if they exceed
* the bounds of the Octree.
*
* @param {Triangle} triangle - The triangle to add.
* @return {Octree} A reference to this Octree.
*/
addTriangle( triangle ) {

@@ -113,2 +161,7 @@

/**
* Prepares {@link Octree#box} for the build.
*
* @return {Octree} A reference to this Octree.
*/
calcBox() {

@@ -127,2 +180,9 @@

/**
* Splits the Octree. This method is used recursively when
* building the Octree.
*
* @param {number} level - The current level.
* @return {Octree} A reference to this Octree.
*/
split( level ) {

@@ -193,2 +253,7 @@

/**
* Builds the Octree.
*
* @return {Octree} A reference to this Octree.
*/
build() {

@@ -203,2 +268,8 @@

/**
* Computes the triangles that potentially intersect with the given ray.
*
* @param {Ray} ray - The ray to test.
* @param {Array<Triangle>} triangles - The target array that holds the triangles.
*/
getRayTriangles( ray, triangles ) {

@@ -227,6 +298,12 @@

return triangles;
}
/**
* Computes the intersection between the given capsule and triangle.
*
* @param {Capsule} capsule - The capsule to test.
* @param {Triangle} triangle - The triangle to test.
* @return {Object|false} The intersection object. If no intersection
* is detected, the method returns `false`.
*/
triangleCapsuleIntersect( capsule, triangle ) {

@@ -286,2 +363,10 @@

/**
* Computes the intersection between the given sphere and triangle.
*
* @param {Sphere} sphere - The sphere to test.
* @param {Triangle} triangle - The triangle to test.
* @return {Object|false} The intersection object. If no intersection
* is detected, the method returns `false`.
*/
triangleSphereIntersect( sphere, triangle ) {

@@ -329,2 +414,8 @@

/**
* Computes the triangles that potentially intersect with the given bounding sphere.
*
* @param {Sphere} sphere - The sphere to test.
* @param {Array<Triangle>} triangles - The target array that holds the triangles.
*/
getSphereTriangles( sphere, triangles ) {

@@ -356,2 +447,8 @@

/**
* Computes the triangles that potentially intersect with the given capsule.
*
* @param {Capsule} capsule - The capsule to test.
* @param {Array<Triangle>} triangles - The target array that holds the triangles.
*/
getCapsuleTriangles( capsule, triangles ) {

@@ -383,2 +480,9 @@

/**
* Performs a bounding sphere intersection test with this Octree.
*
* @param {Sphere} sphere - The bounding sphere to test.
* @return {Object|boolean} The intersection object. If no intersection
* is detected, the method returns `false`.
*/
sphereIntersect( sphere ) {

@@ -418,2 +522,9 @@

/**
* Performs a capsule intersection test with this Octree.
*
* @param {Capsule} capsule - The capsule to test.
* @return {Object|boolean} The intersection object. If no intersection
* is detected, the method returns `false`.
*/
capsuleIntersect( capsule ) {

@@ -453,6 +564,11 @@

/**
* Performs a ray intersection test with this Octree.
*
* @param {Ray} ray - The ray to test.
* @return {Object|boolean} The nearest intersection object. If no intersection
* is detected, the method returns `false`.
*/
rayIntersect( ray ) {
if ( ray.direction.length() === 0 ) return;
const triangles = [];

@@ -487,2 +603,8 @@ let triangle, position, distance = 1e100;

/**
* Constructs the Octree from the given 3D object.
*
* @param {Object3D} group - The scene graph node.
* @return {Octree} A reference to this Octree.
*/
fromGraphNode( group ) {

@@ -545,2 +667,7 @@

/**
* Clears the Octree by making it empty.
*
* @return {Octree} A reference to this Octree.
*/
clear() {

@@ -547,0 +674,0 @@

@@ -1,15 +0,15 @@

// Ported from Stefan Gustavson's java implementation
// http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
// Read Stefan's excellent paper for details on how this code works.
//
// Sean McCullough banksean@gmail.com
//
// Added 4D noise
/**
* You can pass in a random number generator object if you like.
* It is assumed to have a random() method.
* A utility class providing noise functions.
*
* The code is based on [Simplex noise demystified]{@link https://web.archive.org/web/20210210162332/http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf}
* by Stefan Gustavson, 2005.
*/
class SimplexNoise {
/**
* Constructs a new simplex noise object.
*
* @param {Object} [r=Math] - A math utility class that holds a `random()` method. This makes it
* possible to pass in custom random number generator.
*/
constructor( r = Math ) {

@@ -61,20 +61,9 @@

dot( g, x, y ) {
return g[ 0 ] * x + g[ 1 ] * y;
}
dot3( g, x, y, z ) {
return g[ 0 ] * x + g[ 1 ] * y + g[ 2 ] * z;
}
dot4( g, x, y, z, w ) {
return g[ 0 ] * x + g[ 1 ] * y + g[ 2 ] * z + g[ 3 ] * w;
}
/**
* A 2D simplex noise method.
*
* @param {number} xin - The x coordinate.
* @param {number} yin - The y coordinate.
* @return {number} The noise value.
*/
noise( xin, yin ) {

@@ -133,3 +122,3 @@

t0 *= t0;
n0 = t0 * t0 * this.dot( this.grad3[ gi0 ], x0, y0 ); // (x,y) of grad3 used for 2D gradient
n0 = t0 * t0 * this._dot( this.grad3[ gi0 ], x0, y0 ); // (x,y) of grad3 used for 2D gradient

@@ -143,3 +132,3 @@ }

t1 *= t1;
n1 = t1 * t1 * this.dot( this.grad3[ gi1 ], x1, y1 );
n1 = t1 * t1 * this._dot( this.grad3[ gi1 ], x1, y1 );

@@ -153,3 +142,3 @@ }

t2 *= t2;
n2 = t2 * t2 * this.dot( this.grad3[ gi2 ], x2, y2 );
n2 = t2 * t2 * this._dot( this.grad3[ gi2 ], x2, y2 );

@@ -164,3 +153,10 @@ }

// 3D simplex noise
/**
* A 3D simplex noise method.
*
* @param {number} xin - The x coordinate.
* @param {number} yin - The y coordinate.
* @param {number} zin - The z coordinate.
* @return {number} The noise value.
*/
noise3d( xin, yin, zin ) {

@@ -265,3 +261,3 @@

t0 *= t0;
n0 = t0 * t0 * this.dot3( this.grad3[ gi0 ], x0, y0, z0 );
n0 = t0 * t0 * this._dot3( this.grad3[ gi0 ], x0, y0, z0 );

@@ -275,3 +271,3 @@ }

t1 *= t1;
n1 = t1 * t1 * this.dot3( this.grad3[ gi1 ], x1, y1, z1 );
n1 = t1 * t1 * this._dot3( this.grad3[ gi1 ], x1, y1, z1 );

@@ -285,3 +281,3 @@ }

t2 *= t2;
n2 = t2 * t2 * this.dot3( this.grad3[ gi2 ], x2, y2, z2 );
n2 = t2 * t2 * this._dot3( this.grad3[ gi2 ], x2, y2, z2 );

@@ -295,3 +291,3 @@ }

t3 *= t3;
n3 = t3 * t3 * this.dot3( this.grad3[ gi3 ], x3, y3, z3 );
n3 = t3 * t3 * this._dot3( this.grad3[ gi3 ], x3, y3, z3 );

@@ -306,3 +302,11 @@ }

// 4D simplex noise
/**
* A 4D simplex noise method.
*
* @param {number} x - The x coordinate.
* @param {number} y - The y coordinate.
* @param {number} z - The z coordinate.
* @param {number} w - The w coordinate.
* @return {number} The noise value.
*/
noise4d( x, y, z, w ) {

@@ -407,3 +411,3 @@

t0 *= t0;
n0 = t0 * t0 * this.dot4( grad4[ gi0 ], x0, y0, z0, w0 );
n0 = t0 * t0 * this._dot4( grad4[ gi0 ], x0, y0, z0, w0 );

@@ -417,3 +421,3 @@ }

t1 *= t1;
n1 = t1 * t1 * this.dot4( grad4[ gi1 ], x1, y1, z1, w1 );
n1 = t1 * t1 * this._dot4( grad4[ gi1 ], x1, y1, z1, w1 );

@@ -427,3 +431,3 @@ }

t2 *= t2;
n2 = t2 * t2 * this.dot4( grad4[ gi2 ], x2, y2, z2, w2 );
n2 = t2 * t2 * this._dot4( grad4[ gi2 ], x2, y2, z2, w2 );

@@ -437,3 +441,3 @@ }

t3 *= t3;
n3 = t3 * t3 * this.dot4( grad4[ gi3 ], x3, y3, z3, w3 );
n3 = t3 * t3 * this._dot4( grad4[ gi3 ], x3, y3, z3, w3 );

@@ -447,3 +451,3 @@ }

t4 *= t4;
n4 = t4 * t4 * this.dot4( grad4[ gi4 ], x4, y4, z4, w4 );
n4 = t4 * t4 * this._dot4( grad4[ gi4 ], x4, y4, z4, w4 );

@@ -457,4 +461,24 @@ }

// private
_dot( g, x, y ) {
return g[ 0 ] * x + g[ 1 ] * y;
}
_dot3( g, x, y, z ) {
return g[ 0 ] * x + g[ 1 ] * y + g[ 2 ] * z;
}
_dot4( g, x, y, z, w ) {
return g[ 0 ] * x + g[ 1 ] * y + g[ 2 ] * z + g[ 3 ] * w;
}
}
export { SimplexNoise };

@@ -9,35 +9,29 @@ import {

const _v1 = new Vector3();
/**
* @fileoverview This class can be used to subdivide a convex Geometry object into pieces.
* This class can be used to subdivide a convex Geometry object into pieces.
*
* Usage:
*
* Use the function prepareBreakableObject to prepare a Mesh object to be broken.
*
* Then, call the various functions to subdivide the object (subdivideByImpact, cutByPlane)
*
* Then, call the various functions to subdivide the object (subdivideByImpact, cutByPlane).
* Sub-objects that are product of subdivision don't need prepareBreakableObject to be called on them.
*
* Requisites for the object:
* - Mesh object must have a buffer geometry and a material.
* - Vertex normals must be planar (not smoothed).
* - The geometry must be convex (this is not checked in the library). You can create convex
* geometries with {@link ConvexGeometry}. The {@link BoxGeometry}, {@link SphereGeometry} and other
* convex primitives can also be used.
*
* - Mesh object must have a buffer geometry and a material
*
* - Vertex normals must be planar (not smoothed)
*
* - The geometry must be convex (this is not checked in the library). You can create convex
* geometries with ConvexGeometry. The BoxGeometry, SphereGeometry and other convex primitives
* can also be used.
*
* Note: This lib adds member variables to object's userData member (see prepareBreakableObject function)
* Use with caution and read the code when using with other libs.
*
* @param {double} minSizeForBreak Min size a debris can have to break.
* @param {double} smallDelta Max distance to consider that a point belongs to a plane.
*
*/
const _v1 = new Vector3();
class ConvexObjectBreaker {
/**
* Constructs a new convex object breaker.
*
* @param {number} [minSizeForBreak=1.4] - Min size a debris can have to break.
* @param {number} [smallDelta=0.0001] - Max distance to consider that a point belongs to a plane.
*/
constructor( minSizeForBreak = 1.4, smallDelta = 0.0001 ) {

@@ -72,2 +66,11 @@

/**
* Must be called for all 3D objects that should be breakable.
*
* @param {Object3D} object - The 3D object. It must have a convex geometry.
* @param {number} mass - The 3D object's mass in kg. Must be greater than `0`.
* @param {Vector3} velocity - The 3D object's velocity.
* @param {Vector3} angularVelocity - The 3D object's angular velocity.
* @param {boolean} breakable - Whether the 3D object is breakable or not.
*/
prepareBreakableObject( object, mass, velocity, angularVelocity, breakable ) {

@@ -87,7 +90,12 @@

/*
* @param {int} maxRadialIterations Iterations for radial cuts.
* @param {int} maxRandomIterations Max random iterations for not-radial cuts
/**
* Subdivides the given 3D object into pieces by an impact (meaning another object hits
* the given 3D object at a certain surface point).
*
* Returns the array of pieces
* @param {Object3D} object - The 3D object to subdivide.
* @param {Vector3} pointOfImpact - The point of impact.
* @param {Vector3} normal - The impact normal.
* @param {number} maxRadialIterations - Iterations for radial cuts.
* @param {number} maxRandomIterations - Max random iterations for not-radial cuts.
* @return {Array<Object3D>} The array of pieces.
*/

@@ -174,2 +182,10 @@ subdivideByImpact( object, pointOfImpact, normal, maxRadialIterations, maxRandomIterations ) {

/**
* Subdivides the given 3D object into pieces by a plane.
*
* @param {Object3D} object - The 3D object to subdivide.
* @param {Plane} plane - The plane to cut the 3D object.
* @param {{object1:?Mesh,object2:?Mesh}} output - An object that stores the pieces.
* @return {number} The number of pieces.
*/
cutByPlane( object, plane, output ) {

@@ -456,2 +472,4 @@

// internal helpers
static transformFreeVector( v, m ) {

@@ -458,0 +476,0 @@

@@ -14,6 +14,6 @@ import {

/**
* GPUComputationRenderer, based on SimulationRenderer by zz85
* GPUComputationRenderer, based on SimulationRenderer by @zz85.
*
* The GPUComputationRenderer uses the concept of variables. These variables are RGBA float textures that hold 4 floats
* for each compute element (texel)
* for each compute element (texel).
*

@@ -33,8 +33,7 @@ * Each variable has a fragment shader that defines the computation made to obtain the variable in question.

* The size of the computation (sizeX * sizeY) is defined as 'resolution' automatically in the shader. For example:
* ```
* #DEFINE resolution vec2( 1024.0, 1024.0 )
*
* -------------
*
* ```
* Basic use:
*
* ```js
* // Initialization...

@@ -67,3 +66,2 @@ *

*
*
* // In each frame...

@@ -79,8 +77,8 @@ *

* renderer.render( myScene, myCamera );
* ```
*
* -------------
*
* Also, you can use utility functions to create ShaderMaterial and perform computations (rendering between textures)
* Note that the shaders can have multiple input textures.
*
* ```js
* const myFilter1 = gpuCompute.createShaderMaterial( myFilterFragmentShader1, { theTexture: { value: null } } );

@@ -106,10 +104,12 @@ * const myFilter2 = gpuCompute.createShaderMaterial( myFilterFragmentShader2, { theTexture: { value: null } } );

* gpuCompute.doRenderTarget( myFilter2, outputRenderTarget );
* ```
*/
class GPUComputationRenderer {
/**
* @param {number} sizeX Computation problem size is always 2d: sizeX * sizeY elements.
* @param {number} sizeY Computation problem size is always 2d: sizeX * sizeY elements.
* @param {WebGLRenderer} renderer The renderer
* Constructs a new GPU computation renderer.
*
* @param {number} sizeX - Computation problem size is always 2d: sizeX * sizeY elements.
* @param {number} sizeY - Computation problem size is always 2d: sizeX * sizeY elements.
* @param {WebGLRenderer} renderer - The renderer.
*/

@@ -132,2 +132,8 @@ constructor( sizeX, sizeY, renderer ) {

/**
* Sets the data type of the internal textures.
*
* @param {(FloatType|HalfFloatType)} type - The type to set.
* @return {GPUComputationRenderer} A reference to this renderer.
*/
this.setDataType = function ( type ) {

@@ -140,2 +146,10 @@

/**
* Adds a compute variable to the renderer.
*
* @param {string} variableName - The variable name.
* @param {string} computeFragmentShader - The compute (fragment) shader source.
* @param {Texture} initialValueTexture - The initial value texture.
* @return {Object} The compute variable.
*/
this.addVariable = function ( variableName, computeFragmentShader, initialValueTexture ) {

@@ -163,2 +177,8 @@

/**
* Sets variable dependencies.
*
* @param {Object} variable - The compute variable.
* @param {Array<Object>} dependencies - Other compute variables that represents the dependencies.
*/
this.setVariableDependencies = function ( variable, dependencies ) {

@@ -170,2 +190,7 @@

/**
* Initializes the renderer.
*
* @return {?string} Returns `null` if no errors are detected. Otherwise returns the error message.
*/
this.init = function () {

@@ -239,2 +264,5 @@

/**
* Executes the compute. This method is usually called in the animation loop.
*/
this.compute = function () {

@@ -273,2 +301,8 @@

/**
* Returns the current render target for the given compute variable.
*
* @param {Object} variable - The compute variable.
* @return {WebGLRenderTarget} The current render target.
*/
this.getCurrentRenderTarget = function ( variable ) {

@@ -280,2 +314,8 @@

/**
* Returns the alternate render target for the given compute variable.
*
* @param {Object} variable - The compute variable.
* @return {WebGLRenderTarget} The alternate render target.
*/
this.getAlternateRenderTarget = function ( variable ) {

@@ -287,2 +327,6 @@

/**
* Frees all internal resources. Call this method if you don't need the
* renderer anymore.
*/
this.dispose = function () {

@@ -319,2 +363,7 @@

/**
* Adds a resolution defined for the given material shader.
*
* @param {Object} materialShader - The material shader.
*/
this.addResolutionDefine = addResolutionDefine;

@@ -344,2 +393,13 @@

/**
* Creates a new render target from the given parameters.
*
* @param {number} sizeXTexture - The width of the render target.
* @param {number} sizeYTexture - The height of the render target.
* @param {number} wrapS - The wrapS value.
* @param {number} wrapT - The wrapS value.
* @param {number} minFilter - The minFilter value.
* @param {number} magFilter - The magFilter value.
* @return {WebGLRenderTarget} The new render target.
*/
this.createRenderTarget = function ( sizeXTexture, sizeYTexture, wrapS, wrapT, minFilter, magFilter ) {

@@ -370,2 +430,7 @@

/**
* Creates a new data texture.
*
* @return {DataTexture} The new data texture.
*/
this.createTexture = function () {

@@ -380,8 +445,10 @@

/**
* Renders the given texture into the given render target.
*
* @param {Texture} input - The input.
* @param {WebGLRenderTarget} output - The output.
*/
this.renderTexture = function ( input, output ) {
// Takes a texture, and render out in rendertarget
// input = Texture
// output = RenderTarget
passThruUniforms.passThruTexture.value = input;

@@ -395,2 +462,10 @@

/**
* Renders the given material into the given render target
* with a full-screen pass.
*
* @param {Material} material - The material.
* @param {WebGLRenderTarget} output - The output.
*/
this.doRenderTarget = function ( material, output ) {

@@ -397,0 +472,0 @@

@@ -15,4 +15,15 @@ import {

/**
* A special type of 3D object that takes a position from the scene graph hierarchy
* but uses its local rotation as world rotation. It works like real-world gyroscope -
* you can move it around using hierarchy while its orientation stays fixed with
* respect to the world.
*
* @augments Object3D
*/
class Gyroscope extends Object3D {
/**
* Constructs a new gyroscope.
*/
constructor() {

@@ -19,0 +30,0 @@

@@ -13,25 +13,98 @@ import {

/**
* This class represents a management component for animated MD2
* character assets.
*/
class MD2Character {
/**
* Constructs a new MD2 character.
*/
constructor() {
/**
* The mesh scale.
*
* @type {number}
* @default 1
*/
this.scale = 1;
/**
* The FPS
*
* @type {number}
* @default 6
*/
this.animationFPS = 6;
/**
* The root 3D object
*
* @type {Object3D}
*/
this.root = new Object3D();
/**
* The body mesh.
*
* @type {?Mesh}
* @default null
*/
this.meshBody = null;
/**
* The weapon mesh.
*
* @type {?Mesh}
* @default null
*/
this.meshWeapon = null;
/**
* The body skins.
*
* @type {Array<Texture>}
*/
this.skinsBody = [];
/**
* The weapon skins.
*
* @type {Array<Texture>}
*/
this.skinsWeapon = [];
/**
* The weapon meshes.
*
* @type {Array<Mesh>}
*/
this.weapons = [];
this.activeAnimation = null;
/**
* The name of the active animation clip.
*
* @type {?string}
* @default null
*/
this.activeAnimationClipName = null;
/**
* The animation mixer.
*
* @type {?AnimationMixer}
* @default null
*/
this.mixer = null;
/**
* The `onLoad` callback function.
*
* @type {Function}
*/
this.onLoadComplete = function () {};
// internal
this.loadCounter = 0;

@@ -41,2 +114,7 @@

/**
* Loads the character model for the given config.
*
* @param {Object} config - The config which defines the model and textures paths.
*/
loadParts( config ) {

@@ -161,2 +239,7 @@

/**
* Sets the animation playback rate.
*
* @param {number} rate - The playback rate to set.
*/
setPlaybackRate( rate ) {

@@ -176,2 +259,7 @@

/**
* Sets the wireframe material flag.
*
* @param {boolean} wireframeEnabled - Whether to enable wireframe rendering or not.
*/
setWireframe( wireframeEnabled ) {

@@ -193,2 +281,8 @@

/**
* Sets the skin defined by the given skin index. This will result in a different texture
* for the body mesh.
*
* @param {number} index - The skin index.
*/
setSkin( index ) {

@@ -204,2 +298,8 @@

/**
* Sets the weapon defined by the given weapon index. This will result in a different weapon
* hold by the character.
*
* @param {number} index - The weapon index.
*/
setWeapon( index ) {

@@ -222,2 +322,7 @@

/**
* Sets the defined animation clip as the active animation.
*
* @param {string} clipName - The name of the animation clip.
*/
setAnimation( clipName ) {

@@ -250,2 +355,5 @@

/**
* Synchronizes the weapon with the body animation.
*/
syncWeaponAnimation() {

@@ -276,2 +384,7 @@

/**
* Updates the animations of the mesh. Must be called inside the animation loop.
*
* @param {number} delta - The delta time in seconds.
*/
update( delta ) {

@@ -278,0 +391,0 @@

@@ -13,41 +13,143 @@ import {

/**
* This class represents a management component for animated MD2
* character assets. It provides a larger API compared to {@link MD2Character}.
*/
class MD2CharacterComplex {
/**
* Constructs a new MD2 character.
*/
constructor() {
/**
* The mesh scale.
*
* @type {number}
* @default 1
*/
this.scale = 1;
// animation parameters
/**
* The FPS
*
* @type {number}
* @default 6
*/
this.animationFPS = 6;
this.animationFPS = 6;
/**
* The transition frames.
*
* @type {number}
* @default 15
*/
this.transitionFrames = 15;
// movement model parameters
/**
* The character's maximum speed.
*
* @type {number}
* @default 275
*/
this.maxSpeed = 275;
this.maxSpeed = 275;
/**
* The character's maximum reverse speed.
*
* @type {number}
* @default - 275
*/
this.maxReverseSpeed = - 275;
/**
* The character's front acceleration.
*
* @type {number}
* @default 600
*/
this.frontAcceleration = 600;
/**
* The character's back acceleration.
*
* @type {number}
* @default 600
*/
this.backAcceleration = 600;
/**
* The character's front decceleration.
*
* @type {number}
* @default 600
*/
this.frontDecceleration = 600;
/**
* The character's angular speed.
*
* @type {number}
* @default 2.5
*/
this.angularSpeed = 2.5;
// rig
/**
* The root 3D object
*
* @type {Object3D}
*/
this.root = new Object3D();
/**
* The body mesh.
*
* @type {?Mesh}
* @default null
*/
this.meshBody = null;
/**
* The weapon mesh.
*
* @type {?Mesh}
* @default null
*/
this.meshWeapon = null;
/**
* The movement controls.
*
* @type {Object}
* @default null
*/
this.controls = null;
// skins
/**
* The body skins.
*
* @type {Array<Texture>}
*/
this.skinsBody = [];
this.skinsBody = [];
/**
* The weapon skins.
*
* @type {Array<Texture>}
*/
this.skinsWeapon = [];
/**
* The weapon meshes.
*
* @type {Array<Mesh>}
*/
this.weapons = [];
/**
* The current skin.
*
* @type {Texture}
* @default undefined
*/
this.currentSkin = undefined;

@@ -83,2 +185,7 @@

/**
* Toggles shadow casting and receiving on the character's meshes.
*
* @param {boolean} enable - Whether to enable shadows or not.
*/
enableShadows( enable ) {

@@ -95,2 +202,7 @@

/**
* Toggles visibility on the character's meshes.
*
* @param {boolean} enable - Whether the character is visible or not.
*/
setVisible( enable ) {

@@ -107,2 +219,7 @@

/**
* Shares certain resources from a different character model.
*
* @param {MD2CharacterComplex} original - The original MD2 character.
*/
shareParts( original ) {

@@ -150,2 +267,7 @@

/**
* Loads the character model for the given config.
*
* @param {Object} config - The config which defines the model and textures paths.
*/
loadParts( config ) {

@@ -249,2 +371,7 @@

/**
* Sets the animation playback rate.
*
* @param {number} rate - The playback rate to set.
*/
setPlaybackRate( rate ) {

@@ -257,2 +384,7 @@

/**
* Sets the wireframe material flag.
*
* @param {boolean} wireframeEnabled - Whether to enable wireframe rendering or not.
*/
setWireframe( wireframeEnabled ) {

@@ -274,2 +406,8 @@

/**
* Sets the skin defined by the given skin index. This will result in a different texture
* for the body mesh.
*
* @param {number} index - The skin index.
*/
setSkin( index ) {

@@ -286,2 +424,8 @@

/**
* Sets the weapon defined by the given weapon index. This will result in a different weapon
* hold by the character.
*
* @param {number} index - The weapon index.
*/
setWeapon( index ) {

@@ -309,2 +453,7 @@

/**
* Sets the defined animation clip as the active animation.
*
* @param {string} animationName - The name of the animation clip.
*/
setAnimation( animationName ) {

@@ -349,2 +498,7 @@

/**
* Updates the animations of the mesh. Must be called inside the animation loop.
*
* @param {number} delta - The delta time in seconds.
*/
updateAnimations( delta ) {

@@ -381,2 +535,5 @@

/**
* Updates the animation state based on the control inputs.
*/
updateBehaviors() {

@@ -491,2 +648,7 @@

/**
* Transforms the character model based on the control input.
*
* @param {number} delta - The delta time in seconds.
*/
updateMovementModel( delta ) {

@@ -493,0 +655,0 @@

@@ -7,4 +7,17 @@ import {

/**
* A special type of an animated mesh with a simple interface
* for animation playback. It allows to playback just one animation
* without any transitions or fading between animation changes.
*
* @augments Mesh
*/
class MorphAnimMesh extends Mesh {
/**
* Constructs a new morph anim mesh.
*
* @param {BufferGeometry} [geometry] - The mesh geometry.
* @param {Material|Array<Material>} [material] - The mesh material.
*/
constructor( geometry, material ) {

@@ -16,3 +29,15 @@

/**
* The internal animation mixer.
*
* @type {AnimationMixer}
*/
this.mixer = new AnimationMixer( this );
/**
* The current active animation action.
*
* @type {?AnimationAction}
* @default null
*/
this.activeAction = null;

@@ -22,2 +47,5 @@

/**
* Sets the animation playback direction to "forward".
*/
setDirectionForward() {

@@ -29,2 +57,5 @@

/**
* Sets the animation playback direction to "backward".
*/
setDirectionBackward() {

@@ -36,2 +67,9 @@

/**
* Plays the defined animation clip. The implementation assumes the animation
* clips are stored in {@link Object3D#animations} or the geometry.
*
* @param {string} label - The name of the animation clip.
* @param {number} fps - The FPS of the animation clip.
*/
playAnimation( label, fps ) {

@@ -62,2 +100,7 @@

/**
* Updates the animations of the mesh. Must be called inside the animation loop.
*
* @param {number} delta - The delta time in seconds.
*/
updateAnimation( delta ) {

@@ -64,0 +107,0 @@

@@ -6,4 +6,18 @@ import {

/**
* A special type of an animated mesh with a more advanced interface
* for animation playback. Unlike {@link MorphAnimMesh}. It allows to
* playback more than one morph animation at the same time but without
* fading options.
*
* @augments Mesh
*/
class MorphBlendMesh extends Mesh {
/**
* Constructs a new morph blend mesh.
*
* @param {BufferGeometry} [geometry] - The mesh geometry.
* @param {Material|Array<Material>} [material] - The mesh material.
*/
constructor( geometry, material ) {

@@ -13,3 +27,14 @@

/**
* A dictionary of animations.
*
* @type {Object<string,Object>}
*/
this.animationsMap = {};
/**
* A list of animations.
*
* @type {Array<Object>}
*/
this.animationsList = [];

@@ -34,2 +59,10 @@

/**
* Creates a new animation.
*
* @param {string} name - The animation name.
* @param {number} start - The start time.
* @param {number} end - The end time.
* @param {number} fps - The FPS.
*/
createAnimation( name, start, end, fps ) {

@@ -66,2 +99,8 @@

/**
* Automatically creates animations based on the values in
* {@link Mesh#morphTargetDictionary}.
*
* @param {number} fps - The FPS of all animations.
*/
autoCreateAnimations( fps ) {

@@ -111,2 +150,8 @@

/**
* Sets the animation playback direction to "forward" for the
* defined animation.
*
* @param {string} name - The animation name.
*/
setAnimationDirectionForward( name ) {

@@ -125,2 +170,8 @@

/**
* Sets the animation playback direction to "backward" for the
* defined animation.
*
* @param {string} name - The animation name.
*/
setAnimationDirectionBackward( name ) {

@@ -139,2 +190,8 @@

/**
* Sets the FPS to the given value for the defined animation.
*
* @param {string} name - The animation name.
* @param {number} fps - The FPS to set.
*/
setAnimationFPS( name, fps ) {

@@ -153,2 +210,8 @@

/**
* Sets the duration to the given value for the defined animation.
*
* @param {string} name - The animation name.
* @param {number} duration - The duration to set.
*/
setAnimationDuration( name, duration ) {

@@ -167,2 +230,8 @@

/**
* Sets the weight to the given value for the defined animation.
*
* @param {string} name - The animation name.
* @param {number} weight - The weight to set.
*/
setAnimationWeight( name, weight ) {

@@ -180,2 +249,8 @@

/**
* Sets the time to the given value for the defined animation.
*
* @param {string} name - The animation name.
* @param {number} time - The time to set.
*/
setAnimationTime( name, time ) {

@@ -193,2 +268,8 @@

/**
* Returns the time for the defined animation.
*
* @param {string} name - The animation name.
* @return {number} The time.
*/
getAnimationTime( name ) {

@@ -210,2 +291,8 @@

/**
* Returns the duration for the defined animation.
*
* @param {string} name - The animation name.
* @return {number} The duration.
*/
getAnimationDuration( name ) {

@@ -227,2 +314,7 @@

/**
* Plays the defined animation.
*
* @param {string} name - The animation name.
*/
playAnimation( name ) {

@@ -245,2 +337,7 @@

/**
* Stops the defined animation.
*
* @param {string} name - The animation name.
*/
stopAnimation( name ) {

@@ -258,2 +355,7 @@

/**
* Updates the animations of the mesh.
*
* @param {number} delta - The delta time in seconds.
*/
update( delta ) {

@@ -260,0 +362,0 @@

@@ -5,3 +5,3 @@ import { DoubleSide, FloatType, HalfFloatType, Mesh, MeshBasicMaterial, MeshPhongMaterial, PlaneGeometry, Scene, WebGLRenderTarget } from 'three';

/**
* Progressive Light Map Accumulator, by [zalo](https://github.com/zalo/)
* Progressive Light Map Accumulator, by [zalo]{@link https://github.com/zalo/}.
*

@@ -17,2 +17,5 @@ * To use, simply construct a `ProgressiveLightMap` object,

* the texture-space effect you're looking for.
*
* This class can only be used with {@link WebGLRenderer}.
* When using {@link WebGPURenderer}, import from `ProgressiveLightMapGPU.js`.
*/

@@ -22,9 +25,26 @@ class ProgressiveLightMap {

/**
* @param {WebGLRenderer} renderer An instance of WebGLRenderer.
* @param {number} [res=1024] The side-long dimension of you total lightmap.
* Constructs a new progressive light map.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {number} [res=1024] - The side-long dimension of the total lightmap.
*/
constructor( renderer, res = 1024 ) {
/**
* The renderer.
*
* @type {WebGLRenderer}
*/
this.renderer = renderer;
/**
* The side-long dimension of the total lightmap.
*
* @type {number}
* @default 1024
*/
this.res = res;
// internals
this.lightMapContainers = [];

@@ -82,3 +102,4 @@ this.scene = new Scene();

* Sets these objects' materials' lightmaps and modifies their uv1's.
* @param {Object3D} objects An array of objects and lights to set up your lightmap.
*
* @param {Array<Object3D>} objects - An array of objects and lights to set up your lightmap.
*/

@@ -149,6 +170,7 @@ addObjectsToLightMap( objects ) {

/**
* This function renders each mesh one at a time into their respective surface maps
* @param {Camera} camera Standard Rendering Camera
* @param {number} blendWindow When >1, samples will accumulate over time.
* @param {boolean} blurEdges Whether to fix UV Edges via blurring
* This function renders each mesh one at a time into their respective surface maps.
*
* @param {Camera} camera - The camera the scene is rendered with.
* @param {number} [blendWindow=100] - When >1, samples will accumulate over time.
* @param {boolean} [blurEdges=true] - Whether to fix UV Edges via blurring.
*/

@@ -223,6 +245,7 @@ update( camera, blendWindow = 100, blurEdges = true ) {

/** DEBUG
* Draw the lightmap in the main scene. Call this after adding the objects to it.
* @param {boolean} visible Whether the debug plane should be visible
* @param {Vector3} position Where the debug plane should be drawn
/**
* Draws the lightmap in the main scene. Call this after adding the objects to it.
*
* @param {boolean} visible - Whether the debug plane should be visible
* @param {Vector3} [position] - Where the debug plane should be drawn
*/

@@ -260,5 +283,7 @@ showDebugLightmap( visible, position = undefined ) {

/**
* INTERNAL Creates the Blurring Plane
* @param {number} res The square resolution of this object's lightMap.
* @param {WebGLRenderTexture} lightMap The lightmap to initialize the plane with.
* Creates the Blurring Plane.
*
* @private
* @param {number} res - The square resolution of this object's lightMap.
* @param {WebGLRenderTarget} [lightMap] - The lightmap to initialize the plane with.
*/

@@ -265,0 +290,0 @@ _initializeBlurPlane( res, lightMap = null ) {

@@ -7,3 +7,3 @@ import { DoubleSide, FloatType, HalfFloatType, PlaneGeometry, Mesh, RenderTarget, Scene, MeshPhongNodeMaterial, NodeMaterial } from 'three/webgpu';

/**
* Progressive Light Map Accumulator, by [zalo](https://github.com/zalo/)
* Progressive Light Map Accumulator, by [zalo]{@link https://github.com/zalo/}.
*

@@ -19,2 +19,5 @@ * To use, simply construct a `ProgressiveLightMap` object,

* the texture-space effect you're looking for.
*
* This class can only be used with {@link WebGPURenderer}.
* When using {@link WebGLRenderer}, import from `ProgressiveLightMap.js`.
*/

@@ -24,8 +27,20 @@ class ProgressiveLightMap {

/**
* @param {WebGPURenderer} renderer An instance of WebGPURenderer.
* @param {number} [resolution=1024] The side-long dimension of you total lightmap.
* @param {WebGPURenderer} renderer - The renderer.
* @param {number} [resolution=1024] - The side-long dimension of the total lightmap.
*/
constructor( renderer, resolution = 1024 ) {
/**
* The renderer.
*
* @type {WebGPURenderer}
*/
this.renderer = renderer;
/**
* The side-long dimension of the total lightmap.
*
* @type {number}
* @default 1024
*/
this.resolution = resolution;

@@ -63,3 +78,4 @@

* Sets these objects' materials' lightmaps and modifies their uv1's.
* @param {Object3D} objects An array of objects and lights to set up your lightmap.
*
* @param {Array<Object3D>} objects - An array of objects and lights to set up your lightmap.
*/

@@ -103,5 +119,5 @@ addObjectsToLightMap( objects ) {

// Prepare UV boxes for potpack
// Prepare UV boxes for potpack (potpack will update x and y)
// TODO: Size these by object surface area
uv_boxes.push( { w: 1 + ( padding * 2 ), h: 1 + ( padding * 2 ), index: ob } );
uv_boxes.push( { w: 1 + ( padding * 2 ), h: 1 + ( padding * 2 ), index: ob, x: 0, y: 0 } );

@@ -158,6 +174,7 @@ this._lightMapContainers.push( { basicMat: object.material, object: object } );

/**
* This function renders each mesh one at a time into their respective surface maps
* @param {Camera} camera Standard Rendering Camera
* @param {number} blendWindow When >1, samples will accumulate over time.
* @param {boolean} blurEdges Whether to fix UV Edges via blurring
* This function renders each mesh one at a time into their respective surface maps.
*
* @param {Camera} camera - The camera the scene is rendered with.
* @param {number} [blendWindow=100] - When >1, samples will accumulate over time.
* @param {boolean} [blurEdges=true] - Whether to fix UV Edges via blurring.
*/

@@ -222,5 +239,6 @@ update( camera, blendWindow = 100, blurEdges = true ) {

/**
* Draw the lightmap in the main scene. Call this after adding the objects to it.
* @param {boolean} visible Whether the debug plane should be visible.
* @param {Vector3} position Where the debug plane should be drawn.
* Draws the lightmap in the main scene. Call this after adding the objects to it.
*
* @param {boolean} visible - Whether the debug plane should be visible
* @param {Vector3} [position] - Where the debug plane should be drawn
*/

@@ -264,2 +282,4 @@ showDebugLightmap( visible, position = null ) {

* Creates the Blurring Plane.
*
* @private
*/

@@ -266,0 +286,0 @@ _initializeBlurPlane() {

@@ -11,4 +11,15 @@ import {

/**
* A procedural roller coaster geometry.
*
* @augments BufferGeometry
*/
class RollerCoasterGeometry extends BufferGeometry {
/**
* Constructs a new geometry.
*
* @param {Curve} curve - The curve to generate the geometry along.
* @param {number} divisions - The number of divisions which defines the detail of the geometry.
*/
constructor( curve, divisions ) {

@@ -226,4 +237,15 @@

/**
* A procedural roller coaster lifters geometry.
*
* @augments BufferGeometry
*/
class RollerCoasterLiftersGeometry extends BufferGeometry {
/**
* Constructs a new geometry.
*
* @param {Curve} curve - The curve to generate the geometry along.
* @param {number} divisions - The number of divisions which defines the detail of the geometry.
*/
constructor( curve, divisions ) {

@@ -403,4 +425,15 @@

/**
* A procedural roller coaster shadow geometry.
*
* @augments BufferGeometry
*/
class RollerCoasterShadowGeometry extends BufferGeometry {
/**
* Constructs a new geometry.
*
* @param {Curve} curve - The curve to generate the geometry along.
* @param {number} divisions - The number of divisions which defines the detail of the geometry.
*/
constructor( curve, divisions ) {

@@ -476,4 +509,12 @@

/**
* A procedural sky geometry.
*
* @augments BufferGeometry
*/
class SkyGeometry extends BufferGeometry {
/**
* Constructs a new geometry.
*/
constructor() {

@@ -510,4 +551,15 @@

/**
* A procedural trees geometry.
*
* @augments BufferGeometry
*/
class TreesGeometry extends BufferGeometry {
/**
* Constructs a new geometry.
*
* @param {Mesh} landscape - A mesh representing the landscape. Trees will be positioned
* randomly on the landscape's surface.
*/
constructor( landscape ) {

@@ -514,0 +566,0 @@

@@ -0,3 +1,20 @@

/**
* This class is an alternative to {@link Clock} with a different API design and behavior.
* The goal is to avoid the conceptual flaws that became apparent in `Clock` over time.
*
* - `Timer` has an `update()` method that updates its internal state. That makes it possible to
* call `getDelta()` and `getElapsed()` multiple times per simulation step without getting different values.
* - The class can make use of the Page Visibility API to avoid large time delta values when the app
* is inactive (e.g. tab switched or browser hidden).
*
* ```js
* const timer = new Timer();
* timer.connect( document ); // use Page Visibility API
* ```
*/
class Timer {
/**
* Constructs a new timer.
*/
constructor() {

@@ -19,2 +36,9 @@

/**
* Connect the timer to the given document.Calling this method is not mandatory to
* use the timer but enables the usage of the Page Visibility API to avoid large time
* delta values.
*
* @param {Document} document - The document.
*/
connect( document ) {

@@ -36,2 +60,5 @@

/**
* Disconnects the timer from the DOM and also disables the usage of the Page Visibility API.
*/
disconnect() {

@@ -50,2 +77,7 @@

/**
* Returns the time delta in seconds.
*
* @return {number} The time delta in second.
*/
getDelta() {

@@ -57,2 +89,7 @@

/**
* Returns the elapsed time in seconds.
*
* @return {number} The elapsed time in second.
*/
getElapsed() {

@@ -64,2 +101,7 @@

/**
* Returns the timescale.
*
* @return {number} The timescale.
*/
getTimescale() {

@@ -71,2 +113,9 @@

/**
* Sets the given timescale which scale the time delta computation
* in `update()`.
*
* @param {number} timescale - The timescale to set.
* @return {Timer} A reference to this timer.
*/
setTimescale( timescale ) {

@@ -80,2 +129,7 @@

/**
* Resets the time computation for the current simulation step.
*
* @return {Timer} A reference to this timer.
*/
reset() {

@@ -89,2 +143,6 @@

/**
* Can be used to free all internal resources. Usually called when
* the timer instance isn't required anymore.
*/
dispose() {

@@ -94,6 +152,14 @@

return this;
}
/**
* Updates the internal state of the timer. This method should be called
* once per simulation step and before you perform queries against the timer
* (e.g. via `getDelta()`).
*
* @param {number} timestamp - The current time in milliseconds. Can be obtained
* from the `requestAnimationFrame` callback argument. If not provided, the current
* time will be determined with `performance.now`.
* @return {Timer} A reference to this timer.
*/
update( timestamp ) {

@@ -121,4 +187,15 @@

/**
* A special version of a timer with a fixed time delta value.
* Can be useful for testing and debugging purposes.
*
* @augments Timer
*/
class FixedTimer extends Timer {
/**
* Constructs a new timer.
*
* @param {number} [fps=60] - The fixed FPS of this timer.
*/
constructor( fps = 60 ) {

@@ -125,0 +202,0 @@

@@ -12,2 +12,15 @@ import {

/**
* @classdesc This module can be used to paint tube-like meshes
* along a sequence of points. This module is used in a XR
* painter demo.
*
* ```js
* const painter = new TubePainter();
* scene.add( painter.mesh );
* ```
*
* @name TubePainter
* @class
*/
function TubePainter() {

@@ -194,6 +207,46 @@

return {
/**
* The "painted" tube mesh. Must be added to the scene.
*
* @name TubePainter#mesh
* @type {Mesh}
*/
mesh: mesh,
/**
* Moves the current painting position to the given value.
*
* @method
* @name TubePainter#moveTo
* @param {Vector3} position The new painting position.
*/
moveTo: moveTo,
/**
* Draw a stroke from the current position to the given one.
* This method extends the tube while drawing with the XR
* controllers.
*
* @method
* @name TubePainter#lineTo
* @param {Vector3} position The destination position.
*/
lineTo: lineTo,
/**
* Sets the size of newly rendered tube segments.
*
* @method
* @name TubePainter#setSize
* @param {number} size The size.
*/
setSize: setSize,
/**
* Updates the internal geometry buffers so the new painted
* segments are rendered.
*
* @method
* @name TubePainter#update
*/
update: update

@@ -200,0 +253,0 @@ };

@@ -9,7 +9,4 @@ import {

/**
* This class had been written to handle the output of the NRRD loader.
* It contains a volume of data and information about it.
* For now it only handles 3 dimensional data.
* See the webgl_loader_nrrd.html example and the loaderNRRD.js file to see how to use this class.
* @class
* This class had been written to handle the output of the {@link NRRDLoader}.
* It contains a volume of data and information about it. For now it only handles 3 dimensional data.
*/

@@ -19,7 +16,9 @@ class Volume {

/**
* @param {number} xLength Width of the volume
* @param {number} yLength Length of the volume
* @param {number} zLength Depth of the volume
* @param {string} type The type of data (uint8, uint16, ...)
* @param {ArrayBuffer} arrayBuffer The buffer with volume data
* Constructs a new volume.
*
* @param {number} [xLength] - Width of the volume.
* @param {number} [yLength] - Length of the volume.
* @param {number} [zLength] - Depth of the volume.
* @param {string} [type] - The type of data (uint8, uint16, ...).
* @param {ArrayBuffer} [arrayBuffer] - The buffer with volume data.
*/

@@ -31,20 +30,38 @@ constructor( xLength, yLength, zLength, type, arrayBuffer ) {

/**
* @member {number} xLength Width of the volume in the IJK coordinate system
* Width of the volume in the IJK coordinate system.
*
* @type {number}
* @default 1
*/
this.xLength = Number( xLength ) || 1;
/**
* @member {number} yLength Height of the volume in the IJK coordinate system
* Height of the volume in the IJK coordinate system.
*
* @type {number}
* @default 1
*/
this.yLength = Number( yLength ) || 1;
/**
* @member {number} zLength Depth of the volume in the IJK coordinate system
* Depth of the volume in the IJK coordinate system.
*
* @type {number}
* @default 1
*/
this.zLength = Number( zLength ) || 1;
/**
* @member {Array<string>} The order of the Axis dictated by the NRRD header
* The order of the Axis dictated by the NRRD header
*
* @type {Array<string>}
*/
this.axisOrder = [ 'x', 'y', 'z' ];
/**
* @member {TypedArray} data Data of the volume
* The data of the volume.
*
* @type {TypedArray}
*/
this.data;

@@ -135,21 +152,30 @@ switch ( type ) {

/**
* @member {Array} spacing Spacing to apply to the volume from IJK to RAS coordinate system
* Spacing to apply to the volume from IJK to RAS coordinate system
*
* @type {Array<number>}
*/
this.spacing = [ 1, 1, 1 ];
/**
* @member {Array} offset Offset of the volume in the RAS coordinate system
* Offset of the volume in the RAS coordinate system
*
* @type {Array<number>}
*/
this.offset = [ 0, 0, 0 ];
/**
* @member {Martrix3} matrix The IJK to RAS matrix
* The IJK to RAS matrix.
*
* @type {Martrix3}
*/
this.matrix = new Matrix3();
this.matrix.identity();
/**
* @member {Martrix3} inverseMatrix The RAS to IJK matrix
* The RAS to IJK matrix.
*
* @type {Martrix3}
*/
/**
* @member {number} lowerThreshold The voxels with values under this threshold won't appear in the slices.
* If changed, geometryNeedsUpdate is automatically set to true on all the slices associated to this volume
*/
this.inverseMatrix = new Matrix3();
let lowerThreshold = - Infinity;

@@ -162,2 +188,10 @@ Object.defineProperty( this, 'lowerThreshold', {

},
/**
* The voxels with values under this threshold won't appear in the slices.
* If changed, geometryNeedsUpdate is automatically set to true on all the slices associated to this volume.
*
* @name Volume#lowerThreshold
* @type {number}
* @param {number} value
*/
set: function ( value ) {

@@ -174,6 +208,3 @@

} );
/**
* @member {number} upperThreshold The voxels with values over this threshold won't appear in the slices.
* If changed, geometryNeedsUpdate is automatically set to true on all the slices associated to this volume
*/
let upperThreshold = Infinity;

@@ -186,2 +217,10 @@ Object.defineProperty( this, 'upperThreshold', {

},
/**
* The voxels with values over this threshold won't appear in the slices.
* If changed, geometryNeedsUpdate is automatically set to true on all the slices associated to this volume
*
* @name Volume#upperThreshold
* @type {number}
* @param {number} value
*/
set: function ( value ) {

@@ -201,9 +240,14 @@

/**
* @member {Array} sliceList The list of all the slices associated to this volume
* The list of all the slices associated to this volume
*
* @type {Array}
*/
this.sliceList = [];
/**
* @member {boolean} segmentation in segmentation mode, it can load 16-bits nrrds correctly
* Whether to use segmentation mode or not.
* It can load 16-bits nrrds correctly.
*
* @type {boolean}
* @default false
*/

@@ -214,17 +258,17 @@ this.segmentation = false;

/**
* @member {Array} RASDimensions This array holds the dimensions of the volume in the RAS space
* This array holds the dimensions of the volume in the RAS space
*
* @type {Array<number>}
*/
this.RASDimensions = [];
}
/**
* Shortcut for data[access(i,j,k)]
* Shortcut for data[access(i,j,k)].
*
* @memberof Volume
* @param {number} i First coordinate
* @param {number} j Second coordinate
* @param {number} k Third coordinate
* @returns {number} value in the data array
* @param {number} i - First coordinate.
* @param {number} j - Second coordinate.
* @param {number} k - Third coordinate.
* @returns {number} The value in the data array.
*/

@@ -238,9 +282,8 @@ getData( i, j, k ) {

/**
* Compute the index in the data array corresponding to the given coordinates in IJK system
* Compute the index in the data array corresponding to the given coordinates in IJK system.
*
* @memberof Volume
* @param {number} i First coordinate
* @param {number} j Second coordinate
* @param {number} k Third coordinate
* @returns {number} index
* @param {number} i - First coordinate.
* @param {number} j - Second coordinate.
* @param {number} k - Third coordinate.
* @returns {number} The index.
*/

@@ -254,7 +297,6 @@ access( i, j, k ) {

/**
* Retrieve the IJK coordinates of the voxel corresponding of the given index in the data
* Retrieve the IJK coordinates of the voxel corresponding of the given index in the data.
*
* @memberof Volume
* @param {number} index index of the voxel
* @returns {Array} [x,y,z]
* @param {number} index - Index of the voxel.
* @returns {Array<number>} The IJK coordinates as `[x,y,z]`.
*/

@@ -271,11 +313,8 @@ reverseAccess( index ) {

/**
* Apply a function to all the voxels, be careful, the value will be replaced
* Apply a function to all the voxels, be careful, the value will be replaced.
*
* @memberof Volume
* @param {Function} functionToMap A function to apply to every voxel, will be called with the following parameters :
* value of the voxel
* index of the voxel
* the data (TypedArray)
* @param {Object} context You can specify a context in which call the function, default if this Volume
* @returns {Volume} this
* @param {Function} functionToMap A function to apply to every voxel, will be called with the following parameters:
* value of the voxel, index of the voxel, the data (TypedArray).
* @param {Object} context - You can specify a context in which call the function, default if this Volume.
* @returns {Volume} A reference to this instance.
*/

@@ -298,8 +337,8 @@ map( functionToMap, context ) {

/**
* Compute the orientation of the slice and returns all the information relative to the geometry such as sliceAccess, the plane matrix (orientation and position in RAS coordinate) and the dimensions of the plane in both coordinate system.
* Compute the orientation of the slice and returns all the information relative to the geometry such as sliceAccess,
* the plane matrix (orientation and position in RAS coordinate) and the dimensions of the plane in both coordinate system.
*
* @memberof Volume
* @param {string} axis the normal axis to the slice 'x' 'y' or 'z'
* @param {number} RASIndex the index of the slice
* @returns {Object} an object containing all the useful information on the geometry of the slice
* @param {('x'|'y'|'z')} axis - The normal axis to the slice.
* @param {number} RASIndex - The index of the slice.
* @returns {Object} An object containing all the useful information on the geometry of the slice.
*/

@@ -427,6 +466,5 @@ extractPerpendicularPlane( axis, RASIndex ) {

*
* @memberof Volume
* @param {string} axis the normal axis to the slice 'x' 'y' or 'z'
* @param {number} index the index of the slice
* @returns {VolumeSlice} the extracted slice
* @param {('x'|'y'|'z')} axis - The normal axis to the slice.
* @param {number} index - The index of the slice.
* @returns {VolumeSlice} The extracted slice.
*/

@@ -442,7 +480,6 @@ extractSlice( axis, index ) {

/**
* Call repaint on all the slices extracted from this volume
* Call repaint on all the slices extracted from this volume.
*
* @see {@link VolumeSlice#repaint}
* @memberof Volume
* @returns {Volume} this
* @returns {Volume} A reference to this volume.
*/

@@ -462,6 +499,5 @@ repaintAllSlices() {

/**
* Compute the minimum and the maximum of the data in the volume
* Compute the minimum and the maximum of the data in the volume.
*
* @memberof Volume
* @returns {Array} [min,max]
* @returns {Array<number>} The min/max data as `[min,max]`.
*/

@@ -468,0 +504,0 @@ computeMinMax() {

@@ -13,4 +13,4 @@ import {

/**
* This class has been made to hold a slice of a volume data
* @class
* This class has been made to hold a slice of a volume data.
*
* @see {@link Volume}

@@ -21,17 +21,19 @@ */

/**
* @param {Volume} volume The associated volume
* @param {number} [index=0] The index of the slice
* @param {string} [axis='z'] For now only 'x', 'y' or 'z' but later it will change to a normal vector
* Constructs a new volume slice.
*
* @param {Volume} volume - The associated volume.
* @param {number} [index=0] - The index of the slice.
* @param {('x'|'y'|'z')} [axis='z'] - For now only 'x', 'y' or 'z' but later it will change to a normal vector.
*/
constructor( volume, index, axis ) {
constructor( volume, index = 0, axis = 'z' ) {
const slice = this;
/**
* @member {Volume} volume The associated volume
* The associated volume.
*
* @type {Volume}
*/
this.volume = volume;
/**
* @member {number} index The index of the slice, if changed, will automatically call updateGeometry at the next repaint
*/
index = index || 0;
Object.defineProperty( this, 'index', {

@@ -43,2 +45,11 @@ get: function () {

},
/**
* The index of the slice, if changed, will automatically call updateGeometry at the next repaint.
*
* @name VolumeSlice#index
* @type {number}
* @default 0
* @param {number} value
* @return {number}
*/
set: function ( value ) {

@@ -52,21 +63,38 @@

} );
/**
* @member {string} axis The normal axis
* The normal axis.
*
* @type {('x'|'y'|'z')}
*/
this.axis = axis || 'z';
this.axis = axis;
/**
* @member {HTMLCanvasElement} canvas The final canvas used for the texture
* The final canvas used for the texture.
*
* @type {HTMLCanvasElement}
*/
this.canvas = document.createElement( 'canvas' );
/**
* @member {CanvasRenderingContext2D} ctx Context of the canvas
* The rendering context of the canvas.
*
* @type {CanvasRenderingContext2D}
*/
this.canvas = document.createElement( 'canvas' );
this.ctx;
/**
* @member {HTMLCanvasElement} canvasBuffer The intermediary canvas used to paint the data
* The intermediary canvas used to paint the data.
*
* @type {HTMLCanvasElement}
*/
this.canvasBuffer = document.createElement( 'canvas' );
/**
* @member {CanvasRenderingContext2D} ctxBuffer Context of the canvas buffer
* The rendering context of the canvas buffer,
*
* @type {CanvasRenderingContext2D}
*/
this.canvasBuffer = document.createElement( 'canvas' );
this.ctxBuffer;
this.updateGeometry();

@@ -81,9 +109,16 @@

const material = new MeshBasicMaterial( { map: canvasMap, side: DoubleSide, transparent: true } );
/**
* @member {Mesh} mesh The mesh ready to get used in the scene
* The mesh ready to get used in the scene.
*
* @type {Mesh}
*/
this.mesh = new Mesh( this.geometry, material );
this.mesh.matrixAutoUpdate = false;
/**
* @member {boolean} geometryNeedsUpdate If set to true, updateGeometry will be triggered at the next repaint
* If set to `true`, `updateGeometry()` will be triggered at the next repaint.
*
* @type {boolean}
* @default true
*/

@@ -94,23 +129,29 @@ this.geometryNeedsUpdate = true;

/**
* @member {number} iLength Width of slice in the original coordinate system, corresponds to the width of the buffer canvas
* Width of slice in the original coordinate system, corresponds to the width of the buffer canvas.
*
* @type {number}
* @default 0
*/
this.iLength = 0;
/**
* @member {number} jLength Height of slice in the original coordinate system, corresponds to the height of the buffer canvas
* Height of slice in the original coordinate system, corresponds to the height of the buffer canvas.
*
* @type {number}
* @default 0
*/
this.jLength = 0;
/**
* @member {Function} sliceAccess Function that allow the slice to access right data
* Function that allow the slice to access right data.
*
* @type {?Function}
* @see {@link Volume#extractPerpendicularPlane}
* @param {number} i The first coordinate
* @param {number} j The second coordinate
* @returns {number} the index corresponding to the voxel in volume.data of the given position in the slice
*/
this.sliceAccess = null;
}
/**
* Refresh the texture and the geometry if geometryNeedsUpdate is set to true
* @memberof VolumeSlice
* Refresh the texture and the geometry if geometryNeedsUpdate is set to `true`.
*/

@@ -147,20 +188,23 @@ repaint() {

//this part is currently useless but will be used when colortables will be handled
for ( let j = 0; j < jLength; j ++ ) {
console.error( 'THREE.VolumeSlice.repaint: label are not supported yet' );
for ( let i = 0; i < iLength; i ++ ) {
// This part is currently useless but will be used when colortables will be handled
let label = volumeData[ sliceAccess( i, j ) ];
label = label >= this.colorMap.length ? ( label % this.colorMap.length ) + 1 : label;
const color = this.colorMap[ label ];
data[ 4 * pixelCount ] = ( color >> 24 ) & 0xff;
data[ 4 * pixelCount + 1 ] = ( color >> 16 ) & 0xff;
data[ 4 * pixelCount + 2 ] = ( color >> 8 ) & 0xff;
data[ 4 * pixelCount + 3 ] = color & 0xff;
pixelCount ++;
// for ( let j = 0; j < jLength; j ++ ) {
}
// for ( let i = 0; i < iLength; i ++ ) {
}
// let label = volumeData[ sliceAccess( i, j ) ];
// label = label >= this.colorMap.length ? ( label % this.colorMap.length ) + 1 : label;
// const color = this.colorMap[ label ];
// data[ 4 * pixelCount ] = ( color >> 24 ) & 0xff;
// data[ 4 * pixelCount + 1 ] = ( color >> 16 ) & 0xff;
// data[ 4 * pixelCount + 2 ] = ( color >> 8 ) & 0xff;
// data[ 4 * pixelCount + 3 ] = color & 0xff;
// pixelCount ++;
// }
// }
} else {

@@ -201,5 +245,4 @@

/**
* Refresh the geometry according to axis and index
* Refresh the geometry according to axis and index.
* @see {@link Volume#extractPerpendicularPlane}
* @memberof VolumeSlice
*/

@@ -206,0 +249,0 @@ updateGeometry() {

@@ -22,6 +22,7 @@ // Original src: https://github.com/zz85/threejs-path-flow

*
* @param { number } numberOfCurves the number of curves needed to be described by this texture.
* @returns { DataTexture }
* @private
* @param {number} numberOfCurves - The number of curves needed to be described by this texture.
* @returns {DataTexture}
*/
export function initSplineTexture( numberOfCurves = 1 ) {
function initSplineTexture( numberOfCurves = 1 ) {

@@ -48,9 +49,10 @@ const dataArray = new Uint16Array( TEXTURE_WIDTH * TEXTURE_HEIGHT * numberOfCurves * CHANNELS );

/**
* Write the curve description to the data texture
* Write the curve description to the data texture.
*
* @param { DataTexture } texture The DataTexture to write to
* @param { Curve } splineCurve The curve to describe
* @param { number } offset Which curve slot to write to
* @private
* @param {DataTexture} texture - The data texture to write to.
* @param {Curve} splineCurve - The curve to describe.
* @param {number} offset - Which curve slot to write to.
*/
export function updateSplineTexture( texture, splineCurve, offset = 0 ) {
function updateSplineTexture( texture, splineCurve, offset = 0 ) {

@@ -83,3 +85,2 @@ const numberOfPoints = Math.floor( TEXTURE_WIDTH * ( TEXTURE_HEIGHT / 4 ) );

function setTextureValue( texture, index, x, y, z, o ) {

@@ -98,8 +99,8 @@

/**
* Create a new set of uniforms for describing the curve modifier
* Create a new set of uniforms for describing the curve modifier.
*
* @param { DataTexture } splineTexture which holds the curve description
* @returns { Object } The uniforms object to be used in the shader
* @param {DataTexture} splineTexture - Which holds the curve description.
* @returns {Object} The uniforms object to be used in the shader.
*/
export function getUniforms( splineTexture ) {
function getUniforms( splineTexture ) {

@@ -118,3 +119,3 @@ const uniforms = {

export function modifyShader( material, uniforms, numberOfCurves = 1 ) {
function modifyShader( material, uniforms, numberOfCurves = 1 ) {

@@ -206,3 +207,6 @@ if ( material.__ok ) return;

/**
* A helper class for making meshes bend around curves
* A modifier for making meshes bend around curves.
*
* This module can only be used with {@link WebGLRenderer}. When using {@link WebGPURenderer},
* import the class from `CurveModifierGPU.js`.
*/

@@ -212,4 +216,6 @@ export class Flow {

/**
* @param {Mesh} mesh The mesh to clone and modify to bend around the curve
* @param {number} numberOfCurves The amount of space that should preallocated for additional curves
* Constructs a new Flow instance.
*
* @param {Mesh} mesh - The mesh to clone and modify to bend around the curve.
* @param {number} numberOfCurves - The amount of space that should preallocated for additional curves.
*/

@@ -262,5 +268,11 @@ constructor( mesh, numberOfCurves = 1 ) {

/**
* Updates the curve for the given curve index.
*
* @param {number} index - The curve index.
* @param {Curve} curve - The curve that should be used to bend the mesh.
*/
updateCurve( index, curve ) {
if ( index >= this.curveArray.length ) throw Error( 'Index out of range for Flow' );
if ( index >= this.curveArray.length ) throw Error( 'Flow: Index out of range.' );
const curveLength = curve.getLength();

@@ -274,2 +286,7 @@ this.uniforms.spineLength.value = curveLength;

/**
* Moves the mesh along the curve.
*
* @param {number} amount - The offset.
*/
moveAlongCurve( amount ) {

@@ -282,6 +299,11 @@

}
const matrix = new Matrix4();
const _matrix = new Matrix4();
/**
* A helper class for creating instanced versions of flow, where the instances are placed on the curve.
* An instanced version of {@link Flow} for making meshes bend around curves, where the instances are placed on the curve.
*
* This module can only be used with {@link WebGLRenderer}.
*
* @augments Flow
*/

@@ -291,7 +313,8 @@ export class InstancedFlow extends Flow {

/**
* Constructs a new InstancedFlow instance.
*
* @param {number} count The number of instanced elements
* @param {number} curveCount The number of curves to preallocate for
* @param {Geometry} geometry The geometry to use for the instanced mesh
* @param {Material} material The material to use for the instanced mesh
* @param {number} count - The number of instanced elements.
* @param {number} curveCount - The number of curves to preallocate for.
* @param {Geometry} geometry - The geometry to use for the instanced mesh.
* @param {Material} material - The material to use for the instanced mesh.
*/

@@ -318,7 +341,7 @@ constructor( count, curveCount, geometry, material ) {

*
* @param {number} index of the instanced element to update
* @param {number} index - The index of tge instanced element to update.
*/
writeChanges( index ) {
matrix.makeTranslation(
_matrix.makeTranslation(
this.curveLengthArray[ this.whichCurve[ index ] ],

@@ -328,3 +351,3 @@ this.whichCurve[ index ],

);
this.object3D.setMatrixAt( index, matrix );
this.object3D.setMatrixAt( index, _matrix );
this.object3D.instanceMatrix.needsUpdate = true;

@@ -335,6 +358,6 @@

/**
* Move an individual element along the curve by a specific amount
* Move an individual element along the curve by a specific amount.
*
* @param {number} index Which element to update
* @param {number} offset Move by how much
* @param {number} index - Which element to update.
* @param {number} offset - The offset.
*/

@@ -349,10 +372,10 @@ moveIndividualAlongCurve( index, offset ) {

/**
* Select which curve to use for an element
* Select which curve to use for an element.
*
* @param {number} index the index of the instanced element to update
* @param {number} curveNo the index of the curve it should use
* @param {number} index - The index of the instanced element to update.
* @param {number} curveNo - The index of the curve it should use.
*/
setCurve( index, curveNo ) {
if ( isNaN( curveNo ) ) throw Error( 'curve index being set is Not a Number (NaN)' );
if ( isNaN( curveNo ) ) throw Error( 'InstancedFlow: Curve index being set is Not a Number (NaN).' );
this.whichCurve[ index ] = curveNo;

@@ -359,0 +382,0 @@ this.writeChanges( index );

@@ -22,6 +22,7 @@ // Original src: https://github.com/zz85/threejs-path-flow

*
* @param { number } [numberOfCurves=1] the number of curves needed to be described by this texture.
* @returns { DataTexture } The new DataTexture
* @private
* @param {number} [numberOfCurves=1] - The number of curves needed to be described by this texture.
* @returns {DataTexture} The new data texture.
*/
export function initSplineTexture( numberOfCurves = 1 ) {
function initSplineTexture( numberOfCurves = 1 ) {

@@ -48,9 +49,10 @@ const dataArray = new Uint16Array( TEXTURE_WIDTH * TEXTURE_HEIGHT * numberOfCurves * CHANNELS );

/**
* Write the curve description to the data texture
* Write the curve description to the data texture.
*
* @param { DataTexture } texture The DataTexture to write to
* @param { Curve } splineCurve The curve to describe
* @param { number } offset Which curve slot to write to
* @private
* @param {DataTexture} texture - The data texture to write to.
* @param {Curve} splineCurve - The curve to describe.
* @param {number} [offset=0] - Which curve slot to write to.
*/
export function updateSplineTexture( texture, splineCurve, offset = 0 ) {
function updateSplineTexture( texture, splineCurve, offset = 0 ) {

@@ -98,8 +100,9 @@ const numberOfPoints = Math.floor( TEXTURE_WIDTH * ( TEXTURE_HEIGHT / 4 ) );

/**
* Create a new set of uniforms for describing the curve modifier
* Create a new set of uniforms for describing the curve modifier.
*
* @param { DataTexture } splineTexture which holds the curve description
* @returns { Object } The uniforms object
* @private
* @param {DataTexture} splineTexture - Which holds the curve description.
* @returns {Object} The uniforms object.
*/
export function getUniforms( splineTexture ) {
function getUniforms( splineTexture ) {

@@ -117,3 +120,3 @@ return {

export function modifyShader( material, uniforms, numberOfCurves ) {
function modifyShader( material, uniforms, numberOfCurves ) {

@@ -164,3 +167,6 @@ const spineTexture = uniforms.spineTexture;

/**
* A helper class for making meshes bend around curves
* A modifier for making meshes bend around curves.
*
* This module can only be used with {@link WebGPURenderer}. When using {@link WebGLRenderer},
* import the class from `CurveModifier.js`.
*/

@@ -170,4 +176,6 @@ export class Flow {

/**
* @param {Mesh} mesh The mesh to clone and modify to bend around the curve
* @param {number} numberOfCurves The amount of space that should preallocated for additional curves
* Constructs a new Flow instance.
*
* @param {Mesh} mesh - The mesh to clone and modify to bend around the curve.
* @param {number} numberOfCurves - The amount of space that should preallocated for additional curves.
*/

@@ -221,5 +229,11 @@ constructor( mesh, numberOfCurves = 1 ) {

/**
* Updates the curve for the given curve index.
*
* @param {number} index - The curve index.
* @param {Curve} curve - The curve that should be used to bend the mesh.
*/
updateCurve( index, curve ) {
if ( index >= this.curveArray.length ) throw Error( 'Index out of range for Flow' );
if ( index >= this.curveArray.length ) throw Error( 'Flow: Index out of range.' );

@@ -236,2 +250,7 @@ const curveLength = curve.getLength();

/**
* Moves the mesh along the curve.
*
* @param {number} amount - The offset.
*/
moveAlongCurve( amount ) {

@@ -238,0 +257,0 @@

@@ -12,4 +12,22 @@ import {

/**
* The modifier can be used to split faces at sharp edges. This allows to compute
* normals without smoothing the edges which can lead to an improved visual result.
*
* ```js
* const modifier = new EdgeSplitModifier();
* geometry = modifier.modify( geometry, Math.PI * 0.4 );
* ```
*/
class EdgeSplitModifier {
/**
* Returns a new, modified version of the given geometry by applying an edge-split operation.
* Please note that the resulting geometry is always indexed.
*
* @param {BufferGeometry} geometry - The geometry to modify.
* @param {number} cutOffAngle - The cut off angle in radians.
* @param {boolean} [tryKeepNormals=true] - Whether to try to keep normals or not.
* @return {BufferGeometry} A new, modified geometry.
*/
modify( geometry, cutOffAngle, tryKeepNormals = true ) {

@@ -16,0 +34,0 @@

@@ -11,14 +11,26 @@ import {

const _cb = new Vector3(), _ab = new Vector3();
/**
* Simplification Geometry Modifier
* - based on code and technique
* - by Stan Melax in 1998
* - Progressive Mesh type Polygon Reduction Algorithm
* - http://www.melax.com/polychop/
* This class can be used to modify a geometry by simplifying it. A typical use
* case for such a modifier is automatic LOD generation.
*
* The implementation is based on [Progressive Mesh type Polygon Reduction Algorithm]{@link https://web.archive.org/web/20230610044040/http://www.melax.com/polychop/}
* by Stan Melax in 1998.
*
* ```js
* const modifier = new SimplifyModifier();
* geometry = modifier.modify( geometry );
* ```
*/
const _cb = new Vector3(), _ab = new Vector3();
class SimplifyModifier {
/**
* Returns a new, modified version of the given geometry by applying a simplification.
* Please note that the resulting geometry is always non-indexed.
*
* @param {BufferGeometry} geometry - The geometry to modify.
* @param {number} count - The number of vertices to remove.
* @return {BufferGeometry} A new, modified geometry.
*/
modify( geometry, count ) {

@@ -25,0 +37,0 @@

@@ -10,10 +10,34 @@ import {

/**
* Break faces with edges longer than maxEdgeLength
* This class can be used to modify a geometry by breaking its edges if they
* are longer than maximum length.
*
* ```js
* const modifier = new TessellateModifier( 8, 6 );
* geometry = modifier.modify( geometry );
* ```
*/
class TessellateModifier {
/**
* Constructs a new Tessellate modifier.
*
* @param {number} [maxEdgeLength=0.1] - The maximum edge length.
* @param {number} [maxIterations=6] - The number of iterations.
*/
constructor( maxEdgeLength = 0.1, maxIterations = 6 ) {
/**
* The maximum edge length.
*
* @type {number}
* @default 0.1
*/
this.maxEdgeLength = maxEdgeLength;
/**
* The maximum edge length.
*
* @type {number}
* @default 0.1
*/
this.maxIterations = maxIterations;

@@ -23,2 +47,9 @@

/**
* Returns a new, modified version of the given geometry by applying a tesselation.
* Please note that the resulting geometry is always non-indexed.
*
* @param {BufferGeometry} geometry - The geometry to modify.
* @return {BufferGeometry} A new, modified geometry.
*/
modify( geometry ) {

@@ -25,0 +56,0 @@

import { Mesh, MeshBasicMaterial, SphereGeometry, Vector3 } from 'three';
/**
* A ground-projected skybox. The height is how far the camera that took the photo was above the ground -
* a larger value will magnify the downward part of the image. By default the object is centered at the camera,
* so it is often helpful to set skybox.position.y = height to put the ground at the origin. Set the radius
* large enough to ensure your user's camera stays inside.
* A ground-projected skybox.
*
* By default the object is centered at the camera, so it is often helpful to set
* `skybox.position.y = height` to put the ground at the origin.
*
* ```js
* const height = 15, radius = 100;
*
* const skybox = new GroundedSkybox( envMap, height, radius );
* skybox.position.y = height;
* scene.add( skybox );
* ```
*
* @augments Mesh
*/
class GroundedSkybox extends Mesh {
/**
* Constructs a new ground-projected skybox.
*
* @param {Texture} map - The environment map to use.
* @param {number} height - The height is how far the camera that took the photo was above the ground.
* A larger value will magnify the downward part of the image.
* @param {number} radius - The radius of the skybox. Must be large enough to ensure the scene's camera stays inside.
* @param {number} [resolution=128] - The geometry resolution of the skybox.
*/
constructor( map, height, radius, resolution = 128 ) {

@@ -13,0 +31,0 @@

@@ -18,4 +18,26 @@ import {

/**
* Creates a simulated lens flare that tracks a light.
*
* Note that this class can only be used with {@link WebGLRenderer}.
* When using {@link WebGPURenderer}, use {@link LensflareMesh}.
*
* ```js
* const light = new THREE.PointLight( 0xffffff, 1.5, 2000 );
*
* const lensflare = new Lensflare();
* lensflare.addElement( new LensflareElement( textureFlare0, 512, 0 ) );
* lensflare.addElement( new LensflareElement( textureFlare1, 512, 0 ) );
* lensflare.addElement( new LensflareElement( textureFlare2, 60, 0.6 ) );
*
* light.add( lensflare );
* ```
*
* @augments Mesh
*/
class Lensflare extends Mesh {
/**
* Constructs a new lensflare.
*/
constructor() {

@@ -25,6 +47,27 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isLensflare = true;
this.type = 'Lensflare';
/**
* Overwritten to disable view-frustum culling by default.
*
* @type {boolean}
* @default false
*/
this.frustumCulled = false;
/**
* Overwritten to make sure lensflares a rendered last.
*
* @type {number}
* @default Infinity
*/
this.renderOrder = Infinity;

@@ -154,2 +197,7 @@

/**
* Adds the given lensflare element to this instance.
*
* @param {LensflareElement} element - The element to add.
*/
this.addElement = function ( element ) {

@@ -269,2 +317,6 @@

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*/
this.dispose = function () {

@@ -291,11 +343,48 @@

//
/**
* Represents a single flare that can be added to a {@link Lensflare} container.
*/
class LensflareElement {
/**
* Constructs a new lensflare element.
*
* @param {Texture} texture - The flare's texture.
* @param {number} [size=1] - The size in pixels.
* @param {number} [distance=0] - The normalized distance (`[0,1]`) from the light source.
* A value of `0` means the flare is located at light source.
* @param {Color} [color] - The flare's color
*/
constructor( texture, size = 1, distance = 0, color = new Color( 0xffffff ) ) {
/**
* The flare's texture.
*
* @type {Texture}
*/
this.texture = texture;
/**
* The size in pixels.
*
* @type {number}
* @default 1
*/
this.size = size;
/**
* The normalized distance (`[0,1]`) from the light source.
* A value of `0` means the flare is located at light source.
*
* @type {number}
* @default 0
*/
this.distance = distance;
/**
* The flare's color
*
* @type {Color}
* @default (1,1,1)
*/
this.color = color;

@@ -302,0 +391,0 @@

@@ -21,4 +21,26 @@ import {

/**
* Creates a simulated lens flare that tracks a light.
*
* Note that this class can only be used with {@link WebGPURenderer}.
* When using {@link WebGLRenderer}, use {@link Lensflare}.
*
* ```js
* const light = new THREE.PointLight( 0xffffff, 1.5, 2000 );
*
* const lensflare = new LensflareMesh();
* lensflare.addElement( new LensflareElement( textureFlare0, 512, 0 ) );
* lensflare.addElement( new LensflareElement( textureFlare1, 512, 0 ) );
* lensflare.addElement( new LensflareElement( textureFlare2, 60, 0.6 ) );
*
* light.add( lensflare );
* ```
*
* @augments Mesh
*/
class LensflareMesh extends Mesh {
/**
* Constructs a new lensflare mesh.
*/
constructor() {

@@ -28,6 +50,27 @@

this.isLensflare = true;
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isLensflareMesh = true;
this.type = 'LensflareMesh';
/**
* Overwritten to disable view-frustum culling by default.
*
* @type {boolean}
* @default false
*/
this.frustumCulled = false;
/**
* Overwritten to make sure lensflares a rendered last.
*
* @type {number}
* @default Infinity
*/
this.renderOrder = Infinity;

@@ -151,3 +194,7 @@

/**
* Adds the given lensflare element to this instance.
*
* @param {LensflareElement} element - The element to add.
*/
this.addElement = function ( element ) {

@@ -270,2 +317,6 @@

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*/
this.dispose = function () {

@@ -272,0 +323,0 @@

@@ -12,7 +12,17 @@ import {

/**
* Port of http://webglsamples.org/blob/blob.html
* A marching cubes implementation.
*
* Port of: {@link http://webglsamples.org/blob/blob.html}
*/
class MarchingCubes extends Mesh {
/**
* Constructs a new marching cubes instance.
*
* @param {number} resolution - The effect's resolution.
* @param {Material} material - The cube's material.
* @param {boolean} [enableUvs=false] - Whether texture coordinates should be animated or not.
* @param {boolean} [enableColors=false] - Whether colors should be animated or not.
* @param {number} [maxPolyCount=10000] - The maximum size of the geometry buffers.
*/
constructor( resolution, material, enableUvs = false, enableColors = false, maxPolyCount = 10000 ) {

@@ -24,2 +34,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isMarchingCubes = true;

@@ -35,3 +52,16 @@

/**
* Whether texture coordinates should be animated or not.
*
* @type {boolean}
* @default false
*/
this.enableUvs = enableUvs;
/**
* Whether colors should be animated or not.
*
* @type {boolean}
* @default false
*/
this.enableColors = enableColors;

@@ -501,5 +531,13 @@

// Adds a reciprocal ball (nice and blobby) that, to be fast, fades to zero after
// a fixed distance, determined by strength and subtract.
/**
* Adds a reciprocal ball (nice and blobby) that, to be fast, fades to zero after
* a fixed distance, determined by strength and subtract.
*
* @param {number} ballx - The x-coordinate of the ball.
* @param {number} bally - The y-coordinate of the ball.
* @param {number} ballz - The z-coordinate of the ball.
* @param {number} strength - The strength factor.
* @param {number} subtract - The subtract factor.
* @param {Color} colors - The color.
*/
this.addBall = function ( ballx, bally, ballz, strength, subtract, colors ) {

@@ -605,2 +643,8 @@

/**
* Adds a plane along the x-axis.
*
* @param {number} strength - The strength factor.
* @param {number} subtract - The subtract factor.
*/
this.addPlaneX = function ( strength, subtract ) {

@@ -651,2 +695,8 @@

/**
* Adds a plane along the y-axis.
*
* @param {number} strength - The strength factor.
* @param {number} subtract - The subtract factor.
*/
this.addPlaneY = function ( strength, subtract ) {

@@ -696,2 +746,8 @@

/**
* Adds a plane along the z-axis.
*
* @param {number} strength - The strength factor.
* @param {number} subtract - The subtract factor.
*/
this.addPlaneZ = function ( strength, subtract ) {

@@ -745,2 +801,10 @@

/**
* Sets the cell value for the given coordinates.
*
* @param {number} x - The x value.
* @param {number} y - The y value.
* @param {number} z - The z value.
* @param {number} value - The value to set.
*/
this.setCell = function ( x, y, z, value ) {

@@ -753,2 +817,10 @@

/**
* Returns the cell value for the given coordinates.
*
* @param {number} x - The x value.
* @param {number} y - The y value.
* @param {number} z - The z value.
* @return {number} The value.
*/
this.getCell = function ( x, y, z ) {

@@ -761,2 +833,7 @@

/**
* Applies a blur with the given intensity.
*
* @param {number} [intensity=1] - The intensity of the blur.
*/
this.blur = function ( intensity = 1 ) {

@@ -815,2 +892,5 @@

/**
* Resets the effect.
*/
this.reset = function () {

@@ -832,2 +912,5 @@

/**
* Updates the effect.
*/
this.update = function () {

@@ -834,0 +917,0 @@

@@ -15,4 +15,31 @@ import {

/**
* Can be used to create a flat, reflective surface like a mirror.
*
* Note that this class can only be used with {@link WebGLRenderer}.
* When using {@link WebGPURenderer}, use {@link ReflectorNode}.
*
* ```js
* const geometry = new THREE.PlaneGeometry( 100, 100 );
*
* const reflector = new Reflector( geometry, {
* clipBias: 0.003,
* textureWidth: window.innerWidth * window.devicePixelRatio,
* textureHeight: window.innerHeight * window.devicePixelRatio,
* color: 0xc1cbcb
* } );
*
* scene.add( reflector );
* ```
*
* @augments Mesh
*/
class Reflector extends Mesh {
/**
* Constructs a new reflector.
*
* @param {BufferGeometry} geometry - The reflector's geometry.
* @param {Reflector~Options} [options] - The configuration options.
*/
constructor( geometry, options = {} ) {

@@ -22,6 +49,28 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isReflector = true;
this.type = 'Reflector';
/**
* Whether to force an update, no matter if the reflector
* is in view or not.
*
* @type {boolean}
* @default false
*/
this.forceUpdate = false;
/**
* The reflector's virtual camera. This is used to render
* the scene from the mirror's point of view.
*
* @type {PerspectiveCamera}
*/
this.camera = new PerspectiveCamera();

@@ -183,2 +232,7 @@

/**
* Returns the reflector's internal render target.
*
* @return {WebGLRenderTarget} The internal render target
*/
this.getRenderTarget = function () {

@@ -190,2 +244,6 @@

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*/
this.dispose = function () {

@@ -271,2 +329,14 @@

/**
* Constructor options of `Reflector`.
*
* @typedef {Object} Reflector~Options
* @property {number|Color|string} [color=0x7F7F7F] - The reflector's color.
* @property {number} [textureWidth=512] - The texture width. A higher value results in more clear reflections but is also more expensive.
* @property {number} [textureHeight=512] - The texture height. A higher value results in more clear reflections but is also more expensive.
* @property {number} [clipBias=0] - The clip bias.
* @property {Object} [shader] - Can be used to pass in a custom shader that defines how the reflective view is projected onto the reflector's geometry.
* @property {number} [multisample=4] - How many samples to use for MSAA. `0` disables MSAA.
**/
export { Reflector };

@@ -18,4 +18,15 @@ import {

/**
* A special version of {@link Reflector} for usage with {@link SSRPass}.
*
* @augments Mesh
*/
class ReflectorForSSRPass extends Mesh {
/**
* Constructs a new reflector.
*
* @param {BufferGeometry} geometry - The reflector's geometry.
* @param {ReflectorForSSRPass~Options} [options] - The configuration options.
*/
constructor( geometry, options = {} ) {

@@ -244,2 +255,7 @@

/**
* Returns the reflector's internal render target.
*
* @return {WebGLRenderTarget} The internal render target
*/
this.getRenderTarget = function () {

@@ -251,2 +267,13 @@

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*/
this.dispose = function () {
renderTarget.dispose();
scope.material.dispose();
};
}

@@ -355,2 +382,14 @@

/**
* Constructor options of `ReflectorForSSRPass`.
*
* @typedef {Object} ReflectorForSSRPass~Options
* @property {number|Color|string} [color=0x7F7F7F] - The reflector's color.
* @property {number} [textureWidth=512] - The texture width. A higher value results in more clear reflections but is also more expensive.
* @property {number} [textureHeight=512] - The texture height. A higher value results in more clear reflections but is also more expensive.
* @property {number} [clipBias=0] - The clip bias.
* @property {Object} [shader] - Can be used to pass in a custom shader that defines how the reflective view is projected onto the reflector's geometry.
* @property {boolean} [useDepthTexture=true] - Whether to store depth values in a texture or not.
**/
export { ReflectorForSSRPass };

@@ -16,4 +16,31 @@ import {

/**
* Can be used to create a flat, refractive surface like for special
* windows or water effects.
*
* Note that this class can only be used with {@link WebGLRenderer}.
* When using {@link WebGPURenderer}, use {@link viewportSharedTexture}.
*
* ```js
* const geometry = new THREE.PlaneGeometry( 100, 100 );
*
* const refractor = new Refractor( refractorGeometry, {
* color: 0xcbcbcb,
* textureWidth: 1024,
* textureHeight: 1024
* } );
*
* scene.add( refractor );
* ```
*
* @augments Mesh
*/
class Refractor extends Mesh {
/**
* Constructs a new refractor.
*
* @param {BufferGeometry} geometry - The refractor's geometry.
* @param {Refractor~Options} [options] - The configuration options.
*/
constructor( geometry, options = {} ) {

@@ -23,5 +50,18 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isRefractor = true;
this.type = 'Refractor';
/**
* The reflector's virtual camera.
*
* @type {PerspectiveCamera}
*/
this.camera = new PerspectiveCamera();

@@ -248,2 +288,7 @@

/**
* Returns the reflector's internal render target.
*
* @return {WebGLRenderTarget} The internal render target
*/
this.getRenderTarget = function () {

@@ -255,2 +300,6 @@

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*/
this.dispose = function () {

@@ -331,2 +380,14 @@

/**
* Constructor options of `Refractor`.
*
* @typedef {Object} Refractor~Options
* @property {number|Color|string} [color=0x7F7F7F] - The refractor's color.
* @property {number} [textureWidth=512] - The texture width. A higher value results in more clear refractions but is also more expensive.
* @property {number} [textureHeight=512] - The texture height. A higher value results in more clear refractions but is also more expensive.
* @property {number} [clipBias=0] - The clip bias.
* @property {Object} [shader] - Can be used to pass in a custom shader that defines how the refractive view is projected onto the reflector's geometry.
* @property {number} [multisample=4] - How many samples to use for MSAA. `0` disables MSAA.
**/
export { Refractor };

@@ -9,10 +9,27 @@ import {

const _shadowMatrix = new Matrix4();
/**
* A shadow Mesh that follows a shadow-casting Mesh in the scene, but is confined to a single plane.
* A Shadow Mesh that follows a shadow-casting mesh in the scene,
* but is confined to a single plane. This technique can be used as
* a very performant alternative to classic shadow mapping. However,
* it has serious limitations like:
*
* - Shadows can only be casted on flat planes.
* - No soft shadows support.
*
* ```js
* const cubeShadow = new ShadowMesh( cube );
* scene.add( cubeShadow );
* ```
*
* @augments Mesh
*/
const _shadowMatrix = new Matrix4();
class ShadowMesh extends Mesh {
/**
* Constructs a new shadow mesh.
*
* @param {Mesh} mesh - The shadow-casting reference mesh.
*/
constructor( mesh ) {

@@ -35,7 +52,33 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isShadowMesh = true;
/**
* Represent the world matrix of the reference mesh.
*
* @type {Matrix4}
*/
this.meshMatrix = mesh.matrixWorld;
/**
* Overwritten to disable view-frustum culling by default.
*
* @type {boolean}
* @default false
*/
this.frustumCulled = false;
/**
* Overwritten to disable automatic matrix update. The local
* matrix is computed manually in {@link ShadowMesh#update}.
*
* @type {boolean}
* @default false
*/
this.matrixAutoUpdate = false;

@@ -45,2 +88,8 @@

/**
* Updates the shadow mesh so it follows its shadow-casting reference mesh.
*
* @param {Plane} plane - The plane onto the shadow mesh is projected.
* @param {Vector4} lightPosition4D - The light position.
*/
update( plane, lightPosition4D ) {

@@ -47,0 +96,0 @@

@@ -11,17 +11,27 @@ import {

/**
* Based on "A Practical Analytic Model for Daylight"
* aka The Preetham Model, the de facto standard analytic skydome model
* https://www.researchgate.net/publication/220720443_A_Practical_Analytic_Model_for_Daylight
* Represents a skydome for scene backgrounds. Based on [A Practical Analytic Model for Daylight]{@link https://www.researchgate.net/publication/220720443_A_Practical_Analytic_Model_for_Daylight}
* aka The Preetham Model, the de facto standard for analytical skydomes.
*
* First implemented by Simon Wallner
* http://simonwallner.at/project/atmospheric-scattering/
* Note that this class can only be used with {@link WebGLRenderer}.
* When using {@link WebGPURenderer}, use {@link SkyMesh}.
*
* Improved by Martin Upitis
* http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR
* More references:
*
* Three.js integration by zz85 http://twitter.com/blurspline
* - {@link http://simonwallner.at/project/atmospheric-scattering/}
* - {@link http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR}
*
*
* ```js
* const sky = new Sky();
* sky.scale.setScalar( 10000 );
* scene.add( sky );
* ```
*
* @augments Mesh
*/
class Sky extends Mesh {
/**
* Constructs a new skydome.
*/
constructor() {

@@ -42,2 +52,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isSky = true;

@@ -44,0 +61,0 @@

@@ -12,17 +12,26 @@ import {

/**
* Based on "A Practical Analytic Model for Daylight"
* aka The Preetham Model, the de facto standard analytic skydome model
* https://www.researchgate.net/publication/220720443_A_Practical_Analytic_Model_for_Daylight
* Represents a skydome for scene backgrounds. Based on [A Practical Analytic Model for Daylight]{@link https://www.researchgate.net/publication/220720443_A_Practical_Analytic_Model_for_Daylight}
* aka The Preetham Model, the de facto standard for analytical skydomes.
*
* First implemented by Simon Wallner
* http://simonwallner.at/project/atmospheric-scattering/
* Note that this class can only be used with {@link WebGLRenderer}.
* When using {@link WebGPURenderer}, use {@link SkyMesh}.
*
* Improved by Martin Upitis
* http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR
* More references:
*
* Three.js integration by zz85 http://twitter.com/blurspline
* - {@link http://simonwallner.at/project/atmospheric-scattering/}
* - {@link http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR}
*
* ```js
* const sky = new SkyMesh();
* sky.scale.setScalar( 10000 );
* scene.add( sky );
* ```
*
* @augments Mesh
*/
class SkyMesh extends Mesh {
/**
* Constructs a new skydome.
*/
constructor() {

@@ -34,9 +43,51 @@

/**
* The turbidity uniform.
*
* @type {UniformNode<float>}
*/
this.turbidity = uniform( 2 );
/**
* The rayleigh uniform.
*
* @type {UniformNode<float>}
*/
this.rayleigh = uniform( 1 );
/**
* The mieCoefficient uniform.
*
* @type {UniformNode<float>}
*/
this.mieCoefficient = uniform( 0.005 );
/**
* The mieDirectionalG uniform.
*
* @type {UniformNode<float>}
*/
this.mieDirectionalG = uniform( 0.8 );
/**
* The sun position uniform.
*
* @type {UniformNode<vec3>}
*/
this.sunPosition = uniform( new Vector3() );
/**
* The up position.
*
* @type {UniformNode<vec3>}
*/
this.upUniform = uniform( new Vector3( 0, 1, 0 ) );
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isSky = true;

@@ -43,0 +94,0 @@

@@ -17,10 +17,23 @@ import {

/**
* Work based on :
* https://github.com/Slayvin: Flat mirror for three.js
* https://home.adelphi.edu/~stemkoski/ : An implementation of water shader based on the flat mirror
* http://29a.ch/ && http://29a.ch/slides/2012/webglwater/ : Water shader explanations in WebGL
* A basic flat, reflective water effect.
*
* Note that this class can only be used with {@link WebGLRenderer}.
* When using {@link WebGPURenderer}, use {@link WaterMesh}.
*
* References:
*
* - [Flat mirror for three.js]{@link https://github.com/Slayvin}
* - [An implementation of water shader based on the flat mirror]{@link https://home.adelphi.edu/~stemkoski/}
* - [Water shader explanations in WebGL]{@link http://29a.ch/slides/2012/webglwater/ }
*
* @augments Mesh
*/
class Water extends Mesh {
/**
* Constructs a new water instance.
*
* @param {BufferGeometry} geometry - The water's geometry.
* @param {Water~Options} [options] - The configuration options.
*/
constructor( geometry, options = {} ) {

@@ -30,2 +43,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isWater = true;

@@ -335,2 +355,21 @@

/**
* Constructor options of `Water`.
*
* @typedef {Object} Water~Options
* @property {number} [textureWidth=512] - The texture width. A higher value results in more clear reflections but is also more expensive.
* @property {number} [textureHeight=512] - The texture height. A higher value results in more clear reflections but is also more expensive.
* @property {number} [clipBias=0] - The clip bias.
* @property {number} [alpha=1] - The alpha value.
* @property {number} [time=0] - The time value.
* @property {?Texture} [waterNormals=null] - The water's normal map.
* @property {Vector3} [sunDirection=(0.70707,0.70707,0.0)] - The sun direction.
* @property {number|Color|string} [sunColor=0xffffff] - The sun color.
* @property {number|Color|string} [waterColor=0x7F7F7F] - The water color.
* @property {Vector3} [eye] - The eye vector.
* @property {number} [distortionScale=20] - The distortion scale.
* @property {(FrontSide|BackSide|DoubleSide)} [side=FrontSide] - The water material's `side` property.
* @property {boolean} [fog=false] - Whether the water should be affected by fog or not.
**/
export { Water };

@@ -17,11 +17,25 @@ import {

/** @module Water2 */
/**
* An advanced water effect that supports reflections, refractions and flow maps.
*
* Note that this class can only be used with {@link WebGLRenderer}.
* When using {@link WebGPURenderer}, use {@link module:Water2Mesh}.
*
* References:
* https://alex.vlachos.com/graphics/Vlachos-SIGGRAPH10-WaterFlow.pdf
* http://graphicsrunner.blogspot.de/2010/08/water-using-flow-maps.html
*
* - {@link https://alex.vlachos.com/graphics/Vlachos-SIGGRAPH10-WaterFlow.pdf}
* - {@link http://graphicsrunner.blogspot.de/2010/08/water-using-flow-maps.html}
*
* @augments Mesh
*/
class Water extends Mesh {
/**
* Constructs a new water instance.
*
* @param {BufferGeometry} geometry - The water's geometry.
* @param {module:Water2~Options} [options] - The configuration options.
*/
constructor( geometry, options = {} ) {

@@ -31,2 +45,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isWater = true;

@@ -363,2 +384,20 @@

/**
* Constructor options of `Water`.
*
* @typedef {Object} module:Water2~Options
* @property {number|Color|string} [color=0xFFFFFF] - The water color.
* @property {number} [textureWidth=512] - The texture width. A higher value results in better quality but is also more expensive.
* @property {number} [textureHeight=512] - The texture height. A higher value results in better quality but is also more expensive.
* @property {number} [clipBias=0] - The clip bias.
* @property {Vector2} [flowDirection=(1,0)] - The water's flow direction.
* @property {number} [flowSpeed=0.03] - The water's flow speed.
* @property {number} [reflectivity=0.02] - The water's reflectivity.
* @property {number} [scale=1] - The water's scale.
* @property {Object} [shader] - A custom water shader.
* @property {?Texture} [flowMap=null] - The flow map. If no flow map is assigned, the water flow is defined by `flowDirection`.
* @property {?Texture} [normalMap0] - The first water normal map.
* @property {?Texture} [normalMap1] - The second water normal map.
**/
export { Water };

@@ -13,11 +13,25 @@ import {

/** @module Water2Mesh */
/**
* An advanced water effect that supports reflections, refractions and flow maps.
*
* Note that this class can only be used with {@link WebGPURenderer}.
* When using {@link WebGLRenderer}, use {@link module:Water2}.
*
* References:
* https://alex.vlachos.com/graphics/Vlachos-SIGGRAPH10-WaterFlow.pdf
* http://graphicsrunner.blogspot.de/2010/08/water-using-flow-maps.html
*
* - {@link https://alex.vlachos.com/graphics/Vlachos-SIGGRAPH10-WaterFlow.pdf}
* - {@link http://graphicsrunner.blogspot.de/2010/08/water-using-flow-maps.html}
*
* @augments Mesh
*/
class WaterMesh extends Mesh {
/**
* Constructs a new water mesh.
*
* @param {BufferGeometry} geometry - The water's geometry.
* @param {module:Water2~Options} [options] - The configuration options.
*/
constructor( geometry, options = {} ) {

@@ -29,2 +43,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isWater = true;

@@ -164,2 +185,16 @@

/**
* Constructor options of `WaterMesh`.
*
* @typedef {Object} module:Water2Mesh~Options
* @property {number|Color|string} [color=0xFFFFFF] - The water color.
* @property {Vector2} [flowDirection=(1,0)] - The water's flow direction.
* @property {number} [flowSpeed=0.03] - The water's flow speed.
* @property {number} [reflectivity=0.02] - The water's reflectivity.
* @property {number} [scale=1] - The water's scale.
* @property {?Texture} [flowMap=null] - The flow map. If no flow map is assigned, the water flow is defined by `flowDirection`.
* @property {Texture} normalMap0 - The first water normal map.
* @property {Texture} normalMap1 - The second water normal map.
**/
export { WaterMesh };

@@ -11,10 +11,23 @@ import {

/**
* Work based on :
* https://github.com/Slayvin: Flat mirror for three.js
* https://home.adelphi.edu/~stemkoski/ : An implementation of water shader based on the flat mirror
* http://29a.ch/ && http://29a.ch/slides/2012/webglwater/ : Water shader explanations in WebGL
* A basic flat, reflective water effect.
*
* Note that this class can only be used with {@link WebGPURenderer}.
* When using {@link WebGLRenderer}, use {@link Water}.
*
* References:
*
* - [Flat mirror for three.js]{@link https://github.com/Slayvin}
* - [An implementation of water shader based on the flat mirror]{@link https://home.adelphi.edu/~stemkoski/}
* - [Water shader explanations in WebGL]{@link http://29a.ch/slides/2012/webglwater/ }
*
* @augments Mesh
*/
class WaterMesh extends Mesh {
/**
* Constructs a new water mesh.
*
* @param {BufferGeometry} geometry - The water mesh's geometry.
* @param {WaterMesh~Options} [options] - The configuration options.
*/
constructor( geometry, options ) {

@@ -26,4 +39,17 @@

this.isWater = true;
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isWaterMesh = true;
/**
* The effect's resolution scale.
*
* @type {number}
* @default 0.5
*/
this.resolution = options.resolution !== undefined ? options.resolution : 0.5;

@@ -33,8 +59,55 @@

/**
* The water's normal map.
*
* @type {TextureNode}
*/
this.waterNormals = texture( options.waterNormals );
/**
* The alpha value.
*
* @type {UniformNode<float>}
* @default 1
*/
this.alpha = uniform( options.alpha !== undefined ? options.alpha : 1.0 );
/**
* The size value.
*
* @type {UniformNode<float>}
* @default 1
*/
this.size = uniform( options.size !== undefined ? options.size : 1.0 );
/**
* The sun color.
*
* @type {UniformNode<color>}
* @default 0xffffff
*/
this.sunColor = uniform( new Color( options.sunColor !== undefined ? options.sunColor : 0xffffff ) );
/**
* The sun direction.
*
* @type {UniformNode<vec3>}
* @default (0.70707,0.70707,0.0)
*/
this.sunDirection = uniform( options.sunDirection !== undefined ? options.sunDirection : new Vector3( 0.70707, 0.70707, 0.0 ) );
/**
* The water color.
*
* @type {UniformNode<color>}
* @default 0x7f7f7f
*/
this.waterColor = uniform( new Color( options.waterColor !== undefined ? options.waterColor : 0x7f7f7f ) );
/**
* The distortion scale.
*
* @type {UniformNode<float>}
* @default 20
*/
this.distortionScale = uniform( options.distortionScale !== undefined ? options.distortionScale : 20.0 );

@@ -111,2 +184,16 @@

/**
* Constructor options of `WaterMesh`.
*
* @typedef {Object} WaterMesh~Options
* @property {number} [resolution=0.5] - The resolution scale.
* @property {?Texture} [waterNormals=null] - The water's normal map.
* @property {number} [alpha=1] - The alpha value.
* @property {number} [size=1] - The size value.
* @property {number|Color|string} [sunColor=0xffffff] - The sun color.
* @property {Vector3} [sunDirection=(0.70707,0.70707,0.0)] - The sun direction.
* @property {number|Color|string} [waterColor=0x7F7F7F] - The water color.
* @property {number} [distortionScale=20] - The distortion scale.
**/
export { WaterMesh };

@@ -0,1 +1,16 @@

/**
* @classdesc Can be used to include Ammo.js as a Physics engine into
* `three.js` apps. Make sure to include `ammo.wasm.js` first:
* ```
* <script src="jsm/libs/ammo.wasm.js"></script>
* ```
* It is then possible to initialize the API via:
* ```js
* const physics = await AmmoPhysics();
* ```
*
* @name AmmoPhysics
* @class
* @hideconstructor
*/
async function AmmoPhysics() {

@@ -268,4 +283,36 @@

return {
/**
* Adds the given scene to this physics simulation. Only meshes with a
* `physics` object in their {@link Object3D#userData} field will be honored.
* The object can be used to store the mass of the mesh. E.g.:
* ```js
* box.userData.physics = { mass: 1 };
* ```
*
* @method
* @name AmmoPhysics#addScene
* @param {Object3D} scene The scene or any type of 3D object to add.
*/
addScene: addScene,
/**
* Adds the given mesh to this physics simulation.
*
* @method
* @name AmmoPhysics#addMesh
* @param {Mesh} mesh The mesh to add.
* @param {number} [mass=0] The mass in kg of the mesh.
*/
addMesh: addMesh,
/**
* Set the position of the given mesh which is part of the physics simulation. Calling this
* method will reset the current simulated velocity of the mesh.
*
* @method
* @name AmmoPhysics#setMeshPosition
* @param {Mesh} mesh The mesh to update the position for.
* @param {Vector3} position - The new position.
* @param {number} [index=0] - If the mesh is instanced, the index represents the instanced ID.
*/
setMeshPosition: setMeshPosition

@@ -272,0 +319,0 @@ // addCompoundMesh

@@ -60,2 +60,15 @@ import { Clock, Vector3, Quaternion, Matrix4 } from 'three';

/**
* @classdesc Can be used to include Jolt as a Physics engine into
* `three.js` apps. The API can be initialized via:
* ```js
* const physics = await JoltPhysics();
* ```
* The component automatically imports Jolt from a CDN so make sure
* to use the component with an active Internet connection.
*
* @name JoltPhysics
* @class
* @hideconstructor
*/
async function JoltPhysics() {

@@ -274,5 +287,40 @@

return {
/**
* Adds the given scene to this physics simulation. Only meshes with a
* `physics` object in their {@link Object3D#userData} field will be honored.
* The object can be used to store the mass and restitution of the mesh. E.g.:
* ```js
* box.userData.physics = { mass: 1, restitution: 0 };
* ```
*
* @method
* @name JoltPhysics#addScene
* @param {Object3D} scene The scene or any type of 3D object to add.
*/
addScene: addScene,
/**
* Adds the given mesh to this physics simulation.
*
* @method
* @name JoltPhysics#addMesh
* @param {Mesh} mesh The mesh to add.
* @param {number} [mass=0] The mass in kg of the mesh.
* @param {number} [restitution=0] The restitution/friction of the mesh.
*/
addMesh: addMesh,
/**
* Set the position of the given mesh which is part of the physics simulation. Calling this
* method will reset the current simulated velocity of the mesh.
*
* @method
* @name JoltPhysics#setMeshPosition
* @param {Mesh} mesh The mesh to update the position for.
* @param {Vector3} position - The new position.
* @param {number} [index=0] - If the mesh is instanced, the index represents the instanced ID.
*/
setMeshPosition: setMeshPosition,
// NOOP
setMeshVelocity: setMeshVelocity

@@ -279,0 +327,0 @@ };

@@ -57,2 +57,15 @@ import { Clock, Vector3, Quaternion, Matrix4 } from 'three';

/**
* @classdesc Can be used to include Rapier as a Physics engine into
* `three.js` apps. The API can be initialized via:
* ```js
* const physics = await RapierPhysics();
* ```
* The component automatically imports Rapier from a CDN so make sure
* to use the component with an active Internet connection.
*
* @name RapierPhysics
* @class
* @hideconstructor
*/
async function RapierPhysics() {

@@ -233,5 +246,48 @@

return {
/**
* Adds the given scene to this physics simulation. Only meshes with a
* `physics` object in their {@link Object3D#userData} field will be honored.
* The object can be used to store the mass and restitution of the mesh. E.g.:
* ```js
* box.userData.physics = { mass: 1, restitution: 0 };
* ```
*
* @method
* @name RapierPhysics#addScene
* @param {Object3D} scene The scene or any type of 3D object to add.
*/
addScene: addScene,
/**
* Adds the given mesh to this physics simulation.
*
* @method
* @name RapierPhysics#addMesh
* @param {Mesh} mesh The mesh to add.
* @param {number} [mass=0] The mass in kg of the mesh.
* @param {number} [restitution=0] The restitution/friction of the mesh.
*/
addMesh: addMesh,
/**
* Set the position of the given mesh which is part of the physics simulation. Calling this
* method will reset the current simulated velocity of the mesh.
*
* @method
* @name RapierPhysics#setMeshPosition
* @param {Mesh} mesh The mesh to update the position for.
* @param {Vector3} position - The new position.
* @param {number} [index=0] - If the mesh is instanced, the index represents the instanced ID.
*/
setMeshPosition: setMeshPosition,
/**
* Set the velocity of the given mesh which is part of the physics simulation.
*
* @method
* @name RapierPhysics#setMeshVelocity
* @param {Mesh} mesh The mesh to update the velocity for.
* @param {Vector3} velocity - The new velocity.
* @param {number} [index=0] - If the mesh is instanced, the index represents the instanced ID.
*/
setMeshVelocity: setMeshVelocity

@@ -238,0 +294,0 @@ };

@@ -13,4 +13,19 @@ import {

/**
* Pass for a basic after image effect.
*
* ```js
* const afterimagePass = new AfterimagePass( 0.9 );
* composer.addPass( afterimagePass );
* ```
*
* @augments Pass
*/
class AfterimagePass extends Pass {
/**
* Constructs a new after image pass.
*
* @param {number} [damp=0.96] - The damping intensity. A higher value means a stronger after image effect.
*/
constructor( damp = 0.96 ) {

@@ -20,34 +35,37 @@

this.shader = AfterimageShader;
/**
* The pass uniforms. Use this object if you want to update the
* `damp` value at runtime.
* ```js
* pass.uniforms.damp.value = 0.9;
* ```
*
* @type {Object}
*/
this.uniforms = UniformsUtils.clone( AfterimageShader.uniforms );
this.uniforms = UniformsUtils.clone( this.shader.uniforms );
this.uniforms[ 'damp' ].value = damp;
this.textureComp = new WebGLRenderTarget( window.innerWidth, window.innerHeight, {
magFilter: NearestFilter,
type: HalfFloatType
} );
this.textureOld = new WebGLRenderTarget( window.innerWidth, window.innerHeight, {
magFilter: NearestFilter,
type: HalfFloatType
} );
/**
* The composition material.
*
* @type {ShaderMaterial}
*/
this.compFsMaterial = new ShaderMaterial( {
uniforms: this.uniforms,
vertexShader: this.shader.vertexShader,
fragmentShader: this.shader.fragmentShader
vertexShader: AfterimageShader.vertexShader,
fragmentShader: AfterimageShader.fragmentShader
} );
this.compFsQuad = new FullScreenQuad( this.compFsMaterial );
const copyShader = CopyShader;
/**
* The copy material.
*
* @type {ShaderMaterial}
*/
this.copyFsMaterial = new ShaderMaterial( {
uniforms: UniformsUtils.clone( copyShader.uniforms ),
vertexShader: copyShader.vertexShader,
fragmentShader: copyShader.fragmentShader,
uniforms: UniformsUtils.clone( CopyShader.uniforms ),
vertexShader: CopyShader.vertexShader,
fragmentShader: CopyShader.fragmentShader,
blending: NoBlending,

@@ -58,15 +76,39 @@ depthTest: false,

this.copyFsQuad = new FullScreenQuad( this.copyFsMaterial );
// internals
this._textureComp = new WebGLRenderTarget( window.innerWidth, window.innerHeight, {
magFilter: NearestFilter,
type: HalfFloatType
} );
this._textureOld = new WebGLRenderTarget( window.innerWidth, window.innerHeight, {
magFilter: NearestFilter,
type: HalfFloatType
} );
this._compFsQuad = new FullScreenQuad( this.compFsMaterial );
this._copyFsQuad = new FullScreenQuad( this.copyFsMaterial );
}
/**
* Performs the after image pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive*/ ) {
this.uniforms[ 'tOld' ].value = this.textureOld.texture;
this.uniforms[ 'tOld' ].value = this._textureOld.texture;
this.uniforms[ 'tNew' ].value = readBuffer.texture;
renderer.setRenderTarget( this.textureComp );
this.compFsQuad.render( renderer );
renderer.setRenderTarget( this._textureComp );
this._compFsQuad.render( renderer );
this.copyFsQuad.material.uniforms.tDiffuse.value = this.textureComp.texture;
this._copyFsQuad.material.uniforms.tDiffuse.value = this._textureComp.texture;

@@ -76,3 +118,3 @@ if ( this.renderToScreen ) {

renderer.setRenderTarget( null );
this.copyFsQuad.render( renderer );
this._copyFsQuad.render( renderer );

@@ -85,3 +127,3 @@ } else {

this.copyFsQuad.render( renderer );
this._copyFsQuad.render( renderer );

@@ -91,5 +133,5 @@ }

// Swap buffers.
const temp = this.textureOld;
this.textureOld = this.textureComp;
this.textureComp = temp;
const temp = this._textureOld;
this._textureOld = this._textureComp;
this._textureComp = temp;
// Now textureOld contains the latest image, ready for the next frame.

@@ -99,13 +141,23 @@

/**
* Sets the size of the pass.
*
* @param {number} width - The width to set.
* @param {number} height - The width to set.
*/
setSize( width, height ) {
this.textureComp.setSize( width, height );
this.textureOld.setSize( width, height );
this._textureComp.setSize( width, height );
this._textureOld.setSize( width, height );
}
/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {
this.textureComp.dispose();
this.textureOld.dispose();
this._textureComp.dispose();
this._textureOld.dispose();

@@ -115,4 +167,4 @@ this.compFsMaterial.dispose();

this.compFsQuad.dispose();
this.copyFsQuad.dispose();
this._compFsQuad.dispose();
this._copyFsQuad.dispose();

@@ -119,0 +171,0 @@ }

@@ -12,4 +12,24 @@ import {

/**
* A pass for a basic Bloom effect.
*
* {@link UnrealBloomPass} produces a more advanced Bloom but is also
* more expensive.
*
* ```js
* const effectBloom = new BloomPass( 0.75 );
* composer.addPass( effectBloom );
* ```
*
* @augments Pass
*/
class BloomPass extends Pass {
/**
* Constructs a new Bloom pass.
*
* @param {number} [strength=1] - The Bloom strength.
* @param {number} [kernelSize=25] - The kernel size.
* @param {number} [sigma=4] - The sigma.
*/
constructor( strength = 1, kernelSize = 25, sigma = 4 ) {

@@ -19,15 +39,17 @@

// render targets
this.renderTargetX = new WebGLRenderTarget( 1, 1, { type: HalfFloatType } ); // will be resized later
this.renderTargetX.texture.name = 'BloomPass.x';
this.renderTargetY = new WebGLRenderTarget( 1, 1, { type: HalfFloatType } ); // will be resized later
this.renderTargetY.texture.name = 'BloomPass.y';
// combine material
/**
* The combine pass uniforms.
*
* @type {Object}
*/
this.combineUniforms = UniformsUtils.clone( CombineShader.uniforms );
this.combineUniforms[ 'strength' ].value = strength;
/**
* The combine pass material.
*
* @type {ShaderMaterial}
*/
this.materialCombine = new ShaderMaterial( {

@@ -48,7 +70,17 @@

/**
* The convolution pass uniforms.
*
* @type {Object}
*/
this.convolutionUniforms = UniformsUtils.clone( convolutionShader.uniforms );
this.convolutionUniforms[ 'uImageIncrement' ].value = BloomPass.blurX;
this.convolutionUniforms[ 'cKernel' ].value = ConvolutionShader.buildKernel( sigma );
this.convolutionUniforms[ 'cKernel' ].value = buildKernel( sigma );
/**
* The convolution pass material.
*
* @type {ShaderMaterial}
*/
this.materialConvolution = new ShaderMaterial( {

@@ -67,8 +99,32 @@

/**
* Overwritten to disable the swap.
*
* @type {boolean}
* @default false
*/
this.needsSwap = false;
this.fsQuad = new FullScreenQuad( null );
// internals
this._renderTargetX = new WebGLRenderTarget( 1, 1, { type: HalfFloatType } ); // will be resized later
this._renderTargetX.texture.name = 'BloomPass.x';
this._renderTargetY = new WebGLRenderTarget( 1, 1, { type: HalfFloatType } ); // will be resized later
this._renderTargetY.texture.name = 'BloomPass.y';
this._fsQuad = new FullScreenQuad( null );
}
/**
* Performs the Bloom pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {

@@ -80,3 +136,3 @@

this.fsQuad.material = this.materialConvolution;
this._fsQuad.material = this.materialConvolution;

@@ -86,5 +142,5 @@ this.convolutionUniforms[ 'tDiffuse' ].value = readBuffer.texture;

renderer.setRenderTarget( this.renderTargetX );
renderer.setRenderTarget( this._renderTargetX );
renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -94,14 +150,14 @@

this.convolutionUniforms[ 'tDiffuse' ].value = this.renderTargetX.texture;
this.convolutionUniforms[ 'tDiffuse' ].value = this._renderTargetX.texture;
this.convolutionUniforms[ 'uImageIncrement' ].value = BloomPass.blurY;
renderer.setRenderTarget( this.renderTargetY );
renderer.setRenderTarget( this._renderTargetY );
renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );
// Render original scene with superimposed blur to texture
this.fsQuad.material = this.materialCombine;
this._fsQuad.material = this.materialCombine;
this.combineUniforms[ 'tDiffuse' ].value = this.renderTargetY.texture;
this.combineUniforms[ 'tDiffuse' ].value = this._renderTargetY.texture;

@@ -112,17 +168,27 @@ if ( maskActive ) renderer.state.buffers.stencil.setTest( true );

if ( this.clear ) renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );
}
/**
* Sets the size of the pass.
*
* @param {number} width - The width to set.
* @param {number} height - The width to set.
*/
setSize( width, height ) {
this.renderTargetX.setSize( width, height );
this.renderTargetY.setSize( width, height );
this._renderTargetX.setSize( width, height );
this._renderTargetY.setSize( width, height );
}
/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {
this.renderTargetX.dispose();
this.renderTargetY.dispose();
this._renderTargetX.dispose();
this._renderTargetY.dispose();

@@ -132,3 +198,3 @@ this.materialCombine.dispose();

this.fsQuad.dispose();
this._fsQuad.dispose();

@@ -181,2 +247,37 @@ }

function gauss( x, sigma ) {
return Math.exp( - ( x * x ) / ( 2.0 * sigma * sigma ) );
}
function buildKernel( sigma ) {
// We loop off the sqrt(2 * pi) * sigma term, since we're going to normalize anyway.
const kMaxKernelSize = 25;
let kernelSize = 2 * Math.ceil( sigma * 3.0 ) + 1;
if ( kernelSize > kMaxKernelSize ) kernelSize = kMaxKernelSize;
const halfWidth = ( kernelSize - 1 ) * 0.5;
const values = new Array( kernelSize );
let sum = 0.0;
for ( let i = 0; i < kernelSize; ++ i ) {
values[ i ] = gauss( i - halfWidth, sigma );
sum += values[ i ];
}
// normalize the kernel
for ( let i = 0; i < kernelSize; ++ i ) values[ i ] /= sum;
return values;
}
export { BloomPass };

@@ -16,7 +16,24 @@ import {

/**
* Depth-of-field post-process with bokeh shader
* Pass for creating depth of field (DOF) effect.
*
* ```js
* const bokehPass = new BokehPass( scene, camera, {
* focus: 500
* aperture: 5,
* maxblur: 0.01
* } );
* composer.addPass( bokehPass );
* ```
*
* @augments Pass
*/
class BokehPass extends Pass {
/**
* Constructs a new Bokeh pass.
*
* @param {Scene} scene - The scene to render the DOF for.
* @param {Camera} camera - The camera.
* @param {BokehPass~Options} params - The pass options.
*/
constructor( scene, camera, params ) {

@@ -26,3 +43,14 @@

/**
* The scene to render the DOF for.
*
* @type {Scene}
*/
this.scene = scene;
/**
* The camera.
*
* @type {Camera}
*/
this.camera = camera;

@@ -36,3 +64,3 @@

this.renderTargetDepth = new WebGLRenderTarget( 1, 1, { // will be resized later
this._renderTargetDepth = new WebGLRenderTarget( 1, 1, { // will be resized later
minFilter: NearestFilter,

@@ -43,16 +71,15 @@ magFilter: NearestFilter,

this.renderTargetDepth.texture.name = 'BokehPass.depth';
this._renderTargetDepth.texture.name = 'BokehPass.depth';
// depth material
this.materialDepth = new MeshDepthMaterial();
this.materialDepth.depthPacking = RGBADepthPacking;
this.materialDepth.blending = NoBlending;
this._materialDepth = new MeshDepthMaterial();
this._materialDepth.depthPacking = RGBADepthPacking;
this._materialDepth.blending = NoBlending;
// bokeh material
const bokehShader = BokehShader;
const bokehUniforms = UniformsUtils.clone( bokehShader.uniforms );
const bokehUniforms = UniformsUtils.clone( BokehShader.uniforms );
bokehUniforms[ 'tDepth' ].value = this.renderTargetDepth.texture;
bokehUniforms[ 'tDepth' ].value = this._renderTargetDepth.texture;

@@ -66,13 +93,32 @@ bokehUniforms[ 'focus' ].value = focus;

/**
* The pass bokeh material.
*
* @type {ShaderMaterial}
*/
this.materialBokeh = new ShaderMaterial( {
defines: Object.assign( {}, bokehShader.defines ),
defines: Object.assign( {}, BokehShader.defines ),
uniforms: bokehUniforms,
vertexShader: bokehShader.vertexShader,
fragmentShader: bokehShader.fragmentShader
vertexShader: BokehShader.vertexShader,
fragmentShader: BokehShader.fragmentShader
} );
/**
* The pass uniforms. Use this object if you want to update the
* `focus`, `aperture` or `maxblur` values at runtime.
*
* ```js
* pass.uniforms.focus.value = focus;
* pass.uniforms.aperture.value = aperture;
* pass.uniforms.maxblur.value = maxblur;
* ```
*
* @type {Object}
*/
this.uniforms = bokehUniforms;
this.fsQuad = new FullScreenQuad( this.materialBokeh );
// internals
this._fsQuad = new FullScreenQuad( this.materialBokeh );
this._oldClearColor = new Color();

@@ -82,2 +128,13 @@

/**
* Performs the Bokeh pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive*/ ) {

@@ -87,3 +144,3 @@

this.scene.overrideMaterial = this.materialDepth;
this.scene.overrideMaterial = this._materialDepth;

@@ -97,3 +154,3 @@ renderer.getClearColor( this._oldClearColor );

renderer.setClearAlpha( 1.0 );
renderer.setRenderTarget( this.renderTargetDepth );
renderer.setRenderTarget( this._renderTargetDepth );
renderer.clear();

@@ -111,3 +168,3 @@ renderer.render( this.scene, this.camera );

renderer.setRenderTarget( null );
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -118,3 +175,3 @@ } else {

renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -130,2 +187,8 @@ }

/**
* Sets the size of the pass.
*
* @param {number} width - The width to set.
* @param {number} height - The width to set.
*/
setSize( width, height ) {

@@ -135,14 +198,18 @@

this.renderTargetDepth.setSize( width, height );
this._renderTargetDepth.setSize( width, height );
}
/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {
this.renderTargetDepth.dispose();
this._renderTargetDepth.dispose();
this.materialDepth.dispose();
this._materialDepth.dispose();
this.materialBokeh.dispose();
this.fsQuad.dispose();
this._fsQuad.dispose();

@@ -153,2 +220,11 @@ }

/**
* Constructor options of `BokehPass`.
*
* @typedef {Object} BokehPass~Options
* @property {number} [focus=1] - Defines the effect's focus which is the distance along the camera's look direction in world units.
* @property {number} [aperture=0.025] - Defines the effect's aperture.
* @property {number} [maxblur=1] - Defines the effect's maximum blur.
**/
export { BokehPass };

@@ -6,12 +6,51 @@ import {

/**
* This class can be used to force a clear operation for the current read or
* default framebuffer (when rendering to screen).
*
* ```js
* const clearPass = new ClearPass();
* composer.addPass( clearPass );
* ```
*
* @augments Pass
*/
class ClearPass extends Pass {
constructor( clearColor, clearAlpha ) {
/**
* Constructs a new clear pass.
*
* @param {(number|Color|string)} [clearColor=0x000000] - The clear color.
* @param {number} [clearAlpha=0] - The clear alpha.
*/
constructor( clearColor = 0x000000, clearAlpha = 0 ) {
super();
/**
* Overwritten to disable the swap.
*
* @type {boolean}
* @default false
*/
this.needsSwap = false;
this.clearColor = ( clearColor !== undefined ) ? clearColor : 0x000000;
this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 0;
/**
* The clear color.
*
* @type {(number|Color|string)}
* @default 0x000000
*/
this.clearColor = clearColor;
/**
* The clear alpha.
*
* @type {number}
* @default 0
*/
this.clearAlpha = clearAlpha;
// internals
this._oldClearColor = new Color();

@@ -21,2 +60,13 @@

/**
* Performs the clear operation. This affects the current read or the default framebuffer.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) {

@@ -23,0 +73,0 @@

@@ -13,4 +13,23 @@ import {

/**
* This pass can be used to render a cube texture over the entire screen.
*
* ```js
* const cubeMap = new THREE.CubeTextureLoader().load( urls );
*
* const cubeTexturePass = new CubeTexturePass( camera, cubemap );
* composer.addPass( cubeTexturePass );
* ```
*
* @augments Pass
*/
class CubeTexturePass extends Pass {
/**
* Constructs a new cube texture pass.
*
* @param {PerspectiveCamera} camera - The camera.
* @param {CubeTexture} tCube - The cube texture to render.
* @param {number} [opacity=1] - The opacity.
*/
constructor( camera, tCube, opacity = 1 ) {

@@ -20,13 +39,42 @@

/**
* The camera.
*
* @type {PerspectiveCamera}
*/
this.camera = camera;
/**
* The cube texture to render.
*
* @type {CubeTexture}
*/
this.tCube = tCube;
/**
* The opacity.
*
* @type {number}
* @default 1
*/
this.opacity = opacity;
/**
* Overwritten to disable the swap.
*
* @type {boolean}
* @default false
*/
this.needsSwap = false;
this.cubeShader = ShaderLib[ 'cube' ];
this.cubeMesh = new Mesh(
// internals
const cubeShader = ShaderLib[ 'cube' ];
this._cubeMesh = new Mesh(
new BoxGeometry( 10, 10, 10 ),
new ShaderMaterial( {
uniforms: UniformsUtils.clone( this.cubeShader.uniforms ),
vertexShader: this.cubeShader.vertexShader,
fragmentShader: this.cubeShader.fragmentShader,
uniforms: UniformsUtils.clone( cubeShader.uniforms ),
vertexShader: cubeShader.vertexShader,
fragmentShader: cubeShader.fragmentShader,
depthTest: false,

@@ -38,3 +86,3 @@ depthWrite: false,

Object.defineProperty( this.cubeMesh.material, 'envMap', {
Object.defineProperty( this._cubeMesh.material, 'envMap', {

@@ -49,11 +97,19 @@ get: function () {

this.tCube = tCube;
this.opacity = opacity;
this._cubeScene = new Scene();
this._cubeCamera = new PerspectiveCamera();
this._cubeScene.add( this._cubeMesh );
this.cubeScene = new Scene();
this.cubeCamera = new PerspectiveCamera();
this.cubeScene.add( this.cubeMesh );
}
/**
* Performs the cube texture pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive*/ ) {

@@ -64,13 +120,13 @@

this.cubeCamera.projectionMatrix.copy( this.camera.projectionMatrix );
this.cubeCamera.quaternion.setFromRotationMatrix( this.camera.matrixWorld );
this._cubeCamera.projectionMatrix.copy( this.camera.projectionMatrix );
this._cubeCamera.quaternion.setFromRotationMatrix( this.camera.matrixWorld );
this.cubeMesh.material.uniforms.tCube.value = this.tCube;
this.cubeMesh.material.uniforms.tFlip.value = ( this.tCube.isCubeTexture && this.tCube.isRenderTargetTexture === false ) ? - 1 : 1;
this.cubeMesh.material.uniforms.opacity.value = this.opacity;
this.cubeMesh.material.transparent = ( this.opacity < 1.0 );
this._cubeMesh.material.uniforms.tCube.value = this.tCube;
this._cubeMesh.material.uniforms.tFlip.value = ( this.tCube.isCubeTexture && this.tCube.isRenderTargetTexture === false ) ? - 1 : 1;
this._cubeMesh.material.uniforms.opacity.value = this.opacity;
this._cubeMesh.material.transparent = ( this.opacity < 1.0 );
renderer.setRenderTarget( this.renderToScreen ? null : readBuffer );
if ( this.clear ) renderer.clear();
renderer.render( this.cubeScene, this.cubeCamera );
renderer.render( this._cubeScene, this._cubeCamera );

@@ -81,6 +137,10 @@ renderer.autoClear = oldAutoClear;

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {
this.cubeMesh.geometry.dispose();
this.cubeMesh.material.dispose();
this._cubeMesh.geometry.dispose();
this._cubeMesh.material.dispose();

@@ -87,0 +147,0 @@ }

@@ -8,4 +8,21 @@ import {

/**
* Pass for creating a dot-screen effect.
*
* ```js
* const pass = new DotScreenPass( new THREE.Vector2( 0, 0 ), 0.5, 0.8 );
* composer.addPass( pass );
* ```
*
* @augments Pass
*/
class DotScreenPass extends Pass {
/**
* Constructs a new dot screen pass.
*
* @param {Vector2} center - The center point.
* @param {number} angle - The rotation of the effect in radians.
* @param {number} scale - The scale of the effect. A higher value means smaller dots.
*/
constructor( center, angle, scale ) {

@@ -15,6 +32,15 @@

const shader = DotScreenShader;
/**
* The pass uniforms. Use this object if you want to update the
* `center`, `angle` or `scale` values at runtime.
* ```js
* pass.uniforms.center.value.copy( center );
* pass.uniforms.angle.value = 0;
* pass.uniforms.scale.value = 0.5;
* ```
*
* @type {Object}
*/
this.uniforms = UniformsUtils.clone( DotScreenShader.uniforms );
this.uniforms = UniformsUtils.clone( shader.uniforms );
if ( center !== undefined ) this.uniforms[ 'center' ].value.copy( center );

@@ -24,15 +50,33 @@ if ( angle !== undefined ) this.uniforms[ 'angle' ].value = angle;

/**
* The pass material.
*
* @type {ShaderMaterial}
*/
this.material = new ShaderMaterial( {
name: shader.name,
name: DotScreenShader.name,
uniforms: this.uniforms,
vertexShader: shader.vertexShader,
fragmentShader: shader.fragmentShader
vertexShader: DotScreenShader.vertexShader,
fragmentShader: DotScreenShader.fragmentShader
} );
this.fsQuad = new FullScreenQuad( this.material );
// internals
this._fsQuad = new FullScreenQuad( this.material );
}
/**
* Performs the dot screen pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) {

@@ -46,3 +90,3 @@

renderer.setRenderTarget( null );
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -53,3 +97,3 @@ } else {

if ( this.clear ) renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -60,2 +104,6 @@ }

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {

@@ -65,3 +113,3 @@

this.fsQuad.dispose();
this._fsQuad.dispose();

@@ -68,0 +116,0 @@ }

@@ -12,6 +12,47 @@ import {

/**
* Used to implement post-processing effects in three.js.
* The class manages a chain of post-processing passes to produce the final visual result.
* Post-processing passes are executed in order of their addition/insertion.
* The last pass is automatically rendered to screen.
*
* This module can only be used with {@link WebGLRenderer}.
*
* ```js
* const composer = new EffectComposer( renderer );
*
* // adding some passes
* const renderPass = new RenderPass( scene, camera );
* composer.addPass( renderPass );
*
* const glitchPass = new GlitchPass();
* composer.addPass( glitchPass );
*
* const outputPass = new OutputPass()
* composer.addPass( outputPass );
*
* function animate() {
*
* composer.render(); // instead of renderer.render()
*
* }
* ```
*/
class EffectComposer {
/**
* Constructs a new effect composer.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} [renderTarget] - This render target and a clone will
* be used as the internal read and write buffers. If not given, the composer creates
* the buffers automatically.
*/
constructor( renderer, renderTarget ) {
/**
* The renderer.
*
* @type {WebGLRenderer}
*/
this.renderer = renderer;

@@ -41,12 +82,48 @@

/**
* A reference to the internal write buffer. Passes usually write
* their result into this buffer.
*
* @type {WebGLRenderTarget}
*/
this.writeBuffer = this.renderTarget1;
/**
* A reference to the internal read buffer. Passes usually read
* the previous render result from this buffer.
*
* @type {WebGLRenderTarget}
*/
this.readBuffer = this.renderTarget2;
/**
* Whether the final pass is rendered to the screen (default framebuffer) or not.
*
* @type {boolean}
* @default true
*/
this.renderToScreen = true;
/**
* An array representing the (ordered) chain of post-processing passes.
*
* @type {Array<Pass>}
*/
this.passes = [];
/**
* A copy pass used for internal swap operations.
*
* @private
* @type {ShaderPass}
*/
this.copyPass = new ShaderPass( CopyShader );
this.copyPass.material.blending = NoBlending;
/**
* The intenral clock for managing time data.
*
* @private
* @type {Clock}
*/
this.clock = new Clock();

@@ -56,2 +133,5 @@

/**
* Swaps the internal read/write buffers.
*/
swapBuffers() {

@@ -65,2 +145,7 @@

/**
* Adds the given pass to the pass chain.
*
* @param {Pass} pass - The pass to add.
*/
addPass( pass ) {

@@ -73,2 +158,8 @@

/**
* Inserts the given pass at a given index.
*
* @param {Pass} pass - The pass to insert.
* @param {number} index - The index into the pass chain.
*/
insertPass( pass, index ) {

@@ -81,2 +172,7 @@

/**
* Removes the given pass from the pass chain.
*
* @param {Pass} pass - The pass to remove.
*/
removePass( pass ) {

@@ -94,2 +190,8 @@

/**
* Returns `true` if the pass for the given index is the last enabled pass in the pass chain.
*
* @param {number} passIndex - The pass index.
* @return {boolean} Whether the the pass for the given index is the last pass in the pass chain.
*/
isLastEnabledPass( passIndex ) {

@@ -111,2 +213,8 @@

/**
* Executes all enabled post-processing passes in order to produce the final frame.
*
* @param {number} deltaTime - The delta time in seconds. If not given, the composer computes
* its own time delta value.
*/
render( deltaTime ) {

@@ -176,2 +284,8 @@

/**
* Resets the internal state of the EffectComposer.
*
* @param {WebGLRenderTarget} [renderTarget] - This render target has the same purpose like
* the one from the constructor. If set, it is used to setup the read and write buffers.
*/
reset( renderTarget ) {

@@ -201,2 +315,9 @@

/**
* Resizes the internal read and write buffers as well as all passes. Similar to {@link WebGLRenderer#setSize},
* this method honors the current pixel ration.
*
* @param {number} width - The width in logical pixels.
* @param {number} height - The height in logical pixels.
*/
setSize( width, height ) {

@@ -221,2 +342,8 @@

/**
* Sets device pixel ratio. This is usually used for HiDPI device to prevent blurring output.
* Setting the pixel ratio will automatically resize the composer.
*
* @param {number} pixelRatio - The pixel ratio to set.
*/
setPixelRatio( pixelRatio ) {

@@ -230,2 +357,6 @@

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the composer is no longer used in your app.
*/
dispose() {

@@ -232,0 +363,0 @@

@@ -8,4 +8,20 @@ import {

/**
* This pass can be used to create a film grain effect.
*
* ```js
* const filmPass = new FilmPass();
* composer.addPass( filmPass );
* ```
*
* @augments Pass
*/
class FilmPass extends Pass {
/**
* Constructs a new film pass.
*
* @param {number} [intensity=0.5] - The grain intensity in the range `[0,1]` (0 = no effect, 1 = full effect).
* @param {boolean} [grayscale=false] - Whether to apply a grayscale effect or not.
*/
constructor( intensity = 0.5, grayscale = false ) {

@@ -17,4 +33,19 @@

/**
* The pass uniforms. Use this object if you want to update the
* `intensity` or `grayscale` values at runtime.
* ```js
* pass.uniforms.intensity.value = 1;
* pass.uniforms.grayscale.value = true;
* ```
*
* @type {Object}
*/
this.uniforms = UniformsUtils.clone( shader.uniforms );
/**
* The pass material.
*
* @type {ShaderMaterial}
*/
this.material = new ShaderMaterial( {

@@ -29,9 +60,22 @@

this.uniforms.intensity.value = intensity; // (0 = no effect, 1 = full effect)
this.uniforms.intensity.value = intensity;
this.uniforms.grayscale.value = grayscale;
this.fsQuad = new FullScreenQuad( this.material );
// internals
this._fsQuad = new FullScreenQuad( this.material );
}
/**
* Performs the film pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer, deltaTime /*, maskActive */ ) {

@@ -45,3 +89,3 @@

renderer.setRenderTarget( null );
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -52,3 +96,3 @@ } else {

if ( this.clear ) renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -59,2 +103,6 @@ }

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {

@@ -64,3 +112,3 @@

this.fsQuad.dispose();
this._fsQuad.dispose();

@@ -67,0 +115,0 @@ }

@@ -12,4 +12,20 @@ import {

/**
* Pass for creating a glitch effect.
*
* ```js
* const glitchPass = new GlitchPass();
* composer.addPass( glitchPass );
* ```
*
* @augments Pass
*/
class GlitchPass extends Pass {
/**
* Constructs a new glitch pass.
*
* @param {number} [dt_size=64] - The size of the displacement texture
* for digital glitch squares.
*/
constructor( dt_size = 64 ) {

@@ -19,31 +35,60 @@

const shader = DigitalGlitch;
/**
* The pass uniforms.
*
* @type {Object}
*/
this.uniforms = UniformsUtils.clone( DigitalGlitch.uniforms );
this.uniforms = UniformsUtils.clone( shader.uniforms );
/**
* The pass material.
*
* @type {ShaderMaterial}
*/
this.material = new ShaderMaterial( {
uniforms: this.uniforms,
vertexShader: DigitalGlitch.vertexShader,
fragmentShader: DigitalGlitch.fragmentShader
} );
this.heightMap = this.generateHeightmap( dt_size );
/**
* Whether to noticeably increase the effect instensity or not.
*
* @type {boolean}
* @default false
*/
this.goWild = false;
// internals
this._heightMap = this._generateHeightmap( dt_size );
this.uniforms[ 'tDisp' ].value = this.heightMap;
this.material = new ShaderMaterial( {
uniforms: this.uniforms,
vertexShader: shader.vertexShader,
fragmentShader: shader.fragmentShader
} );
this._fsQuad = new FullScreenQuad( this.material );
this.fsQuad = new FullScreenQuad( this.material );
this._curF = 0;
this._randX = 0;
this.goWild = false;
this.curF = 0;
this.generateTrigger();
this._generateTrigger();
}
/**
* Performs the glitch pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) {
this.uniforms[ 'tDiffuse' ].value = readBuffer.texture;
this.uniforms[ 'seed' ].value = Math.random();//default seeding
this.uniforms[ 'seed' ].value = Math.random(); // default seeding
this.uniforms[ 'byp' ].value = 0;
if ( this.curF % this.randX == 0 || this.goWild == true ) {
if ( this._curF % this._randX == 0 || this.goWild == true ) {

@@ -56,6 +101,6 @@ this.uniforms[ 'amount' ].value = Math.random() / 30;

this.uniforms[ 'distortion_y' ].value = MathUtils.randFloat( 0, 1 );
this.curF = 0;
this.generateTrigger();
this._curF = 0;
this._generateTrigger();
} else if ( this.curF % this.randX < this.randX / 5 ) {
} else if ( this._curF % this._randX < this._randX / 5 ) {

@@ -75,3 +120,3 @@ this.uniforms[ 'amount' ].value = Math.random() / 90;

this.curF ++;
this._curF ++;

@@ -81,3 +126,3 @@ if ( this.renderToScreen ) {

renderer.setRenderTarget( null );
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -88,3 +133,3 @@ } else {

if ( this.clear ) renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -95,10 +140,26 @@ }

generateTrigger() {
/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {
this.randX = MathUtils.randInt( 120, 240 );
this.material.dispose();
this.heightMap.dispose();
this._fsQuad.dispose();
}
generateHeightmap( dt_size ) {
// internals
_generateTrigger() {
this._randX = MathUtils.randInt( 120, 240 );
}
_generateHeightmap( dt_size ) {
const data_arr = new Float32Array( dt_size * dt_size );

@@ -120,14 +181,4 @@ const length = dt_size * dt_size;

dispose() {
this.material.dispose();
this.heightMap.dispose();
this.fsQuad.dispose();
}
}
export { GlitchPass };

@@ -29,24 +29,114 @@ import {

/**
* A pass for an GTAO effect.
*
* `GTAOPass` provides better quality than {@link SSAOPass} but is also more expensive.
*
* ```js
* const gtaoPass = new GTAOPass( scene, camera, width, height );
* gtaoPass.output = GTAOPass.OUTPUT.Denoise;
* composer.addPass( gtaoPass );
* ```
*
* @augments Pass
*/
class GTAOPass extends Pass {
constructor( scene, camera, width, height, parameters, aoParameters, pdParameters ) {
/**
* Constructs a new GTAO pass.
*
* @param {Scene} scene - The scene to compute the AO for.
* @param {Camera} camera - The camera.
* @param {number} [width=512] - The width of the effect.
* @param {number} [height=512] - The height of the effect.
* @param {Object} [parameters] - The pass parameters.
* @param {Object} [aoParameters] - The AO parameters.
* @param {Object} [pdParameters] - The denoise parameters.
*/
constructor( scene, camera, width = 512, height = 512, parameters, aoParameters, pdParameters ) {
super();
this.width = ( width !== undefined ) ? width : 512;
this.height = ( height !== undefined ) ? height : 512;
/**
* The width of the effect.
*
* @type {number}
* @default 512
*/
this.width = width;
/**
* The height of the effect.
*
* @type {number}
* @default 512
*/
this.height = height;
/**
* Overwritten to perform a clear operation by default.
*
* @type {boolean}
* @default true
*/
this.clear = true;
/**
* The camera.
*
* @type {Camera}
*/
this.camera = camera;
/**
* The scene to render the AO for.
*
* @type {Scene}
*/
this.scene = scene;
/**
* The output configuration.
*
* @type {number}
* @default 0
*/
this.output = 0;
this._renderGBuffer = true;
this._visibilityCache = new Map();
/**
* The AO blend intensity.
*
* @type {number}
* @default 1
*/
this.blendIntensity = 1.;
/**
* The number of Poisson Denoise rings.
*
* @type {number}
* @default 2
*/
this.pdRings = 2.;
/**
* The Poisson Denoise radius exponent.
*
* @type {number}
* @default 2
*/
this.pdRadiusExponent = 2.;
/**
* The Poisson Denoise sample count.
*
* @type {number}
* @default 16
*/
this.pdSamples = 16;
this.gtaoNoiseTexture = generateMagicSquareNoise();
this.pdNoiseTexture = this.generateNoise();
this.pdNoiseTexture = this._generateNoise();

@@ -131,5 +221,5 @@ this.gtaoRenderTarget = new WebGLRenderTarget( this.width, this.height, { type: HalfFloatType } );

this.fsQuad = new FullScreenQuad( null );
this._fsQuad = new FullScreenQuad( null );
this.originalClearColor = new Color();
this._originalClearColor = new Color();

@@ -152,2 +242,30 @@ this.setGBuffer( parameters ? parameters.depthTexture : undefined, parameters ? parameters.normalTexture : undefined );

/**
* Sets the size of the pass.
*
* @param {number} width - The width to set.
* @param {number} height - The width to set.
*/
setSize( width, height ) {
this.width = width;
this.height = height;
this.gtaoRenderTarget.setSize( width, height );
this.normalRenderTarget.setSize( width, height );
this.pdRenderTarget.setSize( width, height );
this.gtaoMaterial.uniforms.resolution.value.set( width, height );
this.gtaoMaterial.uniforms.cameraProjectionMatrix.value.copy( this.camera.projectionMatrix );
this.gtaoMaterial.uniforms.cameraProjectionMatrixInverse.value.copy( this.camera.projectionMatrixInverse );
this.pdMaterial.uniforms.resolution.value.set( width, height );
this.pdMaterial.uniforms.cameraProjectionMatrixInverse.value.copy( this.camera.projectionMatrixInverse );
}
/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {

@@ -164,6 +282,12 @@

this.depthRenderMaterial.dispose();
this.fsQuad.dispose();
this._fsQuad.dispose();
}
/**
* A texture holding the computed AO.
*
* @type {Texture}
* @readonly
*/
get gtaoMap() {

@@ -175,2 +299,10 @@

/**
* Configures the GBuffer of this pass. If no arguments are passed,
* the pass creates an internal render target for holding depth
* and normal data.
*
* @param {DepthTexture} [depthTexture] - The depth texture.
* @param {DepthTexture} [normalTexture] - The normal texture.
*/
setGBuffer( depthTexture, normalTexture ) {

@@ -217,2 +349,8 @@

/**
* Configures the clip box of the GTAO shader with the given AABB.
*
* @param {?Box3} box - The AABB enclosing the scene that should receive AO. When passing
* `null`, to clip box is used.
*/
setSceneClipBox( box ) {

@@ -236,2 +374,7 @@

/**
* Updates the GTAO material from the given paramter object.
*
* @param {Object} parameters - The GTAO material parameters.
*/
updateGtaoMaterial( parameters ) {

@@ -286,2 +429,7 @@

/**
* Updates the Denoise material from the given paramter object.
*
* @param {Object} parameters - The denoise parameters.
*/
updatePdMaterial( parameters ) {

@@ -346,2 +494,13 @@

/**
* Performs the GTAO pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) {

@@ -353,5 +512,5 @@

this.overrideVisibility();
this.renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0x7777ff, 1.0 );
this.restoreVisibility();
this._overrideVisibility();
this._renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0x7777ff, 1.0 );
this._restoreVisibility();

@@ -367,3 +526,3 @@ }

this.gtaoMaterial.uniforms.cameraWorldMatrix.value.copy( this.camera.matrixWorld );
this.renderPass( renderer, this.gtaoMaterial, this.gtaoRenderTarget, 0xffffff, 1.0 );
this._renderPass( renderer, this.gtaoMaterial, this.gtaoRenderTarget, 0xffffff, 1.0 );

@@ -373,3 +532,3 @@ // render poisson denoise

this.pdMaterial.uniforms.cameraProjectionMatrixInverse.value.copy( this.camera.projectionMatrixInverse );
this.renderPass( renderer, this.pdMaterial, this.pdRenderTarget, 0xffffff, 1.0 );
this._renderPass( renderer, this.pdMaterial, this.pdRenderTarget, 0xffffff, 1.0 );

@@ -387,3 +546,3 @@ // output result to screen

this.copyMaterial.blending = NoBlending;
this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );

@@ -396,3 +555,3 @@ break;

this.copyMaterial.blending = NoBlending;
this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );

@@ -405,3 +564,3 @@ break;

this.copyMaterial.blending = NoBlending;
this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );

@@ -414,3 +573,3 @@ break;

this.depthRenderMaterial.uniforms.cameraFar.value = this.camera.far;
this.renderPass( renderer, this.depthRenderMaterial, this.renderToScreen ? null : writeBuffer );
this._renderPass( renderer, this.depthRenderMaterial, this.renderToScreen ? null : writeBuffer );

@@ -423,3 +582,3 @@ break;

this.copyMaterial.blending = NoBlending;
this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );

@@ -432,7 +591,7 @@ break;

this.copyMaterial.blending = NoBlending;
this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
this.blendMaterial.uniforms.intensity.value = this.blendIntensity;
this.blendMaterial.uniforms.tDiffuse.value = this.pdRenderTarget.texture;
this.renderPass( renderer, this.blendMaterial, this.renderToScreen ? null : writeBuffer );
this._renderPass( renderer, this.blendMaterial, this.renderToScreen ? null : writeBuffer );

@@ -448,6 +607,8 @@ break;

renderPass( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) {
// internals
_renderPass( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) {
// save original state
renderer.getClearColor( this.originalClearColor );
renderer.getClearColor( this._originalClearColor );
const originalClearAlpha = renderer.getClearAlpha();

@@ -468,8 +629,8 @@ const originalAutoClear = renderer.autoClear;

this.fsQuad.material = passMaterial;
this.fsQuad.render( renderer );
this._fsQuad.material = passMaterial;
this._fsQuad.render( renderer );
// restore original state
renderer.autoClear = originalAutoClear;
renderer.setClearColor( this.originalClearColor );
renderer.setClearColor( this._originalClearColor );
renderer.setClearAlpha( originalClearAlpha );

@@ -479,5 +640,5 @@

renderOverride( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {
_renderOverride( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {
renderer.getClearColor( this.originalClearColor );
renderer.getClearColor( this._originalClearColor );
const originalClearAlpha = renderer.getClearAlpha();

@@ -505,3 +666,3 @@ const originalAutoClear = renderer.autoClear;

renderer.autoClear = originalAutoClear;
renderer.setClearColor( this.originalClearColor );
renderer.setClearColor( this._originalClearColor );
renderer.setClearAlpha( originalClearAlpha );

@@ -511,22 +672,4 @@

setSize( width, height ) {
_overrideVisibility() {
this.width = width;
this.height = height;
this.gtaoRenderTarget.setSize( width, height );
this.normalRenderTarget.setSize( width, height );
this.pdRenderTarget.setSize( width, height );
this.gtaoMaterial.uniforms.resolution.value.set( width, height );
this.gtaoMaterial.uniforms.cameraProjectionMatrix.value.copy( this.camera.projectionMatrix );
this.gtaoMaterial.uniforms.cameraProjectionMatrixInverse.value.copy( this.camera.projectionMatrixInverse );
this.pdMaterial.uniforms.resolution.value.set( width, height );
this.pdMaterial.uniforms.cameraProjectionMatrixInverse.value.copy( this.camera.projectionMatrixInverse );
}
overrideVisibility() {
const scene = this.scene;

@@ -545,3 +688,3 @@ const cache = this._visibilityCache;

restoreVisibility() {
_restoreVisibility() {

@@ -562,3 +705,3 @@ const scene = this.scene;

generateNoise( size = 64 ) {
_generateNoise( size = 64 ) {

@@ -565,0 +708,0 @@ const simplex = new SimplexNoise();

@@ -9,12 +9,46 @@ import {

/**
* RGB Halftone pass for three.js effects composer. Requires HalftoneShader.
* Pass for creating a RGB halftone effect.
*
* ```js
* const params = {
* shape: 1,
* radius: 4,
* rotateR: Math.PI / 12,
* rotateB: Math.PI / 12 * 2,
* rotateG: Math.PI / 12 * 3,
* scatter: 0,
* blending: 1,
* blendingMode: 1,
* greyscale: false,
* disable: false
* };
* const halftonePass = new HalftonePass( params );
* composer.addPass( halftonePass );
* ```
*
* @augments Pass
*/
class HalftonePass extends Pass {
constructor( width, height, params ) {
/**
* Constructs a new halftone pass.
*
* @param {Object} params - The halftone shader parameter.
*/
constructor( params ) {
super();
/**
* The pass uniforms.
*
* @type {Object}
*/
this.uniforms = UniformsUtils.clone( HalftoneShader.uniforms );
/**
* The pass material.
*
* @type {ShaderMaterial}
*/
this.material = new ShaderMaterial( {

@@ -26,5 +60,2 @@ uniforms: this.uniforms,

// set params
this.uniforms.width.value = width;
this.uniforms.height.value = height;

@@ -41,6 +72,19 @@ for ( const key in params ) {

this.fsQuad = new FullScreenQuad( this.material );
// internals
this._fsQuad = new FullScreenQuad( this.material );
}
/**
* Performs the halftone pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive*/ ) {

@@ -53,3 +97,3 @@

renderer.setRenderTarget( null );
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -60,3 +104,3 @@ } else {

if ( this.clear ) renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -67,2 +111,8 @@ }

/**
* Sets the size of the pass.
*
* @param {number} width - The width to set.
* @param {number} height - The width to set.
*/
setSize( width, height ) {

@@ -75,2 +125,6 @@

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {

@@ -80,3 +134,3 @@

this.fsQuad.dispose();
this._fsQuad.dispose();

@@ -83,0 +137,0 @@ }

@@ -59,4 +59,41 @@ import { ShaderPass } from './ShaderPass.js';

/**
* Pass for color grading via lookup tables.
*
* ```js
* const lutPass = new LUTPass( { lut: lut.texture3D } );
* composer.addPass( lutPass );
* ```
*
* @augments ShaderPass
*/
class LUTPass extends ShaderPass {
/**
* Constructs a LUT pass.
*
* @param {{lut:Data3DTexture,intensity:number}} [options={}] - The pass options.
*/
constructor( options = {} ) {
super( LUTShader );
/**
* The LUT as a 3D texture.
*
* @type {?Data3DTexture}
* @default null
*/
this.lut = options.lut || null;
/**
* The intensity.
*
* @type {?number}
* @default 1
*/
this.intensity = 'intensity' in options ? options.intensity : 1;
}
set lut( v ) {

@@ -99,12 +136,4 @@

constructor( options = {} ) {
super( LUTShader );
this.lut = options.lut || null;
this.intensity = 'intensity' in options ? options.intensity : 1;
}
}
export { LUTPass };
import { Pass } from './Pass.js';
/**
* This pass can be used to define a mask during post processing.
* Meaning only areas of subsequent post processing are affected
* which lie in the masking area of this pass. Internally, the masking
* is implemented with the stencil buffer.
*
* ```js
* const maskPass = new MaskPass( scene, camera );
* composer.addPass( maskPass );
* ```
*
* @augments Pass
*/
class MaskPass extends Pass {
/**
* Constructs a new mask pass.
*
* @param {Scene} scene - The 3D objects in this scene will define the mask.
* @param {Camera} camera - The camera.
*/
constructor( scene, camera ) {

@@ -9,8 +28,38 @@

/**
* The scene that defines the mask.
*
* @type {Scene}
*/
this.scene = scene;
/**
* The camera.
*
* @type {Camera}
*/
this.camera = camera;
/**
* Overwritten to perform a clear operation by default.
*
* @type {boolean}
* @default true
*/
this.clear = true;
/**
* Overwritten to disable the swap.
*
* @type {boolean}
* @default false
*/
this.needsSwap = false;
/**
* Whether to inverse the mask or not.
*
* @type {boolean}
* @default false
*/
this.inverse = false;

@@ -20,2 +69,13 @@

/**
* Performs a mask pass with the configured scene and camera.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) {

@@ -87,4 +147,17 @@

/**
* This pass can be used to clear a mask previously defined with {@link MaskPass}.
*
* ```js
* const clearPass = new ClearMaskPass();
* composer.addPass( clearPass );
* ```
*
* @augments Pass
*/
class ClearMaskPass extends Pass {
/**
* Constructs a new clear mask pass.
*/
constructor() {

@@ -94,2 +167,8 @@

/**
* Overwritten to disable the swap.
*
* @type {boolean}
* @default false
*/
this.needsSwap = false;

@@ -99,2 +178,13 @@

/**
* Performs the clear of the currently defined mask.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer /*, writeBuffer, readBuffer, deltaTime, maskActive */ ) {

@@ -101,0 +191,0 @@

@@ -19,4 +19,24 @@ import {

/**
* A pass for rendering outlines around selected objects.
*
* ```js
* const resolution = new THREE.Vector2( window.innerWidth, window.innerHeight );
* const outlinePass = new OutlinePass( resolution, scene, camera );
* composer.addPass( outlinePass );
* ```
*
* @augments Pass
*/
class OutlinePass extends Pass {
/**
* Constructs a new outline pass.
*
* @param {Vector2} [resolution] - The effect's resolution.
* @param {Scene} scene - The scene to render.
* @param {Camera} camera - The camera.
* @param {Array<Object3D>} [selectedObjects] - The selected 3D objects that should receive an outline.
*
*/
constructor( resolution, scene, camera, selectedObjects ) {

@@ -26,12 +46,96 @@

/**
* The scene to render.
*
* @type {Object}
*/
this.renderScene = scene;
/**
* The camera.
*
* @type {Object}
*/
this.renderCamera = camera;
/**
* The selected 3D objects that should receive an outline.
*
* @type {Array<Object3D>}
*/
this.selectedObjects = selectedObjects !== undefined ? selectedObjects : [];
/**
* The visible edge color.
*
* @type {Color}
* @default (1,1,1)
*/
this.visibleEdgeColor = new Color( 1, 1, 1 );
/**
* The hidden edge color.
*
* @type {Color}
* @default (0.1,0.04,0.02)
*/
this.hiddenEdgeColor = new Color( 0.1, 0.04, 0.02 );
/**
* Can be used for an animated glow/pulse effect.
*
* @type {number}
* @default 0
*/
this.edgeGlow = 0.0;
/**
* Whether to use a pattern texture for to highlight selected
* 3D objects or not.
*
* @type {boolean}
* @default false
*/
this.usePatternTexture = false;
/**
* Can be used to highlight selected 3D objects. Requires to set
* {@link OutlinePass#usePatternTexture} to `true`.
*
* @type {?Texture}
* @default null
*/
this.patternTexture = null;
/**
* The edge thickness.
*
* @type {number}
* @default 1
*/
this.edgeThickness = 1.0;
/**
* The edge strength.
*
* @type {number}
* @default 3
*/
this.edgeStrength = 3.0;
/**
* The downsample ratio. The effect can be rendered in a much
* lower resolution than the beauty pass.
*
* @type {number}
* @default 2
*/
this.downSampleRatio = 2;
/**
* The pulse period.
*
* @type {number}
* @default 0
*/
this.pulsePeriod = 0;

@@ -42,2 +146,8 @@

/**
* The effect's resolution.
*
* @type {Vector2}
* @default (256,256)
*/
this.resolution = ( resolution !== undefined ) ? new Vector2( resolution.x, resolution.y ) : new Vector2( 256, 256 );

@@ -57,3 +167,3 @@

this.prepareMaskMaterial = this.getPrepareMaskMaterial();
this.prepareMaskMaterial = this._getPrepareMaskMaterial();
this.prepareMaskMaterial.side = DoubleSide;

@@ -77,3 +187,3 @@ this.prepareMaskMaterial.fragmentShader = replaceDepthToViewZ( this.prepareMaskMaterial.fragmentShader, this.renderCamera );

this.edgeDetectionMaterial = this.getEdgeDetectionMaterial();
this.edgeDetectionMaterial = this._getEdgeDetectionMaterial();
this.renderTargetEdgeBuffer1 = new WebGLRenderTarget( resx, resy, { type: HalfFloatType } );

@@ -89,6 +199,6 @@ this.renderTargetEdgeBuffer1.texture.name = 'OutlinePass.edge1';

this.separableBlurMaterial1 = this.getSeparableBlurMaterial( MAX_EDGE_THICKNESS );
this.separableBlurMaterial1 = this._getSeparableBlurMaterial( MAX_EDGE_THICKNESS );
this.separableBlurMaterial1.uniforms[ 'texSize' ].value.set( resx, resy );
this.separableBlurMaterial1.uniforms[ 'kernelRadius' ].value = 1;
this.separableBlurMaterial2 = this.getSeparableBlurMaterial( MAX_EDGE_GLOW );
this.separableBlurMaterial2 = this._getSeparableBlurMaterial( MAX_EDGE_GLOW );
this.separableBlurMaterial2.uniforms[ 'texSize' ].value.set( Math.round( resx / 2 ), Math.round( resy / 2 ) );

@@ -98,3 +208,3 @@ this.separableBlurMaterial2.uniforms[ 'kernelRadius' ].value = MAX_EDGE_GLOW;

// Overlay material
this.overlayMaterial = this.getOverlayMaterial();
this.overlayMaterial = this._getOverlayMaterial();

@@ -122,3 +232,3 @@ // copy material

this.fsQuad = new FullScreenQuad( null );
this._fsQuad = new FullScreenQuad( null );

@@ -139,2 +249,6 @@ this.tempPulseColor1 = new Color();

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {

@@ -158,6 +272,12 @@

this.fsQuad.dispose();
this._fsQuad.dispose();
}
/**
* Sets the size of the pass.
*
* @param {number} width - The width to set.
* @param {number} height - The width to set.
*/
setSize( width, height ) {

@@ -185,104 +305,13 @@

updateSelectionCache() {
const cache = this._selectionCache;
function gatherSelectedMeshesCallBack( object ) {
if ( object.isMesh ) cache.add( object );
}
cache.clear();
for ( let i = 0; i < this.selectedObjects.length; i ++ ) {
const selectedObject = this.selectedObjects[ i ];
selectedObject.traverse( gatherSelectedMeshesCallBack );
}
}
changeVisibilityOfSelectedObjects( bVisible ) {
const cache = this._visibilityCache;
for ( const mesh of this._selectionCache ) {
if ( bVisible === true ) {
mesh.visible = cache.get( mesh );
} else {
cache.set( mesh, mesh.visible );
mesh.visible = bVisible;
}
}
}
changeVisibilityOfNonSelectedObjects( bVisible ) {
const visibilityCache = this._visibilityCache;
const selectionCache = this._selectionCache;
function VisibilityChangeCallBack( object ) {
if ( object.isMesh || object.isSprite ) {
// only meshes and sprites are supported by OutlinePass
if ( ! selectionCache.has( object ) ) {
const visibility = object.visible;
if ( bVisible === false || visibilityCache.get( object ) === true ) {
object.visible = bVisible;
}
visibilityCache.set( object, visibility );
}
} else if ( object.isPoints || object.isLine ) {
// the visibility of points and lines is always set to false in order to
// not affect the outline computation
if ( bVisible === true ) {
object.visible = visibilityCache.get( object ); // restore
} else {
visibilityCache.set( object, object.visible );
object.visible = bVisible;
}
}
}
this.renderScene.traverse( VisibilityChangeCallBack );
}
updateTextureMatrix() {
this.textureMatrix.set( 0.5, 0.0, 0.0, 0.5,
0.0, 0.5, 0.0, 0.5,
0.0, 0.0, 0.5, 0.5,
0.0, 0.0, 0.0, 1.0 );
this.textureMatrix.multiply( this.renderCamera.projectionMatrix );
this.textureMatrix.multiply( this.renderCamera.matrixWorldInverse );
}
/**
* Performs the Outline pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {

@@ -302,6 +331,6 @@

this.updateSelectionCache();
this._updateSelectionCache();
// Make selected objects invisible
this.changeVisibilityOfSelectedObjects( false );
this._changeVisibilityOfSelectedObjects( false );

@@ -319,10 +348,10 @@ const currentBackground = this.renderScene.background;

// Make selected objects visible
this.changeVisibilityOfSelectedObjects( true );
this._changeVisibilityOfSelectedObjects( true );
this._visibilityCache.clear();
// Update Texture Matrix for Depth compare
this.updateTextureMatrix();
this._updateTextureMatrix();
// Make non selected objects invisible, and draw only the selected objects, by comparing the depth buffer of non selected objects
this.changeVisibilityOfNonSelectedObjects( false );
this._changeVisibilityOfNonSelectedObjects( false );
this.renderScene.overrideMaterial = this.prepareMaskMaterial;

@@ -335,3 +364,3 @@ this.prepareMaskMaterial.uniforms[ 'cameraNearFar' ].value.set( this.renderCamera.near, this.renderCamera.far );

renderer.render( this.renderScene, this.renderCamera );
this.changeVisibilityOfNonSelectedObjects( true );
this._changeVisibilityOfNonSelectedObjects( true );
this._visibilityCache.clear();

@@ -344,7 +373,7 @@ this._selectionCache.clear();

// 2. Downsample to Half resolution
this.fsQuad.material = this.materialCopy;
this._fsQuad.material = this.materialCopy;
this.copyUniforms[ 'tDiffuse' ].value = this.renderTargetMaskBuffer.texture;
renderer.setRenderTarget( this.renderTargetMaskDownSampleBuffer );
renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -363,3 +392,3 @@ this.tempPulseColor1.copy( this.visibleEdgeColor );

// 3. Apply Edge Detection Pass
this.fsQuad.material = this.edgeDetectionMaterial;
this._fsQuad.material = this.edgeDetectionMaterial;
this.edgeDetectionMaterial.uniforms[ 'maskTexture' ].value = this.renderTargetMaskDownSampleBuffer.texture;

@@ -371,6 +400,6 @@ this.edgeDetectionMaterial.uniforms[ 'texSize' ].value.set( this.renderTargetMaskDownSampleBuffer.width, this.renderTargetMaskDownSampleBuffer.height );

renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );
// 4. Apply Blur on Half res
this.fsQuad.material = this.separableBlurMaterial1;
this._fsQuad.material = this.separableBlurMaterial1;
this.separableBlurMaterial1.uniforms[ 'colorTexture' ].value = this.renderTargetEdgeBuffer1.texture;

@@ -381,3 +410,3 @@ this.separableBlurMaterial1.uniforms[ 'direction' ].value = OutlinePass.BlurDirectionX;

renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );
this.separableBlurMaterial1.uniforms[ 'colorTexture' ].value = this.renderTargetBlurBuffer1.texture;

@@ -387,6 +416,6 @@ this.separableBlurMaterial1.uniforms[ 'direction' ].value = OutlinePass.BlurDirectionY;

renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );
// Apply Blur on quarter res
this.fsQuad.material = this.separableBlurMaterial2;
this._fsQuad.material = this.separableBlurMaterial2;
this.separableBlurMaterial2.uniforms[ 'colorTexture' ].value = this.renderTargetEdgeBuffer1.texture;

@@ -396,3 +425,3 @@ this.separableBlurMaterial2.uniforms[ 'direction' ].value = OutlinePass.BlurDirectionX;

renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );
this.separableBlurMaterial2.uniforms[ 'colorTexture' ].value = this.renderTargetBlurBuffer2.texture;

@@ -402,6 +431,6 @@ this.separableBlurMaterial2.uniforms[ 'direction' ].value = OutlinePass.BlurDirectionY;

renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );
// Blend it additively over the input texture
this.fsQuad.material = this.overlayMaterial;
this._fsQuad.material = this.overlayMaterial;
this.overlayMaterial.uniforms[ 'maskTexture' ].value = this.renderTargetMaskBuffer.texture;

@@ -419,3 +448,3 @@ this.overlayMaterial.uniforms[ 'edgeTexture1' ].value = this.renderTargetEdgeBuffer1.texture;

renderer.setRenderTarget( readBuffer );
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -429,6 +458,6 @@ renderer.setClearColor( this._oldClearColor, this.oldClearAlpha );

this.fsQuad.material = this.materialCopy;
this._fsQuad.material = this.materialCopy;
this.copyUniforms[ 'tDiffuse' ].value = readBuffer.texture;
renderer.setRenderTarget( null );
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -439,4 +468,108 @@ }

getPrepareMaskMaterial() {
// internals
_updateSelectionCache() {
const cache = this._selectionCache;
function gatherSelectedMeshesCallBack( object ) {
if ( object.isMesh ) cache.add( object );
}
cache.clear();
for ( let i = 0; i < this.selectedObjects.length; i ++ ) {
const selectedObject = this.selectedObjects[ i ];
selectedObject.traverse( gatherSelectedMeshesCallBack );
}
}
_changeVisibilityOfSelectedObjects( bVisible ) {
const cache = this._visibilityCache;
for ( const mesh of this._selectionCache ) {
if ( bVisible === true ) {
mesh.visible = cache.get( mesh );
} else {
cache.set( mesh, mesh.visible );
mesh.visible = bVisible;
}
}
}
_changeVisibilityOfNonSelectedObjects( bVisible ) {
const visibilityCache = this._visibilityCache;
const selectionCache = this._selectionCache;
function VisibilityChangeCallBack( object ) {
if ( object.isMesh || object.isSprite ) {
// only meshes and sprites are supported by OutlinePass
if ( ! selectionCache.has( object ) ) {
const visibility = object.visible;
if ( bVisible === false || visibilityCache.get( object ) === true ) {
object.visible = bVisible;
}
visibilityCache.set( object, visibility );
}
} else if ( object.isPoints || object.isLine ) {
// the visibility of points and lines is always set to false in order to
// not affect the outline computation
if ( bVisible === true ) {
object.visible = visibilityCache.get( object ); // restore
} else {
visibilityCache.set( object, object.visible );
object.visible = bVisible;
}
}
}
this.renderScene.traverse( VisibilityChangeCallBack );
}
_updateTextureMatrix() {
this.textureMatrix.set( 0.5, 0.0, 0.0, 0.5,
0.0, 0.5, 0.0, 0.5,
0.0, 0.0, 0.5, 0.5,
0.0, 0.0, 0.0, 1.0 );
this.textureMatrix.multiply( this.renderCamera.projectionMatrix );
this.textureMatrix.multiply( this.renderCamera.matrixWorldInverse );
}
_getPrepareMaskMaterial() {
return new ShaderMaterial( {

@@ -502,3 +635,3 @@

getEdgeDetectionMaterial() {
_getEdgeDetectionMaterial() {

@@ -550,3 +683,3 @@ return new ShaderMaterial( {

getSeparableBlurMaterial( maxRadius ) {
_getSeparableBlurMaterial( maxRadius ) {

@@ -608,3 +741,3 @@ return new ShaderMaterial( {

getOverlayMaterial() {
_getOverlayMaterial() {

@@ -611,0 +744,0 @@ return new ShaderMaterial( {

@@ -17,4 +17,22 @@ import {

/**
* This pass is responsible for including tone mapping and color space conversion
* into your pass chain. In most cases, this pass should be included at the end
* of each pass chain. If a pass requires sRGB input (e.g. like FXAA), the pass
* must follow `OutputPass` in the pass chain.
*
* The tone mapping and color space settings are extracted from the renderer.
*
* ```js
* const outputPass = new OutputPass();
* composer.addPass( outputPass );
* ```
*
* @augments Pass
*/
class OutputPass extends Pass {
/**
* Constructs a new output pass.
*/
constructor() {

@@ -24,18 +42,24 @@

//
/**
* The pass uniforms.
*
* @type {Object}
*/
this.uniforms = UniformsUtils.clone( OutputShader.uniforms );
const shader = OutputShader;
this.uniforms = UniformsUtils.clone( shader.uniforms );
/**
* The pass material.
*
* @type {RawShaderMaterial}
*/
this.material = new RawShaderMaterial( {
name: shader.name,
name: OutputShader.name,
uniforms: this.uniforms,
vertexShader: shader.vertexShader,
fragmentShader: shader.fragmentShader
vertexShader: OutputShader.vertexShader,
fragmentShader: OutputShader.fragmentShader
} );
this.fsQuad = new FullScreenQuad( this.material );
// internals
// internal cache
this._fsQuad = new FullScreenQuad( this.material );

@@ -47,2 +71,13 @@ this._outputColorSpace = null;

/**
* Performs the output pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive */ ) {

@@ -81,3 +116,3 @@

renderer.setRenderTarget( null );
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -88,3 +123,3 @@ } else {

if ( this.clear ) renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -95,6 +130,10 @@ }

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {
this.material.dispose();
this.fsQuad.dispose();
this._fsQuad.dispose();

@@ -101,0 +140,0 @@ }

@@ -8,18 +8,56 @@ import {

/**
* Abstract base class for all post processing passes.
*
* This module is only relevant for post processing with {@link WebGLRenderer}.
*
* @abstract
*/
class Pass {
/**
* Constructs a new pass.
*/
constructor() {
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isPass = true;
// if set to true, the pass is processed by the composer
/**
* If set to `true`, the pass is processed by the composer.
*
* @type {boolean}
* @default true
*/
this.enabled = true;
// if set to true, the pass indicates to swap read and write buffer after rendering
/**
* If set to `true`, the pass indicates to swap read and write buffer after rendering.
*
* @type {boolean}
* @default true
*/
this.needsSwap = true;
// if set to true, the pass clears its buffer before rendering
/**
* If set to `true`, the pass clears its buffer before rendering
*
* @type {boolean}
* @default false
*/
this.clear = false;
// if set to true, the result of the pass is rendered to screen. This is set automatically by EffectComposer.
/**
* If set to `true`, the result of the pass is rendered to screen. The last pass in the composers
* pass chain gets automatically rendered to screen, no matter how this property is configured.
*
* @type {boolean}
* @default false
*/
this.renderToScreen = false;

@@ -29,4 +67,23 @@

/**
* Sets the size of the pass.
*
* @abstract
* @param {number} width - The width to set.
* @param {number} height - The width to set.
*/
setSize( /* width, height */ ) {}
/**
* This method holds the render logic of a pass. It must be implemented in all derived classes.
*
* @abstract
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( /* renderer, writeBuffer, readBuffer, deltaTime, maskActive */ ) {

@@ -38,2 +95,8 @@

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*
* @abstract
*/
dispose() {}

@@ -64,4 +127,21 @@

/**
* 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 full screen quad for rendering
* subsequent passes by just reassigning the `material` reference.
*
* This module can only be used with {@link WebGLRenderer}.
*
* @augments Mesh
*/
class FullScreenQuad {
/**
* Constructs a new full screen quad.
*
* @param {?Material} material - The material to render te full screen quad with.
*/
constructor( material ) {

@@ -73,2 +153,6 @@

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the instance is no longer used in your app.
*/
dispose() {

@@ -80,2 +164,7 @@

/**
* Renders the full screen quad.
*
* @param {WebGLRenderer} renderer - The renderer.
*/
render( renderer ) {

@@ -87,2 +176,7 @@

/**
* The quad's material.
*
* @type {?Material}
*/
get material() {

@@ -89,0 +183,0 @@

@@ -6,4 +6,25 @@ import {

/**
* This class represents a render pass. It takes a camera and a scene and produces
* a beauty pass for subsequent post processing effects.
*
* ```js
* const renderPass = new RenderPass( scene, camera );
* composer.addPass( renderPass );
* ```
*
* @augments Pass
*/
class RenderPass extends Pass {
/**
* Constructs a new render pass.
*
* @param {Scene} scene - The scene to render.
* @param {Camera} camera - The camera.
* @param {?Material} [overrideMaterial=null] - The override material. If set, this material is used
* for all objects in the scene.
* @param {?(number|Color|string)} [clearColor=null] - The clear color of the render pass.
* @param {?number} [clearAlpha=null] - The clear alpha of the render pass.
*/
constructor( scene, camera, overrideMaterial = null, clearColor = null, clearAlpha = null ) {

@@ -13,12 +34,63 @@

/**
* The scene to render.
*
* @type {Scene}
*/
this.scene = scene;
/**
* The camera.
*
* @type {Camera}
*/
this.camera = camera;
/**
* The override material. If set, this material is used
* for all objects in the scene.
*
* @type {?Material}
* @default null
*/
this.overrideMaterial = overrideMaterial;
/**
* The clear color of the render pass.
*
* @type {?(number|Color|string)}
* @default null
*/
this.clearColor = clearColor;
/**
* The clear alpha of the render pass.
*
* @type {?number}
* @default null
*/
this.clearAlpha = clearAlpha;
/**
* Overwritten to perform a clear operation by default.
*
* @type {boolean}
* @default true
*/
this.clear = true;
/**
* If set to `true`, only the depth can be cleared when `clear` is to `false`.
*
* @type {boolean}
* @default false
*/
this.clearDepth = false;
/**
* Overwritten to disable the swap.
*
* @type {boolean}
* @default false
*/
this.needsSwap = false;

@@ -29,2 +101,13 @@ this._oldClearColor = new Color();

/**
* Performs a beauty pass with the configured scene and camera.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) {

@@ -31,0 +114,0 @@

@@ -13,4 +13,22 @@ import {

/**
* A special type of render pass that produces a pixelated beauty pass.
*
* ```js
* const renderPixelatedPass = new RenderPixelatedPass( 6, scene, camera );
* composer.addPass( renderPixelatedPass );
* ```
*
* @augments Pass
*/
class RenderPixelatedPass extends Pass {
/**
* Constructs a new render pixelated pass.
*
* @param {number} pixelSize - The effect's pixel size.
* @param {Scene} scene - The scene to render.
* @param {Camera} camera - The camera.
* @param {{normalEdgeStrength:number,depthEdgeStrength:number}} options - The pass options.
*/
constructor( pixelSize, scene, camera, options = {} ) {

@@ -20,77 +38,142 @@

/**
* The effect's pixel size.
*
* @type {number}
*/
this.pixelSize = pixelSize;
this.resolution = new Vector2();
this.renderResolution = new Vector2();
this.pixelatedMaterial = this.createPixelatedMaterial();
this.normalMaterial = new MeshNormalMaterial();
/**
* The scene to render.
*
* @type {Scene}
*/
this.scene = scene;
this.fsQuad = new FullScreenQuad( this.pixelatedMaterial );
this.scene = scene;
/**
* The camera.
*
* @type {Camera}
*/
this.camera = camera;
/**
* The normal edge strength.
*
* @type {number}
* @default 0.3
*/
this.normalEdgeStrength = options.normalEdgeStrength || 0.3;
/**
* The normal edge strength.
*
* @type {number}
* @default 0.4
*/
this.depthEdgeStrength = options.depthEdgeStrength || 0.4;
this.beautyRenderTarget = new WebGLRenderTarget();
this.beautyRenderTarget.texture.minFilter = NearestFilter;
this.beautyRenderTarget.texture.magFilter = NearestFilter;
this.beautyRenderTarget.texture.type = HalfFloatType;
this.beautyRenderTarget.depthTexture = new DepthTexture();
/**
* The pixelated material.
*
* @type {ShaderMaterial}
*/
this.pixelatedMaterial = this._createPixelatedMaterial();
this.normalRenderTarget = new WebGLRenderTarget();
this.normalRenderTarget.texture.minFilter = NearestFilter;
this.normalRenderTarget.texture.magFilter = NearestFilter;
this.normalRenderTarget.texture.type = HalfFloatType;
// internals
this._resolution = new Vector2();
this._renderResolution = new Vector2();
this._normalMaterial = new MeshNormalMaterial();
this._beautyRenderTarget = new WebGLRenderTarget();
this._beautyRenderTarget.texture.minFilter = NearestFilter;
this._beautyRenderTarget.texture.magFilter = NearestFilter;
this._beautyRenderTarget.texture.type = HalfFloatType;
this._beautyRenderTarget.depthTexture = new DepthTexture();
this._normalRenderTarget = new WebGLRenderTarget();
this._normalRenderTarget.texture.minFilter = NearestFilter;
this._normalRenderTarget.texture.magFilter = NearestFilter;
this._normalRenderTarget.texture.type = HalfFloatType;
this._fsQuad = new FullScreenQuad( this.pixelatedMaterial );
}
/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {
this.beautyRenderTarget.dispose();
this.normalRenderTarget.dispose();
this._beautyRenderTarget.dispose();
this._normalRenderTarget.dispose();
this.pixelatedMaterial.dispose();
this.normalMaterial.dispose();
this._normalMaterial.dispose();
this.fsQuad.dispose();
this._fsQuad.dispose();
}
/**
* Sets the size of the pass.
*
* @param {number} width - The width to set.
* @param {number} height - The width to set.
*/
setSize( width, height ) {
this.resolution.set( width, height );
this.renderResolution.set( ( width / this.pixelSize ) | 0, ( height / this.pixelSize ) | 0 );
const { x, y } = this.renderResolution;
this.beautyRenderTarget.setSize( x, y );
this.normalRenderTarget.setSize( x, y );
this.fsQuad.material.uniforms.resolution.value.set( x, y, 1 / x, 1 / y );
this._resolution.set( width, height );
this._renderResolution.set( ( width / this.pixelSize ) | 0, ( height / this.pixelSize ) | 0 );
const { x, y } = this._renderResolution;
this._beautyRenderTarget.setSize( x, y );
this._normalRenderTarget.setSize( x, y );
this._fsQuad.material.uniforms.resolution.value.set( x, y, 1 / x, 1 / y );
}
/**
* Sets the effect's pixel size.
*
* @param {number} pixelSize - The pixel size to set.
*/
setPixelSize( pixelSize ) {
this.pixelSize = pixelSize;
this.setSize( this.resolution.x, this.resolution.y );
this.setSize( this._resolution.x, this._resolution.y );
}
render( renderer, writeBuffer ) {
/**
* Performs the pixelation pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer/*, readBuffer , deltaTime, maskActive */ ) {
const uniforms = this.fsQuad.material.uniforms;
const uniforms = this._fsQuad.material.uniforms;
uniforms.normalEdgeStrength.value = this.normalEdgeStrength;
uniforms.depthEdgeStrength.value = this.depthEdgeStrength;
renderer.setRenderTarget( this.beautyRenderTarget );
renderer.setRenderTarget( this._beautyRenderTarget );
renderer.render( this.scene, this.camera );
const overrideMaterial_old = this.scene.overrideMaterial;
renderer.setRenderTarget( this.normalRenderTarget );
this.scene.overrideMaterial = this.normalMaterial;
renderer.setRenderTarget( this._normalRenderTarget );
this.scene.overrideMaterial = this._normalMaterial;
renderer.render( this.scene, this.camera );
this.scene.overrideMaterial = overrideMaterial_old;
uniforms.tDiffuse.value = this.beautyRenderTarget.texture;
uniforms.tDepth.value = this.beautyRenderTarget.depthTexture;
uniforms.tNormal.value = this.normalRenderTarget.texture;
uniforms.tDiffuse.value = this._beautyRenderTarget.texture;
uniforms.tDepth.value = this._beautyRenderTarget.depthTexture;
uniforms.tNormal.value = this._normalRenderTarget.texture;

@@ -109,8 +192,10 @@ if ( this.renderToScreen ) {

this.fsQuad.render( renderer );
this._fsQuad.render( renderer );
}
createPixelatedMaterial() {
// internals
_createPixelatedMaterial() {
return new ShaderMaterial( {

@@ -121,10 +206,3 @@ uniforms: {

tNormal: { value: null },
resolution: {
value: new Vector4(
this.renderResolution.x,
this.renderResolution.y,
1 / this.renderResolution.x,
1 / this.renderResolution.y,
)
},
resolution: { value: new Vector4() },
normalEdgeStrength: { value: 0 },

@@ -131,0 +209,0 @@ depthEdgeStrength: { value: 0 }

@@ -8,4 +8,24 @@ import {

/**
* A special type of render pass for implementing transition effects.
* When active, the pass will transition from scene A to scene B.
*
* ```js
* const renderTransitionPass = new RenderTransitionPass( fxSceneA.scene, fxSceneA.camera, fxSceneB.scene, fxSceneB.camera );
* renderTransitionPass.setTexture( textures[ 0 ] );
* composer.addPass( renderTransitionPass );
* ```
*
* @augments Pass
*/
class RenderTransitionPass extends Pass {
/**
* Constructs a render transition pass.
*
* @param {Scene} sceneA - The first scene.
* @param {Camera} cameraA - The camera of the first scene.
* @param {Scene} sceneB - The second scene.
* @param {Camera} cameraB - The camera of the second scene.
*/
constructor( sceneA, cameraA, sceneB, cameraB ) {

@@ -15,17 +35,55 @@

this.material = this.createMaterial();
this.fsQuad = new FullScreenQuad( this.material );
/**
* The first scene.
*
* @type {Scene}
*/
this.sceneA = sceneA;
this.sceneA = sceneA;
/**
* The camera of the first scene.
*
* @type {Camera}
*/
this.cameraA = cameraA;
/**
* The second scene.
*
* @type {Scene}
*/
this.sceneB = sceneB;
/**
* The camera of the second scene.
*
* @type {Camera}
*/
this.cameraB = cameraB;
this.renderTargetA = new WebGLRenderTarget();
this.renderTargetA.texture.type = HalfFloatType;
this.renderTargetB = new WebGLRenderTarget();
this.renderTargetB.texture.type = HalfFloatType;
/**
* The pass material.
*
* @type {ShaderMaterial}
*/
this.material = this._createMaterial();
// internals
this._renderTargetA = new WebGLRenderTarget();
this._renderTargetA.texture.type = HalfFloatType;
this._renderTargetB = new WebGLRenderTarget();
this._renderTargetB.texture.type = HalfFloatType;
this._fsQuad = new FullScreenQuad( this.material );
}
/**
* Sets the transition factor. Must be in the range `[0,1]`.
* This value determines to what degree both scenes are mixed.
*
* @param {boolenumberan} value - The transition factor.
*/
setTransition( value ) {

@@ -37,2 +95,7 @@

/**
* Toggles the usage of a texture for the effect.
*
* @param {boolean} value - Whether to use a texture for the transition effect or not.
*/
useTexture( value ) {

@@ -44,2 +107,7 @@

/**
* Sets the effect texture.
*
* @param {Texture} value - The effect texture.
*/
setTexture( value ) {

@@ -51,2 +119,8 @@

/**
* Sets the texture threshold. This value defined how strong the texture effects
* the transition. Must be in the range `[0,1]` (0 means full effect, 1 means no effect).
*
* @param {boolenumberan} value - The threshold value.
*/
setTextureThreshold( value ) {

@@ -58,19 +132,36 @@

/**
* Sets the size of the pass.
*
* @param {number} width - The width to set.
* @param {number} height - The width to set.
*/
setSize( width, height ) {
this.renderTargetA.setSize( width, height );
this.renderTargetB.setSize( width, height );
this._renderTargetA.setSize( width, height );
this._renderTargetB.setSize( width, height );
}
render( renderer, writeBuffer ) {
/**
* Performs the transition pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer/*, readBuffer , deltaTime, maskActive */ ) {
renderer.setRenderTarget( this.renderTargetA );
renderer.setRenderTarget( this._renderTargetA );
renderer.render( this.sceneA, this.cameraA );
renderer.setRenderTarget( this.renderTargetB );
renderer.setRenderTarget( this._renderTargetB );
renderer.render( this.sceneB, this.cameraB );
const uniforms = this.fsQuad.material.uniforms;
uniforms.tDiffuse1.value = this.renderTargetA.texture;
uniforms.tDiffuse2.value = this.renderTargetB.texture;
const uniforms = this._fsQuad.material.uniforms;
uniforms.tDiffuse1.value = this._renderTargetA.texture;
uniforms.tDiffuse2.value = this._renderTargetB.texture;

@@ -89,17 +180,24 @@ if ( this.renderToScreen ) {

this.fsQuad.render( renderer );
this._fsQuad.render( renderer );
}
/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {
this.renderTargetA.dispose();
this.renderTargetB.dispose();
this.material.dispose();
this.fsQuad.dispose();
this._renderTargetA.dispose();
this._renderTargetB.dispose();
this._fsQuad.dispose();
}
createMaterial() {
// internals
_createMaterial() {
return new ShaderMaterial( {

@@ -106,0 +204,0 @@ uniforms: {

@@ -26,7 +26,22 @@ import {

/**
* SAO implementation inspired from bhouston previous SAO work
* A SAO implementation inspired from @bhouston previous SAO work.
*
* `SAOPass` provides better quality than {@link SSAOPass} but is also more expensive.
*
* ```js
* const saoPass = new SAOPass( scene, camera );
* composer.addPass( saoPass );
* ```
*
* @augments Pass
*/
class SAOPass extends Pass {
/**
* Constructs a new SAO pass.
*
* @param {Scene} scene - The scene to compute the AO for.
* @param {Camera} camera - The camera.
* @param {Vector2} [resolution] - The effect's resolution.
*/
constructor( scene, camera, resolution = new Vector2( 256, 256 ) ) {

@@ -36,12 +51,41 @@

/**
* The scene to render the AO for.
*
* @type {Scene}
*/
this.scene = scene;
/**
* The camera.
*
* @type {Camera}
*/
this.camera = camera;
/**
* Overwritten to perform a clear operation by default.
*
* @type {boolean}
* @default true
*/
this.clear = true;
/**
* Overwritten to disable the swap.
*
* @type {boolean}
* @default false
*/
this.needsSwap = false;
this.originalClearColor = new Color();
this._originalClearColor = new Color();
this._oldClearColor = new Color();
this.oldClearAlpha = 1;
this._oldClearAlpha = 1;
/**
* The SAO paramter.
*
* @type {Object}
*/
this.params = {

@@ -60,2 +104,8 @@ output: 0,

/**
* The effect's resolution.
*
* @type {Vector2}
* @default (256,256)
*/
this.resolution = new Vector2( resolution.x, resolution.y );

@@ -141,2 +191,13 @@

/**
* Performs the SAO pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive*/ ) {

@@ -150,3 +211,3 @@

this.materialCopy.needsUpdate = true;
this.renderPass( renderer, this.materialCopy, null );
this._renderPass( renderer, this.materialCopy, null );

@@ -156,3 +217,3 @@ }

renderer.getClearColor( this._oldClearColor );
this.oldClearAlpha = renderer.getClearAlpha();
this._oldClearAlpha = renderer.getClearAlpha();
const oldAutoClear = renderer.autoClear;

@@ -190,6 +251,6 @@ renderer.autoClear = false;

// render normal and depth
this.renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0x7777ff, 1.0 );
this._renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0x7777ff, 1.0 );
// Rendering SAO texture
this.renderPass( renderer, this.saoMaterial, this.saoRenderTarget, 0xffffff, 1.0 );
this._renderPass( renderer, this.saoMaterial, this.saoRenderTarget, 0xffffff, 1.0 );

@@ -199,4 +260,4 @@ // Blurring SAO texture

this.renderPass( renderer, this.vBlurMaterial, this.blurIntermediateRenderTarget, 0xffffff, 1.0 );
this.renderPass( renderer, this.hBlurMaterial, this.saoRenderTarget, 0xffffff, 1.0 );
this._renderPass( renderer, this.vBlurMaterial, this.blurIntermediateRenderTarget, 0xffffff, 1.0 );
this._renderPass( renderer, this.hBlurMaterial, this.saoRenderTarget, 0xffffff, 1.0 );

@@ -232,5 +293,5 @@ }

// Rendering SAOPass result on top of previous pass
this.renderPass( renderer, outputMaterial, this.renderToScreen ? null : readBuffer );
this._renderPass( renderer, outputMaterial, this.renderToScreen ? null : readBuffer );
renderer.setClearColor( this._oldClearColor, this.oldClearAlpha );
renderer.setClearColor( this._oldClearColor, this._oldClearAlpha );
renderer.autoClear = oldAutoClear;

@@ -240,6 +301,53 @@

renderPass( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) {
/**
* Sets the size of the pass.
*
* @param {number} width - The width to set.
* @param {number} height - The width to set.
*/
setSize( width, height ) {
this.saoRenderTarget.setSize( width, height );
this.blurIntermediateRenderTarget.setSize( width, height );
this.normalRenderTarget.setSize( width, height );
this.saoMaterial.uniforms[ 'size' ].value.set( width, height );
this.saoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse );
this.saoMaterial.uniforms[ 'cameraProjectionMatrix' ].value = this.camera.projectionMatrix;
this.saoMaterial.needsUpdate = true;
this.vBlurMaterial.uniforms[ 'size' ].value.set( width, height );
this.vBlurMaterial.needsUpdate = true;
this.hBlurMaterial.uniforms[ 'size' ].value.set( width, height );
this.hBlurMaterial.needsUpdate = true;
}
/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {
this.saoRenderTarget.dispose();
this.blurIntermediateRenderTarget.dispose();
this.normalRenderTarget.dispose();
this.normalMaterial.dispose();
this.saoMaterial.dispose();
this.vBlurMaterial.dispose();
this.hBlurMaterial.dispose();
this.materialCopy.dispose();
this.fsQuad.dispose();
}
// internal
_renderPass( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) {
// save original state
renderer.getClearColor( this.originalClearColor );
renderer.getClearColor( this._originalClearColor );
const originalClearAlpha = renderer.getClearAlpha();

@@ -265,3 +373,3 @@ const originalAutoClear = renderer.autoClear;

renderer.autoClear = originalAutoClear;
renderer.setClearColor( this.originalClearColor );
renderer.setClearColor( this._originalClearColor );
renderer.setClearAlpha( originalClearAlpha );

@@ -271,5 +379,5 @@

renderOverride( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {
_renderOverride( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {
renderer.getClearColor( this.originalClearColor );
renderer.getClearColor( this._originalClearColor );
const originalClearAlpha = renderer.getClearAlpha();

@@ -297,3 +405,3 @@ const originalAutoClear = renderer.autoClear;

renderer.autoClear = originalAutoClear;
renderer.setClearColor( this.originalClearColor );
renderer.setClearColor( this._originalClearColor );
renderer.setClearAlpha( originalClearAlpha );

@@ -303,37 +411,2 @@

setSize( width, height ) {
this.saoRenderTarget.setSize( width, height );
this.blurIntermediateRenderTarget.setSize( width, height );
this.normalRenderTarget.setSize( width, height );
this.saoMaterial.uniforms[ 'size' ].value.set( width, height );
this.saoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse );
this.saoMaterial.uniforms[ 'cameraProjectionMatrix' ].value = this.camera.projectionMatrix;
this.saoMaterial.needsUpdate = true;
this.vBlurMaterial.uniforms[ 'size' ].value.set( width, height );
this.vBlurMaterial.needsUpdate = true;
this.hBlurMaterial.uniforms[ 'size' ].value.set( width, height );
this.hBlurMaterial.needsUpdate = true;
}
dispose() {
this.saoRenderTarget.dispose();
this.blurIntermediateRenderTarget.dispose();
this.normalRenderTarget.dispose();
this.normalMaterial.dispose();
this.saoMaterial.dispose();
this.vBlurMaterial.dispose();
this.hBlurMaterial.dispose();
this.materialCopy.dispose();
this.fsQuad.dispose();
}
}

@@ -340,0 +413,0 @@

@@ -11,4 +11,20 @@ import {

/**
* A pass that saves the contents of the current read buffer in a render target.
*
* ```js
* const savePass = new SavePass( customRenderTarget );
* composer.addPass( savePass );
* ```
*
* @augments Pass
*/
class SavePass extends Pass {
/**
* Constructs a new save pass.
*
* @param {WebGLRenderTarget} [renderTarget] - The render target for saving the read buffer.
* If not provided, the pass automatically creates a render target.
*/
constructor( renderTarget ) {

@@ -18,13 +34,19 @@

const shader = CopyShader;
/**
* The pass uniforms.
*
* @type {Object}
*/
this.uniforms = UniformsUtils.clone( CopyShader.uniforms );
this.textureID = 'tDiffuse';
this.uniforms = UniformsUtils.clone( shader.uniforms );
/**
* The pass material.
*
* @type {ShaderMaterial}
*/
this.material = new ShaderMaterial( {
uniforms: this.uniforms,
vertexShader: shader.vertexShader,
fragmentShader: shader.fragmentShader,
vertexShader: CopyShader.vertexShader,
fragmentShader: CopyShader.fragmentShader,
blending: NoBlending

@@ -34,2 +56,7 @@

/**
* The render target which is used to save the read buffer.
*
* @type {WebGLRenderTarget}
*/
this.renderTarget = renderTarget;

@@ -44,22 +71,43 @@

/**
* Overwritten to disable the swap.
*
* @type {boolean}
* @default false
*/
this.needsSwap = false;
this.fsQuad = new FullScreenQuad( this.material );
// internals
this._fsQuad = new FullScreenQuad( this.material );
}
/**
* Performs the save pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive */ ) {
if ( this.uniforms[ this.textureID ] ) {
this.uniforms[ 'tDiffuse' ].value = readBuffer.texture;
this.uniforms[ this.textureID ].value = readBuffer.texture;
}
renderer.setRenderTarget( this.renderTarget );
if ( this.clear ) renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );
}
/**
* Sets the size of the pass.
*
* @param {number} width - The width to set.
* @param {number} height - The width to set.
*/
setSize( width, height ) {

@@ -71,2 +119,6 @@

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {

@@ -78,3 +130,3 @@

this.fsQuad.dispose();
this._fsQuad.dispose();

@@ -81,0 +133,0 @@ }

@@ -7,10 +7,50 @@ import {

/**
* This pass can be used to create a post processing effect
* with a raw GLSL shader object. Useful for implementing custom
* effects.
*
* ```js
* const fxaaPass = new ShaderPass( FXAAShader );
* composer.addPass( fxaaPass );
* ```
*
* @augments Pass
*/
class ShaderPass extends Pass {
constructor( shader, textureID ) {
/**
* Constructs a new shader pass.
*
* @param {Object|ShaderMaterial} [shader] - A shader object holding vertex and fragment shader as well as
* defines and uniforms. It's also valid to pass a custom shader material.
* @param {string} [textureID='tDiffuse'] - The name of the texture uniform that should sample
* the read buffer.
*/
constructor( shader, textureID = 'tDiffuse' ) {
super();
this.textureID = ( textureID !== undefined ) ? textureID : 'tDiffuse';
/**
* The name of the texture uniform that should sample the read buffer.
*
* @type {string}
* @default 'tDiffuse'
*/
this.textureID = textureID;
/**
* The pass uniforms.
*
* @type {?Object}
*/
this.uniforms = null;
/**
* The pass material.
*
* @type {?ShaderMaterial}
*/
this.material = null;
if ( shader instanceof ShaderMaterial ) {

@@ -38,6 +78,19 @@

this.fsQuad = new FullScreenQuad( this.material );
// internals
this._fsQuad = new FullScreenQuad( this.material );
}
/**
* Performs the shader pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) {

@@ -51,3 +104,3 @@

this.fsQuad.material = this.material;
this._fsQuad.material = this.material;

@@ -57,3 +110,3 @@ if ( this.renderToScreen ) {

renderer.setRenderTarget( null );
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -65,3 +118,3 @@ } else {

if ( this.clear ) renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -72,2 +125,6 @@ }

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {

@@ -77,3 +134,3 @@

this.fsQuad.dispose();
this._fsQuad.dispose();

@@ -80,0 +137,0 @@ }

@@ -13,5 +13,19 @@ import {

/**
* A pass for applying SMAA. Unlike {@link FXAAPass}, `SMAAPass` operates in
* `linar-srgb` so this pass must be executed before {@link OutputPass}.
*
* ```js
* const smaaPass = new SMAAPass();
* composer.addPass( smaaPass );
* ```
*
* @augments Pass
*/
class SMAAPass extends Pass {
constructor( width, height ) {
/**
* Constructs a new SMAA pass.
*/
constructor( ) {

@@ -22,13 +36,13 @@ super();

this.edgesRT = new WebGLRenderTarget( width, height, {
this._edgesRT = new WebGLRenderTarget( 1, 1, {
depthBuffer: false,
type: HalfFloatType
} );
this.edgesRT.texture.name = 'SMAAPass.edges';
this._edgesRT.texture.name = 'SMAAPass.edges';
this.weightsRT = new WebGLRenderTarget( width, height, {
this._weightsRT = new WebGLRenderTarget( 1, 1, {
depthBuffer: false,
type: HalfFloatType
} );
this.weightsRT.texture.name = 'SMAAPass.weights';
this._weightsRT.texture.name = 'SMAAPass.weights';

@@ -39,43 +53,41 @@ // textures

const areaTextureImage = new Image();
areaTextureImage.src = this.getAreaTexture();
areaTextureImage.src = this._getAreaTexture();
areaTextureImage.onload = function () {
// assigning data to HTMLImageElement.src is asynchronous (see #15162)
scope.areaTexture.needsUpdate = true;
scope._areaTexture.needsUpdate = true;
};
this.areaTexture = new Texture();
this.areaTexture.name = 'SMAAPass.area';
this.areaTexture.image = areaTextureImage;
this.areaTexture.minFilter = LinearFilter;
this.areaTexture.generateMipmaps = false;
this.areaTexture.flipY = false;
this._areaTexture = new Texture();
this._areaTexture.name = 'SMAAPass.area';
this._areaTexture.image = areaTextureImage;
this._areaTexture.minFilter = LinearFilter;
this._areaTexture.generateMipmaps = false;
this._areaTexture.flipY = false;
const searchTextureImage = new Image();
searchTextureImage.src = this.getSearchTexture();
searchTextureImage.src = this._getSearchTexture();
searchTextureImage.onload = function () {
// assigning data to HTMLImageElement.src is asynchronous (see #15162)
scope.searchTexture.needsUpdate = true;
scope._searchTexture.needsUpdate = true;
};
this.searchTexture = new Texture();
this.searchTexture.name = 'SMAAPass.search';
this.searchTexture.image = searchTextureImage;
this.searchTexture.magFilter = NearestFilter;
this.searchTexture.minFilter = NearestFilter;
this.searchTexture.generateMipmaps = false;
this.searchTexture.flipY = false;
this._searchTexture = new Texture();
this._searchTexture.name = 'SMAAPass.search';
this._searchTexture.image = searchTextureImage;
this._searchTexture.magFilter = NearestFilter;
this._searchTexture.minFilter = NearestFilter;
this._searchTexture.generateMipmaps = false;
this._searchTexture.flipY = false;
// materials - pass 1
this.uniformsEdges = UniformsUtils.clone( SMAAEdgesShader.uniforms );
this._uniformsEdges = UniformsUtils.clone( SMAAEdgesShader.uniforms );
this.uniformsEdges[ 'resolution' ].value.set( 1 / width, 1 / height );
this.materialEdges = new ShaderMaterial( {
this._materialEdges = new ShaderMaterial( {
defines: Object.assign( {}, SMAAEdgesShader.defines ),
uniforms: this.uniformsEdges,
uniforms: this._uniformsEdges,
vertexShader: SMAAEdgesShader.vertexShader,

@@ -87,12 +99,11 @@ fragmentShader: SMAAEdgesShader.fragmentShader

this.uniformsWeights = UniformsUtils.clone( SMAAWeightsShader.uniforms );
this._uniformsWeights = UniformsUtils.clone( SMAAWeightsShader.uniforms );
this.uniformsWeights[ 'resolution' ].value.set( 1 / width, 1 / height );
this.uniformsWeights[ 'tDiffuse' ].value = this.edgesRT.texture;
this.uniformsWeights[ 'tArea' ].value = this.areaTexture;
this.uniformsWeights[ 'tSearch' ].value = this.searchTexture;
this._uniformsWeights[ 'tDiffuse' ].value = this._edgesRT.texture;
this._uniformsWeights[ 'tArea' ].value = this._areaTexture;
this._uniformsWeights[ 'tSearch' ].value = this._searchTexture;
this.materialWeights = new ShaderMaterial( {
this._materialWeights = new ShaderMaterial( {
defines: Object.assign( {}, SMAAWeightsShader.defines ),
uniforms: this.uniformsWeights,
uniforms: this._uniformsWeights,
vertexShader: SMAAWeightsShader.vertexShader,

@@ -104,9 +115,7 @@ fragmentShader: SMAAWeightsShader.fragmentShader

this.uniformsBlend = UniformsUtils.clone( SMAABlendShader.uniforms );
this._uniformsBlend = UniformsUtils.clone( SMAABlendShader.uniforms );
this._uniformsBlend[ 'tDiffuse' ].value = this._weightsRT.texture;
this.uniformsBlend[ 'resolution' ].value.set( 1 / width, 1 / height );
this.uniformsBlend[ 'tDiffuse' ].value = this.weightsRT.texture;
this.materialBlend = new ShaderMaterial( {
uniforms: this.uniformsBlend,
this._materialBlend = new ShaderMaterial( {
uniforms: this._uniformsBlend,
vertexShader: SMAABlendShader.vertexShader,

@@ -116,6 +125,17 @@ fragmentShader: SMAABlendShader.fragmentShader

this.fsQuad = new FullScreenQuad( null );
this._fsQuad = new FullScreenQuad( null );
}
/**
* Performs the SMAA pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive*/ ) {

@@ -125,23 +145,23 @@

this.uniformsEdges[ 'tDiffuse' ].value = readBuffer.texture;
this._uniformsEdges[ 'tDiffuse' ].value = readBuffer.texture;
this.fsQuad.material = this.materialEdges;
this._fsQuad.material = this._materialEdges;
renderer.setRenderTarget( this.edgesRT );
renderer.setRenderTarget( this._edgesRT );
if ( this.clear ) renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );
// pass 2
this.fsQuad.material = this.materialWeights;
this._fsQuad.material = this._materialWeights;
renderer.setRenderTarget( this.weightsRT );
renderer.setRenderTarget( this._weightsRT );
if ( this.clear ) renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );
// pass 3
this.uniformsBlend[ 'tColor' ].value = readBuffer.texture;
this._uniformsBlend[ 'tColor' ].value = readBuffer.texture;
this.fsQuad.material = this.materialBlend;
this._fsQuad.material = this._materialBlend;

@@ -151,3 +171,3 @@ if ( this.renderToScreen ) {

renderer.setRenderTarget( null );
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -158,3 +178,3 @@ } else {

if ( this.clear ) renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -165,39 +185,51 @@ }

/**
* Sets the size of the pass.
*
* @param {number} width - The width to set.
* @param {number} height - The width to set.
*/
setSize( width, height ) {
this.edgesRT.setSize( width, height );
this.weightsRT.setSize( width, height );
this._edgesRT.setSize( width, height );
this._weightsRT.setSize( width, height );
this.materialEdges.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height );
this.materialWeights.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height );
this.materialBlend.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height );
this._materialEdges.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height );
this._materialWeights.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height );
this._materialBlend.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height );
}
getAreaTexture() {
/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {
return 'data:image/png;base64,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';
this._edgesRT.dispose();
this._weightsRT.dispose();
}
this._areaTexture.dispose();
this._searchTexture.dispose();
getSearchTexture() {
this._materialEdges.dispose();
this._materialWeights.dispose();
this._materialBlend.dispose();
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEIAAAAhCAAAAABIXyLAAAAAOElEQVRIx2NgGAWjYBSMglEwEICREYRgFBZBqDCSLA2MGPUIVQETE9iNUAqLR5gIeoQKRgwXjwAAGn4AtaFeYLEAAAAASUVORK5CYII=';
this._fsQuad.dispose();
}
dispose() {
// internals
this.edgesRT.dispose();
this.weightsRT.dispose();
_getAreaTexture() {
this.areaTexture.dispose();
this.searchTexture.dispose();
return 'data:image/png;base64,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';
this.materialEdges.dispose();
this.materialWeights.dispose();
this.materialBlend.dispose();
}
this.fsQuad.dispose();
_getSearchTexture() {
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEIAAAAhCAAAAABIXyLAAAAAOElEQVRIx2NgGAWjYBSMglEwEICREYRgFBZBqDCSLA2MGPUIVQETE9iNUAqLR5gIeoQKRgwXjwAAGn4AtaFeYLEAAAAASUVORK5CYII=';
}

@@ -204,0 +236,0 @@

@@ -13,37 +13,98 @@ import {

/**
*
* Supersample Anti-Aliasing Render Pass
*
* This manual approach to SSAA re-renders the scene ones for each sample with camera jitter and accumulates the results.
*
* References: https://en.wikipedia.org/wiki/Supersampling
*
*/
* Supersample Anti-Aliasing Render Pass.
*
* This manual approach to SSAA re-renders the scene ones for each sample with camera jitter and accumulates the results.
*
* ```js
* const ssaaRenderPass = new SSAARenderPass( scene, camera );
* ssaaRenderPass.sampleLevel = 3;
* composer.addPass( ssaaRenderPass );
* ```
*
* @augments Pass
*/
class SSAARenderPass extends Pass {
constructor( scene, camera, clearColor, clearAlpha ) {
/**
* Constructs a new SSAA render pass.
*
* @param {Scene} scene - The scene to render.
* @param {Camera} camera - The camera.
* @param {?(number|Color|string)} [clearColor=0x000000] - The clear color of the render pass.
* @param {?number} [clearAlpha=0] - The clear alpha of the render pass.
*/
constructor( scene, camera, clearColor = 0x000000, clearAlpha = 0 ) {
super();
/**
* The scene to render.
*
* @type {Scene}
*/
this.scene = scene;
/**
* The camera.
*
* @type {Camera}
*/
this.camera = camera;
this.sampleLevel = 4; // specified as n, where the number of samples is 2^n, so sampleLevel = 4, is 2^4 samples, 16.
/**
* The sample level. Specified as n, where the number of
* samples is 2^n, so sampleLevel = 4, is 2^4 samples, 16.
*
* @type {number}
* @default 4
*/
this.sampleLevel = 4;
/**
* Whether the pass should be unbiased or not. This property has the most
* visible effect when rendering to a RGBA8 buffer because it mitigates
* rounding errors. By default RGBA16F is used.
*
* @type {boolean}
* @default true
*/
this.unbiased = true;
/**
* Whether to use a stencil buffer or not. This property can't
* be changed after the first render.
*
* @type {boolean}
* @default false
*/
this.stencilBuffer = false;
// as we need to clear the buffer in this pass, clearColor must be set to something, defaults to black.
this.clearColor = ( clearColor !== undefined ) ? clearColor : 0x000000;
this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 0;
/**
* The clear color of the render pass.
*
* @type {?(number|Color|string)}
* @default 0x000000
*/
this.clearColor = clearColor;
/**
* The clear alpha of the render pass.
*
* @type {?number}
* @default 0
*/
this.clearAlpha = clearAlpha;
// internals
this._sampleRenderTarget = null;
this._oldClearColor = new Color();
const copyShader = CopyShader;
this.copyUniforms = UniformsUtils.clone( copyShader.uniforms );
this._copyUniforms = UniformsUtils.clone( CopyShader.uniforms );
this.copyMaterial = new ShaderMaterial( {
uniforms: this.copyUniforms,
vertexShader: copyShader.vertexShader,
fragmentShader: copyShader.fragmentShader,
this._copyMaterial = new ShaderMaterial( {
uniforms: this._copyUniforms,
vertexShader: CopyShader.vertexShader,
fragmentShader: CopyShader.fragmentShader,
transparent: true,

@@ -56,33 +117,54 @@ depthTest: false,

this.fsQuad = new FullScreenQuad( this.copyMaterial );
this._fsQuad = new FullScreenQuad( this._copyMaterial );
}
/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {
if ( this.sampleRenderTarget ) {
if ( this._sampleRenderTarget ) {
this.sampleRenderTarget.dispose();
this.sampleRenderTarget = null;
this._sampleRenderTarget.dispose();
this._sampleRenderTarget = null;
}
this.copyMaterial.dispose();
this._copyMaterial.dispose();
this.fsQuad.dispose();
this._fsQuad.dispose();
}
/**
* Sets the size of the pass.
*
* @param {number} width - The width to set.
* @param {number} height - The width to set.
*/
setSize( width, height ) {
if ( this.sampleRenderTarget ) this.sampleRenderTarget.setSize( width, height );
if ( this._sampleRenderTarget ) this._sampleRenderTarget.setSize( width, height );
}
render( renderer, writeBuffer, readBuffer ) {
/**
* Performs the SSAA render pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer/*, deltaTime, maskActive */ ) {
if ( ! this.sampleRenderTarget ) {
if ( ! this._sampleRenderTarget ) {
this.sampleRenderTarget = new WebGLRenderTarget( readBuffer.width, readBuffer.height, { type: HalfFloatType, stencilBuffer: this.stencilBuffer } );
this.sampleRenderTarget.texture.name = 'SSAARenderPass.sample';
this._sampleRenderTarget = new WebGLRenderTarget( readBuffer.width, readBuffer.height, { type: HalfFloatType, stencilBuffer: this.stencilBuffer } );
this._sampleRenderTarget.texture.name = 'SSAARenderPass.sample';

@@ -101,3 +183,3 @@ }

const roundingRange = 1 / 32;
this.copyUniforms[ 'tDiffuse' ].value = this.sampleRenderTarget.texture;
this._copyUniforms[ 'tDiffuse' ].value = this._sampleRenderTarget.texture;

@@ -151,5 +233,5 @@ const viewOffset = {

this.copyUniforms[ 'opacity' ].value = sampleWeight;
this._copyUniforms[ 'opacity' ].value = sampleWeight;
renderer.setClearColor( this.clearColor, this.clearAlpha );
renderer.setRenderTarget( this.sampleRenderTarget );
renderer.setRenderTarget( this._sampleRenderTarget );
renderer.clear();

@@ -167,3 +249,3 @@ renderer.render( this.scene, this.camera );

this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -170,0 +252,0 @@ }

@@ -30,23 +30,111 @@ import {

/**
* A pass for a basic SSAO effect.
*
* {@link SAOPass} and {@link GTAPass} produce a more advanced AO but are also
* more expensive.
*
* ```js
* const ssaoPass = new SSAOPass( scene, camera, width, height );
* composer.addPass( ssaoPass );
* ```
*
* @augments Pass
*/
class SSAOPass extends Pass {
constructor( scene, camera, width, height, kernelSize = 32 ) {
/**
* Constructs a new SSAO pass.
*
* @param {Scene} scene - The scene to compute the AO for.
* @param {Camera} camera - The camera.
* @param {number} [width=512] - The width of the effect.
* @param {number} [height=512] - The height of the effect.
* @param {number} [kernelSize=32] - The kernel size.
*/
constructor( scene, camera, width = 512, height = 512, kernelSize = 32 ) {
super();
this.width = ( width !== undefined ) ? width : 512;
this.height = ( height !== undefined ) ? height : 512;
/**
* The width of the effect.
*
* @type {number}
* @default 512
*/
this.width = width;
/**
* The height of the effect.
*
* @type {number}
* @default 512
*/
this.height = height;
/**
* Overwritten to perform a clear operation by default.
*
* @type {boolean}
* @default true
*/
this.clear = true;
/**
* Overwritten to disable the swap.
*
* @type {boolean}
* @default false
*/
this.needsSwap = false;
/**
* The camera.
*
* @type {Camera}
*/
this.camera = camera;
/**
* The scene to render the AO for.
*
* @type {Scene}
*/
this.scene = scene;
/**
* The kernel radius controls how wide the
* AO spreads.
*
* @type {number}
* @default 8
*/
this.kernelRadius = 8;
this.kernel = [];
this.noiseTexture = null;
/**
* The output configuration.
*
* @type {number}
* @default 0
*/
this.output = 0;
/**
* Defines the minimum distance that should be
* affected by the AO.
*
* @type {number}
* @default 0.005
*/
this.minDistance = 0.005;
/**
* Defines the maximum distance that should be
* affected by the AO.
*
* @type {number}
* @default 0.1
*/
this.maxDistance = 0.1;

@@ -58,4 +146,4 @@

this.generateSampleKernel( kernelSize );
this.generateRandomKernelRotations();
this._generateSampleKernel( kernelSize );
this._generateRandomKernelRotations();

@@ -151,8 +239,14 @@ // depth texture

this.fsQuad = new FullScreenQuad( null );
// internals
this.originalClearColor = new Color();
this._fsQuad = new FullScreenQuad( null );
this._originalClearColor = new Color();
}
/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {

@@ -175,6 +269,17 @@

this.fsQuad.dispose();
this._fsQuad.dispose();
}
/**
* Performs the SSAO pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) {

@@ -184,5 +289,5 @@

this.overrideVisibility();
this.renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0x7777ff, 1.0 );
this.restoreVisibility();
this._overrideVisibility();
this._renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0x7777ff, 1.0 );
this._restoreVisibility();

@@ -194,7 +299,7 @@ // render SSAO

this.ssaoMaterial.uniforms[ 'maxDistance' ].value = this.maxDistance;
this.renderPass( renderer, this.ssaoMaterial, this.ssaoRenderTarget );
this._renderPass( renderer, this.ssaoMaterial, this.ssaoRenderTarget );
// render blur
this.renderPass( renderer, this.blurMaterial, this.blurRenderTarget );
this._renderPass( renderer, this.blurMaterial, this.blurRenderTarget );

@@ -209,3 +314,3 @@ // output result to screen

this.copyMaterial.blending = NoBlending;
this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : readBuffer );
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : readBuffer );

@@ -218,3 +323,3 @@ break;

this.copyMaterial.blending = NoBlending;
this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : readBuffer );
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : readBuffer );

@@ -225,3 +330,3 @@ break;

this.renderPass( renderer, this.depthRenderMaterial, this.renderToScreen ? null : readBuffer );
this._renderPass( renderer, this.depthRenderMaterial, this.renderToScreen ? null : readBuffer );

@@ -234,3 +339,3 @@ break;

this.copyMaterial.blending = NoBlending;
this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : readBuffer );
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : readBuffer );

@@ -243,3 +348,3 @@ break;

this.copyMaterial.blending = CustomBlending;
this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : readBuffer );
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : readBuffer );

@@ -255,6 +360,31 @@ break;

renderPass( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) {
/**
* Sets the size of the pass.
*
* @param {number} width - The width to set.
* @param {number} height - The width to set.
*/
setSize( width, height ) {
this.width = width;
this.height = height;
this.ssaoRenderTarget.setSize( width, height );
this.normalRenderTarget.setSize( width, height );
this.blurRenderTarget.setSize( width, height );
this.ssaoMaterial.uniforms[ 'resolution' ].value.set( width, height );
this.ssaoMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix );
this.ssaoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse );
this.blurMaterial.uniforms[ 'resolution' ].value.set( width, height );
}
// internals
_renderPass( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) {
// save original state
renderer.getClearColor( this.originalClearColor );
renderer.getClearColor( this._originalClearColor );
const originalClearAlpha = renderer.getClearAlpha();

@@ -275,8 +405,8 @@ const originalAutoClear = renderer.autoClear;

this.fsQuad.material = passMaterial;
this.fsQuad.render( renderer );
this._fsQuad.material = passMaterial;
this._fsQuad.render( renderer );
// restore original state
renderer.autoClear = originalAutoClear;
renderer.setClearColor( this.originalClearColor );
renderer.setClearColor( this._originalClearColor );
renderer.setClearAlpha( originalClearAlpha );

@@ -286,5 +416,5 @@

renderOverride( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {
_renderOverride( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {
renderer.getClearColor( this.originalClearColor );
renderer.getClearColor( this._originalClearColor );
const originalClearAlpha = renderer.getClearAlpha();

@@ -314,3 +444,3 @@ const originalAutoClear = renderer.autoClear;

renderer.autoClear = originalAutoClear;
renderer.setClearColor( this.originalClearColor );
renderer.setClearColor( this._originalClearColor );
renderer.setClearAlpha( originalClearAlpha );

@@ -320,21 +450,4 @@

setSize( width, height ) {
_generateSampleKernel( kernelSize ) {
this.width = width;
this.height = height;
this.ssaoRenderTarget.setSize( width, height );
this.normalRenderTarget.setSize( width, height );
this.blurRenderTarget.setSize( width, height );
this.ssaoMaterial.uniforms[ 'resolution' ].value.set( width, height );
this.ssaoMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix );
this.ssaoMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse );
this.blurMaterial.uniforms[ 'resolution' ].value.set( width, height );
}
generateSampleKernel( kernelSize ) {
const kernel = this.kernel;

@@ -361,3 +474,3 @@

generateRandomKernelRotations() {
_generateRandomKernelRotations() {

@@ -388,3 +501,3 @@ const width = 4, height = 4;

overrideVisibility() {
_overrideVisibility() {

@@ -404,3 +517,3 @@ const scene = this.scene;

restoreVisibility() {
_restoreVisibility() {

@@ -407,0 +520,0 @@ const scene = this.scene;

@@ -22,22 +22,113 @@ import {

/**
* A pass for a basic SSR effect.
*
* ```js
* const ssrPass = new SSRPass( {
* renderer,
* scene,
* camera,
* width: innerWidth,
* height: innerHeight
* } );
* composer.addPass( ssrPass );
* ```
*
* @augments Pass
*/
class SSRPass extends Pass {
constructor( { renderer, scene, camera, width, height, selects, bouncing = false, groundReflector } ) {
/**
* Constructs a new SSR pass.
*
* @param {SSRPass~Options} options - The pass options.
*/
constructor( { renderer, scene, camera, width = 512, height = 512, selects = null, bouncing = false, groundReflector = null } ) {
super();
this.width = ( width !== undefined ) ? width : 512;
this.height = ( height !== undefined ) ? height : 512;
/**
* The width of the effect.
*
* @type {number}
* @default 512
*/
this.width = width;
/**
* The height of the effect.
*
* @type {number}
* @default 512
*/
this.height = height;
/**
* Overwritten to perform a clear operation by default.
*
* @type {boolean}
* @default true
*/
this.clear = true;
/**
* The renderer.
*
* @type {WebGLRenderer}
*/
this.renderer = renderer;
/**
* The scene to render.
*
* @type {Scene}
*/
this.scene = scene;
/**
* The camera.
*
* @type {Camera}
*/
this.camera = camera;
/**
* The ground reflector.
*
* @type {?ReflectorForSSRPass}
* @default 0
*/
this.groundReflector = groundReflector;
/**
* The opactiy.
*
* @type {number}
* @default 0.5
*/
this.opacity = SSRShader.uniforms.opacity.value;
/**
* The output configuration.
*
* @type {number}
* @default 0
*/
this.output = 0;
/**
* Controls how far a fragment can reflect.
*
* @type {number}
* @default 180
*/
this.maxDistance = SSRShader.uniforms.maxDistance.value;
/**
* Controls the cutoff between what counts as a
* possible reflection hit and what does not.
*
* @type {number}
* @default .018
*/
this.thickness = SSRShader.uniforms.thickness.value;

@@ -48,3 +139,18 @@

this._selects = selects;
/**
* Whether the pass is selective or not.
*
* @type {boolean}
* @default false
*/
this.selective = Array.isArray( this._selects );
/**
* Which 3D objects should be affected by SSR. If not set, the entire scene is affected.
*
* @name SSRPass#selects
* @type {?Array<Object3D>}
* @default null
*/
Object.defineProperty( this, 'selects', {

@@ -78,2 +184,10 @@ get() {

this._bouncing = bouncing;
/**
* Whether bouncing is enabled or not.
*
* @name SSRPass#bouncing
* @type {boolean}
* @default false
*/
Object.defineProperty( this, 'bouncing', {

@@ -102,5 +216,19 @@ get() {

/**
* Whether to blur reflections or not.
*
* @type {boolean}
* @default true
*/
this.blur = true;
this._distanceAttenuation = SSRShader.defines.DISTANCE_ATTENUATION;
/**
* Whether to use distance attenutation or not.
*
* @name SSRPass#distanceAttenuation
* @type {boolean}
* @default true
*/
Object.defineProperty( this, 'distanceAttenuation', {

@@ -124,2 +252,10 @@ get() {

this._fresnel = SSRShader.defines.FRESNEL;
/**
* Whether to use fresnel or not.
*
* @name SSRPass#fresnel
* @type {boolean}
* @default true
*/
Object.defineProperty( this, 'fresnel', {

@@ -142,2 +278,10 @@ get() {

this._infiniteThick = SSRShader.defines.INFINITE_THICK;
/**
* Whether to use infinite thickness or not.
*
* @name SSRPass#infiniteThick
* @type {boolean}
* @default false
*/
Object.defineProperty( this, 'infiniteThick', {

@@ -321,2 +465,6 @@ get() {

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {

@@ -351,2 +499,13 @@

/**
* Performs the SSR pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer /*, readBuffer, deltaTime, maskActive */ ) {

@@ -371,3 +530,3 @@

this.renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0, 0 );
this._renderOverride( renderer, this.normalMaterial, this.normalRenderTarget, 0, 0 );

@@ -378,3 +537,3 @@ // render metalnesses

this.renderMetalness( renderer, this.metalnessOnMaterial, this.metalnessRenderTarget, 0, 0 );
this._renderMetalness( renderer, this.metalnessOnMaterial, this.metalnessRenderTarget, 0, 0 );

@@ -388,3 +547,3 @@ }

this.ssrMaterial.uniforms[ 'thickness' ].value = this.thickness;
this.renderPass( renderer, this.ssrMaterial, this.ssrRenderTarget );
this._renderPass( renderer, this.ssrMaterial, this.ssrRenderTarget );

@@ -396,5 +555,5 @@

this.renderPass( renderer, this.blurMaterial, this.blurRenderTarget );
this.renderPass( renderer, this.blurMaterial2, this.blurRenderTarget2 );
// this.renderPass(renderer, this.blurMaterial3, this.blurRenderTarget3);
this._renderPass( renderer, this.blurMaterial, this.blurRenderTarget );
this._renderPass( renderer, this.blurMaterial2, this.blurRenderTarget2 );
// this._renderPass(renderer, this.blurMaterial3, this.blurRenderTarget3);

@@ -413,3 +572,3 @@ }

this.copyMaterial.blending = NoBlending;
this.renderPass( renderer, this.copyMaterial, this.prevRenderTarget );
this._renderPass( renderer, this.copyMaterial, this.prevRenderTarget );

@@ -421,7 +580,7 @@ if ( this.blur )

this.copyMaterial.blending = NormalBlending;
this.renderPass( renderer, this.copyMaterial, this.prevRenderTarget );
this._renderPass( renderer, this.copyMaterial, this.prevRenderTarget );
this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.prevRenderTarget.texture;
this.copyMaterial.blending = NoBlending;
this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );

@@ -432,3 +591,3 @@ } else {

this.copyMaterial.blending = NoBlending;
this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );

@@ -440,3 +599,3 @@ if ( this.blur )

this.copyMaterial.blending = NormalBlending;
this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );

@@ -453,3 +612,3 @@ }

this.copyMaterial.blending = NoBlending;
this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );

@@ -463,7 +622,7 @@ if ( this.bouncing ) {

this.copyMaterial.blending = NoBlending;
this.renderPass( renderer, this.copyMaterial, this.prevRenderTarget );
this._renderPass( renderer, this.copyMaterial, this.prevRenderTarget );
this.copyMaterial.uniforms[ 'tDiffuse' ].value = this.ssrRenderTarget.texture;
this.copyMaterial.blending = NormalBlending;
this.renderPass( renderer, this.copyMaterial, this.prevRenderTarget );
this._renderPass( renderer, this.copyMaterial, this.prevRenderTarget );

@@ -478,3 +637,3 @@ }

this.copyMaterial.blending = NoBlending;
this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );

@@ -485,3 +644,3 @@ break;

this.renderPass( renderer, this.depthRenderMaterial, this.renderToScreen ? null : writeBuffer );
this._renderPass( renderer, this.depthRenderMaterial, this.renderToScreen ? null : writeBuffer );

@@ -494,3 +653,3 @@ break;

this.copyMaterial.blending = NoBlending;
this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );

@@ -503,3 +662,3 @@ break;

this.copyMaterial.blending = NoBlending;
this.renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );
this._renderPass( renderer, this.copyMaterial, this.renderToScreen ? null : writeBuffer );

@@ -515,4 +674,37 @@ break;

renderPass( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) {
/**
* Sets the size of the pass.
*
* @param {number} width - The width to set.
* @param {number} height - The width to set.
*/
setSize( width, height ) {
this.width = width;
this.height = height;
this.ssrMaterial.defines.MAX_STEP = Math.sqrt( width * width + height * height );
this.ssrMaterial.needsUpdate = true;
this.beautyRenderTarget.setSize( width, height );
this.prevRenderTarget.setSize( width, height );
this.ssrRenderTarget.setSize( width, height );
this.normalRenderTarget.setSize( width, height );
this.metalnessRenderTarget.setSize( width, height );
this.blurRenderTarget.setSize( width, height );
this.blurRenderTarget2.setSize( width, height );
// this.blurRenderTarget3.setSize(width, height);
this.ssrMaterial.uniforms[ 'resolution' ].value.set( width, height );
this.ssrMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix );
this.ssrMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse );
this.blurMaterial.uniforms[ 'resolution' ].value.set( width, height );
this.blurMaterial2.uniforms[ 'resolution' ].value.set( width, height );
}
// internals
_renderPass( renderer, passMaterial, renderTarget, clearColor, clearAlpha ) {
// save original state

@@ -545,3 +737,3 @@ this.originalClearColor.copy( renderer.getClearColor( this.tempColor ) );

renderOverride( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {
_renderOverride( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {

@@ -578,3 +770,3 @@ this.originalClearColor.copy( renderer.getClearColor( this.tempColor ) );

renderMetalness( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {
_renderMetalness( renderer, overrideMaterial, renderTarget, clearColor, clearAlpha ) {

@@ -634,29 +826,18 @@ this.originalClearColor.copy( renderer.getClearColor( this.tempColor ) );

setSize( width, height ) {
}
this.width = width;
this.height = height;
/**
* Constructor options of `SSRPass`.
*
* @typedef {Object} SSRPass~Options
* @property {WebGLRenderer} renderer - The renderer.
* @property {Scene} scene - The scene to render.
* @property {Camera} camera - The camera.
* @property {number} [width=512] - The width of the effect.
* @property {number} [height=512] - The width of the effect.
* @property {?Array<Object3D>} [selects=null] - Which 3D objects should be affected by SSR. If not set, the entire scene is affected.
* @property {boolean} [bouncing=false] - Whether bouncing is enabled or not.
* @property {?ReflectorForSSRPass} [groundReflector=null] - A ground reflector.
**/
this.ssrMaterial.defines.MAX_STEP = Math.sqrt( width * width + height * height );
this.ssrMaterial.needsUpdate = true;
this.beautyRenderTarget.setSize( width, height );
this.prevRenderTarget.setSize( width, height );
this.ssrRenderTarget.setSize( width, height );
this.normalRenderTarget.setSize( width, height );
this.metalnessRenderTarget.setSize( width, height );
this.blurRenderTarget.setSize( width, height );
this.blurRenderTarget2.setSize( width, height );
// this.blurRenderTarget3.setSize(width, height);
this.ssrMaterial.uniforms[ 'resolution' ].value.set( width, height );
this.ssrMaterial.uniforms[ 'cameraProjectionMatrix' ].value.copy( this.camera.projectionMatrix );
this.ssrMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.copy( this.camera.projectionMatrixInverse );
this.blurMaterial.uniforms[ 'resolution' ].value.set( width, height );
this.blurMaterial2.uniforms[ 'resolution' ].value.set( width, height );
}
}
SSRPass.OUTPUT = {

@@ -663,0 +844,0 @@ 'Default': 0,

@@ -9,14 +9,27 @@ import {

*
* Temporal Anti-Aliasing Render Pass
* Temporal Anti-Aliasing Render Pass.
*
* When there is no motion in the scene, the TAA render pass accumulates jittered camera samples across frames to create a high quality anti-aliased result.
* When there is no motion in the scene, the TAA render pass accumulates jittered camera
* samples across frames to create a high quality anti-aliased result.
*
* References:
* Note: This effect uses no reprojection so it is no TRAA implementation.
*
* TODO: Add support for motion vector pas so that accumulation of samples across frames can occur on dynamics scenes.
* ```js
* const taaRenderPass = new TAARenderPass( scene, camera );
* taaRenderPass.unbiased = false;
* composer.addPass( taaRenderPass );
* ```
*
* @augments SSAARenderPass
*/
class TAARenderPass extends SSAARenderPass {
/**
* Constructs a new TAA render pass.
*
* @param {Scene} scene - The scene to render.
* @param {Camera} camera - The camera.
* @param {?(number|Color|string)} [clearColor=0x000000] - The clear color of the render pass.
* @param {?number} [clearAlpha=0] - The clear alpha of the render pass.
*/
constructor( scene, camera, clearColor, clearAlpha ) {

@@ -26,9 +39,46 @@

/**
* Overwritten and set to 0 by default.
*
* @type {number}
* @default 0
*/
this.sampleLevel = 0;
/**
* Whether to accumulate frames or not. This enables
* the TAA.
*
* @type {boolean}
* @default false
*/
this.accumulate = false;
/**
* The accumulation index.
*
* @type {number}
* @default -1
*/
this.accumulateIndex = - 1;
// internals
this._sampleRenderTarget = null;
this._holdRenderTarget = null;
}
render( renderer, writeBuffer, readBuffer, deltaTime ) {
/**
* Performs the TAA render pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer, deltaTime/*, maskActive*/ ) {

@@ -46,13 +96,13 @@ if ( this.accumulate === false ) {

if ( this.sampleRenderTarget === undefined ) {
if ( this._sampleRenderTarget === null ) {
this.sampleRenderTarget = new WebGLRenderTarget( readBuffer.width, readBuffer.height, { type: HalfFloatType } );
this.sampleRenderTarget.texture.name = 'TAARenderPass.sample';
this._sampleRenderTarget = new WebGLRenderTarget( readBuffer.width, readBuffer.height, { type: HalfFloatType } );
this._sampleRenderTarget.texture.name = 'TAARenderPass.sample';
}
if ( this.holdRenderTarget === undefined ) {
if ( this._holdRenderTarget === null ) {
this.holdRenderTarget = new WebGLRenderTarget( readBuffer.width, readBuffer.height, { type: HalfFloatType } );
this.holdRenderTarget.texture.name = 'TAARenderPass.hold';
this._holdRenderTarget = new WebGLRenderTarget( readBuffer.width, readBuffer.height, { type: HalfFloatType } );
this._holdRenderTarget.texture.name = 'TAARenderPass.hold';

@@ -63,3 +113,3 @@ }

super.render( renderer, this.holdRenderTarget, readBuffer, deltaTime );
super.render( renderer, this._holdRenderTarget, readBuffer, deltaTime );

@@ -80,4 +130,4 @@ this.accumulateIndex = 0;

this.copyUniforms[ 'opacity' ].value = sampleWeight;
this.copyUniforms[ 'tDiffuse' ].value = writeBuffer.texture;
this._copyUniforms[ 'opacity' ].value = sampleWeight;
this._copyUniforms[ 'tDiffuse' ].value = writeBuffer.texture;

@@ -104,3 +154,3 @@ // render the scene multiple times, each slightly jitter offset from the last and accumulate the results.

renderer.setRenderTarget( this.sampleRenderTarget );
renderer.setRenderTarget( this._sampleRenderTarget );
if ( this.accumulateIndex === 0 ) {

@@ -113,3 +163,3 @@

this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -131,7 +181,7 @@ this.accumulateIndex ++;

this.copyUniforms[ 'opacity' ].value = 1.0;
this.copyUniforms[ 'tDiffuse' ].value = this.sampleRenderTarget.texture;
this._copyUniforms[ 'opacity' ].value = 1.0;
this._copyUniforms[ 'tDiffuse' ].value = this._sampleRenderTarget.texture;
renderer.setRenderTarget( writeBuffer );
renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -142,6 +192,6 @@ }

this.copyUniforms[ 'opacity' ].value = 1.0 - accumulationWeight;
this.copyUniforms[ 'tDiffuse' ].value = this.holdRenderTarget.texture;
this._copyUniforms[ 'opacity' ].value = 1.0 - accumulationWeight;
this._copyUniforms[ 'tDiffuse' ].value = this._holdRenderTarget.texture;
renderer.setRenderTarget( writeBuffer );
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -155,2 +205,6 @@ }

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {

@@ -160,3 +214,3 @@

if ( this.holdRenderTarget ) this.holdRenderTarget.dispose();
if ( this._holdRenderTarget ) this._holdRenderTarget.dispose();

@@ -163,0 +217,0 @@ }

@@ -8,5 +8,24 @@ import {

/**
* This pass can be used to render a texture over the entire screen.
*
* ```js
* const texture = new THREE.TextureLoader().load( 'textures/2294472375_24a3b8ef46_o.jpg' );
* texture.colorSpace = THREE.SRGBColorSpace;
*
* const texturePass = new TexturePass( texture );
* composer.addPass( texturePass );
* ```
*
* @augments Pass
*/
class TexturePass extends Pass {
constructor( map, opacity ) {
/**
* Constructs a new texture pass.
*
* @param {Texture} map - The texture to render.
* @param {number} [opacity=1] - The opacity.
*/
constructor( map, opacity = 1 ) {

@@ -17,7 +36,37 @@ super();

/**
* The texture to render.
*
* @type {Texture}
*/
this.map = map;
this.opacity = ( opacity !== undefined ) ? opacity : 1.0;
/**
* The opacity.
*
* @type {number}
* @default 1
*/
this.opacity = opacity;
/**
* Overwritten to disable the swap.
*
* @type {boolean}
* @default false
*/
this.needsSwap = false;
/**
* The pass uniforms.
*
* @type {Object}
*/
this.uniforms = UniformsUtils.clone( shader.uniforms );
/**
* The pass material.
*
* @type {ShaderMaterial}
*/
this.material = new ShaderMaterial( {

@@ -34,8 +83,19 @@

this.needsSwap = false;
// internals
this.fsQuad = new FullScreenQuad( null );
this._fsQuad = new FullScreenQuad( null );
}
/**
* Performs the texture pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) {

@@ -46,3 +106,3 @@

this.fsQuad.material = this.material;
this._fsQuad.material = this.material;

@@ -55,3 +115,3 @@ this.uniforms[ 'opacity' ].value = this.opacity;

if ( this.clear ) renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -62,8 +122,11 @@ renderer.autoClear = oldAutoClear;

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {
this.material.dispose();
this._fsQuad.dispose();
this.fsQuad.dispose();
}

@@ -70,0 +133,0 @@

@@ -17,3 +17,3 @@ import {

/**
* UnrealBloomPass is inspired by the bloom pass of Unreal Engine. It creates a
* This pass is inspired by the bloom pass of Unreal Engine. It creates a
* mip map chain of bloom textures and blurs them with different radii. Because

@@ -23,19 +23,77 @@ * of the weighted combination of mips, and because larger blurs are done on

*
* When using this pass, tone mapping must be enabled in the renderer settings.
*
* Reference:
* - https://docs.unrealengine.com/latest/INT/Engine/Rendering/PostProcessEffects/Bloom/
* - [Bloom in Unreal Engine]{@link https://docs.unrealengine.com/latest/INT/Engine/Rendering/PostProcessEffects/Bloom/}
*
* ```js
* const resolution = new THREE.Vector2( window.innerWidth, window.innerHeight );
* const bloomPass = new UnrealBloomPass( resolution, 1.5, 0.4, 0.85 );
* composer.addPass( bloomPass );
* ```
*
* @augments Pass
*/
class UnrealBloomPass extends Pass {
constructor( resolution, strength, radius, threshold ) {
/**
* Constructs a new Unreal Bloom pass.
*
* @param {Vector2} [resolution] - The effect's resolution.
* @param {number} [strength=1] - The Bloom strength.
* @param {number} radius - The Bloom radius.
* @param {number} threshold - The luminance threshold limits which bright areas contribute to the Bloom effect.
*/
constructor( resolution, strength = 1, radius, threshold ) {
super();
this.strength = ( strength !== undefined ) ? strength : 1;
/**
* The Bloom strength.
*
* @type {number}
* @default 1
*/
this.strength = strength;
/**
* The Bloom radius.
*
* @type {number}
*/
this.radius = radius;
/**
* The luminance threshold limits which bright areas contribute to the Bloom effect.
*
* @type {number}
*/
this.threshold = threshold;
/**
* The effect's resolution.
*
* @type {Vector2}
* @default (256,256)
*/
this.resolution = ( resolution !== undefined ) ? new Vector2( resolution.x, resolution.y ) : new Vector2( 256, 256 );
// create color only once here, reuse it later inside the render function
/**
* The effect's clear color
*
* @type {Color}
* @default (0,0,0)
*/
this.clearColor = new Color( 0, 0, 0 );
/**
* Overwritten to disable the swap.
*
* @type {boolean}
* @default false
*/
this.needsSwap = false;
// internals
// render targets

@@ -97,3 +155,3 @@ this.renderTargetsHorizontal = [];

this.separableBlurMaterials.push( this.getSeparableBlurMaterial( kernelSizeArray[ i ] ) );
this.separableBlurMaterials.push( this._getSeparableBlurMaterial( kernelSizeArray[ i ] ) );

@@ -110,3 +168,3 @@ this.separableBlurMaterials[ i ].uniforms[ 'invSize' ].value = new Vector2( 1 / resx, 1 / resy );

this.compositeMaterial = this.getCompositeMaterial( this.nMips );
this.compositeMaterial = this._getCompositeMaterial( this.nMips );
this.compositeMaterial.uniforms[ 'blurTexture1' ].value = this.renderTargetsVertical[ 0 ].texture;

@@ -127,10 +185,8 @@ this.compositeMaterial.uniforms[ 'blurTexture2' ].value = this.renderTargetsVertical[ 1 ].texture;

const copyShader = CopyShader;
this.copyUniforms = UniformsUtils.clone( CopyShader.uniforms );
this.copyUniforms = UniformsUtils.clone( copyShader.uniforms );
this.blendMaterial = new ShaderMaterial( {
uniforms: this.copyUniforms,
vertexShader: copyShader.vertexShader,
fragmentShader: copyShader.fragmentShader,
vertexShader: CopyShader.vertexShader,
fragmentShader: CopyShader.fragmentShader,
blending: AdditiveBlending,

@@ -142,14 +198,15 @@ depthTest: false,

this.enabled = true;
this.needsSwap = false;
this._oldClearColor = new Color();
this.oldClearAlpha = 1;
this._oldClearAlpha = 1;
this.basic = new MeshBasicMaterial();
this._basic = new MeshBasicMaterial();
this.fsQuad = new FullScreenQuad( null );
this._fsQuad = new FullScreenQuad( null );
}
/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever the pass is no longer used in your app.
*/
dispose() {

@@ -181,10 +238,16 @@

this.blendMaterial.dispose();
this.basic.dispose();
this._basic.dispose();
//
this.fsQuad.dispose();
this._fsQuad.dispose();
}
/**
* Sets the size of the pass.
*
* @param {number} width - The width to set.
* @param {number} height - The width to set.
*/
setSize( width, height ) {

@@ -211,6 +274,17 @@

/**
* Performs the Bloom pass.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGLRenderTarget} writeBuffer - The write buffer. This buffer is intended as the rendering
* destination for the pass.
* @param {WebGLRenderTarget} readBuffer - The read buffer. The pass can access the result from the
* previous pass from this buffer.
* @param {number} deltaTime - The delta time in seconds.
* @param {boolean} maskActive - Whether masking is active or not.
*/
render( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
renderer.getClearColor( this._oldClearColor );
this.oldClearAlpha = renderer.getClearAlpha();
this._oldClearAlpha = renderer.getClearAlpha();
const oldAutoClear = renderer.autoClear;

@@ -227,8 +301,8 @@ renderer.autoClear = false;

this.fsQuad.material = this.basic;
this.basic.map = readBuffer.texture;
this._fsQuad.material = this._basic;
this._basic.map = readBuffer.texture;
renderer.setRenderTarget( null );
renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -241,7 +315,7 @@ }

this.highPassUniforms[ 'luminosityThreshold' ].value = this.threshold;
this.fsQuad.material = this.materialHighPassFilter;
this._fsQuad.material = this.materialHighPassFilter;
renderer.setRenderTarget( this.renderTargetBright );
renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -254,3 +328,3 @@ // 2. Blur All the mips progressively

this.fsQuad.material = this.separableBlurMaterials[ i ];
this._fsQuad.material = this.separableBlurMaterials[ i ];

@@ -261,3 +335,3 @@ this.separableBlurMaterials[ i ].uniforms[ 'colorTexture' ].value = inputRenderTarget.texture;

renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -268,3 +342,3 @@ this.separableBlurMaterials[ i ].uniforms[ 'colorTexture' ].value = this.renderTargetsHorizontal[ i ].texture;

renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -277,3 +351,3 @@ inputRenderTarget = this.renderTargetsVertical[ i ];

this.fsQuad.material = this.compositeMaterial;
this._fsQuad.material = this.compositeMaterial;
this.compositeMaterial.uniforms[ 'bloomStrength' ].value = this.strength;

@@ -285,7 +359,7 @@ this.compositeMaterial.uniforms[ 'bloomRadius' ].value = this.radius;

renderer.clear();
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );
// Blend it additively over the input texture
this.fsQuad.material = this.blendMaterial;
this._fsQuad.material = this.blendMaterial;
this.copyUniforms[ 'tDiffuse' ].value = this.renderTargetsHorizontal[ 0 ].texture;

@@ -298,3 +372,3 @@

renderer.setRenderTarget( null );
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -304,3 +378,3 @@ } else {

renderer.setRenderTarget( readBuffer );
this.fsQuad.render( renderer );
this._fsQuad.render( renderer );

@@ -311,3 +385,3 @@ }

renderer.setClearColor( this._oldClearColor, this.oldClearAlpha );
renderer.setClearColor( this._oldClearColor, this._oldClearAlpha );
renderer.autoClear = oldAutoClear;

@@ -317,4 +391,6 @@

getSeparableBlurMaterial( kernelRadius ) {
// internals
_getSeparableBlurMaterial( kernelRadius ) {
const coefficients = [];

@@ -374,3 +450,3 @@

getCompositeMaterial( nMips ) {
_getCompositeMaterial( nMips ) {

@@ -377,0 +453,0 @@ return new ShaderMaterial( {

@@ -8,4 +8,14 @@ import {

/**
* The only type of 3D object that is supported by {@link CSS2DRenderer}.
*
* @augments Object3D
*/
class CSS2DObject extends Object3D {
/**
* Constructs a new CSS2D object.
*
* @param {DOMElement} [element] - The DOM element.
*/
constructor( element = document.createElement( 'div' ) ) {

@@ -15,4 +25,18 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isCSS2DObject = true;
/**
* The DOM element which defines the appearance of this 3D object.
*
* @type {DOMElement}
* @readonly
* @default true
*/
this.element = element;

@@ -25,3 +49,10 @@

this.center = new Vector2( 0.5, 0.5 ); // ( 0, 0 ) is the lower left; ( 1, 1 ) is the top right
/**
* The 3D objects center point.
* `( 0, 0 )` is the lower left, `( 1, 1 )` is the top right.
*
* @type {Vector2}
* @default (0.5,0.5)
*/
this.center = new Vector2( 0.5, 0.5 );

@@ -69,4 +100,19 @@ this.addEventListener( 'removed', function () {

/**
* This renderer is a simplified version of {@link CSS3DRenderer}. The only transformation that is
* supported is translation.
*
* The renderer is very useful if you want to combine HTML based labels with 3D objects. Here too,
* the respective DOM elements are wrapped into an instance of {@link CSS2DObject} and added to the
* scene graph. All other types of renderable 3D objects (like meshes or point clouds) are ignored.
*
* `CSS2DRenderer` only supports 100% browser and display zoom.
*/
class CSS2DRenderer {
/**
* Constructs a new CSS2D renderer.
*
* @param {CSS2DRenderer~Parameters} [parameters] - The parameters.
*/
constructor( parameters = {} ) {

@@ -87,4 +133,14 @@

/**
* The DOM where the renderer appends its child-elements.
*
* @type {DOMElement}
*/
this.domElement = domElement;
/**
* Returns an object containing the width and height of the renderer.
*
* @return {{width:number,height:number}} The size of the renderer.
*/
this.getSize = function () {

@@ -99,2 +155,8 @@

/**
* Renders the given scene using the given camera.
*
* @param {Object3D} scene - A scene or any other type of 3D object.
* @param {Camera} camera - The camera.
*/
this.render = function ( scene, camera ) {

@@ -113,2 +175,8 @@

/**
* Resizes the renderer to the given width and height.
*
* @param {number} width - The width of the renderer.
* @param {number} height - The height of the renderer.
*/
this.setSize = function ( width, height ) {

@@ -245,2 +313,10 @@

/**
* Constructor parameters of `CSS2DRenderer`.
*
* @typedef {Object} CSS2DRenderer~Parameters
* @property {DOMElement} [element] - A DOM element where the renderer appends its child-elements.
* If not passed in here, a new div element will be created.
**/
export { CSS2DObject, CSS2DRenderer };

@@ -8,5 +8,3 @@ import {

/**
* Based on http://www.emagix.net/academic/mscs-project/item/camera-sync-with-css3-and-webgl-threejs
*/
// Based on http://www.emagix.net/academic/mscs-project/item/camera-sync-with-css3-and-webgl-threejs

@@ -17,4 +15,14 @@ const _position = new Vector3();

/**
* The base 3D object that is supported by {@link CSS3DRenderer}.
*
* @augments Object3D
*/
class CSS3DObject extends Object3D {
/**
* Constructs a new CSS3D object.
*
* @param {DOMElement} [element] - The DOM element.
*/
constructor( element = document.createElement( 'div' ) ) {

@@ -24,4 +32,18 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isCSS3DObject = true;
/**
* The DOM element which defines the appearance of this 3D object.
*
* @type {DOMElement}
* @readonly
* @default true
*/
this.element = element;

@@ -65,4 +87,15 @@ this.element.style.position = 'absolute';

/**
* A specialized version of {@link CSS3DObject} that represents
* DOM elements as sprites.
*
* @augments CSS3DObject
*/
class CSS3DSprite extends CSS3DObject {
/**
* Constructs a new CSS3D sprite object.
*
* @param {DOMElement} [element] - The DOM element.
*/
constructor( element ) {

@@ -72,4 +105,17 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isCSS3DSprite = true;
/**
* The sprite's rotation in radians.
*
* @type {number}
* @default 0
*/
this.rotation2D = 0;

@@ -96,4 +142,24 @@

/**
* This renderer can be used to apply hierarchical 3D transformations to DOM elements
* via the CSS3 [transform]{@link https://www.w3schools.com/cssref/css3_pr_transform.asp} property.
* `CSS3DRenderer` is particularly interesting if you want to apply 3D effects to a website without
* canvas based rendering. It can also be used in order to combine DOM elements with WebGLcontent.
*
* There are, however, some important limitations:
*
* - It's not possible to use the material system of *three.js*.
* - It's also not possible to use geometries.
* - The renderer only supports 100% browser and display zoom.
*
* So `CSS3DRenderer` is just focused on ordinary DOM elements. These elements are wrapped into special
* 3D objects ({@link CSS3DObject} or {@link CSS3DSprite}) and then added to the scene graph.
*/
class CSS3DRenderer {
/**
* Constructs a new CSS3D renderer.
*
* @param {CSS3DRenderer~Parameters} [parameters] - The parameters.
*/
constructor( parameters = {} ) {

@@ -115,2 +181,7 @@

/**
* The DOM where the renderer appends its child-elements.
*
* @type {DOMElement}
*/
this.domElement = domElement;

@@ -129,2 +200,7 @@

/**
* Returns an object containing the width and height of the renderer.
*
* @return {{width:number,height:number}} The size of the renderer.
*/
this.getSize = function () {

@@ -139,2 +215,8 @@

/**
* Renders the given scene using the given camera.
*
* @param {Object3D} scene - A scene or any other type of 3D object.
* @param {Camera} camera - The camera.
*/
this.render = function ( scene, camera ) {

@@ -191,2 +273,8 @@

/**
* Resizes the renderer to the given width and height.
*
* @param {number} width - The width of the renderer.
* @param {number} height - The height of the renderer.
*/
this.setSize = function ( width, height ) {

@@ -363,2 +451,10 @@

/**
* Constructor parameters of `CSS3DRenderer`.
*
* @typedef {Object} CSS3DRenderer~Parameters
* @property {DOMElement} [element] - A DOM element where the renderer appends its child-elements.
* If not passed in here, a new div element will be created.
**/
export { CSS3DObject, CSS3DSprite, CSS3DRenderer };

@@ -123,6 +123,12 @@ import {

//
/**
* This class can project a given scene in 3D space into a 2D representation
* used for rendering with a 2D API. `Projector` is currently used by {@link SVGRenderer}
* and was previously used by the legacy `CanvasRenderer`.
*/
class Projector {
/**
* Constructs a new projector.
*/
constructor() {

@@ -407,2 +413,12 @@

/**
* Projects the given scene in 3D space into a 2D representation. The result
* is an object with renderable items.
*
* @param {Object3D} scene - A scene or any other type of 3D object.
* @param {Camera} camera - The camera.
* @param {boolean} sortObjects - Whether to sort objects or not.
* @param {boolean} sortElements - Whether to sort elements (faces, lines and sprites) or not.
* @return {{objects:Array<Objects>,lights:Array<Objects>,elements:Array<Objects>}} The projected scene as renderable objects.
*/
this.projectScene = function ( scene, camera, sortObjects, sortElements ) {

@@ -409,0 +425,0 @@

@@ -18,4 +18,14 @@ import {

/**
* Can be used to wrap SVG elements into a 3D object.
*
* @augments Object3D
*/
class SVGObject extends Object3D {
/**
* Constructs a new SVG object.
*
* @param {SVGElement} node - The SVG element.
*/
constructor( node ) {

@@ -25,4 +35,16 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isSVGObject = true;
/**
* This SVG element.
*
* @type {SVGElement}
*/
this.node = node;

@@ -34,4 +56,26 @@

/**
* This renderer an be used to render geometric data using SVG. The produced vector
* graphics are particular useful in the following use cases:
*
* - Animated logos or icons.
* - Interactive 2D/3D diagrams or graphs.
* - Interactive maps.
* - Complex or animated user interfaces.
*
* `SVGRenderer` has various advantages. It produces crystal-clear and sharp output which
* is independent of the actual viewport resolution.SVG elements can be styled via CSS.
* And they have good accessibility since it's possible to add metadata like title or description
* (useful for search engines or screen readers).
*
* There are, however, some important limitations:
* - No advanced shading.
* - No texture support.
* - No shadow support.
*/
class SVGRenderer {
/**
* Constructs a new SVG renderer.
*/
constructor() {

@@ -76,12 +120,56 @@

/**
* The DOM where the renderer appends its child-elements.
*
* @type {DOMElement}
*/
this.domElement = _svg;
/**
* Whether to automatically perform a clear before a render call or not.
*
* @type {boolean}
* @default true
*/
this.autoClear = true;
/**
* Whether to sort 3D objects or not.
*
* @type {boolean}
* @default true
*/
this.sortObjects = true;
/**
* Whether to sort elements or not.
*
* @type {boolean}
* @default true
*/
this.sortElements = true;
/**
* Number of fractional pixels to enlarge polygons in order to
* prevent anti-aliasing gaps. Range is `[0,1]`.
*
* @type {number}
* @default 0.5
*/
this.overdraw = 0.5;
/**
* The output color space.
*
* @type {(SRGBColorSpace|LinearSRGBColorSpace)}
* @default SRGBColorSpace
*/
this.outputColorSpace = SRGBColorSpace;
/**
* Provides information about the number of
* rendered vertices and faces.
*
* @type {Object}
*/
this.info = {

@@ -98,2 +186,8 @@

/**
* Sets the render quality. Setting to `high` means This value indicates that the browser
* tries to improve the SVG quality over rendering speed and geometric precision.
*
* @param {('low'|'high')} quality - The quality.
*/
this.setQuality = function ( quality ) {

@@ -110,2 +204,7 @@

/**
* Sets the clear color.
*
* @param {(number|Color|string)} color - The clear color to set.
*/
this.setClearColor = function ( color ) {

@@ -119,2 +218,8 @@

/**
* Resizes the renderer to the given width and height.
*
* @param {number} width - The width of the renderer.
* @param {number} height - The height of the renderer.
*/
this.setSize = function ( width, height ) {

@@ -134,2 +239,7 @@

/**
* Returns an object containing the width and height of the renderer.
*
* @return {{width:number,height:number}} The size of the renderer.
*/
this.getSize = function () {

@@ -144,2 +254,7 @@

/**
* Sets the precision of the data used to create a paths.
*
* @param {number} precision - The precision to set.
*/
this.setPrecision = function ( precision ) {

@@ -169,2 +284,5 @@

/**
* Performs a manual clear with the defined clear color.
*/
this.clear = function () {

@@ -177,2 +295,8 @@

/**
* Renders the given scene using the given camera.
*
* @param {Object3D} scene - A scene or any other type of 3D object.
* @param {Camera} camera - The camera.
*/
this.render = function ( scene, camera ) {

@@ -179,0 +303,0 @@

@@ -0,9 +1,13 @@

/** @module ACESFilmicToneMappingShader */
/**
* ACES Filmic Tone Mapping Shader by Stephen Hill
* source: https://github.com/selfshadow/ltc_code/blob/master/webgl/shaders/ltc/ltc_blit.fs
* ACES Filmic Tone Mapping Shader by Stephen Hill.
* Reference: [ltc_blit.fs]{@link https://github.com/selfshadow/ltc_code/blob/master/webgl/shaders/ltc/ltc_blit.fs}
*
* this implementation of ACES is modified to accommodate a brighter viewing environment.
* the scale factor of 1/0.6 is subjective. see discussion in #19621.
* This implementation of ACES is modified to accommodate a brighter viewing environment.
* The scale factor of 1/0.6 is subjective. See discussion in #19621.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const ACESFilmicToneMappingShader = {

@@ -10,0 +14,0 @@

@@ -0,7 +1,9 @@

/** @module AfterimageShader */
/**
* Afterimage shader
* I created this effect inspired by a demo on codepen:
* https://codepen.io/brunoimbrizi/pen/MoRJaN?page=1&
* Inspired by [Three.js FBO motion trails]{@link https://codepen.io/brunoimbrizi/pen/MoRJaN?page=1&}.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const AfterimageShader = {

@@ -8,0 +10,0 @@

@@ -0,5 +1,9 @@

/** @module BasicShader */
/**
* Simple test shader
* Simple shader for testing.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const BasicShader = {

@@ -6,0 +10,0 @@

@@ -0,7 +1,11 @@

/** @module BleachBypassShader */
/**
* Bleach bypass shader [http://en.wikipedia.org/wiki/Bleach_bypass]
* - based on Nvidia example
* http://developer.download.nvidia.com/shaderlibrary/webpages/shader_library.html#post_bleach_bypass
* Bleach bypass shader [http://en.wikipedia.org/wiki/Bleach_bypass] based on
* [Nvidia Shader library]{@link http://developer.download.nvidia.com/shaderlibrary/webpages/shader_library.html#post_bleach_bypass}.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const BleachBypassShader = {

@@ -8,0 +12,0 @@

@@ -0,5 +1,9 @@

/** @module BlendShader */
/**
* Blend two textures
* Blends two textures.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const BlendShader = {

@@ -6,0 +10,0 @@

@@ -0,7 +1,10 @@

/** @module BokehShader */
/**
* Depth-of-field shader with bokeh
* ported from GLSL shader by Martins Upitis
* http://artmartinsh.blogspot.com/2010/02/glsl-lens-blur-filter-with-bokeh.html
* Depth-of-field shader with bokeh ported from
* [GLSL shader by Martins Upitis]{@link http://artmartinsh.blogspot.com/2010/02/glsl-lens-blur-filter-with-bokeh.html}.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const BokehShader = {

@@ -8,0 +11,0 @@

@@ -5,8 +5,12 @@ import {

/** @module BokehShader2 */
/**
* Depth-of-field shader with bokeh
* ported from GLSL shader by Martins Upitis
* http://blenderartists.org/forum/showthread.php?237488-GLSL-depth-of-field-with-bokeh-v2-4-(update)
* Depth-of-field shader with bokeh ported from
* [GLSL shader by Martins Upitis]{@link http://blenderartists.org/forum/showthread.php?237488-GLSL-depth-of-field-with-bokeh-v2-4-(update)}.
*
* Requires #define RINGS and SAMPLES integers
*
* @constant
* @type {ShaderMaterial~Shader}
*/

@@ -13,0 +17,0 @@ const BokehShader = {

@@ -0,8 +1,11 @@

/** @module BrightnessContrastShader */
/**
* Brightness and contrast adjustment
* https://github.com/evanw/glfx.js
* brightness: -1 to 1 (-1 is solid black, 0 is no change, and 1 is solid white)
* contrast: -1 to 1 (-1 is solid gray, 0 is no change, and 1 is maximum contrast)
* Brightness and contrast adjustment {@link https://github.com/evanw/glfx.js}.
* Brightness: -1 to 1 (-1 is solid black, 0 is no change, and 1 is solid white)
* Contrast: -1 to 1 (-1 is solid gray, 0 is no change, and 1 is maximum contrast)
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const BrightnessContrastShader = {

@@ -9,0 +12,0 @@

@@ -5,6 +5,10 @@ import {

/** @module ColorCorrectionShader */
/**
* Color correction
* Color correction shader.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const ColorCorrectionShader = {

@@ -11,0 +15,0 @@

@@ -5,6 +5,10 @@ import {

/** @module ColorifyShader */
/**
* Colorify shader
* Colorify shader.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const ColorifyShader = {

@@ -11,0 +15,0 @@

@@ -5,7 +5,10 @@ import {

/** @module ConvolutionShader */
/**
* Convolution shader
* ported from o3d sample to WebGL / GLSL
* Convolution shader ported from o3d sample to WebGL / GLSL.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const ConvolutionShader = {

@@ -66,40 +69,5 @@

}`,
buildKernel: function ( sigma ) {
// We lop off the sqrt(2 * pi) * sigma term, since we're going to normalize anyway.
const kMaxKernelSize = 25;
let kernelSize = 2 * Math.ceil( sigma * 3.0 ) + 1;
if ( kernelSize > kMaxKernelSize ) kernelSize = kMaxKernelSize;
const halfWidth = ( kernelSize - 1 ) * 0.5;
const values = new Array( kernelSize );
let sum = 0.0;
for ( let i = 0; i < kernelSize; ++ i ) {
values[ i ] = gauss( i - halfWidth, sigma );
sum += values[ i ];
}
// normalize the kernel
for ( let i = 0; i < kernelSize; ++ i ) values[ i ] /= sum;
return values;
}
}`
};
function gauss( x, sigma ) {
return Math.exp( - ( x * x ) / ( 2.0 * sigma * sigma ) );
}
export { ConvolutionShader };

@@ -0,5 +1,9 @@

/** @module CopyShader */
/**
* Full-screen textured quad shader
* Full-screen copy shader pass.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const CopyShader = {

@@ -6,0 +10,0 @@

@@ -5,6 +5,12 @@ import {

/** @module DepthLimitedBlurShader */
/**
* TODO
*
* Used by {@link SAOPass}.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const DepthLimitedBlurShader = {

@@ -11,0 +17,0 @@

@@ -0,13 +1,13 @@

/** @module DigitalGlitch */
/**
* RGB Shift Shader
* Shifts red and blue channels from center in opposite directions
* Ported from http://kriss.cx/tom/2009/05/rgb-shift/
* by Tom Butterworth / http://kriss.cx/tom/
* Digital glitch shader.
*
* amount: shift distance (1 is width of input)
* angle: shift angle in radians
* @constant
* @type {ShaderMaterial~Shader}
*/
const DigitalGlitch = {
name: 'DigitalGlitch',
uniforms: {

@@ -14,0 +14,0 @@

@@ -0,7 +1,11 @@

/** @module DOFMipMapShader */
/**
* Depth-of-field shader using mipmaps
* - from Matt Handley @applmak
* - requires power-of-2 sized render target with enabled mipmaps
* Depth-of-field shader using mipmaps from Matt Handley @applmak.
*
* Requires power-of-2 sized render target with enabled mipmaps.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const DOFMipMapShader = {

@@ -8,0 +12,0 @@

@@ -5,8 +5,10 @@ import {

/** @module DotScreenShader */
/**
* Dot screen shader
* based on glfx.js sepia shader
* https://github.com/evanw/glfx.js
* Dot screen shader based on [glfx.js sepia shader]{@link https://github.com/evanw/glfx.js}.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const DotScreenShader = {

@@ -13,0 +15,0 @@

@@ -0,5 +1,9 @@

/** @module ExposureShader */
/**
* Exposure shader
* TODO
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const ExposureShader = {

@@ -6,0 +10,0 @@

@@ -0,1 +1,11 @@

/** @module FilmShader */
/**
* TODO
*
* Used by {@link FilmPass}.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const FilmShader = {

@@ -2,0 +12,0 @@

@@ -0,7 +1,9 @@

/** @module FocusShader */
/**
* Focus shader
* based on PaintEffect postprocess from ro.me
* http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js
* Focus shader based on [PaintEffect postprocess from ro.me]{@link http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js}.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const FocusShader = {

@@ -8,0 +10,0 @@

@@ -5,9 +5,13 @@ import {

/** @module FreiChenShader */
/**
* Edge Detection Shader using Frei-Chen filter
* Based on http://rastergrid.com/blog/2011/01/frei-chen-edge-detector
* Edge Detection Shader using Frei-Chen filter.
* Based on {@link http://rastergrid.com/blog/2011/01/frei-chen-edge-detector}.
*
* aspect: vec2 of (1/width, 1/height)
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const FreiChenShader = {

@@ -14,0 +18,0 @@

@@ -5,2 +5,14 @@ import {

/** @module FXAAShader */
/**
* FXAA algorithm from NVIDIA, C# implementation by Jasper Flick, GLSL port by Dave Hoskins.
*
* References:
* - {@link http://developer.download.nvidia.com/assets/gamedev/files/sdk/11/FXAA_WhitePaper.pdf}.
* - {@link https://catlikecoding.com/unity/tutorials/advanced-rendering/fxaa/}.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const FXAAShader = {

@@ -30,6 +42,2 @@

// FXAA algorithm from NVIDIA, C# implementation by Jasper Flick, GLSL port by Dave Hoskins
// http://developer.download.nvidia.com/assets/gamedev/files/sdk/11/FXAA_WhitePaper.pdf
// https://catlikecoding.com/unity/tutorials/advanced-rendering/fxaa/
uniform sampler2D tDiffuse;

@@ -143,3 +151,3 @@ uniform vec2 resolution;

e.pixelStep = e.isHorizontal ? texSize.y : texSize.x;
if (pGradient < nGradient) {

@@ -224,3 +232,3 @@

} else {
pDistance = puv.y - uv.y;

@@ -286,3 +294,3 @@ nDistance = uv.y - nuv.y;

gl_FragColor = ApplyFXAA( tDiffuse, resolution.xy, vUv );
}`

@@ -289,0 +297,0 @@

@@ -0,6 +1,12 @@

/** @module GammaCorrectionShader */
/**
* Gamma Correction Shader
* http://en.wikipedia.org/wiki/gamma_correction
*
* References:
* - {@link http://en.wikipedia.org/wiki/gamma_correction}.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const GammaCorrectionShader = {

@@ -7,0 +13,0 @@

@@ -6,2 +6,4 @@ import {

/** @module GodRaysShader */
/**

@@ -21,6 +23,7 @@ * God-rays (crepuscular rays)

* References:
* - [Sousa2008, Crysis Next Gen Effects, GDC2008]{@link http://www.crytek.com/sites/default/files/GDC08_SousaT_CrysisEffects.ppt}.
*
* Sousa2008 - Crysis Next Gen Effects, GDC2008, http://www.crytek.com/sites/default/files/GDC08_SousaT_CrysisEffects.ppt
* @constant
* @type {ShaderMaterial~Shader}
*/
const GodRaysDepthMaskShader = {

@@ -77,4 +80,6 @@

* decreased distance between samples.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const GodRaysGenerateShader = {

@@ -200,4 +205,6 @@

* fGodRayIntensity attenuates the god rays.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const GodRaysCombineShader = {

@@ -260,4 +267,6 @@

* cheaper/faster/simpler to implement this as a simple sun sprite.
*
* @constant
* @type {Object}
*/
const GodRaysFakeSunShader = {

@@ -264,0 +273,0 @@

@@ -9,32 +9,14 @@ import {

/** @module GTAOShader */
/**
* GTAO shader. Use by {@link GTAOPass}.
*
* References:
* - implemented algorithm - GTAO
* - https://iryoku.com/downloads/Practical-Realtime-Strategies-for-Accurate-Indirect-Occlusion.pdf
* - https://github.com/Patapom/GodComplex/blob/master/Tests/TestHBIL/2018%20Mayaux%20-%20Horizon-Based%20Indirect%20Lighting%20(HBIL).pdf
* - [Practical Realtime Strategies for Accurate Indirect Occlusion]{@link https://iryoku.com/downloads/Practical-Realtime-Strategies-for-Accurate-Indirect-Occlusion.pdf}.
* - [Horizon-Based Indirect Lighting (HBIL)]{@link https://github.com/Patapom/GodComplex/blob/master/Tests/TestHBIL/2018%20Mayaux%20-%20Horizon-Based%20Indirect%20Lighting%20(HBIL).pdf}
*
* - other AO algorithms that are not implemented here:
* - Screen Space Ambient Occlusion (SSAO), see also SSAOShader.js
* - http://john-chapman-graphics.blogspot.com/2013/01/ssao-tutorial.html
* - https://learnopengl.com/Advanced-Lighting/SSAO
* - https://creativecoding.soe.ucsc.edu/courses/cmpm164/_schedule/AmbientOcclusion.pdf
* - https://drive.google.com/file/d/1SyagcEVplIm2KkRD3WQYSO9O0Iyi1hfy/edit
* - Scalable Ambient Occlusion (SAO), see also SAOShader.js
* - https://casual-effects.com/research/McGuire2012SAO/index.html
* - https://research.nvidia.com/sites/default/files/pubs/2012-06_Scalable-Ambient-Obscurance/McGuire12SAO.pdf
* - N8HO
* - https://github.com/N8python/n8ao
* - Horizon Based Ambient Occlusion (HBAO)
* - http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.577.2286&rep=rep1&type=pdf
* - https://www.derschmale.com/2013/12/20/an-alternative-implementation-for-hbao-2/
*
* - further reading
* - https://ceur-ws.org/Vol-3027/paper5.pdf
* - https://www.comp.nus.edu.sg/~lowkl/publications/mssao_visual_computer_2012.pdf
* - https://web.ics.purdue.edu/~tmcgraw/papers/mcgraw-ao-2008.pdf
* - https://www.activision.com/cdn/research/Practical_Real_Time_Strategies_for_Accurate_Indirect_Occlusion_NEW%20VERSION_COLOR.pdf
* - https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.390.2463&rep=rep1&type=pdf
* - https://www.intel.com/content/www/us/en/developer/articles/technical/adaptive-screen-space-ambient-occlusion.html
* @constant
* @type {ShaderMaterial~Shader}
*/
const GTAOShader = {

@@ -91,3 +73,3 @@

uniform mat4 cameraProjectionMatrix;
uniform mat4 cameraProjectionMatrixInverse;
uniform mat4 cameraProjectionMatrixInverse;
uniform mat4 cameraWorldMatrix;

@@ -103,3 +85,3 @@ uniform float radius;

#endif
#include <common>

@@ -118,7 +100,7 @@ #include <packing>

float getDepth(const vec2 uv) {
float getDepth(const vec2 uv) {
return textureLod(tDepth, uv.xy, 0.0).DEPTH_SWIZZLING;
}
float fetchDepth(const ivec2 uv) {
float fetchDepth(const ivec2 uv) {
return texelFetch(tDepth, uv.xy, 0).DEPTH_SWIZZLING;

@@ -173,3 +155,3 @@ }

}
void main() {

@@ -200,3 +182,3 @@ float depth = getDepth(vUv.xy);

#endif
vec2 noiseResolution = vec2(textureSize(tNoise, 0));

@@ -214,5 +196,5 @@ vec2 noiseUv = vUv * resolution / noiseResolution;

for (int i = 0; i < DIRECTIONS; ++i) {
float angle = float(i) / float(DIRECTIONS) * PI;
vec4 sampleDir = vec4(cos(angle), sin(angle), 0., 0.5 + 0.5 * noiseTexel.w);
vec4 sampleDir = vec4(cos(angle), sin(angle), 0., 0.5 + 0.5 * noiseTexel.w);
sampleDir.xyz = normalize(kernelMatrix * sampleDir.xyz);

@@ -224,8 +206,8 @@

vec3 normalInSlice = normalize(viewNormal - sliceBitangent * dot(viewNormal, sliceBitangent));
vec3 tangentToNormalInSlice = cross(normalInSlice, sliceBitangent);
vec2 cosHorizons = vec2(dot(viewDir, tangentToNormalInSlice), dot(viewDir, -tangentToNormalInSlice));
for (int j = 0; j < STEPS; ++j) {
vec3 sampleViewOffset = sampleDir.xyz * radiusToUse * sampleDir.w * pow(float(j + 1) / float(STEPS), distanceExponent);
vec3 sampleViewOffset = sampleDir.xyz * radiusToUse * sampleDir.w * pow(float(j + 1) / float(STEPS), distanceExponent);

@@ -238,3 +220,3 @@ vec3 sampleSceneUvDepth = getSceneUvAndDepth(viewPos + sampleViewOffset);

cosHorizons.x += max(0., (sampleCosHorizon - cosHorizons.x) * mix(1., 2. / float(j + 2), distanceFallOff));
}
}

@@ -259,3 +241,3 @@ sampleSceneUvDepth = getSceneUvAndDepth(viewPos - sampleViewOffset);

ao = clamp(ao / float(DIRECTIONS), 0., 1.);
ao = clamp(ao / float(DIRECTIONS), 0., 1.);
#if SCENE_CLIP_BOX == 1

@@ -271,2 +253,8 @@ ao = mix(ao, 1., smoothstep(0., radiusToUse, boxDistance));

/**
* GTAO depth shader. Use by {@link GTAOPass}.
*
* @constant
* @type {Object}
*/
const GTAODepthShader = {

@@ -320,2 +308,8 @@

/**
* GTAO blend shader. Use by {@link GTAOPass}.
*
* @constant
* @type {Object}
*/
const GTAOBlendShader = {

@@ -322,0 +316,0 @@

@@ -0,8 +1,14 @@

/** @module HalftoneShader */
/**
* RGB Halftone shader for three.js.
* NOTE:
* Shape (1 = Dot, 2 = Ellipse, 3 = Line, 4 = Square)
* Blending Mode (1 = Linear, 2 = Multiply, 3 = Add, 4 = Lighter, 5 = Darker)
* RGB Halftone shader.
*
* Used by {@link HalftonePass}.
*
* Shape (1 = Dot, 2 = Ellipse, 3 = Line, 4 = Square)
* Blending Mode (1 = Linear, 2 = Multiply, 3 = Add, 4 = Lighter, 5 = Darker)
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const HalftoneShader = {

@@ -9,0 +15,0 @@

@@ -0,10 +1,16 @@

/** @module HorizontalBlurShader */
/**
* Two pass Gaussian blur filter (horizontal and vertical blur shaders)
* - see http://www.cake23.de/traveling-wavefronts-lit-up.html
* Two pass Gaussian blur filter (horizontal and vertical blur shaders).
*
* References:
* - {@link http://www.cake23.de/traveling-wavefronts-lit-up.html}.
*
* - 9 samples per pass
* - standard deviation 2.7
* - "h" and "v" parameters should be set to "1 / width" and "1 / height"
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const HorizontalBlurShader = {

@@ -11,0 +17,0 @@

@@ -0,3 +1,5 @@

/** @module HorizontalTiltShiftShader */
/**
* Simple fake tilt-shift effect, modulating two pass Gaussian blur (see above) by vertical position
* Simple fake tilt-shift effect, modulating two pass Gaussian blur (see above) by vertical position.
*

@@ -8,4 +10,6 @@ * - 9 samples per pass

* - "r" parameter control where "focused" horizontal line lies
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const HorizontalTiltShiftShader = {

@@ -12,0 +16,0 @@

@@ -0,8 +1,12 @@

/** @module HueSaturationShader */
/**
* Hue and saturation adjustment
* https://github.com/evanw/glfx.js
* Hue and saturation adjustment, {@link https://github.com/evanw/glfx.js}.
*
* hue: -1 to 1 (-1 is 180 degrees in the negative direction, 0 is no change, etc.
* saturation: -1 to 1 (-1 is solid gray, 0 is no change, and 1 is maximum contrast)
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const HueSaturationShader = {

@@ -9,0 +13,0 @@

@@ -0,11 +1,15 @@

/** @module KaleidoShader */
/**
* Kaleidoscope Shader
* Kaleidoscope Shader.
* Radial reflection around center point
* Ported from: http://pixelshaders.com/editor/
* by Toby Schachman / http://tobyschachman.com/
* Ported from: {@link http://pixelshaders.com/editor/}
* by [Toby Schachman]{@link http://tobyschachman.com/}
*
* sides: number of reflections
* angle: initial angle in radians
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const KaleidoShader = {

@@ -12,0 +16,0 @@

@@ -5,7 +5,10 @@ import {

/** @module LuminosityHighPassShader */
/**
* Luminosity
* http://en.wikipedia.org/wiki/Luminosity
* Luminosity high pass shader.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const LuminosityHighPassShader = {

@@ -15,4 +18,2 @@

shaderID: 'luminosityHighPass',
uniforms: {

@@ -19,0 +20,0 @@

@@ -0,6 +1,9 @@

/** @module LuminosityShader */
/**
* Luminosity
* http://en.wikipedia.org/wiki/Luminosity
* Luminosity shader.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const LuminosityShader = {

@@ -7,0 +10,0 @@

@@ -0,8 +1,11 @@

/** @module MirrorShader */
/**
* Mirror Shader
* Copies half the input to the other half
* Copies half the input to the other half.
*
* side: side of input to mirror (0 = left, 1 = right, 2 = top, 3 = bottom)
* side: side of input to mirror (0 = left, 1 = right, 2 = top, 3 = bottom).
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const MirrorShader = {

@@ -9,0 +12,0 @@

@@ -5,7 +5,9 @@ import {

/** @module NormalMapShader */
/**
* Normal map shader
* - compute normals from heightmap
* Normal map shader, compute normals from heightmap.
* @constant
* @type {ShaderMaterial~Shader}
*/
const NormalMapShader = {

@@ -12,0 +14,0 @@

@@ -0,1 +1,12 @@

/** @module OutputShader */
/**
* Performs tone mapping and color space conversion for
* FX workflows.
*
* Used by {@link OutputPass}.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const OutputShader = {

@@ -2,0 +13,0 @@

@@ -7,8 +7,14 @@ import {

/** @module PoissonDenoiseShader */
/**
* Poisson Denoise Shader.
*
* References:
* https://openaccess.thecvf.com/content/WACV2021/papers/Khademi_Self-Supervised_Poisson-Gaussian_Denoising_WACV_2021_paper.pdf
* https://arxiv.org/pdf/2206.01856.pdf
* - [Self-Supervised Poisson-Gaussian Denoising]{@link https://openaccess.thecvf.com/content/WACV2021/papers/Khademi_Self-Supervised_Poisson-Gaussian_Denoising_WACV_2021_paper.pdf}.
* - [Poisson2Sparse: Self-Supervised Poisson Denoising From a Single Image]{@link https://arxiv.org/pdf/2206.01856.pdf}
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const PoissonDenoiseShader = {

@@ -63,3 +69,3 @@

uniform int index;
#include <common>

@@ -87,5 +93,5 @@ #include <packing>

}
float getDepth(const vec2 uv) {
#if DEPTH_VALUE_SOURCE == 1
#if DEPTH_VALUE_SOURCE == 1
return textureLod(tDepth, uv.xy, 0.0).a;

@@ -98,3 +104,3 @@ #else

float fetchDepth(const ivec2 uv) {
#if DEPTH_VALUE_SOURCE == 1
#if DEPTH_VALUE_SOURCE == 1
return texelFetch(tDepth, uv.xy, 0).a;

@@ -146,3 +152,3 @@ #else

vec3 viewPosSample = getViewPosition(sampleUv, sampleDepth);
float normalDiff = dot(viewNormal, sampleNormal);

@@ -155,10 +161,10 @@ float normalSimilarity = pow(max(normalDiff, 0.), normalPhi);

float w = lumaSimilarity * depthSimilarity * normalSimilarity;
denoised += w * neighborColor;
totalWeight += w;
}
void main() {
float depth = getDepth(vUv.xy);
vec3 viewNormal = getViewNormal(vUv);
float depth = getDepth(vUv.xy);
vec3 viewNormal = getViewNormal(vUv);
if (depth == 1. || dot(viewNormal, viewNormal) == 0.) {

@@ -177,3 +183,3 @@ discard;

mat2 rotationMatrix = mat2(noiseVec.x, -noiseVec.y, noiseVec.x, noiseVec.y);
float totalWeight = 1.0;

@@ -187,4 +193,4 @@ vec3 denoised = texel.rgb;

}
if (totalWeight > 0.) {
if (totalWeight > 0.) {
denoised /= totalWeight;

@@ -191,0 +197,0 @@ }

@@ -0,1 +1,3 @@

/** @module RGBShiftShader */
/**

@@ -9,4 +11,6 @@ * RGB Shift Shader

* angle: shift angle in radians
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const RGBShiftShader = {

@@ -13,0 +17,0 @@

@@ -6,6 +6,12 @@ import {

/** @module SAOShader */
/**
* TODO
* SAO shader.
*
* Used by {@link SAOPass}.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const SAOShader = {

@@ -12,0 +18,0 @@

@@ -0,7 +1,9 @@

/** @module SepiaShader */
/**
* Sepia tone shader
* based on glfx.js sepia shader
* https://github.com/evanw/glfx.js
* Sepia tone shader based on [glfx.js sepia shader]{@link https://github.com/evanw/glfx.js}.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const SepiaShader = {

@@ -8,0 +10,0 @@

@@ -8,5 +8,15 @@ import {

* Preset: SMAA 1x Medium (with color edge detection)
* https://github.com/iryoku/smaa/releases/tag/v2.8
*
* References:
* - {@link https://github.com/iryoku/smaa/releases/tag/v2.8}
*
* @module SMAAShader
*/
/**
* SMAA Edges shader.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const SMAAEdgesShader = {

@@ -119,2 +129,8 @@

/**
* SMAA Weights shader.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const SMAAWeightsShader = {

@@ -376,2 +392,8 @@

/**
* SMAA Blend shader.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const SMAABlendShader = {

@@ -378,0 +400,0 @@

@@ -5,9 +5,12 @@ import {

/** @module SobelOperatorShader */
/**
* Sobel Edge Detection (see https://youtu.be/uihBwtPIBxM)
* Sobel Edge Detection (see {@link https://youtu.be/uihBwtPIBxM}).
*
* As mentioned in the video the Sobel operator expects a grayscale image as input.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const SobelOperatorShader = {

@@ -14,0 +17,0 @@

@@ -6,9 +6,15 @@ import {

/** @module SSAOShader */
/**
* SSAO shader.
*
* References:
* http://john-chapman-graphics.blogspot.com/2013/01/ssao-tutorial.html
* https://learnopengl.com/Advanced-Lighting/SSAO
* https://github.com/McNopper/OpenGL/blob/master/Example28/shader/ssao.frag.glsl
* - {@link http://john-chapman-graphics.blogspot.com/2013/01/ssao-tutorial.html}
* - {@link https://learnopengl.com/Advanced-Lighting/SSAO}
* - {@link https://github.com/McNopper/OpenGL/blob/master/Example28/shader/ssao.frag.glsl}
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const SSAOShader = {

@@ -135,3 +141,3 @@

gl_FragColor = vec4( 1.0 ); // don't influence background
} else {

@@ -187,2 +193,8 @@

/**
* SSAO depth shader.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const SSAODepthShader = {

@@ -251,2 +263,8 @@

/**
* SSAO blur shader.
*
* @constant
* @type {Object}
*/
const SSAOBlurShader = {

@@ -253,0 +271,0 @@

@@ -5,7 +5,19 @@ import {

} from 'three';
/**
* A collection of shaders used for SSR.
*
* References:
* https://lettier.github.io/3d-game-shaders-for-beginners/screen-space-reflection.html
* - [3D Game Shaders For Beginners, Screen Space Reflection (SSR)]{@link https://lettier.github.io/3d-game-shaders-for-beginners/screen-space-reflection.html}.
*
* @module SSRShader
*/
/**
* SSR shader.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const SSRShader = {

@@ -237,2 +249,8 @@

/**
* SSR Depth shader.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const SSRDepthShader = {

@@ -307,2 +325,8 @@

/**
* SSR Blur shader.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const SSRBlurShader = {

@@ -309,0 +333,0 @@

@@ -8,10 +8,2 @@ import {

/**
* ------------------------------------------------------------------------------------------
* Subsurface Scattering shader
* Based on GDC 2011 – Approximating Translucency for a Fast, Cheap and Convincing Subsurface Scattering Look
* https://colinbarrebrisebois.com/2011/03/07/gdc-2011-approximating-translucency-for-a-fast-cheap-and-convincing-subsurface-scattering-look/
*------------------------------------------------------------------------------------------
*/
function replaceAll( string, find, replace ) {

@@ -26,2 +18,12 @@

/** @module SubsurfaceScatteringShader */
/**
* Subsurface Scattering shader.
*
* Based on GDC 2011 – [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/}
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const SubsurfaceScatteringShader = {

@@ -28,0 +30,0 @@

@@ -0,8 +1,11 @@

/** @module TriangleBlurShader */
/**
* Technicolor Shader
* Simulates the look of the two-strip technicolor process popular in early 20th century films.
* More historical info here: http://www.widescreenmuseum.com/oldcolor/technicolor1.htm
* Demo here: http://charliehoey.com/technicolor_shader/shader_test.html
* More historical info here: {@link http://www.widescreenmuseum.com/oldcolor/technicolor1.htm}
* Demo here: {@link http://charliehoey.com/technicolor_shader/shader_test.html}
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const TechnicolorShader = {

@@ -9,0 +12,0 @@

@@ -7,12 +7,17 @@ import {

/**
* Currently contains:
* Collection of toon shaders.
*
* toon1
* toon2
* hatching
* dotted
* @module TriangleBlurShader
* */
/**
* Toon1 shader.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const ToonShader1 = {
name: 'ToonShader1',
uniforms: {

@@ -89,3 +94,8 @@

};
/**
* Toon2 shader.
*
* @constant
* @type {Object}
*/
const ToonShader2 = {

@@ -159,2 +169,8 @@

/**
* Toon Hatching shader.
*
* @constant
* @type {Object}
*/
const ToonShaderHatching = {

@@ -256,2 +272,8 @@

/**
* Toon Dotted shader.
*
* @constant
* @type {Object}
*/
const ToonShaderDotted = {

@@ -258,0 +280,0 @@

@@ -5,6 +5,6 @@ import {

/** @module TriangleBlurShader */
/**
* Triangle blur shader
* based on glfx.js triangle blur shader
* https://github.com/evanw/glfx.js
* Triangle blur shader based on [glfx.js triangle blur shader]{@link https://github.com/evanw/glfx.js}.
*

@@ -14,4 +14,6 @@ * A basic blur filter, which convolves the image with a

* perpendicular triangle filters.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const TriangleBlurShader = {

@@ -18,0 +20,0 @@

@@ -0,6 +1,9 @@

/** @module UnpackDepthRGBAShader */
/**
* Unpack RGBA depth shader
* - show RGBA encoded depth as monochrome color
* Unpack RGBA depth shader that shows RGBA encoded depth as monochrome color.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const UnpackDepthRGBAShader = {

@@ -7,0 +10,0 @@

@@ -7,6 +7,10 @@ import {

/** @module VelocityShader */
/**
* Mesh Velocity Shader @bhouston
* Mesh velocity shader by @bhouston.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const VelocityShader = {

@@ -13,0 +17,0 @@

@@ -0,4 +1,6 @@

/** @module VerticalBlurShader */
/**
* Two pass Gaussian blur filter (horizontal and vertical blur shaders)
* - see http://www.cake23.de/traveling-wavefronts-lit-up.html
* - see {@link http://www.cake23.de/traveling-wavefronts-lit-up.html}
*

@@ -8,4 +10,6 @@ * - 9 samples per pass

* - "h" and "v" parameters should be set to "1 / width" and "1 / height"
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const VerticalBlurShader = {

@@ -12,0 +16,0 @@

@@ -0,1 +1,3 @@

/** @module VerticalTiltShiftShader */
/**

@@ -8,4 +10,6 @@ * Simple fake tilt-shift effect, modulating two pass Gaussian blur (see above) by vertical position

* - "r" parameter control where "focused" horizontal line lies
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const VerticalTiltShiftShader = {

@@ -12,0 +16,0 @@

@@ -0,7 +1,9 @@

/** @module VignetteShader */
/**
* Vignette shader
* based on PaintEffect postprocess from ro.me
* http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js
* Based on [PaintEffect postprocess from ro.me]{@link http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js}.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const VignetteShader = {

@@ -8,0 +10,0 @@

@@ -6,2 +6,4 @@ import {

/** @module VolumeShader */
/**

@@ -11,6 +13,10 @@ * Shaders to render 3D volumes using raycasting.

* This is not the only approach, therefore it's marked 1.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const VolumeRenderShader1 = {
name: 'VolumeRenderShader1',
uniforms: {

@@ -17,0 +23,0 @@ 'u_size': { value: new Vector3( 1, 1, 1 ) },

@@ -0,1 +1,9 @@

/** @module WaterRefractionShader */
/**
* Basic water refraction shader.
*
* @constant
* @type {ShaderMaterial~Shader}
*/
const WaterRefractionShader = {

@@ -2,0 +10,0 @@

@@ -0,3 +1,15 @@

/**
* Utility class for generating a flakes texture image. This image might be used
* as a normal map to produce a car paint like effect.
*/
class FlakesTexture {
/**
* Generates a new flakes texture image. The result is a canvas
* that can be used as an input for {@link CanvasTexture}.
*
* @param {number} [width=512] - The width of the image.
* @param {number} [height=512] - The height of the image.
* @return {HTMLCanvasElement} The generated image.
*/
constructor( width = 512, height = 512 ) {

@@ -4,0 +16,0 @@

@@ -0,6 +1,31 @@

/**
* A class that transpiles shader code from one language into another.
*
* `Transpiler` can only be used to convert GLSL into TSL right now. It is intended
* to support developers when they want to migrate their custom materials from the
* current to the new node-based material system.
*/
class Transpiler {
/**
* Constructs a new transpiler.
*
* @param {GLSLDecoder} decoder - The GLSL decoder.
* @param {TSLEncoder} encoder - The TSL encoder.
*/
constructor( decoder, encoder ) {
/**
* The GLSL decoder. This component parse GLSL and produces
* a language-independent AST for further processing.
*
* @type {GLSLDecoder}
*/
this.decoder = decoder;
/**
* The TSL encoder. It takes the AST and emits TSL code.
*
* @type {TSLEncoder}
*/
this.encoder = encoder;

@@ -10,2 +35,8 @@

/**
* Parses the given GLSL source and returns TSL syntax.
*
* @param {string} source - The GLSL source.
* @return {string} The TSL code.
*/
parse( source ) {

@@ -12,0 +43,0 @@

@@ -44,3 +44,3 @@ import { RenderTarget, Vector2, QuadMesh, NodeMaterial, RendererUtils, TempNode, NodeUpdateType } from 'three/webgpu';

*/
this.textureNodeOld = texture();
this.textureNodeOld = texture( null );

@@ -47,0 +47,0 @@ /**

@@ -460,3 +460,3 @@ import { HalfFloatType, RenderTarget, Vector2, Vector3, TempNode, QuadMesh, NodeMaterial, RendererUtils, NodeUpdateType } from 'three/webgpu';

const colorTexture = texture();
const colorTexture = texture( null );
const gaussianCoefficients = uniformArray( coefficients );

@@ -463,0 +463,0 @@ const invSize = uniform( new Vector2() );

@@ -237,4 +237,4 @@ import { NearestFilter, Vector4, TempNode, NodeUpdateType, PassNode } from 'three/webgpu';

* @param {Node<float> | number} [pixelSize=6] - The pixel size.
* @param {Node<float> | number} [normalEdgeStrength=03] - The normal edge strength.
* @param {Node<float> | number} [depthEdgeStrength=03] - The depth edge strength.
* @param {Node<float> | number} [normalEdgeStrength=0.3] - The normal edge strength.
* @param {Node<float> | number} [depthEdgeStrength=0.4] - The depth edge strength.
*/

@@ -328,4 +328,4 @@ constructor( scene, camera, pixelSize = 6, normalEdgeStrength = 0.3, depthEdgeStrength = 0.4 ) {

* @param {Node<float> | number} [pixelSize=6] - The pixel size.
* @param {Node<float> | number} [normalEdgeStrength=03] - The normal edge strength.
* @param {Node<float> | number} [depthEdgeStrength=03] - The depth edge strength.
* @param {Node<float> | number} [normalEdgeStrength=0.3] - The normal edge strength.
* @param {Node<float> | number} [depthEdgeStrength=0.4] - The depth edge strength.
* @returns {PixelationPassNode}

@@ -332,0 +332,0 @@ */

@@ -101,3 +101,3 @@ import { NearestFilter, RenderTarget, Vector2, RendererUtils, QuadMesh, TempNode, NodeMaterial, NodeUpdateType } from 'three/webgpu';

/**
* Controls how far a fragment can reflect
* Controls how far a fragment can reflect.
*

@@ -104,0 +104,0 @@ *

@@ -37,2 +37,9 @@ import { DataTexture, FloatType, RGBAFormat, Vector2, Vector3, LightsNode, NodeUpdateType } from 'three/webgpu';

/**
* A custom version of `LightsNode` implementing tiled lighting. This node is used in
* {@link TiledLighting} to overwrite the renderer's default lighting with
* a custom implementation.
*
* @augments LightsNode
*/
class TiledLightsNode extends LightsNode {

@@ -46,2 +53,8 @@

/**
* Constructs a new tiled lights node.
*
* @param {number} [maxLights=1024] - The maximum number of lights.
* @param {number} [tileSize=32] - The tile size.
*/
constructor( maxLights = 1024, tileSize = 32 ) {

@@ -54,3 +67,16 @@

/**
* The maximum number of lights.
*
* @type {number}
* @default 1024
*/
this.maxLights = maxLights;
/**
* The tile size.
*
* @type {number}
* @default 32
*/
this.tileSize = tileSize;

@@ -177,3 +203,3 @@

return this._lightIndexes.element( tileIndex ).element( element.modInt( stride ) );
return this._lightIndexes.element( tileIndex ).element( element.mod( stride ) );

@@ -322,3 +348,3 @@ }

return lightIndexes.element( tileIndex ).element( elementIndex.modInt( stride ) );
return lightIndexes.element( tileIndex ).element( elementIndex.mod( stride ) );

@@ -334,3 +360,3 @@ };

const tileScreen = vec2(
instanceIndex.modInt( tiledBufferSize.width ),
instanceIndex.mod( tiledBufferSize.width ),
instanceIndex.div( tiledBufferSize.width )

@@ -337,0 +363,0 @@ ).mul( tileSize ).div( screenSize );

import { TextureLoader } from 'three';
import { Fn, int, ivec2, textureLoad } from 'three/tsl';
/** @module Bayer */
let bayer16Texture = null;
/**
* This TSL function can be used to sample a Bayer16 texture which is a 16x16 texture with a Bayer Matrix pattern.
* It can be used for dithering effects but also as an alternative to blue-noise. When used with Ray Marching
* specifically in {@link VolumeNodeMaterial#offsetNode}, it reduces banding problem, thus being able to use
* fewer steps without affecting the visuals as much.
*
* @tsl
* @function
* @param {Node<vec2>} uv - The uv to sample the bayer16 texture.
* @return {Node<vec4>} The sampled bayer value.
*/
export const bayer16 = Fn( ( [ uv ] ) => {

@@ -16,4 +29,4 @@

return textureLoad( bayer16Texture, ivec2( uv ).modInt( int( 16 ) ) );
return textureLoad( bayer16Texture, ivec2( uv ).mod( int( 16 ) ) );
} );
import { varying, vec4, modelWorldMatrixInverse, cameraPosition, positionGeometry, float, Fn, Loop, max, min, vec2, vec3 } from 'three/tsl';
/** @module Raymarching */
const hitBox = /*@__PURE__*/ Fn( ( { orig, dir } ) => {

@@ -24,3 +26,4 @@

/**
* Performs raymarching box-area using the specified number of steps and a callback function.
* TSL function for performing raymarching in a box-area using the specified number of steps
* and a callback function.
*

@@ -37,3 +40,2 @@ * ```js

* @param {Function|FunctionNode} callback - The callback function to execute at each step.
* @returns {void}
*/

@@ -40,0 +42,0 @@ export const RaymarchingBox = ( steps, callback ) => {

@@ -14,2 +14,23 @@ import {

/** @module BufferGeometryUtils */
/**
* Computes vertex tangents using the MikkTSpace algorithm. MikkTSpace generates the same tangents consistently,
* and is used in most modelling tools and normal map bakers. Use MikkTSpace for materials with normal maps,
* because inconsistent tangents may lead to subtle visual issues in the normal map, particularly around mirrored
* UV seams.
*
* In comparison to this method, {@link BufferGeometry#computeTangents} (a custom algorithm) generates tangents that
* probably will not match the tangents in other software. The custom algorithm is sufficient for general use with a
* custom material, and may be faster than MikkTSpace.
*
* Returns the original BufferGeometry. Indexed geometries will be de-indexed. Requires position, normal, and uv attributes.
*
* @param {BufferGeometry} geometry - The geometry to compute tangents for.
* @param {Object} MikkTSpace - Instance of `examples/jsm/libs/mikktspace.module.js`, or `mikktspace` npm package.
* Await `MikkTSpace.ready` before use.
* @param {boolean} [negateSign=true] - Whether to negate the sign component (.w) of each tangent.
* Required for normal map conventions in some formats, including glTF.
* @return {BufferGeometry} The updated geometry.
*/
function computeMikkTSpaceTangents( geometry, MikkTSpace, negateSign = true ) {

@@ -104,5 +125,7 @@

/**
* @param {Array<BufferGeometry>} geometries
* @param {boolean} useGroups
* @return {BufferGeometry}
* Merges a set of geometries into a single instance. All geometries must have compatible attributes.
*
* @param {Array<BufferGeometry>} geometries - The geometries to merge.
* @param {boolean} [useGroups=false] - Whether to use groups or not.
* @return {?BufferGeometry} The merged geometry. Returns `null` if the merge does not succeed.
*/

@@ -301,4 +324,7 @@ function mergeGeometries( geometries, useGroups = false ) {

/**
* @param {Array<BufferAttribute>} attributes
* @return {BufferAttribute}
* Merges a set of attributes into a single instance. All attributes must have compatible properties and types.
* Instances of {@link InterleavedBufferAttribute} are not supported.
*
* @param {Array<BufferAttribute>} attributes - The attributes to merge.
* @return {?BufferAttribute} The merged attribute. Returns `null` if the merge does not succeed.
*/

@@ -395,6 +421,8 @@ function mergeAttributes( attributes ) {

/**
* @param {BufferAttribute} attribute
* @return {BufferAttribute}
* Performs a deep clone of the given buffer attribute.
*
* @param {BufferAttribute} attribute - The attribute to clone.
* @return {BufferAttribute} The cloned attribute.
*/
export function deepCloneAttribute( attribute ) {
function deepCloneAttribute( attribute ) {

@@ -418,4 +446,7 @@ if ( attribute.isInstancedInterleavedBufferAttribute || attribute.isInterleavedBufferAttribute ) {

/**
* @param {Array<BufferAttribute>} attributes
* @return {Array<InterleavedBufferAttribute>}
* Interleaves a set of attributes and returns a new array of corresponding attributes that share a
* single {@link InterleavedBuffer} instance. All attributes must have compatible types.
*
* @param {Array<BufferAttribute>} attributes - The attributes to interleave.
* @return {Array<InterleavedBufferAttribute>} An array of interleaved attributes. If interleave does not succeed, the method returns `null`.
*/

@@ -483,4 +514,9 @@ function interleaveAttributes( attributes ) {

// returns a new, non-interleaved version of the provided attribute
export function deinterleaveAttribute( attribute ) {
/**
* Returns a new, non-interleaved version of the given attribute.
*
* @param {InterleavedBufferAttribute} attribute - The interleaved attribute.
* @return {BufferAttribute} The non-interleaved attribute.
*/
function deinterleaveAttribute( attribute ) {

@@ -532,4 +568,8 @@ const cons = attribute.data.array.constructor;

// deinterleaves all attributes on the geometry
export function deinterleaveGeometry( geometry ) {
/**
* Deinterleaves all attributes on the given geometry.
*
* @param {BufferGeometry} geometry - The geometry to deinterleave.
*/
function deinterleaveGeometry( geometry ) {

@@ -577,4 +617,6 @@ const attributes = geometry.attributes;

/**
* @param {BufferGeometry} geometry
* @return {number}
* Returns the amount of bytes used by all attributes to represent the geometry.
*
* @param {BufferGeometry} geometry - The geometry.
* @return {number} The estimate bytes used.
*/

@@ -601,5 +643,7 @@ function estimateBytesUsed( geometry ) {

/**
* @param {BufferGeometry} geometry
* @param {number} tolerance
* @return {BufferGeometry}
* Returns a new geometry with vertices for which all similar vertex attributes (within tolerance) are merged.
*
* @param {BufferGeometry} geometry - The geometry to merge vertices for.
* @param {number} [tolerance=1e-4] - The tolerance value.
* @return {BufferGeometry} - The new geometry with merged vertices.
*/

@@ -765,5 +809,8 @@ function mergeVertices( geometry, tolerance = 1e-4 ) {

/**
* @param {BufferGeometry} geometry
* @param {number} drawMode
* @return {BufferGeometry}
* Returns a new indexed geometry based on `TrianglesDrawMode` draw mode.
* This mode corresponds to the `gl.TRIANGLES` primitive in WebGL.
*
* @param {BufferGeometry} geometry - The geometry to convert.
* @param {number} drawMode - The current draw mode.
* @return {BufferGeometry} The new geometry using `TrianglesDrawMode`.
*/

@@ -877,5 +924,9 @@ function toTrianglesDrawMode( geometry, drawMode ) {

* Calculates the morphed attributes of a morphed/skinned BufferGeometry.
* Helpful for Raytracing or Decals.
* @param {Mesh | Line | Points} object An instance of Mesh, Line or Points.
* @return {Object} An Object with original position/normal attributes and morphed ones.
*
* Helpful for Raytracing or Decals (i.e. a `DecalGeometry` applied to a morphed Object with a `BufferGeometry`
* will use the original `BufferGeometry`, not the morphed/skinned one, generating an incorrect result.
* Using this function to create a shadow `Object3`D the `DecalGeometry` can be correctly generated).
*
* @param {Mesh|Line|Points} object - The 3D object to compute morph attributes for.
* @return {Object} An object with original position/normal attributes and morphed ones.
*/

@@ -1156,2 +1207,8 @@ function computeMorphedAttributes( object ) {

/**
* Merges the {@link BufferGeometry#groups} for the given geometry.
*
* @param {BufferGeometry} geometry - The geometry to modify.
* @return {BufferGeometry} - The updated geometry
*/
function mergeGroups( geometry ) {

@@ -1259,3 +1316,2 @@

/**

@@ -1266,5 +1322,5 @@ * Modifies the supplied geometry if it is non-indexed, otherwise creates a new,

*
* @param {BufferGeometry} geometry
* @param {number} [creaseAngle]
* @return {BufferGeometry}
* @param {BufferGeometry} geometry - The geometry to modify.
* @param {number} [creaseAngle=Math.PI/3] - The crease angle in radians.
* @return {BufferGeometry} - The updated geometry
*/

@@ -1380,2 +1436,5 @@ function toCreasedNormals( geometry, creaseAngle = Math.PI / 3 /* 60 degrees */ ) {

mergeAttributes,
deepCloneAttribute,
deinterleaveAttribute,
deinterleaveGeometry,
interleaveAttributes,

@@ -1382,0 +1441,0 @@ estimateBytesUsed,

@@ -7,2 +7,4 @@ import {

/** @module CameraUtils */
const _va = /*@__PURE__*/ new Vector3(), // from pe to pa

@@ -18,12 +20,13 @@ _vb = /*@__PURE__*/ new Vector3(), // from pe to pb

/** Set a PerspectiveCamera's projectionMatrix and quaternion
/**
* Set projection matrix and the orientation of a perspective camera
* to exactly frame the corners of an arbitrary rectangle.
* NOTE: This function ignores the standard parameters;
* do not call updateProjectionMatrix() after this!
* do not call `updateProjectionMatrix()` after this.
*
* @param {PerspectiveCamera} camera
* @param {Vector3} bottomLeftCorner
* @param {Vector3} bottomRightCorner
* @param {Vector3} topLeftCorner
* @param {boolean} [estimateViewFrustum=false]
* @param {PerspectiveCamera} camera - The camera.
* @param {Vector3} bottomLeftCorner - The bottom-left corner point.
* @param {Vector3} bottomRightCorner - The bottom-right corner point.
* @param {Vector3} topLeftCorner - The top-left corner point.
* @param {boolean} [estimateViewFrustum=false] - If set to `true`, the function tries to estimate the camera's FOV.
*/

@@ -30,0 +33,0 @@ function frameCorners( camera, bottomLeftCorner, bottomRightCorner, topLeftCorner, estimateViewFrustum = false ) {

@@ -1,8 +0,1 @@

/**
* Octahedron and Quantization encodings based on work by:
*
* @link https://github.com/tsherif/mesh-quantization-example
*
*/
import {

@@ -15,10 +8,11 @@ BufferAttribute,

/** @module GeometryCompressionUtils */
// Octahedron and Quantization encodings based on work by: https://github.com/tsherif/mesh-quantization-example
/**
* Make the input geometry's normal attribute encoded and compressed by 3 different methods.
* Compressed the given geometry's `normal` attribute by the selected encode method.
*
* @param {THREE.BufferGeometry} geometry
* @param {string} encodeMethod "DEFAULT" || "OCT1Byte" || "OCT2Byte" || "ANGLES"
*
* @param {BufferGeometry} geometry - The geometry whose normals should be compressed.
* @param {('DEFAULT'|'OCT1Byte'|'OCT2Byte'|'ANGLES')} encodeMethod - The compression method.
*/

@@ -31,3 +25,3 @@ function compressNormals( geometry, encodeMethod ) {

console.error( 'Geometry must contain normal attribute. ' );
console.error( 'THREE.GeometryCompressionUtils.compressNormals(): Geometry must contain normal attribute.' );

@@ -40,3 +34,3 @@ }

console.error( 'normal.itemSize is not 3, which cannot be encoded. ' );
console.error( 'THREE.GeometryCompressionUtils.compressNormals(): normal.itemSize is not 3, which cannot be encoded.' );

@@ -69,8 +63,7 @@ }

/**
* It is not recommended to use 1-byte octahedron normals encoding unless you want to extremely reduce the memory usage
* As it makes vertex data not aligned to a 4 byte boundary which may harm some WebGL implementations and sometimes the normal distortion is visible
* Please refer to @zeux 's comments in https://github.com/mrdoob/three.js/pull/18208
*/
// It is not recommended to use 1-byte octahedron normals encoding unless you want to extremely reduce the memory usage
// As it makes vertex data not aligned to a 4 byte boundary which may harm some WebGL implementations and sometimes the normal distortion is visible
// Please refer to @zeux 's comments in https://github.com/mrdoob/three.js/pull/18208
result = new Int8Array( count * 2 );

@@ -134,9 +127,7 @@

/**
* Make the input geometry's position attribute encoded and compressed.
*
* @param {THREE.BufferGeometry} geometry
*
*/
* Compressed the given geometry's `position` attribute.
*
* @param {BufferGeometry} geometry - The geometry whose position values should be compressed.
*/
function compressPositions( geometry ) {

@@ -148,3 +139,3 @@

console.error( 'Geometry must contain position attribute. ' );
console.error( 'THREE.GeometryCompressionUtils.compressPositions(): Geometry must contain position attribute.' );

@@ -157,3 +148,3 @@ }

console.error( 'position.itemSize is not 3, which cannot be packed. ' );
console.error( 'THREE.GeometryCompressionUtils.compressPositions(): position.itemSize is not 3, which cannot be packed.' );

@@ -181,6 +172,5 @@ }

/**
* Make the input geometry's uv attribute encoded and compressed.
* Compressed the given geometry's `uv` attribute.
*
* @param {THREE.BufferGeometry} geometry
*
* @param {BufferGeometry} geometry - The geometry whose texture coordinates should be compressed.
*/

@@ -193,3 +183,3 @@ function compressUvs( geometry ) {

console.error( 'Geometry must contain uv attribute. ' );
console.error( 'THREE.GeometryCompressionUtils.compressUvs(): Geometry must contain uv attribute.' );

@@ -196,0 +186,0 @@ }

import { Vector3 } from 'three';
/** @module GeometryUtils */
/**
* Generates 2D-Coordinates in a very fast way.
* Generates 2D-Coordinates along a Hilbert curve.
*
* Based on work by:
* @link http://www.openprocessing.org/sketch/15493
* Based on work by: {@link http://www.openprocessing.org/sketch/15493}
*
* @param {Vector3} center - Center of Hilbert curve.
* @param {Vector3} [center] - Center of Hilbert curve.
* @param {number} [size=10] - Total width of Hilbert curve.

@@ -17,3 +17,3 @@ * @param {number} [iterations=10] - Number of subdivisions.

* @param {number} [v3=3] - Corner index +X, -Z.
* @returns {Array<Array<number>>} The Hilbert curve points.
* @returns {Array<Vector3>} The Hilbert curve points.
*/

@@ -56,8 +56,7 @@ function hilbert2D( center = new Vector3( 0, 0, 0 ), size = 10, iterations = 1, v0 = 0, v1 = 1, v2 = 2, v3 = 3 ) {

/**
* Generates 3D-Coordinates in a very fast way.
* Generates 3D-Coordinates along a Hilbert curve.
*
* Based on work by:
* @link https://openprocessing.org/user/5654
* Based on work by: {@link https://openprocessing.org/user/5654}
*
* @param {Vector3} [center=new Vector3( 0, 0, 0 )] - Center of Hilbert curve.
* @param {Vector3} [center] - Center of Hilbert curve.
* @param {number} [size=10] - Total width of Hilbert curve.

@@ -73,3 +72,3 @@ * @param {number} [iterations=1] - Number of subdivisions.

* @param {number} [v7=7] - Corner index +X, +Y, -Z.
* @returns {Array<Array<number>>} - The Hilbert curve points.
* @returns {Array<Vector3>} - The Hilbert curve points.
*/

@@ -125,8 +124,8 @@ function hilbert3D( center = new Vector3( 0, 0, 0 ), size = 10, iterations = 1, v0 = 0, v1 = 1, v2 = 2, v3 = 3, v4 = 4, v5 = 5, v6 = 6, v7 = 7 ) {

/**
* Generates a Gosper curve (lying in the XY plane)
* Generates a Gosper curve (lying in the XY plane).
*
* https://gist.github.com/nitaku/6521802
* Reference: {@link https://gist.github.com/nitaku/6521802}
*
* @param {number} [size=1] - The size of a single gosper island.
* @return {Array<[number, number, number]>} The gosper island points.
* @return {Array<number>} The gosper island points.
*/

@@ -133,0 +132,0 @@ function gosper( size = 1 ) {

@@ -12,10 +12,17 @@ import {

/**
* Utility class for LDraw models.
*/
class LDrawUtils {
/**
* Merges geometries in the given object by materials and returns a new group object.
* Use on not indexed geometries. The object buffers reference the old object ones.
* Special treatment is done to the conditional lines generated by LDrawLoader.
*
* @param {Object3D} object - The object to merge.
* @returns {Group} The merged object.
*/
static mergeObject( object ) {
// Merges geometries in object by materials and returns new object. Use on not indexed geometries.
// The object buffers reference the old object ones.
// Special treatment is done to the conditional lines generated by LDrawLoader.
function extractGroup( geometry, group, elementSize, isConditionalLine ) {

@@ -22,0 +29,0 @@

import * as THREE from 'three';
/**
* This class can be used to optimized scenes by converting
* individual meshes into {@link BatchedMesh}. This component
* is an experimental attempt to implement auto-batching in three.js.
*/
class SceneOptimizer {
/**
* Constructs a new scene optimizer.
*
* @param {Scene} scene - The scene to optimize.
* @param {SceneOptimizer~Options} options - The configuration options.
*/
constructor( scene, options = {} ) {

@@ -12,3 +23,3 @@

bufferToHash( buffer ) {
_bufferToHash( buffer ) {

@@ -47,3 +58,3 @@ let hash = 0;

getMaterialPropertiesHash( material ) {
_getMaterialPropertiesHash( material ) {

@@ -133,3 +144,3 @@ const mapProps = [

getAttributesSignature( geometry ) {
_getAttributesSignature( geometry ) {

@@ -148,9 +159,9 @@ return Object.keys( geometry.attributes )

getGeometryHash( geometry ) {
_getGeometryHash( geometry ) {
const indexHash = geometry.index
? this.bufferToHash( geometry.index.array )
? this._bufferToHash( geometry.index.array )
: 'noIndex';
const positionHash = this.bufferToHash( geometry.attributes.position.array );
const attributesSignature = this.getAttributesSignature( geometry );
const positionHash = this._bufferToHash( geometry.attributes.position.array );
const attributesSignature = this._getAttributesSignature( geometry );
return `${indexHash}_${positionHash}_${attributesSignature}`;

@@ -160,3 +171,3 @@

getBatchKey( materialProps, attributesSignature ) {
_getBatchKey( materialProps, attributesSignature ) {

@@ -167,3 +178,3 @@ return `${materialProps}_${attributesSignature}`;

analyzeModel() {
_analyzeModel() {

@@ -179,6 +190,6 @@ const batchGroups = new Map();

const materialProps = this.getMaterialPropertiesHash( node.material );
const attributesSignature = this.getAttributesSignature( node.geometry );
const batchKey = this.getBatchKey( materialProps, attributesSignature );
const geometryHash = this.getGeometryHash( node.geometry );
const materialProps = this._getMaterialPropertiesHash( node.material );
const attributesSignature = this._getAttributesSignature( node.geometry );
const batchKey = this._getBatchKey( materialProps, attributesSignature );
const geometryHash = this._getGeometryHash( node.geometry );
uniqueGeometries.add( geometryHash );

@@ -232,3 +243,3 @@

createBatchedMeshes( batchGroups ) {
_createBatchedMeshes( batchGroups ) {

@@ -280,3 +291,3 @@ const meshesToRemove = new Set();

const geometryHash = this.getGeometryHash( mesh.geometry );
const geometryHash = this._getGeometryHash( mesh.geometry );

@@ -320,2 +331,7 @@ if ( ! geometryIds.has( geometryHash ) ) {

/**
* Removes empty nodes from all descendants of the given 3D object.
*
* @param {Object3D} object - The 3D object to process.
*/
removeEmptyNodes( object ) {

@@ -340,2 +356,7 @@

/**
* Removes the given array of meshes from the scene.
*
* @param {Set<Mesh>} meshesToRemove - The meshes to remove.
*/
disposeMeshes( meshesToRemove ) {

@@ -370,3 +391,3 @@

logDebugInfo( stats ) {
_logDebugInfo( stats ) {

@@ -383,6 +404,14 @@ console.group( 'Scene Optimization Results' );

/**
* Performs the auto-baching by identifying groups of meshes in the scene
* that can be represented as a single {@link BatchedMesh}. The method modifies
* the scene by adding instances of `BatchedMesh` and removing the now redundant
* individual meshes.
*
* @return {Scene} The optimized scene.
*/
toBatchedMesh() {
const { batchGroups, singleGroups, uniqueGeometries } = this.analyzeModel();
const meshesToRemove = this.createBatchedMeshes( batchGroups );
const { batchGroups, singleGroups, uniqueGeometries } = this._analyzeModel();
const meshesToRemove = this._createBatchedMeshes( batchGroups );

@@ -406,3 +435,3 @@ this.disposeMeshes( meshesToRemove );

this.logDebugInfo( stats );
this._logDebugInfo( stats );

@@ -415,3 +444,13 @@ }

// Placeholder for future implementation
/**
* Performs the auto-instancing by identifying groups of meshes in the scene
* that can be represented as a single {@link InstancedMesh}. The method modifies
* the scene by adding instances of `InstancedMesh` and removing the now redundant
* individual meshes.
*
* This method is not yet implemented.
*
* @abstract
* @return {Scene} The optimized scene.
*/
toInstancingMesh() {

@@ -425,2 +464,9 @@

/**
* Constructor options of `SceneOptimizer`.
*
* @typedef {Object} SceneOptimizer~Options
* @property {boolean} [debug=false] - Whether to enable debug mode or not.
**/
export { SceneOptimizer };

@@ -13,5 +13,15 @@ import {

/** @module SceneUtils */
const _color = /*@__PURE__*/new Color();
const _matrix = /*@__PURE__*/new Matrix4();
/**
* This function creates a mesh for each instance of the given instanced mesh and
* adds it to a group. Each mesh will honor the current 3D transformation of its
* corresponding instance.
*
* @param {InstancedMesh} instancedMesh - The instanced mesh.
* @return {Group} A group of meshes.
*/
function createMeshesFromInstancedMesh( instancedMesh ) {

@@ -43,2 +53,9 @@

/**
* This function creates a mesh for each geometry-group of the given multi-material mesh and
* adds it to a group.
*
* @param {Mesh} mesh - The multi-material mesh.
* @return {Group} A group of meshes.
*/
function createMeshesFromMultiMaterialMesh( mesh ) {

@@ -115,2 +132,12 @@

/**
* This function represents an alternative way to create 3D objects with multiple materials.
* Normally, {@link BufferGeometry#groups} are used which might introduce issues e.g. when
* exporting the object to a 3D format. This function accepts a geometry and an array of
* materials and creates for each material a mesh that is added to a group.
*
* @param {BufferGeometry} geometry - The geometry.
* @param {Array<Material>} materials - An array of materials.
* @return {Group} A group representing a multi-material object.
*/
function createMultiMaterialObject( geometry, materials ) {

@@ -130,2 +157,14 @@

/**
* Executes a reducer function for each vertex of the given 3D object.
* `reduceVertices()` returns a single value: the function's accumulated result.
*
* @param {Object3D} object - The 3D object that should be processed. It must have a
* geometry with a `position` attribute.
* @param {function(number,Vector3):number} func - The reducer function. First argument
* is the current value, second argument the current vertex.
* @param {any} initialValue - The initial value.
* @return {any} The result.
*/
function reduceVertices( object, func, initialValue ) {

@@ -181,4 +220,6 @@

/**
* @param {InstancedMesh} mesh
* @param {function(int, int):int} compareFn
* Sorts the instances of the given instanced mesh.
*
* @param {InstancedMesh} mesh - The instanced mesh to sort.
* @param {function(number, number):number} compareFn - A custom compare function for the sort.
*/

@@ -254,3 +295,5 @@ function sortInstancedMesh( mesh, compareFn ) {

/**
* @param {Object3D} object Object to traverse.
* Generator based alternative to {@link Object3D#traverse}.
*
* @param {Object3D} object - Object to traverse.
* @yields {Object3D} Objects that passed the filter condition.

@@ -273,2 +316,4 @@ */

/**
* Generator based alternative to {@link Object3D#traverseVisible}.
*
* @param {Object3D} object Object to traverse.

@@ -294,2 +339,4 @@ * @yields {Object3D} Objects that passed the filter condition.

/**
* Generator based alternative to {@link Object3D#traverseAncestors}.
*
* @param {Object3D} object Object to traverse.

@@ -296,0 +343,0 @@ * @yields {Object3D} Objects that passed the filter condition.

@@ -19,26 +19,21 @@ import {

*
* Example usage:
* 1) Import ShadowMapViewer into your app.
* This module can only be used with {@link WebGLRenderer}. When using {@link WebGPURenderer},
* import the class from `ShadowMapViewerGPU.js`.
*
* 2) Create a shadow casting light and name it optionally:
* let light = new DirectionalLight( 0xffffff, 1 );
* light.castShadow = true;
* light.name = 'Sun';
*
* 3) Create a shadow map viewer for that light and set its size and position optionally:
* let shadowMapViewer = new ShadowMapViewer( light );
* shadowMapViewer.size.set( 128, 128 ); //width, height default: 256, 256
* shadowMapViewer.position.set( 10, 10 ); //x, y in pixel default: 0, 0 (top left corner)
*
* 4) Render the shadow map viewer in your render loop:
* shadowMapViewer.render( renderer );
*
* 5) Optionally: Update the shadow map viewer on window resize:
* shadowMapViewer.updateForWindowResize();
*
* 6) If you set the position or size members directly, you need to call shadowMapViewer.update();
* ```js
* const lightShadowMapViewer = new ShadowMapViewer( light );
* lightShadowMapViewer.position.x = 10;
* lightShadowMapViewer.position.y = SCREEN_HEIGHT - ( SHADOW_MAP_HEIGHT / 4 ) - 10;
* lightShadowMapViewer.size.width = SHADOW_MAP_WIDTH / 4;
* lightShadowMapViewer.size.height = SHADOW_MAP_HEIGHT / 4;
* lightShadowMapViewer.update();
* ```
*/
class ShadowMapViewer {
/**
* Constructs a new shadow map viewer.
*
* @param {Light} light - The shadow casting light.
*/
constructor( light ) {

@@ -114,7 +109,17 @@

//- API
// Set to false to disable displaying this shadow map
/**
* Whether to display the shadow map viewer or not.
*
* @type {boolean}
* @default true
*/
this.enabled = true;
// Set the size of the displayed shadow map on the HUD
/**
* The size of the viewer. When changing this property, make sure
* to call {@link ShadowMapViewer#update}.
*
* @type {{width:number,height:number}}
* @default true
*/
this.size = {

@@ -136,3 +141,9 @@ width: frame.width,

// Set the position of the displayed shadow map on the HUD
/**
* The position of the viewer. When changing this property, make sure
* to call {@link ShadowMapViewer#update}.
*
* @type {{x:number,y:number, set:function(number,number)}}
* @default true
*/
this.position = {

@@ -156,2 +167,7 @@ x: frame.x,

/**
* Renders the viewer. This method must be called in the app's animation loop.
*
* @param {WebGLRenderer} renderer - The renderer.
*/
this.render = function ( renderer ) {

@@ -178,2 +194,6 @@

/**
* Resizes the viewer. This method should be called whenever the app's
* window is resized.
*/
this.updateForWindowResize = function () {

@@ -195,2 +215,5 @@

/**
* Updates the viewer.
*/
this.update = function () {

@@ -197,0 +220,0 @@

@@ -19,26 +19,21 @@ import {

*
* Example usage:
* 1) Import ShadowMapViewer into your app.
* This module can only be used with {@link WebGPURenderer}. When using {@link WebGLRenderer},
* import the class from `ShadowMapViewer.js`.
*
* 2) Create a shadow casting light and name it optionally:
* let light = new DirectionalLight( 0xffffff, 1 );
* light.castShadow = true;
* light.name = 'Sun';
*
* 3) Create a shadow map viewer for that light and set its size and position optionally:
* let shadowMapViewer = new ShadowMapViewer( light );
* shadowMapViewer.size.set( 128, 128 ); //width, height default: 256, 256
* shadowMapViewer.position.set( 10, 10 ); //x, y in pixel default: 0, 0 (top left corner)
*
* 4) Render the shadow map viewer in your render loop:
* shadowMapViewer.render( renderer );
*
* 5) Optionally: Update the shadow map viewer on window resize:
* shadowMapViewer.updateForWindowResize();
*
* 6) If you set the position or size members directly, you need to call shadowMapViewer.update();
* ```js
* const lightShadowMapViewer = new ShadowMapViewer( light );
* lightShadowMapViewer.position.x = 10;
* lightShadowMapViewer.position.y = SCREEN_HEIGHT - ( SHADOW_MAP_HEIGHT / 4 ) - 10;
* lightShadowMapViewer.size.width = SHADOW_MAP_WIDTH / 4;
* lightShadowMapViewer.size.height = SHADOW_MAP_HEIGHT / 4;
* lightShadowMapViewer.update();
* ```
*/
class ShadowMapViewer {
/**
* Constructs a new shadow map viewer.
*
* @param {Light} light - The shadow casting light.
*/
constructor( light ) {

@@ -110,7 +105,17 @@

//- API
// Set to false to disable displaying this shadow map
/**
* Whether to display the shadow map viewer or not.
*
* @type {boolean}
* @default true
*/
this.enabled = true;
// Set the size of the displayed shadow map on the HUD
/**
* The size of the viewer. When changing this property, make sure
* to call {@link ShadowMapViewer#update}.
*
* @type {{width:number,height:number}}
* @default true
*/
this.size = {

@@ -132,3 +137,9 @@ width: frame.width,

// Set the position of the displayed shadow map on the HUD
/**
* The position of the viewer. When changing this property, make sure
* to call {@link ShadowMapViewer#update}.
*
* @type {{width:number,height:number}}
* @default true
*/
this.position = {

@@ -152,2 +163,7 @@ x: frame.x,

/**
* Renders the viewer. This method must be called in the app's animation loop.
*
* @param {WebGPURenderer} renderer - The renderer.
*/
this.render = function ( renderer ) {

@@ -174,2 +190,6 @@

/**
* Resizes the viewer. This method should be called whenever the app's
* window is resized.
*/
this.updateForWindowResize = function () {

@@ -191,2 +211,5 @@

/**
* Updates the viewer.
*/
this.update = function () {

@@ -193,0 +216,0 @@

@@ -12,2 +12,4 @@ import {

/** @module SkeletonUtils */
function getBoneName( bone, options ) {

@@ -25,2 +27,10 @@

/**
* Retargets the skeleton from the given source 3D object to the
* target 3D object.
*
* @param {Object3D} target - The target 3D object.
* @param {Object3D} source - The source 3D object.
* @param {module:SkeletonUtils~RetargetOptions} options - The options.
*/
function retarget( target, source, options = {} ) {

@@ -201,2 +211,12 @@

/**
* Retargets the animation clip of the source object to the
* target 3D object.
*
* @param {Object3D} target - The target 3D object.
* @param {Object3D} source - The source 3D object.
* @param {AnimationClip} clip - The animation clip.
* @param {module:SkeletonUtils~RetargetOptions} options - The options.
* @return {AnimationClip} The retargeted animation clip.
*/
function retargetClip( target, source, clip, options = {} ) {

@@ -360,2 +380,10 @@

/**
* Clones the given 3D object and its descendants, ensuring that any `SkinnedMesh` instances are
* correctly associated with their bones. Bones are also cloned, and must be descendants of the
* object passed to this method. Other data, like geometries and materials, are reused by reference.
*
* @param {Object3D} source - The 3D object to clone.
* @return {Object3D} The cloned 3D object.
*/
function clone( source ) {

@@ -442,2 +470,19 @@

/**
* Retarget options of `SkeletonUtils`.
*
* @typedef {Object} module:SkeletonUtils~RetargetOptions
* @property {boolean} [useFirstFramePosition=false] - Whether to use the position of the first frame or not.
* @property {number} [fps] - The FPS of the clip.
* @property {Object<string,string>} [names] - A dictionary for mapping target to source bone names.
* @property {function(string):string} [getBoneName] - A function for mapping bone names. Alternative to `names`.
* @property {Array<number>} [trim] - Whether to trim the clip or not. If set the array should hold two values for the start and end.
* @property {boolean} [preserveBoneMatrix=true] - Whether to preserve bone matrices or not.
* @property {boolean} [preserveBonePositions=true] - Whether to preserve bone positions or not.
* @property {boolean} [useTargetMatrix=false] - Whether to use the target matrix or not.
* @property {string} [hip='hip'] - The name of the source's hip bone.
* @property {Vector3} [hipInfluence=(1,1,1)] - The hip influence.
* @property {number} [scale=1] - The scale.
**/
export {

@@ -444,0 +489,0 @@ retarget,

@@ -1,7 +0,4 @@

// Hybrid radix sort from
// - https://gist.github.com/sciecode/93ed864dd77c5c8803c6a86698d68dab
// - https://github.com/mrdoob/three.js/pull/27202#issuecomment-1817640271
//
// expects unsigned 32b integer values
/** @module SortUtils */
const POWER = 3;

@@ -27,2 +24,14 @@ const BIT_MAX = 32;

/**
* Hybrid radix sort from.
*
* - {@link https://gist.github.com/sciecode/93ed864dd77c5c8803c6a86698d68dab}
* - {@link https://github.com/mrdoob/three.js/pull/27202#issuecomment-1817640271}
*
* Expects unsigned 32b integer values.
*
* @function
* @param {Array<Object>} arr - The array to sort.
* @param {Object} opt - The options
*/
export const radixSort = ( arr, opt ) => {

@@ -29,0 +38,0 @@

@@ -5,10 +5,15 @@ import {

/** @module UVsDebug */
/**
* tool for "unwrapping" and debugging three.js geometries UV mapping
* Function for "unwrapping" and debugging three.js geometries UV mapping.
*
* Sample usage:
* document.body.appendChild( UVsDebug( new THREE.SphereGeometry( 10, 10, 10, 10 ) ) );
* ```js
* document.body.appendChild( UVsDebug( new THREE.SphereGeometry() ) );
* ```
*
* @param {BufferGeometry} geometry - The geometry whose uv coordinates should be inspected.
* @param {number} [size=1024] - The size of the debug canvas.
* @return {HTMLCanvasElement} A canvas element with visualized uv coordinates.
*/
function UVsDebug( geometry, size = 1024 ) {

@@ -15,0 +20,0 @@

@@ -13,2 +13,4 @@ import {

/** @module WebGLTextureUtils */
let _renderer;

@@ -19,2 +21,13 @@ let fullscreenQuadGeometry;

/**
* Returns an uncompressed version of the given compressed texture.
*
* This module can only be used with {@link WebGLRenderer}. When using {@link WebGPURenderer},
* import the function from {@link WebGPUTextureUtils}.
*
* @param {CompressedTexture} texture - The compressed texture.
* @param {number} [maxTextureSize=Infinity] - The maximum size of the uncompressed texture.
* @param {?WebGLRenderer} [renderer=null] - A reference to a renderer.
* @return {CanvasTexture} The uncompressed texture.
*/
export function decompress( texture, maxTextureSize = Infinity, renderer = null ) {

@@ -21,0 +34,0 @@

@@ -9,5 +9,19 @@ import {

/** @module WebGPUTextureUtils */
let _renderer;
const _quadMesh = /*@__PURE__*/ new QuadMesh();
/**
* Returns an uncompressed version of the given compressed texture.
*
* This module can only be used with {@link WebGPURenderer}. When using {@link WebGLRenderer},
* import the function from {@link WebGLTextureUtils}.
*
* @async
* @param {CompressedTexture} blitTexture - The compressed texture.
* @param {number} [maxTextureSize=Infinity] - The maximum size of the uncompressed texture.
* @param {?WebGPURenderer} [renderer=null] - A reference to a renderer.
* @return {Promise<CanvasTexture>} A Promise that resolved with the uncompressed texture.
*/
export async function decompress( blitTexture, maxTextureSize = Infinity, renderer = null ) {

@@ -14,0 +28,0 @@

/**
* @author Deepkolos / https://github.com/deepkolos
* A simple pool for managing Web Workers.
*/
export class WorkerPool {
/**
* Constructs a new Worker pool.
*
* @param {number} [pool=4] - The size of the pool.
*/
constructor( pool = 4 ) {
/**
* The size of the pool.
*
* @type {number}
* @default 4
*/
this.pool = pool;
/**
* A message queue.
*
* @type {Array<Object>}
*/
this.queue = [];
/**
* An array of Workers.
*
* @type {Array<Worker>}
*/
this.workers = [];
/**
* An array with resolve functions for messages.
*
* @type {Array<Function>}
*/
this.workersResolve = [];
/**
* The current worker status.
*
* @type {number}
*/
this.workerStatus = 0;
/**
* A factory function for creating workers.
*
* @type {?Function}
*/
this.workerCreator = null;
}

@@ -57,2 +98,7 @@

/**
* Sets a function that is responsible for creating Workers.
*
* @param {Function} workerCreator - The worker creator function.
*/
setWorkerCreator( workerCreator ) {

@@ -64,2 +110,7 @@

/**
* Sets the Worker limit
*
* @param {number} pool - The size of the pool.
*/
setWorkerLimit( pool ) {

@@ -71,2 +122,10 @@

/**
* Post a message to an idle Worker. If no Worker is available,
* the message is pushed into a message queue for later processing.
*
* @param {Object} msg - The message.
* @param {Array<ArrayBuffer>} transfer - An array with array buffers for data transfer.
* @return {Promise} A Promise that resolves when the message has been processed.
*/
postMessage( msg, transfer ) {

@@ -95,2 +154,6 @@

/**
* Terminates all Workers of this pool. Call this method whenever this
* Worker pool is no longer used in your app.
*/
dispose() {

@@ -97,0 +160,0 @@

@@ -0,3 +1,21 @@

/**
* A utility class for creating a button that allows to initiate
* immersive AR sessions based on WebXR. The button can be created
* with a factory method and then appended ot the website's DOM.
*
* ```js
* document.body.appendChild( ARButton.createButton( renderer ) );
* ```
*
* @hideconstructor
*/
class ARButton {
/**
* Constructs a new AR button.
*
* @param {WebGLRenderer|WebGPURenderer} renderer - The renderer.
* @param {XRSessionInit} [sessionInit] - The a configuration object for the AR session.
* @return {HTMLElement} The button or an error message if `immersive-ar` isn't supported.
*/
static createButton( renderer, sessionInit = {} ) {

@@ -4,0 +22,0 @@

@@ -7,4 +7,16 @@ import { Object3D, Sphere, Box3 } from 'three';

/**
* Represents an Oculus hand model.
*
* @augments Object3D
*/
class OculusHandModel extends Object3D {
/**
* Constructs a new Oculus hand model.
*
* @param {Group} controller - The hand controller.
* @param {?Loader} [loader=null] - A loader that is used to load hand models.
* @param {?Function} [onLoad=null] - A callback that is executed when a hand model has been loaded.
*/
constructor( controller, loader = null, onLoad = null ) {

@@ -14,8 +26,55 @@

/**
* The hand controller.
*
* @type {Group}
*/
this.controller = controller;
/**
* The motion controller.
*
* @type {?MotionController}
* @default null
*/
this.motionController = null;
/**
* The model's environment map.
*
* @type {?Texture}
* @default null
*/
this.envMap = null;
/**
* A loader that is used to load hand models.
*
* @type {?Loader}
* @default null
*/
this.loader = loader;
/**
* A callback that is executed when a hand model has been loaded.
*
* @type {?Function}
* @default null
*/
this.onLoad = onLoad;
/**
* The path to the model repository.
*
* @type {?string}
* @default null
*/
this.path = null;
/**
* The model mesh.
*
* @type {Mesh}
* @default null
*/
this.mesh = null;

@@ -46,2 +105,8 @@

/**
* Overwritten with a custom implementation. Makes sure the motion controller updates the mesh.
*
* @param {boolean} [force=false] - When set to `true`, a recomputation of world matrices is forced even
* when {@link Object3D#matrixWorldAutoUpdate} is set to `false`.
*/
updateMatrixWorld( force ) {

@@ -59,2 +124,7 @@

/**
* Returns the pointer position which is the position of the index finger tip.
*
* @return {Vector3|null} The pointer position. Returns `null` if not index finger tip joint was found.
*/
getPointerPosition() {

@@ -75,2 +145,9 @@

/**
* Returns `true` if the current pointer position (the index finger tip) intersections
* with the given box object.
*
* @param {Mesh} boxObject - The box object.
* @return {boolean} Whether an intersection was found or not.
*/
intersectBoxObject( boxObject ) {

@@ -93,2 +170,8 @@

/**
* Executed actions depending on the interaction state with
* the given button.
*
* @param {Object} button - The button.
*/
checkButton( button ) {

@@ -95,0 +178,0 @@

@@ -22,4 +22,15 @@ import { BufferGeometry, Float32BufferAttribute, Matrix4, Mesh, MeshBasicMaterial, Object3D, Raycaster, SphereGeometry, Vector3 } from 'three';

/**
* Represents an Oculus hand pointer model.
*
* @augments Object3D
*/
class OculusHandPointerModel extends Object3D {
/**
* Constructs a new Oculus hand model.
*
* @param {Group} hand - The hand controller.
* @param {Group} controller - The WebXR controller in target ray space.
*/
constructor( hand, controller ) {

@@ -29,3 +40,14 @@

/**
* The hand controller.
*
* @type {Group}
*/
this.hand = hand;
/**
* The WebXR controller in target ray space.
*
* @type {Group}
*/
this.controller = controller;

@@ -38,11 +60,57 @@

/**
* The pointer geometry.
*
* @type {?BufferGeometry}
* @default null
*/
this.pointerGeometry = null;
/**
* The pointer mesh.
*
* @type {?Mesh}
* @default null
*/
this.pointerMesh = null;
/**
* The pointer object that holds the pointer mesh.
*
* @type {?Object3D}
* @default null
*/
this.pointerObject = null;
/**
* Whether the model is pinched or not.
*
* @type {?boolean}
* @default false
*/
this.pinched = false;
/**
* Whether the model is attached or not.
*
* @type {boolean}
* @default false
*/
this.attached = false;
/**
* The cursor object.
*
* @type {?Mesh}
* @default null
*/
this.cursorObject = null;
/**
* The internal raycaster used for detecting
* intersections.
*
* @type {?Raycaster}
* @default null
*/
this.raycaster = null;

@@ -149,2 +217,5 @@

/**
* Creates a pointer mesh and adds it to this model.
*/
createPointer() {

@@ -324,2 +395,8 @@

/**
* Overwritten with a custom implementation. Makes sure the internal pointer and raycaster are updated.
*
* @param {boolean} [force=false] - When set to `true`, a recomputation of world matrices is forced even
* when {@link Object3D#matrixWorldAutoUpdate} is set to `false`.
*/
updateMatrixWorld( force ) {

@@ -337,2 +414,7 @@

/**
* Returns `true` is the model is pinched.
*
* @return {boolean} Whether the model is pinched or not.
*/
isPinched() {

@@ -344,2 +426,7 @@

/**
* Sets the attached state.
*
* @param {boolean} attached - Whether the model is attached or not.
*/
setAttached( attached ) {

@@ -351,2 +438,7 @@

/**
* Returns `true` is the model is attached.
*
* @return {boolean} Whether the model is attached or not.
*/
isAttached() {

@@ -358,2 +450,10 @@

/**
* Performs an intersection test with the model's raycaster and the given object.
*
* @param {Object3D} object - The 3D object to check for intersection with the ray.
* @param {boolean} [recursive=true] - If set to `true`, it also checks all descendants.
* Otherwise it only checks intersection with the object.
* @return {Array<Raycaster~Intersection>} An array holding the intersection points.
*/
intersectObject( object, recursive = true ) {

@@ -369,2 +469,10 @@

/**
* Performs an intersection test with the model's raycaster and the given objects.
*
* @param {Array<Object3D>} objects - The 3D objects to check for intersection with the ray.
* @param {boolean} [recursive=true] - If set to `true`, it also checks all descendants.
* Otherwise it only checks intersection with the object.
* @return {Array<Raycaster~Intersection>} An array holding the intersection points.
*/
intersectObjects( objects, recursive = true ) {

@@ -380,2 +488,10 @@

/**
* Checks for intersections between the model's raycaster and the given objects. The method
* updates the cursor object to the intersection point.
*
* @param {Array<Object3D>} objects - The 3D objects to check for intersection with the ray.
* @param {boolean} [recursive=false] - If set to `true`, it also checks all descendants.
* Otherwise it only checks intersection with the object.
*/
checkIntersections( objects, recursive = false ) {

@@ -403,2 +519,7 @@

/**
* Sets the cursor to the given distance.
*
* @param {number} distance - The distance to set the cursor to.
*/
setCursor( distance ) {

@@ -415,2 +536,6 @@

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*/
dispose() {

@@ -417,0 +542,0 @@

import { DoubleSide, Mesh, MeshBasicMaterial, PlaneGeometry, Texture } from 'three';
/** @module Text2D */
/**
* A helper function for creating a simple plane mesh
* that can be used as a text label. The mesh's material
* holds a canvas texture that displays the given message.
*
* @param {string} message - The message to display.
* @param {number} height - The labels height.
* @return {Mesh} The plane mesh representing a text label.
*/
function createText( message, height ) {

@@ -4,0 +15,0 @@

@@ -0,3 +1,21 @@

/**
* A utility class for creating a button that allows to initiate
* immersive VR sessions based on WebXR. The button can be created
* with a factory method and then appended ot the website's DOM.
*
* ```js
* document.body.appendChild( VRButton.createButton( renderer ) );
* ```
*
* @hideconstructor
*/
class VRButton {
/**
* Constructs a new VR button.
*
* @param {WebGLRenderer|WebGPURenderer} renderer - The renderer.
* @param {XRSessionInit} [sessionInit] - The a configuration object for the AR session.
* @return {HTMLElement} The button or an error message if `immersive-ar` isn't supported.
*/
static createButton( renderer, sessionInit = {} ) {

@@ -210,2 +228,7 @@

/**
* Registers a `sessiongranted` event listener. When a session is granted, the {@link VRButton#xrSessionIsGranted}
* flag will evaluate to `true`. This method is automatically called by the module itself so there
* should be no need to use it on app level.
*/
static registerSessionGrantedListener() {

@@ -231,2 +254,9 @@

/**
* Whether a XR session has been granted or not.
*
* @static
* @type {boolean}
* @default false
*/
VRButton.xrSessionIsGranted = false;

@@ -233,0 +263,0 @@ VRButton.registerSessionGrantedListener();

@@ -0,3 +1,25 @@

/**
* A utility class for creating a button that allows to initiate
* immersive XR sessions based on WebXR. The button can be created
* with a factory method and then appended ot the website's DOM.
*
* ```js
* document.body.appendChild( XRButton.createButton( renderer ) );
* ```
*
* Compared to {@link ARButton} and {@link VRButton}, this class will
* try to offer an immersive AR session first. If the device does not
* support this type of session, it uses an immersive VR session.
*
* @hideconstructor
*/
class XRButton {
/**
* Constructs a new XR button.
*
* @param {WebGLRenderer|WebGPURenderer} renderer - The renderer.
* @param {XRSessionInit} [sessionInit] - The a configuration object for the AR session.
* @return {HTMLElement} The button or an error message if WebXR isn't supported.
*/
static createButton( renderer, sessionInit = {} ) {

@@ -4,0 +26,0 @@

@@ -19,4 +19,12 @@ import {

/**
* Represents a XR controller model.
*
* @augments Object3D
*/
class XRControllerModel extends Object3D {
/**
* Constructs a new XR controller model.
*/
constructor() {

@@ -26,3 +34,16 @@

/**
* The motion controller.
*
* @type {?MotionController}
* @default null
*/
this.motionController = null;
/**
* The controller's environment map.
*
* @type {?Texture}
* @default null
*/
this.envMap = null;

@@ -32,2 +53,8 @@

/**
* Sets an environment map that is applied to the controller model.
*
* @param {?Texture} envMap - The environment map to apply.
* @return {XRControllerModel} A reference to this instance.
*/
setEnvironmentMap( envMap ) {

@@ -58,6 +85,7 @@

/**
* Polls data from the XRInputSource and updates the model's components to match
* the real world data
* Overwritten with a custom implementation. Polls data from the XRInputSource and updates the
* model's components to match the real world data.
*
* @param {boolean} force
* @param {boolean} [force=false] - When set to `true`, a recomputation of world matrices is forced even
* when {@link Object3D#matrixWorldAutoUpdate} is set to `false`.
*/

@@ -119,2 +147,3 @@ updateMatrixWorld( force ) {

*
* @private
* @param {MotionController} motionController

@@ -217,9 +246,52 @@ * @param {Object3D} scene

/**
* Allows to create controller models for WebXR controllers that can be added as a visual
* representation to your scene. `XRControllerModelFactory` will automatically fetch controller
* models that match what the user is holding as closely as possible. The models should be
* attached to the object returned from getControllerGrip in order to match the orientation of
* the held device.
*
* This module depends on the [motion-controllers]{@link https://github.com/immersive-web/webxr-input-profiles/blob/main/packages/motion-controllers/README.md}
* third-part library.
*
* ```js
* const controllerModelFactory = new XRControllerModelFactory();
*
* const controllerGrip = renderer.xr.getControllerGrip( 0 );
* controllerGrip.add( controllerModelFactory.createControllerModel( controllerGrip ) );
* scene.add( controllerGrip );
* ```
*/
class XRControllerModelFactory {
/**
* Constructs a new XR controller model factory.
*
* @param {?GLTFLoader} [gltfLoader=null] - A glTF loader that is used to load controller models.
* @param {?Function} [onLoad=null] - A callback that is executed when a controller model has been loaded.
*/
constructor( gltfLoader = null, onLoad = null ) {
/**
* A glTF loader that is used to load controller models.
*
* @type {?GLTFLoader}
* @default null
*/
this.gltfLoader = gltfLoader;
/**
* The path to the model repository.
*
* @type {string}
*/
this.path = DEFAULT_PROFILES_PATH;
this._assetCache = {};
/**
* A callback that is executed when a controller model has been loaded.
*
* @type {?Function}
* @default null
*/
this.onLoad = onLoad;

@@ -236,2 +308,8 @@

/**
* Sets the path to the model repository.
*
* @param {string} path - The path to set.
* @return {XRControllerModelFactory} A reference to this instance.
*/
setPath( path ) {

@@ -245,2 +323,8 @@

/**
* Creates a controller model for the given WebXR controller.
*
* @param {Group} controller - The controller.
* @return {XRControllerModel} The XR controller model.
*/
createControllerModel( controller ) {

@@ -247,0 +331,0 @@

@@ -136,4 +136,16 @@ import {

/**
* This class can be used to represent the environmental light of
* a XR session. It relies on the WebXR Lighting Estimation API.
*
* @augments Group
*/
export class XREstimatedLight extends Group {
/**
* Constructs a new light.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {boolean} [environmentEstimation=true] - Whether to use environment estimation or not.
*/
constructor( renderer, environmentEstimation = true ) {

@@ -143,2 +155,7 @@

/**
* The light probe that represents the estimated light.
*
* @type {LightProbe}
*/
this.lightProbe = new LightProbe();

@@ -148,2 +165,7 @@ this.lightProbe.intensity = 0;

/**
* Represents the primary light from the XR environment.
*
* @type {DirectionalLight}
*/
this.directionalLight = new DirectionalLight();

@@ -153,4 +175,9 @@ this.directionalLight.intensity = 0;

// Will be set to a cube map in the SessionLightProbe if environment estimation is
// available and requested.
/**
* Will be set to a cube map in the SessionLightProbe if environment estimation is
* available and requested.
*
* @type {?Texture}
* @default null
*/
this.environment = null;

@@ -205,3 +232,6 @@

// Done inline to provide access to sessionLightProbe.
/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*/
this.dispose = () => {

@@ -208,0 +238,0 @@

@@ -5,9 +5,41 @@ import { GLTFLoader } from '../loaders/GLTFLoader.js';

/**
* Represents one of the hand model types {@link XRHandModelFactory} might produce
* depending on the selected profile. `XRHandMeshModel` represents a hand with a
* custom asset.
*/
class XRHandMeshModel {
/**
* Constructs a new XR hand mesh model.
*
* @param {XRHandModel} handModel - The hand model.
* @param {Group} controller - The WebXR controller.
* @param {?string} path - The model path.
* @param {XRHandedness} handedness - The handedness of the XR input source.
* @param {?Loader} [loader=null] - The loader. If not provided, an instance of `GLTFLoader` will be used to load models.
* @param {?Function} [onLoad=null] - A callback that is executed when a controller model has been loaded.
*/
constructor( handModel, controller, path, handedness, loader = null, onLoad = null ) {
/**
* The WebXR controller.
*
* @type {Group}
*/
this.controller = controller;
/**
* The hand model.
*
* @type {XRHandModel}
*/
this.handModel = handModel;
/**
* An array of bones representing the bones
* of the hand skeleton.
*
* @type {Array<Bone>}
*/
this.bones = [];

@@ -84,2 +116,5 @@

/**
* Updates the mesh based on the tracked XR joints data.
*/
updateMesh() {

@@ -86,0 +121,0 @@

@@ -13,4 +13,14 @@ import {

/**
* Represents a XR hand model.
*
* @augments Object3D
*/
class XRHandModel extends Object3D {
/**
* Constructs a new XR hand model.
*
* @param {Group} controller - The hand controller.
*/
constructor( controller ) {

@@ -20,6 +30,31 @@

/**
* The hand controller.
*
* @type {Group}
*/
this.controller = controller;
/**
* The motion controller.
*
* @type {?MotionController}
* @default null
*/
this.motionController = null;
/**
* The controller's environment map.
*
* @type {?Texture}
* @default null
*/
this.envMap = null;
/**
* The model mesh.
*
* @type {Mesh}
* @default null
*/
this.mesh = null;

@@ -29,2 +64,8 @@

/**
* Overwritten with a custom implementation. Makes sure the motion controller updates the mesh.
*
* @param {boolean} [force=false] - When set to `true`, a recomputation of world matrices is forced even
* when {@link Object3D#matrixWorldAutoUpdate} is set to `false`.
*/
updateMatrixWorld( force ) {

@@ -44,8 +85,46 @@

/**
* Similar to {@link XRControllerModelFactory}, this class allows to create hand models
* for WebXR controllers that can be added as a visual representation to your scene.
*
* ```js
* const handModelFactory = new XRHandModelFactory();
*
* const hand = renderer.xr.getHand( 0 );
* hand.add( handModelFactory.createHandModel( hand ) );
* scene.add( hand );
* ```
*/
class XRHandModelFactory {
/**
* Constructs a new XR hand model factory.
*
* @param {?GLTFLoader} [gltfLoader=null] - A glTF loader that is used to load hand models.
* @param {?Function} [onLoad=null] - A callback that is executed when a hand model has been loaded.
*/
constructor( gltfLoader = null, onLoad = null ) {
/**
* A glTF loader that is used to load hand models.
*
* @type {?GLTFLoader}
* @default null
*/
this.gltfLoader = gltfLoader;
/**
* The path to the model repository.
*
* @type {?string}
* @default null
*/
this.path = null;
/**
* A callback that is executed when a hand model has been loaded.
*
* @type {?Function}
* @default null
*/
this.onLoad = onLoad;

@@ -55,2 +134,8 @@

/**
* Sets the path to the hand model repository.
*
* @param {string} path - The path to set.
* @return {XRHandModelFactory} A reference to this instance.
*/
setPath( path ) {

@@ -64,2 +149,9 @@

/**
* Creates a controller model for the given WebXR hand controller.
*
* @param {Group} controller - The hand controller.
* @param {('spheres'|'boxes'|'mesh')} [profile] - The model profile that defines the model type.
* @return {XRHandModel} The XR hand model.
*/
createHandModel( controller, profile ) {

@@ -66,0 +158,0 @@

@@ -14,8 +14,40 @@ import {

/**
* Represents one of the hand model types {@link XRHandModelFactory} might produce
* depending on the selected profile. `XRHandPrimitiveModel` represents a hand
* with sphere or box primitives according to the selected `primitive` option.
*/
class XRHandPrimitiveModel {
/**
* Constructs a new XR hand primitive model.
*
* @param {XRHandModel} handModel - The hand model.
* @param {Group} controller - The WebXR controller.
* @param {string} path - The model path.
* @param {XRHandedness} handedness - The handedness of the XR input source.
* @param {XRHandPrimitiveModel~Options} options - The model options.
*/
constructor( handModel, controller, path, handedness, options ) {
/**
* The WebXR controller.
*
* @type {Group}
*/
this.controller = controller;
/**
* The hand model.
*
* @type {XRHandModel}
*/
this.handModel = handModel;
/**
* The model's environment map.
*
* @type {?Texture}
* @default null
*/
this.envMap = null;

@@ -74,2 +106,5 @@

/**
* Updates the mesh based on the tracked XR joints data.
*/
updateMesh() {

@@ -105,2 +140,9 @@

/**
* Constructor options of `XRHandPrimitiveModel`.
*
* @typedef {Object} XRHandPrimitiveModel~Options
* @property {('box'|'sphere')} [primitive] - The primitive type.
**/
export { XRHandPrimitiveModel };

@@ -9,4 +9,21 @@ import {

/**
* A utility class for the WebXR Plane Detection Module. If planes
* are detected by WebXR, this class will automatically add them
* as thin box meshes to the scene when below code snippet is used.
*
* ```js
* const planes = new XRPlanes( renderer );
* scene.add( planes );
* ```
*
* @augments Object3D
*/
class XRPlanes extends Object3D {
/**
* Constructs a new XR plane container.
*
* @param {WebGLRenderer|WebGPURenderer} renderer - The renderer.
*/
constructor( renderer ) {

@@ -13,0 +30,0 @@

{
"name": "three",
"version": "0.174.0",
"version": "0.175.0",
"description": "JavaScript 3D library",

@@ -5,0 +5,0 @@ "type": "module",

import { WrapAroundEnding, ZeroCurvatureEnding, ZeroSlopeEnding, LoopPingPong, LoopOnce, LoopRepeat, NormalAnimationBlendMode, AdditiveAnimationBlendMode } from '../constants.js';
/**
* An instance of `AnimationAction` schedules the playback of an animation which is
* stored in {@link AnimationClip}.
*/
class AnimationAction {
/**
* Constructs a new animation action.
*
* @param {AnimationMixer} mixer - The mixer that is controlled by this action.
* @param {AnimationClip} clip - The animation clip that holds the actual keyframes.
* @param {?Object3D} [localRoot=null] - The root object on which this action is performed.
* @param {(NormalAnimationBlendMode|AdditiveAnimationBlendMode)} [blendMode] - The blend mode.
*/
constructor( mixer, clip, localRoot = null, blendMode = clip.blendMode ) {

@@ -11,2 +22,9 @@

this._localRoot = localRoot;
/**
* Defines how the animation is blended/combined when two or more animations
* are simultaneously played.
*
* @type {(NormalAnimationBlendMode|AdditiveAnimationBlendMode)}
*/
this.blendMode = blendMode;

@@ -44,2 +62,8 @@

/**
* The loop mode, set via {@link AnimationAction#setLoop}.
*
* @type {(LoopRepeat|LoopOnce|LoopPingPong)}
* @default LoopRepeat
*/
this.loop = LoopRepeat;

@@ -52,26 +76,103 @@ this._loopCount = - 1;

// scaled local time of the action
// gets clamped or wrapped to 0..clip.duration according to loop
/**
* The local time of this action (in seconds, starting with `0`).
*
* The value gets clamped or wrapped to `[0,clip.duration]` (according to the
* loop state).
*
* @type {number}
* @default Infinity
*/
this.time = 0;
/**
* Scaling factor for the {@link AnimationAction#time}. A value of `0` causes the
* animation to pause. Negative values cause the animation to play backwards.
*
* @type {number}
* @default 1
*/
this.timeScale = 1;
this._effectiveTimeScale = 1;
/**
* The degree of influence of this action (in the interval `[0, 1]`). Values
* between `0` (no impact) and `1` (full impact) can be used to blend between
* several actions.
*
* @type {number}
* @default 1
*/
this.weight = 1;
this._effectiveWeight = 1;
this.repetitions = Infinity; // no. of repetitions when looping
/**
* The number of repetitions of the performed clip over the course of this action.
* Can be set via {@link AnimationAction#setLoop}.
*
* Setting this number has no effect if {@link AnimationAction#loop} is set to
* `THREE:LoopOnce`.
*
* @type {number}
* @default Infinity
*/
this.repetitions = Infinity;
this.paused = false; // true -> zero effective time scale
this.enabled = true; // false -> zero effective weight
/**
* If set to `true`, the playback of the action is paused.
*
* @type {boolean}
* @default false
*/
this.paused = false;
this.clampWhenFinished = false;// keep feeding the last frame?
/**
* If set to `false`, the action is disabled so it has no impact.
*
* When the action is re-enabled, the animation continues from its current
* time (setting `enabled` to `false` doesn't reset the action).
*
* @type {boolean}
* @default true
*/
this.enabled = true;
this.zeroSlopeAtStart = true;// for smooth interpolation w/o separate
this.zeroSlopeAtEnd = true;// clips for start, loop and end
/**
* If set to true the animation will automatically be paused on its last frame.
*
* If set to false, {@link AnimationAction#enabled} will automatically be switched
* to `false` when the last loop of the action has finished, so that this action has
* no further impact.
*
* Note: This member has no impact if the action is interrupted (it
* has only an effect if its last loop has really finished).
*
* @type {boolean}
* @default false
*/
this.clampWhenFinished = false;
/**
* Enables smooth interpolation without separate clips for start, loop and end.
*
* @type {boolean}
* @default true
*/
this.zeroSlopeAtStart = true;
/**
* Enables smooth interpolation without separate clips for start, loop and end.
*
* @type {boolean}
* @default true
*/
this.zeroSlopeAtEnd = true;
}
// State & Scheduling
/**
* Starts the playback of the animation.
*
* @return {AnimationAction} A reference to this animation action.
*/
play() {

@@ -85,2 +186,7 @@

/**
* Stops the playback of the animation.
*
* @return {AnimationAction} A reference to this animation action.
*/
stop() {

@@ -94,2 +200,7 @@

/**
* Resets the playback of the animation.
*
* @return {AnimationAction} A reference to this animation action.
*/
reset() {

@@ -108,2 +219,7 @@

/**
* Returns `true` if the animation is running.
*
* @return {boolean} Whether the animation is running or not.
*/
isRunning() {

@@ -116,3 +232,7 @@

// return true when play has been called
/**
* Returns `true` when {@link AnimationAction#play} has been called.
*
* @return {boolean} Whether the animation is scheduled or not.
*/
isScheduled() {

@@ -124,2 +244,8 @@

/**
* Defines the time when the animation should start.
*
* @param {number} time - The start time in seconds.
* @return {AnimationAction} A reference to this animation action.
*/
startAt( time ) {

@@ -133,2 +259,9 @@

/**
* Configures the loop settings for this action.
*
* @param {(LoopRepeat|LoopOnce|LoopPingPong)} mode - The loop mode.
* @param {number} repetitions - The number of repetitions.
* @return {AnimationAction} A reference to this animation action.
*/
setLoop( mode, repetitions ) {

@@ -143,7 +276,11 @@

// Weight
// set the weight stopping any scheduled fading
// although .enabled = false yields an effective weight of zero, this
// method does *not* change .enabled, because it would be confusing
/**
* Sets the effective weight of this action.
*
* An action has no effect and thus an effective weight of zero when the
* action is disabled.
*
* @param {number} weight - The weight to set.
* @return {AnimationAction} A reference to this animation action.
*/
setEffectiveWeight( weight ) {

@@ -160,3 +297,7 @@

// return the weight considering fading and .enabled
/**
* Returns the effective weight of this action.
*
* @return {number} The effective weight.
*/
getEffectiveWeight() {

@@ -168,2 +309,9 @@

/**
* Fades the animation in by increasing its weight gradually from `0` to `1`,
* within the passed time interval.
*
* @param {number} duration - The duration of the fade.
* @return {AnimationAction} A reference to this animation action.
*/
fadeIn( duration ) {

@@ -175,2 +323,9 @@

/**
* Fades the animation out by decreasing its weight gradually from `1` to `0`,
* within the passed time interval.
*
* @param {number} duration - The duration of the fade.
* @return {AnimationAction} A reference to this animation action.
*/
fadeOut( duration ) {

@@ -182,3 +337,12 @@

crossFadeFrom( fadeOutAction, duration, warp ) {
/**
* Causes this action to fade in and the given action to fade out,
* within the passed time interval.
*
* @param {AnimationAction} fadeOutAction - The animation action to fade out.
* @param {number} duration - The duration of the fade.
* @param {boolean} [warp=false] - Whether warping should be used or not.
* @return {AnimationAction} A reference to this animation action.
*/
crossFadeFrom( fadeOutAction, duration, warp = false ) {

@@ -188,3 +352,3 @@ fadeOutAction.fadeOut( duration );

if ( warp ) {
if ( warp === true ) {

@@ -206,3 +370,12 @@ const fadeInDuration = this._clip.duration,

crossFadeTo( fadeInAction, duration, warp ) {
/**
* Causes this action to fade out and the given action to fade in,
* within the passed time interval.
*
* @param {AnimationAction} fadeInAction - The animation action to fade in.
* @param {number} duration - The duration of the fade.
* @param {boolean} [warp=false] - Whether warping should be used or not.
* @return {AnimationAction} A reference to this animation action.
*/
crossFadeTo( fadeInAction, duration, warp = false ) {

@@ -213,2 +386,7 @@ return fadeInAction.crossFadeFrom( this, duration, warp );

/**
* Stops any fading which is applied to this action.
*
* @return {AnimationAction} A reference to this animation action.
*/
stopFading() {

@@ -229,7 +407,11 @@

// Time Scale Control
// set the time scale stopping any scheduled warping
// although .paused = true yields an effective time scale of zero, this
// method does *not* change .paused, because it would be confusing
/**
* Sets the effective time scale of this action.
*
* An action has no effect and thus an effective time scale of zero when the
* action is paused.
*
* @param {number} timeScale - The time scale to set.
* @return {AnimationAction} A reference to this animation action.
*/
setEffectiveTimeScale( timeScale ) {

@@ -244,3 +426,7 @@

// return the time scale considering warping and .paused
/**
* Returns the effective time scale of this action.
*
* @return {number} The effective time scale.
*/
getEffectiveTimeScale() {

@@ -252,2 +438,8 @@

/**
* Sets the duration for a single loop of this action.
*
* @param {number} duration - The duration to set.
* @return {AnimationAction} A reference to this animation action.
*/
setDuration( duration ) {

@@ -261,2 +453,8 @@

/**
* Synchronizes this action with the passed other action.
*
* @param {AnimationAction} action - The action to sync with.
* @return {AnimationAction} A reference to this animation action.
*/
syncWith( action ) {

@@ -271,2 +469,8 @@

/**
* Decelerates this animation's speed to `0` within the passed time interval.
*
* @param {number} duration - The duration.
* @return {AnimationAction} A reference to this animation action.
*/
halt( duration ) {

@@ -278,2 +482,12 @@

/**
* Changes the playback speed, within the passed time interval, by modifying
* {@link AnimationAction#timeScale} gradually from `startTimeScale` to
* `endTimeScale`.
*
* @param {number} startTimeScale - The start time scale.
* @param {number} endTimeScale - The end time scale.
* @param {number} duration - The duration.
* @return {AnimationAction} A reference to this animation action.
*/
warp( startTimeScale, endTimeScale, duration ) {

@@ -307,2 +521,7 @@

/**
* Stops any scheduled warping which is applied to this action.
*
* @return {AnimationAction} A reference to this animation action.
*/
stopWarping() {

@@ -323,4 +542,7 @@

// Object Accessors
/**
* Returns the animation mixer of this animation action.
*
* @return {AnimationMixer} The animation mixer.
*/
getMixer() {

@@ -332,2 +554,7 @@

/**
* Returns the animation clip of this animation action.
*
* @return {AnimationClip} The animation clip.
*/
getClip() {

@@ -339,2 +566,7 @@

/**
* Returns the root object of this animation action.
*
* @return {Object3D} The root object.
*/
getRoot() {

@@ -341,0 +573,0 @@

@@ -12,11 +12,58 @@ import * as AnimationUtils from './AnimationUtils.js';

/**
* A reusable set of keyframe tracks which represent an animation.
*/
class AnimationClip {
/**
* Constructs a new animation clip.
*
* Note: Instead of instantiating an AnimationClip directly with the constructor, you can
* use the static interface of this class for creating clips. In most cases though, animation clips
* will automatically be created by loaders when importing animated 3D assets.
*
* @param {string} [name=''] - The clip's name.
* @param {number} [duration=-1] - The clip's duration in seconds. If a negative value is passed,
* the duration will be calculated from the passed keyframes.
* @param {Array<KeyframeTrack>} tracks - An array of keyframe tracks.
* @param {(NormalAnimationBlendMode|AdditiveAnimationBlendMode)} [blendMode=NormalAnimationBlendMode] - Defines how the animation
* is blended/combined when two or more animations are simultaneously played.
*/
constructor( name = '', duration = - 1, tracks = [], blendMode = NormalAnimationBlendMode ) {
/**
* The clip's name.
*
* @type {string}
*/
this.name = name;
/**
* An array of keyframe tracks.
*
* @type {Array<KeyframeTrack>}
*/
this.tracks = tracks;
/**
* The clip's duration in seconds.
*
* @type {number}
*/
this.duration = duration;
/**
* Defines how the animation is blended/combined when two or more animations
* are simultaneously played.
*
* @type {(NormalAnimationBlendMode|AdditiveAnimationBlendMode)}
*/
this.blendMode = blendMode;
/**
* The UUID of the animation clip.
*
* @type {string}
* @readonly
*/
this.uuid = generateUUID();

@@ -33,3 +80,9 @@

/**
* Factory method for creating an animation clip from the given JSON.
*
* @static
* @param {Object} json - The serialized animation clip.
* @return {AnimationClip} The new animation clip.
*/
static parse( json ) {

@@ -54,2 +107,9 @@

/**
* Serializes the given animation clip into JSON.
*
* @static
* @param {AnimationClip} clip - The animation clip to serialize.
* @return {Object} The JSON object.
*/
static toJSON( clip ) {

@@ -80,2 +140,16 @@

/**
* Returns a new animation clip from the passed morph targets array of a
* geometry, taking a name and the number of frames per second.
*
* Note: The fps parameter is required, but the animation speed can be
* overridden via {@link AnimationAction#setDuration}.
*
* @static
* @param {string} name - The name of the animation clip.
* @param {Array<Object>} morphTargetSequence - A sequence of morph targets.
* @param {number} fps - The Frames-Per-Second value.
* @param {boolean} noLoop - Whether the clip should be no loop or not.
* @return {AnimationClip} The new animation clip.
*/
static CreateFromMorphTargetSequence( name, morphTargetSequence, fps, noLoop ) {

@@ -123,2 +197,12 @@

/**
* Searches for an animation clip by name, taking as its first parameter
* either an array of clips, or a mesh or geometry that contains an
* array named "animations" property.
*
* @static
* @param {(Array<AnimationClip>|Object3D)} objectOrClipArray - The array or object to search through.
* @param {string} name - The name to search for.
* @return {?AnimationClip} The found animation clip. Returns `null` if no clip has been found.
*/
static findByName( objectOrClipArray, name ) {

@@ -149,2 +233,15 @@

/**
* Returns an array of new AnimationClips created from the morph target
* sequences of a geometry, trying to sort morph target names into
* animation-group-based patterns like "Walk_001, Walk_002, Run_001, Run_002...".
*
* See {@link MD2Loader#parse} as an example for how the method should be used.
*
* @static
* @param {Array<Object>} morphTargets - A sequence of morph targets.
* @param {number} fps - The Frames-Per-Second value.
* @param {boolean} noLoop - Whether the clip should be no loop or not.
* @return {Array<AnimationClip>} An array of new animation clips.
*/
static CreateClipsFromMorphTargetSequences( morphTargets, fps, noLoop ) {

@@ -195,5 +292,15 @@

// parse the animation.hierarchy format
/**
* Parses the `animation.hierarchy` format and returns a new animation clip.
*
* @static
* @deprecated since r175.
* @param {Object} animation - A serialized animation clip as JSON.
* @param {Array<Bones>} bones - An array of bones.
* @return {?AnimationClip} The new animation clip.
*/
static parseAnimation( animation, bones ) {
console.warn( 'THREE.AnimationClip: parseAnimation() is deprecated and will be removed with r185' );
if ( ! animation ) {

@@ -324,2 +431,7 @@

/**
* Sets the duration of this clip to the duration of its longest keyframe track.
*
* @return {AnimationClip} A reference to this animation clip.
*/
resetDuration() {

@@ -344,2 +456,7 @@

/**
* Trims all tracks to the clip's duration.
*
* @return {AnimationClip} A reference to this animation clip.
*/
trim() {

@@ -357,2 +474,8 @@

/**
* Performs minimal validation on each track in the clip. Returns `true` if all
* tracks are valid.
*
* @return {boolean} Whether the clip's keyframes are valid or not.
*/
validate() {

@@ -372,2 +495,8 @@

/**
* Optimizes each track by removing equivalent sequential keys (which are
* common in morph target sequences).
*
* @return {AnimationClip} A reference to this animation clip.
*/
optimize() {

@@ -385,2 +514,7 @@

/**
* Returns a new animation clip with copied values from this instance.
*
* @return {AnimationClip} A clone of this instance.
*/
clone() {

@@ -400,2 +534,7 @@

/**
* Serializes this animation clip into JSON.
*
* @return {Object} The JSON object.
*/
toJSON() {

@@ -402,0 +541,0 @@

@@ -9,8 +9,16 @@ import { AnimationAction } from './AnimationAction.js';

const _controlInterpolantsResultBuffer = new Float32Array( 1 );
/**
* `AnimationMixer` is a player for animations on a particular object in
* the scene. When multiple objects in the scene are animated independently,
* one `AnimationMixer` may be used for each object.
*/
class AnimationMixer extends EventDispatcher {
/**
* Constructs a new animation mixer.
*
* @param {Object3D} root - The object whose animations shall be played by this mixer.
*/
constructor( root ) {

@@ -23,3 +31,21 @@

this._accuIndex = 0;
/**
* The global mixer time (in seconds; starting with `0` on the mixer's creation).
*
* @type {number}
* @default 0
*/
this.time = 0;
/**
* A scaling factor for the global time.
*
* Note: Setting this member to `0` and later back to `1` is a
* possibility to pause/unpause all actions that are controlled by this
* mixer.
*
* @type {number}
* @default 1
*/
this.timeScale = 1.0;

@@ -515,5 +541,14 @@

// return an action for a clip optionally using a custom root target
// object (this method allocates a lot of dynamic memory in case a
// previously unknown clip/root combination is specified)
/**
* Returns an instance of {@link AnimationAction} for the passed clip.
*
* If an action fitting the clip and root parameters doesn't yet exist, it
* will be created by this method. Calling this method several times with the
* same clip and root parameters always returns the same action.
*
* @param {AnimationClip|string} clip - An animation clip or alternatively the name of the animation clip.
* @param {Object3D} [optionalRoot] - An alternative root object.
* @param {(NormalAnimationBlendMode|AdditiveAnimationBlendMode)} [blendMode] - The blend mode.
* @return {?AnimationAction} The animation action.
*/
clipAction( clip, optionalRoot, blendMode ) {

@@ -580,3 +615,9 @@

// get an existing action
/**
* Returns an existing animation action for the passed clip.
*
* @param {AnimationClip|string} clip - An animation clip or alternatively the name of the animation clip.
* @param {Object3D} [optionalRoot] - An alternative root object.
* @return {?AnimationAction} The animation action. Returns `null` if no action was found.
*/
existingAction( clip, optionalRoot ) {

@@ -604,3 +645,7 @@

// deactivates all previously scheduled actions
/**
* Deactivates all previously scheduled actions on this mixer.
*
* @return {AnimationMixer} A reference to thi animation mixer.
*/
stopAllAction() {

@@ -621,3 +666,11 @@

// advance the time and update apply the animation
/**
* Advances the global mixer time and updates the animation.
*
* This is usually done in the render loop by passing the delta
* time from {@link Clock} or {@link Timer}.
*
* @param {number} deltaTime - The delta time in seconds.
* @return {AnimationMixer} A reference to thi animation mixer.
*/
update( deltaTime ) {

@@ -660,4 +713,12 @@

// Allows you to seek to a specific time in an animation.
setTime( timeInSeconds ) {
/**
* Sets the global mixer to a specific time and updates the animation accordingly.
*
* This is useful when you need to jump to an exact time in an animation. The
* input parameter will be scaled by {@link AnimationMixer#timeScale}
*
* @param {number} time - The time to set in seconds.
* @return {AnimationMixer} A reference to thi animation mixer.
*/
setTime( time ) {

@@ -671,7 +732,11 @@ this.time = 0; // Zero out time attribute for AnimationMixer object;

return this.update( timeInSeconds ); // Update used to set exact time. Returns "this" AnimationMixer object.
return this.update( time ); // Update used to set exact time. Returns "this" AnimationMixer object.
}
// return this mixer's root target object
/**
* Returns this mixer's root object.
*
* @return {Object3D} The mixer's root object.
*/
getRoot() {

@@ -683,3 +748,8 @@

// free all resources specific to a particular clip
/**
* Deallocates all memory resources for a clip. Before using this method make
* sure to call {@link AnimationAction#stop} for all related actions.
*
* @param {AnimationClip} clip - The clip to uncache.
*/
uncacheClip( clip ) {

@@ -726,3 +796,10 @@

// free all resources specific to a particular root target object
/**
* Deallocates all memory resources for a root object. Before using this
* method make sure to call {@link AnimationAction#stop} for all related
* actions or alternatively {@link AnimationMixer#stopAllAction} when the
* mixer operates on a single root.
*
* @param {Object3D} root - The root object to uncache.
*/
uncacheRoot( root ) {

@@ -764,3 +841,10 @@

// remove a targeted clip from the cache
/**
* Deallocates all memory resources for an action. The action is identified by the
* given clip and an optional root object. Before using this method make
* sure to call {@link AnimationAction#stop} to deactivate the action.
*
* @param {AnimationClip|string} clip - An animation clip or alternatively the name of the animation clip.
* @param {Object3D} [optionalRoot] - An alternative root object.
*/
uncacheAction( clip, optionalRoot ) {

@@ -767,0 +851,0 @@

@@ -5,3 +5,2 @@ import { PropertyBinding } from './PropertyBinding.js';

/**
*
* A group of objects that receives a shared animation state.

@@ -11,31 +10,41 @@ *

*
* - Add objects you would otherwise pass as 'root' to the
* constructor or the .clipAction method of AnimationMixer.
* - Add objects you would otherwise pass as 'root' to the
* constructor or the .clipAction method of AnimationMixer.
* - Instead pass this object as 'root'.
* - You can also add and remove objects later when the mixer is running.
*
* - Instead pass this object as 'root'.
*
* - You can also add and remove objects later when the mixer
* is running.
*
* Note:
*
* Objects of this class appear as one object to the mixer,
* so cache control of the individual objects must be done
* on the group.
* - Objects of this class appear as one object to the mixer,
* so cache control of the individual objects must be done on the group.
*
* Limitation:
*
* - The animated properties must be compatible among the
* all objects in the group.
*
* - A single property can either be controlled through a
* target group or directly, but not both.
* - The animated properties must be compatible among the all objects in the group.
* - A single property can either be controlled through a target group or directly, but not both.
*/
class AnimationObjectGroup {
/**
* Constructs a new animation group.
*
* @param {...Object3D} arguments - An arbitrary number of 3D objects that share the same animation state.
*/
constructor() {
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isAnimationObjectGroup = true;
/**
* The UUID of the 3D object.
*
* @type {string}
* @readonly
*/
this.uuid = generateUUID();

@@ -89,2 +98,7 @@

/**
* Adds an arbitrary number of objects to this animation group.
*
* @param {...Object3D} arguments - The 3D objects to add.
*/
add() {

@@ -178,2 +192,7 @@

/**
* Removes an arbitrary number of objects to this animation group
*
* @param {...Object3D} arguments - The 3D objects to remove.
*/
remove() {

@@ -228,3 +247,7 @@

// remove & forget
/**
* Deallocates all memory resources for the passed 3D objects of this animation group.
*
* @param {...Object3D} arguments - The 3D objects to uncache.
*/
uncache() {

@@ -231,0 +254,0 @@

import { Quaternion } from '../math/Quaternion.js';
import { AdditiveAnimationBlendMode } from '../constants.js';
// converts an array to a specific type
function convertArray( array, type, forceClone ) {
/**
* Converts an array to a specific type.
*
* @param {TypedArray|Array} array - The array to convert.
* @param {TypedArray.constructor} type - The constructor of a typed array that defines the new type.
* @return {TypedArray} The converted array.
*/
function convertArray( array, type ) {
if ( ! array || // let 'undefined' and 'null' pass
! forceClone && array.constructor === type ) return array;
if ( ! array || array.constructor === type ) return array;

@@ -20,10 +25,20 @@ if ( typeof type.BYTES_PER_ELEMENT === 'number' ) {

/**
* Returns `true` if the given object is a typed array.
*
* @param {any} object - The object to check.
* @return {boolean} Whether the given object is a typed array.
*/
function isTypedArray( object ) {
return ArrayBuffer.isView( object ) &&
! ( object instanceof DataView );
return ArrayBuffer.isView( object ) && ! ( object instanceof DataView );
}
// returns an array by which times and values can be sorted
/**
* Returns an array by which times and values can be sorted.
*
* @param {Array<number>} times - The keyframe time values.
* @return {Array<number>} The array.
*/
function getKeyframeOrder( times ) {

@@ -47,3 +62,10 @@

// uses the array previously returned by 'getKeyframeOrder' to sort data
/**
* Sorts the given array by the previously computed order via `getKeyframeOrder()`.
*
* @param {Array<number>} values - The values to sort.
* @param {number} stride - The stride.
* @param {Array<number>} order - The sort order.
* @return {Array<number>} The sorted values.
*/
function sortedArray( values, stride, order ) {

@@ -70,3 +92,10 @@

// function for parsing AOS keyframe formats
/**
* Used for parsing AOS keyframe formats.
*
* @param {Array<number>} jsonKeys - A list of JSON keyframes.
* @param {Array<number>} times - This array will be filled with keyframe times by this function.
* @param {Array<number>} values - This array will be filled with keyframe values by this function.
* @param {string} valuePropertyName - The name of the property to use.
*/
function flattenJSON( jsonKeys, times, values, valuePropertyName ) {

@@ -146,2 +175,12 @@

/**
* Creates a new clip, containing only the segment of the original clip between the given frames.
*
* @param {AnimationClip} sourceClip - The values to sort.
* @param {string} name - The name of the clip.
* @param {number} startFrame - The start frame.
* @param {number} endFrame - The end frame.
* @param {number} [fps=30] - The FPS.
* @return {AnimationClip} The new sub clip.
*/
function subclip( sourceClip, name, startFrame, endFrame, fps = 30 ) {

@@ -218,2 +257,11 @@

/**
* Converts the keyframes of the given animation clip to an additive format.
*
* @param {AnimationClip} targetClip - The clip to make additive.
* @param {number} [referenceFrame=0] - The reference frame.
* @param {AnimationClip} [referenceClip=targetClip] - The reference clip.
* @param {number} [fps=30] - The FPS.
* @return {AnimationClip} The updated clip which is now additive.
*/
function makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) {

@@ -342,12 +390,114 @@

const AnimationUtils = {
convertArray: convertArray,
isTypedArray: isTypedArray,
getKeyframeOrder: getKeyframeOrder,
sortedArray: sortedArray,
flattenJSON: flattenJSON,
subclip: subclip,
makeClipAdditive: makeClipAdditive
};
/**
* A class with various methods to assist with animations.
*
* @hideconstructor
*/
class AnimationUtils {
/**
* Converts an array to a specific type
*
* @static
* @param {TypedArray|Array} array - The array to convert.
* @param {TypedArray.constructor} type - The constructor of a type array.
* @return {TypedArray} The converted array
*/
static convertArray( array, type ) {
return convertArray( array, type );
}
/**
* Returns `true` if the given object is a typed array.
*
* @static
* @param {any} object - The object to check.
* @return {boolean} Whether the given object is a typed array.
*/
static isTypedArray( object ) {
return isTypedArray( object );
}
/**
* Returns an array by which times and values can be sorted.
*
* @static
* @param {Array<number>} times - The keyframe time values.
* @return {Array<number>} The array.
*/
static getKeyframeOrder( times ) {
return getKeyframeOrder( times );
}
/**
* Sorts the given array by the previously computed order via `getKeyframeOrder()`.
*
* @static
* @param {Array<number>} values - The values to sort.
* @param {number} stride - The stride.
* @param {Array<number>} order - The sort order.
* @return {Array<number>} The sorted values.
*/
static sortedArray( values, stride, order ) {
return sortedArray( values, stride, order );
}
/**
* Used for parsing AOS keyframe formats.
*
* @static
* @param {Array<number>} jsonKeys - A list of JSON keyframes.
* @param {Array<number>} times - This array will be filled with keyframe times by this method.
* @param {Array<number>} values - This array will be filled with keyframe values by this method.
* @param {string} valuePropertyName - The name of the property to use.
*/
static flattenJSON( jsonKeys, times, values, valuePropertyName ) {
flattenJSON( jsonKeys, times, values, valuePropertyName );
}
/**
* Creates a new clip, containing only the segment of the original clip between the given frames.
*
* @static
* @param {AnimationClip} sourceClip - The values to sort.
* @param {string} name - The name of the clip.
* @param {number} startFrame - The start frame.
* @param {number} endFrame - The end frame.
* @param {number} [fps=30] - The FPS.
* @return {AnimationClip} The new sub clip.
*/
static subclip( sourceClip, name, startFrame, endFrame, fps = 30 ) {
return subclip( sourceClip, name, startFrame, endFrame, fps );
}
/**
* Converts the keyframes of the given animation clip to an additive format.
*
* @static
* @param {AnimationClip} targetClip - The clip to make additive.
* @param {number} [referenceFrame=0] - The reference frame.
* @param {AnimationClip} [referenceClip=targetClip] - The reference clip.
* @param {number} [fps=30] - The FPS.
* @return {AnimationClip} The updated clip which is now additive.
*/
static makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) {
return makeClipAdditive( targetClip, referenceFrame, referenceClip, fps );
}
}
export {

@@ -354,0 +504,0 @@ convertArray,

@@ -11,4 +11,17 @@ import {

/**
* Represents s a timed sequence of keyframes, which are composed of lists of
* times and related values, and which are used to animate a specific property
* of an object.
*/
class KeyframeTrack {
/**
* Constructs a new keyframe track.
*
* @param {string} name - The keyframe track's name.
* @param {Array<number>} times - A list of keyframe times.
* @param {Array<number>} values - A list of keyframe values.
* @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)} [interpolation] - The interpolation type.
*/
constructor( name, times, values, interpolation ) {

@@ -19,5 +32,23 @@

/**
* The track's name can refer to morph targets or bones or
* possibly other values within an animated object. See {@link PropertyBinding#parseTrackName}
* for the forms of strings that can be parsed for property binding.
*
* @type {string}
*/
this.name = name;
/**
* The keyframe times.
*
* @type {Float32Array}
*/
this.times = AnimationUtils.convertArray( times, this.TimeBufferType );
/**
* The keyframe values.
*
* @type {Float32Array}
*/
this.values = AnimationUtils.convertArray( values, this.ValueBufferType );

@@ -29,5 +60,9 @@

// Serialization (in static context, because of constructor invocation
// and automatic invocation of .toJSON):
/**
* Converts the keyframe track to JSON.
*
* @static
* @param {KeyframeTrack} track - The keyframe track to serialize.
* @return {Object} The serialized keyframe track as JSON.
*/
static toJSON( track ) {

@@ -71,2 +106,9 @@

/**
* Factory method for creating a new discrete interpolant.
*
* @static
* @param {TypedArray} [result] - The result buffer.
* @return {DiscreteInterpolant} The new interpolant.
*/
InterpolantFactoryMethodDiscrete( result ) {

@@ -78,2 +120,9 @@

/**
* Factory method for creating a new linear interpolant.
*
* @static
* @param {TypedArray} [result] - The result buffer.
* @return {LinearInterpolant} The new interpolant.
*/
InterpolantFactoryMethodLinear( result ) {

@@ -85,2 +134,9 @@

/**
* Factory method for creating a new smooth interpolant.
*
* @static
* @param {TypedArray} [result] - The result buffer.
* @return {CubicInterpolant} The new interpolant.
*/
InterpolantFactoryMethodSmooth( result ) {

@@ -92,2 +148,8 @@

/**
* Defines the interpolation factor method for this keyframe track.
*
* @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)} interpolation - The interpolation type.
* @return {KeyframeTrack} A reference to this keyframe track.
*/
setInterpolation( interpolation ) {

@@ -150,2 +212,7 @@

/**
* Returns the current interpolation type.
*
* @return {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)} The interpolation type.
*/
getInterpolation() {

@@ -171,2 +238,7 @@

/**
* Returns the value size.
*
* @return {number} The value size.
*/
getValueSize() {

@@ -178,3 +250,8 @@

// move all keyframes either forwards or backwards in time
/**
* Moves all keyframes either forward or backward in time.
*
* @param {number} timeOffset - The offset to move the time values.
* @return {KeyframeTrack} A reference to this keyframe track.
*/
shift( timeOffset ) {

@@ -198,3 +275,8 @@

// scale all keyframe times by a factor (useful for frame <-> seconds conversions)
/**
* Scale all keyframe times by a factor (useful for frame - seconds conversions).
*
* @param {number} timeScale - The time scale.
* @return {KeyframeTrack} A reference to this keyframe track.
*/
scale( timeScale ) {

@@ -218,4 +300,12 @@

// removes keyframes before and after animation without changing any values within the range [startTime, endTime].
// IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
/**
* Removes keyframes before and after animation without changing any values within the defined time range.
*
* Note: The method does not shift around keys to the start of the track time, because for interpolated
* keys this will change their values
*
* @param {number} startTime - The start time.
* @param {number} endTime - The end time.
* @return {KeyframeTrack} A reference to this keyframe track.
*/
trim( startTime, endTime ) {

@@ -263,3 +353,8 @@

// ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
/**
* Performs minimal validation on the keyframe track. Returns `true` if the values
* are valid.
*
* @return {boolean} Whether the keyframes are valid or not.
*/
validate() {

@@ -341,6 +436,12 @@

// removes equivalent sequential keys as common in morph target sequences
// (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
/**
* Optimizes this keyframe track by removing equivalent sequential keys (which are
* common in morph target sequences).
*
* @return {AnimationClip} A reference to this animation clip.
*/
optimize() {
// (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
// times or values may be shared with other tracks, so overwriting is unsafe

@@ -455,2 +556,7 @@ const times = this.times.slice(),

/**
* Returns a new keyframe track with copied values from this instance.
*
* @return {KeyframeTrack} A clone of this instance.
*/
clone() {

@@ -473,6 +579,34 @@

/**
* The value type name.
*
* @type {String}
* @default ''
*/
KeyframeTrack.prototype.ValueTypeName = '';
/**
* The time buffer type of this keyframe track.
*
* @type {TypedArray|Array}
* @default Float32Array.constructor
*/
KeyframeTrack.prototype.TimeBufferType = Float32Array;
/**
* The value buffer type of this keyframe track.
*
* @type {TypedArray|Array}
* @default Float32Array.constructor
*/
KeyframeTrack.prototype.ValueBufferType = Float32Array;
/**
* The default interpolation type of this keyframe track.
*
* @type {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)}
* @default InterpolateLinear
*/
KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear;
export { KeyframeTrack };

@@ -103,11 +103,44 @@ // Characters [].:/ are reserved for track binding syntax.

// become no-ops.
/**
* This holds a reference to a real property in the scene graph; used internally.
*/
class PropertyBinding {
/**
* Constructs a new property binding.
*
* @param {Object} rootNode - The root node.
* @param {string} path - The path.
* @param {?Object} [parsedPath] - The parsed path.
*/
constructor( rootNode, path, parsedPath ) {
/**
* The object path to the animated property.
*
* @type {string}
*/
this.path = path;
/**
* An object holding information about the path.
*
* @type {Object}
*/
this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path );
/**
* The object owns the animated property.
*
* @type {?Object}
*/
this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName );
/**
* The root node.
*
* @type {Object3D|Skeleton}
*/
this.rootNode = rootNode;

@@ -122,2 +155,11 @@

/**
* Factory method for creating a property binding from the given parameters.
*
* @static
* @param {Object} root - The root node.
* @param {string} path - The path.
* @param {?Object} [parsedPath] - The parsed path.
* @return {PropertyBinding|Composite} The created property binding or composite.
*/
static create( root, path, parsedPath ) {

@@ -141,4 +183,4 @@

*
* @param {string} name Node name to be sanitized.
* @return {string}
* @param {string} name - Node name to be sanitized.
* @return {string} The sanitized node name.
*/

@@ -151,2 +193,20 @@ static sanitizeNodeName( name ) {

/**
* Parses the given track name (an object path to an animated property) and
* returns an object with information about the path. Matches strings in the following forms:
*
* - nodeName.property
* - nodeName.property[accessor]
* - nodeName.material.property[accessor]
* - uuid.property[accessor]
* - uuid.objectName[objectIndex].propertyName[propertyIndex]
* - parentName/nodeName.property
* - parentName/parentName/nodeName.property[index]
* - .bone[Armature.DEF_cog].position
* - scene:helium_balloon_model:helium_balloon_model.position
*
* @static
* @param {string} trackName - The track name to parse.
* @return {Object} The parsed track name as an object.
*/
static parseTrackName( trackName ) {

@@ -200,2 +260,11 @@

/**
* Searches for a node in the hierarchy of the given root object by the given
* node name.
*
* @static
* @param {Object} root - The root object.
* @param {string|number} nodeName - The name of the node.
* @return {?Object} The found node. Returns `null` if no object was found.
*/
static findNode( root, nodeName ) {

@@ -419,3 +488,5 @@

// create getter / setter pair for a property in the scene graph
/**
* Creates a getter / setter pair for the property tracked by this binding.
*/
bind() {

@@ -653,2 +724,5 @@

/**
* Unbinds the property.
*/
unbind() {

@@ -655,0 +729,0 @@

import { Quaternion } from '../math/Quaternion.js';
/**
* Buffered scene graph property that allows weighted accumulation; used internally.
*/
class PropertyMixer {
/**
* Constructs a new property mixer.
*
* @param {PropertyBinding} binding - The property binding.
* @param {string} typeName - The keyframe track type name.
* @param {number} valueSize - The keyframe track value size.
*/
constructor( binding, typeName, valueSize ) {
/**
* The property binding.
*
* @type {PropertyBinding}
*/
this.binding = binding;
/**
* The keyframe track value size.
*
* @type {number}
*/
this.valueSize = valueSize;

@@ -69,6 +90,32 @@

/**
* TODO
*
* @type {number}
* @default 0
*/
this.cumulativeWeight = 0;
/**
* TODO
*
* @type {number}
* @default 0
*/
this.cumulativeWeightAdditive = 0;
/**
* TODO
*
* @type {number}
* @default 0
*/
this.useCount = 0;
/**
* TODO
*
* @type {number}
* @default 0
*/
this.referenceCount = 0;

@@ -78,3 +125,8 @@

// accumulate data in the 'incoming' region into 'accu<i>'
/**
* Accumulates data in the `incoming` region into `accu<i>`.
*
* @param {number} accuIndex - The accumulation index.
* @param {number} weight - The weight.
*/
accumulate( accuIndex, weight ) {

@@ -117,3 +169,7 @@

// accumulate data in the 'incoming' region into 'add'
/**
* Accumulates data in the `incoming` region into `add`.
*
* @param {number} weight - The weight.
*/
accumulateAdditive( weight ) {

@@ -140,3 +196,7 @@

// apply the state of 'accu<i>' to the binding when accus differ
/**
* Applies the state of `accu<i>` to the binding when accus differ.
*
* @param {number} accuIndex - The accumulation index.
*/
apply( accuIndex ) {

@@ -190,3 +250,6 @@

// remember the state of the bound property and copy it to both accus
/**
* Remembers the state of the bound property and copy it to both accus.
*/
saveOriginalState() {

@@ -218,3 +281,5 @@

// apply the state previously taken via 'saveOriginalState' to the binding
/**
* Applies the state previously taken via {@link PropertyMixer#saveOriginalState} to the binding.
*/
restoreOriginalState() {

@@ -227,2 +292,4 @@

// internals
_setAdditiveIdentityNumeric() {

@@ -229,0 +296,0 @@

@@ -5,7 +5,18 @@ import { InterpolateDiscrete } from '../../constants.js';

/**
* A Track of Boolean keyframe values.
* A track for boolean keyframe values.
*
* @augments KeyframeTrack
*/
class BooleanKeyframeTrack extends KeyframeTrack {
// No interpolation parameter because only InterpolateDiscrete is valid.
/**
* Constructs a new boolean keyframe track.
*
* This keyframe track type has no `interpolation` parameter because the
* interpolation is always discrete.
*
* @param {string} name - The keyframe track's name.
* @param {Array<number>} times - A list of keyframe times.
* @param {Array<number>} values - A list of keyframe values.
*/
constructor( name, times, values ) {

@@ -19,4 +30,24 @@

/**
* The value type name.
*
* @type {String}
* @default 'bool'
*/
BooleanKeyframeTrack.prototype.ValueTypeName = 'bool';
/**
* The value buffer type of this keyframe track.
*
* @type {TypedArray|Array}
* @default Array.constructor
*/
BooleanKeyframeTrack.prototype.ValueBufferType = Array;
/**
* The default interpolation type of this keyframe track.
*
* @type {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)}
* @default InterpolateDiscrete
*/
BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete;

@@ -26,6 +57,2 @@ BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined;

// Note: Actually this track could have a optimized / compressed
// representation of a single value and a custom interpolant that
// computes "firstValue ^ isOdd( index )".
export { BooleanKeyframeTrack };
import { KeyframeTrack } from '../KeyframeTrack.js';
/**
* A Track of keyframe values that represent color.
* A track for color keyframe values.
*
* @augments KeyframeTrack
*/
class ColorKeyframeTrack extends KeyframeTrack {}
class ColorKeyframeTrack extends KeyframeTrack {
/**
* Constructs a new color keyframe track.
*
* @param {string} name - The keyframe track's name.
* @param {Array<number>} times - A list of keyframe times.
* @param {Array<number>} values - A list of keyframe values.
* @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)} [interpolation] - The interpolation type.
*/
constructor( name, times, values, interpolation ) {
super( name, times, values, interpolation );
}
}
/**
* The value type name.
*
* @type {String}
* @default 'color'
*/
ColorKeyframeTrack.prototype.ValueTypeName = 'color';

@@ -12,5 +36,2 @@ // ValueBufferType is inherited

// Note: Very basic implementation and nothing special yet.
// However, this is the place for color space parameterization.
export { ColorKeyframeTrack };
import { KeyframeTrack } from '../KeyframeTrack.js';
/**
* A Track of numeric keyframe values.
* A track for numeric keyframe values.
*
* @augments KeyframeTrack
*/
class NumberKeyframeTrack extends KeyframeTrack {}
class NumberKeyframeTrack extends KeyframeTrack {
/**
* Constructs a new number keyframe track.
*
* @param {string} name - The keyframe track's name.
* @param {Array<number>} times - A list of keyframe times.
* @param {Array<number>} values - A list of keyframe values.
* @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)} [interpolation] - The interpolation type.
*/
constructor( name, times, values, interpolation ) {
super( name, times, values, interpolation );
}
}
/**
* The value type name.
*
* @type {String}
* @default 'number'
*/
NumberKeyframeTrack.prototype.ValueTypeName = 'number';

@@ -9,0 +33,0 @@ // ValueBufferType is inherited

@@ -5,6 +5,29 @@ import { KeyframeTrack } from '../KeyframeTrack.js';

/**
* A Track of quaternion keyframe values.
* A track for Quaternion keyframe values.
*
* @augments KeyframeTrack
*/
class QuaternionKeyframeTrack extends KeyframeTrack {
/**
* Constructs a new Quaternion keyframe track.
*
* @param {string} name - The keyframe track's name.
* @param {Array<number>} times - A list of keyframe times.
* @param {Array<number>} values - A list of keyframe values.
* @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)} [interpolation] - The interpolation type.
*/
constructor( name, times, values, interpolation ) {
super( name, times, values, interpolation );
}
/**
* Overwritten so the method returns Quaternion based interpolant.
*
* @static
* @param {TypedArray} [result] - The result buffer.
* @return {QuaternionLinearInterpolant} The new interpolant.
*/
InterpolantFactoryMethodLinear( result ) {

@@ -18,2 +41,8 @@

/**
* The value type name.
*
* @type {String}
* @default 'quaternion'
*/
QuaternionKeyframeTrack.prototype.ValueTypeName = 'quaternion';

@@ -20,0 +49,0 @@ // ValueBufferType is inherited

@@ -5,7 +5,18 @@ import { InterpolateDiscrete } from '../../constants.js';

/**
* A Track that interpolates Strings
* A track for string keyframe values.
*
* @augments KeyframeTrack
*/
class StringKeyframeTrack extends KeyframeTrack {
// No interpolation parameter because only InterpolateDiscrete is valid.
/**
* Constructs a new string keyframe track.
*
* This keyframe track type has no `interpolation` parameter because the
* interpolation is always discrete.
*
* @param {string} name - The keyframe track's name.
* @param {Array<number>} times - A list of keyframe times.
* @param {Array<number>} values - A list of keyframe values.
*/
constructor( name, times, values ) {

@@ -19,4 +30,24 @@

/**
* The value type name.
*
* @type {String}
* @default 'string'
*/
StringKeyframeTrack.prototype.ValueTypeName = 'string';
/**
* The value buffer type of this keyframe track.
*
* @type {TypedArray|Array}
* @default Array.constructor
*/
StringKeyframeTrack.prototype.ValueBufferType = Array;
/**
* The default interpolation type of this keyframe track.
*
* @type {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)}
* @default InterpolateDiscrete
*/
StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete;

@@ -23,0 +54,0 @@ StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined;

import { KeyframeTrack } from '../KeyframeTrack.js';
/**
* A Track of vectored keyframe values.
* A track for vector keyframe values.
*
* @augments KeyframeTrack
*/
class VectorKeyframeTrack extends KeyframeTrack {}
class VectorKeyframeTrack extends KeyframeTrack {
/**
* Constructs a new vector keyframe track.
*
* @param {string} name - The keyframe track's name.
* @param {Array<number>} times - A list of keyframe times.
* @param {Array<number>} values - A list of keyframe values.
* @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)} [interpolation] - The interpolation type.
*/
constructor( name, times, values, interpolation ) {
super( name, times, values, interpolation );
}
}
/**
* The value type name.
*
* @type {String}
* @default 'vector'
*/
VectorKeyframeTrack.prototype.ValueTypeName = 'vector';

@@ -9,0 +33,0 @@ // ValueBufferType is inherited

@@ -34,3 +34,3 @@ /**

* @param {Audio} audio - The audio to analyze.
* @param {Audio} [fftSize=2048] - The window size in samples that is used when performing a Fast Fourier Transform (FFT) to get frequency domain data.
* @param {number} [fftSize=2048] - The window size in samples that is used when performing a Fast Fourier Transform (FFT) to get frequency domain data.
*/

@@ -37,0 +37,0 @@ constructor( audio, fftSize = 2048 ) {

@@ -53,3 +53,3 @@ import { Vector3 } from '../math/Vector3.js';

*
* Defined via {@AudioListener#setFilter}.
* Defined via {@link AudioListener#setFilter}.
*

@@ -113,3 +113,3 @@ * @type {?AudioNode}

*
* @return {AudioNode} The filter.
* @return {?AudioNode} The filter.
*/

@@ -116,0 +116,0 @@ getFilter() {

@@ -107,3 +107,3 @@ import { Vector3 } from '../math/Vector3.js';

* @param {number} value - The reference distance to set.
* @return {Audio} A reference to this instance.
* @return {PositionalAudio} A reference to this instance.
*/

@@ -133,3 +133,3 @@ setRefDistance( value ) {

* @param {number} value - The rolloff factor.
* @return {Audio} A reference to this instance.
* @return {PositionalAudio} A reference to this instance.
*/

@@ -163,3 +163,3 @@ setRolloffFactor( value ) {

* @param {('linear'|'inverse'|'exponential')} value - The distance model to set.
* @return {Audio} A reference to this instance.
* @return {PositionalAudio} A reference to this instance.
*/

@@ -192,3 +192,3 @@ setDistanceModel( value ) {

* @param {number} value - The max distance.
* @return {Audio} A reference to this instance.
* @return {PositionalAudio} A reference to this instance.
*/

@@ -209,3 +209,3 @@ setMaxDistance( value ) {

* @param {number} coneOuterGain - The amount of volume reduction outside the cone defined by the `coneOuterAngle`. When set to `0`, no sound can be heard.
* @return {Audio} A reference to this instance.
* @return {PositionalAudio} A reference to this instance.
*/

@@ -212,0 +212,0 @@ setDirectionalCone( coneInnerAngle, coneOuterAngle, coneOuterGain ) {

@@ -1,213 +0,1607 @@

export const REVISION = '174';
export const REVISION = '175';
/**
* Represents mouse buttons and interaction types in context of controls.
*
* @type {ConstantsMouse}
* @constant
*/
export const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 };
/**
* Represents touch interaction types in context of controls.
*
* @type {ConstantsTouch}
* @constant
*/
export const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 };
/**
* Disables face culling.
*
* @type {number}
* @constant
*/
export const CullFaceNone = 0;
/**
* Culls back faces.
*
* @type {number}
* @constant
*/
export const CullFaceBack = 1;
/**
* Culls front faces.
*
* @type {number}
* @constant
*/
export const CullFaceFront = 2;
/**
* Culls both front and back faces.
*
* @type {number}
* @constant
*/
export const CullFaceFrontBack = 3;
/**
* Gives unfiltered shadow maps - fastest, but lowest quality.
*
* @type {number}
* @constant
*/
export const BasicShadowMap = 0;
/**
* Filters shadow maps using the Percentage-Closer Filtering (PCF) algorithm.
*
* @type {number}
* @constant
*/
export const PCFShadowMap = 1;
/**
* Filters shadow maps using the Percentage-Closer Filtering (PCF) algorithm with
* better soft shadows especially when using low-resolution shadow maps.
*
* @type {number}
* @constant
*/
export const PCFSoftShadowMap = 2;
/**
* Filters shadow maps using the Variance Shadow Map (VSM) algorithm.
* When using VSMShadowMap all shadow receivers will also cast shadows.
*
* @type {number}
* @constant
*/
export const VSMShadowMap = 3;
/**
* Only front faces are rendered.
*
* @type {number}
* @constant
*/
export const FrontSide = 0;
/**
* Only back faces are rendered.
*
* @type {number}
* @constant
*/
export const BackSide = 1;
/**
* Both front and back faces are rendered.
*
* @type {number}
* @constant
*/
export const DoubleSide = 2;
/**
* No blending is performed which effectively disables
* alpha transparency.
*
* @type {number}
* @constant
*/
export const NoBlending = 0;
/**
* The default blending.
*
* @type {number}
* @constant
*/
export const NormalBlending = 1;
/**
* Represents additive blending.
*
* @type {number}
* @constant
*/
export const AdditiveBlending = 2;
/**
* Represents subtractive blending.
*
* @type {number}
* @constant
*/
export const SubtractiveBlending = 3;
/**
* Represents multiply blending.
*
* @type {number}
* @constant
*/
export const MultiplyBlending = 4;
/**
* Represents custom blending.
*
* @type {number}
* @constant
*/
export const CustomBlending = 5;
/**
* A `source + destination` blending equation.
*
* @type {number}
* @constant
*/
export const AddEquation = 100;
/**
* A `source - destination` blending equation.
*
* @type {number}
* @constant
*/
export const SubtractEquation = 101;
/**
* A `destination - source` blending equation.
*
* @type {number}
* @constant
*/
export const ReverseSubtractEquation = 102;
/**
* A blend equation that uses the minimum of source and destination.
*
* @type {number}
* @constant
*/
export const MinEquation = 103;
/**
* A blend equation that uses the maximum of source and destination.
*
* @type {number}
* @constant
*/
export const MaxEquation = 104;
/**
* Multiplies all colors by `0`.
*
* @type {number}
* @constant
*/
export const ZeroFactor = 200;
/**
* Multiplies all colors by `1`.
*
* @type {number}
* @constant
*/
export const OneFactor = 201;
/**
* Multiplies all colors by the source colors.
*
* @type {number}
* @constant
*/
export const SrcColorFactor = 202;
/**
* Multiplies all colors by `1` minus each source color.
*
* @type {number}
* @constant
*/
export const OneMinusSrcColorFactor = 203;
/**
* Multiplies all colors by the source alpha value.
*
* @type {number}
* @constant
*/
export const SrcAlphaFactor = 204;
/**
* Multiplies all colors by 1 minus the source alpha value.
*
* @type {number}
* @constant
*/
export const OneMinusSrcAlphaFactor = 205;
/**
* Multiplies all colors by the destination alpha value.
*
* @type {number}
* @constant
*/
export const DstAlphaFactor = 206;
/**
* Multiplies all colors by `1` minus the destination alpha value.
*
* @type {number}
* @constant
*/
export const OneMinusDstAlphaFactor = 207;
/**
* Multiplies all colors by the destination color.
*
* @type {number}
* @constant
*/
export const DstColorFactor = 208;
/**
* Multiplies all colors by `1` minus each destination color.
*
* @type {number}
* @constant
*/
export const OneMinusDstColorFactor = 209;
/**
* Multiplies the RGB colors by the smaller of either the source alpha
* value or the value of `1` minus the destination alpha value. The alpha
* value is multiplied by `1`.
*
* @type {number}
* @constant
*/
export const SrcAlphaSaturateFactor = 210;
/**
* Multiplies all colors by a constant color.
*
* @type {number}
* @constant
*/
export const ConstantColorFactor = 211;
/**
* Multiplies all colors by `1` minus a constant color.
*
* @type {number}
* @constant
*/
export const OneMinusConstantColorFactor = 212;
/**
* Multiplies all colors by a constant alpha value.
*
* @type {number}
* @constant
*/
export const ConstantAlphaFactor = 213;
/**
* Multiplies all colors by 1 minus a constant alpha value.
*
* @type {number}
* @constant
*/
export const OneMinusConstantAlphaFactor = 214;
/**
* Never pass.
*
* @type {number}
* @constant
*/
export const NeverDepth = 0;
/**
* Always pass.
*
* @type {number}
* @constant
*/
export const AlwaysDepth = 1;
/**
* Pass if the incoming value is less than the depth buffer value.
*
* @type {number}
* @constant
*/
export const LessDepth = 2;
/**
* Pass if the incoming value is less than or equal to the depth buffer value.
*
* @type {number}
* @constant
*/
export const LessEqualDepth = 3;
/**
* Pass if the incoming value equals the depth buffer value.
*
* @type {number}
* @constant
*/
export const EqualDepth = 4;
/**
* Pass if the incoming value is greater than or equal to the depth buffer value.
*
* @type {number}
* @constant
*/
export const GreaterEqualDepth = 5;
/**
* Pass if the incoming value is greater than the depth buffer value.
*
* @type {number}
* @constant
*/
export const GreaterDepth = 6;
/**
* Pass if the incoming value is not equal to the depth buffer value.
*
* @type {number}
* @constant
*/
export const NotEqualDepth = 7;
/**
* Multiplies the environment map color with the surface color.
*
* @type {number}
* @constant
*/
export const MultiplyOperation = 0;
/**
* Uses reflectivity to blend between the two colors.
*
* @type {number}
* @constant
*/
export const MixOperation = 1;
/**
* Adds the two colors.
*
* @type {number}
* @constant
*/
export const AddOperation = 2;
/**
* No tone mapping is applied.
*
* @type {number}
* @constant
*/
export const NoToneMapping = 0;
/**
* Linear tone mapping.
*
* @type {number}
* @constant
*/
export const LinearToneMapping = 1;
/**
* Reinhard tone mapping.
*
* @type {number}
* @constant
*/
export const ReinhardToneMapping = 2;
/**
* Cineon tone mapping.
*
* @type {number}
* @constant
*/
export const CineonToneMapping = 3;
/**
* ACES Filmic tone mapping.
*
* @type {number}
* @constant
*/
export const ACESFilmicToneMapping = 4;
/**
* Custom tone mapping.
*
* Expects a custom implementation by modifying shader code of the material's fragment shader.
*
* @type {number}
* @constant
*/
export const CustomToneMapping = 5;
/**
* AgX tone mapping.
*
* @type {number}
* @constant
*/
export const AgXToneMapping = 6;
/**
* Neutral tone mapping.
*
* Implementation based on the Khronos 3D Commerce Group standard tone mapping.
*
* @type {number}
* @constant
*/
export const NeutralToneMapping = 7;
/**
* The skinned mesh shares the same world space as the skeleton.
*
* @type {string}
* @constant
*/
export const AttachedBindMode = 'attached';
/**
* The skinned mesh does not share the same world space as the skeleton.
* This is useful when a skeleton is shared across multiple skinned meshes.
*
* @type {string}
* @constant
*/
export const DetachedBindMode = 'detached';
/**
* Maps textures using the geometry's UV coordinates.
*
* @type {number}
* @constant
*/
export const UVMapping = 300;
/**
* Reflection mapping for cube textures.
*
* @type {number}
* @constant
*/
export const CubeReflectionMapping = 301;
/**
* Refraction mapping for cube textures.
*
* @type {number}
* @constant
*/
export const CubeRefractionMapping = 302;
/**
* Reflection mapping for equirectangular textures.
*
* @type {number}
* @constant
*/
export const EquirectangularReflectionMapping = 303;
/**
* Refraction mapping for equirectangular textures.
*
* @type {number}
* @constant
*/
export const EquirectangularRefractionMapping = 304;
/**
* Reflection mapping for PMREM textures.
*
* @type {number}
* @constant
*/
export const CubeUVReflectionMapping = 306;
/**
* The texture will simply repeat to infinity.
*
* @type {number}
* @constant
*/
export const RepeatWrapping = 1000;
/**
* The last pixel of the texture stretches to the edge of the mesh.
*
* @type {number}
* @constant
*/
export const ClampToEdgeWrapping = 1001;
/**
* The texture will repeats to infinity, mirroring on each repeat.
*
* @type {number}
* @constant
*/
export const MirroredRepeatWrapping = 1002;
/**
* Returns the value of the texture element that is nearest (in Manhattan distance)
* to the specified texture coordinates.
*
* @type {number}
* @constant
*/
export const NearestFilter = 1003;
/**
* Chooses the mipmap that most closely matches the size of the pixel being textured
* and uses the `NearestFilter` criterion (the texel nearest to the center of the pixel)
* to produce a texture value.
*
* @type {number}
* @constant
*/
export const NearestMipmapNearestFilter = 1004;
export const NearestMipMapNearestFilter = 1004;
export const NearestMipMapNearestFilter = 1004; // legacy
/**
* Chooses the two mipmaps that most closely match the size of the pixel being textured and
* uses the `NearestFilter` criterion to produce a texture value from each mipmap.
* The final texture value is a weighted average of those two values.
*
* @type {number}
* @constant
*/
export const NearestMipmapLinearFilter = 1005;
export const NearestMipMapLinearFilter = 1005;
export const NearestMipMapLinearFilter = 1005; // legacy
/**
* Returns the weighted average of the four texture elements that are closest to the specified
* texture coordinates, and can include items wrapped or repeated from other parts of a texture,
* depending on the values of `wrapS` and `wrapT`, and on the exact mapping.
*
* @type {number}
* @constant
*/
export const LinearFilter = 1006;
/**
* Chooses the mipmap that most closely matches the size of the pixel being textured and uses
* the `LinearFilter` criterion (a weighted average of the four texels that are closest to the
* center of the pixel) to produce a texture value.
*
* @type {number}
* @constant
*/
export const LinearMipmapNearestFilter = 1007;
export const LinearMipMapNearestFilter = 1007;
export const LinearMipMapNearestFilter = 1007; // legacy
/**
* Chooses the two mipmaps that most closely match the size of the pixel being textured and uses
* the `LinearFilter` criterion to produce a texture value from each mipmap. The final texture value
* is a weighted average of those two values.
*
* @type {number}
* @constant
*/
export const LinearMipmapLinearFilter = 1008;
export const LinearMipMapLinearFilter = 1008;
export const LinearMipMapLinearFilter = 1008; // legacy
/**
* An unsigned byte data type for textures.
*
* @type {number}
* @constant
*/
export const UnsignedByteType = 1009;
/**
* A byte data type for textures.
*
* @type {number}
* @constant
*/
export const ByteType = 1010;
/**
* A short data type for textures.
*
* @type {number}
* @constant
*/
export const ShortType = 1011;
/**
* An unsigned short data type for textures.
*
* @type {number}
* @constant
*/
export const UnsignedShortType = 1012;
/**
* An int data type for textures.
*
* @type {number}
* @constant
*/
export const IntType = 1013;
/**
* An unsigned int data type for textures.
*
* @type {number}
* @constant
*/
export const UnsignedIntType = 1014;
/**
* A float data type for textures.
*
* @type {number}
* @constant
*/
export const FloatType = 1015;
/**
* A half float data type for textures.
*
* @type {number}
* @constant
*/
export const HalfFloatType = 1016;
/**
* An unsigned short 4_4_4_4 (packed) data type for textures.
*
* @type {number}
* @constant
*/
export const UnsignedShort4444Type = 1017;
/**
* An unsigned short 5_5_5_1 (packed) data type for textures.
*
* @type {number}
* @constant
*/
export const UnsignedShort5551Type = 1018;
/**
* An unsigned int 24_8 data type for textures.
*
* @type {number}
* @constant
*/
export const UnsignedInt248Type = 1020;
/**
* An unsigned int 5_9_9_9 (packed) data type for textures.
*
* @type {number}
* @constant
*/
export const UnsignedInt5999Type = 35902;
/**
* Discards the red, green and blue components and reads just the alpha component.
*
* @type {number}
* @constant
*/
export const AlphaFormat = 1021;
/**
* Discards the alpha component and reads the red, green and blue component.
*
* @type {number}
* @constant
*/
export const RGBFormat = 1022;
/**
* Reads the red, green, blue and alpha components.
*
* @type {number}
* @constant
*/
export const RGBAFormat = 1023;
/**
* reads each element as a single luminance component. This is then converted to a floating point,
* clamped to the range `[0,1]`, and then assembled into an RGBA element by placing the luminance value
* in the red, green and blue channels, and attaching 1.0 to the alpha channel.
*
* @type {number}
* @constant
*/
export const LuminanceFormat = 1024;
/**
* Reads each element as a luminance/alpha double. The same process occurs as for the `LuminanceFormat`,
* except that the alpha channel may have values other than `1.0`.
*
* @type {number}
* @constant
*/
export const LuminanceAlphaFormat = 1025;
/**
* Reads each element as a single depth value, converts it to floating point, and clamps to the range `[0,1]`.
*
* @type {number}
* @constant
*/
export const DepthFormat = 1026;
/**
* Reads each element is a pair of depth and stencil values. The depth component of the pair is interpreted as
* in `DepthFormat`. The stencil component is interpreted based on the depth + stencil internal format.
*
* @type {number}
* @constant
*/
export const DepthStencilFormat = 1027;
/**
* Discards the green, blue and alpha components and reads just the red component.
*
* @type {number}
* @constant
*/
export const RedFormat = 1028;
/**
* Discards the green, blue and alpha components and reads just the red component. The texels are read as integers instead of floating point.
*
* @type {number}
* @constant
*/
export const RedIntegerFormat = 1029;
/**
* Discards the alpha, and blue components and reads the red, and green components.
*
* @type {number}
* @constant
*/
export const RGFormat = 1030;
/**
* Discards the alpha, and blue components and reads the red, and green components. The texels are read as integers instead of floating point.
*
* @type {number}
* @constant
*/
export const RGIntegerFormat = 1031;
/**
* Discards the alpha component and reads the red, green and blue component. The texels are read as integers instead of floating point.
*
* @type {number}
* @constant
*/
export const RGBIntegerFormat = 1032;
/**
* Reads the red, green, blue and alpha components. The texels are read as integers instead of floating point.
*
* @type {number}
* @constant
*/
export const RGBAIntegerFormat = 1033;
/**
* A DXT1-compressed image in an RGB image format.
*
* @type {number}
* @constant
*/
export const RGB_S3TC_DXT1_Format = 33776;
/**
* A DXT1-compressed image in an RGB image format with a simple on/off alpha value.
*
* @type {number}
* @constant
*/
export const RGBA_S3TC_DXT1_Format = 33777;
/**
* A DXT3-compressed image in an RGBA image format. Compared to a 32-bit RGBA texture, it offers 4:1 compression.
*
* @type {number}
* @constant
*/
export const RGBA_S3TC_DXT3_Format = 33778;
/**
* A DXT5-compressed image in an RGBA image format. It also provides a 4:1 compression, but differs to the DXT3
* compression in how the alpha compression is done.
*
* @type {number}
* @constant
*/
export const RGBA_S3TC_DXT5_Format = 33779;
/**
* PVRTC RGB compression in 4-bit mode. One block for each 4×4 pixels.
*
* @type {number}
* @constant
*/
export const RGB_PVRTC_4BPPV1_Format = 35840;
/**
* PVRTC RGB compression in 2-bit mode. One block for each 8×4 pixels.
*
* @type {number}
* @constant
*/
export const RGB_PVRTC_2BPPV1_Format = 35841;
/**
* PVRTC RGBA compression in 4-bit mode. One block for each 4×4 pixels.
*
* @type {number}
* @constant
*/
export const RGBA_PVRTC_4BPPV1_Format = 35842;
/**
* PVRTC RGBA compression in 2-bit mode. One block for each 8×4 pixels.
*
* @type {number}
* @constant
*/
export const RGBA_PVRTC_2BPPV1_Format = 35843;
/**
* ETC1 RGB format.
*
* @type {number}
* @constant
*/
export const RGB_ETC1_Format = 36196;
/**
* ETC2 RGB format.
*
* @type {number}
* @constant
*/
export const RGB_ETC2_Format = 37492;
/**
* ETC2 RGBA format.
*
* @type {number}
* @constant
*/
export const RGBA_ETC2_EAC_Format = 37496;
/**
* ASTC RGBA 4x4 format.
*
* @type {number}
* @constant
*/
export const RGBA_ASTC_4x4_Format = 37808;
/**
* ASTC RGBA 5x4 format.
*
* @type {number}
* @constant
*/
export const RGBA_ASTC_5x4_Format = 37809;
/**
* ASTC RGBA 5x5 format.
*
* @type {number}
* @constant
*/
export const RGBA_ASTC_5x5_Format = 37810;
/**
* ASTC RGBA 6x5 format.
*
* @type {number}
* @constant
*/
export const RGBA_ASTC_6x5_Format = 37811;
/**
* ASTC RGBA 6x6 format.
*
* @type {number}
* @constant
*/
export const RGBA_ASTC_6x6_Format = 37812;
/**
* ASTC RGBA 8x5 format.
*
* @type {number}
* @constant
*/
export const RGBA_ASTC_8x5_Format = 37813;
/**
* ASTC RGBA 8x6 format.
*
* @type {number}
* @constant
*/
export const RGBA_ASTC_8x6_Format = 37814;
/**
* ASTC RGBA 8x8 format.
*
* @type {number}
* @constant
*/
export const RGBA_ASTC_8x8_Format = 37815;
/**
* ASTC RGBA 10x5 format.
*
* @type {number}
* @constant
*/
export const RGBA_ASTC_10x5_Format = 37816;
/**
* ASTC RGBA 10x6 format.
*
* @type {number}
* @constant
*/
export const RGBA_ASTC_10x6_Format = 37817;
/**
* ASTC RGBA 10x8 format.
*
* @type {number}
* @constant
*/
export const RGBA_ASTC_10x8_Format = 37818;
/**
* ASTC RGBA 10x10 format.
*
* @type {number}
* @constant
*/
export const RGBA_ASTC_10x10_Format = 37819;
/**
* ASTC RGBA 12x10 format.
*
* @type {number}
* @constant
*/
export const RGBA_ASTC_12x10_Format = 37820;
/**
* ASTC RGBA 12x12 format.
*
* @type {number}
* @constant
*/
export const RGBA_ASTC_12x12_Format = 37821;
/**
* BPTC RGBA format.
*
* @type {number}
* @constant
*/
export const RGBA_BPTC_Format = 36492;
/**
* BPTC Signed RGB format.
*
* @type {number}
* @constant
*/
export const RGB_BPTC_SIGNED_Format = 36494;
/**
* BPTC Unsigned RGB format.
*
* @type {number}
* @constant
*/
export const RGB_BPTC_UNSIGNED_Format = 36495;
/**
* RGTC1 Red format.
*
* @type {number}
* @constant
*/
export const RED_RGTC1_Format = 36283;
/**
* RGTC1 Signed Red format.
*
* @type {number}
* @constant
*/
export const SIGNED_RED_RGTC1_Format = 36284;
/**
* RGTC2 Red Green format.
*
* @type {number}
* @constant
*/
export const RED_GREEN_RGTC2_Format = 36285;
/**
* RGTC2 Signed Red Green format.
*
* @type {number}
* @constant
*/
export const SIGNED_RED_GREEN_RGTC2_Format = 36286;
/**
* Animations are played once.
*
* @type {number}
* @constant
*/
export const LoopOnce = 2200;
/**
* Animations are played with a chosen number of repetitions, each time jumping from
* the end of the clip directly to its beginning.
*
* @type {number}
* @constant
*/
export const LoopRepeat = 2201;
/**
* Animations are played with a chosen number of repetitions, alternately playing forward
* and backward.
*
* @type {number}
* @constant
*/
export const LoopPingPong = 2202;
/**
* Discrete interpolation mode for keyframe tracks.
*
* @type {number}
* @constant
*/
export const InterpolateDiscrete = 2300;
/**
* Linear interpolation mode for keyframe tracks.
*
* @type {number}
* @constant
*/
export const InterpolateLinear = 2301;
/**
* Smooth interpolation mode for keyframe tracks.
*
* @type {number}
* @constant
*/
export const InterpolateSmooth = 2302;
/**
* Zero curvature ending for animations.
*
* @type {number}
* @constant
*/
export const ZeroCurvatureEnding = 2400;
/**
* Zero slope ending for animations.
*
* @type {number}
* @constant
*/
export const ZeroSlopeEnding = 2401;
/**
* Wrap around ending for animations.
*
* @type {number}
* @constant
*/
export const WrapAroundEnding = 2402;
/**
* Default animation blend mode.
*
* @type {number}
* @constant
*/
export const NormalAnimationBlendMode = 2500;
/**
* Additive animation blend mode. Can be used to layer motions on top of
* each other to build complex performances from smaller re-usable assets.
*
* @type {number}
* @constant
*/
export const AdditiveAnimationBlendMode = 2501;
/**
* For every three vertices draw a single triangle.
*
* @type {number}
* @constant
*/
export const TrianglesDrawMode = 0;
/**
* For each vertex draw a triangle from the last three vertices.
*
* @type {number}
* @constant
*/
export const TriangleStripDrawMode = 1;
/**
* For each vertex draw a triangle from the first vertex and the last two vertices.
*
* @type {number}
* @constant
*/
export const TriangleFanDrawMode = 2;
/**
* Basic depth packing.
*
* @type {number}
* @constant
*/
export const BasicDepthPacking = 3200;
/**
* A depth value is packed into 32 bit RGBA.
*
* @type {number}
* @constant
*/
export const RGBADepthPacking = 3201;
/**
* A depth value is packed into 24 bit RGB.
*
* @type {number}
* @constant
*/
export const RGBDepthPacking = 3202;
/**
* A depth value is packed into 16 bit RG.
*
* @type {number}
* @constant
*/
export const RGDepthPacking = 3203;
/**
* Normal information is relative to the underlying surface.
*
* @type {number}
* @constant
*/
export const TangentSpaceNormalMap = 0;
/**
* Normal information is relative to the object orientation.
*
* @type {number}
* @constant
*/
export const ObjectSpaceNormalMap = 1;
// Color space string identifiers, matching CSS Color Module Level 4 and WebGPU names where available.
/**
* No color space.
*
* @type {string}
* @constant
*/
export const NoColorSpace = '';
/**
* sRGB color space.
*
* @type {string}
* @constant
*/
export const SRGBColorSpace = 'srgb';
/**
* sRGB-linear color space.
*
* @type {string}
* @constant
*/
export const LinearSRGBColorSpace = 'srgb-linear';
/**
* Linear transfer function.
*
* @type {string}
* @constant
*/
export const LinearTransfer = 'linear';
/**
* sRGB transfer function.
*
* @type {string}
* @constant
*/
export const SRGBTransfer = 'srgb';
/**
* Sets the stencil buffer value to `0`.
*
* @type {number}
* @constant
*/
export const ZeroStencilOp = 0;
/**
* Keeps the current value.
*
* @type {number}
* @constant
*/
export const KeepStencilOp = 7680;
/**
* Sets the stencil buffer value to the specified reference value.
*
* @type {number}
* @constant
*/
export const ReplaceStencilOp = 7681;
/**
* Increments the current stencil buffer value. Clamps to the maximum representable unsigned value.
*
* @type {number}
* @constant
*/
export const IncrementStencilOp = 7682;
/**
* Decrements the current stencil buffer value. Clamps to `0`.
*
* @type {number}
* @constant
*/
export const DecrementStencilOp = 7683;
/**
* Increments the current stencil buffer value. Wraps stencil buffer value to zero when incrementing
* the maximum representable unsigned value.
*
* @type {number}
* @constant
*/
export const IncrementWrapStencilOp = 34055;
/**
* Decrements the current stencil buffer value. Wraps stencil buffer value to the maximum representable
* unsigned value when decrementing a stencil buffer value of `0`.
*
* @type {number}
* @constant
*/
export const DecrementWrapStencilOp = 34056;
/**
* Inverts the current stencil buffer value bitwise.
*
* @type {number}
* @constant
*/
export const InvertStencilOp = 5386;
/**
* Will never return true.
*
* @type {number}
* @constant
*/
export const NeverStencilFunc = 512;
/**
* Will return true if the stencil reference value is less than the current stencil value.
*
* @type {number}
* @constant
*/
export const LessStencilFunc = 513;
/**
* Will return true if the stencil reference value is equal to the current stencil value.
*
* @type {number}
* @constant
*/
export const EqualStencilFunc = 514;
/**
* Will return true if the stencil reference value is less than or equal to the current stencil value.
*
* @type {number}
* @constant
*/
export const LessEqualStencilFunc = 515;
/**
* Will return true if the stencil reference value is greater than the current stencil value.
*
* @type {number}
* @constant
*/
export const GreaterStencilFunc = 516;
/**
* Will return true if the stencil reference value is not equal to the current stencil value.
*
* @type {number}
* @constant
*/
export const NotEqualStencilFunc = 517;
/**
* Will return true if the stencil reference value is greater than or equal to the current stencil value.
*
* @type {number}
* @constant
*/
export const GreaterEqualStencilFunc = 518;
/**
* Will always return true.
*
* @type {number}
* @constant
*/
export const AlwaysStencilFunc = 519;
/**
* Never pass.
*
* @type {number}
* @constant
*/
export const NeverCompare = 512;
/**
* Pass if the incoming value is less than the texture value.
*
* @type {number}
* @constant
*/
export const LessCompare = 513;
/**
* Pass if the incoming value equals the texture value.
*
* @type {number}
* @constant
*/
export const EqualCompare = 514;
/**
* Pass if the incoming value is less than or equal to the texture value.
*
* @type {number}
* @constant
*/
export const LessEqualCompare = 515;
/**
* Pass if the incoming value is greater than the texture value.
*
* @type {number}
* @constant
*/
export const GreaterCompare = 516;
/**
* Pass if the incoming value is not equal to the texture value.
*
* @type {number}
* @constant
*/
export const NotEqualCompare = 517;
/**
* Pass if the incoming value is greater than or equal to the texture value.
*
* @type {number}
* @constant
*/
export const GreaterEqualCompare = 518;
/**
* Always pass.
*
* @type {number}
* @constant
*/
export const AlwaysCompare = 519;
/**
* The contents are intended to be specified once by the application, and used many
* times as the source for drawing and image specification commands.
*
* @type {number}
* @constant
*/
export const StaticDrawUsage = 35044;
/**
* The contents are intended to be respecified repeatedly by the application, and
* used many times as the source for drawing and image specification commands.
*
* @type {number}
* @constant
*/
export const DynamicDrawUsage = 35048;
/**
* The contents are intended to be specified once by the application, and used at most
* a few times as the source for drawing and image specification commands.
*
* @type {number}
* @constant
*/
export const StreamDrawUsage = 35040;
/**
* The contents are intended to be specified once by reading data from the 3D API, and queried
* many times by the application.
*
* @type {number}
* @constant
*/
export const StaticReadUsage = 35045;
/**
* The contents are intended to be respecified repeatedly by reading data from the 3D API, and queried
* many times by the application.
*
* @type {number}
* @constant
*/
export const DynamicReadUsage = 35049;
/**
* The contents are intended to be specified once by reading data from the 3D API, and queried at most
* a few times by the application
*
* @type {number}
* @constant
*/
export const StreamReadUsage = 35041;
/**
* The contents are intended to be specified once by reading data from the 3D API, and used many times as
* the source for WebGL drawing and image specification commands.
*
* @type {number}
* @constant
*/
export const StaticCopyUsage = 35046;
/**
* The contents are intended to be respecified repeatedly by reading data from the 3D API, and used many times
* as the source for WebGL drawing and image specification commands.
*
* @type {number}
* @constant
*/
export const DynamicCopyUsage = 35050;
/**
* The contents are intended to be specified once by reading data from the 3D API, and used at most a few times
* as the source for WebGL drawing and image specification commands.
*
* @type {number}
* @constant
*/
export const StreamCopyUsage = 35042;
/**
* GLSL 1 shader code.
*
* @type {string}
* @constant
*/
export const GLSL1 = '100';
/**
* GLSL 3 shader code.
*
* @type {string}
* @constant
*/
export const GLSL3 = '300 es';
/**
* WebGL coordinate system.
*
* @type {number}
* @constant
*/
export const WebGLCoordinateSystem = 2000;
/**
* WebGPU coordinate system.
*
* @type {number}
* @constant
*/
export const WebGPUCoordinateSystem = 2001;
/**
* Represents the different timestamp query types.
*
* @type {ConstantsTimestampQuery}
* @constant
*/
export const TimestampQuery = {

@@ -217,1 +1611,31 @@ COMPUTE: 'compute',

};
/**
* This type represents mouse buttons and interaction types in context of controls.
*
* @typedef {Object} ConstantsMouse
* @property {number} MIDDLE - The left mouse button.
* @property {number} LEFT - The middle mouse button.
* @property {number} RIGHT - The right mouse button.
* @property {number} ROTATE - A rotate interaction.
* @property {number} DOLLY - A dolly interaction.
* @property {number} PAN - A pan interaction.
**/
/**
* This type represents touch interaction types in context of controls.
*
* @typedef {Object} ConstantsTouch
* @property {number} ROTATE - A rotate interaction.
* @property {number} PAN - A pan interaction.
* @property {number} DOLLY_PAN - The dolly-pan interaction.
* @property {number} DOLLY_ROTATE - A dolly-rotate interaction.
**/
/**
* This type represents the different timestamp query types.
*
* @typedef {Object} ConstantsTimestampQuery
* @property {string} COMPUTE - A `compute` timestamp query.
* @property {string} RENDER - A `render` timestamp query.
**/

@@ -12,4 +12,19 @@ import { Vector3 } from '../math/Vector3.js';

/**
* This class stores data for an attribute (such as vertex positions, face
* indices, normals, colors, UVs, and any custom attributes ) associated with
* a geometry, which allows for more efficient passing of data to the GPU.
*
* When working with vector-like data, the `fromBufferAttribute( attribute, index )`
* helper methods on vector and color class might be helpful. E.g. {@link Vector3#fromBufferAttribute}.
*/
class BufferAttribute {
/**
* Constructs a new buffer attribute.
*
* @param {TypedArray} array - The array holding the attribute data.
* @param {number} itemSize - The item size.
* @param {boolean} [normalized=false] - Whether the data are normalized or not.
*/
constructor( array, itemSize, normalized = false ) {

@@ -23,17 +38,99 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isBufferAttribute = true;
/**
* The ID of the buffer attribute.
*
* @name BufferAttribute#id
* @type {number}
* @readonly
*/
Object.defineProperty( this, 'id', { value: _id ++ } );
/**
* The name of the buffer attribute.
*
* @type {string}
*/
this.name = '';
/**
* The array holding the attribute data. It should have `itemSize * numVertices`
* elements, where `numVertices` is the number of vertices in the associated geometry.
*
* @type {TypedArray}
*/
this.array = array;
/**
* The number of values of the array that should be associated with a particular vertex.
* For instance, if this attribute is storing a 3-component vector (such as a position,
* normal, or color), then the value should be `3`.
*
* @type {number}
*/
this.itemSize = itemSize;
/**
* Represents the number of items this buffer attribute stores. It is internally computed
* by dividing the `array` length by the `itemSize`.
*
* @type {number}
* @readonly
*/
this.count = array !== undefined ? array.length / itemSize : 0;
/**
* Applies to integer data only. Indicates how the underlying data in the buffer maps to
* the values in the GLSL code. For instance, if `array` is an instance of `UInt16Array`,
* and `normalized` is `true`, the values `0 -+65535` in the array data will be mapped to
* `0.0f - +1.0f` in the GLSL attribute. If `normalized` is `false`, the values will be converted
* to floats unmodified, i.e. `65535` becomes `65535.0f`.
*
* @type {boolean}
*/
this.normalized = normalized;
/**
* Defines the intended usage pattern of the data store for optimization purposes.
*
* Note: After the initial use of a buffer, its usage cannot be changed. Instead,
* instantiate a new one and set the desired usage before the next render.
*
* @type {(StaticDrawUsage|DynamicDrawUsage|StreamDrawUsage|StaticReadUsage|DynamicReadUsage|StreamReadUsage|StaticCopyUsage|DynamicCopyUsage|StreamCopyUsage)}
* @default StaticDrawUsage
*/
this.usage = StaticDrawUsage;
/**
* This can be used to only update some components of stored vectors (for example, just the
* component related to color). Use the `addUpdateRange()` function to add ranges to this array.
*
* @type {Array<Object>}
*/
this.updateRanges = [];
/**
* Configures the bound GPU type for use in shaders.
*
* Note: this only has an effect for integer arrays and is not configurable for float arrays.
* For lower precision float types, use `Float16BufferAttribute`.
*
* @type {(FloatType|IntType)}
* @default FloatType
*/
this.gpuType = FloatType;
/**
* A version number, incremented every time the `needsUpdate` is set to `true`.
*
* @type {number}
*/
this.version = 0;

@@ -43,4 +140,16 @@

/**
* A callback function that is executed after the renderer has transferred the attribute
* array data to the GPU.
*/
onUploadCallback() {}
/**
* Flag to indicate that this attribute has changed and should be re-sent to
* the GPU. Set this to `true` when you modify the value of the array.
*
* @type {number}
* @default false
* @param {boolean} value
*/
set needsUpdate( value ) {

@@ -52,2 +161,8 @@

/**
* Sets the usage of this buffer attribute.
*
* @param {(StaticDrawUsage|DynamicDrawUsage|StreamDrawUsage|StaticReadUsage|DynamicReadUsage|StreamReadUsage|StaticCopyUsage|DynamicCopyUsage|StreamCopyUsage)} value - The usage to set.
* @return {BufferAttribute} A reference to this buffer attribute.
*/
setUsage( value ) {

@@ -61,2 +176,8 @@

/**
* Adds a range of data in the data array to be updated on the GPU.
*
* @param {number} start - Position at which to start update.
* @param {number} count - The number of components to update.
*/
addUpdateRange( start, count ) {

@@ -68,2 +189,5 @@

/**
* Clears the update ranges.
*/
clearUpdateRanges() {

@@ -75,2 +199,8 @@

/**
* Copies the values of the given buffer attribute to this instance.
*
* @param {BufferAttribute} source - The buffer attribute to copy.
* @return {BufferAttribute} A reference to this instance.
*/
copy( source ) {

@@ -91,2 +221,12 @@

/**
* Copies a vector from the given buffer attribute to this one. The start
* and destination position in the attribute buffers are represented by the
* given indices.
*
* @param {number} index1 - The destination index into this buffer attribute.
* @param {BufferAttribute} attribute - The buffer attribute to copy from.
* @param {number} index2 - The source index into the given buffer attribute.
* @return {BufferAttribute} A reference to this instance.
*/
copyAt( index1, attribute, index2 ) {

@@ -107,2 +247,8 @@

/**
* Copies the given array data into this buffer attribute.
*
* @param {(TypedArray|Array)} array - The array to copy.
* @return {BufferAttribute} A reference to this instance.
*/
copyArray( array ) {

@@ -116,2 +262,9 @@

/**
* Applies the given 3x3 matrix to the given attribute. Works with
* item size `2` and `3`.
*
* @param {Matrix3} m - The matrix to apply.
* @return {BufferAttribute} A reference to this instance.
*/
applyMatrix3( m ) {

@@ -147,2 +300,9 @@

/**
* Applies the given 4x4 matrix to the given attribute. Only works with
* item size `3`.
*
* @param {Matrix4} m - The matrix to apply.
* @return {BufferAttribute} A reference to this instance.
*/
applyMatrix4( m ) {

@@ -164,2 +324,9 @@

/**
* Applies the given 3x3 normal matrix to the given attribute. Only works with
* item size `3`.
*
* @param {Matrix3} m - The normal matrix to apply.
* @return {BufferAttribute} A reference to this instance.
*/
applyNormalMatrix( m ) {

@@ -181,2 +348,9 @@

/**
* Applies the given 4x4 matrix to the given attribute. Only works with
* item size `3` and with direction vectors.
*
* @param {Matrix4} m - The matrix to apply.
* @return {BufferAttribute} A reference to this instance.
*/
transformDirection( m ) {

@@ -198,2 +372,9 @@

/**
* Sets the given array data in the buffer attribute.
*
* @param {(TypedArray|Array)} value - The array data to set.
* @param {number} [offset=0] - The offset in this buffer attribute's array.
* @return {BufferAttribute} A reference to this instance.
*/
set( value, offset = 0 ) {

@@ -208,2 +389,9 @@

/**
* Returns the given component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @param {number} component - The component index.
* @return {number} The returned value.
*/
getComponent( index, component ) {

@@ -219,2 +407,10 @@

/**
* Sets the given value to the given component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @param {number} component - The component index.
* @param {number} value - The value to set.
* @return {BufferAttribute} A reference to this instance.
*/
setComponent( index, component, value ) {

@@ -230,2 +426,8 @@

/**
* Returns the x component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @return {number} The x component.
*/
getX( index ) {

@@ -241,2 +443,9 @@

/**
* Sets the x component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @param {number} x - The value to set.
* @return {BufferAttribute} A reference to this instance.
*/
setX( index, x ) {

@@ -252,2 +461,8 @@

/**
* Returns the y component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @return {number} The y component.
*/
getY( index ) {

@@ -263,2 +478,9 @@

/**
* Sets the y component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @param {number} y - The value to set.
* @return {BufferAttribute} A reference to this instance.
*/
setY( index, y ) {

@@ -274,2 +496,8 @@

/**
* Returns the z component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @return {number} The z component.
*/
getZ( index ) {

@@ -285,2 +513,9 @@

/**
* Sets the z component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @param {number} z - The value to set.
* @return {BufferAttribute} A reference to this instance.
*/
setZ( index, z ) {

@@ -296,2 +531,8 @@

/**
* Returns the w component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @return {number} The w component.
*/
getW( index ) {

@@ -307,2 +548,9 @@

/**
* Sets the w component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @param {number} w - The value to set.
* @return {BufferAttribute} A reference to this instance.
*/
setW( index, w ) {

@@ -318,2 +566,10 @@

/**
* Sets the x and y component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @param {number} x - The value for the x component to set.
* @param {number} y - The value for the y component to set.
* @return {BufferAttribute} A reference to this instance.
*/
setXY( index, x, y ) {

@@ -337,2 +593,11 @@

/**
* Sets the x, y and z component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @param {number} x - The value for the x component to set.
* @param {number} y - The value for the y component to set.
* @param {number} z - The value for the z component to set.
* @return {BufferAttribute} A reference to this instance.
*/
setXYZ( index, x, y, z ) {

@@ -358,2 +623,12 @@

/**
* Sets the x, y, z and w component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @param {number} x - The value for the x component to set.
* @param {number} y - The value for the y component to set.
* @param {number} z - The value for the z component to set.
* @param {number} w - The value for the w component to set.
* @return {BufferAttribute} A reference to this instance.
*/
setXYZW( index, x, y, z, w ) {

@@ -381,2 +656,10 @@

/**
* Sets the given callback function that is executed after the Renderer has transferred
* the attribute array data to the GPU. Can be used to perform clean-up operations after
* the upload when attribute data are not needed anymore on the CPU side.
*
* @param {Function} callback - The `onUpload()` callback.
* @return {BufferAttribute} A reference to this instance.
*/
onUpload( callback ) {

@@ -390,2 +673,7 @@

/**
* Returns a new buffer attribute with copied values from this instance.
*
* @return {BufferAttribute} A clone of this instance.
*/
clone() {

@@ -397,2 +685,7 @@

/**
* Serializes the buffer attribute into JSON.
*
* @return {Object} A JSON object representing the serialized buffer attribute.
*/
toJSON() {

@@ -416,6 +709,17 @@

//
/**
* Convenient class that can be used when creating a `Int8` buffer attribute with
* a plain `Array` instance.
*
* @augments BufferAttribute
*/
class Int8BufferAttribute extends BufferAttribute {
/**
* Constructs a new buffer attribute.
*
* @param {(Array<number>|Int8Array)} array - The array holding the attribute data.
* @param {number} itemSize - The item size.
* @param {boolean} [normalized=false] - Whether the data are normalized or not.
*/
constructor( array, itemSize, normalized ) {

@@ -429,4 +733,17 @@

/**
* Convenient class that can be used when creating a `UInt8` buffer attribute with
* a plain `Array` instance.
*
* @augments BufferAttribute
*/
class Uint8BufferAttribute extends BufferAttribute {
/**
* Constructs a new buffer attribute.
*
* @param {(Array<number>|Uint8Array)} array - The array holding the attribute data.
* @param {number} itemSize - The item size.
* @param {boolean} [normalized=false] - Whether the data are normalized or not.
*/
constructor( array, itemSize, normalized ) {

@@ -440,4 +757,17 @@

/**
* Convenient class that can be used when creating a `UInt8Clamped` buffer attribute with
* a plain `Array` instance.
*
* @augments BufferAttribute
*/
class Uint8ClampedBufferAttribute extends BufferAttribute {
/**
* Constructs a new buffer attribute.
*
* @param {(Array<number>|Uint8ClampedArray)} array - The array holding the attribute data.
* @param {number} itemSize - The item size.
* @param {boolean} [normalized=false] - Whether the data are normalized or not.
*/
constructor( array, itemSize, normalized ) {

@@ -451,4 +781,17 @@

/**
* Convenient class that can be used when creating a `Int16` buffer attribute with
* a plain `Array` instance.
*
* @augments BufferAttribute
*/
class Int16BufferAttribute extends BufferAttribute {
/**
* Constructs a new buffer attribute.
*
* @param {(Array<number>|Int16Array)} array - The array holding the attribute data.
* @param {number} itemSize - The item size.
* @param {boolean} [normalized=false] - Whether the data are normalized or not.
*/
constructor( array, itemSize, normalized ) {

@@ -462,4 +805,17 @@

/**
* Convenient class that can be used when creating a `UInt16` buffer attribute with
* a plain `Array` instance.
*
* @augments BufferAttribute
*/
class Uint16BufferAttribute extends BufferAttribute {
/**
* Constructs a new buffer attribute.
*
* @param {(Array<number>|Uint16Array)} array - The array holding the attribute data.
* @param {number} itemSize - The item size.
* @param {boolean} [normalized=false] - Whether the data are normalized or not.
*/
constructor( array, itemSize, normalized ) {

@@ -473,4 +829,17 @@

/**
* Convenient class that can be used when creating a `Int32` buffer attribute with
* a plain `Array` instance.
*
* @augments BufferAttribute
*/
class Int32BufferAttribute extends BufferAttribute {
/**
* Constructs a new buffer attribute.
*
* @param {(Array<number>|Int32Array)} array - The array holding the attribute data.
* @param {number} itemSize - The item size.
* @param {boolean} [normalized=false] - Whether the data are normalized or not.
*/
constructor( array, itemSize, normalized ) {

@@ -484,4 +853,17 @@

/**
* Convenient class that can be used when creating a `UInt32` buffer attribute with
* a plain `Array` instance.
*
* @augments BufferAttribute
*/
class Uint32BufferAttribute extends BufferAttribute {
/**
* Constructs a new buffer attribute.
*
* @param {(Array<number>|Uint32Array)} array - The array holding the attribute data.
* @param {number} itemSize - The item size.
* @param {boolean} [normalized=false] - Whether the data are normalized or not.
*/
constructor( array, itemSize, normalized ) {

@@ -495,4 +877,20 @@

/**
* Convenient class that can be used when creating a `Float16` buffer attribute with
* a plain `Array` instance.
*
* This class automatically converts to to and from FP16 since `Float16Array` is not
* natively supported in JavaScript.
*
* @augments BufferAttribute
*/
class Float16BufferAttribute extends BufferAttribute {
/**
* Constructs a new buffer attribute.
*
* @param {(Array<number>|Uint16Array)} array - The array holding the attribute data.
* @param {number} itemSize - The item size.
* @param {boolean} [normalized=false] - Whether the data are normalized or not.
*/
constructor( array, itemSize, normalized ) {

@@ -648,5 +1046,17 @@

/**
* Convenient class that can be used when creating a `Float32` buffer attribute with
* a plain `Array` instance.
*
* @augments BufferAttribute
*/
class Float32BufferAttribute extends BufferAttribute {
/**
* Constructs a new buffer attribute.
*
* @param {(Array<number>|Float32Array)} array - The array holding the attribute data.
* @param {number} itemSize - The item size.
* @param {boolean} [normalized=false] - Whether the data are normalized or not.
*/
constructor( array, itemSize, normalized ) {

@@ -653,0 +1063,0 @@

@@ -22,4 +22,33 @@ import { Vector3 } from '../math/Vector3.js';

/**
* A representation of mesh, line, or point geometry. Includes vertex
* positions, face indices, normals, colors, UVs, and custom attributes
* within buffers, reducing the cost of passing all this data to the GPU.
*
* ```js
* const geometry = new THREE.BufferGeometry();
* // create a simple square shape. We duplicate the top left and bottom right
* // vertices because each vertex needs to appear once per triangle.
* 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
* -1.0, 1.0, 1.0, // v4
* -1.0, -1.0, 1.0 // v5
* ] );
* // itemSize = 3 because there are 3 values (components) per vertex
* geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
* const material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
* const mesh = new THREE.Mesh( geometry, material );
* ```
*
* @augments EventDispatcher
*/
class BufferGeometry extends EventDispatcher {
/**
* Constructs a new geometry.
*/
constructor() {

@@ -29,25 +58,131 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isBufferGeometry = true;
/**
* The ID of the geometry.
*
* @name BufferGeometry#id
* @type {number}
* @readonly
*/
Object.defineProperty( this, 'id', { value: _id ++ } );
/**
* The UUID of the geometry.
*
* @type {string}
* @readonly
*/
this.uuid = generateUUID();
/**
* The name of the geometry.
*
* @type {string}
*/
this.name = '';
this.type = 'BufferGeometry';
/**
* Allows for vertices to be re-used across multiple triangles; this is
* called using "indexed triangles". Each triangle is associated with the
* indices of three vertices. This attribute therefore stores the index of
* each vertex for each triangular face. If this attribute is not set, the
* renderer assumes that each three contiguous positions represent a single triangle.
*
* @type {?BufferAttribute}
* @default null
*/
this.index = null;
/**
* A (storage) buffer attribute which was generated with a compute shader and
* now defines indirect draw calls.
*
* Can only be used with {@link WebGPURenderer} and a WebGPU backend.
*
* @type {?BufferAttribute}
* @default null
*/
this.indirect = null;
/**
* This dictionary has as id the name of the attribute to be set and as value
* the buffer attribute to set it to. Rather than accessing this property directly,
* use `setAttribute()` and `getAttribute()` to access attributes of this geometry.
*
* @type {Object<string,(BufferAttribute|InterleavedBufferAttribute)>}
*/
this.attributes = {};
/**
* This dictionary holds the morph targets of the geometry.
*
* Note: Once the geometry has been rendered, the morph attribute data cannot
* be changed. You will have to call `dispose()?, and create a new geometry instance.
*
* @type {Object}
*/
this.morphAttributes = {};
/**
* Used to control the morph target behavior; when set to `true`, the morph
* target data is treated as relative offsets, rather than as absolute
* positions/normals.
*
* @type {boolean}
* @default false
*/
this.morphTargetsRelative = false;
/**
* Split the geometry into groups, each of which will be rendered in a
* separate draw call. This allows an array of materials to be used with the geometry.
*
* Use `addGroup()` and `clearGroups()` to edit groups, rather than modifying this array directly.
*
* Every vertex and index must belong to exactly one group — groups must not share vertices or
* indices, and must not leave vertices or indices unused.
*
* @type {Array<Object>}
*/
this.groups = [];
/**
* Bounding box for the geometry which can be calculated with `computeBoundingBox()`.
*
* @type {Box3}
* @default null
*/
this.boundingBox = null;
/**
* Bounding sphere for the geometry which can be calculated with `computeBoundingSphere()`.
*
* @type {Sphere}
* @default null
*/
this.boundingSphere = null;
/**
* Determines the part of the geometry to render. This should not be set directly,
* instead use `setDrawRange()`.
*
* @type {{start:number,count:number}}
*/
this.drawRange = { start: 0, count: Infinity };
/**
* An object that can be used to store custom data about the geometry.
* It should not hold references to functions as these will not be cloned.
*
* @type {Object}
*/
this.userData = {};

@@ -57,2 +192,7 @@

/**
* Returns the index of this geometry.
*
* @return {?BufferAttribute} The index. Returns `null` if no index is defined.
*/
getIndex() {

@@ -64,2 +204,8 @@

/**
* Sets the given index to this geometry.
*
* @param {Array<number>|BufferAttribute} index - The index to set.
* @return {BufferGeometry} A reference to this instance.
*/
setIndex( index ) {

@@ -81,2 +227,8 @@

/**
* Sets the given indirect attribute to this geometry.
*
* @param {BufferAttribute} indirect - The attribute holding indirect draw calls.
* @return {BufferGeometry} A reference to this instance.
*/
setIndirect( indirect ) {

@@ -90,2 +242,7 @@

/**
* Returns the indirect attribute of this geometry.
*
* @return {?BufferAttribute} The indirect attribute. Returns `null` if no indirect attribute is defined.
*/
getIndirect() {

@@ -97,2 +254,9 @@

/**
* Returns the buffer attribute for the given name.
*
* @param {string} name - The attribute name.
* @return {BufferAttribute|InterleavedBufferAttribute|undefined} The buffer attribute.
* Returns `undefined` if not attribute has been found.
*/
getAttribute( name ) {

@@ -104,2 +268,9 @@

/**
* Sets the given attribute for the given name.
*
* @param {string} name - The attribute name.
* @param {BufferAttribute|InterleavedBufferAttribute} attribute - The attribute to set.
* @return {BufferGeometry} A reference to this instance.
*/
setAttribute( name, attribute ) {

@@ -113,2 +284,8 @@

/**
* Deletes the attribute for the given name.
*
* @param {string} name - The attribute name to delete.
* @return {BufferGeometry} A reference to this instance.
*/
deleteAttribute( name ) {

@@ -122,2 +299,8 @@

/**
* Returns `true` if this geometry has an attribute for the given name.
*
* @param {string} name - The attribute name.
* @return {boolean} Whether this geometry has an attribute for the given name or not.
*/
hasAttribute( name ) {

@@ -129,2 +312,10 @@

/**
* Adds a group to this geometry.
*
* @param {number} start - The first element in this draw call. That is the first
* vertex for non-indexed geometry, otherwise the first triangle index.
* @param {number} count - Specifies how many vertices (or indices) are part of this group.
* @param {number} [materialIndex=0] - The material array index to use.
*/
addGroup( start, count, materialIndex = 0 ) {

@@ -142,2 +333,5 @@

/**
* Clears all groups.
*/
clearGroups() {

@@ -149,2 +343,9 @@

/**
* Sets the draw range for this geometry.
*
* @param {number} start - The first vertex for non-indexed geometry, otherwise the first triangle index.
* @param {number} count - For non-indexed BufferGeometry, `count` is the number of vertices to render.
* For indexed BufferGeometry, `count` is the number of indices to render.
*/
setDrawRange( start, count ) {

@@ -157,2 +358,8 @@

/**
* Applies the given 4x4 transformation matrix to the geometry.
*
* @param {Matrix4} matrix - The matrix to apply.
* @return {BufferGeometry} A reference to this instance.
*/
applyMatrix4( matrix ) {

@@ -208,2 +415,8 @@

/**
* Applies the rotation represented by the Quaternion to the geometry.
*
* @param {Quaternion} q - The Quaternion to apply.
* @return {BufferGeometry} A reference to this instance.
*/
applyQuaternion( q ) {

@@ -219,2 +432,10 @@

/**
* Rotates the geometry about the X axis. This is typically done as a one time
* operation, and not during a loop. Use {@link Object3D#rotation} for typical
* real-time mesh rotation.
*
* @param {number} angle - The angle in radians.
* @return {BufferGeometry} A reference to this instance.
*/
rotateX( angle ) {

@@ -232,2 +453,10 @@

/**
* Rotates the geometry about the Y axis. This is typically done as a one time
* operation, and not during a loop. Use {@link Object3D#rotation} for typical
* real-time mesh rotation.
*
* @param {number} angle - The angle in radians.
* @return {BufferGeometry} A reference to this instance.
*/
rotateY( angle ) {

@@ -245,2 +474,10 @@

/**
* Rotates the geometry about the Z axis. This is typically done as a one time
* operation, and not during a loop. Use {@link Object3D#rotation} for typical
* real-time mesh rotation.
*
* @param {number} angle - The angle in radians.
* @return {BufferGeometry} A reference to this instance.
*/
rotateZ( angle ) {

@@ -258,2 +495,12 @@

/**
* Translates the geometry. This is typically done as a one time
* operation, and not during a loop. Use {@link Object3D#position} for typical
* real-time mesh rotation.
*
* @param {number} x - The x offset.
* @param {number} y - The y offset.
* @param {number} z - The z offset.
* @return {BufferGeometry} A reference to this instance.
*/
translate( x, y, z ) {

@@ -271,2 +518,12 @@

/**
* Scales the geometry. This is typically done as a one time
* operation, and not during a loop. Use {@link Object3D#scale} for typical
* real-time mesh rotation.
*
* @param {number} x - The x scale.
* @param {number} y - The y scale.
* @param {number} z - The z scale.
* @return {BufferGeometry} A reference to this instance.
*/
scale( x, y, z ) {

@@ -284,2 +541,10 @@

/**
* Rotates the geometry to face a point in 3D space. This is typically done as a one time
* operation, and not during a loop. Use {@link Object3D#lookAt} for typical
* real-time mesh rotation.
*
* @param {Vector3} vector - The target point.
* @return {BufferGeometry} A reference to this instance.
*/
lookAt( vector ) {

@@ -297,2 +562,7 @@

/**
* Center the geometry based on its bounding box.
*
* @return {BufferGeometry} A reference to this instance.
*/
center() {

@@ -310,2 +580,13 @@

/**
* Defines a geometry by creating a `position` attribute based on the given array of points. The array
* can hold 2D or 3D vectors. When using two-dimensional data, the `z` coordinate for all vertices is
* set to `0`.
*
* If the method is used with an existing `position` attribute, the vertex data are overwritten with the
* data from the array. The length of the array must match the vertex count.
*
* @param {Array<Vector2>|Array<Vector3>} points - The points.
* @return {BufferGeometry} A reference to this instance.
*/
setFromPoints( points ) {

@@ -353,2 +634,7 @@

/**
* Computes the bounding box of the geometry, and updates the `boundingBox` member.
* The bounding box is not computed by the engine; it must be computed by your app.
* You may need to recompute the bounding box if the geometry vertices are modified.
*/
computeBoundingBox() {

@@ -424,2 +710,7 @@

/**
* Computes the bounding sphere of the geometry, and updates the `boundingSphere` member.
* The engine automatically computes the bounding sphere when it is needed, e.g., for ray casting or view frustum culling.
* You may need to recompute the bounding sphere if the geometry vertices are modified.
*/
computeBoundingSphere() {

@@ -537,2 +828,9 @@

/**
* Calculates and adds a tangent attribute to this geometry.
*
* The computation is only supported for indexed geometries and if position, normal, and uv attributes
* are defined. When using a tangent space normal map, prefer the MikkTSpace algorithm provided by
* {@link BufferGeometryUtils#computeMikkTSpaceTangents} instead.
*/
computeTangents() {

@@ -697,2 +995,8 @@

/**
* Computes vertex normals for the given vertex data. For indexed geometries, the method sets
* each vertex normal to be the average of the face normals of the faces that share that vertex.
* For non-indexed geometries, vertices are not shared, and the method sets each vertex normal
* to be the same as the face normal.
*/
computeVertexNormals() {

@@ -790,2 +1094,6 @@

/**
* Ensures every normal vector in a geometry will have a magnitude of `1`. This will
* correct lighting on the geometry surfaces.
*/
normalizeNormals() {

@@ -807,2 +1115,8 @@

/**
* Return a new non-index version of this indexed geometry. If the geometry
* is already non-indexed, the method is a NOOP.
*
* @return {BufferGeometry} The non-indexed version of this indexed geometry.
*/
toNonIndexed() {

@@ -910,2 +1224,7 @@

/**
* Serializes the geometry into JSON.
*
* @return {Object} A JSON object representing the serialized geometry.
*/
toJSON() {

@@ -1024,2 +1343,7 @@

/**
* Returns a new geometry with copied values from this instance.
*
* @return {BufferGeometry} A clone of this instance.
*/
clone() {

@@ -1031,2 +1355,8 @@

/**
* Copies the values of the given geometry to this instance.
*
* @param {BufferGeometry} source - The geometry to copy.
* @return {BufferGeometry} A reference to this instance.
*/
copy( source ) {

@@ -1057,3 +1387,3 @@

this.setIndex( index.clone( data ) );
this.setIndex( index.clone() );

@@ -1138,2 +1468,8 @@ }

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*
* @fires BufferGeometry#dispose
*/
dispose() {

@@ -1140,0 +1476,0 @@

@@ -0,11 +1,54 @@

/**
* Class for keeping track of time.
*/
class Clock {
/**
* Constructs a new clock.
*
* @param {boolean} [autoStart=true] - Whether to automatically start the clock when
* `getDelta()` is called for the first time.
*/
constructor( autoStart = true ) {
/**
* If set to `true`, the clock starts automatically when `getDelta()` is called
* for the first time.
*
* @type {boolean}
* @default true
*/
this.autoStart = autoStart;
/**
* Holds the time at which the clock's `start()` method was last called.
*
* @type {number}
* @default 0
*/
this.startTime = 0;
/**
* Holds the time at which the clock's `start()`, `getElapsedTime()` or
* `getDelta()` methods were last called.
*
* @type {number}
* @default 0
*/
this.oldTime = 0;
/**
* Keeps track of the total time that the clock has been running.
*
* @type {number}
* @default 0
*/
this.elapsedTime = 0;
/**
* Whether the clock is running or not.
*
* @type {boolean}
* @default true
*/
this.running = false;

@@ -15,2 +58,6 @@

/**
* Starts the clock. When `autoStart` is set to `true`, the method is automatically
* called by the class.
*/
start() {

@@ -26,2 +73,5 @@

/**
* Stops the clock.
*/
stop() {

@@ -35,2 +85,7 @@

/**
* Returns the elapsed time in seconds.
*
* @return {number} The elapsed time.
*/
getElapsedTime() {

@@ -43,2 +98,7 @@

/**
* Returns the delta time in seconds.
*
* @return {number} The delta time.
*/
getDelta() {

@@ -45,0 +105,0 @@

@@ -0,15 +1,81 @@

/**
* An alternative version of a buffer attribute with more control over the VBO.
*
* The renderer does not construct a VBO for this kind of attribute. Instead, it uses
* whatever VBO is passed in constructor and can later be altered via the `buffer` property.
*
* The most common use case for this class is when some kind of GPGPU calculation interferes
* or even produces the VBOs in question.
*
* Notice that this class can only be used with {@link WebGLRenderer}.
*/
class GLBufferAttribute {
/**
* Constructs a new GL buffer attribute.
*
* @param {WebGLBuffer} buffer - The native WebGL buffer.
* @param {number} type - The native data type (e.g. `gl.FLOAT`).
* @param {number} itemSize - The item size.
* @param {number} elementSize - The corresponding size (in bytes) for the given `type` parameter.
* @param {number} count - The expected number of vertices in VBO.
*/
constructor( buffer, type, itemSize, elementSize, count ) {
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isGLBufferAttribute = true;
/**
* The name of the buffer attribute.
*
* @type {string}
*/
this.name = '';
/**
* The native WebGL buffer.
*
* @type {WebGLBuffer}
*/
this.buffer = buffer;
/**
* The native data type.
*
* @type {number}
*/
this.type = type;
/**
* The item size, see {@link BufferAttribute#itemSize}.
*
* @type {number}
*/
this.itemSize = itemSize;
/**
* The corresponding size (in bytes) for the given `type` parameter.
*
* @type {number}
*/
this.elementSize = elementSize;
/**
* The expected number of vertices in VBO.
*
* @type {number}
*/
this.count = count;
/**
* A version number, incremented every time the `needsUpdate` is set to `true`.
*
* @type {number}
*/
this.version = 0;

@@ -19,2 +85,10 @@

/**
* Flag to indicate that this attribute has changed and should be re-sent to
* the GPU. Set this to `true` when you modify the value of the array.
*
* @type {number}
* @default false
* @param {boolean} value
*/
set needsUpdate( value ) {

@@ -26,2 +100,8 @@

/**
* Sets the given native WebGL buffer.
*
* @param {WebGLBuffer} buffer - The buffer to set.
* @return {BufferAttribute} A reference to this instance.
*/
setBuffer( buffer ) {

@@ -35,2 +115,9 @@

/**
* Sets the given native data type and element size.
*
* @param {number} type - The native data type (e.g. `gl.FLOAT`).
* @param {number} elementSize - The corresponding size (in bytes) for the given `type` parameter.
* @return {BufferAttribute} A reference to this instance.
*/
setType( type, elementSize ) {

@@ -45,2 +132,8 @@

/**
* Sets the item size.
*
* @param {number} itemSize - The item size.
* @return {BufferAttribute} A reference to this instance.
*/
setItemSize( itemSize ) {

@@ -54,2 +147,8 @@

/**
* Sets the count (the expected number of vertices in VBO).
*
* @param {number} count - The count.
* @return {BufferAttribute} A reference to this instance.
*/
setCount( count ) {

@@ -56,0 +155,0 @@

import { BufferAttribute } from './BufferAttribute.js';
/**
* An instanced version of a buffer attribute.
*
* @augments BufferAttribute
*/
class InstancedBufferAttribute extends BufferAttribute {
/**
* Constructs a new instanced buffer attribute.
*
* @param {TypedArray} array - The array holding the attribute data.
* @param {number} itemSize - The item size.
* @param {boolean} [normalized=false] - Whether the data are normalized or not.
* @param {number} [meshPerAttribute=1] - How often a value of this buffer attribute should be repeated.
*/
constructor( array, itemSize, normalized, meshPerAttribute = 1 ) {

@@ -9,4 +22,20 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isInstancedBufferAttribute = true;
/**
* Defines how often a value of this buffer attribute should be repeated. A
* value of one means that each value of the instanced attribute is used for
* a single instance. A value of two means that each value is used for two
* consecutive instances (and so on).
*
* @type {number}
* @default 1
*/
this.meshPerAttribute = meshPerAttribute;

@@ -13,0 +42,0 @@

import { BufferGeometry } from './BufferGeometry.js';
/**
* An instanced version of a geometry.
*/
class InstancedBufferGeometry extends BufferGeometry {
/**
* Constructs a new instanced buffer geometry.
*/
constructor() {

@@ -9,5 +15,19 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isInstancedBufferGeometry = true;
this.type = 'InstancedBufferGeometry';
/**
* The instance count.
*
* @type {number}
* @default Infinity
*/
this.instanceCount = Infinity;

@@ -14,0 +34,0 @@

import { InterleavedBuffer } from './InterleavedBuffer.js';
/**
* An instanced version of an interleaved buffer.
*
* @augments InterleavedBuffer
*/
class InstancedInterleavedBuffer extends InterleavedBuffer {
/**
* Constructs a new instanced interleaved buffer.
*
* @param {TypedArray} array - A typed array with a shared buffer storing attribute data.
* @param {number} stride - The number of typed-array elements per vertex.
* @param {number} [meshPerAttribute=1] - Defines how often a value of this interleaved buffer should be repeated.
*/
constructor( array, stride, meshPerAttribute = 1 ) {

@@ -9,4 +21,18 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isInstancedInterleavedBuffer = true;
/**
* Defines how often a value of this buffer attribute should be repeated,
* see {@link InstancedBufferAttribute#meshPerAttribute}.
*
* @type {number}
* @default 1
*/
this.meshPerAttribute = meshPerAttribute;

@@ -13,0 +39,0 @@

import { generateUUID } from '../math/MathUtils.js';
import { StaticDrawUsage } from '../constants.js';
/**
* "Interleaved" means that multiple attributes, possibly of different types,
* (e.g., position, normal, uv, color) are packed into a single array buffer.
*
* An introduction into interleaved arrays can be found here: [Interleaved array basics]{@link https://blog.tojicode.com/2011/05/interleaved-array-basics.html}
*/
class InterleavedBuffer {
/**
* Constructs a new interleaved buffer.
*
* @param {TypedArray} array - A typed array with a shared buffer storing attribute data.
* @param {number} stride - The number of typed-array elements per vertex.
*/
constructor( array, stride ) {
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isInterleavedBuffer = true;
/**
* A typed array with a shared buffer storing attribute data.
*
* @type {TypedArray}
*/
this.array = array;
/**
* The number of typed-array elements per vertex.
*
* @type {number}
*/
this.stride = stride;
/**
* The total number of elements in the array
*
* @type {number}
* @readonly
*/
this.count = array !== undefined ? array.length / stride : 0;
/**
* Defines the intended usage pattern of the data store for optimization purposes.
*
* Note: After the initial use of a buffer, its usage cannot be changed. Instead,
* instantiate a new one and set the desired usage before the next render.
*
* @type {(StaticDrawUsage|DynamicDrawUsage|StreamDrawUsage|StaticReadUsage|DynamicReadUsage|StreamReadUsage|StaticCopyUsage|DynamicCopyUsage|StreamCopyUsage)}
* @default StaticDrawUsage
*/
this.usage = StaticDrawUsage;
/**
* This can be used to only update some components of stored vectors (for example, just the
* component related to color). Use the `addUpdateRange()` function to add ranges to this array.
*
* @type {Array<Object>}
*/
this.updateRanges = [];
/**
* A version number, incremented every time the `needsUpdate` is set to `true`.
*
* @type {number}
*/
this.version = 0;
/**
* The UUID of the interleaved buffer.
*
* @type {string}
* @readonly
*/
this.uuid = generateUUID();

@@ -23,4 +87,16 @@

/**
* A callback function that is executed after the renderer has transferred the attribute array
* data to the GPU.
*/
onUploadCallback() {}
/**
* Flag to indicate that this attribute has changed and should be re-sent to
* the GPU. Set this to `true` when you modify the value of the array.
*
* @type {number}
* @default false
* @param {boolean} value
*/
set needsUpdate( value ) {

@@ -32,2 +108,8 @@

/**
* Sets the usage of this interleaved buffer.
*
* @param {(StaticDrawUsage|DynamicDrawUsage|StreamDrawUsage|StaticReadUsage|DynamicReadUsage|StreamReadUsage|StaticCopyUsage|DynamicCopyUsage|StreamCopyUsage)} value - The usage to set.
* @return {InterleavedBuffer} A reference to this interleaved buffer.
*/
setUsage( value ) {

@@ -41,2 +123,8 @@

/**
* Adds a range of data in the data array to be updated on the GPU.
*
* @param {number} start - Position at which to start update.
* @param {number} count - The number of components to update.
*/
addUpdateRange( start, count ) {

@@ -48,2 +136,5 @@

/**
* Clears the update ranges.
*/
clearUpdateRanges() {

@@ -55,2 +146,8 @@

/**
* Copies the values of the given interleaved buffer to this instance.
*
* @param {InterleavedBuffer} source - The interleaved buffer to copy.
* @return {InterleavedBuffer} A reference to this instance.
*/
copy( source ) {

@@ -67,10 +164,20 @@

copyAt( index1, attribute, index2 ) {
/**
* Copies a vector from the given interleaved buffer to this one. The start
* and destination position in the attribute buffers are represented by the
* given indices.
*
* @param {number} index1 - The destination index into this interleaved buffer.
* @param {InterleavedBuffer} interleavedBuffer - The interleaved buffer to copy from.
* @param {number} index2 - The source index into the given interleaved buffer.
* @return {InterleavedBuffer} A reference to this instance.
*/
copyAt( index1, interleavedBuffer, index2 ) {
index1 *= this.stride;
index2 *= attribute.stride;
index2 *= interleavedBuffer.stride;
for ( let i = 0, l = this.stride; i < l; i ++ ) {
this.array[ index1 + i ] = attribute.array[ index2 + i ];
this.array[ index1 + i ] = interleavedBuffer.array[ index2 + i ];

@@ -83,2 +190,9 @@ }

/**
* Sets the given array data in the interleaved buffer.
*
* @param {(TypedArray|Array)} value - The array data to set.
* @param {number} [offset=0] - The offset in this interleaved buffer's array.
* @return {InterleavedBuffer} A reference to this instance.
*/
set( value, offset = 0 ) {

@@ -92,2 +206,8 @@

/**
* Returns a new interleaved buffer with copied values from this instance.
*
* @param {Object} [data] - An object with shared array buffers that allows to retain shared structures.
* @return {InterleavedBuffer} A clone of this instance.
*/
clone( data ) {

@@ -122,2 +242,10 @@

/**
* Sets the given callback function that is executed after the Renderer has transferred
* the array data to the GPU. Can be used to perform clean-up operations after
* the upload when data are not needed anymore on the CPU side.
*
* @param {Function} callback - The `onUpload()` callback.
* @return {InterleavedBuffer} A reference to this instance.
*/
onUpload( callback ) {

@@ -131,2 +259,8 @@

/**
* Serializes the interleaved buffer into JSON.
*
* @param {Object} [data] - An optional value holding meta information about the serialization.
* @return {Object} A JSON object representing the serialized interleaved buffer.
*/
toJSON( data ) {

@@ -133,0 +267,0 @@

@@ -7,14 +7,61 @@ import { Vector3 } from '../math/Vector3.js';

/**
* An alternative version of a buffer attribute with interleaved data. Interleaved
* attributes share a common interleaved data storage ({@link InterleavedBuffer}) and refer with
* different offsets into the buffer.
*/
class InterleavedBufferAttribute {
/**
* Constructs a new interleaved buffer attribute.
*
* @param {InterleavedBuffer} interleavedBuffer - The buffer holding the interleaved data.
* @param {number} itemSize - The item size.
* @param {number} offset - The attribute offset into the buffer.
* @param {boolean} [normalized=false] - Whether the data are normalized or not.
*/
constructor( interleavedBuffer, itemSize, offset, normalized = false ) {
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isInterleavedBufferAttribute = true;
/**
* The name of the buffer attribute.
*
* @type {string}
*/
this.name = '';
/**
* The buffer holding the interleaved data.
*
* @type {InterleavedBuffer}
*/
this.data = interleavedBuffer;
/**
* The item size, see {@link BufferAttribute#itemSize}.
*
* @type {number}
*/
this.itemSize = itemSize;
/**
* The attribute offset into the buffer.
*
* @type {number}
*/
this.offset = offset;
/**
* Whether the data are normalized or not, see {@link BufferAttribute#normalized}
*
* @type {InterleavedBuffer}
*/
this.normalized = normalized;

@@ -24,2 +71,8 @@

/**
* The item count of this buffer attribute.
*
* @type {number}
* @readonly
*/
get count() {

@@ -31,2 +84,7 @@

/**
* The array holding the interleaved buffer attribute data.
*
* @type {TypedArray}
*/
get array() {

@@ -38,2 +96,10 @@

/**
* Flag to indicate that this attribute has changed and should be re-sent to
* the GPU. Set this to `true` when you modify the value of the array.
*
* @type {number}
* @default false
* @param {boolean} value
*/
set needsUpdate( value ) {

@@ -45,2 +111,9 @@

/**
* Applies the given 4x4 matrix to the given attribute. Only works with
* item size `3`.
*
* @param {Matrix4} m - The matrix to apply.
* @return {InterleavedBufferAttribute} A reference to this instance.
*/
applyMatrix4( m ) {

@@ -62,2 +135,9 @@

/**
* Applies the given 3x3 normal matrix to the given attribute. Only works with
* item size `3`.
*
* @param {Matrix3} m - The normal matrix to apply.
* @return {InterleavedBufferAttribute} A reference to this instance.
*/
applyNormalMatrix( m ) {

@@ -79,2 +159,9 @@

/**
* Applies the given 4x4 matrix to the given attribute. Only works with
* item size `3` and with direction vectors.
*
* @param {Matrix4} m - The matrix to apply.
* @return {InterleavedBufferAttribute} A reference to this instance.
*/
transformDirection( m ) {

@@ -96,2 +183,9 @@

/**
* Returns the given component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @param {number} component - The component index.
* @return {number} The returned value.
*/
getComponent( index, component ) {

@@ -107,2 +201,10 @@

/**
* Sets the given value to the given component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @param {number} component - The component index.
* @param {number} value - The value to set.
* @return {InterleavedBufferAttribute} A reference to this instance.
*/
setComponent( index, component, value ) {

@@ -118,2 +220,9 @@

/**
* Sets the x component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @param {number} x - The value to set.
* @return {InterleavedBufferAttribute} A reference to this instance.
*/
setX( index, x ) {

@@ -129,2 +238,9 @@

/**
* Sets the y component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @param {number} y - The value to set.
* @return {InterleavedBufferAttribute} A reference to this instance.
*/
setY( index, y ) {

@@ -140,2 +256,9 @@

/**
* Sets the z component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @param {number} z - The value to set.
* @return {InterleavedBufferAttribute} A reference to this instance.
*/
setZ( index, z ) {

@@ -151,2 +274,9 @@

/**
* Sets the w component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @param {number} w - The value to set.
* @return {InterleavedBufferAttribute} A reference to this instance.
*/
setW( index, w ) {

@@ -162,2 +292,8 @@

/**
* Returns the x component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @return {number} The x component.
*/
getX( index ) {

@@ -173,2 +309,8 @@

/**
* Returns the y component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @return {number} The y component.
*/
getY( index ) {

@@ -184,2 +326,8 @@

/**
* Returns the z component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @return {number} The z component.
*/
getZ( index ) {

@@ -195,2 +343,8 @@

/**
* Returns the w component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @return {number} The w component.
*/
getW( index ) {

@@ -206,2 +360,10 @@

/**
* Sets the x and y component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @param {number} x - The value for the x component to set.
* @param {number} y - The value for the y component to set.
* @return {InterleavedBufferAttribute} A reference to this instance.
*/
setXY( index, x, y ) {

@@ -225,2 +387,11 @@

/**
* Sets the x, y and z component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @param {number} x - The value for the x component to set.
* @param {number} y - The value for the y component to set.
* @param {number} z - The value for the z component to set.
* @return {InterleavedBufferAttribute} A reference to this instance.
*/
setXYZ( index, x, y, z ) {

@@ -246,2 +417,12 @@

/**
* Sets the x, y, z and w component of the vector at the given index.
*
* @param {number} index - The index into the buffer attribute.
* @param {number} x - The value for the x component to set.
* @param {number} y - The value for the y component to set.
* @param {number} z - The value for the z component to set.
* @param {number} w - The value for the w component to set.
* @return {InterleavedBufferAttribute} A reference to this instance.
*/
setXYZW( index, x, y, z, w ) {

@@ -269,2 +450,10 @@

/**
* Returns a new buffer attribute with copied values from this instance.
*
* If no parameter is provided, cloning an interleaved buffer attribute will de-interleave buffer data.
*
* @param {Object} [data] - An object with interleaved buffers that allows to retain the interleaved property.
* @return {BufferAttribute|InterleavedBufferAttribute} A clone of this instance.
*/
clone( data ) {

@@ -312,2 +501,10 @@

/**
* Serializes the buffer attribute into JSON.
*
* If no parameter is provided, cloning an interleaved buffer attribute will de-interleave buffer data.
*
* @param {Object} [data] - An optional value holding meta information about the serialization.
* @return {Object} A JSON object representing the serialized buffer attribute.
*/
toJSON( data ) {

@@ -314,0 +511,0 @@

@@ -0,5 +1,27 @@

/**
* A layers object assigns an 3D object to 1 or more of 32
* layers numbered `0` to `31` - internally the layers are stored as a
* bit mask], and by default all 3D objects are a member of layer `0`.
*
* This can be used to control visibility - an object must share a layer with
* a camera to be visible when that camera's view is
* rendered.
*
* All classes that inherit from {@link Object3D} have an `layers` property which
* is an instance of this class.
*/
class Layers {
/**
* Constructs a new layers instance, with membership
* initially set to layer `0`.
*/
constructor() {
/**
* A bit mask storing which of the 32 layers this layers object is currently
* a member of.
*
* @type {number}
*/
this.mask = 1 | 0;

@@ -9,14 +31,27 @@

set( channel ) {
/**
* Sets membership to the given layer, and remove membership all other layers.
*
* @param {number} layer - The layer to set.
*/
set( layer ) {
this.mask = ( 1 << channel | 0 ) >>> 0;
this.mask = ( 1 << layer | 0 ) >>> 0;
}
enable( channel ) {
/**
* Adds membership of the given layer.
*
* @param {number} layer - The layer to enable.
*/
enable( layer ) {
this.mask |= 1 << channel | 0;
this.mask |= 1 << layer | 0;
}
/**
* Adds membership to all layers.
*/
enableAll() {

@@ -28,14 +63,27 @@

toggle( channel ) {
/**
* Toggles the membership of the given layer.
*
* @param {number} layer - The layer to toggle.
*/
toggle( layer ) {
this.mask ^= 1 << channel | 0;
this.mask ^= 1 << layer | 0;
}
disable( channel ) {
/**
* Removes membership of the given layer.
*
* @param {number} layer - The layer to enable.
*/
disable( layer ) {
this.mask &= ~ ( 1 << channel | 0 );
this.mask &= ~ ( 1 << layer | 0 );
}
/**
* Removes the membership from all layers.
*/
disableAll() {

@@ -47,2 +95,9 @@

/**
* Returns `true` if this and the given layers object have at least one
* layer in common.
*
* @param {Layers} layers - The layers to test.
* @return {boolean } Whether this and the given layers object have at least one layer in common or not.
*/
test( layers ) {

@@ -54,5 +109,11 @@

isEnabled( channel ) {
/**
* Returns `true` if the given layer is enabled.
*
* @param {number} layer - The layer to test.
* @return {boolean } Whether the given layer is enabled or not.
*/
isEnabled( layer ) {
return ( this.mask & ( 1 << channel | 0 ) ) !== 0;
return ( this.mask & ( 1 << layer | 0 ) ) !== 0;

@@ -59,0 +120,0 @@ }

@@ -334,2 +334,25 @@ import { Quaternion } from '../math/Quaternion.js';

/**
* Custom depth material to be used when rendering to the depth map. Can only be used
* in context of meshes. When shadow-casting with a {@link DirectionalLight} or {@link SpotLight},
* if you are modifying vertex positions in the vertex shader you must specify a custom depth
* material for proper shadows.
*
* Only relevant in context of {@link WebGLRenderer}.
*
* @type {(Material|undefined)}
* @default undefined
*/
this.customDepthMaterial = undefined;
/**
* Same as {@link Object3D#customDepthMaterial}, but used with {@link PointLight}.
*
* Only relevant in context of {@link WebGLRenderer}.
*
* @type {(Material|undefined)}
* @default undefined
*/
this.customDistanceMaterial = undefined;
/**
* An object that can be used to store custom data about the 3D object. It

@@ -336,0 +359,0 @@ * should not hold references to functions as these will not be cloned.

@@ -7,14 +7,82 @@ import { Matrix4 } from '../math/Matrix4.js';

/**
* This class is designed to assist with raycasting. Raycasting is used for
* mouse picking (working out what objects in the 3d space the mouse is over)
* amongst other things.
*/
class Raycaster {
/**
* Constructs a new raycaster.
*
* @param {Vector3} origin - The origin vector where the ray casts from.
* @param {Vector3} direction - The (normalized) direction vector that gives direction to the ray.
* @param {number} [near=0] - All results returned are further away than near. Near can't be negative.
* @param {number} [far=Infinity] - All results returned are closer than far. Far can't be lower than near.
*/
constructor( origin, direction, near = 0, far = Infinity ) {
/**
* The ray used for raycasting.
*
* @type {Ray}
*/
this.ray = new Ray( origin, direction );
// direction is assumed to be normalized (for accurate distance calculations)
/**
* All results returned are further away than near. Near can't be negative.
*
* @type {number}
* @default 0
*/
this.near = near;
/**
* All results returned are further away than near. Near can't be negative.
*
* @type {number}
* @default Infinity
*/
this.far = far;
/**
* The camera to use when raycasting against view-dependent objects such as
* billboarded objects like sprites. This field can be set manually or
* is set when calling `setFromCamera()`.
*
* @type {?Camera}
* @default null
*/
this.camera = null;
/**
* Allows to selectively ignore 3D objects when performing intersection tests.
* The following code example ensures that only 3D objects on layer `1` will be
* honored by raycaster.
* ```js
* raycaster.layers.set( 1 );
* object.layers.enable( 1 );
* ```
*
* @type {Layers}
*/
this.layers = new Layers();
/**
* A parameter object that configures the raycasting. It has the structure:
*
* ```
* {
* Mesh: {},
* Line: { threshold: 1 },
* LOD: {},
* Points: { threshold: 1 },
* Sprite: {}
* }
* ```
* Where `threshold` is the precision of the raycaster when intersecting objects, in world units.
*
* @type {Object}
*/
this.params = {

@@ -30,2 +98,8 @@ Mesh: {},

/**
* Updates the ray with a new origin and direction by copying the values from the arguments.
*
* @param {Vector3} origin - The origin vector where the ray casts from.
* @param {Vector3} direction - The (normalized) direction vector that gives direction to the ray.
*/
set( origin, direction ) {

@@ -39,2 +113,9 @@

/**
* Uses the given coordinates and camera to compute a new origin and direction for the internal ray.
*
* @param {Vector2} coords - 2D coordinates of the mouse, in normalized device coordinates (NDC).
* X and Y components should be between `-1` and `1`.
* @param {Camera} camera - The camera from which the ray should originate.
*/
setFromCamera( coords, camera ) {

@@ -62,2 +143,8 @@

/**
* Uses the given WebXR controller to compute a new origin and direction for the internal ray.
*
* @param {WebXRController} controller - The controller to copy the position and direction from.
* @return {Raycaster} A reference to this raycaster.
*/
setFromXRController( controller ) {

@@ -74,2 +161,38 @@

/**
* The intersection point of a raycaster intersection test.
* @typedef {Object} Raycaster~Intersection
* @property {number} distance - The distance from the ray's origin to the intersection point.
* @property {number} distanceToRay - Some 3D objects e.g. {@link Points} provide the distance of the
* intersection to the nearest point on the ray. For other objects it will be `undefined`.
* @property {Vector3} point - The intersection point, in world coordinates.
* @property {Object} face - The face that has been intersected.
* @property {number} faceIndex - The face index.
* @property {Object3D} object - The 3D object that has been intersected.
* @property {Vector2} uv - U,V coordinates at point of intersection.
* @property {Vector2} uv1 - Second set of U,V coordinates at point of intersection.
* @property {Vector3} uv1 - Interpolated normal vector at point of intersection.
* @property {number} instanceId - The index number of the instance where the ray
* intersects the {@link InstancedMesh}.
*/
/**
* Checks all intersection between the ray and the object with or without the
* descendants. Intersections are returned sorted by distance, closest first.
*
* `Raycaster` delegates to the `raycast()` method of the passed 3D object, when
* evaluating whether the ray intersects the object or not. This allows meshes to respond
* differently to ray casting than lines or points.
*
* Note that for meshes, faces must be pointed towards the origin of the ray in order
* to be detected; intersections of the ray passing through the back of a face will not
* be detected. To raycast against both faces of an object, you'll want to set {@link Material#side}
* to `THREE.DoubleSide`.
*
* @param {Object3D} object - The 3D object to check for intersection with the ray.
* @param {boolean} [recursive=true] - If set to `true`, it also checks all descendants.
* Otherwise it only checks intersection with the object.
* @param {Array<Raycaster~Intersection>} [intersects=[]] The target array that holds the result of the method.
* @return {Array<Raycaster~Intersection>} An array holding the intersection points.
*/
intersectObject( object, recursive = true, intersects = [] ) {

@@ -85,2 +208,12 @@

/**
* Checks all intersection between the ray and the objects with or without
* the descendants. Intersections are returned sorted by distance, closest first.
*
* @param {Array<Object3D>} objects - The 3D objects to check for intersection with the ray.
* @param {boolean} [recursive=true] - If set to `true`, it also checks all descendants.
* Otherwise it only checks intersection with the object.
* @param {Array<Raycaster~Intersection>} [intersects=[]] The target array that holds the result of the method.
* @return {Array<Raycaster~Intersection>} An array holding the intersection points.
*/
intersectObjects( objects, recursive = true, intersects = [] ) {

@@ -87,0 +220,0 @@

@@ -7,9 +7,42 @@ import { EventDispatcher } from './EventDispatcher.js';

/*
In options, we can specify:
* Texture parameters for an auto-generated target texture
* depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
*/
/**
* A render target is a buffer where the video card draws pixels for a scene
* that is being rendered in the background. It is used in different effects,
* such as applying postprocessing to a rendered image before displaying it
* on the screen.
*
* @augments EventDispatcher
*/
class RenderTarget extends EventDispatcher {
/**
* Render target options.
*
* @typedef {Object} RenderTarget~Options
* @property {boolean} [generateMipmaps=false] - Whether to generate mipmaps or not.
* @property {number} [magFilter=LinearFilter] - The mag filter.
* @property {number} [minFilter=LinearFilter] - The min filter.
* @property {number} [format=RGBAFormat] - The texture format.
* @property {number} [type=UnsignedByteType] - The texture type.
* @property {?string} [internalFormat=null] - The texture's internal format.
* @property {number} [wrapS=ClampToEdgeWrapping] - The texture's uv wrapping mode.
* @property {number} [wrapT=ClampToEdgeWrapping] - The texture's uv wrapping mode.
* @property {number} [anisotropy=1] - The texture's anisotropy value.
* @property {string} [colorSpace=NoColorSpace] - The texture's color space.
* @property {boolean} [depthBuffer=true] - Whether to allocate a depth buffer or not.
* @property {boolean} [stencilBuffer=false] - Whether to allocate a stencil buffer or not.
* @property {boolean} [resolveDepthBuffer=true] - Whether to resolve the depth buffer or not.
* @property {boolean} [resolveStencilBuffer=true] - Whether to resolve the stencil buffer or not.
* @property {?Texture} [depthTexture=null] - Reference to a depth texture.
* @property {number} [samples=0] - The MSAA samples count.
* @property {number} [count=1] - Defines the number of color attachments . Must be at least `1`.
*/
/**
* Constructs a new render target.
*
* @param {number} [width=1] - The width of the render target.
* @param {number} [height=1] - The height of the render target.
* @param {RenderTarget~Options} [options] - The configuration object.
*/
constructor( width = 1, height = 1, options = {} ) {

@@ -19,11 +52,59 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isRenderTarget = true;
/**
* The width of the render target.
*
* @type {number}
* @default 1
*/
this.width = width;
/**
* The height of the render target.
*
* @type {number}
* @default 1
*/
this.height = height;
/**
* The depth of the render target.
*
* @type {number}
* @default 1
*/
this.depth = 1;
/**
* A rectangular area inside the render target's viewport. Fragments that are
* outside the area will be discarded.
*
* @type {Vector4}
* @default (0,0,width,height)
*/
this.scissor = new Vector4( 0, 0, width, height );
/**
* Indicates whether the scissor test should be enabled when rendering into
* this render target or not.
*
* @type {boolean}
* @default false
*/
this.scissorTest = false;
/**
* A rectangular area representing the render target's viewport.
*
* @type {Vector4}
* @default (0,0,width,height)
*/
this.viewport = new Vector4( 0, 0, width, height );

@@ -52,2 +133,8 @@

/**
* An array of textures. Each color attachment is represented as a separate texture.
* Has at least a single entry for the default color attachment.
*
* @type {Array<Texture>}
*/
this.textures = [];

@@ -64,11 +151,44 @@

/**
* Whether to allocate a depth buffer or not.
*
* @type {boolean}
* @default true
*/
this.depthBuffer = options.depthBuffer;
/**
* Whether to allocate a stencil buffer or not.
*
* @type {boolean}
* @default false
*/
this.stencilBuffer = options.stencilBuffer;
/**
* Whether to resolve the depth buffer or not.
*
* @type {boolean}
* @default true
*/
this.resolveDepthBuffer = options.resolveDepthBuffer;
/**
* Whether to resolve the stencil buffer or not.
*
* @type {boolean}
* @default true
*/
this.resolveStencilBuffer = options.resolveStencilBuffer;
this._depthTexture = null;
this.depthTexture = options.depthTexture;
this._depthTexture = options.depthTexture;
/**
* The number of MSAA samples.
*
* A value of `0` disables MSAA.
*
* @type {number}
* @default 0
*/
this.samples = options.samples;

@@ -78,2 +198,7 @@

/**
* The texture representing the default color attachment.
*
* @type {Texture}
*/
get texture() {

@@ -100,2 +225,10 @@

/**
* Instead of saving the depth in a renderbuffer, a texture
* can be used instead which is useful for further processing
* e.g. in context of post-processing.
*
* @type {?DepthTexture}
* @default null
*/
get depthTexture() {

@@ -107,2 +240,9 @@

/**
* Sets the size of this render target.
*
* @param {number} width - The width.
* @param {number} height - The height.
* @param {number} [depth=1] - The depth.
*/
setSize( width, height, depth = 1 ) {

@@ -133,2 +273,7 @@

/**
* Returns a new render target with copied values from this instance.
*
* @return {RenderTarget} A clone of this instance.
*/
clone() {

@@ -140,2 +285,10 @@

/**
* Copies the settings of the given render target. This is a structural copy so
* no resources are shared between render targets after the copy. That includes
* all MRT textures and the depth texture.
*
* @param {RenderTarget} source - The render target to copy.
* @return {RenderTarget} A reference to this instance.
*/
copy( source ) {

@@ -181,2 +334,8 @@

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*
* @fires RenderTarget#dispose
*/
dispose() {

@@ -183,0 +342,0 @@

import { RenderTarget } from './RenderTarget.js';
import { Data3DTexture } from '../textures/Data3DTexture.js';
/**
* Represents a 3D render target.
*
* @augments RenderTarget
*/
class RenderTarget3D extends RenderTarget {
/**
* Constructs a new 3D render target.
*
* @param {number} [width=1] - The width of the render target.
* @param {number} [height=1] - The height of the render target.
* @param {number} [depth=1] - The height of the render target.
* @param {RenderTarget~Options} [options] - The configuration object.
*/
constructor( width = 1, height = 1, depth = 1, options = {} ) {

@@ -10,2 +23,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isRenderTarget3D = true;

@@ -15,2 +35,7 @@

/**
* Overwritten with a different texture type.
*
* @type {Data3DTexture}
*/
this.texture = new Data3DTexture( null, width, height, depth );

@@ -17,0 +42,0 @@

import { RenderTarget } from './RenderTarget.js';
import { DataArrayTexture } from '../textures/DataArrayTexture.js';
/**
* Represents an array render target.
*
* @augments RenderTarget
*/
class RenderTargetArray extends RenderTarget {
/**
* Constructs a new 3D render target.
*
* @param {number} [width=1] - The width of the render target.
* @param {number} [height=1] - The height of the render target.
* @param {number} [depth=1] - The height of the render target.
* @param {RenderTarget~Options} [options] - The configuration object.
*/
constructor( width = 1, height = 1, depth = 1, options = {} ) {

@@ -14,2 +27,7 @@

/**
* Overwritten with a different texture type.
*
* @type {DataArrayTexture}
*/
this.texture = new DataArrayTexture( null, width, height, depth );

@@ -16,0 +34,0 @@

@@ -0,5 +1,28 @@

/**
* Represents a uniform which is a global shader variable. They are passed to shader programs.
*
* When declaring a uniform of a {@link ShaderMaterial}, it is declared by value or by object.
* ```js
* uniforms: {
* time: { value: 1.0 },
* resolution: new Uniform( new Vector2() )
* };
* ```
* Since this class can only be used in context of {@link ShaderMaterial}, it is only supported
* in {@link WebGLRenderer}.
*/
class Uniform {
/**
* Constructs a new uniform.
*
* @param {any} value - The uniform value.
*/
constructor( value ) {
/**
* The uniform value.
*
* @type {any}
*/
this.value = value;

@@ -9,2 +32,8 @@

/**
* Returns a new uniform with copied values from this instance.
* If the value has a `clone()` method, the value is cloned as well.
*
* @return {Uniform} A clone of this instance.
*/
clone() {

@@ -11,0 +40,0 @@

@@ -6,4 +6,16 @@ import { EventDispatcher } from './EventDispatcher.js';

/**
* A class for managing multiple uniforms in a single group. The renderer will process
* such a definition as a single UBO.
*
* Since this class can only be used in context of {@link ShaderMaterial}, it is only supported
* in {@link WebGLRenderer}.
*
* @augments EventDispatcher
*/
class UniformsGroup extends EventDispatcher {
/**
* Constructs a new uniforms group.
*/
constructor() {

@@ -13,9 +25,40 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isUniformsGroup = true;
/**
* The ID of the 3D object.
*
* @name UniformsGroup#id
* @type {number}
* @readonly
*/
Object.defineProperty( this, 'id', { value: _id ++ } );
/**
* The name of the uniforms group.
*
* @type {string}
*/
this.name = '';
/**
* The buffer usage.
*
* @type {(StaticDrawUsage|DynamicDrawUsage|StreamDrawUsage|StaticReadUsage|DynamicReadUsage|StreamReadUsage|StaticCopyUsage|DynamicCopyUsage|StreamCopyUsage)}
* @default StaticDrawUsage
*/
this.usage = StaticDrawUsage;
/**
* An array holding the uniforms.
*
* @type {Array<Uniform>}
*/
this.uniforms = [];

@@ -25,2 +68,8 @@

/**
* Adds the given uniform to this uniforms group.
*
* @param {Uniform} uniform - The uniform to add.
* @return {UniformsGroup} A reference to this uniforms group.
*/
add( uniform ) {

@@ -34,2 +83,8 @@

/**
* Removes the given uniform from this uniforms group.
*
* @param {Uniform} uniform - The uniform to remove.
* @return {UniformsGroup} A reference to this uniforms group.
*/
remove( uniform ) {

@@ -45,2 +100,8 @@

/**
* Sets the name of this uniforms group.
*
* @param {string} name - The name to set.
* @return {UniformsGroup} A reference to this uniforms group.
*/
setName( name ) {

@@ -54,2 +115,8 @@

/**
* Sets the usage of this uniforms group.
*
* @param {(StaticDrawUsage|DynamicDrawUsage|StreamDrawUsage|StaticReadUsage|DynamicReadUsage|StreamReadUsage|StaticCopyUsage|DynamicCopyUsage|StreamCopyUsage)} value - The usage to set.
* @return {UniformsGroup} A reference to this uniforms group.
*/
setUsage( value ) {

@@ -63,2 +130,8 @@

/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*
* @fires Texture#dispose
*/
dispose() {

@@ -68,6 +141,10 @@

return this;
}
/**
* Copies the values of the given uniforms group to this instance.
*
* @param {UniformsGroup} source - The uniforms group to copy.
* @return {UniformsGroup} A reference to this uniforms group.
*/
copy( source ) {

@@ -98,2 +175,7 @@

/**
* Returns a new uniforms group with copied values from this instance.
*
* @return {UniformsGroup} A clone of this instance.
*/
clone() {

@@ -100,0 +182,0 @@

@@ -80,5 +80,20 @@ import { EventDispatcher } from '../core/EventDispatcher.js';

* it adds the module's event listeners to the DOM.
*
* @param {HTMLDOMElement} element - The DOM element to connect to.
*/
connect() {}
connect( element ) {
if ( element === undefined ) {
console.warn( 'THREE.Controls: connect() now requires an element.' ); // @deprecated, the warning can be removed with r185
return;
}
if ( this.domElement !== null ) this.disconnect();
this.domElement = element;
}
/**

@@ -85,0 +100,0 @@ * Disconnects the controls from the DOM.

@@ -65,3 +65,3 @@ import { clamp } from '../../math/MathUtils.js';

* @param {(Vector2|Vector3)} [optionalTarget] - The optional target vector the result is written to.
* @return {?(Vector2|Vector3)} The position on the curve. It can be a 2D or 3D vector depending on the curve definition.
* @return {(Vector2|Vector3)} The position on the curve. It can be a 2D or 3D vector depending on the curve definition.
*/

@@ -68,0 +68,0 @@ getPoint( /* t, optionalTarget */ ) {

@@ -243,3 +243,3 @@ import { Vector2 } from '../../math/Vector2.js';

* @param {boolean} [aClockwise=false] - Whether to sweep the ellipse clockwise or not.
* @param {boolean} [aRotation=0] - The rotation angle of the ellipse in radians, counterclockwise from the positive X axis.
* @param {number} [aRotation=0] - The rotation angle of the ellipse in radians, counterclockwise from the positive X axis.
* @return {Path} A reference to this path.

@@ -246,0 +246,0 @@ */

@@ -1,7 +0,3 @@

/**
* An implementation of the earcut polygon triangulation algorithm. The code
* is a port of [mapbox/earcut]{@link https://github.com/mapbox/earcut mapbox/earcut} (v2.2.4).
*
* @hideconstructor
*/
import earcut from './lib/earcut.js';
class Earcut {

@@ -20,40 +16,4 @@

const hasHoles = holeIndices && holeIndices.length;
const outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length;
let outerNode = linkedList( data, 0, outerLen, dim, true );
const triangles = [];
return earcut( data, holeIndices, dim );
if ( ! outerNode || outerNode.next === outerNode.prev ) return triangles;
let minX, minY, maxX, maxY, x, y, invSize;
if ( hasHoles ) outerNode = eliminateHoles( data, holeIndices, outerNode, dim );
// if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
if ( data.length > 80 * dim ) {
minX = maxX = data[ 0 ];
minY = maxY = data[ 1 ];
for ( let i = dim; i < outerLen; i += dim ) {
x = data[ i ];
y = data[ i + 1 ];
if ( x < minX ) minX = x;
if ( y < minY ) minY = y;
if ( x > maxX ) maxX = x;
if ( y > maxY ) maxY = y;
}
// minX, minY and invSize are later used to transform coords into integers for z-order calculation
invSize = Math.max( maxX - minX, maxY - minY );
invSize = invSize !== 0 ? 32767 / invSize : 0;
}
earcutLinked( outerNode, triangles, dim, minX, minY, invSize, 0 );
return triangles;
}

@@ -63,740 +23,2 @@

// create a circular doubly linked list from polygon points in the specified winding order
function linkedList( data, start, end, dim, clockwise ) {
let i, last;
if ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) {
for ( i = start; i < end; i += dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
} else {
for ( i = end - dim; i >= start; i -= dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
}
if ( last && equals( last, last.next ) ) {
removeNode( last );
last = last.next;
}
return last;
}
// eliminate colinear or duplicate points
function filterPoints( start, end ) {
if ( ! start ) return start;
if ( ! end ) end = start;
let p = start,
again;
do {
again = false;
if ( ! p.steiner && ( equals( p, p.next ) || area( p.prev, p, p.next ) === 0 ) ) {
removeNode( p );
p = end = p.prev;
if ( p === p.next ) break;
again = true;
} else {
p = p.next;
}
} while ( again || p !== end );
return end;
}
// main ear slicing loop which triangulates a polygon (given as a linked list)
function earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) {
if ( ! ear ) return;
// interlink polygon nodes in z-order
if ( ! pass && invSize ) indexCurve( ear, minX, minY, invSize );
let stop = ear,
prev, next;
// iterate through ears, slicing them one by one
while ( ear.prev !== ear.next ) {
prev = ear.prev;
next = ear.next;
if ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) {
// cut off the triangle
triangles.push( prev.i / dim | 0 );
triangles.push( ear.i / dim | 0 );
triangles.push( next.i / dim | 0 );
removeNode( ear );
// skipping the next vertex leads to less sliver triangles
ear = next.next;
stop = next.next;
continue;
}
ear = next;
// if we looped through the whole remaining polygon and can't find any more ears
if ( ear === stop ) {
// try filtering points and slicing again
if ( ! pass ) {
earcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 );
// if this didn't work, try curing all small self-intersections locally
} else if ( pass === 1 ) {
ear = cureLocalIntersections( filterPoints( ear ), triangles, dim );
earcutLinked( ear, triangles, dim, minX, minY, invSize, 2 );
// as a last resort, try splitting the remaining polygon into two
} else if ( pass === 2 ) {
splitEarcut( ear, triangles, dim, minX, minY, invSize );
}
break;
}
}
}
// check whether a polygon node forms a valid ear with adjacent nodes
function isEar( ear ) {
const a = ear.prev,
b = ear,
c = ear.next;
if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
// now make sure we don't have other points inside the potential ear
const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
// triangle bbox; min & max are calculated like this for speed
const x0 = ax < bx ? ( ax < cx ? ax : cx ) : ( bx < cx ? bx : cx ),
y0 = ay < by ? ( ay < cy ? ay : cy ) : ( by < cy ? by : cy ),
x1 = ax > bx ? ( ax > cx ? ax : cx ) : ( bx > cx ? bx : cx ),
y1 = ay > by ? ( ay > cy ? ay : cy ) : ( by > cy ? by : cy );
let p = c.next;
while ( p !== a ) {
if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 &&
pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) &&
area( p.prev, p, p.next ) >= 0 ) return false;
p = p.next;
}
return true;
}
function isEarHashed( ear, minX, minY, invSize ) {
const a = ear.prev,
b = ear,
c = ear.next;
if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
// triangle bbox; min & max are calculated like this for speed
const x0 = ax < bx ? ( ax < cx ? ax : cx ) : ( bx < cx ? bx : cx ),
y0 = ay < by ? ( ay < cy ? ay : cy ) : ( by < cy ? by : cy ),
x1 = ax > bx ? ( ax > cx ? ax : cx ) : ( bx > cx ? bx : cx ),
y1 = ay > by ? ( ay > cy ? ay : cy ) : ( by > cy ? by : cy );
// z-order range for the current triangle bbox;
const minZ = zOrder( x0, y0, minX, minY, invSize ),
maxZ = zOrder( x1, y1, minX, minY, invSize );
let p = ear.prevZ,
n = ear.nextZ;
// look for points inside the triangle in both directions
while ( p && p.z >= minZ && n && n.z <= maxZ ) {
if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&
pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) return false;
p = p.prevZ;
if ( n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&
pointInTriangle( ax, ay, bx, by, cx, cy, n.x, n.y ) && area( n.prev, n, n.next ) >= 0 ) return false;
n = n.nextZ;
}
// look for remaining points in decreasing z-order
while ( p && p.z >= minZ ) {
if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&
pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) return false;
p = p.prevZ;
}
// look for remaining points in increasing z-order
while ( n && n.z <= maxZ ) {
if ( n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&
pointInTriangle( ax, ay, bx, by, cx, cy, n.x, n.y ) && area( n.prev, n, n.next ) >= 0 ) return false;
n = n.nextZ;
}
return true;
}
// go through all polygon nodes and cure small local self-intersections
function cureLocalIntersections( start, triangles, dim ) {
let p = start;
do {
const a = p.prev,
b = p.next.next;
if ( ! equals( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) {
triangles.push( a.i / dim | 0 );
triangles.push( p.i / dim | 0 );
triangles.push( b.i / dim | 0 );
// remove two nodes involved
removeNode( p );
removeNode( p.next );
p = start = b;
}
p = p.next;
} while ( p !== start );
return filterPoints( p );
}
// try splitting polygon into two and triangulate them independently
function splitEarcut( start, triangles, dim, minX, minY, invSize ) {
// look for a valid diagonal that divides the polygon into two
let a = start;
do {
let b = a.next.next;
while ( b !== a.prev ) {
if ( a.i !== b.i && isValidDiagonal( a, b ) ) {
// split the polygon in two by the diagonal
let c = splitPolygon( a, b );
// filter colinear points around the cuts
a = filterPoints( a, a.next );
c = filterPoints( c, c.next );
// run earcut on each half
earcutLinked( a, triangles, dim, minX, minY, invSize, 0 );
earcutLinked( c, triangles, dim, minX, minY, invSize, 0 );
return;
}
b = b.next;
}
a = a.next;
} while ( a !== start );
}
// link every hole into the outer loop, producing a single-ring polygon without holes
function eliminateHoles( data, holeIndices, outerNode, dim ) {
const queue = [];
let i, len, start, end, list;
for ( i = 0, len = holeIndices.length; i < len; i ++ ) {
start = holeIndices[ i ] * dim;
end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length;
list = linkedList( data, start, end, dim, false );
if ( list === list.next ) list.steiner = true;
queue.push( getLeftmost( list ) );
}
queue.sort( compareX );
// process holes from left to right
for ( i = 0; i < queue.length; i ++ ) {
outerNode = eliminateHole( queue[ i ], outerNode );
}
return outerNode;
}
function compareX( a, b ) {
return a.x - b.x;
}
// find a bridge between vertices that connects hole with an outer ring and link it
function eliminateHole( hole, outerNode ) {
const bridge = findHoleBridge( hole, outerNode );
if ( ! bridge ) {
return outerNode;
}
const bridgeReverse = splitPolygon( bridge, hole );
// filter collinear points around the cuts
filterPoints( bridgeReverse, bridgeReverse.next );
return filterPoints( bridge, bridge.next );
}
// David Eberly's algorithm for finding a bridge between hole and outer polygon
function findHoleBridge( hole, outerNode ) {
let p = outerNode,
qx = - Infinity,
m;
const hx = hole.x, hy = hole.y;
// find a segment intersected by a ray from the hole's leftmost point to the left;
// segment's endpoint with lesser x will be potential connection point
do {
if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) {
const x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y );
if ( x <= hx && x > qx ) {
qx = x;
m = p.x < p.next.x ? p : p.next;
if ( x === hx ) return m; // hole touches outer segment; pick leftmost endpoint
}
}
p = p.next;
} while ( p !== outerNode );
if ( ! m ) return null;
// look for points inside the triangle of hole point, segment intersection and endpoint;
// if there are no points found, we have a valid connection;
// otherwise choose the point of the minimum angle with the ray as connection point
const stop = m,
mx = m.x,
my = m.y;
let tanMin = Infinity, tan;
p = m;
do {
if ( hx >= p.x && p.x >= mx && hx !== p.x &&
pointInTriangle( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y ) ) {
tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential
if ( locallyInside( p, hole ) && ( tan < tanMin || ( tan === tanMin && ( p.x > m.x || ( p.x === m.x && sectorContainsSector( m, p ) ) ) ) ) ) {
m = p;
tanMin = tan;
}
}
p = p.next;
} while ( p !== stop );
return m;
}
// whether sector in vertex m contains sector in vertex p in the same coordinates
function sectorContainsSector( m, p ) {
return area( m.prev, m, p.prev ) < 0 && area( p.next, m, m.next ) < 0;
}
// interlink polygon nodes in z-order
function indexCurve( start, minX, minY, invSize ) {
let p = start;
do {
if ( p.z === 0 ) p.z = zOrder( p.x, p.y, minX, minY, invSize );
p.prevZ = p.prev;
p.nextZ = p.next;
p = p.next;
} while ( p !== start );
p.prevZ.nextZ = null;
p.prevZ = null;
sortLinked( p );
}
// Simon Tatham's linked list merge sort algorithm
// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
function sortLinked( list ) {
let i, p, q, e, tail, numMerges, pSize, qSize,
inSize = 1;
do {
p = list;
list = null;
tail = null;
numMerges = 0;
while ( p ) {
numMerges ++;
q = p;
pSize = 0;
for ( i = 0; i < inSize; i ++ ) {
pSize ++;
q = q.nextZ;
if ( ! q ) break;
}
qSize = inSize;
while ( pSize > 0 || ( qSize > 0 && q ) ) {
if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) {
e = p;
p = p.nextZ;
pSize --;
} else {
e = q;
q = q.nextZ;
qSize --;
}
if ( tail ) tail.nextZ = e;
else list = e;
e.prevZ = tail;
tail = e;
}
p = q;
}
tail.nextZ = null;
inSize *= 2;
} while ( numMerges > 1 );
return list;
}
// z-order of a point given coords and inverse of the longer side of data bbox
function zOrder( x, y, minX, minY, invSize ) {
// coords are transformed into non-negative 15-bit integer range
x = ( x - minX ) * invSize | 0;
y = ( y - minY ) * invSize | 0;
x = ( x | ( x << 8 ) ) & 0x00FF00FF;
x = ( x | ( x << 4 ) ) & 0x0F0F0F0F;
x = ( x | ( x << 2 ) ) & 0x33333333;
x = ( x | ( x << 1 ) ) & 0x55555555;
y = ( y | ( y << 8 ) ) & 0x00FF00FF;
y = ( y | ( y << 4 ) ) & 0x0F0F0F0F;
y = ( y | ( y << 2 ) ) & 0x33333333;
y = ( y | ( y << 1 ) ) & 0x55555555;
return x | ( y << 1 );
}
// find the leftmost node of a polygon ring
function getLeftmost( start ) {
let p = start,
leftmost = start;
do {
if ( p.x < leftmost.x || ( p.x === leftmost.x && p.y < leftmost.y ) ) leftmost = p;
p = p.next;
} while ( p !== start );
return leftmost;
}
// check if a point lies within a convex triangle
function pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) {
return ( cx - px ) * ( ay - py ) >= ( ax - px ) * ( cy - py ) &&
( ax - px ) * ( by - py ) >= ( bx - px ) * ( ay - py ) &&
( bx - px ) * ( cy - py ) >= ( cx - px ) * ( by - py );
}
// check if a diagonal between two polygon nodes is valid (lies in polygon interior)
function isValidDiagonal( a, b ) {
return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) && // doesn't intersect other edges
( locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b ) && // locally visible
( area( a.prev, a, b.prev ) || area( a, b.prev, b ) ) || // does not create opposite-facing sectors
equals( a, b ) && area( a.prev, a, a.next ) > 0 && area( b.prev, b, b.next ) > 0 ); // special zero-length case
}
// signed area of a triangle
function area( p, q, r ) {
return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y );
}
// check if two points are equal
function equals( p1, p2 ) {
return p1.x === p2.x && p1.y === p2.y;
}
// check if two segments intersect
function intersects( p1, q1, p2, q2 ) {
const o1 = sign( area( p1, q1, p2 ) );
const o2 = sign( area( p1, q1, q2 ) );
const o3 = sign( area( p2, q2, p1 ) );
const o4 = sign( area( p2, q2, q1 ) );
if ( o1 !== o2 && o3 !== o4 ) return true; // general case
if ( o1 === 0 && onSegment( p1, p2, q1 ) ) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
if ( o2 === 0 && onSegment( p1, q2, q1 ) ) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
if ( o3 === 0 && onSegment( p2, p1, q2 ) ) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
if ( o4 === 0 && onSegment( p2, q1, q2 ) ) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2
return false;
}
// for collinear points p, q, r, check if point q lies on segment pr
function onSegment( p, q, r ) {
return q.x <= Math.max( p.x, r.x ) && q.x >= Math.min( p.x, r.x ) && q.y <= Math.max( p.y, r.y ) && q.y >= Math.min( p.y, r.y );
}
function sign( num ) {
return num > 0 ? 1 : num < 0 ? - 1 : 0;
}
// check if a polygon diagonal intersects any polygon segments
function intersectsPolygon( a, b ) {
let p = a;
do {
if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
intersects( p, p.next, a, b ) ) return true;
p = p.next;
} while ( p !== a );
return false;
}
// check if a polygon diagonal is locally inside the polygon
function locallyInside( a, b ) {
return area( a.prev, a, a.next ) < 0 ?
area( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 :
area( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0;
}
// check if the middle point of a polygon diagonal is inside the polygon
function middleInside( a, b ) {
let p = a,
inside = false;
const px = ( a.x + b.x ) / 2,
py = ( a.y + b.y ) / 2;
do {
if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y &&
( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) )
inside = ! inside;
p = p.next;
} while ( p !== a );
return inside;
}
// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
// if one belongs to the outer ring and another to a hole, it merges it into a single ring
function splitPolygon( a, b ) {
const a2 = new Node( a.i, a.x, a.y ),
b2 = new Node( b.i, b.x, b.y ),
an = a.next,
bp = b.prev;
a.next = b;
b.prev = a;
a2.next = an;
an.prev = a2;
b2.next = a2;
a2.prev = b2;
bp.next = b2;
b2.prev = bp;
return b2;
}
// create a node and optionally link it with previous one (in a circular doubly linked list)
function insertNode( i, x, y, last ) {
const p = new Node( i, x, y );
if ( ! last ) {
p.prev = p;
p.next = p;
} else {
p.next = last.next;
p.prev = last;
last.next.prev = p;
last.next = p;
}
return p;
}
function removeNode( p ) {
p.next.prev = p.prev;
p.prev.next = p.next;
if ( p.prevZ ) p.prevZ.nextZ = p.nextZ;
if ( p.nextZ ) p.nextZ.prevZ = p.prevZ;
}
function Node( i, x, y ) {
// vertex index in coordinates array
this.i = i;
// vertex coordinates
this.x = x;
this.y = y;
// previous and next vertex nodes in a polygon ring
this.prev = null;
this.next = null;
// z-order curve value
this.z = 0;
// previous and next nodes in z-order
this.prevZ = null;
this.nextZ = null;
// indicates whether this is a steiner point
this.steiner = false;
}
function signedArea( data, start, end, dim ) {
let sum = 0;
for ( let i = start, j = end - dim; i < end; i += dim ) {
sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] );
j = i;
}
return sum;
}
export { Earcut };

@@ -17,5 +17,6 @@ import { createElementNS } from '../utils.js';

* @param {(HTMLImageElement|HTMLCanvasElement)} image - The image object.
* @param {string} [type='image/png'] - Indicates the image format.
* @return {string} The data URI.
*/
static getDataURL( image ) {
static getDataURL( image, type = 'image/png' ) {

@@ -63,3 +64,3 @@ if ( /^data:/i.test( image.src ) ) {

return canvas.toDataURL( 'image/png' );
return canvas.toDataURL( type );

@@ -66,0 +67,0 @@ }

@@ -76,8 +76,12 @@ import {

*
* Paper: Fast, Accurate Image-Based Lighting
* https://drive.google.com/file/d/15y8r_UpKlU9SvV4ILb0C3qCPecS8pvLz/view
* Paper: Fast, Accurate Image-Based Lighting:
* {@link https://drive.google.com/file/d/15y8r_UpKlU9SvV4ILb0C3qCPecS8pvLz/view}
*/
class PMREMGenerator {
/**
* Constructs a new PMREM generator.
*
* @param {WebGLRenderer} renderer - The renderer.
*/
constructor( renderer ) {

@@ -108,8 +112,10 @@

*
* @param {Scene} scene
* @param {number} sigma
* @param {number} near
* @param {number} far
* @param {Object} [options={}]
* @return {WebGLRenderTarget}
* @param {Scene} scene - The scene to be captured.
* @param {number} [sigma=0] - The blur radius in radians.
* @param {number} [near=0.1] - The near plane distance.
* @param {number} [far=100] - The far plane distance.
* @param {Object} [options={}] - The configuration options.
* @param {number} [options.size=256] - The texture size of the PMREM.
* @param {Vector3} [options.renderTarget=origin] - The position of the internal cube camera that renders the scene.
* @return {WebGLRenderTarget} The resulting PMREM.
*/

@@ -154,7 +160,6 @@ fromScene( scene, sigma = 0, near = 0.1, far = 100, options = {} ) {

* as this matches best with the 256 x 256 cubemap output.
* The smallest supported equirectangular image size is 64 x 32.
*
* @param {Texture} equirectangular
* @param {?WebGLRenderTarget} [renderTarget=null] - Optional render target.
* @return {WebGLRenderTarget}
* @param {Texture} equirectangular - The equirectangular texture to be converted.
* @param {?WebGLRenderTarget} [renderTarget=null] - The render target to use.
* @return {WebGLRenderTarget} The resulting PMREM.
*/

@@ -171,7 +176,6 @@ fromEquirectangular( equirectangular, renderTarget = null ) {

* as this matches best with the 256 x 256 cubemap output.
* The smallest supported cube size is 16 x 16.
*
* @param {Texture} cubemap
* @param {null} [renderTarget=null] - Optional render target.
* @return {WebGLRenderTarget}
* @param {Texture} cubemap - The cubemap texture to be converted.
* @param {?WebGLRenderTarget} [renderTarget=null] - The render target to use.
* @return {WebGLRenderTarget} The resulting PMREM.
*/

@@ -499,2 +503,3 @@ fromCubemap( cubemap, renderTarget = null ) {

*
* @private
* @param {WebGLRenderTarget} cubeUVRenderTarget

@@ -501,0 +506,0 @@ * @param {number} lodIn

@@ -25,4 +25,4 @@ import { CylinderGeometry } from './CylinderGeometry.js';

* @param {boolean} [openEnded=false] - Whether the base of the cone is open or capped.
* @param {boolean} [thetaStart=0] - Start angle for first segment, in radians.
* @param {boolean} [thetaLength=Math.PI*2] - The central angle, often called theta, of the circular sector, in radians.
* @param {number} [thetaStart=0] - Start angle for first segment, in radians.
* @param {number} [thetaLength=Math.PI*2] - The central angle, often called theta, of the circular sector, in radians.
* The default value results in a complete cone.

@@ -29,0 +29,0 @@ */

@@ -29,4 +29,4 @@ import { BufferGeometry } from '../core/BufferGeometry.js';

* @param {boolean} [openEnded=false] - Whether the base of the cylinder is open or capped.
* @param {boolean} [thetaStart=0] - Start angle for first segment, in radians.
* @param {boolean} [thetaLength=Math.PI*2] - The central angle, often called theta, of the circular sector, in radians.
* @param {number} [thetaStart=0] - Start angle for first segment, in radians.
* @param {number} [thetaLength=Math.PI*2] - The central angle, often called theta, of the circular sector, in radians.
* The default value results in a complete cylinder.

@@ -33,0 +33,0 @@ */

@@ -1,23 +0,1 @@

/**
* Creates extruded geometry from a path shape.
*
* parameters = {
*
* curveSegments: <int>, // number of points on the curves
* steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
* depth: <float>, // Depth to extrude the shape
*
* bevelEnabled: <bool>, // turn on bevel
* bevelThickness: <float>, // how deep into the original shape bevel goes
* bevelSize: <float>, // how far from shape outline (including bevelOffset) is bevel
* bevelOffset: <float>, // how far from shape outline does bevel start
* bevelSegments: <int>, // number of bevel layers
*
* extrudePath: <THREE.Curve> // curve to extrude shape along
*
* UVGenerator: <Object> // object that provides UV generator functions
*
* }
*/
import { BufferGeometry } from '../core/BufferGeometry.js';

@@ -58,13 +36,3 @@ import { Float32BufferAttribute } from '../core/BufferAttribute.js';

* @param {Shape|Array<Shape>} [shapes] - A shape or an array of shapes.
* @param {Object} [options={}] - The extrude settings.
* @param {number} [options.curveSegments=12] - Number of points on the curves.
* @param {number} [options.steps=1] - Number of points used for subdividing segments along the depth of the extruded spline.
* @param {number} [options.depth=1] - Depth to extrude the shape.
* @param {boolean} [options.bevelEnabled=true] - Whether to beveling to the shape or not.
* @param {number} [options.bevelThickness=0.2] - How deep into the original shape the bevel goes.
* @param {number} [options.bevelSize=bevelThickness-0.1] - Distance from the shape outline that the bevel extends.
* @param {number} [options.bevelOffset=0] - Distance from the shape outline that the bevel starts.
* @param {number} [options.bevelSegments=3] - Number of bevel layers.
* @param {Curve} [options.extrudePath=3] - A 3D spline path along which the shape should be extruded. Bevels not supported for path extrusion.
* @param {Object} [options.UVGenerator] - An object that provides UV generator functions for custom UV generation.
* @param {ExtrudeGeometry~Options} [options] - The extrude settings.
*/

@@ -198,5 +166,44 @@ constructor( shapes = new Shape( [ new Vector2( 0.5, 0.5 ), new Vector2( - 0.5, 0.5 ), new Vector2( - 0.5, - 0.5 ), new Vector2( 0.5, - 0.5 ) ] ), options = {} ) {

/**Merges index-adjacent points that are within a threshold distance of each other. Array is modified in-place. Threshold distance is empirical, and scaled based on the magnitude of point coordinates.
* @param {Array<Vector2>} points
*/
function mergeOverlappingPoints( points ) {
const faces = ShapeUtils.triangulateShape( vertices, holes );
const THRESHOLD = 1e-10;
const THRESHOLD_SQ = THRESHOLD * THRESHOLD;
let prevPos = points[ 0 ];
for ( let i = 1; i <= points.length; i ++ ) {
const currentIndex = i % points.length;
const currentPos = points[ currentIndex ];
const dx = currentPos.x - prevPos.x;
const dy = currentPos.y - prevPos.y;
const distSq = dx * dx + dy * dy;
const scalingFactorSqrt = Math.max(
Math.abs( currentPos.x ),
Math.abs( currentPos.y ),
Math.abs( prevPos.x ),
Math.abs( prevPos.y )
);
const thesholdSqScaled = THRESHOLD_SQ * scalingFactorSqrt * scalingFactorSqrt;
if ( distSq <= thesholdSqScaled ) {
points.splice( currentIndex, 1 );
i --;
continue;
}
prevPos = currentPos;
}
}
mergeOverlappingPoints( vertices );
holes.forEach( mergeOverlappingPoints );
const numHoles = holes.length;
/* Vertices */

@@ -206,3 +213,3 @@

for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
for ( let h = 0; h < numHoles; h ++ ) {

@@ -224,3 +231,3 @@ const ahole = holes[ h ];

const vlen = vertices.length, flen = faces.length;
const vlen = vertices.length;

@@ -372,3 +379,3 @@

for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
for ( let h = 0, hl = numHoles; h < hl; h ++ ) {

@@ -394,2 +401,4 @@ const ahole = holes[ h ];

const contractedContourVertices = [];
const expandedHoleVertices = [];

@@ -413,2 +422,3 @@ // Loop bevelSegments, 1 for the front, 1 for the back

v( vert.x, vert.y, - z );
if ( t == 0 ) contractedContourVertices.push( vert );

@@ -419,7 +429,7 @@ }

for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
for ( let h = 0, hl = numHoles; h < hl; h ++ ) {
const ahole = holes[ h ];
oneHoleMovements = holesMovements[ h ];
const oneHoleVertices = [];
for ( let i = 0, il = ahole.length; i < il; i ++ ) {

@@ -430,5 +440,8 @@

v( vert.x, vert.y, - z );
if ( t == 0 ) oneHoleVertices.push( vert );
}
if ( t == 0 ) expandedHoleVertices.push( oneHoleVertices );
}

@@ -438,2 +451,6 @@

const faces = ShapeUtils.triangulateShape( contractedContourVertices, expandedHoleVertices );
const flen = faces.length;
const bs = bevelSize + bevelOffset;

@@ -875,3 +892,18 @@

/**
* Represents the `options` type of the geometry's constructor.
*
* @typedef {Object} ExtrudeGeometry~Options
* @property {number} [curveSegments=12] - Number of points on the curves.
* @property {number} [steps=1] - Number of points used for subdividing segments along the depth of the extruded spline.
* @property {number} [depth=1] - Depth to extrude the shape.
* @property {boolean} [bevelEnabled=true] - Whether to beveling to the shape or not.
* @property {number} [bevelThickness=0.2] - How deep into the original shape the bevel goes.
* @property {number} [bevelSize=bevelThickness-0.1] - Distance from the shape outline that the bevel extends.
* @property {number} [bevelOffset=0] - Distance from the shape outline that the bevel starts.
* @property {number} [bevelSegments=3] - Number of bevel layers.
* @property {?Curve} [extrudePath=null] - A 3D spline path along which the shape should be extruded. Bevels not supported for path extrusion.
* @property {Object} [UVGenerator] - An object that provides UV generator functions for custom UV generation.
**/
export { ExtrudeGeometry };

@@ -28,3 +28,3 @@ import { Float32BufferAttribute } from '../core/BufferAttribute.js';

*
* @param {Array<Vector2>} [points] - An array of points in 2D space. The x-coordinate of each point
* @param {Array<Vector2|Vector3>} [points] - An array of points in 2D space. The x-coordinate of each point
* must be greater than zero.

@@ -31,0 +31,0 @@ * @param {number} [segments=12] - The number of circumference segments to generate.

@@ -13,3 +13,3 @@ import { Matrix4 } from '../math/Matrix4.js';

* Abstract base class for light shadow classes. These classes
* represent the shadow configuration for different ligth types.
* represent the shadow configuration for different light types.
*

@@ -16,0 +16,0 @@ * @abstract

@@ -25,3 +25,3 @@ import { SpotLight } from '../SpotLight.js';

/**
* TOOD
* TODO
*

@@ -28,0 +28,0 @@ * @type {?Texture}

@@ -5,4 +5,20 @@ import { AnimationClip } from '../animation/AnimationClip.js';

/**
* Class for loading animation clips in the JSON format. The files are internally
* loaded via {@link FileLoader}.
*
* ```js
* const loader = new THREE.AnimationLoader();
* const animations = await loader.loadAsync( 'animations/animation.js' );
* ```
*
* @augments Loader
*/
class AnimationLoader extends Loader {
/**
* Constructs a new animation loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -14,2 +30,11 @@

/**
* Starts loading from the given URL and pass the loaded animations as an array
* holding instances of {@link AnimationClip} to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(Array<AnimationClip>)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -49,2 +74,8 @@

/**
* Parses the given JSON object and returns an array of animation clips.
*
* @param {Object} json - The serialized animation clips.
* @return {Array<AnimationClip>} The parsed animation clips.
*/
parse( json ) {

@@ -51,0 +82,0 @@

@@ -5,4 +5,26 @@ import { AudioContext } from '../audio/AudioContext.js';

/**
* Class for loading audio buffers. Audios are internally
* loaded via {@link FileLoader}.
*
* ```js
* const audioListener = new THREE.AudioListener();
* const ambientSound = new THREE.Audio( audioListener );
*
* const loader = new THREE.AudioLoader();
* const audioBuffer = await loader.loadAsync( 'audio/ambient_ocean.ogg' );
*
* ambientSound.setBuffer( audioBuffer );
* ambientSound.play();
* ```
*
* @augments Loader
*/
class AudioLoader extends Loader {
/**
* Constructs a new audio loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -14,2 +36,11 @@

/**
* Starts loading from the given URL and passes the loaded audio buffer
* to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(AudioBuffer)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -16,0 +47,0 @@

@@ -13,4 +13,24 @@ import { Sphere } from '../math/Sphere.js';

/**
* Class for loading geometries. The files are internally
* loaded via {@link FileLoader}.
*
* ```js
* const loader = new THREE.BufferGeometryLoader();
* const geometry = await loader.loadAsync( 'models/json/pressure.json' );
*
* const material = new THREE.MeshBasicMaterial( { color: 0xF5F5F5 } );
* const object = new THREE.Mesh( geometry, material );
* scene.add( object );
* ```
*
* @augments Loader
*/
class BufferGeometryLoader extends Loader {
/**
* Constructs a new geometry loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -22,2 +42,10 @@

/**
* Starts loading from the given URL and pass the loaded geometry to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(BufferGeometry)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -57,2 +85,8 @@

/**
* Parses the given JSON object and returns a geometry.
*
* @param {Object} json - The serialized geometry.
* @return {BufferGeometry} The parsed geometry.
*/
parse( json ) {

@@ -59,0 +93,0 @@

@@ -0,7 +1,34 @@

/**
* @class
* @classdesc A simple caching system, used internally by {@link FileLoader}.
* To enable caching across all loaders that use {@link FileLoader}, add `THREE.Cache.enabled = true.` once in your app.
* @hideconstructor
*/
const Cache = {
/**
* Whether caching is enabled or not.
*
* @static
* @type {boolean}
* @default false
*/
enabled: false,
/**
* A dictionary that holds cached files.
*
* @static
* @type {Object<string,Object>}
*/
files: {},
/**
* Adds a cache entry with a key to reference the file. If this key already
* holds a file, it is overwritten.
*
* @static
* @param {string} key - The key to reference the cached file.
* @param {Object} file - The file to be cached.
*/
add: function ( key, file ) {

@@ -17,2 +44,9 @@

/**
* Gets the cached value for the given key.
*
* @static
* @param {string} key - The key to reference the cached file.
* @return {Object|undefined} The cached file. If the key does not exist `undefined` is returned.
*/
get: function ( key ) {

@@ -28,2 +62,8 @@

/**
* Removes the cached file associated with the given key.
*
* @static
* @param {string} key - The key to reference the cached file.
*/
remove: function ( key ) {

@@ -35,2 +75,7 @@

/**
* Remove all values from the cache.
*
* @static
*/
clear: function () {

@@ -37,0 +82,0 @@

@@ -7,9 +7,18 @@ import { LinearFilter } from '../constants.js';

/**
* Abstract Base class to block based textures loader (dds, pvr, ...)
* Abstract base class for loading compressed texture formats S3TC, ASTC or ETC.
* Textures are internally loaded via {@link FileLoader}.
*
* Sub classes have to implement the parse() method which will be used in load().
* Derived classes have to implement the `parse()` method which holds the parsing
* for the respective format.
*
* @abstract
* @augments Loader
*/
class CompressedTextureLoader extends Loader {
/**
* Constructs a new compressed texture loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -21,2 +30,14 @@

/**
* Starts loading from the given URL and passes the loaded compressed texture
* to the `onLoad()` callback. The method also returns a new texture object which can
* directly be used for material creation. If you do it this way, the texture
* may pop up in your scene once the respective loading process is finished.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(CompressedTexture)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
* @return {CompressedTexture} The compressed texture.
*/
load( url, onLoad, onProgress, onError ) {

@@ -135,3 +156,15 @@

/**
* Represents the result object type of the `parse()` method.
*
* @typedef {Object} CompressedTextureLoader~TexData
* @property {number} width - The width of the base mip.
* @property {number} height - The width of the base mip.
* @property {boolean} isCubemap - Whether the data represent a cubemap or not.
* @property {number} mipmapCount - The mipmap count.
* @property {Array<{data:TypedArray,width:number,height:number}>} mipmaps - An array holding the mipmaps.
* Each entry holds the data and the dimensions for each level.
* @property {number} format - The texture format.
**/
export { CompressedTextureLoader };

@@ -6,4 +6,35 @@ import { ImageLoader } from './ImageLoader.js';

/**
* Class for loading cube textures. Images are internally loaded via {@link ImageLoader}.
*
* The loader returns an instance of {@link CubeTexture} and expects the cube map to
* be defined as six separate images representing the sides of a cube. Other cube map definitions
* like vertical and horizontal cross, column and row layouts are not supported.
*
* Note that, by convention, cube maps are specified in a coordinate system
* in which positive-x is to the right when looking up the positive-z axis --
* in other words, using a left-handed coordinate system. Since three.js uses
* a right-handed coordinate system, environment maps used in three.js will
* have pos-x and neg-x swapped.
*
* The loaded cube texture is in sRGB color space. Meaning {@link Texture#colorSpace}
* is set to `SRGBColorSpace` by default.
*
* ```js
* const loader = new THREE.CubeTextureLoader().setPath( 'textures/cubeMaps/' );
* const cubeTexture = await loader.loadAsync( [
* 'px.png', 'nx.png', 'py.png', 'ny.png', 'pz.png', 'nz.png'
* ] );
* scene.background = cubeTexture;
* ```
*
* @augments Loader
*/
class CubeTextureLoader extends Loader {
/**
* Constructs a new cube texture loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -15,2 +46,16 @@

/**
* Starts loading from the given URL and pass the fully loaded cube texture
* to the `onLoad()` callback. The method also returns a new cube texture object which can
* directly be used for material creation. If you do it this way, the cube texture
* may pop up in your scene once the respective loading process is finished.
*
* @param {Array<string>} urls - Array of 6 URLs to images, one for each side of the
* cube texture. The urls should be specified in the following order: pos-x,
* neg-x, pos-y, neg-y, pos-z, neg-z. An array of data URIs are allowed as well.
* @param {function(CubeTexture)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Unsupported in this loader.
* @param {onErrorCallback} onError - Executed when errors occur.
* @return {CubeTexture} The cube texture.
*/
load( urls, onLoad, onProgress, onError ) {

@@ -17,0 +62,0 @@

@@ -7,9 +7,18 @@ import { LinearFilter, LinearMipmapLinearFilter, ClampToEdgeWrapping } from '../constants.js';

/**
* Abstract Base class to load generic binary textures formats (rgbe, hdr, ...)
* Abstract base class for loading binary texture formats RGBE, EXR or TGA.
* Textures are internally loaded via {@link FileLoader}.
*
* Sub classes have to implement the parse() method which will be used in load().
* Derived classes have to implement the `parse()` method which holds the parsing
* for the respective format.
*
* @abstract
* @augments Loader
*/
class DataTextureLoader extends Loader {
/**
* Constructs a new data texture loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -21,2 +30,14 @@

/**
* Starts loading from the given URL and passes the loaded data texture
* to the `onLoad()` callback. The method also returns a new texture object which can
* directly be used for material creation. If you do it this way, the texture
* may pop up in your scene once the respective loading process is finished.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(DataTexture)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
* @return {DataTexture} The data texture.
*/
load( url, onLoad, onProgress, onError ) {

@@ -132,3 +153,23 @@

/**
* Represents the result object type of the `parse()` method.
*
* @typedef {Object} DataTextureLoader~TexData
* @property {Object} [image] - An object holding width, height and the texture data.
* @property {number} [width] - The width of the base mip.
* @property {number} [height] - The width of the base mip.
* @property {TypedArray} [data] - The texture data.
* @property {number} [format] - The texture format.
* @property {number} [type] - The texture type.
* @property {boolean} [flipY] - If set to `true`, the texture is flipped along the vertical axis when uploaded to the GPU.
* @property {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
* @property {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
* @property {number} [anisotropy=1] - The anisotropy value.
* @property {boolean} [generateMipmaps] - Whether to generate mipmaps or not.
* @property {string} [colorSpace] - The color space.
* @property {number} [magFilter] - The mag filter.
* @property {number} [minFilter] - The min filter.
* @property {Array<Object>} [mipmaps] - The mipmaps.
**/
export { DataTextureLoader };

@@ -17,4 +17,24 @@ import { Cache } from './Cache.js';

/**
* A low level class for loading resources with the Fetch API, used internally by
* most loaders. It can also be used directly to load any file type that does
* not have a loader.
*
* This loader supports caching. If you want to use it, add `THREE.Cache.enabled = true;`
* once to your application.
*
* ```js
* const loader = new THREE.FileLoader();
* const data = await loader.loadAsync( 'example.txt' );
* ```
*
* @augments Loader
*/
class FileLoader extends Loader {
/**
* Constructs a new file loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -24,4 +44,28 @@

/**
* The expected mime type.
*
* @type {string}
*/
this.mimeType = '';
/**
* The expected response type.
*
* @type {('arraybuffer'|'blob'|'document'|'json'|'')}
* @default ''
*/
this.responseType = '';
}
/**
* Starts loading from the given URL and pass the loaded response to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(any)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} [onProgress] - Executed while the loading is in progress.
* @param {onErrorCallback} [onError] - Executed when errors occur.
* @return {any|undefined} The cached resource if available.
*/
load( url, onLoad, onProgress, onError ) {

@@ -202,3 +246,3 @@

if ( mimeType === undefined ) {
if ( mimeType === '' ) {

@@ -274,2 +318,8 @@ return response.text();

/**
* Sets the expected response type.
*
* @param {('arraybuffer'|'blob'|'document'|'json'|'')} value - The response type.
* @return {FileLoader} A reference to this file loader.
*/
setResponseType( value ) {

@@ -282,2 +332,8 @@

/**
* Sets the expected mime type of the loaded file.
*
* @param {string} value - The mime type.
* @return {FileLoader} A reference to this file loader.
*/
setMimeType( value ) {

@@ -284,0 +340,0 @@

import { Cache } from './Cache.js';
import { Loader } from './Loader.js';
/**
* A loader for loading images as an [ImageBitmap]{@link https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap}.
* An `ImageBitmap` provides an asynchronous and resource efficient pathway to prepare
* textures for rendering.
*
* Note that {@link Texture#flipY} and {@link Texture#premultiplyAlpha} are ignored with image bitmaps.
* They needs these configuration on bitmap creation unlike regular images need them on uploading to GPU.
*
* You need to set the equivalent options via {@link ImageBitmapLoader#setOptions} instead.
*
* Also note that unlike {@link FileLoader}, this loader does not avoid multiple concurrent requests to the same URL.
*
* ```js
* const loader = new THREE.ImageBitmapLoader();
* loader.setOptions( { imageOrientation: 'flipY' } ); // set options if needed
* const imageBitmap = await loader.loadAsync( 'image.png' );
*
* const texture = new THREE.Texture( imageBitmap );
* texture.needsUpdate = true;
* ```
*
* @augments Loader
*/
class ImageBitmapLoader extends Loader {
/**
* Constructs a new image bitmap loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -10,2 +38,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isImageBitmapLoader = true;

@@ -25,2 +60,8 @@

/**
* Represents the loader options.
*
* @type {Object}
* @default {premultiplyAlpha:'none'}
*/
this.options = { premultiplyAlpha: 'none' };

@@ -30,2 +71,9 @@

/**
* Sets the given loader options. The structure of the object must match the `options` parameter of
* [createImageBitmap]{@link https://developer.mozilla.org/en-US/docs/Web/API/Window/createImageBitmap}.
*
* @param {Object} options - The loader options to set.
* @return {ImageBitmapLoader} A reference to this image bitmap loader.
*/
setOptions( options ) {

@@ -39,2 +87,11 @@

/**
* Starts loading from the given URL and pass the loaded image bitmap to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(ImageBitmap)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Unsupported in this loader.
* @param {onErrorCallback} onError - Executed when errors occur.
* @return {ImageBitmap|undefined} The image bitmap.
*/
load( url, onLoad, onProgress, onError ) {

@@ -41,0 +98,0 @@

@@ -5,4 +5,22 @@ import { Cache } from './Cache.js';

/**
* A loader for loading images. The class loads images with the HTML `Image` API.
*
* ```js
* const loader = new THREE.ImageLoader();
* const image = await loader.loadAsync( 'image.png' );
* ```
* Please note that `ImageLoader` has dropped support for progress
* events in `r84`. For an `ImageLoader` that supports progress events, see
* [this thread]{@link https://github.com/mrdoob/three.js/issues/10439#issuecomment-275785639}.
*
* @augments Loader
*/
class ImageLoader extends Loader {
/**
* Constructs a new image loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -14,2 +32,14 @@

/**
* Starts loading from the given URL and passes the loaded image
* to the `onLoad()` callback. The method also returns a new `Image` object which can
* directly be used for texture creation. If you do it this way, the texture
* may pop up in your scene once the respective loading process is finished.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(Image)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Unsupported in this loader.
* @param {onErrorCallback} onError - Executed when errors occur.
* @return {Image} The image.
*/
load( url, onLoad, onProgress, onError ) {

@@ -16,0 +46,0 @@

@@ -60,3 +60,3 @@ import { DefaultLoadingManager } from './LoadingManager.js';

*
* @type {Object}
* @type {Object<string, any>}
*/

@@ -73,4 +73,4 @@ this.requestHeader = {};

* @param {Function} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
* @param {onProgressCallback} [onProgress] - Executed while the loading is in progress.
* @param {onErrorCallback} [onError] - Executed when errors occur.
*/

@@ -83,3 +83,3 @@ load( /* url, onLoad, onProgress, onError */ ) {}

* @param {string} url - The path/URL of the file to be loaded.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onProgressCallback} [onProgress] - Executed while the loading is in progress.
* @return {Promise} A Promise that resolves when the asset has been loaded.

@@ -182,3 +182,2 @@ */

*
*
* @callback onProgressCallback

@@ -191,3 +190,2 @@ * @param {ProgressEvent} event - An instance of `ProgressEvent` that represents the current loading status.

*
*
* @callback onErrorCallback

@@ -194,0 +192,0 @@ * @param {Error} error - The error which occurred during the loading process.

@@ -0,39 +1,12 @@

/**
* A class with loader utility functions.
*/
class LoaderUtils {
static decodeText( array ) { // @deprecated, r165
console.warn( 'THREE.LoaderUtils: decodeText() has been deprecated with r165 and will be removed with r175. Use TextDecoder instead.' );
if ( typeof TextDecoder !== 'undefined' ) {
return new TextDecoder().decode( array );
}
// Avoid the String.fromCharCode.apply(null, array) shortcut, which
// throws a "maximum call stack size exceeded" error for large arrays.
let s = '';
for ( let i = 0, il = array.length; i < il; i ++ ) {
// Implicitly assumes little-endian.
s += String.fromCharCode( array[ i ] );
}
try {
// merges multi-byte utf-8 characters.
return decodeURIComponent( escape( s ) );
} catch ( e ) { // see #16358
return s;
}
}
/**
* Extracts the base URL from the given URL.
*
* @param {string} url -The URL to extract the base URL from.
* @return {string} The extracted base URL.
*/
static extractUrlBase( url ) {

@@ -49,2 +22,11 @@

/**
* Resolves relative URLs against the given path. Absolute paths, data urls,
* and blob URLs will be returned as is. Invalid URLs will return an empty
* string.
*
* @param {string} url -The URL to resolve.
* @param {string} path - The base path for relative URLs to be resolved against.
* @return {string} The resolved URL.
*/
static resolveURL( url, path ) {

@@ -51,0 +33,0 @@

@@ -0,3 +1,27 @@

/**
* Handles and keeps track of loaded and pending data. A default global
* instance of this class is created and used by loaders if not supplied
* manually.
*
* In general that should be sufficient, however there are times when it can
* be useful to have separate loaders - for example if you want to show
* separate loading bars for objects and textures.
*
* ```js
* const manager = new THREE.LoadingManager();
* manager.onLoad = () => console.log( 'Loading complete!' );
*
* const loader1 = new OBJLoader( manager );
* const loader2 = new ColladaLoader( manager );
* ```
*/
class LoadingManager {
/**
* Constructs a new loading manager.
*
* @param {Function} [onLoad] - Executes when all items have been loaded.
* @param {Function} [onProgress] - Executes when single items have been loaded.
* @param {Function} [onError] - Executes when an error occurs.
*/
constructor( onLoad, onProgress, onError ) {

@@ -16,7 +40,40 @@

/**
* Executes when an item starts loading.
*
* @type {Function|undefined}
* @default undefined
*/
this.onStart = undefined;
/**
* Executes when all items have been loaded.
*
* @type {Function|undefined}
* @default undefined
*/
this.onLoad = onLoad;
/**
* Executes when single items have been loaded.
*
* @type {Function|undefined}
* @default undefined
*/
this.onProgress = onProgress;
/**
* Executes when an error occurs.
*
* @type {Function|undefined}
* @default undefined
*/
this.onError = onError;
/**
* This should be called by any loader using the manager when the loader
* starts loading an item.
*
* @param {string} url - The URL to load.
*/
this.itemStart = function ( url ) {

@@ -40,2 +97,8 @@

/**
* This should be called by any loader using the manager when the loader
* ended loading an item.
*
* @param {string} url - The URL of the loaded item.
*/
this.itemEnd = function ( url ) {

@@ -65,2 +128,8 @@

/**
* This should be called by any loader using the manager when the loader
* encounters an error when loading an item.
*
* @param {string} url - The URL of the item that produces an error.
*/
this.itemError = function ( url ) {

@@ -76,2 +145,9 @@

/**
* Given a URL, uses the URL modifier callback (if any) and returns a
* resolved URL. If no URL modifier is set, returns the original URL.
*
* @param {string} url - The URL to load.
* @return {string} The resolved URL.
*/
this.resolveURL = function ( url ) {

@@ -89,2 +165,36 @@

/**
* If provided, the callback will be passed each resource URL before a
* request is sent. The callback may return the original URL, or a new URL to
* override loading behavior. This behavior can be used to load assets from
* .ZIP files, drag-and-drop APIs, and Data URIs.
*
* ```js
* const blobs = {'fish.gltf': blob1, 'diffuse.png': blob2, 'normal.png': blob3};
*
* const manager = new THREE.LoadingManager();
*
* // Initialize loading manager with URL callback.
* const objectURLs = [];
* manager.setURLModifier( ( url ) => {
*
* url = URL.createObjectURL( blobs[ url ] );
* objectURLs.push( url );
* return url;
*
* } );
*
* // Load as usual, then revoke the blob URLs.
* const loader = new GLTFLoader( manager );
* loader.load( 'fish.gltf', (gltf) => {
*
* scene.add( gltf.scene );
* objectURLs.forEach( ( url ) => URL.revokeObjectURL( url ) );
*
* } );
* ```
*
* @param {function(string):string} transform - URL modifier callback. Called with an URL and must return a resolved URL.
* @return {LoadingManager} A reference to this loading manager.
*/
this.setURLModifier = function ( transform ) {

@@ -98,2 +208,16 @@

/**
* Registers a loader with the given regular expression. Can be used to
* define what loader should be used in order to load specific files. A
* typical use case is to overwrite the default loader for textures.
*
* ```js
* // add handler for TGA textures
* manager.addHandler( /\.tga$/i, new TGALoader() );
* ```
*
* @param {string} regex - A regular expression.
* @param {Loader} loader - A loader that should handle matched cases.
* @return {LoadingManager} A reference to this loading manager.
*/
this.addHandler = function ( regex, loader ) {

@@ -107,2 +231,8 @@

/**
* Removes the loader for the given regular expression.
*
* @param {string} regex - A regular expression.
* @return {LoadingManager} A reference to this loading manager.
*/
this.removeHandler = function ( regex ) {

@@ -122,2 +252,8 @@

/**
* Can be used to retrieve the registered loader for the given file path.
*
* @param {string} file - The file path.
* @return {?Loader} The registered loader. Returns `null` if no loader was found.
*/
this.getHandler = function ( file ) {

@@ -148,4 +284,10 @@

/**
* The global default loading manager.
*
* @constant
* @type {LoadingManager}
*/
const DefaultLoadingManager = /*@__PURE__*/ new LoadingManager();
export { DefaultLoadingManager, LoadingManager };

@@ -30,7 +30,30 @@ import { Color } from '../math/Color.js';

/**
* Class for loading geometries. The files are internally
* loaded via {@link FileLoader}.
*
* ```js
* const loader = new THREE.MaterialLoader();
* const material = await loader.loadAsync( 'material.json' );
* ```
* This loader does not support node materials. Use {@link NodeMaterialLoader} instead.
*
* @augments Loader
*/
class MaterialLoader extends Loader {
/**
* Constructs a new material loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {
super( manager );
/**
* A dictionary holding textures used by the material.
*
* @type {Object<string,Texture>}
*/
this.textures = {};

@@ -40,2 +63,10 @@

/**
* Starts loading from the given URL and pass the loaded material to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(Material)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -75,2 +106,8 @@

/**
* Parses the given JSON object and returns a material.
*
* @param {Object} json - The serialized material.
* @return {Material} The parsed material.
*/
parse( json ) {

@@ -341,2 +378,9 @@

/**
* Textures are not embedded in the material JSON so they have
* to be injected before the loading process starts.
*
* @param {Object} value - A dictionary holding textures for material properties.
* @return {MaterialLoader} A reference to this material loader.
*/
setTextures( value ) {

@@ -349,2 +393,8 @@

/**
* Creates a material for the given type.
*
* @param {string} type - The material type.
* @return {Material} The new material.
*/
createMaterialFromType( type ) {

@@ -356,2 +406,9 @@

/**
* Creates a material for the given type.
*
* @static
* @param {string} type - The material type.
* @return {Material} The new material.
*/
static createMaterialFromType( type ) {

@@ -358,0 +415,0 @@

@@ -16,3 +16,3 @@ import { nodeObject, float } from '../../nodes/tsl/TSLBase.js';

*
* @param {?LoadingManager} manager - A reference to a loading manager.
* @param {LoadingManager} [manager] - A reference to a loading manager.
*/

@@ -82,3 +82,3 @@ constructor( manager ) {

*
* @param {Object} json - The JSON definition
* @param {Array<Object>} [json] - The JSON definition
* @return {Object<string,Node>} A dictionary with node dependencies.

@@ -124,2 +124,6 @@ */

* @param {Object} json - The JSON definition
* @param {string} json.type - The node type.
* @param {string} json.uuid - The node UUID.
* @param {Array<Object>} [json.nodes] - The node dependencies.
* @param {Object} [json.meta] - The meta data.
* @return {Node} The parsed node.

@@ -126,0 +130,0 @@ */

@@ -13,3 +13,3 @@ import { MaterialLoader } from '../../loaders/MaterialLoader.js';

*
* @param {?LoadingManager} manager - A reference to a loading manager.
* @param {LoadingManager} [manager] - A reference to a loading manager.
*/

@@ -16,0 +16,0 @@ constructor( manager ) {

@@ -17,3 +17,3 @@ import NodeLoader from './NodeLoader.js';

*
* @param {?LoadingManager} manager - A reference to a loading manager.
* @param {LoadingManager} [manager] - A reference to a loading manager.
*/

@@ -52,3 +52,3 @@ constructor( manager ) {

* @param {Object<string,Node.constructor>} value - The node library defined as `<classname,class>`.
* @return {NodeLoader} A reference to this loader.
* @return {NodeObjectLoader} A reference to this loader.
*/

@@ -66,3 +66,3 @@ setNodes( value ) {

* @param {Object<string,NodeMaterial.constructor>} value - The node material library defined as `<classname,class>`.
* @return {NodeLoader} A reference to this loader.
* @return {NodeObjectLoader} A reference to this loader.
*/

@@ -69,0 +69,0 @@ setNodeMaterials( value ) {

@@ -66,4 +66,25 @@ import {

/**
* A loader for loading a JSON resource in the [JSON Object/Scene format]{@link https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4}.
* The files are internally loaded via {@link FileLoader}.
*
* ```js
* const loader = new THREE.ObjectLoader();
* const obj = await loader.loadAsync( 'models/json/example.json' );
* scene.add( obj );
*
* // Alternatively, to parse a previously loaded JSON structure
* const object = await loader.parseAsync( a_json_object );
* scene.add( object );
* ```
*
* @augments Loader
*/
class ObjectLoader extends Loader {
/**
* Constructs a new object loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -75,2 +96,10 @@

/**
* Starts loading from the given URL and pass the loaded 3D object to the `onLoad()` callback.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(Object3D)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
*/
load( url, onLoad, onProgress, onError ) {

@@ -122,2 +151,10 @@

/**
* Async version of {@link ObjectLoader#load}.
*
* @async
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @return {Promise<Object3D>} A Promise that resolves with the loaded 3D object.
*/
async loadAsync( url, onProgress ) {

@@ -151,2 +188,10 @@

/**
* Parses the given JSON. This is used internally by {@link ObjectLoader#load}
* but can also be used directly to parse a previously loaded JSON structure.
*
* @param {Object} json - The serialized 3D object.
* @param {onLoad} onLoad - Executed when all resources (e.g. textures) have been fully loaded.
* @return {Object3D} The parsed 3D object.
*/
parse( json, onLoad ) {

@@ -198,2 +243,8 @@

/**
* Async version of {@link ObjectLoader#parse}.
*
* @param {Object} json - The serialized 3D object.
* @return {Promise<Object3D>} A Promise that resolves with the parsed 3D object.
*/
async parseAsync( json ) {

@@ -220,2 +271,4 @@

// internals
parseShapes( json ) {

@@ -222,0 +275,0 @@

@@ -5,4 +5,25 @@ import { ImageLoader } from './ImageLoader.js';

/**
* Class for loading textures. Images are internally
* loaded via {@link ImageLoader}.
*
* ```js
* const loader = new THREE.TextureLoader();
* const texture = await loader.loadAsync( 'textures/land_ocean_ice_cloud_2048.jpg' );
*
* const material = new THREE.MeshBasicMaterial( { map:texture } );
* ```
* Please note that `TextureLoader` has dropped support for progress
* events in `r84`. For a `TextureLoader` that supports progress events, see
* [this thread]{@link https://github.com/mrdoob/three.js/issues/10439#issuecomment-293260145}.
*
* @augments Loader
*/
class TextureLoader extends Loader {
/**
* Constructs a new texture loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor( manager ) {

@@ -14,2 +35,14 @@

/**
* Starts loading from the given URL and pass the fully loaded texture
* to the `onLoad()` callback. The method also returns a new texture object which can
* directly be used for material creation. If you do it this way, the texture
* may pop up in your scene once the respective loading process is finished.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(Texture)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Unsupported in this loader.
* @param {onErrorCallback} onError - Executed when errors occur.
* @return {Texture} The texture.
*/
load( url, onLoad, onProgress, onError ) {

@@ -16,0 +49,0 @@

import { Material } from './Material.js';
import { Color } from '../math/Color.js';
/**
* A material for rendering line primitives.
*
* Materials define the appearance of renderable 3D objects.
*
* ```js
* const material = new THREE.LineBasicMaterial( { color: 0xffffff } );
* ```
*
* @augments Material
*/
class LineBasicMaterial extends Material {
/**
* Constructs a new line basic material.
*
* @param {Object} [parameters] - An object with one or more properties
* defining the material's appearance. Any property of the material
* (including any property from inherited materials) can be passed
* in here. Color values can be passed any type of value accepted
* by {@link Color#set}.
*/
constructor( parameters ) {

@@ -10,2 +30,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isLineBasicMaterial = true;

@@ -15,10 +42,57 @@

/**
* Color of the material.
*
* @type {Color}
* @default (1,1,1)
*/
this.color = new Color( 0xffffff );
/**
* Sets the color of the lines using data from a texture. The texture map
* color is modulated by the diffuse `color`.
*
* @type {?Texture}
* @default null
*/
this.map = null;
/**
* Controls line thickness or lines.
*
* Can only be used with {@link SVGRenderer}. WebGL and WebGPU
* ignore this setting and always render line primitives with a
* width of one pixel.
*
* @type {number}
* @default 1
*/
this.linewidth = 1;
/**
* Defines appearance of line ends.
*
* Can only be used with {@link SVGRenderer}.
*
* @type {('butt'|'round'|'square')}
* @default 'round'
*/
this.linecap = 'round';
/**
* Defines appearance of line joints.
*
* Can only be used with {@link SVGRenderer}.
*
* @type {('round'|'bevel'|'miter')}
* @default 'round'
*/
this.linejoin = 'round';
/**
* Whether the material is affected by fog or not.
*
* @type {boolean}
* @default true
*/
this.fog = true;

@@ -30,3 +104,2 @@

copy( source ) {

@@ -33,0 +106,0 @@

import { LineBasicMaterial } from './LineBasicMaterial.js';
/**
* A material for rendering line primitives.
*
* Materials define the appearance of renderable 3D objects.
*
* ```js
* const material = new THREE.LineDashedMaterial( {
* color: 0xffffff,
* scale: 1,
* dashSize: 3,
* gapSize: 1,
* } );
* ```
*
* @augments LineBasicMaterial
*/
class LineDashedMaterial extends LineBasicMaterial {
/**
* Constructs a new line dashed material.
*
* @param {Object} [parameters] - An object with one or more properties
* defining the material's appearance. Any property of the material
* (including any property from inherited materials) can be passed
* in here. Color values can be passed any type of value accepted
* by {@link Color#set}.
*/
constructor( parameters ) {

@@ -9,7 +34,34 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isLineDashedMaterial = true;
this.type = 'LineDashedMaterial';
/**
* The scale of the dashed part of a line.
*
* @type {number}
* @default 1
*/
this.scale = 1;
/**
* The size of the dash. This is both the gap with the stroke.
*
* @type {number}
* @default 3
*/
this.dashSize = 3;
/**
* The size of the gap.
*
* @type {number}
* @default 1
*/
this.gapSize = 1;

@@ -16,0 +68,0 @@

@@ -154,3 +154,3 @@ import { Color } from '../math/Color.js';

* @type {(AddEquation|SubtractEquation|ReverseSubtractEquation|MinEquation|MaxEquation)}
* @default OneMinusSrcAlphaFactor
* @default AddEquation
*/

@@ -178,4 +178,4 @@ this.blendEquation = AddEquation;

*
* @type {(AddEquation|SubtractEquation|ReverseSubtractEquation|MinEquation|MaxEquation)}
* @default OneMinusSrcAlphaFactor
* @type {?(AddEquation|SubtractEquation|ReverseSubtractEquation|MinEquation|MaxEquation)}
* @default null
*/

@@ -433,2 +433,10 @@ this.blendEquationAlpha = null;

/**
* Whether it's possible to override the material with {@link Scene#overrideMaterial} or not.
*
* @type {boolean}
* @default true
*/
this.allowOverride = true;
/**
* Defines whether 3D objects using this material are visible.

@@ -542,2 +550,9 @@ *

/**
* This method can be used to set default values from parameter objects.
* It is a generic implementation so it can be used with different types
* of materials.
*
* @param {Object} [values] - The material values to set.
*/
setValues( values ) {

@@ -544,0 +559,0 @@

@@ -6,4 +6,20 @@ import { Material } from './Material.js';

/**
* A material for drawing geometries in a simple shaded (flat or wireframe) way.
*
* This material is not affected by lights.
*
* @augments Material
*/
class MeshBasicMaterial extends Material {
/**
* Constructs a new mesh basic material.
*
* @param {Object} [parameters] - An object with one or more properties
* defining the material's appearance. Any property of the material
* (including any property from inherited materials) can be passed
* in here. Color values can be passed any type of value accepted
* by {@link Color#set}.
*/
constructor( parameters ) {

@@ -13,2 +29,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isMeshBasicMaterial = true;

@@ -18,27 +41,169 @@

/**
* Color of the material.
*
* @type {Color}
* @default (1,1,1)
*/
this.color = new Color( 0xffffff ); // emissive
/**
* The color map. May optionally include an alpha channel, typically combined
* with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
* color is modulated by the diffuse `color`.
*
* @type {?Texture}
* @default null
*/
this.map = null;
/**
* The light map. Requires a second set of UVs.
*
* @type {?Texture}
* @default null
*/
this.lightMap = null;
/**
* Intensity of the baked light.
*
* @type {number}
* @default 1
*/
this.lightMapIntensity = 1.0;
/**
* The red channel of this texture is used as the ambient occlusion map.
* Requires a second set of UVs.
*
* @type {?Texture}
* @default null
*/
this.aoMap = null;
/**
* Intensity of the ambient occlusion effect. Range is `[0,1]`, where `0`
* disables ambient occlusion. Where intensity is `1` and the AO map's
* red channel is also `1`, ambient light is fully occluded on a surface.
*
* @type {number}
* @default 1
*/
this.aoMapIntensity = 1.0;
/**
* Specular map used by the material.
*
* @type {?Texture}
* @default null
*/
this.specularMap = null;
/**
* The alpha map is a grayscale texture that controls the opacity across the
* surface (black: fully transparent; white: fully opaque).
*
* Only the color of the texture is used, ignoring the alpha channel if one
* exists. For RGB and RGBA textures, the renderer will use the green channel
* when sampling this texture due to the extra bit of precision provided for
* green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
* luminance/alpha textures will also still work as expected.
*
* @type {?Texture}
* @default null
*/
this.alphaMap = null;
/**
* The environment map.
*
* @type {?Texture}
* @default null
*/
this.envMap = null;
/**
* The rotation of the environment map in radians.
*
* @type {Euler}
* @default (0,0,0)
*/
this.envMapRotation = new Euler();
/**
* How to combine the result of the surface's color with the environment map, if any.
*
* When set to `MixOperation`, the {@link MeshBasicMaterial#reflectivity} is used to
* blend between the two colors.
*
* @type {(MultiplyOperation|MixOperation|AddOperation)}
* @default MultiplyOperation
*/
this.combine = MultiplyOperation;
/**
* How much the environment map affects the surface.
* The valid range is between `0` (no reflections) and `1` (full reflections).
*
* @type {number}
* @default 1
*/
this.reflectivity = 1;
/**
* The index of refraction (IOR) of air (approximately 1) divided by the
* index of refraction of the material. It is used with environment mapping
* modes {@link CubeRefractionMapping} and {@link EquirectangularRefractionMapping}.
* The refraction ratio should not exceed `1`.
*
* @type {number}
* @default 0.98
*/
this.refractionRatio = 0.98;
/**
* Renders the geometry as a wireframe.
*
* @type {boolean}
* @default false
*/
this.wireframe = false;
/**
* Controls the thickness of the wireframe.
*
* Can only be used with {@link SVGRenderer}.
*
* @type {number}
* @default 1
*/
this.wireframeLinewidth = 1;
/**
* Defines appearance of wireframe ends.
*
* Can only be used with {@link SVGRenderer}.
*
* @type {('round'|'bevel'|'miter')}
* @default 'round'
*/
this.wireframeLinecap = 'round';
/**
* Defines appearance of wireframe joints.
*
* Can only be used with {@link SVGRenderer}.
*
* @type {('round'|'bevel'|'miter')}
* @default 'round'
*/
this.wireframeLinejoin = 'round';
/**
* Whether the material is affected by fog or not.
*
* @type {boolean}
* @default true
*/
this.fog = true;

@@ -45,0 +210,0 @@

import { Material } from './Material.js';
import { BasicDepthPacking } from '../constants.js';
/**
* A material for drawing geometry by depth. Depth is based off of the camera
* near and far plane. White is nearest, black is farthest.
*
* @augments Material
*/
class MeshDepthMaterial extends Material {
/**
* Constructs a new mesh depth material.
*
* @param {Object} [parameters] - An object with one or more properties
* defining the material's appearance. Any property of the material
* (including any property from inherited materials) can be passed
* in here. Color values can be passed any type of value accepted
* by {@link Color#set}.
*/
constructor( parameters ) {

@@ -10,2 +25,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isMeshDepthMaterial = true;

@@ -15,13 +37,84 @@

/**
* Type for depth packing.
*
* @type {(BasicDepthPacking|RGBADepthPacking|RGBDepthPacking|RGDepthPacking)}
* @default BasicDepthPacking
*/
this.depthPacking = BasicDepthPacking;
/**
* The color map. May optionally include an alpha channel, typically combined
* with {@link Material#transparent} or {@link Material#alphaTest}.
*
* @type {?Texture}
* @default null
*/
this.map = null;
/**
* The alpha map is a grayscale texture that controls the opacity across the
* surface (black: fully transparent; white: fully opaque).
*
* Only the color of the texture is used, ignoring the alpha channel if one
* exists. For RGB and RGBA textures, the renderer will use the green channel
* when sampling this texture due to the extra bit of precision provided for
* green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
* luminance/alpha textures will also still work as expected.
*
* @type {?Texture}
* @default null
*/
this.alphaMap = null;
/**
* The displacement map affects the position of the mesh's vertices. Unlike
* other maps which only affect the light and shade of the material the
* displaced vertices can cast shadows, block other objects, and otherwise
* act as real geometry. The displacement texture is an image where the value
* of each pixel (white being the highest) is mapped against, and
* repositions, the vertices of the mesh.
*
* @type {?Texture}
* @default null
*/
this.displacementMap = null;
/**
* How much the displacement map affects the mesh (where black is no
* displacement, and white is maximum displacement). Without a displacement
* map set, this value is not applied.
*
* @type {number}
* @default 0
*/
this.displacementScale = 1;
/**
* The offset of the displacement map's values on the mesh's vertices.
* The bias is added to the scaled sample of the displacement map.
* Without a displacement map set, this value is not applied.
*
* @type {number}
* @default 0
*/
this.displacementBias = 0;
/**
* Renders the geometry as a wireframe.
*
* @type {boolean}
* @default false
*/
this.wireframe = false;
/**
* Controls the thickness of the wireframe.
*
* WebGL and WebGPU ignore this property and always render
* 1 pixel wide lines.
*
* @type {number}
* @default 1
*/
this.wireframeLinewidth = 1;

@@ -28,0 +121,0 @@

import { Material } from './Material.js';
/**
* A material used internally for implementing shadow mapping with
* point lights.
*
* Can also be used to customize the shadow casting of an object by assigning
* an instance of `MeshDistanceMaterial` to {@link Object3D#customDistanceMaterial}.
* The following examples demonstrates this approach in order to ensure
* transparent parts of objects do no cast shadows.
*
* @augments Material
*/
class MeshDistanceMaterial extends Material {
/**
* Constructs a new mesh distance material.
*
* @param {Object} [parameters] - An object with one or more properties
* defining the material's appearance. Any property of the material
* (including any property from inherited materials) can be passed
* in here. Color values can be passed any type of value accepted
* by {@link Color#set}.
*/
constructor( parameters ) {

@@ -9,2 +29,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isMeshDistanceMaterial = true;

@@ -14,8 +41,57 @@

/**
* The color map. May optionally include an alpha channel, typically combined
* with {@link Material#transparent} or {@link Material#alphaTest}.
*
* @type {?Texture}
* @default null
*/
this.map = null;
/**
* The alpha map is a grayscale texture that controls the opacity across the
* surface (black: fully transparent; white: fully opaque).
*
* Only the color of the texture is used, ignoring the alpha channel if one
* exists. For RGB and RGBA textures, the renderer will use the green channel
* when sampling this texture due to the extra bit of precision provided for
* green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
* luminance/alpha textures will also still work as expected.
*
* @type {?Texture}
* @default null
*/
this.alphaMap = null;
/**
* The displacement map affects the position of the mesh's vertices. Unlike
* other maps which only affect the light and shade of the material the
* displaced vertices can cast shadows, block other objects, and otherwise
* act as real geometry. The displacement texture is an image where the value
* of each pixel (white being the highest) is mapped against, and
* repositions, the vertices of the mesh.
*
* @type {?Texture}
* @default null
*/
this.displacementMap = null;
/**
* How much the displacement map affects the mesh (where black is no
* displacement, and white is maximum displacement). Without a displacement
* map set, this value is not applied.
*
* @type {number}
* @default 0
*/
this.displacementScale = 1;
/**
* The offset of the displacement map's values on the mesh's vertices.
* The bias is added to the scaled sample of the displacement map.
* Without a displacement map set, this value is not applied.
*
* @type {number}
* @default 0
*/
this.displacementBias = 0;

@@ -22,0 +98,0 @@

@@ -7,4 +7,29 @@ import { MultiplyOperation, TangentSpaceNormalMap } from '../constants.js';

/**
* A material for non-shiny surfaces, without specular highlights.
*
* The material uses a non-physically based [Lambertian]{@link https://en.wikipedia.org/wiki/Lambertian_reflectance}
* model for calculating reflectance. This can simulate some surfaces (such
* as untreated wood or stone) well, but cannot simulate shiny surfaces with
* specular highlights (such as varnished wood). `MeshLambertMaterial` uses per-fragment
* shading.
*
* Due to the simplicity of the reflectance and illumination models,
* performance will be greater when using this material over the
* {@link MeshPhongMaterial}, {@link MeshStandardMaterial} or
* {@link MeshPhysicalMaterial}, at the cost of some graphical accuracy.
*
* @augments Material
*/
class MeshLambertMaterial extends Material {
/**
* Constructs a new mesh lambert material.
*
* @param {Object} [parameters] - An object with one or more properties
* defining the material's appearance. Any property of the material
* (including any property from inherited materials) can be passed
* in here. Color values can be passed any type of value accepted
* by {@link Color#set}.
*/
constructor( parameters ) {

@@ -14,2 +39,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isMeshLambertMaterial = true;

@@ -19,44 +51,285 @@

/**
* Color of the material.
*
* @type {Color}
* @default (1,1,1)
*/
this.color = new Color( 0xffffff ); // diffuse
/**
* The color map. May optionally include an alpha channel, typically combined
* with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
* color is modulated by the diffuse `color`.
*
* @type {?Texture}
* @default null
*/
this.map = null;
/**
* The light map. Requires a second set of UVs.
*
* @type {?Texture}
* @default null
*/
this.lightMap = null;
/**
* Intensity of the baked light.
*
* @type {number}
* @default 1
*/
this.lightMapIntensity = 1.0;
/**
* The red channel of this texture is used as the ambient occlusion map.
* Requires a second set of UVs.
*
* @type {?Texture}
* @default null
*/
this.aoMap = null;
/**
* Intensity of the ambient occlusion effect. Range is `[0,1]`, where `0`
* disables ambient occlusion. Where intensity is `1` and the AO map's
* red channel is also `1`, ambient light is fully occluded on a surface.
*
* @type {number}
* @default 1
*/
this.aoMapIntensity = 1.0;
/**
* Emissive (light) color of the material, essentially a solid color
* unaffected by other lighting.
*
* @type {Color}
* @default (0,0,0)
*/
this.emissive = new Color( 0x000000 );
/**
* Intensity of the emissive light. Modulates the emissive color.
*
* @type {number}
* @default 1
*/
this.emissiveIntensity = 1.0;
/**
* Set emissive (glow) map. The emissive map color is modulated by the
* emissive color and the emissive intensity. If you have an emissive map,
* be sure to set the emissive color to something other than black.
*
* @type {?Texture}
* @default null
*/
this.emissiveMap = null;
/**
* The texture to create a bump map. The black and white values map to the
* perceived depth in relation to the lights. Bump doesn't actually affect
* the geometry of the object, only the lighting. If a normal map is defined
* this will be ignored.
*
* @type {?Texture}
* @default null
*/
this.bumpMap = null;
/**
* How much the bump map affects the material. Typical range is `[0,1]`.
*
* @type {number}
* @default 1
*/
this.bumpScale = 1;
/**
* The texture to create a normal map. The RGB values affect the surface
* normal for each pixel fragment and change the way the color is lit. Normal
* maps do not change the actual shape of the surface, only the lighting. In
* case the material has a normal map authored using the left handed
* convention, the `y` component of `normalScale` should be negated to compensate
* for the different handedness.
*
* @type {?Texture}
* @default null
*/
this.normalMap = null;
/**
* The type of normal map.
*
* @type {(TangentSpaceNormalMap|ObjectSpaceNormalMap)}
* @default TangentSpaceNormalMap
*/
this.normalMapType = TangentSpaceNormalMap;
/**
* How much the normal map affects the material. Typical value range is `[0,1]`.
*
* @type {Vector2}
* @default (1,1)
*/
this.normalScale = new Vector2( 1, 1 );
/**
* The displacement map affects the position of the mesh's vertices. Unlike
* other maps which only affect the light and shade of the material the
* displaced vertices can cast shadows, block other objects, and otherwise
* act as real geometry. The displacement texture is an image where the value
* of each pixel (white being the highest) is mapped against, and
* repositions, the vertices of the mesh.
*
* @type {?Texture}
* @default null
*/
this.displacementMap = null;
/**
* How much the displacement map affects the mesh (where black is no
* displacement, and white is maximum displacement). Without a displacement
* map set, this value is not applied.
*
* @type {number}
* @default 0
*/
this.displacementScale = 1;
/**
* The offset of the displacement map's values on the mesh's vertices.
* The bias is added to the scaled sample of the displacement map.
* Without a displacement map set, this value is not applied.
*
* @type {number}
* @default 0
*/
this.displacementBias = 0;
/**
* Specular map used by the material.
*
* @type {?Texture}
* @default null
*/
this.specularMap = null;
/**
* The alpha map is a grayscale texture that controls the opacity across the
* surface (black: fully transparent; white: fully opaque).
*
* Only the color of the texture is used, ignoring the alpha channel if one
* exists. For RGB and RGBA textures, the renderer will use the green channel
* when sampling this texture due to the extra bit of precision provided for
* green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
* luminance/alpha textures will also still work as expected.
*
* @type {?Texture}
* @default null
*/
this.alphaMap = null;
/**
* The environment map.
*
* @type {?Texture}
* @default null
*/
this.envMap = null;
/**
* The rotation of the environment map in radians.
*
* @type {Euler}
* @default (0,0,0)
*/
this.envMapRotation = new Euler();
/**
* How to combine the result of the surface's color with the environment map, if any.
*
* When set to `MixOperation`, the {@link MeshBasicMaterial#reflectivity} is used to
* blend between the two colors.
*
* @type {(MultiplyOperation|MixOperation|AddOperation)}
* @default MultiplyOperation
*/
this.combine = MultiplyOperation;
/**
* How much the environment map affects the surface.
* The valid range is between `0` (no reflections) and `1` (full reflections).
*
* @type {number}
* @default 1
*/
this.reflectivity = 1;
/**
* The index of refraction (IOR) of air (approximately 1) divided by the
* index of refraction of the material. It is used with environment mapping
* modes {@link CubeRefractionMapping} and {@link EquirectangularRefractionMapping}.
* The refraction ratio should not exceed `1`.
*
* @type {number}
* @default 0.98
*/
this.refractionRatio = 0.98;
/**
* Renders the geometry as a wireframe.
*
* @type {boolean}
* @default false
*/
this.wireframe = false;
/**
* Controls the thickness of the wireframe.
*
* Can only be used with {@link SVGRenderer}.
*
* @type {number}
* @default 1
*/
this.wireframeLinewidth = 1;
/**
* Defines appearance of wireframe ends.
*
* Can only be used with {@link SVGRenderer}.
*
* @type {('round'|'bevel'|'miter')}
* @default 'round'
*/
this.wireframeLinecap = 'round';
/**
* Defines appearance of wireframe joints.
*
* Can only be used with {@link SVGRenderer}.
*
* @type {('round'|'bevel'|'miter')}
* @default 'round'
*/
this.wireframeLinejoin = 'round';
/**
* Whether the material is rendered with flat shading or not.
*
* @type {boolean}
* @default false
*/
this.flatShading = false;
/**
* Whether the material is affected by fog or not.
*
* @type {boolean}
* @default true
*/
this.fog = true;

@@ -63,0 +336,0 @@

@@ -6,4 +6,24 @@ import { TangentSpaceNormalMap } from '../constants.js';

/**
* This material is defined by a MatCap (or Lit Sphere) texture, which encodes the
* material color and shading.
*
* `MeshMatcapMaterial` does not respond to lights since the matcap image file encodes
* baked lighting. It will cast a shadow onto an object that receives shadows
* (and shadow clipping works), but it will not self-shadow or receive
* shadows.
*
* @augments Material
*/
class MeshMatcapMaterial extends Material {
/**
* Constructs a new mesh matcap material.
*
* @param {Object} [parameters] - An object with one or more properties
* defining the material's appearance. Any property of the material
* (including any property from inherited materials) can be passed
* in here. Color values can be passed any type of value accepted
* by {@link Color#set}.
*/
constructor( parameters ) {

@@ -13,2 +33,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isMeshMatcapMaterial = true;

@@ -20,23 +47,138 @@

/**
* Color of the material.
*
* @type {Color}
* @default (1,1,1)
*/
this.color = new Color( 0xffffff ); // diffuse
/**
* The matcap map.
*
* @type {?Texture}
* @default null
*/
this.matcap = null;
/**
* The color map. May optionally include an alpha channel, typically combined
* with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
* color is modulated by the diffuse `color`.
*
* @type {?Texture}
* @default null
*/
this.map = null;
/**
* The texture to create a bump map. The black and white values map to the
* perceived depth in relation to the lights. Bump doesn't actually affect
* the geometry of the object, only the lighting. If a normal map is defined
* this will be ignored.
*
* @type {?Texture}
* @default null
*/
this.bumpMap = null;
/**
* How much the bump map affects the material. Typical range is `[0,1]`.
*
* @type {number}
* @default 1
*/
this.bumpScale = 1;
/**
* The texture to create a normal map. The RGB values affect the surface
* normal for each pixel fragment and change the way the color is lit. Normal
* maps do not change the actual shape of the surface, only the lighting. In
* case the material has a normal map authored using the left handed
* convention, the `y` component of `normalScale` should be negated to compensate
* for the different handedness.
*
* @type {?Texture}
* @default null
*/
this.normalMap = null;
/**
* The type of normal map.
*
* @type {(TangentSpaceNormalMap|ObjectSpaceNormalMap)}
* @default TangentSpaceNormalMap
*/
this.normalMapType = TangentSpaceNormalMap;
/**
* How much the normal map affects the material. Typical value range is `[0,1]`.
*
* @type {Vector2}
* @default (1,1)
*/
this.normalScale = new Vector2( 1, 1 );
/**
* The displacement map affects the position of the mesh's vertices. Unlike
* other maps which only affect the light and shade of the material the
* displaced vertices can cast shadows, block other objects, and otherwise
* act as real geometry. The displacement texture is an image where the value
* of each pixel (white being the highest) is mapped against, and
* repositions, the vertices of the mesh.
*
* @type {?Texture}
* @default null
*/
this.displacementMap = null;
/**
* How much the displacement map affects the mesh (where black is no
* displacement, and white is maximum displacement). Without a displacement
* map set, this value is not applied.
*
* @type {number}
* @default 0
*/
this.displacementScale = 1;
/**
* The offset of the displacement map's values on the mesh's vertices.
* The bias is added to the scaled sample of the displacement map.
* Without a displacement map set, this value is not applied.
*
* @type {number}
* @default 0
*/
this.displacementBias = 0;
/**
* The alpha map is a grayscale texture that controls the opacity across the
* surface (black: fully transparent; white: fully opaque).
*
* Only the color of the texture is used, ignoring the alpha channel if one
* exists. For RGB and RGBA textures, the renderer will use the green channel
* when sampling this texture due to the extra bit of precision provided for
* green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
* luminance/alpha textures will also still work as expected.
*
* @type {?Texture}
* @default null
*/
this.alphaMap = null;
/**
* Whether the material is rendered with flat shading or not.
*
* @type {boolean}
* @default false
*/
this.flatShading = false;
/**
* Whether the material is affected by fog or not.
*
* @type {boolean}
* @default true
*/
this.fog = true;

@@ -43,0 +185,0 @@

@@ -5,4 +5,18 @@ import { TangentSpaceNormalMap } from '../constants.js';

/**
* A material that maps the normal vectors to RGB colors.
*
* @augments Material
*/
class MeshNormalMaterial extends Material {
/**
* Constructs a new mesh normal material.
*
* @param {Object} [parameters] - An object with one or more properties
* defining the material's appearance. Any property of the material
* (including any property from inherited materials) can be passed
* in here. Color values can be passed any type of value accepted
* by {@link Color#set}.
*/
constructor( parameters ) {

@@ -12,2 +26,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isMeshNormalMaterial = true;

@@ -17,16 +38,108 @@

/**
* The texture to create a bump map. The black and white values map to the
* perceived depth in relation to the lights. Bump doesn't actually affect
* the geometry of the object, only the lighting. If a normal map is defined
* this will be ignored.
*
* @type {?Texture}
* @default null
*/
this.bumpMap = null;
/**
* How much the bump map affects the material. Typical range is `[0,1]`.
*
* @type {number}
* @default 1
*/
this.bumpScale = 1;
/**
* The texture to create a normal map. The RGB values affect the surface
* normal for each pixel fragment and change the way the color is lit. Normal
* maps do not change the actual shape of the surface, only the lighting. In
* case the material has a normal map authored using the left handed
* convention, the `y` component of `normalScale` should be negated to compensate
* for the different handedness.
*
* @type {?Texture}
* @default null
*/
this.normalMap = null;
/**
* The type of normal map.
*
* @type {(TangentSpaceNormalMap|ObjectSpaceNormalMap)}
* @default TangentSpaceNormalMap
*/
this.normalMapType = TangentSpaceNormalMap;
/**
* How much the normal map affects the material. Typical value range is `[0,1]`.
*
* @type {Vector2}
* @default (1,1)
*/
this.normalScale = new Vector2( 1, 1 );
/**
* The displacement map affects the position of the mesh's vertices. Unlike
* other maps which only affect the light and shade of the material the
* displaced vertices can cast shadows, block other objects, and otherwise
* act as real geometry. The displacement texture is an image where the value
* of each pixel (white being the highest) is mapped against, and
* repositions, the vertices of the mesh.
*
* @type {?Texture}
* @default null
*/
this.displacementMap = null;
/**
* How much the displacement map affects the mesh (where black is no
* displacement, and white is maximum displacement). Without a displacement
* map set, this value is not applied.
*
* @type {number}
* @default 0
*/
this.displacementScale = 1;
/**
* The offset of the displacement map's values on the mesh's vertices.
* The bias is added to the scaled sample of the displacement map.
* Without a displacement map set, this value is not applied.
*
* @type {number}
* @default 0
*/
this.displacementBias = 0;
/**
* Renders the geometry as a wireframe.
*
* @type {boolean}
* @default false
*/
this.wireframe = false;
/**
* Controls the thickness of the wireframe.
*
* WebGL and WebGPU ignore this property and always render
* 1 pixel wide lines.
*
* @type {number}
* @default 1
*/
this.wireframeLinewidth = 1;
/**
* Whether the material is rendered with flat shading or not.
*
* @type {boolean}
* @default false
*/
this.flatShading = false;

@@ -33,0 +146,0 @@

@@ -6,4 +6,28 @@ import { MultiplyOperation, TangentSpaceNormalMap } from '../constants.js';

import { Euler } from '../math/Euler.js';
/**
* A material for shiny surfaces with specular highlights.
*
* The material uses a non-physically based [Blinn-Phong]{@link https://en.wikipedia.org/wiki/Blinn-Phong_shading_model}
* model for calculating reflectance. Unlike the Lambertian model used in the
* {@link MeshLambertMaterial} this can simulate shiny surfaces with specular
* highlights (such as varnished wood). `MeshPhongMaterial` uses per-fragment shading.
*
* Performance will generally be greater when using this material over the
* {@link MeshStandardMaterial} or {@link MeshPhysicalMaterial}, at the cost of
* some graphical accuracy.
*
* @augments Material
*/
class MeshPhongMaterial extends Material {
/**
* Constructs a new mesh phong material.
*
* @param {Object} [parameters] - An object with one or more properties
* defining the material's appearance. Any property of the material
* (including any property from inherited materials) can be passed
* in here. Color values can be passed any type of value accepted
* by {@link Color#set}.
*/
constructor( parameters ) {

@@ -13,2 +37,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isMeshPhongMaterial = true;

@@ -18,47 +49,304 @@

/**
* Color of the material.
*
* @type {Color}
* @default (1,1,1)
*/
this.color = new Color( 0xffffff ); // diffuse
/**
* Specular color of the material. The default color is set to `0x111111` (very dark grey)
*
* This defines how shiny the material is and the color of its shine.
*
* @type {Color}
*/
this.specular = new Color( 0x111111 );
/**
* How shiny the specular highlight is; a higher value gives a sharper highlight.
*
* @type {number}
* @default 30
*/
this.shininess = 30;
/**
* The color map. May optionally include an alpha channel, typically combined
* with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
* color is modulated by the diffuse `color`.
*
* @type {?Texture}
* @default null
*/
this.map = null;
/**
* The light map. Requires a second set of UVs.
*
* @type {?Texture}
* @default null
*/
this.lightMap = null;
/**
* Intensity of the baked light.
*
* @type {number}
* @default 1
*/
this.lightMapIntensity = 1.0;
/**
* The red channel of this texture is used as the ambient occlusion map.
* Requires a second set of UVs.
*
* @type {?Texture}
* @default null
*/
this.aoMap = null;
/**
* Intensity of the ambient occlusion effect. Range is `[0,1]`, where `0`
* disables ambient occlusion. Where intensity is `1` and the AO map's
* red channel is also `1`, ambient light is fully occluded on a surface.
*
* @type {number}
* @default 1
*/
this.aoMapIntensity = 1.0;
/**
* Emissive (light) color of the material, essentially a solid color
* unaffected by other lighting.
*
* @type {Color}
* @default (0,0,0)
*/
this.emissive = new Color( 0x000000 );
/**
* Intensity of the emissive light. Modulates the emissive color.
*
* @type {number}
* @default 1
*/
this.emissiveIntensity = 1.0;
/**
* Set emissive (glow) map. The emissive map color is modulated by the
* emissive color and the emissive intensity. If you have an emissive map,
* be sure to set the emissive color to something other than black.
*
* @type {?Texture}
* @default null
*/
this.emissiveMap = null;
/**
* The texture to create a bump map. The black and white values map to the
* perceived depth in relation to the lights. Bump doesn't actually affect
* the geometry of the object, only the lighting. If a normal map is defined
* this will be ignored.
*
* @type {?Texture}
* @default null
*/
this.bumpMap = null;
/**
* How much the bump map affects the material. Typical range is `[0,1]`.
*
* @type {number}
* @default 1
*/
this.bumpScale = 1;
/**
* The texture to create a normal map. The RGB values affect the surface
* normal for each pixel fragment and change the way the color is lit. Normal
* maps do not change the actual shape of the surface, only the lighting. In
* case the material has a normal map authored using the left handed
* convention, the `y` component of `normalScale` should be negated to compensate
* for the different handedness.
*
* @type {?Texture}
* @default null
*/
this.normalMap = null;
/**
* The type of normal map.
*
* @type {(TangentSpaceNormalMap|ObjectSpaceNormalMap)}
* @default TangentSpaceNormalMap
*/
this.normalMapType = TangentSpaceNormalMap;
/**
* How much the normal map affects the material. Typical value range is `[0,1]`.
*
* @type {Vector2}
* @default (1,1)
*/
this.normalScale = new Vector2( 1, 1 );
/**
* The displacement map affects the position of the mesh's vertices. Unlike
* other maps which only affect the light and shade of the material the
* displaced vertices can cast shadows, block other objects, and otherwise
* act as real geometry. The displacement texture is an image where the value
* of each pixel (white being the highest) is mapped against, and
* repositions, the vertices of the mesh.
*
* @type {?Texture}
* @default null
*/
this.displacementMap = null;
/**
* How much the displacement map affects the mesh (where black is no
* displacement, and white is maximum displacement). Without a displacement
* map set, this value is not applied.
*
* @type {number}
* @default 0
*/
this.displacementScale = 1;
/**
* The offset of the displacement map's values on the mesh's vertices.
* The bias is added to the scaled sample of the displacement map.
* Without a displacement map set, this value is not applied.
*
* @type {number}
* @default 0
*/
this.displacementBias = 0;
/**
* The specular map value affects both how much the specular surface
* highlight contributes and how much of the environment map affects the
* surface.
*
* @type {?Texture}
* @default null
*/
this.specularMap = null;
/**
* The alpha map is a grayscale texture that controls the opacity across the
* surface (black: fully transparent; white: fully opaque).
*
* Only the color of the texture is used, ignoring the alpha channel if one
* exists. For RGB and RGBA textures, the renderer will use the green channel
* when sampling this texture due to the extra bit of precision provided for
* green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
* luminance/alpha textures will also still work as expected.
*
* @type {?Texture}
* @default null
*/
this.alphaMap = null;
/**
* The environment map.
*
* @type {?Texture}
* @default null
*/
this.envMap = null;
/**
* The rotation of the environment map in radians.
*
* @type {Euler}
* @default (0,0,0)
*/
this.envMapRotation = new Euler();
/**
* How to combine the result of the surface's color with the environment map, if any.
*
* When set to `MixOperation`, the {@link MeshBasicMaterial#reflectivity} is used to
* blend between the two colors.
*
* @type {(MultiplyOperation|MixOperation|AddOperation)}
* @default MultiplyOperation
*/
this.combine = MultiplyOperation;
/**
* How much the environment map affects the surface.
* The valid range is between `0` (no reflections) and `1` (full reflections).
*
* @type {number}
* @default 1
*/
this.reflectivity = 1;
/**
* The index of refraction (IOR) of air (approximately 1) divided by the
* index of refraction of the material. It is used with environment mapping
* modes {@link CubeRefractionMapping} and {@link EquirectangularRefractionMapping}.
* The refraction ratio should not exceed `1`.
*
* @type {number}
* @default 0.98
*/
this.refractionRatio = 0.98;
/**
* Renders the geometry as a wireframe.
*
* @type {boolean}
* @default false
*/
this.wireframe = false;
/**
* Controls the thickness of the wireframe.
*
* Can only be used with {@link SVGRenderer}.
*
* @type {number}
* @default 1
*/
this.wireframeLinewidth = 1;
/**
* Defines appearance of wireframe ends.
*
* Can only be used with {@link SVGRenderer}.
*
* @type {('round'|'bevel'|'miter')}
* @default 'round'
*/
this.wireframeLinecap = 'round';
/**
* Defines appearance of wireframe joints.
*
* Can only be used with {@link SVGRenderer}.
*
* @type {('round'|'bevel'|'miter')}
* @default 'round'
*/
this.wireframeLinejoin = 'round';
/**
* Whether the material is rendered with flat shading or not.
*
* @type {boolean}
* @default false
*/
this.flatShading = false;
/**
* Whether the material is affected by fog or not.
*
* @type {boolean}
* @default true
*/
this.fog = true;

@@ -65,0 +353,0 @@

@@ -6,4 +6,38 @@ import { Vector2 } from '../math/Vector2.js';

/**
* An extension of the {@link MeshStandardMaterial}, providing more advanced
* physically-based rendering properties:
*
* - Anisotropy: Ability to represent the anisotropic property of materials
* as observable with brushed metals.
* - Clearcoat: Some materials — like car paints, carbon fiber, and wet surfaces — require
* a clear, reflective layer on top of another layer that may be irregular or rough.
* Clearcoat approximates this effect, without the need for a separate transparent surface.
* - Iridescence: Allows to render the effect where hue varies depending on the viewing
* angle and illumination angle. This can be seen on soap bubbles, oil films, or on the
* wings of many insects.
* - Physically-based transparency: One limitation of {@link Material#opacity} is that highly
* transparent materials are less reflective. Physically-based transmission provides a more
* realistic option for thin, transparent surfaces like glass.
* - Advanced reflectivity: More flexible reflectivity for non-metallic materials.
* - Sheen: Can be used for representing cloth and fabric materials.
*
* As a result of these complex shading features, `MeshPhysicalMaterial` has a
* higher performance cost, per pixel, than other three.js materials. Most
* effects are disabled by default, and add cost as they are enabled. For
* best results, always specify an environment map when using this material.
*
* @augments MeshStandardMaterial
*/
class MeshPhysicalMaterial extends MeshStandardMaterial {
/**
* Constructs a new mesh physical material.
*
* @param {Object} [parameters] - An object with one or more properties
* defining the material's appearance. Any property of the material
* (including any property from inherited materials) can be passed
* in here. Color values can be passed any type of value accepted
* by {@link Color#set}.
*/
constructor( parameters ) {

@@ -13,2 +47,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isMeshPhysicalMaterial = true;

@@ -25,13 +66,84 @@

/**
* The rotation of the anisotropy in tangent, bitangent space, measured in radians
* counter-clockwise from the tangent. When `anisotropyMap` is present, this
* property provides additional rotation to the vectors in the texture.
*
* @type {number}
* @default 1
*/
this.anisotropyRotation = 0;
/**
* Red and green channels represent the anisotropy direction in `[-1, 1]` tangent,
* bitangent space, to be rotated by `anisotropyRotation`. The blue channel
* contains strength as `[0, 1]` to be multiplied by `anisotropy`.
*
* @type {?Texture}
* @default null
*/
this.anisotropyMap = null;
/**
* The red channel of this texture is multiplied against `clearcoat`,
* for per-pixel control over a coating's intensity.
*
* @type {?Texture}
* @default null
*/
this.clearcoatMap = null;
/**
* Roughness of the clear coat layer, from `0.0` to `1.0`.
*
* @type {number}
* @default 0
*/
this.clearcoatRoughness = 0.0;
/**
* The green channel of this texture is multiplied against
* `clearcoatRoughness`, for per-pixel control over a coating's roughness.
*
* @type {?Texture}
* @default null
*/
this.clearcoatRoughnessMap = null;
/**
* How much `clearcoatNormalMap` affects the clear coat layer, from
* `(0,0)` to `(1,1)`.
*
* @type {Vector2}
* @default (1,1)
*/
this.clearcoatNormalScale = new Vector2( 1, 1 );
/**
* Can be used to enable independent normals for the clear coat layer.
*
* @type {?Texture}
* @default null
*/
this.clearcoatNormalMap = null;
/**
* Index-of-refraction for non-metallic materials, from `1.0` to `2.333`.
*
* @type {number}
* @default 1.5
*/
this.ior = 1.5;
/**
* Degree of reflectivity, from `0.0` to `1.0`. Default is `0.5`, which
* corresponds to an index-of-refraction of `1.5`.
*
* This models the reflectivity of non-metallic materials. It has no effect
* when `metalness` is `1.0`
*
* @name MeshPhysicalMaterial#reflectivity
* @type {number}
* @default 0.5
*/
Object.defineProperty( this, 'reflectivity', {

@@ -50,22 +162,155 @@ get: function () {

/**
* The red channel of this texture is multiplied against `iridescence`, for per-pixel
* control over iridescence.
*
* @type {?Texture}
* @default null
*/
this.iridescenceMap = null;
/**
* Strength of the iridescence RGB color shift effect, represented by an index-of-refraction.
* Between `1.0` to `2.333`.
*
* @type {number}
* @default 1.3
*/
this.iridescenceIOR = 1.3;
/**
*Array of exactly 2 elements, specifying minimum and maximum thickness of the iridescence layer.
Thickness of iridescence layer has an equivalent effect of the one `thickness` has on `ior`.
*
* @type {Array<number,number>}
* @default [100,400]
*/
this.iridescenceThicknessRange = [ 100, 400 ];
/**
* A texture that defines the thickness of the iridescence layer, stored in the green channel.
* Minimum and maximum values of thickness are defined by `iridescenceThicknessRange` array:
* - `0.0` in the green channel will result in thickness equal to first element of the array.
* - `1.0` in the green channel will result in thickness equal to second element of the array.
* - Values in-between will linearly interpolate between the elements of the array.
*
* @type {?Texture}
* @default null
*/
this.iridescenceThicknessMap = null;
/**
* The sheen tint.
*
* @type {Color}
* @default (0,0,0)
*/
this.sheenColor = new Color( 0x000000 );
/**
* The RGB channels of this texture are multiplied against `sheenColor`, for per-pixel control
* over sheen tint.
*
* @type {?Texture}
* @default null
*/
this.sheenColorMap = null;
/**
* Roughness of the sheen layer, from `0.0` to `1.0`.
*
* @type {number}
* @default 1
*/
this.sheenRoughness = 1.0;
/**
* The alpha channel of this texture is multiplied against `sheenRoughness`, for per-pixel control
* over sheen roughness.
*
* @type {?Texture}
* @default null
*/
this.sheenRoughnessMap = null;
/**
* The red channel of this texture is multiplied against `transmission`, for per-pixel control over
* optical transparency.
*
* @type {?Texture}
* @default null
*/
this.transmissionMap = null;
/**
* The thickness of the volume beneath the surface. The value is given in the
* coordinate space of the mesh. If the value is `0` the material is
* thin-walled. Otherwise the material is a volume boundary.
*
* @type {number}
* @default 0
*/
this.thickness = 0;
/**
* A texture that defines the thickness, stored in the green channel. This will
* be multiplied by `thickness`.
*
* @type {?Texture}
* @default null
*/
this.thicknessMap = null;
/**
* Density of the medium given as the average distance that light travels in
* the medium before interacting with a particle. The value is given in world
* space units, and must be greater than zero.
*
* @type {number}
* @default Infinity
*/
this.attenuationDistance = Infinity;
/**
* The color that white light turns into due to absorption when reaching the
* attenuation distance.
*
* @type {Color}
* @default (1,1,1)
*/
this.attenuationColor = new Color( 1, 1, 1 );
/**
* A float that scales the amount of specular reflection for non-metals only.
* When set to zero, the model is effectively Lambertian. From `0.0` to `1.0`.
*
* @type {number}
* @default 1
*/
this.specularIntensity = 1.0;
/**
* The alpha channel of this texture is multiplied against `specularIntensity`,
* for per-pixel control over specular intensity.
*
* @type {?Texture}
* @default null
*/
this.specularIntensityMap = null;
/**
* Tints the specular reflection at normal incidence for non-metals only.
*
* @type {Color}
* @default (1,1,1)
*/
this.specularColor = new Color( 1, 1, 1 );
/**
* The RGB channels of this texture are multiplied against `specularColor`,
* for per-pixel control over specular color.
*
* @type {?Texture}
* @default null
*/
this.specularColorMap = null;

@@ -84,2 +329,8 @@

/**
* The anisotropy strength.
*
* @type {number}
* @default 0
*/
get anisotropy() {

@@ -103,2 +354,10 @@

/**
* Represents the intensity of the clear coat layer, from `0.0` to `1.0`. Use
* clear coat related properties to enable multilayer materials that have a
* thin translucent layer over the base layer.
*
* @type {number}
* @default 0
*/
get clearcoat() {

@@ -121,3 +380,9 @@

}
/**
* The intensity of the iridescence layer, simulating RGB color shift based on the angle between
* the surface and the viewer, from `0.0` to `1.0`.
*
* @type {number}
* @default 0
*/
get iridescence() {

@@ -141,2 +406,10 @@

/**
* Defines the strength of the angular separation of colors (chromatic aberration) transmitting
* through a relatively clear volume. Any value zero or larger is valid, the typical range of
* realistic values is `[0, 1]`. This property can be only be used with transmissive objects.
*
* @type {number}
* @default 0
*/
get dispersion() {

@@ -160,2 +433,8 @@

/**
* The intensity of the sheen layer, from `0.0` to `1.0`.
*
* @type {number}
* @default 0
*/
get sheen() {

@@ -179,2 +458,14 @@

/**
* Degree of transmission (or optical transparency), from `0.0` to `1.0`.
*
* Thin, transparent or semitransparent, plastic or glass materials remain
* largely reflective even if they are fully transmissive. The transmission
* property can be used to model these materials.
*
* When transmission is non-zero, `opacity` should be set to `1`.
*
* @type {number}
* @default 0
*/
get transmission() {

@@ -181,0 +472,0 @@

@@ -7,4 +7,46 @@ import { TangentSpaceNormalMap } from '../constants.js';

/**
* A standard physically based material, using Metallic-Roughness workflow.
*
* Physically based rendering (PBR) has recently become the standard in many
* 3D applications, such as [Unity]{@link https://blogs.unity3d.com/2014/10/29/physically-based-shading-in-unity-5-a-primer/},
* [Unreal]{@link https://docs.unrealengine.com/latest/INT/Engine/Rendering/Materials/PhysicallyBased/} and
* [3D Studio Max]{@link http://area.autodesk.com/blogs/the-3ds-max-blog/what039s-new-for-rendering-in-3ds-max-2017}.
*
* This approach differs from older approaches in that instead of using
* approximations for the way in which light interacts with a surface, a
* physically correct model is used. The idea is that, instead of tweaking
* materials to look good under specific lighting, a material can be created
* that will react 'correctly' under all lighting scenarios.
*
* In practice this gives a more accurate and realistic looking result than
* the {@link MeshLambertMaterial} or {@link MeshPhongMaterial}, at the cost of
* being somewhat more computationally expensive. `MeshStandardMaterial` uses per-fragment
* shading.
*
* Note that for best results you should always specify an environment map when using this material.
*
* For a non-technical introduction to the concept of PBR and how to set up a
* PBR material, check out these articles by the people at [marmoset]{@link https://www.marmoset.co}:
*
* - [Basic Theory of Physically Based Rendering]{@link https://www.marmoset.co/posts/basic-theory-of-physically-based-rendering/}
* - [Physically Based Rendering and You Can Too]{@link https://www.marmoset.co/posts/physically-based-rendering-and-you-can-too/}
*
* Technical details of the approach used in three.js (and most other PBR systems) can be found is this
* [paper from Disney]{@link https://media.disneyanimation.com/uploads/production/publication_asset/48/asset/s2012_pbs_disney_brdf_notes_v3.pdf}
* (pdf), by Brent Burley.
*
* @augments Material
*/
class MeshStandardMaterial extends Material {
/**
* Constructs a new mesh standard material.
*
* @param {Object} [parameters] - An object with one or more properties
* defining the material's appearance. Any property of the material
* (including any property from inherited materials) can be passed
* in here. Color values can be passed any type of value accepted
* by {@link Color#set}.
*/
constructor( parameters ) {

@@ -14,2 +56,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isMeshStandardMaterial = true;

@@ -21,46 +70,294 @@

/**
* Color of the material.
*
* @type {Color}
* @default (1,1,1)
*/
this.color = new Color( 0xffffff ); // diffuse
/**
* How rough the material appears. `0.0` means a smooth mirror reflection, `1.0`
* means fully diffuse. If `roughnessMap` is also provided,
* both values are multiplied.
*
* @type {number}
* @default 1
*/
this.roughness = 1.0;
/**
* How much the material is like a metal. Non-metallic materials such as wood
* or stone use `0.0`, metallic use `1.0`, with nothing (usually) in between.
* A value between `0.0` and `1.0` could be used for a rusty metal look.
* If `metalnessMap` is also provided, both values are multiplied.
*
* @type {number}
* @default 0
*/
this.metalness = 0.0;
/**
* The color map. May optionally include an alpha channel, typically combined
* with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
* color is modulated by the diffuse `color`.
*
* @type {?Texture}
* @default null
*/
this.map = null;
/**
* The light map. Requires a second set of UVs.
*
* @type {?Texture}
* @default null
*/
this.lightMap = null;
/**
* Intensity of the baked light.
*
* @type {number}
* @default 1
*/
this.lightMapIntensity = 1.0;
/**
* The red channel of this texture is used as the ambient occlusion map.
* Requires a second set of UVs.
*
* @type {?Texture}
* @default null
*/
this.aoMap = null;
/**
* Intensity of the ambient occlusion effect. Range is `[0,1]`, where `0`
* disables ambient occlusion. Where intensity is `1` and the AO map's
* red channel is also `1`, ambient light is fully occluded on a surface.
*
* @type {number}
* @default 1
*/
this.aoMapIntensity = 1.0;
/**
* Emissive (light) color of the material, essentially a solid color
* unaffected by other lighting.
*
* @type {Color}
* @default (0,0,0)
*/
this.emissive = new Color( 0x000000 );
/**
* Intensity of the emissive light. Modulates the emissive color.
*
* @type {number}
* @default 1
*/
this.emissiveIntensity = 1.0;
/**
* Set emissive (glow) map. The emissive map color is modulated by the
* emissive color and the emissive intensity. If you have an emissive map,
* be sure to set the emissive color to something other than black.
*
* @type {?Texture}
* @default null
*/
this.emissiveMap = null;
/**
* The texture to create a bump map. The black and white values map to the
* perceived depth in relation to the lights. Bump doesn't actually affect
* the geometry of the object, only the lighting. If a normal map is defined
* this will be ignored.
*
* @type {?Texture}
* @default null
*/
this.bumpMap = null;
/**
* How much the bump map affects the material. Typical range is `[0,1]`.
*
* @type {number}
* @default 1
*/
this.bumpScale = 1;
/**
* The texture to create a normal map. The RGB values affect the surface
* normal for each pixel fragment and change the way the color is lit. Normal
* maps do not change the actual shape of the surface, only the lighting. In
* case the material has a normal map authored using the left handed
* convention, the `y` component of `normalScale` should be negated to compensate
* for the different handedness.
*
* @type {?Texture}
* @default null
*/
this.normalMap = null;
/**
* The type of normal map.
*
* @type {(TangentSpaceNormalMap|ObjectSpaceNormalMap)}
* @default TangentSpaceNormalMap
*/
this.normalMapType = TangentSpaceNormalMap;
/**
* How much the normal map affects the material. Typical value range is `[0,1]`.
*
* @type {Vector2}
* @default (1,1)
*/
this.normalScale = new Vector2( 1, 1 );
/**
* The displacement map affects the position of the mesh's vertices. Unlike
* other maps which only affect the light and shade of the material the
* displaced vertices can cast shadows, block other objects, and otherwise
* act as real geometry. The displacement texture is an image where the value
* of each pixel (white being the highest) is mapped against, and
* repositions, the vertices of the mesh.
*
* @type {?Texture}
* @default null
*/
this.displacementMap = null;
/**
* How much the displacement map affects the mesh (where black is no
* displacement, and white is maximum displacement). Without a displacement
* map set, this value is not applied.
*
* @type {number}
* @default 0
*/
this.displacementScale = 1;
/**
* The offset of the displacement map's values on the mesh's vertices.
* The bias is added to the scaled sample of the displacement map.
* Without a displacement map set, this value is not applied.
*
* @type {number}
* @default 0
*/
this.displacementBias = 0;
/**
* The green channel of this texture is used to alter the roughness of the
* material.
*
* @type {?Texture}
* @default null
*/
this.roughnessMap = null;
/**
* The blue channel of this texture is used to alter the metalness of the
* material.
*
* @type {?Texture}
* @default null
*/
this.metalnessMap = null;
/**
* The alpha map is a grayscale texture that controls the opacity across the
* surface (black: fully transparent; white: fully opaque).
*
* Only the color of the texture is used, ignoring the alpha channel if one
* exists. For RGB and RGBA textures, the renderer will use the green channel
* when sampling this texture due to the extra bit of precision provided for
* green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
* luminance/alpha textures will also still work as expected.
*
* @type {?Texture}
* @default null
*/
this.alphaMap = null;
/**
* The environment map. To ensure a physically correct rendering, environment maps
* are internally pre-processed with {@link PMREMGenerator}.
*
* @type {?Texture}
* @default null
*/
this.envMap = null;
/**
* The rotation of the environment map in radians.
*
* @type {Euler}
* @default (0,0,0)
*/
this.envMapRotation = new Euler();
/**
* Scales the effect of the environment map by multiplying its color.
*
* @type {number}
* @default 1
*/
this.envMapIntensity = 1.0;
/**
* Renders the geometry as a wireframe.
*
* @type {boolean}
* @default false
*/
this.wireframe = false;
/**
* Controls the thickness of the wireframe.
*
* Can only be used with {@link SVGRenderer}.
*
* @type {number}
* @default 1
*/
this.wireframeLinewidth = 1;
/**
* Defines appearance of wireframe ends.
*
* Can only be used with {@link SVGRenderer}.
*
* @type {('round'|'bevel'|'miter')}
* @default 'round'
*/
this.wireframeLinecap = 'round';
/**
* Defines appearance of wireframe joints.
*
* Can only be used with {@link SVGRenderer}.
*
* @type {('round'|'bevel'|'miter')}
* @default 'round'
*/
this.wireframeLinejoin = 'round';
/**
* Whether the material is rendered with flat shading or not.
*
* @type {boolean}
* @default false
*/
this.flatShading = false;
/**
* Whether the material is affected by fog or not.
*
* @type {boolean}
* @default true
*/
this.fog = true;

@@ -67,0 +364,0 @@

@@ -6,4 +6,18 @@ import { TangentSpaceNormalMap } from '../constants.js';

/**
* A material implementing toon shading.
*
* @augments Material
*/
class MeshToonMaterial extends Material {
/**
* Constructs a new mesh toon material.
*
* @param {Object} [parameters] - An object with one or more properties
* defining the material's appearance. Any property of the material
* (including any property from inherited materials) can be passed
* in here. Color values can be passed any type of value accepted
* by {@link Color#set}.
*/
constructor( parameters ) {

@@ -13,2 +27,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isMeshToonMaterial = true;

@@ -20,35 +41,232 @@

/**
* Color of the material.
*
* @type {Color}
* @default (1,1,1)
*/
this.color = new Color( 0xffffff );
/**
* The color map. May optionally include an alpha channel, typically combined
* with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
* color is modulated by the diffuse `color`.
*
* @type {?Texture}
* @default null
*/
this.map = null;
/**
* Gradient map for toon shading. It's required to set
* {@link Texture#minFilter} and {@link Texture#magFilter} to {@linkNearestFilter}
* when using this type of texture.
*
* @type {?Texture}
* @default null
*/
this.gradientMap = null;
/**
* The light map. Requires a second set of UVs.
*
* @type {?Texture}
* @default null
*/
this.lightMap = null;
/**
* Intensity of the baked light.
*
* @type {number}
* @default 1
*/
this.lightMapIntensity = 1.0;
/**
* The red channel of this texture is used as the ambient occlusion map.
* Requires a second set of UVs.
*
* @type {?Texture}
* @default null
*/
this.aoMap = null;
/**
* Intensity of the ambient occlusion effect. Range is `[0,1]`, where `0`
* disables ambient occlusion. Where intensity is `1` and the AO map's
* red channel is also `1`, ambient light is fully occluded on a surface.
*
* @type {number}
* @default 1
*/
this.aoMapIntensity = 1.0;
/**
* Emissive (light) color of the material, essentially a solid color
* unaffected by other lighting.
*
* @type {Color}
* @default (0,0,0)
*/
this.emissive = new Color( 0x000000 );
/**
* Intensity of the emissive light. Modulates the emissive color.
*
* @type {number}
* @default 1
*/
this.emissiveIntensity = 1.0;
/**
* Set emissive (glow) map. The emissive map color is modulated by the
* emissive color and the emissive intensity. If you have an emissive map,
* be sure to set the emissive color to something other than black.
*
* @type {?Texture}
* @default null
*/
this.emissiveMap = null;
/**
* The texture to create a bump map. The black and white values map to the
* perceived depth in relation to the lights. Bump doesn't actually affect
* the geometry of the object, only the lighting. If a normal map is defined
* this will be ignored.
*
* @type {?Texture}
* @default null
*/
this.bumpMap = null;
/**
* How much the bump map affects the material. Typical range is `[0,1]`.
*
* @type {number}
* @default 1
*/
this.bumpScale = 1;
/**
* The texture to create a normal map. The RGB values affect the surface
* normal for each pixel fragment and change the way the color is lit. Normal
* maps do not change the actual shape of the surface, only the lighting. In
* case the material has a normal map authored using the left handed
* convention, the `y` component of `normalScale` should be negated to compensate
* for the different handedness.
*
* @type {?Texture}
* @default null
*/
this.normalMap = null;
/**
* The type of normal map.
*
* @type {(TangentSpaceNormalMap|ObjectSpaceNormalMap)}
* @default TangentSpaceNormalMap
*/
this.normalMapType = TangentSpaceNormalMap;
/**
* How much the normal map affects the material. Typical value range is `[0,1]`.
*
* @type {Vector2}
* @default (1,1)
*/
this.normalScale = new Vector2( 1, 1 );
/**
* The displacement map affects the position of the mesh's vertices. Unlike
* other maps which only affect the light and shade of the material the
* displaced vertices can cast shadows, block other objects, and otherwise
* act as real geometry. The displacement texture is an image where the value
* of each pixel (white being the highest) is mapped against, and
* repositions, the vertices of the mesh.
*
* @type {?Texture}
* @default null
*/
this.displacementMap = null;
/**
* How much the displacement map affects the mesh (where black is no
* displacement, and white is maximum displacement). Without a displacement
* map set, this value is not applied.
*
* @type {number}
* @default 0
*/
this.displacementScale = 1;
/**
* The offset of the displacement map's values on the mesh's vertices.
* The bias is added to the scaled sample of the displacement map.
* Without a displacement map set, this value is not applied.
*
* @type {number}
* @default 0
*/
this.displacementBias = 0;
/**
* The alpha map is a grayscale texture that controls the opacity across the
* surface (black: fully transparent; white: fully opaque).
*
* Only the color of the texture is used, ignoring the alpha channel if one
* exists. For RGB and RGBA textures, the renderer will use the green channel
* when sampling this texture due to the extra bit of precision provided for
* green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
* luminance/alpha textures will also still work as expected.
*
* @type {?Texture}
* @default null
*/
this.alphaMap = null;
/**
* Renders the geometry as a wireframe.
*
* @type {boolean}
* @default false
*/
this.wireframe = false;
/**
* Controls the thickness of the wireframe.
*
* Can only be used with {@link SVGRenderer}.
*
* @type {number}
* @default 1
*/
this.wireframeLinewidth = 1;
/**
* Defines appearance of wireframe ends.
*
* Can only be used with {@link SVGRenderer}.
*
* @type {('round'|'bevel'|'miter')}
* @default 'round'
*/
this.wireframeLinecap = 'round';
/**
* Defines appearance of wireframe joints.
*
* Can only be used with {@link SVGRenderer}.
*
* @type {('round'|'bevel'|'miter')}
* @default 'round'
*/
this.wireframeLinejoin = 'round';
/**
* Whether the material is affected by fog or not.
*
* @type {boolean}
* @default true
*/
this.fog = true;

@@ -55,0 +273,0 @@

@@ -36,3 +36,3 @@ import NodeMaterial from './NodeMaterial.js';

*
* @param {?Object} parameters - The configuration parameter.
* @param {Object} [parameters={}] - The configuration parameter.
*/

@@ -39,0 +39,0 @@ constructor( parameters = {} ) {

@@ -8,3 +8,3 @@ import NodeMaterial from './NodeMaterial.js';

/**
* Node material version of `LineBasicMaterial`.
* Node material version of {@link LineBasicMaterial}.
*

@@ -24,3 +24,3 @@ * @augments NodeMaterial

*
* @param {?Object} parameters - The configuration parameter.
* @param {Object} [parameters] - The configuration parameter.
*/

@@ -27,0 +27,0 @@ constructor( parameters ) {

@@ -12,3 +12,3 @@ import NodeMaterial from './NodeMaterial.js';

/**
* Node material version of `LineDashedMaterial`.
* Node material version of {@link LineDashedMaterial}.
*

@@ -28,3 +28,3 @@ * @augments NodeMaterial

*
* @param {?Object} parameters - The configuration parameter.
* @param {Object} [parameters] - The configuration parameter.
*/

@@ -31,0 +31,0 @@ constructor( parameters ) {

@@ -14,3 +14,3 @@ import NodeMaterial from './NodeMaterial.js';

/**
* Node material version of `MeshBasicMaterial`.
* Node material version of {@link MeshBasicMaterial}.
*

@@ -30,3 +30,3 @@ * @augments NodeMaterial

*
* @param {?Object} parameters - The configuration parameter.
* @param {Object} [parameters] - The configuration parameter.
*/

@@ -33,0 +33,0 @@ constructor( parameters ) {

@@ -10,3 +10,3 @@ import NodeMaterial from './NodeMaterial.js';

/**
* Node material version of `MeshLambertMaterial`.
* Node material version of {@link MeshLambertMaterial}.
*

@@ -26,3 +26,3 @@ * @augments NodeMaterial

*
* @param {?Object} parameters - The configuration parameter.
* @param {Object} [parameters] - The configuration parameter.
*/

@@ -29,0 +29,0 @@ constructor( parameters ) {

@@ -13,3 +13,3 @@ import NodeMaterial from './NodeMaterial.js';

/**
* Node material version of `MeshMatcapMaterial`.
* Node material version of {@link MeshMatcapMaterial}.
*

@@ -29,3 +29,3 @@ * @augments NodeMaterial

*
* @param {?Object} parameters - The configuration parameter.
* @param {Object} [parameters] - The configuration parameter.
*/

@@ -32,0 +32,0 @@ constructor( parameters ) {

@@ -15,3 +15,3 @@ import NodeMaterial from './NodeMaterial.js';

/**
* Node material version of `MeshNormalMaterial`.
* Node material version of {@link MeshNormalMaterial}.
*

@@ -31,3 +31,3 @@ * @augments NodeMaterial

*
* @param {?Object} parameters - The configuration parameter.
* @param {Object} [parameters] - The configuration parameter.
*/

@@ -34,0 +34,0 @@ constructor( parameters ) {

@@ -13,3 +13,3 @@ import NodeMaterial from './NodeMaterial.js';

/**
* Node material version of `MeshPhongMaterial`.
* Node material version of {@link MeshPhongMaterial}.
*

@@ -29,3 +29,3 @@ * @augments NodeMaterial

*
* @param {?Object} parameters - The configuration parameter.
* @param {Object} [parameters] - The configuration parameter.
*/

@@ -32,0 +32,0 @@ constructor( parameters ) {

@@ -15,3 +15,3 @@ import { clearcoat, clearcoatRoughness, sheen, sheenRoughness, iridescence, iridescenceIOR, iridescenceThickness, specularColor, specularF90, diffuseColor, metalness, roughness, anisotropy, alphaT, anisotropyT, anisotropyB, ior, transmission, thickness, attenuationDistance, attenuationColor, dispersion } from '../../nodes/core/PropertyNode.js';

/**
* Node material version of `MeshPhysicalMaterial`.
* Node material version of {@link MeshPhysicalMaterial}.
*

@@ -31,3 +31,3 @@ * @augments MeshStandardNodeMaterial

*
* @param {?Object} parameters - The configuration parameter.
* @param {Object} [parameters] - The configuration parameter.
*/

@@ -34,0 +34,0 @@ constructor( parameters ) {

@@ -86,3 +86,3 @@ import MeshPhysicalNodeMaterial from './MeshPhysicalNodeMaterial.js';

*
* @param {?Object} parameters - The configuration parameter.
* @param {Object} [parameters] - The configuration parameter.
*/

@@ -89,0 +89,0 @@ constructor( parameters ) {

@@ -15,3 +15,3 @@ import NodeMaterial from './NodeMaterial.js';

/**
* Node material version of `MeshStandardMaterial`.
* Node material version of {@link MeshStandardMaterial}.
*

@@ -31,3 +31,3 @@ * @augments NodeMaterial

*
* @param {?Object} parameters - The configuration parameter.
* @param {Object} [parameters] - The configuration parameter.
*/

@@ -34,0 +34,0 @@ constructor( parameters ) {

@@ -9,3 +9,3 @@ import NodeMaterial from './NodeMaterial.js';

/**
* Node material version of `MeshToonMaterial`.
* Node material version of {@link MeshToonMaterial}.
*

@@ -25,3 +25,3 @@ * @augments NodeMaterial

*
* @param {?Object} parameters - The configuration parameter.
* @param {Object} [parameters] - The configuration parameter.
*/

@@ -28,0 +28,0 @@ constructor( parameters ) {

@@ -14,3 +14,3 @@ import { Material } from '../Material.js';

import { positionLocal, positionView } from '../../nodes/accessors/Position.js';
import { skinningReference } from '../../nodes/accessors/SkinningNode.js';
import { skinning } from '../../nodes/accessors/SkinningNode.js';
import { morphReference } from '../../nodes/accessors/MorphNode.js';

@@ -480,4 +480,6 @@ import { mix } from '../../nodes/math/MathNode.js';

if ( this.outputNode !== null ) resultNode = this.outputNode;
const isCustomOutput = this.outputNode !== null;
if ( isCustomOutput ) resultNode = this.outputNode;
// MRT

@@ -492,2 +494,4 @@

if ( isCustomOutput ) output.assign( resultNode );
resultNode = mrt;

@@ -701,3 +705,3 @@

skinningReference( object ).append();
skinning( object ).append();

@@ -704,0 +708,0 @@ }

@@ -14,3 +14,3 @@ import SpriteNodeMaterial from './SpriteNodeMaterial.js';

/**
* Node material version of `PointsMaterial`.
* Node material version of {@link PointsMaterial}.
*

@@ -17,0 +17,0 @@ * @augments SpriteNodeMaterial

@@ -9,3 +9,3 @@ import NodeMaterial from './NodeMaterial.js';

/**
* Node material version of `ShadowMaterial`.
* Node material version of {@link ShadowMaterial}.
*

@@ -25,3 +25,3 @@ * @augments NodeMaterial

*
* @param {?Object} parameters - The configuration parameter.
* @param {Object} [parameters] - The configuration parameter.
*/

@@ -50,2 +50,11 @@ constructor( parameters ) {

/**
* Overwritten since shadow materials are transparent
* by default.
*
* @type {boolean}
* @default true
*/
this.transparent = true;
this.setDefaultValues( _defaultValues );

@@ -52,0 +61,0 @@

@@ -15,3 +15,3 @@ import NodeMaterial from './NodeMaterial.js';

/**
* Node material version of `SpriteMaterial`.
* Node material version of {@link SpriteMaterial}.
*

@@ -18,0 +18,0 @@ * @augments NodeMaterial

@@ -21,3 +21,3 @@ import NodeMaterial from './NodeMaterial.js';

*
* @param {?Object} parameters - The configuration parameter.
* @param {Object} [parameters] - The configuration parameter.
*/

@@ -46,2 +46,11 @@ constructor( parameters ) {

/**
* Offsets the distance a ray has been traveled through a volume.
* Can be used to implement dithering to reduce banding.
*
* @type {Node<float>}
* @default null
*/
this.offsetNode = null;
/**
* Node used for scattering calculations.

@@ -48,0 +57,0 @@ *

import { Material } from './Material.js';
import { Color } from '../math/Color.js';
/**
* A material for rendering point primitives.
*
* Materials define the appearance of renderable 3D objects.
*
* ```js
* const vertices = [];
*
* for ( let i = 0; i < 10000; i ++ ) {
* const x = THREE.MathUtils.randFloatSpread( 2000 );
* const y = THREE.MathUtils.randFloatSpread( 2000 );
* const z = THREE.MathUtils.randFloatSpread( 2000 );
*
* vertices.push( x, y, z );
* }
*
* const geometry = new THREE.BufferGeometry();
* geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
* const material = new THREE.PointsMaterial( { color: 0x888888 } );
* const points = new THREE.Points( geometry, material );
* scene.add( points );
* ```
*
* @augments Material
*/
class PointsMaterial extends Material {
/**
* Constructs a new points material.
*
* @param {Object} [parameters] - An object with one or more properties
* defining the material's appearance. Any property of the material
* (including any property from inherited materials) can be passed
* in here. Color values can be passed any type of value accepted
* by {@link Color#set}.
*/
constructor( parameters ) {

@@ -10,2 +44,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isPointsMaterial = true;

@@ -15,11 +56,59 @@

/**
* Color of the material.
*
* @type {Color}
* @default (1,1,1)
*/
this.color = new Color( 0xffffff );
/**
* The color map. May optionally include an alpha channel, typically combined
* with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
* color is modulated by the diffuse `color`.
*
* @type {?Texture}
* @default null
*/
this.map = null;
/**
* The alpha map is a grayscale texture that controls the opacity across the
* surface (black: fully transparent; white: fully opaque).
*
* Only the color of the texture is used, ignoring the alpha channel if one
* exists. For RGB and RGBA textures, the renderer will use the green channel
* when sampling this texture due to the extra bit of precision provided for
* green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
* luminance/alpha textures will also still work as expected.
*
* @type {?Texture}
* @default null
*/
this.alphaMap = null;
/**
* Defines the size of the points in pixels.
*
* Might be capped if the value exceeds hardware dependent parameters like [gl.ALIASED_POINT_SIZE_RANGE]{@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getParamete}.
*
* @type {number}
* @default 1
*/
this.size = 1;
/**
* Specifies whether size of individual points is attenuated by the camera depth (perspective camera only).
*
* @type {boolean}
* @default true
*/
this.sizeAttenuation = true;
/**
* Whether the material is affected by fog or not.
*
* @type {boolean}
* @default true
*/
this.fog = true;

@@ -26,0 +115,0 @@

import { ShaderMaterial } from './ShaderMaterial.js';
/**
* This class works just like {@link ShaderMaterial}, except that definitions
* of built-in uniforms and attributes are not automatically prepended to the
* GLSL shader code.
*
* `RawShaderMaterial` can only be used with {@link WebGLRenderer}.
*
* @augments ShaderMaterial
*/
class RawShaderMaterial extends ShaderMaterial {
/**
* Constructs a new raw shader material.
*
* @param {Object} [parameters] - An object with one or more properties
* defining the material's appearance. Any property of the material
* (including any property from inherited materials) can be passed
* in here. Color values can be passed any type of value accepted
* by {@link Color#set}.
*/
constructor( parameters ) {

@@ -9,2 +27,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isRawShaderMaterial = true;

@@ -11,0 +36,0 @@

@@ -7,4 +7,45 @@ import { Material } from './Material.js';

/**
* A material rendered with custom shaders. A shader is a small program written in GLSL.
* that runs on the GPU. You may want to use a custom shader if you need to implement an
* effect not included with any of the built-in materials.
*
* There are the following notes to bear in mind when using a `ShaderMaterial`:
*
* - `ShaderMaterial` can only be used with {@link WebGLRenderer}.
* - Built in attributes and uniforms are passed to the shaders along with your code. If
* you don't want that, use {@link RawShaderMaterial} instead.
* - You can use the directive `#pragma unroll_loop_start` and `#pragma unroll_loop_end`
* in order to unroll a `for` loop in GLSL by the shader preprocessor. The directive has
* to be placed right above the loop. The loop formatting has to correspond to a defined standard.
* - The loop has to be [normalized]{@link https://en.wikipedia.org/wiki/Normalized_loop}.
* - The loop variable has to be *i*.
* - The value `UNROLLED_LOOP_INDEX` will be replaced with the explicitly
* value of *i* for the given iteration and can be used in preprocessor
* statements.
*
* ```js
* const material = new THREE.ShaderMaterial( {
* uniforms: {
* time: { value: 1.0 },
* resolution: { value: new THREE.Vector2() }
* },
* vertexShader: document.getElementById( 'vertexShader' ).textContent,
* fragmentShader: document.getElementById( 'fragmentShader' ).textContent
* } );
* ```
*
* @augments Material
*/
class ShaderMaterial extends Material {
/**
* Constructs a new shader material.
*
* @param {Object} [parameters] - An object with one or more properties
* defining the material's appearance. Any property of the material
* (including any property from inherited materials) can be passed
* in here. Color values can be passed any type of value accepted
* by {@link Color#set}.
*/
constructor( parameters ) {

@@ -14,2 +55,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isShaderMaterial = true;

@@ -19,20 +67,140 @@

/**
* Defines custom constants using `#define` directives within the GLSL code
* for both the vertex shader and the fragment shader; each key/value pair
* yields another directive.
* ```js
* defines: {
* FOO: 15,
* BAR: true
* }
* ```
* Yields the lines:
* ```
* #define FOO 15
* #define BAR true
* ```
*
* @type {Object}
*/
this.defines = {};
/**
* An object of the form:
* ```js
* {
* "uniform1": { value: 1.0 },
* "uniform2": { value: 2 }
* }
* ```
* specifying the uniforms to be passed to the shader code; keys are uniform
* names, values are definitions of the form
* ```
* {
* value: 1.0
* }
* ```
* where `value` is the value of the uniform. Names must match the name of
* the uniform, as defined in the GLSL code. Note that uniforms are refreshed
* on every frame, so updating the value of the uniform will immediately
* update the value available to the GLSL code.
*
* @type {Object}
*/
this.uniforms = {};
/**
* An array holding uniforms groups for configuring UBOs.
*
* @type {Array<UniformsGroup>}
*/
this.uniformsGroups = [];
/**
* Vertex shader GLSL code. This is the actual code for the shader.
*
* @type {string}
*/
this.vertexShader = default_vertex;
/**
* Fragment shader GLSL code. This is the actual code for the shader.
*
* @type {string}
*/
this.fragmentShader = default_fragment;
/**
* Controls line thickness or lines.
*
* WebGL and WebGPU ignore this setting and always render line primitives with a
* width of one pixel.
*
* @type {number}
* @default 1
*/
this.linewidth = 1;
/**
* Renders the geometry as a wireframe.
*
* @type {boolean}
* @default false
*/
this.wireframe = false;
/**
* Controls the thickness of the wireframe.
*
* WebGL and WebGPU ignore this property and always render
* 1 pixel wide lines.
*
* @type {number}
* @default 1
*/
this.wireframeLinewidth = 1;
this.fog = false; // set to use scene fog
this.lights = false; // set to use scene lights
this.clipping = false; // set to use user-defined clipping planes
/**
* Define whether the material color is affected by global fog settings; `true`
* to pass fog uniforms to the shader.
*
* @type {boolean}
* @default false
*/
this.fog = false;
/**
* Defines whether this material uses lighting; `true` to pass uniform data
* related to lighting to this shader.
*
* @type {boolean}
* @default false
*/
this.lights = false;
/**
* Defines whether this material supports clipping; `true` to let the renderer
* pass the clippingPlanes uniform.
*
* @type {boolean}
* @default false
*/
this.clipping = false;
/**
* Overwritten and set to `true` by default.
*
* @type {boolean}
* @default true
*/
this.forceSinglePass = true;
/**
* This object allows to enable certain WebGL 2 extensions.
*
* - clipCullDistance: set to `true` to use vertex shader clipping
* - multiDraw: set to `true` to use vertex shader multi_draw / enable gl_DrawID
*
* @type {{clipCullDistance:false,multiDraw:false}}
*/
this.extensions = {

@@ -43,4 +211,13 @@ clipCullDistance: false, // set to use vertex shader clipping

// When rendered geometry doesn't include these attributes but the material does,
// use these default values in WebGL. This avoids errors when buffer data is missing.
/**
* When the rendered geometry doesn't include these attributes but the
* material does, these default values will be passed to the shaders. This
* avoids errors when buffer data is missing.
*
* - color: [ 1, 1, 1 ]
* - uv: [ 0, 0 ]
* - uv1: [ 0, 0 ]
*
* @type {Object}
*/
this.defaultAttributeValues = {

@@ -52,5 +229,26 @@ 'color': [ 1, 1, 1 ],

/**
* If set, this calls [gl.bindAttribLocation]{@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bindAttribLocation}
* to bind a generic vertex index to an attribute variable.
*
* @type {string|undefined}
* @default undefined
*/
this.index0AttributeName = undefined;
/**
* Can be used to force a uniform update while changing uniforms in
* {@link Object3D#onBeforeRender}.
*
* @type {boolean}
* @default false
*/
this.uniformsNeedUpdate = false;
/**
* Defines the GLSL version of custom shader code.
*
* @type {?(GLSL1|GLSL3)}
* @default null
*/
this.glslVersion = null;

@@ -190,2 +388,13 @@

/**
* This type represents the fields required to store and run the shader code.
*
* @typedef {Object} ShaderMaterial~Shader
* @property {string} name - The name of the shader.
* @property {Object<string, Uniform>} uniforms - The uniforms of the shader.
* @property {Object<string, any>} defines - The defines of the shader.
* @property {string} vertexShader - The vertex shader code.
* @property {string} fragmentShader - The fragment shader code.
**/
export { ShaderMaterial };
import { Material } from './Material.js';
import { Color } from '../math/Color.js';
/**
* This material can receive shadows, but otherwise is completely transparent.
*
* ```js
* const geometry = new THREE.PlaneGeometry( 2000, 2000 );
* geometry.rotateX( - Math.PI / 2 );
*
* const material = new THREE.ShadowMaterial();
* material.opacity = 0.2;
*
* const plane = new THREE.Mesh( geometry, material );
* plane.position.y = -200;
* plane.receiveShadow = true;
* scene.add( plane );
* ```
*
* @augments Material
*/
class ShadowMaterial extends Material {
/**
* Constructs a new shadow material.
*
* @param {Object} [parameters] - An object with one or more properties
* defining the material's appearance. Any property of the material
* (including any property from inherited materials) can be passed
* in here. Color values can be passed any type of value accepted
* by {@link Color#set}.
*/
constructor( parameters ) {

@@ -10,2 +37,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isShadowMaterial = true;

@@ -15,5 +49,25 @@

/**
* Color of the material.
*
* @type {Color}
* @default (0,0,0)
*/
this.color = new Color( 0x000000 );
/**
* Overwritten since shadow materials are transparent
* by default.
*
* @type {boolean}
* @default true
*/
this.transparent = true;
/**
* Whether the material is affected by fog or not.
*
* @type {boolean}
* @default true
*/
this.fog = true;

@@ -20,0 +74,0 @@

import { Material } from './Material.js';
import { Color } from '../math/Color.js';
/**
* A material for rendering instances of {@link Sprite}.
*
* ```js
* const map = new THREE.TextureLoader().load( 'textures/sprite.png' );
* const material = new THREE.SpriteMaterial( { map: map, color: 0xffffff } );
*
* const sprite = new THREE.Sprite( material );
* sprite.scale.set(200, 200, 1)
* scene.add( sprite );
* ```
*
* @augments Material
*/
class SpriteMaterial extends Material {
/**
* Constructs a new sprite material.
*
* @param {Object} [parameters] - An object with one or more properties
* defining the material's appearance. Any property of the material
* (including any property from inherited materials) can be passed
* in here. Color values can be passed any type of value accepted
* by {@link Color#set}.
*/
constructor( parameters ) {

@@ -10,2 +33,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isSpriteMaterial = true;

@@ -15,14 +45,66 @@

/**
* Color of the material.
*
* @type {Color}
* @default (1,1,1)
*/
this.color = new Color( 0xffffff );
/**
* The color map. May optionally include an alpha channel, typically combined
* with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
* color is modulated by the diffuse `color`.
*
* @type {?Texture}
* @default null
*/
this.map = null;
/**
* The alpha map is a grayscale texture that controls the opacity across the
* surface (black: fully transparent; white: fully opaque).
*
* Only the color of the texture is used, ignoring the alpha channel if one
* exists. For RGB and RGBA textures, the renderer will use the green channel
* when sampling this texture due to the extra bit of precision provided for
* green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
* luminance/alpha textures will also still work as expected.
*
* @type {?Texture}
* @default null
*/
this.alphaMap = null;
/**
* The rotation of the sprite in radians.
*
* @type {number}
* @default 0
*/
this.rotation = 0;
/**
* Specifies whether size of the sprite is attenuated by the camera depth (perspective camera only).
*
* @type {boolean}
* @default true
*/
this.sizeAttenuation = true;
/**
* Overwritten since sprite materials are transparent
* by default.
*
* @type {boolean}
* @default true
*/
this.transparent = true;
/**
* Whether the material is affected by fog or not.
*
* @type {boolean}
* @default true
*/
this.fog = true;

@@ -29,0 +111,0 @@

@@ -562,3 +562,3 @@ import { clamp, euclideanModulo, lerp } from './MathUtils.js';

*
* @param {{h:0,s:0,l:0}} target - The target object that is used to store the method's result.
* @param {{h:number,s:number,l:number}} target - The target object that is used to store the method's result.
* @param {string} [colorSpace=ColorManagement.workingColorSpace] - The color space.

@@ -565,0 +565,0 @@ * @return {{h:number,s:number,l:number}} The HSL representation of this color.

@@ -473,26 +473,249 @@ const _lut = [ '00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '0a', '0b', '0c', '0d', '0e', '0f', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '1a', '1b', '1c', '1d', '1e', '1f', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '2a', '2b', '2c', '2d', '2e', '2f', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '3a', '3b', '3c', '3d', '3e', '3f', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '4a', '4b', '4c', '4d', '4e', '4f', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '5a', '5b', '5c', '5d', '5e', '5f', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '6a', '6b', '6c', '6d', '6e', '6f', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '7a', '7b', '7c', '7d', '7e', '7f', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '8a', '8b', '8c', '8d', '8e', '8f', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '9a', '9b', '9c', '9d', '9e', '9f', 'a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9', 'aa', 'ab', 'ac', 'ad', 'ae', 'af', 'b0', 'b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8', 'b9', 'ba', 'bb', 'bc', 'bd', 'be', 'bf', 'c0', 'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'ca', 'cb', 'cc', 'cd', 'ce', 'cf', 'd0', 'd1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8', 'd9', 'da', 'db', 'dc', 'dd', 'de', 'df', 'e0', 'e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7', 'e8', 'e9', 'ea', 'eb', 'ec', 'ed', 'ee', 'ef', 'f0', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'fa', 'fb', 'fc', 'fd', 'fe', 'ff' ];

/**
* @class
* @classdesc A collection of math utility functions.
* @hideconstructor
*/
const MathUtils = {
DEG2RAD: DEG2RAD,
RAD2DEG: RAD2DEG,
/**
* Generate a [UUID]{@link https://en.wikipedia.org/wiki/Universally_unique_identifier}
* (universally unique identifier).
*
* @static
* @method
* @return {string} The UUID.
*/
generateUUID: generateUUID,
/**
* Clamps the given value between min and max.
*
* @static
* @method
* @param {number} value - The value to clamp.
* @param {number} min - The min value.
* @param {number} max - The max value.
* @return {number} The clamped value.
*/
clamp: clamp,
/**
* Computes the Euclidean modulo of the given parameters that
* is `( ( n % m ) + m ) % m`.
*
* @static
* @method
* @param {number} n - The first parameter.
* @param {number} m - The second parameter.
* @return {number} The Euclidean modulo.
*/
euclideanModulo: euclideanModulo,
/**
* Performs a linear mapping from range `<a1, a2>` to range `<b1, b2>`
* for the given value.
*
* @static
* @method
* @param {number} x - The value to be mapped.
* @param {number} a1 - Minimum value for range A.
* @param {number} a2 - Maximum value for range A.
* @param {number} b1 - Minimum value for range B.
* @param {number} b2 - Maximum value for range B.
* @return {number} The mapped value.
*/
mapLinear: mapLinear,
/**
* Returns the percentage in the closed interval `[0, 1]` of the given value
* between the start and end point.
*
* @static
* @method
* @param {number} x - The start point
* @param {number} y - The end point.
* @param {number} value - A value between start and end.
* @return {number} The interpolation factor.
*/
inverseLerp: inverseLerp,
/**
* Returns a value linearly interpolated from two known points based on the given interval -
* `t = 0` will return `x` and `t = 1` will return `y`.
*
* @static
* @method
* @param {number} x - The start point
* @param {number} y - The end point.
* @param {number} t - The interpolation factor in the closed interval `[0, 1]`.
* @return {number} The interpolated value.
*/
lerp: lerp,
/**
* Smoothly interpolate a number from `x` to `y` in a spring-like manner using a delta
* time to maintain frame rate independent movement. For details, see
* [Frame rate independent damping using lerp]{@link http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/}.
*
* @static
* @method
* @param {number} x - The current point.
* @param {number} y - The target point.
* @param {number} lambda - A higher lambda value will make the movement more sudden,
* and a lower value will make the movement more gradual.
* @param {number} dt - Delta time in seconds.
* @return {number} The interpolated value.
*/
damp: damp,
/**
* Returns a value that alternates between `0` and the given `length` parameter.
*
* @static
* @method
* @param {number} x - The value to pingpong.
* @param {number} [length=1] - The positive value the function will pingpong to.
* @return {number} The alternated value.
*/
pingpong: pingpong,
/**
* Returns a value in the range `[0,1]` that represents the percentage that `x` has
* moved between `min` and `max`, but smoothed or slowed down the closer `x` is to
* the `min` and `max`.
*
* See [Smoothstep]{@link http://en.wikipedia.org/wiki/Smoothstep} for more details.
*
* @static
* @method
* @param {number} x - The value to evaluate based on its position between min and max.
* @param {number} min - The min value. Any x value below min will be `0`.
* @param {number} max - The max value. Any x value above max will be `1`.
* @return {number} The alternated value.
*/
smoothstep: smoothstep,
/**
* A [variation on smoothstep]{@link https://en.wikipedia.org/wiki/Smoothstep#Variations}
* that has zero 1st and 2nd order derivatives at x=0 and x=1.
*
* @static
* @method
* @param {number} x - The value to evaluate based on its position between min and max.
* @param {number} min - The min value. Any x value below min will be `0`.
* @param {number} max - The max value. Any x value above max will be `1`.
* @return {number} The alternated value.
*/
smootherstep: smootherstep,
/**
* Returns a random integer from `<low, high>` interval.
*
* @static
* @method
* @param {number} low - The lower value boundary.
* @param {number} high - The upper value boundary
* @return {number} A random integer.
*/
randInt: randInt,
/**
* Returns a random float from `<low, high>` interval.
*
* @static
* @method
* @param {number} low - The lower value boundary.
* @param {number} high - The upper value boundary
* @return {number} A random float.
*/
randFloat: randFloat,
/**
* Returns a random integer from `<-range/2, range/2>` interval.
*
* @static
* @method
* @param {number} range - Defines the value range.
* @return {number} A random float.
*/
randFloatSpread: randFloatSpread,
/**
* Returns a deterministic pseudo-random float in the interval `[0, 1]`.
*
* @static
* @method
* @param {number} [s] - The integer seed.
* @return {number} A random float.
*/
seededRandom: seededRandom,
/**
* Converts degrees to radians.
*
* @static
* @method
* @param {number} degrees - A value in degrees.
* @return {number} The converted value in radians.
*/
degToRad: degToRad,
/**
* Converts radians to degrees.
*
* @static
* @method
* @param {number} radians - A value in radians.
* @return {number} The converted value in degrees.
*/
radToDeg: radToDeg,
/**
* Returns `true` if the given number is a power of two.
*
* @static
* @method
* @param {number} value - The value to check.
* @return {boolean} Whether the given number is a power of two or not.
*/
isPowerOfTwo: isPowerOfTwo,
/**
* Returns the smallest power of two that is greater than or equal to the given number.
*
* @static
* @method
* @param {number} value - The value to find a POT for.
* @return {number} The smallest power of two that is greater than or equal to the given number.
*/
ceilPowerOfTwo: ceilPowerOfTwo,
/**
* Returns the largest power of two that is less than or equal to the given number.
*
* @static
* @method
* @param {number} value - The value to find a POT for.
* @return {number} The largest power of two that is less than or equal to the given number.
*/
floorPowerOfTwo: floorPowerOfTwo,
/**
* Sets the given quaternion from the [Intrinsic Proper Euler Angles]{@link https://en.wikipedia.org/wiki/Euler_angles}
* defined by the given angles and order.
*
* Rotations are applied to the axes in the order specified by order:
* rotation by angle `a` is applied first, then by angle `b`, then by angle `c`.
*
* @static
* @method
* @param {Quaternion} q - The quaternion to set.
* @param {number} a - The rotation applied to the first axis, in radians.
* @param {number} b - The rotation applied to the second axis, in radians.
* @param {number} c - The rotation applied to the third axis, in radians.
* @param {('XYX'|'XZX'|'YXY'|'YZY'|'ZXZ'|'ZYZ')} order - A string specifying the axes order.
*/
setQuaternionFromProperEuler: setQuaternionFromProperEuler,
/**
* Normalizes the given value according to the given typed array.
*
* @static
* @method
* @param {number} value - The float value in the range `[0,1]` to normalize.
* @param {TypedArray} array - The typed array that defines the data type of the value.
* @return {number} The normalize value.
*/
normalize: normalize,
/**
* Denormalizes the given value according to the given typed array.
*
* @static
* @method
* @param {number} value - The value to denormalize.
* @param {TypedArray} array - The typed array that defines the data type of the value.
* @return {number} The denormalize (float) value in the range `[0,1]`.
*/
denormalize: denormalize

@@ -499,0 +722,0 @@ };

@@ -77,4 +77,4 @@ import Node from '../core/Node.js';

const size = int( textureSize( textureLoad( this.batchMesh._indirectTexture ), 0 ) );
const x = int( id ).modInt( size );
const size = int( textureSize( textureLoad( this.batchMesh._indirectTexture ), 0 ).x );
const x = int( id ).mod( size );
const y = int( id ).div( size );

@@ -95,7 +95,7 @@ return textureLoad( this.batchMesh._indirectTexture, ivec2( x, y ) ).x;

const size = textureSize( textureLoad( matricesTexture ), 0 );
const size = int( textureSize( textureLoad( matricesTexture ), 0 ).x );
const j = float( indirectId ).mul( 4 ).toInt().toVar();
const x = j.modInt( size );
const y = j.div( int( size ) );
const x = j.mod( size );
const y = j.div( size );
const batchingMatrix = mat4(

@@ -115,5 +115,5 @@ textureLoad( matricesTexture, ivec2( x, y ) ),

const size = textureSize( textureLoad( colorsTexture ), 0 ).x;
const size = int( textureSize( textureLoad( colorsTexture ), 0 ).x );
const j = id;
const x = j.modInt( size );
const x = j.mod( size );
const y = j.div( size );

@@ -166,2 +166,2 @@ return textureLoad( colorsTexture, ivec2( x, y ) ).rgb;

*/
export const batch = /*@__PURE__*/ nodeProxy( BatchNode );
export const batch = /*@__PURE__*/ nodeProxy( BatchNode ).setParameterLength( 1 );

@@ -63,2 +63,2 @@ import Node from '../core/Node.js';

*/
export const builtin = nodeProxy( BuiltinNode );
export const builtin = nodeProxy( BuiltinNode ).setParameterLength( 1 );

@@ -141,2 +141,2 @@ import TextureNode from './TextureNode.js';

*/
export const cubeTexture = /*@__PURE__*/ nodeProxy( CubeTextureNode );
export const cubeTexture = /*@__PURE__*/ nodeProxy( CubeTextureNode ).setParameterLength( 1, 4 ).setName( 'cubeTexture' );

@@ -50,2 +50,2 @@ import InstanceNode from './InstanceNode.js';

*/
export const instancedMesh = /*@__PURE__*/ nodeProxy( InstancedMeshNode );
export const instancedMesh = /*@__PURE__*/ nodeProxy( InstancedMeshNode ).setParameterLength( 1 );

@@ -66,3 +66,3 @@ import Node from '../core/Node.js';

*
* @type {Node}
* @type {?Node}
*/

@@ -74,3 +74,3 @@ this.instanceMatrixNode = null;

*
* @type {Node}
* @type {?Node}
*/

@@ -91,3 +91,3 @@ this.instanceColorNode = null;

*
* @type {InstancedInterleavedBuffer}
* @type {?InstancedInterleavedBuffer}
*/

@@ -99,3 +99,3 @@ this.buffer = null;

*
* @type {InstancedBufferAttribute}
* @type {?InstancedBufferAttribute}
*/

@@ -227,2 +227,2 @@ this.bufferColor = null;

*/
export const instance = /*@__PURE__*/ nodeProxy( InstanceNode );
export const instance = /*@__PURE__*/ nodeProxy( InstanceNode ).setParameterLength( 3 );
import Node from '../core/Node.js';
import { NodeUpdateType } from '../core/constants.js';
import { float, nodeProxy, Fn, ivec2, int } from '../tsl/TSLBase.js';
import { float, nodeProxy, Fn, ivec2, int, If } from '../tsl/TSLBase.js';
import { uniform } from '../core/UniformNode.js';

@@ -27,3 +27,3 @@ import { reference } from './ReferenceNode.js';

const bufferAttrib = textureLoad( bufferMap, ivec2( x, y ) ).depth( depth );
const bufferAttrib = textureLoad( bufferMap, ivec2( x, y ) ).depth( depth ).xyz;

@@ -244,28 +244,32 @@ return bufferAttrib.mul( influence );

if ( hasMorphPosition === true ) {
If( influence.notEqual( 0 ), () => {
positionLocal.addAssign( getMorph( {
bufferMap,
influence,
stride,
width,
depth: i,
offset: int( 0 )
} ) );
if ( hasMorphPosition === true ) {
}
positionLocal.addAssign( getMorph( {
bufferMap,
influence,
stride,
width,
depth: i,
offset: int( 0 )
} ) );
if ( hasMorphNormals === true ) {
}
normalLocal.addAssign( getMorph( {
bufferMap,
influence,
stride,
width,
depth: i,
offset: int( 1 )
} ) );
if ( hasMorphNormals === true ) {
}
normalLocal.addAssign( getMorph( {
bufferMap,
influence,
stride,
width,
depth: i,
offset: int( 1 )
} ) );
}
} );
} );

@@ -308,2 +312,2 @@

*/
export const morphReference = /*@__PURE__*/ nodeProxy( MorphNode );
export const morphReference = /*@__PURE__*/ nodeProxy( MorphNode ).setParameterLength( 1 );

@@ -26,3 +26,3 @@ import { attribute } from '../core/AttributeNode.js';

console.warn( 'TSL.NormalNode: Vertex attribute "normal" not found on geometry.' );
console.warn( 'THREE.TSL: Vertex attribute "normal" not found on geometry.' );

@@ -29,0 +29,0 @@ return vec3( 0, 1, 0 );

@@ -216,6 +216,6 @@ import Node from '../core/Node.js';

* @function
* @param {?Object3D} [object3d=null] - The 3D object.
* @param {?Object3D} [object3d] - The 3D object.
* @returns {Object3DNode<vec3>}
*/
export const objectDirection = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.DIRECTION );
export const objectDirection = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.DIRECTION ).setParameterLength( 1 );

@@ -227,6 +227,6 @@ /**

* @function
* @param {?Object3D} [object3d=null] - The 3D object.
* @param {?Object3D} [object3d] - The 3D object.
* @returns {Object3DNode<mat4>}
*/
export const objectWorldMatrix = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.WORLD_MATRIX );
export const objectWorldMatrix = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.WORLD_MATRIX ).setParameterLength( 1 );

@@ -238,6 +238,6 @@ /**

* @function
* @param {?Object3D} [object3d=null] - The 3D object.
* @param {?Object3D} [object3d] - The 3D object.
* @returns {Object3DNode<vec3>}
*/
export const objectPosition = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.POSITION );
export const objectPosition = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.POSITION ).setParameterLength( 1 );

@@ -249,6 +249,6 @@ /**

* @function
* @param {?Object3D} [object3d=null] - The 3D object.
* @param {?Object3D} [object3d] - The 3D object.
* @returns {Object3DNode<vec3>}
*/
export const objectScale = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.SCALE );
export const objectScale = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.SCALE ).setParameterLength( 1 );

@@ -260,6 +260,6 @@ /**

* @function
* @param {?Object3D} [object3d=null] - The 3D object.
* @param {?Object3D} [object3d] - The 3D object.
* @returns {Object3DNode<vec3>}
*/
export const objectViewPosition = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.VIEW_POSITION );
export const objectViewPosition = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.VIEW_POSITION ).setParameterLength( 1 );

@@ -271,5 +271,5 @@ /**

* @function
* @param {?Object3D} [object3d=null] - The 3D object.
* @param {?Object3D} [object3d] - The 3D object.
* @returns {Object3DNode<vec3>}
*/
export const objectRadius = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.RADIUS );
export const objectRadius = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.RADIUS ).setParameterLength( 1 );

@@ -27,3 +27,3 @@ import Node from '../core/Node.js';

*
* @param {?ReferenceBaseNode} referenceNode - The reference node.
* @param {ReferenceBaseNode} referenceNode - The reference node.
* @param {Node} indexNode - The index node that defines the element access.

@@ -355,5 +355,5 @@ */

* @param {number} count - The number of value inside the array-like object.
* @param {Object} object - An array-like object the property belongs to.
* @param {Object} [object] - An array-like object the property belongs to.
* @returns {ReferenceBaseNode}
*/
export const referenceBuffer = ( name, type, count, object ) => nodeObject( new ReferenceBaseNode( name, type, object, count ) );

@@ -391,3 +391,3 @@ import Node from '../core/Node.js';

* @param {string} type - The uniform type that should be used to represent the property value.
* @param {?Object} object - The object the property belongs to.
* @param {?Object} [object] - The object the property belongs to.
* @returns {ReferenceNode}

@@ -394,0 +394,0 @@ */

@@ -13,2 +13,5 @@ import Node from '../core/Node.js';

import { getDataFromObject } from '../core/NodeUtils.js';
import { storage } from './StorageBufferNode.js';
import { InstancedBufferAttribute } from '../../core/InstancedBufferAttribute.js';
import { instanceIndex } from '../core/IndexNode.js';

@@ -35,5 +38,4 @@ const _frameId = new WeakMap();

* @param {SkinnedMesh} skinnedMesh - The skinned mesh.
* @param {boolean} [useReference=false] - Whether to use reference nodes for internal skinned mesh related data or not.
*/
constructor( skinnedMesh, useReference = false ) {
constructor( skinnedMesh ) {

@@ -50,10 +52,2 @@ super( 'void' );

/**
* Whether to use reference nodes for internal skinned mesh related data or not.
* TODO: Explain the purpose of the property.
*
* @type {boolean}
*/
this.useReference = useReference;
/**
* The update type overwritten since skinning nodes are updated per object.

@@ -81,18 +75,2 @@ *

let bindMatrixNode, bindMatrixInverseNode, boneMatricesNode;
if ( useReference ) {
bindMatrixNode = reference( 'bindMatrix', 'mat4' );
bindMatrixInverseNode = reference( 'bindMatrixInverse', 'mat4' );
boneMatricesNode = referenceBuffer( 'skeleton.boneMatrices', 'mat4', skinnedMesh.skeleton.bones.length );
} else {
bindMatrixNode = uniform( skinnedMesh.bindMatrix, 'mat4' );
bindMatrixInverseNode = uniform( skinnedMesh.bindMatrixInverse, 'mat4' );
boneMatricesNode = buffer( skinnedMesh.skeleton.boneMatrices, 'mat4', skinnedMesh.skeleton.bones.length );
}
/**

@@ -103,3 +81,3 @@ * The bind matrix node.

*/
this.bindMatrixNode = bindMatrixNode;
this.bindMatrixNode = reference( 'bindMatrix', 'mat4' );

@@ -111,3 +89,3 @@ /**

*/
this.bindMatrixInverseNode = bindMatrixInverseNode;
this.bindMatrixInverseNode = reference( 'bindMatrixInverse', 'mat4' );

@@ -119,5 +97,19 @@ /**

*/
this.boneMatricesNode = boneMatricesNode;
this.boneMatricesNode = referenceBuffer( 'skeleton.boneMatrices', 'mat4', skinnedMesh.skeleton.bones.length );
/**
* The current vertex position in local space.
*
* @type {Node<vec3>}
*/
this.positionNode = positionLocal;
/**
* The result of vertex position in local space.
*
* @type {Node<vec3>}
*/
this.toPositionNode = positionLocal;
/**
* The previous bind matrices as a uniform buffer node.

@@ -137,6 +129,6 @@ * Required for computing motion vectors.

* @param {Node} [boneMatrices=this.boneMatricesNode] - The bone matrices
* @param {Node<vec3>} [position=positionLocal] - The vertex position in local space.
* @param {Node<vec3>} [position=this.positionNode] - The vertex position in local space.
* @return {Node<vec3>} The transformed vertex position.
*/
getSkinnedPosition( boneMatrices = this.boneMatricesNode, position = positionLocal ) {
getSkinnedPosition( boneMatrices = this.boneMatricesNode, position = this.positionNode ) {

@@ -236,2 +228,3 @@ const { skinIndexNode, skinWeightNode, bindMatrixNode, bindMatrixInverseNode } = this;

* @param {NodeBuilder} builder - The current node builder.
* @return {Node<vec3>} The transformed vertex position.
*/

@@ -248,4 +241,5 @@ setup( builder ) {

if ( this.toPositionNode ) this.toPositionNode.assign( skinPosition );
positionLocal.assign( skinPosition );
//

@@ -266,2 +260,4 @@ if ( builder.hasGeometryAttribute( 'normal' ) ) {

return skinPosition;
}

@@ -280,3 +276,3 @@

return positionLocal.build( builder, output );
return super.generate( builder, output );

@@ -294,4 +290,3 @@ }

const object = this.useReference ? frame.object : this.skinnedMesh;
const skeleton = object.skeleton;
const skeleton = frame.object && frame.object.skeleton ? frame.object.skeleton : this.skinnedMesh.skeleton;

@@ -323,3 +318,3 @@ if ( _frameId.get( skeleton ) === frame.frameId ) return;

/**
* TSL function for creating a skinning node with reference usage.
* TSL function for computing skinning.
*

@@ -329,4 +324,18 @@ * @tsl

* @param {SkinnedMesh} skinnedMesh - The skinned mesh.
* @param {Node<vec3>} [toPosition=null] - The target position.
* @returns {SkinningNode}
*/
export const skinningReference = ( skinnedMesh ) => nodeObject( new SkinningNode( skinnedMesh, true ) );
export const computeSkinning = ( skinnedMesh, toPosition = null ) => {
const node = new SkinningNode( skinnedMesh );
node.positionNode = storage( new InstancedBufferAttribute( skinnedMesh.geometry.getAttribute( 'position' ).array, 3 ), 'vec3' ).setPBO( true ).toReadOnly().element( instanceIndex ).toVar();
node.skinIndexNode = storage( new InstancedBufferAttribute( new Uint32Array( skinnedMesh.geometry.getAttribute( 'skinIndex' ).array ), 4 ), 'uvec4' ).setPBO( true ).toReadOnly().element( instanceIndex ).toVar();
node.skinWeightNode = storage( new InstancedBufferAttribute( skinnedMesh.geometry.getAttribute( 'skinWeight' ).array, 4 ), 'vec4' ).setPBO( true ).toReadOnly().element( instanceIndex ).toVar();
node.bindMatrixNode = uniform( skinnedMesh.bindMatrix, 'mat4' );
node.bindMatrixInverseNode = uniform( skinnedMesh.bindMatrixInverse, 'mat4' );
node.boneMatricesNode = buffer( skinnedMesh.skeleton.boneMatrices, 'mat4', skinnedMesh.skeleton.bones.length );
node.toPositionNode = toPosition;
return nodeObject( node );
};

@@ -89,3 +89,3 @@ import BufferNode from './BufferNode.js';

*
* @type {?structTypeNode}
* @type {?StructTypeNode}
* @default null

@@ -92,0 +92,0 @@ */

@@ -14,3 +14,3 @@ import TextureNode from './TextureNode.js';

*
* const posX = instanceIndex.modInt( width );
* const posX = instanceIndex.mod( width );
* const posY = instanceIndex.div( width );

@@ -207,7 +207,7 @@ * const indexUV = uvec2( posX, posY );

* @param {StorageTexture} value - The storage texture.
* @param {Node<vec2|vec3>} uvNode - The uv node.
* @param {?Node<vec2|vec3>} uvNode - The uv node.
* @param {?Node} [storeNode=null] - The value node that should be stored in the texture.
* @returns {StorageTextureNode}
*/
export const storageTexture = /*@__PURE__*/ nodeProxy( StorageTextureNode );
export const storageTexture = /*@__PURE__*/ nodeProxy( StorageTextureNode ).setParameterLength( 1, 3 );

@@ -214,0 +214,0 @@

@@ -186,2 +186,2 @@ import TextureNode from './TextureNode.js';

*/
export const texture3D = /*@__PURE__*/ nodeProxy( Texture3DNode );
export const texture3D = /*@__PURE__*/ nodeProxy( Texture3DNode ).setParameterLength( 1, 3 );

@@ -10,3 +10,3 @@ import UniformNode, { uniform } from '../core/UniformNode.js';

import { IntType, UnsignedIntType } from '../../constants.js';
import { IntType, NearestFilter, UnsignedIntType } from '../../constants.js';

@@ -443,3 +443,3 @@ /**

if ( output === 'sampler' ) {
if ( /^sampler/.test( output ) ) {

@@ -567,2 +567,12 @@ return textureProperty + '_sampler';

const map = textureNode.value;
if ( map && map.generateMipmaps === false || map.minFilter === NearestFilter || map.magFilter === NearestFilter ) {
console.warn( 'THREE.TSL: texture().blur() requires mipmaps and sampling. Use .generateMipmaps=true and .minFilter/.magFilter=THREE.LinearFilter in the Texture.' );
textureNode.biasNode = null;
}
return nodeObject( textureNode );

@@ -736,3 +746,3 @@

*/
export const texture = /*@__PURE__*/ nodeProxy( TextureNode );
export const texture = /*@__PURE__*/ nodeProxy( TextureNode ).setParameterLength( 1, 4 );

@@ -759,5 +769,15 @@ /**

* @function
* @param {TextureNode|Texture} aTexture - The texture or texture node to convert.
* @param {TextureNode|Texture} value - The texture or texture node to convert.
* @returns {Node}
*/
export const sampler = ( aTexture ) => ( aTexture.isNode === true ? aTexture : texture( aTexture ) ).convert( 'sampler' );
export const sampler = ( value ) => ( value.isNode === true ? value : texture( value ) ).convert( 'sampler' );
/**
* Converts a texture or texture node to a sampler comparison.
*
* @tsl
* @function
* @param {TextureNode|Texture} value - The texture or texture node to convert.
* @returns {Node}
*/
export const samplerComparison = ( value ) => ( value.isNode === true ? value : texture( value ) ).convert( 'samplerComparison' );

@@ -77,2 +77,2 @@ import Node from '../core/Node.js';

*/
export const textureSize = /*@__PURE__*/ nodeProxy( TextureSizeNode );
export const textureSize = /*@__PURE__*/ nodeProxy( TextureSizeNode ).setParameterLength( 1, 2 );

@@ -345,3 +345,3 @@ import { nodeObject } from '../tsl/TSLBase.js';

* @param {Array<any>} values - Array-like data.
* @param {?string} nodeType - The data type of the array elements.
* @param {?string} [nodeType] - The data type of the array elements.
* @returns {UniformArrayNode}

@@ -362,5 +362,5 @@ */

console.warn( 'TSL.UniformArrayNode: uniforms() has been renamed to uniformArray().' );
console.warn( 'THREE.TSL: uniforms() has been renamed to uniformArray().' );
return nodeObject( new UniformArrayNode( values, nodeType ) );
};

@@ -146,8 +146,8 @@ import Node from '../core/Node.js';

* @function
* @param {string} [code=''] - The native code.
* @param {Array<Node>} [includes=[]] - An array of includes.
* @param {('js'|'wgsl'|'glsl')} [language=''] - The used language.
* @param {string} [code] - The native code.
* @param {?Array<Node>} [includes=[]] - An array of includes.
* @param {?('js'|'wgsl'|'glsl')} [language=''] - The used language.
* @returns {CodeNode}
*/
export const code = /*@__PURE__*/ nodeProxy( CodeNode );
export const code = /*@__PURE__*/ nodeProxy( CodeNode ).setParameterLength( 1, 3 );

@@ -154,0 +154,0 @@ /**

@@ -49,3 +49,3 @@ import Node from '../core/Node.js';

return builder.format( `( ${ snippet } )`, type, output );
return builder.format( snippet, type, output );

@@ -65,6 +65,6 @@ }

* @function
* @param {string} [snippet=''] - The native code snippet.
* @param {string} [nodeType='void'] - The node type.
* @param {string} [snippet] - The native code snippet.
* @param {?string} [nodeType='void'] - The node type.
* @returns {ExpressionNode}
*/
export const expression = /*@__PURE__*/ nodeProxy( ExpressionNode );
export const expression = /*@__PURE__*/ nodeProxy( ExpressionNode ).setParameterLength( 1, 2 );
import TempNode from '../core/TempNode.js';
import { addMethodChaining, nodeArray, nodeObject, nodeObjects } from '../tsl/TSLCore.js';
import { addMethodChaining, nodeArray, nodeObject, nodeObjects, float } from '../tsl/TSLCore.js';

@@ -103,2 +103,20 @@ /**

if ( parameters.length > inputs.length ) {
console.error( 'THREE.TSL: The number of provided parameters exceeds the expected number of inputs in \'Fn()\'.' );
parameters.length = inputs.length;
} else if ( parameters.length < inputs.length ) {
console.error( 'THREE.TSL: The number of provided parameters is less than the expected number of inputs in \'Fn()\'.' );
while ( parameters.length < inputs.length ) {
parameters.push( float( 0 ) );
}
}
for ( let i = 0; i < parameters.length; i ++ ) {

@@ -122,4 +140,6 @@

throw new Error( `FunctionCallNode: Input '${inputNode.name}' not found in FunctionNode.` );
console.error( `THREE.TSL: Input '${ inputNode.name }' not found in \'Fn()\'.` );
params.push( generateInput( float( 0 ), inputNode ) );
}

@@ -133,3 +153,3 @@

return `${functionName}( ${params.join( ', ' )} )`;
return `${ functionName }( ${ params.join( ', ' ) } )`;

@@ -136,0 +156,0 @@ }

@@ -144,3 +144,3 @@ import Node from '../core/Node.js';

this._local = new Resources();
this._output = scriptableValue();
this._output = scriptableValue( null );
this._outputs = {};

@@ -723,6 +723,6 @@ this._source = this.source;

* @function
* @param {?CodeNode} [codeNode=null] - The code node.
* @param {Object} [parameters={}] - The parameters definition.
* @param {CodeNode} [codeNode] - The code node.
* @param {?Object} [parameters={}] - The parameters definition.
* @returns {ScriptableNode}
*/
export const scriptable = /*@__PURE__*/ nodeProxy( ScriptableNode );
export const scriptable = /*@__PURE__*/ nodeProxy( ScriptableNode ).setParameterLength( 1, 2 );

@@ -250,5 +250,5 @@ import Node from '../core/Node.js';

* @function
* @param {any} [value=null] - The value.
* @param {any} [value] - The value.
* @returns {ScriptableValueNode}
*/
export const scriptableValue = /*@__PURE__*/ nodeProxy( ScriptableValueNode );
export const scriptableValue = /*@__PURE__*/ nodeProxy( ScriptableValueNode ).setParameterLength( 1 );

@@ -174,4 +174,4 @@ import TempNode from '../core/TempNode.js';

*/
export const assign = /*@__PURE__*/ nodeProxy( AssignNode );
export const assign = /*@__PURE__*/ nodeProxy( AssignNode ).setParameterLength( 2 );
addMethodChaining( 'assign', assign );

@@ -164,5 +164,5 @@ import Node from './Node.js';

* @param {string} name - The name of the attribute.
* @param {?string} nodeType - The node type.
* @param {string} [nodeType] - The node type.
* @returns {AttributeNode}
*/
export const attribute = ( name, nodeType ) => nodeObject( new AttributeNode( name, nodeType ) );

@@ -91,4 +91,4 @@ import Node from './Node.js';

*/
export const bypass = /*@__PURE__*/ nodeProxy( BypassNode );
export const bypass = /*@__PURE__*/ nodeProxy( BypassNode ).setParameterLength( 2 );
addMethodChaining( 'bypass', bypass );

@@ -95,3 +95,3 @@ import Node from './Node.js';

* @param {Node} node - The node that should be cached.
* @param {boolean} parent - Whether this node refers to a shared parent cache or not.
* @param {boolean} [parent] - Whether this node refers to a shared parent cache or not.
* @returns {CacheNode}

@@ -98,0 +98,0 @@ */

@@ -128,3 +128,3 @@ import Node from './Node.js';

*/
export const context = /*@__PURE__*/ nodeProxy( ContextNode );
export const context = /*@__PURE__*/ nodeProxy( ContextNode ).setParameterLength( 1, 2 );

@@ -131,0 +131,0 @@ /**

@@ -20,3 +20,3 @@ import Node from './Node.js';

*
* @param {any} value - The value of this node. This can be a any JS primitive, functions, array buffers or even three.js objects (vector, matrices, colors).
* @param {any} value - The value of this node. This can be any JS primitive, functions, array buffers or even three.js objects (vector, matrices, colors).
* @param {?string} nodeType - The node type. If no explicit type is defined, the node tries to derive the type from its value.

@@ -38,3 +38,3 @@ */

/**
* The value of this node. This can be a any JS primitive, functions, array buffers or even three.js objects (vector, matrices, colors).
* The value of this node. This can be any JS primitive, functions, array buffers or even three.js objects (vector, matrices, colors).
*

@@ -41,0 +41,0 @@ * @type {any}

@@ -677,6 +677,18 @@ import { NodeUpdateType } from './constants.js';

result = this.generate( builder ) || '';
if ( nodeData.generated === undefined ) {
nodeData.snippet = result;
nodeData.generated = true;
result = this.generate( builder ) || '';
nodeData.snippet = result;
} else {
console.warn( 'THREE.Node: Recursion detected.', this );
result = '';
}
} else if ( nodeData.flowCodes !== undefined && builder.context.nodeBlock !== undefined ) {

@@ -683,0 +695,0 @@

@@ -317,4 +317,6 @@ import NodeUniform from './NodeUniform.js';

* The variables are maintained in an array for each shader stage.
* This dictionary is also used to count the number of variables
* according to their type (const, vars).
*
* @type {Object<string,Array<NodeVar>>}
* @type {Object<string,Array<NodeVar>|number>}
*/

@@ -324,2 +326,9 @@ this.vars = {};

/**
* This dictionary holds the declarations for each shader stage.
*
* @type {Object}
*/
this.declarations = {};
/**
* Current code flow.

@@ -415,10 +424,2 @@ * All code generated in this stack will be stored in `.flow`.

/**
* Whether comparison in shader code are generated with methods or not.
*
* @type {boolean}
* @default false
*/
this.useComparisonMethod = false;
}

@@ -952,3 +953,3 @@

* @abstract
* @return {string} The drawIndex shader string.
* @return {?string} The drawIndex shader string.
*/

@@ -1239,2 +1240,4 @@ getDrawIndex() {

this.registerDeclaration( attribute );
attributes.push( attribute );

@@ -1291,3 +1294,3 @@

return type === 'void' || type === 'property' || type === 'sampler' || type === 'texture' || type === 'cubeTexture' || type === 'storageTexture' || type === 'depthTexture' || type === 'texture3D';
return type === 'void' || type === 'property' || type === 'sampler' || type === 'samplerComparison' || type === 'texture' || type === 'cubeTexture' || type === 'storageTexture' || type === 'depthTexture' || type === 'texture3D';

@@ -1423,2 +1426,14 @@ }

/**
* Returns the type is an integer type.
*
* @param {string} type - The type.
* @return {boolean} Whether the type is an integer type or not.
*/
isInteger( type ) {
return /int|uint|(i|u)vec/.test( type );
}
/**
* Returns the type for a given buffer attribute.

@@ -1692,2 +1707,4 @@ *

this.registerDeclaration( nodeUniform );
nodeData.uniform = nodeUniform;

@@ -1762,2 +1779,4 @@

this.registerDeclaration( nodeVar );
nodeData.variable = nodeVar;

@@ -1843,2 +1862,4 @@

this.registerDeclaration( nodeVarying );
nodeData.varying = nodeVarying;

@@ -1853,2 +1874,37 @@

/**
* Registers a node declaration in the current shader stage.
*
* @param {Object} node - The node to be registered.
*/
registerDeclaration( node ) {
const shaderStage = this.shaderStage;
const declarations = this.declarations[ shaderStage ] || ( this.declarations[ shaderStage ] = {} );
const property = this.getPropertyName( node );
let index = 1;
let name = property;
// Automatically renames the property if the name is already in use.
while ( declarations[ name ] !== undefined ) {
name = property + '_' + index ++;
}
declarations[ name ] = node;
if ( index > 1 ) {
node.name = name;
console.warn( `THREE.TSL: Declaration name '${ property }' of '${ node.type }' already in use. Renamed to '${ name }'.` );
}
}
/**
* Returns an instance of {@link NodeCode} for the given code node.

@@ -2140,2 +2196,3 @@ *

const previousVars = this.vars;
const previousDeclarations = this.declarations;
const previousCache = this.cache;

@@ -2151,2 +2208,3 @@ const previousBuildStage = this.buildStage;

this.vars = {};
this.declarations = {};
this.cache = new NodeCache();

@@ -2167,2 +2225,3 @@ this.stack = stack();

this.vars = previousVars;
this.declarations = previousDeclarations;
this.cache = previousCache;

@@ -2183,3 +2242,3 @@ this.stack = previousStack;

* @param {string} op - The operator name to resolve.
* @return {string} The resolved operator name.
* @return {?string} The resolved operator name.
*/

@@ -2193,2 +2252,15 @@ getFunctionOperator( /* op */ ) {

/**
* Builds the given shader node.
*
* @abstract
* @param {ShaderNodeInternal} shaderNode - The shader node.
* @return {string} The function code.
*/
buildFunctionCode( /* shaderNode */ ) {
console.warn( 'Abstract function.' );
}
/**
* Generates a code flow based on a child Node.

@@ -2561,3 +2633,3 @@ *

return `${ this.getType( toType ) }(${ snippet }[0].xyz, ${ snippet }[1].xyz, ${ snippet }[2].xyz)`;
return `${ this.getType( toType ) }( ${ snippet }[ 0 ].xyz, ${ snippet }[ 1 ].xyz, ${ snippet }[ 2 ].xyz )`;

@@ -2568,3 +2640,3 @@ }

return `${ this.getType( toType ) }(${ snippet }[0].xy, ${ snippet }[1].xy)`;
return `${ this.getType( toType ) }( ${ snippet }[ 0 ].xy, ${ snippet }[ 1 ].xy )`;

@@ -2571,0 +2643,0 @@ }

@@ -170,3 +170,3 @@ import Node from './Node.js';

*
* @param {...any} params
* @param {...any} params
* @returns {StackNode}

@@ -176,3 +176,3 @@ */

console.warn( 'TSL.StackNode: .else() has been renamed to .Else().' );
console.warn( 'THREE.TSL: .else() has been renamed to .Else().' );
return this.Else( ...params );

@@ -185,3 +185,3 @@

*
* @param {...any} params
* @param {...any} params
* @returns {StackNode}

@@ -191,3 +191,3 @@ */

console.warn( 'TSL.StackNode: .elseif() has been renamed to .ElseIf().' );
console.warn( 'THREE.TSL: .elseif() has been renamed to .ElseIf().' );
return this.ElseIf( ...params );

@@ -209,2 +209,2 @@

*/
export const stack = /*@__PURE__*/ nodeProxy( StackNode );
export const stack = /*@__PURE__*/ nodeProxy( StackNode ).setParameterLength( 0, 1 );

@@ -78,3 +78,3 @@ import Node from './Node.js';

* @param {Object} membersLayout - The layout of the struct members.
* @param {string} [name=null] - The name of the struct.
* @param {?string} [name=null] - The name of the struct.
* @returns {Function} The struct function.

@@ -81,0 +81,0 @@ */

@@ -49,3 +49,3 @@

* @param {Object} membersLayout - The layout of the members for the struct.
* @param {string} [name=null] - The optional name of the struct.
* @param {?string} [name=null] - The optional name of the struct.
*/

@@ -66,3 +66,3 @@ constructor( membersLayout, name = null ) {

*
* @type {string}
* @type {?string}
* @default null

@@ -69,0 +69,0 @@ */

@@ -26,4 +26,4 @@ import Node from './Node.js';

* @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.
* @param {?string} [name=null] - The name of the variable in the shader.
* @param {boolean} [readOnly=false] - The read-only flag.
*/

@@ -78,8 +78,2 @@ constructor( node, name = null, readOnly = false ) {

getHash( builder ) {
return this.name || super.getHash( builder );
}
getMemberType( builder, name ) {

@@ -86,0 +80,0 @@

@@ -176,3 +176,3 @@ import Node from './Node.js';

*/
export const varying = /*@__PURE__*/ nodeProxy( VaryingNode );
export const varying = /*@__PURE__*/ nodeProxy( VaryingNode ).setParameterLength( 1, 2 );

@@ -196,3 +196,3 @@ /**

console.warn( 'TSL.VaryingNode: .varying() has been renamed to .toVarying().' );
console.warn( 'THREE.TSL: .varying() has been renamed to .toVarying().' );
return varying( ...params );

@@ -204,5 +204,5 @@

console.warn( 'TSL.VaryingNode: .vertexStage() has been renamed to .toVertexStage().' );
console.warn( 'THREE.TSL: .vertexStage() has been renamed to .toVertexStage().' );
return varying( ...params );
} );

@@ -140,3 +140,3 @@ import { Fn, vec4 } from '../tsl/TSLBase.js';

*
* @param {...any} params
* @param {...any} params
* @returns {Function}

@@ -156,3 +156,3 @@ */

*
* @param {...any} params
* @param {...any} params
* @returns {Function}

@@ -172,3 +172,3 @@ */

*
* @param {...any} params
* @param {...any} params
* @returns {Function}

@@ -188,3 +188,3 @@ */

*
* @param {...any} params
* @param {...any} params
* @returns {Function}

@@ -191,0 +191,0 @@ */

@@ -117,2 +117,2 @@ import TempNode from '../core/TempNode.js';

*/
export const bumpMap = /*@__PURE__*/ nodeProxy( BumpMapNode );
export const bumpMap = /*@__PURE__*/ nodeProxy( BumpMapNode ).setParameterLength( 1, 2 );

@@ -148,2 +148,2 @@ import TempNode from '../core/TempNode.js';

*/
export const normalMap = /*@__PURE__*/ nodeProxy( NormalMapNode );
export const normalMap = /*@__PURE__*/ nodeProxy( NormalMapNode ).setParameterLength( 1, 2 );

@@ -65,2 +65,2 @@ import TempNode from '../core/TempNode.js';

*/
export const posterize = /*@__PURE__*/ nodeProxy( PosterizeNode );
export const posterize = /*@__PURE__*/ nodeProxy( PosterizeNode ).setParameterLength( 2 );

@@ -256,3 +256,3 @@ import Node from '../core/Node.js';

console.warn( 'TSL.ViewportNode: "viewportResolution" is deprecated. Use "screenSize" instead.' );
console.warn( 'THREE.TSL: "viewportResolution" is deprecated. Use "screenSize" instead.' );

@@ -270,3 +270,3 @@ return screenSize;

console.warn( 'TSL.ViewportNode: "viewportTopLeft" is deprecated. Use "screenUV" instead.' );
console.warn( 'THREE.TSL: "viewportTopLeft" is deprecated. Use "screenUV" instead.' );

@@ -284,3 +284,3 @@ return screenUV;

console.warn( 'TSL.ViewportNode: "viewportBottomLeft" is deprecated. Use "screenUV.flipY()" instead.' );
console.warn( 'THREE.TSL: "viewportBottomLeft" is deprecated. Use "screenUV.flipY()" instead.' );

@@ -287,0 +287,0 @@ return screenUV.flipY();

@@ -281,6 +281,6 @@ import Node from '../core/Node.js';

* @function
* @param {Node<float>} value - The perspective depth.
* @param {?Node<float>} [value=null] - The perspective depth. If `null` is provided, the current fragment's depth is used.
* @returns {ViewportDepthNode<float>}
*/
export const linearDepth = /*@__PURE__*/ nodeProxy( ViewportDepthNode, ViewportDepthNode.LINEAR_DEPTH );
export const linearDepth = /*@__PURE__*/ nodeProxy( ViewportDepthNode, ViewportDepthNode.LINEAR_DEPTH ).setParameterLength( 0, 1 );

@@ -287,0 +287,0 @@ /**

@@ -51,6 +51,6 @@ import ViewportTextureNode from './ViewportTextureNode.js';

* @function
* @param {Node} [uvNode=screenUV] - The uv node.
* @param {?Node} [uvNode=screenUV] - The uv node.
* @param {?Node} [levelNode=null] - The level node.
* @returns {ViewportDepthTextureNode}
*/
export const viewportDepthTexture = /*@__PURE__*/ nodeProxy( ViewportDepthTextureNode );
export const viewportDepthTexture = /*@__PURE__*/ nodeProxy( ViewportDepthTextureNode ).setParameterLength( 0, 2 );

@@ -57,6 +57,6 @@ import ViewportTextureNode from './ViewportTextureNode.js';

* @function
* @param {Node} [uvNode=screenUV] - The uv node.
* @param {?Node} [uvNode=screenUV] - The uv node.
* @param {?Node} [levelNode=null] - The level node.
* @returns {ViewportSharedTextureNode}
*/
export const viewportSharedTexture = /*@__PURE__*/ nodeProxy( ViewportSharedTextureNode );
export const viewportSharedTexture = /*@__PURE__*/ nodeProxy( ViewportSharedTextureNode ).setParameterLength( 0, 2 );

@@ -121,3 +121,3 @@ import TextureNode from '../accessors/TextureNode.js';

* @function
* @param {Node} [uvNode=screenUV] - The uv node.
* @param {?Node} [uvNode=screenUV] - The uv node.
* @param {?Node} [levelNode=null] - The level node.

@@ -127,3 +127,3 @@ * @param {?Texture} [framebufferTexture=null] - A framebuffer texture holding the viewport data. If not provided, a framebuffer texture is created automatically.

*/
export const viewportTexture = /*@__PURE__*/ nodeProxy( ViewportTextureNode );
export const viewportTexture = /*@__PURE__*/ nodeProxy( ViewportTextureNode ).setParameterLength( 0, 3 );

@@ -135,3 +135,3 @@ /**

* @function
* @param {Node} [uvNode=screenUV] - The uv node.
* @param {?Node} [uvNode=screenUV] - The uv node.
* @param {?Node} [levelNode=null] - The level node.

@@ -141,2 +141,2 @@ * @param {?Texture} [framebufferTexture=null] - A framebuffer texture holding the viewport data. If not provided, a framebuffer texture is created automatically.

*/
export const viewportMipTexture = /*@__PURE__*/ nodeProxy( ViewportTextureNode, null, null, { generateMipmaps: true } );
export const viewportMipTexture = /*@__PURE__*/ nodeProxy( ViewportTextureNode, null, null, { generateMipmaps: true } ).setParameterLength( 0, 3 );

@@ -23,6 +23,6 @@ import { positionWorld } from '../../accessors/Position.js';

const nDir = normalize( normal ).toVar( 'nDir' );
const rbmax = sub( float( 0.5 ).mul( cubeSize.sub( cubePos ) ), positionWorld ).div( nDir ).toVar( 'rbmax' );
const rbmin = sub( float( - 0.5 ).mul( cubeSize.sub( cubePos ) ), positionWorld ).div( nDir ).toVar( 'rbmin' );
const rbminmax = vec3().toVar( 'rbminmax' );
const nDir = normalize( normal ).toVar();
const rbmax = sub( float( 0.5 ).mul( cubeSize.sub( cubePos ) ), positionWorld ).div( nDir ).toVar();
const rbmin = sub( float( - 0.5 ).mul( cubeSize.sub( cubePos ) ), positionWorld ).div( nDir ).toVar();
const rbminmax = vec3().toVar();
rbminmax.x = nDir.x.greaterThan( float( 0 ) ).select( rbmax.x, rbmin.x );

@@ -32,4 +32,4 @@ rbminmax.y = nDir.y.greaterThan( float( 0 ) ).select( rbmax.y, rbmin.y );

const correction = min( min( rbminmax.x, rbminmax.y ), rbminmax.z ).toVar( 'correction' );
const boxIntersection = positionWorld.add( nDir.mul( correction ) ).toVar( 'boxIntersection' );
const correction = min( min( rbminmax.x, rbminmax.y ), rbminmax.z ).toVar();
const boxIntersection = positionWorld.add( nDir.mul( correction ) ).toVar();
return boxIntersection.sub( cubePos );

@@ -36,0 +36,0 @@

@@ -33,5 +33,5 @@ import LightingModel from '../core/LightingModel.js';

*/
direct( { shadowMask } ) {
direct( { lightNode } ) {
this.shadowNode.mulAssign( shadowMask );
this.shadowNode.mulAssign( lightNode.shadowNode );

@@ -43,5 +43,5 @@ }

*
* @param {ContextNode} context - The current node context.
* @param {NodeBuilder} builder - The current node builder.
*/
finish( context ) {
finish( { context } ) {

@@ -48,0 +48,0 @@ diffuseColor.a.mulAssign( this.shadowNode.oneMinus() );

@@ -172,2 +172,2 @@ import Node from '../core/Node.js';

*/
export const range = /*@__PURE__*/ nodeProxy( RangeNode );
export const range = /*@__PURE__*/ nodeProxy( RangeNode ).setParameterLength( 2 );

@@ -29,5 +29,4 @@ import TempNode from '../core/TempNode.js';

* @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 ) {
constructor( method, pointerNode, valueNode ) {

@@ -57,10 +56,2 @@ super( 'uint' );

/**
* A variable storing the return value of an atomic operation, typically the value of the atomic variable before the operation.
*
* @type {?Node}
* @default null
*/
this.storeNode = storeNode;
}

@@ -114,12 +105,6 @@

const methodSnippet = `${ builder.getMethod( method, type ) }( ${params.join( ', ' )} )`;
const methodSnippet = `${ builder.getMethod( method, type ) }( ${ params.join( ', ' ) } )`;
if ( this.storeNode !== null ) {
if ( b !== null ) {
const varSnippet = this.storeNode.build( builder, inputType );
builder.addLineFlowCode( `${varSnippet} = ${methodSnippet}`, this );
} else {
builder.addLineFlowCode( methodSnippet, this );

@@ -129,2 +114,4 @@

return methodSnippet;
}

@@ -154,3 +141,2 @@

* @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}

@@ -168,8 +154,7 @@ */

* @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}
*/
export const atomicFunc = ( method, pointerNode, valueNode, storeNode = null ) => {
export const atomicFunc = ( method, pointerNode, valueNode ) => {
const node = atomicNode( method, pointerNode, valueNode, storeNode );
const node = atomicNode( method, pointerNode, valueNode );
node.append();

@@ -187,6 +172,5 @@

* @param {Node} pointerNode - An atomic variable or element of an atomic buffer.
* @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}
*/
export const atomicLoad = ( pointerNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_LOAD, pointerNode, null, storeNode );
export const atomicLoad = ( pointerNode ) => atomicFunc( AtomicFunctionNode.ATOMIC_LOAD, pointerNode, null );

@@ -200,6 +184,5 @@ /**

* @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}
*/
export const atomicStore = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_STORE, pointerNode, valueNode, storeNode );
export const atomicStore = ( pointerNode, valueNode ) => atomicFunc( AtomicFunctionNode.ATOMIC_STORE, pointerNode, valueNode );

@@ -213,6 +196,5 @@ /**

* @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}
*/
export const atomicAdd = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_ADD, pointerNode, valueNode, storeNode );
export const atomicAdd = ( pointerNode, valueNode ) => atomicFunc( AtomicFunctionNode.ATOMIC_ADD, pointerNode, valueNode );

@@ -226,6 +208,5 @@ /**

* @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}
*/
export const atomicSub = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_SUB, pointerNode, valueNode, storeNode );
export const atomicSub = ( pointerNode, valueNode ) => atomicFunc( AtomicFunctionNode.ATOMIC_SUB, pointerNode, valueNode );

@@ -239,6 +220,5 @@ /**

* @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}
*/
export const atomicMax = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_MAX, pointerNode, valueNode, storeNode );
export const atomicMax = ( pointerNode, valueNode ) => atomicFunc( AtomicFunctionNode.ATOMIC_MAX, pointerNode, valueNode );

@@ -252,6 +232,5 @@ /**

* @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}
*/
export const atomicMin = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_MIN, pointerNode, valueNode, storeNode );
export const atomicMin = ( pointerNode, valueNode ) => atomicFunc( AtomicFunctionNode.ATOMIC_MIN, pointerNode, valueNode );

@@ -265,6 +244,5 @@ /**

* @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}
*/
export const atomicAnd = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_AND, pointerNode, valueNode, storeNode );
export const atomicAnd = ( pointerNode, valueNode ) => atomicFunc( AtomicFunctionNode.ATOMIC_AND, pointerNode, valueNode );

@@ -278,6 +256,5 @@ /**

* @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}
*/
export const atomicOr = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_OR, pointerNode, valueNode, storeNode );
export const atomicOr = ( pointerNode, valueNode ) => atomicFunc( AtomicFunctionNode.ATOMIC_OR, pointerNode, valueNode );

@@ -291,5 +268,4 @@ /**

* @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}
*/
export const atomicXor = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_XOR, pointerNode, valueNode, storeNode );
export const atomicXor = ( pointerNode, valueNode ) => atomicFunc( AtomicFunctionNode.ATOMIC_XOR, pointerNode, valueNode );

@@ -184,3 +184,3 @@ import Node from '../core/Node.js';

*
* If( workgroupId.x.modInt( 2 ).equal( 0 ), () => {
* If( workgroupId.x.mod( 2 ).equal( 0 ), () => {
*

@@ -187,0 +187,0 @@ * storageBuffer.element( instanceIndex ).assign( instanceIndex );

@@ -94,3 +94,3 @@ import Node from '../core/Node.js';

*
* @type {Function}
* @type {?Function}
*/

@@ -167,4 +167,21 @@ this.onInitFunction = null;

generate( builder ) {
setup( builder ) {
const result = this.computeNode.setup( builder );
if ( result ) {
const properties = builder.getNodeProperties( this );
properties.outputComputeNode = result.outputNode;
result.outputNode = null;
}
return result;
}
generate( builder, output ) {
const { shaderStage } = builder;

@@ -182,2 +199,13 @@

} else {
const properties = builder.getNodeProperties( this );
const outputComputeNode = properties.outputComputeNode;
if ( outputComputeNode ) {
return outputComputeNode.build( builder, output );
}
}

@@ -184,0 +212,0 @@

@@ -131,5 +131,13 @@ import LightingNode from './LightingNode.js';

* @param {NodeBuilder} builder - The builder object used for setting up the light.
* @return {Object|undefined} The direct light data (color and direction).
*/
setupDirect( /*builder*/ ) { }
/**
* Sets up the direct rect area lighting for the analytic light node.
*
* @abstract
* @param {NodeBuilder} builder - The builder object used for setting up the light.
* @return {Object|undefined} The direct rect area light data.
*/
setupDirectRectArea( /*builder*/ ) { }

@@ -176,3 +184,3 @@

shadowNode = this.setupShadowNode( builder );
shadowNode = this.setupShadowNode();

@@ -179,0 +187,0 @@ }

@@ -56,3 +56,3 @@ import Node from '../core/Node.js';

*/
this.totalDiffuseNode = vec3().toVar( 'totalDiffuse' );
this.totalDiffuseNode = vec3().toVar();

@@ -64,3 +64,3 @@ /**

*/
this.totalSpecularNode = vec3().toVar( 'totalSpecular' );
this.totalSpecularNode = vec3().toVar();

@@ -72,3 +72,3 @@ /**

*/
this.outgoingLightNode = vec3().toVar( 'outgoingLight' );
this.outgoingLightNode = vec3().toVar();

@@ -75,0 +75,0 @@ /**

@@ -809,5 +809,5 @@ import ShadowBaseNode, { shadowPositionWorld } from './ShadowBaseNode.js';

* @param {Light} light - The shadow casting light.
* @param {LightShadow} shadow - The light shadow.
* @param {?LightShadow} [shadow] - The light shadow.
* @return {ShadowNode} The created shadow node.
*/
export const shadow = ( light, shadow ) => nodeObject( new ShadowNode( light, shadow ) );

@@ -136,2 +136,3 @@ import Node from '../core/Node.js';

const functionNode = builder.currentFunctionNode;
const needsOutput = output !== 'void';

@@ -158,2 +159,10 @@ const nodeProperty = needsOutput ? property( type ).build( builder ) : '';

if ( functionNode === null ) {
console.warn( 'THREE.TSL: Return statement used in an inline \'Fn()\'. Define a layout struct to allow return values.' );
ifSnippet = '// ' + ifSnippet;
}
}

@@ -181,2 +190,10 @@

if ( functionNode === null ) {
console.warn( 'THREE.TSL: Return statement used in an inline \'Fn()\'. Define a layout struct to allow return values.' );
elseSnippet = '// ' + elseSnippet;
}
}

@@ -212,3 +229,3 @@

*/
export const select = /*@__PURE__*/ nodeProxy( ConditionalNode );
export const select = /*@__PURE__*/ nodeProxy( ConditionalNode ).setParameterLength( 2, 3 );

@@ -224,3 +241,3 @@ addMethodChaining( 'select', select );

*
* @param {...any} params
* @param {...any} params
* @returns {ConditionalNode}

@@ -230,3 +247,3 @@ */

console.warn( 'TSL.ConditionalNode: cond() has been renamed to select().' );
console.warn( 'THREE.TSL: cond() has been renamed to select().' );
return select( ...params );

@@ -233,0 +250,0 @@

import TempNode from '../core/TempNode.js';
import { sub, mul, div } from './OperatorNode.js';
import { sub, mul, div, mod, equal } from './OperatorNode.js';
import { addMethodChaining, nodeObject, nodeProxy, float, vec2, vec3, vec4, Fn } from '../tsl/TSLCore.js';

@@ -36,2 +36,20 @@ import { WebGLCoordinateSystem, WebGPUCoordinateSystem } from '../../constants.js';

// Allow the max() and min() functions to take an arbitrary number of arguments.
if ( ( method === MathNode.MAX || method === MathNode.MIN ) && arguments.length > 3 ) {
let finalOp = new MathNode( method, aNode, bNode );
for ( let i = 2; i < arguments.length - 1; i ++ ) {
finalOp = new MathNode( method, finalOp, arguments[ i ] );
}
aNode = finalOp;
bNode = arguments[ arguments.length - 1 ];
cNode = null;
}
/**

@@ -130,3 +148,3 @@ * The method name.

} else if ( method === MathNode.ALL ) {
} else if ( method === MathNode.ALL || method === MathNode.ANY ) {

@@ -139,6 +157,2 @@ return 'bool';

} else if ( method === MathNode.MOD ) {
return this.aNode.getNodeType( builder );
} else {

@@ -207,3 +221,3 @@

if ( method === MathNode.CROSS || method === MathNode.MOD ) {
if ( method === MathNode.CROSS ) {

@@ -222,3 +236,3 @@ params.push(

} else if ( ( coordinateSystem === WebGLCoordinateSystem && ( method === MathNode.MIN || method === MathNode.MAX ) ) || method === MathNode.MOD ) {
} else if ( coordinateSystem === WebGLCoordinateSystem && ( method === MathNode.MIN || method === MathNode.MAX ) ) {

@@ -326,3 +340,2 @@ params.push(

MathNode.MAX = 'max';
MathNode.MOD = 'mod';
MathNode.STEP = 'step';

@@ -389,3 +402,3 @@ MathNode.REFLECT = 'reflect';

*/
export const all = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ALL );
export const all = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ALL ).setParameterLength( 1 );

@@ -400,3 +413,3 @@ /**

*/
export const any = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ANY );
export const any = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ANY ).setParameterLength( 1 );

@@ -411,3 +424,3 @@ /**

*/
export const radians = /*@__PURE__*/ nodeProxy( MathNode, MathNode.RADIANS );
export const radians = /*@__PURE__*/ nodeProxy( MathNode, MathNode.RADIANS ).setParameterLength( 1 );

@@ -422,3 +435,3 @@ /**

*/
export const degrees = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DEGREES );
export const degrees = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DEGREES ).setParameterLength( 1 );

@@ -433,3 +446,3 @@ /**

*/
export const exp = /*@__PURE__*/ nodeProxy( MathNode, MathNode.EXP );
export const exp = /*@__PURE__*/ nodeProxy( MathNode, MathNode.EXP ).setParameterLength( 1 );

@@ -444,3 +457,3 @@ /**

*/
export const exp2 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.EXP2 );
export const exp2 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.EXP2 ).setParameterLength( 1 );

@@ -455,3 +468,3 @@ /**

*/
export const log = /*@__PURE__*/ nodeProxy( MathNode, MathNode.LOG );
export const log = /*@__PURE__*/ nodeProxy( MathNode, MathNode.LOG ).setParameterLength( 1 );

@@ -466,3 +479,3 @@ /**

*/
export const log2 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.LOG2 );
export const log2 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.LOG2 ).setParameterLength( 1 );

@@ -477,3 +490,3 @@ /**

*/
export const sqrt = /*@__PURE__*/ nodeProxy( MathNode, MathNode.SQRT );
export const sqrt = /*@__PURE__*/ nodeProxy( MathNode, MathNode.SQRT ).setParameterLength( 1 );

@@ -488,3 +501,3 @@ /**

*/
export const inverseSqrt = /*@__PURE__*/ nodeProxy( MathNode, MathNode.INVERSE_SQRT );
export const inverseSqrt = /*@__PURE__*/ nodeProxy( MathNode, MathNode.INVERSE_SQRT ).setParameterLength( 1 );

@@ -499,3 +512,3 @@ /**

*/
export const floor = /*@__PURE__*/ nodeProxy( MathNode, MathNode.FLOOR );
export const floor = /*@__PURE__*/ nodeProxy( MathNode, MathNode.FLOOR ).setParameterLength( 1 );

@@ -510,3 +523,3 @@ /**

*/
export const ceil = /*@__PURE__*/ nodeProxy( MathNode, MathNode.CEIL );
export const ceil = /*@__PURE__*/ nodeProxy( MathNode, MathNode.CEIL ).setParameterLength( 1 );

@@ -521,3 +534,3 @@ /**

*/
export const normalize = /*@__PURE__*/ nodeProxy( MathNode, MathNode.NORMALIZE );
export const normalize = /*@__PURE__*/ nodeProxy( MathNode, MathNode.NORMALIZE ).setParameterLength( 1 );

@@ -532,3 +545,3 @@ /**

*/
export const fract = /*@__PURE__*/ nodeProxy( MathNode, MathNode.FRACT );
export const fract = /*@__PURE__*/ nodeProxy( MathNode, MathNode.FRACT ).setParameterLength( 1 );

@@ -543,3 +556,3 @@ /**

*/
export const sin = /*@__PURE__*/ nodeProxy( MathNode, MathNode.SIN );
export const sin = /*@__PURE__*/ nodeProxy( MathNode, MathNode.SIN ).setParameterLength( 1 );

@@ -554,3 +567,3 @@ /**

*/
export const cos = /*@__PURE__*/ nodeProxy( MathNode, MathNode.COS );
export const cos = /*@__PURE__*/ nodeProxy( MathNode, MathNode.COS ).setParameterLength( 1 );

@@ -565,3 +578,3 @@ /**

*/
export const tan = /*@__PURE__*/ nodeProxy( MathNode, MathNode.TAN );
export const tan = /*@__PURE__*/ nodeProxy( MathNode, MathNode.TAN ).setParameterLength( 1 );

@@ -576,3 +589,3 @@ /**

*/
export const asin = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ASIN );
export const asin = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ASIN ).setParameterLength( 1 );

@@ -587,3 +600,3 @@ /**

*/
export const acos = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ACOS );
export const acos = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ACOS ).setParameterLength( 1 );

@@ -600,3 +613,3 @@ /**

*/
export const atan = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ATAN );
export const atan = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ATAN ).setParameterLength( 1, 2 );

@@ -611,3 +624,3 @@ /**

*/
export const abs = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ABS );
export const abs = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ABS ).setParameterLength( 1 );

@@ -622,3 +635,3 @@ /**

*/
export const sign = /*@__PURE__*/ nodeProxy( MathNode, MathNode.SIGN );
export const sign = /*@__PURE__*/ nodeProxy( MathNode, MathNode.SIGN ).setParameterLength( 1 );

@@ -633,3 +646,3 @@ /**

*/
export const length = /*@__PURE__*/ nodeProxy( MathNode, MathNode.LENGTH );
export const length = /*@__PURE__*/ nodeProxy( MathNode, MathNode.LENGTH ).setParameterLength( 1 );

@@ -644,3 +657,3 @@ /**

*/
export const negate = /*@__PURE__*/ nodeProxy( MathNode, MathNode.NEGATE );
export const negate = /*@__PURE__*/ nodeProxy( MathNode, MathNode.NEGATE ).setParameterLength( 1 );

@@ -655,3 +668,3 @@ /**

*/
export const oneMinus = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ONE_MINUS );
export const oneMinus = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ONE_MINUS ).setParameterLength( 1 );

@@ -666,3 +679,3 @@ /**

*/
export const dFdx = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DFDX );
export const dFdx = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DFDX ).setParameterLength( 1 );

@@ -677,3 +690,3 @@ /**

*/
export const dFdy = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DFDY );
export const dFdy = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DFDY ).setParameterLength( 1 );

@@ -688,3 +701,3 @@ /**

*/
export const round = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ROUND );
export const round = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ROUND ).setParameterLength( 1 );

@@ -699,3 +712,3 @@ /**

*/
export const reciprocal = /*@__PURE__*/ nodeProxy( MathNode, MathNode.RECIPROCAL );
export const reciprocal = /*@__PURE__*/ nodeProxy( MathNode, MathNode.RECIPROCAL ).setParameterLength( 1 );

@@ -710,3 +723,3 @@ /**

*/
export const trunc = /*@__PURE__*/ nodeProxy( MathNode, MathNode.TRUNC );
export const trunc = /*@__PURE__*/ nodeProxy( MathNode, MathNode.TRUNC ).setParameterLength( 1 );

@@ -721,3 +734,3 @@ /**

*/
export const fwidth = /*@__PURE__*/ nodeProxy( MathNode, MathNode.FWIDTH );
export const fwidth = /*@__PURE__*/ nodeProxy( MathNode, MathNode.FWIDTH ).setParameterLength( 1 );

@@ -732,3 +745,3 @@ /**

*/
export const transpose = /*@__PURE__*/ nodeProxy( MathNode, MathNode.TRANSPOSE );
export const transpose = /*@__PURE__*/ nodeProxy( MathNode, MathNode.TRANSPOSE ).setParameterLength( 1 );

@@ -746,3 +759,3 @@ // 2 inputs

*/
export const bitcast = /*@__PURE__*/ nodeProxy( MathNode, MathNode.BITCAST );
export const bitcast = /*@__PURE__*/ nodeProxy( MathNode, MathNode.BITCAST ).setParameterLength( 2 );

@@ -756,38 +769,31 @@ /**

* @param {Node | number} y - The second parameter.
* @deprecated since r175. Use {@link equal} instead.
* @returns {Node<bool>}
*/
export const equals = /*@__PURE__*/ nodeProxy( MathNode, MathNode.EQUALS );
export const equals = ( x, y ) => { // @deprecated, r172
/**
* Returns the lesser of two values.
*
* @tsl
* @function
* @param {Node | number} x - The y parameter.
* @param {Node | number} y - The x parameter.
* @returns {Node}
*/
export const min = /*@__PURE__*/ nodeProxy( MathNode, MathNode.MIN );
console.warn( 'THREE.TSL: "equals" is deprecated. Use "equal" inside a vector instead, like: "bvec*( equal( ... ) )"' );
return equal( x, y );
};
/**
* Returns the greater of two values.
* Returns the least of the given values.
*
* @tsl
* @function
* @param {Node | number} x - The y parameter.
* @param {Node | number} y - The x parameter.
* @param {...(Node | number)} values - The values to compare.
* @returns {Node}
*/
export const max = /*@__PURE__*/ nodeProxy( MathNode, MathNode.MAX );
export const min = /*@__PURE__*/ nodeProxy( MathNode, MathNode.MIN ).setParameterLength( 2, Infinity );
/**
* Computes the remainder of dividing the first node by the second one.
* Returns the greatest of the given values.
*
* @tsl
* @function
* @param {Node | number} x - The y parameter.
* @param {Node | number} y - The x parameter.
* @param {...(Node | number)} values - The values to compare.
* @returns {Node}
*/
export const mod = /*@__PURE__*/ nodeProxy( MathNode, MathNode.MOD );
export const max = /*@__PURE__*/ nodeProxy( MathNode, MathNode.MAX ).setParameterLength( 2, Infinity );

@@ -803,3 +809,3 @@ /**

*/
export const step = /*@__PURE__*/ nodeProxy( MathNode, MathNode.STEP );
export const step = /*@__PURE__*/ nodeProxy( MathNode, MathNode.STEP ).setParameterLength( 2 );

@@ -815,3 +821,3 @@ /**

*/
export const reflect = /*@__PURE__*/ nodeProxy( MathNode, MathNode.REFLECT );
export const reflect = /*@__PURE__*/ nodeProxy( MathNode, MathNode.REFLECT ).setParameterLength( 2 );

@@ -827,3 +833,3 @@ /**

*/
export const distance = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DISTANCE );
export const distance = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DISTANCE ).setParameterLength( 2 );

@@ -839,3 +845,3 @@ /**

*/
export const difference = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DIFFERENCE );
export const difference = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DIFFERENCE ).setParameterLength( 2 );

@@ -851,3 +857,3 @@ /**

*/
export const dot = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DOT );
export const dot = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DOT ).setParameterLength( 2 );

@@ -863,3 +869,3 @@ /**

*/
export const cross = /*@__PURE__*/ nodeProxy( MathNode, MathNode.CROSS );
export const cross = /*@__PURE__*/ nodeProxy( MathNode, MathNode.CROSS ).setParameterLength( 2 );

@@ -875,3 +881,3 @@ /**

*/
export const pow = /*@__PURE__*/ nodeProxy( MathNode, MathNode.POW );
export const pow = /*@__PURE__*/ nodeProxy( MathNode, MathNode.POW ).setParameterLength( 2 );

@@ -886,3 +892,3 @@ /**

*/
export const pow2 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.POW, 2 );
export const pow2 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.POW, 2 ).setParameterLength( 1 );

@@ -897,3 +903,3 @@ /**

*/
export const pow3 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.POW, 3 );
export const pow3 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.POW, 3 ).setParameterLength( 1 );

@@ -908,3 +914,3 @@ /**

*/
export const pow4 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.POW, 4 );
export const pow4 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.POW, 4 ).setParameterLength( 1 );

@@ -920,3 +926,3 @@ /**

*/
export const transformDirection = /*@__PURE__*/ nodeProxy( MathNode, MathNode.TRANSFORM_DIRECTION );
export const transformDirection = /*@__PURE__*/ nodeProxy( MathNode, MathNode.TRANSFORM_DIRECTION ).setParameterLength( 2 );

@@ -953,3 +959,3 @@ /**

*/
export const mix = /*@__PURE__*/ nodeProxy( MathNode, MathNode.MIX );
export const mix = /*@__PURE__*/ nodeProxy( MathNode, MathNode.MIX ).setParameterLength( 3 );

@@ -985,6 +991,6 @@ /**

* @param {Node<vec2|vec3|vec4>} N - The normal vector.
* @param {Node<float>} eta - The the ratio of indices of refraction.
* @param {Node<float>} eta - The ratio of indices of refraction.
* @returns {Node<vec2|vec3|vec4>}
*/
export const refract = /*@__PURE__*/ nodeProxy( MathNode, MathNode.REFRACT );
export const refract = /*@__PURE__*/ nodeProxy( MathNode, MathNode.REFRACT ).setParameterLength( 3 );

@@ -1001,3 +1007,3 @@ /**

*/
export const smoothstep = /*@__PURE__*/ nodeProxy( MathNode, MathNode.SMOOTHSTEP );
export const smoothstep = /*@__PURE__*/ nodeProxy( MathNode, MathNode.SMOOTHSTEP ).setParameterLength( 3 );

@@ -1014,3 +1020,3 @@ /**

*/
export const faceForward = /*@__PURE__*/ nodeProxy( MathNode, MathNode.FACEFORWARD );
export const faceForward = /*@__PURE__*/ nodeProxy( MathNode, MathNode.FACEFORWARD ).setParameterLength( 3 );

@@ -1120,3 +1126,2 @@ /**

addMethodChaining( 'max', max );
addMethodChaining( 'mod', mod );
addMethodChaining( 'step', step );

@@ -1123,0 +1128,0 @@ addMethodChaining( 'reflect', reflect );

@@ -0,3 +1,4 @@

import { WebGLCoordinateSystem } from '../../constants.js';
import TempNode from '../core/TempNode.js';
import { addMethodChaining, nodeProxy } from '../tsl/TSLCore.js';
import { addMethodChaining, int, nodeProxy } from '../tsl/TSLCore.js';

@@ -107,3 +108,3 @@ /**

} else if ( op === '!' || op === '==' || op === '&&' || op === '||' || op === '^^' ) {
} else if ( op === '!' || op === '==' || op === '!=' || op === '&&' || op === '||' || op === '^^' ) {

@@ -121,2 +122,3 @@ return 'bool';

// Handle matrix operations
if ( builder.isMatrix( typeA ) ) {

@@ -153,2 +155,3 @@

// Handle non-matrix cases
if ( builder.getTypeLength( typeB ) > builder.getTypeLength( typeA ) ) {

@@ -185,3 +188,3 @@

if ( op === '<' || op === '>' || op === '<=' || op === '>=' || op === '==' ) {
if ( op === '<' || op === '>' || op === '<=' || op === '>=' || op === '==' || op === '!=' ) {

@@ -203,2 +206,7 @@ if ( builder.isVector( typeA ) ) {

} else if ( op === '%' ) {
typeA = type;
typeB = builder.isInteger( typeA ) && builder.isInteger( typeB ) ? typeB : typeA;
} else if ( builder.isMatrix( typeA ) ) {

@@ -209,2 +217,3 @@

// Keep matrix type for typeA, but ensure typeB stays float
typeB = 'float';

@@ -218,3 +227,5 @@

} else if ( builder.isMatrix( typeB ) ) {
// matrix x matrix - keep both types
} else {

@@ -231,2 +242,3 @@

// Keep matrix type for typeB, but ensure typeA stays float
typeA = 'float';

@@ -237,2 +249,3 @@

// vector x matrix
typeA = builder.getVectorFromMatrix( typeB );

@@ -268,6 +281,38 @@

if ( op === '<' && outputLength > 1 ) {
const isGLSL = builder.renderer.coordinateSystem === WebGLCoordinateSystem;
if ( builder.useComparisonMethod ) {
if ( op === '==' ) {
if ( isGLSL ) {
if ( outputLength > 1 ) {
return builder.format( `${ builder.getMethod( 'equal', output ) }( ${ a }, ${ b } )`, type, output );
} else {
return builder.format( `( ${ a } ${ op } ${ b } )`, type, output );
}
} else {
// WGSL
if ( outputLength > 1 || ! builder.isVector( typeA ) ) {
return builder.format( `( ${ a } == ${ b } )`, type, output );
} else {
return builder.format( `all( ${ a } == ${ b } )`, type, output );
}
}
} else if ( op === '<' && outputLength > 1 ) {
if ( isGLSL ) {
return builder.format( `${ builder.getMethod( 'lessThan', output ) }( ${ a }, ${ b } )`, type, output );

@@ -277,2 +322,4 @@

// WGSL
return builder.format( `( ${ a } < ${ b } )`, type, output );

@@ -284,3 +331,3 @@

if ( builder.useComparisonMethod ) {
if ( isGLSL ) {

@@ -291,2 +338,4 @@ return builder.format( `${ builder.getMethod( 'lessThanEqual', output ) }( ${ a }, ${ b } )`, type, output );

// WGSL
return builder.format( `( ${ a } <= ${ b } )`, type, output );

@@ -298,3 +347,3 @@

if ( builder.useComparisonMethod ) {
if ( isGLSL ) {

@@ -305,2 +354,4 @@ return builder.format( `${ builder.getMethod( 'greaterThan', output ) }( ${ a }, ${ b } )`, type, output );

// WGSL
return builder.format( `( ${ a } > ${ b } )`, type, output );

@@ -312,3 +363,3 @@

if ( builder.useComparisonMethod ) {
if ( isGLSL ) {

@@ -319,2 +370,4 @@ return builder.format( `${ builder.getMethod( 'greaterThanEqual', output ) }( ${ a }, ${ b } )`, type, output );

// WGSL
return builder.format( `( ${ a } >= ${ b } )`, type, output );

@@ -324,2 +377,14 @@

} else if ( op === '%' ) {
if ( builder.isInteger( typeB ) ) {
return builder.format( `( ${ a } % ${ b } )`, type, output );
} else {
return builder.format( `${ builder.getMethod( 'mod', type ) }( ${ a }, ${ b } )`, type, output );
}
} else if ( op === '!' || op === '~' ) {

@@ -336,2 +401,3 @@

// Handle matrix operations
if ( builder.isMatrix( typeA ) && typeB === 'float' ) {

@@ -347,4 +413,12 @@

return builder.format( `( ${ a } ${ op } ${ b } )`, type, output );
let snippet = `( ${ a } ${ op } ${ b } )`;
if ( ! isGLSL && type === 'bool' && builder.isVector( typeA ) && builder.isVector( typeB ) ) {
snippet = `all${ snippet }`;
}
return builder.format( snippet, type, output );
}

@@ -403,8 +477,8 @@

* @function
* @param {Node} aNode - The first input.
* @param {Node} bNode - The second input.
* @param {Node} a - The first input.
* @param {Node} b - The second input.
* @param {...Node} params - Additional input parameters.
* @returns {OperatorNode}
*/
export const add = /*@__PURE__*/ nodeProxy( OperatorNode, '+' );
export const add = /*@__PURE__*/ nodeProxy( OperatorNode, '+' ).setParameterLength( 2, Infinity ).setName( 'add' );

@@ -416,8 +490,8 @@ /**

* @function
* @param {Node} aNode - The first input.
* @param {Node} bNode - The second input.
* @param {Node} a - The first input.
* @param {Node} b - The second input.
* @param {...Node} params - Additional input parameters.
* @returns {OperatorNode}
*/
export const sub = /*@__PURE__*/ nodeProxy( OperatorNode, '-' );
export const sub = /*@__PURE__*/ nodeProxy( OperatorNode, '-' ).setParameterLength( 2, Infinity ).setName( 'sub' );

@@ -429,8 +503,8 @@ /**

* @function
* @param {Node} aNode - The first input.
* @param {Node} bNode - The second input.
* @param {Node} a - The first input.
* @param {Node} b - The second input.
* @param {...Node} params - Additional input parameters.
* @returns {OperatorNode}
*/
export const mul = /*@__PURE__*/ nodeProxy( OperatorNode, '*' );
export const mul = /*@__PURE__*/ nodeProxy( OperatorNode, '*' ).setParameterLength( 2, Infinity ).setName( 'mul' );

@@ -442,19 +516,19 @@ /**

* @function
* @param {Node} aNode - The first input.
* @param {Node} bNode - The second input.
* @param {Node} a - The first input.
* @param {Node} b - The second input.
* @param {...Node} params - Additional input parameters.
* @returns {OperatorNode}
*/
export const div = /*@__PURE__*/ nodeProxy( OperatorNode, '/' );
export const div = /*@__PURE__*/ nodeProxy( OperatorNode, '/' ).setParameterLength( 2, Infinity ).setName( 'div' );
/**
* Computes the remainder of dividing the first node by the second, for integer values.
* Computes the remainder of dividing the first node by the second one.
*
* @tsl
* @function
* @param {Node} aNode - The first input.
* @param {Node} bNode - The second input.
* @param {Node} a - The first input.
* @param {Node} b - The second input.
* @returns {OperatorNode}
*/
export const modInt = /*@__PURE__*/ nodeProxy( OperatorNode, '%' );
export const mod = /*@__PURE__*/ nodeProxy( OperatorNode, '%' ).setParameterLength( 2 ).setName( 'mod' );

@@ -466,7 +540,7 @@ /**

* @function
* @param {Node} aNode - The first input.
* @param {Node} bNode - The second input.
* @param {Node} a - The first input.
* @param {Node} b - The second input.
* @returns {OperatorNode}
*/
export const equal = /*@__PURE__*/ nodeProxy( OperatorNode, '==' );
export const equal = /*@__PURE__*/ nodeProxy( OperatorNode, '==' ).setParameterLength( 2 ).setName( 'equal' );

@@ -478,7 +552,7 @@ /**

* @function
* @param {Node} aNode - The first input.
* @param {Node} bNode - The second input.
* @param {Node} a - The first input.
* @param {Node} b - The second input.
* @returns {OperatorNode}
*/
export const notEqual = /*@__PURE__*/ nodeProxy( OperatorNode, '!=' );
export const notEqual = /*@__PURE__*/ nodeProxy( OperatorNode, '!=' ).setParameterLength( 2 ).setName( 'notEqual' );

@@ -490,7 +564,7 @@ /**

* @function
* @param {Node} aNode - The first input.
* @param {Node} bNode - The second input.
* @param {Node} a - The first input.
* @param {Node} b - The second input.
* @returns {OperatorNode}
*/
export const lessThan = /*@__PURE__*/ nodeProxy( OperatorNode, '<' );
export const lessThan = /*@__PURE__*/ nodeProxy( OperatorNode, '<' ).setParameterLength( 2 ).setName( 'lessThan' );

@@ -502,7 +576,7 @@ /**

* @function
* @param {Node} aNode - The first input.
* @param {Node} bNode - The second input.
* @param {Node} a - The first input.
* @param {Node} b - The second input.
* @returns {OperatorNode}
*/
export const greaterThan = /*@__PURE__*/ nodeProxy( OperatorNode, '>' );
export const greaterThan = /*@__PURE__*/ nodeProxy( OperatorNode, '>' ).setParameterLength( 2 ).setName( 'greaterThan' );

@@ -514,7 +588,7 @@ /**

* @function
* @param {Node} aNode - The first input.
* @param {Node} bNode - The second input.
* @param {Node} a - The first input.
* @param {Node} b - The second input.
* @returns {OperatorNode}
*/
export const lessThanEqual = /*@__PURE__*/ nodeProxy( OperatorNode, '<=' );
export const lessThanEqual = /*@__PURE__*/ nodeProxy( OperatorNode, '<=' ).setParameterLength( 2 ).setName( 'lessThanEqual' );

@@ -526,29 +600,27 @@ /**

* @function
* @param {Node} aNode - The first input.
* @param {Node} bNode - The second input.
* @param {Node} a - The first input.
* @param {Node} b - The second input.
* @returns {OperatorNode}
*/
export const greaterThanEqual = /*@__PURE__*/ nodeProxy( OperatorNode, '>=' );
export const greaterThanEqual = /*@__PURE__*/ nodeProxy( OperatorNode, '>=' ).setParameterLength( 2 ).setName( 'greaterThanEqual' );
/**
* Performs logical AND on two nodes.
* Performs a logical AND operation on multiple nodes.
*
* @tsl
* @function
* @param {Node} aNode - The first input.
* @param {Node} bNode - The second input.
* @param {...Node} nodes - The input nodes to be combined using AND.
* @returns {OperatorNode}
*/
export const and = /*@__PURE__*/ nodeProxy( OperatorNode, '&&' );
export const and = /*@__PURE__*/ nodeProxy( OperatorNode, '&&' ).setParameterLength( 2, Infinity ).setName( 'and' );
/**
* Performs logical OR on two nodes.
* Performs a logical OR operation on multiple nodes.
*
* @tsl
* @function
* @param {Node} aNode - The first input.
* @param {Node} bNode - The second input.
* @param {...Node} nodes - The input nodes to be combined using OR.
* @returns {OperatorNode}
*/
export const or = /*@__PURE__*/ nodeProxy( OperatorNode, '||' );
export const or = /*@__PURE__*/ nodeProxy( OperatorNode, '||' ).setParameterLength( 2, Infinity ).setName( 'or' );

@@ -560,7 +632,6 @@ /**

* @function
* @param {Node} aNode - The first input.
* @param {Node} bNode - The second input.
* @param {Node} value - The value.
* @returns {OperatorNode}
*/
export const not = /*@__PURE__*/ nodeProxy( OperatorNode, '!' );
export const not = /*@__PURE__*/ nodeProxy( OperatorNode, '!' ).setParameterLength( 1 ).setName( 'not' );

@@ -572,7 +643,7 @@ /**

* @function
* @param {Node} aNode - The first input.
* @param {Node} bNode - The second input.
* @param {Node} a - The first input.
* @param {Node} b - The second input.
* @returns {OperatorNode}
*/
export const xor = /*@__PURE__*/ nodeProxy( OperatorNode, '^^' );
export const xor = /*@__PURE__*/ nodeProxy( OperatorNode, '^^' ).setParameterLength( 2 ).setName( 'xor' );

@@ -584,7 +655,7 @@ /**

* @function
* @param {Node} aNode - The first input.
* @param {Node} bNode - The second input.
* @param {Node} a - The first input.
* @param {Node} b - The second input.
* @returns {OperatorNode}
*/
export const bitAnd = /*@__PURE__*/ nodeProxy( OperatorNode, '&' );
export const bitAnd = /*@__PURE__*/ nodeProxy( OperatorNode, '&' ).setParameterLength( 2 ).setName( 'bitAnd' );

@@ -596,7 +667,7 @@ /**

* @function
* @param {Node} aNode - The first input.
* @param {Node} bNode - The second input.
* @param {Node} a - The first input.
* @param {Node} b - The second input.
* @returns {OperatorNode}
*/
export const bitNot = /*@__PURE__*/ nodeProxy( OperatorNode, '~' );
export const bitNot = /*@__PURE__*/ nodeProxy( OperatorNode, '~' ).setParameterLength( 2 ).setName( 'bitNot' );

@@ -608,7 +679,7 @@ /**

* @function
* @param {Node} aNode - The first input.
* @param {Node} bNode - The second input.
* @param {Node} a - The first input.
* @param {Node} b - The second input.
* @returns {OperatorNode}
*/
export const bitOr = /*@__PURE__*/ nodeProxy( OperatorNode, '|' );
export const bitOr = /*@__PURE__*/ nodeProxy( OperatorNode, '|' ).setParameterLength( 2 ).setName( 'bitOr' );

@@ -620,7 +691,7 @@ /**

* @function
* @param {Node} aNode - The first input.
* @param {Node} bNode - The second input.
* @param {Node} a - The first input.
* @param {Node} b - The second input.
* @returns {OperatorNode}
*/
export const bitXor = /*@__PURE__*/ nodeProxy( OperatorNode, '^' );
export const bitXor = /*@__PURE__*/ nodeProxy( OperatorNode, '^' ).setParameterLength( 2 ).setName( 'bitXor' );

@@ -632,7 +703,7 @@ /**

* @function
* @param {Node} aNode - The node to shift.
* @param {Node} bNode - The value to shift.
* @param {Node} a - The node to shift.
* @param {Node} b - The value to shift.
* @returns {OperatorNode}
*/
export const shiftLeft = /*@__PURE__*/ nodeProxy( OperatorNode, '<<' );
export const shiftLeft = /*@__PURE__*/ nodeProxy( OperatorNode, '<<' ).setParameterLength( 2 ).setName( 'shiftLeft' );

@@ -644,7 +715,7 @@ /**

* @function
* @param {Node} aNode - The node to shift.
* @param {Node} bNode - The value to shift.
* @param {Node} a - The node to shift.
* @param {Node} b - The value to shift.
* @returns {OperatorNode}
*/
export const shiftRight = /*@__PURE__*/ nodeProxy( OperatorNode, '>>' );
export const shiftRight = /*@__PURE__*/ nodeProxy( OperatorNode, '>>' ).setParameterLength( 2 ).setName( 'shiftRight' );

@@ -655,3 +726,3 @@ addMethodChaining( 'add', add );

addMethodChaining( 'div', div );
addMethodChaining( 'modInt', modInt );
addMethodChaining( 'mod', mod );
addMethodChaining( 'equal', equal );

@@ -677,14 +748,32 @@ addMethodChaining( 'notEqual', notEqual );

* @function
* @deprecated since r168. Use {@link modInt} instead.
* @deprecated since r168. Use {@link mod} instead.
*
* @param {...any} params
* @returns {Function}
* @param {Node} a - The first input.
* @param {Node} b - The second input.
* @returns {OperatorNode}
*/
export const remainder = ( ...params ) => { // @deprecated, r168
export const remainder = ( a, b ) => { // @deprecated, r168
console.warn( 'TSL.OperatorNode: .remainder() has been renamed to .modInt().' );
return modInt( ...params );
console.warn( 'THREE.TSL: "remainder()" is deprecated. Use "mod( int( ... ) )" instead.' );
return mod( a, b );
};
/**
* @tsl
* @function
* @deprecated since r175. Use {@link mod} instead.
*
* @param {Node} a - The first input.
* @param {Node} b - The second input.
* @returns {OperatorNode}
*/
export const modInt = ( a, b ) => { // @deprecated, r175
console.warn( 'THREE.TSL: "modInt()" is deprecated. Use "mod( int( ... ) )" instead.' );
return mod( int( a ), int( b ) );
};
addMethodChaining( 'remainder', remainder );
addMethodChaining( 'modInt', modInt );

@@ -59,2 +59,3 @@ // constants

export { default as MemberNode } from './utils/MemberNode.js';
export { default as DebugNode } from './utils/DebugNode.js';

@@ -61,0 +62,0 @@ // accessors

@@ -351,3 +351,3 @@ import TempNode from '../core/TempNode.js';

* @private
* @param {Array<(Image|Object)>} image - The cube map image.
* @param {?Array<(Image|Object)>} [image] - The cube map image.
* @return {boolean} Whether the given cube map is ready or not.

@@ -394,6 +394,6 @@ */

* @param {Texture} value - The input texture.
* @param {Node<vec2>} [uvNode=null] - The uv node.
* @param {Node<float>} [levelNode=null] - The level node.
* @param {?Node<vec2>} [uvNode=null] - The uv node.
* @param {?Node<float>} [levelNode=null] - The level node.
* @returns {PMREMNode}
*/
export const pmremTexture = /*@__PURE__*/ nodeProxy( PMREMNode );
export const pmremTexture = /*@__PURE__*/ nodeProxy( PMREMNode ).setParameterLength( 1, 3 );
import { Fn, int, float, vec2, vec3, vec4, If } from '../tsl/TSLBase.js';
import { cos, sin, abs, max, exp2, log2, clamp, fract, mix, floor, normalize, cross, all } from '../math/MathNode.js';
import { cos, sin, abs, max, exp2, log2, clamp, fract, mix, floor, normalize, cross } from '../math/MathNode.js';
import { mul } from '../math/OperatorNode.js';

@@ -261,3 +261,3 @@ import { select } from '../math/ConditionalNode.js';

If( all( axis.equals( vec3( 0.0 ) ) ), () => {
If( axis.equal( vec3( 0.0 ) ), () => {

@@ -264,0 +264,0 @@ axis.assign( vec3( outputDirection.z, 0.0, outputDirection.x.negate() ) );

@@ -26,7 +26,8 @@ // Non-PURE exports list, side-effects are required here.

export * from '../display/RenderOutputNode.js'; // .renderOutput()
export * from '../utils/DebugNode.js'; // debug()
export function addNodeElement( name/*, nodeElement*/ ) {
console.warn( 'THREE.TSLBase: AddNodeElement has been removed in favor of tree-shaking. Trying add', name );
console.warn( 'THREE.TSL: AddNodeElement has been removed in favor of tree-shaking. Trying add', name );
}

@@ -20,3 +20,3 @@ import Node from '../core/Node.js';

console.warn( `Redefinition of method chaining ${ name }` );
console.warn( `THREE.TSL: Redefinition of method chaining '${ name }'.` );
return;

@@ -26,3 +26,3 @@

if ( typeof nodeElement !== 'function' ) throw new Error( `Node element ${ name } is not a function` );
if ( typeof nodeElement !== 'function' ) throw new Error( `THREE.TSL: Node element ${ name } is not a function` );

@@ -218,7 +218,34 @@ NodeElements.set( name, nodeElement );

let fn, name = scope, minParams, maxParams;
function verifyParamsLimit( params ) {
let tslName;
if ( name ) tslName = /[a-z]/i.test( name ) ? name + '()' : name;
else tslName = NodeClass.type;
if ( minParams !== undefined && params.length < minParams ) {
console.error( `THREE.TSL: "${ tslName }" parameter length is less than minimum required.` );
return params.concat( new Array( minParams - params.length ).fill( 0 ) );
} else if ( maxParams !== undefined && params.length > maxParams ) {
console.error( `THREE.TSL: "${ tslName }" parameter length exceeds limit.` );
return params.slice( 0, maxParams );
}
return params;
}
if ( scope === null ) {
return ( ...params ) => {
fn = ( ...params ) => {
return assignNode( new NodeClass( ...nodeArray( params ) ) );
return assignNode( new NodeClass( ...nodeArray( verifyParamsLimit( params ) ) ) );

@@ -231,5 +258,5 @@ };

return ( ...params ) => {
fn = ( ...params ) => {
return assignNode( new NodeClass( scope, ...nodeArray( params ), factor ) );
return assignNode( new NodeClass( scope, ...nodeArray( verifyParamsLimit( params ) ), factor ) );

@@ -240,5 +267,5 @@ };

return ( ...params ) => {
fn = ( ...params ) => {
return assignNode( new NodeClass( scope, ...nodeArray( params ) ) );
return assignNode( new NodeClass( scope, ...nodeArray( verifyParamsLimit( params ) ) ) );

@@ -249,2 +276,21 @@ };

fn.setParameterLength = ( ...params ) => {
if ( params.length === 1 ) minParams = maxParams = params[ 0 ];
else if ( params.length === 2 ) [ minParams, maxParams ] = params;
return fn;
};
fn.setName = ( value ) => {
name = value;
return fn;
};
return fn;
};

@@ -523,4 +569,32 @@

export const Fn = ( jsFunc, nodeType ) => {
let fnId = 0;
export const Fn = ( jsFunc, layout = null ) => {
let nodeType = null;
if ( layout !== null ) {
if ( typeof layout === 'object' ) {
nodeType = layout.return;
} else {
if ( typeof layout === 'string' ) {
nodeType = layout;
} else {
console.error( 'THREE.TSL: Invalid layout type.' );
}
layout = null;
}
}
const shaderNode = new ShaderNode( jsFunc, nodeType );

@@ -566,2 +640,31 @@

if ( layout !== null ) {
if ( typeof layout.inputs !== 'object' ) {
const fullLayout = {
name: 'fn' + fnId ++,
type: nodeType,
inputs: []
};
for ( const name in layout ) {
if ( name === 'return' ) continue;
fullLayout.inputs.push( {
name: name,
type: layout[ name ]
} );
}
layout = fullLayout;
}
fn.setLayout( layout );
}
return fn;

@@ -576,3 +679,3 @@

*
* @param {...any} params
* @param {...any} params
* @returns {Function}

@@ -582,3 +685,3 @@ */

console.warn( 'TSL.ShaderNode: tslFn() has been renamed to Fn().' );
console.warn( 'THREE.TSL: tslFn() has been renamed to Fn().' );
return Fn( ...params );

@@ -680,3 +783,3 @@

export const element = /*@__PURE__*/ nodeProxy( ArrayElementNode );
export const element = /*@__PURE__*/ nodeProxy( ArrayElementNode ).setParameterLength( 2 );
export const convert = ( node, types ) => nodeObject( new ConvertNode( nodeObject( node ), types ) );

@@ -683,0 +786,0 @@ export const split = ( node, channels ) => nodeObject( new SplitNode( nodeObject( node ), channels ) );

@@ -66,4 +66,6 @@ import Node from '../core/Node.js';

const indexType = this.indexNode.getNodeType( builder );
const nodeSnippet = this.node.build( builder );
const indexSnippet = this.indexNode.build( builder, 'uint' );
const indexSnippet = this.indexNode.build( builder, ! builder.isVector( indexType ) && builder.isInteger( indexType ) ? indexType : 'uint' );

@@ -70,0 +72,0 @@ return `${ nodeSnippet }[ ${ indexSnippet } ]`;

@@ -45,3 +45,3 @@ import TempNode from '../core/TempNode.js';

* @private
* @type {CubeTexture}
* @type {?CubeTexture}
* @default null

@@ -57,3 +57,3 @@ */

*/
this._cubeTextureNode = cubeTexture();
this._cubeTextureNode = cubeTexture( null );

@@ -239,2 +239,2 @@ const defaultTexture = new CubeTexture();

*/
export const cubeMapNode = /*@__PURE__*/ nodeProxy( CubeMapNode );
export const cubeMapNode = /*@__PURE__*/ nodeProxy( CubeMapNode ).setParameterLength( 1 );

@@ -62,5 +62,5 @@ import TempNode from '../core/TempNode.js';

* @function
* @param {Node<vec3>} [dirNode=positionWorldDirection] - A direction vector for sampling which is by default `positionWorldDirection`.
* @param {?Node<vec3>} [dirNode=positionWorldDirection] - A direction vector for sampling which is by default `positionWorldDirection`.
* @returns {EquirectUVNode}
*/
export const equirectUV = /*@__PURE__*/ nodeProxy( EquirectUVNode );
export const equirectUV = /*@__PURE__*/ nodeProxy( EquirectUVNode ).setParameterLength( 0, 1 );

@@ -59,2 +59,4 @@ import TempNode from '../core/TempNode.js';

const type = this.getNodeType( builder );
const maxLength = builder.getTypeLength( type );
const nodes = this.nodes;

@@ -66,8 +68,31 @@

let length = 0;
for ( const input of nodes ) {
let inputSnippet = input.build( builder );
if ( length >= maxLength ) {
const inputPrimitiveType = builder.getComponentType( input.getNodeType( builder ) );
console.error( `THREE.TSL: Length of parameters exceeds maximum length of function '${ type }()' type.` );
break;
}
let inputType = input.getNodeType( builder );
let inputTypeLength = builder.getTypeLength( inputType );
let inputSnippet;
if ( length + inputTypeLength > maxLength ) {
console.error( `THREE.TSL: Length of '${ type }()' data exceeds maximum length of output type.` );
inputTypeLength = maxLength - length;
inputType = builder.getTypeFromLength( inputTypeLength );
}
length += inputTypeLength;
inputSnippet = input.build( builder, inputType );
const inputPrimitiveType = builder.getComponentType( inputType );
if ( inputPrimitiveType !== primitiveType ) {

@@ -74,0 +99,0 @@

@@ -28,2 +28,12 @@ import Node from '../core/Node.js';

* ```
* It is possible to execute with boolean values, similar to the `while` syntax.
* ```js
* const value = float( 0 ).toVar();
*
* Loop( value.lessThan( 10 ), () => {
*
* value.addAssign( 1 );
*
* } );
* ```
* The module also provides `Break()` and `Continue()` TSL expression for loop control.

@@ -137,12 +147,22 @@ * @augments Node

let start = null, end = null, name = null, type = null, condition = null, update = null;
let isWhile = false, start = null, end = null, name = null, type = null, condition = null, update = null;
if ( param.isNode ) {
type = 'int';
name = this.getVarName( i );
start = '0';
end = param.build( builder, type );
condition = '<';
if ( param.getNodeType( builder ) === 'bool' ) {
isWhile = true;
type = 'bool';
end = param.build( builder, type );
} else {
type = 'int';
name = this.getVarName( i );
start = '0';
end = param.build( builder, type );
condition = '<';
}
} else {

@@ -192,37 +212,47 @@

const internalParam = { start, end, condition };
let loopSnippet;
//
if ( isWhile ) {
const startSnippet = internalParam.start;
const endSnippet = internalParam.end;
loopSnippet = `while ( ${ end } )`;
let declarationSnippet = '';
let conditionalSnippet = '';
let updateSnippet = '';
} else {
if ( ! update ) {
const internalParam = { start, end, condition };
if ( type === 'int' || type === 'uint' ) {
//
if ( condition.includes( '<' ) ) update = '++';
else update = '--';
const startSnippet = internalParam.start;
const endSnippet = internalParam.end;
} else {
let declarationSnippet = '';
let conditionalSnippet = '';
let updateSnippet = '';
if ( condition.includes( '<' ) ) update = '+= 1.';
else update = '-= 1.';
if ( ! update ) {
if ( type === 'int' || type === 'uint' ) {
if ( condition.includes( '<' ) ) update = '++';
else update = '--';
} else {
if ( condition.includes( '<' ) ) update = '+= 1.';
else update = '-= 1.';
}
}
}
declarationSnippet += builder.getVar( type, name ) + ' = ' + startSnippet;
declarationSnippet += builder.getVar( type, name ) + ' = ' + startSnippet;
conditionalSnippet += name + ' ' + condition + ' ' + endSnippet;
updateSnippet += name + ' ' + update;
conditionalSnippet += name + ' ' + condition + ' ' + endSnippet;
updateSnippet += name + ' ' + update;
loopSnippet = `for ( ${ declarationSnippet }; ${ conditionalSnippet }; ${ updateSnippet } )`;
const forSnippet = `for ( ${ declarationSnippet }; ${ conditionalSnippet }; ${ updateSnippet } )`;
}
builder.addFlowCode( ( i === 0 ? '\n' : '' ) + builder.tab + forSnippet + ' {\n\n' ).addFlowTab();
builder.addFlowCode( ( i === 0 ? '\n' : '' ) + builder.tab + loopSnippet + ' {\n\n' ).addFlowTab();

@@ -288,3 +318,3 @@ }

*
* @param {...any} params
* @param {...any} params
* @returns {LoopNode}

@@ -294,5 +324,5 @@ */

console.warn( 'TSL.LoopNode: loop() has been renamed to Loop().' );
console.warn( 'THREE.TSL: loop() has been renamed to Loop().' );
return Loop( ...params );
};

@@ -103,2 +103,2 @@ import UniformNode from '../core/UniformNode.js';

*/
export const maxMipLevel = /*@__PURE__*/ nodeProxy( MaxMipLevelNode );
export const maxMipLevel = /*@__PURE__*/ nodeProxy( MaxMipLevelNode ).setParameterLength( 1 );

@@ -79,4 +79,4 @@ import Node from '../core/Node.js';

* @private
* @type {?ReflectorBaseNode}
* @default null
* @type {ReflectorBaseNode}
* @default ReflectorBaseNode
*/

@@ -83,0 +83,0 @@ this._reflectorBaseNode = parameters.reflector || new ReflectorBaseNode( this, parameters );

@@ -104,7 +104,7 @@ import Node from '../core/Node.js';

* @param {Node} inHighNode - The source or current upper bound of the range.
* @param {Node} [outLowNode=float(0)] - The target lower bound of the range.
* @param {Node} [outHighNode=float(1)] - The target upper bound of the range.
* @param {?Node} [outLowNode=float(0)] - The target lower bound of the range.
* @param {?Node} [outHighNode=float(1)] - The target upper bound of the range.
* @returns {RemapNode}
*/
export const remap = /*@__PURE__*/ nodeProxy( RemapNode, null, null, { doClamp: false } );
export const remap = /*@__PURE__*/ nodeProxy( RemapNode, null, null, { doClamp: false } ).setParameterLength( 3, 5 );

@@ -119,9 +119,9 @@ /**

* @param {Node} inHighNode - The source or current upper bound of the range.
* @param {Node} [outLowNode=float(0)] - The target lower bound of the range.
* @param {Node} [outHighNode=float(1)] - The target upper bound of the range.
* @param {?Node} [outLowNode=float(0)] - The target lower bound of the range.
* @param {?Node} [outHighNode=float(1)] - The target upper bound of the range.
* @returns {RemapNode}
*/
export const remapClamp = /*@__PURE__*/ nodeProxy( RemapNode );
export const remapClamp = /*@__PURE__*/ nodeProxy( RemapNode ).setParameterLength( 3, 5 );
addMethodChaining( 'remap', remap );
addMethodChaining( 'remapClamp', remapClamp );

@@ -103,2 +103,2 @@ import TempNode from '../core/TempNode.js';

*/
export const rotate = /*@__PURE__*/ nodeProxy( RotateNode );
export const rotate = /*@__PURE__*/ nodeProxy( RotateNode ).setParameterLength( 2 );

@@ -86,6 +86,6 @@ import Node from '../core/Node.js';

* @param {Node<vec2>} countNode - The node that defines the number of sprites in the x and y direction (e.g 6x6).
* @param {Node<vec2>} [uvNode=uv()] - The uv node.
* @param {Node<float>} [frameNode=float()] - The node that defines the current frame/sprite.
* @param {?Node<vec2>} [uvNode=uv()] - The uv node.
* @param {?Node<float>} [frameNode=float()] - The node that defines the current frame/sprite.
* @returns {SpriteSheetUVNode}
*/
export const spritesheetUV = /*@__PURE__*/ nodeProxy( SpriteSheetUVNode );
export const spritesheetUV = /*@__PURE__*/ nodeProxy( SpriteSheetUVNode ).setParameterLength( 3 );

@@ -143,2 +143,2 @@ import { nodeProxy } from '../tsl/TSLBase.js';

*/
export const storageElement = /*@__PURE__*/ nodeProxy( StorageArrayElementNode );
export const storageElement = /*@__PURE__*/ nodeProxy( StorageArrayElementNode ).setParameterLength( 2 );

@@ -49,3 +49,3 @@ import Node from '../core/Node.js';

*
* @type {Node}
* @type {?Node}
* @default null

@@ -58,3 +58,3 @@ */

*
* @type {Node}
* @type {?Node}
* @default null

@@ -135,3 +135,3 @@ */

*/
export const triplanarTextures = /*@__PURE__*/ nodeProxy( TriplanarTexturesNode );
export const triplanarTextures = /*@__PURE__*/ nodeProxy( TriplanarTexturesNode ).setParameterLength( 1, 6 );

@@ -138,0 +138,0 @@ /**

@@ -449,3 +449,3 @@ import { BufferAttribute } from '../core/BufferAttribute.js';

*
* @param {number} instanceId - The the instance to validate.
* @param {number} instanceId - The instance to validate.
*/

@@ -466,3 +466,3 @@ validateInstanceId( instanceId ) {

*
* @param {number} geometryId - The the geometry to validate.
* @param {number} geometryId - The geometry to validate.
*/

@@ -710,3 +710,3 @@ validateGeometryId( geometryId ) {

*
* @param {number} geometryId - The ID of the geomtry that should be replaced with the given geometry.
* @param {number} geometryId - The ID of the geometry that should be replaced with the given geometry.
* @param {BufferGeometry} geometry - The new geometry.

@@ -824,3 +824,3 @@ * @return {number} The geometry ID.

*
* @param {number} geometryId - The ID of the geomtry to remove from the batch.
* @param {number} geometryId - The ID of the geometry to remove from the batch.
* @return {BatchedMesh} A reference to this batched mesh.

@@ -827,0 +827,0 @@ */

@@ -74,3 +74,3 @@ import { InstancedBufferAttribute } from '../core/InstancedBufferAttribute.js';

*
* @type {?InstancedBufferAttribute}
* @type {?DataTexture}
* @default null

@@ -325,3 +325,3 @@ */

* @param {number} index - The instance index.
* @param {Matrix4} matrix - The the local transformation.
* @param {Matrix4} matrix - The local transformation.
*/

@@ -328,0 +328,0 @@ setMatrixAt( index, matrix ) {

@@ -248,3 +248,3 @@ import { Vector3 } from '../math/Vector3.js';

*
* @param {Camera} camera - The camera the scene is renderd with.
* @param {Camera} camera - The camera the scene is rendered with.
*/

@@ -251,0 +251,0 @@ update( camera ) {

@@ -313,3 +313,3 @@ import {

* @param {Object} json - The skeleton as serialized JSON.
* @param {Array<Bone>} bones - An array of bones.
* @param {Object<string, Bone>} bones - An array of bones.
* @return {Skeleton} A reference of this instance.

@@ -316,0 +316,0 @@ */

@@ -95,3 +95,3 @@

*
* @return {Function} The animation loop.
* @return {?Function} The animation loop.
*/

@@ -107,3 +107,3 @@ getAnimationLoop() {

*
* @param {Function} callback - The animation loop.
* @param {?Function} callback - The animation loop.
*/

@@ -110,0 +110,0 @@ setAnimationLoop( callback ) {

@@ -36,3 +36,3 @@ import DataMap from './DataMap.js';

* @param {BufferAttribute} attribute - The attribute.
* @return {Object} The deleted attribute data.
* @return {Object|null} The deleted attribute data.
*/

@@ -43,3 +43,3 @@ delete( attribute ) {

if ( attributeData !== undefined ) {
if ( attributeData !== null ) {

@@ -46,0 +46,0 @@ this.backend.destroyAttribute( attribute );

@@ -71,2 +71,10 @@ let _vector2 = null;

/**
* Whether to track timestamps with a Timestamp Query API or not.
*
* @type {boolean}
* @default false
*/
this.trackTimestamp = ( parameters.trackTimestamp === true );
}

@@ -348,7 +356,8 @@

* @param {Texture} dstTexture - The destination texture.
* @param {?Vector4} [srcRegion=null] - The region of the source texture to copy.
* @param {?(Box3|Box2)} [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.
* @param {number} [srcLevel=0] - The source mip level to copy from.
* @param {number} [dstLevel=0] - The destination mip level to copy to.
*/
copyTextureToTexture( /*srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0*/ ) {}
copyTextureToTexture( /*srcTexture, dstTexture, srcRegion = null, dstPosition = null, srcLevel = 0, dstLevel = 0*/ ) {}

@@ -355,0 +364,0 @@ /**

@@ -104,2 +104,3 @@ import DataMap from './DataMap.js';

nodeMaterial.depthWrite = false;
nodeMaterial.allowOverride = false;
nodeMaterial.fog = false;

@@ -106,0 +107,0 @@ nodeMaterial.lights = false;

@@ -36,3 +36,3 @@ import { Color } from '../../math/Color.js';

*
* @param {number|string} r - The red value.
* @param {number|string|Color} r - The red value.
* @param {number} g - The green value.

@@ -39,0 +39,0 @@ * @param {number} b - The blue value.

@@ -23,2 +23,8 @@ import { equirectUV } from '../../nodes/utils/EquirectUVNode.js';

/**
* Constructs a new cube render target.
*
* @param {number} [size=1] - The size of the render target.
* @param {RenderTarget~Options} [options] - The configuration object.
*/
constructor( size = 1, options = {} ) {

@@ -28,2 +34,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isCubeRenderTarget = true;

@@ -30,0 +43,0 @@

@@ -103,2 +103,7 @@ import NodeMaterial from '../../../materials/nodes/NodeMaterial.js';

/**
* Constructs a new PMREM generator.
*
* @param {Renderer} renderer - The renderer.
*/
constructor( renderer ) {

@@ -645,2 +650,3 @@

*
* @private
* @param {RenderTarget} cubeUVRenderTarget - The cubemap render target.

@@ -647,0 +653,0 @@ * @param {number} lodIn - The input level-of-detail.

@@ -17,5 +17,5 @@ import BindGroup from '../BindGroup.js';

*
* @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 {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<NodeAttribute>} nodeAttributes - An array of node attributes.

@@ -22,0 +22,0 @@ * @param {Array<BindGroup>} bindings - An array of bind groups.

@@ -17,2 +17,4 @@ import NodeMaterial from '../../materials/nodes/NodeMaterial.js';

* ```
*
* Note: This module can only be used with `WebGPURenderer`.
*/

@@ -19,0 +21,0 @@ class PostProcessing {

@@ -46,2 +46,4 @@ import { BufferGeometry } from '../../core/BufferGeometry.js';

*
* Note: This module can only be used with `WebGPURenderer`.
*
* @augments Mesh

@@ -48,0 +50,0 @@ */

@@ -359,4 +359,4 @@ import { DoubleSide } from '../../constants.js';

*
* @param {function(any, any): number} customOpaqueSort - A custom sort function for opaque objects.
* @param {function(any, any): number} customTransparentSort - A custom sort function for transparent objects.
* @param {?function(any, any): number} customOpaqueSort - A custom sort function for opaque objects.
* @param {?function(any, any): number} customTransparentSort - A custom sort function for transparent objects.
*/

@@ -363,0 +363,0 @@ sort( customOpaqueSort, customTransparentSort ) {

@@ -497,3 +497,3 @@ import { hash, hashString } from '../../nodes/core/NodeUtils.js';

*
* @return {{vertexCount: number, firstVertex: number, instanceCount: number, firstInstance: number}} The draw parameters.
* @return {?{vertexCount: number, firstVertex: number, instanceCount: number, firstInstance: number}} The draw parameters.
*/

@@ -500,0 +500,0 @@ getDrawParameters() {

@@ -87,3 +87,3 @@ import ChainMap from './ChainMap.js';

* @param {ClippingContext} clippingContext - The clipping context.
* @param {?string} passId - An optional ID for identifying the pass.
* @param {string} [passId] - An optional ID for identifying the pass.
* @return {RenderObject} The render object.

@@ -177,3 +177,3 @@ */

* @param {ClippingContext} clippingContext - The clipping context.
* @param {?string} passId - An optional ID for identifying the pass.
* @param {string} [passId] - An optional ID for identifying the pass.
* @return {RenderObject} The render object.

@@ -180,0 +180,0 @@ */

import { ArrayCamera } from '../../cameras/ArrayCamera.js';
import { EventDispatcher } from '../../core/EventDispatcher.js';
import { PerspectiveCamera } from '../../cameras/PerspectiveCamera.js';
import { Quaternion } from '../../math/Quaternion.js';
import { RAD2DEG } from '../../math/MathUtils.js';

@@ -9,5 +10,9 @@ import { Vector2 } from '../../math/Vector2.js';

import { WebXRController } from '../webxr/WebXRController.js';
import { DepthFormat, DepthStencilFormat, RGBAFormat, UnsignedByteType, UnsignedInt248Type, UnsignedIntType } from '../../constants.js';
import { AddEquation, BackSide, CustomBlending, DepthFormat, DepthStencilFormat, FrontSide, RGBAFormat, UnsignedByteType, UnsignedInt248Type, UnsignedIntType, ZeroFactor } from '../../constants.js';
import { DepthTexture } from '../../textures/DepthTexture.js';
import { XRRenderTarget } from './XRRenderTarget.js';
import { CylinderGeometry } from '../../geometries/CylinderGeometry.js';
import { PlaneGeometry } from '../../geometries/PlaneGeometry.js';
import { MeshBasicMaterial } from '../../materials/MeshBasicMaterial.js';
import { Mesh } from '../../objects/Mesh.js';

@@ -151,2 +156,36 @@ const _cameraLPos = /*@__PURE__*/ new Vector3();

/**
* An array holding all the non-projection layers
*
* @private
* @type {Array<Object>}
* @default []
*/
this._layers = [];
/**
* Whether the device has support for all layer types.
*
* @type {boolean}
* @default false
*/
this._supportsLayers = false;
/**
* Helper function to create native WebXR Layer.
*
* @private
* @type {Function}
*/
this._createXRLayer = createXRLayer.bind( this );
/**
* The current WebGL context.
*
* @private
* @type {?WebGL2RenderingContext}
* @default null
*/
this._gl = null;
/**
* The current animation context.

@@ -234,3 +273,3 @@ *

* @private
* @type {string}
* @type {XRReferenceSpaceType}
* @default 'local-floor'

@@ -445,3 +484,3 @@ */

*
* @return {string} The reference space type.
* @return {XRReferenceSpaceType} The reference space type.
*/

@@ -459,3 +498,3 @@ getReferenceSpaceType() {

*
* @param {string} type - The reference space type.
* @param {XRReferenceSpaceType} type - The reference space type.
*/

@@ -510,3 +549,3 @@ setReferenceSpaceType( type ) {

*
* @return {?('opaque'|'additive'|'alpha-blend')} The environment blend mode. Returns `null` when used outside of a XR session.
* @return {'opaque'|'additive'|'alpha-blend'|undefined} The environment blend mode. Returns `undefined` when used outside of a XR session.
*/

@@ -534,2 +573,186 @@ getEnvironmentBlendMode() {

createQuadLayer( width, height, translation, quaternion, pixelwidth, pixelheight, rendercall, attributes = [] ) {
const geometry = new PlaneGeometry( width, height );
const renderTarget = new XRRenderTarget(
pixelwidth,
pixelheight,
{
format: RGBAFormat,
type: UnsignedByteType,
depthTexture: new DepthTexture(
pixelwidth,
pixelheight,
attributes.stencil ? UnsignedInt248Type : UnsignedIntType,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
attributes.stencil ? DepthStencilFormat : DepthFormat
),
stencilBuffer: attributes.stencil,
resolveDepthBuffer: false,
resolveStencilBuffer: false
} );
const material = new MeshBasicMaterial( { color: 0xffffff, side: FrontSide } );
material.map = renderTarget.texture;
material.map.offset.y = 1;
material.map.repeat.y = - 1;
const plane = new Mesh( geometry, material );
plane.position.copy( translation );
plane.quaternion.copy( quaternion );
const layer = {
type: 'quad',
width: width,
height: height,
translation: translation,
quaternion: quaternion,
pixelwidth: pixelwidth,
pixelheight: pixelheight,
plane: plane,
material: material,
rendercall: rendercall,
renderTarget: renderTarget };
this._layers.push( layer );
if ( this._session !== null ) {
layer.plane.material = new MeshBasicMaterial( { color: 0xffffff, side: FrontSide } );
layer.plane.material.blending = CustomBlending;
layer.plane.material.blendEquation = AddEquation;
layer.plane.material.blendSrc = ZeroFactor;
layer.plane.material.blendDst = ZeroFactor;
layer.xrlayer = this._createXRLayer( layer );
const xrlayers = this._session.renderState.layers;
xrlayers.unshift( layer.xrlayer );
this._session.updateRenderState( { layers: xrlayers } );
} else {
renderTarget.isXRRenderTarget = false;
}
return plane;
}
createCylinderLayer( radius, centralAngle, aspectratio, translation, quaternion, pixelwidth, pixelheight, rendercall, attributes = [] ) {
const geometry = new CylinderGeometry( radius, radius, radius * centralAngle / aspectratio, 64, 64, true, Math.PI - centralAngle / 2, centralAngle );
const renderTarget = new XRRenderTarget(
pixelwidth,
pixelheight,
{
format: RGBAFormat,
type: UnsignedByteType,
depthTexture: new DepthTexture(
pixelwidth,
pixelheight,
attributes.stencil ? UnsignedInt248Type : UnsignedIntType,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
attributes.stencil ? DepthStencilFormat : DepthFormat
),
stencilBuffer: attributes.stencil,
resolveDepthBuffer: false,
resolveStencilBuffer: false
} );
const material = new MeshBasicMaterial( { color: 0xffffff, side: BackSide } );
material.map = renderTarget.texture;
material.map.offset.y = 1;
material.map.repeat.y = - 1;
const plane = new Mesh( geometry, material );
plane.position.copy( translation );
plane.quaternion.copy( quaternion );
const layer = {
type: 'cylinder',
radius: radius,
centralAngle: centralAngle,
aspectratio: aspectratio,
translation: translation,
quaternion: quaternion,
pixelwidth: pixelwidth,
pixelheight: pixelheight,
plane: plane,
material: material,
rendercall: rendercall,
renderTarget: renderTarget };
this._layers.push( layer );
if ( this._session !== null ) {
layer.plane.material = new MeshBasicMaterial( { color: 0xffffff, side: BackSide } );
layer.plane.material.blending = CustomBlending;
layer.plane.material.blendEquation = AddEquation;
layer.plane.material.blendSrc = ZeroFactor;
layer.plane.material.blendDst = ZeroFactor;
layer.xrlayer = this._createXRLayer( layer );
const xrlayers = this._session.renderState.layers;
xrlayers.unshift( layer.xrlayer );
this._session.updateRenderState( { layers: xrlayers } );
} else {
renderTarget.isXRRenderTarget = false;
}
return plane;
}
renderLayers( ) {
const translationObject = new Vector3();
const quaternionObject = new Quaternion();
const wasPresenting = this.isPresenting;
this.isPresenting = false;
for ( const layer of this._layers ) {
layer.renderTarget.isXRRenderTarget = this._session !== null;
layer.renderTarget.hasExternalTextures = layer.renderTarget.isXRRenderTarget;
layer.renderTarget.autoAllocateDepthBuffer = ! layer.renderTarget.isXRRenderTarget;
if ( layer.renderTarget.isXRRenderTarget && this._supportsLayers ) {
layer.xrlayer.transform = new XRRigidTransform( layer.plane.getWorldPosition( translationObject ), layer.plane.getWorldQuaternion( quaternionObject ) );
const glSubImage = this._glBinding.getSubImage( layer.xrlayer, this._xrFrame );
this._renderer.backend.setXRRenderTargetTextures(
layer.renderTarget,
glSubImage.colorTexture,
glSubImage.depthStencilTexture );
}
this._renderer.setRenderTarget( layer.renderTarget );
layer.rendercall();
}
this.isPresenting = wasPresenting;
this._renderer.setRenderTarget( null );
}
/**

@@ -560,3 +783,5 @@ * Returns the current XR session.

const gl = renderer.getContext();
this._gl = renderer.getContext();
const gl = this._gl;
const attributes = gl.getContextAttributes();

@@ -613,2 +838,3 @@ this._session = session;

const glProjLayer = glBinding.createProjectionLayer( projectionlayerInit );
const layersArray = [ glProjLayer ];

@@ -618,4 +844,2 @@ this._glBinding = glBinding;

session.updateRenderState( { layers: [ glProjLayer ] } );
renderer.setPixelRatio( 1 );

@@ -633,2 +857,3 @@ renderer.setSize( glProjLayer.textureWidth, glProjLayer.textureHeight, false );

stencilBuffer: renderer.stencil,
samples: attributes.antialias ? 4 : 0,
resolveDepthBuffer: ( glProjLayer.ignoreDepthValues === false ),

@@ -640,2 +865,28 @@ resolveStencilBuffer: ( glProjLayer.ignoreDepthValues === false ),

this._referenceSpace = await session.requestReferenceSpace( this.getReferenceSpaceType() );
this._supportsLayers = session.enabledFeatures.includes( 'layers' );
if ( this._supportsLayers ) {
// switch layers to native
for ( const layer of this._layers ) {
// change material so it "punches" out a hole to show the XR Layer.
layer.plane.material = new MeshBasicMaterial( { color: 0xffffff, side: layer.type === 'cylinder' ? BackSide : FrontSide } );
layer.plane.material.blending = CustomBlending;
layer.plane.material.blendEquation = AddEquation;
layer.plane.material.blendSrc = ZeroFactor;
layer.plane.material.blendDst = ZeroFactor;
layer.xrlayer = this._createXRLayer( layer );
layersArray.unshift( layer.xrlayer );
}
}
session.updateRenderState( { layers: layersArray } );
} else {

@@ -680,4 +931,2 @@

this._referenceSpace = await session.requestReferenceSpace( this.getReferenceSpaceType() );
renderer._animation.setAnimationLoop( this._onAnimationFrame );

@@ -981,2 +1230,3 @@ renderer._animation.setContext( session );

renderer.setOutputRenderTarget( null );
renderer.setRenderTarget( null );

@@ -986,2 +1236,41 @@ this._session = null;

// switch layers back to emulated
if ( this._supportsLayers === true ) {
for ( const layer of this._layers ) {
// Recreate layer render target to reset state
layer.renderTarget = new XRRenderTarget(
layer.pixelwidth,
layer.pixelheight,
{
format: RGBAFormat,
type: UnsignedByteType,
depthTexture: new DepthTexture(
layer.pixelwidth,
layer.pixelheight,
layer.stencilBuffer ? UnsignedInt248Type : UnsignedIntType,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
layer.stencilBuffer ? DepthStencilFormat : DepthFormat
),
stencilBuffer: layer.stencilBuffer,
resolveDepthBuffer: false,
resolveStencilBuffer: false
} );
layer.renderTarget.isXRRenderTarget = false;
layer.plane.material = layer.material;
layer.material.map = layer.renderTarget.texture;
delete layer.xrlayer;
}
}
//

@@ -1073,2 +1362,36 @@

// Creation method for native WebXR layers
function createXRLayer( layer ) {
if ( layer.type === 'quad' ) {
return this._glBinding.createQuadLayer( {
transform: new XRRigidTransform( layer.translation, layer.quaternion ),
depthFormat: this._gl.DEPTH_COMPONENT,
width: layer.width / 2,
height: layer.height / 2,
space: this._referenceSpace,
viewPixelWidth: layer.pixelwidth,
viewPixelHeight: layer.pixelheight
} );
} else {
return this._glBinding.createCylinderLayer( {
transform: new XRRigidTransform( layer.translation, layer.quaternion ),
depthFormat: this._gl.DEPTH_COMPONENT,
radius: layer.radius,
centralAngle: layer.centralAngle,
aspectRatio: layer.aspectRatio,
space: this._referenceSpace,
viewPixelWidth: layer.pixelwidth,
viewPixelHeight: layer.pixelheight
} );
}
}
// Animation Loop
function onAnimationFrame( time, frame ) {

@@ -1075,0 +1398,0 @@

@@ -5,6 +5,3 @@ import { Color } from '../../math/Color.js';

/**
* Uniforms library for shared webgl shaders
*/
// Uniforms library for shared webgl shaders
const UniformsLib = {

@@ -11,0 +8,0 @@

import { ColorManagement } from '../../math/ColorManagement.js';
/**
* Uniform Utilities
*/
// Uniform Utilities

@@ -7,0 +5,0 @@ export function cloneUniforms( src ) {

@@ -82,3 +82,3 @@ import { GLSLNodeParser, NodeBuilder, TextureNode, vectorComponents } from '../../../nodes/Nodes.js';

*
* @type {Object<string,Map<string,Object>>}
* @type {Array<Object<string,AttributeNode|string>>}
*/

@@ -101,10 +101,2 @@ this.transforms = [];

/**
* Whether comparison in shader code are generated with methods or not.
*
* @type {boolean}
* @default true
*/
this.useComparisonMethod = true;
}

@@ -780,3 +772,3 @@

snippet += `${flat} out ${type} ${varying.name};\n`;
snippet += `${flat}out ${type} ${varying.name};\n`;

@@ -1079,6 +1071,5 @@ } else {

const transform = transforms[ i ];
const attributeName = this.getPropertyName( transform.attributeNode );
snippet += `${ transform.varyingName } = ${ attributeName };\n\t`;
if ( attributeName ) snippet += `${ transform.varyingName } = ${ attributeName };\n\t`;

@@ -1085,0 +1076,0 @@ }

@@ -700,7 +700,8 @@ import { LinearFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, NearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, FloatType, MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, SRGBColorSpace, NeverCompare, AlwaysCompare, LessCompare, LessEqualCompare, EqualCompare, GreaterEqualCompare, GreaterCompare, NotEqualCompare } from '../../../constants.js';

* @param {Texture} dstTexture - The destination texture.
* @param {?Vector4} [srcRegion=null] - The region of the source texture to copy.
* @param {?(Box3|Box2)} [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.
* @param {number} [srcLevel=0] - The source mip level to copy from.
* @param {number} [dstLevel=0] - The destination mip level to copy to.
*/
copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) {
copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, srcLevel = 0, dstLevel = 0 ) {

@@ -712,5 +713,9 @@ const { gl, backend } = this;

let width, height, minX, minY;
let dstX, dstY;
state.bindTexture( glTextureType, dstTextureGPU );
// gather the necessary dimensions to copy
let width, height, depth, minX, minY, minZ;
let dstX, dstY, dstZ;
const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ dstLevel ] : srcTexture.image;
if ( srcRegion !== null ) {

@@ -720,11 +725,30 @@

height = srcRegion.max.y - srcRegion.min.y;
depth = srcRegion.isBox3 ? srcRegion.max.z - srcRegion.min.z : 1;
minX = srcRegion.min.x;
minY = srcRegion.min.y;
minZ = srcRegion.isBox3 ? srcRegion.min.z : 0;
} else {
width = srcTexture.image.width;
height = srcTexture.image.height;
const levelScale = Math.pow( 2, - srcLevel );
width = Math.floor( image.width * levelScale );
height = Math.floor( image.height * levelScale );
if ( srcTexture.isDataArrayTexture ) {
depth = image.depth;
} else if ( srcTexture.isData3DTexture ) {
depth = Math.floor( image.depth * levelScale );
} else {
depth = 1;
}
minX = 0;
minY = 0;
minZ = 0;

@@ -737,2 +761,3 @@ }

dstY = dstPosition.y;
dstZ = dstPosition.z;

@@ -743,10 +768,7 @@ } else {

dstY = 0;
dstZ = 0;
}
state.bindTexture( glTextureType, dstTextureGPU );
// As another texture upload may have changed pixelStorei
// parameters, make sure they are correct for the dstTexture
gl.pixelStorei( gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment );
gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY );

@@ -756,2 +778,3 @@ gl.pixelStorei( gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha );

// used for copying data from cpu
const currentUnpackRowLen = gl.getParameter( gl.UNPACK_ROW_LENGTH );

@@ -763,4 +786,2 @@ const currentUnpackImageHeight = gl.getParameter( gl.UNPACK_IMAGE_HEIGHT );

const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ level ] : srcTexture.image;
gl.pixelStorei( gl.UNPACK_ROW_LENGTH, image.width );

@@ -770,3 +791,6 @@ gl.pixelStorei( gl.UNPACK_IMAGE_HEIGHT, image.height );

gl.pixelStorei( gl.UNPACK_SKIP_ROWS, minY );
gl.pixelStorei( gl.UNPACK_SKIP_IMAGES, minZ );
// set up the src texture
const isDst3D = dstTexture.isDataArrayTexture || dstTexture.isData3DTexture;
if ( srcTexture.isRenderTargetTexture || srcTexture.isDepthTexture ) {

@@ -797,15 +821,33 @@

if ( srcTexture.isDataTexture ) {
if ( isDst3D ) {
gl.texSubImage2D( gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image.data );
// copy data into the 3d texture
if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) {
gl.texSubImage3D( glTextureType, dstLevel, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image.data );
} else if ( dstTexture.isCompressedArrayTexture ) {
gl.compressedTexSubImage3D( glTextureType, dstLevel, dstX, dstY, dstZ, width, height, depth, glFormat, image.data );
} else {
gl.texSubImage3D( glTextureType, dstLevel, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image );
}
} else {
if ( srcTexture.isCompressedTexture ) {
// copy data into the 2d texture
if ( srcTexture.isDataTexture ) {
gl.compressedTexSubImage2D( gl.TEXTURE_2D, level, dstX, dstY, image.width, image.height, glFormat, image.data );
gl.texSubImage2D( glTextureType, dstLevel, dstX, dstY, width, height, glFormat, glType, image.data );
} else if ( srcTexture.isCompressedTexture ) {
gl.compressedTexSubImage2D( glTextureType, dstLevel, dstX, dstY, image.width, image.height, glFormat, image.data );
} else {
gl.texSubImage2D( gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image );
gl.texSubImage2D( glTextureType, dstLevel, dstX, dstY, width, height, glFormat, glType, image );

@@ -818,2 +860,3 @@ }

// reset values
gl.pixelStorei( gl.UNPACK_ROW_LENGTH, currentUnpackRowLen );

@@ -826,4 +869,8 @@ gl.pixelStorei( gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight );

// Generate mipmaps only when copying level 0
if ( level === 0 && dstTexture.generateMipmaps ) gl.generateMipmap( gl.TEXTURE_2D );
if ( dstLevel === 0 && dstTexture.generateMipmaps ) {
gl.generateMipmap( glTextureType );
}
state.unbindTexture();

@@ -833,2 +880,3 @@

/**

@@ -835,0 +883,0 @@ * Copies the current bound framebuffer to the given texture.

@@ -48,3 +48,3 @@ 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';

* @param {string} [colorSpace=NoColorSpace] - The color space.
* @return {number} The corresponding WebGL constant.
* @return {?number} The corresponding WebGL constant.
*/

@@ -51,0 +51,0 @@ convert( p, colorSpace = NoColorSpace ) {

@@ -27,13 +27,19 @@ import GLSLNodeBuilder from './nodes/GLSLNodeBuilder.js';

/**
* WebGLBackend options.
*
* @typedef {Object} WebGLBackend~Options
* @property {boolean} [logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not.
* @property {boolean} [alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque.
* @property {boolean} [depth=true] - Whether the default framebuffer should have a depth buffer or not.
* @property {boolean} [stencil=false] - Whether the default framebuffer should have a stencil buffer or not.
* @property {boolean} [antialias=false] - Whether MSAA as the default anti-aliasing should be enabled or not.
* @property {number} [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.
* @property {boolean} [forceWebGL=false] - If set to `true`, the renderer uses a WebGL 2 backend no matter if WebGPU is supported or not.
* @property {WebGL2RenderingContext} [context=undefined] - A WebGL 2 rendering context.
*/
/**
* 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.
* @param {WebGLBackend~Options} [parameters] - The configuration parameter.
*/

@@ -166,10 +172,2 @@ constructor( parameters = {} ) {

/**
* 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.

@@ -365,7 +363,5 @@ *

renderTarget.autoAllocateDepthBuffer = false;
// The multisample_render_to_texture extension doesn't work properly if there
// are midframe flushes and an external depth texture.
if ( this.extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) {
if ( ( this.extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) && renderTarget.autoAllocateDepthBuffer ) {

@@ -376,2 +372,4 @@ console.warn( 'THREE.WebGLBackend: Render-to-texture extension was disabled because an external texture was provided' );

renderTarget.autoAllocateDepthBuffer = false;
}

@@ -1893,9 +1891,10 @@

* @param {Texture} dstTexture - The destination texture.
* @param {?Vector4} [srcRegion=null] - The region of the source texture to copy.
* @param {?(Box3|Box2)} [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.
* @param {number} [srcLevel=0] - The source mip level to copy from.
* @param {number} [dstLevel=0] - The destination mip level to copy to.
*/
copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) {
copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, srcLevel = 0, dstLevel = 0 ) {
this.textureUtils.copyTextureToTexture( srcTexture, dstTexture, srcRegion, dstPosition, level );
this.textureUtils.copyTextureToTexture( srcTexture, dstTexture, srcRegion, dstPosition, srcLevel, dstLevel );

@@ -2007,3 +2006,3 @@ }

if ( useMultisampledRTT ) {
if ( hasExternalTextures && useMultisampledRTT ) {

@@ -2041,3 +2040,3 @@ multisampledRTTExt.framebufferTexture2DMultisampleEXT( gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureData.textureGPU, 0, samples );

if ( useMultisampledRTT ) {
if ( hasExternalTextures && useMultisampledRTT ) {

@@ -2044,0 +2043,0 @@ multisampledRTTExt.framebufferTexture2DMultisampleEXT( gl.FRAMEBUFFER, depthStyle, gl.TEXTURE_2D, textureData.textureGPU, 0, samples );

@@ -104,3 +104,4 @@ import { BackSide, FrontSide, CubeUVReflectionMapping, SRGBTransfer } from '../../constants.js';

depthWrite: false,
fog: false
fog: false,
allowOverride: false
} )

@@ -184,3 +185,4 @@ );

depthWrite: false,
fog: false
fog: false,
allowOverride: false
} )

@@ -187,0 +189,0 @@ );

@@ -81,4 +81,4 @@ import { NotEqualDepth, GreaterDepth, GreaterEqualDepth, EqualDepth, LessEqualDepth, LessDepth, AlwaysDepth, NeverDepth, CullFaceFront, CullFaceBack, CullFaceNone, DoubleSide, BackSide, CustomBlending, MultiplyBlending, SubtractiveBlending, AdditiveBlending, NoBlending, NormalBlending, AddEquation, SubtractEquation, ReverseSubtractEquation, MinEquation, MaxEquation, ZeroFactor, OneFactor, SrcColorFactor, SrcAlphaFactor, SrcAlphaSaturateFactor, DstColorFactor, DstAlphaFactor, OneMinusSrcColorFactor, OneMinusSrcAlphaFactor, OneMinusDstColorFactor, OneMinusDstAlphaFactor, ConstantColorFactor, OneMinusConstantColorFactor, ConstantAlphaFactor, OneMinusConstantAlphaFactor } from '../../constants.js';

let locked = false;
let reversed = false;
let currentReversed = false;
let currentDepthMask = null;

@@ -90,5 +90,5 @@ let currentDepthFunc = null;

setReversed: function ( value ) {
setReversed: function ( reversed ) {
if ( reversed !== value ) {
if ( currentReversed !== reversed ) {

@@ -107,2 +107,4 @@ const ext = extensions.get( 'EXT_clip_control' );

currentReversed = reversed;
const oldDepth = currentDepthClear;

@@ -114,4 +116,2 @@ currentDepthClear = null;

reversed = value;
},

@@ -121,3 +121,3 @@

return reversed;
return currentReversed;

@@ -153,3 +153,3 @@ },

if ( reversed ) depthFunc = reversedFuncs[ depthFunc ];
if ( currentReversed ) depthFunc = reversedFuncs[ depthFunc ];

@@ -222,3 +222,3 @@ if ( currentDepthFunc !== depthFunc ) {

if ( reversed ) {
if ( currentReversed ) {

@@ -243,3 +243,3 @@ depth = 1 - depth;

currentDepthClear = null;
reversed = false;
currentReversed = false;

@@ -246,0 +246,0 @@ }

import { WebGLRenderTarget } from './WebGLRenderTarget.js';
import { Data3DTexture } from '../textures/Data3DTexture.js';
/**
* A 3D render target used in context of {@link WebGLRenderer}.
*
* @augments WebGLRenderTarget
*/
class WebGL3DRenderTarget extends WebGLRenderTarget {
/**
* Constructs a new 3D render target.
*
* @param {number} [width=1] - The width of the render target.
* @param {number} [height=1] - The height of the render target.
* @param {number} [depth=1] - The height of the render target.
* @param {RenderTarget~Options} [options] - The configuration object.
*/
constructor( width = 1, height = 1, depth = 1, options = {} ) {

@@ -10,2 +23,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isWebGL3DRenderTarget = true;

@@ -15,2 +35,7 @@

/**
* Overwritten with a different texture type.
*
* @type {Data3DTexture}
*/
this.texture = new Data3DTexture( null, width, height, depth );

@@ -17,0 +42,0 @@

import { WebGLRenderTarget } from './WebGLRenderTarget.js';
import { DataArrayTexture } from '../textures/DataArrayTexture.js';
/**
* An array render target used in context of {@link WebGLRenderer}.
*
* @augments WebGLRenderTarget
*/
class WebGLArrayRenderTarget extends WebGLRenderTarget {
/**
* Constructs a new array render target.
*
* @param {number} [width=1] - The width of the render target.
* @param {number} [height=1] - The height of the render target.
* @param {number} [depth=1] - The height of the render target.
* @param {RenderTarget~Options} [options] - The configuration object.
*/
constructor( width = 1, height = 1, depth = 1, options = {} ) {

@@ -10,2 +23,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isWebGLArrayRenderTarget = true;

@@ -15,2 +35,7 @@

/**
* Overwritten with a different texture type.
*
* @type {DataArrayTexture}
*/
this.texture = new DataArrayTexture( null, width, height, depth );

@@ -17,0 +42,0 @@

@@ -10,4 +10,15 @@ import { BackSide, LinearFilter, LinearMipmapLinearFilter, NoBlending } from '../constants.js';

/**
* A cube render target used in context of {@link WebGLRenderer}.
*
* @augments WebGLRenderTarget
*/
class WebGLCubeRenderTarget extends WebGLRenderTarget {
/**
* Constructs a new cube render target.
*
* @param {number} [size=1] - The size of the render target.
* @param {RenderTarget~Options} [options] - The configuration object.
*/
constructor( size = 1, options = {} ) {

@@ -17,2 +28,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isWebGLCubeRenderTarget = true;

@@ -23,2 +41,7 @@

/**
* Overwritten with a different texture type.
*
* @type {DataArrayTexture}
*/
this.texture = new CubeTexture( images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace );

@@ -41,2 +64,9 @@

/**
* Converts the given equirectangular texture to a cube map.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {Texture} texture - The equirectangular texture.
* @return {WebGLCubeRenderTarget} A reference to this cube render target.
*/
fromEquirectangularTexture( renderer, texture ) {

@@ -132,3 +162,11 @@

clear( renderer, color, depth, stencil ) {
/**
* Clears this cube render target.
*
* @param {WebGLRenderer} renderer - The renderer.
* @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.
*/
clear( renderer, color = true, depth = true, stencil = true ) {

@@ -135,0 +173,0 @@ const currentRenderTarget = renderer.getRenderTarget();

import { RenderTarget } from '../core/RenderTarget.js';
/**
* A render target used in context of {@link WebGLRenderer}.
*
* @augments RenderTarget
*/
class WebGLRenderTarget extends RenderTarget {
/**
* Constructs a new 3D render target.
*
* @param {number} [width=1] - The width of the render target.
* @param {number} [height=1] - The height of the render target.
* @param {RenderTarget~Options} [options] - The configuration object.
*/
constructor( width = 1, height = 1, options = {} ) {

@@ -9,2 +21,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isWebGLRenderTarget = true;

@@ -11,0 +30,0 @@

@@ -324,3 +324,3 @@ import NodeUniformsGroup from '../../common/nodes/NodeUniformsGroup.js';

const functionName = `tsl_coord_${ wrapNames[ texture.wrapS ] }S_${ wrapNames[ texture.wrapT ] }_${texture.isData3DTexture ? '3d' : '2d'}T`;
const functionName = `tsl_coord_${ wrapNames[ texture.wrapS ] }S_${ wrapNames[ texture.wrapT ] }_${ texture.isData3DTexture ? '3d' : '2d' }T`;

@@ -335,3 +335,3 @@ let nodeCode = wgslCodeCache[ functionName ];

const coordType = texture.isData3DTexture ? 'vec3f' : 'vec2f';
let code = `fn ${functionName}( coord : ${coordType} ) -> ${coordType} {\n\n\treturn ${coordType}(\n`;
let code = `fn ${ functionName }( coord : ${ coordType } ) -> ${ coordType } {\n\n\treturn ${ coordType }(\n`;

@@ -408,3 +408,3 @@ const addWrapSnippet = ( wrap, axis ) => {

* 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
* It also returns information about the number of layers (elements) of an arrayed
* texture as well as the cube face count of cube textures.

@@ -522,3 +522,3 @@ *

const vecType = texture.isData3DTexture ? 'vec3' : 'vec2';
const coordSnippet = `${vecType}<u32>(${wrapFunction}(${uvSnippet}) * ${vecType}<f32>(${textureDimension}))`;
const coordSnippet = `${ vecType }<u32>(${ wrapFunction }(${ uvSnippet }) * ${ vecType }<f32>(${ textureDimension }))`;

@@ -525,0 +525,0 @@ return this.generateTextureLoad( texture, textureProperty, coordSnippet, depthSnippet, levelSnippet );

@@ -74,7 +74,7 @@ import { GPUInputStepMode } from './WebGPUConstants.js';

if ( array.constructor === Int16Array ) {
if ( array.constructor === Int16Array || array.constructor === Int8Array ) {
array = new Int32Array( array );
} else if ( array.constructor === Uint16Array ) {
} else if ( array.constructor === Uint16Array || array.constructor === Uint8Array ) {

@@ -206,5 +206,7 @@ array = new Uint32Array( array );

const bufferOffset = dataOffset * ( isTypedArray ? array.BYTES_PER_ELEMENT : 1 ); // bufferOffset is always in bytes
device.queue.writeBuffer(
buffer,
0,
bufferOffset,
array,

@@ -211,0 +213,0 @@ dataOffset,

@@ -116,3 +116,3 @@ export const GPUPrimitiveTopology = {

RGB10A2Unorm: 'rgb10a2unorm',
RG11B10uFloat: 'rgb10a2unorm',
RG11B10UFloat: 'rgb10a2unorm',

@@ -119,0 +119,0 @@ // 64-bit formats

@@ -880,3 +880,3 @@ import {

if ( format === GPUTextureFormat.BC3RGBAUnorm || format === GPUTextureFormat.BC3RGBAUnormSRGB ) return { byteLength: 16, width: 4, height: 4 }; // DXT5
if ( format === GPUTextureFormat.BC4RUnorm || format === GPUTextureFormat.BC4RSNorm ) return { byteLength: 8, width: 4, height: 4 }; // RGTC1
if ( format === GPUTextureFormat.BC4RUnorm || format === GPUTextureFormat.BC4RSnorm ) return { byteLength: 8, width: 4, height: 4 }; // RGTC1
if ( format === GPUTextureFormat.BC5RGUnorm || format === GPUTextureFormat.BC5RGSnorm ) return { byteLength: 16, width: 4, height: 4 }; // RGTC2

@@ -883,0 +883,0 @@ if ( format === GPUTextureFormat.BC6HRGBUFloat || format === GPUTextureFormat.BC6HRGBFloat ) return { byteLength: 16, width: 4, height: 4 }; // BPTC (float)

@@ -29,17 +29,23 @@ /*// debugger tools

/**
* WebGPUBackend options.
*
* @typedef {Object} WebGPUBackend~Options
* @property {boolean} [logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not.
* @property {boolean} [alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque.
* @property {boolean} [depth=true] - Whether the default framebuffer should have a depth buffer or not.
* @property {boolean} [stencil=false] - Whether the default framebuffer should have a stencil buffer or not.
* @property {boolean} [antialias=false] - Whether MSAA as the default anti-aliasing should be enabled or not.
* @property {number} [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.
* @property {boolean} [forceWebGL=false] - If set to `true`, the renderer uses a WebGL 2 backend no matter if WebGPU is supported or not.
* @property {boolean} [trackTimestamp=false] - Whether to track timestamps with a Timestamp Query API or not.
* @property {string} [powerPreference=undefined] - The power preference.
* @property {Object} [requiredLimits=undefined] - Specifies the limits that are required by the device request. The request will fail if the adapter cannot provide these limits.
* @property {GPUDevice} [device=undefined] - If there is an existing GPU device on app level, it can be passed to the renderer as a parameter.
* @property {number} [outputType=undefined] - Texture type for output to canvas. By default, device's preferred format is used; other formats may incur overhead.
*/
/**
* 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.
* @param {number} [parameters.outputType=undefined] - Texture type for output to canvas. By default, device's preferred format is used; other formats may incur overhead.
* @param {WebGPUBackend~Options} [parameters] - The configuration parameter.
*/

@@ -65,10 +71,2 @@ constructor( parameters = {} ) {

/**
* 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.

@@ -368,6 +366,5 @@ *

renderTargetData.dimensions !== renderTarget.dimensions ||
renderTargetData.activeMipmapLevel !== renderTarget.activeMipmapLevel ||
renderTargetData.activeMipmapLevel !== renderContext.activeMipmapLevel ||
renderTargetData.activeCubeFace !== renderContext.activeCubeFace ||
renderTargetData.samples !== renderTarget.samples ||
renderTargetData.loadOp !== colorAttachmentsConfig.loadOp
renderTargetData.samples !== renderTarget.samples
) {

@@ -384,3 +381,2 @@

renderTarget.removeEventListener( 'dispose', onDispose );
this.delete( renderTarget );

@@ -390,14 +386,17 @@

renderTarget.addEventListener( 'dispose', onDispose );
if ( renderTarget.hasEventListener( 'dispose', onDispose ) === false ) {
renderTarget.addEventListener( 'dispose', onDispose );
}
}
const cacheKey = renderContext.getCacheKey();
let descriptorBase = descriptors[ cacheKey ];
let descriptor = descriptors[ cacheKey ];
if ( descriptorBase === undefined ) {
if ( descriptor === undefined ) {
const textures = renderContext.textures;
const colorAttachments = [];
const textureViews = [];

@@ -450,19 +449,6 @@ let sliceIndex;

// only apply the user-defined clearValue to the first color attachment like in beginRender()
let clearValue = { r: 0, g: 0, b: 0, a: 1 };
if ( i === 0 && colorAttachmentsConfig.clearValue ) {
clearValue = colorAttachmentsConfig.clearValue;
}
colorAttachments.push( {
textureViews.push( {
view,
depthSlice: sliceIndex,
resolveTarget,
loadOp: colorAttachmentsConfig.loadOP || GPULoadOp.Load,
storeOp: colorAttachmentsConfig.storeOP || GPUStoreOp.Store,
clearValue: clearValue
depthSlice: sliceIndex
} );

@@ -472,19 +458,12 @@

descriptorBase = { textureViews };
descriptor = {
colorAttachments,
};
if ( renderContext.depth ) {
const depthTextureData = this.get( renderContext.depthTexture );
descriptorBase.depthStencilView = depthTextureData.texture.createView();
const depthStencilAttachment = {
view: depthTextureData.texture.createView()
};
descriptor.depthStencilAttachment = depthStencilAttachment;
}
descriptors[ cacheKey ] = descriptor;
descriptors[ cacheKey ] = descriptorBase;

@@ -497,7 +476,40 @@ renderTargetData.width = renderTarget.width;

renderTargetData.dimensions = renderTarget.dimensions;
renderTargetData.depthSlice = sliceIndex;
renderTargetData.loadOp = colorAttachments[ 0 ].loadOp;
}
const descriptor = {
colorAttachments: []
};
// Apply dynamic properties to cached views
for ( let i = 0; i < descriptorBase.textureViews.length; i ++ ) {
const viewInfo = descriptorBase.textureViews[ i ];
let clearValue = { r: 0, g: 0, b: 0, a: 1 };
if ( i === 0 && colorAttachmentsConfig.clearValue ) {
clearValue = colorAttachmentsConfig.clearValue;
}
descriptor.colorAttachments.push( {
view: viewInfo.view,
depthSlice: viewInfo.depthSlice,
resolveTarget: viewInfo.resolveTarget,
loadOp: colorAttachmentsConfig.loadOp || GPULoadOp.Load,
storeOp: colorAttachmentsConfig.storeOp || GPUStoreOp.Store,
clearValue: clearValue
} );
}
if ( descriptorBase.depthStencilView ) {
descriptor.depthStencilAttachment = {
view: descriptorBase.depthStencilView
};
}
return descriptor;

@@ -878,3 +890,2 @@

let colorAttachments = [];
let depthStencilAttachment;

@@ -923,26 +934,32 @@ let clearValue;

if ( color ) {
const clearConfig = {
loadOp: color ? GPULoadOp.Clear : GPULoadOp.Load,
clearValue: color ? clearValue : undefined
};
const descriptor = this._getRenderPassDescriptor( renderTargetContext, { loadOp: GPULoadOp.Clear, clearValue } );
if ( supportsDepth ) {
colorAttachments = descriptor.colorAttachments;
clearConfig.depthLoadOp = depth ? GPULoadOp.Clear : GPULoadOp.Load;
clearConfig.depthClearValue = depth ? renderer.getClearDepth() : undefined;
clearConfig.depthStoreOp = GPUStoreOp.Store;
}
if ( supportsDepth || supportsStencil ) {
if ( supportsStencil ) {
const depthTextureData = this.get( renderTargetContext.depthTexture );
clearConfig.stencilLoadOp = stencil ? GPULoadOp.Clear : GPULoadOp.Load;
clearConfig.stencilClearValue = stencil ? renderer.getClearStencil() : undefined;
clearConfig.stencilStoreOp = GPUStoreOp.Store;
depthStencilAttachment = {
view: depthTextureData.texture.createView()
};
}
const descriptor = this._getRenderPassDescriptor( renderTargetContext, clearConfig );
colorAttachments = descriptor.colorAttachments;
depthStencilAttachment = descriptor.depthStencilAttachment;
}
//
if ( supportsDepth && depthStencilAttachment && depthStencilAttachment.depthLoadOp === undefined ) {
if ( supportsDepth ) {
if ( depth ) {

@@ -965,3 +982,3 @@

if ( supportsStencil ) {
if ( supportsStencil && depthStencilAttachment && depthStencilAttachment.stencilLoadOp === undefined ) {

@@ -1879,29 +1896,47 @@ if ( stencil ) {

* @param {Texture} dstTexture - The destination texture.
* @param {?Vector4} [srcRegion=null] - The region of the source texture to copy.
* @param {?(Box3|Box2)} [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.
* @param {number} [srcLevel=0] - The mipmap level to copy.
* @param {number} [dstLevel=0] - The destination mip level to copy to.
*/
copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) {
copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, srcLevel = 0, dstLevel = 0 ) {
let dstX = 0;
let dstY = 0;
let dstLayer = 0;
let dstZ = 0;
let srcX = 0;
let srcY = 0;
let srcLayer = 0;
let srcZ = 0;
let srcWidth = srcTexture.image.width;
let srcHeight = srcTexture.image.height;
let srcDepth = 1;
if ( srcRegion !== null ) {
srcX = srcRegion.x;
srcY = srcRegion.y;
srcLayer = srcRegion.z || 0;
srcWidth = srcRegion.width;
srcHeight = srcRegion.height;
if ( srcRegion.isBox3 === true ) {
srcX = srcRegion.min.x;
srcY = srcRegion.min.y;
srcZ = srcRegion.min.z;
srcWidth = srcRegion.max.x - srcRegion.min.x;
srcHeight = srcRegion.max.y - srcRegion.min.y;
srcDepth = srcRegion.max.z - srcRegion.min.z;
} else {
// Assume it's a Box2
srcX = srcRegion.min.x;
srcY = srcRegion.min.y;
srcWidth = srcRegion.max.x - srcRegion.min.x;
srcHeight = srcRegion.max.y - srcRegion.min.y;
srcDepth = 1;
}
}
if ( dstPosition !== null ) {

@@ -1911,3 +1946,3 @@

dstY = dstPosition.y;
dstLayer = dstPosition.z || 0;
dstZ = dstPosition.z || 0;

@@ -1924,9 +1959,9 @@ }

texture: sourceGPU,
mipLevel: level,
origin: { x: srcX, y: srcY, z: srcLayer }
mipLevel: srcLevel,
origin: { x: srcX, y: srcY, z: srcZ }
},
{
texture: destinationGPU,
mipLevel: level,
origin: { x: dstX, y: dstY, z: dstLayer }
mipLevel: dstLevel,
origin: { x: dstX, y: dstY, z: dstZ }
},

@@ -1936,3 +1971,3 @@ [

srcHeight,
1
srcDepth
]

@@ -1943,2 +1978,8 @@ );

if ( dstLevel === 0 && dstTexture.generateMipmaps ) {
this.textureUtils.generateMipmaps( dstTexture );
}
}

@@ -1945,0 +1986,0 @@

@@ -30,16 +30,22 @@ import Renderer from '../common/Renderer.js';

/**
* Constructs a new WebGPU renderer.
* WebGPURenderer options.
*
* @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 {number} [parameters.outputType=undefined] - Texture type for output to canvas. By default, device's preferred format is used; other formats may incur overhead.
* @param {number} [parameters.colorBufferType=HalfFloatType] - Defines the type of color buffers. The default `HalfFloatType` is recommend for best
* @typedef {Object} WebGPURenderer~Options
* @property {boolean} [logarithmicDepthBuffer=false] - Whether logarithmic depth buffer is enabled or not.
* @property {boolean} [alpha=true] - Whether the default framebuffer (which represents the final contents of the canvas) should be transparent or opaque.
* @property {boolean} [depth=true] - Whether the default framebuffer should have a depth buffer or not.
* @property {boolean} [stencil=false] - Whether the default framebuffer should have a stencil buffer or not.
* @property {boolean} [antialias=false] - Whether MSAA as the default anti-aliasing should be enabled or not.
* @property {number} [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.
* @property {boolean} [forceWebGL=false] - If set to `true`, the renderer uses a WebGL 2 backend no matter if WebGPU is supported or not.
* @property {number} [outputType=undefined] - Texture type for output to canvas. By default, device's preferred format is used; other formats may incur overhead.
* @property {number} [colorBufferType=HalfFloatType] - Defines the type of color buffers. The default `HalfFloatType` is recommend for best
* quality. To save memory and bandwidth, `UnsignedByteType` might be used. This will reduce rendering quality though.
*/
/**
* Constructs a new WebGPU renderer.
*
* @param {WebGPURenderer~Options} [parameters] - The configuration parameter.
*/
constructor( parameters = {} ) {

@@ -46,0 +52,0 @@

@@ -18,13 +18,3 @@ import Renderer from '../common/Renderer.js';

*
* @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.
* @param {number} [parameters.outputType=undefined] - Texture type for output to canvas. By default, device's preferred format is used; other formats may incur overhead.
* @param {number} [parameters.colorBufferType=HalfFloatType] - Defines the type of color buffers. The default `HalfFloatType` is recommend for best
* quality. To save memory and bandwidth, `UnsignedByteType` might be used. This will reduce rendering quality though.
* @param {WebGPURenderer~Options} [parameters] - The configuration parameter.
*/

@@ -31,0 +21,0 @@ constructor( parameters = {} ) {

@@ -6,8 +6,43 @@ import { Vector3 } from '../../math/Vector3.js';

/**
* Class for representing a XR controller with its
* different coordinate systems.
*
* @private
*/
class WebXRController {
/**
* Constructs a new XR controller.
*/
constructor() {
/**
* A group representing the target ray space
* of the XR controller.
*
* @private
* @type {?Group}
* @default null
*/
this._targetRay = null;
/**
* A group representing the grip space
* of the XR controller.
*
* @private
* @type {?Group}
* @default null
*/
this._grip = null;
/**
* A group representing the hand space
* of the XR controller.
*
* @private
* @type {?Group}
* @default null
*/
this._hand = null;

@@ -17,2 +52,7 @@

/**
* Returns a group representing the hand space of the XR controller.
*
* @return {Group} A group representing the hand space of the XR controller.
*/
getHandSpace() {

@@ -35,2 +75,7 @@

/**
* Returns a group representing the target ray space of the XR controller.
*
* @return {Group} A group representing the target ray space of the XR controller.
*/
getTargetRaySpace() {

@@ -54,2 +99,7 @@

/**
* Returns a group representing the grip space of the XR controller.
*
* @return {Group} A group representing the grip space of the XR controller.
*/
getGripSpace() {

@@ -73,2 +123,9 @@

/**
* Dispatches the given event to the groups representing
* the different coordinate spaces of the XR controller.
*
* @param {Object} event - The event to dispatch.
* @return {WebXRController} A reference to this instance.
*/
dispatchEvent( event ) {

@@ -98,2 +155,8 @@

/**
* Connects the controller with the given XR input source.
*
* @param {XRInputSource} inputSource - The input source.
* @return {WebXRController} A reference to this instance.
*/
connect( inputSource ) {

@@ -124,2 +187,8 @@

/**
* Disconnects the controller from the given XR input source.
*
* @param {XRInputSource} inputSource - The input source.
* @return {WebXRController} A reference to this instance.
*/
disconnect( inputSource ) {

@@ -151,2 +220,12 @@

/**
* Updates the controller with the given input source, XR frame and reference space.
* This updates the transformations of the groups that represent the different
* coordinate systems of the controller.
*
* @param {XRInputSource} inputSource - The input source.
* @param {XRFrame} frame - The XR frame.
* @param {XRReferenceSpace} referenceSpace - The reference space.
* @return {WebXRController} A reference to this instance.
*/
update( inputSource, frame, referenceSpace ) {

@@ -329,4 +408,10 @@

// private method
/**
* Returns a group representing the hand joint for the given input joint.
*
* @private
* @param {Group} hand - The group representing the hand space.
* @param {XRHandJoint} inputjoint - The XR frame.
* @return {Group} A group representing the hand joint for the given input joint.
*/
_getHandJoint( hand, inputjoint ) {

@@ -333,0 +418,0 @@

@@ -34,10 +34,38 @@ import { PlaneGeometry } from '../../geometries/PlaneGeometry.js';

/**
* A XR module that manages the access to the Depth Sensing API.
*/
class WebXRDepthSensing {
/**
* Constructs a new depth sensing module.
*/
constructor() {
/**
* A texture representing the depth of the user's environment.
*
* @type {?Texture}
*/
this.texture = null;
/**
* A plane mesh for visualizing the depth texture.
*
* @type {?Mesh}
*/
this.mesh = null;
/**
* The depth near value.
*
* @type {number}
*/
this.depthNear = 0;
/**
* The depth near far.
*
* @type {number}
*/
this.depthFar = 0;

@@ -47,2 +75,9 @@

/**
* Inits the depth sensing module
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {XRWebGLDepthInformation} depthData - The XR depth data.
* @param {XRRenderState} renderState - The XR render state.
*/
init( renderer, depthData, renderState ) {

@@ -70,2 +105,8 @@

/**
* Returns a plane mesh that visualizes the depth texture.
*
* @param {ArrayCamera} cameraXR - The XR camera.
* @return {?Mesh} The plane mesh.
*/
getMesh( cameraXR ) {

@@ -98,2 +139,5 @@

/**
* Resets the module
*/
reset() {

@@ -106,2 +150,7 @@

/**
* Returns a texture representing the depth of the user's environment.
*
* @return {?Texture} The depth texture.
*/
getDepthTexture() {

@@ -108,0 +157,0 @@

@@ -15,4 +15,19 @@ import { ArrayCamera } from '../../cameras/ArrayCamera.js';

/**
* This class represents an abstraction of the WebXR Device API and is
* internally used by {@link WebGLRenderer}. `WebXRManager` also provides a public
* interface that allows users to enable/disable XR and perform XR related
* tasks like for instance retrieving controllers.
*
* @augments EventDispatcher
* @hideconstructor
*/
class WebXRManager extends EventDispatcher {
/**
* Constructs a new WebGL renderer.
*
* @param {WebGLRenderer} renderer - The renderer.
* @param {WebGL2RenderingContext} gl - The rendering context.
*/
constructor( renderer, gl ) {

@@ -69,7 +84,36 @@

/**
* Whether the manager's XR camera should be automatically updated or not.
*
* @type {boolean}
* @default true
*/
this.cameraAutoUpdate = true;
/**
* This flag notifies the renderer to be ready for XR rendering. Set it to `true`
* if you are going to use XR in your app.
*
* @type {boolean}
* @default false
*/
this.enabled = false;
/**
* Whether XR presentation is active or not.
*
* @type {boolean}
* @readonly
* @default false
*/
this.isPresenting = false;
/**
* Returns a group representing the `target ray` space of the XR controller.
* Use this space for visualizing 3D objects that support the user in pointing
* tasks like UI interaction.
*
* @param {number} index - The index of the controller.
* @return {Group} A group representing the `target ray` space.
*/
this.getController = function ( index ) {

@@ -90,2 +134,17 @@

/**
* Returns a group representing the `grip` space of the XR controller.
* Use this space for visualizing 3D objects that support the user in pointing
* tasks like UI interaction.
*
* Note: If you want to show something in the user's hand AND offer a
* pointing ray at the same time, you'll want to attached the handheld object
* to the group returned by `getControllerGrip()` and the ray to the
* group returned by `getController()`. The idea is to have two
* different groups in two different coordinate spaces for the same WebXR
* controller.
*
* @param {number} index - The index of the controller.
* @return {Group} A group representing the `grip` space.
*/
this.getControllerGrip = function ( index ) {

@@ -106,2 +165,10 @@

/**
* Returns a group representing the `hand` space of the XR controller.
* Use this space for visualizing 3D objects that support the user in pointing
* tasks like UI interaction.
*
* @param {number} index - The index of the controller.
* @return {Group} A group representing the `hand` space.
*/
this.getHand = function ( index ) {

@@ -196,2 +263,9 @@

/**
* Sets the framebuffer scale factor.
*
* This method can not be used during a XR session.
*
* @param {number} value - The framebuffer scale factor.
*/
this.setFramebufferScaleFactor = function ( value ) {

@@ -209,2 +283,11 @@

/**
* Sets the reference space type. Can be used to configure a spatial relationship with the user's physical
* environment. Depending on how the user moves in 3D space, setting an appropriate reference space can
* improve tracking. Default is `local-floor`.
*
* This method can not be used during a XR session.
*
* @param {string} value - The reference space type.
*/
this.setReferenceSpaceType = function ( value ) {

@@ -222,2 +305,7 @@

/**
* Returns the XR reference space.
*
* @return {XRReferenceSpace} The XR reference space.
*/
this.getReferenceSpace = function () {

@@ -229,2 +317,7 @@

/**
* Sets a custom XR reference space.
*
* @param {XRReferenceSpace} space - The XR reference space.
*/
this.setReferenceSpace = function ( space ) {

@@ -236,2 +329,7 @@

/**
* Returns the current base layer.
*
* @return {?(XRWebGLLayer|XRProjectionLayer)} The XR base layer.
*/
this.getBaseLayer = function () {

@@ -243,2 +341,7 @@

/**
* Returns the current XR binding.
*
* @return {?XRWebGLBinding} The XR binding.
*/
this.getBinding = function () {

@@ -250,2 +353,7 @@

/**
* Returns the current XR frame.
*
* @return {?XRFrame} The XR frame. Returns `null` when used outside a XR session.
*/
this.getFrame = function () {

@@ -257,2 +365,7 @@

/**
* Returns the current XR session.
*
* @return {?XRSession} The XR session. Returns `null` when used outside a XR session.
*/
this.getSession = function () {

@@ -264,2 +377,11 @@

/**
* After a XR session has been requested usually with one of the `*Button` modules, it
* is injected into the renderer with this method. This method triggers the start of
* the actual XR rendering.
*
* @async
* @param {XRSession} value - The XR session to set.
* @return {Promise} A Promise that resolves when the session has been set.
*/
this.setSession = async function ( value ) {

@@ -389,2 +511,7 @@

/**
* Returns the environment blend mode from the current XR session.
*
* @return {'opaque'|'additive'|'alpha-blend'|undefined} The environment blend mode. Returns `undefined` when used outside of a XR session.
*/
this.getEnvironmentBlendMode = function () {

@@ -400,2 +527,7 @@

/**
* Returns the current depth texture computed via depth sensing.
*
* @return {?Texture} The depth texture.
*/
this.getDepthTexture = function () {

@@ -567,2 +699,11 @@

/**
* Updates the state of the XR camera. Use this method on app level if you
* set cameraAutoUpdate` to `false`. The method requires the non-XR
* camera of the scene as a parameter. The passed in camera's transformation
* is automatically adjusted to the position of the XR camera when calling
* this method.
*
* @param {Camera} camera - The camera.
*/
this.updateCamera = function ( camera ) {

@@ -663,2 +804,12 @@

/**
* Returns an instance of {@link ArrayCamera} which represents the XR camera
* of the active XR session. For each view it holds a separate camera object.
*
* The camera's `fov` is currently not used and does not reflect the fov of
* the XR camera. If you need the fov on app level, you have to compute in
* manually from the XR camera's projection matrices.
*
* @return {ArrayCamera} The XR camera.
*/
this.getCamera = function () {

@@ -670,2 +821,7 @@

/**
* Returns the amount of foveation used by the XR compositor for the projection layer.
*
* @return {number} The amount of foveation.
*/
this.getFoveation = function () {

@@ -683,2 +839,8 @@

/**
* Sets the foveation value.
*
* @param {number} value - A number in the range `[0,1]` where `0` means no foveation (full resolution)
* and `1` means maximum foveation (the edges render at lower resolution).
*/
this.setFoveation = function ( value ) {

@@ -705,2 +867,7 @@

/**
* Returns `true` if depth sensing is supported.
*
* @return {boolean} Whether depth sensing is supported or not.
*/
this.hasDepthSensing = function () {

@@ -712,2 +879,7 @@

/**
* Returns the depth sensing mesh.
*
* @return {Mesh} The depth sensing mesh.
*/
this.getDepthSensingMesh = function () {

@@ -771,3 +943,3 @@

glSubImage.colorTexture,
glProjLayer.ignoreDepthValues ? undefined : glSubImage.depthStencilTexture );
glSubImage.depthStencilTexture );

@@ -774,0 +946,0 @@ renderer.setRenderTarget( newRenderTarget );

@@ -107,3 +107,4 @@ import { Object3D } from '../core/Object3D.js';

/**
* Forces everything in the scene to be rendered with the defined material.
* Forces everything in the scene to be rendered with the defined material. It is possible
* to exclude materials from override by setting {@link Material#allowOverride} to `false`.
*

@@ -110,0 +111,0 @@ * @type {?Material}

import { Texture } from './Texture.js';
/**
* Creates a texture from a canvas element.
*
* This is almost the same as the base texture class, except that it sets {@link Texture#needsUpdate}
* to `true` immediately since a canvas can directly be used for rendering.
*
* @augments Texture
*/
class CanvasTexture extends Texture {
/**
* Constructs a new texture.
*
* @param {HTMLCanvasElement} [canvas] - The HTML canvas element.
* @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
* @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
* @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
* @param {number} [magFilter=LinearFilter] - The mag filter value.
* @param {number} [minFilter=LinearMipmapLinearFilter] - The min filter value.
* @param {number} [format=RGBAFormat] - The texture format.
* @param {number} [type=UnsignedByteType] - The texture type.
* @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
*/
constructor( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {

@@ -9,2 +30,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isCanvasTexture = true;

@@ -11,0 +39,0 @@

import { ClampToEdgeWrapping } from '../constants.js';
import { CompressedTexture } from './CompressedTexture.js';
/**
* Creates a texture 2D array based on data in compressed form.
*
* These texture are usually loaded with {@link CompressedTextureLoader}.
*
* @augments CompressedTexture
*/
class CompressedArrayTexture extends CompressedTexture {
/**
* Constructs a new compressed array texture.
*
* @param {Array<Object>} mipmaps - This array holds for all mipmaps (including the bases mip)
* the data and dimensions.
* @param {number} width - The width of the texture.
* @param {number} height - The height of the texture.
* @param {number} depth - The depth of the texture.
* @param {number} [format=RGBAFormat] - The min filter value.
* @param {number} [type=UnsignedByteType] - The min filter value.
*/
constructor( mipmaps, width, height, depth, format, type ) {

@@ -10,6 +28,33 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isCompressedArrayTexture = true;
/**
* The image property of a compressed texture just defines its dimensions.
*
* @name CompressedArrayTexture#image
* @type {{width:number,height:number,depth:number}}
*/
this.image.depth = depth;
/**
* This defines how the texture is wrapped in the depth and corresponds to
* *W* in UVW mapping.
*
* @type {(RepeatWrapping|ClampToEdgeWrapping|MirroredRepeatWrapping)}
* @default ClampToEdgeWrapping
*/
this.wrapR = ClampToEdgeWrapping;
/**
* A set of all layers which need to be updated in the texture.
*
* @type {Set<number>}
*/
this.layerUpdates = new Set();

@@ -19,2 +64,11 @@

/**
* Describes that a specific layer of the texture needs to be updated.
* Normally when {@link Texture#needsUpdate} is set to `true`, the
* entire compressed texture array is sent to the GPU. Marking specific
* layers will only transmit subsets of all mipmaps associated with a
* specific depth in the array which is often much more performant.
*
* @param {number} layerIndex - The layer index that should be updated.
*/
addLayerUpdate( layerIndex ) {

@@ -26,2 +80,5 @@

/**
* Resets the layer updates registry.
*/
clearLayerUpdates() {

@@ -28,0 +85,0 @@

import { CubeReflectionMapping } from '../constants.js';
import { CompressedTexture } from './CompressedTexture.js';
/**
* Creates a cube texture based on data in compressed form.
*
* These texture are usually loaded with {@link CompressedTextureLoader}.
*
* @augments CompressedTexture
*/
class CompressedCubeTexture extends CompressedTexture {
/**
* Constructs a new compressed texture.
*
* @param {Array<CompressedTexture>} images - An array of compressed textures.
* @param {number} [format=RGBAFormat] - The texture format.
* @param {number} [type=UnsignedByteType] - The texture type.
*/
constructor( images, format, type ) {

@@ -10,3 +24,18 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isCompressedCubeTexture = true;
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isCubeTexture = true;

@@ -13,0 +42,0 @@

import { Texture } from './Texture.js';
/**
* Creates a texture based on data in compressed form.
*
* These texture are usually loaded with {@link CompressedTextureLoader}.
*
* @augments Texture
*/
class CompressedTexture extends Texture {
/**
* Constructs a new compressed texture.
*
* @param {Array<Object>} mipmaps - This array holds for all mipmaps (including the bases mip)
* the data and dimensions.
* @param {number} width - The width of the texture.
* @param {number} height - The height of the texture.
* @param {number} [format=RGBAFormat] - The texture format.
* @param {number} [type=UnsignedByteType] - The texture type.
* @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
* @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
* @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
* @param {number} [magFilter=LinearFilter] - The mag filter value.
* @param {number} [minFilter=LinearMipmapLinearFilter] - The min filter value.
* @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
* @param {string} [colorSpace=NoColorSpace] - The color space.
*/
constructor( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, colorSpace ) {

@@ -9,15 +33,49 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isCompressedTexture = true;
/**
* The image property of a compressed texture just defines its dimensions.
*
* @type {{width:number,height:number}}
*/
this.image = { width: width, height: height };
/**
* This array holds for all mipmaps (including the bases mip) the data and dimensions.
*
* @type {Array<Object>}
*/
this.mipmaps = mipmaps;
// no flipping for cube textures
// (also flipping doesn't work for compressed textures )
/**
* If set to `true`, the texture is flipped along the vertical axis when
* uploaded to the GPU.
*
* Overwritten and set to `false` by default since it is not possible to
* flip compressed textures.
*
* @type {boolean}
* @default false
* @readonly
*/
this.flipY = false;
// can't generate mipmaps for compressed textures
// mips must be embedded in DDS files
/**
* Whether to generate mipmaps (if possible) for a texture.
*
* Overwritten and set to `false` by default since it is not
* possible to generate mipmaps for compressed data. Mipmaps
* must be embedded in the compressed texture file.
*
* @type {boolean}
* @default false
* @readonly
*/
this.generateMipmaps = false;

@@ -24,0 +82,0 @@

import { Texture } from './Texture.js';
import { CubeReflectionMapping } from '../constants.js';
/**
* Creates a cube texture made up of six images.
*
* ```js
* const loader = new THREE.CubeTextureLoader();
* loader.setPath( 'textures/cube/pisa/' );
*
* const textureCube = loader.load( [
* 'px.png', 'nx.png', 'py.png', 'ny.png', 'pz.png', 'nz.png'
* ] );
*
* const material = new THREE.MeshBasicMaterial( { color: 0xffffff, envMap: textureCube } );
* ```
*
* @augments Texture
*/
class CubeTexture extends Texture {
constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ) {
/**
* Constructs a new cube texture.
*
* @param {Array<Image>} [images=[]] - An array holding a image for each side of a cube.
* @param {number} [mapping=CubeReflectionMapping] - The texture mapping.
* @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
* @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
* @param {number} [magFilter=LinearFilter] - The mag filter value.
* @param {number} [minFilter=LinearMipmapLinearFilter] - The min filter value.
* @param {number} [format=RGBAFormat] - The texture format.
* @param {number} [type=UnsignedByteType] - The texture type.
* @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
* @param {string} [colorSpace=NoColorSpace] - The color space value.
*/
constructor( images = [], mapping = CubeReflectionMapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ) {
images = images !== undefined ? images : [];
mapping = mapping !== undefined ? mapping : CubeReflectionMapping;
super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace );
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isCubeTexture = true;
/**
* If set to `true`, the texture is flipped along the vertical axis when
* uploaded to the GPU.
*
* Overwritten and set to `false` by default.
*
* @type {boolean}
* @default false
*/
this.flipY = false;

@@ -19,2 +62,7 @@

/**
* Alias for {@link CubeTexture#image}.
*
* @type {Array<Image>}
*/
get images() {

@@ -21,0 +69,0 @@

import { Texture } from './Texture.js';
import { ClampToEdgeWrapping, NearestFilter } from '../constants.js';
/**
* Creates a three-dimensional texture from raw data, with parameters to
* divide it into width, height, and depth.
*
* @augments Texture
*/
class Data3DTexture extends Texture {
/**
* Constructs a new data array texture.
*
* @param {?TypedArray} [data=null] - The buffer data.
* @param {number} [width=1] - The width of the texture.
* @param {number} [height=1] - The height of the texture.
* @param {number} [depth=1] - The depth of the texture.
*/
constructor( data = null, width = 1, height = 1, depth = 1 ) {

@@ -18,13 +32,76 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isData3DTexture = true;
/**
* The image definition of a data texture.
*
* @type {{data:TypedArray,width:number,height:number,depth:number}}
*/
this.image = { data, width, height, depth };
/**
* How the texture is sampled when a texel covers more than one pixel.
*
* Overwritten and set to `NearestFilter` by default.
*
* @type {(NearestFilter|NearestMipmapNearestFilter|NearestMipmapLinearFilter|LinearFilter|LinearMipmapNearestFilter|LinearMipmapLinearFilter)}
* @default NearestFilter
*/
this.magFilter = NearestFilter;
/**
* How the texture is sampled when a texel covers less than one pixel.
*
* Overwritten and set to `NearestFilter` by default.
*
* @type {(NearestFilter|NearestMipmapNearestFilter|NearestMipmapLinearFilter|LinearFilter|LinearMipmapNearestFilter|LinearMipmapLinearFilter)}
* @default NearestFilter
*/
this.minFilter = NearestFilter;
/**
* This defines how the texture is wrapped in the depth and corresponds to
* *W* in UVW mapping.
*
* @type {(RepeatWrapping|ClampToEdgeWrapping|MirroredRepeatWrapping)}
* @default ClampToEdgeWrapping
*/
this.wrapR = ClampToEdgeWrapping;
/**
* Whether to generate mipmaps (if possible) for a texture.
*
* Overwritten and set to `false` by default.
*
* @type {boolean}
* @default false
*/
this.generateMipmaps = false;
/**
* If set to `true`, the texture is flipped along the vertical axis when
* uploaded to the GPU.
*
* Overwritten and set to `false` by default.
*
* @type {boolean}
* @default false
*/
this.flipY = false;
/**
* Specifies the alignment requirements for the start of each pixel row in memory.
*
* Overwritten and set to `1` by default.
*
* @type {boolean}
* @default 1
*/
this.unpackAlignment = 1;

@@ -31,0 +108,0 @@

import { Texture } from './Texture.js';
import { ClampToEdgeWrapping, NearestFilter } from '../constants.js';
/**
* Creates an array of textures directly from raw buffer data.
*
* @augments Texture
*/
class DataArrayTexture extends Texture {
/**
* Constructs a new data array texture.
*
* @param {?TypedArray} [data=null] - The buffer data.
* @param {number} [width=1] - The width of the texture.
* @param {number} [height=1] - The height of the texture.
* @param {number} [depth=1] - The depth of the texture.
*/
constructor( data = null, width = 1, height = 1, depth = 1 ) {

@@ -10,15 +23,83 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isDataArrayTexture = true;
/**
* The image definition of a data texture.
*
* @type {{data:TypedArray,width:number,height:number,depth:number}}
*/
this.image = { data, width, height, depth };
/**
* How the texture is sampled when a texel covers more than one pixel.
*
* Overwritten and set to `NearestFilter` by default.
*
* @type {(NearestFilter|NearestMipmapNearestFilter|NearestMipmapLinearFilter|LinearFilter|LinearMipmapNearestFilter|LinearMipmapLinearFilter)}
* @default NearestFilter
*/
this.magFilter = NearestFilter;
/**
* How the texture is sampled when a texel covers less than one pixel.
*
* Overwritten and set to `NearestFilter` by default.
*
* @type {(NearestFilter|NearestMipmapNearestFilter|NearestMipmapLinearFilter|LinearFilter|LinearMipmapNearestFilter|LinearMipmapLinearFilter)}
* @default NearestFilter
*/
this.minFilter = NearestFilter;
/**
* This defines how the texture is wrapped in the depth and corresponds to
* *W* in UVW mapping.
*
* @type {(RepeatWrapping|ClampToEdgeWrapping|MirroredRepeatWrapping)}
* @default ClampToEdgeWrapping
*/
this.wrapR = ClampToEdgeWrapping;
/**
* Whether to generate mipmaps (if possible) for a texture.
*
* Overwritten and set to `false` by default.
*
* @type {boolean}
* @default false
*/
this.generateMipmaps = false;
/**
* If set to `true`, the texture is flipped along the vertical axis when
* uploaded to the GPU.
*
* Overwritten and set to `false` by default.
*
* @type {boolean}
* @default false
*/
this.flipY = false;
/**
* Specifies the alignment requirements for the start of each pixel row in memory.
*
* Overwritten and set to `1` by default.
*
* @type {boolean}
* @default 1
*/
this.unpackAlignment = 1;
/**
* A set of all layers which need to be updated in the texture.
*
* @type {Set<number>}
*/
this.layerUpdates = new Set();

@@ -28,2 +109,11 @@

/**
* Describes that a specific layer of the texture needs to be updated.
* Normally when {@link Texture#needsUpdate} is set to `true`, the
* entire data texture array is sent to the GPU. Marking specific
* layers will only transmit subsets of all mipmaps associated with a
* specific depth in the array which is often much more performant.
*
* @param {number} layerIndex - The layer index that should be updated.
*/
addLayerUpdate( layerIndex ) {

@@ -35,2 +125,5 @@

/**
* Resets the layer updates registry.
*/
clearLayerUpdates() {

@@ -37,0 +130,0 @@

import { Texture } from './Texture.js';
import { NearestFilter } from '../constants.js';
/**
* Creates a texture directly from raw buffer data.
*
* The interpretation of the data depends on type and format: If the type is
* `UnsignedByteType`, a `Uint8Array` will be useful for addressing the
* texel data. If the format is `RGBAFormat`, data needs four values for
* one texel; Red, Green, Blue and Alpha (typically the opacity).
*
* @augments Texture
*/
class DataTexture extends Texture {
/**
* Constructs a new data texture.
*
* @param {?TypedArray} [data=null] - The buffer data.
* @param {number} [width=1] - The width of the texture.
* @param {number} [height=1] - The height of the texture.
* @param {number} [format=RGBAFormat] - The texture format.
* @param {number} [type=UnsignedByteType] - The texture type.
* @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
* @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
* @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
* @param {number} [magFilter=NearestFilter] - The mag filter value.
* @param {number} [minFilter=NearestFilter] - The min filter value.
* @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
* @param {string} [colorSpace=NoColorSpace] - The color space.
*/
constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, colorSpace ) {

@@ -10,8 +36,47 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isDataTexture = true;
/**
* The image definition of a data texture.
*
* @type {{data:TypedArray,width:number,height:number}}
*/
this.image = { data: data, width: width, height: height };
/**
* Whether to generate mipmaps (if possible) for a texture.
*
* Overwritten and set to `false` by default.
*
* @type {boolean}
* @default false
*/
this.generateMipmaps = false;
/**
* If set to `true`, the texture is flipped along the vertical axis when
* uploaded to the GPU.
*
* Overwritten and set to `false` by default.
*
* @type {boolean}
* @default false
*/
this.flipY = false;
/**
* Specifies the alignment requirements for the start of each pixel row in memory.
*
* Overwritten and set to `1` by default.
*
* @type {boolean}
* @default 1
*/
this.unpackAlignment = 1;

@@ -18,0 +83,0 @@

import { Source } from './Source.js';
import { Texture } from './Texture.js';
import { NearestFilter, UnsignedIntType, UnsignedInt248Type, DepthFormat, DepthStencilFormat } from '../constants.js';
import { NearestFilter, UnsignedIntType, DepthFormat, DepthStencilFormat } from '../constants.js';
/**
* This class can be used to automatically save the depth information of a
* rendering into a texture.
*
* @augments Texture
*/
class DepthTexture extends Texture {
constructor( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format = DepthFormat ) {
/**
* Constructs a new depth texture.
*
* @param {number} width - The width of the texture.
* @param {number} height - The height of the texture.
* @param {number} [type=UnsignedIntType] - The texture type.
* @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
* @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
* @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
* @param {number} [magFilter=LinearFilter] - The mag filter value.
* @param {number} [minFilter=LinearFilter] - The min filter value.
* @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
* @param {number} [format=DepthFormat] - The texture format.
*/
constructor( width, height, type = UnsignedIntType, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, format = DepthFormat ) {

@@ -15,17 +35,47 @@ if ( format !== DepthFormat && format !== DepthStencilFormat ) {

if ( type === undefined && format === DepthFormat ) type = UnsignedIntType;
if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type;
super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isDepthTexture = true;
/**
* The image property of a depth texture just defines its dimensions.
*
* @type {{width:number,height:number}}
*/
this.image = { width: width, height: height };
this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
/**
* If set to `true`, the texture is flipped along the vertical axis when
* uploaded to the GPU.
*
* Overwritten and set to `false` by default.
*
* @type {boolean}
* @default false
*/
this.flipY = false;
this.flipY = false;
/**
* Whether to generate mipmaps (if possible) for a texture.
*
* Overwritten and set to `false` by default.
*
* @type {boolean}
* @default false
*/
this.generateMipmaps = false;
/**
* The depth compare function.
*
* @type {?(NeverCompare|LessCompare|EqualCompare|LessEqualCompare|GreaterCompare|NotEqualCompare|GreaterEqualCompare|AlwaysCompare)}
* @default null
*/
this.compareFunction = null;

@@ -32,0 +82,0 @@

import { Texture } from './Texture.js';
import { NearestFilter } from '../constants.js';
/**
* This class can only be used in combination with `copyFramebufferToTexture()` methods
* of renderers. It extracts the contents of the current bound framebuffer and provides it
* as a texture for further usage.
*
* ```js
* const pixelRatio = window.devicePixelRatio;
* const textureSize = 128 * pixelRatio;
*
* const frameTexture = new FramebufferTexture( textureSize, textureSize );
*
* // calculate start position for copying part of the frame data
* const vector = new Vector2();
* vector.x = ( window.innerWidth * pixelRatio / 2 ) - ( textureSize / 2 );
* vector.y = ( window.innerHeight * pixelRatio / 2 ) - ( textureSize / 2 );
*
* renderer.render( scene, camera );
*
* // copy part of the rendered frame into the framebuffer texture
* renderer.copyFramebufferToTexture( frameTexture, vector );
* ```
*
* @augments Texture
*/
class FramebufferTexture extends Texture {
/**
* Constructs a new framebuffer texture.
*
* @param {number} width - The width of the texture.
* @param {number} height - The height of the texture.
*/
constructor( width, height ) {

@@ -10,7 +40,39 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isFramebufferTexture = true;
/**
* How the texture is sampled when a texel covers more than one pixel.
*
* Overwritten and set to `NearestFilter` by default to disable filtering.
*
* @type {(NearestFilter|NearestMipmapNearestFilter|NearestMipmapLinearFilter|LinearFilter|LinearMipmapNearestFilter|LinearMipmapLinearFilter)}
* @default NearestFilter
*/
this.magFilter = NearestFilter;
/**
* How the texture is sampled when a texel covers less than one pixel.
*
* Overwritten and set to `NearestFilter` by default to disable filtering.
*
* @type {(NearestFilter|NearestMipmapNearestFilter|NearestMipmapLinearFilter|LinearFilter|LinearMipmapNearestFilter|LinearMipmapLinearFilter)}
* @default NearestFilter
*/
this.minFilter = NearestFilter;
/**
* Whether to generate mipmaps (if possible) for a texture.
*
* Overwritten and set to `false` by default.
*
* @type {boolean}
* @default false
*/
this.generateMipmaps = false;

@@ -17,0 +79,0 @@

@@ -6,15 +6,68 @@ import { ImageUtils } from '../extras/ImageUtils.js';

/**
* Represents the data source of a texture.
*
* The main purpose of this class is to decouple the data definition from the texture
* definition so the same data can be used with multiple texture instances.
*/
class Source {
/**
* Constructs a new video texture.
*
* @param {any} [data=null] - The data definition of a texture.
*/
constructor( data = null ) {
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isSource = true;
/**
* The ID of the source.
*
* @name Source#id
* @type {number}
* @readonly
*/
Object.defineProperty( this, 'id', { value: _sourceId ++ } );
/**
* The UUID of the source.
*
* @type {string}
* @readonly
*/
this.uuid = generateUUID();
/**
* The data definition of a texture.
*
* @type {any}
*/
this.data = data;
/**
* This property is only relevant when {@link Source#needsUpdate} is set to `true` and
* provides more control on how texture data should be processed. When `dataReady` is set
* to `false`, the engine performs the memory allocation (if necessary) but does not transfer
* the data into the GPU memory.
*
* @type {boolean}
* @default true
*/
this.dataReady = true;
/**
* This starts at `0` and counts how many times {@link Source#needsUpdate} is set to `true`.
*
* @type {number}
* @readonly
* @default 0
*/
this.version = 0;

@@ -24,2 +77,11 @@

/**
* When the property is set to `true`, the engine allocates the memory
* for the texture (if necessary) and triggers the actual texture upload
* to the GPU next time the source is used.
*
* @type {boolean}
* @default false
* @param {boolean} value
*/
set needsUpdate( value ) {

@@ -31,2 +93,9 @@

/**
* Serializes the source into JSON.
*
* @param {?(Object|string)} meta - An optional value holding meta information about the serialization.
* @return {Object} A JSON object representing the serialized source.
* @see {@link ObjectLoader#parse}
*/
toJSON( meta ) {

@@ -33,0 +102,0 @@

@@ -38,7 +38,7 @@ import { EventDispatcher } from '../core/EventDispatcher.js';

* @param {number} [magFilter=LinearFilter] - The mag filter value.
* @param {number} [minFilter=LinearFilter] - The min filter value.
* @param {number} [format=RGBAFormat] - The min filter value.
* @param {number} [type=UnsignedByteType] - The min filter value.
* @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The min filter value.
* @param {string} [colorSpace=NoColorSpace] - The min filter value.
* @param {number} [minFilter=LinearMipmapLinearFilter] - The min filter value.
* @param {number} [format=RGBAFormat] - The texture format.
* @param {number} [type=UnsignedByteType] - The texture type.
* @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
* @param {string} [colorSpace=NoColorSpace] - The color space.
*/

@@ -45,0 +45,0 @@ constructor( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = Texture.DEFAULT_ANISOTROPY, colorSpace = NoColorSpace ) {

import { VideoTexture } from './VideoTexture.js';
/**
* This class can be used as an alternative way to define video data. Instead of using
* an instance of `HTMLVideoElement` like with `VideoTexture`, `VideoFrameTexture` expects each frame is
* defined manually via {@link VideoFrameTexture#setFrame}. A typical use case for this module is when
* video frames are decoded with the WebCodecs API.
*
* ```js
* const texture = new THREE.VideoFrameTexture();
* texture.setFrame( frame );
* ```
*
* @augments VideoTexture
*/
class VideoFrameTexture extends VideoTexture {
/**
* Constructs a new video frame texture.
*
* @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
* @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
* @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
* @param {number} [magFilter=LinearFilter] - The mag filter value.
* @param {number} [minFilter=LinearFilter] - The min filter value.
* @param {number} [format=RGBAFormat] - The texture format.
* @param {number} [type=UnsignedByteType] - The texture type.
* @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
*/
constructor( mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {

@@ -9,2 +34,9 @@

/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isVideoFrameTexture = true;

@@ -14,9 +46,8 @@

update() {
/**
* This method overwritten with an empty implementation since
* this type of texture is updated via `setFrame()`.
*/
update() {}
// overwrites `VideoTexture.update()` with an empty method since
// this type of texture is updated via `setFrame()`.
}
clone() {

@@ -28,2 +59,8 @@

/**
* Sets the current frame of the video. This will automatically update the texture
* so the data can be used for rendering.
*
* @param {VideoFrame} frame - The video frame.
*/
setFrame( frame ) {

@@ -30,0 +67,0 @@

import { LinearFilter } from '../constants.js';
import { Texture } from './Texture.js';
/**
* A texture for use with a video.
*
* ```js
* // assuming you have created a HTML video element with id="video"
* const video = document.getElementById( 'video' );
* const texture = new THREE.VideoTexture( video );
* ```
*
* Note: After the initial use of a texture, its dimensions, format, and type
* cannot be changed. Instead, call {@link Texture#dispose} on the texture and instantiate a new one.
*
* @augments Texture
*/
class VideoTexture extends Texture {
constructor( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
/**
* Constructs a new video texture.
*
* @param {Video} video - The video element to use as a data source for the texture.
* @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
* @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
* @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
* @param {number} [magFilter=LinearFilter] - The mag filter value.
* @param {number} [minFilter=LinearFilter] - The min filter value.
* @param {number} [format=RGBAFormat] - The texture format.
* @param {number} [type=UnsignedByteType] - The texture type.
* @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
*/
constructor( video, mapping, wrapS, wrapT, magFilter = LinearFilter, minFilter = LinearFilter, format, type, anisotropy ) {
super( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
/**
* This flag can be used for type testing.
*
* @type {boolean}
* @readonly
* @default true
*/
this.isVideoTexture = true;
this.minFilter = minFilter !== undefined ? minFilter : LinearFilter;
this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
/**
* Whether to generate mipmaps (if possible) for a texture.
*
* Overwritten and set to `false` by default.
*
* @type {boolean}
* @default false
*/
this.generateMipmaps = false;

@@ -40,2 +79,8 @@

/**
* This method is called automatically by the renderer and sets {@link Texture#needsUpdate}
* to `true` every time a new frame is available.
*
* Only relevant if `requestVideoFrameCallback` is not supported in the browser.
*/
update() {

@@ -42,0 +87,0 @@

@@ -119,2 +119,3 @@ import { TSL } from 'three/webgpu';

export const compute = TSL.compute;
export const computeSkinning = TSL.computeSkinning;
export const cond = TSL.cond;

@@ -132,2 +133,3 @@ export const Const = TSL.Const;

export const dashSize = TSL.dashSize;
export const debug = TSL.debug;
export const defaultBuildStages = TSL.defaultBuildStages;

@@ -412,2 +414,3 @@ export const defaultShaderStages = TSL.defaultShaderStages;

export const sampler = TSL.sampler;
export const samplerComparison = TSL.samplerComparison;
export const saturate = TSL.saturate;

@@ -438,3 +441,2 @@ export const saturation = TSL.saturation;

export const skinning = TSL.skinning;
export const skinningReference = TSL.skinningReference;
export const smoothstep = TSL.smoothstep;

@@ -441,0 +443,0 @@ export const smoothstepElement = TSL.smoothstepElement;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display