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
@@ -1,11 +1,17 @@
1
- import { Program, FunctionDeclaration, For, AccessorElements, Ternary, Varying, DynamicElement, StaticElement, FunctionParameter, Unary, Conditional, VariableDeclaration, Operator, Number, String, FunctionCall, Return, Accessor, Uniform, Discard } from './AST.js';
1
+ import { Program, FunctionDeclaration, Switch, For, AccessorElements, Ternary, Varying, DynamicElement, StaticElement, FunctionParameter, Unary, Conditional, VariableDeclaration, Operator, Number, String, FunctionCall, Return, Accessor, Uniform, Discard, SwitchCase, Continue, Break, While, Comment } from './AST.js';
2
+
3
+ import { isType } from './TranspilerUtils.js';
2
4
 
3
5
  const unaryOperators = [
4
6
  '+', '-', '~', '!', '++', '--'
5
7
  ];
6
8
 
9
+ const arithmeticOperators = [
10
+ '*', '/', '%', '+', '-', '<<', '>>'
11
+ ];
12
+
7
13
  const precedenceOperators = [
8
- '*', '/', '%',
14
+ '/', '*', '%',
9
15
  '-', '+',
10
16
  '<<', '>>',
11
17
  '<', '>', '<=', '>=',
@@ -41,7 +47,7 @@ const samplers3D = [ 'sampler3D', 'isampler3D', 'usampler3D' ];
41
47
  const spaceRegExp = /^((\t| )\n*)+/;
42
48
  const lineRegExp = /^\n+/;
43
49
  const commentRegExp = /^\/\*[\s\S]*?\*\//;
44
- const inlineCommentRegExp = /^\/\/.*?(\n|$)/;
50
+ const inlineCommentRegExp = /^\/\/.*?(?=\n|$)/;
45
51
 
46
52
  const numberRegExp = /^((0x\w+)|(\.?\d+\.?\d*((e-?\d+)|\w)?))/;
47
53
  const stringDoubleRegExp = /^(\"((?:[^"\\]|\\.)*)\")/;
@@ -80,7 +86,9 @@ class Token {
80
86
  this.str = str;
81
87
  this.pos = pos;
82
88
 
83
- this.tag = null;
89
+ this.isTag = false;
90
+
91
+ this.tags = null;
84
92
 
85
93
  }
86
94
 
@@ -189,7 +197,7 @@ class Tokenizer {
189
197
 
190
198
  }
191
199
 
192
- readToken() {
200
+ nextToken() {
193
201
 
194
202
  const remainingCode = this.skip( spaceRegExp );
195
203
 
@@ -201,35 +209,46 @@ class Tokenizer {
201
209
  if ( result ) {
202
210
 
203
211
  const token = new Token( this, parser.type, result[ parser.group || 0 ], this.position );
212
+ token.isTag = parser.isTag;
204
213
 
205
214
  this.position += result[ 0 ].length;
206
215
 
207
- if ( parser.isTag ) {
216
+ return token;
208
217
 
209
- const nextToken = this.readToken();
218
+ }
210
219
 
211
- if ( nextToken ) {
220
+ }
212
221
 
213
- nextToken.tag = token;
222
+ }
214
223
 
215
- }
224
+ readToken() {
216
225
 
217
- return nextToken;
226
+ let token = this.nextToken();
218
227
 
219
- }
228
+ if ( token && token.isTag ) {
220
229
 
221
- return token;
230
+ const tags = [];
231
+
232
+ while ( token.isTag ) {
233
+
234
+ tags.push( token );
235
+
236
+ token = this.nextToken();
237
+
238
+ if ( ! token ) return;
222
239
 
223
240
  }
224
241
 
242
+ token.tags = tags;
243
+
225
244
  }
226
245
 
246
+ return token;
247
+
227
248
  }
228
249
 
229
250
  }
230
251
 
231
- const isType = ( str ) => /void|bool|float|u?int|mat[234]|mat[234]x[234]|(u|i|b)?vec[234]/.test( str );
232
-
233
252
  class GLSLDecoder {
234
253
 
235
254
  constructor() {
@@ -238,8 +257,6 @@ class GLSLDecoder {
238
257
  this.tokenizer = null;
239
258
  this.keywords = [];
240
259
 
241
- this._currentFunction = null;
242
-
243
260
  this.addPolyfill( 'gl_FragCoord', 'vec3 gl_FragCoord = vec3( screenCoordinate.x, screenCoordinate.y.oneMinus(), screenCoordinate.z );' );
244
261
 
245
262
  }
@@ -327,6 +344,13 @@ class GLSLDecoder {
327
344
 
328
345
  if ( ! token.isOperator || i === 0 || i === tokens.length - 1 ) return;
329
346
 
347
+ // important for negate operator after arithmetic operator: a * -1, a * -( b )
348
+ if ( inverse && arithmeticOperators.includes( tokens[ i - 1 ].str ) ) {
349
+
350
+ return;
351
+
352
+ }
353
+
330
354
  if ( groupIndex === 0 && token.str === operator ) {
331
355
 
332
356
  if ( operator === '?' ) {
@@ -346,7 +370,7 @@ class GLSLDecoder {
346
370
  const left = this.parseExpressionFromTokens( tokens.slice( 0, i ) );
347
371
  const right = this.parseExpressionFromTokens( tokens.slice( i + 1, tokens.length ) );
348
372
 
349
- return this._evalOperator( new Operator( operator, left, right ) );
373
+ return new Operator( operator, left, right );
350
374
 
351
375
  }
352
376
 
@@ -447,7 +471,7 @@ class GLSLDecoder {
447
471
  const rightTokens = tokens.slice( leftTokens.length + 1 );
448
472
  const right = this.parseExpressionFromTokens( rightTokens );
449
473
 
450
- return this._evalOperator( new Operator( operator.str, left, right ) );
474
+ return new Operator( operator.str, left, right );
451
475
 
452
476
  }
453
477
 
@@ -492,6 +516,14 @@ class GLSLDecoder {
492
516
 
493
517
  return new Discard();
494
518
 
519
+ } else if ( firstToken.str === 'continue' ) {
520
+
521
+ return new Continue();
522
+
523
+ } else if ( firstToken.str === 'break' ) {
524
+
525
+ return new Break();
526
+
495
527
  }
496
528
 
497
529
  const secondToken = tokens[ 1 ];
@@ -657,14 +689,9 @@ class GLSLDecoder {
657
689
  const paramsTokens = this.readTokensUntil( ')' );
658
690
 
659
691
  const params = this.parseFunctionParams( paramsTokens.slice( 1, paramsTokens.length - 1 ) );
692
+ const body = this.parseBlock();
660
693
 
661
- const func = new FunctionDeclaration( type, name, params );
662
-
663
- this._currentFunction = func;
664
-
665
- this.parseBlock( func );
666
-
667
- this._currentFunction = null;
694
+ const func = new FunctionDeclaration( type, name, params, body );
668
695
 
669
696
  return func;
670
697
 
@@ -760,6 +787,31 @@ class GLSLDecoder {
760
787
 
761
788
  }
762
789
 
790
+ parseWhile() {
791
+
792
+ this.readToken(); // skip 'while'
793
+
794
+ const conditionTokens = this.readTokensUntil( ')' ).slice( 1, - 1 );
795
+ const condition = this.parseExpressionFromTokens( conditionTokens );
796
+
797
+ let body;
798
+
799
+ if ( this.getToken().str === '{' ) {
800
+
801
+ body = this.parseBlock();
802
+
803
+ } else {
804
+
805
+ body = [ this.parseExpression() ];
806
+
807
+ }
808
+
809
+ const statement = new While( condition, body );
810
+
811
+ return statement;
812
+
813
+ }
814
+
763
815
  parseFor() {
764
816
 
765
817
  this.readToken(); // skip 'for'
@@ -785,22 +837,100 @@ class GLSLDecoder {
785
837
  const condition = this.parseExpressionFromTokens( conditionTokens );
786
838
  const afterthought = this.parseExpressionFromTokens( afterthoughtTokens );
787
839
 
788
- const statement = new For( initialization, condition, afterthought );
840
+ let body;
789
841
 
790
842
  if ( this.getToken().str === '{' ) {
791
843
 
792
- this.parseBlock( statement );
844
+ body = this.parseBlock();
793
845
 
794
846
  } else {
795
847
 
796
- statement.body.push( this.parseExpression() );
848
+ body = [ this.parseExpression() ];
797
849
 
798
850
  }
799
851
 
852
+ const statement = new For( initialization, condition, afterthought, body );
853
+
800
854
  return statement;
801
855
 
802
856
  }
803
857
 
858
+ parseSwitch() {
859
+
860
+ this.readToken(); // Skip 'switch'
861
+
862
+ const switchDeterminantTokens = this.readTokensUntil( ')' );
863
+
864
+ // Parse expression between parentheses. Index 1: char after '('. Index -1: char before ')'
865
+ const discriminant = this.parseExpressionFromTokens( switchDeterminantTokens.slice( 1, - 1 ) );
866
+
867
+ // Validate curly braces
868
+ if ( this.getToken().str !== '{' ) {
869
+
870
+ throw new Error( 'Expected \'{\' after switch(...) ' );
871
+
872
+ }
873
+
874
+ this.readToken(); // Skip '{'
875
+
876
+ const cases = this.parseSwitchCases();
877
+
878
+ const switchStatement = new Switch( discriminant, cases );
879
+
880
+ return switchStatement;
881
+
882
+ }
883
+
884
+ parseSwitchCases() {
885
+
886
+ const cases = [];
887
+
888
+ let token = this.getToken();
889
+ let conditions = null;
890
+
891
+ const isCase = ( token ) => token.str === 'case' || token.str === 'default';
892
+
893
+ while ( isCase( token ) ) {
894
+
895
+ this.readToken(); // Skip 'case' or 'default'
896
+
897
+ if ( token.str === 'case' ) {
898
+
899
+ const caseTokens = this.readTokensUntil( ':' );
900
+ const caseStatement = this.parseExpressionFromTokens( caseTokens.slice( 0, - 1 ) );
901
+
902
+ conditions = conditions || [];
903
+ conditions.push( caseStatement );
904
+
905
+ } else {
906
+
907
+ this.readTokensUntil( ':' ); // Skip 'default:'
908
+
909
+ conditions = null;
910
+
911
+ }
912
+
913
+ token = this.getToken();
914
+
915
+ if ( isCase( token ) ) {
916
+
917
+ // If the next token is another case/default, continue parsing
918
+ continue;
919
+
920
+ }
921
+
922
+ cases.push( new SwitchCase( this.parseBlock(), conditions ) );
923
+
924
+ token = this.getToken();
925
+
926
+ conditions = null;
927
+
928
+ }
929
+
930
+ return cases;
931
+
932
+ }
933
+
804
934
  parseIf() {
805
935
 
806
936
  const parseIfExpression = () => {
@@ -813,25 +943,28 @@ class GLSLDecoder {
813
943
 
814
944
  };
815
945
 
816
- const parseIfBlock = ( cond ) => {
946
+ const parseIfBlock = () => {
947
+
948
+ let body;
817
949
 
818
950
  if ( this.getToken().str === '{' ) {
819
951
 
820
- this.parseBlock( cond );
952
+ body = this.parseBlock();
821
953
 
822
954
  } else {
823
955
 
824
- cond.body.push( this.parseExpression() );
956
+ body = [ this.parseExpression() ];
825
957
 
826
958
  }
827
959
 
960
+ return body;
961
+
828
962
  };
829
963
 
830
964
  //
831
965
 
832
- const conditional = new Conditional( parseIfExpression() );
833
-
834
- parseIfBlock( conditional );
966
+ // Parse the first if statement
967
+ const conditional = new Conditional( parseIfExpression(), parseIfBlock() );
835
968
 
836
969
  //
837
970
 
@@ -841,21 +974,24 @@ class GLSLDecoder {
841
974
 
842
975
  this.readToken(); // skip 'else'
843
976
 
977
+ // Assign the current if/else statement as the previous within the chain of conditionals
844
978
  const previous = current;
845
979
 
846
- if ( this.getToken().str === 'if' ) {
847
-
848
- current = new Conditional( parseIfExpression() );
980
+ let expression = null;
849
981
 
850
- } else {
982
+ // If an 'else if' statement, parse the conditional within the if
983
+ if ( this.getToken().str === 'if' ) {
851
984
 
852
- current = new Conditional();
985
+ // Current conditional now equal to next conditional in the chain
986
+ expression = parseIfExpression();
853
987
 
854
988
  }
855
989
 
856
- previous.elseConditional = current;
990
+ current = new Conditional( expression, parseIfBlock() );
991
+ current.parent = previous;
857
992
 
858
- parseIfBlock( current );
993
+ // n - 1 conditional's else statement assigned to new if/else statement
994
+ previous.elseConditional = current;
859
995
 
860
996
  }
861
997
 
@@ -863,7 +999,9 @@ class GLSLDecoder {
863
999
 
864
1000
  }
865
1001
 
866
- parseBlock( scope ) {
1002
+ parseBlock() {
1003
+
1004
+ const body = [];
867
1005
 
868
1006
  const firstToken = this.getToken();
869
1007
 
@@ -883,16 +1021,47 @@ class GLSLDecoder {
883
1021
 
884
1022
  groupIndex += getGroupDelta( token.str );
885
1023
 
886
- if ( groupIndex < 0 ) {
1024
+ if ( groupIndex === 0 && ( token.str === 'case' || token.str === 'default' ) ) {
1025
+
1026
+ return body; // switch case or default statement, return body
1027
+
1028
+ } else if ( groupIndex < 0 ) {
887
1029
 
888
1030
  this.readToken(); // skip '}'
889
1031
 
890
- break;
1032
+ return body;
891
1033
 
892
1034
  }
893
1035
 
894
1036
  //
895
1037
 
1038
+ if ( token.tags ) {
1039
+
1040
+ let lastStatement = null;
1041
+
1042
+ for ( const tag of token.tags ) {
1043
+
1044
+ if ( tag.type === Token.COMMENT ) {
1045
+
1046
+ const str = tag.str.replace( /\t/g, '' );
1047
+
1048
+ if ( ! lastStatement || lastStatement.isComment !== true ) {
1049
+
1050
+ lastStatement = new Comment( str );
1051
+ body.push( lastStatement );
1052
+
1053
+ } else {
1054
+
1055
+ lastStatement.comment += '\n' + str;
1056
+
1057
+ }
1058
+
1059
+ }
1060
+
1061
+ }
1062
+
1063
+ }
1064
+
896
1065
  if ( token.isLiteral || token.isOperator ) {
897
1066
 
898
1067
  if ( token.str === 'const' ) {
@@ -931,6 +1100,14 @@ class GLSLDecoder {
931
1100
 
932
1101
  statement = this.parseFor();
933
1102
 
1103
+ } else if ( token.str === 'while' ) {
1104
+
1105
+ statement = this.parseWhile();
1106
+
1107
+ } else if ( token.str === 'switch' ) {
1108
+
1109
+ statement = this.parseSwitch();
1110
+
934
1111
  } else {
935
1112
 
936
1113
  statement = this.parseExpression();
@@ -941,7 +1118,7 @@ class GLSLDecoder {
941
1118
 
942
1119
  if ( statement ) {
943
1120
 
944
- scope.body.push( statement );
1121
+ body.push( statement );
945
1122
 
946
1123
  } else {
947
1124
 
@@ -951,43 +1128,7 @@ class GLSLDecoder {
951
1128
 
952
1129
  }
953
1130
 
954
- }
955
-
956
- _evalOperator( operator ) {
957
-
958
- if ( operator.type.includes( '=' ) ) {
959
-
960
- const parameter = this._getFunctionParameter( operator.left.property );
961
-
962
- if ( parameter !== undefined ) {
963
-
964
- // Parameters are immutable in WGSL
965
-
966
- parameter.immutable = false;
967
-
968
- }
969
-
970
- }
971
-
972
- return operator;
973
-
974
- }
975
-
976
- _getFunctionParameter( name ) {
977
-
978
- if ( this._currentFunction ) {
979
-
980
- for ( const param of this._currentFunction.params ) {
981
-
982
- if ( param.name === name ) {
983
-
984
- return param;
985
-
986
- }
987
-
988
- }
989
-
990
- }
1131
+ return body;
991
1132
 
992
1133
  }
993
1134
 
@@ -1014,9 +1155,8 @@ class GLSLDecoder {
1014
1155
  this.index = 0;
1015
1156
  this.tokenizer = new Tokenizer( polyfill + source ).tokenize();
1016
1157
 
1017
- const program = new Program();
1018
-
1019
- this.parseBlock( program );
1158
+ const body = this.parseBlock();
1159
+ const program = new Program( body );
1020
1160
 
1021
1161
  return program;
1022
1162