@plastic-software/three 0.181.2 → 0.182.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -4
- package/build/three.cjs +1192 -522
- package/build/three.core.js +345 -219
- package/build/three.core.min.js +1 -1
- package/build/three.module.js +864 -328
- package/build/three.module.min.js +1 -1
- package/build/three.tsl.js +15 -3
- package/build/three.tsl.min.js +1 -1
- package/build/three.webgpu.js +3660 -1545
- package/build/three.webgpu.min.js +1 -1
- package/build/three.webgpu.nodes.js +3659 -1544
- package/build/three.webgpu.nodes.min.js +1 -1
- package/examples/jsm/controls/MapControls.js +55 -1
- package/examples/jsm/controls/OrbitControls.js +6 -6
- package/examples/jsm/controls/TrackballControls.js +6 -6
- package/examples/jsm/csm/CSM.js +2 -1
- package/examples/jsm/environments/RoomEnvironment.js +2 -0
- package/examples/jsm/geometries/DecalGeometry.js +1 -1
- package/examples/jsm/helpers/LightProbeHelperGPU.js +1 -1
- package/examples/jsm/helpers/TextureHelperGPU.js +1 -1
- package/examples/jsm/inspector/Inspector.js +53 -9
- package/examples/jsm/inspector/RendererInspector.js +12 -2
- package/examples/jsm/inspector/tabs/Console.js +2 -2
- package/examples/jsm/inspector/tabs/Parameters.js +2 -2
- package/examples/jsm/inspector/tabs/Performance.js +2 -2
- package/examples/jsm/inspector/tabs/Viewer.js +4 -4
- package/examples/jsm/inspector/ui/Profiler.js +1836 -31
- package/examples/jsm/inspector/ui/Style.js +948 -13
- package/examples/jsm/inspector/ui/Tab.js +188 -1
- package/examples/jsm/inspector/ui/Values.js +17 -1
- package/examples/jsm/loaders/3DMLoader.js +5 -4
- package/examples/jsm/loaders/DRACOLoader.js +5 -5
- package/examples/jsm/loaders/FBXLoader.js +0 -2
- package/examples/jsm/loaders/HDRLoader.js +0 -1
- package/examples/jsm/loaders/KTX2Loader.js +16 -0
- package/examples/jsm/loaders/LDrawLoader.js +2 -3
- package/examples/jsm/loaders/PCDLoader.js +1 -0
- package/examples/jsm/loaders/SVGLoader.js +1 -1
- package/examples/jsm/loaders/TDSLoader.js +0 -2
- package/examples/jsm/loaders/TGALoader.js +0 -2
- package/examples/jsm/loaders/UltraHDRLoader.js +110 -137
- package/examples/jsm/loaders/VOXLoader.js +660 -117
- package/examples/jsm/loaders/VRMLLoader.js +2 -2
- package/examples/jsm/loaders/usd/USDCParser.js +1 -1
- package/examples/jsm/materials/LDrawConditionalLineNodeMaterial.js +1 -1
- package/examples/jsm/materials/MeshGouraudMaterial.js +0 -1
- package/examples/jsm/materials/WoodNodeMaterial.js +11 -11
- package/examples/jsm/math/Octree.js +131 -1
- package/examples/jsm/misc/Volume.js +0 -1
- package/examples/jsm/misc/VolumeSlice.js +0 -1
- package/examples/jsm/objects/SkyMesh.js +13 -3
- package/examples/jsm/physics/AmmoPhysics.js +12 -7
- package/examples/jsm/physics/JoltPhysics.js +3 -1
- package/examples/jsm/physics/RapierPhysics.js +3 -1
- package/examples/jsm/postprocessing/OutputPass.js +9 -0
- package/examples/jsm/postprocessing/RenderPass.js +10 -0
- package/examples/jsm/postprocessing/UnrealBloomPass.js +48 -18
- package/examples/jsm/renderers/Projector.js +268 -30
- package/examples/jsm/renderers/SVGRenderer.js +191 -58
- package/examples/jsm/shaders/UnpackDepthRGBAShader.js +2 -4
- package/examples/jsm/transpiler/AST.js +44 -0
- package/examples/jsm/transpiler/GLSLDecoder.js +61 -4
- package/examples/jsm/transpiler/ShaderToyDecoder.js +2 -0
- package/examples/jsm/transpiler/TSLEncoder.js +46 -3
- package/examples/jsm/transpiler/TranspilerUtils.js +3 -3
- package/examples/jsm/transpiler/WGSLEncoder.js +27 -0
- package/examples/jsm/tsl/display/AnaglyphPassNode.js +2 -0
- package/examples/jsm/tsl/display/BloomNode.js +11 -1
- package/examples/jsm/tsl/display/GTAONode.js +3 -2
- package/examples/jsm/tsl/display/PixelationPassNode.js +2 -1
- package/examples/jsm/tsl/display/SSGINode.js +7 -19
- package/examples/jsm/tsl/display/SSRNode.js +1 -1
- package/examples/jsm/tsl/display/SSSNode.js +4 -2
- package/examples/jsm/tsl/display/StereoCompositePassNode.js +8 -1
- package/examples/jsm/tsl/display/TRAANode.js +265 -114
- package/examples/jsm/tsl/display/radialBlur.js +68 -0
- package/examples/jsm/utils/ShadowMapViewer.js +24 -10
- package/examples/jsm/utils/ShadowMapViewerGPU.js +1 -1
- package/examples/jsm/utils/WebGPUTextureUtils.js +1 -1
- package/package.json +14 -12
- package/src/Three.Core.js +1 -0
- package/src/Three.TSL.js +14 -2
- package/src/animation/AnimationUtils.js +1 -12
- package/src/animation/KeyframeTrack.js +1 -1
- package/src/animation/tracks/BooleanKeyframeTrack.js +1 -1
- package/src/animation/tracks/ColorKeyframeTrack.js +1 -1
- package/src/animation/tracks/NumberKeyframeTrack.js +1 -1
- package/src/animation/tracks/QuaternionKeyframeTrack.js +1 -1
- package/src/animation/tracks/StringKeyframeTrack.js +1 -1
- package/src/animation/tracks/VectorKeyframeTrack.js +1 -1
- package/src/constants.js +61 -5
- package/src/core/BufferGeometry.js +14 -2
- package/src/core/Raycaster.js +2 -2
- package/src/extras/PMREMGenerator.js +3 -10
- package/src/extras/TextureUtils.js +5 -1
- package/src/geometries/ExtrudeGeometry.js +2 -2
- package/src/geometries/PolyhedronGeometry.js +1 -1
- package/src/helpers/PointLightHelper.js +1 -1
- package/src/lights/DirectionalLight.js +13 -0
- package/src/lights/HemisphereLight.js +10 -0
- package/src/lights/Light.js +1 -11
- package/src/lights/LightProbe.js +0 -15
- package/src/lights/LightShadow.js +0 -3
- package/src/lights/PointLight.js +15 -0
- package/src/lights/PointLightShadow.js +0 -86
- package/src/lights/SpotLight.js +22 -1
- package/src/loaders/MaterialLoader.js +2 -1
- package/src/loaders/ObjectLoader.js +3 -1
- package/src/loaders/nodes/NodeLoader.js +2 -2
- package/src/materials/Material.js +2 -0
- package/src/materials/ShaderMaterial.js +20 -1
- package/src/materials/nodes/Line2NodeMaterial.js +2 -2
- package/src/materials/nodes/MeshPhysicalNodeMaterial.js +3 -2
- package/src/materials/nodes/MeshStandardNodeMaterial.js +5 -4
- package/src/materials/nodes/NodeMaterial.js +59 -3
- package/src/materials/nodes/manager/NodeMaterialObserver.js +1 -1
- package/src/math/Matrix4.js +40 -40
- package/src/math/Sphere.js +1 -1
- package/src/math/Vector3.js +0 -2
- package/src/nodes/TSL.js +4 -1
- package/src/nodes/accessors/BatchNode.js +10 -10
- package/src/nodes/accessors/BufferAttributeNode.js +98 -12
- package/src/nodes/accessors/BufferNode.js +29 -2
- package/src/nodes/accessors/ClippingNode.js +4 -4
- package/src/nodes/accessors/CubeTextureNode.js +20 -1
- package/src/nodes/accessors/InstanceNode.js +69 -29
- package/src/nodes/accessors/MaterialNode.js +9 -1
- package/src/nodes/accessors/MaterialReferenceNode.js +1 -2
- package/src/nodes/accessors/ModelNode.js +1 -1
- package/src/nodes/accessors/Normal.js +2 -2
- package/src/nodes/accessors/ReferenceBaseNode.js +4 -4
- package/src/nodes/accessors/ReferenceNode.js +4 -4
- package/src/nodes/accessors/RendererReferenceNode.js +1 -2
- package/src/nodes/accessors/SkinningNode.js +15 -2
- package/src/nodes/accessors/StorageBufferNode.js +4 -2
- package/src/nodes/accessors/Tangent.js +1 -11
- package/src/nodes/accessors/Texture3DNode.js +26 -1
- package/src/nodes/accessors/UniformArrayNode.js +2 -2
- package/src/nodes/accessors/UserDataNode.js +1 -2
- package/src/nodes/accessors/VertexColorNode.js +1 -2
- package/src/nodes/code/FunctionNode.js +1 -2
- package/src/nodes/core/ArrayNode.js +20 -1
- package/src/nodes/core/AssignNode.js +2 -2
- package/src/nodes/core/AttributeNode.js +2 -2
- package/src/nodes/core/ContextNode.js +103 -4
- package/src/nodes/core/NodeBuilder.js +56 -14
- package/src/nodes/core/NodeFrame.js +12 -4
- package/src/nodes/core/NodeUtils.js +5 -5
- package/src/nodes/core/ParameterNode.js +1 -2
- package/src/nodes/core/PropertyNode.js +19 -3
- package/src/nodes/core/StackNode.js +56 -8
- package/src/nodes/core/StructNode.js +1 -2
- package/src/nodes/core/StructTypeNode.js +11 -17
- package/src/nodes/core/UniformNode.js +19 -4
- package/src/nodes/core/VarNode.js +46 -21
- package/src/nodes/display/NormalMapNode.js +37 -2
- package/src/nodes/display/PassNode.js +77 -7
- package/src/nodes/display/ScreenNode.js +1 -0
- package/src/nodes/functions/BSDF/BRDF_GGX_Multiscatter.js +3 -3
- package/src/nodes/functions/BSDF/DFGLUT.js +56 -0
- package/src/nodes/functions/BSDF/EnvironmentBRDF.js +2 -2
- package/src/nodes/functions/BSDF/V_GGX_SmithCorrelated_Anisotropic.js +1 -1
- package/src/nodes/functions/PhysicalLightingModel.js +102 -43
- package/src/nodes/gpgpu/ComputeBuiltinNode.js +1 -2
- package/src/nodes/gpgpu/SubgroupFunctionNode.js +1 -1
- package/src/nodes/gpgpu/WorkgroupInfoNode.js +2 -3
- package/src/nodes/lighting/AnalyticLightNode.js +53 -0
- package/src/nodes/lighting/LightsNode.js +2 -2
- package/src/nodes/lighting/PointShadowNode.js +141 -140
- package/src/nodes/lighting/ShadowFilterNode.js +53 -37
- package/src/nodes/lighting/ShadowNode.js +53 -19
- package/src/nodes/math/BitcountNode.js +433 -0
- package/src/nodes/math/PackFloatNode.js +98 -0
- package/src/nodes/math/UnpackFloatNode.js +96 -0
- package/src/nodes/pmrem/PMREMNode.js +1 -1
- package/src/nodes/tsl/TSLCore.js +4 -4
- package/src/nodes/utils/ArrayElementNode.js +13 -0
- package/src/nodes/utils/EventNode.js +1 -2
- package/src/nodes/utils/Packing.js +13 -1
- package/src/nodes/utils/PostProcessingUtils.js +33 -1
- package/src/nodes/utils/ReflectorNode.js +1 -1
- package/src/nodes/utils/SampleNode.js +1 -1
- package/src/nodes/utils/UVUtils.js +26 -0
- package/src/objects/BatchedMesh.js +5 -2
- package/src/objects/Line.js +1 -1
- package/src/objects/Mesh.js +1 -1
- package/src/objects/Points.js +1 -1
- package/src/objects/Skeleton.js +9 -0
- package/src/renderers/WebGLRenderer.js +145 -33
- package/src/renderers/common/Backend.js +8 -0
- package/src/renderers/common/Background.js +19 -9
- package/src/renderers/common/Binding.js +11 -0
- package/src/renderers/common/Bindings.js +7 -7
- package/src/renderers/common/Buffer.js +40 -0
- package/src/renderers/common/ChainMap.js +30 -6
- package/src/renderers/common/Geometries.js +12 -0
- package/src/renderers/common/RenderContexts.js +8 -1
- package/src/renderers/common/RenderObject.js +14 -1
- package/src/renderers/common/Renderer.js +53 -35
- package/src/renderers/common/Textures.js +1 -1
- package/src/renderers/common/UniformsGroup.js +1 -0
- package/src/renderers/common/XRManager.js +1 -0
- package/src/renderers/common/extras/PMREMGenerator.js +2 -8
- package/src/renderers/common/nodes/NodeUniformBuffer.js +52 -0
- package/src/renderers/shaders/DFGLUTData.js +19 -34
- package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +5 -2
- package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +8 -4
- package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +90 -51
- package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +194 -186
- package/src/renderers/shaders/ShaderChunk/shadowmask_pars_fragment.glsl.js +1 -1
- package/src/renderers/shaders/ShaderChunk/transmission_fragment.glsl.js +1 -1
- package/src/renderers/shaders/ShaderChunk.js +3 -3
- package/src/renderers/shaders/ShaderLib/depth.glsl.js +3 -0
- package/src/renderers/shaders/ShaderLib/{distanceRGBA.glsl.js → distance.glsl.js} +1 -2
- package/src/renderers/shaders/ShaderLib/meshlambert.glsl.js +0 -1
- package/src/renderers/shaders/ShaderLib/meshnormal.glsl.js +1 -2
- package/src/renderers/shaders/ShaderLib/meshphong.glsl.js +0 -1
- package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +4 -9
- package/src/renderers/shaders/ShaderLib/meshtoon.glsl.js +0 -1
- package/src/renderers/shaders/ShaderLib/shadow.glsl.js +0 -1
- package/src/renderers/shaders/ShaderLib/vsm.glsl.js +4 -6
- package/src/renderers/shaders/ShaderLib.js +3 -3
- package/src/renderers/webgl/WebGLCapabilities.js +3 -4
- package/src/renderers/webgl/WebGLLights.js +18 -1
- package/src/renderers/webgl/WebGLOutput.js +267 -0
- package/src/renderers/webgl/WebGLProgram.js +43 -107
- package/src/renderers/webgl/WebGLPrograms.js +35 -45
- package/src/renderers/webgl/WebGLShadowMap.js +188 -25
- package/src/renderers/webgl/WebGLState.js +20 -20
- package/src/renderers/webgl/WebGLTextures.js +89 -28
- package/src/renderers/webgl/WebGLUniforms.js +40 -3
- package/src/renderers/webgl/WebGLUtils.js +6 -2
- package/src/renderers/webgl-fallback/WebGLBackend.js +79 -13
- package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +59 -7
- package/src/renderers/webgl-fallback/utils/WebGLState.js +18 -3
- package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +5 -3
- package/src/renderers/webgl-fallback/utils/WebGLTimestampQueryPool.js +9 -9
- package/src/renderers/webgl-fallback/utils/WebGLUtils.js +6 -2
- package/src/renderers/webgpu/WebGPUBackend.js +61 -4
- package/src/renderers/webgpu/WebGPURenderer.js +1 -1
- package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +65 -23
- package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +4 -17
- package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +354 -186
- package/src/renderers/webgpu/utils/WebGPUConstants.js +2 -0
- package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +20 -7
- package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +40 -17
- package/src/renderers/webgpu/utils/WebGPUTimestampQueryPool.js +7 -7
- package/src/renderers/webgpu/utils/WebGPUUtils.js +7 -5
- package/src/textures/CubeDepthTexture.js +76 -0
- package/src/textures/Source.js +1 -1
- package/src/textures/Texture.js +1 -1
- package/src/utils.js +13 -1
- package/src/nodes/functions/BSDF/DFGApprox.js +0 -71
|
@@ -1,122 +1,95 @@
|
|
|
1
1
|
import ShadowNode from './ShadowNode.js';
|
|
2
2
|
import { uniform } from '../core/UniformNode.js';
|
|
3
|
-
import { float,
|
|
3
|
+
import { float, vec3, If, Fn } from '../tsl/TSLBase.js';
|
|
4
4
|
import { reference } from '../accessors/ReferenceNode.js';
|
|
5
|
-
import {
|
|
6
|
-
import { max, abs, sign } from '../math/MathNode.js';
|
|
7
|
-
import { sub, div } from '../math/OperatorNode.js';
|
|
5
|
+
import { cubeTexture } from '../accessors/CubeTextureNode.js';
|
|
8
6
|
import { renderGroup } from '../core/UniformGroupNode.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
7
|
+
import { Matrix4 } from '../../math/Matrix4.js';
|
|
8
|
+
import { Vector3 } from '../../math/Vector3.js';
|
|
11
9
|
import { Color } from '../../math/Color.js';
|
|
12
|
-
import { BasicShadowMap } from '../../constants.js';
|
|
10
|
+
import { BasicShadowMap, LessCompare, WebGPUCoordinateSystem } from '../../constants.js';
|
|
11
|
+
import { CubeDepthTexture } from '../../textures/CubeDepthTexture.js';
|
|
12
|
+
import { screenCoordinate } from '../display/ScreenNode.js';
|
|
13
|
+
import { interleavedGradientNoise, vogelDiskSample } from '../utils/PostProcessingUtils.js';
|
|
14
|
+
import { abs, normalize, cross } from '../math/MathNode.js';
|
|
13
15
|
|
|
14
16
|
const _clearColor = /*@__PURE__*/ new Color();
|
|
17
|
+
const _projScreenMatrix = /*@__PURE__*/ new Matrix4();
|
|
18
|
+
const _lightPositionWorld = /*@__PURE__*/ new Vector3();
|
|
19
|
+
const _lookTarget = /*@__PURE__*/ new Vector3();
|
|
20
|
+
|
|
21
|
+
// Cube map face directions and up vectors for point light shadows
|
|
22
|
+
// Face order: +X, -X, +Y, -Y, +Z, -Z
|
|
23
|
+
// WebGPU coordinate system - Y faces swapped to match texture sampling convention
|
|
24
|
+
const _cubeDirectionsWebGPU = [
|
|
25
|
+
/*@__PURE__*/ new Vector3( 1, 0, 0 ), /*@__PURE__*/ new Vector3( - 1, 0, 0 ), /*@__PURE__*/ new Vector3( 0, - 1, 0 ),
|
|
26
|
+
/*@__PURE__*/ new Vector3( 0, 1, 0 ), /*@__PURE__*/ new Vector3( 0, 0, 1 ), /*@__PURE__*/ new Vector3( 0, 0, - 1 )
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
const _cubeUpsWebGPU = [
|
|
30
|
+
/*@__PURE__*/ new Vector3( 0, - 1, 0 ), /*@__PURE__*/ new Vector3( 0, - 1, 0 ), /*@__PURE__*/ new Vector3( 0, 0, - 1 ),
|
|
31
|
+
/*@__PURE__*/ new Vector3( 0, 0, 1 ), /*@__PURE__*/ new Vector3( 0, - 1, 0 ), /*@__PURE__*/ new Vector3( 0, - 1, 0 )
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
// WebGL coordinate system - standard OpenGL convention
|
|
35
|
+
const _cubeDirectionsWebGL = [
|
|
36
|
+
/*@__PURE__*/ new Vector3( 1, 0, 0 ), /*@__PURE__*/ new Vector3( - 1, 0, 0 ), /*@__PURE__*/ new Vector3( 0, 1, 0 ),
|
|
37
|
+
/*@__PURE__*/ new Vector3( 0, - 1, 0 ), /*@__PURE__*/ new Vector3( 0, 0, 1 ), /*@__PURE__*/ new Vector3( 0, 0, - 1 )
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
const _cubeUpsWebGL = [
|
|
41
|
+
/*@__PURE__*/ new Vector3( 0, - 1, 0 ), /*@__PURE__*/ new Vector3( 0, - 1, 0 ), /*@__PURE__*/ new Vector3( 0, 0, 1 ),
|
|
42
|
+
/*@__PURE__*/ new Vector3( 0, 0, - 1 ), /*@__PURE__*/ new Vector3( 0, - 1, 0 ), /*@__PURE__*/ new Vector3( 0, - 1, 0 )
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
export const BasicPointShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, bd3D, dp } ) => {
|
|
46
|
+
|
|
47
|
+
return cubeTexture( depthTexture, bd3D ).compare( dp );
|
|
15
48
|
|
|
16
|
-
|
|
17
|
-
// vector suitable for 2D texture mapping. This code uses the following layout for the
|
|
18
|
-
// 2D texture:
|
|
19
|
-
//
|
|
20
|
-
// xzXZ
|
|
21
|
-
// y Y
|
|
22
|
-
//
|
|
23
|
-
// Y - Positive y direction
|
|
24
|
-
// y - Negative y direction
|
|
25
|
-
// X - Positive x direction
|
|
26
|
-
// x - Negative x direction
|
|
27
|
-
// Z - Positive z direction
|
|
28
|
-
// z - Negative z direction
|
|
29
|
-
//
|
|
30
|
-
// Source and test bed:
|
|
31
|
-
// https://gist.github.com/tschw/da10c43c467ce8afd0c4
|
|
32
|
-
|
|
33
|
-
export const cubeToUV = /*@__PURE__*/ Fn( ( [ pos, texelSizeY ] ) => {
|
|
34
|
-
|
|
35
|
-
const v = pos.toVar();
|
|
36
|
-
|
|
37
|
-
// Number of texels to avoid at the edge of each square
|
|
38
|
-
|
|
39
|
-
const absV = abs( v );
|
|
40
|
-
|
|
41
|
-
// Intersect unit cube
|
|
42
|
-
|
|
43
|
-
const scaleToCube = div( 1.0, max( absV.x, max( absV.y, absV.z ) ) );
|
|
44
|
-
absV.mulAssign( scaleToCube );
|
|
45
|
-
|
|
46
|
-
// Apply scale to avoid seams
|
|
47
|
-
|
|
48
|
-
// two texels less per square (one texel will do for NEAREST)
|
|
49
|
-
v.mulAssign( scaleToCube.mul( texelSizeY.mul( 2 ).oneMinus() ) );
|
|
50
|
-
|
|
51
|
-
// Unwrap
|
|
52
|
-
|
|
53
|
-
// space: -1 ... 1 range for each square
|
|
54
|
-
//
|
|
55
|
-
// #X## dim := ( 4 , 2 )
|
|
56
|
-
// # # center := ( 1 , 1 )
|
|
57
|
-
|
|
58
|
-
const planar = vec2( v.xy ).toVar();
|
|
59
|
-
|
|
60
|
-
const almostATexel = texelSizeY.mul( 1.5 );
|
|
61
|
-
const almostOne = almostATexel.oneMinus();
|
|
62
|
-
|
|
63
|
-
If( absV.z.greaterThanEqual( almostOne ), () => {
|
|
64
|
-
|
|
65
|
-
If( v.z.greaterThan( 0.0 ), () => {
|
|
66
|
-
|
|
67
|
-
planar.x.assign( sub( 4.0, v.x ) );
|
|
68
|
-
|
|
69
|
-
} );
|
|
70
|
-
|
|
71
|
-
} ).ElseIf( absV.x.greaterThanEqual( almostOne ), () => {
|
|
72
|
-
|
|
73
|
-
const signX = sign( v.x );
|
|
74
|
-
planar.x.assign( v.z.mul( signX ).add( signX.mul( 2.0 ) ) );
|
|
75
|
-
|
|
76
|
-
} ).ElseIf( absV.y.greaterThanEqual( almostOne ), () => {
|
|
77
|
-
|
|
78
|
-
const signY = sign( v.y );
|
|
79
|
-
planar.x.assign( v.x.add( signY.mul( 2.0 ) ).add( 2.0 ) );
|
|
80
|
-
planar.y.assign( v.z.mul( signY ).sub( 2.0 ) );
|
|
81
|
-
|
|
82
|
-
} );
|
|
83
|
-
|
|
84
|
-
// Transform to UV space
|
|
49
|
+
} );
|
|
85
50
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
51
|
+
/**
|
|
52
|
+
* A shadow filtering function for point lights using Vogel disk sampling and IGN.
|
|
53
|
+
*
|
|
54
|
+
* Uses 5 samples distributed via Vogel disk pattern in tangent space around the
|
|
55
|
+
* sample direction, rotated per-pixel using Interleaved Gradient Noise (IGN).
|
|
56
|
+
*
|
|
57
|
+
* @method
|
|
58
|
+
* @param {Object} inputs - The input parameter object.
|
|
59
|
+
* @param {CubeDepthTexture} inputs.depthTexture - A reference to the shadow cube map.
|
|
60
|
+
* @param {Node<vec3>} inputs.bd3D - The normalized direction from light to fragment.
|
|
61
|
+
* @param {Node<float>} inputs.dp - The depth value to compare against.
|
|
62
|
+
* @param {LightShadow} inputs.shadow - The light shadow.
|
|
63
|
+
* @return {Node<float>} The filtering result.
|
|
64
|
+
*/
|
|
65
|
+
export const PointShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, bd3D, dp, shadow } ) => {
|
|
89
66
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
type: 'vec2',
|
|
93
|
-
inputs: [
|
|
94
|
-
{ name: 'pos', type: 'vec3' },
|
|
95
|
-
{ name: 'texelSizeY', type: 'float' }
|
|
96
|
-
]
|
|
97
|
-
} );
|
|
67
|
+
const radius = reference( 'radius', 'float', shadow ).setGroup( renderGroup );
|
|
68
|
+
const mapSize = reference( 'mapSize', 'vec2', shadow ).setGroup( renderGroup );
|
|
98
69
|
|
|
99
|
-
|
|
70
|
+
const texelSize = radius.div( mapSize.x );
|
|
100
71
|
|
|
101
|
-
|
|
72
|
+
// Build a tangent-space coordinate system for applying offsets
|
|
73
|
+
const absDir = abs( bd3D );
|
|
74
|
+
const tangent = normalize( cross( bd3D, absDir.x.greaterThan( absDir.z ).select( vec3( 0, 1, 0 ), vec3( 1, 0, 0 ) ) ) );
|
|
75
|
+
const bitangent = cross( bd3D, tangent );
|
|
102
76
|
|
|
103
|
-
|
|
77
|
+
// Use IGN to rotate sampling pattern per pixel (phi = IGN * 2π)
|
|
78
|
+
const phi = interleavedGradientNoise( screenCoordinate.xy ).mul( 6.28318530718 );
|
|
104
79
|
|
|
105
|
-
|
|
80
|
+
// 5 samples using Vogel disk distribution in tangent space
|
|
81
|
+
const sample0 = vogelDiskSample( 0, 5, phi );
|
|
82
|
+
const sample1 = vogelDiskSample( 1, 5, phi );
|
|
83
|
+
const sample2 = vogelDiskSample( 2, 5, phi );
|
|
84
|
+
const sample3 = vogelDiskSample( 3, 5, phi );
|
|
85
|
+
const sample4 = vogelDiskSample( 4, 5, phi );
|
|
106
86
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
.add(
|
|
112
|
-
.
|
|
113
|
-
.add( texture( depthTexture, cubeToUV( bd3D.add( offset.yyx ), texelSize.y ) ).compare( dp ) )
|
|
114
|
-
.add( texture( depthTexture, cubeToUV( bd3D, texelSize.y ) ).compare( dp ) )
|
|
115
|
-
.add( texture( depthTexture, cubeToUV( bd3D.add( offset.xxy ), texelSize.y ) ).compare( dp ) )
|
|
116
|
-
.add( texture( depthTexture, cubeToUV( bd3D.add( offset.yxy ), texelSize.y ) ).compare( dp ) )
|
|
117
|
-
.add( texture( depthTexture, cubeToUV( bd3D.add( offset.xxx ), texelSize.y ) ).compare( dp ) )
|
|
118
|
-
.add( texture( depthTexture, cubeToUV( bd3D.add( offset.yxx ), texelSize.y ) ).compare( dp ) )
|
|
119
|
-
.mul( 1.0 / 9.0 );
|
|
87
|
+
return cubeTexture( depthTexture, bd3D.add( tangent.mul( sample0.x ).add( bitangent.mul( sample0.y ) ).mul( texelSize ) ) ).compare( dp )
|
|
88
|
+
.add( cubeTexture( depthTexture, bd3D.add( tangent.mul( sample1.x ).add( bitangent.mul( sample1.y ) ).mul( texelSize ) ) ).compare( dp ) )
|
|
89
|
+
.add( cubeTexture( depthTexture, bd3D.add( tangent.mul( sample2.x ).add( bitangent.mul( sample2.y ) ).mul( texelSize ) ) ).compare( dp ) )
|
|
90
|
+
.add( cubeTexture( depthTexture, bd3D.add( tangent.mul( sample3.x ).add( bitangent.mul( sample3.y ) ).mul( texelSize ) ) ).compare( dp ) )
|
|
91
|
+
.add( cubeTexture( depthTexture, bd3D.add( tangent.mul( sample4.x ).add( bitangent.mul( sample4.y ) ).mul( texelSize ) ) ).compare( dp ) )
|
|
92
|
+
.mul( 1.0 / 5.0 );
|
|
120
93
|
|
|
121
94
|
} );
|
|
122
95
|
|
|
@@ -130,7 +103,6 @@ const pointShadowFilter = /*@__PURE__*/ Fn( ( { filterFn, depthTexture, shadowCo
|
|
|
130
103
|
const cameraNearLocal = uniform( 'float' ).setGroup( renderGroup ).onRenderUpdate( () => shadow.camera.near );
|
|
131
104
|
const cameraFarLocal = uniform( 'float' ).setGroup( renderGroup ).onRenderUpdate( () => shadow.camera.far );
|
|
132
105
|
const bias = reference( 'bias', 'float', shadow ).setGroup( renderGroup );
|
|
133
|
-
const mapSize = uniform( shadow.mapSize ).setGroup( renderGroup );
|
|
134
106
|
|
|
135
107
|
const result = float( 1.0 ).toVar();
|
|
136
108
|
|
|
@@ -140,12 +112,11 @@ const pointShadowFilter = /*@__PURE__*/ Fn( ( { filterFn, depthTexture, shadowCo
|
|
|
140
112
|
const dp = lightToPositionLength.sub( cameraNearLocal ).div( cameraFarLocal.sub( cameraNearLocal ) ).toVar(); // need to clamp?
|
|
141
113
|
dp.addAssign( bias );
|
|
142
114
|
|
|
143
|
-
// bd3D = base direction 3D
|
|
115
|
+
// bd3D = base direction 3D (direction from light to fragment)
|
|
144
116
|
const bd3D = lightToPosition.normalize();
|
|
145
|
-
const texelSize = vec2( 1.0 ).div( mapSize.mul( vec2( 4.0, 2.0 ) ) );
|
|
146
117
|
|
|
147
|
-
// percentage-closer filtering
|
|
148
|
-
result.assign( filterFn( { depthTexture, bd3D, dp,
|
|
118
|
+
// percentage-closer filtering using cube texture sampling
|
|
119
|
+
result.assign( filterFn( { depthTexture, bd3D, dp, shadow } ) );
|
|
149
120
|
|
|
150
121
|
} );
|
|
151
122
|
|
|
@@ -153,10 +124,6 @@ const pointShadowFilter = /*@__PURE__*/ Fn( ( { filterFn, depthTexture, shadowCo
|
|
|
153
124
|
|
|
154
125
|
} );
|
|
155
126
|
|
|
156
|
-
const _viewport = /*@__PURE__*/ new Vector4();
|
|
157
|
-
const _viewportSize = /*@__PURE__*/ new Vector2();
|
|
158
|
-
const _shadowMapSize = /*@__PURE__*/ new Vector2();
|
|
159
|
-
|
|
160
127
|
|
|
161
128
|
/**
|
|
162
129
|
* Represents the shadow implementation for point light nodes.
|
|
@@ -216,15 +183,35 @@ class PointShadowNode extends ShadowNode {
|
|
|
216
183
|
* @param {NodeBuilder} builder - A reference to the current node builder.
|
|
217
184
|
* @param {Object} inputs - A configuration object that defines the shadow filtering.
|
|
218
185
|
* @param {Function} inputs.filterFn - This function defines the filtering type of the shadow map e.g. PCF.
|
|
219
|
-
* @param {
|
|
220
|
-
* @param {DepthTexture} inputs.depthTexture - A reference to the shadow map's texture data.
|
|
186
|
+
* @param {DepthTexture} inputs.depthTexture - A reference to the shadow map's depth texture.
|
|
221
187
|
* @param {Node<vec3>} inputs.shadowCoord - Shadow coordinates which are used to sample from the shadow map.
|
|
222
188
|
* @param {LightShadow} inputs.shadow - The light shadow.
|
|
223
189
|
* @return {Node<float>} The result node of the shadow filtering.
|
|
224
190
|
*/
|
|
225
|
-
setupShadowFilter( builder, { filterFn,
|
|
191
|
+
setupShadowFilter( builder, { filterFn, depthTexture, shadowCoord, shadow } ) {
|
|
192
|
+
|
|
193
|
+
return pointShadowFilter( { filterFn, depthTexture, shadowCoord, shadow } );
|
|
194
|
+
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Overwrites the default implementation to create a CubeRenderTarget with CubeDepthTexture.
|
|
199
|
+
*
|
|
200
|
+
* @param {LightShadow} shadow - The light shadow object.
|
|
201
|
+
* @param {NodeBuilder} builder - A reference to the current node builder.
|
|
202
|
+
* @return {Object} An object containing the shadow map and depth texture.
|
|
203
|
+
*/
|
|
204
|
+
setupRenderTarget( shadow, builder ) {
|
|
205
|
+
|
|
206
|
+
const depthTexture = new CubeDepthTexture( shadow.mapSize.width );
|
|
207
|
+
depthTexture.name = 'PointShadowDepthTexture';
|
|
208
|
+
depthTexture.compareFunction = LessCompare;
|
|
209
|
+
|
|
210
|
+
const shadowMap = builder.createCubeRenderTarget( shadow.mapSize.width );
|
|
211
|
+
shadowMap.texture.name = 'PointShadowMap';
|
|
212
|
+
shadowMap.depthTexture = depthTexture;
|
|
226
213
|
|
|
227
|
-
return
|
|
214
|
+
return { shadowMap, depthTexture };
|
|
228
215
|
|
|
229
216
|
}
|
|
230
217
|
|
|
@@ -239,14 +226,15 @@ class PointShadowNode extends ShadowNode {
|
|
|
239
226
|
const { shadow, shadowMap, light } = this;
|
|
240
227
|
const { renderer, scene } = frame;
|
|
241
228
|
|
|
242
|
-
const
|
|
229
|
+
const camera = shadow.camera;
|
|
230
|
+
const shadowMatrix = shadow.matrix;
|
|
243
231
|
|
|
244
|
-
|
|
245
|
-
|
|
232
|
+
// Select cube directions/ups based on coordinate system
|
|
233
|
+
const isWebGPU = renderer.coordinateSystem === WebGPUCoordinateSystem;
|
|
234
|
+
const cubeDirections = isWebGPU ? _cubeDirectionsWebGPU : _cubeDirectionsWebGL;
|
|
235
|
+
const cubeUps = isWebGPU ? _cubeUpsWebGPU : _cubeUpsWebGL;
|
|
246
236
|
|
|
247
|
-
shadowMap.setSize(
|
|
248
|
-
|
|
249
|
-
_viewportSize.copy( shadow.mapSize );
|
|
237
|
+
shadowMap.setSize( shadow.mapSize.width, shadow.mapSize.width );
|
|
250
238
|
|
|
251
239
|
//
|
|
252
240
|
|
|
@@ -257,33 +245,46 @@ class PointShadowNode extends ShadowNode {
|
|
|
257
245
|
|
|
258
246
|
renderer.autoClear = false;
|
|
259
247
|
renderer.setClearColor( shadow.clearColor, shadow.clearAlpha );
|
|
260
|
-
renderer.clear();
|
|
261
248
|
|
|
262
|
-
|
|
249
|
+
// Render each cube face
|
|
250
|
+
for ( let face = 0; face < 6; face ++ ) {
|
|
251
|
+
|
|
252
|
+
// Set render target to the specific cube face
|
|
253
|
+
renderer.setRenderTarget( shadowMap, face );
|
|
254
|
+
renderer.clear();
|
|
255
|
+
|
|
256
|
+
// Update shadow camera matrices for this face
|
|
257
|
+
|
|
258
|
+
const far = light.distance || camera.far;
|
|
259
|
+
|
|
260
|
+
if ( far !== camera.far ) {
|
|
261
|
+
|
|
262
|
+
camera.far = far;
|
|
263
|
+
camera.updateProjectionMatrix();
|
|
263
264
|
|
|
264
|
-
|
|
265
|
+
}
|
|
265
266
|
|
|
266
|
-
|
|
267
|
+
_lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
|
|
268
|
+
camera.position.copy( _lightPositionWorld );
|
|
267
269
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
+
_lookTarget.copy( camera.position );
|
|
271
|
+
_lookTarget.add( cubeDirections[ face ] );
|
|
272
|
+
camera.up.copy( cubeUps[ face ] );
|
|
273
|
+
camera.lookAt( _lookTarget );
|
|
274
|
+
camera.updateMatrixWorld();
|
|
270
275
|
|
|
271
|
-
|
|
272
|
-
x,
|
|
273
|
-
y,
|
|
274
|
-
_viewportSize.x * viewport.z,
|
|
275
|
-
_viewportSize.y * viewport.w
|
|
276
|
-
);
|
|
276
|
+
shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z );
|
|
277
277
|
|
|
278
|
-
|
|
278
|
+
_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
|
|
279
|
+
shadow._frustum.setFromProjectionMatrix( _projScreenMatrix, camera.coordinateSystem, camera.reversedDepth );
|
|
279
280
|
|
|
280
|
-
|
|
281
|
+
//
|
|
281
282
|
|
|
282
283
|
const currentSceneName = scene.name;
|
|
283
284
|
|
|
284
|
-
scene.name = `Point Light Shadow [ ${ light.name || 'ID: ' + light.id } ] - Face ${
|
|
285
|
+
scene.name = `Point Light Shadow [ ${ light.name || 'ID: ' + light.id } ] - Face ${ face + 1 }`;
|
|
285
286
|
|
|
286
|
-
renderer.render( scene,
|
|
287
|
+
renderer.render( scene, camera );
|
|
287
288
|
|
|
288
289
|
scene.name = currentSceneName;
|
|
289
290
|
|
|
@@ -309,4 +310,4 @@ export default PointShadowNode;
|
|
|
309
310
|
* @param {?PointLightShadow} [shadow=null] - An optional point light shadow.
|
|
310
311
|
* @return {PointShadowNode} The created point shadow node.
|
|
311
312
|
*/
|
|
312
|
-
export const pointShadow = ( light, shadow ) =>
|
|
313
|
+
export const pointShadow = ( light, shadow ) => new PointShadowNode( light, shadow );
|
|
@@ -7,6 +7,8 @@ import { renderGroup } from '../core/UniformGroupNode.js';
|
|
|
7
7
|
import NodeMaterial from '../../materials/nodes/NodeMaterial.js';
|
|
8
8
|
import { objectPosition } from '../accessors/Object3DNode.js';
|
|
9
9
|
import { positionWorld } from '../accessors/Position.js';
|
|
10
|
+
import { screenCoordinate } from '../display/ScreenNode.js';
|
|
11
|
+
import { interleavedGradientNoise, vogelDiskSample } from '../utils/PostProcessingUtils.js';
|
|
10
12
|
|
|
11
13
|
const shadowMaterialLib = /*@__PURE__*/ new WeakMap();
|
|
12
14
|
|
|
@@ -35,7 +37,11 @@ export const BasicShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, shadowCoord
|
|
|
35
37
|
} );
|
|
36
38
|
|
|
37
39
|
/**
|
|
38
|
-
* A shadow filtering function performing PCF filtering.
|
|
40
|
+
* A shadow filtering function performing PCF filtering with Vogel disk sampling and IGN.
|
|
41
|
+
*
|
|
42
|
+
* Uses 5 samples distributed via Vogel disk pattern, rotated per-pixel using Interleaved
|
|
43
|
+
* Gradient Noise (IGN) to break up banding artifacts. Combined with hardware PCF (4-tap
|
|
44
|
+
* filtering per sample), this effectively provides 20 filtered taps with better distribution.
|
|
39
45
|
*
|
|
40
46
|
* @method
|
|
41
47
|
* @param {Object} inputs - The input parameter object.
|
|
@@ -64,34 +70,19 @@ export const PCFShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, shadowCoord,
|
|
|
64
70
|
const radius = reference( 'radius', 'float', shadow ).setGroup( renderGroup );
|
|
65
71
|
|
|
66
72
|
const texelSize = vec2( 1 ).div( mapSize );
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
const dx2 = dx0.div( 2 );
|
|
72
|
-
const dy2 = dy0.div( 2 );
|
|
73
|
-
const dx3 = dx1.div( 2 );
|
|
74
|
-
const dy3 = dy1.div( 2 );
|
|
73
|
+
const radiusScaled = radius.mul( texelSize.x );
|
|
74
|
+
|
|
75
|
+
// Use IGN to rotate sampling pattern per pixel (phi = IGN * 2π)
|
|
76
|
+
const phi = interleavedGradientNoise( screenCoordinate.xy ).mul( 6.28318530718 );
|
|
75
77
|
|
|
78
|
+
// 5 samples using Vogel disk distribution
|
|
76
79
|
return add(
|
|
77
|
-
depthCompare( shadowCoord.xy.add(
|
|
78
|
-
depthCompare( shadowCoord.xy.add(
|
|
79
|
-
depthCompare( shadowCoord.xy.add(
|
|
80
|
-
depthCompare( shadowCoord.xy.add(
|
|
81
|
-
depthCompare( shadowCoord.xy.add(
|
|
82
|
-
|
|
83
|
-
depthCompare( shadowCoord.xy.add( vec2( dx0, 0 ) ), shadowCoord.z ),
|
|
84
|
-
depthCompare( shadowCoord.xy.add( vec2( dx2, 0 ) ), shadowCoord.z ),
|
|
85
|
-
depthCompare( shadowCoord.xy, shadowCoord.z ),
|
|
86
|
-
depthCompare( shadowCoord.xy.add( vec2( dx3, 0 ) ), shadowCoord.z ),
|
|
87
|
-
depthCompare( shadowCoord.xy.add( vec2( dx1, 0 ) ), shadowCoord.z ),
|
|
88
|
-
depthCompare( shadowCoord.xy.add( vec2( dx2, dy3 ) ), shadowCoord.z ),
|
|
89
|
-
depthCompare( shadowCoord.xy.add( vec2( 0, dy3 ) ), shadowCoord.z ),
|
|
90
|
-
depthCompare( shadowCoord.xy.add( vec2( dx3, dy3 ) ), shadowCoord.z ),
|
|
91
|
-
depthCompare( shadowCoord.xy.add( vec2( dx0, dy1 ) ), shadowCoord.z ),
|
|
92
|
-
depthCompare( shadowCoord.xy.add( vec2( 0, dy1 ) ), shadowCoord.z ),
|
|
93
|
-
depthCompare( shadowCoord.xy.add( vec2( dx1, dy1 ) ), shadowCoord.z )
|
|
94
|
-
).mul( 1 / 17 );
|
|
80
|
+
depthCompare( shadowCoord.xy.add( vogelDiskSample( 0, 5, phi ).mul( radiusScaled ) ), shadowCoord.z ),
|
|
81
|
+
depthCompare( shadowCoord.xy.add( vogelDiskSample( 1, 5, phi ).mul( radiusScaled ) ), shadowCoord.z ),
|
|
82
|
+
depthCompare( shadowCoord.xy.add( vogelDiskSample( 2, 5, phi ).mul( radiusScaled ) ), shadowCoord.z ),
|
|
83
|
+
depthCompare( shadowCoord.xy.add( vogelDiskSample( 3, 5, phi ).mul( radiusScaled ) ), shadowCoord.z ),
|
|
84
|
+
depthCompare( shadowCoord.xy.add( vogelDiskSample( 4, 5, phi ).mul( radiusScaled ) ), shadowCoord.z )
|
|
85
|
+
).mul( 1 / 5 );
|
|
95
86
|
|
|
96
87
|
} );
|
|
97
88
|
|
|
@@ -185,8 +176,6 @@ export const PCFSoftShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, shadowCoo
|
|
|
185
176
|
*/
|
|
186
177
|
export const VSMShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, shadowCoord, depthLayer } ) => {
|
|
187
178
|
|
|
188
|
-
const occlusion = float( 1 ).toVar();
|
|
189
|
-
|
|
190
179
|
let distribution = texture( depthTexture ).sample( shadowCoord.xy );
|
|
191
180
|
|
|
192
181
|
if ( depthTexture.isArrayTexture ) {
|
|
@@ -197,19 +186,28 @@ export const VSMShadowFilter = /*@__PURE__*/ Fn( ( { depthTexture, shadowCoord,
|
|
|
197
186
|
|
|
198
187
|
distribution = distribution.rg;
|
|
199
188
|
|
|
200
|
-
const
|
|
189
|
+
const mean = distribution.x;
|
|
190
|
+
const variance = max( 0.0000001, distribution.y.mul( distribution.y ) );
|
|
201
191
|
|
|
202
|
-
|
|
192
|
+
const hardShadow = step( shadowCoord.z, mean );
|
|
203
193
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
occlusion.assign( clamp( max( hardShadow, softnessProbability ) ) );
|
|
194
|
+
// Early return if fully lit
|
|
195
|
+
If( hardShadow.equal( 1.0 ), () => {
|
|
196
|
+
|
|
197
|
+
return float( 1.0 );
|
|
209
198
|
|
|
210
199
|
} );
|
|
211
200
|
|
|
212
|
-
|
|
201
|
+
// Distance from mean
|
|
202
|
+
const d = shadowCoord.z.sub( mean );
|
|
203
|
+
|
|
204
|
+
// Chebyshev's inequality for upper bound on probability
|
|
205
|
+
let p_max = variance.div( variance.add( d.mul( d ) ) );
|
|
206
|
+
|
|
207
|
+
// Reduce light bleeding by remapping [amount, 1] to [0, 1]
|
|
208
|
+
p_max = clamp( sub( p_max, 0.3 ).div( 0.65 ) );
|
|
209
|
+
|
|
210
|
+
return max( hardShadow, p_max );
|
|
213
211
|
|
|
214
212
|
} );
|
|
215
213
|
|
|
@@ -274,3 +272,21 @@ export const getShadowMaterial = ( light ) => {
|
|
|
274
272
|
return material;
|
|
275
273
|
|
|
276
274
|
};
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Disposes the shadow material for the given light source.
|
|
278
|
+
*
|
|
279
|
+
* @param {Light} light - The light source.
|
|
280
|
+
*/
|
|
281
|
+
export const disposeShadowMaterial = ( light ) => {
|
|
282
|
+
|
|
283
|
+
const material = shadowMaterialLib.get( light );
|
|
284
|
+
|
|
285
|
+
if ( material !== undefined ) {
|
|
286
|
+
|
|
287
|
+
material.dispose();
|
|
288
|
+
shadowMaterialLib.delete( light );
|
|
289
|
+
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import ShadowBaseNode, { shadowPositionWorld } from './ShadowBaseNode.js';
|
|
2
|
-
import { float, vec2, vec3, int, Fn
|
|
2
|
+
import { float, vec2, vec3, int, Fn } from '../tsl/TSLBase.js';
|
|
3
3
|
import { reference } from '../accessors/ReferenceNode.js';
|
|
4
4
|
import { texture, textureLoad } from '../accessors/TextureNode.js';
|
|
5
|
+
import { cubeTexture } from '../accessors/CubeTextureNode.js';
|
|
5
6
|
import { normalWorld } from '../accessors/Normal.js';
|
|
6
7
|
import { mix, sqrt } from '../math/MathNode.js';
|
|
7
8
|
import { add } from '../math/OperatorNode.js';
|
|
@@ -16,7 +17,7 @@ import { viewZToLogarithmicDepth } from '../display/ViewportDepthNode.js';
|
|
|
16
17
|
import { lightShadowMatrix } from '../accessors/Lights.js';
|
|
17
18
|
import { resetRendererAndSceneState, restoreRendererAndSceneState } from '../../renderers/common/RendererUtils.js';
|
|
18
19
|
import { getDataFromObject } from '../core/NodeUtils.js';
|
|
19
|
-
import { getShadowMaterial, BasicShadowFilter, PCFShadowFilter, PCFSoftShadowFilter, VSMShadowFilter } from './ShadowFilterNode.js';
|
|
20
|
+
import { getShadowMaterial, disposeShadowMaterial, BasicShadowFilter, PCFShadowFilter, PCFSoftShadowFilter, VSMShadowFilter } from './ShadowFilterNode.js';
|
|
20
21
|
import ChainMap from '../../renderers/common/ChainMap.js';
|
|
21
22
|
import { warn } from '../../utils.js';
|
|
22
23
|
import { textureSize } from '../accessors/TextureSizeNode.js';
|
|
@@ -36,16 +37,7 @@ const _shadowRenderObjectKeys = [];
|
|
|
36
37
|
* @param {LightShadow} shadow - The light shadow object containing shadow properties.
|
|
37
38
|
* @param {number} shadowType - The type of shadow map (e.g., BasicShadowMap).
|
|
38
39
|
* @param {boolean} useVelocity - Whether to use velocity data for rendering.
|
|
39
|
-
* @return {
|
|
40
|
-
*
|
|
41
|
-
* The returned function has the following parameters:
|
|
42
|
-
* @param {Object3D} object - The 3D object to render.
|
|
43
|
-
* @param {Scene} scene - The scene containing the object.
|
|
44
|
-
* @param {Camera} _camera - The camera used for rendering.
|
|
45
|
-
* @param {BufferGeometry} geometry - The geometry of the object.
|
|
46
|
-
* @param {Material} material - The material of the object.
|
|
47
|
-
* @param {Group} group - The group the object belongs to.
|
|
48
|
-
* @param {...any} params - Additional parameters for rendering.
|
|
40
|
+
* @return {shadowRenderObjectFunction} A function that renders shadow objects.
|
|
49
41
|
*/
|
|
50
42
|
export const getShadowRenderObjectFunction = ( renderer, shadow, shadowType, useVelocity ) => {
|
|
51
43
|
|
|
@@ -93,6 +85,7 @@ export const getShadowRenderObjectFunction = ( renderer, shadow, shadowType, use
|
|
|
93
85
|
/**
|
|
94
86
|
* Represents the shader code for the first VSM render pass.
|
|
95
87
|
*
|
|
88
|
+
* @private
|
|
96
89
|
* @method
|
|
97
90
|
* @param {Object} inputs - The input parameter object.
|
|
98
91
|
* @param {Node<float>} inputs.samples - The number of samples
|
|
@@ -131,7 +124,7 @@ const VSMPassVertical = /*@__PURE__*/ Fn( ( { samples, radius, size, shadowPass,
|
|
|
131
124
|
mean.divAssign( samples );
|
|
132
125
|
squaredMean.divAssign( samples );
|
|
133
126
|
|
|
134
|
-
const std_dev = sqrt( squaredMean.sub( mean.mul( mean ) ) );
|
|
127
|
+
const std_dev = sqrt( squaredMean.sub( mean.mul( mean ) ).max( 0 ) );
|
|
135
128
|
return vec2( mean, std_dev );
|
|
136
129
|
|
|
137
130
|
} );
|
|
@@ -139,6 +132,7 @@ const VSMPassVertical = /*@__PURE__*/ Fn( ( { samples, radius, size, shadowPass,
|
|
|
139
132
|
/**
|
|
140
133
|
* Represents the shader code for the second VSM render pass.
|
|
141
134
|
*
|
|
135
|
+
* @private
|
|
142
136
|
* @method
|
|
143
137
|
* @param {Object} inputs - The input parameter object.
|
|
144
138
|
* @param {Node<float>} inputs.samples - The number of samples
|
|
@@ -175,7 +169,7 @@ const VSMPassHorizontal = /*@__PURE__*/ Fn( ( { samples, radius, size, shadowPas
|
|
|
175
169
|
mean.divAssign( samples );
|
|
176
170
|
squaredMean.divAssign( samples );
|
|
177
171
|
|
|
178
|
-
const std_dev = sqrt( squaredMean.sub( mean.mul( mean ) ) );
|
|
172
|
+
const std_dev = sqrt( squaredMean.sub( mean.mul( mean ) ).max( 0 ) );
|
|
179
173
|
return vec2( mean, std_dev );
|
|
180
174
|
|
|
181
175
|
} );
|
|
@@ -523,11 +517,22 @@ class ShadowNode extends ShadowBaseNode {
|
|
|
523
517
|
|
|
524
518
|
const shadowNode = this.setupShadowFilter( builder, { filterFn, shadowTexture: shadowMap.texture, depthTexture: shadowDepthTexture, shadowCoord, shadow, depthLayer: this.depthLayer } );
|
|
525
519
|
|
|
526
|
-
let shadowColor
|
|
520
|
+
let shadowColor;
|
|
527
521
|
|
|
528
|
-
if (
|
|
522
|
+
if ( shadowMap.texture.isCubeTexture ) {
|
|
529
523
|
|
|
530
|
-
|
|
524
|
+
// For cube shadow maps (point lights), use cubeTexture with vec3 coordinates
|
|
525
|
+
shadowColor = cubeTexture( shadowMap.texture, shadowCoord.xyz );
|
|
526
|
+
|
|
527
|
+
} else {
|
|
528
|
+
|
|
529
|
+
shadowColor = texture( shadowMap.texture, shadowCoord );
|
|
530
|
+
|
|
531
|
+
if ( depthTexture.isArrayTexture ) {
|
|
532
|
+
|
|
533
|
+
shadowColor = shadowColor.depth( this.depthLayer );
|
|
534
|
+
|
|
535
|
+
}
|
|
531
536
|
|
|
532
537
|
}
|
|
533
538
|
|
|
@@ -542,11 +547,25 @@ class ShadowNode extends ShadowBaseNode {
|
|
|
542
547
|
|
|
543
548
|
return shadowOutput.toInspector( `${ inspectName } / Color`, () => {
|
|
544
549
|
|
|
550
|
+
if ( this.shadowMap.texture.isCubeTexture ) {
|
|
551
|
+
|
|
552
|
+
return cubeTexture( this.shadowMap.texture );
|
|
553
|
+
|
|
554
|
+
}
|
|
555
|
+
|
|
545
556
|
return texture( this.shadowMap.texture );
|
|
546
557
|
|
|
547
558
|
} ).toInspector( `${ inspectName } / Depth`, () => {
|
|
548
559
|
|
|
549
|
-
|
|
560
|
+
// TODO: Use linear depth
|
|
561
|
+
|
|
562
|
+
if ( this.shadowMap.texture.isCubeTexture ) {
|
|
563
|
+
|
|
564
|
+
return cubeTexture( this.shadowMap.texture ).r.oneMinus();
|
|
565
|
+
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
return textureLoad( this.shadowMap.depthTexture, uv().mul( textureSize( texture( this.shadowMap.depthTexture ) ) ) ).r.oneMinus();
|
|
550
569
|
|
|
551
570
|
} );
|
|
552
571
|
|
|
@@ -729,6 +748,8 @@ class ShadowNode extends ShadowBaseNode {
|
|
|
729
748
|
|
|
730
749
|
this._currentShadowType = null;
|
|
731
750
|
|
|
751
|
+
disposeShadowMaterial( this.light );
|
|
752
|
+
|
|
732
753
|
if ( this.shadowMap ) {
|
|
733
754
|
|
|
734
755
|
this.shadowMap.dispose();
|
|
@@ -799,6 +820,19 @@ class ShadowNode extends ShadowBaseNode {
|
|
|
799
820
|
|
|
800
821
|
export default ShadowNode;
|
|
801
822
|
|
|
823
|
+
/**
|
|
824
|
+
* Shadow Render Object Function.
|
|
825
|
+
*
|
|
826
|
+
* @function shadowRenderObjectFunction
|
|
827
|
+
* @param {Object3D} object - The 3D object to render.
|
|
828
|
+
* @param {Scene} scene - The scene containing the object.
|
|
829
|
+
* @param {Camera} _camera - The camera used for rendering.
|
|
830
|
+
* @param {BufferGeometry} geometry - The geometry of the object.
|
|
831
|
+
* @param {Material} material - The material of the object.
|
|
832
|
+
* @param {Group} group - The group the object belongs to.
|
|
833
|
+
* @param {...any} params - Additional parameters for rendering.
|
|
834
|
+
*/
|
|
835
|
+
|
|
802
836
|
/**
|
|
803
837
|
* TSL function for creating an instance of `ShadowNode`.
|
|
804
838
|
*
|
|
@@ -808,4 +842,4 @@ export default ShadowNode;
|
|
|
808
842
|
* @param {?LightShadow} [shadow] - The light shadow.
|
|
809
843
|
* @return {ShadowNode} The created shadow node.
|
|
810
844
|
*/
|
|
811
|
-
export const shadow = ( light, shadow ) =>
|
|
845
|
+
export const shadow = ( light, shadow ) => new ShadowNode( light, shadow );
|