super-three 0.177.0 → 0.179.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 (211) hide show
  1. package/README.md +1 -1
  2. package/build/three.cjs +959 -231
  3. package/build/three.core.js +751 -170
  4. package/build/three.core.min.js +1 -1
  5. package/build/three.module.js +210 -64
  6. package/build/three.module.min.js +1 -1
  7. package/build/three.tsl.js +78 -29
  8. package/build/three.tsl.min.js +1 -1
  9. package/build/three.webgpu.js +3269 -1545
  10. package/build/three.webgpu.min.js +1 -1
  11. package/build/three.webgpu.nodes.js +3093 -1545
  12. package/build/three.webgpu.nodes.min.js +1 -1
  13. package/examples/jsm/Addons.js +1 -2
  14. package/examples/jsm/capabilities/WebGL.js +0 -27
  15. package/examples/jsm/capabilities/WebGPU.js +1 -1
  16. package/examples/jsm/controls/ArcballControls.js +1 -1
  17. package/examples/jsm/controls/TransformControls.js +61 -14
  18. package/examples/jsm/csm/CSMShadowNode.js +4 -4
  19. package/examples/jsm/environments/RoomEnvironment.js +8 -3
  20. package/examples/jsm/exporters/USDZExporter.js +676 -299
  21. package/examples/jsm/geometries/RoundedBoxGeometry.js +47 -8
  22. package/examples/jsm/interactive/HTMLMesh.js +5 -3
  23. package/examples/jsm/libs/meshopt_decoder.module.js +75 -58
  24. package/examples/jsm/lights/LightProbeGenerator.js +14 -3
  25. package/examples/jsm/loaders/ColladaLoader.js +1 -1
  26. package/examples/jsm/loaders/EXRLoader.js +210 -22
  27. package/examples/jsm/loaders/FBXLoader.js +2 -2
  28. package/examples/jsm/loaders/MaterialXLoader.js +212 -30
  29. package/examples/jsm/loaders/TTFLoader.js +13 -1
  30. package/examples/jsm/loaders/USDLoader.js +219 -0
  31. package/examples/jsm/loaders/USDZLoader.js +4 -892
  32. package/examples/jsm/loaders/usd/USDAParser.js +741 -0
  33. package/examples/jsm/loaders/usd/USDCParser.js +17 -0
  34. package/examples/jsm/objects/LensflareMesh.js +3 -3
  35. package/examples/jsm/objects/SkyMesh.js +2 -2
  36. package/examples/jsm/physics/RapierPhysics.js +95 -16
  37. package/examples/jsm/postprocessing/GTAOPass.js +10 -9
  38. package/examples/jsm/postprocessing/OutlinePass.js +17 -17
  39. package/examples/jsm/postprocessing/SSAOPass.js +10 -9
  40. package/examples/jsm/shaders/UnpackDepthRGBAShader.js +11 -2
  41. package/examples/jsm/transpiler/AST.js +381 -30
  42. package/examples/jsm/transpiler/GLSLDecoder.js +226 -86
  43. package/examples/jsm/transpiler/Linker.js +327 -0
  44. package/examples/jsm/transpiler/TSLEncoder.js +197 -92
  45. package/examples/jsm/transpiler/Transpiler.js +17 -1
  46. package/examples/jsm/transpiler/TranspilerUtils.js +29 -0
  47. package/examples/jsm/transpiler/WGSLEncoder.js +788 -0
  48. package/examples/jsm/tsl/display/BloomNode.js +8 -7
  49. package/examples/jsm/tsl/display/ChromaticAberrationNode.js +206 -0
  50. package/examples/jsm/tsl/display/GaussianBlurNode.js +8 -10
  51. package/examples/jsm/tsl/display/SSAAPassNode.js +2 -2
  52. package/examples/jsm/tsl/display/{TRAAPassNode.js → TRAANode.js} +181 -172
  53. package/examples/jsm/tsl/display/hashBlur.js +3 -3
  54. package/examples/jsm/tsl/lighting/TiledLightsNode.js +1 -1
  55. package/package.json +1 -1
  56. package/src/Three.Core.js +1 -0
  57. package/src/Three.TSL.js +77 -28
  58. package/src/Three.WebGPU.js +2 -0
  59. package/src/animation/KeyframeTrack.js +1 -1
  60. package/src/animation/tracks/BooleanKeyframeTrack.js +1 -1
  61. package/src/animation/tracks/StringKeyframeTrack.js +1 -1
  62. package/src/cameras/Camera.js +14 -0
  63. package/src/cameras/OrthographicCamera.js +1 -1
  64. package/src/cameras/PerspectiveCamera.js +1 -1
  65. package/src/constants.js +3 -3
  66. package/src/core/BufferAttribute.js +3 -3
  67. package/src/core/Clock.js +2 -8
  68. package/src/core/GLBufferAttribute.js +13 -1
  69. package/src/core/Object3D.js +1 -1
  70. package/{examples/jsm/misc → src/core}/Timer.js +4 -42
  71. package/src/extras/PMREMGenerator.js +11 -0
  72. package/src/extras/core/Path.js +22 -22
  73. package/src/helpers/CameraHelper.js +41 -11
  74. package/src/helpers/SkeletonHelper.js +35 -6
  75. package/src/lights/LightShadow.js +21 -8
  76. package/src/lights/PointLightShadow.js +1 -1
  77. package/src/loaders/FileLoader.js +27 -4
  78. package/src/loaders/ImageBitmapLoader.js +27 -4
  79. package/src/loaders/ImageLoader.js +55 -8
  80. package/src/loaders/Loader.js +14 -0
  81. package/src/loaders/LoadingManager.js +23 -0
  82. package/src/materials/MeshBasicMaterial.js +1 -1
  83. package/src/materials/nodes/Line2NodeMaterial.js +0 -8
  84. package/src/materials/nodes/MeshBasicNodeMaterial.js +4 -3
  85. package/src/materials/nodes/MeshMatcapNodeMaterial.js +1 -1
  86. package/src/materials/nodes/MeshNormalNodeMaterial.js +2 -2
  87. package/src/materials/nodes/MeshPhysicalNodeMaterial.js +2 -1
  88. package/src/materials/nodes/MeshSSSNodeMaterial.js +2 -2
  89. package/src/materials/nodes/NodeMaterial.js +28 -5
  90. package/src/materials/nodes/PointsNodeMaterial.js +5 -0
  91. package/src/materials/nodes/manager/NodeMaterialObserver.js +87 -2
  92. package/src/math/Frustum.js +25 -9
  93. package/src/math/FrustumArray.js +10 -5
  94. package/src/math/Line3.js +129 -2
  95. package/src/math/Matrix4.js +48 -27
  96. package/src/math/Quaternion.js +1 -1
  97. package/src/math/Spherical.js +2 -2
  98. package/src/nodes/Nodes.js +2 -3
  99. package/src/nodes/TSL.js +5 -3
  100. package/src/nodes/accessors/AccessorsUtils.js +7 -8
  101. package/src/nodes/accessors/Bitangent.js +31 -25
  102. package/src/nodes/accessors/Camera.js +12 -12
  103. package/src/nodes/accessors/Normal.js +95 -29
  104. package/src/nodes/accessors/Object3DNode.js +1 -1
  105. package/src/nodes/accessors/Position.js +7 -7
  106. package/src/nodes/accessors/ReferenceNode.js +18 -3
  107. package/src/nodes/accessors/ReflectVector.js +3 -3
  108. package/src/nodes/accessors/SceneNode.js +1 -1
  109. package/src/nodes/accessors/StorageTextureNode.js +1 -1
  110. package/src/nodes/accessors/Tangent.js +25 -17
  111. package/src/nodes/accessors/TangentUtils.js +46 -0
  112. package/src/nodes/accessors/TextureBicubic.js +21 -3
  113. package/src/nodes/accessors/TextureNode.js +12 -0
  114. package/src/nodes/accessors/UniformArrayNode.js +0 -16
  115. package/src/nodes/core/ArrayNode.js +12 -0
  116. package/src/nodes/core/AssignNode.js +3 -0
  117. package/src/nodes/core/CacheNode.js +0 -14
  118. package/src/nodes/core/ContextNode.js +20 -1
  119. package/src/nodes/core/Node.js +15 -3
  120. package/src/nodes/core/NodeBuilder.js +228 -92
  121. package/src/nodes/core/NodeUtils.js +4 -1
  122. package/src/nodes/core/StackNode.js +49 -29
  123. package/src/nodes/core/SubBuildNode.js +89 -0
  124. package/src/nodes/core/UniformNode.js +63 -5
  125. package/src/nodes/core/VarNode.js +91 -2
  126. package/src/nodes/core/VaryingNode.js +6 -4
  127. package/src/nodes/display/BlendModes.js +2 -2
  128. package/src/nodes/display/FrontFacingNode.js +34 -2
  129. package/src/nodes/display/NormalMapNode.js +19 -50
  130. package/src/nodes/display/PassNode.js +157 -9
  131. package/src/nodes/display/ScreenNode.js +0 -26
  132. package/src/nodes/display/ViewportTextureNode.js +67 -7
  133. package/src/nodes/functions/BSDF/BRDF_GGX.js +2 -6
  134. package/src/nodes/functions/BSDF/BRDF_Sheen.js +4 -4
  135. package/src/nodes/functions/PhongLightingModel.js +3 -3
  136. package/src/nodes/functions/PhysicalLightingModel.js +16 -16
  137. package/src/nodes/functions/material/getGeometryRoughness.js +2 -2
  138. package/src/nodes/gpgpu/AtomicFunctionNode.js +1 -1
  139. package/src/nodes/gpgpu/ComputeNode.js +67 -23
  140. package/src/nodes/gpgpu/WorkgroupInfoNode.js +28 -3
  141. package/src/nodes/lighting/EnvironmentNode.js +5 -5
  142. package/src/nodes/lighting/LightsNode.js +4 -4
  143. package/src/nodes/lighting/ProjectorLightNode.js +19 -6
  144. package/src/nodes/lighting/ShadowFilterNode.js +1 -1
  145. package/src/nodes/lighting/ShadowNode.js +2 -2
  146. package/src/nodes/materialx/MaterialXNodes.js +131 -2
  147. package/src/nodes/materialx/lib/mx_noise.js +165 -1
  148. package/src/nodes/math/ConditionalNode.js +1 -20
  149. package/src/nodes/math/MathNode.js +90 -55
  150. package/src/nodes/math/OperatorNode.js +22 -39
  151. package/src/nodes/tsl/TSLBase.js +1 -0
  152. package/src/nodes/tsl/TSLCore.js +114 -55
  153. package/src/nodes/utils/DebugNode.js +1 -1
  154. package/src/nodes/utils/EquirectUV.js +27 -0
  155. package/src/nodes/utils/EventNode.js +83 -0
  156. package/src/nodes/utils/LoopNode.js +0 -17
  157. package/src/nodes/utils/MatcapUV.js +22 -0
  158. package/src/nodes/utils/RTTNode.js +22 -5
  159. package/src/nodes/utils/ReflectorNode.js +11 -4
  160. package/src/nodes/utils/SampleNode.js +81 -0
  161. package/src/nodes/utils/TriplanarTextures.js +65 -0
  162. package/src/objects/BatchedMesh.js +4 -2
  163. package/src/renderers/WebGLRenderer.js +26 -24
  164. package/src/renderers/common/Background.js +2 -2
  165. package/src/renderers/common/Bindings.js +19 -18
  166. package/src/renderers/common/Color4.js +2 -2
  167. package/src/renderers/common/CubeRenderTarget.js +1 -1
  168. package/src/renderers/common/PostProcessing.js +60 -5
  169. package/src/renderers/common/RenderObject.js +68 -3
  170. package/src/renderers/common/Renderer.js +19 -16
  171. package/src/renderers/common/SampledTexture.js +3 -71
  172. package/src/renderers/common/Sampler.js +79 -0
  173. package/src/renderers/common/Storage3DTexture.js +100 -0
  174. package/src/renderers/common/StorageArrayTexture.js +84 -0
  175. package/src/renderers/common/StorageTexture.js +19 -0
  176. package/src/renderers/common/Textures.js +19 -3
  177. package/src/renderers/common/XRManager.js +31 -12
  178. package/src/renderers/common/XRRenderTarget.js +21 -4
  179. package/src/renderers/common/extras/PMREMGenerator.js +1 -1
  180. package/src/renderers/common/nodes/NodeSampledTexture.js +0 -12
  181. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +20 -2
  182. package/src/renderers/shaders/ShaderLib/depth.glsl.js +11 -2
  183. package/src/renderers/webgl/WebGLAttributes.js +4 -0
  184. package/src/renderers/webgl/WebGLCapabilities.js +2 -2
  185. package/src/renderers/webgl/WebGLProgram.js +12 -6
  186. package/src/renderers/webgl/WebGLPrograms.js +6 -4
  187. package/src/renderers/webgl/WebGLShadowMap.js +11 -1
  188. package/src/renderers/webgl/WebGLState.js +4 -4
  189. package/src/renderers/webgl/WebGLTextures.js +19 -7
  190. package/src/renderers/webgl-fallback/WebGLBackend.js +103 -72
  191. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +3 -5
  192. package/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js +4 -0
  193. package/src/renderers/webgl-fallback/utils/WebGLState.js +4 -4
  194. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +2 -0
  195. package/src/renderers/webgpu/WebGPUBackend.js +63 -16
  196. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +64 -79
  197. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +6 -0
  198. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +45 -31
  199. package/src/renderers/webgpu/utils/WebGPUConstants.js +7 -1
  200. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +5 -5
  201. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +12 -65
  202. package/src/renderers/webgpu/utils/WebGPUUtils.js +2 -17
  203. package/src/renderers/webxr/WebXRDepthSensing.js +6 -10
  204. package/src/renderers/webxr/WebXRManager.js +68 -6
  205. package/src/textures/ExternalTexture.js +45 -0
  206. package/src/textures/FramebufferTexture.js +2 -2
  207. package/src/textures/Source.js +11 -1
  208. package/src/textures/VideoTexture.js +30 -2
  209. package/src/nodes/utils/EquirectUVNode.js +0 -65
  210. package/src/nodes/utils/MatcapUVNode.js +0 -49
  211. package/src/nodes/utils/TriplanarTexturesNode.js +0 -148
@@ -2,6 +2,7 @@ import { REVISION } from 'three/webgpu';
2
2
  import * as TSL from 'three/tsl';
3
3
 
4
4
  import { VariableDeclaration, Accessor } from './AST.js';
5
+ import { isExpression, isPrimitive } from './TranspilerUtils.js';
5
6
 
6
7
  const opLib = {
7
8
  '=': 'assign',
@@ -47,8 +48,6 @@ const unaryLib = {
47
48
 
48
49
  const textureLookupFunctions = [ 'texture', 'texture2D', 'texture3D', 'textureCube', 'textureLod', 'texelFetch', 'textureGrad' ];
49
50
 
50
- const isPrimitive = ( value ) => /^(true|false|-?(\d|\.\d))/.test( value );
51
-
52
51
  class TSLEncoder {
53
52
 
54
53
  constructor() {
@@ -58,13 +57,9 @@ class TSLEncoder {
58
57
  this.global = new Set();
59
58
  this.overloadings = new Map();
60
59
  this.iife = false;
61
- this.uniqueNames = false;
62
60
  this.reference = false;
63
61
 
64
- this._currentVariable = null;
65
-
66
- this._currentProperties = {};
67
- this._lastStatement = null;
62
+ this.block = null;
68
63
 
69
64
  }
70
65
 
@@ -74,7 +69,7 @@ class TSLEncoder {
74
69
 
75
70
  name = name.split( '.' )[ 0 ];
76
71
 
77
- if ( TSL[ name ] !== undefined && this.global.has( name ) === false && this._currentProperties[ name ] === undefined ) {
72
+ if ( TSL[ name ] !== undefined && this.global.has( name ) === false ) {
78
73
 
79
74
  this.imports.add( name );
80
75
 
@@ -132,29 +127,23 @@ class TSLEncoder {
132
127
 
133
128
  }
134
129
 
135
- emitExpression( node ) {
130
+ emitExpression( node, output = null ) {
136
131
 
137
132
  let code;
138
133
 
139
134
  if ( node.isAccessor ) {
140
135
 
141
- this.addImport( node.property );
136
+ if ( node.linker.reference === null ) {
142
137
 
143
- code = node.property;
144
-
145
- } else if ( node.isNumber ) {
138
+ this.addImport( node.property );
146
139
 
147
- if ( node.type === 'int' || node.type === 'uint' ) {
148
-
149
- code = node.type + '( ' + node.value + ' )';
150
-
151
- this.addImport( node.type );
140
+ }
152
141
 
153
- } else {
142
+ code = node.property;
154
143
 
155
- code = node.value;
144
+ } else if ( node.isNumber ) {
156
145
 
157
- }
146
+ code = node.value;
158
147
 
159
148
  } else if ( node.isString ) {
160
149
 
@@ -164,10 +153,10 @@ class TSLEncoder {
164
153
 
165
154
  const opFn = opLib[ node.type ] || node.type;
166
155
 
167
- const left = this.emitExpression( node.left );
168
- const right = this.emitExpression( node.right );
156
+ const left = this.emitExpression( node.left, output );
157
+ const right = this.emitExpression( node.right, output );
169
158
 
170
- if ( isPrimitive( left ) && isPrimitive( right ) ) {
159
+ if ( node.isNumericExpression ) {
171
160
 
172
161
  return left + ' ' + node.type + ' ' + right;
173
162
 
@@ -253,6 +242,18 @@ class TSLEncoder {
253
242
 
254
243
  code = 'Discard()';
255
244
 
245
+ } else if ( node.isBreak ) {
246
+
247
+ this.addImport( 'Break' );
248
+
249
+ code = 'Break()';
250
+
251
+ } else if ( node.isContinue ) {
252
+
253
+ this.addImport( 'Continue' );
254
+
255
+ code = 'Continue()';
256
+
256
257
  } else if ( node.isAccessorElements ) {
257
258
 
258
259
  code = this.emitExpression( node.object );
@@ -293,6 +294,14 @@ class TSLEncoder {
293
294
 
294
295
  code = this.emitFor( node );
295
296
 
297
+ } else if ( node.isWhile ) {
298
+
299
+ code = this.emitWhile( node );
300
+
301
+ } else if ( node.isSwitch ) {
302
+
303
+ code = this.emitSwitch( node );
304
+
296
305
  } else if ( node.isVariableDeclaration ) {
297
306
 
298
307
  code = this.emitVariables( node );
@@ -313,26 +322,23 @@ class TSLEncoder {
313
322
 
314
323
  code = this.emitConditional( node );
315
324
 
316
- } else if ( node.isUnary && node.expression.isNumber ) {
325
+ } else if ( node.isUnary && node.expression.isNumber && node.type === '-' ) {
317
326
 
318
- code = node.expression.type + '( ' + node.type + ' ' + node.expression.value + ' )';
327
+ code = '- ' + node.expression.value;
319
328
 
320
- this.addImport( node.expression.type );
329
+ if ( node.expression.type !== 'float' ) {
321
330
 
322
- } else if ( node.isUnary ) {
323
-
324
- let type = unaryLib[ node.type ];
331
+ code = node.expression.type + '( ' + code + ' )';
325
332
 
326
- if ( node.type === '++' || node.type === '--' ) {
333
+ this.addImport( node.expression.type );
327
334
 
328
- if ( this._currentVariable === null ) {
335
+ }
329
336
 
330
- // optimize increment/decrement operator
331
- // to avoid creating a new variable
337
+ } else if ( node.isUnary ) {
332
338
 
333
- node.after = false;
339
+ let type = unaryLib[ node.type ];
334
340
 
335
- }
341
+ if ( node.hasAssignment ) {
336
342
 
337
343
  if ( node.after === false ) {
338
344
 
@@ -370,23 +376,34 @@ class TSLEncoder {
370
376
 
371
377
  emitBody( body ) {
372
378
 
373
- this.setLastStatement( null );
374
-
375
379
  let code = '';
376
380
 
377
381
  this.tab += '\t';
378
382
 
379
383
  for ( const statement of body ) {
380
384
 
381
- code += this.emitExtraLine( statement );
385
+ code += this.emitExtraLine( statement, body );
386
+
387
+ if ( statement.isComment ) {
388
+
389
+ code += this.emitComment( statement, body );
390
+
391
+ continue;
392
+
393
+ }
394
+
395
+ if ( this.block && this.block.isSwitchCase ) {
396
+
397
+ if ( statement.isBreak ) continue; // skip break statements in switch cases
398
+
399
+ }
400
+
382
401
  code += this.tab + this.emitExpression( statement );
383
402
 
384
403
  if ( code.slice( - 1 ) !== '}' ) code += ';';
385
404
 
386
405
  code += '\n';
387
406
 
388
- this.setLastStatement( statement );
389
-
390
407
  }
391
408
 
392
409
  code = code.slice( 0, - 1 ); // remove the last extra line
@@ -507,6 +524,63 @@ ${ this.tab }} )`;
507
524
 
508
525
  }
509
526
 
527
+
528
+ emitSwitch( switchNode ) {
529
+
530
+ const discriminantString = this.emitExpression( switchNode.discriminant );
531
+
532
+ this.tab += '\t';
533
+
534
+ let switchString = `Switch( ${ discriminantString } )\n${ this.tab }`;
535
+
536
+ const previousBlock = this.block;
537
+
538
+ for ( const switchCase of switchNode.cases ) {
539
+
540
+ this.block = switchCase;
541
+
542
+ let caseBodyString;
543
+
544
+ if ( ! switchCase.isDefault ) {
545
+
546
+ const caseConditions = [ ];
547
+
548
+ for ( const condition of switchCase.conditions ) {
549
+
550
+ caseConditions.push( this.emitExpression( condition ) );
551
+
552
+ }
553
+
554
+ caseBodyString = this.emitBody( switchCase.body );
555
+
556
+ switchString += `.Case( ${ caseConditions.join( ', ' ) }, `;
557
+
558
+ } else {
559
+
560
+ caseBodyString = this.emitBody( switchCase.body );
561
+
562
+ switchString += '.Default( ';
563
+
564
+ }
565
+
566
+ switchString += `() => {
567
+
568
+ ${ caseBodyString }
569
+
570
+ ${ this.tab }} )`;
571
+
572
+ }
573
+
574
+ this.block = previousBlock;
575
+
576
+ this.tab = this.tab.slice( 0, - 1 );
577
+
578
+ this.imports.add( 'Switch' );
579
+
580
+ return switchString;
581
+
582
+ }
583
+
510
584
  emitFor( node ) {
511
585
 
512
586
  const { initialization, condition, afterthought } = node;
@@ -554,38 +628,58 @@ ${ this.tab }} )`;
554
628
 
555
629
  }
556
630
 
557
- emitVariables( node, isRoot = true ) {
631
+ emitWhile( node ) {
558
632
 
559
- const { name, type, value, next } = node;
633
+ const condition = this.emitExpression( node.condition );
634
+
635
+ let whileStr = `Loop( ${ condition }, () => {\n\n`;
636
+
637
+ whileStr += this.emitBody( node.body ) + '\n\n';
638
+
639
+ whileStr += this.tab + '} )';
560
640
 
561
- this._currentVariable = node;
641
+ this.imports.add( 'Loop' );
642
+
643
+ return whileStr;
562
644
 
563
- const valueStr = value ? this.emitExpression( value ) : '';
645
+ }
646
+
647
+ emitVariables( node, isRoot = true ) {
648
+
649
+ const { name, type, value, next } = node;
564
650
 
565
651
  let varStr = isRoot ? 'const ' : '';
566
652
  varStr += name;
567
653
 
568
654
  if ( value ) {
569
655
 
570
- if ( value.isFunctionCall && value.name === type ) {
656
+ let valueStr = this.emitExpression( value );
571
657
 
572
- varStr += ' = ' + valueStr;
658
+ if ( value.isNumericExpression ) {
573
659
 
574
- } else {
660
+ // convert JS primitive to node
575
661
 
576
- varStr += ` = ${ type }( ${ valueStr } )`;
662
+ valueStr = `${ type }( ${ valueStr } )`;
663
+
664
+ this.addImport( type );
577
665
 
578
666
  }
579
667
 
580
- } else {
668
+ if ( node.linker.assignments.length > 0 ) {
581
669
 
582
- varStr += ` = ${ type }()`;
670
+ varStr += ' = ' + valueStr + '.toVar()';
583
671
 
584
- }
672
+ } else {
585
673
 
586
- if ( node.immutable === false ) {
674
+ varStr += ' = ' + valueStr;
587
675
 
588
- varStr += '.toVar()';
676
+ }
677
+
678
+ } else {
679
+
680
+ varStr += ` = property( '${ type }' )`;
681
+
682
+ this.addImport( 'property' );
589
683
 
590
684
  }
591
685
 
@@ -595,10 +689,6 @@ ${ this.tab }} )`;
595
689
 
596
690
  }
597
691
 
598
- this.addImport( type );
599
-
600
- this._currentVariable = null;
601
-
602
692
  return varStr;
603
693
 
604
694
  }
@@ -622,7 +712,7 @@ ${ this.tab }} )`;
622
712
 
623
713
  const prefix = this.iife === false ? 'export ' : '';
624
714
 
625
- return `${ prefix }const ${ name } = /*#__PURE__*/ overloadingFn( [ ${ nodes.map( node => node.name + '_' + nodes.indexOf( node ) ).join( ', ' ) } ] );\n`;
715
+ return `${ prefix }const ${ name } = /*@__PURE__*/ overloadingFn( [ ${ nodes.map( node => node.name + '_' + nodes.indexOf( node ) ).join( ', ' ) } ] );\n`;
626
716
 
627
717
  }
628
718
 
@@ -630,8 +720,6 @@ ${ this.tab }} )`;
630
720
 
631
721
  const { name, type } = node;
632
722
 
633
- this._currentProperties = { name: node };
634
-
635
723
  const params = [];
636
724
  const inputs = [];
637
725
  const mutableParams = [];
@@ -640,11 +728,9 @@ ${ this.tab }} )`;
640
728
 
641
729
  for ( const param of node.params ) {
642
730
 
643
- let str = `{ name: '${ param.name }', type: '${ param.type }'`;
644
-
645
731
  let name = param.name;
646
732
 
647
- if ( param.immutable === false && ( param.qualifier !== 'inout' && param.qualifier !== 'out' ) ) {
733
+ if ( param.linker.assignments.length > 0 ) {
648
734
 
649
735
  name = name + '_immutable';
650
736
 
@@ -660,20 +746,20 @@ ${ this.tab }} )`;
660
746
 
661
747
  }
662
748
 
663
- str += ', qualifier: \'' + param.qualifier + '\'';
664
-
665
749
  }
666
750
 
667
- inputs.push( str + ' }' );
751
+ inputs.push( param.name + ': \'' + param.type + '\'' );
668
752
  params.push( name );
669
753
 
670
- this._currentProperties[ name ] = param;
671
-
672
754
  }
673
755
 
674
756
  for ( const param of mutableParams ) {
675
757
 
676
- node.body.unshift( new VariableDeclaration( param.type, param.name, new Accessor( param.name + '_immutable' ) ) );
758
+ const mutableParam = new VariableDeclaration( param.type, param.name, new Accessor( param.name + '_immutable' ), null, true );
759
+ mutableParam.parent = param.parent; // link to the original node
760
+ mutableParam.linker.assignments.push( mutableParam );
761
+
762
+ node.body.unshift( mutableParam );
677
763
 
678
764
  }
679
765
 
@@ -705,27 +791,19 @@ ${ this.tab }} )`;
705
791
 
706
792
  const prefix = this.iife === false ? 'export ' : '';
707
793
 
708
- let funcStr = `${ prefix }const ${ fnName } = /*#__PURE__*/ Fn( (${ paramsStr }) => {
794
+ let funcStr = `${ prefix }const ${ fnName } = /*@__PURE__*/ Fn( (${ paramsStr }) => {
709
795
 
710
796
  ${ bodyStr }
711
797
 
712
- ${ this.tab }} )`;
713
-
714
- const layoutInput = inputs.length > 0 ? '\n\t\t' + this.tab + inputs.join( ',\n\t\t' + this.tab ) + '\n\t' + this.tab : '';
798
+ ${ this.tab }}`;
715
799
 
716
800
  if ( node.layout !== false && hasPointer === false ) {
717
801
 
718
- const uniqueName = this.uniqueNames ? fnName + '_' + Math.random().toString( 36 ).slice( 2 ) : fnName;
719
-
720
- funcStr += `.setLayout( {
721
- ${ this.tab }\tname: '${ uniqueName }',
722
- ${ this.tab }\ttype: '${ type }',
723
- ${ this.tab }\tinputs: [${ layoutInput }]
724
- ${ this.tab }} )`;
802
+ funcStr += ', { ' + inputs.join( ', ' ) + ', return: \'' + type + '\' }';
725
803
 
726
804
  }
727
805
 
728
- funcStr += ';\n';
806
+ funcStr += ' );\n';
729
807
 
730
808
  this.imports.add( 'Fn' );
731
809
 
@@ -741,21 +819,42 @@ ${ this.tab }} )`;
741
819
 
742
820
  }
743
821
 
744
- setLastStatement( statement ) {
822
+ emitComment( statement, body ) {
823
+
824
+ const index = body.indexOf( statement );
825
+ const previous = body[ index - 1 ];
826
+ const next = body[ index + 1 ];
827
+
828
+ let output = '';
745
829
 
746
- this._lastStatement = statement;
830
+ if ( previous && isExpression( previous ) ) {
831
+
832
+ output += '\n';
833
+
834
+ }
835
+
836
+ output += this.tab + statement.comment.replace( /\n/g, '\n' + this.tab ) + '\n';
837
+
838
+ if ( next && isExpression( next ) ) {
839
+
840
+ output += '\n';
841
+
842
+ }
843
+
844
+ return output;
747
845
 
748
846
  }
749
847
 
750
- emitExtraLine( statement ) {
848
+ emitExtraLine( statement, body ) {
849
+
850
+ const index = body.indexOf( statement );
851
+ const previous = body[ index - 1 ];
751
852
 
752
- const last = this._lastStatement;
753
- if ( last === null ) return '';
853
+ if ( previous === undefined ) return '';
754
854
 
755
855
  if ( statement.isReturn ) return '\n';
756
856
 
757
- const isExpression = ( st ) => st.isFunctionDeclaration !== true && st.isFor !== true && st.isConditional !== true;
758
- const lastExp = isExpression( last );
857
+ const lastExp = isExpression( previous );
759
858
  const currExp = isExpression( statement );
760
859
 
761
860
  if ( lastExp !== currExp || ( ! lastExp && ! currExp ) ) return '\n';
@@ -790,7 +889,15 @@ ${ this.tab }} )`;
790
889
 
791
890
  for ( const statement of ast.body ) {
792
891
 
793
- code += this.emitExtraLine( statement );
892
+ code += this.emitExtraLine( statement, ast.body );
893
+
894
+ if ( statement.isComment ) {
895
+
896
+ code += this.emitComment( statement, ast.body );
897
+
898
+ continue;
899
+
900
+ }
794
901
 
795
902
  if ( statement.isFunctionDeclaration ) {
796
903
 
@@ -802,8 +909,6 @@ ${ this.tab }} )`;
802
909
 
803
910
  }
804
911
 
805
- this.setLastStatement( statement );
806
-
807
912
  }
808
913
 
809
914
  const imports = [ ...this.imports ];
@@ -1,3 +1,5 @@
1
+ import Linker from './Linker.js';
2
+
1
3
  /**
2
4
  * A class that transpiles shader code from one language into another.
3
5
  *
@@ -32,6 +34,15 @@ class Transpiler {
32
34
  */
33
35
  this.encoder = encoder;
34
36
 
37
+ /**
38
+ * The linker. It processes the AST and resolves
39
+ * variable and function references, ensuring that all
40
+ * dependencies are properly linked.
41
+ *
42
+ * @type {Linker}
43
+ */
44
+ this.linker = new Linker();
45
+
35
46
  }
36
47
 
37
48
  /**
@@ -42,7 +53,12 @@ class Transpiler {
42
53
  */
43
54
  parse( source ) {
44
55
 
45
- return this.encoder.emit( this.decoder.parse( source ) );
56
+ const ast = this.decoder.parse( source );
57
+
58
+ // Process the AST to resolve variable and function references and optimizations.
59
+ this.linker.process( ast );
60
+
61
+ return this.encoder.emit( ast );
46
62
 
47
63
  }
48
64
 
@@ -0,0 +1,29 @@
1
+ export function isExpression( st ) {
2
+
3
+ return st.isFunctionDeclaration !== true && st.isFor !== true && st.isWhile !== true && st.isConditional !== true && st.isSwitch !== true;
4
+
5
+ }
6
+
7
+ export function isPrimitive( value ) {
8
+
9
+ return /^(true|false|-?(\d|\.\d))/.test( value );
10
+
11
+ }
12
+
13
+ export function isType( str ) {
14
+
15
+ return /void|bool|float|u?int|mat[234]|mat[234]x[234]|(u|i|b)?vec[234]/.test( str );
16
+
17
+ }
18
+
19
+ export function toFloatType( type ) {
20
+
21
+ if ( /^(i?int)$/.test( type ) ) return 'float';
22
+
23
+ const vecMatch = /^(i|u)?vec([234])$/.exec( type );
24
+
25
+ if ( vecMatch ) return 'vec' + vecMatch[ 2 ];
26
+
27
+ return type;
28
+
29
+ }