super-three 0.164.0 → 0.165.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 (124) hide show
  1. package/README.md +3 -3
  2. package/build/three.cjs +664 -217
  3. package/build/three.module.js +664 -217
  4. package/build/three.module.min.js +1 -1
  5. package/examples/jsm/controls/TransformControls.js +1 -1
  6. package/examples/jsm/environments/RoomEnvironment.js +1 -5
  7. package/examples/jsm/exporters/GLTFExporter.js +1 -1
  8. package/examples/jsm/exporters/USDZExporter.js +6 -4
  9. package/examples/jsm/helpers/ViewHelper.js +32 -67
  10. package/examples/jsm/libs/tween.module.js +75 -64
  11. package/examples/jsm/lines/LineMaterial.js +1 -15
  12. package/examples/jsm/lines/LineSegments2.js +15 -0
  13. package/examples/jsm/lines/Wireframe.js +16 -1
  14. package/examples/jsm/loaders/DRACOLoader.js +1 -1
  15. package/examples/jsm/loaders/FBXLoader.js +24 -13
  16. package/examples/jsm/loaders/GLTFLoader.js +2 -0
  17. package/examples/jsm/loaders/LDrawLoader.js +3 -2
  18. package/examples/jsm/loaders/MMDLoader.js +31 -12
  19. package/examples/jsm/modifiers/CurveModifier.js +11 -9
  20. package/examples/jsm/nodes/Nodes.js +12 -11
  21. package/examples/jsm/nodes/accessors/BitangentNode.js +7 -83
  22. package/examples/jsm/nodes/accessors/BufferNode.js +6 -0
  23. package/examples/jsm/nodes/accessors/CameraNode.js +12 -119
  24. package/examples/jsm/nodes/accessors/MaterialNode.js +2 -0
  25. package/examples/jsm/nodes/accessors/ModelNode.js +3 -0
  26. package/examples/jsm/nodes/accessors/NormalNode.js +9 -101
  27. package/examples/jsm/nodes/accessors/PositionNode.js +6 -100
  28. package/examples/jsm/nodes/accessors/ReferenceNode.js +6 -0
  29. package/examples/jsm/nodes/accessors/ReflectVectorNode.js +2 -31
  30. package/examples/jsm/nodes/accessors/{TextureStoreNode.js → StorageTextureNode.js} +19 -6
  31. package/examples/jsm/nodes/accessors/TangentNode.js +11 -97
  32. package/examples/jsm/nodes/accessors/Texture3DNode.js +100 -0
  33. package/examples/jsm/nodes/accessors/UVNode.js +2 -46
  34. package/examples/jsm/nodes/core/AttributeNode.js +15 -3
  35. package/examples/jsm/nodes/core/ContextNode.js +6 -0
  36. package/examples/jsm/nodes/core/Node.js +15 -2
  37. package/examples/jsm/nodes/core/NodeBuilder.js +20 -9
  38. package/examples/jsm/nodes/core/NodeKeywords.js +1 -1
  39. package/examples/jsm/nodes/core/OutputStructNode.js +1 -5
  40. package/examples/jsm/nodes/core/PropertyNode.js +1 -0
  41. package/examples/jsm/nodes/core/VaryingNode.js +40 -9
  42. package/examples/jsm/nodes/display/AfterImageNode.js +14 -2
  43. package/examples/jsm/nodes/display/PassNode.js +3 -1
  44. package/examples/jsm/nodes/display/ViewportNode.js +1 -1
  45. package/examples/jsm/nodes/functions/PhysicalLightingModel.js +61 -17
  46. package/examples/jsm/nodes/functions/ToonLightingModel.js +49 -0
  47. package/examples/jsm/nodes/lighting/AnalyticLightNode.js +2 -1
  48. package/examples/jsm/nodes/lighting/LightsNode.js +17 -0
  49. package/examples/jsm/nodes/materials/Line2NodeMaterial.js +1 -1
  50. package/examples/jsm/nodes/materials/Materials.js +3 -0
  51. package/examples/jsm/nodes/materials/MeshMatcapNodeMaterial.js +52 -0
  52. package/examples/jsm/nodes/materials/MeshPhysicalNodeMaterial.js +21 -4
  53. package/examples/jsm/nodes/materials/MeshToonNodeMaterial.js +34 -0
  54. package/examples/jsm/nodes/materials/NodeMaterial.js +13 -5
  55. package/examples/jsm/nodes/materials/VolumeNodeMaterial.js +106 -0
  56. package/examples/jsm/nodes/math/HashNode.js +2 -2
  57. package/examples/jsm/nodes/shadernode/ShaderNode.js +55 -33
  58. package/examples/jsm/nodes/utils/ArrayElementNode.js +1 -1
  59. package/examples/jsm/nodes/utils/MatcapUVNode.js +1 -1
  60. package/examples/jsm/nodes/utils/TimerNode.js +1 -1
  61. package/examples/jsm/objects/Lensflare.js +2 -2
  62. package/examples/jsm/postprocessing/RenderPass.js +1 -1
  63. package/examples/jsm/renderers/CSS2DRenderer.js +25 -5
  64. package/examples/jsm/renderers/CSS3DRenderer.js +24 -3
  65. package/examples/jsm/renderers/common/Attributes.js +2 -0
  66. package/examples/jsm/renderers/common/Bindings.js +17 -0
  67. package/examples/jsm/renderers/common/ChainMap.js +18 -48
  68. package/examples/jsm/renderers/common/ClippingContext.js +4 -4
  69. package/examples/jsm/renderers/common/Pipelines.js +2 -2
  70. package/examples/jsm/renderers/common/RenderBundle.js +18 -0
  71. package/examples/jsm/renderers/common/RenderBundles.js +38 -0
  72. package/examples/jsm/renderers/common/RenderList.js +9 -0
  73. package/examples/jsm/renderers/common/RenderObject.js +6 -0
  74. package/examples/jsm/renderers/common/Renderer.js +139 -11
  75. package/examples/jsm/renderers/common/Uniform.js +1 -1
  76. package/examples/jsm/renderers/common/nodes/NodeSampledTexture.js +18 -4
  77. package/examples/jsm/renderers/common/nodes/NodeSampler.js +6 -0
  78. package/examples/jsm/renderers/webgl/nodes/GLSLNodeBuilder.js +17 -5
  79. package/examples/jsm/renderers/webgl/utils/WebGLTextureUtils.js +93 -6
  80. package/examples/jsm/renderers/webgpu/WebGPUBackend.js +50 -4
  81. package/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js +69 -11
  82. package/examples/jsm/renderers/webgpu/utils/WebGPUBindingUtils.js +10 -1
  83. package/examples/jsm/renderers/webgpu/utils/WebGPUConstants.js +6 -0
  84. package/examples/jsm/renderers/webgpu/utils/WebGPUPipelineUtils.js +62 -19
  85. package/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js +62 -3
  86. package/examples/jsm/utils/BufferGeometryUtils.js +18 -16
  87. package/examples/jsm/utils/GPUStatsPanel.js +2 -0
  88. package/examples/jsm/utils/SortUtils.js +8 -5
  89. package/package.json +3 -2
  90. package/src/animation/tracks/BooleanKeyframeTrack.js +10 -1
  91. package/src/animation/tracks/QuaternionKeyframeTrack.js +1 -2
  92. package/src/animation/tracks/StringKeyframeTrack.js +10 -1
  93. package/src/constants.js +1 -1
  94. package/src/core/Object3D.js +2 -0
  95. package/src/core/Raycaster.js +6 -2
  96. package/src/loaders/FileLoader.js +4 -0
  97. package/src/loaders/LoaderUtils.js +3 -1
  98. package/src/loaders/ObjectLoader.js +1 -0
  99. package/src/objects/BatchedMesh.js +91 -1
  100. package/src/renderers/WebGLRenderer.js +288 -57
  101. package/src/renderers/shaders/ShaderChunk/batching_pars_vertex.glsl.js +15 -0
  102. package/src/renderers/shaders/ShaderChunk/color_pars_vertex.glsl.js +1 -1
  103. package/src/renderers/shaders/ShaderChunk/color_vertex.glsl.js +9 -1
  104. package/src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js +8 -22
  105. package/src/renderers/shaders/ShaderChunk/morphcolor_vertex.glsl.js +1 -1
  106. package/src/renderers/shaders/ShaderChunk/morphinstance_vertex.glsl.js +1 -1
  107. package/src/renderers/shaders/ShaderChunk/morphnormal_vertex.glsl.js +3 -14
  108. package/src/renderers/shaders/ShaderChunk/morphtarget_pars_vertex.glsl.js +10 -31
  109. package/src/renderers/shaders/ShaderChunk/morphtarget_vertex.glsl.js +3 -23
  110. package/src/renderers/webgl/WebGLBackground.js +6 -0
  111. package/src/renderers/webgl/WebGLExtensions.js +3 -1
  112. package/src/renderers/webgl/WebGLLights.js +9 -12
  113. package/src/renderers/webgl/WebGLMaterials.js +1 -5
  114. package/src/renderers/webgl/WebGLMorphtargets.js +1 -2
  115. package/src/renderers/webgl/WebGLProgram.js +2 -31
  116. package/src/renderers/webgl/WebGLPrograms.js +14 -14
  117. package/src/renderers/webgl/WebGLRenderStates.js +2 -2
  118. package/src/renderers/webgl/WebGLTextures.js +139 -70
  119. package/src/renderers/webxr/WebXRDepthSensing.js +3 -3
  120. package/src/renderers/webxr/WebXRManager.js +6 -2
  121. package/src/textures/CompressedArrayTexture.js +14 -0
  122. package/src/textures/DataArrayTexture.js +14 -0
  123. package/src/textures/DepthTexture.js +1 -3
  124. package/src/utils.js +30 -1
@@ -33,11 +33,7 @@ class OutputStructNode extends Node {
33
33
 
34
34
  generate( builder, output ) {
35
35
 
36
- const nodeVar = builder.getVarFromNode( this );
37
- nodeVar.isOutputStructVar = true;
38
-
39
- const propertyName = builder.getPropertyName( nodeVar );
40
-
36
+ const propertyName = builder.getOutputStructName();
41
37
  const members = this.members;
42
38
 
43
39
  const structPrefix = propertyName !== '' ? propertyName + '.' : '';
@@ -78,5 +78,6 @@ export const transmission = nodeImmutable( PropertyNode, 'float', 'Transmission'
78
78
  export const thickness = nodeImmutable( PropertyNode, 'float', 'Thickness' );
79
79
  export const attenuationDistance = nodeImmutable( PropertyNode, 'float', 'AttenuationDistance' );
80
80
  export const attenuationColor = nodeImmutable( PropertyNode, 'color', 'AttenuationColor' );
81
+ export const dispersion = nodeImmutable( PropertyNode, 'float', 'Dispersion' );
81
82
 
82
83
  addNodeClass( 'PropertyNode', PropertyNode );
@@ -35,22 +35,53 @@ class VaryingNode extends Node {
35
35
 
36
36
  }
37
37
 
38
+ setupVarying( builder ) {
39
+
40
+ const properties = builder.getNodeProperties( this );
41
+
42
+ let varying = properties.varying;
43
+
44
+ if ( varying === undefined ) {
45
+
46
+ const name = this.name;
47
+ const type = this.getNodeType( builder );
48
+
49
+ properties.varying = varying = builder.getVaryingFromNode( this, name, type );
50
+ properties.node = this.node;
51
+
52
+ }
53
+
54
+ // this property can be used to check if the varying can be optimized for a variable
55
+ varying.needsInterpolation || ( varying.needsInterpolation = ( builder.shaderStage === 'fragment' ) );
56
+
57
+ return varying;
58
+
59
+ }
60
+
61
+ setup( builder ) {
62
+
63
+ this.setupVarying( builder );
64
+
65
+ }
66
+
38
67
  generate( builder ) {
39
68
 
40
- const { name, node } = this;
41
- const type = this.getNodeType( builder );
69
+ const properties = builder.getNodeProperties( this );
70
+ const varying = this.setupVarying( builder );
71
+
72
+ if ( properties.propertyName === undefined ) {
42
73
 
43
- const nodeVarying = builder.getVaryingFromNode( this, name, type );
74
+ const type = this.getNodeType( builder );
75
+ const propertyName = builder.getPropertyName( varying, NodeShaderStage.VERTEX );
44
76
 
45
- // this property can be used to check if the varying can be optimized for a var
46
- nodeVarying.needsInterpolation || ( nodeVarying.needsInterpolation = ( builder.shaderStage === 'fragment' ) );
77
+ // force node run in vertex stage
78
+ builder.flowNodeFromShaderStage( NodeShaderStage.VERTEX, this.node, type, propertyName );
47
79
 
48
- const propertyName = builder.getPropertyName( nodeVarying, NodeShaderStage.VERTEX );
80
+ properties.propertyName = propertyName;
49
81
 
50
- // force node run in vertex stage
51
- builder.flowNodeFromShaderStage( NodeShaderStage.VERTEX, node, type, propertyName );
82
+ }
52
83
 
53
- return builder.getPropertyName( nodeVarying );
84
+ return builder.getPropertyName( varying );
54
85
 
55
86
  }
56
87
 
@@ -8,6 +8,9 @@ import { uniform } from '../core/UniformNode.js';
8
8
  import { RenderTarget } from 'three';
9
9
  import { sign, max } from '../math/MathNode.js';
10
10
  import QuadMesh from '../../objects/QuadMesh.js';
11
+ import { NoToneMapping, Vector2 } from 'three';
12
+
13
+ const _size = new Vector2();
11
14
 
12
15
  const quadMeshComp = new QuadMesh();
13
16
 
@@ -58,12 +61,21 @@ class AfterImageNode extends TempNode {
58
61
  this._compRT.texture.type = textureType;
59
62
  this._oldRT.texture.type = textureType;
60
63
 
64
+ renderer.getDrawingBufferSize( _size );
65
+
66
+ this.setSize( _size.x, _size.y );
67
+
68
+
69
+ const currentToneMapping = renderer.toneMapping;
70
+ const currentToneMappingNode = renderer.toneMappingNode;
61
71
  const currentRenderTarget = renderer.getRenderTarget();
62
72
  const currentTexture = textureNode.value;
63
73
 
64
74
  this.textureNodeOld.value = this._oldRT.texture;
65
75
 
66
76
  // comp
77
+ renderer.toneMapping = NoToneMapping;
78
+ renderer.toneMappingNode = null;
67
79
  renderer.setRenderTarget( this._compRT );
68
80
  quadMeshComp.render( renderer );
69
81
 
@@ -72,9 +84,9 @@ class AfterImageNode extends TempNode {
72
84
  this._oldRT = this._compRT;
73
85
  this._compRT = temp;
74
86
 
75
- // set size before swapping fails
76
- this.setSize( map.image.width, map.image.height );
77
87
 
88
+ renderer.toneMapping = currentToneMapping;
89
+ renderer.toneMappingNode = currentToneMappingNode;
78
90
  renderer.setRenderTarget( currentRenderTarget );
79
91
  textureNode.value = currentTexture;
80
92
 
@@ -7,6 +7,8 @@ import { uniform } from '../core/UniformNode.js';
7
7
  import { viewZToOrthographicDepth, perspectiveDepthToViewZ } from './ViewportDepthNode.js';
8
8
  import { RenderTarget, Vector2, HalfFloatType, DepthTexture, NoToneMapping/*, FloatType*/ } from 'three';
9
9
 
10
+ const _size = new Vector2();
11
+
10
12
  class PassTextureNode extends TextureNode {
11
13
 
12
14
  constructor( passNode, texture ) {
@@ -135,7 +137,7 @@ class PassNode extends TempNode {
135
137
 
136
138
  this._pixelRatio = renderer.getPixelRatio();
137
139
 
138
- const size = renderer.getSize( new Vector2() );
140
+ const size = renderer.getSize( _size );
139
141
 
140
142
  this.setSize( size.width, size.height );
141
143
 
@@ -33,7 +33,7 @@ class ViewportNode extends Node {
33
33
 
34
34
  if ( this.scope === ViewportNode.RESOLUTION || this.scope === ViewportNode.VIEWPORT ) {
35
35
 
36
- updateType = NodeUpdateType.FRAME;
36
+ updateType = NodeUpdateType.RENDER;
37
37
 
38
38
  }
39
39
 
@@ -6,7 +6,7 @@ import F_Schlick from './BSDF/F_Schlick.js';
6
6
  import Schlick_to_F0 from './BSDF/Schlick_to_F0.js';
7
7
  import BRDF_Sheen from './BSDF/BRDF_Sheen.js';
8
8
  import LightingModel from '../core/LightingModel.js';
9
- import { diffuseColor, specularColor, specularF90, roughness, clearcoat, clearcoatRoughness, sheen, sheenRoughness, iridescence, iridescenceIOR, iridescenceThickness, ior, thickness, transmission, attenuationDistance, attenuationColor } from '../core/PropertyNode.js';
9
+ import { diffuseColor, specularColor, specularF90, roughness, clearcoat, clearcoatRoughness, sheen, sheenRoughness, iridescence, iridescenceIOR, iridescenceThickness, ior, thickness, transmission, attenuationDistance, attenuationColor, dispersion } from '../core/PropertyNode.js';
10
10
  import { transformedNormalView, transformedClearcoatNormalView, transformedNormalWorld } from '../accessors/NormalNode.js';
11
11
  import { positionViewDirection, positionWorld } from '../accessors/PositionNode.js';
12
12
  import { tslFn, float, vec2, vec3, vec4, mat3, If } from '../shadernode/ShaderNode.js';
@@ -17,6 +17,7 @@ import { cameraPosition, cameraProjectionMatrix, cameraViewMatrix } from '../acc
17
17
  import { modelWorldMatrix } from '../accessors/ModelNode.js';
18
18
  import { viewportResolution } from '../display/ViewportNode.js';
19
19
  import { viewportMipTexture } from '../display/ViewportTextureNode.js';
20
+ import { loop } from '../utils/LoopNode.js';
20
21
 
21
22
  //
22
23
  // Transmission
@@ -102,21 +103,62 @@ const volumeAttenuation = tslFn( ( [ transmissionDistance, attenuationColor, att
102
103
  ]
103
104
  } );
104
105
 
105
- const getIBLVolumeRefraction = tslFn( ( [ n, v, roughness, diffuseColor, specularColor, specularF90, position, modelMatrix, viewMatrix, projMatrix, ior, thickness, attenuationColor, attenuationDistance ] ) => {
106
+ const getIBLVolumeRefraction = tslFn( ( [ n, v, roughness, diffuseColor, specularColor, specularF90, position, modelMatrix, viewMatrix, projMatrix, ior, thickness, attenuationColor, attenuationDistance, dispersion ] ) => {
106
107
 
107
- const transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );
108
- const refractedRayExit = position.add( transmissionRay );
108
+ let transmittedLight, transmittance;
109
109
 
110
- // Project refracted vector on the framebuffer, while mapping to normalized device coordinates.
111
- const ndcPos = projMatrix.mul( viewMatrix.mul( vec4( refractedRayExit, 1.0 ) ) );
112
- const refractionCoords = vec2( ndcPos.xy.div( ndcPos.w ) ).toVar();
113
- refractionCoords.addAssign( 1.0 );
114
- refractionCoords.divAssign( 2.0 );
115
- refractionCoords.assign( vec2( refractionCoords.x, refractionCoords.y.oneMinus() ) ); // webgpu
110
+ if ( dispersion ) {
111
+
112
+ transmittedLight = vec4().toVar();
113
+ transmittance = vec3().toVar();
114
+
115
+ const halfSpread = ior.sub( 1.0 ).mul( dispersion.mul( 0.025 ) );
116
+ const iors = vec3( ior.sub( halfSpread ), ior, ior.add( halfSpread ) );
117
+
118
+ loop( { start: 0, end: 3 }, ( { i } ) => {
119
+
120
+ const ior = iors.element( i );
121
+
122
+ const transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );
123
+ const refractedRayExit = position.add( transmissionRay );
124
+
125
+ // Project refracted vector on the framebuffer, while mapping to normalized device coordinates.
126
+ const ndcPos = projMatrix.mul( viewMatrix.mul( vec4( refractedRayExit, 1.0 ) ) );
127
+ const refractionCoords = vec2( ndcPos.xy.div( ndcPos.w ) ).toVar();
128
+ refractionCoords.addAssign( 1.0 );
129
+ refractionCoords.divAssign( 2.0 );
130
+ refractionCoords.assign( vec2( refractionCoords.x, refractionCoords.y.oneMinus() ) ); // webgpu
131
+
132
+ // Sample framebuffer to get pixel the refracted ray hits.
133
+ const transmissionSample = getTransmissionSample( refractionCoords, roughness, ior );
134
+
135
+ transmittedLight.element( i ).assign( transmissionSample.element( i ) );
136
+ transmittedLight.a.addAssign( transmissionSample.a );
137
+
138
+ transmittance.element( i ).assign( diffuseColor.element( i ).mul( volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance ).element( i ) ) );
139
+
140
+ } );
141
+
142
+ transmittedLight.a.divAssign( 3.0 );
143
+
144
+ } else {
145
+
146
+ const transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );
147
+ const refractedRayExit = position.add( transmissionRay );
148
+
149
+ // Project refracted vector on the framebuffer, while mapping to normalized device coordinates.
150
+ const ndcPos = projMatrix.mul( viewMatrix.mul( vec4( refractedRayExit, 1.0 ) ) );
151
+ const refractionCoords = vec2( ndcPos.xy.div( ndcPos.w ) ).toVar();
152
+ refractionCoords.addAssign( 1.0 );
153
+ refractionCoords.divAssign( 2.0 );
154
+ refractionCoords.assign( vec2( refractionCoords.x, refractionCoords.y.oneMinus() ) ); // webgpu
155
+
156
+ // Sample framebuffer to get pixel the refracted ray hits.
157
+ transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );
158
+ transmittance = diffuseColor.mul( volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance ) );
159
+
160
+ }
116
161
 
117
- // Sample framebuffer to get pixel the refracted ray hits.
118
- const transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );
119
- const transmittance = diffuseColor.mul( volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance ) );
120
162
  const attenuatedColor = transmittance.rgb.mul( transmittedLight.rgb );
121
163
  const dotNV = n.dot( v ).clamp();
122
164
 
@@ -211,7 +253,7 @@ const evalIridescence = tslFn( ( { outsideIOR, eta2, cosTheta1, thinFilmThicknes
211
253
 
212
254
  // Second interface
213
255
  const baseIOR = Fresnel0ToIor( baseF0.clamp( 0.0, 0.9999 ) ); // guard against 1.0
214
- const R1 = IorToFresnel0( baseIOR, iridescenceIOR.vec3() );
256
+ const R1 = IorToFresnel0( baseIOR, iridescenceIOR.toVec3() );
215
257
  const R23 = F_Schlick( { f0: R1, f90: 1.0, dotVH: cosTheta2 } );
216
258
  const phi23 = vec3(
217
259
  baseIOR.x.lessThan( iridescenceIOR ).cond( Math.PI, 0.0 ),
@@ -289,13 +331,13 @@ const IBLSheenBRDF = tslFn( ( { normal, viewDir, roughness } ) => {
289
331
  } );
290
332
 
291
333
  const clearcoatF0 = vec3( 0.04 );
292
- const clearcoatF90 = vec3( 1 );
334
+ const clearcoatF90 = float( 1 );
293
335
 
294
336
  //
295
337
 
296
338
  class PhysicalLightingModel extends LightingModel {
297
339
 
298
- constructor( clearcoat = false, sheen = false, iridescence = false, anisotropy = false, transmission = false ) {
340
+ constructor( clearcoat = false, sheen = false, iridescence = false, anisotropy = false, transmission = false, dispersion = false ) {
299
341
 
300
342
  super();
301
343
 
@@ -304,6 +346,7 @@ class PhysicalLightingModel extends LightingModel {
304
346
  this.iridescence = iridescence;
305
347
  this.anisotropy = anisotropy;
306
348
  this.transmission = transmission;
349
+ this.dispersion = dispersion;
307
350
 
308
351
  this.clearcoatRadiance = null;
309
352
  this.clearcoatSpecularDirect = null;
@@ -368,7 +411,8 @@ class PhysicalLightingModel extends LightingModel {
368
411
  ior,
369
412
  thickness,
370
413
  attenuationColor,
371
- attenuationDistance
414
+ attenuationDistance,
415
+ this.dispersion ? dispersion : null
372
416
  );
373
417
 
374
418
  context.backdropAlpha = transmission;
@@ -0,0 +1,49 @@
1
+ import LightingModel from '../core/LightingModel.js';
2
+ import BRDF_Lambert from './BSDF/BRDF_Lambert.js';
3
+ import { diffuseColor } from '../core/PropertyNode.js';
4
+ import { normalGeometry } from '../accessors/NormalNode.js';
5
+ import { tslFn, float, vec2, vec3 } from '../shadernode/ShaderNode.js';
6
+ import { mix, smoothstep } from '../math/MathNode.js';
7
+ import { materialReference } from '../accessors/MaterialReferenceNode.js';
8
+
9
+ const getGradientIrradiance = tslFn( ( { normal, lightDirection, builder } ) => {
10
+
11
+ // dotNL will be from -1.0 to 1.0
12
+ const dotNL = normal.dot( lightDirection );
13
+ const coord = vec2( dotNL.mul( 0.5 ).add( 0.5 ), 0.0 );
14
+
15
+ if ( builder.material.gradientMap ) {
16
+
17
+ const gradientMap = materialReference( 'gradientMap', 'texture' ).context( { getUV: () => coord } );
18
+
19
+ return vec3( gradientMap.r );
20
+
21
+ } else {
22
+
23
+ const fw = coord.fwidth().mul( 0.5 );
24
+
25
+ return mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( float( 0.7 ).sub( fw.x ), float( 0.7 ).add( fw.x ), coord.x ) );
26
+
27
+ }
28
+
29
+ } );
30
+
31
+ class ToonLightingModel extends LightingModel {
32
+
33
+ direct( { lightDirection, lightColor, reflectedLight }, stack, builder ) {
34
+
35
+ const irradiance = getGradientIrradiance( { normal: normalGeometry, lightDirection, builder } ).mul( lightColor );
36
+
37
+ reflectedLight.directDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) );
38
+
39
+ }
40
+
41
+ indirectDiffuse( { irradiance, reflectedLight } ) {
42
+
43
+ reflectedLight.indirectDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) );
44
+
45
+ }
46
+
47
+ }
48
+
49
+ export default ToonLightingModel;
@@ -182,7 +182,7 @@ class AnalyticLightNode extends LightingNode {
182
182
  updateShadow( frame ) {
183
183
 
184
184
  const { rtt, light } = this;
185
- const { renderer, scene } = frame;
185
+ const { renderer, scene, camera } = frame;
186
186
 
187
187
  const currentOverrideMaterial = scene.overrideMaterial;
188
188
 
@@ -191,6 +191,7 @@ class AnalyticLightNode extends LightingNode {
191
191
  rtt.setSize( light.shadow.mapSize.width, light.shadow.mapSize.height );
192
192
 
193
193
  light.shadow.updateMatrices( light );
194
+ light.shadow.camera.layers.mask = camera.layers.mask;
194
195
 
195
196
  const currentToneMapping = renderer.toneMapping;
196
197
  const currentRenderTarget = renderer.getRenderTarget();
@@ -53,6 +53,18 @@ class LightsNode extends Node {
53
53
 
54
54
  }
55
55
 
56
+ analyze( builder ) {
57
+
58
+ const properties = builder.getDataFromNode( this );
59
+
60
+ for ( const node of properties.nodes ) {
61
+
62
+ node.build( builder );
63
+
64
+ }
65
+
66
+ }
67
+
56
68
  setup( builder ) {
57
69
 
58
70
  const context = builder.context;
@@ -70,6 +82,11 @@ class LightsNode extends Node {
70
82
 
71
83
  //
72
84
 
85
+ const properties = builder.getDataFromNode( this );
86
+ properties.nodes = stack.nodes;
87
+
88
+ //
89
+
73
90
  lightingModel.start( context, stack, builder );
74
91
 
75
92
  // lights
@@ -147,7 +147,7 @@ class Line2NodeMaterial extends NodeMaterial {
147
147
 
148
148
  const worldPos = varyingProperty( 'vec4', 'worldPos' );
149
149
 
150
- worldPos.assign( positionGeometry.y.lessThan( 0.5 ).cond( start, end) );
150
+ worldPos.assign( positionGeometry.y.lessThan( 0.5 ).cond( start, end ) );
151
151
 
152
152
  // height offset
153
153
  const hw = materialLineWidth.mul( 0.5 );
@@ -12,6 +12,9 @@ export { default as MeshPhongNodeMaterial } from './MeshPhongNodeMaterial.js';
12
12
  export { default as MeshStandardNodeMaterial } from './MeshStandardNodeMaterial.js';
13
13
  export { default as MeshPhysicalNodeMaterial } from './MeshPhysicalNodeMaterial.js';
14
14
  export { default as MeshSSSNodeMaterial } from './MeshSSSNodeMaterial.js';
15
+ export { default as MeshToonNodeMaterial } from './MeshToonNodeMaterial.js';
16
+ export { default as MeshMatcapNodeMaterial } from './MeshMatcapNodeMaterial.js';
15
17
  export { default as PointsNodeMaterial } from './PointsNodeMaterial.js';
16
18
  export { default as SpriteNodeMaterial } from './SpriteNodeMaterial.js';
17
19
  export { default as ShadowNodeMaterial } from './ShadowNodeMaterial.js';
20
+ export { default as VolumeNodeMaterial } from './VolumeNodeMaterial.js';
@@ -0,0 +1,52 @@
1
+ import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js';
2
+ import { materialReference } from '../accessors/MaterialReferenceNode.js';
3
+ import { diffuseColor } from '../core/PropertyNode.js';
4
+ import { vec3 } from '../shadernode/ShaderNode.js';
5
+ import { MeshMatcapMaterial } from 'three';
6
+ import { mix } from '../math/MathNode.js';
7
+ import { matcapUV } from '../utils/MatcapUVNode.js';
8
+
9
+ const defaultValues = new MeshMatcapMaterial();
10
+
11
+ class MeshMatcapNodeMaterial extends NodeMaterial {
12
+
13
+ constructor( parameters ) {
14
+
15
+ super();
16
+
17
+ this.isMeshMatcapNodeMaterial = true;
18
+
19
+ this.lights = false;
20
+
21
+ this.setDefaultValues( defaultValues );
22
+
23
+ this.setValues( parameters );
24
+
25
+ }
26
+
27
+ setupVariants( builder ) {
28
+
29
+ const uv = matcapUV;
30
+
31
+ let matcapColor;
32
+
33
+ if ( builder.material.matcap ) {
34
+
35
+ matcapColor = materialReference( 'matcap', 'texture' ).context( { getUV: () => uv } );
36
+
37
+ } else {
38
+
39
+ matcapColor = vec3( mix( 0.2, 0.8, uv.y ) ); // default if matcap is missing
40
+
41
+ }
42
+
43
+ diffuseColor.rgb.mulAssign( matcapColor.rgb );
44
+
45
+ }
46
+
47
+ }
48
+
49
+
50
+ export default MeshMatcapNodeMaterial;
51
+
52
+ addNodeMaterial( 'MeshMatcapNodeMaterial', MeshMatcapNodeMaterial );
@@ -1,8 +1,9 @@
1
1
  import { addNodeMaterial } from './NodeMaterial.js';
2
2
  import { transformedClearcoatNormalView } from '../accessors/NormalNode.js';
3
- import { clearcoat, clearcoatRoughness, sheen, sheenRoughness, iridescence, iridescenceIOR, iridescenceThickness, specularColor, specularF90, diffuseColor, metalness, roughness, anisotropy, alphaT, anisotropyT, anisotropyB, ior, transmission, thickness, attenuationDistance, attenuationColor } from '../core/PropertyNode.js';
4
- import { materialClearcoat, materialClearcoatRoughness, materialClearcoatNormal, materialSheen, materialSheenRoughness, materialIridescence, materialIridescenceIOR, materialIridescenceThickness, materialSpecularIntensity, materialSpecularColor, materialAnisotropy, materialIOR, materialTransmission, materialThickness, materialAttenuationDistance, materialAttenuationColor } from '../accessors/MaterialNode.js';
3
+ import { clearcoat, clearcoatRoughness, sheen, sheenRoughness, iridescence, iridescenceIOR, iridescenceThickness, specularColor, specularF90, diffuseColor, metalness, roughness, anisotropy, alphaT, anisotropyT, anisotropyB, ior, transmission, thickness, attenuationDistance, attenuationColor, dispersion } from '../core/PropertyNode.js';
4
+ import { materialClearcoat, materialClearcoatRoughness, materialClearcoatNormal, materialSheen, materialSheenRoughness, materialIridescence, materialIridescenceIOR, materialIridescenceThickness, materialSpecularIntensity, materialSpecularColor, materialAnisotropy, materialIOR, materialTransmission, materialThickness, materialAttenuationDistance, materialAttenuationColor, materialDispersion } from '../accessors/MaterialNode.js';
5
5
  import { float, vec2, vec3, If } from '../shadernode/ShaderNode.js';
6
+ import getRoughness from '../functions/material/getRoughness.js';
6
7
  import { TBNViewMatrix } from '../accessors/AccessorsUtils.js';
7
8
  import PhysicalLightingModel from '../functions/PhysicalLightingModel.js';
8
9
  import MeshStandardNodeMaterial from './MeshStandardNodeMaterial.js';
@@ -38,6 +39,7 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial {
38
39
  this.thicknessNode = null;
39
40
  this.attenuationDistanceNode = null;
40
41
  this.attenuationColorNode = null;
42
+ this.dispersionNode = null;
41
43
 
42
44
  this.anisotropyNode = null;
43
45
 
@@ -77,6 +79,12 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial {
77
79
 
78
80
  }
79
81
 
82
+ get useDispersion() {
83
+
84
+ return this.dispersion > 0 || this.dispersionNode !== null;
85
+
86
+ }
87
+
80
88
  setupSpecular() {
81
89
 
82
90
  const iorNode = this.iorNode ? float( this.iorNode ) : materialIOR;
@@ -89,7 +97,7 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial {
89
97
 
90
98
  setupLightingModel( /*builder*/ ) {
91
99
 
92
- return new PhysicalLightingModel( this.useClearcoat, this.useSheen, this.useIridescence, this.useAnisotropy, this.useTransmission );
100
+ return new PhysicalLightingModel( this.useClearcoat, this.useSheen, this.useIridescence, this.useAnisotropy, this.useTransmission, this.useDispersion );
93
101
 
94
102
  }
95
103
 
@@ -105,7 +113,7 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial {
105
113
  const clearcoatRoughnessNode = this.clearcoatRoughnessNode ? float( this.clearcoatRoughnessNode ) : materialClearcoatRoughness;
106
114
 
107
115
  clearcoat.assign( clearcoatNode );
108
- clearcoatRoughness.assign( clearcoatRoughnessNode );
116
+ clearcoatRoughness.assign( getRoughness( { roughness: clearcoatRoughnessNode } ) );
109
117
 
110
118
  }
111
119
 
@@ -176,6 +184,14 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial {
176
184
  attenuationDistance.assign( attenuationDistanceNode );
177
185
  attenuationColor.assign( attenuationColorNode );
178
186
 
187
+ if ( this.useDispersion ) {
188
+
189
+ const dispersionNode = this.dispersionNode ? float( this.dispersionNode ) : materialDispersion;
190
+
191
+ dispersion.assign( dispersionNode );
192
+
193
+ }
194
+
179
195
  }
180
196
 
181
197
  }
@@ -212,6 +228,7 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial {
212
228
  this.thicknessNode = source.thicknessNode;
213
229
  this.attenuationDistanceNode = source.attenuationDistanceNode;
214
230
  this.attenuationColorNode = source.attenuationColorNode;
231
+ this.dispersionNode = source.dispersionNode;
215
232
 
216
233
  this.anisotropyNode = source.anisotropyNode;
217
234
 
@@ -0,0 +1,34 @@
1
+ import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js';
2
+ import ToonLightingModel from '../functions/ToonLightingModel.js';
3
+
4
+ import { MeshToonMaterial } from 'three';
5
+
6
+ const defaultValues = new MeshToonMaterial();
7
+
8
+ class MeshToonNodeMaterial extends NodeMaterial {
9
+
10
+ constructor( parameters ) {
11
+
12
+ super();
13
+
14
+ this.isMeshToonNodeMaterial = true;
15
+
16
+ this.lights = true;
17
+
18
+ this.setDefaultValues( defaultValues );
19
+
20
+ this.setValues( parameters );
21
+
22
+ }
23
+
24
+ setupLightingModel( /*builder*/ ) {
25
+
26
+ return new ToonLightingModel();
27
+
28
+ }
29
+
30
+ }
31
+
32
+ export default MeshToonNodeMaterial;
33
+
34
+ addNodeMaterial( 'MeshToonNodeMaterial', MeshToonNodeMaterial );
@@ -1,10 +1,10 @@
1
- import { Material, ShaderMaterial } from 'three';
1
+ import { Material } from 'three';
2
2
  import { getNodeChildren, getCacheKey } from '../core/NodeUtils.js';
3
3
  import { attribute } from '../core/AttributeNode.js';
4
4
  import { output, diffuseColor, varyingProperty } from '../core/PropertyNode.js';
5
5
  import { materialAlphaTest, materialColor, materialOpacity, materialEmissive, materialNormal } from '../accessors/MaterialNode.js';
6
6
  import { modelViewProjection } from '../accessors/ModelViewProjectionNode.js';
7
- import { transformedNormalView } from '../accessors/NormalNode.js';
7
+ import { transformedNormalView, normalLocal } from '../accessors/NormalNode.js';
8
8
  import { instance } from '../accessors/InstanceNode.js';
9
9
  import { batch } from '../accessors/BatchNode.js';
10
10
  import { materialReference } from '../accessors/MaterialReferenceNode.js';
@@ -27,7 +27,7 @@ import { faceDirection } from '../display/FrontFacingNode.js';
27
27
 
28
28
  const NodeMaterials = new Map();
29
29
 
30
- class NodeMaterial extends ShaderMaterial {
30
+ class NodeMaterial extends Material {
31
31
 
32
32
  constructor() {
33
33
 
@@ -216,6 +216,16 @@ class NodeMaterial extends ShaderMaterial {
216
216
 
217
217
  }
218
218
 
219
+ if ( this.displacementMap ) {
220
+
221
+ const displacementMap = materialReference( 'displacementMap', 'texture' );
222
+ const displacementScale = materialReference( 'displacementScale', 'float' );
223
+ const displacementBias = materialReference( 'displacementBias', 'float' );
224
+
225
+ positionLocal.addAssign( normalLocal.normalize().mul( ( displacementMap.x.mul( displacementScale ).add( displacementBias ) ) ) );
226
+
227
+ }
228
+
219
229
  if ( object.isBatchedMesh ) {
220
230
 
221
231
  batch( object ).append();
@@ -448,8 +458,6 @@ class NodeMaterial extends ShaderMaterial {
448
458
 
449
459
  }
450
460
 
451
- Object.assign( this.defines, material.defines );
452
-
453
461
  const descriptors = Object.getOwnPropertyDescriptors( material.constructor.prototype );
454
462
 
455
463
  for ( const key in descriptors ) {