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
@@ -23,6 +23,8 @@ class VelocityNode extends TempNode {
23
23
 
24
24
  super( 'vec2' );
25
25
 
26
+ this.projectionMatrix = null;
27
+
26
28
  this.updateType = NodeUpdateType.OBJECT;
27
29
  this.updateAfterType = NodeUpdateType.OBJECT;
28
30
 
@@ -32,6 +34,12 @@ class VelocityNode extends TempNode {
32
34
 
33
35
  }
34
36
 
37
+ setProjectionMatrix( projectionMatrix ) {
38
+
39
+ this.projectionMatrix = projectionMatrix;
40
+
41
+ }
42
+
35
43
  update( { frameId, camera, object } ) {
36
44
 
37
45
  const previousModelMatrix = getPreviousMatrix( object );
@@ -54,7 +62,7 @@ class VelocityNode extends TempNode {
54
62
  cameraData.currentProjectionMatrix = new Matrix4();
55
63
  cameraData.currentCameraViewMatrix = new Matrix4();
56
64
 
57
- cameraData.previousProjectionMatrix.copy( camera.projectionMatrix );
65
+ cameraData.previousProjectionMatrix.copy( this.projectionMatrix || camera.projectionMatrix );
58
66
  cameraData.previousCameraViewMatrix.copy( camera.matrixWorldInverse );
59
67
 
60
68
  } else {
@@ -64,7 +72,7 @@ class VelocityNode extends TempNode {
64
72
 
65
73
  }
66
74
 
67
- cameraData.currentProjectionMatrix.copy( camera.projectionMatrix );
75
+ cameraData.currentProjectionMatrix.copy( this.projectionMatrix || camera.projectionMatrix );
68
76
  cameraData.currentCameraViewMatrix.copy( camera.matrixWorldInverse );
69
77
 
70
78
  this.previousProjectionMatrix.value.copy( cameraData.previousProjectionMatrix );
@@ -82,9 +90,11 @@ class VelocityNode extends TempNode {
82
90
 
83
91
  setup( /*builder*/ ) {
84
92
 
93
+ const projectionMatrix = ( this.projectionMatrix === null ) ? cameraProjectionMatrix : uniform( this.projectionMatrix );
94
+
85
95
  const previousModelViewMatrix = this.previousCameraViewMatrix.mul( this.previousModelWorldMatrix );
86
96
 
87
- const clipPositionCurrent = cameraProjectionMatrix.mul( modelViewMatrix ).mul( positionLocal );
97
+ const clipPositionCurrent = projectionMatrix.mul( modelViewMatrix ).mul( positionLocal );
88
98
  const clipPositionPrevious = this.previousProjectionMatrix.mul( previousModelViewMatrix ).mul( positionPrevious );
89
99
 
90
100
  const ndcPositionCurrent = clipPositionCurrent.xy.div( clipPositionCurrent.w );
@@ -47,14 +47,25 @@ class FunctionCallNode extends TempNode {
47
47
  const inputs = functionNode.getInputs( builder );
48
48
  const parameters = this.parameters;
49
49
 
50
+ const generateInput = ( node, inputNode ) => {
51
+
52
+ const type = inputNode.type;
53
+ const pointer = type === 'pointer';
54
+
55
+ let output;
56
+
57
+ if ( pointer ) output = '&' + node.build( builder );
58
+ else output = node.build( builder, type );
59
+
60
+ return output;
61
+
62
+ };
63
+
50
64
  if ( Array.isArray( parameters ) ) {
51
65
 
52
66
  for ( let i = 0; i < parameters.length; i ++ ) {
53
67
 
54
- const inputNode = inputs[ i ];
55
- const node = parameters[ i ];
56
-
57
- params.push( node.build( builder, inputNode.type ) );
68
+ params.push( generateInput( parameters[ i ], inputs[ i ] ) );
58
69
 
59
70
  }
60
71
 
@@ -66,7 +77,7 @@ class FunctionCallNode extends TempNode {
66
77
 
67
78
  if ( node !== undefined ) {
68
79
 
69
- params.push( node.build( builder, inputNode.type ) );
80
+ params.push( generateInput( node, inputNode ) );
70
81
 
71
82
  } else {
72
83
 
@@ -58,7 +58,7 @@ class Parameters {
58
58
 
59
59
  }
60
60
 
61
- export const global = new Resources();
61
+ export const ScriptableNodeResources = new Resources();
62
62
 
63
63
  class ScriptableNode extends Node {
64
64
 
@@ -299,11 +299,11 @@ class ScriptableNode extends Node {
299
299
 
300
300
  const parameters = new Parameters( this );
301
301
 
302
- const THREE = global.get( 'THREE' );
303
- const TSL = global.get( 'TSL' );
302
+ const THREE = ScriptableNodeResources.get( 'THREE' );
303
+ const TSL = ScriptableNodeResources.get( 'TSL' );
304
304
 
305
305
  const method = this.getMethod( this.codeNode );
306
- const params = [ parameters, this._local, global, refresh, setOutput, THREE, TSL ];
306
+ const params = [ parameters, this._local, ScriptableNodeResources, refresh, setOutput, THREE, TSL ];
307
307
 
308
308
  this._object = method( ...params );
309
309
 
@@ -378,6 +378,7 @@ class Node extends EventDispatcher {
378
378
  }
379
379
 
380
380
  builder.removeChain( this );
381
+ builder.addSequentialNode( this );
381
382
 
382
383
  return result;
383
384
 
@@ -55,9 +55,17 @@ const typeFromArray = new Map( [
55
55
 
56
56
  const toFloat = ( value ) => {
57
57
 
58
- value = Number( value );
58
+ if ( /e/g.test( value ) ) {
59
59
 
60
- return value + ( value % 1 ? '' : '.0' );
60
+ return String( value ).replace( /\+/g, '' );
61
+
62
+ } else {
63
+
64
+ value = Number( value );
65
+
66
+ return value + ( value % 1 ? '' : '.0' );
67
+
68
+ }
61
69
 
62
70
  };
63
71
 
@@ -74,6 +82,7 @@ class NodeBuilder {
74
82
  this.camera = null;
75
83
 
76
84
  this.nodes = [];
85
+ this.sequentialNodes = [];
77
86
  this.updateNodes = [];
78
87
  this.updateBeforeNodes = [];
79
88
  this.updateAfterNodes = [];
@@ -312,13 +321,21 @@ class NodeBuilder {
312
321
 
313
322
  }
314
323
 
324
+ addSequentialNode( node ) {
325
+
326
+ if ( this.sequentialNodes.includes( node ) === false ) {
327
+
328
+ this.sequentialNodes.push( node );
329
+
330
+ }
331
+
332
+ }
333
+
315
334
  buildUpdateNodes() {
316
335
 
317
336
  for ( const node of this.nodes ) {
318
337
 
319
338
  const updateType = node.getUpdateType();
320
- const updateBeforeType = node.getUpdateBeforeType();
321
- const updateAfterType = node.getUpdateAfterType();
322
339
 
323
340
  if ( updateType !== NodeUpdateType.NONE ) {
324
341
 
@@ -326,6 +343,13 @@ class NodeBuilder {
326
343
 
327
344
  }
328
345
 
346
+ }
347
+
348
+ for ( const node of this.sequentialNodes ) {
349
+
350
+ const updateBeforeType = node.getUpdateBeforeType();
351
+ const updateAfterType = node.getUpdateAfterType();
352
+
329
353
  if ( updateBeforeType !== NodeUpdateType.NONE ) {
330
354
 
331
355
  this.updateBeforeNodes.push( node.getSelf() );
@@ -1300,7 +1324,7 @@ class NodeBuilder {
1300
1324
 
1301
1325
  if ( material !== null ) {
1302
1326
 
1303
- let nodeMaterial = renderer.nodes.library.fromMaterial( material );
1327
+ let nodeMaterial = renderer.library.fromMaterial( material );
1304
1328
 
1305
1329
  if ( nodeMaterial === null ) {
1306
1330
 
@@ -54,7 +54,19 @@ class VarNode extends Node {
54
54
 
55
55
  export default VarNode;
56
56
 
57
- export const temp = /*@__PURE__*/ nodeProxy( VarNode );
57
+ const createVar = /*@__PURE__*/ nodeProxy( VarNode );
58
+
59
+ addMethodChaining( 'toVar', ( ...params ) => createVar( ...params ).append() );
60
+
61
+ // Deprecated
62
+
63
+ export const temp = ( node ) => { // @deprecated, r170
64
+
65
+ console.warn( 'TSL: "temp" is deprecated. Use ".toVar()" instead.' );
66
+
67
+ return createVar( node );
68
+
69
+ };
70
+
71
+ addMethodChaining( 'temp', temp );
58
72
 
59
- addMethodChaining( 'temp', temp ); // @TODO: Will be removed in the future
60
- addMethodChaining( 'toVar', ( ...params ) => temp( ...params ).append() );
@@ -1,8 +1,9 @@
1
- import { dot, mix } from '../math/MathNode.js';
1
+ import { dot, max, mix } from '../math/MathNode.js';
2
2
  import { add } from '../math/OperatorNode.js';
3
- import { Fn, float, vec3 } from '../tsl/TSLBase.js';
3
+ import { Fn, If, float, vec3, vec4 } from '../tsl/TSLBase.js';
4
4
  import { ColorManagement } from '../../math/ColorManagement.js';
5
5
  import { Vector3 } from '../../math/Vector3.js';
6
+ import { LinearSRGBColorSpace } from '../../constants.js';
6
7
 
7
8
  export const grayscale = /*@__PURE__*/ Fn( ( [ color ] ) => {
8
9
 
@@ -37,10 +38,58 @@ export const hue = /*@__PURE__*/ Fn( ( [ color, adjustment = float( 1 ) ] ) => {
37
38
 
38
39
  } );
39
40
 
40
- const _luminanceCoefficients = /*@__PURE__*/ new Vector3();
41
41
  export const luminance = (
42
42
  color,
43
- luminanceCoefficients = vec3( ... ColorManagement.getLuminanceCoefficients( _luminanceCoefficients ) )
43
+ luminanceCoefficients = vec3( ColorManagement.getLuminanceCoefficients( new Vector3() ) )
44
44
  ) => dot( color, luminanceCoefficients );
45
45
 
46
46
  export const threshold = ( color, threshold ) => mix( vec3( 0.0 ), color, luminance( color ).sub( threshold ).max( 0 ) );
47
+
48
+ /**
49
+ * Color Decision List (CDL) v1.2
50
+ *
51
+ * Compact representation of color grading information, defined by slope, offset, power, and
52
+ * saturation. The CDL should be typically be given input in a log space (such as LogC, ACEScc,
53
+ * or AgX Log), and will return output in the same space. Output may require clamping >=0.
54
+ *
55
+ * @param {vec4} color Input (-Infinity < input < +Infinity)
56
+ * @param {number | vec3} slope Slope (0 ≤ slope < +Infinity)
57
+ * @param {number | vec3} offset Offset (-Infinity < offset < +Infinity; typically -1 < offset < 1)
58
+ * @param {number | vec3} power Power (0 < power < +Infinity)
59
+ * @param {number} saturation Saturation (0 ≤ saturation < +Infinity; typically 0 ≤ saturation < 4)
60
+ * @param {vec3} luminanceCoefficients Luminance coefficients for saturation term, typically Rec. 709
61
+ * @return Output, -Infinity < output < +Infinity
62
+ *
63
+ * References:
64
+ * - ASC CDL v1.2
65
+ * - https://blender.stackexchange.com/a/55239/43930
66
+ * - https://docs.acescentral.com/specifications/acescc/
67
+ */
68
+ export const cdl = /*@__PURE__*/ Fn( ( [
69
+ color,
70
+ slope = vec3( 1 ),
71
+ offset = vec3( 0 ),
72
+ power = vec3( 1 ),
73
+ saturation = float( 1 ),
74
+ // ASC CDL v1.2 explicitly requires Rec. 709 luminance coefficients.
75
+ luminanceCoefficients = vec3( ColorManagement.getLuminanceCoefficients( new Vector3(), LinearSRGBColorSpace ) )
76
+ ] ) => {
77
+
78
+ // NOTE: The ASC CDL v1.2 defines a [0, 1] clamp on the slope+offset term, and another on the
79
+ // saturation term. Per the ACEScc specification and Filament, limits may be omitted to support
80
+ // values outside [0, 1], requiring a workaround for negative values in the power expression.
81
+
82
+ const luma = color.rgb.dot( vec3( luminanceCoefficients ) );
83
+
84
+ const v = max( color.rgb.mul( slope ).add( offset ), 0.0 ).toVar();
85
+ const pv = v.pow( power ).toVar();
86
+
87
+ If( v.r.greaterThan( 0.0 ), () => { v.r.assign( pv.r ); } ); // eslint-disable-line
88
+ If( v.g.greaterThan( 0.0 ), () => { v.g.assign( pv.g ); } ); // eslint-disable-line
89
+ If( v.b.greaterThan( 0.0 ), () => { v.b.assign( pv.b ); } ); // eslint-disable-line
90
+
91
+ v.assign( luma.add( v.sub( luma ).mul( saturation ) ) );
92
+
93
+ return vec4( v.rgb, color.a );
94
+
95
+ } );
@@ -1,7 +1,7 @@
1
1
  import { mix } from '../math/MathNode.js';
2
- import { Fn } from '../tsl/TSLBase.js';
2
+ import { Fn } from '../tsl/TSLCore.js';
3
3
 
4
- export const sRGBToLinearSRGB = /*@__PURE__*/ Fn( ( [ color ] ) => {
4
+ export const sRGBTransferEOTF = /*@__PURE__*/ Fn( ( [ color ] ) => {
5
5
 
6
6
  const a = color.mul( 0.9478672986 ).add( 0.0521327014 ).pow( 2.4 );
7
7
  const b = color.mul( 0.0773993808 );
@@ -12,14 +12,14 @@ export const sRGBToLinearSRGB = /*@__PURE__*/ Fn( ( [ color ] ) => {
12
12
  return rgbResult;
13
13
 
14
14
  } ).setLayout( {
15
- name: 'sRGBToLinearSRGB',
15
+ name: 'sRGBTransferEOTF',
16
16
  type: 'vec3',
17
17
  inputs: [
18
18
  { name: 'color', type: 'vec3' }
19
19
  ]
20
20
  } );
21
21
 
22
- export const linearSRGBTosRGB = /*@__PURE__*/ Fn( ( [ color ] ) => {
22
+ export const sRGBTransferOETF = /*@__PURE__*/ Fn( ( [ color ] ) => {
23
23
 
24
24
  const a = color.pow( 0.41666 ).mul( 1.055 ).sub( 0.055 );
25
25
  const b = color.mul( 12.92 );
@@ -30,7 +30,7 @@ export const linearSRGBTosRGB = /*@__PURE__*/ Fn( ( [ color ] ) => {
30
30
  return rgbResult;
31
31
 
32
32
  } ).setLayout( {
33
- name: 'linearSRGBTosRGB',
33
+ name: 'sRGBTransferOETF',
34
34
  type: 'vec3',
35
35
  inputs: [
36
36
  { name: 'color', type: 'vec3' }
@@ -1,36 +1,14 @@
1
1
  import TempNode from '../core/TempNode.js';
2
- import { addMethodChaining, nodeObject, vec4 } from '../tsl/TSLCore.js';
2
+ import { addMethodChaining, mat3, nodeObject, vec4 } from '../tsl/TSLCore.js';
3
3
 
4
- import { LinearSRGBColorSpace, SRGBColorSpace } from '../../constants.js';
4
+ import { SRGBTransfer } from '../../constants.js';
5
5
  import { ColorManagement } from '../../math/ColorManagement.js';
6
+ import { sRGBTransferEOTF, sRGBTransferOETF } from './ColorSpaceFunctions.js';
7
+ import { Matrix3 } from '../../math/Matrix3.js';
6
8
 
7
9
  const WORKING_COLOR_SPACE = 'WorkingColorSpace';
8
10
  const OUTPUT_COLOR_SPACE = 'OutputColorSpace';
9
11
 
10
- function getColorSpaceName( colorSpace ) {
11
-
12
- let method = null;
13
-
14
- if ( colorSpace === LinearSRGBColorSpace ) {
15
-
16
- method = 'Linear';
17
-
18
- } else if ( colorSpace === SRGBColorSpace ) {
19
-
20
- method = 'sRGB';
21
-
22
- }
23
-
24
- return method;
25
-
26
- }
27
-
28
- export function getColorSpaceMethod( source, target ) {
29
-
30
- return getColorSpaceName( source ) + 'To' + getColorSpaceName( target );
31
-
32
- }
33
-
34
12
  class ColorSpaceNode extends TempNode {
35
13
 
36
14
  static get type() {
@@ -49,7 +27,7 @@ class ColorSpaceNode extends TempNode {
49
27
 
50
28
  }
51
29
 
52
- getColorSpace( builder, colorSpace ) {
30
+ resolveColorSpace( builder, colorSpace ) {
53
31
 
54
32
  if ( colorSpace === WORKING_COLOR_SPACE ) {
55
33
 
@@ -67,29 +45,37 @@ class ColorSpaceNode extends TempNode {
67
45
 
68
46
  setup( builder ) {
69
47
 
70
- const { renderer } = builder;
71
48
  const { colorNode } = this;
72
49
 
73
- const source = this.getColorSpace( builder, this.source );
74
- const target = this.getColorSpace( builder, this.target );
50
+ const source = this.resolveColorSpace( builder, this.source );
51
+ const target = this.resolveColorSpace( builder, this.target );
75
52
 
76
- if ( source === target ) return colorNode;
53
+ let outputNode = colorNode;
77
54
 
78
- const colorSpace = getColorSpaceMethod( source, target );
55
+ if ( ColorManagement.enabled === false || source === target || ! source || ! target ) {
79
56
 
80
- let outputNode = null;
57
+ return outputNode;
81
58
 
82
- const colorSpaceFn = renderer.nodes.library.getColorSpaceFunction( colorSpace );
59
+ }
83
60
 
84
- if ( colorSpaceFn !== null ) {
61
+ if ( ColorManagement.getTransfer( source ) === SRGBTransfer ) {
85
62
 
86
- outputNode = vec4( colorSpaceFn( colorNode.rgb ), colorNode.a );
63
+ outputNode = vec4( sRGBTransferEOTF( outputNode.rgb ), outputNode.a );
87
64
 
88
- } else {
65
+ }
89
66
 
90
- console.error( 'ColorSpaceNode: Unsupported Color Space configuration.', colorSpace );
67
+ if ( ColorManagement.getPrimaries( source ) !== ColorManagement.getPrimaries( target ) ) {
91
68
 
92
- outputNode = colorNode;
69
+ outputNode = vec4(
70
+ mat3( ColorManagement._getMatrix( new Matrix3(), source, target ) ).mul( outputNode.rgb ),
71
+ outputNode.a
72
+ );
73
+
74
+ }
75
+
76
+ if ( ColorManagement.getTransfer( target ) === SRGBTransfer ) {
77
+
78
+ outputNode = vec4( sRGBTransferOETF( outputNode.rgb ), outputNode.a );
93
79
 
94
80
  }
95
81
 
@@ -107,6 +93,8 @@ export const toWorkingColorSpace = ( node ) => nodeObject( new ColorSpaceNode( n
107
93
  export const workingToColorSpace = ( node, colorSpace ) => nodeObject( new ColorSpaceNode( nodeObject( node ), WORKING_COLOR_SPACE, colorSpace ) );
108
94
  export const colorSpaceToWorking = ( node, colorSpace ) => nodeObject( new ColorSpaceNode( nodeObject( node ), colorSpace, WORKING_COLOR_SPACE ) );
109
95
 
96
+ export const convertColorSpace = ( node, sourceColorSpace, targetColorSpace ) => nodeObject( new ColorSpaceNode( nodeObject( node ), sourceColorSpace, targetColorSpace ) );
97
+
110
98
  addMethodChaining( 'toOutputColorSpace', toOutputColorSpace );
111
99
  addMethodChaining( 'toWorkingColorSpace', toWorkingColorSpace );
112
100
 
@@ -226,8 +226,9 @@ class PassNode extends TempNode {
226
226
 
227
227
  if ( textureNode === undefined ) {
228
228
 
229
- this._textureNodes[ name ] = textureNode = nodeObject( new PassMultipleTextureNode( this, name ) );
230
- this._textureNodes[ name ].updateTexture();
229
+ textureNode = nodeObject( new PassMultipleTextureNode( this, name ) );
230
+ textureNode.updateTexture();
231
+ this._textureNodes[ name ] = textureNode;
231
232
 
232
233
  }
233
234
 
@@ -243,8 +244,9 @@ class PassNode extends TempNode {
243
244
 
244
245
  if ( this._textureNodes[ name ] === undefined ) this.getTextureNode( name );
245
246
 
246
- this._previousTextureNodes[ name ] = textureNode = nodeObject( new PassMultipleTextureNode( this, name, true ) );
247
- this._previousTextureNodes[ name ].updateTexture();
247
+ textureNode = nodeObject( new PassMultipleTextureNode( this, name, true ) );
248
+ textureNode.updateTexture();
249
+ this._previousTextureNodes[ name ] = textureNode;
248
250
 
249
251
  }
250
252
 
@@ -39,7 +39,7 @@ class ToneMappingNode extends TempNode {
39
39
 
40
40
  let outputNode = null;
41
41
 
42
- const toneMappingFn = builder.renderer.nodes.library.getToneMappingFunction( toneMapping );
42
+ const toneMappingFn = builder.renderer.library.getToneMappingFunction( toneMapping );
43
43
 
44
44
  if ( toneMappingFn !== null ) {
45
45
 
@@ -1,5 +1,5 @@
1
1
  import Node from '../core/Node.js';
2
- import { nodeImmutable, nodeProxy } from '../tsl/TSLBase.js';
2
+ import { log2, nodeImmutable, nodeProxy } from '../tsl/TSLBase.js';
3
3
  import { cameraNear, cameraFar } from '../accessors/Camera.js';
4
4
  import { positionView } from '../accessors/Position.js';
5
5
  import { viewportDepthTexture } from './ViewportDepthTextureNode.js';
@@ -116,6 +116,38 @@ export const viewZToPerspectiveDepth = ( viewZ, near, far ) => near.add( viewZ )
116
116
  // maps perspective depth in [ 0, 1 ] to viewZ
117
117
  export const perspectiveDepthToViewZ = ( depth, near, far ) => near.mul( far ).div( far.sub( near ).mul( depth ).sub( far ) );
118
118
 
119
+ export const perspectiveDepthToLogarithmicDepth = ( perspectiveW, near, far ) => {
120
+
121
+ // The final logarithmic depth formula used here is adapted from one described in an
122
+ // article by Thatcher Ulrich (see http://tulrich.com/geekstuff/log_depth_buffer.txt),
123
+ // which was an improvement upon an earlier formula one described in an
124
+ // Outerra article (https://outerra.blogspot.com/2009/08/logarithmic-z-buffer.html).
125
+ // Ulrich's formula is the following:
126
+ // z = K * log( w / cameraNear ) / log( cameraFar / cameraNear )
127
+ // where K = 2^k - 1, and k is the number of bits in the depth buffer.
128
+ // The Outerra variant ignored the camera near plane (it assumed it was 0) and instead
129
+ // opted for a "C-constant" for resolution adjustment of objects near the camera.
130
+ // Outerra states: "Notice that the 'C' variant doesn’t use a near plane distance, it has it
131
+ // set at 0" (quote from https://outerra.blogspot.com/2012/11/maximizing-depth-buffer-range-and.html).
132
+ // Ulrich's variant has the benefit of constant relative precision over the whole near-far range.
133
+ // It was debated here whether Outerra's "C-constant" or Ulrich's "near plane" variant should
134
+ // be used, and ultimately Ulrich's "near plane" version was chosen.
135
+ // Outerra eventually made another improvement to their original "C-constant" variant,
136
+ // but it still does not incorporate the camera near plane (for this version,
137
+ // see https://outerra.blogspot.com/2013/07/logarithmic-depth-buffer-optimizations.html).
138
+ // Here we make 4 changes to Ulrich's formula:
139
+ // 1. Clamp the camera near plane so we don't divide by 0.
140
+ // 2. Use log2 instead of log to avoid an extra multiply (shaders implement log using log2).
141
+ // 3. Assume K is 1 (K = maximum value in depth buffer; see Ulrich's formula above).
142
+ // 4. Add 1 to each division by cameraNear to ensure the depth curve is shifted to the left as cameraNear increases.
143
+ // For visual representation of this depth curve, see https://www.desmos.com/calculator/lz5rqfysih
144
+ near = near.max( 1e-6 ).toVar();
145
+ const numerator = log2( perspectiveW.div( near ).add( 1 ) );
146
+ const denominator = log2( far.div( near ).add( 1 ) );
147
+ return numerator.div( denominator );
148
+
149
+ };
150
+
119
151
  const depthBase = /*@__PURE__*/ nodeProxy( ViewportDepthNode, ViewportDepthNode.DEPTH_BASE );
120
152
 
121
153
  export const depth = /*@__PURE__*/ nodeImmutable( ViewportDepthNode, ViewportDepthNode.DEPTH );
@@ -20,6 +20,7 @@ import { screenSize } from '../display/ScreenNode.js';
20
20
  import { viewportMipTexture } from '../display/ViewportTextureNode.js';
21
21
  import { textureBicubic } from '../accessors/TextureBicubic.js';
22
22
  import { Loop } from '../utils/LoopNode.js';
23
+ import { BackSide } from '../../constants.js';
23
24
 
24
25
  //
25
26
  // Transmission
@@ -67,14 +68,17 @@ const applyIorToRoughness = /*@__PURE__*/ Fn( ( [ roughness, ior ] ) => {
67
68
  ]
68
69
  } );
69
70
 
70
- const singleViewportMipTexture = /*@__PURE__*/ viewportMipTexture();
71
+ const viewportBackSideTexture = /*@__PURE__*/ viewportMipTexture();
72
+ const viewportFrontSideTexture = /*@__PURE__*/ viewportMipTexture();
71
73
 
72
- const getTransmissionSample = /*@__PURE__*/ Fn( ( [ fragCoord, roughness, ior ] ) => {
74
+ const getTransmissionSample = /*@__PURE__*/ Fn( ( [ fragCoord, roughness, ior ], { material } ) => {
73
75
 
74
- const transmissionSample = singleViewportMipTexture.uv( fragCoord );
76
+ const vTexture = material.side == BackSide ? viewportBackSideTexture : viewportFrontSideTexture;
77
+
78
+ const transmissionSample = vTexture.uv( fragCoord );
75
79
  //const transmissionSample = viewportMipTexture( fragCoord );
76
80
 
77
- const lod = log2( float( screenSize.x ) ).mul( applyIorToRoughness( roughness, ior ) );
81
+ const lod = log2( screenSize.x ).mul( applyIorToRoughness( roughness, ior ) );
78
82
 
79
83
  return textureBicubic( transmissionSample, lod );
80
84
 
@@ -233,15 +237,16 @@ const evalIridescence = /*@__PURE__*/ Fn( ( { outsideIOR, eta2, cosTheta1, thinF
233
237
  // Force iridescenceIOR -> outsideIOR when thinFilmThickness -> 0.0
234
238
  const iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );
235
239
  // Evaluate the cosTheta on the base layer (Snell law)
236
- const sinTheta2Sq = outsideIOR.div( iridescenceIOR ).pow2().mul( float( 1 ).sub( cosTheta1.pow2() ) );
240
+ const sinTheta2Sq = outsideIOR.div( iridescenceIOR ).pow2().mul( cosTheta1.pow2().oneMinus() );
237
241
 
238
242
  // Handle TIR:
239
- const cosTheta2Sq = float( 1 ).sub( sinTheta2Sq );
240
- /*if ( cosTheta2Sq < 0.0 ) {
243
+ const cosTheta2Sq = sinTheta2Sq.oneMinus();
244
+
245
+ If( cosTheta2Sq.lessThan( 0 ), () => {
241
246
 
242
- return vec3( 1.0 );
247
+ return vec3( 1.0 );
243
248
 
244
- }*/
249
+ } );
245
250
 
246
251
  const cosTheta2 = cosTheta2Sq.sqrt();
247
252
 
@@ -274,17 +279,18 @@ const evalIridescence = /*@__PURE__*/ Fn( ( { outsideIOR, eta2, cosTheta1, thinF
274
279
 
275
280
  // Reflectance term for m = 0 (DC term amplitude)
276
281
  const C0 = R12.add( Rs );
277
- let I = C0;
282
+ const I = C0.toVar();
278
283
 
279
284
  // Reflectance term for m > 0 (pairs of diracs)
280
- let Cm = Rs.sub( T121 );
281
- for ( let m = 1; m <= 2; ++ m ) {
285
+ const Cm = Rs.sub( T121 ).toVar();
282
286
 
283
- Cm = Cm.mul( r123 );
287
+ Loop( { start: 1, end: 2, condition: '<=', name: 'm' }, ( { m } ) => {
288
+
289
+ Cm.mulAssign( r123 );
284
290
  const Sm = evalSensitivity( float( m ).mul( OPD ), float( m ).mul( phi ) ).mul( 2.0 );
285
- I = I.add( Cm.mul( Sm ) );
291
+ I.addAssign( Cm.mul( Sm ) );
286
292
 
287
- }
293
+ } );
288
294
 
289
295
  // Since out of gamut colors might be produced, negative color values are clamped to 0.
290
296
  return I.max( vec3( 0.0 ) );
@@ -0,0 +1,64 @@
1
+ import { abs, add, ceil, clamp, dFdx, dFdy, exp2, float, floor, Fn, fract, length, log2, max, min, mul, sin, sub, vec2, vec3 } from '../../tsl/TSLBase.js';
2
+
3
+ /**
4
+ * See: https://casual-effects.com/research/Wyman2017Hashed/index.html
5
+ */
6
+
7
+ const ALPHA_HASH_SCALE = 0.05; // Derived from trials only, and may be changed.
8
+
9
+ const hash2D = /*@__PURE__*/ Fn( ( [ value ] ) => {
10
+
11
+ return fract( mul( 1.0e4, sin( mul( 17.0, value.x ).add( mul( 0.1, value.y ) ) ) ).mul( add( 0.1, abs( sin( mul( 13.0, value.y ).add( value.x ) ) ) ) ) );
12
+
13
+ } );
14
+
15
+ const hash3D = /*@__PURE__*/ Fn( ( [ value ] ) => {
16
+
17
+ return hash2D( vec2( hash2D( value.xy ), value.z ) );
18
+
19
+ } );
20
+
21
+ const getAlphaHashThreshold = /*@__PURE__*/ Fn( ( [ position ] ) => {
22
+
23
+ // Find the discretized derivatives of our coordinates
24
+ const maxDeriv = max(
25
+ length( dFdx( position.xyz ) ),
26
+ length( dFdy( position.xyz ) )
27
+ ).toVar( 'maxDeriv' );
28
+
29
+ const pixScale = float( 1 ).div( float( ALPHA_HASH_SCALE ).mul( maxDeriv ) ).toVar( 'pixScale' );
30
+
31
+ // Find two nearest log-discretized noise scales
32
+ const pixScales = vec2(
33
+ exp2( floor( log2( pixScale ) ) ),
34
+ exp2( ceil( log2( pixScale ) ) )
35
+ ).toVar( 'pixScales' );
36
+
37
+ // Compute alpha thresholds at our two noise scales
38
+ const alpha = vec2(
39
+ hash3D( floor( pixScales.x.mul( position.xyz ) ) ),
40
+ hash3D( floor( pixScales.y.mul( position.xyz ) ) ),
41
+ ).toVar( 'alpha' );
42
+
43
+ // Factor to interpolate lerp with
44
+ const lerpFactor = fract( log2( pixScale ) ).toVar( 'lerpFactor' );
45
+
46
+ // Interpolate alpha threshold from noise at two scales
47
+ const x = add( mul( lerpFactor.oneMinus(), alpha.x ), mul( lerpFactor, alpha.y ) ).toVar( 'x' );
48
+
49
+ // Pass into CDF to compute uniformly distrib threshold
50
+ const a = min( lerpFactor, lerpFactor.oneMinus() ).toVar( 'a' );
51
+ const cases = vec3(
52
+ x.mul( x ).div( mul( 2.0, a ).mul( sub( 1.0, a ) ) ),
53
+ x.sub( mul( 0.5, a ) ).div( sub( 1.0, a ) ),
54
+ sub( 1.0, sub( 1.0, x ).mul( sub( 1.0, x ) ).div( mul( 2.0, a ).mul( sub( 1.0, a ) ) ) ) ).toVar( 'cases' );
55
+
56
+ // Find our final, uniformly distributed alpha threshold (ατ)
57
+ const threshold = x.lessThan( a.oneMinus() ).select( x.lessThan( a ).select( cases.x, cases.y ), cases.z );
58
+
59
+ // Avoids ατ == 0. Could also do ατ =1-ατ
60
+ return clamp( threshold, 1.0e-6, 1.0 );
61
+
62
+ } );
63
+
64
+ export default getAlphaHashThreshold;