super-three 0.154.0 → 0.155.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 (107) hide show
  1. package/build/three.cjs +257 -40
  2. package/build/three.js +257 -40
  3. package/build/three.min.js +1 -2
  4. package/build/three.module.js +256 -41
  5. package/build/three.module.min.js +1 -2
  6. package/examples/jsm/controls/OrbitControls.js +143 -21
  7. package/examples/jsm/environments/RoomEnvironment.js +1 -1
  8. package/examples/jsm/exporters/USDZExporter.js +1 -0
  9. package/examples/jsm/interactive/SelectionHelper.js +7 -0
  10. package/examples/jsm/loaders/FBXLoader.js +1 -1
  11. package/examples/jsm/loaders/GLTFLoader.js +8 -3
  12. package/examples/jsm/loaders/KTX2Loader.js +4 -4
  13. package/examples/jsm/loaders/LDrawLoader.js +1 -1
  14. package/examples/jsm/loaders/NRRDLoader.js +3 -3
  15. package/examples/jsm/loaders/PLYLoader.js +1 -1
  16. package/examples/jsm/loaders/TGALoader.js +10 -10
  17. package/examples/jsm/loaders/VRMLLoader.js +1 -1
  18. package/examples/jsm/misc/GPUComputationRenderer.js +0 -9
  19. package/examples/jsm/misc/Volume.js +4 -6
  20. package/examples/jsm/nodes/Nodes.js +5 -6
  21. package/examples/jsm/nodes/accessors/BufferAttributeNode.js +1 -1
  22. package/examples/jsm/nodes/accessors/CubeTextureNode.js +2 -0
  23. package/examples/jsm/nodes/accessors/ExtendedMaterialNode.js +14 -1
  24. package/examples/jsm/nodes/accessors/InstanceNode.js +8 -8
  25. package/examples/jsm/nodes/accessors/MaterialNode.js +34 -44
  26. package/examples/jsm/nodes/accessors/SceneNode.js +6 -0
  27. package/examples/jsm/nodes/accessors/TextureNode.js +48 -7
  28. package/examples/jsm/nodes/core/LightingModel.js +7 -9
  29. package/examples/jsm/nodes/core/Node.js +11 -2
  30. package/examples/jsm/nodes/core/PropertyNode.js +4 -0
  31. package/examples/jsm/nodes/display/BumpMapNode.js +77 -0
  32. package/examples/jsm/nodes/display/NormalMapNode.js +2 -2
  33. package/examples/jsm/nodes/functions/BSDF/BRDF_GGX.js +10 -2
  34. package/examples/jsm/nodes/functions/BSDF/Schlick_to_F0.js +13 -0
  35. package/examples/jsm/nodes/functions/PhongLightingModel.js +53 -14
  36. package/examples/jsm/nodes/functions/PhysicalLightingModel.js +236 -97
  37. package/examples/jsm/nodes/geometry/RangeNode.js +2 -2
  38. package/examples/jsm/nodes/gpgpu/ComputeNode.js +13 -0
  39. package/examples/jsm/nodes/lighting/AONode.js +1 -1
  40. package/examples/jsm/nodes/lighting/AnalyticLightNode.js +58 -20
  41. package/examples/jsm/nodes/lighting/DirectionalLightNode.js +7 -10
  42. package/examples/jsm/nodes/lighting/EnvironmentNode.js +22 -12
  43. package/examples/jsm/nodes/lighting/HemisphereLightNode.js +1 -1
  44. package/examples/jsm/nodes/lighting/LightingContextNode.js +12 -9
  45. package/examples/jsm/nodes/lighting/PointLightNode.js +7 -10
  46. package/examples/jsm/nodes/lighting/SpotLightNode.js +7 -10
  47. package/examples/jsm/nodes/materials/Materials.js +1 -0
  48. package/examples/jsm/nodes/materials/MeshLambertNodeMaterial.js +34 -0
  49. package/examples/jsm/nodes/materials/MeshNormalNodeMaterial.js +2 -0
  50. package/examples/jsm/nodes/materials/MeshPhongNodeMaterial.js +2 -2
  51. package/examples/jsm/nodes/materials/MeshPhysicalNodeMaterial.js +19 -2
  52. package/examples/jsm/nodes/materials/MeshStandardNodeMaterial.js +2 -2
  53. package/examples/jsm/nodes/materials/NodeMaterial.js +50 -24
  54. package/examples/jsm/nodes/materials/SpriteNodeMaterial.js +2 -2
  55. package/examples/jsm/nodes/shadernode/ShaderNode.js +2 -2
  56. package/examples/jsm/objects/Reflector.js +1 -9
  57. package/examples/jsm/objects/Refractor.js +0 -8
  58. package/examples/jsm/offscreen/scene.js +0 -1
  59. package/examples/jsm/postprocessing/MaskPass.js +4 -1
  60. package/examples/jsm/postprocessing/OutputPass.js +33 -14
  61. package/examples/jsm/postprocessing/UnrealBloomPass.js +21 -17
  62. package/examples/jsm/renderers/common/Background.js +22 -20
  63. package/examples/jsm/renderers/common/Binding.js +8 -0
  64. package/examples/jsm/renderers/common/Bindings.js +2 -6
  65. package/examples/jsm/renderers/common/Geometries.js +1 -1
  66. package/examples/jsm/renderers/common/Pipelines.js +94 -45
  67. package/examples/jsm/renderers/common/RenderContext.js +1 -0
  68. package/examples/jsm/renderers/common/RenderContexts.js +16 -5
  69. package/examples/jsm/renderers/common/RenderObject.js +20 -4
  70. package/examples/jsm/renderers/common/RenderObjects.js +10 -7
  71. package/examples/jsm/renderers/common/Renderer.js +70 -39
  72. package/examples/jsm/renderers/common/Textures.js +20 -8
  73. package/examples/jsm/renderers/common/nodes/Nodes.js +15 -4
  74. package/examples/jsm/renderers/webgpu/WebGPUBackend.js +51 -54
  75. package/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js +33 -9
  76. package/examples/jsm/renderers/webgpu/utils/WebGPUAttributeUtils.js +55 -36
  77. package/examples/jsm/renderers/webgpu/utils/WebGPUBindingUtils.js +83 -5
  78. package/examples/jsm/renderers/webgpu/utils/WebGPUConstants.js +24 -22
  79. package/examples/jsm/renderers/webgpu/utils/WebGPUPipelineUtils.js +83 -130
  80. package/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js +35 -8
  81. package/examples/jsm/renderers/webgpu/utils/WebGPUUtils.js +1 -1
  82. package/examples/jsm/shaders/OutputShader.js +19 -2
  83. package/examples/jsm/utils/BufferGeometryUtils.js +13 -4
  84. package/examples/jsm/webxr/OculusHandPointerModel.js +2 -2
  85. package/package.json +2 -2
  86. package/src/Three.js +2 -0
  87. package/src/animation/PropertyBinding.js +1 -1
  88. package/src/cameras/CubeCamera.js +1 -4
  89. package/src/constants.js +1 -1
  90. package/src/core/BufferAttribute.js +20 -0
  91. package/src/core/Object3D.js +1 -1
  92. package/src/core/RenderTarget.js +122 -0
  93. package/src/geometries/CapsuleGeometry.js +1 -1
  94. package/src/loaders/DataTextureLoader.js +21 -2
  95. package/src/renderers/WebGLMultipleRenderTargets.js +0 -2
  96. package/src/renderers/WebGLRenderTarget.js +3 -110
  97. package/src/renderers/WebGLRenderer.js +62 -8
  98. package/src/renderers/shaders/ShaderChunk/iridescence_fragment.glsl.js +1 -2
  99. package/src/renderers/webgl/WebGLGeometries.js +5 -1
  100. package/src/renderers/webgl/WebGLMaterials.js +1 -1
  101. package/src/renderers/webgl/WebGLPrograms.js +14 -2
  102. package/src/renderers/webgl/WebGLTextures.js +97 -12
  103. package/src/renderers/webxr/WebXRManager.js +1 -1
  104. package/src/textures/CompressedCubeTexture.js +19 -0
  105. package/examples/jsm/nodes/functions/BSDF/BRDF_BlinnPhong.js +0 -30
  106. package/examples/jsm/renderers/common/RenderTarget.js +0 -15
  107. package/examples/jsm/renderers/common/nodes/NodeRender.js +0 -302
@@ -4,6 +4,7 @@ import MaterialNode from './MaterialNode.js';
4
4
  import { materialReference } from './MaterialReferenceNode.js';
5
5
  import { normalView } from './NormalNode.js';
6
6
  import { normalMap } from '../display/NormalMapNode.js';
7
+ import { bumpMap } from '../display/BumpMapNode.js';
7
8
  import { addNodeClass } from '../core/Node.js';
8
9
  import { nodeImmutable } from '../shadernode/ShaderNode.js';
9
10
 
@@ -39,7 +40,19 @@ class ExtendedMaterialNode extends MaterialNode {
39
40
 
40
41
  if ( scope === ExtendedMaterialNode.NORMAL ) {
41
42
 
42
- node = material.normalMap ? normalMap( this.getTexture( 'normalMap' ), materialReference( 'normalScale', 'vec2' ) ) : normalView;
43
+ if ( material.normalMap ) {
44
+
45
+ node = normalMap( this.getTexture( 'normalMap' ), materialReference( 'normalScale', 'vec2' ) );
46
+
47
+ } else if ( material.bumpMap ) {
48
+
49
+ node = bumpMap( material.bumpMap, materialReference( 'bumpScale', 'float' ) );
50
+
51
+ } else {
52
+
53
+ node = normalView;
54
+
55
+ }
43
56
 
44
57
  } else if ( scope === ExtendedMaterialNode.CLEARCOAT_NORMAL ) {
45
58
 
@@ -3,7 +3,7 @@ import { instancedBufferAttribute, instancedDynamicBufferAttribute } from './Buf
3
3
  import { normalLocal } from './NormalNode.js';
4
4
  import { positionLocal } from './PositionNode.js';
5
5
  import { nodeProxy, vec3, mat3, mat4 } from '../shadernode/ShaderNode.js';
6
- import { DynamicDrawUsage } from 'three';
6
+ import { DynamicDrawUsage, InstancedInterleavedBuffer } from 'three';
7
7
 
8
8
  class InstanceNode extends Node {
9
9
 
@@ -24,17 +24,17 @@ class InstanceNode extends Node {
24
24
  if ( instanceMatrixNode === null ) {
25
25
 
26
26
  const instanceMesh = this.instanceMesh;
27
- const instaceAttribute = instanceMesh.instanceMatrix;
28
- const array = instaceAttribute.array;
27
+ const instanceAttribute = instanceMesh.instanceMatrix;
28
+ const buffer = new InstancedInterleavedBuffer( instanceAttribute.array, 16, 1 );
29
29
 
30
- const bufferFn = instaceAttribute.usage === DynamicDrawUsage ? instancedDynamicBufferAttribute : instancedBufferAttribute;
30
+ const bufferFn = instanceAttribute.usage === DynamicDrawUsage ? instancedDynamicBufferAttribute : instancedBufferAttribute;
31
31
 
32
32
  const instanceBuffers = [
33
33
  // F.Signature -> bufferAttribute( array, type, stride, offset )
34
- bufferFn( array, 'vec4', 16, 0 ),
35
- bufferFn( array, 'vec4', 16, 4 ),
36
- bufferFn( array, 'vec4', 16, 8 ),
37
- bufferFn( array, 'vec4', 16, 12 )
34
+ bufferFn( buffer, 'vec4', 16, 0 ),
35
+ bufferFn( buffer, 'vec4', 16, 4 ),
36
+ bufferFn( buffer, 'vec4', 16, 8 ),
37
+ bufferFn( buffer, 'vec4', 16, 12 )
38
38
  ];
39
39
 
40
40
  instanceMatrixNode = mat4( ...instanceBuffers );
@@ -1,6 +1,7 @@
1
1
  import Node, { addNodeClass } from '../core/Node.js';
2
+ import { reference } from './ReferenceNode.js';
2
3
  import { materialReference } from './MaterialReferenceNode.js';
3
- import { nodeImmutable } from '../shadernode/ShaderNode.js';
4
+ import { nodeImmutable, float } from '../shadernode/ShaderNode.js';
4
5
 
5
6
  class MaterialNode extends Node {
6
7
 
@@ -12,31 +13,6 @@ class MaterialNode extends Node {
12
13
 
13
14
  }
14
15
 
15
- getNodeType( builder ) {
16
-
17
- const scope = this.scope;
18
- const material = builder.context.material;
19
-
20
- if ( scope === MaterialNode.COLOR ) {
21
-
22
- return material.map !== null ? 'vec4' : 'vec3';
23
-
24
- } else if ( scope === MaterialNode.OPACITY || scope === MaterialNode.ROTATION ) {
25
-
26
- return 'float';
27
-
28
- } else if ( scope === MaterialNode.EMISSIVE || scope === MaterialNode.SHEEN ) {
29
-
30
- return 'vec3';
31
-
32
- } else if ( scope === MaterialNode.ROUGHNESS || scope === MaterialNode.METALNESS || scope === MaterialNode.SPECULAR || scope === MaterialNode.SHININESS || scope === MaterialNode.CLEARCOAT_ROUGHNESS || scope === MaterialNode.SHEEN_ROUGHNESS ) {
33
-
34
- return 'float';
35
-
36
- }
37
-
38
- }
39
-
40
16
  getFloat( property ) {
41
17
 
42
18
  //@TODO: Check if it can be cached by property name.
@@ -70,9 +46,13 @@ class MaterialNode extends Node {
70
46
 
71
47
  let node = null;
72
48
 
73
- if ( scope === MaterialNode.ALPHA_TEST ) {
49
+ if ( scope === MaterialNode.ALPHA_TEST || scope === MaterialNode.SHININESS || scope === MaterialNode.REFLECTIVITY || scope === MaterialNode.ROTATION || scope === MaterialNode.IRIDESCENCE || scope === MaterialNode.IRIDESCENCE_IOR ) {
74
50
 
75
- node = this.getFloat( 'alphaTest' );
51
+ node = this.getFloat( scope );
52
+
53
+ } else if ( scope === MaterialNode.SPECULAR_COLOR ) {
54
+
55
+ node = this.getColor( 'specular' );
76
56
 
77
57
  } else if ( scope === MaterialNode.COLOR ) {
78
58
 
@@ -102,25 +82,15 @@ class MaterialNode extends Node {
102
82
 
103
83
  }
104
84
 
105
- } else if ( scope === MaterialNode.SHININESS ) {
106
-
107
- node = this.getFloat( 'shininess' );
108
-
109
- } else if ( scope === MaterialNode.SPECULAR_COLOR ) {
110
-
111
- node = this.getColor( 'specular' );
112
-
113
- } else if ( scope === MaterialNode.REFLECTIVITY ) {
114
-
115
- const reflectivityNode = this.getFloat( 'reflectivity' );
85
+ } else if ( scope === MaterialNode.SPECULAR_STRENGTH ) {
116
86
 
117
87
  if ( material.specularMap && material.specularMap.isTexture === true ) {
118
88
 
119
- node = reflectivityNode.mul( this.getTexture( 'specularMap' ).r );
89
+ node = this.getTexture( 'specularMap' ).r;
120
90
 
121
91
  } else {
122
92
 
123
- node = reflectivityNode;
93
+ node = float( 1 );
124
94
 
125
95
  }
126
96
 
@@ -224,9 +194,21 @@ class MaterialNode extends Node {
224
194
 
225
195
  node = node.clamp( 0.07, 1.0 );
226
196
 
227
- } else if ( scope === MaterialNode.ROTATION ) {
197
+ } else if ( scope === MaterialNode.IRIDESCENCE_THICKNESS ) {
228
198
 
229
- node = this.getFloat( 'rotation' );
199
+ const iridescenceThicknessMaximum = reference( 1, 'float', material.iridescenceThicknessRange );
200
+
201
+ if ( material.iridescenceThicknessMap ) {
202
+
203
+ const iridescenceThicknessMinimum = reference( 0, 'float', material.iridescenceThicknessRange );
204
+
205
+ node = iridescenceThicknessMaximum.sub( iridescenceThicknessMinimum ).mul( this.getTexture( 'iridescenceThicknessMap' ).g ).add( iridescenceThicknessMinimum );
206
+
207
+ } else {
208
+
209
+ node = iridescenceThicknessMaximum;
210
+
211
+ }
230
212
 
231
213
  } else {
232
214
 
@@ -246,7 +228,8 @@ MaterialNode.ALPHA_TEST = 'alphaTest';
246
228
  MaterialNode.COLOR = 'color';
247
229
  MaterialNode.OPACITY = 'opacity';
248
230
  MaterialNode.SHININESS = 'shininess';
249
- MaterialNode.SPECULAR_COLOR = 'specularColor';
231
+ MaterialNode.SPECULAR = 'specular';
232
+ MaterialNode.SPECULAR_STRENGTH = 'specularStrength';
250
233
  MaterialNode.REFLECTIVITY = 'reflectivity';
251
234
  MaterialNode.ROUGHNESS = 'roughness';
252
235
  MaterialNode.METALNESS = 'metalness';
@@ -256,6 +239,9 @@ MaterialNode.EMISSIVE = 'emissive';
256
239
  MaterialNode.ROTATION = 'rotation';
257
240
  MaterialNode.SHEEN = 'sheen';
258
241
  MaterialNode.SHEEN_ROUGHNESS = 'sheenRoughness';
242
+ MaterialNode.IRIDESCENCE = 'iridescence';
243
+ MaterialNode.IRIDESCENCE_IOR = 'iridescenceIOR';
244
+ MaterialNode.IRIDESCENCE_THICKNESS = 'iridescenceThickness';
259
245
 
260
246
  export default MaterialNode;
261
247
 
@@ -265,6 +251,7 @@ export const materialShininess = nodeImmutable( MaterialNode, MaterialNode.SHINI
265
251
  export const materialEmissive = nodeImmutable( MaterialNode, MaterialNode.EMISSIVE );
266
252
  export const materialOpacity = nodeImmutable( MaterialNode, MaterialNode.OPACITY );
267
253
  export const materialSpecularColor = nodeImmutable( MaterialNode, MaterialNode.SPECULAR_COLOR );
254
+ export const materialSpecularStrength = nodeImmutable( MaterialNode, MaterialNode.SPECULAR_STRENGTH );
268
255
  export const materialReflectivity = nodeImmutable( MaterialNode, MaterialNode.REFLECTIVITY );
269
256
  export const materialRoughness = nodeImmutable( MaterialNode, MaterialNode.ROUGHNESS );
270
257
  export const materialMetalness = nodeImmutable( MaterialNode, MaterialNode.METALNESS );
@@ -273,5 +260,8 @@ export const materialClearcoatRoughness = nodeImmutable( MaterialNode, MaterialN
273
260
  export const materialRotation = nodeImmutable( MaterialNode, MaterialNode.ROTATION );
274
261
  export const materialSheen = nodeImmutable( MaterialNode, MaterialNode.SHEEN );
275
262
  export const materialSheenRoughness = nodeImmutable( MaterialNode, MaterialNode.SHEEN_ROUGHNESS );
263
+ export const materialIridescence = nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE );
264
+ export const materialIridescenceIOR = nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE_IOR );
265
+ export const materialIridescenceThickness = nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE_THICKNESS );
276
266
 
277
267
  addNodeClass( MaterialNode );
@@ -25,6 +25,10 @@ class SceneNode extends Node {
25
25
 
26
26
  output = reference( 'backgroundBlurriness', 'float', scene );
27
27
 
28
+ } else if ( scope === SceneNode.BACKGROUND_INTENSITY ) {
29
+
30
+ output = reference( 'backgroundIntensity', 'float', scene );
31
+
28
32
  } else {
29
33
 
30
34
  console.error( 'THREE.SceneNode: Unknown scope:', scope );
@@ -38,9 +42,11 @@ class SceneNode extends Node {
38
42
  }
39
43
 
40
44
  SceneNode.BACKGROUND_BLURRINESS = 'backgroundBlurriness';
45
+ SceneNode.BACKGROUND_INTENSITY = 'backgroundIntensity';
41
46
 
42
47
  export default SceneNode;
43
48
 
44
49
  export const backgroundBlurriness = nodeImmutable( SceneNode, SceneNode.BACKGROUND_BLURRINESS );
50
+ export const backgroundIntensity = nodeImmutable( SceneNode, SceneNode.BACKGROUND_INTENSITY );
45
51
 
46
52
  addNodeClass( SceneNode );
@@ -5,12 +5,12 @@ import { colorSpaceToLinear } from '../display/ColorSpaceNode.js';
5
5
  import { context } from '../core/ContextNode.js';
6
6
  import { expression } from '../code/ExpressionNode.js';
7
7
  import { addNodeClass } from '../core/Node.js';
8
- import { addNodeElement, nodeProxy, vec3 } from '../shadernode/ShaderNode.js';
8
+ import { addNodeElement, nodeProxy, vec3, nodeObject } from '../shadernode/ShaderNode.js';
9
9
  import { NodeUpdateType } from '../core/constants.js';
10
10
 
11
11
  class TextureNode extends UniformNode {
12
12
 
13
- constructor( value, uvNode = null, levelNode = null ) {
13
+ constructor( value, uvNode = null, levelNode = null, compareNode = null ) {
14
14
 
15
15
  super( value );
16
16
 
@@ -18,8 +18,12 @@ class TextureNode extends UniformNode {
18
18
 
19
19
  this.uvNode = uvNode;
20
20
  this.levelNode = levelNode;
21
+ this.compareNode = compareNode;
21
22
 
22
- this.updateType = NodeUpdateType.FRAME;
23
+ this.updateMatrix = false;
24
+ this.updateType = NodeUpdateType.NONE;
25
+
26
+ this.setUpdateMatrix( uvNode === null );
23
27
 
24
28
  }
25
29
 
@@ -45,9 +49,24 @@ class TextureNode extends UniformNode {
45
49
 
46
50
  getDefaultUV() {
47
51
 
52
+ return uv( this.value.channel );
53
+
54
+ }
55
+
56
+ getTextureMatrix( uvNode ) {
57
+
48
58
  const texture = this.value;
49
59
 
50
- return uniform( texture.matrix ).mul( vec3( uv( texture.channel ), 1 ) );
60
+ return uniform( texture.matrix ).mul( vec3( uvNode, 1 ) ).xy;
61
+
62
+ }
63
+
64
+ setUpdateMatrix( value ) {
65
+
66
+ this.updateMatrix = value;
67
+ this.updateType = value ? NodeUpdateType.FRAME : NodeUpdateType.NONE;
68
+
69
+ return this;
51
70
 
52
71
  }
53
72
 
@@ -65,7 +84,13 @@ class TextureNode extends UniformNode {
65
84
 
66
85
  }
67
86
 
68
- uvNode || ( uvNode = this.getDefaultUV() );
87
+ if ( ! uvNode ) uvNode = this.getDefaultUV();
88
+
89
+ if ( this.updateMatrix ) {
90
+
91
+ uvNode = this.getTextureMatrix( uvNode );
92
+
93
+ }
69
94
 
70
95
  //
71
96
 
@@ -88,6 +113,7 @@ class TextureNode extends UniformNode {
88
113
 
89
114
  const { uvNode, levelNode } = builder.getNodeProperties( this );
90
115
 
116
+ const compareNode = this.compareNode;
91
117
  const texture = this.value;
92
118
 
93
119
  if ( ! texture || texture.isTexture !== true ) {
@@ -128,6 +154,12 @@ class TextureNode extends UniformNode {
128
154
 
129
155
  snippet = builder.getTextureLevel( texture, textureProperty, uvSnippet, levelSnippet );
130
156
 
157
+ } else if ( compareNode !== null ) {
158
+
159
+ const compareSnippet = compareNode.build( builder, 'float' );
160
+
161
+ snippet = builder.getTextureCompare( texture, textureProperty, uvSnippet, compareSnippet );
162
+
131
163
  } else {
132
164
 
133
165
  snippet = builder.getTexture( texture, textureProperty, uvSnippet );
@@ -160,7 +192,7 @@ class TextureNode extends UniformNode {
160
192
  const textureNode = this.clone();
161
193
  textureNode.uvNode = uvNode;
162
194
 
163
- return textureNode;
195
+ return nodeObject( textureNode );
164
196
 
165
197
  }
166
198
 
@@ -181,6 +213,15 @@ class TextureNode extends UniformNode {
181
213
 
182
214
  }
183
215
 
216
+ compare( compareNode ) {
217
+
218
+ const textureNode = this.clone();
219
+ textureNode.compareNode = nodeObject( compareNode );
220
+
221
+ return nodeObject( textureNode );
222
+
223
+ }
224
+
184
225
  serialize( data ) {
185
226
 
186
227
  super.serialize( data );
@@ -211,7 +252,7 @@ class TextureNode extends UniformNode {
211
252
 
212
253
  clone() {
213
254
 
214
- return new this.constructor( this.value, this.uvNode, this.levelNode );
255
+ return new this.constructor( this.value, this.uvNode, this.levelNode, this.compareNode );
215
256
 
216
257
  }
217
258
 
@@ -1,17 +1,15 @@
1
1
  class LightingModel {
2
2
 
3
- constructor( init = null, direct = null, indirectDiffuse = null, indirectSpecular = null, ambientOcclusion = null ) {
3
+ init( /*input, stack, builder*/ ) { }
4
4
 
5
- this.init = init;
6
- this.direct = direct;
7
- this.indirectDiffuse = indirectDiffuse;
8
- this.indirectSpecular = indirectSpecular;
9
- this.ambientOcclusion = ambientOcclusion;
5
+ direct( /*input, stack, builder*/ ) { }
10
6
 
11
- }
7
+ indirectDiffuse( /*input, stack, builder*/ ) { }
8
+
9
+ indirectSpecular( /*input, stack, builder*/ ) { }
10
+
11
+ ambientOcclusion( /*input, stack, builder*/ ) { }
12
12
 
13
13
  }
14
14
 
15
15
  export default LightingModel;
16
-
17
- export const lightingModel = ( ...params ) => new LightingModel( ...params );
@@ -1,3 +1,4 @@
1
+ import { EventDispatcher } from 'three';
1
2
  import { NodeUpdateType } from './constants.js';
2
3
  import { getNodeChildren, getCacheKey } from './NodeUtils.js';
3
4
  import { MathUtils } from 'three';
@@ -6,11 +7,11 @@ const NodeClasses = new Map();
6
7
 
7
8
  let _nodeId = 0;
8
9
 
9
- class Node {
10
+ class Node extends EventDispatcher {
10
11
 
11
12
  constructor( nodeType = null ) {
12
13
 
13
- this.isNode = true;
14
+ super();
14
15
 
15
16
  this.nodeType = nodeType;
16
17
 
@@ -19,6 +20,8 @@ class Node {
19
20
 
20
21
  this.uuid = MathUtils.generateUUID();
21
22
 
23
+ this.isNode = true;
24
+
22
25
  Object.defineProperty( this, 'id', { value: _nodeId ++ } );
23
26
 
24
27
  }
@@ -52,6 +55,12 @@ class Node {
52
55
 
53
56
  }
54
57
 
58
+ dispose() {
59
+
60
+ this.dispatchEvent( { type: 'dispose' } );
61
+
62
+ }
63
+
55
64
  traverse( callback, replaceNode = null ) {
56
65
 
57
66
  callback( this, replaceNode );
@@ -51,7 +51,11 @@ export const clearcoat = nodeImmutable( PropertyNode, 'float', 'Clearcoat' );
51
51
  export const clearcoatRoughness = nodeImmutable( PropertyNode, 'float', 'ClearcoatRoughness' );
52
52
  export const sheen = nodeImmutable( PropertyNode, 'vec3', 'Sheen' );
53
53
  export const sheenRoughness = nodeImmutable( PropertyNode, 'float', 'SheenRoughness' );
54
+ export const iridescence = nodeImmutable( PropertyNode, 'float', 'Iridescence' );
55
+ export const iridescenceIOR = nodeImmutable( PropertyNode, 'float', 'IridescenceIOR' );
56
+ export const iridescenceThickness = nodeImmutable( PropertyNode, 'float', 'IridescenceThickness' );
54
57
  export const specularColor = nodeImmutable( PropertyNode, 'color', 'SpecularColor' );
55
58
  export const shininess = nodeImmutable( PropertyNode, 'float', 'Shininess' );
59
+ export const output = nodeImmutable( PropertyNode, 'vec4', 'Output' );
56
60
 
57
61
  addNodeClass( PropertyNode );
@@ -0,0 +1,77 @@
1
+ import TempNode from '../core/TempNode.js';
2
+ import { texture } from '../accessors/TextureNode.js';
3
+ import { addNodeClass } from '../core/Node.js';
4
+ import { uv } from '../accessors/UVNode.js';
5
+ import { normalView } from '../accessors/NormalNode.js';
6
+ import { positionView } from '../accessors/PositionNode.js';
7
+ import { faceDirection } from './FrontFacingNode.js';
8
+ import { tslFn, nodeProxy, vec2 } from '../shadernode/ShaderNode.js';
9
+
10
+ // Bump Mapping Unparametrized Surfaces on the GPU by Morten S. Mikkelsen
11
+ // https://mmikk.github.io/papers3d/mm_sfgrad_bump.pdf
12
+
13
+ // Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)
14
+
15
+ const dHdxy_fwd = tslFn( ( { bumpTexture, bumpScale } ) => {
16
+
17
+ const uvNode = uv();
18
+
19
+ const Hll = texture( bumpTexture, uvNode ).x;
20
+
21
+ return vec2(
22
+ texture( bumpTexture, uvNode.add( uvNode.dFdx() ) ).x.sub( Hll ),
23
+ texture( bumpTexture, uvNode.add( uvNode.dFdy() ) ).x.sub( Hll )
24
+ ).mul( bumpScale );
25
+
26
+ } );
27
+
28
+ const perturbNormalArb = tslFn( ( inputs ) => {
29
+
30
+ const { surf_pos, surf_norm, dHdxy } = inputs;
31
+
32
+ const vSigmaX = surf_pos.dFdx();
33
+ const vSigmaY = surf_pos.dFdy();
34
+ const vN = surf_norm; // normalized
35
+
36
+ const R1 = vSigmaY.cross( vN );
37
+ const R2 = vN.cross( vSigmaX );
38
+
39
+ const fDet = vSigmaX.dot( R1 ).mul( faceDirection );
40
+
41
+ const vGrad = fDet.sign().mul( dHdxy.x.mul( R1 ).add( dHdxy.y.mul( R2 ) ) );
42
+
43
+ return fDet.abs().mul( surf_norm ).sub( vGrad ).normalize();
44
+
45
+ } );
46
+
47
+ class BumpMapNode extends TempNode {
48
+
49
+ constructor( texture, scaleNode = null ) {
50
+
51
+ super( 'vec3' );
52
+
53
+ this.texture = texture;
54
+ this.scaleNode = scaleNode;
55
+
56
+ }
57
+
58
+ construct() {
59
+
60
+ const bumpScale = this.scaleNode !== null ? this.scaleNode : 1;
61
+ const dHdxy = dHdxy_fwd( { bumpTexture: this.texture, bumpScale } );
62
+
63
+ return perturbNormalArb( {
64
+ surf_pos: positionView.negate(),
65
+ surf_norm: normalView,
66
+ dHdxy
67
+ } );
68
+
69
+ }
70
+
71
+ }
72
+
73
+ export default BumpMapNode;
74
+
75
+ export const bumpMap = nodeProxy( BumpMapNode );
76
+
77
+ addNodeClass( BumpMapNode );
@@ -15,7 +15,7 @@ import { TangentSpaceNormalMap, ObjectSpaceNormalMap } from 'three';
15
15
  // Normal Mapping Without Precomputed Tangents
16
16
  // http://www.thetenthplanet.de/archives/1180
17
17
 
18
- const perturbNormal2ArbNode = tslFn( ( inputs ) => {
18
+ const perturbNormal2Arb = tslFn( ( inputs ) => {
19
19
 
20
20
  const { eye_pos, surf_norm, mapN, uv } = inputs;
21
21
 
@@ -80,7 +80,7 @@ class NormalMapNode extends TempNode {
80
80
 
81
81
  } else {
82
82
 
83
- outputNode = perturbNormal2ArbNode( {
83
+ outputNode = perturbNormal2Arb( {
84
84
  eye_pos: positionView,
85
85
  surf_norm: normalView,
86
86
  mapN: normalMap,
@@ -3,12 +3,13 @@ import V_GGX_SmithCorrelated from './V_GGX_SmithCorrelated.js';
3
3
  import D_GGX from './D_GGX.js';
4
4
  import { transformedNormalView } from '../../accessors/NormalNode.js';
5
5
  import { positionViewDirection } from '../../accessors/PositionNode.js';
6
+ import { iridescence } from '../../core/PropertyNode.js';
6
7
  import { tslFn } from '../../shadernode/ShaderNode.js';
7
8
 
8
9
  // GGX Distribution, Schlick Fresnel, GGX_SmithCorrelated Visibility
9
10
  const BRDF_GGX = tslFn( ( inputs ) => {
10
11
 
11
- const { lightDirection, f0, f90, roughness } = inputs;
12
+ const { lightDirection, f0, f90, roughness, iridescenceFresnel } = inputs;
12
13
 
13
14
  const normalView = inputs.normalView || transformedNormalView;
14
15
 
@@ -21,7 +22,14 @@ const BRDF_GGX = tslFn( ( inputs ) => {
21
22
  const dotNH = normalView.dot( halfDir ).clamp();
22
23
  const dotVH = positionViewDirection.dot( halfDir ).clamp();
23
24
 
24
- const F = F_Schlick( { f0, f90, dotVH } );
25
+ let F = F_Schlick( { f0, f90, dotVH } );
26
+
27
+ if ( iridescenceFresnel ) {
28
+
29
+ F = iridescence.mix( F, iridescenceFresnel );
30
+
31
+ }
32
+
25
33
  const V = V_GGX_SmithCorrelated( { alpha, dotNL, dotNV } );
26
34
  const D = D_GGX( { alpha, dotNH } );
27
35
 
@@ -0,0 +1,13 @@
1
+ import { tslFn, vec3 } from '../../shadernode/ShaderNode.js';
2
+
3
+ const Schlick_to_F0 = tslFn( ( { f, f90, dotVH } ) => {
4
+
5
+ const x = dotVH.oneMinus().saturate();
6
+ const x2 = x.mul( x );
7
+ const x5 = x.mul( x2, x2 ).clamp( 0, .9999 );
8
+
9
+ return f.sub( vec3( f90 ).mul( x5 ) ).div( x5.oneMinus() );
10
+
11
+ } );
12
+
13
+ export default Schlick_to_F0;
@@ -1,28 +1,67 @@
1
+ import LightingModel from '../core/LightingModel.js';
2
+ import F_Schlick from './BSDF/F_Schlick.js';
1
3
  import BRDF_Lambert from './BSDF/BRDF_Lambert.js';
2
- import BRDF_BlinnPhong from './BSDF/BRDF_BlinnPhong.js';
3
- import { lightingModel } from '../core/LightingModel.js';
4
4
  import { diffuseColor } from '../core/PropertyNode.js';
5
- import { materialReflectivity } from '../accessors/MaterialNode.js';
6
5
  import { transformedNormalView } from '../accessors/NormalNode.js';
7
- import { tslFn } from '../shadernode/ShaderNode.js';
6
+ import { materialSpecularStrength } from '../accessors/MaterialNode.js';
7
+ import { shininess, specularColor } from '../core/PropertyNode.js';
8
+ import { positionViewDirection } from '../accessors/PositionNode.js';
9
+ import { tslFn, float } from '../shadernode/ShaderNode.js';
8
10
 
9
- const RE_Direct_BlinnPhong = tslFn( ( { lightDirection, lightColor, reflectedLight } ) => {
11
+ const G_BlinnPhong_Implicit = () => float( 0.25 );
10
12
 
11
- const dotNL = transformedNormalView.dot( lightDirection ).clamp();
12
- const irradiance = dotNL.mul( lightColor );
13
+ const D_BlinnPhong = tslFn( ( { dotNH } ) => {
13
14
 
14
- reflectedLight.directDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) );
15
-
16
- reflectedLight.directSpecular.addAssign( irradiance.mul( BRDF_BlinnPhong( { lightDirection } ) ).mul( materialReflectivity ) );
15
+ return shininess.mul( 0.5 / Math.PI ).add( 1.0 ).mul( dotNH.pow( shininess ) );
17
16
 
18
17
  } );
19
18
 
20
- const RE_IndirectDiffuse_BlinnPhong = tslFn( ( { irradiance, reflectedLight } ) => {
19
+ const BRDF_BlinnPhong = tslFn( ( { lightDirection } ) => {
20
+
21
+ const halfDir = lightDirection.add( positionViewDirection ).normalize();
22
+
23
+ const dotNH = transformedNormalView.dot( halfDir ).clamp();
24
+ const dotVH = positionViewDirection.dot( halfDir ).clamp();
21
25
 
22
- reflectedLight.indirectDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) );
26
+ const F = F_Schlick( { f0: specularColor, f90: 1.0, dotVH } );
27
+ const G = G_BlinnPhong_Implicit();
28
+ const D = D_BlinnPhong( { dotNH } );
29
+
30
+ return F.mul( G ).mul( D );
23
31
 
24
32
  } );
25
33
 
26
- const phongLightingModel = lightingModel( null, RE_Direct_BlinnPhong, RE_IndirectDiffuse_BlinnPhong );
34
+ class PhongLightingModel extends LightingModel {
35
+
36
+ constructor( specular = true ) {
37
+
38
+ super();
39
+
40
+ this.specular = specular;
41
+
42
+ }
43
+
44
+ direct( { lightDirection, lightColor, reflectedLight } ) {
45
+
46
+ const dotNL = transformedNormalView.dot( lightDirection ).clamp();
47
+ const irradiance = dotNL.mul( lightColor );
48
+
49
+ reflectedLight.directDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) );
50
+
51
+ if ( this.specular === true ) {
52
+
53
+ reflectedLight.directSpecular.addAssign( irradiance.mul( BRDF_BlinnPhong( { lightDirection } ) ).mul( materialSpecularStrength ) );
54
+
55
+ }
56
+
57
+ }
58
+
59
+ indirectDiffuse( { irradiance, reflectedLight } ) {
60
+
61
+ reflectedLight.indirectDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) );
62
+
63
+ }
64
+
65
+ }
27
66
 
28
- export default phongLightingModel;
67
+ export default PhongLightingModel;