super-three 0.169.1 → 0.170.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.
Files changed (193) hide show
  1. package/build/three.cjs +974 -562
  2. package/build/three.module.js +975 -559
  3. package/build/three.module.min.js +1 -1
  4. package/build/three.webgpu.js +8398 -9842
  5. package/build/three.webgpu.min.js +1 -1
  6. package/build/three.webgpu.nodes.js +8398 -9842
  7. package/build/three.webgpu.nodes.min.js +1 -1
  8. package/examples/jsm/Addons.js +3 -3
  9. package/examples/jsm/animation/MMDAnimationHelper.js +2 -0
  10. package/examples/jsm/animation/MMDPhysics.js +2 -0
  11. package/examples/jsm/controls/TransformControls.js +22 -6
  12. package/examples/jsm/csm/CSM.js +2 -2
  13. package/examples/jsm/csm/CSMFrustum.js +7 -4
  14. package/examples/jsm/csm/CSMHelper.js +2 -0
  15. package/examples/jsm/csm/CSMShadowNode.js +435 -0
  16. package/examples/jsm/curves/NURBSCurve.js +34 -3
  17. package/examples/jsm/exporters/GLTFExporter.js +138 -71
  18. package/examples/jsm/exporters/KTX2Exporter.js +35 -12
  19. package/examples/jsm/exporters/MMDExporter.js +6 -0
  20. package/examples/jsm/exporters/USDZExporter.js +21 -3
  21. package/examples/jsm/geometries/DecalGeometry.js +65 -20
  22. package/examples/jsm/geometries/InstancedPointsGeometry.js +2 -0
  23. package/examples/jsm/helpers/TextureHelperGPU.js +175 -0
  24. package/examples/jsm/interactive/HTMLMesh.js +1 -0
  25. package/examples/jsm/lighting/TiledLighting.js +18 -0
  26. package/examples/jsm/lights/RectAreaLightTexturesLib.js +1 -1
  27. package/examples/jsm/lines/LineMaterial.js +7 -2
  28. package/examples/jsm/lines/LineSegmentsGeometry.js +2 -0
  29. package/examples/jsm/lines/webgpu/LineSegments2.js +0 -15
  30. package/examples/jsm/lines/webgpu/Wireframe.js +56 -0
  31. package/examples/jsm/loaders/3DMLoader.js +1 -0
  32. package/examples/jsm/loaders/3MFLoader.js +91 -0
  33. package/examples/jsm/loaders/FBXLoader.js +12 -2
  34. package/examples/jsm/loaders/GLTFLoader.js +2 -0
  35. package/examples/jsm/loaders/KTX2Loader.js +140 -49
  36. package/examples/jsm/loaders/LDrawLoader.js +22 -136
  37. package/examples/jsm/loaders/LottieLoader.js +1 -0
  38. package/examples/jsm/loaders/MMDLoader.js +9 -2
  39. package/examples/jsm/materials/LDrawConditionalLineMaterial.js +143 -0
  40. package/examples/jsm/materials/LDrawConditionalLineNodeMaterial.js +114 -0
  41. package/examples/jsm/materials/MeshGouraudMaterial.js +6 -2
  42. package/examples/jsm/math/ColorSpaces.js +76 -0
  43. package/examples/jsm/misc/ProgressiveLightMap.js +52 -40
  44. package/examples/jsm/misc/ProgressiveLightMapGPU.js +293 -0
  45. package/examples/jsm/misc/VolumeSlice.js +1 -0
  46. package/examples/jsm/objects/WaterMesh.js +8 -8
  47. package/examples/jsm/postprocessing/AfterimagePass.js +14 -3
  48. package/examples/jsm/postprocessing/SSRPass.js +6 -0
  49. package/examples/jsm/renderers/CSS2DRenderer.js +6 -3
  50. package/examples/jsm/renderers/CSS3DRenderer.js +7 -4
  51. package/examples/jsm/shaders/FXAAShader.js +225 -224
  52. package/examples/jsm/transpiler/ShaderToyDecoder.js +1 -1
  53. package/{src/nodes → examples/jsm/tsl}/display/AfterImageNode.js +17 -20
  54. package/{src/nodes → examples/jsm/tsl}/display/AnaglyphPassNode.js +2 -6
  55. package/{src/nodes → examples/jsm/tsl}/display/AnamorphicNode.js +12 -18
  56. package/{src/nodes → examples/jsm/tsl}/display/BleachBypass.js +1 -3
  57. package/{src/nodes → examples/jsm/tsl}/display/BloomNode.js +11 -40
  58. package/{src/nodes → examples/jsm/tsl}/display/DenoiseNode.js +18 -41
  59. package/{src/nodes → examples/jsm/tsl}/display/DepthOfFieldNode.js +2 -8
  60. package/{src/nodes → examples/jsm/tsl}/display/DotScreenNode.js +2 -9
  61. package/examples/jsm/tsl/display/FXAANode.js +316 -0
  62. package/{src/nodes → examples/jsm/tsl}/display/FilmNode.js +2 -6
  63. package/{src/nodes → examples/jsm/tsl}/display/GTAONode.js +30 -70
  64. package/{src/nodes → examples/jsm/tsl}/display/GaussianBlurNode.js +74 -36
  65. package/examples/jsm/tsl/display/LensflareNode.js +161 -0
  66. package/{src/nodes → examples/jsm/tsl}/display/Lut3DNode.js +1 -4
  67. package/{src/nodes → examples/jsm/tsl}/display/MotionBlur.js +2 -3
  68. package/examples/jsm/tsl/display/OutlineNode.js +434 -0
  69. package/{src/nodes → examples/jsm/tsl}/display/ParallaxBarrierPassNode.js +1 -5
  70. package/{src/nodes → examples/jsm/tsl}/display/PixelationPassNode.js +3 -15
  71. package/{src/nodes → examples/jsm/tsl}/display/RGBShiftNode.js +1 -6
  72. package/examples/jsm/tsl/display/SMAANode.js +620 -0
  73. package/{src/nodes → examples/jsm/tsl}/display/SSAAPassNode.js +10 -25
  74. package/examples/jsm/tsl/display/SSRNode.js +343 -0
  75. package/{src/nodes → examples/jsm/tsl}/display/Sepia.js +1 -2
  76. package/{src/nodes → examples/jsm/tsl}/display/SobelOperatorNode.js +3 -11
  77. package/{src/nodes → examples/jsm/tsl}/display/StereoCompositePassNode.js +9 -11
  78. package/{src/nodes → examples/jsm/tsl}/display/StereoPassNode.js +10 -11
  79. package/examples/jsm/tsl/display/TRAAPassNode.js +355 -0
  80. package/{src/nodes → examples/jsm/tsl}/display/TransitionNode.js +1 -6
  81. package/examples/jsm/tsl/display/hashBlur.js +24 -0
  82. package/examples/jsm/tsl/lighting/TiledLightsNode.js +392 -0
  83. package/examples/jsm/utils/{TextureUtilsGPU.js → WebGPUTextureUtils.js} +2 -1
  84. package/examples/jsm/webxr/OculusHandPointerModel.js +21 -21
  85. package/examples/jsm/webxr/Text2D.js +6 -6
  86. package/package.json +2 -2
  87. package/src/Three.WebGPU.Nodes.js +4 -0
  88. package/src/Three.WebGPU.js +4 -0
  89. package/src/constants.js +1 -6
  90. package/src/core/BufferGeometry.js +44 -6
  91. package/src/geometries/CylinderGeometry.js +2 -2
  92. package/src/materials/LineBasicMaterial.js +6 -2
  93. package/src/materials/LineDashedMaterial.js +6 -2
  94. package/src/materials/Material.js +14 -1
  95. package/src/materials/MeshBasicMaterial.js +6 -2
  96. package/src/materials/MeshDepthMaterial.js +6 -2
  97. package/src/materials/MeshDistanceMaterial.js +6 -2
  98. package/src/materials/MeshLambertMaterial.js +6 -2
  99. package/src/materials/MeshMatcapMaterial.js +6 -2
  100. package/src/materials/MeshNormalMaterial.js +6 -2
  101. package/src/materials/MeshPhongMaterial.js +6 -2
  102. package/src/materials/MeshPhysicalMaterial.js +6 -2
  103. package/src/materials/MeshStandardMaterial.js +6 -2
  104. package/src/materials/MeshToonMaterial.js +6 -2
  105. package/src/materials/PointsMaterial.js +6 -2
  106. package/src/materials/RawShaderMaterial.js +6 -2
  107. package/src/materials/ShaderMaterial.js +6 -2
  108. package/src/materials/ShadowMaterial.js +6 -2
  109. package/src/materials/SpriteMaterial.js +6 -2
  110. package/src/materials/nodes/NodeMaterial.js +31 -9
  111. package/src/materials/nodes/SpriteNodeMaterial.js +11 -2
  112. package/src/materials/nodes/manager/NodeMaterialObserver.js +111 -2
  113. package/src/math/ColorManagement.js +118 -85
  114. package/src/math/Vector4.js +11 -0
  115. package/src/nodes/Nodes.js +1 -21
  116. package/src/nodes/TSL.js +6 -24
  117. package/src/nodes/accessors/Camera.js +0 -1
  118. package/src/nodes/accessors/SceneNode.js +35 -1
  119. package/src/nodes/accessors/StorageBufferNode.js +32 -10
  120. package/src/nodes/accessors/VelocityNode.js +13 -3
  121. package/src/nodes/code/FunctionCallNode.js +16 -5
  122. package/src/nodes/code/ScriptableNode.js +4 -4
  123. package/src/nodes/core/Node.js +1 -0
  124. package/src/nodes/core/NodeBuilder.js +29 -5
  125. package/src/nodes/core/VarNode.js +15 -3
  126. package/src/nodes/display/ColorAdjustment.js +53 -4
  127. package/src/nodes/display/ColorSpaceFunctions.js +5 -5
  128. package/src/nodes/display/ColorSpaceNode.js +27 -39
  129. package/src/nodes/display/PassNode.js +6 -4
  130. package/src/nodes/display/ToneMappingNode.js +1 -1
  131. package/src/nodes/display/ViewportDepthNode.js +33 -1
  132. package/src/nodes/functions/PhysicalLightingModel.js +21 -15
  133. package/src/nodes/functions/material/getAlphaHashThreshold.js +64 -0
  134. package/src/nodes/functions/material/getGeometryRoughness.js +8 -2
  135. package/src/nodes/functions/material/getParallaxCorrectNormal.js +22 -0
  136. package/src/nodes/gpgpu/ComputeNode.js +9 -1
  137. package/src/nodes/lighting/AnalyticLightNode.js +12 -416
  138. package/src/nodes/lighting/LightsNode.js +24 -12
  139. package/src/nodes/lighting/PointLightNode.js +36 -26
  140. package/src/nodes/lighting/RectAreaLightNode.js +3 -0
  141. package/src/nodes/lighting/ShadowNode.js +484 -0
  142. package/src/nodes/utils/LoopNode.js +2 -2
  143. package/src/nodes/utils/Oscillators.js +6 -0
  144. package/src/nodes/utils/PostProcessingUtils.js +89 -0
  145. package/src/nodes/utils/ReflectorNode.js +101 -15
  146. package/src/nodes/utils/Timer.js +29 -0
  147. package/src/objects/BatchedMesh.js +458 -241
  148. package/src/renderers/WebGLRenderer.js +120 -117
  149. package/src/renderers/common/Attributes.js +4 -0
  150. package/src/renderers/common/Backend.js +2 -0
  151. package/src/renderers/common/Background.js +14 -4
  152. package/src/renderers/common/Bindings.js +3 -2
  153. package/src/renderers/common/Constants.js +2 -1
  154. package/src/renderers/common/Geometries.js +20 -0
  155. package/src/renderers/common/IndirectStorageBufferAttribute.js +15 -0
  156. package/src/renderers/common/Lighting.js +45 -0
  157. package/src/renderers/common/PostProcessingUtils.js +86 -0
  158. package/src/renderers/common/RenderList.js +39 -11
  159. package/src/renderers/common/RenderLists.js +4 -2
  160. package/src/renderers/common/RenderObject.js +18 -1
  161. package/src/renderers/common/Renderer.js +165 -26
  162. package/src/renderers/common/Textures.js +30 -14
  163. package/src/renderers/common/nodes/NodeLibrary.js +1 -14
  164. package/src/renderers/common/nodes/Nodes.js +2 -2
  165. package/src/renderers/shaders/ShaderChunk/colorspace_pars_fragment.glsl.js +4 -24
  166. package/src/renderers/shaders/ShaderChunk/emissivemap_fragment.glsl.js +8 -0
  167. package/src/renderers/shaders/ShaderChunk/map_fragment.glsl.js +2 -2
  168. package/src/renderers/webgl/WebGLBufferRenderer.js +2 -6
  169. package/src/renderers/webgl/WebGLCapabilities.js +0 -7
  170. package/src/renderers/webgl/WebGLIndexedBufferRenderer.js +2 -6
  171. package/src/renderers/webgl/WebGLProgram.js +24 -28
  172. package/src/renderers/webgl/WebGLPrograms.js +5 -2
  173. package/src/renderers/webgl/WebGLState.js +37 -1
  174. package/src/renderers/webgl/WebGLTextures.js +29 -12
  175. package/src/renderers/webgl-fallback/WebGLBackend.js +98 -31
  176. package/src/renderers/webgl-fallback/WebGLBufferRenderer.js +2 -7
  177. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +33 -8
  178. package/src/renderers/webgpu/WebGPUBackend.js +105 -25
  179. package/src/renderers/webgpu/WebGPURenderer.Nodes.js +1 -1
  180. package/src/renderers/webgpu/WebGPURenderer.js +1 -1
  181. package/src/renderers/webgpu/nodes/BasicNodeLibrary.js +0 -8
  182. package/src/renderers/webgpu/nodes/StandardNodeLibrary.js +0 -8
  183. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +10 -20
  184. package/src/renderers/webgpu/nodes/WGSLNodeFunction.js +12 -4
  185. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +29 -9
  186. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +24 -6
  187. package/src/renderers/webgpu/utils/WebGPUUtils.js +0 -1
  188. package/src/renderers/webxr/WebXRManager.js +4 -4
  189. package/examples/jsm/cameras/CinematicCamera.js +0 -208
  190. package/src/nodes/display/FXAANode.js +0 -332
  191. package/src/nodes/utils/OscNode.js +0 -85
  192. package/src/nodes/utils/TimerNode.js +0 -97
  193. /package/examples/jsm/utils/{TextureUtils.js → WebGLTextureUtils.js} +0 -0
@@ -3,7 +3,35 @@ import { getDistanceAttenuation } from './LightUtils.js';
3
3
  import { uniform } from '../core/UniformNode.js';
4
4
  import { lightViewPosition } from '../accessors/Lights.js';
5
5
  import { positionView } from '../accessors/Position.js';
6
- import { renderGroup } from '../TSL.js';
6
+ import { Fn } from '../tsl/TSLBase.js';
7
+ import { renderGroup } from '../core/UniformGroupNode.js';
8
+
9
+ export const directPointLight = Fn( ( { color, lightViewPosition, cutoffDistance, decayExponent }, builder ) => {
10
+
11
+ const lightingModel = builder.context.lightingModel;
12
+
13
+ const lVector = lightViewPosition.sub( positionView ); // @TODO: Add it into LightNode
14
+
15
+ const lightDirection = lVector.normalize();
16
+ const lightDistance = lVector.length();
17
+
18
+ const lightAttenuation = getDistanceAttenuation( {
19
+ lightDistance,
20
+ cutoffDistance,
21
+ decayExponent
22
+ } );
23
+
24
+ const lightColor = color.mul( lightAttenuation );
25
+
26
+ const reflectedLight = builder.context.reflectedLight;
27
+
28
+ lightingModel.direct( {
29
+ lightDirection,
30
+ lightColor,
31
+ reflectedLight
32
+ }, builder.stack, builder );
33
+
34
+ } );
7
35
 
8
36
  class PointLightNode extends AnalyticLightNode {
9
37
 
@@ -33,32 +61,14 @@ class PointLightNode extends AnalyticLightNode {
33
61
 
34
62
  }
35
63
 
36
- setup( builder ) {
37
-
38
- const { colorNode, cutoffDistanceNode, decayExponentNode, light } = this;
39
-
40
- const lightingModel = builder.context.lightingModel;
41
-
42
- const lVector = lightViewPosition( light ).sub( positionView ); // @TODO: Add it into LightNode
43
-
44
- const lightDirection = lVector.normalize();
45
- const lightDistance = lVector.length();
46
-
47
- const lightAttenuation = getDistanceAttenuation( {
48
- lightDistance,
49
- cutoffDistance: cutoffDistanceNode,
50
- decayExponent: decayExponentNode
51
- } );
52
-
53
- const lightColor = colorNode.mul( lightAttenuation );
54
-
55
- const reflectedLight = builder.context.reflectedLight;
64
+ setup() {
56
65
 
57
- lightingModel.direct( {
58
- lightDirection,
59
- lightColor,
60
- reflectedLight
61
- }, builder.stack, builder );
66
+ directPointLight( {
67
+ color: this.colorNode,
68
+ lightViewPosition: lightViewPosition( this.light ),
69
+ cutoffDistance: this.cutoffDistanceNode,
70
+ decayExponent: this.decayExponentNode
71
+ } ).append();
62
72
 
63
73
  }
64
74
 
@@ -6,6 +6,7 @@ import { renderGroup } from '../core/UniformGroupNode.js';
6
6
 
7
7
  import { Matrix4 } from '../../math/Matrix4.js';
8
8
  import { Vector3 } from '../../math/Vector3.js';
9
+ import { NodeUpdateType } from '../core/constants.js';
9
10
 
10
11
  const _matrix41 = /*@__PURE__*/ new Matrix4();
11
12
  const _matrix42 = /*@__PURE__*/ new Matrix4();
@@ -27,6 +28,8 @@ class RectAreaLightNode extends AnalyticLightNode {
27
28
  this.halfHeight = uniform( new Vector3() ).setGroup( renderGroup );
28
29
  this.halfWidth = uniform( new Vector3() ).setGroup( renderGroup );
29
30
 
31
+ this.updateType = NodeUpdateType.RENDER;
32
+
30
33
  }
31
34
 
32
35
  update( frame ) {
@@ -0,0 +1,484 @@
1
+ import Node from '../core/Node.js';
2
+ import { NodeUpdateType } from '../core/constants.js';
3
+ import { uniform } from '../core/UniformNode.js';
4
+ import { float, vec2, vec3, vec4, If, int, Fn, nodeObject } from '../tsl/TSLBase.js';
5
+ import { reference } from '../accessors/ReferenceNode.js';
6
+ import { texture } from '../accessors/TextureNode.js';
7
+ import { positionWorld } from '../accessors/Position.js';
8
+ import { transformedNormalWorld } from '../accessors/Normal.js';
9
+ import { mix, fract, step, max, clamp, sqrt } from '../math/MathNode.js';
10
+ import { add, sub } from '../math/OperatorNode.js';
11
+ import { DepthTexture } from '../../textures/DepthTexture.js';
12
+ import NodeMaterial from '../../materials/nodes/NodeMaterial.js';
13
+ import QuadMesh from '../../renderers/common/QuadMesh.js';
14
+ import { Loop } from '../utils/LoopNode.js';
15
+ import { screenCoordinate } from '../display/ScreenNode.js';
16
+ import { HalfFloatType, LessCompare, RGFormat, VSMShadowMap, WebGPUCoordinateSystem } from '../../constants.js';
17
+ import { renderGroup } from '../core/UniformGroupNode.js';
18
+ import { perspectiveDepthToLogarithmicDepth } from '../display/ViewportDepthNode.js';
19
+
20
+ const BasicShadowMap = Fn( ( { depthTexture, shadowCoord } ) => {
21
+
22
+ return texture( depthTexture, shadowCoord.xy ).compare( shadowCoord.z );
23
+
24
+ } );
25
+
26
+ const PCFShadowMap = Fn( ( { depthTexture, shadowCoord, shadow } ) => {
27
+
28
+ const depthCompare = ( uv, compare ) => texture( depthTexture, uv ).compare( compare );
29
+
30
+ const mapSize = reference( 'mapSize', 'vec2', shadow ).setGroup( renderGroup );
31
+ const radius = reference( 'radius', 'float', shadow ).setGroup( renderGroup );
32
+
33
+ const texelSize = vec2( 1 ).div( mapSize );
34
+ const dx0 = texelSize.x.negate().mul( radius );
35
+ const dy0 = texelSize.y.negate().mul( radius );
36
+ const dx1 = texelSize.x.mul( radius );
37
+ const dy1 = texelSize.y.mul( radius );
38
+ const dx2 = dx0.div( 2 );
39
+ const dy2 = dy0.div( 2 );
40
+ const dx3 = dx1.div( 2 );
41
+ const dy3 = dy1.div( 2 );
42
+
43
+ return add(
44
+ depthCompare( shadowCoord.xy.add( vec2( dx0, dy0 ) ), shadowCoord.z ),
45
+ depthCompare( shadowCoord.xy.add( vec2( 0, dy0 ) ), shadowCoord.z ),
46
+ depthCompare( shadowCoord.xy.add( vec2( dx1, dy0 ) ), shadowCoord.z ),
47
+ depthCompare( shadowCoord.xy.add( vec2( dx2, dy2 ) ), shadowCoord.z ),
48
+ depthCompare( shadowCoord.xy.add( vec2( 0, dy2 ) ), shadowCoord.z ),
49
+ depthCompare( shadowCoord.xy.add( vec2( dx3, dy2 ) ), shadowCoord.z ),
50
+ depthCompare( shadowCoord.xy.add( vec2( dx0, 0 ) ), shadowCoord.z ),
51
+ depthCompare( shadowCoord.xy.add( vec2( dx2, 0 ) ), shadowCoord.z ),
52
+ depthCompare( shadowCoord.xy, shadowCoord.z ),
53
+ depthCompare( shadowCoord.xy.add( vec2( dx3, 0 ) ), shadowCoord.z ),
54
+ depthCompare( shadowCoord.xy.add( vec2( dx1, 0 ) ), shadowCoord.z ),
55
+ depthCompare( shadowCoord.xy.add( vec2( dx2, dy3 ) ), shadowCoord.z ),
56
+ depthCompare( shadowCoord.xy.add( vec2( 0, dy3 ) ), shadowCoord.z ),
57
+ depthCompare( shadowCoord.xy.add( vec2( dx3, dy3 ) ), shadowCoord.z ),
58
+ depthCompare( shadowCoord.xy.add( vec2( dx0, dy1 ) ), shadowCoord.z ),
59
+ depthCompare( shadowCoord.xy.add( vec2( 0, dy1 ) ), shadowCoord.z ),
60
+ depthCompare( shadowCoord.xy.add( vec2( dx1, dy1 ) ), shadowCoord.z )
61
+ ).mul( 1 / 17 );
62
+
63
+ } );
64
+
65
+ const PCFSoftShadowMap = Fn( ( { depthTexture, shadowCoord, shadow } ) => {
66
+
67
+ const depthCompare = ( uv, compare ) => texture( depthTexture, uv ).compare( compare );
68
+
69
+ const mapSize = reference( 'mapSize', 'vec2', shadow ).setGroup( renderGroup );
70
+
71
+ const texelSize = vec2( 1 ).div( mapSize );
72
+ const dx = texelSize.x;
73
+ const dy = texelSize.y;
74
+
75
+ const uv = shadowCoord.xy;
76
+ const f = fract( uv.mul( mapSize ).add( 0.5 ) );
77
+ uv.subAssign( f.mul( texelSize ) );
78
+
79
+ return add(
80
+ depthCompare( uv, shadowCoord.z ),
81
+ depthCompare( uv.add( vec2( dx, 0 ) ), shadowCoord.z ),
82
+ depthCompare( uv.add( vec2( 0, dy ) ), shadowCoord.z ),
83
+ depthCompare( uv.add( texelSize ), shadowCoord.z ),
84
+ mix(
85
+ depthCompare( uv.add( vec2( dx.negate(), 0 ) ), shadowCoord.z ),
86
+ depthCompare( uv.add( vec2( dx.mul( 2 ), 0 ) ), shadowCoord.z ),
87
+ f.x
88
+ ),
89
+ mix(
90
+ depthCompare( uv.add( vec2( dx.negate(), dy ) ), shadowCoord.z ),
91
+ depthCompare( uv.add( vec2( dx.mul( 2 ), dy ) ), shadowCoord.z ),
92
+ f.x
93
+ ),
94
+ mix(
95
+ depthCompare( uv.add( vec2( 0, dy.negate() ) ), shadowCoord.z ),
96
+ depthCompare( uv.add( vec2( 0, dy.mul( 2 ) ) ), shadowCoord.z ),
97
+ f.y
98
+ ),
99
+ mix(
100
+ depthCompare( uv.add( vec2( dx, dy.negate() ) ), shadowCoord.z ),
101
+ depthCompare( uv.add( vec2( dx, dy.mul( 2 ) ) ), shadowCoord.z ),
102
+ f.y
103
+ ),
104
+ mix(
105
+ mix(
106
+ depthCompare( uv.add( vec2( dx.negate(), dy.negate() ) ), shadowCoord.z ),
107
+ depthCompare( uv.add( vec2( dx.mul( 2 ), dy.negate() ) ), shadowCoord.z ),
108
+ f.x
109
+ ),
110
+ mix(
111
+ depthCompare( uv.add( vec2( dx.negate(), dy.mul( 2 ) ) ), shadowCoord.z ),
112
+ depthCompare( uv.add( vec2( dx.mul( 2 ), dy.mul( 2 ) ) ), shadowCoord.z ),
113
+ f.x
114
+ ),
115
+ f.y
116
+ )
117
+ ).mul( 1 / 9 );
118
+
119
+ } );
120
+
121
+ // VSM
122
+
123
+ const VSMShadowMapNode = Fn( ( { depthTexture, shadowCoord } ) => {
124
+
125
+ const occlusion = float( 1 ).toVar();
126
+
127
+ const distribution = texture( depthTexture ).uv( shadowCoord.xy ).rg;
128
+
129
+ const hardShadow = step( shadowCoord.z, distribution.x );
130
+
131
+ If( hardShadow.notEqual( float( 1.0 ) ), () => {
132
+
133
+ const distance = shadowCoord.z.sub( distribution.x );
134
+ const variance = max( 0, distribution.y.mul( distribution.y ) );
135
+ let softnessProbability = variance.div( variance.add( distance.mul( distance ) ) ); // Chebeyshevs inequality
136
+ softnessProbability = clamp( sub( softnessProbability, 0.3 ).div( 0.95 - 0.3 ) );
137
+ occlusion.assign( clamp( max( hardShadow, softnessProbability ) ) );
138
+
139
+ } );
140
+
141
+ return occlusion;
142
+
143
+ } );
144
+
145
+ const VSMPassVertical = Fn( ( { samples, radius, size, shadowPass } ) => {
146
+
147
+ const mean = float( 0 ).toVar();
148
+ const squaredMean = float( 0 ).toVar();
149
+
150
+ const uvStride = samples.lessThanEqual( float( 1 ) ).select( float( 0 ), float( 2 ).div( samples.sub( 1 ) ) );
151
+ const uvStart = samples.lessThanEqual( float( 1 ) ).select( float( 0 ), float( - 1 ) );
152
+
153
+ Loop( { start: int( 0 ), end: int( samples ), type: 'int', condition: '<' }, ( { i } ) => {
154
+
155
+ const uvOffset = uvStart.add( float( i ).mul( uvStride ) );
156
+
157
+ const depth = shadowPass.uv( add( screenCoordinate.xy, vec2( 0, uvOffset ).mul( radius ) ).div( size ) ).x;
158
+ mean.addAssign( depth );
159
+ squaredMean.addAssign( depth.mul( depth ) );
160
+
161
+ } );
162
+
163
+ mean.divAssign( samples );
164
+ squaredMean.divAssign( samples );
165
+
166
+ const std_dev = sqrt( squaredMean.sub( mean.mul( mean ) ) );
167
+ return vec2( mean, std_dev );
168
+
169
+ } );
170
+
171
+ const VSMPassHorizontal = Fn( ( { samples, radius, size, shadowPass } ) => {
172
+
173
+ const mean = float( 0 ).toVar();
174
+ const squaredMean = float( 0 ).toVar();
175
+
176
+ const uvStride = samples.lessThanEqual( float( 1 ) ).select( float( 0 ), float( 2 ).div( samples.sub( 1 ) ) );
177
+ const uvStart = samples.lessThanEqual( float( 1 ) ).select( float( 0 ), float( - 1 ) );
178
+
179
+ Loop( { start: int( 0 ), end: int( samples ), type: 'int', condition: '<' }, ( { i } ) => {
180
+
181
+ const uvOffset = uvStart.add( float( i ).mul( uvStride ) );
182
+
183
+ const distribution = shadowPass.uv( add( screenCoordinate.xy, vec2( uvOffset, 0 ).mul( radius ) ).div( size ) );
184
+ mean.addAssign( distribution.x );
185
+ squaredMean.addAssign( add( distribution.y.mul( distribution.y ), distribution.x.mul( distribution.x ) ) );
186
+
187
+ } );
188
+
189
+ mean.divAssign( samples );
190
+ squaredMean.divAssign( samples );
191
+
192
+ const std_dev = sqrt( squaredMean.sub( mean.mul( mean ) ) );
193
+ return vec2( mean, std_dev );
194
+
195
+ } );
196
+
197
+ const _shadowFilterLib = [ BasicShadowMap, PCFShadowMap, PCFSoftShadowMap, VSMShadowMapNode ];
198
+
199
+ //
200
+
201
+ let _overrideMaterial = null;
202
+ const _quadMesh = /*@__PURE__*/ new QuadMesh();
203
+
204
+ class ShadowNode extends Node {
205
+
206
+ static get type() {
207
+
208
+ return 'ShadowNode';
209
+
210
+ }
211
+
212
+ constructor( light, shadow = null ) {
213
+
214
+ super();
215
+
216
+ this.light = light;
217
+ this.shadow = shadow || light.shadow;
218
+
219
+ this.shadowMap = null;
220
+
221
+ this.vsmShadowMapVertical = null;
222
+ this.vsmShadowMapHorizontal = null;
223
+
224
+ this.vsmMaterialVertical = null;
225
+ this.vsmMaterialHorizontal = null;
226
+
227
+ this.updateBeforeType = NodeUpdateType.RENDER;
228
+ this._node = null;
229
+
230
+ this.isShadowNode = true;
231
+
232
+ }
233
+
234
+ setupShadow( builder ) {
235
+
236
+ const { object, renderer } = builder;
237
+
238
+ if ( _overrideMaterial === null ) {
239
+
240
+ _overrideMaterial = new NodeMaterial();
241
+ _overrideMaterial.fragmentNode = vec4( 0, 0, 0, 1 );
242
+ _overrideMaterial.isShadowNodeMaterial = true; // Use to avoid other overrideMaterial override material.fragmentNode unintentionally when using material.shadowNode
243
+ _overrideMaterial.name = 'ShadowMaterial';
244
+
245
+ }
246
+
247
+ const shadow = this.shadow;
248
+ const shadowMapType = renderer.shadowMap.type;
249
+
250
+ const depthTexture = new DepthTexture( shadow.mapSize.width, shadow.mapSize.height );
251
+ depthTexture.compareFunction = LessCompare;
252
+
253
+ const shadowMap = builder.createRenderTarget( shadow.mapSize.width, shadow.mapSize.height );
254
+ shadowMap.depthTexture = depthTexture;
255
+
256
+ shadow.camera.updateProjectionMatrix();
257
+
258
+ // VSM
259
+
260
+ if ( shadowMapType === VSMShadowMap ) {
261
+
262
+ depthTexture.compareFunction = null; // VSM does not use textureSampleCompare()/texture2DCompare()
263
+
264
+ this.vsmShadowMapVertical = builder.createRenderTarget( shadow.mapSize.width, shadow.mapSize.height, { format: RGFormat, type: HalfFloatType } );
265
+ this.vsmShadowMapHorizontal = builder.createRenderTarget( shadow.mapSize.width, shadow.mapSize.height, { format: RGFormat, type: HalfFloatType } );
266
+
267
+ const shadowPassVertical = texture( depthTexture );
268
+ const shadowPassHorizontal = texture( this.vsmShadowMapVertical.texture );
269
+
270
+ const samples = reference( 'blurSamples', 'float', shadow ).setGroup( renderGroup );
271
+ const radius = reference( 'radius', 'float', shadow ).setGroup( renderGroup );
272
+ const size = reference( 'mapSize', 'vec2', shadow ).setGroup( renderGroup );
273
+
274
+ let material = this.vsmMaterialVertical || ( this.vsmMaterialVertical = new NodeMaterial() );
275
+ material.fragmentNode = VSMPassVertical( { samples, radius, size, shadowPass: shadowPassVertical } ).context( builder.getSharedContext() );
276
+ material.name = 'VSMVertical';
277
+
278
+ material = this.vsmMaterialHorizontal || ( this.vsmMaterialHorizontal = new NodeMaterial() );
279
+ material.fragmentNode = VSMPassHorizontal( { samples, radius, size, shadowPass: shadowPassHorizontal } ).context( builder.getSharedContext() );
280
+ material.name = 'VSMHorizontal';
281
+
282
+ }
283
+
284
+ //
285
+
286
+ const shadowIntensity = reference( 'intensity', 'float', shadow ).setGroup( renderGroup );
287
+ const bias = reference( 'bias', 'float', shadow ).setGroup( renderGroup );
288
+ const normalBias = reference( 'normalBias', 'float', shadow ).setGroup( renderGroup );
289
+
290
+ const position = object.material.shadowPositionNode || positionWorld;
291
+
292
+ let shadowCoord = uniform( shadow.matrix ).setGroup( renderGroup ).mul( position.add( transformedNormalWorld.mul( normalBias ) ) );
293
+
294
+ let coordZ;
295
+
296
+ if ( shadow.camera.isOrthographicCamera || renderer.logarithmicDepthBuffer !== true ) {
297
+
298
+ shadowCoord = shadowCoord.xyz.div( shadowCoord.w );
299
+
300
+ coordZ = shadowCoord.z;
301
+
302
+ if ( renderer.coordinateSystem === WebGPUCoordinateSystem ) {
303
+
304
+ coordZ = coordZ.mul( 2 ).sub( 1 ); // WebGPU: Conversion [ 0, 1 ] to [ - 1, 1 ]
305
+
306
+ }
307
+
308
+ } else {
309
+
310
+ const w = shadowCoord.w;
311
+ shadowCoord = shadowCoord.xy.div( w ); // <-- Only divide X/Y coords since we don't need Z
312
+
313
+ // The normally available "cameraNear" and "cameraFar" nodes cannot be used here because they do not get
314
+ // updated to use the shadow camera. So, we have to declare our own "local" ones here.
315
+ // TODO: How do we get the cameraNear/cameraFar nodes to use the shadow camera so we don't have to declare local ones here?
316
+ const cameraNearLocal = uniform( 'float' ).onRenderUpdate( () => shadow.camera.near );
317
+ const cameraFarLocal = uniform( 'float' ).onRenderUpdate( () => shadow.camera.far );
318
+
319
+ coordZ = perspectiveDepthToLogarithmicDepth( w, cameraNearLocal, cameraFarLocal );
320
+
321
+ }
322
+
323
+ shadowCoord = vec3(
324
+ shadowCoord.x,
325
+ shadowCoord.y.oneMinus(), // follow webgpu standards
326
+ coordZ.add( bias )
327
+ );
328
+
329
+ const frustumTest = shadowCoord.x.greaterThanEqual( 0 )
330
+ .and( shadowCoord.x.lessThanEqual( 1 ) )
331
+ .and( shadowCoord.y.greaterThanEqual( 0 ) )
332
+ .and( shadowCoord.y.lessThanEqual( 1 ) )
333
+ .and( shadowCoord.z.lessThanEqual( 1 ) );
334
+
335
+ //
336
+
337
+ const filterFn = shadow.filterNode || _shadowFilterLib[ renderer.shadowMap.type ] || null;
338
+
339
+ if ( filterFn === null ) {
340
+
341
+ throw new Error( 'THREE.WebGPURenderer: Shadow map type not supported yet.' );
342
+
343
+ }
344
+
345
+ const shadowColor = texture( shadowMap.texture, shadowCoord );
346
+ const shadowNode = frustumTest.select( filterFn( { depthTexture: ( shadowMapType === VSMShadowMap ) ? this.vsmShadowMapHorizontal.texture : depthTexture, shadowCoord, shadow } ), float( 1 ) );
347
+
348
+ this.shadowMap = shadowMap;
349
+ this.shadow.map = shadowMap;
350
+
351
+ return mix( 1, shadowNode.rgb.mix( shadowColor, 1 ), shadowIntensity.mul( shadowColor.a ) );
352
+
353
+ }
354
+
355
+ setup( builder ) {
356
+
357
+ if ( builder.renderer.shadowMap.enabled === false ) return;
358
+
359
+ return this._node !== null ? this._node : ( this._node = this.setupShadow( builder ) );
360
+
361
+ }
362
+
363
+ updateShadow( frame ) {
364
+
365
+ const { shadowMap, light, shadow } = this;
366
+ const { renderer, scene, camera } = frame;
367
+
368
+ const shadowType = renderer.shadowMap.type;
369
+
370
+ const depthVersion = shadowMap.depthTexture.version;
371
+ this._depthVersionCached = depthVersion;
372
+
373
+ const currentOverrideMaterial = scene.overrideMaterial;
374
+
375
+ scene.overrideMaterial = _overrideMaterial;
376
+
377
+ shadowMap.setSize( shadow.mapSize.width, shadow.mapSize.height );
378
+
379
+ shadow.updateMatrices( light );
380
+ shadow.camera.layers.mask = camera.layers.mask;
381
+
382
+ const currentRenderTarget = renderer.getRenderTarget();
383
+ const currentRenderObjectFunction = renderer.getRenderObjectFunction();
384
+
385
+ renderer.setRenderObjectFunction( ( object, ...params ) => {
386
+
387
+ if ( object.castShadow === true || ( object.receiveShadow && shadowType === VSMShadowMap ) ) {
388
+
389
+ renderer.renderObject( object, ...params );
390
+
391
+ }
392
+
393
+ } );
394
+
395
+ renderer.setRenderTarget( shadowMap );
396
+ renderer.render( scene, shadow.camera );
397
+
398
+ renderer.setRenderObjectFunction( currentRenderObjectFunction );
399
+
400
+ // vsm blur pass
401
+
402
+ if ( light.isPointLight !== true && shadowType === VSMShadowMap ) {
403
+
404
+ this.vsmPass( renderer );
405
+
406
+ }
407
+
408
+ renderer.setRenderTarget( currentRenderTarget );
409
+
410
+ scene.overrideMaterial = currentOverrideMaterial;
411
+
412
+ }
413
+
414
+ vsmPass( renderer ) {
415
+
416
+ const { shadow } = this;
417
+
418
+ this.vsmShadowMapVertical.setSize( shadow.mapSize.width, shadow.mapSize.height );
419
+ this.vsmShadowMapHorizontal.setSize( shadow.mapSize.width, shadow.mapSize.height );
420
+
421
+ renderer.setRenderTarget( this.vsmShadowMapVertical );
422
+ _quadMesh.material = this.vsmMaterialVertical;
423
+ _quadMesh.render( renderer );
424
+
425
+ renderer.setRenderTarget( this.vsmShadowMapHorizontal );
426
+ _quadMesh.material = this.vsmMaterialHorizontal;
427
+ _quadMesh.render( renderer );
428
+
429
+ }
430
+
431
+ dispose() {
432
+
433
+ this.shadowMap.dispose();
434
+ this.shadowMap = null;
435
+
436
+ if ( this.vsmShadowMapVertical !== null ) {
437
+
438
+ this.vsmShadowMapVertical.dispose();
439
+ this.vsmShadowMapVertical = null;
440
+
441
+ this.vsmMaterialVertical.dispose();
442
+ this.vsmMaterialVertical = null;
443
+
444
+ }
445
+
446
+ if ( this.vsmShadowMapHorizontal !== null ) {
447
+
448
+ this.vsmShadowMapHorizontal.dispose();
449
+ this.vsmShadowMapHorizontal = null;
450
+
451
+ this.vsmMaterialHorizontal.dispose();
452
+ this.vsmMaterialHorizontal = null;
453
+
454
+ }
455
+
456
+ this.updateBeforeType = NodeUpdateType.NONE;
457
+
458
+ }
459
+
460
+ updateBefore( frame ) {
461
+
462
+ const { shadow } = this;
463
+
464
+ const needsUpdate = shadow.needsUpdate || shadow.autoUpdate;
465
+
466
+ if ( needsUpdate ) {
467
+
468
+ this.updateShadow( frame );
469
+
470
+ if ( this.shadowMap.depthTexture.version === this._depthVersionCached ) {
471
+
472
+ shadow.needsUpdate = false;
473
+
474
+ }
475
+
476
+ }
477
+
478
+ }
479
+
480
+ }
481
+
482
+ export default ShadowNode;
483
+
484
+ export const shadow = ( light, shadow ) => nodeObject( new ShadowNode( light, shadow ) );
@@ -102,10 +102,10 @@ class LoopNode extends Node {
102
102
  condition = param.condition;
103
103
  update = param.update;
104
104
 
105
- if ( typeof start === 'number' ) start = start.toString();
105
+ if ( typeof start === 'number' ) start = builder.generateConst( type, start );
106
106
  else if ( start && start.isNode ) start = start.build( builder, type );
107
107
 
108
- if ( typeof end === 'number' ) end = end.toString();
108
+ if ( typeof end === 'number' ) end = builder.generateConst( type, end );
109
109
  else if ( end && end.isNode ) end = end.build( builder, type );
110
110
 
111
111
  if ( start !== undefined && end === undefined ) {
@@ -0,0 +1,6 @@
1
+ import { time } from './Timer.js';
2
+
3
+ export const oscSine = ( t = time ) => t.add( 0.75 ).mul( Math.PI * 2 ).sin().mul( 0.5 ).add( 0.5 );
4
+ export const oscSquare = ( t = time ) => t.fract().round();
5
+ export const oscTriangle = ( t = time ) => t.add( 0.5 ).fract().mul( 2 ).sub( 1 ).abs();
6
+ export const oscSawtooth = ( t = time ) => t.fract();
@@ -0,0 +1,89 @@
1
+ import { abs, cross, float, Fn, normalize, ivec2, sub, vec2, vec3, vec4 } from '../tsl/TSLBase.js';
2
+ import { textureSize } from '../accessors/TextureSizeNode.js';
3
+ import { textureLoad } from '../accessors/TextureNode.js';
4
+ import { WebGPUCoordinateSystem } from '../../constants.js';
5
+
6
+ /**
7
+ * Computes a position in view space based on a fragment's screen position expressed as uv coordinates, the fragments
8
+ * depth value and the camera's inverse projection matrix.
9
+ *
10
+ * @param {vec2} screenPosition - The fragment's screen position expressed as uv coordinates.
11
+ * @param {float} depth - The fragment's depth value.
12
+ * @param {mat4} projectionMatrixInverse - The camera's inverse projection matrix.
13
+ * @return {vec3} The fragments position in view space.
14
+ */
15
+ export const getViewPosition = /*@__PURE__*/ Fn( ( [ screenPosition, depth, projectionMatrixInverse ], builder ) => {
16
+
17
+ let clipSpacePosition;
18
+
19
+ if ( builder.renderer.coordinateSystem === WebGPUCoordinateSystem ) {
20
+
21
+ screenPosition = vec2( screenPosition.x, screenPosition.y.oneMinus() ).mul( 2.0 ).sub( 1.0 );
22
+ clipSpacePosition = vec4( vec3( screenPosition, depth ), 1.0 );
23
+
24
+ } else {
25
+
26
+ clipSpacePosition = vec4( vec3( screenPosition.x, screenPosition.y.oneMinus(), depth ).mul( 2.0 ).sub( 1.0 ), 1.0 );
27
+
28
+ }
29
+
30
+ const viewSpacePosition = vec4( projectionMatrixInverse.mul( clipSpacePosition ) );
31
+
32
+ return viewSpacePosition.xyz.div( viewSpacePosition.w );
33
+
34
+ } );
35
+
36
+ /**
37
+ * Computes a screen position expressed as uv coordinates based on a fragment's position in view space
38
+ * and the camera's projection matrix
39
+ *
40
+ * @param {vec3} viewPosition - The fragments position in view space.
41
+ * @param {mat4} projectionMatrix - The camera's projection matrix.
42
+ * @return {vec2} The fragment's screen position expressed as uv coordinates.
43
+ */
44
+ export const getScreenPosition = /*@__PURE__*/ Fn( ( [ viewPosition, projectionMatrix ] ) => {
45
+
46
+ const sampleClipPos = projectionMatrix.mul( vec4( viewPosition, 1.0 ) );
47
+ const sampleUv = sampleClipPos.xy.div( sampleClipPos.w ).mul( 0.5 ).add( 0.5 ).toVar();
48
+ return vec2( sampleUv.x, sampleUv.y.oneMinus() );
49
+
50
+ } );
51
+
52
+ /**
53
+ * Computes a normal vector based on depth data. Can be used as a fallback when no normal render
54
+ * target is available or if flat surface normals are required.
55
+ *
56
+ * @param {vec2} uv - The texture coordinate.
57
+ * @param {DepthTexture} depthTexture - The depth texture.
58
+ * @param {mat4} projectionMatrixInverse - The camera's inverse projection matrix.
59
+ * @return {vec3} The computed normal vector.
60
+ */
61
+ export const getNormalFromDepth = /*@__PURE__*/ Fn( ( [ uv, depthTexture, projectionMatrixInverse ] ) => {
62
+
63
+ const size = textureSize( textureLoad( depthTexture ) );
64
+ const p = ivec2( uv.mul( size ) ).toVar();
65
+
66
+ const c0 = textureLoad( depthTexture, p ).toVar();
67
+
68
+ const l2 = textureLoad( depthTexture, p.sub( ivec2( 2, 0 ) ) ).toVar();
69
+ const l1 = textureLoad( depthTexture, p.sub( ivec2( 1, 0 ) ) ).toVar();
70
+ const r1 = textureLoad( depthTexture, p.add( ivec2( 1, 0 ) ) ).toVar();
71
+ const r2 = textureLoad( depthTexture, p.add( ivec2( 2, 0 ) ) ).toVar();
72
+ const b2 = textureLoad( depthTexture, p.add( ivec2( 0, 2 ) ) ).toVar();
73
+ const b1 = textureLoad( depthTexture, p.add( ivec2( 0, 1 ) ) ).toVar();
74
+ const t1 = textureLoad( depthTexture, p.sub( ivec2( 0, 1 ) ) ).toVar();
75
+ const t2 = textureLoad( depthTexture, p.sub( ivec2( 0, 2 ) ) ).toVar();
76
+
77
+ const dl = abs( sub( float( 2 ).mul( l1 ).sub( l2 ), c0 ) ).toVar();
78
+ const dr = abs( sub( float( 2 ).mul( r1 ).sub( r2 ), c0 ) ).toVar();
79
+ const db = abs( sub( float( 2 ).mul( b1 ).sub( b2 ), c0 ) ).toVar();
80
+ const dt = abs( sub( float( 2 ).mul( t1 ).sub( t2 ), c0 ) ).toVar();
81
+
82
+ const ce = getViewPosition( uv, c0, projectionMatrixInverse ).toVar();
83
+
84
+ const dpdx = dl.lessThan( dr ).select( ce.sub( getViewPosition( uv.sub( vec2( float( 1 ).div( size.x ), 0 ) ), l1, projectionMatrixInverse ) ), ce.negate().add( getViewPosition( uv.add( vec2( float( 1 ).div( size.x ), 0 ) ), r1, projectionMatrixInverse ) ) );
85
+ const dpdy = db.lessThan( dt ).select( ce.sub( getViewPosition( uv.add( vec2( 0, float( 1 ).div( size.y ) ) ), b1, projectionMatrixInverse ) ), ce.negate().add( getViewPosition( uv.sub( vec2( 0, float( 1 ).div( size.y ) ) ), t1, projectionMatrixInverse ) ) );
86
+
87
+ return normalize( cross( dpdx, dpdy ) );
88
+
89
+ } );