super-three 0.163.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 (197) hide show
  1. package/README.md +3 -3
  2. package/build/three.cjs +1127 -452
  3. package/build/three.module.js +1127 -452
  4. package/build/three.module.min.js +2 -2
  5. package/examples/jsm/animation/CCDIKSolver.js +4 -2
  6. package/examples/jsm/controls/TransformControls.js +1 -1
  7. package/examples/jsm/environments/RoomEnvironment.js +1 -5
  8. package/examples/jsm/exporters/GLTFExporter.js +45 -1
  9. package/examples/jsm/exporters/USDZExporter.js +13 -5
  10. package/examples/jsm/helpers/ViewHelper.js +32 -67
  11. package/examples/jsm/libs/draco/README.md +2 -2
  12. package/examples/jsm/libs/tween.module.js +75 -64
  13. package/examples/jsm/lines/LineMaterial.js +1 -15
  14. package/examples/jsm/lines/LineSegments2.js +15 -0
  15. package/examples/jsm/lines/Wireframe.js +16 -1
  16. package/examples/jsm/loaders/DRACOLoader.js +1 -1
  17. package/examples/jsm/loaders/EXRLoader.js +283 -99
  18. package/examples/jsm/loaders/FBXLoader.js +24 -13
  19. package/examples/jsm/loaders/GLTFLoader.js +55 -0
  20. package/examples/jsm/loaders/KTX2Loader.js +3 -6
  21. package/examples/jsm/loaders/LDrawLoader.js +3 -2
  22. package/examples/jsm/loaders/MMDLoader.js +31 -12
  23. package/examples/jsm/loaders/VRMLLoader.js +1 -1
  24. package/examples/jsm/loaders/lwo/IFFParser.js +8 -5
  25. package/examples/jsm/materials/MeshGouraudMaterial.js +7 -1
  26. package/examples/jsm/math/Octree.js +26 -20
  27. package/examples/jsm/modifiers/CurveModifier.js +11 -9
  28. package/examples/jsm/nodes/Nodes.js +15 -13
  29. package/examples/jsm/nodes/accessors/AccessorsUtils.js +16 -1
  30. package/examples/jsm/nodes/accessors/BitangentNode.js +7 -83
  31. package/examples/jsm/nodes/accessors/BufferNode.js +6 -0
  32. package/examples/jsm/nodes/accessors/CameraNode.js +12 -119
  33. package/examples/jsm/nodes/accessors/ClippingNode.js +3 -2
  34. package/examples/jsm/nodes/accessors/MaterialNode.js +109 -3
  35. package/examples/jsm/nodes/accessors/ModelNode.js +3 -0
  36. package/examples/jsm/nodes/accessors/NormalNode.js +9 -101
  37. package/examples/jsm/nodes/accessors/PositionNode.js +6 -100
  38. package/examples/jsm/nodes/accessors/ReferenceNode.js +6 -0
  39. package/examples/jsm/nodes/accessors/ReflectVectorNode.js +2 -31
  40. package/examples/jsm/nodes/accessors/StorageBufferNode.js +9 -0
  41. package/examples/jsm/nodes/accessors/{TextureStoreNode.js → StorageTextureNode.js} +19 -6
  42. package/examples/jsm/nodes/accessors/TangentNode.js +11 -97
  43. package/examples/jsm/nodes/accessors/Texture3DNode.js +100 -0
  44. package/examples/jsm/nodes/accessors/TextureNode.js +21 -3
  45. package/examples/jsm/nodes/accessors/TextureSizeNode.js +1 -1
  46. package/examples/jsm/nodes/accessors/UVNode.js +2 -46
  47. package/examples/jsm/nodes/code/FunctionNode.js +0 -8
  48. package/examples/jsm/nodes/core/AttributeNode.js +15 -3
  49. package/examples/jsm/nodes/core/ContextNode.js +6 -0
  50. package/examples/jsm/nodes/core/Node.js +23 -2
  51. package/examples/jsm/nodes/core/NodeBuilder.js +25 -18
  52. package/examples/jsm/nodes/core/NodeKeywords.js +1 -1
  53. package/examples/jsm/nodes/core/OutputStructNode.js +3 -6
  54. package/examples/jsm/nodes/core/PropertyNode.js +11 -0
  55. package/examples/jsm/nodes/core/VaryingNode.js +40 -9
  56. package/examples/jsm/nodes/display/AfterImageNode.js +14 -2
  57. package/examples/jsm/nodes/display/BumpMapNode.js +7 -26
  58. package/examples/jsm/nodes/display/FrontFacingNode.js +13 -0
  59. package/examples/jsm/nodes/display/PassNode.js +3 -1
  60. package/examples/jsm/nodes/display/ViewportDepthNode.js +1 -1
  61. package/examples/jsm/nodes/display/ViewportNode.js +5 -3
  62. package/examples/jsm/nodes/display/ViewportTextureNode.js +4 -1
  63. package/examples/jsm/nodes/functions/BSDF/BRDF_GGX.js +26 -7
  64. package/examples/jsm/nodes/functions/BSDF/D_GGX_Anisotropic.js +28 -0
  65. package/examples/jsm/nodes/functions/BSDF/V_GGX_SmithCorrelated.js +1 -3
  66. package/examples/jsm/nodes/functions/BSDF/V_GGX_SmithCorrelated_Anisotropic.js +29 -0
  67. package/examples/jsm/nodes/functions/PhongLightingModel.js +1 -1
  68. package/examples/jsm/nodes/functions/PhysicalLightingModel.js +210 -12
  69. package/examples/jsm/nodes/functions/ShadowMaskModel.js +31 -0
  70. package/examples/jsm/nodes/functions/ToonLightingModel.js +49 -0
  71. package/examples/jsm/nodes/lighting/AnalyticLightNode.js +20 -5
  72. package/examples/jsm/nodes/lighting/DirectionalLightNode.js +2 -1
  73. package/examples/jsm/nodes/lighting/EnvironmentNode.js +11 -2
  74. package/examples/jsm/nodes/lighting/IrradianceNode.js +24 -0
  75. package/examples/jsm/nodes/lighting/LightsNode.js +28 -1
  76. package/examples/jsm/nodes/lighting/PointLightNode.js +2 -1
  77. package/examples/jsm/nodes/lighting/SpotLightNode.js +2 -1
  78. package/examples/jsm/nodes/materials/Line2NodeMaterial.js +11 -7
  79. package/examples/jsm/nodes/materials/Materials.js +4 -0
  80. package/examples/jsm/nodes/materials/MeshMatcapNodeMaterial.js +52 -0
  81. package/examples/jsm/nodes/materials/MeshNormalNodeMaterial.js +0 -2
  82. package/examples/jsm/nodes/materials/MeshPhongNodeMaterial.js +2 -2
  83. package/examples/jsm/nodes/materials/MeshPhysicalNodeMaterial.js +94 -6
  84. package/examples/jsm/nodes/materials/MeshStandardNodeMaterial.js +11 -4
  85. package/examples/jsm/nodes/materials/MeshToonNodeMaterial.js +34 -0
  86. package/examples/jsm/nodes/materials/NodeMaterial.js +43 -45
  87. package/examples/jsm/nodes/materials/ShadowNodeMaterial.js +34 -0
  88. package/examples/jsm/nodes/materials/VolumeNodeMaterial.js +106 -0
  89. package/examples/jsm/nodes/math/HashNode.js +2 -2
  90. package/examples/jsm/nodes/pmrem/PMREMUtils.js +1 -1
  91. package/examples/jsm/nodes/shadernode/ShaderNode.js +57 -41
  92. package/examples/jsm/nodes/utils/ArrayElementNode.js +1 -1
  93. package/examples/jsm/nodes/utils/MatcapUVNode.js +1 -1
  94. package/examples/jsm/nodes/utils/TimerNode.js +1 -1
  95. package/examples/jsm/objects/Lensflare.js +2 -2
  96. package/examples/jsm/physics/JoltPhysics.js +281 -0
  97. package/examples/jsm/postprocessing/RenderPass.js +1 -1
  98. package/examples/jsm/postprocessing/RenderTransitionPass.js +193 -0
  99. package/examples/jsm/renderers/CSS2DRenderer.js +25 -5
  100. package/examples/jsm/renderers/CSS3DRenderer.js +24 -3
  101. package/examples/jsm/renderers/common/Attributes.js +2 -0
  102. package/examples/jsm/renderers/common/Background.js +3 -3
  103. package/examples/jsm/renderers/common/Bindings.js +17 -0
  104. package/examples/jsm/renderers/common/ChainMap.js +18 -48
  105. package/examples/jsm/renderers/common/ClippingContext.js +5 -5
  106. package/examples/jsm/renderers/common/Pipelines.js +2 -2
  107. package/examples/jsm/renderers/common/RenderBundle.js +18 -0
  108. package/examples/jsm/renderers/common/RenderBundles.js +38 -0
  109. package/examples/jsm/renderers/common/RenderList.js +10 -1
  110. package/examples/jsm/renderers/common/RenderObject.js +49 -1
  111. package/examples/jsm/renderers/common/Renderer.js +268 -25
  112. package/examples/jsm/renderers/common/Textures.js +1 -1
  113. package/examples/jsm/renderers/common/Uniform.js +1 -1
  114. package/examples/jsm/renderers/common/extras/PMREMGenerator.js +13 -17
  115. package/examples/jsm/renderers/common/nodes/NodeSampledTexture.js +18 -4
  116. package/examples/jsm/renderers/common/nodes/NodeSampler.js +6 -0
  117. package/examples/jsm/renderers/common/nodes/Nodes.js +31 -47
  118. package/examples/jsm/renderers/webgl/WebGLBackend.js +7 -21
  119. package/examples/jsm/renderers/webgl/WebGLBufferRenderer.js +5 -1
  120. package/examples/jsm/renderers/webgl/nodes/GLSLNodeBuilder.js +23 -5
  121. package/examples/jsm/renderers/webgl/utils/WebGLTextureUtils.js +114 -13
  122. package/examples/jsm/renderers/webgl/utils/WebGLUtils.js +3 -21
  123. package/examples/jsm/renderers/webgpu/WebGPUBackend.js +80 -46
  124. package/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js +85 -12
  125. package/examples/jsm/renderers/webgpu/utils/WebGPUAttributeUtils.js +4 -1
  126. package/examples/jsm/renderers/webgpu/utils/WebGPUBindingUtils.js +10 -1
  127. package/examples/jsm/renderers/webgpu/utils/WebGPUConstants.js +6 -0
  128. package/examples/jsm/renderers/webgpu/utils/WebGPUPipelineUtils.js +62 -19
  129. package/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js +62 -3
  130. package/examples/jsm/transpiler/GLSLDecoder.js +1 -1
  131. package/examples/jsm/transpiler/ShaderToyDecoder.js +1 -1
  132. package/examples/jsm/utils/BufferGeometryUtils.js +18 -16
  133. package/examples/jsm/utils/GPUStatsPanel.js +2 -0
  134. package/examples/jsm/utils/SceneUtils.js +60 -1
  135. package/examples/jsm/utils/SortUtils.js +8 -5
  136. package/examples/jsm/webxr/OculusHandModel.js +3 -2
  137. package/examples/jsm/webxr/XRHandModelFactory.js +4 -2
  138. package/package.json +3 -2
  139. package/src/animation/tracks/BooleanKeyframeTrack.js +10 -1
  140. package/src/animation/tracks/QuaternionKeyframeTrack.js +1 -2
  141. package/src/animation/tracks/StringKeyframeTrack.js +10 -1
  142. package/src/constants.js +1 -1
  143. package/src/core/Object3D.js +2 -0
  144. package/src/core/Raycaster.js +6 -2
  145. package/src/core/RenderTarget.js +8 -0
  146. package/src/extras/PMREMGenerator.js +12 -11
  147. package/src/loaders/FileLoader.js +5 -1
  148. package/src/loaders/LoaderUtils.js +3 -1
  149. package/src/loaders/MaterialLoader.js +1 -0
  150. package/src/loaders/ObjectLoader.js +1 -0
  151. package/src/materials/Material.js +2 -0
  152. package/src/materials/MeshPhysicalMaterial.js +20 -0
  153. package/src/objects/BatchedMesh.js +114 -1
  154. package/src/objects/Line.js +66 -43
  155. package/src/renderers/WebGLRenderer.js +371 -109
  156. package/src/renderers/shaders/ShaderChunk/batching_pars_vertex.glsl.js +15 -0
  157. package/src/renderers/shaders/ShaderChunk/color_pars_vertex.glsl.js +1 -1
  158. package/src/renderers/shaders/ShaderChunk/color_vertex.glsl.js +9 -1
  159. package/src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js +8 -22
  160. package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +6 -0
  161. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +1 -0
  162. package/src/renderers/shaders/ShaderChunk/morphcolor_vertex.glsl.js +1 -1
  163. package/src/renderers/shaders/ShaderChunk/morphinstance_vertex.glsl.js +1 -1
  164. package/src/renderers/shaders/ShaderChunk/morphnormal_vertex.glsl.js +3 -14
  165. package/src/renderers/shaders/ShaderChunk/morphtarget_pars_vertex.glsl.js +10 -31
  166. package/src/renderers/shaders/ShaderChunk/morphtarget_vertex.glsl.js +3 -23
  167. package/src/renderers/shaders/ShaderChunk/tonemapping_pars_fragment.glsl.js +17 -9
  168. package/src/renderers/shaders/ShaderChunk/transmission_fragment.glsl.js +1 -1
  169. package/src/renderers/shaders/ShaderChunk/transmission_pars_fragment.glsl.js +47 -13
  170. package/src/renderers/shaders/ShaderChunk.js +0 -2
  171. package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +4 -0
  172. package/src/renderers/shaders/ShaderLib.js +1 -0
  173. package/src/renderers/webgl/WebGLBackground.js +24 -3
  174. package/src/renderers/webgl/WebGLBufferRenderer.js +36 -0
  175. package/src/renderers/webgl/WebGLCapabilities.js +33 -1
  176. package/src/renderers/webgl/WebGLExtensions.js +3 -1
  177. package/src/renderers/webgl/WebGLIndexedBufferRenderer.js +36 -0
  178. package/src/renderers/webgl/WebGLLights.js +9 -12
  179. package/src/renderers/webgl/WebGLMaterials.js +7 -5
  180. package/src/renderers/webgl/WebGLMorphtargets.js +1 -2
  181. package/src/renderers/webgl/WebGLProgram.js +5 -36
  182. package/src/renderers/webgl/WebGLPrograms.js +19 -14
  183. package/src/renderers/webgl/WebGLRenderStates.js +8 -4
  184. package/src/renderers/webgl/WebGLShadowMap.js +25 -25
  185. package/src/renderers/webgl/WebGLTextures.js +206 -129
  186. package/src/renderers/webgl/WebGLUtils.js +3 -21
  187. package/src/renderers/webxr/WebXRDepthSensing.js +3 -3
  188. package/src/renderers/webxr/WebXRManager.js +8 -6
  189. package/src/textures/CompressedArrayTexture.js +14 -0
  190. package/src/textures/DataArrayTexture.js +14 -0
  191. package/src/textures/DepthTexture.js +1 -3
  192. package/src/utils.js +30 -1
  193. package/examples/jsm/renderers/webgl-legacy/nodes/GLSL1NodeBuilder.js +0 -318
  194. package/examples/jsm/renderers/webgl-legacy/nodes/SlotNode.js +0 -26
  195. package/examples/jsm/renderers/webgl-legacy/nodes/WebGLNodeBuilder.js +0 -792
  196. package/examples/jsm/renderers/webgl-legacy/nodes/WebGLNodes.js +0 -51
  197. package/src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl.js +0 -10
@@ -6,12 +6,177 @@ 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, roughness, clearcoat, clearcoatRoughness, sheen, sheenRoughness, iridescence, iridescenceIOR, iridescenceThickness } from '../core/PropertyNode.js';
10
- import { transformedNormalView, transformedClearcoatNormalView } from '../accessors/NormalNode.js';
11
- import { positionViewDirection } from '../accessors/PositionNode.js';
12
- import { tslFn, float, vec3, mat3 } from '../shadernode/ShaderNode.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
+ import { transformedNormalView, transformedClearcoatNormalView, transformedNormalWorld } from '../accessors/NormalNode.js';
11
+ import { positionViewDirection, positionWorld } from '../accessors/PositionNode.js';
12
+ import { tslFn, float, vec2, vec3, vec4, mat3, If } from '../shadernode/ShaderNode.js';
13
13
  import { cond } from '../math/CondNode.js';
14
- import { mix, smoothstep } from '../math/MathNode.js';
14
+ import { mix, normalize, refract, length, clamp, log2, log, exp, smoothstep } from '../math/MathNode.js';
15
+ import { div } from '../math/OperatorNode.js';
16
+ import { cameraPosition, cameraProjectionMatrix, cameraViewMatrix } from '../accessors/CameraNode.js';
17
+ import { modelWorldMatrix } from '../accessors/ModelNode.js';
18
+ import { viewportResolution } from '../display/ViewportNode.js';
19
+ import { viewportMipTexture } from '../display/ViewportTextureNode.js';
20
+ import { loop } from '../utils/LoopNode.js';
21
+
22
+ //
23
+ // Transmission
24
+ //
25
+
26
+ const getVolumeTransmissionRay = tslFn( ( [ n, v, thickness, ior, modelMatrix ] ) => {
27
+
28
+ // Direction of refracted light.
29
+ const refractionVector = vec3( refract( v.negate(), normalize( n ), div( 1.0, ior ) ) );
30
+
31
+ // Compute rotation-independant scaling of the model matrix.
32
+ const modelScale = vec3(
33
+ length( modelMatrix[ 0 ].xyz ),
34
+ length( modelMatrix[ 1 ].xyz ),
35
+ length( modelMatrix[ 2 ].xyz )
36
+ );
37
+
38
+ // The thickness is specified in local space.
39
+ return normalize( refractionVector ).mul( thickness.mul( modelScale ) );
40
+
41
+ } ).setLayout( {
42
+ name: 'getVolumeTransmissionRay',
43
+ type: 'vec3',
44
+ inputs: [
45
+ { name: 'n', type: 'vec3' },
46
+ { name: 'v', type: 'vec3' },
47
+ { name: 'thickness', type: 'float' },
48
+ { name: 'ior', type: 'float' },
49
+ { name: 'modelMatrix', type: 'mat4' }
50
+ ]
51
+ } );
52
+
53
+ const applyIorToRoughness = tslFn( ( [ roughness, ior ] ) => {
54
+
55
+ // Scale roughness with IOR so that an IOR of 1.0 results in no microfacet refraction and
56
+ // an IOR of 1.5 results in the default amount of microfacet refraction.
57
+ return roughness.mul( clamp( ior.mul( 2.0 ).sub( 2.0 ), 0.0, 1.0 ) );
58
+
59
+ } ).setLayout( {
60
+ name: 'applyIorToRoughness',
61
+ type: 'float',
62
+ inputs: [
63
+ { name: 'roughness', type: 'float' },
64
+ { name: 'ior', type: 'float' }
65
+ ]
66
+ } );
67
+
68
+ const singleViewportMipTexture = viewportMipTexture();
69
+
70
+ const getTransmissionSample = tslFn( ( [ fragCoord, roughness, ior ] ) => {
71
+
72
+ const transmissionSample = singleViewportMipTexture.uv( fragCoord );
73
+ //const transmissionSample = viewportMipTexture( fragCoord );
74
+
75
+ const lod = log2( float( viewportResolution.x ) ).mul( applyIorToRoughness( roughness, ior ) );
76
+
77
+ return transmissionSample.bicubic( lod );
78
+
79
+ } );
80
+
81
+ const volumeAttenuation = tslFn( ( [ transmissionDistance, attenuationColor, attenuationDistance ] ) => {
82
+
83
+ If( attenuationDistance.notEqual( 0 ), () => {
84
+
85
+ // Compute light attenuation using Beer's law.
86
+ const attenuationCoefficient = log( attenuationColor ).negate().div( attenuationDistance );
87
+ const transmittance = exp( attenuationCoefficient.negate().mul( transmissionDistance ) );
88
+
89
+ return transmittance;
90
+
91
+ } );
92
+
93
+ // Attenuation distance is +∞, i.e. the transmitted color is not attenuated at all.
94
+ return vec3( 1.0 );
95
+
96
+ } ).setLayout( {
97
+ name: 'volumeAttenuation',
98
+ type: 'vec3',
99
+ inputs: [
100
+ { name: 'transmissionDistance', type: 'float' },
101
+ { name: 'attenuationColor', type: 'vec3' },
102
+ { name: 'attenuationDistance', type: 'float' }
103
+ ]
104
+ } );
105
+
106
+ const getIBLVolumeRefraction = tslFn( ( [ n, v, roughness, diffuseColor, specularColor, specularF90, position, modelMatrix, viewMatrix, projMatrix, ior, thickness, attenuationColor, attenuationDistance, dispersion ] ) => {
107
+
108
+ let transmittedLight, transmittance;
109
+
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
+ }
161
+
162
+ const attenuatedColor = transmittance.rgb.mul( transmittedLight.rgb );
163
+ const dotNV = n.dot( v ).clamp();
164
+
165
+ // Get the specular component.
166
+ const F = vec3( EnvironmentBRDF( { // n, v, specularColor, specularF90, roughness
167
+ dotNV,
168
+ specularColor,
169
+ specularF90,
170
+ roughness
171
+ } ) );
172
+
173
+ // As less light is transmitted, the opacity should be increased. This simple approximation does a decent job
174
+ // of modulating a CSS background, and has no effect when the buffer is opaque, due to a solid object or clear color.
175
+ const transmittanceFactor = transmittance.r.add( transmittance.g, transmittance.b ).div( 3.0 );
176
+
177
+ return vec4( F.oneMinus().mul( attenuatedColor ), transmittedLight.a.oneMinus().mul( transmittanceFactor ).oneMinus() );
178
+
179
+ } );
15
180
 
16
181
  //
17
182
  // Iridescence
@@ -88,7 +253,7 @@ const evalIridescence = tslFn( ( { outsideIOR, eta2, cosTheta1, thinFilmThicknes
88
253
 
89
254
  // Second interface
90
255
  const baseIOR = Fresnel0ToIor( baseF0.clamp( 0.0, 0.9999 ) ); // guard against 1.0
91
- const R1 = IorToFresnel0( baseIOR, iridescenceIOR.vec3() );
256
+ const R1 = IorToFresnel0( baseIOR, iridescenceIOR.toVec3() );
92
257
  const R23 = F_Schlick( { f0: R1, f90: 1.0, dotVH: cosTheta2 } );
93
258
  const phi23 = vec3(
94
259
  baseIOR.x.lessThan( iridescenceIOR ).cond( Math.PI, 0.0 ),
@@ -166,19 +331,22 @@ const IBLSheenBRDF = tslFn( ( { normal, viewDir, roughness } ) => {
166
331
  } );
167
332
 
168
333
  const clearcoatF0 = vec3( 0.04 );
169
- const clearcoatF90 = vec3( 1 );
334
+ const clearcoatF90 = float( 1 );
170
335
 
171
336
  //
172
337
 
173
338
  class PhysicalLightingModel extends LightingModel {
174
339
 
175
- constructor( clearcoat = false, sheen = false, iridescence = false ) {
340
+ constructor( clearcoat = false, sheen = false, iridescence = false, anisotropy = false, transmission = false, dispersion = false ) {
176
341
 
177
342
  super();
178
343
 
179
344
  this.clearcoat = clearcoat;
180
345
  this.sheen = sheen;
181
346
  this.iridescence = iridescence;
347
+ this.anisotropy = anisotropy;
348
+ this.transmission = transmission;
349
+ this.dispersion = dispersion;
182
350
 
183
351
  this.clearcoatRadiance = null;
184
352
  this.clearcoatSpecularDirect = null;
@@ -190,7 +358,7 @@ class PhysicalLightingModel extends LightingModel {
190
358
 
191
359
  }
192
360
 
193
- start( /*context*/ ) {
361
+ start( context ) {
194
362
 
195
363
  if ( this.clearcoat === true ) {
196
364
 
@@ -223,13 +391,43 @@ class PhysicalLightingModel extends LightingModel {
223
391
 
224
392
  }
225
393
 
394
+ if ( this.transmission === true ) {
395
+
396
+ const position = positionWorld;
397
+ const v = cameraPosition.sub( positionWorld ).normalize(); // TODO: Create Node for this, same issue in MaterialX
398
+ const n = transformedNormalWorld;
399
+
400
+ context.backdrop = getIBLVolumeRefraction(
401
+ n,
402
+ v,
403
+ roughness,
404
+ diffuseColor,
405
+ specularColor,
406
+ specularF90, // specularF90
407
+ position, // positionWorld
408
+ modelWorldMatrix, // modelMatrix
409
+ cameraViewMatrix, // viewMatrix
410
+ cameraProjectionMatrix, // projMatrix
411
+ ior,
412
+ thickness,
413
+ attenuationColor,
414
+ attenuationDistance,
415
+ this.dispersion ? dispersion : null
416
+ );
417
+
418
+ context.backdropAlpha = transmission;
419
+
420
+ diffuseColor.a.mulAssign( mix( 1, context.backdrop.a, transmission ) );
421
+
422
+ }
423
+
226
424
  }
227
425
 
228
426
  // Fdez-Agüera's "Multiple-Scattering Microfacet Model for Real-Time Image Based Lighting"
229
427
  // Approximates multiscattering in order to preserve energy.
230
428
  // http://www.jcgt.org/published/0008/01/03/
231
429
 
232
- computeMultiscattering( singleScatter, multiScatter, specularF90 = float( 1 ) ) {
430
+ computeMultiscattering( singleScatter, multiScatter, specularF90 ) {
233
431
 
234
432
  const dotNV = transformedNormalView.dot( positionViewDirection ).clamp(); // @ TODO: Move to core dotNV
235
433
 
@@ -272,7 +470,7 @@ class PhysicalLightingModel extends LightingModel {
272
470
 
273
471
  reflectedLight.directDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) );
274
472
 
275
- reflectedLight.directSpecular.addAssign( irradiance.mul( BRDF_GGX( { lightDirection, f0: specularColor, f90: 1, roughness, iridescence: this.iridescence, iridescenceFresnel: this.iridescenceFresnel } ) ) );
473
+ reflectedLight.directSpecular.addAssign( irradiance.mul( BRDF_GGX( { lightDirection, f0: specularColor, f90: 1, roughness, iridescence: this.iridescence, f: this.iridescenceFresnel, USE_IRIDESCENCE: this.iridescence, USE_ANISOTROPY: this.anisotropy } ) ) );
276
474
 
277
475
  }
278
476
 
@@ -318,7 +516,7 @@ class PhysicalLightingModel extends LightingModel {
318
516
  const multiScattering = vec3().temp( 'multiScattering' );
319
517
  const cosineWeightedIrradiance = iblIrradiance.mul( 1 / Math.PI );
320
518
 
321
- this.computeMultiscattering( singleScattering, multiScattering );
519
+ this.computeMultiscattering( singleScattering, multiScattering, specularF90 );
322
520
 
323
521
  const totalScattering = singleScattering.add( multiScattering );
324
522
 
@@ -0,0 +1,31 @@
1
+ import LightingModel from '../core/LightingModel.js';
2
+ import { diffuseColor } from '../core/PropertyNode.js';
3
+ import { float } from '../shadernode/ShaderNode.js';
4
+
5
+ class ShadowMaskModel extends LightingModel {
6
+
7
+ constructor() {
8
+
9
+ super();
10
+
11
+ this.shadowNode = float( 1 ).toVar( 'shadowMask' );
12
+
13
+ }
14
+
15
+ direct( { shadowMask } ) {
16
+
17
+ this.shadowNode.mulAssign( shadowMask );
18
+
19
+ }
20
+
21
+ finish( context ) {
22
+
23
+ diffuseColor.a.mulAssign( this.shadowNode.oneMinus() );
24
+
25
+ context.outgoingLight.rgb.assign( diffuseColor.rgb ); // TODO: Optimize LightsNode to avoid this assignment
26
+
27
+ }
28
+
29
+ }
30
+
31
+ export default ShadowMaskModel;
@@ -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;
@@ -10,7 +10,7 @@ import { normalWorld } from '../accessors/NormalNode.js';
10
10
  import { WebGPUCoordinateSystem } from 'three';
11
11
  //import { add } from '../math/OperatorNode.js';
12
12
 
13
- import { Color, DepthTexture, NearestFilter, LessCompare } from 'three';
13
+ import { Color, DepthTexture, NearestFilter, LessCompare, NoToneMapping } from 'three';
14
14
 
15
15
  let overrideMaterial = null;
16
16
 
@@ -26,6 +26,7 @@ class AnalyticLightNode extends LightingNode {
26
26
 
27
27
  this.rtt = null;
28
28
  this.shadowNode = null;
29
+ this.shadowMaskNode = null;
29
30
 
30
31
  this.color = new Color();
31
32
  this._defaultColorNode = uniform( this.color );
@@ -50,6 +51,10 @@ class AnalyticLightNode extends LightingNode {
50
51
 
51
52
  setupShadow( builder ) {
52
53
 
54
+ const { object } = builder;
55
+
56
+ if ( object.receiveShadow === false ) return;
57
+
53
58
  let shadowNode = this.shadowNode;
54
59
 
55
60
  if ( shadowNode === null ) {
@@ -81,7 +86,9 @@ class AnalyticLightNode extends LightingNode {
81
86
  const bias = reference( 'bias', 'float', shadow );
82
87
  const normalBias = reference( 'normalBias', 'float', shadow );
83
88
 
84
- let shadowCoord = uniform( shadow.matrix ).mul( positionWorld.add( normalWorld.mul( normalBias ) ) );
89
+ const position = object.material.shadowPositionNode || positionWorld;
90
+
91
+ let shadowCoord = uniform( shadow.matrix ).mul( position.add( normalWorld.mul( normalBias ) ) );
85
92
  shadowCoord = shadowCoord.xyz.div( shadowCoord.w );
86
93
 
87
94
  const frustumTest = shadowCoord.x.greaterThanEqual( 0 )
@@ -145,15 +152,17 @@ class AnalyticLightNode extends LightingNode {
145
152
  textureCompare( depthTexture, shadowCoord.xy.add( vec2( 0, dy1 ) ), shadowCoord.z ),
146
153
  textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx1, dy1 ) ), shadowCoord.z )
147
154
  ).mul( 1 / 17 );
148
- */
155
+ */
149
156
  //
150
157
 
151
158
  const shadowColor = texture( rtt.texture, shadowCoord );
159
+ const shadowMaskNode = frustumTest.mix( 1, shadowNode.mix( shadowColor.a.mix( 1, shadowColor ), 1 ) );
152
160
 
153
161
  this.rtt = rtt;
154
- this.colorNode = this.colorNode.mul( frustumTest.mix( 1, shadowNode.mix( shadowColor.a.mix( 1, shadowColor ), 1 ) ) );
162
+ this.colorNode = this.colorNode.mul( shadowMaskNode );
155
163
 
156
164
  this.shadowNode = shadowNode;
165
+ this.shadowMaskNode = shadowMaskNode;
157
166
 
158
167
  //
159
168
 
@@ -173,7 +182,7 @@ class AnalyticLightNode extends LightingNode {
173
182
  updateShadow( frame ) {
174
183
 
175
184
  const { rtt, light } = this;
176
- const { renderer, scene } = frame;
185
+ const { renderer, scene, camera } = frame;
177
186
 
178
187
  const currentOverrideMaterial = scene.overrideMaterial;
179
188
 
@@ -182,7 +191,9 @@ class AnalyticLightNode extends LightingNode {
182
191
  rtt.setSize( light.shadow.mapSize.width, light.shadow.mapSize.height );
183
192
 
184
193
  light.shadow.updateMatrices( light );
194
+ light.shadow.camera.layers.mask = camera.layers.mask;
185
195
 
196
+ const currentToneMapping = renderer.toneMapping;
186
197
  const currentRenderTarget = renderer.getRenderTarget();
187
198
  const currentRenderObjectFunction = renderer.getRenderObjectFunction();
188
199
 
@@ -197,12 +208,15 @@ class AnalyticLightNode extends LightingNode {
197
208
  } );
198
209
 
199
210
  renderer.setRenderTarget( rtt );
211
+ renderer.toneMapping = NoToneMapping;
200
212
 
201
213
  renderer.render( scene, light.shadow.camera );
202
214
 
203
215
  renderer.setRenderTarget( currentRenderTarget );
204
216
  renderer.setRenderObjectFunction( currentRenderObjectFunction );
205
217
 
218
+ renderer.toneMapping = currentToneMapping;
219
+
206
220
  scene.overrideMaterial = currentOverrideMaterial;
207
221
 
208
222
  }
@@ -212,6 +226,7 @@ class AnalyticLightNode extends LightingNode {
212
226
  this.rtt.dispose();
213
227
 
214
228
  this.shadowNode = null;
229
+ this.shadowMaskNode = null;
215
230
  this.rtt = null;
216
231
 
217
232
  this.colorNode = this._defaultColorNode;
@@ -26,7 +26,8 @@ class DirectionalLightNode extends AnalyticLightNode {
26
26
  lightingModel.direct( {
27
27
  lightDirection,
28
28
  lightColor,
29
- reflectedLight
29
+ reflectedLight,
30
+ shadowMask: this.shadowMaskNode
30
31
  }, builder.stack, builder );
31
32
 
32
33
  }
@@ -8,6 +8,7 @@ import { positionViewDirection } from '../accessors/PositionNode.js';
8
8
  import { addNodeClass } from '../core/Node.js';
9
9
  import { float } from '../shadernode/ShaderNode.js';
10
10
  import { reference } from '../accessors/ReferenceNode.js';
11
+ import { transformedBentNormalView } from '../accessors/AccessorsUtils.js';
11
12
  import { pmremTexture } from '../pmrem/PMREMNode.js';
12
13
 
13
14
  const envNodeCache = new WeakMap();
@@ -44,10 +45,15 @@ class EnvironmentNode extends LightingNode {
44
45
 
45
46
  //
46
47
 
47
- const envMap = builder.material.envMap;
48
+ const { material } = builder;
49
+
50
+ const envMap = material.envMap;
48
51
  const intensity = envMap ? reference( 'envMapIntensity', 'float', builder.material ) : reference( 'environmentIntensity', 'float', builder.scene ); // @TODO: Add materialEnvIntensity in MaterialNode
49
52
 
50
- const radiance = context( envNode, createRadianceContext( roughness, transformedNormalView ) ).mul( intensity );
53
+ const useAnisotropy = material.useAnisotropy === true || material.anisotropy > 0;
54
+ const radianceNormalView = useAnisotropy ? transformedBentNormalView : transformedNormalView;
55
+
56
+ const radiance = context( envNode, createRadianceContext( roughness, radianceNormalView ) ).mul( intensity );
51
57
  const irradiance = context( envNode, createIrradianceContext( transformedNormalWorld ) ).mul( Math.PI ).mul( intensity );
52
58
 
53
59
  const isolateRadiance = cache( radiance );
@@ -85,7 +91,10 @@ const createRadianceContext = ( roughnessNode, normalViewNode ) => {
85
91
  if ( reflectVec === null ) {
86
92
 
87
93
  reflectVec = positionViewDirection.negate().reflect( normalViewNode );
94
+
95
+ // Mixing the reflection with the normal is more accurate and keeps rough objects from gathering light from behind their tangent plane.
88
96
  reflectVec = roughnessNode.mul( roughnessNode ).mix( reflectVec, normalViewNode ).normalize();
97
+
89
98
  reflectVec = reflectVec.transformDirection( cameraViewMatrix );
90
99
 
91
100
  }
@@ -0,0 +1,24 @@
1
+ import LightingNode from './LightingNode.js';
2
+ import { addNodeClass } from '../core/Node.js';
3
+
4
+ class IrradianceNode extends LightingNode {
5
+
6
+ constructor( node ) {
7
+
8
+ super();
9
+
10
+ this.node = node;
11
+
12
+ }
13
+
14
+ setup( builder ) {
15
+
16
+ builder.context.irradiance.addAssign( this.node );
17
+
18
+ }
19
+
20
+ }
21
+
22
+ export default IrradianceNode;
23
+
24
+ addNodeClass( 'IrradianceNode', IrradianceNode );
@@ -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
@@ -95,7 +112,17 @@ class LightsNode extends Node {
95
112
 
96
113
  if ( backdrop !== null ) {
97
114
 
98
- totalDiffuse = vec3( backdropAlpha !== null ? backdropAlpha.mix( totalDiffuse, backdrop ) : backdrop );
115
+ if ( backdropAlpha !== null ) {
116
+
117
+ totalDiffuse = vec3( backdropAlpha.mix( totalDiffuse, backdrop ) );
118
+
119
+ } else {
120
+
121
+ totalDiffuse = vec3( backdrop );
122
+
123
+ }
124
+
125
+ context.material.transparent = true;
99
126
 
100
127
  }
101
128
 
@@ -54,7 +54,8 @@ class PointLightNode extends AnalyticLightNode {
54
54
  lightingModel.direct( {
55
55
  lightDirection,
56
56
  lightColor,
57
- reflectedLight
57
+ reflectedLight,
58
+ shadowMask: this.shadowMaskNode
58
59
  }, builder.stack, builder );
59
60
 
60
61
  }
@@ -75,7 +75,8 @@ class SpotLightNode extends AnalyticLightNode {
75
75
  lightingModel.direct( {
76
76
  lightDirection,
77
77
  lightColor,
78
- reflectedLight
78
+ reflectedLight,
79
+ shadowMask: this.shadowMaskNode
79
80
  }, builder.stack, builder );
80
81
 
81
82
  }
@@ -43,9 +43,15 @@ class Line2NodeMaterial extends NodeMaterial {
43
43
  this.dashSizeNode = null;
44
44
  this.gapSizeNode = null;
45
45
 
46
+ this.setValues( params );
47
+
48
+ }
49
+
50
+ setup( builder ) {
51
+
46
52
  this.setupShaders();
47
53
 
48
- this.setValues( params );
54
+ super.setup( builder );
49
55
 
50
56
  }
51
57
 
@@ -141,7 +147,7 @@ class Line2NodeMaterial extends NodeMaterial {
141
147
 
142
148
  const worldPos = varyingProperty( 'vec4', 'worldPos' );
143
149
 
144
- worldPos.assign( positionGeometry.y.lessThan( 0.5 ).cond( start, end) );
150
+ worldPos.assign( positionGeometry.y.lessThan( 0.5 ).cond( start, end ) );
145
151
 
146
152
  // height offset
147
153
  const hw = materialLineWidth.mul( 0.5 );
@@ -371,8 +377,6 @@ class Line2NodeMaterial extends NodeMaterial {
371
377
 
372
378
  } )();
373
379
 
374
- this.needsUpdate = true;
375
-
376
380
  }
377
381
 
378
382
 
@@ -387,7 +391,7 @@ class Line2NodeMaterial extends NodeMaterial {
387
391
  if ( this.useWorldUnits !== value ) {
388
392
 
389
393
  this.useWorldUnits = value;
390
- this.setupShaders();
394
+ this.needsUpdate = true;
391
395
 
392
396
  }
393
397
 
@@ -405,7 +409,7 @@ class Line2NodeMaterial extends NodeMaterial {
405
409
  if ( this.useDash !== value ) {
406
410
 
407
411
  this.useDash = value;
408
- this.setupShaders();
412
+ this.needsUpdate = true;
409
413
 
410
414
  }
411
415
 
@@ -423,7 +427,7 @@ class Line2NodeMaterial extends NodeMaterial {
423
427
  if ( this.useAlphaToCoverage !== value ) {
424
428
 
425
429
  this.useAlphaToCoverage = value;
426
- this.setupShaders();
430
+ this.needsUpdate = true;
427
431
 
428
432
  }
429
433
 
@@ -12,5 +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';
19
+ export { default as ShadowNodeMaterial } from './ShadowNodeMaterial.js';
20
+ export { default as VolumeNodeMaterial } from './VolumeNodeMaterial.js';