Ver código fonte

Merge branch 'master' of https://github.com/BabylonJS/Babylon.js

DEV-UNITY-6\Utilisateur 6 anos atrás
pai
commit
582039a205
95 arquivos alterados com 37194 adições e 23463 exclusões
  1. 135 57
      Playground/babylon.d.txt
  2. 209 287
      Playground/indexWebGPU.html
  3. 0 1263
      Playground/js/indexWebGPU.js
  4. 860 0
      Playground/js/mainWebGPU.js
  5. 2 2
      Playground/js/monacoCreator.js
  6. 138 57
      dist/preview release/babylon.d.ts
  7. 2 2
      dist/preview release/babylon.js
  8. 649 315
      dist/preview release/babylon.max.js
  9. 1 1
      dist/preview release/babylon.max.js.map
  10. 291 119
      dist/preview release/babylon.module.d.ts
  11. 138 57
      dist/preview release/documentation.d.ts
  12. 10 11
      dist/preview release/inspector/babylon.inspector.bundle.js
  13. 19950 13740
      dist/preview release/inspector/babylon.inspector.bundle.max.js
  14. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.max.js.map
  15. 13 17
      dist/preview release/inspector/babylon.inspector.d.ts
  16. 26 34
      dist/preview release/inspector/babylon.inspector.module.d.ts
  17. 45 4
      dist/preview release/nodeEditor/babylon.nodeEditor.d.ts
  18. 10 11
      dist/preview release/nodeEditor/babylon.nodeEditor.js
  19. 13115 6605
      dist/preview release/nodeEditor/babylon.nodeEditor.max.js
  20. 1 1
      dist/preview release/nodeEditor/babylon.nodeEditor.max.js.map
  21. 107 9
      dist/preview release/nodeEditor/babylon.nodeEditor.module.d.ts
  22. 1 1
      dist/preview release/packagesSizeBaseLine.json
  23. 291 119
      dist/preview release/viewer/babylon.module.d.ts
  24. 53 45
      dist/preview release/viewer/babylon.viewer.js
  25. 1 1
      dist/preview release/viewer/babylon.viewer.max.js
  26. 1 1
      inspector/src/components/actionTabs/actionTabsComponent.tsx
  27. 1 1
      inspector/src/components/actionTabs/lines/radioLineComponent.tsx
  28. 1 1
      inspector/src/components/actionTabs/lines/textureLinkLineComponent.tsx
  29. 0 5
      inspector/src/components/actionTabs/tabs/debugTabComponent.tsx
  30. 1 1
      inspector/src/components/actionTabs/tabs/propertyGridTabComponent.tsx
  31. 6 8
      inspector/src/components/actionTabs/tabs/propertyGrids/animationGroupPropertyGridComponent.tsx
  32. 1 1
      inspector/src/components/actionTabs/tabs/propertyGrids/animationPropertyGridComponent.tsx
  33. 0 2
      inspector/src/components/actionTabs/tabs/propertyGrids/materials/texturePropertyGridComponent.tsx
  34. 42 12
      inspector/src/components/actionTabs/tabs/propertyGrids/meshes/meshPropertyGridComponent.tsx
  35. 2 4
      inspector/src/components/actionTabs/tabs/propertyGrids/meshes/skeletonPropertyGridComponent.tsx
  36. 1 1
      inspector/src/components/actionTabs/tabs/propertyGrids/renderGridPropertyGridComponent.tsx
  37. 0 2
      inspector/src/components/actionTabs/tabs/statisticsTabComponent.tsx
  38. 1 1
      inspector/src/components/actionTabs/tabs/toolsTabComponent.tsx
  39. 1 1
      inspector/src/components/headerComponent.tsx
  40. 1 1
      inspector/src/components/sceneExplorer/entities/cameraTreeItemComponent.tsx
  41. 1 1
      inspector/src/components/sceneExplorer/entities/sceneTreeItemComponent.tsx
  42. 1 1
      inspector/src/components/sceneExplorer/sceneExplorerComponent.tsx
  43. 159 306
      localDev/fresnel.json
  44. 91 2
      nodeEditor/src/blockTools.ts
  45. 23 0
      nodeEditor/src/components/diagram/clamp/clampNodeFactory.tsx
  46. 25 0
      nodeEditor/src/components/diagram/clamp/clampNodeModel.tsx
  47. 42 0
      nodeEditor/src/components/diagram/clamp/clampNodePropertyComponent.tsx
  48. 64 0
      nodeEditor/src/components/diagram/clamp/clampNodeWidget.tsx
  49. 14 0
      nodeEditor/src/components/diagram/generic/genericNodeModel.tsx
  50. 4 2
      nodeEditor/src/components/diagram/trigonometry/trigonometryNodePropertyComponent.tsx
  51. 1 1
      nodeEditor/src/components/log/logComponent.tsx
  52. 111 106
      nodeEditor/src/components/nodeList/nodeList.scss
  53. 11 9
      nodeEditor/src/components/nodeList/nodeListComponent.tsx
  54. 4 4
      nodeEditor/src/components/preview/previewManager.ts
  55. 1 1
      nodeEditor/src/components/propertyTab/propertyTab.scss
  56. 4 4
      nodeEditor/src/components/propertyTab/propertyTabComponent.tsx
  57. 12 0
      nodeEditor/src/graphEditor.tsx
  58. 2 0
      nodeEditor/src/main.scss
  59. 11 0
      nodeEditor/src/nodeEditor.ts
  60. 1 1
      nodeEditor/src/stringTools.ts
  61. 2 2
      package.json
  62. 1 1
      src/Lights/light.ts
  63. 13 5
      src/Materials/Node/Blocks/Dual/fogBlock.ts
  64. 15 11
      src/Materials/Node/Blocks/Dual/lightBlock.ts
  65. 30 14
      src/Materials/Node/Blocks/Dual/reflectionTextureBlock.ts
  66. 7 3
      src/Materials/Node/Blocks/Dual/textureBlock.ts
  67. 0 137
      src/Materials/Node/Blocks/Fragment/fresnelBlock.ts
  68. 0 1
      src/Materials/Node/Blocks/Fragment/index.ts
  69. 19 7
      src/Materials/Node/Blocks/Vertex/bonesBlock.ts
  70. 31 11
      src/Materials/Node/Blocks/Vertex/instancesBlock.ts
  71. 25 9
      src/Materials/Node/Blocks/Vertex/morphTargetsBlock.ts
  72. 1 0
      src/Materials/Node/Blocks/addBlock.ts
  73. 1 0
      src/Materials/Node/Blocks/crossBlock.ts
  74. 1 0
      src/Materials/Node/Blocks/divideBlock.ts
  75. 2 0
      src/Materials/Node/Blocks/dotBlock.ts
  76. 100 0
      src/Materials/Node/Blocks/fresnelBlock.ts
  77. 4 1
      src/Materials/Node/Blocks/index.ts
  78. 1 0
      src/Materials/Node/Blocks/lerpBlock.ts
  79. 2 2
      src/Materials/Node/Blocks/multiplyBlock.ts
  80. 57 0
      src/Materials/Node/Blocks/oppositeBlock.ts
  81. 1 0
      src/Materials/Node/Blocks/subtractBlock.ts
  82. 1 1
      src/Materials/Node/Blocks/trigonometryBlock.ts
  83. 79 0
      src/Materials/Node/Blocks/viewDirectionBlock.ts
  84. 30 0
      src/Materials/Node/nodeMaterial.ts
  85. 15 3
      src/Materials/Node/nodeMaterialBlock.ts
  86. 8 1
      src/Materials/Node/nodeMaterialBlockConnectionPoint.ts
  87. 13 2
      src/Materials/PBR/pbrBaseMaterial.ts
  88. 8 0
      src/Materials/Textures/videoTexture.ts
  89. 6 1
      src/Materials/materialDefines.ts
  90. 8 4
      src/Materials/materialHelper.ts
  91. 11 1
      src/Materials/standardMaterial.ts
  92. 4 4
      src/Meshes/abstractMesh.ts
  93. 1 1
      src/Meshes/instancedMesh.ts
  94. 6 1
      src/Particles/solidParticleSystem.ts
  95. 1 1
      src/scene.ts

+ 135 - 57
Playground/babylon.d.txt

@@ -7570,6 +7570,7 @@ declare module BABYLON {
         private _isDirty;
         /** @hidden */
private _renderId: number;
         /** @hidden */
private _areLightsDirty: boolean;
+        /** @hidden */
private _areLightsDisposed: boolean;
         /** @hidden */
private _areAttributesDirty: boolean;
         /** @hidden */
private _areTexturesDirty: boolean;
         /** @hidden */
private _areFresnelDirty: boolean;
@@ -7602,8 +7603,9 @@ declare module BABYLON {
         markAsImageProcessingDirty(): void;
         /**
          * Marks the material to indicate the lights need to be re-calculated
+         * @param disposed Defines whether the light is dirty due to dispose or not
          */
-        markAsLightDirty(): void;
+        markAsLightDirty(disposed?: boolean): void;
         /**
          * Marks the attribute state as changed
          */
@@ -8883,8 +8885,9 @@ declare module BABYLON {
          * @param effect The effect we are binding the data to
          * @param useSpecular Defines if specular is supported
          * @param usePhysicalLightFalloff Specifies whether the light falloff is defined physically or not
+         * @param rebuildInParallel Specifies whether the shader is rebuilding in parallel
          */
-        static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff?: boolean): void;
+        static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff?: boolean, rebuildInParallel?: boolean): void;
         /**
          * Binds the lights information from the scene to the effect for the given mesh.
          * @param scene The scene the lights belongs to
@@ -8893,8 +8896,9 @@ declare module BABYLON {
          * @param defines The generated defines for the effect
          * @param maxSimultaneousLights The maximum number of light that can be bound to the effect
          * @param usePhysicalLightFalloff Specifies whether the light falloff is defined physically or not
+         * @param rebuildInParallel Specifies whether the shader is rebuilding in parallel
          */
-        static BindLights(scene: Scene, mesh: AbstractMesh, effect: Effect, defines: any, maxSimultaneousLights?: number, usePhysicalLightFalloff?: boolean): void;
+        static BindLights(scene: Scene, mesh: AbstractMesh, effect: Effect, defines: any, maxSimultaneousLights?: number, usePhysicalLightFalloff?: boolean, rebuildInParallel?: boolean): void;
         private static _tempFogColor;
         /**
          * Binds the fog information from the scene to the effect for the given mesh.
@@ -18333,7 +18337,7 @@ declare module BABYLON {
          */
         getClassName(): string;
         /** Gets the list of lights affecting that mesh */
-        readonly lightSources: Light[];
private _resyncLightSources(): void;
private _resyncLighSource(light: Light): void;
private _removeLightSource(light: Light): void;
+        readonly lightSources: Light[];
private _resyncLightSources(): void;
private _resyncLighSource(light: Light): void;
private _removeLightSource(light: Light, dispose: boolean): void;
         /**
          * If the source mesh receives shadows
          */
@@ -25466,9 +25470,9 @@ declare module BABYLON {
         /** @hidden */
private _resyncLightSources(): void;
         /** @hidden */
private _resyncLighSource(light: Light): void;
         /** @hidden */
private _unBindEffect(): void;
-        /** @hidden */
private _removeLightSource(light: Light): void;
+        /** @hidden */
private _removeLightSource(light: Light, dispose: boolean): void;
         private _markSubMeshesAsDirty;
-        /** @hidden */
private _markSubMeshesAsLightDirty(): void;
+        /** @hidden */
private _markSubMeshesAsLightDirty(dispose?: boolean): void;
         /** @hidden */
private _markSubMeshesAsAttributesDirty(): void;
         /** @hidden */
private _markSubMeshesAsMiscDirty(): void;
         /**
@@ -28926,6 +28930,7 @@ declare module BABYLON {
         private _displayingPosterTexture;
         private _settings;
         private _createInternalTextureOnEvent;
+        private _frameId;
         /**
          * Creates a video texture.
          * If you want to display a video in your scene, this is the special texture for that.
@@ -39501,6 +39506,7 @@ declare module BABYLON {
         protected _worldViewProjectionMatrix: Matrix;
         protected _globalAmbientColor: Color3;
         protected _useLogarithmicDepth: boolean;
+        protected _rebuildInParallel: boolean;
         /**
          * Instantiates a new standard material.
          * This is the default material used in Babylon. It is the best trade off between quality
@@ -46130,6 +46136,7 @@ declare module BABYLON {
          * Custom callback helping to override the default shader used in the material.
          */
         customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: PBRMaterialDefines) => string;
+        protected _rebuildInParallel: boolean;
         /**
          * Instantiates a new PBRMaterial instance.
          *
@@ -50937,6 +50944,7 @@ declare module BABYLON {
         readonly transform: NodeMaterialConnectionPoint;
         protected _buildBlock(state: NodeMaterialBuildState): this;
         serialize(): any;
private _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
+        protected _dumpPropertiesCode(): string;
     }
 }
 declare module BABYLON {
@@ -51092,7 +51100,7 @@ declare module BABYLON {
          * Gets the b output component
          */
         readonly b: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         isReady(): boolean;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
@@ -51234,6 +51242,18 @@ declare module BABYLON {
          */
         getBlockByName(name: string): Nullable<NodeMaterialBlock>;
         /**
+         * Get a block by its name
+         * @param predicate defines the predicate used to find the good candidate
+         * @returns the required block or null if not found
+         */
+        getBlockByPredicate(predicate: (block: NodeMaterialBlock) => boolean): Nullable<NodeMaterialBlock>;
+        /**
+         * Get an input block by its name
+         * @param predicate defines the predicate used to find the good candidate
+         * @returns the required input block or null if not found
+         */
+        getInputBlockByPredicate(predicate: (block: InputBlock) => boolean): Nullable<InputBlock>;
+        /**
          * Gets the list of input blocks attached to this material
          * @returns an array of InputBlocks
          */
@@ -51448,7 +51468,7 @@ declare module BABYLON {
          */
         readonly a: NodeMaterialConnectionPoint;
         readonly target: NodeMaterialBlockTargets;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         initializeDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         isReady(): boolean;
@@ -51824,6 +51844,7 @@ declare module BABYLON {
          * @returns true if the block is ready
          */
         isReady(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): boolean;
+        protected _linkConnectionTypes(inputIndex0: number, inputIndex1: number): void;
         private _processBuild;
         /**
          * Compile the current node and generate the shader code
@@ -51996,6 +52017,7 @@ declare module BABYLON {
         private _endpoints;
         private _associatedVariableName;
         /** @hidden */
private _typeConnectionSource: Nullable<NodeMaterialConnectionPoint>;
+        /** @hidden */
private _linkedConnectionSource: Nullable<NodeMaterialConnectionPoint>;
         private _type;
         /** @hidden */
private _enforceAssociatedVariableName: boolean;
         /**
@@ -52068,9 +52090,10 @@ declare module BABYLON {
         /**
          * Connect this point to another connection point
          * @param connectionPoint defines the other connection point
+         * @param ignoreConstraints defines if the system will ignore connection type constraints (default is false)
          * @returns the current connection point
          */
-        connectTo(connectionPoint: NodeMaterialConnectionPoint): NodeMaterialConnectionPoint;
+        connectTo(connectionPoint: NodeMaterialConnectionPoint, ignoreConstraints?: boolean): NodeMaterialConnectionPoint;
         /**
          * Disconnect this point from one of his endpoint
          * @param endpoint defines the other connection point
@@ -52128,7 +52151,7 @@ declare module BABYLON {
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         provideFallbacks(mesh: AbstractMesh, fallbacks: EffectFallbacks): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
@@ -52175,7 +52198,7 @@ declare module BABYLON {
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         protected _buildBlock(state: NodeMaterialBuildState): this;
     }
@@ -52230,7 +52253,7 @@ declare module BABYLON {
          */
         readonly uvOutput: NodeMaterialConnectionPoint;
         initialize(state: NodeMaterialBuildState): void;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         replaceRepeatableContent(vertexShaderState: NodeMaterialBuildState, fragmentShaderState: NodeMaterialBuildState, mesh: AbstractMesh, defines: NodeMaterialDefines): void;
@@ -52265,49 +52288,8 @@ declare module BABYLON {
          */
         readonly alpha: NodeMaterialConnectionPoint;
         protected _buildBlock(state: NodeMaterialBuildState): this;
-    }
-}
-declare module BABYLON {
-    /**
-     * Block used to compute fresnel value
-     */
-    export class FresnelBlock extends NodeMaterialBlock {
-        /**
-         * Create a new FresnelBlock
-         * @param name defines the block name
-         */
-        constructor(name: string);
-        /**
-         * Gets the current class name
-         * @returns the class name
-         */
-        getClassName(): string;
-        /**
-         * Gets the world position input component
-         */
-        readonly worldPosition: NodeMaterialConnectionPoint;
-        /**
-         * Gets the world normal input component
-         */
-        readonly worldNormal: NodeMaterialConnectionPoint;
-        /**
-        * Gets the camera (or eye) position component
-        */
-        readonly cameraPosition: NodeMaterialConnectionPoint;
-        /**
-        * Gets the bias input component
-        */
-        readonly bias: NodeMaterialConnectionPoint;
-        /**
-        * Gets the camera (or eye) position component
-        */
-        readonly power: NodeMaterialConnectionPoint;
-        /**
-         * Gets the fresnel output component
-         */
-        readonly fresnel: NodeMaterialConnectionPoint;
-        autoConfigure(material: NodeMaterial): void;
-        protected _buildBlock(state: NodeMaterialBuildState): this | undefined;
+        protected _dumpPropertiesCode(): string;
+        serialize(): any;
private _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
     }
 }
 declare module BABYLON {
@@ -52381,7 +52363,7 @@ declare module BABYLON {
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         protected _buildBlock(state: NodeMaterialBuildState): this;
@@ -52427,7 +52409,7 @@ declare module BABYLON {
          * Gets the specular output component
          */
         readonly specularOutput: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
@@ -53049,6 +53031,102 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * Block used to get the opposite of a value
+     */
+    export class OppositeBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new OppositeBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the input component
+         */
+        readonly input: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to get the view direction
+     */
+    export class ViewDirectionBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new ViewDirectionBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world position component
+         */
+        readonly worldPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the camera position component
+         */
+        readonly cameraPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to compute fresnel value
+     */
+    export class FresnelBlock extends NodeMaterialBlock {
+        /**
+         * Create a new FresnelBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world normal input component
+         */
+        readonly worldNormal: NodeMaterialConnectionPoint;
+        /**
+        * Gets the view direction input component
+        */
+        readonly viewDirection: NodeMaterialConnectionPoint;
+        /**
+        * Gets the bias input component
+        */
+        readonly bias: NodeMaterialConnectionPoint;
+        /**
+        * Gets the camera (or eye) position component
+        */
+        readonly power: NodeMaterialConnectionPoint;
+        /**
+         * Gets the fresnel output component
+         */
+        readonly fresnel: NodeMaterialConnectionPoint;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
      * Effect Render Options
      */
     export interface IEffectRendererOptions {

+ 209 - 287
Playground/indexWebGPU.html

@@ -5,22 +5,23 @@
     <title>Babylon.js Playground WEBGPU</title>
     <meta charset='utf-8' />
     <meta name="viewport" content="width=device-width, user-scalable=no">
-    <link rel="shortcut icon" href="https://www.babylonjs.com/img/favicon/favicon.ico">
-    <link rel="manifest" href="https://www.babylonjs.com/img/favicon/manifest.json">
-    <meta name="msapplication-TileColor" content="#ffffff">
-    <meta name="msapplication-TileImage" content="https://www.babylonjs.com/img/favicon/ms-icon-144x144.png">
-    <meta name="msapplication-config" content="https://www.babylonjs.com/img/favicon/browserconfig.xml">
-    <meta name="theme-color" content="#ffffff">
-    <link rel="stylesheet" href="https://use.typekit.net/cta4xsb.css">
+    <link rel="shortcut icon" href="https://www.babylonjs.com/favicon.ico">
 
+    <link rel="stylesheet" href="https://use.typekit.net/cta4xsb.css" />
+    <link rel="stylesheet" href="css/index.css" />
+    <link rel="stylesheet" href="css/index_mobile.css" />
+
+    <!-- Pep -->
     <script src="js/libs/pep.min.js"></script>
-    <!--For canvas/code separator-->
+    <!-- For canvas/code separator -->
     <script src="js/libs/split.js"></script>
 
+    <!-- DatGUI -->
     <script src="js/libs/dat.gui.min.js"></script>
     <!-- jszip -->
     <script src="js/libs/jszip.min.js"></script>
     <script src="js/libs/fileSaver.js"></script>
+
     <!-- Dependencies -->
     <script src="https://preview.babylonjs.com/ammo.js"></script>
     <script src="https://preview.babylonjs.com/recast.js"></script>
@@ -51,347 +52,254 @@
     <!-- Scene Manager -->
     <script src="https://mackeyk24.github.io/toolkit/babylon.manager.js"></script>
     <script src="https://mackeyk24.github.io/toolkit/babylon.navmesh.js"></script>
-
-    <link href="css/index.css" rel="stylesheet" />
 </head>
 
 <body>
-    <div class="navbar navBar1600">
-        <div class="title">
-            Babylon.js Playground WEBGPU
-        </div>
-        <div class="version" id="mainTitle">
-        </div>
-
-        <div class="category">
-            <div class="button run" id="runButton1600">Run
-                <i class="fa fa-play" aria-hidden="true"></i>
-            </div>
-        </div>
-
-
-        <div class="category">
-            <div class="button" id="newButton1600">New
-                <i class="fa fa-file" aria-hidden="true"></i>
-            </div>
-            <div class="button removeOnPhone" id="clearButton1600">Clear
-                <i class="fa fa-trash" aria-hidden="true"></i>
-            </div>
-        </div>
-
-        <div class="category">
-            <div class="button" id="saveButton1600">Save
-                <i class="fa fa-floppy-o" aria-hidden="true"></i>
-            </div>
-        </div>
-
-        <div class="category">
-            <div class="button select">Settings
-                <div class="toDisplay">
-                    <div class="option subSelect">Theme
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" id="darkTheme1600">Dark</div>
-                            <div class="option" id="lightTheme1600">Light</div>
-                        </div>
-                    </div>
-                    <div class="option subSelect">
-                        <span id="currentFontSize1600">Font: 14</span>
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setFontSize(12);">12</div>
-                            <div class="option" onclick="setFontSize(14);">14</div>
-                            <div class="option" onclick="setFontSize(16);">16</div>
-                            <div class="option" onclick="setFontSize(18);">18</div>
-                            <div class="option" onclick="setFontSize(20);">20</div>
-                            <div class="option" onclick="setFontSize(22);">22</div>
-                        </div>
-                    </div>
-                    <div class="option" id="safemodeToggle1600">Safe mode
-                        <i class="far fa-square" aria-hidden="true"></i>
-                    </div>
-                    <div class="option checked" id="editorButton1600">Editor
-                        <i class="fa fa-check-square" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="fullscreenButton1600">Fullscreen</div>
-                    <div class="option" id="editorFullscreenButton1600">Editor Fullscreen</div>
-                    <div class="option" id="formatButton1600">Format code</div>
-                    <div class="option" id="minimapToggle1600">Minimap
-                        <i class="far fa-square" aria-hidden="true"></i>
-                    </div>
-                </div>
-            </div>
-
-            <div class="button uncheck" id="debugButton1600">Inspector</div>
-            <div class="button" id="metadataButton1600">Metadata</div>
-        </div>
-
-        <div class="category right">
-            <div class="button select">
-                <span id="currentVersion1600">Version: Latest</span>
-                <div class="toDisplay">
-                    <div class="option" onclick="setVersion('latest');">Latest</div>
-                    <div class="option" onclick="setVersion('stable');">Stable</div>
-                </div>
-            </div>
-            <div class="button select">
-                <span class="examplesButton">Examples</span>
-            </div>
-        </div>
-    </div>
-
-    <div class="navbar navBar1475">
-        <div class="title">
-            Babylon.js Playground WEBGPU
-        </div>
-        <div class="version" id="mainTitle">
-        </div>
-
-        <div class="category">
-            <div class="button run" id="runButton1475">Run
-                <i class="fa fa-play" aria-hidden="true"></i>
-            </div>
-        </div>
-
-
-        <div class="category">
-            <div class="button" id="newButton1475">New
-                <i class="fa fa-file" aria-hidden="true"></i>
-            </div>
-            <div class="button removeOnPhone" id="clearButton1475">Clear
-                <i class="fa fa-trash" aria-hidden="true"></i>
-            </div>
+    <!-- Big screens -->
+    <div class="navbar navBar1280 languageJS">
+        <div class="categoryTitle">
+            <img class="logo" src="css/img/logo_v4.svg">
+            <div class="version">Playground <span class="versionSub" id="mainTitle1280"></span></div>
         </div>
 
-        <div class="category">
-            <div class="button" id="saveButton1475">Save
-                <i class="fa fa-floppy-o" aria-hidden="true"></i>
-            </div>
-        </div>
-
-        <div class="category">
-            <div class="button select">Settings
-                <div class="toDisplay">
-                    <div class="option subSelect">Theme
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" id="darkTheme1475">Dark</div>
-                            <div class="option" id="lightTheme1475">Light</div>
+        <div class="category languageJS" id="JStoTSbar">
+            <div class="buttonJStoTS languageTS" id="toTSbutton1280">Typescript</div>
+            <div class="buttonJStoTS languageJS" id="toJSbutton1280">Javascript</div>
+            <div class="buttonPG run" id="runButton1280"><img src="css/img/playButton.svg"></div>
+            <div class="buttonPG" id="saveButton1280"><img src="css/img/saveButton.svg"></div>
+            <div class="buttonPG removeOnPhone" id="zipButton1280"><img src="css/img/downloadButton.svg"></div>
+            <div class="buttonPG" id="newButton1280"><img src="css/img/newButton.svg"></div>
+            <div class="buttonPG removeOnPhone" id="clearButton1280"><img src="css/img/clearButton.svg"></div>
+            <div class="buttonPG select" id="menuButton1280"><img src="css/img/optionsButton.svg">
+                <div class="toDisplay languageJS">
+                    <div class="option subSelect">Theme <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                        <div class="toDisplaySub languageJS">
+                            <div class="option selected" id="darkTheme1280">Dark</div>
+                            <div class="option" id="lightTheme1280">Light</div>
                         </div>
                     </div>
-                    <div class="option subSelect">
-                        <span id="currentFontSize1475">Font: 14</span>
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setFontSize(12);">12</div>
-                            <div class="option" onclick="setFontSize(14);">14</div>
-                            <div class="option" onclick="setFontSize(16);">16</div>
-                            <div class="option" onclick="setFontSize(18);">18</div>
-                            <div class="option" onclick="setFontSize(20);">20</div>
-                            <div class="option" onclick="setFontSize(22);">22</div>
+                    <div class="option subSelect">Font size <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                        <div class="toDisplaySub displayFontSize languageJS">
+                            <div class="option">12</div>
+                            <div class="option selected">14</div>
+                            <div class="option">16</div>
+                            <div class="option">18</div>
+                            <div class="option">20</div>
+                            <div class="option">22</div>
                         </div>
                     </div>
-                    <div class="option" id='safemodeToggle1475'>Safe mode
-                        <i class="far fa-square" aria-hidden="true"></i>
+                    <div class="option noSubSelect" id="safemodeToggle1280">Safe mode
+                        <i class="fa fa-square" aria-hidden="true"></i>
                     </div>
-                    <div class="option checked" id="editorButton1475">Editor
+                    <div class="option checked noSubSelect" id="editorButton1280">Editor
                         <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
-                    <div class="option" id="fullscreenButton1475">Fullscreen</div>
-                    <div class="option" id="editorFullscreenButton1475">Editor Fullscreen</div>
-                    <div class="option" id="formatButton1475">Format code</div>
-                    <div class="option" id="minimapToggle1475">Minimap
-                        <i class="far fa-square" aria-hidden="true"></i>
+                    <div class="option noSubSelect" id="fullscreenButton1280">Fullscreen</div>
+                    <div class="option noSubSelect" id="editorFullscreenButton1280">Editor Fullscreen</div>
+                    <div class="option noSubSelect" id="formatButton1280">Format code</div>
+                    <div class="option noSubSelect" id="minimapToggle1280">Minimap
+                        <i class="fa fa-square" aria-hidden="true"></i>
                     </div>
-                    <div class="option" id="debugButton1475">Inspector</div>
-                    <div class="option" id="metadataButton1475">Metadata</div>
-                    <div class="option subSelect">
-                        <span id="currentVersion1475">Vers. : Latest</span>
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setVersion('latest');">Latest</div>
-                            <div class="option" onclick="setVersion('stable');">Stable</div>
-                        </div>
-                    </div>
-                    <div class="option subSelect" id="qrCodeHover" onmouseover="showQRCode();">QR Code Link
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" style="height:auto;padding: 20px;background: white;" id="qrCodeImage">QR Code Image</div>
+                    <div class="option subSelect" id="qrCodeHover1280">QR Code Link <i class="fa fa-chevron-right"
+                            aria-hidden="true"></i>
+                        <div class="toDisplaySub qrCodeImage">
+                            <div class="option" id="qrCodeImage1280">[QR Code Image]</div>
                         </div>
                     </div>
+                    <div class="option uncheck noSubSelect" id="debugButton1280">Inspector</div>
+                    <div class="option nosubselect" id="metadataButton1280">Metadata</div>
                 </div>
             </div>
         </div>
 
         <div class="category right">
-            <div class="button select">
-                <span class="examplesButton">Examples</span>
+            <div class="buttonPG select">
+                <span id="currentVersion1280"></span>
+                <div class="toDisplay currentVersionDisplay" style="display: none"></div>
             </div>
+            <div class="buttonPG select"><img class="examplesButton" src="css/img/examplesButton.svg"></div>
         </div>
     </div>
 
-    <div class="navbar navBar1030">
-        <div class="category">
-            <div class="button run" id="runButton1030">Run
-                <i class="fa fa-play" aria-hidden="true"></i>
-            </div>
-        </div>
-
-
-        <div class="category">
-            <div class="button" id="newButton1030">New
-                <i class="fa fa-file" aria-hidden="true"></i>
-            </div>
-            <div class="button removeOnPhone" id="clearButton1030">Clear
-                <i class="fa fa-trash" aria-hidden="true"></i>
-            </div>
+    <!-- Mid-size screens -->
+    <div class="navbar navBar1024 languageJS">
+        <div class="categoryTitle">
+            <img class="logo" src="css/img/logo_v4.svg">
+            <div class="version"><span class="versionSub" id="mainTitle1024"></span></div>
         </div>
 
-        <div class="category">
-            <div class="button" id="saveButton1030">Save
-                <i class="fa fa-floppy-o" aria-hidden="true"></i>
-            </div>
-        </div>
-
-        <div class="category">
-            <div class="button select">Settings
+        <div class="category languageJS" id="JStoTSbar">
+            <div class="buttonJStoTS languageTS" id="toTSbutton1024">TS</div>
+            <div class="buttonJStoTS languageJS" id="toJSbutton1024">JS</div>
+            <div class="buttonSpaceKiller"></div>
+            <div class="buttonPG run" id="runButton1024"><img src="css/img/playButton.svg"></div>
+            <div class="buttonPG" id="saveButton1024"><img src="css/img/saveButton.svg"></div>
+            <div class="buttonPG removeOnPhone" id="zipButton1024"><img src="css/img/downloadButton.svg"></div>
+            <div class="buttonPG" id="newButton1024"><img src="css/img/newButton.svg"></div>
+            <div class="buttonPG removeOnPhone" id="clearButton1024"><img src="css/img/clearButton.svg"></div>
+
+            <div class="buttonPG select" id="menuButton1024"><img src="css/img/optionsButton.svg">
                 <div class="toDisplay">
-                    <div class="option subSelect">Theme
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                    <div class="option subSelect">Theme <i class="fa fa-chevron-right" aria-hidden="true"></i>
+
                         <div class="toDisplaySub">
-                            <div class="option" id="darkTheme1030">Dark</div>
-                            <div class="option" id="lightTheme1030">Light</div>
+                            <div class="option selected" id="darkTheme1024">Dark</div>
+                            <div class="option" id="lightTheme1024">Light</div>
                         </div>
                     </div>
-                    <div class="option subSelect">
-                        <span id="currentFontSize1030">Font: 14</span>
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setFontSize(12);">12</div>
-                            <div class="option" onclick="setFontSize(14);">14</div>
-                            <div class="option" onclick="setFontSize(16);">16</div>
-                            <div class="option" onclick="setFontSize(18);">18</div>
-                            <div class="option" onclick="setFontSize(20);">20</div>
-                            <div class="option" onclick="setFontSize(22);">22</div>
+                    <div class="option subSelect">Font size <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                        <div class="toDisplaySub displayFontSize">
+                            <div class="option">12</div>
+                            <div class="option selected">14</div>
+                            <div class="option">16</div>
+                            <div class="option">18</div>
+                            <div class="option">20</div>
+                            <div class="option">22</div>
                         </div>
                     </div>
-                    <div class="option" id="safemodeToggle1030">Safe mode
-                        <i class="far fa-square" aria-hidden="true"></i>
+                    <div class="option noSubSelect" id="safemodeToggle1024">Safe mode
+                        <i class="fa fa-square" aria-hidden="true"></i>
                     </div>
-                    <div class="option checked" id="editorButton1030">Editor
+                    <div class="option checked noSubSelect" id="editorButton1024">Editor
                         <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
-                    <div class="option" id="fullscreenButton1030">Fullscreen</div>
-                    <div class="option" id="editorFullscreenButton1030">Editor Fullscreen</div>
-                    <div class="option" id="formatButton1030">Format code</div>
-                    <div class="option" id="minimapToggle1030">Minimap
-                        <i class="far fa-square" aria-hidden="true"></i>
+                    <div class="option noSubSelect" id="fullscreenButton1024">Fullscreen</div>
+                    <div class="option noSubSelect" id="editorFullscreenButton1024">Editor Fullscreen</div>
+                    <div class="option noSubSelect" id="formatButton1024">Format code</div>
+                    <div class="option noSubSelect" id="minimapToggle1024">Minimap
+                        <i class="fa fa-square" aria-hidden="true"></i>
                     </div>
-                    <div class="option" id="debugButton1030">Inspector</div>
-                    <div class="option" id="metadataButton1030">Metadata</div>
-                    <div class="option subSelect">
-                        <span id="currentVersion1030">Vers. : Latest</span>
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setVersion('latest');">Latest</div>
-                            <div class="option" onclick="setVersion('stable');">Stable</div>
+                    <div class="option subSelect" id="qrCodeHover1024">QR Code Link <i class="fa fa-chevron-right"
+                            aria-hidden="true"></i>
+                        <div class="toDisplaySub qrCodeImage">
+                            <div class="option" id="qrCodeImage1024">[QR Code Image]</div>
                         </div>
                     </div>
+                    <div class="option uncheck noSubSelect" id="debugButton1024">Inspector</div>
+                    <div class="option noSubSelect" id="metadataButton1024">Metadata</div>
                 </div>
             </div>
         </div>
 
         <div class="category right">
-            <div class="button select">
-                <span class="examplesButton">Examples</span>
+            <div class="buttonPG select">
+                <span id="currentVersion1024"></span>
+                <div class="toDisplay currentVersionDisplay" style="display: none">
+                </div>
             </div>
+            <div class="buttonPG select"><img class="examplesButton" src="css/img/examplesButton.svg"></div>
         </div>
     </div>
 
-    <div class="navbar navBar750">
-        <div class="category">
-            <div class="button select">File
+    <!-- Mobile -->
+    <div class="navbar navBarMobile languageJS">
+        <div class="category languageJS" id="JStoTSbar">
+            <div class="buttonPG select" id="menuButtonMobile"><img src="css/img/hamburgerButton.svg">
                 <div class="toDisplay">
-                    <div class="option" id="runButton750">Run
-                        <i class="fa fa-play" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="newButton750">New
-                        <i class="fa fa-file" aria-hidden="true"></i>
+                    <div class="option noSubSelect languageTS" id="toTSbuttonMobile">TypeScript</div>
+                    <div class="option noSubSelect languageJS" id="toJSbuttonMobile">JavaScript</div>
+                    <div class="option noSubSelect run" id="runButtonMobile"><img src="css/img/playButton.svg">Run</div>
+                    <div class="option noSubSelect" id="saveButtonMobile"><img src="css/img/saveButton.svg">Save</div>
+                    <div class="option noSubSelect" id="zipButtonMobile"><img src="css/img/downloadButton.svg">Download
                     </div>
-                    <div class="option" id="clearButton750">Clear
-                        <i class="fa fa-trash" aria-hidden="true"></i>
+                    <div class="option noSubSelect" id="newButtonMobile"><img src="css/img/newButton.svg">New</div>
+                    <div class="option noSubSelect" id="clearButtonMobile"><img src="css/img/clearButton.svg">Clear
                     </div>
-                    <div class="option" id="saveButton750">Save
-                        <i class="fa fa-floppy-o" aria-hidden="true"></i>
+                    <div class="option noSubSelect" id="debugButtonMobile"><img
+                            src="css/img/inspectorButton.svg">Inspector</div>
+                    <div class="option subSelect">
+                        <img src="css/img/optionsButton.svg">
+                        <div id="currentVersionMobile"></div>
+                        <div class="toDisplaySub currentVersionDisplay">
+                        </div>
                     </div>
-                </div>
-            </div>
-        </div>
-
-        <div class="category">
-            <div class="button select">Settings
-                <div class="toDisplay">
-                    <div class="option subSelect">Theme
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                    <div class="option subSelect"><img src="css/img/optionsButton.svg">Theme
                         <div class="toDisplaySub">
-                            <div class="option" id="darkTheme750">Dark</div>
-                            <div class="option" id="lightTheme750">Light</div>
+                            <div class="option selected" id="darkThemeMobile">Dark</div>
+                            <div class="option" id="lightThemeMobile">Light</div>
                         </div>
                     </div>
-                    <div class="option subSelect">
-                        <span id="currentFontSize750">Font: 14</span>
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setFontSize(12);">12</div>
-                            <div class="option" onclick="setFontSize(14);">14</div>
-                            <div class="option" onclick="setFontSize(16);">16</div>
-                            <div class="option" onclick="setFontSize(18);">18</div>
-                            <div class="option" onclick="setFontSize(20);">20</div>
-                            <div class="option" onclick="setFontSize(22);">22</div>
+                    <div class="option subSelect"><img src="css/img/optionsButton.svg">Font size
+                        <div class="toDisplaySub displayFontSize">
+                            <div class="option">8</div>
+                            <div class="option">10</div>
+                            <div class="option selected">12</div>
+                            <div class="option">14</div>
+                            <div class="option">16</div>
+                            <div class="option">18</div>
+                            <div class="option">20</div>
+                            <div class="option">22</div>
                         </div>
                     </div>
-                    <div class="option" id="safemodeToggle750">Safe mode
-                        <i class="far fa-square" aria-hidden="true"></i>
+                    <div style="display: none;" class="option noSubSelect" id="safemodeToggleMobile">Safe mode
+                        <i class="fa fa-square" aria-hidden="true"></i>
                     </div>
-                    <div style="display:none;" class="option checked" id="editorButton750">Editor
+                    <div style="display: none;" class="option checked noSubSelect" id="editorButtonMobile">Editor
                         <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
-                    <div class="option" id="fullscreenButton750">Fullscreen</div>
-                    <div class="option" id="editorFullscreenButton750">Editor Fullscreen</div>
-                    <div class="option" id="formatButton750">Format code</div>
-                    <div class="option" id="minimapToggle750">Minimap
-                        <i class="far fa-square" aria-hidden="true"></i>
+                    <div style="display: none;" class="option nosubselect" id="fullscreenButtonMobile"
+                        style="display: none">Fullscreen</div>
+                    <div style="display: none;" class="option nosubselect" id="editorFullscreenButtonMobile"
+                        style="display: none">Editor
+                        Fullscreen</div>
+                    <div class="option nosubselect" id="formatButtonMobile"><img src="css/img/optionsButton.svg">Format
+                        code</div>
+                    <div style="display: none;" class="option nosubselect" id="minimapToggleMobile">Minimap
+                        <i class="fa fa-square" aria-hidden="true"></i>
                     </div>
-                    <div class="option" id="debugButton750">Inspector</div>
-                    <div class="option" id="metadataButton750">Metadata</div>
-                    <div class="option subSelect">
-                        <span id="currentVersion750">Vers. : Latest</span>
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setVersion('latest');">Latest</div>
-                            <div class="option" onclick="setVersion('stable');">Stable</div>
+                    <!-- <div class="option subSelect" id="qrCodeHoverMobile"><img src="css/img/optionsButton.svg">QR Code Link
+                        <div class="toDisplaySub qrCodeImage">
+                            <div class="option" id="qrCodeImageMobile">[QR Code Image]</div>
+                        </div>
+                    </div> -->
+                    <div class="option nosubselect" id="metadataButtonMobile"><img
+                            src="css/img/metadataButton.svg">Metadata</div>
+                    <div class="option nosubselect"><img class="examplesButton"
+                            src="css/img/examplesButton.svg">Examples</div>
+                    <div class="option subSelect"><img src="css/img/examplesButton.svg">Links / Tools
+                        <div class="toDisplaySub displayFooterLinks">
+                            <div class="option link">
+                                <a target='_new' href="https://www.netlify.com/">Deployed by Netlify</a>
+                            </div>
+                            <div class="option link">
+                                <a target='_new' href="https://forum.babylonjs.com/">Forum</a>
+                            </div>
+                            <div class="option link">
+                                <a target='_new' href="https://www.babylonjs.com/sandbox">Sandbox</a>
+                            </div>
+                            <div class="option link">
+                                <a target='_new' href="https://doc.babylonjs.com">Documentation</a>
+                            </div>
+                            <div class="option link">
+                                <a target='_new' href="https://doc.babylonjs.com/playground">Search</a>
+                            </div>
                         </div>
                     </div>
                 </div>
             </div>
+            <div class="categoryTitle">
+                <img class="logo" src="css/img/logo_v4.svg">
+                <div class="version"><span class="versionSub" id="mainTitleMobile"></span></div>
+            </div>
         </div>
 
-        <div class="category right">
-            <div class="button select">
-                <span class="examplesButton">Examples</span>
-            </div>
+        <div id="switchWrapper" class="languageJS">
+            <img id="switchWrapperCode" src="css/img/codeButton.svg">
+            <img id="switchWrapperCanvas" src="css/img/canvas3Dbutton.svg">
         </div>
     </div>
 
+    <!-- Common things -->
+
     <div class="wrapper">
         <div id="jsEditor"></div>
         <div id="canvasZone">
             <canvas touch-action="none" id="renderCanvas"></canvas>
         </div>
     </div>
-    <div id="exampleList">
-        <div id="exampleBanner">
-            <h1>Examples</h1>
+    <div id="exampleList" class="javascript">
+        <div id="exampleBanner" class="languageJS">
+            <h1>Examples<img id="examplesButtonClose" src="css/img/clearButton.svg"></h1>
         </div>
         <div class="horizontalSeparator"></div>
         <input id="filterBar" type="text" placeholder="Filter examples...">
@@ -399,7 +307,7 @@
             src="https://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
     </div>
 
-    <span class="label" id="fpsLabel">FPS</span>
+    <div class="fpsLabel languageJS" id="fpsLabel"></div>
 
     <div id="errorZone">
     </div>
@@ -426,7 +334,8 @@
     </div>
 
     <div id="saveLayer" class="save-layer">
-        <div class="save-form">
+        <div class="save-form languageJS ">
+            <img id="saveFormButtonClose" src="css/img/clearButton.svg">
             <label for="saveFormTitle">TITLE</label>
             <div class="separator"></div>
             <input type="text" maxlength="120" id="saveFormTitle" class="save-form-title">
@@ -440,24 +349,37 @@
             <textarea id="saveFormTags" rows="4" cols="10"></textarea>
 
             <div class="save-form-buttons" id="saveFormButtons">
-
-                <div id="saveFormButtonOk" class="button">OK</div>
-                <div id="saveFormButtonCancel" class="button">Cancel</div>
+                <div id="saveFormButtonOk">OK</div>
+                <div id="saveFormButtonCancel">Cancel</div>
             </div>
         </div>
     </div>
 
-    <script src="https://code.jquery.com/jquery.js"></script>
+    <div id="waitDiv">
+        <div id="logo-part">
+            <img src="css/img/v4.svg" id="waitLogo" />
+            <img src="css/img/spinner.svg" id="waitSpinner" />
+        </div>
+    </div>
+
+    <!-- jQuery -->
+    <script src="js/libs/jquery.min.js"></script>
     <script src="js/jquery.qrcode.js"></script>
     <script src="js/qrcode.js"></script>
 
-    <script>
-        Split(['#jsEditor', '#canvasZone']);
-    </script>
-
-    <script src="js/actions.js"></script>
+    <!-- Main scripts -->
+    <script src="js/config_versions.js"></script>
     <script src="js/pbt.js"></script>
-    <script src="js/indexWebGPU.js"></script>
+    <script src="js/libs/typescript.js"></script>
+    <script src="js/examples.js"></script>
+    <!-- <script src="js/main.js"></script> -->
+    <script src="js/mainWebGPU.js"></script>
+    <script src="js/menuPG.js"></script>
+    <script src="js/monacoCreator.js"></script>
+    <script src="js/settingsPG.js"></script>
+    <script src="js/utils.js"></script>
+    <script src="js/zipTool.js"></script>
+    <script src="js/index.js"></script>
 
     <!-- Global site tag (gtag.js) - Google Analytics -->
     <script async src="https://www.googletagmanager.com/gtag/js?id=UA-41767310-2"></script>
@@ -470,4 +392,4 @@
     </script>
 </body>
 
-</html>
+</html>

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 1263
Playground/js/indexWebGPU.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 860 - 0
Playground/js/mainWebGPU.js


+ 2 - 2
Playground/js/monacoCreator.js

@@ -48,10 +48,10 @@ class MonacoCreator {
     /**
      * Load the Monaco Node module.
      */
-    loadMonaco() {
+    loadMonaco(typings) {
         var xhr = new XMLHttpRequest();
 
-        xhr.open('GET', "babylon.d.txt", true);
+        xhr.open('GET', typings || "babylon.d.txt", true);
 
         xhr.onreadystatechange = function () {
             if (xhr.readyState === 4) {

+ 138 - 57
dist/preview release/babylon.d.ts

@@ -7610,6 +7610,8 @@ declare module BABYLON {
         /** @hidden */
         _areLightsDirty: boolean;
         /** @hidden */
+        _areLightsDisposed: boolean;
+        /** @hidden */
         _areAttributesDirty: boolean;
         /** @hidden */
         _areTexturesDirty: boolean;
@@ -7650,8 +7652,9 @@ declare module BABYLON {
         markAsImageProcessingDirty(): void;
         /**
          * Marks the material to indicate the lights need to be re-calculated
+         * @param disposed Defines whether the light is dirty due to dispose or not
          */
-        markAsLightDirty(): void;
+        markAsLightDirty(disposed?: boolean): void;
         /**
          * Marks the attribute state as changed
          */
@@ -8955,8 +8958,9 @@ declare module BABYLON {
          * @param effect The effect we are binding the data to
          * @param useSpecular Defines if specular is supported
          * @param usePhysicalLightFalloff Specifies whether the light falloff is defined physically or not
+         * @param rebuildInParallel Specifies whether the shader is rebuilding in parallel
          */
-        static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff?: boolean): void;
+        static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff?: boolean, rebuildInParallel?: boolean): void;
         /**
          * Binds the lights information from the scene to the effect for the given mesh.
          * @param scene The scene the lights belongs to
@@ -8965,8 +8969,9 @@ declare module BABYLON {
          * @param defines The generated defines for the effect
          * @param maxSimultaneousLights The maximum number of light that can be bound to the effect
          * @param usePhysicalLightFalloff Specifies whether the light falloff is defined physically or not
+         * @param rebuildInParallel Specifies whether the shader is rebuilding in parallel
          */
-        static BindLights(scene: Scene, mesh: AbstractMesh, effect: Effect, defines: any, maxSimultaneousLights?: number, usePhysicalLightFalloff?: boolean): void;
+        static BindLights(scene: Scene, mesh: AbstractMesh, effect: Effect, defines: any, maxSimultaneousLights?: number, usePhysicalLightFalloff?: boolean, rebuildInParallel?: boolean): void;
         private static _tempFogColor;
         /**
          * Binds the fog information from the scene to the effect for the given mesh.
@@ -18587,7 +18592,7 @@ declare module BABYLON {
         readonly lightSources: Light[];
         _resyncLightSources(): void;
         _resyncLighSource(light: Light): void;
-        _removeLightSource(light: Light): void;
+        _removeLightSource(light: Light, dispose: boolean): void;
         /**
          * If the source mesh receives shadows
          */
@@ -25907,10 +25912,10 @@ declare module BABYLON {
         /** @hidden */
         _unBindEffect(): void;
         /** @hidden */
-        _removeLightSource(light: Light): void;
+        _removeLightSource(light: Light, dispose: boolean): void;
         private _markSubMeshesAsDirty;
         /** @hidden */
-        _markSubMeshesAsLightDirty(): void;
+        _markSubMeshesAsLightDirty(dispose?: boolean): void;
         /** @hidden */
         _markSubMeshesAsAttributesDirty(): void;
         /** @hidden */
@@ -29480,6 +29485,7 @@ declare module BABYLON {
         private _displayingPosterTexture;
         private _settings;
         private _createInternalTextureOnEvent;
+        private _frameId;
         /**
          * Creates a video texture.
          * If you want to display a video in your scene, this is the special texture for that.
@@ -40217,6 +40223,7 @@ declare module BABYLON {
         protected _worldViewProjectionMatrix: Matrix;
         protected _globalAmbientColor: Color3;
         protected _useLogarithmicDepth: boolean;
+        protected _rebuildInParallel: boolean;
         /**
          * Instantiates a new standard material.
          * This is the default material used in Babylon. It is the best trade off between quality
@@ -46893,6 +46900,7 @@ declare module BABYLON {
          * Custom callback helping to override the default shader used in the material.
          */
         customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: PBRMaterialDefines) => string;
+        protected _rebuildInParallel: boolean;
         /**
          * Instantiates a new PBRMaterial instance.
          *
@@ -51717,6 +51725,7 @@ declare module BABYLON {
         protected _buildBlock(state: NodeMaterialBuildState): this;
         serialize(): any;
         _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
+        protected _dumpPropertiesCode(): string;
     }
 }
 declare module BABYLON {
@@ -51872,7 +51881,7 @@ declare module BABYLON {
          * Gets the b output component
          */
         readonly b: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         isReady(): boolean;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
@@ -52017,6 +52026,18 @@ declare module BABYLON {
          */
         getBlockByName(name: string): Nullable<NodeMaterialBlock>;
         /**
+         * Get a block by its name
+         * @param predicate defines the predicate used to find the good candidate
+         * @returns the required block or null if not found
+         */
+        getBlockByPredicate(predicate: (block: NodeMaterialBlock) => boolean): Nullable<NodeMaterialBlock>;
+        /**
+         * Get an input block by its name
+         * @param predicate defines the predicate used to find the good candidate
+         * @returns the required input block or null if not found
+         */
+        getInputBlockByPredicate(predicate: (block: InputBlock) => boolean): Nullable<InputBlock>;
+        /**
          * Gets the list of input blocks attached to this material
          * @returns an array of InputBlocks
          */
@@ -52231,7 +52252,7 @@ declare module BABYLON {
          */
         readonly a: NodeMaterialConnectionPoint;
         readonly target: NodeMaterialBlockTargets;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         initializeDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         isReady(): boolean;
@@ -52628,6 +52649,7 @@ declare module BABYLON {
          * @returns true if the block is ready
          */
         isReady(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): boolean;
+        protected _linkConnectionTypes(inputIndex0: number, inputIndex1: number): void;
         private _processBuild;
         /**
          * Compile the current node and generate the shader code
@@ -52809,6 +52831,8 @@ declare module BABYLON {
         private _associatedVariableName;
         /** @hidden */
         _typeConnectionSource: Nullable<NodeMaterialConnectionPoint>;
+        /** @hidden */
+        _linkedConnectionSource: Nullable<NodeMaterialConnectionPoint>;
         private _type;
         /** @hidden */
         _enforceAssociatedVariableName: boolean;
@@ -52882,9 +52906,10 @@ declare module BABYLON {
         /**
          * Connect this point to another connection point
          * @param connectionPoint defines the other connection point
+         * @param ignoreConstraints defines if the system will ignore connection type constraints (default is false)
          * @returns the current connection point
          */
-        connectTo(connectionPoint: NodeMaterialConnectionPoint): NodeMaterialConnectionPoint;
+        connectTo(connectionPoint: NodeMaterialConnectionPoint, ignoreConstraints?: boolean): NodeMaterialConnectionPoint;
         /**
          * Disconnect this point from one of his endpoint
          * @param endpoint defines the other connection point
@@ -52942,7 +52967,7 @@ declare module BABYLON {
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         provideFallbacks(mesh: AbstractMesh, fallbacks: EffectFallbacks): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
@@ -52989,7 +53014,7 @@ declare module BABYLON {
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         protected _buildBlock(state: NodeMaterialBuildState): this;
     }
@@ -53044,7 +53069,7 @@ declare module BABYLON {
          */
         readonly uvOutput: NodeMaterialConnectionPoint;
         initialize(state: NodeMaterialBuildState): void;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         replaceRepeatableContent(vertexShaderState: NodeMaterialBuildState, fragmentShaderState: NodeMaterialBuildState, mesh: AbstractMesh, defines: NodeMaterialDefines): void;
@@ -53079,49 +53104,9 @@ declare module BABYLON {
          */
         readonly alpha: NodeMaterialConnectionPoint;
         protected _buildBlock(state: NodeMaterialBuildState): this;
-    }
-}
-declare module BABYLON {
-    /**
-     * Block used to compute fresnel value
-     */
-    export class FresnelBlock extends NodeMaterialBlock {
-        /**
-         * Create a new FresnelBlock
-         * @param name defines the block name
-         */
-        constructor(name: string);
-        /**
-         * Gets the current class name
-         * @returns the class name
-         */
-        getClassName(): string;
-        /**
-         * Gets the world position input component
-         */
-        readonly worldPosition: NodeMaterialConnectionPoint;
-        /**
-         * Gets the world normal input component
-         */
-        readonly worldNormal: NodeMaterialConnectionPoint;
-        /**
-        * Gets the camera (or eye) position component
-        */
-        readonly cameraPosition: NodeMaterialConnectionPoint;
-        /**
-        * Gets the bias input component
-        */
-        readonly bias: NodeMaterialConnectionPoint;
-        /**
-        * Gets the camera (or eye) position component
-        */
-        readonly power: NodeMaterialConnectionPoint;
-        /**
-         * Gets the fresnel output component
-         */
-        readonly fresnel: NodeMaterialConnectionPoint;
-        autoConfigure(material: NodeMaterial): void;
-        protected _buildBlock(state: NodeMaterialBuildState): this | undefined;
+        protected _dumpPropertiesCode(): string;
+        serialize(): any;
+        _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
     }
 }
 declare module BABYLON {
@@ -53195,7 +53180,7 @@ declare module BABYLON {
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         protected _buildBlock(state: NodeMaterialBuildState): this;
@@ -53241,7 +53226,7 @@ declare module BABYLON {
          * Gets the specular output component
          */
         readonly specularOutput: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
@@ -53866,6 +53851,102 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * Block used to get the opposite of a value
+     */
+    export class OppositeBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new OppositeBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the input component
+         */
+        readonly input: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to get the view direction
+     */
+    export class ViewDirectionBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new ViewDirectionBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world position component
+         */
+        readonly worldPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the camera position component
+         */
+        readonly cameraPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to compute fresnel value
+     */
+    export class FresnelBlock extends NodeMaterialBlock {
+        /**
+         * Create a new FresnelBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world normal input component
+         */
+        readonly worldNormal: NodeMaterialConnectionPoint;
+        /**
+        * Gets the view direction input component
+        */
+        readonly viewDirection: NodeMaterialConnectionPoint;
+        /**
+        * Gets the bias input component
+        */
+        readonly bias: NodeMaterialConnectionPoint;
+        /**
+        * Gets the camera (or eye) position component
+        */
+        readonly power: NodeMaterialConnectionPoint;
+        /**
+         * Gets the fresnel output component
+         */
+        readonly fresnel: NodeMaterialConnectionPoint;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
      * Effect Render Options
      */
     export interface IEffectRendererOptions {

Diferenças do arquivo suprimidas por serem muito extensas
+ 2 - 2
dist/preview release/babylon.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 649 - 315
dist/preview release/babylon.max.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 1
dist/preview release/babylon.max.js.map


+ 291 - 119
dist/preview release/babylon.module.d.ts

@@ -7688,6 +7688,8 @@ declare module "babylonjs/Materials/materialDefines" {
         /** @hidden */
         _areLightsDirty: boolean;
         /** @hidden */
+        _areLightsDisposed: boolean;
+        /** @hidden */
         _areAttributesDirty: boolean;
         /** @hidden */
         _areTexturesDirty: boolean;
@@ -7728,8 +7730,9 @@ declare module "babylonjs/Materials/materialDefines" {
         markAsImageProcessingDirty(): void;
         /**
          * Marks the material to indicate the lights need to be re-calculated
+         * @param disposed Defines whether the light is dirty due to dispose or not
          */
-        markAsLightDirty(): void;
+        markAsLightDirty(disposed?: boolean): void;
         /**
          * Marks the attribute state as changed
          */
@@ -9063,8 +9066,9 @@ declare module "babylonjs/Materials/materialHelper" {
          * @param effect The effect we are binding the data to
          * @param useSpecular Defines if specular is supported
          * @param usePhysicalLightFalloff Specifies whether the light falloff is defined physically or not
+         * @param rebuildInParallel Specifies whether the shader is rebuilding in parallel
          */
-        static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff?: boolean): void;
+        static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff?: boolean, rebuildInParallel?: boolean): void;
         /**
          * Binds the lights information from the scene to the effect for the given mesh.
          * @param scene The scene the lights belongs to
@@ -9073,8 +9077,9 @@ declare module "babylonjs/Materials/materialHelper" {
          * @param defines The generated defines for the effect
          * @param maxSimultaneousLights The maximum number of light that can be bound to the effect
          * @param usePhysicalLightFalloff Specifies whether the light falloff is defined physically or not
+         * @param rebuildInParallel Specifies whether the shader is rebuilding in parallel
          */
-        static BindLights(scene: Scene, mesh: AbstractMesh, effect: Effect, defines: any, maxSimultaneousLights?: number, usePhysicalLightFalloff?: boolean): void;
+        static BindLights(scene: Scene, mesh: AbstractMesh, effect: Effect, defines: any, maxSimultaneousLights?: number, usePhysicalLightFalloff?: boolean, rebuildInParallel?: boolean): void;
         private static _tempFogColor;
         /**
          * Binds the fog information from the scene to the effect for the given mesh.
@@ -19082,7 +19087,7 @@ declare module "babylonjs/Meshes/instancedMesh" {
         readonly lightSources: Light[];
         _resyncLightSources(): void;
         _resyncLighSource(light: Light): void;
-        _removeLightSource(light: Light): void;
+        _removeLightSource(light: Light, dispose: boolean): void;
         /**
          * If the source mesh receives shadows
          */
@@ -26653,10 +26658,10 @@ declare module "babylonjs/Meshes/abstractMesh" {
         /** @hidden */
         _unBindEffect(): void;
         /** @hidden */
-        _removeLightSource(light: Light): void;
+        _removeLightSource(light: Light, dispose: boolean): void;
         private _markSubMeshesAsDirty;
         /** @hidden */
-        _markSubMeshesAsLightDirty(): void;
+        _markSubMeshesAsLightDirty(dispose?: boolean): void;
         /** @hidden */
         _markSubMeshesAsAttributesDirty(): void;
         /** @hidden */
@@ -30318,6 +30323,7 @@ declare module "babylonjs/Materials/Textures/videoTexture" {
         private _displayingPosterTexture;
         private _settings;
         private _createInternalTextureOnEvent;
+        private _frameId;
         /**
          * Creates a video texture.
          * If you want to display a video in your scene, this is the special texture for that.
@@ -41591,6 +41597,7 @@ declare module "babylonjs/Materials/standardMaterial" {
         protected _worldViewProjectionMatrix: Matrix;
         protected _globalAmbientColor: Color3;
         protected _useLogarithmicDepth: boolean;
+        protected _rebuildInParallel: boolean;
         /**
          * Instantiates a new standard material.
          * This is the default material used in Babylon. It is the best trade off between quality
@@ -48910,6 +48917,7 @@ declare module "babylonjs/Materials/PBR/pbrBaseMaterial" {
          * Custom callback helping to override the default shader used in the material.
          */
         customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: PBRMaterialDefines) => string;
+        protected _rebuildInParallel: boolean;
         /**
          * Instantiates a new PBRMaterial instance.
          *
@@ -54113,6 +54121,7 @@ declare module "babylonjs/Materials/Node/Blocks/transformBlock" {
         protected _buildBlock(state: NodeMaterialBuildState): this;
         serialize(): any;
         _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
+        protected _dumpPropertiesCode(): string;
     }
 }
 declare module "babylonjs/Materials/Node/Blocks/Vertex/vertexOutputBlock" {
@@ -54284,7 +54293,7 @@ declare module "babylonjs/Materials/Node/Blocks/Dual/reflectionTextureBlock" {
          * Gets the b output component
          */
         readonly b: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         isReady(): boolean;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
@@ -54445,6 +54454,18 @@ declare module "babylonjs/Materials/Node/nodeMaterial" {
          */
         getBlockByName(name: string): Nullable<NodeMaterialBlock>;
         /**
+         * Get a block by its name
+         * @param predicate defines the predicate used to find the good candidate
+         * @returns the required block or null if not found
+         */
+        getBlockByPredicate(predicate: (block: NodeMaterialBlock) => boolean): Nullable<NodeMaterialBlock>;
+        /**
+         * Get an input block by its name
+         * @param predicate defines the predicate used to find the good candidate
+         * @returns the required input block or null if not found
+         */
+        getInputBlockByPredicate(predicate: (block: InputBlock) => boolean): Nullable<InputBlock>;
+        /**
          * Gets the list of input blocks attached to this material
          * @returns an array of InputBlocks
          */
@@ -54670,7 +54691,7 @@ declare module "babylonjs/Materials/Node/Blocks/Dual/textureBlock" {
          */
         readonly a: NodeMaterialConnectionPoint;
         readonly target: NodeMaterialBlockTargets;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         initializeDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         isReady(): boolean;
@@ -55085,6 +55106,7 @@ declare module "babylonjs/Materials/Node/nodeMaterialBlock" {
          * @returns true if the block is ready
          */
         isReady(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): boolean;
+        protected _linkConnectionTypes(inputIndex0: number, inputIndex1: number): void;
         private _processBuild;
         /**
          * Compile the current node and generate the shader code
@@ -55282,6 +55304,8 @@ declare module "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint" {
         private _associatedVariableName;
         /** @hidden */
         _typeConnectionSource: Nullable<NodeMaterialConnectionPoint>;
+        /** @hidden */
+        _linkedConnectionSource: Nullable<NodeMaterialConnectionPoint>;
         private _type;
         /** @hidden */
         _enforceAssociatedVariableName: boolean;
@@ -55355,9 +55379,10 @@ declare module "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint" {
         /**
          * Connect this point to another connection point
          * @param connectionPoint defines the other connection point
+         * @param ignoreConstraints defines if the system will ignore connection type constraints (default is false)
          * @returns the current connection point
          */
-        connectTo(connectionPoint: NodeMaterialConnectionPoint): NodeMaterialConnectionPoint;
+        connectTo(connectionPoint: NodeMaterialConnectionPoint, ignoreConstraints?: boolean): NodeMaterialConnectionPoint;
         /**
          * Disconnect this point from one of his endpoint
          * @param endpoint defines the other connection point
@@ -55422,7 +55447,7 @@ declare module "babylonjs/Materials/Node/Blocks/Vertex/bonesBlock" {
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         provideFallbacks(mesh: AbstractMesh, fallbacks: EffectFallbacks): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
@@ -55474,7 +55499,7 @@ declare module "babylonjs/Materials/Node/Blocks/Vertex/instancesBlock" {
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         protected _buildBlock(state: NodeMaterialBuildState): this;
     }
@@ -55536,7 +55561,7 @@ declare module "babylonjs/Materials/Node/Blocks/Vertex/morphTargetsBlock" {
          */
         readonly uvOutput: NodeMaterialConnectionPoint;
         initialize(state: NodeMaterialBuildState): void;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         replaceRepeatableContent(vertexShaderState: NodeMaterialBuildState, fragmentShaderState: NodeMaterialBuildState, mesh: AbstractMesh, defines: NodeMaterialDefines): void;
@@ -55553,6 +55578,7 @@ declare module "babylonjs/Materials/Node/Blocks/Fragment/alphaTestBlock" {
     import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
     import { NodeMaterialBuildState } from "babylonjs/Materials/Node/nodeMaterialBuildState";
     import { NodeMaterialConnectionPoint } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint";
+    import { Scene } from "babylonjs/scene";
     /**
      * Block used to add an alpha test in the fragment shader
      */
@@ -55580,53 +55606,9 @@ declare module "babylonjs/Materials/Node/Blocks/Fragment/alphaTestBlock" {
          */
         readonly alpha: NodeMaterialConnectionPoint;
         protected _buildBlock(state: NodeMaterialBuildState): this;
-    }
-}
-declare module "babylonjs/Materials/Node/Blocks/Fragment/fresnelBlock" {
-    import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
-    import { NodeMaterialBuildState } from "babylonjs/Materials/Node/nodeMaterialBuildState";
-    import { NodeMaterialConnectionPoint } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint";
-    import { NodeMaterial } from "babylonjs/Materials/Node/nodeMaterial";
-    /**
-     * Block used to compute fresnel value
-     */
-    export class FresnelBlock extends NodeMaterialBlock {
-        /**
-         * Create a new FresnelBlock
-         * @param name defines the block name
-         */
-        constructor(name: string);
-        /**
-         * Gets the current class name
-         * @returns the class name
-         */
-        getClassName(): string;
-        /**
-         * Gets the world position input component
-         */
-        readonly worldPosition: NodeMaterialConnectionPoint;
-        /**
-         * Gets the world normal input component
-         */
-        readonly worldNormal: NodeMaterialConnectionPoint;
-        /**
-        * Gets the camera (or eye) position component
-        */
-        readonly cameraPosition: NodeMaterialConnectionPoint;
-        /**
-        * Gets the bias input component
-        */
-        readonly bias: NodeMaterialConnectionPoint;
-        /**
-        * Gets the camera (or eye) position component
-        */
-        readonly power: NodeMaterialConnectionPoint;
-        /**
-         * Gets the fresnel output component
-         */
-        readonly fresnel: NodeMaterialConnectionPoint;
-        autoConfigure(material: NodeMaterial): void;
-        protected _buildBlock(state: NodeMaterialBuildState): this | undefined;
+        protected _dumpPropertiesCode(): string;
+        serialize(): any;
+        _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
     }
 }
 declare module "babylonjs/Materials/Node/Blocks/Fragment/imageProcessingBlock" {
@@ -55673,7 +55655,6 @@ declare module "babylonjs/Materials/Node/Blocks/Fragment/imageProcessingBlock" {
 declare module "babylonjs/Materials/Node/Blocks/Fragment/index" {
     export * from "babylonjs/Materials/Node/Blocks/Fragment/fragmentOutputBlock";
     export * from "babylonjs/Materials/Node/Blocks/Fragment/alphaTestBlock";
-    export * from "babylonjs/Materials/Node/Blocks/Fragment/fresnelBlock";
     export * from "babylonjs/Materials/Node/Blocks/Fragment/imageProcessingBlock";
 }
 declare module "babylonjs/Materials/Node/Blocks/Dual/fogBlock" {
@@ -55720,7 +55701,7 @@ declare module "babylonjs/Materials/Node/Blocks/Dual/fogBlock" {
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         protected _buildBlock(state: NodeMaterialBuildState): this;
@@ -55776,7 +55757,7 @@ declare module "babylonjs/Materials/Node/Blocks/Dual/lightBlock" {
          * Gets the specular output component
          */
         readonly specularOutput: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
@@ -56463,6 +56444,113 @@ declare module "babylonjs/Materials/Node/Blocks/stepBlock" {
         protected _buildBlock(state: NodeMaterialBuildState): this;
     }
 }
+declare module "babylonjs/Materials/Node/Blocks/oppositeBlock" {
+    import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
+    import { NodeMaterialBuildState } from "babylonjs/Materials/Node/nodeMaterialBuildState";
+    import { NodeMaterialConnectionPoint } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint";
+    /**
+     * Block used to get the opposite of a value
+     */
+    export class OppositeBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new OppositeBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the input component
+         */
+        readonly input: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module "babylonjs/Materials/Node/Blocks/viewDirectionBlock" {
+    import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
+    import { NodeMaterialBuildState } from "babylonjs/Materials/Node/nodeMaterialBuildState";
+    import { NodeMaterialConnectionPoint } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint";
+    import { NodeMaterial } from "babylonjs/Materials/Node/nodeMaterial";
+    /**
+     * Block used to get the view direction
+     */
+    export class ViewDirectionBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new ViewDirectionBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world position component
+         */
+        readonly worldPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the camera position component
+         */
+        readonly cameraPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module "babylonjs/Materials/Node/Blocks/fresnelBlock" {
+    import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
+    import { NodeMaterialBuildState } from "babylonjs/Materials/Node/nodeMaterialBuildState";
+    import { NodeMaterialConnectionPoint } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint";
+    import { NodeMaterial } from "babylonjs/Materials/Node/nodeMaterial";
+    /**
+     * Block used to compute fresnel value
+     */
+    export class FresnelBlock extends NodeMaterialBlock {
+        /**
+         * Create a new FresnelBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world normal input component
+         */
+        readonly worldNormal: NodeMaterialConnectionPoint;
+        /**
+        * Gets the view direction input component
+        */
+        readonly viewDirection: NodeMaterialConnectionPoint;
+        /**
+        * Gets the bias input component
+        */
+        readonly bias: NodeMaterialConnectionPoint;
+        /**
+        * Gets the camera (or eye) position component
+        */
+        readonly power: NodeMaterialConnectionPoint;
+        /**
+         * Gets the fresnel output component
+         */
+        readonly fresnel: NodeMaterialConnectionPoint;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
 declare module "babylonjs/Materials/Node/Blocks/index" {
     export * from "babylonjs/Materials/Node/Blocks/Vertex/index";
     export * from "babylonjs/Materials/Node/Blocks/Fragment/index";
@@ -56486,6 +56574,9 @@ declare module "babylonjs/Materials/Node/Blocks/index" {
     export * from "babylonjs/Materials/Node/Blocks/divideBlock";
     export * from "babylonjs/Materials/Node/Blocks/subtractBlock";
     export * from "babylonjs/Materials/Node/Blocks/stepBlock";
+    export * from "babylonjs/Materials/Node/Blocks/oppositeBlock";
+    export * from "babylonjs/Materials/Node/Blocks/viewDirectionBlock";
+    export * from "babylonjs/Materials/Node/Blocks/fresnelBlock";
 }
 declare module "babylonjs/Materials/Node/Optimizers/index" {
     export * from "babylonjs/Materials/Node/Optimizers/nodeMaterialOptimizer";
@@ -72520,6 +72611,8 @@ declare module BABYLON {
         /** @hidden */
         _areLightsDirty: boolean;
         /** @hidden */
+        _areLightsDisposed: boolean;
+        /** @hidden */
         _areAttributesDirty: boolean;
         /** @hidden */
         _areTexturesDirty: boolean;
@@ -72560,8 +72653,9 @@ declare module BABYLON {
         markAsImageProcessingDirty(): void;
         /**
          * Marks the material to indicate the lights need to be re-calculated
+         * @param disposed Defines whether the light is dirty due to dispose or not
          */
-        markAsLightDirty(): void;
+        markAsLightDirty(disposed?: boolean): void;
         /**
          * Marks the attribute state as changed
          */
@@ -73865,8 +73959,9 @@ declare module BABYLON {
          * @param effect The effect we are binding the data to
          * @param useSpecular Defines if specular is supported
          * @param usePhysicalLightFalloff Specifies whether the light falloff is defined physically or not
+         * @param rebuildInParallel Specifies whether the shader is rebuilding in parallel
          */
-        static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff?: boolean): void;
+        static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff?: boolean, rebuildInParallel?: boolean): void;
         /**
          * Binds the lights information from the scene to the effect for the given mesh.
          * @param scene The scene the lights belongs to
@@ -73875,8 +73970,9 @@ declare module BABYLON {
          * @param defines The generated defines for the effect
          * @param maxSimultaneousLights The maximum number of light that can be bound to the effect
          * @param usePhysicalLightFalloff Specifies whether the light falloff is defined physically or not
+         * @param rebuildInParallel Specifies whether the shader is rebuilding in parallel
          */
-        static BindLights(scene: Scene, mesh: AbstractMesh, effect: Effect, defines: any, maxSimultaneousLights?: number, usePhysicalLightFalloff?: boolean): void;
+        static BindLights(scene: Scene, mesh: AbstractMesh, effect: Effect, defines: any, maxSimultaneousLights?: number, usePhysicalLightFalloff?: boolean, rebuildInParallel?: boolean): void;
         private static _tempFogColor;
         /**
          * Binds the fog information from the scene to the effect for the given mesh.
@@ -83497,7 +83593,7 @@ declare module BABYLON {
         readonly lightSources: Light[];
         _resyncLightSources(): void;
         _resyncLighSource(light: Light): void;
-        _removeLightSource(light: Light): void;
+        _removeLightSource(light: Light, dispose: boolean): void;
         /**
          * If the source mesh receives shadows
          */
@@ -90817,10 +90913,10 @@ declare module BABYLON {
         /** @hidden */
         _unBindEffect(): void;
         /** @hidden */
-        _removeLightSource(light: Light): void;
+        _removeLightSource(light: Light, dispose: boolean): void;
         private _markSubMeshesAsDirty;
         /** @hidden */
-        _markSubMeshesAsLightDirty(): void;
+        _markSubMeshesAsLightDirty(dispose?: boolean): void;
         /** @hidden */
         _markSubMeshesAsAttributesDirty(): void;
         /** @hidden */
@@ -94390,6 +94486,7 @@ declare module BABYLON {
         private _displayingPosterTexture;
         private _settings;
         private _createInternalTextureOnEvent;
+        private _frameId;
         /**
          * Creates a video texture.
          * If you want to display a video in your scene, this is the special texture for that.
@@ -105127,6 +105224,7 @@ declare module BABYLON {
         protected _worldViewProjectionMatrix: Matrix;
         protected _globalAmbientColor: Color3;
         protected _useLogarithmicDepth: boolean;
+        protected _rebuildInParallel: boolean;
         /**
          * Instantiates a new standard material.
          * This is the default material used in Babylon. It is the best trade off between quality
@@ -111803,6 +111901,7 @@ declare module BABYLON {
          * Custom callback helping to override the default shader used in the material.
          */
         customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: PBRMaterialDefines) => string;
+        protected _rebuildInParallel: boolean;
         /**
          * Instantiates a new PBRMaterial instance.
          *
@@ -116627,6 +116726,7 @@ declare module BABYLON {
         protected _buildBlock(state: NodeMaterialBuildState): this;
         serialize(): any;
         _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
+        protected _dumpPropertiesCode(): string;
     }
 }
 declare module BABYLON {
@@ -116782,7 +116882,7 @@ declare module BABYLON {
          * Gets the b output component
          */
         readonly b: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         isReady(): boolean;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
@@ -116927,6 +117027,18 @@ declare module BABYLON {
          */
         getBlockByName(name: string): Nullable<NodeMaterialBlock>;
         /**
+         * Get a block by its name
+         * @param predicate defines the predicate used to find the good candidate
+         * @returns the required block or null if not found
+         */
+        getBlockByPredicate(predicate: (block: NodeMaterialBlock) => boolean): Nullable<NodeMaterialBlock>;
+        /**
+         * Get an input block by its name
+         * @param predicate defines the predicate used to find the good candidate
+         * @returns the required input block or null if not found
+         */
+        getInputBlockByPredicate(predicate: (block: InputBlock) => boolean): Nullable<InputBlock>;
+        /**
          * Gets the list of input blocks attached to this material
          * @returns an array of InputBlocks
          */
@@ -117141,7 +117253,7 @@ declare module BABYLON {
          */
         readonly a: NodeMaterialConnectionPoint;
         readonly target: NodeMaterialBlockTargets;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         initializeDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         isReady(): boolean;
@@ -117538,6 +117650,7 @@ declare module BABYLON {
          * @returns true if the block is ready
          */
         isReady(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): boolean;
+        protected _linkConnectionTypes(inputIndex0: number, inputIndex1: number): void;
         private _processBuild;
         /**
          * Compile the current node and generate the shader code
@@ -117719,6 +117832,8 @@ declare module BABYLON {
         private _associatedVariableName;
         /** @hidden */
         _typeConnectionSource: Nullable<NodeMaterialConnectionPoint>;
+        /** @hidden */
+        _linkedConnectionSource: Nullable<NodeMaterialConnectionPoint>;
         private _type;
         /** @hidden */
         _enforceAssociatedVariableName: boolean;
@@ -117792,9 +117907,10 @@ declare module BABYLON {
         /**
          * Connect this point to another connection point
          * @param connectionPoint defines the other connection point
+         * @param ignoreConstraints defines if the system will ignore connection type constraints (default is false)
          * @returns the current connection point
          */
-        connectTo(connectionPoint: NodeMaterialConnectionPoint): NodeMaterialConnectionPoint;
+        connectTo(connectionPoint: NodeMaterialConnectionPoint, ignoreConstraints?: boolean): NodeMaterialConnectionPoint;
         /**
          * Disconnect this point from one of his endpoint
          * @param endpoint defines the other connection point
@@ -117852,7 +117968,7 @@ declare module BABYLON {
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         provideFallbacks(mesh: AbstractMesh, fallbacks: EffectFallbacks): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
@@ -117899,7 +118015,7 @@ declare module BABYLON {
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         protected _buildBlock(state: NodeMaterialBuildState): this;
     }
@@ -117954,7 +118070,7 @@ declare module BABYLON {
          */
         readonly uvOutput: NodeMaterialConnectionPoint;
         initialize(state: NodeMaterialBuildState): void;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         replaceRepeatableContent(vertexShaderState: NodeMaterialBuildState, fragmentShaderState: NodeMaterialBuildState, mesh: AbstractMesh, defines: NodeMaterialDefines): void;
@@ -117989,49 +118105,9 @@ declare module BABYLON {
          */
         readonly alpha: NodeMaterialConnectionPoint;
         protected _buildBlock(state: NodeMaterialBuildState): this;
-    }
-}
-declare module BABYLON {
-    /**
-     * Block used to compute fresnel value
-     */
-    export class FresnelBlock extends NodeMaterialBlock {
-        /**
-         * Create a new FresnelBlock
-         * @param name defines the block name
-         */
-        constructor(name: string);
-        /**
-         * Gets the current class name
-         * @returns the class name
-         */
-        getClassName(): string;
-        /**
-         * Gets the world position input component
-         */
-        readonly worldPosition: NodeMaterialConnectionPoint;
-        /**
-         * Gets the world normal input component
-         */
-        readonly worldNormal: NodeMaterialConnectionPoint;
-        /**
-        * Gets the camera (or eye) position component
-        */
-        readonly cameraPosition: NodeMaterialConnectionPoint;
-        /**
-        * Gets the bias input component
-        */
-        readonly bias: NodeMaterialConnectionPoint;
-        /**
-        * Gets the camera (or eye) position component
-        */
-        readonly power: NodeMaterialConnectionPoint;
-        /**
-         * Gets the fresnel output component
-         */
-        readonly fresnel: NodeMaterialConnectionPoint;
-        autoConfigure(material: NodeMaterial): void;
-        protected _buildBlock(state: NodeMaterialBuildState): this | undefined;
+        protected _dumpPropertiesCode(): string;
+        serialize(): any;
+        _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
     }
 }
 declare module BABYLON {
@@ -118105,7 +118181,7 @@ declare module BABYLON {
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         protected _buildBlock(state: NodeMaterialBuildState): this;
@@ -118151,7 +118227,7 @@ declare module BABYLON {
          * Gets the specular output component
          */
         readonly specularOutput: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
@@ -118776,6 +118852,102 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * Block used to get the opposite of a value
+     */
+    export class OppositeBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new OppositeBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the input component
+         */
+        readonly input: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to get the view direction
+     */
+    export class ViewDirectionBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new ViewDirectionBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world position component
+         */
+        readonly worldPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the camera position component
+         */
+        readonly cameraPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to compute fresnel value
+     */
+    export class FresnelBlock extends NodeMaterialBlock {
+        /**
+         * Create a new FresnelBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world normal input component
+         */
+        readonly worldNormal: NodeMaterialConnectionPoint;
+        /**
+        * Gets the view direction input component
+        */
+        readonly viewDirection: NodeMaterialConnectionPoint;
+        /**
+        * Gets the bias input component
+        */
+        readonly bias: NodeMaterialConnectionPoint;
+        /**
+        * Gets the camera (or eye) position component
+        */
+        readonly power: NodeMaterialConnectionPoint;
+        /**
+         * Gets the fresnel output component
+         */
+        readonly fresnel: NodeMaterialConnectionPoint;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
      * Effect Render Options
      */
     export interface IEffectRendererOptions {

+ 138 - 57
dist/preview release/documentation.d.ts

@@ -7610,6 +7610,8 @@ declare module BABYLON {
         /** @hidden */
         _areLightsDirty: boolean;
         /** @hidden */
+        _areLightsDisposed: boolean;
+        /** @hidden */
         _areAttributesDirty: boolean;
         /** @hidden */
         _areTexturesDirty: boolean;
@@ -7650,8 +7652,9 @@ declare module BABYLON {
         markAsImageProcessingDirty(): void;
         /**
          * Marks the material to indicate the lights need to be re-calculated
+         * @param disposed Defines whether the light is dirty due to dispose or not
          */
-        markAsLightDirty(): void;
+        markAsLightDirty(disposed?: boolean): void;
         /**
          * Marks the attribute state as changed
          */
@@ -8955,8 +8958,9 @@ declare module BABYLON {
          * @param effect The effect we are binding the data to
          * @param useSpecular Defines if specular is supported
          * @param usePhysicalLightFalloff Specifies whether the light falloff is defined physically or not
+         * @param rebuildInParallel Specifies whether the shader is rebuilding in parallel
          */
-        static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff?: boolean): void;
+        static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff?: boolean, rebuildInParallel?: boolean): void;
         /**
          * Binds the lights information from the scene to the effect for the given mesh.
          * @param scene The scene the lights belongs to
@@ -8965,8 +8969,9 @@ declare module BABYLON {
          * @param defines The generated defines for the effect
          * @param maxSimultaneousLights The maximum number of light that can be bound to the effect
          * @param usePhysicalLightFalloff Specifies whether the light falloff is defined physically or not
+         * @param rebuildInParallel Specifies whether the shader is rebuilding in parallel
          */
-        static BindLights(scene: Scene, mesh: AbstractMesh, effect: Effect, defines: any, maxSimultaneousLights?: number, usePhysicalLightFalloff?: boolean): void;
+        static BindLights(scene: Scene, mesh: AbstractMesh, effect: Effect, defines: any, maxSimultaneousLights?: number, usePhysicalLightFalloff?: boolean, rebuildInParallel?: boolean): void;
         private static _tempFogColor;
         /**
          * Binds the fog information from the scene to the effect for the given mesh.
@@ -18587,7 +18592,7 @@ declare module BABYLON {
         readonly lightSources: Light[];
         _resyncLightSources(): void;
         _resyncLighSource(light: Light): void;
-        _removeLightSource(light: Light): void;
+        _removeLightSource(light: Light, dispose: boolean): void;
         /**
          * If the source mesh receives shadows
          */
@@ -25907,10 +25912,10 @@ declare module BABYLON {
         /** @hidden */
         _unBindEffect(): void;
         /** @hidden */
-        _removeLightSource(light: Light): void;
+        _removeLightSource(light: Light, dispose: boolean): void;
         private _markSubMeshesAsDirty;
         /** @hidden */
-        _markSubMeshesAsLightDirty(): void;
+        _markSubMeshesAsLightDirty(dispose?: boolean): void;
         /** @hidden */
         _markSubMeshesAsAttributesDirty(): void;
         /** @hidden */
@@ -29480,6 +29485,7 @@ declare module BABYLON {
         private _displayingPosterTexture;
         private _settings;
         private _createInternalTextureOnEvent;
+        private _frameId;
         /**
          * Creates a video texture.
          * If you want to display a video in your scene, this is the special texture for that.
@@ -40217,6 +40223,7 @@ declare module BABYLON {
         protected _worldViewProjectionMatrix: Matrix;
         protected _globalAmbientColor: Color3;
         protected _useLogarithmicDepth: boolean;
+        protected _rebuildInParallel: boolean;
         /**
          * Instantiates a new standard material.
          * This is the default material used in Babylon. It is the best trade off between quality
@@ -46893,6 +46900,7 @@ declare module BABYLON {
          * Custom callback helping to override the default shader used in the material.
          */
         customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: PBRMaterialDefines) => string;
+        protected _rebuildInParallel: boolean;
         /**
          * Instantiates a new PBRMaterial instance.
          *
@@ -51717,6 +51725,7 @@ declare module BABYLON {
         protected _buildBlock(state: NodeMaterialBuildState): this;
         serialize(): any;
         _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
+        protected _dumpPropertiesCode(): string;
     }
 }
 declare module BABYLON {
@@ -51872,7 +51881,7 @@ declare module BABYLON {
          * Gets the b output component
          */
         readonly b: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         isReady(): boolean;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
@@ -52017,6 +52026,18 @@ declare module BABYLON {
          */
         getBlockByName(name: string): Nullable<NodeMaterialBlock>;
         /**
+         * Get a block by its name
+         * @param predicate defines the predicate used to find the good candidate
+         * @returns the required block or null if not found
+         */
+        getBlockByPredicate(predicate: (block: NodeMaterialBlock) => boolean): Nullable<NodeMaterialBlock>;
+        /**
+         * Get an input block by its name
+         * @param predicate defines the predicate used to find the good candidate
+         * @returns the required input block or null if not found
+         */
+        getInputBlockByPredicate(predicate: (block: InputBlock) => boolean): Nullable<InputBlock>;
+        /**
          * Gets the list of input blocks attached to this material
          * @returns an array of InputBlocks
          */
@@ -52231,7 +52252,7 @@ declare module BABYLON {
          */
         readonly a: NodeMaterialConnectionPoint;
         readonly target: NodeMaterialBlockTargets;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         initializeDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         isReady(): boolean;
@@ -52628,6 +52649,7 @@ declare module BABYLON {
          * @returns true if the block is ready
          */
         isReady(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): boolean;
+        protected _linkConnectionTypes(inputIndex0: number, inputIndex1: number): void;
         private _processBuild;
         /**
          * Compile the current node and generate the shader code
@@ -52809,6 +52831,8 @@ declare module BABYLON {
         private _associatedVariableName;
         /** @hidden */
         _typeConnectionSource: Nullable<NodeMaterialConnectionPoint>;
+        /** @hidden */
+        _linkedConnectionSource: Nullable<NodeMaterialConnectionPoint>;
         private _type;
         /** @hidden */
         _enforceAssociatedVariableName: boolean;
@@ -52882,9 +52906,10 @@ declare module BABYLON {
         /**
          * Connect this point to another connection point
          * @param connectionPoint defines the other connection point
+         * @param ignoreConstraints defines if the system will ignore connection type constraints (default is false)
          * @returns the current connection point
          */
-        connectTo(connectionPoint: NodeMaterialConnectionPoint): NodeMaterialConnectionPoint;
+        connectTo(connectionPoint: NodeMaterialConnectionPoint, ignoreConstraints?: boolean): NodeMaterialConnectionPoint;
         /**
          * Disconnect this point from one of his endpoint
          * @param endpoint defines the other connection point
@@ -52942,7 +52967,7 @@ declare module BABYLON {
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         provideFallbacks(mesh: AbstractMesh, fallbacks: EffectFallbacks): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
@@ -52989,7 +53014,7 @@ declare module BABYLON {
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         protected _buildBlock(state: NodeMaterialBuildState): this;
     }
@@ -53044,7 +53069,7 @@ declare module BABYLON {
          */
         readonly uvOutput: NodeMaterialConnectionPoint;
         initialize(state: NodeMaterialBuildState): void;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         replaceRepeatableContent(vertexShaderState: NodeMaterialBuildState, fragmentShaderState: NodeMaterialBuildState, mesh: AbstractMesh, defines: NodeMaterialDefines): void;
@@ -53079,49 +53104,9 @@ declare module BABYLON {
          */
         readonly alpha: NodeMaterialConnectionPoint;
         protected _buildBlock(state: NodeMaterialBuildState): this;
-    }
-}
-declare module BABYLON {
-    /**
-     * Block used to compute fresnel value
-     */
-    export class FresnelBlock extends NodeMaterialBlock {
-        /**
-         * Create a new FresnelBlock
-         * @param name defines the block name
-         */
-        constructor(name: string);
-        /**
-         * Gets the current class name
-         * @returns the class name
-         */
-        getClassName(): string;
-        /**
-         * Gets the world position input component
-         */
-        readonly worldPosition: NodeMaterialConnectionPoint;
-        /**
-         * Gets the world normal input component
-         */
-        readonly worldNormal: NodeMaterialConnectionPoint;
-        /**
-        * Gets the camera (or eye) position component
-        */
-        readonly cameraPosition: NodeMaterialConnectionPoint;
-        /**
-        * Gets the bias input component
-        */
-        readonly bias: NodeMaterialConnectionPoint;
-        /**
-        * Gets the camera (or eye) position component
-        */
-        readonly power: NodeMaterialConnectionPoint;
-        /**
-         * Gets the fresnel output component
-         */
-        readonly fresnel: NodeMaterialConnectionPoint;
-        autoConfigure(material: NodeMaterial): void;
-        protected _buildBlock(state: NodeMaterialBuildState): this | undefined;
+        protected _dumpPropertiesCode(): string;
+        serialize(): any;
+        _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
     }
 }
 declare module BABYLON {
@@ -53195,7 +53180,7 @@ declare module BABYLON {
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         protected _buildBlock(state: NodeMaterialBuildState): this;
@@ -53241,7 +53226,7 @@ declare module BABYLON {
          * Gets the specular output component
          */
         readonly specularOutput: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
@@ -53866,6 +53851,102 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * Block used to get the opposite of a value
+     */
+    export class OppositeBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new OppositeBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the input component
+         */
+        readonly input: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to get the view direction
+     */
+    export class ViewDirectionBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new ViewDirectionBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world position component
+         */
+        readonly worldPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the camera position component
+         */
+        readonly cameraPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to compute fresnel value
+     */
+    export class FresnelBlock extends NodeMaterialBlock {
+        /**
+         * Create a new FresnelBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world normal input component
+         */
+        readonly worldNormal: NodeMaterialConnectionPoint;
+        /**
+        * Gets the view direction input component
+        */
+        readonly viewDirection: NodeMaterialConnectionPoint;
+        /**
+        * Gets the bias input component
+        */
+        readonly bias: NodeMaterialConnectionPoint;
+        /**
+        * Gets the camera (or eye) position component
+        */
+        readonly power: NodeMaterialConnectionPoint;
+        /**
+         * Gets the fresnel output component
+         */
+        readonly fresnel: NodeMaterialConnectionPoint;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
      * Effect Render Options
      */
     export interface IEffectRendererOptions {

Diferenças do arquivo suprimidas por serem muito extensas
+ 10 - 11
dist/preview release/inspector/babylon.inspector.bundle.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 19950 - 13740
dist/preview release/inspector/babylon.inspector.bundle.max.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.max.js.map


+ 13 - 17
dist/preview release/inspector/babylon.inspector.d.ts

@@ -149,7 +149,6 @@ declare module INSPECTOR {
         private _engineInstrumentation;
         private _timerIntervalId;
         constructor(props: IPaneComponentProps);
-        componentWillMount(): void;
         componentWillUnmount(): void;
         render(): JSX.Element | null;
     }
@@ -188,7 +187,7 @@ declare module INSPECTOR {
     }> {
         private _gridMesh;
         constructor(props: IRenderGridPropertyGridComponentProps);
-        componentWillMount(): void;
+        componentDidMount(): void;
         addOrRemoveGrid(): void;
         render(): JSX.Element;
     }
@@ -197,8 +196,6 @@ declare module INSPECTOR {
     export class DebugTabComponent extends PaneComponent {
         private _physicsViewersEnabled;
         constructor(props: IPaneComponentProps);
-        componentWillMount(): void;
-        componentWillUnmount(): void;
         switchPhysicsViewers(): void;
         render(): JSX.Element | null;
     }
@@ -476,7 +473,7 @@ declare module INSPECTOR {
     }> {
         private _onDebugSelectionChangeObserver;
         constructor(props: ITextureLinkLineComponentProps);
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         debugTexture(): void;
         onLink(): void;
@@ -570,7 +567,6 @@ declare module INSPECTOR {
     export class TexturePropertyGridComponent extends React.Component<ITexturePropertyGridComponentProps> {
         private _adtInstrumentation;
         constructor(props: ITexturePropertyGridComponentProps);
-        componentWillMount(): void;
         componentWillUnmount(): void;
         updateTexture(file: File): void;
         render(): JSX.Element;
@@ -634,7 +630,7 @@ declare module INSPECTOR {
     }> {
         private _onSelectionChangedObserver;
         constructor(props: IRadioButtonLineComponentProps);
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         onChange(): void;
         render(): JSX.Element;
@@ -782,11 +778,13 @@ declare module INSPECTOR {
     }
     export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGridComponentProps, {
         displayNormals: boolean;
+        displayVertexColors: boolean;
     }> {
         constructor(props: IMeshPropertyGridComponentProps);
         renderWireframeOver(): void;
         renderNormalVectors(): void;
         displayNormals(): void;
+        displayVertexColors(): void;
         onMaterialLink(): void;
         onSourceMeshLink(): void;
         convertPhysicsTypeToString(): string;
@@ -901,7 +899,6 @@ declare module INSPECTOR {
         connect(animationGroup: BABYLON.AnimationGroup): void;
         updateCurrentFrame(animationGroup: BABYLON.AnimationGroup): void;
         shouldComponentUpdate(nextProps: IAnimationGroupGridComponentProps): boolean;
-        componentWillMount(): void;
         componentWillUnmount(): void;
         playOrPause(): void;
         onCurrentFrameChange(value: number): void;
@@ -1176,7 +1173,7 @@ declare module INSPECTOR {
         private _isPlaying;
         constructor(props: IAnimationGridComponentProps);
         playOrPause(): void;
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         onCurrentFrameChange(value: number): void;
         render(): JSX.Element;
@@ -1195,7 +1192,6 @@ declare module INSPECTOR {
         constructor(props: ISkeletonPropertyGridComponentProps);
         switchSkeletonViewers(): void;
         checkSkeletonViewerState(props: ISkeletonPropertyGridComponentProps): void;
-        componentWillMount(): void;
         shouldComponentUpdate(nextProps: ISkeletonPropertyGridComponentProps): boolean;
         render(): JSX.Element;
     }
@@ -1320,7 +1316,7 @@ declare module INSPECTOR {
         private _lockObject;
         constructor(props: IPaneComponentProps);
         timerRefresh(): void;
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         render(): JSX.Element | null;
     }
@@ -1342,7 +1338,7 @@ declare module INSPECTOR {
         private _backStack;
         private _onSelectionChangeObserver;
         constructor(props: IHeaderComponentProps);
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         goBack(): void;
         renderLogo(): JSX.Element | null;
@@ -1376,7 +1372,7 @@ declare module INSPECTOR {
     export class ToolsTabComponent extends PaneComponent {
         private _videoRecorder;
         constructor(props: IPaneComponentProps);
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         captureScreenshot(): void;
         recordVideo(): void;
@@ -1415,7 +1411,7 @@ declare module INSPECTOR {
         private _onTabChangedObserver;
         private _once;
         constructor(props: IActionTabsComponentProps);
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         changeSelectedTab(index: number): void;
         renderContent(): JSX.Element | null;
@@ -1480,7 +1476,7 @@ declare module INSPECTOR {
         private _onActiveCameraObserver;
         constructor(props: ICameraTreeItemComponentProps);
         setActive(): void;
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         render(): JSX.Element;
     }
@@ -1722,7 +1718,7 @@ declare module INSPECTOR {
             isSelected: boolean;
             isInPickingMode: boolean;
         }): boolean;
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         onSelect(): void;
         onPickingMode(): void;
@@ -1762,7 +1758,7 @@ declare module INSPECTOR {
         private sceneMutationFunc;
         constructor(props: ISceneExplorerComponentProps);
         processMutation(): void;
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         filterContent(filter: string): void;
         findSiblings(parent: any, items: any[], target: any, goNext: boolean, data: {

+ 26 - 34
dist/preview release/inspector/babylon.inspector.module.d.ts

@@ -173,7 +173,6 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/statisticsTabComp
         private _engineInstrumentation;
         private _timerIntervalId;
         constructor(props: IPaneComponentProps);
-        componentWillMount(): void;
         componentWillUnmount(): void;
         render(): JSX.Element | null;
     }
@@ -218,7 +217,7 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/ren
     }> {
         private _gridMesh;
         constructor(props: IRenderGridPropertyGridComponentProps);
-        componentWillMount(): void;
+        componentDidMount(): void;
         addOrRemoveGrid(): void;
         render(): JSX.Element;
     }
@@ -228,8 +227,6 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/debugTabComponent
     export class DebugTabComponent extends PaneComponent {
         private _physicsViewersEnabled;
         constructor(props: IPaneComponentProps);
-        componentWillMount(): void;
-        componentWillUnmount(): void;
         switchPhysicsViewers(): void;
         render(): JSX.Element | null;
     }
@@ -554,7 +551,7 @@ declare module "babylonjs-inspector/components/actionTabs/lines/textureLinkLineC
     }> {
         private _onDebugSelectionChangeObserver;
         constructor(props: ITextureLinkLineComponentProps);
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         debugTexture(): void;
         onLink(): void;
@@ -667,7 +664,6 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/mat
     export class TexturePropertyGridComponent extends React.Component<ITexturePropertyGridComponentProps> {
         private _adtInstrumentation;
         constructor(props: ITexturePropertyGridComponentProps);
-        componentWillMount(): void;
         componentWillUnmount(): void;
         updateTexture(file: File): void;
         render(): JSX.Element;
@@ -744,7 +740,7 @@ declare module "babylonjs-inspector/components/actionTabs/lines/radioLineCompone
     }> {
         private _onSelectionChangedObserver;
         constructor(props: IRadioButtonLineComponentProps);
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         onChange(): void;
         render(): JSX.Element;
@@ -954,11 +950,13 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/mes
     }
     export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGridComponentProps, {
         displayNormals: boolean;
+        displayVertexColors: boolean;
     }> {
         constructor(props: IMeshPropertyGridComponentProps);
         renderWireframeOver(): void;
         renderNormalVectors(): void;
         displayNormals(): void;
+        displayVertexColors(): void;
         onMaterialLink(): void;
         onSourceMeshLink(): void;
         convertPhysicsTypeToString(): string;
@@ -1122,7 +1120,6 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/ani
         connect(animationGroup: AnimationGroup): void;
         updateCurrentFrame(animationGroup: AnimationGroup): void;
         shouldComponentUpdate(nextProps: IAnimationGroupGridComponentProps): boolean;
-        componentWillMount(): void;
         componentWillUnmount(): void;
         playOrPause(): void;
         onCurrentFrameChange(value: number): void;
@@ -1524,7 +1521,7 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/ani
         private _isPlaying;
         constructor(props: IAnimationGridComponentProps);
         playOrPause(): void;
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         onCurrentFrameChange(value: number): void;
         render(): JSX.Element;
@@ -1549,7 +1546,6 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/mes
         constructor(props: ISkeletonPropertyGridComponentProps);
         switchSkeletonViewers(): void;
         checkSkeletonViewerState(props: ISkeletonPropertyGridComponentProps): void;
-        componentWillMount(): void;
         shouldComponentUpdate(nextProps: ISkeletonPropertyGridComponentProps): boolean;
         render(): JSX.Element;
     }
@@ -1716,7 +1712,7 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGridTabCo
         private _lockObject;
         constructor(props: IPaneComponentProps);
         timerRefresh(): void;
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         render(): JSX.Element | null;
     }
@@ -1740,7 +1736,7 @@ declare module "babylonjs-inspector/components/headerComponent" {
         private _backStack;
         private _onSelectionChangeObserver;
         constructor(props: IHeaderComponentProps);
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         goBack(): void;
         renderLogo(): JSX.Element | null;
@@ -1780,7 +1776,7 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/toolsTabComponent
     export class ToolsTabComponent extends PaneComponent {
         private _videoRecorder;
         constructor(props: IPaneComponentProps);
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         captureScreenshot(): void;
         recordVideo(): void;
@@ -1823,7 +1819,7 @@ declare module "babylonjs-inspector/components/actionTabs/actionTabsComponent" {
         private _onTabChangedObserver;
         private _once;
         constructor(props: IActionTabsComponentProps);
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         changeSelectedTab(index: number): void;
         renderContent(): JSX.Element | null;
@@ -1897,7 +1893,7 @@ declare module "babylonjs-inspector/components/sceneExplorer/entities/cameraTree
         private _onActiveCameraObserver;
         constructor(props: ICameraTreeItemComponentProps);
         setActive(): void;
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         render(): JSX.Element;
     }
@@ -2190,7 +2186,7 @@ declare module "babylonjs-inspector/components/sceneExplorer/entities/sceneTreeI
             isSelected: boolean;
             isInPickingMode: boolean;
         }): boolean;
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         onSelect(): void;
         onPickingMode(): void;
@@ -2235,7 +2231,7 @@ declare module "babylonjs-inspector/components/sceneExplorer/sceneExplorerCompon
         private sceneMutationFunc;
         constructor(props: ISceneExplorerComponentProps);
         processMutation(): void;
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         filterContent(filter: string): void;
         findSiblings(parent: any, items: any[], target: any, goNext: boolean, data: {
@@ -2466,7 +2462,6 @@ declare module INSPECTOR {
         private _engineInstrumentation;
         private _timerIntervalId;
         constructor(props: IPaneComponentProps);
-        componentWillMount(): void;
         componentWillUnmount(): void;
         render(): JSX.Element | null;
     }
@@ -2505,7 +2500,7 @@ declare module INSPECTOR {
     }> {
         private _gridMesh;
         constructor(props: IRenderGridPropertyGridComponentProps);
-        componentWillMount(): void;
+        componentDidMount(): void;
         addOrRemoveGrid(): void;
         render(): JSX.Element;
     }
@@ -2514,8 +2509,6 @@ declare module INSPECTOR {
     export class DebugTabComponent extends PaneComponent {
         private _physicsViewersEnabled;
         constructor(props: IPaneComponentProps);
-        componentWillMount(): void;
-        componentWillUnmount(): void;
         switchPhysicsViewers(): void;
         render(): JSX.Element | null;
     }
@@ -2793,7 +2786,7 @@ declare module INSPECTOR {
     }> {
         private _onDebugSelectionChangeObserver;
         constructor(props: ITextureLinkLineComponentProps);
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         debugTexture(): void;
         onLink(): void;
@@ -2887,7 +2880,6 @@ declare module INSPECTOR {
     export class TexturePropertyGridComponent extends React.Component<ITexturePropertyGridComponentProps> {
         private _adtInstrumentation;
         constructor(props: ITexturePropertyGridComponentProps);
-        componentWillMount(): void;
         componentWillUnmount(): void;
         updateTexture(file: File): void;
         render(): JSX.Element;
@@ -2951,7 +2943,7 @@ declare module INSPECTOR {
     }> {
         private _onSelectionChangedObserver;
         constructor(props: IRadioButtonLineComponentProps);
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         onChange(): void;
         render(): JSX.Element;
@@ -3099,11 +3091,13 @@ declare module INSPECTOR {
     }
     export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGridComponentProps, {
         displayNormals: boolean;
+        displayVertexColors: boolean;
     }> {
         constructor(props: IMeshPropertyGridComponentProps);
         renderWireframeOver(): void;
         renderNormalVectors(): void;
         displayNormals(): void;
+        displayVertexColors(): void;
         onMaterialLink(): void;
         onSourceMeshLink(): void;
         convertPhysicsTypeToString(): string;
@@ -3218,7 +3212,6 @@ declare module INSPECTOR {
         connect(animationGroup: BABYLON.AnimationGroup): void;
         updateCurrentFrame(animationGroup: BABYLON.AnimationGroup): void;
         shouldComponentUpdate(nextProps: IAnimationGroupGridComponentProps): boolean;
-        componentWillMount(): void;
         componentWillUnmount(): void;
         playOrPause(): void;
         onCurrentFrameChange(value: number): void;
@@ -3493,7 +3486,7 @@ declare module INSPECTOR {
         private _isPlaying;
         constructor(props: IAnimationGridComponentProps);
         playOrPause(): void;
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         onCurrentFrameChange(value: number): void;
         render(): JSX.Element;
@@ -3512,7 +3505,6 @@ declare module INSPECTOR {
         constructor(props: ISkeletonPropertyGridComponentProps);
         switchSkeletonViewers(): void;
         checkSkeletonViewerState(props: ISkeletonPropertyGridComponentProps): void;
-        componentWillMount(): void;
         shouldComponentUpdate(nextProps: ISkeletonPropertyGridComponentProps): boolean;
         render(): JSX.Element;
     }
@@ -3637,7 +3629,7 @@ declare module INSPECTOR {
         private _lockObject;
         constructor(props: IPaneComponentProps);
         timerRefresh(): void;
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         render(): JSX.Element | null;
     }
@@ -3659,7 +3651,7 @@ declare module INSPECTOR {
         private _backStack;
         private _onSelectionChangeObserver;
         constructor(props: IHeaderComponentProps);
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         goBack(): void;
         renderLogo(): JSX.Element | null;
@@ -3693,7 +3685,7 @@ declare module INSPECTOR {
     export class ToolsTabComponent extends PaneComponent {
         private _videoRecorder;
         constructor(props: IPaneComponentProps);
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         captureScreenshot(): void;
         recordVideo(): void;
@@ -3732,7 +3724,7 @@ declare module INSPECTOR {
         private _onTabChangedObserver;
         private _once;
         constructor(props: IActionTabsComponentProps);
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         changeSelectedTab(index: number): void;
         renderContent(): JSX.Element | null;
@@ -3797,7 +3789,7 @@ declare module INSPECTOR {
         private _onActiveCameraObserver;
         constructor(props: ICameraTreeItemComponentProps);
         setActive(): void;
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         render(): JSX.Element;
     }
@@ -4039,7 +4031,7 @@ declare module INSPECTOR {
             isSelected: boolean;
             isInPickingMode: boolean;
         }): boolean;
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         onSelect(): void;
         onPickingMode(): void;
@@ -4079,7 +4071,7 @@ declare module INSPECTOR {
         private sceneMutationFunc;
         constructor(props: ISceneExplorerComponentProps);
         processMutation(): void;
-        componentWillMount(): void;
+        componentDidMount(): void;
         componentWillUnmount(): void;
         filterContent(filter: string): void;
         findSiblings(parent: any, items: any[], target: any, goNext: boolean, data: {

Diferenças do arquivo suprimidas por serem muito extensas
+ 45 - 4
dist/preview release/nodeEditor/babylon.nodeEditor.d.ts


Diferenças do arquivo suprimidas por serem muito extensas
+ 10 - 11
dist/preview release/nodeEditor/babylon.nodeEditor.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 13115 - 6605
dist/preview release/nodeEditor/babylon.nodeEditor.max.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 1
dist/preview release/nodeEditor/babylon.nodeEditor.max.js.map


Diferenças do arquivo suprimidas por serem muito extensas
+ 107 - 9
dist/preview release/nodeEditor/babylon.nodeEditor.module.d.ts


+ 1 - 1
dist/preview release/packagesSizeBaseLine.json

@@ -1 +1 @@
-{"engineOnly":167207,"sceneOnly":507511,"minGridMaterial":636992,"minStandardMaterial":766193}
+{"engineOnly":167207,"sceneOnly":507666,"minGridMaterial":637194,"minStandardMaterial":766571}

+ 291 - 119
dist/preview release/viewer/babylon.module.d.ts

@@ -7688,6 +7688,8 @@ declare module "babylonjs/Materials/materialDefines" {
         /** @hidden */
         _areLightsDirty: boolean;
         /** @hidden */
+        _areLightsDisposed: boolean;
+        /** @hidden */
         _areAttributesDirty: boolean;
         /** @hidden */
         _areTexturesDirty: boolean;
@@ -7728,8 +7730,9 @@ declare module "babylonjs/Materials/materialDefines" {
         markAsImageProcessingDirty(): void;
         /**
          * Marks the material to indicate the lights need to be re-calculated
+         * @param disposed Defines whether the light is dirty due to dispose or not
          */
-        markAsLightDirty(): void;
+        markAsLightDirty(disposed?: boolean): void;
         /**
          * Marks the attribute state as changed
          */
@@ -9063,8 +9066,9 @@ declare module "babylonjs/Materials/materialHelper" {
          * @param effect The effect we are binding the data to
          * @param useSpecular Defines if specular is supported
          * @param usePhysicalLightFalloff Specifies whether the light falloff is defined physically or not
+         * @param rebuildInParallel Specifies whether the shader is rebuilding in parallel
          */
-        static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff?: boolean): void;
+        static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff?: boolean, rebuildInParallel?: boolean): void;
         /**
          * Binds the lights information from the scene to the effect for the given mesh.
          * @param scene The scene the lights belongs to
@@ -9073,8 +9077,9 @@ declare module "babylonjs/Materials/materialHelper" {
          * @param defines The generated defines for the effect
          * @param maxSimultaneousLights The maximum number of light that can be bound to the effect
          * @param usePhysicalLightFalloff Specifies whether the light falloff is defined physically or not
+         * @param rebuildInParallel Specifies whether the shader is rebuilding in parallel
          */
-        static BindLights(scene: Scene, mesh: AbstractMesh, effect: Effect, defines: any, maxSimultaneousLights?: number, usePhysicalLightFalloff?: boolean): void;
+        static BindLights(scene: Scene, mesh: AbstractMesh, effect: Effect, defines: any, maxSimultaneousLights?: number, usePhysicalLightFalloff?: boolean, rebuildInParallel?: boolean): void;
         private static _tempFogColor;
         /**
          * Binds the fog information from the scene to the effect for the given mesh.
@@ -19082,7 +19087,7 @@ declare module "babylonjs/Meshes/instancedMesh" {
         readonly lightSources: Light[];
         _resyncLightSources(): void;
         _resyncLighSource(light: Light): void;
-        _removeLightSource(light: Light): void;
+        _removeLightSource(light: Light, dispose: boolean): void;
         /**
          * If the source mesh receives shadows
          */
@@ -26653,10 +26658,10 @@ declare module "babylonjs/Meshes/abstractMesh" {
         /** @hidden */
         _unBindEffect(): void;
         /** @hidden */
-        _removeLightSource(light: Light): void;
+        _removeLightSource(light: Light, dispose: boolean): void;
         private _markSubMeshesAsDirty;
         /** @hidden */
-        _markSubMeshesAsLightDirty(): void;
+        _markSubMeshesAsLightDirty(dispose?: boolean): void;
         /** @hidden */
         _markSubMeshesAsAttributesDirty(): void;
         /** @hidden */
@@ -30318,6 +30323,7 @@ declare module "babylonjs/Materials/Textures/videoTexture" {
         private _displayingPosterTexture;
         private _settings;
         private _createInternalTextureOnEvent;
+        private _frameId;
         /**
          * Creates a video texture.
          * If you want to display a video in your scene, this is the special texture for that.
@@ -41591,6 +41597,7 @@ declare module "babylonjs/Materials/standardMaterial" {
         protected _worldViewProjectionMatrix: Matrix;
         protected _globalAmbientColor: Color3;
         protected _useLogarithmicDepth: boolean;
+        protected _rebuildInParallel: boolean;
         /**
          * Instantiates a new standard material.
          * This is the default material used in Babylon. It is the best trade off between quality
@@ -48910,6 +48917,7 @@ declare module "babylonjs/Materials/PBR/pbrBaseMaterial" {
          * Custom callback helping to override the default shader used in the material.
          */
         customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: PBRMaterialDefines) => string;
+        protected _rebuildInParallel: boolean;
         /**
          * Instantiates a new PBRMaterial instance.
          *
@@ -54113,6 +54121,7 @@ declare module "babylonjs/Materials/Node/Blocks/transformBlock" {
         protected _buildBlock(state: NodeMaterialBuildState): this;
         serialize(): any;
         _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
+        protected _dumpPropertiesCode(): string;
     }
 }
 declare module "babylonjs/Materials/Node/Blocks/Vertex/vertexOutputBlock" {
@@ -54284,7 +54293,7 @@ declare module "babylonjs/Materials/Node/Blocks/Dual/reflectionTextureBlock" {
          * Gets the b output component
          */
         readonly b: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         isReady(): boolean;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
@@ -54445,6 +54454,18 @@ declare module "babylonjs/Materials/Node/nodeMaterial" {
          */
         getBlockByName(name: string): Nullable<NodeMaterialBlock>;
         /**
+         * Get a block by its name
+         * @param predicate defines the predicate used to find the good candidate
+         * @returns the required block or null if not found
+         */
+        getBlockByPredicate(predicate: (block: NodeMaterialBlock) => boolean): Nullable<NodeMaterialBlock>;
+        /**
+         * Get an input block by its name
+         * @param predicate defines the predicate used to find the good candidate
+         * @returns the required input block or null if not found
+         */
+        getInputBlockByPredicate(predicate: (block: InputBlock) => boolean): Nullable<InputBlock>;
+        /**
          * Gets the list of input blocks attached to this material
          * @returns an array of InputBlocks
          */
@@ -54670,7 +54691,7 @@ declare module "babylonjs/Materials/Node/Blocks/Dual/textureBlock" {
          */
         readonly a: NodeMaterialConnectionPoint;
         readonly target: NodeMaterialBlockTargets;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         initializeDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         isReady(): boolean;
@@ -55085,6 +55106,7 @@ declare module "babylonjs/Materials/Node/nodeMaterialBlock" {
          * @returns true if the block is ready
          */
         isReady(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): boolean;
+        protected _linkConnectionTypes(inputIndex0: number, inputIndex1: number): void;
         private _processBuild;
         /**
          * Compile the current node and generate the shader code
@@ -55282,6 +55304,8 @@ declare module "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint" {
         private _associatedVariableName;
         /** @hidden */
         _typeConnectionSource: Nullable<NodeMaterialConnectionPoint>;
+        /** @hidden */
+        _linkedConnectionSource: Nullable<NodeMaterialConnectionPoint>;
         private _type;
         /** @hidden */
         _enforceAssociatedVariableName: boolean;
@@ -55355,9 +55379,10 @@ declare module "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint" {
         /**
          * Connect this point to another connection point
          * @param connectionPoint defines the other connection point
+         * @param ignoreConstraints defines if the system will ignore connection type constraints (default is false)
          * @returns the current connection point
          */
-        connectTo(connectionPoint: NodeMaterialConnectionPoint): NodeMaterialConnectionPoint;
+        connectTo(connectionPoint: NodeMaterialConnectionPoint, ignoreConstraints?: boolean): NodeMaterialConnectionPoint;
         /**
          * Disconnect this point from one of his endpoint
          * @param endpoint defines the other connection point
@@ -55422,7 +55447,7 @@ declare module "babylonjs/Materials/Node/Blocks/Vertex/bonesBlock" {
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         provideFallbacks(mesh: AbstractMesh, fallbacks: EffectFallbacks): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
@@ -55474,7 +55499,7 @@ declare module "babylonjs/Materials/Node/Blocks/Vertex/instancesBlock" {
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         protected _buildBlock(state: NodeMaterialBuildState): this;
     }
@@ -55536,7 +55561,7 @@ declare module "babylonjs/Materials/Node/Blocks/Vertex/morphTargetsBlock" {
          */
         readonly uvOutput: NodeMaterialConnectionPoint;
         initialize(state: NodeMaterialBuildState): void;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         replaceRepeatableContent(vertexShaderState: NodeMaterialBuildState, fragmentShaderState: NodeMaterialBuildState, mesh: AbstractMesh, defines: NodeMaterialDefines): void;
@@ -55553,6 +55578,7 @@ declare module "babylonjs/Materials/Node/Blocks/Fragment/alphaTestBlock" {
     import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
     import { NodeMaterialBuildState } from "babylonjs/Materials/Node/nodeMaterialBuildState";
     import { NodeMaterialConnectionPoint } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint";
+    import { Scene } from "babylonjs/scene";
     /**
      * Block used to add an alpha test in the fragment shader
      */
@@ -55580,53 +55606,9 @@ declare module "babylonjs/Materials/Node/Blocks/Fragment/alphaTestBlock" {
          */
         readonly alpha: NodeMaterialConnectionPoint;
         protected _buildBlock(state: NodeMaterialBuildState): this;
-    }
-}
-declare module "babylonjs/Materials/Node/Blocks/Fragment/fresnelBlock" {
-    import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
-    import { NodeMaterialBuildState } from "babylonjs/Materials/Node/nodeMaterialBuildState";
-    import { NodeMaterialConnectionPoint } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint";
-    import { NodeMaterial } from "babylonjs/Materials/Node/nodeMaterial";
-    /**
-     * Block used to compute fresnel value
-     */
-    export class FresnelBlock extends NodeMaterialBlock {
-        /**
-         * Create a new FresnelBlock
-         * @param name defines the block name
-         */
-        constructor(name: string);
-        /**
-         * Gets the current class name
-         * @returns the class name
-         */
-        getClassName(): string;
-        /**
-         * Gets the world position input component
-         */
-        readonly worldPosition: NodeMaterialConnectionPoint;
-        /**
-         * Gets the world normal input component
-         */
-        readonly worldNormal: NodeMaterialConnectionPoint;
-        /**
-        * Gets the camera (or eye) position component
-        */
-        readonly cameraPosition: NodeMaterialConnectionPoint;
-        /**
-        * Gets the bias input component
-        */
-        readonly bias: NodeMaterialConnectionPoint;
-        /**
-        * Gets the camera (or eye) position component
-        */
-        readonly power: NodeMaterialConnectionPoint;
-        /**
-         * Gets the fresnel output component
-         */
-        readonly fresnel: NodeMaterialConnectionPoint;
-        autoConfigure(material: NodeMaterial): void;
-        protected _buildBlock(state: NodeMaterialBuildState): this | undefined;
+        protected _dumpPropertiesCode(): string;
+        serialize(): any;
+        _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
     }
 }
 declare module "babylonjs/Materials/Node/Blocks/Fragment/imageProcessingBlock" {
@@ -55673,7 +55655,6 @@ declare module "babylonjs/Materials/Node/Blocks/Fragment/imageProcessingBlock" {
 declare module "babylonjs/Materials/Node/Blocks/Fragment/index" {
     export * from "babylonjs/Materials/Node/Blocks/Fragment/fragmentOutputBlock";
     export * from "babylonjs/Materials/Node/Blocks/Fragment/alphaTestBlock";
-    export * from "babylonjs/Materials/Node/Blocks/Fragment/fresnelBlock";
     export * from "babylonjs/Materials/Node/Blocks/Fragment/imageProcessingBlock";
 }
 declare module "babylonjs/Materials/Node/Blocks/Dual/fogBlock" {
@@ -55720,7 +55701,7 @@ declare module "babylonjs/Materials/Node/Blocks/Dual/fogBlock" {
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         protected _buildBlock(state: NodeMaterialBuildState): this;
@@ -55776,7 +55757,7 @@ declare module "babylonjs/Materials/Node/Blocks/Dual/lightBlock" {
          * Gets the specular output component
          */
         readonly specularOutput: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
@@ -56463,6 +56444,113 @@ declare module "babylonjs/Materials/Node/Blocks/stepBlock" {
         protected _buildBlock(state: NodeMaterialBuildState): this;
     }
 }
+declare module "babylonjs/Materials/Node/Blocks/oppositeBlock" {
+    import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
+    import { NodeMaterialBuildState } from "babylonjs/Materials/Node/nodeMaterialBuildState";
+    import { NodeMaterialConnectionPoint } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint";
+    /**
+     * Block used to get the opposite of a value
+     */
+    export class OppositeBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new OppositeBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the input component
+         */
+        readonly input: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module "babylonjs/Materials/Node/Blocks/viewDirectionBlock" {
+    import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
+    import { NodeMaterialBuildState } from "babylonjs/Materials/Node/nodeMaterialBuildState";
+    import { NodeMaterialConnectionPoint } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint";
+    import { NodeMaterial } from "babylonjs/Materials/Node/nodeMaterial";
+    /**
+     * Block used to get the view direction
+     */
+    export class ViewDirectionBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new ViewDirectionBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world position component
+         */
+        readonly worldPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the camera position component
+         */
+        readonly cameraPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module "babylonjs/Materials/Node/Blocks/fresnelBlock" {
+    import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
+    import { NodeMaterialBuildState } from "babylonjs/Materials/Node/nodeMaterialBuildState";
+    import { NodeMaterialConnectionPoint } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint";
+    import { NodeMaterial } from "babylonjs/Materials/Node/nodeMaterial";
+    /**
+     * Block used to compute fresnel value
+     */
+    export class FresnelBlock extends NodeMaterialBlock {
+        /**
+         * Create a new FresnelBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world normal input component
+         */
+        readonly worldNormal: NodeMaterialConnectionPoint;
+        /**
+        * Gets the view direction input component
+        */
+        readonly viewDirection: NodeMaterialConnectionPoint;
+        /**
+        * Gets the bias input component
+        */
+        readonly bias: NodeMaterialConnectionPoint;
+        /**
+        * Gets the camera (or eye) position component
+        */
+        readonly power: NodeMaterialConnectionPoint;
+        /**
+         * Gets the fresnel output component
+         */
+        readonly fresnel: NodeMaterialConnectionPoint;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
 declare module "babylonjs/Materials/Node/Blocks/index" {
     export * from "babylonjs/Materials/Node/Blocks/Vertex/index";
     export * from "babylonjs/Materials/Node/Blocks/Fragment/index";
@@ -56486,6 +56574,9 @@ declare module "babylonjs/Materials/Node/Blocks/index" {
     export * from "babylonjs/Materials/Node/Blocks/divideBlock";
     export * from "babylonjs/Materials/Node/Blocks/subtractBlock";
     export * from "babylonjs/Materials/Node/Blocks/stepBlock";
+    export * from "babylonjs/Materials/Node/Blocks/oppositeBlock";
+    export * from "babylonjs/Materials/Node/Blocks/viewDirectionBlock";
+    export * from "babylonjs/Materials/Node/Blocks/fresnelBlock";
 }
 declare module "babylonjs/Materials/Node/Optimizers/index" {
     export * from "babylonjs/Materials/Node/Optimizers/nodeMaterialOptimizer";
@@ -72520,6 +72611,8 @@ declare module BABYLON {
         /** @hidden */
         _areLightsDirty: boolean;
         /** @hidden */
+        _areLightsDisposed: boolean;
+        /** @hidden */
         _areAttributesDirty: boolean;
         /** @hidden */
         _areTexturesDirty: boolean;
@@ -72560,8 +72653,9 @@ declare module BABYLON {
         markAsImageProcessingDirty(): void;
         /**
          * Marks the material to indicate the lights need to be re-calculated
+         * @param disposed Defines whether the light is dirty due to dispose or not
          */
-        markAsLightDirty(): void;
+        markAsLightDirty(disposed?: boolean): void;
         /**
          * Marks the attribute state as changed
          */
@@ -73865,8 +73959,9 @@ declare module BABYLON {
          * @param effect The effect we are binding the data to
          * @param useSpecular Defines if specular is supported
          * @param usePhysicalLightFalloff Specifies whether the light falloff is defined physically or not
+         * @param rebuildInParallel Specifies whether the shader is rebuilding in parallel
          */
-        static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff?: boolean): void;
+        static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff?: boolean, rebuildInParallel?: boolean): void;
         /**
          * Binds the lights information from the scene to the effect for the given mesh.
          * @param scene The scene the lights belongs to
@@ -73875,8 +73970,9 @@ declare module BABYLON {
          * @param defines The generated defines for the effect
          * @param maxSimultaneousLights The maximum number of light that can be bound to the effect
          * @param usePhysicalLightFalloff Specifies whether the light falloff is defined physically or not
+         * @param rebuildInParallel Specifies whether the shader is rebuilding in parallel
          */
-        static BindLights(scene: Scene, mesh: AbstractMesh, effect: Effect, defines: any, maxSimultaneousLights?: number, usePhysicalLightFalloff?: boolean): void;
+        static BindLights(scene: Scene, mesh: AbstractMesh, effect: Effect, defines: any, maxSimultaneousLights?: number, usePhysicalLightFalloff?: boolean, rebuildInParallel?: boolean): void;
         private static _tempFogColor;
         /**
          * Binds the fog information from the scene to the effect for the given mesh.
@@ -83497,7 +83593,7 @@ declare module BABYLON {
         readonly lightSources: Light[];
         _resyncLightSources(): void;
         _resyncLighSource(light: Light): void;
-        _removeLightSource(light: Light): void;
+        _removeLightSource(light: Light, dispose: boolean): void;
         /**
          * If the source mesh receives shadows
          */
@@ -90817,10 +90913,10 @@ declare module BABYLON {
         /** @hidden */
         _unBindEffect(): void;
         /** @hidden */
-        _removeLightSource(light: Light): void;
+        _removeLightSource(light: Light, dispose: boolean): void;
         private _markSubMeshesAsDirty;
         /** @hidden */
-        _markSubMeshesAsLightDirty(): void;
+        _markSubMeshesAsLightDirty(dispose?: boolean): void;
         /** @hidden */
         _markSubMeshesAsAttributesDirty(): void;
         /** @hidden */
@@ -94390,6 +94486,7 @@ declare module BABYLON {
         private _displayingPosterTexture;
         private _settings;
         private _createInternalTextureOnEvent;
+        private _frameId;
         /**
          * Creates a video texture.
          * If you want to display a video in your scene, this is the special texture for that.
@@ -105127,6 +105224,7 @@ declare module BABYLON {
         protected _worldViewProjectionMatrix: Matrix;
         protected _globalAmbientColor: Color3;
         protected _useLogarithmicDepth: boolean;
+        protected _rebuildInParallel: boolean;
         /**
          * Instantiates a new standard material.
          * This is the default material used in Babylon. It is the best trade off between quality
@@ -111803,6 +111901,7 @@ declare module BABYLON {
          * Custom callback helping to override the default shader used in the material.
          */
         customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: PBRMaterialDefines) => string;
+        protected _rebuildInParallel: boolean;
         /**
          * Instantiates a new PBRMaterial instance.
          *
@@ -116627,6 +116726,7 @@ declare module BABYLON {
         protected _buildBlock(state: NodeMaterialBuildState): this;
         serialize(): any;
         _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
+        protected _dumpPropertiesCode(): string;
     }
 }
 declare module BABYLON {
@@ -116782,7 +116882,7 @@ declare module BABYLON {
          * Gets the b output component
          */
         readonly b: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         isReady(): boolean;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
@@ -116927,6 +117027,18 @@ declare module BABYLON {
          */
         getBlockByName(name: string): Nullable<NodeMaterialBlock>;
         /**
+         * Get a block by its name
+         * @param predicate defines the predicate used to find the good candidate
+         * @returns the required block or null if not found
+         */
+        getBlockByPredicate(predicate: (block: NodeMaterialBlock) => boolean): Nullable<NodeMaterialBlock>;
+        /**
+         * Get an input block by its name
+         * @param predicate defines the predicate used to find the good candidate
+         * @returns the required input block or null if not found
+         */
+        getInputBlockByPredicate(predicate: (block: InputBlock) => boolean): Nullable<InputBlock>;
+        /**
          * Gets the list of input blocks attached to this material
          * @returns an array of InputBlocks
          */
@@ -117141,7 +117253,7 @@ declare module BABYLON {
          */
         readonly a: NodeMaterialConnectionPoint;
         readonly target: NodeMaterialBlockTargets;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         initializeDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         isReady(): boolean;
@@ -117538,6 +117650,7 @@ declare module BABYLON {
          * @returns true if the block is ready
          */
         isReady(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): boolean;
+        protected _linkConnectionTypes(inputIndex0: number, inputIndex1: number): void;
         private _processBuild;
         /**
          * Compile the current node and generate the shader code
@@ -117719,6 +117832,8 @@ declare module BABYLON {
         private _associatedVariableName;
         /** @hidden */
         _typeConnectionSource: Nullable<NodeMaterialConnectionPoint>;
+        /** @hidden */
+        _linkedConnectionSource: Nullable<NodeMaterialConnectionPoint>;
         private _type;
         /** @hidden */
         _enforceAssociatedVariableName: boolean;
@@ -117792,9 +117907,10 @@ declare module BABYLON {
         /**
          * Connect this point to another connection point
          * @param connectionPoint defines the other connection point
+         * @param ignoreConstraints defines if the system will ignore connection type constraints (default is false)
          * @returns the current connection point
          */
-        connectTo(connectionPoint: NodeMaterialConnectionPoint): NodeMaterialConnectionPoint;
+        connectTo(connectionPoint: NodeMaterialConnectionPoint, ignoreConstraints?: boolean): NodeMaterialConnectionPoint;
         /**
          * Disconnect this point from one of his endpoint
          * @param endpoint defines the other connection point
@@ -117852,7 +117968,7 @@ declare module BABYLON {
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         provideFallbacks(mesh: AbstractMesh, fallbacks: EffectFallbacks): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
@@ -117899,7 +118015,7 @@ declare module BABYLON {
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         protected _buildBlock(state: NodeMaterialBuildState): this;
     }
@@ -117954,7 +118070,7 @@ declare module BABYLON {
          */
         readonly uvOutput: NodeMaterialConnectionPoint;
         initialize(state: NodeMaterialBuildState): void;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         replaceRepeatableContent(vertexShaderState: NodeMaterialBuildState, fragmentShaderState: NodeMaterialBuildState, mesh: AbstractMesh, defines: NodeMaterialDefines): void;
@@ -117989,49 +118105,9 @@ declare module BABYLON {
          */
         readonly alpha: NodeMaterialConnectionPoint;
         protected _buildBlock(state: NodeMaterialBuildState): this;
-    }
-}
-declare module BABYLON {
-    /**
-     * Block used to compute fresnel value
-     */
-    export class FresnelBlock extends NodeMaterialBlock {
-        /**
-         * Create a new FresnelBlock
-         * @param name defines the block name
-         */
-        constructor(name: string);
-        /**
-         * Gets the current class name
-         * @returns the class name
-         */
-        getClassName(): string;
-        /**
-         * Gets the world position input component
-         */
-        readonly worldPosition: NodeMaterialConnectionPoint;
-        /**
-         * Gets the world normal input component
-         */
-        readonly worldNormal: NodeMaterialConnectionPoint;
-        /**
-        * Gets the camera (or eye) position component
-        */
-        readonly cameraPosition: NodeMaterialConnectionPoint;
-        /**
-        * Gets the bias input component
-        */
-        readonly bias: NodeMaterialConnectionPoint;
-        /**
-        * Gets the camera (or eye) position component
-        */
-        readonly power: NodeMaterialConnectionPoint;
-        /**
-         * Gets the fresnel output component
-         */
-        readonly fresnel: NodeMaterialConnectionPoint;
-        autoConfigure(material: NodeMaterial): void;
-        protected _buildBlock(state: NodeMaterialBuildState): this | undefined;
+        protected _dumpPropertiesCode(): string;
+        serialize(): any;
+        _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
     }
 }
 declare module BABYLON {
@@ -118105,7 +118181,7 @@ declare module BABYLON {
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         protected _buildBlock(state: NodeMaterialBuildState): this;
@@ -118151,7 +118227,7 @@ declare module BABYLON {
          * Gets the specular output component
          */
         readonly specularOutput: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
@@ -118776,6 +118852,102 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * Block used to get the opposite of a value
+     */
+    export class OppositeBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new OppositeBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the input component
+         */
+        readonly input: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to get the view direction
+     */
+    export class ViewDirectionBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new ViewDirectionBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world position component
+         */
+        readonly worldPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the camera position component
+         */
+        readonly cameraPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to compute fresnel value
+     */
+    export class FresnelBlock extends NodeMaterialBlock {
+        /**
+         * Create a new FresnelBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world normal input component
+         */
+        readonly worldNormal: NodeMaterialConnectionPoint;
+        /**
+        * Gets the view direction input component
+        */
+        readonly viewDirection: NodeMaterialConnectionPoint;
+        /**
+        * Gets the bias input component
+        */
+        readonly bias: NodeMaterialConnectionPoint;
+        /**
+        * Gets the camera (or eye) position component
+        */
+        readonly power: NodeMaterialConnectionPoint;
+        /**
+         * Gets the fresnel output component
+         */
+        readonly fresnel: NodeMaterialConnectionPoint;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
      * Effect Render Options
      */
     export interface IEffectRendererOptions {

Diferenças do arquivo suprimidas por serem muito extensas
+ 53 - 45
dist/preview release/viewer/babylon.viewer.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 1
dist/preview release/viewer/babylon.viewer.max.js


+ 1 - 1
inspector/src/components/actionTabs/actionTabsComponent.tsx

@@ -50,7 +50,7 @@ export class ActionTabsComponent extends React.Component<IActionTabsComponentPro
         this.state = { selectedEntity: null, selectedIndex: initialIndex }
     }
 
-    componentWillMount() {
+    componentDidMount() {
         if (this.props.globalState) {
             this._onSelectionChangeObserver = this.props.globalState.onSelectionChangedObservable.add((entity) => {
                 this.setState({ selectedEntity: entity, selectedIndex: 0 });

+ 1 - 1
inspector/src/components/actionTabs/lines/radioLineComponent.tsx

@@ -18,7 +18,7 @@ export class RadioButtonLineComponent extends React.Component<IRadioButtonLineCo
         this.state = { isSelected: this.props.isSelected() };
     }
 
-    componentWillMount() {
+    componentDidMount() {
         this._onSelectionChangedObserver = this.props.onSelectionChangedObservable.add((value) => {
             this.setState({ isSelected: value === this });
         });

+ 1 - 1
inspector/src/components/actionTabs/lines/textureLinkLineComponent.tsx

@@ -35,7 +35,7 @@ export class TextureLinkLineComponent extends React.Component<ITextureLinkLineCo
         this.state = { isDebugSelected: material && material.reservedDataStore && material.reservedDataStore.debugTexture === texture };
     }
 
-    componentWillMount() {
+    componentDidMount() {
         if (!this.props.onDebugSelectionChangeObservable) {
             return;
         }

+ 0 - 5
inspector/src/components/actionTabs/tabs/debugTabComponent.tsx

@@ -13,9 +13,7 @@ export class DebugTabComponent extends PaneComponent {
 
     constructor(props: IPaneComponentProps) {
         super(props);
-    }
 
-    componentWillMount() {
         const scene = this.props.scene;
 
         if (!scene) {
@@ -29,9 +27,6 @@ export class DebugTabComponent extends PaneComponent {
         this._physicsViewersEnabled = scene.reservedDataStore.physicsViewer != null;
     }
 
-    componentWillUnmount() {
-    }
-
     switchPhysicsViewers() {
         this._physicsViewersEnabled = !this._physicsViewersEnabled;
         const scene = this.props.scene;

+ 1 - 1
inspector/src/components/actionTabs/tabs/propertyGridTabComponent.tsx

@@ -104,7 +104,7 @@ export class PropertyGridTabComponent extends PaneComponent {
         }
     }
 
-    componentWillMount() {
+    componentDidMount() {
         this._timerIntervalId = window.setInterval(() => this.timerRefresh(), 500);
     }
 

+ 6 - 8
inspector/src/components/actionTabs/tabs/propertyGrids/animationGroupPropertyGridComponent.tsx

@@ -31,6 +31,12 @@ export class AnimationGroupGridComponent extends React.Component<IAnimationGroup
 
         const animationGroup = this.props.animationGroup;
         this.state = { playButtonText: animationGroup.isPlaying ? "Pause" : "Play", currentFrame: 0 };
+
+        this.connect(this.props.animationGroup);
+
+        this._onBeforeRenderObserver = this.props.scene.onBeforeRenderObservable.add(() => {
+            this.updateCurrentFrame(this.props.animationGroup);
+        });        
     }
 
     disconnect(animationGroup: AnimationGroup) {
@@ -78,14 +84,6 @@ export class AnimationGroupGridComponent extends React.Component<IAnimationGroup
         return true;
     }
 
-    componentWillMount() {
-        this.connect(this.props.animationGroup);
-
-        this._onBeforeRenderObserver = this.props.scene.onBeforeRenderObservable.add(() => {
-            this.updateCurrentFrame(this.props.animationGroup);
-        });
-    }
-
     componentWillUnmount() {
         this.disconnect(this.props.animationGroup);
 

+ 1 - 1
inspector/src/components/actionTabs/tabs/propertyGrids/animationPropertyGridComponent.tsx

@@ -89,7 +89,7 @@ export class AnimationGridComponent extends React.Component<IAnimationGridCompon
         this.forceUpdate();
     }
 
-    componentWillMount() {
+    componentDidMount() {
         this._onBeforeRenderObserver = this.props.scene.onBeforeRenderObservable.add(() => {
             if (!this._isPlaying || !this._runningAnimatable) {
                 return;

+ 0 - 2
inspector/src/components/actionTabs/tabs/propertyGrids/materials/texturePropertyGridComponent.tsx

@@ -37,9 +37,7 @@ export class TexturePropertyGridComponent extends React.Component<ITextureProper
 
     constructor(props: ITexturePropertyGridComponentProps) {
         super(props);
-    }
 
-    componentWillMount() {
         const texture = this.props.texture;
 
         if (!texture || !(texture as any).rootContainer) {

+ 42 - 12
inspector/src/components/actionTabs/tabs/propertyGrids/meshes/meshPropertyGridComponent.tsx

@@ -35,13 +35,15 @@ interface IMeshPropertyGridComponentProps {
 }
 
 export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGridComponentProps, {
-    displayNormals: boolean
+    displayNormals: boolean,
+    displayVertexColors: boolean
 }> {
     constructor(props: IMeshPropertyGridComponentProps) {
         super(props);
 
         this.state = {
-            displayNormals: false
+            displayNormals: false,
+            displayVertexColors: false
         };
     }
 
@@ -129,11 +131,8 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
     displayNormals() {
         const mesh = this.props.mesh;
         const scene = mesh.getScene();
-        if (!mesh.material) {
-            return;
-        }
 
-        if (mesh.material.getClassName() === "NormalMaterial") {
+        if (mesh.material && mesh.material.getClassName() === "NormalMaterial") {
             mesh.material.dispose();
 
             mesh.material = mesh.reservedDataStore.originalMaterial;
@@ -156,13 +155,45 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
             mesh.reservedDataStore.originalMaterial = mesh.material;
             const normalMaterial = new (BABYLON as any).NormalMaterial("normalMaterial", scene);
             normalMaterial.disableLighting = true;
-            normalMaterial.sideOrientation = mesh.material.sideOrientation;
+            if (mesh.material) {
+                normalMaterial.sideOrientation = mesh.material.sideOrientation;
+            }
             normalMaterial.reservedDataStore = { hidden: true };
             mesh.material = normalMaterial;
             this.setState({ displayNormals: true });
         }
     }
 
+    displayVertexColors() {
+        const mesh = this.props.mesh;
+        const scene = mesh.getScene();
+
+        if (mesh.material && mesh.material.reservedDataStore && mesh.material.reservedDataStore.isVertexColorMaterial) {
+            mesh.material.dispose();
+
+            mesh.material = mesh.reservedDataStore.originalMaterial;
+            mesh.reservedDataStore.originalMaterial = null;
+            this.setState({ displayVertexColors: false });
+        } else {
+
+            if (!mesh.reservedDataStore) {
+                mesh.reservedDataStore = {};
+            }
+
+            mesh.reservedDataStore.originalMaterial = mesh.material;
+            const vertexColorMaterial = new StandardMaterial("vertex colors", scene);
+            vertexColorMaterial.disableLighting = true;
+            vertexColorMaterial.emissiveColor = Color3.White();
+            if (mesh.material) {
+                vertexColorMaterial.sideOrientation = mesh.material.sideOrientation;
+            }
+            vertexColorMaterial.reservedDataStore = { hidden: true, isVertexColorMaterial: true };
+            mesh.useVertexColors = true;
+            mesh.material = vertexColorMaterial;
+            this.setState({ displayVertexColors: true });
+        }
+    }
+
     onMaterialLink() {
         if (!this.props.onSelectionChangedObservable) {
             return;
@@ -216,6 +247,7 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
         const scene = mesh.getScene();
 
         const displayNormals = mesh.material != null && mesh.material.getClassName() === "NormalMaterial";
+        const displayVertexColors = mesh.material != null && mesh.material.reservedDataStore && mesh.material.reservedDataStore.isVertexColorMaterial;
         const renderNormalVectors = (mesh.reservedDataStore && mesh.reservedDataStore.normalLines) ? true : false;
         const renderWireframeOver = (mesh.reservedDataStore && mesh.reservedDataStore.wireframeOver) ? true : false;
 
@@ -254,7 +286,7 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
                     <CheckBoxLineComponent label="Is enabled" isSelected={() => mesh.isEnabled()} onSelect={(value) => mesh.setEnabled(value)} />
                     <CheckBoxLineComponent label="Is pickable" target={mesh} propertyName="isPickable" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     {
-                        mesh.material &&
+                        mesh.material && (!mesh.material.reservedDataStore || !mesh.material.reservedDataStore.hidden) &&
                         <TextLineComponent label="Material" value={mesh.material.name} onLink={() => this.onMaterialLink()} />
                     }
                     {
@@ -355,10 +387,8 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
                     <Color3LineComponent label="Outline color" target={mesh} propertyName="outlineColor" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                 </LineContainerComponent>
                 <LineContainerComponent globalState={this.props.globalState} title="DEBUG" closed={true}>
-                    {
-                        mesh.material &&
-                        <CheckBoxLineComponent label="Display normals" isSelected={() => displayNormals} onSelect={() => this.displayNormals()} />
-                    }
+                    <CheckBoxLineComponent label="Display normals" isSelected={() => displayNormals} onSelect={() => this.displayNormals()} />
+                    <CheckBoxLineComponent label="Display vertex colors" isSelected={() => displayVertexColors} onSelect={() => this.displayVertexColors()} />
                     {
                         mesh.isVerticesDataPresent(VertexBuffer.NormalKind) &&
                         <CheckBoxLineComponent label="Render vertex normals" isSelected={() => renderNormalVectors} onSelect={() => this.renderNormalVectors()} />

+ 2 - 4
inspector/src/components/actionTabs/tabs/propertyGrids/meshes/skeletonPropertyGridComponent.tsx

@@ -26,6 +26,8 @@ export class SkeletonPropertyGridComponent extends React.Component<ISkeletonProp
 
     constructor(props: ISkeletonPropertyGridComponentProps) {
         super(props);
+        
+        this.checkSkeletonViewerState(this.props);
     }
 
     switchSkeletonViewers() {
@@ -81,10 +83,6 @@ export class SkeletonPropertyGridComponent extends React.Component<ISkeletonProp
         this._skeletonViewersEnabled = (this._skeletonViewers.length > 0);
     }
 
-    componentWillMount() {
-        this.checkSkeletonViewerState(this.props);
-    }
-
     shouldComponentUpdate(nextProps: ISkeletonPropertyGridComponentProps) {
         if (nextProps.skeleton !== this.props.skeleton) {
             this.checkSkeletonViewerState(nextProps);

+ 1 - 1
inspector/src/components/actionTabs/tabs/propertyGrids/renderGridPropertyGridComponent.tsx

@@ -25,7 +25,7 @@ export class RenderGridPropertyGridComponent extends React.Component<IRenderGrid
         this.state = { isEnabled: false };
     }
 
-    componentWillMount() {
+    componentDidMount() {
         const scene = UtilityLayerRenderer.DefaultKeepDepthUtilityLayer.utilityLayerScene;
 
         for (var mesh of scene.meshes) {

+ 0 - 2
inspector/src/components/actionTabs/tabs/statisticsTabComponent.tsx

@@ -18,9 +18,7 @@ export class StatisticsTabComponent extends PaneComponent {
 
     constructor(props: IPaneComponentProps) {
         super(props);
-    }
 
-    componentWillMount() {
         const scene = this.props.scene;
 
         if (!scene) {

+ 1 - 1
inspector/src/components/actionTabs/tabs/toolsTabComponent.tsx

@@ -28,7 +28,7 @@ export class ToolsTabComponent extends PaneComponent {
         this.state = { tag: "Record video" };
     }
 
-    componentWillMount() {
+    componentDidMount() {
         if (!(BABYLON as any).GLTF2Export) {
             Tools.LoadScript("https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js", () => {
             });

+ 1 - 1
inspector/src/components/headerComponent.tsx

@@ -25,7 +25,7 @@ export class HeaderComponent extends React.Component<IHeaderComponentProps, { is
         this.state = { isBackVisible: false };
     }
 
-    componentWillMount() {
+    componentDidMount() {
         if (!this.props.onSelectionChangedObservable) {
             return;
         }

+ 1 - 1
inspector/src/components/sceneExplorer/entities/cameraTreeItemComponent.tsx

@@ -39,7 +39,7 @@ export class CameraTreeItemComponent extends React.Component<ICameraTreeItemComp
         this.setState({ isActive: true });
     }
 
-    componentWillMount() {
+    componentDidMount() {
         const camera = this.props.camera;
         const scene = camera.getScene();
         this._onActiveCameraObserver = scene.onActiveCameraChanged.add(() => {

+ 1 - 1
inspector/src/components/sceneExplorer/entities/sceneTreeItemComponent.tsx

@@ -69,7 +69,7 @@ export class SceneTreeItemComponent extends React.Component<ISceneTreeItemCompon
         return true;
     }
 
-    componentWillMount() {
+    componentDidMount() {
         if (!this.props.onSelectionChangedObservable) {
             return;
         }

+ 1 - 1
inspector/src/components/sceneExplorer/sceneExplorerComponent.tsx

@@ -78,7 +78,7 @@ export class SceneExplorerComponent extends React.Component<ISceneExplorerCompon
         this.forceUpdate();
     }
 
-    componentWillMount() {
+    componentDidMount() {
         this._onSelectionChangeObserver = this.props.globalState.onSelectionChangedObservable.add((entity) => {
             if (this.state.selectedEntity !== entity) {
                 this.setState({ selectedEntity: entity });

+ 159 - 306
localDev/fresnel.json

@@ -22,39 +22,39 @@
   "fillMode": 0,
   "customType": "BABYLON.NodeMaterial",
   "outputNodes": [
-    200,
-    213,
-    226
+    84,
+    93,
+    94
   ],
   "blocks": [
     {
       "customType": "BABYLON.VertexOutputBlock",
-      "id": 200,
+      "id": 84,
       "name": "vertexOutput",
       "inputs": [
         {
           "name": "vector",
           "inputName": "vector",
-          "targetBlockId": 201,
+          "targetBlockId": 83,
           "targetConnectionName": "output"
         }
       ]
     },
     {
       "customType": "BABYLON.TransformBlock",
-      "id": 201,
+      "id": 83,
       "name": "worldPos * viewProjectionTransform",
       "inputs": [
         {
           "name": "vector",
           "inputName": "vector",
-          "targetBlockId": 202,
+          "targetBlockId": 81,
           "targetConnectionName": "output"
         },
         {
           "name": "transform",
           "inputName": "transform",
-          "targetBlockId": 212,
+          "targetBlockId": 82,
           "targetConnectionName": "output"
         }
       ],
@@ -63,19 +63,19 @@
     },
     {
       "customType": "BABYLON.TransformBlock",
-      "id": 202,
+      "id": 81,
       "name": "worldPos",
       "inputs": [
         {
           "name": "vector",
           "inputName": "vector",
-          "targetBlockId": 203,
+          "targetBlockId": 79,
           "targetConnectionName": "positionOutput"
         },
         {
           "name": "transform",
           "inputName": "transform",
-          "targetBlockId": 208,
+          "targetBlockId": 80,
           "targetConnectionName": "output"
         }
       ],
@@ -84,38 +84,38 @@
     },
     {
       "customType": "BABYLON.MorphTargetsBlock",
-      "id": 203,
+      "id": 79,
       "name": "morphTargets",
       "inputs": [
         {
           "name": "position",
           "inputName": "position",
-          "targetBlockId": 204,
+          "targetBlockId": 95,
           "targetConnectionName": "output"
         },
         {
           "name": "normal",
           "inputName": "normal",
-          "targetBlockId": 205,
+          "targetBlockId": 96,
           "targetConnectionName": "output"
         },
         {
           "name": "tangent",
           "inputName": "tangent",
-          "targetBlockId": 206,
+          "targetBlockId": 97,
           "targetConnectionName": "output"
         },
         {
           "name": "uv",
           "inputName": "uv",
-          "targetBlockId": 207,
+          "targetBlockId": 98,
           "targetConnectionName": "output"
         }
       ]
     },
     {
       "customType": "BABYLON.InputBlock",
-      "id": 204,
+      "id": 95,
       "name": "position",
       "inputs": [],
       "type": 8,
@@ -126,7 +126,7 @@
     },
     {
       "customType": "BABYLON.InputBlock",
-      "id": 205,
+      "id": 96,
       "name": "normal",
       "inputs": [],
       "type": 8,
@@ -137,7 +137,7 @@
     },
     {
       "customType": "BABYLON.InputBlock",
-      "id": 206,
+      "id": 97,
       "name": "tangent",
       "inputs": [],
       "type": 8,
@@ -148,7 +148,7 @@
     },
     {
       "customType": "BABYLON.InputBlock",
-      "id": 207,
+      "id": 98,
       "name": "uv",
       "inputs": [],
       "type": 4,
@@ -159,19 +159,19 @@
     },
     {
       "customType": "BABYLON.BonesBlock",
-      "id": 208,
+      "id": 80,
       "name": "bonesBlock",
       "inputs": [
         {
           "name": "matricesIndices",
           "inputName": "matricesIndices",
-          "targetBlockId": 209,
+          "targetBlockId": 99,
           "targetConnectionName": "output"
         },
         {
           "name": "matricesWeights",
           "inputName": "matricesWeights",
-          "targetBlockId": 210,
+          "targetBlockId": 100,
           "targetConnectionName": "output"
         },
         {
@@ -183,14 +183,14 @@
         {
           "name": "world",
           "inputName": "world",
-          "targetBlockId": 211,
+          "targetBlockId": 101,
           "targetConnectionName": "output"
         }
       ]
     },
     {
       "customType": "BABYLON.InputBlock",
-      "id": 209,
+      "id": 99,
       "name": "matricesIndices",
       "inputs": [],
       "type": 16,
@@ -201,7 +201,7 @@
     },
     {
       "customType": "BABYLON.InputBlock",
-      "id": 210,
+      "id": 100,
       "name": "matricesWeights",
       "inputs": [],
       "type": 16,
@@ -212,37 +212,18 @@
     },
     {
       "customType": "BABYLON.InputBlock",
-      "id": 211,
+      "id": 101,
       "name": "world",
       "inputs": [],
       "type": 128,
       "mode": 0,
       "wellKnownValue": 1,
       "animationType": 0,
-      "visibleInInspector": false,
-      "valueType": "BABYLON.Matrix",
-      "value": {
-        "0": 1,
-        "1": 0,
-        "2": 0,
-        "3": 0,
-        "4": 0,
-        "5": 1,
-        "6": 0,
-        "7": 0,
-        "8": 0,
-        "9": 0,
-        "10": 1,
-        "11": 0,
-        "12": 0,
-        "13": 0,
-        "14": 0,
-        "15": 1
-      }
+      "visibleInInspector": false
     },
     {
       "customType": "BABYLON.InputBlock",
-      "id": 212,
+      "id": 82,
       "name": "viewProjection",
       "inputs": [],
       "type": 128,
@@ -253,38 +234,38 @@
     },
     {
       "customType": "BABYLON.FogBlock",
-      "id": 213,
+      "id": 93,
       "name": "fog",
       "inputs": [
         {
           "name": "worldPosition",
           "inputName": "worldPosition",
-          "targetBlockId": 202,
+          "targetBlockId": 81,
           "targetConnectionName": "output"
         },
         {
           "name": "view",
           "inputName": "view",
-          "targetBlockId": 214,
+          "targetBlockId": 102,
           "targetConnectionName": "output"
         },
         {
           "name": "input",
           "inputName": "input",
-          "targetBlockId": 215,
+          "targetBlockId": 92,
           "targetConnectionName": "rgb"
         },
         {
           "name": "fogColor",
           "inputName": "fogColor",
-          "targetBlockId": 225,
+          "targetBlockId": 103,
           "targetConnectionName": "output"
         }
       ]
     },
     {
       "customType": "BABYLON.InputBlock",
-      "id": 214,
+      "id": 102,
       "name": "view",
       "inputs": [],
       "type": 128,
@@ -295,67 +276,67 @@
     },
     {
       "customType": "BABYLON.ColorSplitterBlock",
-      "id": 215,
+      "id": 92,
       "name": "color4 splitter",
       "inputs": [
         {
-          "name": "rgba",
-          "inputName": "rgba",
-          "targetBlockId": 216,
-          "targetConnectionName": "output"
+          "name": "rgba"
         },
         {
-          "name": "rgb "
+          "name": "rgb ",
+          "inputName": "rgb ",
+          "targetBlockId": 491,
+          "targetConnectionName": "output"
         }
       ]
     },
     {
-      "customType": "BABYLON.ScaleBlock",
-      "id": 216,
-      "name": "color scale",
+      "customType": "BABYLON.MultiplyBlock",
+      "id": 491,
+      "name": "Multiply",
       "inputs": [
         {
-          "name": "input",
-          "inputName": "input",
-          "targetBlockId": 217,
+          "name": "left",
+          "inputName": "left",
+          "targetBlockId": 86,
           "targetConnectionName": "output"
         },
         {
-          "name": "factor",
-          "inputName": "factor",
-          "targetBlockId": 224,
-          "targetConnectionName": "output"
+          "name": "right",
+          "inputName": "right",
+          "targetBlockId": 255,
+          "targetConnectionName": "diffuseOutput"
         }
       ]
     },
     {
       "customType": "BABYLON.MultiplyBlock",
-      "id": 217,
+      "id": 86,
       "name": "color multiplier",
       "inputs": [
         {
           "name": "left",
           "inputName": "left",
-          "targetBlockId": 218,
-          "targetConnectionName": "rgba"
+          "targetBlockId": 87,
+          "targetConnectionName": "rgb"
         },
         {
           "name": "right",
           "inputName": "right",
-          "targetBlockId": 221,
-          "targetConnectionName": "rgba"
+          "targetBlockId": 89,
+          "targetConnectionName": "rgb"
         }
       ]
     },
     {
       "customType": "BABYLON.TextureBlock",
-      "id": 218,
+      "id": 87,
       "name": "diffuseTexture",
       "inputs": [
         {
           "name": "uv",
           "inputName": "uv",
-          "targetBlockId": 220,
+          "targetBlockId": 98,
           "targetConnectionName": "output"
         }
       ],
@@ -399,25 +380,14 @@
       }
     },
     {
-      "customType": "BABYLON.InputBlock",
-      "id": 220,
-      "name": "uv",
-      "inputs": [],
-      "type": 4,
-      "mode": 1,
-      "wellKnownValue": null,
-      "animationType": 0,
-      "visibleInInspector": false
-    },
-    {
       "customType": "BABYLON.TextureBlock",
-      "id": 221,
+      "id": 89,
       "name": "diffuseTexture2",
       "inputs": [
         {
           "name": "uv",
           "inputName": "uv",
-          "targetBlockId": 223,
+          "targetBlockId": 98,
           "targetConnectionName": "output"
         }
       ],
@@ -461,136 +431,45 @@
       }
     },
     {
-      "customType": "BABYLON.InputBlock",
-      "id": 223,
-      "name": "uv",
-      "inputs": [],
-      "type": 4,
-      "mode": 1,
-      "wellKnownValue": null,
-      "animationType": 0,
-      "visibleInInspector": false
-    },
-    {
-      "customType": "BABYLON.InputBlock",
-      "id": 224,
-      "name": "time",
-      "inputs": [],
-      "type": 1,
-      "mode": 0,
-      "wellKnownValue": null,
-      "animationType": 0,
-      "visibleInInspector": false,
-      "valueType": "number",
-      "value": 1
-    },
-    {
-      "customType": "BABYLON.InputBlock",
-      "id": 225,
-      "name": "fogColor",
-      "inputs": [],
-      "type": 32,
-      "mode": 0,
-      "wellKnownValue": 8,
-      "animationType": 0,
-      "visibleInInspector": false,
-      "valueType": "BABYLON.Color3",
-      "value": [
-        1,
-        1,
-        1
-      ]
-    },
-    {
-      "customType": "BABYLON.FragmentOutputBlock",
-      "id": 226,
-      "name": "pixelOutput",
-      "inputs": [
-        {
-          "name": "rgba"
-        },
-        {
-          "name": "rgb",
-          "inputName": "rgb",
-          "targetBlockId": 524,
-          "targetConnectionName": "output"
-        },
-        {
-          "name": "a"
-        }
-      ]
-    },
-    {
-      "customType": "BABYLON.ScaleBlock",
-      "id": 524,
-      "name": "Scale",
-      "inputs": [
-        {
-          "name": "input",
-          "inputName": "input",
-          "targetBlockId": 213,
-          "targetConnectionName": "output"
-        },
-        {
-          "name": "factor",
-          "inputName": "factor",
-          "targetBlockId": 228,
-          "targetConnectionName": "fresnel"
-        }
-      ]
-    },
-    {
-      "customType": "BABYLON.FresnelBlock",
-      "id": 228,
-      "name": "Fresnel",
+      "customType": "BABYLON.LightBlock",
+      "id": 255,
+      "name": "Lights",
       "inputs": [
         {
           "name": "worldPosition",
           "inputName": "worldPosition",
-          "targetBlockId": 202,
+          "targetBlockId": 81,
           "targetConnectionName": "output"
         },
         {
           "name": "worldNormal",
           "inputName": "worldNormal",
-          "targetBlockId": 229,
+          "targetBlockId": 418,
           "targetConnectionName": "output"
         },
         {
           "name": "cameraPosition",
           "inputName": "cameraPosition",
-          "targetBlockId": 231,
-          "targetConnectionName": "output"
-        },
-        {
-          "name": "bias",
-          "inputName": "bias",
-          "targetBlockId": 232,
-          "targetConnectionName": "output"
-        },
-        {
-          "name": "power",
-          "inputName": "power",
-          "targetBlockId": 233,
+          "targetBlockId": 256,
           "targetConnectionName": "output"
         }
       ]
     },
     {
       "customType": "BABYLON.TransformBlock",
-      "id": 229,
+      "id": 418,
       "name": "Transform",
       "inputs": [
         {
           "name": "vector",
           "inputName": "vector",
-          "targetBlockId": 230,
+          "targetBlockId": 409,
           "targetConnectionName": "output"
         },
         {
           "name": "transform",
           "inputName": "transform",
-          "targetBlockId": 208,
+          "targetBlockId": 80,
           "targetConnectionName": "output"
         }
       ],
@@ -599,7 +478,7 @@
     },
     {
       "customType": "BABYLON.InputBlock",
-      "id": 230,
+      "id": 409,
       "name": "normal",
       "inputs": [],
       "type": 8,
@@ -610,208 +489,182 @@
     },
     {
       "customType": "BABYLON.InputBlock",
-      "id": 231,
-      "name": "Vector3",
+      "id": 256,
+      "name": "cameraPosition",
       "inputs": [],
       "type": 8,
       "mode": 0,
       "wellKnownValue": 7,
       "animationType": 0,
-      "visibleInInspector": false,
-      "valueType": "BABYLON.Vector3",
-      "value": [
-        0,
-        0,
-        0
-      ]
+      "visibleInInspector": false
     },
     {
       "customType": "BABYLON.InputBlock",
-      "id": 232,
-      "name": "Float",
+      "id": 103,
+      "name": "fogColor",
       "inputs": [],
-      "type": 1,
+      "type": 32,
       "mode": 0,
-      "wellKnownValue": null,
+      "wellKnownValue": 8,
       "animationType": 0,
       "visibleInInspector": false,
-      "valueType": "number",
-      "value": 0
+      "valueType": "BABYLON.Color3",
+      "value": [
+        1,
+        1,
+        1
+      ]
     },
     {
-      "customType": "BABYLON.InputBlock",
-      "id": 233,
-      "name": "Float",
-      "inputs": [],
-      "type": 1,
-      "mode": 0,
-      "wellKnownValue": null,
-      "animationType": 0,
-      "visibleInInspector": false,
-      "valueType": "number",
-      "value": 1
+      "customType": "BABYLON.FragmentOutputBlock",
+      "id": 94,
+      "name": "pixelOutput",
+      "inputs": [
+        {
+          "name": "rgba"
+        },
+        {
+          "name": "rgb",
+          "inputName": "rgb",
+          "targetBlockId": 93,
+          "targetConnectionName": "output"
+        },
+        {
+          "name": "a"
+        }
+      ]
     }
   ],
   "locations": [
     {
-      "blockId": 200,
+      "blockId": 84,
       "x": 1500,
-      "y": 561.5
+      "y": 399
     },
     {
-      "blockId": 201,
+      "blockId": 83,
       "x": 1250,
-      "y": 548.5
+      "y": 386
     },
     {
-      "blockId": 202,
+      "blockId": 81,
       "x": 1000,
-      "y": 465
+      "y": 396
     },
     {
-      "blockId": 203,
+      "blockId": 79,
       "x": 750,
-      "y": 172
+      "y": 137.5
     },
     {
-      "blockId": 204,
+      "blockId": 95,
       "x": 500,
       "y": 0
     },
     {
-      "blockId": 205,
+      "blockId": 96,
       "x": 500,
       "y": 158
     },
     {
-      "blockId": 206,
+      "blockId": 97,
       "x": 500,
       "y": 316
     },
     {
-      "blockId": 207,
-      "x": 500,
-      "y": 474
+      "blockId": 98,
+      "x": 0,
+      "y": 691
     },
     {
-      "blockId": 208,
+      "blockId": 80,
       "x": 750,
-      "y": 639
+      "y": 501
     },
     {
-      "blockId": 209,
+      "blockId": 99,
       "x": 500,
-      "y": 632
+      "y": 494
     },
     {
-      "blockId": 210,
+      "blockId": 100,
       "x": 500,
-      "y": 790
+      "y": 652
     },
     {
-      "blockId": 211,
+      "blockId": 101,
       "x": 500,
-      "y": 948
+      "y": 810
     },
     {
-      "blockId": 212,
+      "blockId": 82,
       "x": 1000,
-      "y": 842
+      "y": 704
     },
     {
-      "blockId": 213,
-      "x": 1473,
-      "y": 1109
+      "blockId": 94,
+      "x": 1500,
+      "y": 973
     },
     {
-      "blockId": 214,
-      "x": 1000,
-      "y": 1000
+      "blockId": 93,
+      "x": 1250,
+      "y": 916
     },
     {
-      "blockId": 215,
+      "blockId": 102,
       "x": 1000,
-      "y": 1158
+      "y": 862
     },
     {
-      "blockId": 216,
-      "x": 750,
-      "y": 1221
+      "blockId": 92,
+      "x": 1000,
+      "y": 1020
     },
     {
-      "blockId": 217,
-      "x": 500,
-      "y": 1137.5
+      "blockId": 86,
+      "x": 519.7647058823529,
+      "y": 965.1764705882352
     },
     {
-      "blockId": 218,
+      "blockId": 87,
       "x": 250,
-      "y": 931.5
-    },
-    {
-      "blockId": 220,
-      "x": 0,
-      "y": 999.5
+      "y": 701.5
     },
     {
-      "blockId": 221,
+      "blockId": 89,
       "x": 250,
-      "y": 1225.5
-    },
-    {
-      "blockId": 223,
-      "x": 0,
-      "y": 1293.5
+      "y": 1056
     },
     {
-      "blockId": 224,
-      "x": 500,
-      "y": 1313.5
-    },
-    {
-      "blockId": 225,
+      "blockId": 103,
       "x": 1000,
-      "y": 1460
-    },
-    {
-      "blockId": 226,
-      "x": 2470.619469026549,
-      "y": 953.8318584070795
-    },
-    {
-      "blockId": 228,
-      "x": 1721.8141602372705,
-      "y": 789.0458809677541
-    },
-    {
-      "blockId": 229,
-      "x": 1176.0973460779783,
-      "y": 704.7538455695241
+      "y": 1322
     },
     {
-      "blockId": 230,
-      "x": 989.1946912107215,
-      "y": 592.1874738881081
+      "blockId": 255,
+      "x": 452.0588235294116,
+      "y": 1241.0588235294117
     },
     {
-      "blockId": 231,
-      "x": 1432.91148916599,
-      "y": 680.329066808462
+      "blockId": 256,
+      "x": 221.05882352941177,
+      "y": 1607.1176470588236
     },
     {
-      "blockId": 232,
-      "x": 1411.6725511128925,
-      "y": 834.3113676934179
+      "blockId": 409,
+      "x": 21.82147288123261,
+      "y": 1389.5119468766763
     },
     {
-      "blockId": 233,
-      "x": 1369.1946750066977,
-      "y": 962.8688898173117
+      "blockId": 418,
+      "x": 333.8214728812328,
+      "y": 1361.2766527590293
     },
     {
-      "blockId": 524,
-      "x": 2063,
-      "y": 1078
+      "blockId": 491,
+      "x": 770.0567669988801,
+      "y": 1040.8060645237351
     }
   ]
 }

+ 91 - 2
nodeEditor/src/blockTools.ts

@@ -24,11 +24,16 @@ import { DotBlock } from 'babylonjs/Materials/Node/Blocks/dotBlock';
 import { MultiplyBlock } from 'babylonjs/Materials/Node/Blocks/multiplyBlock';
 import { TransformBlock } from 'babylonjs/Materials/Node/Blocks/transformBlock';
 import { NodeMaterialBlockConnectionPointTypes } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPointTypes';
-import { FresnelBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/fresnelBlock';
+import { FresnelBlock } from 'babylonjs/Materials/Node/Blocks/fresnelBlock';
 import { LerpBlock } from 'babylonjs/Materials/Node/Blocks/lerpBlock';
 import { DivideBlock } from 'babylonjs/Materials/Node/Blocks/divideBlock';
 import { SubtractBlock } from 'babylonjs/Materials/Node/Blocks/subtractBlock';
 import { StepBlock } from 'babylonjs/Materials/Node/Blocks/stepBlock';
+import { InputBlock } from 'babylonjs/Materials/Node/Blocks/Input/inputBlock';
+import { NodeMaterialWellKnownValues } from 'babylonjs/Materials/Node/nodeMaterialWellKnownValues';
+import { AnimatedInputBlockTypes } from 'babylonjs/Materials/Node/Blocks/Input/animatedInputBlockTypes';
+import { OppositeBlock } from 'babylonjs/Materials/Node/Blocks/oppositeBlock';
+import { ViewDirectionBlock } from 'babylonjs/Materials/Node/Blocks/viewDirectionBlock';
 
 export class BlockTools {
     public static GetBlockFromString(data: string) {
@@ -93,6 +98,10 @@ export class BlockTools {
                 return new SubtractBlock("Subtract"); 
             case "StepBlock":
                 return new StepBlock("Step");        
+            case "OppositeBlock":
+                return new OppositeBlock("Opposite");      
+            case "ViewDirectionBlock":
+                return new ViewDirectionBlock("View direction");                    
             case "CosBlock": {
                 let cosBlock = new TrigonometryBlock("Cos");
                 cosBlock.operation = TrigonometryBlockOperations.Cos;
@@ -132,7 +141,87 @@ export class BlockTools {
                 let floorBlock = new TrigonometryBlock("Floor");
                 floorBlock.operation = TrigonometryBlockOperations.Floor;
                 return floorBlock;
-            }                                    
+            }       
+            case "WorldMatrixBlock": {
+                let worldMatrixBlock = new InputBlock("World");
+                worldMatrixBlock.setAsWellKnownValue(NodeMaterialWellKnownValues.World);
+                return worldMatrixBlock;
+            }             
+            case "WorldViewMatrixBlock": {
+                let worldViewMatrixBlock = new InputBlock("World x View");
+                worldViewMatrixBlock.setAsWellKnownValue(NodeMaterialWellKnownValues.WorldView);
+                return worldViewMatrixBlock;
+            }             
+            case "WorldViewProjectionMatrixBlock": {
+                let worldViewProjectionMatrixBlock = new InputBlock("World x View x Projection");
+                worldViewProjectionMatrixBlock.setAsWellKnownValue(NodeMaterialWellKnownValues.WorldViewProjection);
+                return worldViewProjectionMatrixBlock;
+            }                    
+            case "ViewMatrixBlock": {
+                let viewMatrixBlock = new InputBlock("View");
+                viewMatrixBlock.setAsWellKnownValue(NodeMaterialWellKnownValues.View);
+                return viewMatrixBlock;
+            }                          
+            case "ViewProjectionMatrixBlock": {
+                let viewProjectionMatrixBlock = new InputBlock("View x Projection");
+                viewProjectionMatrixBlock.setAsWellKnownValue(NodeMaterialWellKnownValues.ViewProjection);
+                return viewProjectionMatrixBlock;
+            }                              
+            case "ProjectionMatrixBlock": {
+                let projectionMatrixBlock = new InputBlock("Projection");
+                projectionMatrixBlock.setAsWellKnownValue(NodeMaterialWellKnownValues.Projection);
+                return projectionMatrixBlock;
+            }                                 
+            case "CameraPositionBlock": {
+                let cameraPosition = new InputBlock("Camera position");
+                cameraPosition.setAsWellKnownValue(NodeMaterialWellKnownValues.CameraPosition);
+                return cameraPosition;
+            }                              
+            case "FogColorBlock": {
+                let FogColor = new InputBlock("Fog color");
+                FogColor.setAsWellKnownValue(NodeMaterialWellKnownValues.FogColor);
+                return FogColor;
+            }                                   
+            case "PositionBlock": {
+                let meshPosition = new InputBlock("position");
+                meshPosition.setAsAttribute("position");
+                return meshPosition;
+            }                                        
+            case "UVBlock": {
+                let meshUV = new InputBlock("uv");
+                meshUV.setAsAttribute("uv");
+                return meshUV;
+            }                                         
+            case "ColorBlock": {
+                let meshColor = new InputBlock("color");
+                meshColor.setAsAttribute("color");
+                return meshColor;
+            }                                              
+            case "NormalBlock": {
+                let meshNormal = new InputBlock("normal");
+                meshNormal.setAsAttribute("normal");
+                return meshNormal;
+            }                                                 
+            case "TangentBlock": {
+                let meshTangent = new InputBlock("tangent");
+                meshTangent.setAsAttribute("tangent");
+                return meshTangent;
+            }                                                  
+            case "MatrixIndicesBlock": {
+                let meshMatrixIndices = new InputBlock("matricesIndices");
+                meshMatrixIndices.setAsAttribute("matricesIndices");
+                return meshMatrixIndices;
+            }                                                    
+            case "MatrixWeightsBlock": {
+                let meshMatrixWeights = new InputBlock("matricesWeights");
+                meshMatrixWeights.setAsAttribute("matricesWeights");
+                return meshMatrixWeights;
+            }                                                     
+            case "TimeBlock": {
+                let timeBlock = new InputBlock("Time", undefined, NodeMaterialBlockConnectionPointTypes.Float);
+                timeBlock.animationType = AnimatedInputBlockTypes.Time;
+                return timeBlock;
+            }   
         }
 
         return null;

+ 23 - 0
nodeEditor/src/components/diagram/clamp/clampNodeFactory.tsx

@@ -0,0 +1,23 @@
+import * as SRD from "storm-react-diagrams";
+import * as React from "react";
+import { GlobalState } from '../../../globalState';
+import { ClampNodeWidget } from './clampNodeWidget';
+import { ClampNodeModel } from './clampNodeModel';
+
+export class ClampNodeFactory extends SRD.AbstractNodeFactory {
+    private _globalState: GlobalState;
+
+    constructor(globalState: GlobalState) {
+        super("clamp");
+
+        this._globalState = globalState;
+    }
+
+    generateReactWidget(diagramEngine: SRD.DiagramEngine, node: ClampNodeModel): JSX.Element {
+        return <ClampNodeWidget node={node} globalState={this._globalState} />;
+    }
+
+    getNewInstance() {
+        return new ClampNodeModel();
+    }
+}

+ 25 - 0
nodeEditor/src/components/diagram/clamp/clampNodeModel.tsx

@@ -0,0 +1,25 @@
+import * as React from "react";
+import { DefaultNodeModel } from '../defaultNodeModel';
+import { GlobalState } from '../../../globalState';
+import { ClampBlock } from 'babylonjs/Materials/Node/Blocks/clampBlock';
+import { ClampPropertyTabComponentProps } from './clampNodePropertyComponent';
+
+export class ClampNodeModel extends DefaultNodeModel {
+
+    public get clampBlock(): ClampBlock {
+        return this.block as ClampBlock;
+    }
+
+	/**
+	 * Constructs the node model
+	 */
+    constructor() {
+        super("clamp");
+    }
+
+    renderProperties(globalState: GlobalState) {
+        return (
+            <ClampPropertyTabComponentProps globalState={globalState} remapNode={this} />
+        );
+    }
+}

+ 42 - 0
nodeEditor/src/components/diagram/clamp/clampNodePropertyComponent.tsx

@@ -0,0 +1,42 @@
+
+import * as React from "react";
+import { GlobalState } from '../../../globalState';
+import { LineContainerComponent } from '../../../sharedComponents/lineContainerComponent';
+import { TextInputLineComponent } from '../../../sharedComponents/textInputLineComponent';
+import { TextLineComponent } from '../../../sharedComponents/textLineComponent';
+import { ClampNodeModel } from './clampNodeModel';
+import { FloatLineComponent } from '../../../sharedComponents/floatLineComponent';
+
+interface IClampPropertyTabComponentProps {
+    globalState: GlobalState;
+    remapNode: ClampNodeModel;
+}
+
+export class ClampPropertyTabComponentProps extends React.Component<IClampPropertyTabComponentProps> {
+
+    constructor(props: IClampPropertyTabComponentProps) {
+        super(props)
+    }
+
+    forceRebuild() {
+        this.props.globalState.onUpdateRequiredObservable.notifyObservers();
+        this.props.globalState.onRebuildRequiredObservable.notifyObservers();
+    }
+
+    render() {
+        let clampBlock = this.props.remapNode.clampBlock;
+      
+        return (
+            <div>
+                <LineContainerComponent title="GENERAL">
+                    <TextInputLineComponent globalState={this.props.globalState} label="Name" propertyName="name" target={clampBlock} onChange={() => this.props.globalState.onUpdateRequiredObservable.notifyObservers()} />
+                    <TextLineComponent label="Type" value={clampBlock.getClassName()} />
+                </LineContainerComponent>
+                <LineContainerComponent title="PROPERTIES">
+                  <FloatLineComponent label="Minimum" propertyName="minimum" target={clampBlock} onChange={() => this.forceRebuild()} />
+                  <FloatLineComponent label="Maximum" propertyName="maximum" target={clampBlock} onChange={() => this.forceRebuild()} />
+                </LineContainerComponent>
+            </div>
+        );
+    }
+}

+ 64 - 0
nodeEditor/src/components/diagram/clamp/clampNodeWidget.tsx

@@ -0,0 +1,64 @@
+import * as React from "react";
+import { ClampNodeModel } from './clampNodeModel';
+import { Nullable } from 'babylonjs/types';
+import { GlobalState } from '../../../globalState';
+import { PortHelper } from '../portHelper';
+import { ClampBlock } from 'babylonjs/Materials/Node/Blocks/clampBlock';
+
+export interface ClampNodeWidgetProps {
+    node: Nullable<ClampNodeModel>;
+    globalState: GlobalState;
+}
+
+export class ClampNodeWidget extends React.Component<ClampNodeWidgetProps> {
+    constructor(props: ClampNodeWidgetProps) {
+        super(props);
+        this.state = {};
+
+        if (this.props.node) {
+            this.props.node.addListener({
+                selectionChanged: () => {
+                    let selected = (this.props.node as any).selected;
+                    this.props.globalState.onSelectionChangedObservable.notifyObservers(selected ? this.props.node : null);
+                }
+            });
+        }
+    }
+
+    renderValue(value: string) {
+        if (value) {
+            return (
+                <div className="value-text">
+                    {value}
+                </div>
+            )
+        }
+
+        return null;
+    }
+
+    render() {
+        var inputPorts = PortHelper.GenerateInputPorts(this.props.node, undefined, true);
+        var outputPorts = PortHelper.GenerateOutputPorts(this.props.node, true);
+        let clampBlock = this.props.node!.block! as ClampBlock;
+
+        return (
+            <div className={"diagramBlock remap"}>
+                <div className="header">
+                    {clampBlock.name}
+                </div>
+                <div className="inputs">
+                    {inputPorts}
+                </div>
+                <div className="outputs">
+                    {outputPorts}
+                </div>
+                <div className="value">  
+                {
+                    `[${clampBlock.minimum}, ${clampBlock.maximum}]`
+                }                 
+                </div>
+            </div>
+        );
+    }
+}

+ 14 - 0
nodeEditor/src/components/diagram/generic/genericNodeModel.tsx

@@ -65,6 +65,20 @@ export class GenericNodeModel extends DefaultNodeModel {
                     }} isSelected={() => (this.block as TransformBlock).complementW === 0} />
                 </LineContainerComponent>
             }
+            {
+                this.block!.getClassName() === "TransformBlock" &&
+                <LineContainerComponent title="PROPERTIES">
+                    <CheckBoxLineComponent label="Transform as direction" onSelect={value => {
+                        let transformBlock = this.block as TransformBlock;
+                        if (value) {
+                            transformBlock.complementW = 0;
+                        } else {
+                            transformBlock.complementW = 1;
+                        }
+                        globalState.onRebuildRequiredObservable.notifyObservers();
+                    }} isSelected={() => (this.block as TransformBlock).complementW === 0} />
+                </LineContainerComponent>
+            }            
             </div>
         );
     }

+ 4 - 2
nodeEditor/src/components/diagram/trigonometry/trigonometryNodePropertyComponent.tsx

@@ -36,11 +36,13 @@ export class TrigonometryPropertyTabComponentProps extends React.Component<ITrig
         return (
             <div>
                 <LineContainerComponent title="GENERAL">
-                    <TextInputLineComponent globalState={this.props.globalState} label="Name" propertyName="name" target={trigonometryBlock} onChange={() => this.props.globalState.onUpdateRequiredObservable.notifyObservers()} />
+                    <TextInputLineComponent globalState={this.props.globalState} label="Name" propertyName="name" target={trigonometryBlock} onChange={() => {
+                        this.props.globalState.onUpdateRequiredObservable.notifyObservers();
+                    }} />
                     <TextLineComponent label="Type" value={trigonometryBlock.getClassName()} />
                 </LineContainerComponent>
                 <LineContainerComponent title="PROPERTIES">  
-                    <OptionsLineComponent label="Operation" valuesAreStrings={true} options={operationOptions} target={trigonometryBlock} propertyName="operation" onSelect={(value: any) => {
+                    <OptionsLineComponent label="Operation" options={operationOptions} target={trigonometryBlock} propertyName="operation" onSelect={(value: any) => {
                         this.forceUpdate();
                         this.props.globalState.onRebuildRequiredObservable.notifyObservers();
                     }} />                  

+ 1 - 1
nodeEditor/src/components/log/logComponent.tsx

@@ -23,7 +23,7 @@ export class LogComponent extends React.Component<ILogComponentProps, { logs: Lo
         this.state = { logs: [] };
     }
 
-    componentWillMount() {
+    componentDidMount() {
         this.props.globalState.onLogRequiredObservable.add(log => {
             let currentLogs = this.state.logs;
             currentLogs.push(log);

+ 111 - 106
nodeEditor/src/components/nodeList/nodeList.scss

@@ -9,37 +9,11 @@
 
     .panes {
         overflow: hidden;
-
-        .filter {
-            display: flex;
-            align-items: stretch;
-    
-            input {
-                width: 100%;
-                margin: 10px 10px 5px 10px;
-                display: block;
-                border: none;
-                padding: 0;
-                border-bottom: solid 1px rgb(51, 122, 183);
-                background: linear-gradient(to bottom, rgba(255, 255, 255, 0) 96%, rgb(51, 122, 183) 4%);
-                background-position: -1000px 0;
-                background-size: 1000px 100%;
-                background-repeat: no-repeat;  
-                color:white;    
-            }
-    
-            input:focus  {
-                box-shadow: none;
-                outline: none;
-                background-position: 0 0;
-            }
-        }
         
         .pane {
             color: white;
 
-            overflow-x: hidden;
-            overflow-y: auto;
+            overflow: hidden;
             height: 100%;
 
             -webkit-user-select: none; 
@@ -47,99 +21,130 @@
             -ms-user-select: none;    
             user-select: none;     
 
-            .underline {
-                border-bottom: 0.5px solid rgba(255, 255, 255, 0.5);
+            .filter {
+                display: flex;
+                align-items: stretch;
+        
+                input {
+                    width: 100%;
+                    margin: 10px 10px 5px 10px;
+                    display: block;
+                    border: none;
+                    padding: 0;
+                    border-bottom: solid 1px rgb(51, 122, 183);
+                    background: linear-gradient(to bottom, rgba(255, 255, 255, 0) 96%, rgb(51, 122, 183) 4%);
+                    background-position: -1000px 0;
+                    background-size: 1000px 100%;
+                    background-repeat: no-repeat;  
+                    color:white;    
+                }
+        
+                input:focus  {
+                    box-shadow: none;
+                    outline: none;
+                    background-position: 0 0;
+                }
             }
 
-            .draggableLine {
-                height: 30px;
-                display: grid;
-                align-items: center;
-                justify-items: stretch;
-                background: #222222;
-                cursor: grab;
-                text-align: center;
-                margin: 0;
-                box-sizing: border-box;
-
-                &:hover {
-                    background: rgb(51, 122, 183);
-                    color: white;
+            .list-container {
+                overflow-x: hidden;
+                overflow-y: auto;
+                height: 100%;
+
+                .underline {
+                    border-bottom: 0.5px solid rgba(255, 255, 255, 0.5);
                 }
-            }
-        
-            .buttonLine {
-                height: 30px;
-                display: grid;
-                align-items: center;
-                justify-items: stretch;
 
-                button {
+                .draggableLine {
+                    height: 30px;
+                    display: grid;
+                    align-items: center;
+                    justify-items: stretch;
                     background: #222222;
-                    margin: 5px 10px 5px 10px;
-                    color:white;
-                    padding: 4px 5px;
-                    opacity: 0.9;
+                    cursor: grab;
+                    text-align: center;
+                    margin: 0;
+                    box-sizing: border-box;
+
+                    &:hover {
+                        background: rgb(51, 122, 183);
+                        color: white;
+                    }
                 }
+            
+                .buttonLine {
+                    height: 30px;
+                    display: grid;
+                    align-items: center;
+                    justify-items: stretch;
+
+                    button {
+                        background: #222222;
+                        margin: 5px 10px 5px 10px;
+                        color:white;
+                        padding: 4px 5px;
+                        opacity: 0.9;
+                    }
+
+                    button:hover {
+                        opacity: 1.0;
+                    }
 
-                button:hover {
-                    opacity: 1.0;
+                    button:active {
+                        background: #282828;
+                    }   
+                    
+                    button:focus {
+                        outline: 0px;
+                    }  
                 }
 
-                button:active {
-                    background: #282828;
-                }   
-                
-                button:focus {
-                    outline: 0px;
-                }  
-            }
+                .paneContainer {
+                    margin-top: 3px;
+                    display:grid;
+                    grid-template-rows: 100%;
+                    grid-template-columns: 100%;
+
+                    .paneContainer-content {
+                        grid-row: 1;
+                        grid-column: 1;
+
+                        .header {
+                            display: grid;
+                            grid-template-columns: 1fr auto;
+                            background: #555555;    
+                            height: 30px;   
+                            padding-right: 5px;                        
+                            cursor: pointer;
+                            
+                            .title {                                
+                                border-left: 3px solid transparent;
+                                padding-left: 5px;
+                                grid-column: 1;
+                                display: flex;
+                                align-items: center;
+                            }
 
-            .paneContainer {
-                margin-top: 3px;
-                display:grid;
-                grid-template-rows: 100%;
-                grid-template-columns: 100%;
-
-                .paneContainer-content {
-                    grid-row: 1;
-                    grid-column: 1;
-
-                    .header {
-                        display: grid;
-                        grid-template-columns: 1fr auto;
-                        background: #555555;    
-                        height: 30px;   
-                        padding-right: 5px;                        
-                        cursor: pointer;
-                        
-                        .title {                                
-                            border-left: 3px solid transparent;
-                            padding-left: 5px;
-                            grid-column: 1;
-                            display: flex;
-                            align-items: center;
+                            .collapse {
+                                grid-column: 2;
+                                display: flex;
+                                align-items: center;  
+                                justify-items: center;
+                                transform-origin: center;
+
+                                &.closed {
+                                    transform: rotate(180deg);
+                                }
+                            }                        
                         }
 
-                        .collapse {
-                            grid-column: 2;
-                            display: flex;
-                            align-items: center;  
-                            justify-items: center;
-                            transform-origin: center;
-
-                            &.closed {
-                                transform: rotate(180deg);
-                            }
-                        }                        
-                    }
-
-                    .paneList > div:not(:last-child) {
-                        border-bottom: 1px solid rgba(255, 255, 255, 0.3);
+                        .paneList > div:not(:last-child) {
+                            border-bottom: 1px solid rgba(255, 255, 255, 0.3);
+                        }
                     }
                 }
-            }
-        }    
+            }    
+        }
     }
 }
 

+ 11 - 9
nodeEditor/src/components/nodeList/nodeListComponent.tsx

@@ -26,18 +26,18 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
         // Block types used to create the menu from
         const allBlocks = {
             Animation: ["BonesBlock", "MorphTargetsBlock"],
-            Output_Blocks: ["VertexOutputBlock", "FragmentOutputBlock", "AlphaTestBlock"],
+            Basic_Math: ["AddBlock",  "DivideBlock", "MultiplyBlock", "ScaleBlock", "SubtractBlock", "OppositeBlock"],
+            Conversion_Blocks: ["ColorMergerBlock", "ColorSplitterBlock", "VectorMergerBlock", "VectorSplitterBlock"],
+            Inputs: ["Float", "Vector2", "Vector3", "Vector4", "Color3", "Color4", "TextureBlock", "TimeBlock"],
             Interpolation: ["LerpBlock"],
+            Matrices: ["Matrix", "WorldMatrixBlock", "WorldViewMatrixBlock", "WorldViewProjectionMatrixBlock", "ViewMatrixBlock", "ViewProjectionMatrixBlock", "ProjectionMatrixBlock"],
+            Mesh_Attributes: ["InstancesBlock", "PositionBlock", "UVBlock", "ColorBlock", "NormalBlock", "TangentBlock", "MatrixIndicesBlock", "MatrixWeightsBlock"],
+            Output_Blocks: ["VertexOutputBlock", "FragmentOutputBlock", "AlphaTestBlock"],
             Range: ["ClampBlock", "RemapBlock", "NormalizeBlock"],
             Round: ["StepBlock", "RoundBlock", "CeilingBlock", "FloorBlock"],
-            Vector_Math: ["CrossBlock", "DotBlock", "TransformBlock", "FresnelBlock"],
-            Basic_Math: ["AddBlock",  "DivideBlock", "MultiplyBlock", "ScaleBlock", "SubtractBlock"],
+            Scene_Attributes: ["FogBlock", "CameraPositionBlock", "FogColorBlock", "ImageProcessingBlock", "LightBlock", "ReflectionTextureBlock", "ViewDirectionBlock"],
             Trigonometry: ["CosBlock", "SinBlock", "AbsBlock", "ExpBlock", "Exp2Block"],
-            Conversion_Blocks: ["ColorMergerBlock", "ColorSplitterBlock", "VectorMergerBlock", "VectorSplitterBlock"],
-            Mesh_Attributes: ["InstancesBlock"],
-            Matrices: ["Matrix"],
-            Scene_Attributes: ["FogBlock","ImageProcessingBlock", "LightBlock", "ReflectionTextureBlock"],
-            Inputs: ["Float", "Vector2", "Vector3", "Vector4", "Color3", "Color4", "TextureBlock"],
+            Vector_Math: ["CrossBlock", "DotBlock", "TransformBlock", "FresnelBlock"],
         }
 
         // Create node menu
@@ -65,7 +65,9 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
                         <div className="filter">
                             <input type="text" placeholder="Filter" onChange={(evt) => this.filterContent(evt.target.value)} />
                         </div>
-                        {blockMenu}
+                        <div className="list-container">
+                            {blockMenu}
+                        </div>
                     </div>
                 </div>
             </div>

+ 4 - 4
nodeEditor/src/components/preview/previewManager.ts

@@ -70,16 +70,16 @@ export class PreviewManager {
         
         switch (this._globalState.previewMeshType) {
             case PreviewMeshType.Box:
-                this._dummy = Mesh.CreateBox("dummy", 2, this._scene);
+                this._dummy = Mesh.CreateBox("dummy-box", 2, this._scene);
                 break;
             case PreviewMeshType.Sphere:
-                this._dummy = Mesh.CreateSphere("dummy", 32, 2, this._scene);
+                this._dummy = Mesh.CreateSphere("dummy-sphere", 32, 2, this._scene);
                 break;
             case PreviewMeshType.Torus:
-                this._dummy = Mesh.CreateTorus("dummy", 2, 0.5, 32, this._scene);
+                this._dummy = Mesh.CreateTorus("dummy-torus", 2, 0.5, 32, this._scene);
                 break;
                 case PreviewMeshType.Cylinder:
-                this._dummy = Mesh.CreateCylinder("dummy", 2, 1, 1.2, 32, 1, this._scene);
+                this._dummy = Mesh.CreateCylinder("dummy-cylinder", 2, 1, 1.2, 32, 1, this._scene);
                 break;                
         }
         this._dummy.material = this._material;

+ 1 - 1
nodeEditor/src/components/propertyTab/propertyTab.scss

@@ -11,7 +11,7 @@
         grid-row: 1;
         text-align: center;
         display: grid;
-        grid-template-columns: 30px 1fr 20px;        
+        grid-template-columns: 30px 1fr;        
         -webkit-user-select: none; 
         -moz-user-select: none;   
         -ms-user-select: none;    

+ 4 - 4
nodeEditor/src/components/propertyTab/propertyTabComponent.tsx

@@ -23,7 +23,7 @@ export class PropertyTabComponent extends React.Component<IPropertyTabComponentP
         this.state = { currentNode: null };
     }
 
-    componentWillMount() {
+    componentDidMount() {
         this.props.globalState.onSelectionChangedObservable.add(block => {
             this.setState({ currentNode: block });
         });
@@ -71,7 +71,7 @@ export class PropertyTabComponent extends React.Component<IPropertyTabComponentP
 
         // Output
         let json = JSON.stringify(serializationObject, undefined, 2);
-        StringTools.DownloadAsFile(json, "nodeMaterial.json");
+        StringTools.DownloadAsFile(this.props.globalState.hostDocument, json, "nodeMaterial.json");
     }
 
     render() {
@@ -118,10 +118,10 @@ export class PropertyTabComponent extends React.Component<IPropertyTabComponentP
                             this.save();
                         }} />
                         <ButtonLineComponent label="Generate code" onClick={() => {
-                            StringTools.DownloadAsFile(this.props.globalState.nodeMaterial!.generateCode(), "code.txt");
+                            StringTools.DownloadAsFile(this.props.globalState.hostDocument, this.props.globalState.nodeMaterial!.generateCode(), "code.txt");
                         }} />
                         <ButtonLineComponent label="Export shaders" onClick={() => {
-                            StringTools.DownloadAsFile(this.props.globalState.nodeMaterial!.compiledShaders, "shaders.txt");
+                            StringTools.DownloadAsFile(this.props.globalState.hostDocument, this.props.globalState.nodeMaterial!.compiledShaders, "shaders.txt");
                         }} />
                     </LineContainerComponent>
                 </div>

+ 12 - 0
nodeEditor/src/graphEditor.tsx

@@ -44,6 +44,9 @@ import { TrigonometryNodeFactory } from './components/diagram/trigonometry/trigo
 import { TrigonometryBlock } from 'babylonjs/Materials/Node/Blocks/trigonometryBlock';
 import { TrigonometryNodeModel } from './components/diagram/trigonometry/trigonometryNodeModel';
 import { AdvancedLinkModel } from './components/diagram/link/advancedLinkModel';
+import { ClampNodeFactory } from './components/diagram/clamp/clampNodeFactory';
+import { ClampNodeModel } from './components/diagram/clamp/clampNodeModel';
+import { ClampBlock } from 'babylonjs/Materials/Node/Blocks/clampBlock';
 
 require("storm-react-diagrams/dist/style.min.css");
 require("./main.scss");
@@ -110,6 +113,8 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
             newNode = new TrigonometryNodeModel();                    
         } else if (options.nodeMaterialBlock instanceof RemapBlock) {
             newNode = new RemapNodeModel();
+        } else if (options.nodeMaterialBlock instanceof ClampBlock) {
+            newNode = new ClampNodeModel();
         } else {
             newNode = new GenericNodeModel();
         }
@@ -178,6 +183,7 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
         this._engine.registerNodeFactory(new InputNodeFactory(this.props.globalState));
         this._engine.registerNodeFactory(new RemapNodeFactory(this.props.globalState));
         this._engine.registerNodeFactory(new TrigonometryNodeFactory(this.props.globalState));
+        this._engine.registerNodeFactory(new ClampNodeFactory(this.props.globalState));
         this._engine.registerLinkFactory(new AdvancedLinkFactory());
 
         this.props.globalState.onRebuildRequiredObservable.add(() => {
@@ -379,6 +385,11 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
                         if (!e.link.targetPort && e.link.sourcePort && (e.link.sourcePort as DefaultPortModel).position === "input") {
                             // Drag from input port, we are going to build an input for it                            
                             let input = e.link.sourcePort as DefaultPortModel;
+
+                            if (input.connection!.type == NodeMaterialBlockConnectionPointTypes.AutoDetect) {
+                                return;
+                            }
+
                             let nodeModel = this.addValueNode(BlockTools.GetStringFromConnectionNodeType(input.connection!.type));
                             let link = nodeModel.ports.output.link(input);
 
@@ -594,6 +605,7 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
             setTimeout(() => {
                 this._model.addAll(...this._toAdd!);            
                 this._toAdd = null;  
+                this._model.clearSelection();
                 nodeModel!.setSelected(true);
 
                 this._engine.repaintCanvas();  

+ 2 - 0
nodeEditor/src/main.scss

@@ -43,6 +43,8 @@
     display: grid;
     grid-template-rows: 1fr 30px auto;
     grid-template-columns: 100%;
+    height: 100%;
+    overflow-y: auto;
 
     #propertyTab {
         grid-row: 1;

+ 11 - 0
nodeEditor/src/nodeEditor.ts

@@ -15,11 +15,20 @@ export interface INodeEditorOptions {
  * Class used to create a node editor
  */
 export class NodeEditor {
+    private static _CurrentState: GlobalState;
+
     /**
      * Show the node editor
      * @param options defines the options to use to configure the node editor
      */
     public static Show(options: INodeEditorOptions) {
+        if (this._CurrentState) {
+            var popupWindow = (Popup as any)["node-editor"];
+            if (popupWindow) {
+                popupWindow.close();
+            }
+        }
+
         let hostElement = Popup.CreatePopup("BABYLON.JS NODE EDITOR", "node-editor", 1000, 800)!;
         let globalState = new GlobalState();
         globalState.nodeMaterial = options.nodeMaterial
@@ -32,6 +41,8 @@ export class NodeEditor {
 
         ReactDOM.render(graphEditor, hostElement);
 
+        this._CurrentState = globalState;
+
         // Close the popup window when the page is refreshed or scene is disposed
         var popupWindow = (Popup as any)["node-editor"];
         if (globalState.nodeMaterial && popupWindow) {

+ 1 - 1
nodeEditor/src/stringTools.ts

@@ -13,7 +13,7 @@ export class StringTools {
      * Download a string into a file that will be saved locally by the browser
      * @param content defines the string to download locally as a file
      */
-    public static DownloadAsFile(content: string, filename: string) {
+    public static DownloadAsFile(document: HTMLDocument, content: string, filename: string) {
         let blob = new Blob([content],
             {
                 type: "application/octet-stream"

+ 2 - 2
package.json

@@ -84,9 +84,9 @@
         "plugin-error": "^1.0.1",
         "prompt": "^1.0.0",
         "re-resizable": "~4.9.1",
-        "react": "~16.6.3",
+        "react": "~16.9.0",
         "react-contextmenu": "~2.10.0",
-        "react-dom": "~16.6.3",
+        "react-dom": "~16.9.0",
         "sass-loader": "^7.1.0",
         "shelljs": "^0.8.3",
         "sinon": "^6.1.4",

+ 1 - 1
src/Lights/light.ts

@@ -483,7 +483,7 @@ export abstract class Light extends Node {
 
         // Remove from meshes
         for (var mesh of this.getScene().meshes) {
-            mesh._removeLightSource(this);
+            mesh._removeLightSource(this, true);
         }
 
         this._uniformBuffer.dispose();

+ 13 - 5
src/Materials/Node/Blocks/Dual/fogBlock.ts

@@ -83,15 +83,23 @@ export class FogBlock extends NodeMaterialBlock {
         return this._outputs[0];
     }
 
-    public autoConfigure() {
+    public autoConfigure(material: NodeMaterial) {
         if (!this.view.isConnected) {
-            let viewInput = new InputBlock("view");
-            viewInput.setAsWellKnownValue(NodeMaterialWellKnownValues.View);
+            let viewInput = material.getInputBlockByPredicate((b) => b.wellKnownValue === NodeMaterialWellKnownValues.View);
+
+            if (!viewInput) {
+                viewInput = new InputBlock("view");
+                viewInput.setAsWellKnownValue(NodeMaterialWellKnownValues.View);
+            }
             viewInput.output.connectTo(this.view);
         }
         if (!this.fogColor.isConnected) {
-            let fogColorInput = new InputBlock("fogColor", undefined, NodeMaterialBlockConnectionPointTypes.Color3);
-            fogColorInput.setAsWellKnownValue(NodeMaterialWellKnownValues.FogColor);
+            let fogColorInput = material.getInputBlockByPredicate((b) => b.wellKnownValue === NodeMaterialWellKnownValues.FogColor);
+
+            if (!fogColorInput) {
+                fogColorInput = new InputBlock("fogColor", undefined, NodeMaterialBlockConnectionPointTypes.Color3);
+                fogColorInput.setAsWellKnownValue(NodeMaterialWellKnownValues.FogColor);
+            }
             fogColorInput.output.connectTo(this.fogColor);
         }
     }

+ 15 - 11
src/Materials/Node/Blocks/Dual/lightBlock.ts

@@ -84,10 +84,14 @@ export class LightBlock extends NodeMaterialBlock {
         return this._outputs[1];
     }
 
-    public autoConfigure() {
+    public autoConfigure(material: NodeMaterial) {
         if (!this.cameraPosition.isConnected) {
-            let cameraPositionInput = new InputBlock("cameraPosition");
-            cameraPositionInput.setAsWellKnownValue(NodeMaterialWellKnownValues.CameraPosition);
+            let cameraPositionInput = material.getInputBlockByPredicate((b) => b.wellKnownValue === NodeMaterialWellKnownValues.CameraPosition);
+
+            if (!cameraPositionInput) {
+                cameraPositionInput = new InputBlock("cameraPosition");
+                cameraPositionInput.setAsWellKnownValue(NodeMaterialWellKnownValues.CameraPosition);
+            }
             cameraPositionInput.output.connectTo(this.cameraPosition);
         }
     }
@@ -167,13 +171,13 @@ export class LightBlock extends NodeMaterialBlock {
 
         // Inject code in vertex
         let worldPosVaryingName = "v_" + worldPos.associatedVariableName;
-        if (state._emitVaryingFromString(worldPosVaryingName, "vec3")) {
-            state.compilationString += `${worldPosVaryingName} = ${worldPos.associatedVariableName}.xyz;\r\n`;
+        if (state._emitVaryingFromString(worldPosVaryingName, "vec4")) {
+            state.compilationString += `${worldPosVaryingName} = ${worldPos.associatedVariableName};\r\n`;
         }
 
         let worldNormalVaryingName = "v_" + worldNormal.associatedVariableName;
-        if (state._emitVaryingFromString(worldNormalVaryingName, "vec3")) {
-            state.compilationString += `${worldNormalVaryingName} = ${worldNormal.associatedVariableName}.xyz;\r\n`;
+        if (state._emitVaryingFromString(worldNormalVaryingName, "vec4")) {
+            state.compilationString += `${worldNormalVaryingName} = ${worldNormal.associatedVariableName};\r\n`;
         }
 
         if (this.light) {
@@ -212,13 +216,13 @@ export class LightBlock extends NodeMaterialBlock {
 
         state._emitFunctionFromInclude("lightsFragmentFunctions", comments, {
             replaceStrings: [
-                { search: /vPositionW/g, replace: "v_" + worldPos.associatedVariableName }
+                { search: /vPositionW/g, replace: "v_" + worldPos.associatedVariableName + ".xyz" }
             ]
         });
 
         state._emitFunctionFromInclude("shadowsFragmentFunctions", comments, {
             replaceStrings: [
-                { search: /vPositionW/g, replace: "v_" + worldPos.associatedVariableName }
+                { search: /vPositionW/g, replace: "v_" + worldPos.associatedVariableName + ".xyz" }
             ]
         });
 
@@ -238,14 +242,14 @@ export class LightBlock extends NodeMaterialBlock {
         // Code
         if (this._lightId === 0) {
             if (state._registerTempVariable("viewDirectionW")) {
-                state.compilationString += `vec3 viewDirectionW = normalize(${this.cameraPosition.associatedVariableName} - ${"v_" + worldPos.associatedVariableName});\r\n`;
+                state.compilationString += `vec3 viewDirectionW = normalize(${this.cameraPosition.associatedVariableName} - ${"v_" + worldPos.associatedVariableName}.xyz);\r\n`;
             }
             state.compilationString += `lightingInfo info;\r\n`;
             state.compilationString += `float shadow = 1.;\r\n`;
             state.compilationString += `float glossiness = 0.;\r\n`;
             state.compilationString += `vec3 diffuseBase = vec3(0., 0., 0.);\r\n`;
             state.compilationString += `vec3 specularBase = vec3(0., 0., 0.);\r\n`;
-            state.compilationString += `vec3 normalW = v_${this.worldNormal.associatedVariableName};\r\n`;
+            state.compilationString += `vec3 normalW = v_${this.worldNormal.associatedVariableName}.xyz;\r\n`;
         }
 
         if (this.light) {

+ 30 - 14
src/Materials/Node/Blocks/Dual/reflectionTextureBlock.ts

@@ -144,28 +144,44 @@ export class ReflectionTextureBlock extends NodeMaterialBlock {
         return this._outputs[3];
     }
 
-    public autoConfigure() {
+    public autoConfigure(material: NodeMaterial) {
         if (!this.position.isConnected) {
-            let positionInput = new InputBlock("position");
-            positionInput.setAsAttribute();
+            let positionInput = material.getInputBlockByPredicate((b) => b.isAttribute && b.name === "position");
+
+            if (!positionInput) {
+                positionInput = new InputBlock("position");
+                positionInput.setAsAttribute();
+            }
             positionInput.output.connectTo(this.position);
         }
 
         if (!this.world.isConnected) {
-            let worldInput = new InputBlock("world");
-            worldInput.setAsWellKnownValue(NodeMaterialWellKnownValues.World);
+            let worldInput = material.getInputBlockByPredicate((b) => b.wellKnownValue === NodeMaterialWellKnownValues.World);
+
+            if (!worldInput) {
+                worldInput = new InputBlock("world");
+                worldInput.setAsWellKnownValue(NodeMaterialWellKnownValues.World);
+            }
             worldInput.output.connectTo(this.world);
         }
 
         if (!this.cameraPosition.isConnected) {
-            let cameraPositionInput = new InputBlock("cameraPosition");
-            cameraPositionInput.setAsWellKnownValue(NodeMaterialWellKnownValues.CameraPosition);
+            let cameraPositionInput = material.getInputBlockByPredicate((b) => b.wellKnownValue === NodeMaterialWellKnownValues.CameraPosition);
+
+            if (!cameraPositionInput) {
+                cameraPositionInput = new InputBlock("cameraPosition");
+                cameraPositionInput.setAsWellKnownValue(NodeMaterialWellKnownValues.CameraPosition);
+            }
             cameraPositionInput.output.connectTo(this.cameraPosition);
         }
 
         if (!this.view.isConnected) {
-            let viewInput = new InputBlock("view");
-            viewInput.setAsWellKnownValue(NodeMaterialWellKnownValues.View);
+            let viewInput = material.getInputBlockByPredicate((b) => b.wellKnownValue === NodeMaterialWellKnownValues.View);
+
+            if (!viewInput) {
+                viewInput = new InputBlock("view");
+                viewInput.setAsWellKnownValue(NodeMaterialWellKnownValues.View);
+            }
             viewInput.output.connectTo(this.view);
         }
     }
@@ -216,13 +232,13 @@ export class ReflectionTextureBlock extends NodeMaterialBlock {
 
     private _injectVertexCode(state: NodeMaterialBuildState) {
         let worldPosVaryingName = "v_" + this.worldPosition.associatedVariableName;
-        if (state._emitVaryingFromString(worldPosVaryingName, "vec3")) {
-            state.compilationString += `${worldPosVaryingName} = ${this.worldPosition.associatedVariableName}.xyz;\r\n`;
+        if (state._emitVaryingFromString(worldPosVaryingName, "vec4")) {
+            state.compilationString += `${worldPosVaryingName} = ${this.worldPosition.associatedVariableName};\r\n`;
         }
 
         let worldNormalVaryingName = "v_" + this.worldNormal.associatedVariableName;
-        if (state._emitVaryingFromString(worldNormalVaryingName, "vec3")) {
-            state.compilationString += `${worldNormalVaryingName} = ${this.worldNormal.associatedVariableName}.xyz;\r\n`;
+        if (state._emitVaryingFromString(worldNormalVaryingName, "vec4")) {
+            state.compilationString += `${worldNormalVaryingName} = ${this.worldNormal.associatedVariableName};\r\n`;
         }
 
         this._positionUVWName = state._getFreeVariableName("positionUVW");
@@ -298,7 +314,7 @@ export class ReflectionTextureBlock extends NodeMaterialBlock {
         state._emitUniformFromString(this._reflectionMatrixName, "mat4");
 
         // Code
-        let worldPos = `vec4(v_${this.worldPosition.associatedVariableName}, 1.0)`;
+        let worldPos = `v_${this.worldPosition.associatedVariableName}`;
         let worldNormal = "v_" + this.worldNormal.associatedVariableName + ".xyz";
         let reflectionMatrix = this._reflectionMatrixName;
         let direction = `normalize(${this._directionWName})`;

+ 7 - 3
src/Materials/Node/Blocks/Dual/textureBlock.ts

@@ -145,10 +145,14 @@ export class TextureBlock extends NodeMaterialBlock {
         return NodeMaterialBlockTargets.VertexAndFragment;
     }
 
-    public autoConfigure() {
+    public autoConfigure(material: NodeMaterial) {
         if (!this.uv.isConnected) {
-            let uvInput = new InputBlock("uv");
-            uvInput.setAsAttribute();
+            let uvInput = material.getInputBlockByPredicate((b) => b.isAttribute && b.name === "uv");
+
+            if (!uvInput) {
+                uvInput = new InputBlock("uv");
+                uvInput.setAsAttribute();
+            }
             uvInput.output.connectTo(this.uv);
         }
     }

+ 0 - 137
src/Materials/Node/Blocks/Fragment/fresnelBlock.ts

@@ -1,137 +0,0 @@
-import { NodeMaterialBlock } from '../../nodeMaterialBlock';
-import { NodeMaterialBlockTargets } from '../../nodeMaterialBlockTargets';
-import { NodeMaterialBlockConnectionPointTypes } from '../../nodeMaterialBlockConnectionPointTypes';
-import { NodeMaterialBuildState } from '../../nodeMaterialBuildState';
-import { NodeMaterialConnectionPoint } from '../../nodeMaterialBlockConnectionPoint';
-import { _TypeStore } from '../../../../Misc/typeStore';
-import { InputBlock } from '../Input/inputBlock';
-import { NodeMaterialWellKnownValues } from '../../nodeMaterialWellKnownValues';
-import { NodeMaterial } from '../../nodeMaterial';
-
-/**
- * Block used to compute fresnel value
- */
-export class FresnelBlock extends NodeMaterialBlock {
-
-    /**
-     * Create a new FresnelBlock
-     * @param name defines the block name
-     */
-    public constructor(name: string) {
-        super(name, NodeMaterialBlockTargets.VertexAndFragment);
-
-        this.registerInput("worldPosition", NodeMaterialBlockConnectionPointTypes.Vector4, false, NodeMaterialBlockTargets.Vertex);
-        this.registerInput("worldNormal", NodeMaterialBlockConnectionPointTypes.Vector4, false, NodeMaterialBlockTargets.Vertex);
-
-        this.registerInput("cameraPosition", NodeMaterialBlockConnectionPointTypes.Vector3, false, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("bias", NodeMaterialBlockConnectionPointTypes.Float, false, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("power", NodeMaterialBlockConnectionPointTypes.Float, false, NodeMaterialBlockTargets.Fragment);
-
-        this.registerOutput("fresnel", NodeMaterialBlockConnectionPointTypes.Float, NodeMaterialBlockTargets.Fragment);
-    }
-
-    /**
-     * Gets the current class name
-     * @returns the class name
-     */
-    public getClassName() {
-        return "FresnelBlock";
-    }
-
-    /**
-     * Gets the world position input component
-     */
-    public get worldPosition(): NodeMaterialConnectionPoint {
-        return this._inputs[0];
-    }
-
-    /**
-     * Gets the world normal input component
-     */
-    public get worldNormal(): NodeMaterialConnectionPoint {
-        return this._inputs[1];
-    }
-
-    /**
-    * Gets the camera (or eye) position component
-    */
-    public get cameraPosition(): NodeMaterialConnectionPoint {
-        return this._inputs[2];
-    }
-
-    /**
-    * Gets the bias input component
-    */
-    public get bias(): NodeMaterialConnectionPoint {
-        return this._inputs[3];
-    }
-
-    /**
-    * Gets the camera (or eye) position component
-    */
-    public get power(): NodeMaterialConnectionPoint {
-        return this._inputs[4];
-    }
-
-    /**
-     * Gets the fresnel output component
-     */
-    public get fresnel(): NodeMaterialConnectionPoint {
-        return this._outputs[0];
-    }
-
-    public autoConfigure(material: NodeMaterial) {
-        if (!this.cameraPosition.isConnected) {
-            let cameraPositionInput = new InputBlock("cameraPosition");
-            cameraPositionInput.setAsWellKnownValue(NodeMaterialWellKnownValues.CameraPosition);
-            cameraPositionInput.output.connectTo(this.cameraPosition);
-        }
-
-        if (!this.bias.isConnected) {
-            let biasInput = new InputBlock("bias");
-            biasInput.value = 0;
-            biasInput.output.connectTo(this.bias);
-        }
-
-        if (!this.power.isConnected) {
-            let powerInput = new InputBlock("power");
-            powerInput.value = 1;
-            powerInput.output.connectTo(this.power);
-        }
-    }
-
-    protected _buildBlock(state: NodeMaterialBuildState) {
-        super._buildBlock(state);
-
-        let comments = `//${this.name}`;
-
-        let worldPos = this.worldPosition;
-        let worldNormal = this.worldNormal;
-        let worldPosVaryingName = "v_" + worldPos.associatedVariableName;
-        let worldNormalVaryingName = "v_" + worldNormal.associatedVariableName;
-
-        if (state.target !== NodeMaterialBlockTargets.Fragment) {
-            // Inject code in vertex
-            if (state._emitVaryingFromString(worldPosVaryingName, "vec3")) {
-                state.compilationString += `${worldPosVaryingName} = ${worldPos.associatedVariableName}.xyz;\r\n`;
-            }
-
-            if (state._emitVaryingFromString(worldNormalVaryingName, "vec3")) {
-                state.compilationString += `${worldNormalVaryingName} = ${worldNormal.associatedVariableName}.xyz;\r\n`;
-            }
-
-            return;
-        }
-
-        state._emitFunctionFromInclude("fresnelFunction", comments, {removeIfDef: true});
-
-        if (state._registerTempVariable("viewDirectionW")) {
-            state.compilationString += `vec3 viewDirectionW = normalize(${this.cameraPosition.associatedVariableName} - ${worldPosVaryingName});\r\n`;
-        }
-        state.compilationString += this._declareOutput(this.fresnel, state) + ` = computeFresnelTerm(viewDirectionW, ${worldNormalVaryingName}, ${this.bias.associatedVariableName}, ${this.power.associatedVariableName});;\r\n`;
-
-        return this;
-    }
-}
-
-_TypeStore.RegisteredTypes["BABYLON.FresnelBlock"] = FresnelBlock;

+ 0 - 1
src/Materials/Node/Blocks/Fragment/index.ts

@@ -1,5 +1,4 @@
 
 export * from "./fragmentOutputBlock";
 export * from "./alphaTestBlock";
-export * from "./fresnelBlock";
 export * from "./imageProcessingBlock";

+ 19 - 7
src/Materials/Node/Blocks/Vertex/bonesBlock.ts

@@ -93,20 +93,32 @@ export class BonesBlock extends NodeMaterialBlock {
         return this._outputs[0];
     }
 
-    public autoConfigure() {
+    public autoConfigure(material: NodeMaterial) {
         if (!this.matricesIndices.isConnected) {
-            let matricesIndicesInput = new InputBlock("matricesIndices");
-            matricesIndicesInput.setAsAttribute("matricesIndices");
+            let matricesIndicesInput = material.getInputBlockByPredicate((b) => b.isAttribute && b.name === "matricesIndices");
+
+            if (!matricesIndicesInput) {
+                matricesIndicesInput = new InputBlock("matricesIndices");
+                matricesIndicesInput.setAsAttribute("matricesIndices");
+            }
             matricesIndicesInput.output.connectTo(this.matricesIndices);
         }
         if (!this.matricesWeights.isConnected) {
-            let matricesWeightsInput = new InputBlock("matricesWeights");
-            matricesWeightsInput.setAsAttribute("matricesWeights");
+            let matricesWeightsInput = material.getInputBlockByPredicate((b) => b.isAttribute && b.name === "matricesWeights");
+
+            if (!matricesWeightsInput) {
+                matricesWeightsInput = new InputBlock("matricesWeights");
+                matricesWeightsInput.setAsAttribute("matricesWeights");
+            }
             matricesWeightsInput.output.connectTo(this.matricesWeights);
         }
         if (!this.world.isConnected) {
-            let worldInput = new InputBlock("world", undefined, NodeMaterialBlockConnectionPointTypes.Matrix);
-            worldInput.setAsWellKnownValue(NodeMaterialWellKnownValues.World);
+            let worldInput = material.getInputBlockByPredicate((b) => b.wellKnownValue === NodeMaterialWellKnownValues.World);
+
+            if (!worldInput) {
+                worldInput = new InputBlock("world");
+                worldInput.setAsWellKnownValue(NodeMaterialWellKnownValues.World);
+            }
             worldInput.output.connectTo(this.world);
         }
     }

+ 31 - 11
src/Materials/Node/Blocks/Vertex/instancesBlock.ts

@@ -80,30 +80,50 @@ export class InstancesBlock extends NodeMaterialBlock {
         return this._outputs[0];
     }
 
-    public autoConfigure() {
+    public autoConfigure(material: NodeMaterial) {
         if (!this.world0.connectedPoint) {
-            let world0Input = new InputBlock("world0");
-            world0Input.setAsAttribute("world0");
+            let world0Input = material.getInputBlockByPredicate((b) => b.isAttribute && b.name === "world0");
+
+            if (!world0Input) {
+                world0Input = new InputBlock("world0");
+                world0Input.setAsAttribute("world0");
+            }
             world0Input.output.connectTo(this.world0);
         }
         if (!this.world1.connectedPoint) {
-            let world1Input = new InputBlock("world1");
-            world1Input.setAsAttribute("world1");
+            let world1Input = material.getInputBlockByPredicate((b) => b.isAttribute && b.name === "world1");
+
+            if (!world1Input) {
+                world1Input = new InputBlock("world1");
+                world1Input.setAsAttribute("world1");
+            }
             world1Input.output.connectTo(this.world1);
         }
         if (!this.world2.connectedPoint) {
-            let world2Input = new InputBlock("world2");
-            world2Input.setAsAttribute("world2");
+            let world2Input = material.getInputBlockByPredicate((b) => b.isAttribute && b.name === "world2");
+
+            if (!world2Input) {
+                world2Input = new InputBlock("world2");
+                world2Input.setAsAttribute("world2");
+            }
             world2Input.output.connectTo(this.world2);
         }
         if (!this.world3.connectedPoint) {
-            let world3Input = new InputBlock("world3");
-            world3Input.setAsAttribute("world3");
+            let world3Input = material.getInputBlockByPredicate((b) => b.isAttribute && b.name === "world3");
+
+            if (!world3Input) {
+                world3Input = new InputBlock("world3");
+                world3Input.setAsAttribute("world3");
+            }
             world3Input.output.connectTo(this.world3);
         }
         if (!this.world.connectedPoint) {
-            let worldInput = new InputBlock("world");
-            worldInput.setAsWellKnownValue(NodeMaterialWellKnownValues.World);
+            let worldInput = material.getInputBlockByPredicate((b) => b.isAttribute && b.name === "world");
+
+            if (!worldInput) {
+                worldInput = new InputBlock("world");
+                worldInput.setAsWellKnownValue(NodeMaterialWellKnownValues.World);
+            }
             worldInput.output.connectTo(this.world);
         }
 

+ 25 - 9
src/Materials/Node/Blocks/Vertex/morphTargetsBlock.ts

@@ -104,25 +104,41 @@ export class MorphTargetsBlock extends NodeMaterialBlock {
         state._excludeVariableName("morphTargetInfluences");
     }
 
-    public autoConfigure() {
+    public autoConfigure(material: NodeMaterial) {
         if (!this.position.isConnected) {
-            let positionInput = new InputBlock("position");
-            positionInput.setAsAttribute("position");
+            let positionInput = material.getInputBlockByPredicate((b) => b.isAttribute && b.name === "position");
+
+            if (!positionInput) {
+                positionInput = new InputBlock("position");
+                positionInput.setAsAttribute();
+            }
             positionInput.output.connectTo(this.position);
         }
         if (!this.normal.isConnected) {
-            let normalInput = new InputBlock("normal");
-            normalInput.setAsAttribute("normal");
+            let normalInput = material.getInputBlockByPredicate((b) => b.isAttribute && b.name === "normal");
+
+            if (!normalInput) {
+                normalInput = new InputBlock("normal");
+                normalInput.setAsAttribute("normal");
+            }
             normalInput.output.connectTo(this.normal);
         }
         if (!this.tangent.isConnected) {
-            let tangentInput = new InputBlock("tangent");
-            tangentInput.setAsAttribute("tangent");
+            let tangentInput = material.getInputBlockByPredicate((b) => b.isAttribute && b.name === "tangent");
+
+            if (!tangentInput) {
+                tangentInput = new InputBlock("tangent");
+                tangentInput.setAsAttribute("tangent");
+            }
             tangentInput.output.connectTo(this.tangent);
         }
         if (!this.uv.isConnected) {
-            let uvInput = new InputBlock("uv");
-            uvInput.setAsAttribute("uv");
+            let uvInput = material.getInputBlockByPredicate((b) => b.isAttribute && b.name === "uv");
+
+            if (!uvInput) {
+                uvInput = new InputBlock("uv");
+                uvInput.setAsAttribute("uv");
+            }
             uvInput.output.connectTo(this.uv);
         }
     }

+ 1 - 0
src/Materials/Node/Blocks/addBlock.ts

@@ -20,6 +20,7 @@ export class AddBlock extends NodeMaterialBlock {
         this.registerOutput("output", NodeMaterialBlockConnectionPointTypes.BasedOnInput);
 
         this._outputs[0]._typeConnectionSource = this._inputs[0];
+        this._linkConnectionTypes(0, 1);
     }
 
     /**

+ 1 - 0
src/Materials/Node/Blocks/crossBlock.ts

@@ -20,6 +20,7 @@ export class CrossBlock extends NodeMaterialBlock {
         this.registerOutput("output", NodeMaterialBlockConnectionPointTypes.BasedOnInput);
 
         this._outputs[0]._typeConnectionSource = this._inputs[0];
+        this._linkConnectionTypes(0, 1);
     }
 
     /**

+ 1 - 0
src/Materials/Node/Blocks/divideBlock.ts

@@ -20,6 +20,7 @@ export class DivideBlock extends NodeMaterialBlock {
         this.registerOutput("output", NodeMaterialBlockConnectionPointTypes.BasedOnInput);
 
         this._outputs[0]._typeConnectionSource = this._inputs[0];
+        this._linkConnectionTypes(0, 1);
     }
 
     /**

+ 2 - 0
src/Materials/Node/Blocks/dotBlock.ts

@@ -18,6 +18,8 @@ export class DotBlock extends NodeMaterialBlock {
         this.registerInput("left", NodeMaterialBlockConnectionPointTypes.AutoDetect);
         this.registerInput("right", NodeMaterialBlockConnectionPointTypes.AutoDetect);
         this.registerOutput("output", NodeMaterialBlockConnectionPointTypes.Float);
+
+        this._linkConnectionTypes(0, 1);
     }
 
     /**

+ 100 - 0
src/Materials/Node/Blocks/fresnelBlock.ts

@@ -0,0 +1,100 @@
+import { NodeMaterialBlock } from '../nodeMaterialBlock';
+import { NodeMaterialBlockTargets } from '../nodeMaterialBlockTargets';
+import { NodeMaterialBlockConnectionPointTypes } from '../nodeMaterialBlockConnectionPointTypes';
+import { NodeMaterialBuildState } from '../nodeMaterialBuildState';
+import { NodeMaterialConnectionPoint } from '../nodeMaterialBlockConnectionPoint';
+import { _TypeStore } from '../../../Misc/typeStore';
+import { InputBlock } from './Input/inputBlock';
+import { NodeMaterial } from '../nodeMaterial';
+
+/**
+ * Block used to compute fresnel value
+ */
+export class FresnelBlock extends NodeMaterialBlock {
+
+    /**
+     * Create a new FresnelBlock
+     * @param name defines the block name
+     */
+    public constructor(name: string) {
+        super(name, NodeMaterialBlockTargets.Neutral);
+
+        this.registerInput("worldNormal", NodeMaterialBlockConnectionPointTypes.Vector4);
+        this.registerInput("viewDirection", NodeMaterialBlockConnectionPointTypes.Vector3);
+        this.registerInput("bias", NodeMaterialBlockConnectionPointTypes.Float);
+        this.registerInput("power", NodeMaterialBlockConnectionPointTypes.Float);
+
+        this.registerOutput("fresnel", NodeMaterialBlockConnectionPointTypes.Float);
+    }
+
+    /**
+     * Gets the current class name
+     * @returns the class name
+     */
+    public getClassName() {
+        return "FresnelBlock";
+    }
+
+    /**
+     * Gets the world normal input component
+     */
+    public get worldNormal(): NodeMaterialConnectionPoint {
+        return this._inputs[0];
+    }
+
+    /**
+    * Gets the view direction input component
+    */
+    public get viewDirection(): NodeMaterialConnectionPoint {
+        return this._inputs[1];
+    }
+
+    /**
+    * Gets the bias input component
+    */
+    public get bias(): NodeMaterialConnectionPoint {
+        return this._inputs[2];
+    }
+
+    /**
+    * Gets the camera (or eye) position component
+    */
+    public get power(): NodeMaterialConnectionPoint {
+        return this._inputs[3];
+    }
+
+    /**
+     * Gets the fresnel output component
+     */
+    public get fresnel(): NodeMaterialConnectionPoint {
+        return this._outputs[0];
+    }
+
+    public autoConfigure(material: NodeMaterial) {
+        if (!this.bias.isConnected) {
+            let biasInput = new InputBlock("bias");
+            biasInput.value = 0;
+            biasInput.output.connectTo(this.bias);
+        }
+
+        if (!this.power.isConnected) {
+            let powerInput = new InputBlock("power");
+            powerInput.value = 1;
+            powerInput.output.connectTo(this.power);
+        }
+    }
+
+    protected _buildBlock(state: NodeMaterialBuildState) {
+        super._buildBlock(state);
+
+        let comments = `//${this.name}`;
+
+        state._emitFunctionFromInclude("fresnelFunction", comments, {removeIfDef: true});
+
+        state.compilationString += this._declareOutput(this.fresnel, state) + ` = computeFresnelTerm(${this.viewDirection.associatedVariableName}, ${this.worldNormal.associatedVariableName}, ${this.bias.associatedVariableName}, ${this.power.associatedVariableName});\r\n`;
+
+        return this;
+    }
+}
+
+_TypeStore.RegisteredTypes["BABYLON.FresnelBlock"] = FresnelBlock;

+ 4 - 1
src/Materials/Node/Blocks/index.ts

@@ -19,4 +19,7 @@ export * from "./vectorSplitterBlock";
 export * from "./lerpBlock";
 export * from "./divideBlock";
 export * from "./subtractBlock";
-export * from "./stepBlock";
+export * from "./stepBlock";
+export * from "./oppositeBlock";
+export * from "./viewDirectionBlock";
+export * from "./fresnelBlock";

+ 1 - 0
src/Materials/Node/Blocks/lerpBlock.ts

@@ -21,6 +21,7 @@ export class LerpBlock extends NodeMaterialBlock {
         this.registerOutput("output", NodeMaterialBlockConnectionPointTypes.BasedOnInput);
 
         this._outputs[0]._typeConnectionSource = this._inputs[0];
+        this._linkConnectionTypes(0, 1);
     }
 
     /**

+ 2 - 2
src/Materials/Node/Blocks/multiplyBlock.ts

@@ -16,11 +16,11 @@ export class MultiplyBlock extends NodeMaterialBlock {
         super(name, NodeMaterialBlockTargets.Neutral);
 
         this.registerInput("left", NodeMaterialBlockConnectionPointTypes.AutoDetect);
-        this.registerInput("right", NodeMaterialBlockConnectionPointTypes.BasedOnInput);
+        this.registerInput("right", NodeMaterialBlockConnectionPointTypes.AutoDetect);
         this.registerOutput("output", NodeMaterialBlockConnectionPointTypes.BasedOnInput);
 
         this._outputs[0]._typeConnectionSource = this._inputs[0];
-        this._inputs[1]._typeConnectionSource = this._inputs[0];
+        this._linkConnectionTypes(0, 1);
     }
 
     /**

+ 57 - 0
src/Materials/Node/Blocks/oppositeBlock.ts

@@ -0,0 +1,57 @@
+import { NodeMaterialBlock } from '../nodeMaterialBlock';
+import { NodeMaterialBlockConnectionPointTypes } from '../nodeMaterialBlockConnectionPointTypes';
+import { NodeMaterialBuildState } from '../nodeMaterialBuildState';
+import { NodeMaterialConnectionPoint } from '../nodeMaterialBlockConnectionPoint';
+import { NodeMaterialBlockTargets } from '../nodeMaterialBlockTargets';
+import { _TypeStore } from '../../../Misc/typeStore';
+/**
+ * Block used to get the opposite of a value
+ */
+export class OppositeBlock extends NodeMaterialBlock {
+    /**
+     * Creates a new OppositeBlock
+     * @param name defines the block name
+     */
+    public constructor(name: string) {
+        super(name, NodeMaterialBlockTargets.Neutral);
+
+        this.registerInput("input", NodeMaterialBlockConnectionPointTypes.AutoDetect);
+        this.registerOutput("output", NodeMaterialBlockConnectionPointTypes.BasedOnInput);
+
+        this._outputs[0]._typeConnectionSource = this._inputs[0];
+    }
+
+    /**
+     * Gets the current class name
+     * @returns the class name
+     */
+    public getClassName() {
+        return "OppositeBlock";
+    }
+
+    /**
+     * Gets the input component
+     */
+    public get input(): NodeMaterialConnectionPoint {
+        return this._inputs[0];
+    }
+
+    /**
+     * Gets the output component
+     */
+    public get output(): NodeMaterialConnectionPoint {
+        return this._outputs[0];
+    }
+
+    protected _buildBlock(state: NodeMaterialBuildState) {
+        super._buildBlock(state);
+
+        let output = this._outputs[0];
+
+        state.compilationString += this._declareOutput(output, state) + ` = 1. - ${this.input.associatedVariableName};\r\n`;
+
+        return this;
+    }
+}
+
+_TypeStore.RegisteredTypes["BABYLON.OppositeBlock"] = OppositeBlock;

+ 1 - 0
src/Materials/Node/Blocks/subtractBlock.ts

@@ -20,6 +20,7 @@ export class SubtractBlock extends NodeMaterialBlock {
         this.registerOutput("output", NodeMaterialBlockConnectionPointTypes.BasedOnInput);
 
         this._outputs[0]._typeConnectionSource = this._inputs[0];
+        this._linkConnectionTypes(0, 1);
     }
 
     /**

+ 1 - 1
src/Materials/Node/Blocks/trigonometryBlock.ts

@@ -85,7 +85,7 @@ export class TrigonometryBlock extends NodeMaterialBlock {
                 operation = "sin";
                 break;
             }
-            case TrigonometryBlockOperations.Cos: {
+            case TrigonometryBlockOperations.Abs: {
                 operation = "abs";
                 break;
             }

+ 79 - 0
src/Materials/Node/Blocks/viewDirectionBlock.ts

@@ -0,0 +1,79 @@
+import { NodeMaterialBlock } from '../nodeMaterialBlock';
+import { NodeMaterialBlockConnectionPointTypes } from '../nodeMaterialBlockConnectionPointTypes';
+import { NodeMaterialBuildState } from '../nodeMaterialBuildState';
+import { NodeMaterialConnectionPoint } from '../nodeMaterialBlockConnectionPoint';
+import { NodeMaterialBlockTargets } from '../nodeMaterialBlockTargets';
+import { _TypeStore } from '../../../Misc/typeStore';
+import { NodeMaterial } from '../nodeMaterial';
+import { NodeMaterialWellKnownValues } from '../nodeMaterialWellKnownValues';
+import { InputBlock } from './Input/inputBlock';
+/**
+ * Block used to get the view direction
+ */
+export class ViewDirectionBlock extends NodeMaterialBlock {
+    /**
+     * Creates a new ViewDirectionBlock
+     * @param name defines the block name
+     */
+    public constructor(name: string) {
+        super(name, NodeMaterialBlockTargets.Neutral);
+
+        this.registerInput("worldPosition", NodeMaterialBlockConnectionPointTypes.Vector4);
+        this.registerInput("cameraPosition", NodeMaterialBlockConnectionPointTypes.Vector3);
+
+        this.registerOutput("output", NodeMaterialBlockConnectionPointTypes.Vector3);
+    }
+
+    /**
+     * Gets the current class name
+     * @returns the class name
+     */
+    public getClassName() {
+        return "ViewDirectionBlock";
+    }
+
+    /**
+     * Gets the world position component
+     */
+    public get worldPosition(): NodeMaterialConnectionPoint {
+        return this._inputs[0];
+    }
+
+    /**
+     * Gets the camera position component
+     */
+    public get cameraPosition(): NodeMaterialConnectionPoint {
+        return this._inputs[1];
+    }
+
+    /**
+     * Gets the output component
+     */
+    public get output(): NodeMaterialConnectionPoint {
+        return this._outputs[0];
+    }
+
+    public autoConfigure(material: NodeMaterial) {
+        if (!this.cameraPosition.isConnected) {
+            let cameraPositionInput = material.getInputBlockByPredicate((b) => b.wellKnownValue === NodeMaterialWellKnownValues.CameraPosition);
+
+            if (!cameraPositionInput) {
+                cameraPositionInput = new InputBlock("cameraPosition");
+                cameraPositionInput.setAsWellKnownValue(NodeMaterialWellKnownValues.CameraPosition);
+            }
+            cameraPositionInput.output.connectTo(this.cameraPosition);
+        }
+    }
+
+    protected _buildBlock(state: NodeMaterialBuildState) {
+        super._buildBlock(state);
+
+        let output = this._outputs[0];
+
+        state.compilationString += this._declareOutput(output, state) + ` = normalize(${this.cameraPosition.associatedVariableName} - ${this.worldPosition.associatedVariableName}.xyz);\r\n`;
+
+        return this;
+    }
+}
+
+_TypeStore.RegisteredTypes["BABYLON.ViewDirectionBlock"] = ViewDirectionBlock;

+ 30 - 0
src/Materials/Node/nodeMaterial.ts

@@ -271,6 +271,36 @@ export class NodeMaterial extends PushMaterial {
     }
 
     /**
+     * Get a block by its name
+     * @param predicate defines the predicate used to find the good candidate
+     * @returns the required block or null if not found
+     */
+    public getBlockByPredicate(predicate: (block: NodeMaterialBlock) => boolean) {
+        for (var block of this.attachedBlocks) {
+            if (predicate(block)) {
+                return block;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Get an input block by its name
+     * @param predicate defines the predicate used to find the good candidate
+     * @returns the required input block or null if not found
+     */
+    public getInputBlockByPredicate(predicate: (block: InputBlock) => boolean): Nullable<InputBlock> {
+        for (var block of this.attachedBlocks) {
+            if (block.isInput && predicate(block as InputBlock)) {
+                return block as InputBlock;
+            }
+        }
+
+        return null;
+    }
+
+    /**
      * Gets the list of input blocks attached to this material
      * @returns an array of InputBlocks
      */

+ 15 - 3
src/Materials/Node/nodeMaterialBlock.ts

@@ -384,16 +384,28 @@ export class NodeMaterialBlock {
         return true;
     }
 
+    protected _linkConnectionTypes(inputIndex0: number, inputIndex1: number) {
+        this._inputs[inputIndex0]._linkedConnectionSource = this._inputs[inputIndex1];
+        this._inputs[inputIndex1]._linkedConnectionSource = this._inputs[inputIndex0];
+    }
+
     private _processBuild(block: NodeMaterialBlock, state: NodeMaterialBuildState, input: NodeMaterialConnectionPoint, activeBlocks: NodeMaterialBlock[]) {
         block.build(state, activeBlocks);
 
-        if (state._vertexState && (block.target & this.target) === 0) { // context switch! We need a varying
+        const localBlockIsFragment = (state._vertexState != null);
+        const otherBlockWasGeneratedInVertexShader = block._buildTarget === NodeMaterialBlockTargets.Vertex && block.target !== NodeMaterialBlockTargets.VertexAndFragment;
+
+        if (localBlockIsFragment && (
+            ((block.target & this.target) === 0) ||
+            (this.target !== NodeMaterialBlockTargets.VertexAndFragment && otherBlockWasGeneratedInVertexShader)
+            )) { // context switch! We need a varying
             if ((!block.isInput && state.target !== block._buildTarget) // block was already emitted by vertex shader
                 || (block.isInput && (block as InputBlock).isAttribute) // block is an attribute
             ) {
                 let connectedPoint = input.connectedPoint!;
-                state._vertexState._emitVaryingFromString("v_" + connectedPoint.associatedVariableName, state._getGLType(connectedPoint.type));
-                state._vertexState.compilationString += `${"v_" + connectedPoint.associatedVariableName} = ${connectedPoint.associatedVariableName};\r\n`;
+                if (state._vertexState._emitVaryingFromString("v_" + connectedPoint.associatedVariableName, state._getGLType(connectedPoint.type))) {
+                    state._vertexState.compilationString += `${"v_" + connectedPoint.associatedVariableName} = ${connectedPoint.associatedVariableName};\r\n`;
+                }
                 input.associatedVariableName = "v_" + connectedPoint.associatedVariableName;
                 input._enforceAssociatedVariableName = true;
             }

+ 8 - 1
src/Materials/Node/nodeMaterialBlockConnectionPoint.ts

@@ -20,6 +20,9 @@ export class NodeMaterialConnectionPoint {
     /** @hidden */
     public _typeConnectionSource: Nullable<NodeMaterialConnectionPoint> = null;
 
+    /** @hidden */
+    public _linkedConnectionSource: Nullable<NodeMaterialConnectionPoint> = null;
+
     private _type = NodeMaterialBlockConnectionPointTypes.Float;
 
     /** @hidden */
@@ -38,7 +41,7 @@ export class NodeMaterialConnectionPoint {
             return (this._ownerBlock as InputBlock).associatedVariableName;
         }
 
-        if (!this._enforceAssociatedVariableName && this._connectedPoint) {
+        if ((!this._enforceAssociatedVariableName || !this._associatedVariableName) && this._connectedPoint) {
             return this._connectedPoint.associatedVariableName;
         }
 
@@ -61,6 +64,10 @@ export class NodeMaterialConnectionPoint {
             if (this._connectedPoint) {
                 return this._connectedPoint.type;
             }
+
+            if (this._linkedConnectionSource && this._linkedConnectionSource.isConnected) {
+                return this._linkedConnectionSource.type;
+            }
         }
 
         if (this._type === NodeMaterialBlockConnectionPointTypes.BasedOnInput && this._typeConnectionSource) {

+ 13 - 2
src/Materials/PBR/pbrBaseMaterial.ts

@@ -732,6 +732,8 @@ export abstract class PBRBaseMaterial extends PushMaterial {
      */
     public customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: PBRMaterialDefines) => string;
 
+    protected _rebuildInParallel = false;
+
     /**
      * Instantiates a new PBRMaterial instance.
      *
@@ -1007,15 +1009,24 @@ export abstract class PBRBaseMaterial extends PushMaterial {
             Logger.Warn("PBRMaterial: Normals have been created for the mesh: " + mesh.name);
         }
 
-        let previousEffect = subMesh.effect;
+        const previousEffect = subMesh.effect;
+        const lightDisposed = defines._areLightsDisposed;
         let effect = this._prepareEffect(mesh, defines, this.onCompiled, this.onError, useInstances);
 
         if (effect) {
             // Use previous effect while new one is compiling
             if (this.allowShaderHotSwapping && previousEffect && !effect.isReady()) {
                 effect = previousEffect;
+                this._rebuildInParallel = true;
                 defines.markAsUnprocessed();
+
+                if (lightDisposed) {
+                    // re register in case it takes more than one frame.
+                    defines._areLightsDisposed = true;
+                    return false;
+                }
             } else {
+                this._rebuildInParallel = false;
                 scene.resetCachedMaterial();
                 subMesh.setEffect(effect, defines);
                 this.buildUniformLayout();
@@ -1887,7 +1898,7 @@ export abstract class PBRBaseMaterial extends PushMaterial {
         if (mustRebind || !this.isFrozen) {
             // Lights
             if (scene.lightsEnabled && !this._disableLighting) {
-                MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, this._maxSimultaneousLights, this._lightFalloff !== PBRBaseMaterial.LIGHTFALLOFF_STANDARD);
+                MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, this._maxSimultaneousLights, this._lightFalloff !== PBRBaseMaterial.LIGHTFALLOFF_STANDARD, this._rebuildInParallel);
             }
 
             // View

+ 8 - 0
src/Materials/Textures/videoTexture.ts

@@ -65,6 +65,7 @@ export class VideoTexture extends Texture {
     private _displayingPosterTexture = false;
     private _settings: VideoTextureSettings;
     private _createInternalTextureOnEvent: string;
+    private _frameId = -1;
 
     /**
      * Creates a video texture.
@@ -297,6 +298,13 @@ export class VideoTexture extends Texture {
             return;
         }
 
+        let frameId = this.getScene()!.getFrameId();
+        if (this._frameId === frameId) {
+            return;
+        }
+
+        this._frameId = frameId;
+
         this._engine.updateVideoTexture(this._texture, this.video, this._invertY);
     }
 

+ 6 - 1
src/Materials/materialDefines.ts

@@ -11,6 +11,8 @@ export class MaterialDefines {
     /** @hidden */
     public _areLightsDirty = true;
     /** @hidden */
+    public _areLightsDisposed = false;
+    /** @hidden */
     public _areAttributesDirty = true;
     /** @hidden */
     public _areTexturesDirty = true;
@@ -49,6 +51,7 @@ export class MaterialDefines {
         this._areTexturesDirty = false;
         this._areFresnelDirty = false;
         this._areLightsDirty = false;
+        this._areLightsDisposed = false;
         this._areMiscDirty = false;
         this._areImageProcessingDirty = false;
     }
@@ -83,9 +86,11 @@ export class MaterialDefines {
 
     /**
      * Marks the material to indicate the lights need to be re-calculated
+     * @param disposed Defines whether the light is dirty due to dispose or not
      */
-    public markAsLightDirty() {
+    public markAsLightDirty(disposed = false) {
         this._areLightsDirty = true;
+        this._areLightsDisposed = this._areLightsDisposed || disposed;
         this._isDirty = true;
     }
 

+ 8 - 4
src/Materials/materialHelper.ts

@@ -679,12 +679,15 @@ export class MaterialHelper {
      * @param effect The effect we are binding the data to
      * @param useSpecular Defines if specular is supported
      * @param usePhysicalLightFalloff Specifies whether the light falloff is defined physically or not
+     * @param rebuildInParallel Specifies whether the shader is rebuilding in parallel
      */
-    public static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff = false): void {
+    public static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff = false, rebuildInParallel = false): void {
         let iAsString = lightIndex.toString();
 
         let scaledIntensity = light.getScaledIntensity();
-        light._uniformBuffer.bindToEffect(effect, "Light" + iAsString);
+        if (!rebuildInParallel) {
+            light._uniformBuffer.bindToEffect(effect, "Light" + iAsString);
+        }
 
         MaterialHelper.BindLightProperties(light, effect, lightIndex);
 
@@ -710,14 +713,15 @@ export class MaterialHelper {
      * @param defines The generated defines for the effect
      * @param maxSimultaneousLights The maximum number of light that can be bound to the effect
      * @param usePhysicalLightFalloff Specifies whether the light falloff is defined physically or not
+     * @param rebuildInParallel Specifies whether the shader is rebuilding in parallel
      */
-    public static BindLights(scene: Scene, mesh: AbstractMesh, effect: Effect, defines: any, maxSimultaneousLights = 4, usePhysicalLightFalloff = false): void {
+    public static BindLights(scene: Scene, mesh: AbstractMesh, effect: Effect, defines: any, maxSimultaneousLights = 4, usePhysicalLightFalloff = false, rebuildInParallel = false): void {
         let len = Math.min(mesh.lightSources.length, maxSimultaneousLights);
 
         for (var i = 0; i < len; i++) {
 
             let light = mesh.lightSources[i];
-            this.BindLight(light, i, scene, mesh, effect, typeof defines === "boolean" ? defines : defines["SPECULARTERM"], usePhysicalLightFalloff);
+            this.BindLight(light, i, scene, mesh, effect, typeof defines === "boolean" ? defines : defines["SPECULARTERM"], usePhysicalLightFalloff, rebuildInParallel);
         }
     }
 

+ 11 - 1
src/Materials/standardMaterial.ts

@@ -666,6 +666,7 @@ export class StandardMaterial extends PushMaterial {
     protected _worldViewProjectionMatrix = Matrix.Zero();
     protected _globalAmbientColor = new Color3(0, 0, 0);
     protected _useLogarithmicDepth: boolean;
+    protected _rebuildInParallel = false;
 
     /**
      * Instantiates a new standard material.
@@ -1020,6 +1021,7 @@ export class StandardMaterial extends PushMaterial {
 
         // Get correct effect
         if (defines.isDirty) {
+            const lightDisposed = defines._areLightsDisposed;
             defines.markAsProcessed();
 
             // Fallbacks
@@ -1167,8 +1169,16 @@ export class StandardMaterial extends PushMaterial {
                 // Use previous effect while new one is compiling
                 if (this.allowShaderHotSwapping && previousEffect && !effect.isReady()) {
                     effect = previousEffect;
+                    this._rebuildInParallel = true;
                     defines.markAsUnprocessed();
+
+                    if (lightDisposed) {
+                        // re register in case it takes more than one frame.
+                        defines._areLightsDisposed = true;
+                        return false;
+                    }
                 } else {
+                    this._rebuildInParallel = false;
                     scene.resetCachedMaterial();
                     subMesh.setEffect(effect, defines);
                     this.buildUniformLayout();
@@ -1477,7 +1487,7 @@ export class StandardMaterial extends PushMaterial {
         if (mustRebind || !this.isFrozen) {
             // Lights
             if (scene.lightsEnabled && !this._disableLighting) {
-                MaterialHelper.BindLights(scene, mesh, effect, defines, this._maxSimultaneousLights);
+                MaterialHelper.BindLights(scene, mesh, effect, defines, this._maxSimultaneousLights, false, this._rebuildInParallel);
             }
 
             // View

+ 4 - 4
src/Meshes/abstractMesh.ts

@@ -791,7 +791,7 @@ export class AbstractMesh extends TransformNode implements IDisposable, ICullabl
     }
 
     /** @hidden */
-    public _removeLightSource(light: Light): void {
+    public _removeLightSource(light: Light, dispose: boolean): void {
         var index = this._lightSources.indexOf(light);
 
         if (index === -1) {
@@ -799,7 +799,7 @@ export class AbstractMesh extends TransformNode implements IDisposable, ICullabl
         }
         this._lightSources.splice(index, 1);
 
-        this._markSubMeshesAsLightDirty();
+        this._markSubMeshesAsLightDirty(dispose);
     }
 
     private _markSubMeshesAsDirty(func: (defines: MaterialDefines) => void) {
@@ -815,8 +815,8 @@ export class AbstractMesh extends TransformNode implements IDisposable, ICullabl
     }
 
     /** @hidden */
-    public _markSubMeshesAsLightDirty() {
-        this._markSubMeshesAsDirty((defines) => defines.markAsLightDirty());
+    public _markSubMeshesAsLightDirty(dispose: boolean = false) {
+        this._markSubMeshesAsDirty((defines) => defines.markAsLightDirty(dispose));
     }
 
     /** @hidden */

+ 1 - 1
src/Meshes/instancedMesh.ts

@@ -70,7 +70,7 @@ export class InstancedMesh extends AbstractMesh {
         // Do nothing as all the work will be done by source mesh
     }
 
-    public _removeLightSource(light: Light): void {
+    public _removeLightSource(light: Light, dispose: boolean): void {
         // Do nothing as all the work will be done by source mesh
     }
 

+ 6 - 1
src/Particles/solidParticleSystem.ts

@@ -284,12 +284,17 @@ export class SolidParticleSystem implements IDisposable {
             barycenter.scaleInPlace(1 / shape.length);
 
             // shift the shape from its barycenter to the origin
+            // and compute the BBox required for intersection.
+            var minimum: Vector3 = new Vector3(Infinity, Infinity, Infinity);
+            var maximum: Vector3 = new Vector3(-Infinity, -Infinity, -Infinity);
             for (v = 0; v < shape.length; v++) {
                 shape[v].subtractInPlace(barycenter);
+                minimum.minimizeInPlaceFromFloats(shape[v].x, shape[v].y, shape[v].z);
+                maximum.maximizeInPlaceFromFloats(shape[v].x, shape[v].y, shape[v].z);
             }
             var bInfo;
             if (this._particlesIntersect) {
-                bInfo = new BoundingInfo(barycenter, barycenter);
+                bInfo = new BoundingInfo(minimum, maximum);
             }
             var modelShape = new ModelShape(this._shapeCounter, shape, size * 3, shapeUV, null, null);
 

+ 1 - 1
src/scene.ts

@@ -2106,7 +2106,7 @@ export class Scene extends AbstractScene implements IAnimatable {
         if (index !== -1) {
             // Remove from meshes
             for (var mesh of this.meshes) {
-                mesh._removeLightSource(toRemove);
+                mesh._removeLightSource(toRemove, false);
             }
 
             // Remove from the scene if mesh found