super-three 0.157.1 → 0.158.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 (178) hide show
  1. package/README.md +6 -4
  2. package/build/three.cjs +1013 -790
  3. package/build/three.js +1013 -790
  4. package/build/three.min.js +1 -1
  5. package/build/three.module.js +1008 -791
  6. package/build/three.module.min.js +1 -1
  7. package/examples/jsm/Addons.js +290 -0
  8. package/examples/jsm/controls/FlyControls.js +26 -0
  9. package/examples/jsm/controls/OrbitControls.js +12 -1
  10. package/examples/jsm/controls/TransformControls.js +27 -11
  11. package/examples/jsm/csm/CSMShader.js +1 -1
  12. package/examples/jsm/exporters/GLTFExporter.js +72 -2
  13. package/examples/jsm/geometries/InstancedPointsGeometry.js +174 -0
  14. package/examples/jsm/geometries/SDFGeometryGenerator.js +144 -0
  15. package/examples/jsm/libs/lottie_canvas.module.js +6 -1
  16. package/examples/jsm/libs/opentype.module.js +13 -75
  17. package/examples/jsm/libs/surfaceNet.js +201 -0
  18. package/examples/jsm/loaders/GLTFLoader.js +12 -3
  19. package/examples/jsm/loaders/LUTImageLoader.js +162 -0
  20. package/examples/jsm/loaders/lwo/IFFParser.js +89 -93
  21. package/examples/jsm/materials/MeshGouraudMaterial.js +2 -0
  22. package/examples/jsm/math/Capsule.js +0 -55
  23. package/examples/jsm/math/Octree.js +70 -3
  24. package/examples/jsm/modifiers/SimplifyModifier.js +103 -11
  25. package/examples/jsm/modifiers/TessellateModifier.js +3 -3
  26. package/examples/jsm/nodes/Nodes.js +6 -6
  27. package/examples/jsm/nodes/accessors/CubeTextureNode.js +3 -3
  28. package/examples/jsm/nodes/accessors/InstanceNode.js +3 -3
  29. package/examples/jsm/nodes/accessors/InstancedPointsMaterialNode.js +21 -0
  30. package/examples/jsm/nodes/accessors/MaterialNode.js +68 -31
  31. package/examples/jsm/nodes/accessors/ModelNode.js +1 -2
  32. package/examples/jsm/nodes/accessors/MorphNode.js +5 -5
  33. package/examples/jsm/nodes/accessors/NormalNode.js +1 -1
  34. package/examples/jsm/nodes/accessors/PositionNode.js +1 -1
  35. package/examples/jsm/nodes/accessors/SkinningNode.js +13 -3
  36. package/examples/jsm/nodes/accessors/TextureNode.js +3 -3
  37. package/examples/jsm/nodes/code/FunctionNode.js +1 -1
  38. package/examples/jsm/nodes/core/AssignNode.js +72 -0
  39. package/examples/jsm/nodes/core/LightingModel.js +3 -1
  40. package/examples/jsm/nodes/core/Node.js +7 -12
  41. package/examples/jsm/nodes/core/NodeBuilder.js +126 -16
  42. package/examples/jsm/nodes/core/NodeUtils.js +4 -2
  43. package/examples/jsm/nodes/core/OutputStructNode.js +1 -1
  44. package/examples/jsm/nodes/core/ParameterNode.js +33 -0
  45. package/examples/jsm/nodes/core/PropertyNode.js +4 -10
  46. package/examples/jsm/nodes/core/StackNode.js +7 -17
  47. package/examples/jsm/nodes/core/TempNode.js +1 -1
  48. package/examples/jsm/nodes/core/VarNode.js +6 -35
  49. package/examples/jsm/nodes/core/VaryingNode.js +2 -0
  50. package/examples/jsm/nodes/display/BumpMapNode.js +35 -13
  51. package/examples/jsm/nodes/display/NormalMapNode.js +3 -1
  52. package/examples/jsm/nodes/display/ViewportNode.js +14 -4
  53. package/examples/jsm/nodes/functions/BSDF/BRDF_Sheen.js +20 -6
  54. package/examples/jsm/nodes/functions/BSDF/DFGApprox.js +8 -7
  55. package/examples/jsm/nodes/functions/BSDF/D_GGX.js +8 -3
  56. package/examples/jsm/nodes/functions/BSDF/Schlick_to_F0.js +8 -0
  57. package/examples/jsm/nodes/functions/BSDF/V_GGX_SmithCorrelated.js +8 -0
  58. package/examples/jsm/nodes/functions/PhysicalLightingModel.js +93 -43
  59. package/examples/jsm/nodes/gpgpu/ComputeNode.js +2 -2
  60. package/examples/jsm/nodes/lighting/AmbientLightNode.js +1 -1
  61. package/examples/jsm/nodes/lighting/AnalyticLightNode.js +19 -5
  62. package/examples/jsm/nodes/lighting/DirectionalLightNode.js +1 -1
  63. package/examples/jsm/nodes/lighting/EnvironmentNode.js +0 -6
  64. package/examples/jsm/nodes/lighting/LightingContextNode.js +21 -57
  65. package/examples/jsm/nodes/lighting/LightsNode.js +62 -4
  66. package/examples/jsm/nodes/lighting/PointLightNode.js +1 -1
  67. package/examples/jsm/nodes/lighting/SpotLightNode.js +1 -1
  68. package/examples/jsm/nodes/materials/InstancedPointsNodeMaterial.js +162 -0
  69. package/examples/jsm/nodes/materials/Line2NodeMaterial.js +70 -71
  70. package/examples/jsm/nodes/materials/LineDashedNodeMaterial.js +5 -5
  71. package/examples/jsm/nodes/materials/Materials.js +1 -0
  72. package/examples/jsm/nodes/materials/MeshNormalNodeMaterial.js +2 -2
  73. package/examples/jsm/nodes/materials/MeshPhongNodeMaterial.js +3 -3
  74. package/examples/jsm/nodes/materials/MeshPhysicalNodeMaterial.js +47 -20
  75. package/examples/jsm/nodes/materials/MeshStandardNodeMaterial.js +6 -6
  76. package/examples/jsm/nodes/materials/NodeMaterial.js +17 -20
  77. package/examples/jsm/nodes/materialx/lib/mx_noise.js +5 -5
  78. package/examples/jsm/nodes/math/OperatorNode.js +5 -21
  79. package/examples/jsm/nodes/shadernode/ShaderNode.js +128 -9
  80. package/examples/jsm/nodes/utils/ArrayElementNode.js +2 -0
  81. package/examples/jsm/nodes/utils/DiscardNode.js +3 -2
  82. package/examples/jsm/nodes/utils/JoinNode.js +11 -1
  83. package/examples/jsm/nodes/utils/LoopNode.js +36 -24
  84. package/examples/jsm/nodes/utils/SplitNode.js +2 -0
  85. package/examples/jsm/objects/BatchedMesh.js +586 -0
  86. package/examples/jsm/objects/InstancedPoints.js +21 -0
  87. package/examples/jsm/objects/Lensflare.js +20 -0
  88. package/examples/jsm/objects/ReflectorForSSRPass.js +3 -0
  89. package/examples/jsm/objects/Refractor.js +3 -0
  90. package/examples/jsm/objects/Sky.js +5 -3
  91. package/examples/jsm/objects/Water.js +5 -2
  92. package/examples/jsm/objects/Water2.js +3 -0
  93. package/examples/jsm/physics/AmmoPhysics.js +21 -0
  94. package/examples/jsm/physics/RapierPhysics.js +21 -0
  95. package/examples/jsm/postprocessing/BokehPass.js +3 -2
  96. package/examples/jsm/postprocessing/LUTPass.js +2 -1
  97. package/examples/jsm/postprocessing/OutputPass.js +1 -0
  98. package/examples/jsm/postprocessing/Pass.js +14 -3
  99. package/examples/jsm/postprocessing/SAOPass.js +0 -1
  100. package/examples/jsm/postprocessing/SMAAPass.js +0 -2
  101. package/examples/jsm/postprocessing/TAARenderPass.js +1 -2
  102. package/examples/jsm/renderers/CSS3DRenderer.js +3 -9
  103. package/examples/jsm/renderers/SVGRenderer.js +9 -6
  104. package/examples/jsm/renderers/common/Bindings.js +1 -1
  105. package/examples/jsm/renderers/common/RenderObject.js +8 -1
  106. package/examples/jsm/renderers/common/RenderObjects.js +1 -1
  107. package/examples/jsm/renderers/common/Textures.js +4 -36
  108. package/examples/jsm/renderers/common/nodes/Nodes.js +53 -18
  109. package/examples/jsm/renderers/webgl/WebGLBackend.js +291 -50
  110. package/examples/jsm/renderers/webgl/nodes/GLSLNodeBuilder.js +88 -12
  111. package/examples/jsm/renderers/webgl/utils/WebGLAttributeUtils.js +40 -5
  112. package/examples/jsm/renderers/webgl/utils/WebGLState.js +14 -2
  113. package/examples/jsm/renderers/webgpu/WebGPUBackend.js +2 -0
  114. package/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js +36 -4
  115. package/examples/jsm/shaders/ACESFilmicToneMappingShader.js +2 -0
  116. package/examples/jsm/shaders/AfterimageShader.js +2 -0
  117. package/examples/jsm/shaders/BasicShader.js +2 -0
  118. package/examples/jsm/shaders/BlendShader.js +2 -0
  119. package/examples/jsm/shaders/BokehShader.js +2 -0
  120. package/examples/jsm/shaders/BokehShader2.js +4 -0
  121. package/examples/jsm/shaders/BrightnessContrastShader.js +2 -0
  122. package/examples/jsm/shaders/ColorCorrectionShader.js +2 -0
  123. package/examples/jsm/shaders/DOFMipMapShader.js +2 -0
  124. package/examples/jsm/shaders/DepthLimitedBlurShader.js +5 -0
  125. package/examples/jsm/shaders/FXAAShader.js +2 -0
  126. package/examples/jsm/shaders/FilmShader.js +1 -1
  127. package/examples/jsm/shaders/FocusShader.js +2 -0
  128. package/examples/jsm/shaders/FreiChenShader.js +2 -0
  129. package/examples/jsm/shaders/GodRaysShader.js +8 -0
  130. package/examples/jsm/shaders/HalftoneShader.js +2 -0
  131. package/examples/jsm/shaders/HorizontalTiltShiftShader.js +2 -0
  132. package/examples/jsm/shaders/HueSaturationShader.js +2 -0
  133. package/examples/jsm/shaders/KaleidoShader.js +2 -0
  134. package/examples/jsm/shaders/LuminosityHighPassShader.js +2 -0
  135. package/examples/jsm/shaders/LuminosityShader.js +2 -0
  136. package/examples/jsm/shaders/MMDToonShader.js +2 -0
  137. package/examples/jsm/shaders/MirrorShader.js +2 -0
  138. package/examples/jsm/shaders/NormalMapShader.js +2 -0
  139. package/examples/jsm/shaders/OutputShader.js +4 -5
  140. package/examples/jsm/shaders/SAOShader.js +5 -0
  141. package/examples/jsm/shaders/SMAAShader.js +6 -0
  142. package/examples/jsm/shaders/SSAOShader.js +6 -0
  143. package/examples/jsm/shaders/SSRShader.js +6 -0
  144. package/examples/jsm/shaders/SobelOperatorShader.js +2 -0
  145. package/examples/jsm/shaders/SubsurfaceScatteringShader.js +2 -0
  146. package/examples/jsm/shaders/TechnicolorShader.js +2 -0
  147. package/examples/jsm/shaders/TriangleBlurShader.js +2 -0
  148. package/examples/jsm/shaders/UnpackDepthRGBAShader.js +2 -0
  149. package/examples/jsm/shaders/VelocityShader.js +2 -0
  150. package/examples/jsm/shaders/VerticalTiltShiftShader.js +2 -0
  151. package/examples/jsm/shaders/WaterRefractionShader.js +2 -0
  152. package/examples/jsm/transpiler/AST.js +231 -0
  153. package/examples/jsm/transpiler/GLSLDecoder.js +899 -0
  154. package/examples/jsm/transpiler/ShaderToyDecoder.js +49 -0
  155. package/examples/jsm/transpiler/TSLEncoder.js +611 -0
  156. package/examples/jsm/transpiler/Transpiler.js +18 -0
  157. package/examples/jsm/webxr/VRButton.js +1 -1
  158. package/examples/jsm/webxr/XRButton.js +7 -5
  159. package/examples/jsm/webxr/XREstimatedLight.js +1 -1
  160. package/package.json +4 -1
  161. package/src/constants.js +7 -1
  162. package/src/extras/PMREMGenerator.js +7 -1
  163. package/src/loaders/MaterialLoader.js +10 -2
  164. package/src/materials/Material.js +27 -13
  165. package/src/math/Box3.js +35 -18
  166. package/src/math/Vector3.js +11 -12
  167. package/src/objects/SkinnedMesh.js +6 -7
  168. package/src/renderers/WebGLRenderer.js +142 -25
  169. package/src/renderers/shaders/ShaderChunk/aomap_fragment.glsl.js +8 -0
  170. package/src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl.js +3 -2
  171. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +1 -1
  172. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +8 -6
  173. package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +2 -2
  174. package/src/renderers/webgl/WebGLProgram.js +80 -50
  175. package/src/renderers/webgl/WebGLPrograms.js +3 -0
  176. package/src/renderers/webgl/WebGLState.js +25 -4
  177. package/examples/jsm/nodes/accessors/ExtendedMaterialNode.js +0 -76
  178. package/examples/jsm/nodes/accessors/LineMaterialNode.js +0 -29
@@ -1,26 +1,45 @@
1
1
  import TempNode from '../core/TempNode.js';
2
- import { texture } from '../accessors/TextureNode.js';
3
2
  import { addNodeClass } from '../core/Node.js';
4
3
  import { uv } from '../accessors/UVNode.js';
5
4
  import { normalView } from '../accessors/NormalNode.js';
6
5
  import { positionView } from '../accessors/PositionNode.js';
7
6
  import { faceDirection } from './FrontFacingNode.js';
8
- import { tslFn, nodeProxy, vec2 } from '../shadernode/ShaderNode.js';
7
+ import { addNodeElement, tslFn, nodeProxy, float, vec2 } from '../shadernode/ShaderNode.js';
9
8
 
10
9
  // Bump Mapping Unparametrized Surfaces on the GPU by Morten S. Mikkelsen
11
10
  // https://mmikk.github.io/papers3d/mm_sfgrad_bump.pdf
12
11
 
13
12
  // Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)
14
13
 
15
- const dHdxy_fwd = tslFn( ( { bumpTexture, bumpScale } ) => {
14
+ const dHdxy_fwd = tslFn( ( { textureNode, bumpScale } ) => {
16
15
 
17
- const uvNode = uv();
16
+ let texNode = textureNode;
18
17
 
19
- const Hll = texture( bumpTexture, uvNode ).x;
18
+ if ( texNode.isTextureNode !== true ) {
19
+
20
+ texNode.traverse( ( node ) => {
21
+
22
+ if ( node.isTextureNode === true ) texNode = node;
23
+
24
+ } );
25
+
26
+ }
27
+
28
+ if ( texNode.isTextureNode !== true ) {
29
+
30
+ throw new Error( 'THREE.TSL: dHdxy_fwd() requires a TextureNode.' );
31
+
32
+ }
33
+
34
+ const Hll = float( textureNode );
35
+ const uvNode = texNode.uvNode || uv();
36
+
37
+ // It's used to preserve the same TextureNode instance
38
+ const sampleTexture = ( uv ) => textureNode.cache().context( { getUVNode: () => uv, forceUVContext: true } );
20
39
 
21
40
  return vec2(
22
- texture( bumpTexture, uvNode.add( uvNode.dFdx() ) ).x.sub( Hll ),
23
- texture( bumpTexture, uvNode.add( uvNode.dFdy() ) ).x.sub( Hll )
41
+ float( sampleTexture( uvNode.add( uvNode.dFdx() ) ) ).sub( Hll ),
42
+ float( sampleTexture( uvNode.add( uvNode.dFdy() ) ) ).sub( Hll )
24
43
  ).mul( bumpScale );
25
44
 
26
45
  } );
@@ -29,8 +48,9 @@ const perturbNormalArb = tslFn( ( inputs ) => {
29
48
 
30
49
  const { surf_pos, surf_norm, dHdxy } = inputs;
31
50
 
32
- const vSigmaX = surf_pos.dFdx();
33
- const vSigmaY = surf_pos.dFdy();
51
+ // normalize is done to ensure that the bump map looks the same regardless of the texture's scale
52
+ const vSigmaX = surf_pos.dFdx().normalize();
53
+ const vSigmaY = surf_pos.dFdy().normalize();
34
54
  const vN = surf_norm; // normalized
35
55
 
36
56
  const R1 = vSigmaY.cross( vN );
@@ -46,11 +66,11 @@ const perturbNormalArb = tslFn( ( inputs ) => {
46
66
 
47
67
  class BumpMapNode extends TempNode {
48
68
 
49
- constructor( texture, scaleNode = null ) {
69
+ constructor( textureNode, scaleNode = null ) {
50
70
 
51
71
  super( 'vec3' );
52
72
 
53
- this.texture = texture;
73
+ this.textureNode = textureNode;
54
74
  this.scaleNode = scaleNode;
55
75
 
56
76
  }
@@ -58,10 +78,10 @@ class BumpMapNode extends TempNode {
58
78
  setup() {
59
79
 
60
80
  const bumpScale = this.scaleNode !== null ? this.scaleNode : 1;
61
- const dHdxy = dHdxy_fwd( { bumpTexture: this.texture, bumpScale } );
81
+ const dHdxy = dHdxy_fwd( { textureNode: this.textureNode, bumpScale } );
62
82
 
63
83
  return perturbNormalArb( {
64
- surf_pos: positionView.negate(),
84
+ surf_pos: positionView,
65
85
  surf_norm: normalView,
66
86
  dHdxy
67
87
  } );
@@ -74,4 +94,6 @@ export default BumpMapNode;
74
94
 
75
95
  export const bumpMap = nodeProxy( BumpMapNode );
76
96
 
97
+ addNodeElement( 'bumpMap', bumpMap );
98
+
77
99
  addNodeClass( 'BumpMapNode', BumpMapNode );
@@ -8,7 +8,7 @@ import { tangentView } from '../accessors/TangentNode.js';
8
8
  import { uv } from '../accessors/UVNode.js';
9
9
  import { faceDirection } from './FrontFacingNode.js';
10
10
  import { addNodeClass } from '../core/Node.js';
11
- import { tslFn, nodeProxy, vec3, mat3 } from '../shadernode/ShaderNode.js';
11
+ import { addNodeElement, tslFn, nodeProxy, vec3, mat3 } from '../shadernode/ShaderNode.js';
12
12
 
13
13
  import { TangentSpaceNormalMap, ObjectSpaceNormalMap } from 'three';
14
14
 
@@ -103,4 +103,6 @@ export const normalMap = nodeProxy( NormalMapNode );
103
103
 
104
104
  export const TBNViewMatrix = mat3( tangentView, bitangentView, normalView );
105
105
 
106
+ addNodeElement( 'normalMap', normalMap );
107
+
106
108
  addNodeClass( 'NormalMapNode', NormalMapNode );
@@ -81,9 +81,7 @@ class ViewportNode extends Node {
81
81
  let outX = output.x;
82
82
  let outY = output.y;
83
83
 
84
- if ( /top/i.test( scope ) && builder.isFlipY() ) outY = outY.oneMinus();
85
- else if ( /bottom/i.test( scope ) && builder.isFlipY() === false ) outY = outY.oneMinus();
86
-
84
+ if ( /bottom/i.test( scope ) ) outY = outY.oneMinus();
87
85
  if ( /right/i.test( scope ) ) outX = outX.oneMinus();
88
86
 
89
87
  output = vec2( outX, outY );
@@ -98,7 +96,19 @@ class ViewportNode extends Node {
98
96
 
99
97
  if ( this.scope === ViewportNode.COORDINATE ) {
100
98
 
101
- return builder.getFragCoord();
99
+ let coord = builder.getFragCoord();
100
+
101
+ if ( builder.isFlipY() ) {
102
+
103
+ // follow webgpu standards
104
+
105
+ const resolution = viewportResolution.build( builder );
106
+
107
+ coord = `${ builder.getType( 'vec2' ) }( ${ coord }.x, ${ resolution}.y - ${ coord }.y )`;
108
+
109
+ }
110
+
111
+ return coord;
102
112
 
103
113
  }
104
114
 
@@ -4,7 +4,7 @@ import { sheen, sheenRoughness } from '../../core/PropertyNode.js';
4
4
  import { tslFn, float } from '../../shadernode/ShaderNode.js';
5
5
 
6
6
  // https://github.com/google/filament/blob/master/shaders/src/brdf.fs
7
- const D_Charlie = ( roughness, dotNH ) => {
7
+ const D_Charlie = tslFn( ( { roughness, dotNH } ) => {
8
8
 
9
9
  const alpha = roughness.pow2();
10
10
 
@@ -15,15 +15,29 @@ const D_Charlie = ( roughness, dotNH ) => {
15
15
 
16
16
  return float( 2.0 ).add( invAlpha ).mul( sin2h.pow( invAlpha.mul( 0.5 ) ) ).div( 2.0 * Math.PI );
17
17
 
18
- };
18
+ } ).setLayout( {
19
+ name: 'D_Charlie',
20
+ type: 'float',
21
+ inputs: [
22
+ { name: 'roughness', type: 'float' },
23
+ { name: 'dotNH', type: 'float' }
24
+ ]
25
+ } );
19
26
 
20
27
  // https://github.com/google/filament/blob/master/shaders/src/brdf.fs
21
- const V_Neubelt = ( dotNV, dotNL ) => {
28
+ const V_Neubelt = tslFn( ( { dotNV, dotNL } ) => {
22
29
 
23
30
  // Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886"
24
31
  return float( 1.0 ).div( float( 4.0 ).mul( dotNL.add( dotNV ).sub( dotNL.mul( dotNV ) ) ) );
25
32
 
26
- };
33
+ } ).setLayout( {
34
+ name: 'V_Neubelt',
35
+ type: 'float',
36
+ inputs: [
37
+ { name: 'dotNV', type: 'float' },
38
+ { name: 'dotNL', type: 'float' }
39
+ ]
40
+ } );
27
41
 
28
42
  const BRDF_Sheen = tslFn( ( { lightDirection } ) => {
29
43
 
@@ -33,8 +47,8 @@ const BRDF_Sheen = tslFn( ( { lightDirection } ) => {
33
47
  const dotNV = transformedNormalView.dot( positionViewDirection ).clamp();
34
48
  const dotNH = transformedNormalView.dot( halfDir ).clamp();
35
49
 
36
- const D = D_Charlie( sheenRoughness, dotNH );
37
- const V = V_Neubelt( dotNV, dotNL );
50
+ const D = D_Charlie( { roughness: sheenRoughness, dotNH } );
51
+ const V = V_Neubelt( { dotNV, dotNL } );
38
52
 
39
53
  return sheen.mul( D ).mul( V );
40
54
 
@@ -1,16 +1,10 @@
1
- import { transformedNormalView } from '../../accessors/NormalNode.js';
2
- import { positionViewDirection } from '../../accessors/PositionNode.js';
3
1
  import { tslFn, vec2, vec4 } from '../../shadernode/ShaderNode.js';
4
2
 
5
3
  // Analytical approximation of the DFG LUT, one half of the
6
4
  // split-sum approximation used in indirect specular lighting.
7
5
  // via 'environmentBRDF' from "Physically Based Shading on Mobile"
8
6
  // https://www.unrealengine.com/blog/physically-based-shading-on-mobile
9
- const DFGApprox = tslFn( ( inputs ) => {
10
-
11
- const { roughness } = inputs;
12
-
13
- const dotNV = inputs.dotNV || transformedNormalView.dot( positionViewDirection ).clamp(); // @ TODO: Move to core dotNV
7
+ const DFGApprox = tslFn( ( { roughness, dotNV } ) => {
14
8
 
15
9
  const c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );
16
10
 
@@ -24,6 +18,13 @@ const DFGApprox = tslFn( ( inputs ) => {
24
18
 
25
19
  return fab;
26
20
 
21
+ } ).setLayout( {
22
+ name: 'DFGApprox',
23
+ type: 'vec2',
24
+ inputs: [
25
+ { name: 'roughness', type: 'float' },
26
+ { name: 'dotNV', type: 'vec3' }
27
+ ]
27
28
  } );
28
29
 
29
30
  export default DFGApprox;
@@ -3,9 +3,7 @@ import { tslFn } from '../../shadernode/ShaderNode.js';
3
3
  // Microfacet Models for Refraction through Rough Surfaces - equation (33)
4
4
  // http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html
5
5
  // alpha is "roughness squared" in Disney’s reparameterization
6
- const D_GGX = tslFn( ( inputs ) => {
7
-
8
- const { alpha, dotNH } = inputs;
6
+ const D_GGX = tslFn( ( { alpha, dotNH } ) => {
9
7
 
10
8
  const a2 = alpha.pow2();
11
9
 
@@ -13,6 +11,13 @@ const D_GGX = tslFn( ( inputs ) => {
13
11
 
14
12
  return a2.div( denom.pow2() ).mul( 1 / Math.PI );
15
13
 
14
+ } ).setLayout( {
15
+ name: 'D_GGX',
16
+ type: 'float',
17
+ inputs: [
18
+ { name: 'alpha', type: 'float' },
19
+ { name: 'dotNH', type: 'float' }
20
+ ]
16
21
  } ); // validated
17
22
 
18
23
  export default D_GGX;
@@ -8,6 +8,14 @@ const Schlick_to_F0 = tslFn( ( { f, f90, dotVH } ) => {
8
8
 
9
9
  return f.sub( vec3( f90 ).mul( x5 ) ).div( x5.oneMinus() );
10
10
 
11
+ } ).setLayout( {
12
+ name: 'Schlick_to_F0',
13
+ type: 'vec3',
14
+ inputs: [
15
+ { name: 'f', type: 'vec3' },
16
+ { name: 'f90', type: 'float' },
17
+ { name: 'dotVH', type: 'float' }
18
+ ]
11
19
  } );
12
20
 
13
21
  export default Schlick_to_F0;
@@ -15,6 +15,14 @@ const V_GGX_SmithCorrelated = tslFn( ( inputs ) => {
15
15
 
16
16
  return div( 0.5, gv.add( gl ).max( EPSILON ) );
17
17
 
18
+ } ).setLayout( {
19
+ name: 'V_GGX_SmithCorrelated',
20
+ type: 'float',
21
+ inputs: [
22
+ { name: 'alpha', type: 'float' },
23
+ { name: 'dotNL', type: 'float' },
24
+ { name: 'dotNV', type: 'float' }
25
+ ]
18
26
  } ); // validated
19
27
 
20
28
  export default V_GGX_SmithCorrelated;
@@ -9,7 +9,7 @@ import LightingModel from '../core/LightingModel.js';
9
9
  import { diffuseColor, specularColor, roughness, clearcoat, clearcoatRoughness, sheen, sheenRoughness, iridescence, iridescenceIOR, iridescenceThickness } from '../core/PropertyNode.js';
10
10
  import { transformedNormalView, transformedClearcoatNormalView } from '../accessors/NormalNode.js';
11
11
  import { positionViewDirection } from '../accessors/PositionNode.js';
12
- import { float, vec3, mat3 } from '../shadernode/ShaderNode.js';
12
+ import { tslFn, float, vec3, mat3 } from '../shadernode/ShaderNode.js';
13
13
  import { cond } from '../math/CondNode.js';
14
14
  import { mix, smoothstep } from '../math/MathNode.js';
15
15
 
@@ -56,11 +56,12 @@ const evalSensitivity = ( OPD, shift ) => {
56
56
  xyz = vec3( xyz.x.add( x ), xyz.y, xyz.z ).div( 1.0685e-7 );
57
57
 
58
58
  const rgb = XYZ_TO_REC709.mul( xyz );
59
+
59
60
  return rgb;
60
61
 
61
62
  };
62
63
 
63
- const evalIridescence = ( outsideIOR, eta2, cosTheta1, thinFilmThickness, baseF0 ) => {
64
+ const evalIridescence = tslFn( ( { outsideIOR, eta2, cosTheta1, thinFilmThickness, baseF0 } ) => {
64
65
 
65
66
  // Force iridescenceIOR -> outsideIOR when thinFilmThickness -> 0.0
66
67
  const iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );
@@ -121,7 +122,17 @@ const evalIridescence = ( outsideIOR, eta2, cosTheta1, thinFilmThickness, baseF0
121
122
  // Since out of gamut colors might be produced, negative color values are clamped to 0.
122
123
  return I.max( vec3( 0.0 ) );
123
124
 
124
- };
125
+ } ).setLayout( {
126
+ name: 'evalIridescence',
127
+ type: 'vec3',
128
+ inputs: [
129
+ { name: 'outsideIOR', type: 'float' },
130
+ { name: 'eta2', type: 'float' },
131
+ { name: 'cosTheta1', type: 'float' },
132
+ { name: 'thinFilmThickness', type: 'float' },
133
+ { name: 'baseF0', type: 'vec3' }
134
+ ]
135
+ } );
125
136
 
126
137
  //
127
138
  // Sheen
@@ -130,7 +141,7 @@ const evalIridescence = ( outsideIOR, eta2, cosTheta1, thinFilmThickness, baseF0
130
141
  // This is a curve-fit approxmation to the "Charlie sheen" BRDF integrated over the hemisphere from
131
142
  // Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF". The analysis can be found
132
143
  // in the Sheen section of https://drive.google.com/file/d/1T0D1VSyR4AllqIJTQAraEIzjlb5h4FKH/view?usp=sharing
133
- const IBLSheenBRDF = ( normal, viewDir, roughness ) => {
144
+ const IBLSheenBRDF = tslFn( ( { normal, viewDir, roughness } ) => {
134
145
 
135
146
  const dotNV = normal.dot( viewDir ).saturate();
136
147
 
@@ -152,7 +163,7 @@ const IBLSheenBRDF = ( normal, viewDir, roughness ) => {
152
163
 
153
164
  return DG.mul( 1.0 / Math.PI ).saturate();
154
165
 
155
- };
166
+ } );
156
167
 
157
168
  const clearcoatF0 = vec3( 0.04 );
158
169
  const clearcoatF90 = vec3( 1 );
@@ -161,7 +172,7 @@ const clearcoatF90 = vec3( 1 );
161
172
 
162
173
  class PhysicalLightingModel extends LightingModel {
163
174
 
164
- constructor( clearcoat = true, sheen = true, iridescence = true ) {
175
+ constructor( clearcoat = false, sheen = false, iridescence = false ) {
165
176
 
166
177
  super();
167
178
 
@@ -170,45 +181,29 @@ class PhysicalLightingModel extends LightingModel {
170
181
  this.iridescence = iridescence;
171
182
 
172
183
  this.clearcoatRadiance = null;
173
- this.clearcoatSpecular = null;
174
- this.sheenSpecular = null;
184
+ this.clearcoatSpecularDirect = null;
185
+ this.clearcoatSpecularIndirect = null;
186
+ this.sheenSpecularDirect = null;
187
+ this.sheenSpecularIndirect = null;
175
188
  this.iridescenceFresnel = null;
176
189
  this.iridescenceF0 = null;
177
190
 
178
191
  }
179
192
 
180
- init( { reflectedLight } ) {
193
+ start( /*context*/ ) {
181
194
 
182
195
  if ( this.clearcoat === true ) {
183
196
 
184
- this.clearcoatRadiance = vec3().temp();
185
- this.clearcoatSpecular = vec3().temp();
186
-
187
- const dotNVcc = transformedClearcoatNormalView.dot( positionViewDirection ).clamp();
188
-
189
- const Fcc = F_Schlick( {
190
- dotVH: dotNVcc,
191
- f0: clearcoatF0,
192
- f90: clearcoatF90
193
- } );
194
-
195
- const outgoingLight = reflectedLight.total;
196
- const clearcoatLight = outgoingLight.mul( clearcoat.mul( Fcc ).oneMinus() ).add( this.clearcoatSpecular.mul( clearcoat ) );
197
-
198
- outgoingLight.assign( clearcoatLight );
197
+ this.clearcoatRadiance = vec3().temp( 'clearcoatRadiance' );
198
+ this.clearcoatSpecularDirect = vec3().temp( 'clearcoatSpecularDirect' );
199
+ this.clearcoatSpecularIndirect = vec3().temp( 'clearcoatSpecularIndirect' );
199
200
 
200
201
  }
201
202
 
202
203
  if ( this.sheen === true ) {
203
204
 
204
- this.sheenSpecular = vec3().temp();
205
-
206
- const outgoingLight = reflectedLight.total;
207
-
208
- const sheenEnergyComp = sheen.r.max( sheen.g ).max( sheen.b ).mul( 0.157 ).oneMinus();
209
- const sheenLight = outgoingLight.mul( sheenEnergyComp ).add( this.sheenSpecular );
210
-
211
- outgoingLight.assign( sheenLight );
205
+ this.sheenSpecularDirect = vec3().temp( 'sheenSpecularDirect' );
206
+ this.sheenSpecularIndirect = vec3().temp( 'sheenSpecularIndirect' );
212
207
 
213
208
  }
214
209
 
@@ -216,7 +211,14 @@ class PhysicalLightingModel extends LightingModel {
216
211
 
217
212
  const dotNVi = transformedNormalView.dot( positionViewDirection ).clamp();
218
213
 
219
- this.iridescenceFresnel = evalIridescence( float( 1.0 ), iridescenceIOR, dotNVi, iridescenceThickness, specularColor );
214
+ this.iridescenceFresnel = evalIridescence( {
215
+ outsideIOR: float( 1.0 ),
216
+ eta2: iridescenceIOR,
217
+ cosTheta1: dotNVi,
218
+ thinFilmThickness: iridescenceThickness,
219
+ baseF0: specularColor
220
+ } );
221
+
220
222
  this.iridescenceF0 = Schlick_to_F0( { f: this.iridescenceFresnel, f90: 1.0, dotVH: dotNVi } );
221
223
 
222
224
  }
@@ -229,7 +231,9 @@ class PhysicalLightingModel extends LightingModel {
229
231
 
230
232
  computeMultiscattering( singleScatter, multiScatter, specularF90 = float( 1 ) ) {
231
233
 
232
- const fab = DFGApprox( { roughness } );
234
+ const dotNV = transformedNormalView.dot( positionViewDirection ).clamp(); // @ TODO: Move to core dotNV
235
+
236
+ const fab = DFGApprox( { roughness, dotNV } );
233
237
 
234
238
  const Fr = this.iridescenceF0 ? iridescence.mix( specularColor, this.iridescenceF0 ) : specularColor;
235
239
 
@@ -253,7 +257,7 @@ class PhysicalLightingModel extends LightingModel {
253
257
 
254
258
  if ( this.sheen === true ) {
255
259
 
256
- this.sheenSpecular.addAssign( irradiance.mul( BRDF_Sheen( { lightDirection } ) ) );
260
+ this.sheenSpecularDirect.addAssign( irradiance.mul( BRDF_Sheen( { lightDirection } ) ) );
257
261
 
258
262
  }
259
263
 
@@ -262,7 +266,7 @@ class PhysicalLightingModel extends LightingModel {
262
266
  const dotNLcc = transformedClearcoatNormalView.dot( lightDirection ).clamp();
263
267
  const ccIrradiance = dotNLcc.mul( lightColor );
264
268
 
265
- this.clearcoatSpecular.addAssign( ccIrradiance.mul( BRDF_GGX( { lightDirection, f0: clearcoatF0, f90: clearcoatF90, roughness: clearcoatRoughness, normalView: transformedClearcoatNormalView } ) ) );
269
+ this.clearcoatSpecularDirect.addAssign( ccIrradiance.mul( BRDF_GGX( { lightDirection, f0: clearcoatF0, f90: clearcoatF90, roughness: clearcoatRoughness, normalView: transformedClearcoatNormalView } ) ) );
266
270
 
267
271
  }
268
272
 
@@ -278,13 +282,17 @@ class PhysicalLightingModel extends LightingModel {
278
282
 
279
283
  }
280
284
 
281
- indirectSpecular( { radiance, iblIrradiance, reflectedLight, } ) {
285
+ indirectSpecular( { radiance, iblIrradiance, reflectedLight } ) {
282
286
 
283
287
  if ( this.sheen === true ) {
284
288
 
285
- this.sheenSpecular.addAssign( iblIrradiance.mul(
289
+ this.sheenSpecularIndirect.addAssign( iblIrradiance.mul(
286
290
  sheen,
287
- IBLSheenBRDF( transformedNormalView, positionViewDirection, sheenRoughness )
291
+ IBLSheenBRDF( {
292
+ normal: transformedNormalView,
293
+ viewDir: positionViewDirection,
294
+ roughness: sheenRoughness
295
+ } )
288
296
  ) );
289
297
 
290
298
  }
@@ -300,14 +308,14 @@ class PhysicalLightingModel extends LightingModel {
300
308
  roughness: clearcoatRoughness
301
309
  } );
302
310
 
303
- this.clearcoatSpecular.addAssign( this.clearcoatRadiance.mul( clearcoatEnv ) );
311
+ this.clearcoatSpecularIndirect.addAssign( this.clearcoatRadiance.mul( clearcoatEnv ) );
304
312
 
305
313
  }
306
314
 
307
315
  // Both indirect specular and indirect diffuse light accumulate here
308
316
 
309
- const singleScattering = vec3().temp();
310
- const multiScattering = vec3().temp();
317
+ const singleScattering = vec3().temp( 'singleScattering' );
318
+ const multiScattering = vec3().temp( 'multiScattering' );
311
319
  const cosineWeightedIrradiance = iblIrradiance.mul( 1 / Math.PI );
312
320
 
313
321
  this.computeMultiscattering( singleScattering, multiScattering );
@@ -332,12 +340,54 @@ class PhysicalLightingModel extends LightingModel {
332
340
 
333
341
  const aoNode = ambientOcclusion.sub( aoNV.pow( aoExp ).oneMinus() ).clamp();
334
342
 
335
- reflectedLight.indirectDiffuse.mulAssign( ambientOcclusion );
343
+ if ( this.clearcoat === true ) {
344
+
345
+ this.clearcoatSpecularIndirect.mulAssign( ambientOcclusion );
346
+
347
+ }
348
+
349
+ if ( this.sheen === true ) {
350
+
351
+ this.sheenSpecularIndirect.mulAssign( ambientOcclusion );
336
352
 
353
+ }
354
+
355
+ reflectedLight.indirectDiffuse.mulAssign( ambientOcclusion );
337
356
  reflectedLight.indirectSpecular.mulAssign( aoNode );
338
357
 
339
358
  }
340
359
 
360
+ finish( context ) {
361
+
362
+ const { outgoingLight } = context;
363
+
364
+ if ( this.clearcoat === true ) {
365
+
366
+ const dotNVcc = transformedClearcoatNormalView.dot( positionViewDirection ).clamp();
367
+
368
+ const Fcc = F_Schlick( {
369
+ dotVH: dotNVcc,
370
+ f0: clearcoatF0,
371
+ f90: clearcoatF90
372
+ } );
373
+
374
+ const clearcoatLight = outgoingLight.mul( clearcoat.mul( Fcc ).oneMinus() ).add( this.clearcoatSpecularDirect, this.clearcoatSpecularIndirect ).mul( clearcoat );
375
+
376
+ outgoingLight.assign( clearcoatLight );
377
+
378
+ }
379
+
380
+ if ( this.sheen === true ) {
381
+
382
+ const sheenEnergyComp = sheen.r.max( sheen.g ).max( sheen.b ).mul( 0.157 ).oneMinus();
383
+ const sheenLight = outgoingLight.mul( sheenEnergyComp ).add( this.sheenSpecularDirect, this.sheenSpecularIndirect );
384
+
385
+ outgoingLight.assign( sheenLight );
386
+
387
+ }
388
+
389
+ }
390
+
341
391
  }
342
392
 
343
393
  export default PhysicalLightingModel;
@@ -17,7 +17,7 @@ class ComputeNode extends Node {
17
17
  this.dispatchCount = 0;
18
18
 
19
19
  this.version = 1;
20
- this.updateType = NodeUpdateType.OBJECT;
20
+ this.updateBeforeType = NodeUpdateType.OBJECT;
21
21
 
22
22
  this.updateDispatchCount();
23
23
 
@@ -50,7 +50,7 @@ class ComputeNode extends Node {
50
50
 
51
51
  onInit() { }
52
52
 
53
- update( { renderer } ) {
53
+ updateBefore( { renderer } ) {
54
54
 
55
55
  renderer.compute( this );
56
56
 
@@ -14,7 +14,7 @@ class AmbientLightNode extends AnalyticLightNode {
14
14
 
15
15
  setup( { context } ) {
16
16
 
17
- context.irradiance.addAssign( this.colorNode );
17
+ context.irradiance.addAssign(this.colorNode );
18
18
 
19
19
  }
20
20
 
@@ -7,6 +7,7 @@ import { reference } from '../accessors/ReferenceNode.js';
7
7
  import { texture } from '../accessors/TextureNode.js';
8
8
  import { positionWorld } from '../accessors/PositionNode.js';
9
9
  import { normalWorld } from '../accessors/NormalNode.js';
10
+ import { WebGPUCoordinateSystem } from 'three';
10
11
  //import { add } from '../math/OperatorNode.js';
11
12
 
12
13
  import { Color, DepthTexture, NearestFilter, LessCompare } from 'three';
@@ -73,11 +74,24 @@ class AnalyticLightNode extends LightingNode {
73
74
  .and( shadowCoord.y.lessThanEqual( 1 ) )
74
75
  .and( shadowCoord.z.lessThanEqual( 1 ) );
75
76
 
76
- shadowCoord = vec3(
77
- shadowCoord.x,
78
- shadowCoord.y.oneMinus(), // WebGPU: Flip Y
79
- shadowCoord.z.add( bias ).mul( 2 ).sub( 1 ) // WebGPU: Convertion [ 0, 1 ] to [ - 1, 1 ]
80
- );
77
+
78
+ if ( builder.renderer.coordinateSystem === WebGPUCoordinateSystem ) {
79
+
80
+ shadowCoord = vec3(
81
+ shadowCoord.x,
82
+ shadowCoord.y.oneMinus(), // WebGPU: Flip Y
83
+ shadowCoord.z.add( bias ).mul( 2 ).sub( 1 ) // WebGPU: Convertion [ 0, 1 ] to [ - 1, 1 ]
84
+ );
85
+
86
+ } else {
87
+
88
+ shadowCoord = vec3(
89
+ shadowCoord.x,
90
+ shadowCoord.y,
91
+ shadowCoord.z.add( bias )
92
+ );
93
+
94
+ }
81
95
 
82
96
  const textureCompare = ( depthTexture, shadowCoord, compare ) => texture( depthTexture, shadowCoord ).compare( compare );
83
97
  //const textureCompare = ( depthTexture, shadowCoord, compare ) => compare.step( texture( depthTexture, shadowCoord ) );
@@ -27,7 +27,7 @@ class DirectionalLightNode extends AnalyticLightNode {
27
27
  lightDirection,
28
28
  lightColor,
29
29
  reflectedLight
30
- } );
30
+ }, builder.stack, builder );
31
31
 
32
32
  }
33
33
 
@@ -27,7 +27,6 @@ class EnvironmentNode extends LightingNode {
27
27
  setup( builder ) {
28
28
 
29
29
  let envNode = this.envNode;
30
- const properties = builder.getNodeProperties( this );
31
30
 
32
31
  if ( envNode.isTextureNode && envNode.value.isCubeTexture !== true ) {
33
32
 
@@ -79,11 +78,6 @@ class EnvironmentNode extends LightingNode {
79
78
 
80
79
  }
81
80
 
82
- //
83
-
84
- properties.radiance = isolateRadiance;
85
- properties.irradiance = irradiance;
86
-
87
81
  }
88
82
 
89
83
  }