Browse Source

Associated with #6012 - More light block work

David Catuhe 6 năm trước cách đây
mục cha
commit
990b4c6d9d

+ 73 - 6
Playground/babylon.d.txt

@@ -10789,6 +10789,23 @@ declare module BABYLON {
          * Prepares the defines related to the light information passed in parameter
          * Prepares the defines related to the light information passed in parameter
          * @param scene The scene we are intending to draw
          * @param scene The scene we are intending to draw
          * @param mesh The mesh the effect is compiling for
          * @param mesh The mesh the effect is compiling for
+         * @param light The light the effect is compiling for
+         * @param lightIndex The index of the light
+         * @param defines The defines to update
+         * @param specularSupported Specifies whether specular is supported or not (override lights data)
+         * @param state Defines the current state regarding what is needed (normals, etc...)
+         */
+        static PrepareDefinesForLight(scene: Scene, mesh: AbstractMesh, light: Light, lightIndex: number, defines: any, specularSupported: boolean, state: {
+            needNormals: boolean;
+            needRebuild: boolean;
+            shadowEnabled: boolean;
+            specularEnabled: boolean;
+            lightmapMode: boolean;
+        }): void;
+        /**
+         * Prepares the defines related to the light information passed in parameter
+         * @param scene The scene we are intending to draw
+         * @param mesh The mesh the effect is compiling for
          * @param defines The defines to update
          * @param defines The defines to update
          * @param specularSupported Specifies whether specular is supported or not (override lights data)
          * @param specularSupported Specifies whether specular is supported or not (override lights data)
          * @param maxSimultaneousLights Specfies how manuy lights can be added to the effect at max
          * @param maxSimultaneousLights Specfies how manuy lights can be added to the effect at max
@@ -10797,10 +10814,18 @@ declare module BABYLON {
          */
          */
         static PrepareDefinesForLights(scene: Scene, mesh: AbstractMesh, defines: any, specularSupported: boolean, maxSimultaneousLights?: number, disableLighting?: boolean): boolean;
         static PrepareDefinesForLights(scene: Scene, mesh: AbstractMesh, defines: any, specularSupported: boolean, maxSimultaneousLights?: number, disableLighting?: boolean): boolean;
         /**
         /**
-         * Prepares the uniforms and samplers list to be used in the effect. This can automatically remove from the list uniforms
-         * that won t be acctive due to defines being turned off.
+         * Prepares the uniforms and samplers list to be used in the effect (for a specific light)
+         * @param lightIndex defines the light index
+         * @param uniformsList The uniform list
+         * @param samplersList The sampler list
+         * @param projectedLightTexture defines if projected texture must be used
+         * @param uniformBuffersList defines an optional list of uniform buffers
+         */
+        static PrepareUniformsAndSamplersForLight(lightIndex: number, uniformsList: string[], samplersList: string[], projectedLightTexture?: any, uniformBuffersList?: Nullable<string[]>): void;
+        /**
+         * Prepares the uniforms and samplers list to be used in the effect
          * @param uniformsListOrOptions The uniform names to prepare or an EffectCreationOptions containing the liist and extra information
          * @param uniformsListOrOptions The uniform names to prepare or an EffectCreationOptions containing the liist and extra information
-         * @param samplersList The samplers list
+         * @param samplersList The sampler list
          * @param defines The defines helping in the list generation
          * @param defines The defines helping in the list generation
          * @param maxSimultaneousLights The maximum number of simultanous light allowed in the effect
          * @param maxSimultaneousLights The maximum number of simultanous light allowed in the effect
          */
          */
@@ -10858,6 +10883,17 @@ declare module BABYLON {
         static BindLightProperties(light: Light, effect: Effect, lightIndex: number): void;
         static BindLightProperties(light: Light, effect: Effect, lightIndex: number): void;
         /**
         /**
          * Binds the lights information from the scene to the effect for the given mesh.
          * Binds the lights information from the scene to the effect for the given mesh.
+         * @param light Light to bind
+         * @param lightIndex Light index
+         * @param scene The scene where the light belongs to
+         * @param mesh The mesh we are binding the information to render
+         * @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
+         */
+        static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff?: boolean): void;
+        /**
+         * Binds the lights information from the scene to the effect for the given mesh.
          * @param scene The scene the lights belongs to
          * @param scene The scene the lights belongs to
          * @param mesh The mesh we are binding the information to render
          * @param mesh The mesh we are binding the information to render
          * @param effect The effect we are binding the data to
          * @param effect The effect we are binding the data to
@@ -13621,6 +13657,10 @@ declare module BABYLON {
          */
          */
         static MeshImpostor: number;
         static MeshImpostor: number;
         /**
         /**
+         * Capsule-Impostor type (Ammo.js plugin only)
+         */
+        static CapsuleImpostor: number;
+        /**
          * Cylinder-Imposter type
          * Cylinder-Imposter type
          */
          */
         static CylinderImpostor: number;
         static CylinderImpostor: number;
@@ -49908,6 +49948,10 @@ declare module BABYLON {
          */
          */
         uniforms: string[];
         uniforms: string[];
         /**
         /**
+         * Gets the list of emitted uniform buffers
+         */
+        uniformBuffers: string[];
+        /**
          * Gets the list of emitted samplers
          * Gets the list of emitted samplers
          */
          */
         samplers: string[];
         samplers: string[];
@@ -49922,6 +49966,12 @@ declare module BABYLON {
          */
          */
         target: NodeMaterialBlockTargets;
         target: NodeMaterialBlockTargets;
         /**
         /**
+         * Gets the list of emitted counters
+         */
+        counters: {
+            [key: string]: number;
+        };
+        /**
          * Shared data between multiple NodeMaterialBuildState instances
          * Shared data between multiple NodeMaterialBuildState instances
          */
          */
         sharedData: NodeMaterialBuildStateSharedData;
         sharedData: NodeMaterialBuildStateSharedData;
@@ -49964,7 +50014,7 @@ declare module BABYLON {
                 replace: string;
                 replace: string;
             }[];
             }[];
         }): void;
         }): void;
-        /** @hidden */
private _emitVaryings(point: NodeMaterialConnectionPoint, define?: string, force?: boolean, fromFragment?: boolean, replacementName?: string): void;
+        /** @hidden */
private _emitVaryings(point: NodeMaterialConnectionPoint, define?: string, force?: boolean, fromFragment?: boolean, replacementName?: string, type?: Nullable<NodeMaterialBlockConnectionPointTypes>): void;
         private _emitDefine;
         private _emitDefine;
         /** @hidden */
private _emitUniformOrAttributes(point: NodeMaterialConnectionPoint, define?: string): void;
         /** @hidden */
private _emitUniformOrAttributes(point: NodeMaterialConnectionPoint, define?: string): void;
     }
     }
@@ -50969,19 +51019,36 @@ declare module BABYLON {
      * Block used to add light in the fragment shader
      * Block used to add light in the fragment shader
      */
      */
     export class LightBlock extends NodeMaterialBlock {
     export class LightBlock extends NodeMaterialBlock {
+        private _lightId;
         /**
         /**
          * Create a new LightBlock
          * Create a new LightBlock
          * @param name defines the block name
          * @param name defines the block name
          */
          */
         constructor(name: string);
         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 light input component
         * Gets the light input component
         */
         */
         readonly light: NodeMaterialConnectionPoint;
         readonly light: NodeMaterialConnectionPoint;
         /**
         /**
-         * Gets the output component
+         * Gets the diffuse output component
          */
          */
-        readonly output: NodeMaterialConnectionPoint;
+        readonly diffuseOutput: NodeMaterialConnectionPoint;
+        /**
+         * Gets the specular output component
+         */
+        readonly specularOutput: NodeMaterialConnectionPoint;
+        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
+        private _injectVertexCode;
         protected _buildBlock(state: NodeMaterialBuildState): this;
         protected _buildBlock(state: NodeMaterialBuildState): this;
     }
     }
 }
 }

+ 73 - 6
dist/preview release/babylon.d.ts

@@ -10930,6 +10930,23 @@ declare module BABYLON {
          * Prepares the defines related to the light information passed in parameter
          * Prepares the defines related to the light information passed in parameter
          * @param scene The scene we are intending to draw
          * @param scene The scene we are intending to draw
          * @param mesh The mesh the effect is compiling for
          * @param mesh The mesh the effect is compiling for
+         * @param light The light the effect is compiling for
+         * @param lightIndex The index of the light
+         * @param defines The defines to update
+         * @param specularSupported Specifies whether specular is supported or not (override lights data)
+         * @param state Defines the current state regarding what is needed (normals, etc...)
+         */
+        static PrepareDefinesForLight(scene: Scene, mesh: AbstractMesh, light: Light, lightIndex: number, defines: any, specularSupported: boolean, state: {
+            needNormals: boolean;
+            needRebuild: boolean;
+            shadowEnabled: boolean;
+            specularEnabled: boolean;
+            lightmapMode: boolean;
+        }): void;
+        /**
+         * Prepares the defines related to the light information passed in parameter
+         * @param scene The scene we are intending to draw
+         * @param mesh The mesh the effect is compiling for
          * @param defines The defines to update
          * @param defines The defines to update
          * @param specularSupported Specifies whether specular is supported or not (override lights data)
          * @param specularSupported Specifies whether specular is supported or not (override lights data)
          * @param maxSimultaneousLights Specfies how manuy lights can be added to the effect at max
          * @param maxSimultaneousLights Specfies how manuy lights can be added to the effect at max
@@ -10938,10 +10955,18 @@ declare module BABYLON {
          */
          */
         static PrepareDefinesForLights(scene: Scene, mesh: AbstractMesh, defines: any, specularSupported: boolean, maxSimultaneousLights?: number, disableLighting?: boolean): boolean;
         static PrepareDefinesForLights(scene: Scene, mesh: AbstractMesh, defines: any, specularSupported: boolean, maxSimultaneousLights?: number, disableLighting?: boolean): boolean;
         /**
         /**
-         * Prepares the uniforms and samplers list to be used in the effect. This can automatically remove from the list uniforms
-         * that won t be acctive due to defines being turned off.
+         * Prepares the uniforms and samplers list to be used in the effect (for a specific light)
+         * @param lightIndex defines the light index
+         * @param uniformsList The uniform list
+         * @param samplersList The sampler list
+         * @param projectedLightTexture defines if projected texture must be used
+         * @param uniformBuffersList defines an optional list of uniform buffers
+         */
+        static PrepareUniformsAndSamplersForLight(lightIndex: number, uniformsList: string[], samplersList: string[], projectedLightTexture?: any, uniformBuffersList?: Nullable<string[]>): void;
+        /**
+         * Prepares the uniforms and samplers list to be used in the effect
          * @param uniformsListOrOptions The uniform names to prepare or an EffectCreationOptions containing the liist and extra information
          * @param uniformsListOrOptions The uniform names to prepare or an EffectCreationOptions containing the liist and extra information
-         * @param samplersList The samplers list
+         * @param samplersList The sampler list
          * @param defines The defines helping in the list generation
          * @param defines The defines helping in the list generation
          * @param maxSimultaneousLights The maximum number of simultanous light allowed in the effect
          * @param maxSimultaneousLights The maximum number of simultanous light allowed in the effect
          */
          */
@@ -10999,6 +11024,17 @@ declare module BABYLON {
         static BindLightProperties(light: Light, effect: Effect, lightIndex: number): void;
         static BindLightProperties(light: Light, effect: Effect, lightIndex: number): void;
         /**
         /**
          * Binds the lights information from the scene to the effect for the given mesh.
          * Binds the lights information from the scene to the effect for the given mesh.
+         * @param light Light to bind
+         * @param lightIndex Light index
+         * @param scene The scene where the light belongs to
+         * @param mesh The mesh we are binding the information to render
+         * @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
+         */
+        static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff?: boolean): void;
+        /**
+         * Binds the lights information from the scene to the effect for the given mesh.
          * @param scene The scene the lights belongs to
          * @param scene The scene the lights belongs to
          * @param mesh The mesh we are binding the information to render
          * @param mesh The mesh we are binding the information to render
          * @param effect The effect we are binding the data to
          * @param effect The effect we are binding the data to
@@ -13795,6 +13831,10 @@ declare module BABYLON {
          */
          */
         static MeshImpostor: number;
         static MeshImpostor: number;
         /**
         /**
+         * Capsule-Impostor type (Ammo.js plugin only)
+         */
+        static CapsuleImpostor: number;
+        /**
          * Cylinder-Imposter type
          * Cylinder-Imposter type
          */
          */
         static CylinderImpostor: number;
         static CylinderImpostor: number;
@@ -50685,6 +50725,10 @@ declare module BABYLON {
          */
          */
         uniforms: string[];
         uniforms: string[];
         /**
         /**
+         * Gets the list of emitted uniform buffers
+         */
+        uniformBuffers: string[];
+        /**
          * Gets the list of emitted samplers
          * Gets the list of emitted samplers
          */
          */
         samplers: string[];
         samplers: string[];
@@ -50699,6 +50743,12 @@ declare module BABYLON {
          */
          */
         target: NodeMaterialBlockTargets;
         target: NodeMaterialBlockTargets;
         /**
         /**
+         * Gets the list of emitted counters
+         */
+        counters: {
+            [key: string]: number;
+        };
+        /**
          * Shared data between multiple NodeMaterialBuildState instances
          * Shared data between multiple NodeMaterialBuildState instances
          */
          */
         sharedData: NodeMaterialBuildStateSharedData;
         sharedData: NodeMaterialBuildStateSharedData;
@@ -50752,7 +50802,7 @@ declare module BABYLON {
             }[];
             }[];
         }): void;
         }): void;
         /** @hidden */
         /** @hidden */
-        _emitVaryings(point: NodeMaterialConnectionPoint, define?: string, force?: boolean, fromFragment?: boolean, replacementName?: string): void;
+        _emitVaryings(point: NodeMaterialConnectionPoint, define?: string, force?: boolean, fromFragment?: boolean, replacementName?: string, type?: Nullable<NodeMaterialBlockConnectionPointTypes>): void;
         private _emitDefine;
         private _emitDefine;
         /** @hidden */
         /** @hidden */
         _emitUniformOrAttributes(point: NodeMaterialConnectionPoint, define?: string): void;
         _emitUniformOrAttributes(point: NodeMaterialConnectionPoint, define?: string): void;
@@ -51768,19 +51818,36 @@ declare module BABYLON {
      * Block used to add light in the fragment shader
      * Block used to add light in the fragment shader
      */
      */
     export class LightBlock extends NodeMaterialBlock {
     export class LightBlock extends NodeMaterialBlock {
+        private _lightId;
         /**
         /**
          * Create a new LightBlock
          * Create a new LightBlock
          * @param name defines the block name
          * @param name defines the block name
          */
          */
         constructor(name: string);
         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 light input component
         * Gets the light input component
         */
         */
         readonly light: NodeMaterialConnectionPoint;
         readonly light: NodeMaterialConnectionPoint;
         /**
         /**
-         * Gets the output component
+         * Gets the diffuse output component
          */
          */
-        readonly output: NodeMaterialConnectionPoint;
+        readonly diffuseOutput: NodeMaterialConnectionPoint;
+        /**
+         * Gets the specular output component
+         */
+        readonly specularOutput: NodeMaterialConnectionPoint;
+        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
+        private _injectVertexCode;
         protected _buildBlock(state: NodeMaterialBuildState): this;
         protected _buildBlock(state: NodeMaterialBuildState): this;
     }
     }
 }
 }

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/babylon.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 314 - 148
dist/preview release/babylon.max.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/babylon.max.js.map


+ 151 - 12
dist/preview release/babylon.module.d.ts

@@ -11097,6 +11097,23 @@ declare module "babylonjs/Materials/materialHelper" {
          * Prepares the defines related to the light information passed in parameter
          * Prepares the defines related to the light information passed in parameter
          * @param scene The scene we are intending to draw
          * @param scene The scene we are intending to draw
          * @param mesh The mesh the effect is compiling for
          * @param mesh The mesh the effect is compiling for
+         * @param light The light the effect is compiling for
+         * @param lightIndex The index of the light
+         * @param defines The defines to update
+         * @param specularSupported Specifies whether specular is supported or not (override lights data)
+         * @param state Defines the current state regarding what is needed (normals, etc...)
+         */
+        static PrepareDefinesForLight(scene: Scene, mesh: AbstractMesh, light: Light, lightIndex: number, defines: any, specularSupported: boolean, state: {
+            needNormals: boolean;
+            needRebuild: boolean;
+            shadowEnabled: boolean;
+            specularEnabled: boolean;
+            lightmapMode: boolean;
+        }): void;
+        /**
+         * Prepares the defines related to the light information passed in parameter
+         * @param scene The scene we are intending to draw
+         * @param mesh The mesh the effect is compiling for
          * @param defines The defines to update
          * @param defines The defines to update
          * @param specularSupported Specifies whether specular is supported or not (override lights data)
          * @param specularSupported Specifies whether specular is supported or not (override lights data)
          * @param maxSimultaneousLights Specfies how manuy lights can be added to the effect at max
          * @param maxSimultaneousLights Specfies how manuy lights can be added to the effect at max
@@ -11105,10 +11122,18 @@ declare module "babylonjs/Materials/materialHelper" {
          */
          */
         static PrepareDefinesForLights(scene: Scene, mesh: AbstractMesh, defines: any, specularSupported: boolean, maxSimultaneousLights?: number, disableLighting?: boolean): boolean;
         static PrepareDefinesForLights(scene: Scene, mesh: AbstractMesh, defines: any, specularSupported: boolean, maxSimultaneousLights?: number, disableLighting?: boolean): boolean;
         /**
         /**
-         * Prepares the uniforms and samplers list to be used in the effect. This can automatically remove from the list uniforms
-         * that won t be acctive due to defines being turned off.
+         * Prepares the uniforms and samplers list to be used in the effect (for a specific light)
+         * @param lightIndex defines the light index
+         * @param uniformsList The uniform list
+         * @param samplersList The sampler list
+         * @param projectedLightTexture defines if projected texture must be used
+         * @param uniformBuffersList defines an optional list of uniform buffers
+         */
+        static PrepareUniformsAndSamplersForLight(lightIndex: number, uniformsList: string[], samplersList: string[], projectedLightTexture?: any, uniformBuffersList?: Nullable<string[]>): void;
+        /**
+         * Prepares the uniforms and samplers list to be used in the effect
          * @param uniformsListOrOptions The uniform names to prepare or an EffectCreationOptions containing the liist and extra information
          * @param uniformsListOrOptions The uniform names to prepare or an EffectCreationOptions containing the liist and extra information
-         * @param samplersList The samplers list
+         * @param samplersList The sampler list
          * @param defines The defines helping in the list generation
          * @param defines The defines helping in the list generation
          * @param maxSimultaneousLights The maximum number of simultanous light allowed in the effect
          * @param maxSimultaneousLights The maximum number of simultanous light allowed in the effect
          */
          */
@@ -11166,6 +11191,17 @@ declare module "babylonjs/Materials/materialHelper" {
         static BindLightProperties(light: Light, effect: Effect, lightIndex: number): void;
         static BindLightProperties(light: Light, effect: Effect, lightIndex: number): void;
         /**
         /**
          * Binds the lights information from the scene to the effect for the given mesh.
          * Binds the lights information from the scene to the effect for the given mesh.
+         * @param light Light to bind
+         * @param lightIndex Light index
+         * @param scene The scene where the light belongs to
+         * @param mesh The mesh we are binding the information to render
+         * @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
+         */
+        static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff?: boolean): void;
+        /**
+         * Binds the lights information from the scene to the effect for the given mesh.
          * @param scene The scene the lights belongs to
          * @param scene The scene the lights belongs to
          * @param mesh The mesh we are binding the information to render
          * @param mesh The mesh we are binding the information to render
          * @param effect The effect we are binding the data to
          * @param effect The effect we are binding the data to
@@ -14048,6 +14084,10 @@ declare module "babylonjs/Physics/physicsImpostor" {
          */
          */
         static MeshImpostor: number;
         static MeshImpostor: number;
         /**
         /**
+         * Capsule-Impostor type (Ammo.js plugin only)
+         */
+        static CapsuleImpostor: number;
+        /**
          * Cylinder-Imposter type
          * Cylinder-Imposter type
          */
          */
         static CylinderImpostor: number;
         static CylinderImpostor: number;
@@ -52928,6 +52968,7 @@ declare module "babylonjs/Materials/Node/nodeMaterialBuildState" {
     import { NodeMaterialBlockConnectionPointTypes } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPointTypes";
     import { NodeMaterialBlockConnectionPointTypes } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPointTypes";
     import { NodeMaterialBlockTargets } from "babylonjs/Materials/Node/nodeMaterialBlockTargets";
     import { NodeMaterialBlockTargets } from "babylonjs/Materials/Node/nodeMaterialBlockTargets";
     import { NodeMaterialBuildStateSharedData } from "babylonjs/Materials/Node/nodeMaterialBuildStateSharedData";
     import { NodeMaterialBuildStateSharedData } from "babylonjs/Materials/Node/nodeMaterialBuildStateSharedData";
+    import { Nullable } from "babylonjs/types";
     /**
     /**
      * Class used to store node based material build state
      * Class used to store node based material build state
      */
      */
@@ -52941,6 +52982,10 @@ declare module "babylonjs/Materials/Node/nodeMaterialBuildState" {
          */
          */
         uniforms: string[];
         uniforms: string[];
         /**
         /**
+         * Gets the list of emitted uniform buffers
+         */
+        uniformBuffers: string[];
+        /**
          * Gets the list of emitted samplers
          * Gets the list of emitted samplers
          */
          */
         samplers: string[];
         samplers: string[];
@@ -52955,6 +53000,12 @@ declare module "babylonjs/Materials/Node/nodeMaterialBuildState" {
          */
          */
         target: NodeMaterialBlockTargets;
         target: NodeMaterialBlockTargets;
         /**
         /**
+         * Gets the list of emitted counters
+         */
+        counters: {
+            [key: string]: number;
+        };
+        /**
          * Shared data between multiple NodeMaterialBuildState instances
          * Shared data between multiple NodeMaterialBuildState instances
          */
          */
         sharedData: NodeMaterialBuildStateSharedData;
         sharedData: NodeMaterialBuildStateSharedData;
@@ -53008,7 +53059,7 @@ declare module "babylonjs/Materials/Node/nodeMaterialBuildState" {
             }[];
             }[];
         }): void;
         }): void;
         /** @hidden */
         /** @hidden */
-        _emitVaryings(point: NodeMaterialConnectionPoint, define?: string, force?: boolean, fromFragment?: boolean, replacementName?: string): void;
+        _emitVaryings(point: NodeMaterialConnectionPoint, define?: string, force?: boolean, fromFragment?: boolean, replacementName?: string, type?: Nullable<NodeMaterialBlockConnectionPointTypes>): void;
         private _emitDefine;
         private _emitDefine;
         /** @hidden */
         /** @hidden */
         _emitUniformOrAttributes(point: NodeMaterialConnectionPoint, define?: string): void;
         _emitUniformOrAttributes(point: NodeMaterialConnectionPoint, define?: string): void;
@@ -54115,23 +54166,44 @@ declare module "babylonjs/Materials/Node/Blocks/Fragment/lightBlock" {
     import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
     import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
     import { NodeMaterialBuildState } from "babylonjs/Materials/Node/nodeMaterialBuildState";
     import { NodeMaterialBuildState } from "babylonjs/Materials/Node/nodeMaterialBuildState";
     import { NodeMaterialConnectionPoint } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint";
     import { NodeMaterialConnectionPoint } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint";
+    import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
+    import { NodeMaterial, NodeMaterialDefines } from "babylonjs/Materials/Node/nodeMaterial";
+    import { Effect } from "babylonjs/Materials/effect";
+    import { Mesh } from "babylonjs/Meshes/mesh";
     /**
     /**
      * Block used to add light in the fragment shader
      * Block used to add light in the fragment shader
      */
      */
     export class LightBlock extends NodeMaterialBlock {
     export class LightBlock extends NodeMaterialBlock {
+        private _lightId;
         /**
         /**
          * Create a new LightBlock
          * Create a new LightBlock
          * @param name defines the block name
          * @param name defines the block name
          */
          */
         constructor(name: string);
         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 light input component
         * Gets the light input component
         */
         */
         readonly light: NodeMaterialConnectionPoint;
         readonly light: NodeMaterialConnectionPoint;
         /**
         /**
-         * Gets the output component
+         * Gets the diffuse output component
          */
          */
-        readonly output: NodeMaterialConnectionPoint;
+        readonly diffuseOutput: NodeMaterialConnectionPoint;
+        /**
+         * Gets the specular output component
+         */
+        readonly specularOutput: NodeMaterialConnectionPoint;
+        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
+        private _injectVertexCode;
         protected _buildBlock(state: NodeMaterialBuildState): this;
         protected _buildBlock(state: NodeMaterialBuildState): this;
     }
     }
 }
 }
@@ -73718,6 +73790,23 @@ declare module BABYLON {
          * Prepares the defines related to the light information passed in parameter
          * Prepares the defines related to the light information passed in parameter
          * @param scene The scene we are intending to draw
          * @param scene The scene we are intending to draw
          * @param mesh The mesh the effect is compiling for
          * @param mesh The mesh the effect is compiling for
+         * @param light The light the effect is compiling for
+         * @param lightIndex The index of the light
+         * @param defines The defines to update
+         * @param specularSupported Specifies whether specular is supported or not (override lights data)
+         * @param state Defines the current state regarding what is needed (normals, etc...)
+         */
+        static PrepareDefinesForLight(scene: Scene, mesh: AbstractMesh, light: Light, lightIndex: number, defines: any, specularSupported: boolean, state: {
+            needNormals: boolean;
+            needRebuild: boolean;
+            shadowEnabled: boolean;
+            specularEnabled: boolean;
+            lightmapMode: boolean;
+        }): void;
+        /**
+         * Prepares the defines related to the light information passed in parameter
+         * @param scene The scene we are intending to draw
+         * @param mesh The mesh the effect is compiling for
          * @param defines The defines to update
          * @param defines The defines to update
          * @param specularSupported Specifies whether specular is supported or not (override lights data)
          * @param specularSupported Specifies whether specular is supported or not (override lights data)
          * @param maxSimultaneousLights Specfies how manuy lights can be added to the effect at max
          * @param maxSimultaneousLights Specfies how manuy lights can be added to the effect at max
@@ -73726,10 +73815,18 @@ declare module BABYLON {
          */
          */
         static PrepareDefinesForLights(scene: Scene, mesh: AbstractMesh, defines: any, specularSupported: boolean, maxSimultaneousLights?: number, disableLighting?: boolean): boolean;
         static PrepareDefinesForLights(scene: Scene, mesh: AbstractMesh, defines: any, specularSupported: boolean, maxSimultaneousLights?: number, disableLighting?: boolean): boolean;
         /**
         /**
-         * Prepares the uniforms and samplers list to be used in the effect. This can automatically remove from the list uniforms
-         * that won t be acctive due to defines being turned off.
+         * Prepares the uniforms and samplers list to be used in the effect (for a specific light)
+         * @param lightIndex defines the light index
+         * @param uniformsList The uniform list
+         * @param samplersList The sampler list
+         * @param projectedLightTexture defines if projected texture must be used
+         * @param uniformBuffersList defines an optional list of uniform buffers
+         */
+        static PrepareUniformsAndSamplersForLight(lightIndex: number, uniformsList: string[], samplersList: string[], projectedLightTexture?: any, uniformBuffersList?: Nullable<string[]>): void;
+        /**
+         * Prepares the uniforms and samplers list to be used in the effect
          * @param uniformsListOrOptions The uniform names to prepare or an EffectCreationOptions containing the liist and extra information
          * @param uniformsListOrOptions The uniform names to prepare or an EffectCreationOptions containing the liist and extra information
-         * @param samplersList The samplers list
+         * @param samplersList The sampler list
          * @param defines The defines helping in the list generation
          * @param defines The defines helping in the list generation
          * @param maxSimultaneousLights The maximum number of simultanous light allowed in the effect
          * @param maxSimultaneousLights The maximum number of simultanous light allowed in the effect
          */
          */
@@ -73787,6 +73884,17 @@ declare module BABYLON {
         static BindLightProperties(light: Light, effect: Effect, lightIndex: number): void;
         static BindLightProperties(light: Light, effect: Effect, lightIndex: number): void;
         /**
         /**
          * Binds the lights information from the scene to the effect for the given mesh.
          * Binds the lights information from the scene to the effect for the given mesh.
+         * @param light Light to bind
+         * @param lightIndex Light index
+         * @param scene The scene where the light belongs to
+         * @param mesh The mesh we are binding the information to render
+         * @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
+         */
+        static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff?: boolean): void;
+        /**
+         * Binds the lights information from the scene to the effect for the given mesh.
          * @param scene The scene the lights belongs to
          * @param scene The scene the lights belongs to
          * @param mesh The mesh we are binding the information to render
          * @param mesh The mesh we are binding the information to render
          * @param effect The effect we are binding the data to
          * @param effect The effect we are binding the data to
@@ -76583,6 +76691,10 @@ declare module BABYLON {
          */
          */
         static MeshImpostor: number;
         static MeshImpostor: number;
         /**
         /**
+         * Capsule-Impostor type (Ammo.js plugin only)
+         */
+        static CapsuleImpostor: number;
+        /**
          * Cylinder-Imposter type
          * Cylinder-Imposter type
          */
          */
         static CylinderImpostor: number;
         static CylinderImpostor: number;
@@ -113473,6 +113585,10 @@ declare module BABYLON {
          */
          */
         uniforms: string[];
         uniforms: string[];
         /**
         /**
+         * Gets the list of emitted uniform buffers
+         */
+        uniformBuffers: string[];
+        /**
          * Gets the list of emitted samplers
          * Gets the list of emitted samplers
          */
          */
         samplers: string[];
         samplers: string[];
@@ -113487,6 +113603,12 @@ declare module BABYLON {
          */
          */
         target: NodeMaterialBlockTargets;
         target: NodeMaterialBlockTargets;
         /**
         /**
+         * Gets the list of emitted counters
+         */
+        counters: {
+            [key: string]: number;
+        };
+        /**
          * Shared data between multiple NodeMaterialBuildState instances
          * Shared data between multiple NodeMaterialBuildState instances
          */
          */
         sharedData: NodeMaterialBuildStateSharedData;
         sharedData: NodeMaterialBuildStateSharedData;
@@ -113540,7 +113662,7 @@ declare module BABYLON {
             }[];
             }[];
         }): void;
         }): void;
         /** @hidden */
         /** @hidden */
-        _emitVaryings(point: NodeMaterialConnectionPoint, define?: string, force?: boolean, fromFragment?: boolean, replacementName?: string): void;
+        _emitVaryings(point: NodeMaterialConnectionPoint, define?: string, force?: boolean, fromFragment?: boolean, replacementName?: string, type?: Nullable<NodeMaterialBlockConnectionPointTypes>): void;
         private _emitDefine;
         private _emitDefine;
         /** @hidden */
         /** @hidden */
         _emitUniformOrAttributes(point: NodeMaterialConnectionPoint, define?: string): void;
         _emitUniformOrAttributes(point: NodeMaterialConnectionPoint, define?: string): void;
@@ -114556,19 +114678,36 @@ declare module BABYLON {
      * Block used to add light in the fragment shader
      * Block used to add light in the fragment shader
      */
      */
     export class LightBlock extends NodeMaterialBlock {
     export class LightBlock extends NodeMaterialBlock {
+        private _lightId;
         /**
         /**
          * Create a new LightBlock
          * Create a new LightBlock
          * @param name defines the block name
          * @param name defines the block name
          */
          */
         constructor(name: string);
         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 light input component
         * Gets the light input component
         */
         */
         readonly light: NodeMaterialConnectionPoint;
         readonly light: NodeMaterialConnectionPoint;
         /**
         /**
-         * Gets the output component
+         * Gets the diffuse output component
          */
          */
-        readonly output: NodeMaterialConnectionPoint;
+        readonly diffuseOutput: NodeMaterialConnectionPoint;
+        /**
+         * Gets the specular output component
+         */
+        readonly specularOutput: NodeMaterialConnectionPoint;
+        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
+        private _injectVertexCode;
         protected _buildBlock(state: NodeMaterialBuildState): this;
         protected _buildBlock(state: NodeMaterialBuildState): this;
     }
     }
 }
 }

+ 73 - 6
dist/preview release/documentation.d.ts

@@ -10930,6 +10930,23 @@ declare module BABYLON {
          * Prepares the defines related to the light information passed in parameter
          * Prepares the defines related to the light information passed in parameter
          * @param scene The scene we are intending to draw
          * @param scene The scene we are intending to draw
          * @param mesh The mesh the effect is compiling for
          * @param mesh The mesh the effect is compiling for
+         * @param light The light the effect is compiling for
+         * @param lightIndex The index of the light
+         * @param defines The defines to update
+         * @param specularSupported Specifies whether specular is supported or not (override lights data)
+         * @param state Defines the current state regarding what is needed (normals, etc...)
+         */
+        static PrepareDefinesForLight(scene: Scene, mesh: AbstractMesh, light: Light, lightIndex: number, defines: any, specularSupported: boolean, state: {
+            needNormals: boolean;
+            needRebuild: boolean;
+            shadowEnabled: boolean;
+            specularEnabled: boolean;
+            lightmapMode: boolean;
+        }): void;
+        /**
+         * Prepares the defines related to the light information passed in parameter
+         * @param scene The scene we are intending to draw
+         * @param mesh The mesh the effect is compiling for
          * @param defines The defines to update
          * @param defines The defines to update
          * @param specularSupported Specifies whether specular is supported or not (override lights data)
          * @param specularSupported Specifies whether specular is supported or not (override lights data)
          * @param maxSimultaneousLights Specfies how manuy lights can be added to the effect at max
          * @param maxSimultaneousLights Specfies how manuy lights can be added to the effect at max
@@ -10938,10 +10955,18 @@ declare module BABYLON {
          */
          */
         static PrepareDefinesForLights(scene: Scene, mesh: AbstractMesh, defines: any, specularSupported: boolean, maxSimultaneousLights?: number, disableLighting?: boolean): boolean;
         static PrepareDefinesForLights(scene: Scene, mesh: AbstractMesh, defines: any, specularSupported: boolean, maxSimultaneousLights?: number, disableLighting?: boolean): boolean;
         /**
         /**
-         * Prepares the uniforms and samplers list to be used in the effect. This can automatically remove from the list uniforms
-         * that won t be acctive due to defines being turned off.
+         * Prepares the uniforms and samplers list to be used in the effect (for a specific light)
+         * @param lightIndex defines the light index
+         * @param uniformsList The uniform list
+         * @param samplersList The sampler list
+         * @param projectedLightTexture defines if projected texture must be used
+         * @param uniformBuffersList defines an optional list of uniform buffers
+         */
+        static PrepareUniformsAndSamplersForLight(lightIndex: number, uniformsList: string[], samplersList: string[], projectedLightTexture?: any, uniformBuffersList?: Nullable<string[]>): void;
+        /**
+         * Prepares the uniforms and samplers list to be used in the effect
          * @param uniformsListOrOptions The uniform names to prepare or an EffectCreationOptions containing the liist and extra information
          * @param uniformsListOrOptions The uniform names to prepare or an EffectCreationOptions containing the liist and extra information
-         * @param samplersList The samplers list
+         * @param samplersList The sampler list
          * @param defines The defines helping in the list generation
          * @param defines The defines helping in the list generation
          * @param maxSimultaneousLights The maximum number of simultanous light allowed in the effect
          * @param maxSimultaneousLights The maximum number of simultanous light allowed in the effect
          */
          */
@@ -10999,6 +11024,17 @@ declare module BABYLON {
         static BindLightProperties(light: Light, effect: Effect, lightIndex: number): void;
         static BindLightProperties(light: Light, effect: Effect, lightIndex: number): void;
         /**
         /**
          * Binds the lights information from the scene to the effect for the given mesh.
          * Binds the lights information from the scene to the effect for the given mesh.
+         * @param light Light to bind
+         * @param lightIndex Light index
+         * @param scene The scene where the light belongs to
+         * @param mesh The mesh we are binding the information to render
+         * @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
+         */
+        static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff?: boolean): void;
+        /**
+         * Binds the lights information from the scene to the effect for the given mesh.
          * @param scene The scene the lights belongs to
          * @param scene The scene the lights belongs to
          * @param mesh The mesh we are binding the information to render
          * @param mesh The mesh we are binding the information to render
          * @param effect The effect we are binding the data to
          * @param effect The effect we are binding the data to
@@ -13795,6 +13831,10 @@ declare module BABYLON {
          */
          */
         static MeshImpostor: number;
         static MeshImpostor: number;
         /**
         /**
+         * Capsule-Impostor type (Ammo.js plugin only)
+         */
+        static CapsuleImpostor: number;
+        /**
          * Cylinder-Imposter type
          * Cylinder-Imposter type
          */
          */
         static CylinderImpostor: number;
         static CylinderImpostor: number;
@@ -50685,6 +50725,10 @@ declare module BABYLON {
          */
          */
         uniforms: string[];
         uniforms: string[];
         /**
         /**
+         * Gets the list of emitted uniform buffers
+         */
+        uniformBuffers: string[];
+        /**
          * Gets the list of emitted samplers
          * Gets the list of emitted samplers
          */
          */
         samplers: string[];
         samplers: string[];
@@ -50699,6 +50743,12 @@ declare module BABYLON {
          */
          */
         target: NodeMaterialBlockTargets;
         target: NodeMaterialBlockTargets;
         /**
         /**
+         * Gets the list of emitted counters
+         */
+        counters: {
+            [key: string]: number;
+        };
+        /**
          * Shared data between multiple NodeMaterialBuildState instances
          * Shared data between multiple NodeMaterialBuildState instances
          */
          */
         sharedData: NodeMaterialBuildStateSharedData;
         sharedData: NodeMaterialBuildStateSharedData;
@@ -50752,7 +50802,7 @@ declare module BABYLON {
             }[];
             }[];
         }): void;
         }): void;
         /** @hidden */
         /** @hidden */
-        _emitVaryings(point: NodeMaterialConnectionPoint, define?: string, force?: boolean, fromFragment?: boolean, replacementName?: string): void;
+        _emitVaryings(point: NodeMaterialConnectionPoint, define?: string, force?: boolean, fromFragment?: boolean, replacementName?: string, type?: Nullable<NodeMaterialBlockConnectionPointTypes>): void;
         private _emitDefine;
         private _emitDefine;
         /** @hidden */
         /** @hidden */
         _emitUniformOrAttributes(point: NodeMaterialConnectionPoint, define?: string): void;
         _emitUniformOrAttributes(point: NodeMaterialConnectionPoint, define?: string): void;
@@ -51768,19 +51818,36 @@ declare module BABYLON {
      * Block used to add light in the fragment shader
      * Block used to add light in the fragment shader
      */
      */
     export class LightBlock extends NodeMaterialBlock {
     export class LightBlock extends NodeMaterialBlock {
+        private _lightId;
         /**
         /**
          * Create a new LightBlock
          * Create a new LightBlock
          * @param name defines the block name
          * @param name defines the block name
          */
          */
         constructor(name: string);
         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 light input component
         * Gets the light input component
         */
         */
         readonly light: NodeMaterialConnectionPoint;
         readonly light: NodeMaterialConnectionPoint;
         /**
         /**
-         * Gets the output component
+         * Gets the diffuse output component
          */
          */
-        readonly output: NodeMaterialConnectionPoint;
+        readonly diffuseOutput: NodeMaterialConnectionPoint;
+        /**
+         * Gets the specular output component
+         */
+        readonly specularOutput: NodeMaterialConnectionPoint;
+        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
+        private _injectVertexCode;
         protected _buildBlock(state: NodeMaterialBuildState): this;
         protected _buildBlock(state: NodeMaterialBuildState): this;
     }
     }
 }
 }

+ 40 - 40
dist/preview release/gui/babylon.gui.js

@@ -7,7 +7,7 @@
 		exports["babylonjs-gui"] = factory(require("babylonjs"));
 		exports["babylonjs-gui"] = factory(require("babylonjs"));
 	else
 	else
 		root["BABYLON"] = root["BABYLON"] || {}, root["BABYLON"]["GUI"] = factory(root["BABYLON"]);
 		root["BABYLON"] = root["BABYLON"] || {}, root["BABYLON"]["GUI"] = factory(root["BABYLON"]);
-})((typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : this), function(__WEBPACK_EXTERNAL_MODULE_babylonjs_Misc_observable__) {
+})((typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : this), function(__WEBPACK_EXTERNAL_MODULE_babylonjs_Misc_tools__) {
 return /******/ (function(modules) { // webpackBootstrap
 return /******/ (function(modules) { // webpackBootstrap
 /******/ 	// The module cache
 /******/ 	// The module cache
 /******/ 	var installedModules = {};
 /******/ 	var installedModules = {};
@@ -355,7 +355,7 @@ module.exports = g;
 "use strict";
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AdvancedDynamicTextureInstrumentation", function() { return AdvancedDynamicTextureInstrumentation; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AdvancedDynamicTextureInstrumentation", function() { return AdvancedDynamicTextureInstrumentation; });
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__);
 
 
 /**
 /**
@@ -498,7 +498,7 @@ var AdvancedDynamicTextureInstrumentation = /** @class */ (function () {
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AdvancedDynamicTexture", function() { return AdvancedDynamicTexture; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AdvancedDynamicTexture", function() { return AdvancedDynamicTexture; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _controls_container__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./controls/container */ "./2D/controls/container.ts");
 /* harmony import */ var _controls_container__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./controls/container */ "./2D/controls/container.ts");
 /* harmony import */ var _style__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./style */ "./2D/style.ts");
 /* harmony import */ var _style__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./style */ "./2D/style.ts");
@@ -1619,7 +1619,7 @@ var Button = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Checkbox", function() { return Checkbox; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Checkbox", function() { return Checkbox; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _stackPanel__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./stackPanel */ "./2D/controls/stackPanel.ts");
 /* harmony import */ var _stackPanel__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./stackPanel */ "./2D/controls/stackPanel.ts");
@@ -1800,7 +1800,7 @@ var Checkbox = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ColorPicker", function() { return ColorPicker; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ColorPicker", function() { return ColorPicker; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _inputText__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./inputText */ "./2D/controls/inputText.ts");
 /* harmony import */ var _inputText__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./inputText */ "./2D/controls/inputText.ts");
@@ -3187,7 +3187,7 @@ var ColorPicker = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Container", function() { return Container; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Container", function() { return Container; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/logger */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/logger */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _measure__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../measure */ "./2D/measure.ts");
 /* harmony import */ var _measure__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../measure */ "./2D/measure.ts");
@@ -3592,7 +3592,7 @@ var Container = /** @class */ (function (_super) {
 "use strict";
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Control", function() { return Control; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Control", function() { return Control; });
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
 /* harmony import */ var _measure__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../measure */ "./2D/measure.ts");
 /* harmony import */ var _measure__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../measure */ "./2D/measure.ts");
@@ -5783,7 +5783,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var _container__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./container */ "./2D/controls/container.ts");
 /* harmony import */ var _container__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./container */ "./2D/controls/container.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4__);
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4__);
 
 
 
 
@@ -6239,7 +6239,7 @@ var Grid = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Image", function() { return Image; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Image", function() { return Image; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 
 
@@ -7014,7 +7014,7 @@ var InputPassword = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "InputText", function() { return InputText; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "InputText", function() { return InputText; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
@@ -8023,7 +8023,7 @@ var InputText = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Line", function() { return Line; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Line", function() { return Line; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
@@ -8291,7 +8291,7 @@ var Line = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MultiLine", function() { return MultiLine; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MultiLine", function() { return MultiLine; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/abstractMesh */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/abstractMesh */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _multiLinePoint__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../multiLinePoint */ "./2D/multiLinePoint.ts");
 /* harmony import */ var _multiLinePoint__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../multiLinePoint */ "./2D/multiLinePoint.ts");
@@ -8558,7 +8558,7 @@ var MultiLine = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RadioButton", function() { return RadioButton; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RadioButton", function() { return RadioButton; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _stackPanel__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./stackPanel */ "./2D/controls/stackPanel.ts");
 /* harmony import */ var _stackPanel__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./stackPanel */ "./2D/controls/stackPanel.ts");
@@ -8903,7 +8903,7 @@ var Rectangle = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ScrollViewer", function() { return ScrollViewer; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ScrollViewer", function() { return ScrollViewer; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Events_pointerEvents__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Events/pointerEvents */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Events_pointerEvents__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Events/pointerEvents */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Events_pointerEvents__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Events_pointerEvents__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Events_pointerEvents__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Events_pointerEvents__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _rectangle__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../rectangle */ "./2D/controls/rectangle.ts");
 /* harmony import */ var _rectangle__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../rectangle */ "./2D/controls/rectangle.ts");
 /* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../grid */ "./2D/controls/grid.ts");
 /* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../grid */ "./2D/controls/grid.ts");
@@ -9994,7 +9994,7 @@ var SelectionPanel = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BaseSlider", function() { return BaseSlider; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BaseSlider", function() { return BaseSlider; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../control */ "./2D/controls/control.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../control */ "./2D/controls/control.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../valueAndUnit */ "./2D/valueAndUnit.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../valueAndUnit */ "./2D/valueAndUnit.ts");
@@ -10895,7 +10895,7 @@ var Slider = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StackPanel", function() { return StackPanel; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StackPanel", function() { return StackPanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _container__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./container */ "./2D/controls/container.ts");
 /* harmony import */ var _container__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./container */ "./2D/controls/container.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
@@ -11153,7 +11153,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TextWrapping", function() { return TextWrapping; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TextWrapping", function() { return TextWrapping; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TextBlock", function() { return TextBlock; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TextBlock", function() { return TextBlock; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
@@ -11593,7 +11593,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "KeyPropertySet", function() { return KeyPropertySet; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "KeyPropertySet", function() { return KeyPropertySet; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VirtualKeyboard", function() { return VirtualKeyboard; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VirtualKeyboard", function() { return VirtualKeyboard; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _stackPanel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./stackPanel */ "./2D/controls/stackPanel.ts");
 /* harmony import */ var _stackPanel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./stackPanel */ "./2D/controls/stackPanel.ts");
 /* harmony import */ var _button__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./button */ "./2D/controls/button.ts");
 /* harmony import */ var _button__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./button */ "./2D/controls/button.ts");
@@ -11974,7 +11974,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Vector2WithInfo", function() { return Vector2WithInfo; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Vector2WithInfo", function() { return Vector2WithInfo; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Matrix2D", function() { return Matrix2D; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Matrix2D", function() { return Matrix2D; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__);
 
 
 
 
@@ -12198,7 +12198,7 @@ var Matrix2D = /** @class */ (function () {
 "use strict";
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Measure", function() { return Measure; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Measure", function() { return Measure; });
-/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__);
 
 
 
 
@@ -12331,7 +12331,7 @@ var Measure = /** @class */ (function () {
 "use strict";
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MultiLinePoint", function() { return MultiLinePoint; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MultiLinePoint", function() { return MultiLinePoint; });
-/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./valueAndUnit */ "./2D/valueAndUnit.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./valueAndUnit */ "./2D/valueAndUnit.ts");
 
 
@@ -12474,7 +12474,7 @@ var MultiLinePoint = /** @class */ (function () {
 "use strict";
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Style", function() { return Style; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Style", function() { return Style; });
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./valueAndUnit */ "./2D/valueAndUnit.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./valueAndUnit */ "./2D/valueAndUnit.ts");
 
 
@@ -12781,7 +12781,7 @@ var ValueAndUnit = /** @class */ (function () {
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AbstractButton3D", function() { return AbstractButton3D; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AbstractButton3D", function() { return AbstractButton3D; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/transformNode */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/transformNode */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control3D */ "./3D/controls/control3D.ts");
 /* harmony import */ var _control3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control3D */ "./3D/controls/control3D.ts");
 
 
@@ -12824,7 +12824,7 @@ var AbstractButton3D = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Button3D", function() { return Button3D; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Button3D", function() { return Button3D; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _abstractButton3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./abstractButton3D */ "./3D/controls/abstractButton3D.ts");
 /* harmony import */ var _abstractButton3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./abstractButton3D */ "./3D/controls/abstractButton3D.ts");
 /* harmony import */ var _2D_advancedDynamicTexture__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../2D/advancedDynamicTexture */ "./2D/advancedDynamicTexture.ts");
 /* harmony import */ var _2D_advancedDynamicTexture__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../2D/advancedDynamicTexture */ "./2D/advancedDynamicTexture.ts");
@@ -13001,7 +13001,7 @@ var Button3D = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Container3D", function() { return Container3D; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Container3D", function() { return Container3D; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/transformNode */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/transformNode */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control3D */ "./3D/controls/control3D.ts");
 /* harmony import */ var _control3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control3D */ "./3D/controls/control3D.ts");
 
 
@@ -13158,7 +13158,7 @@ var Container3D = /** @class */ (function (_super) {
 "use strict";
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Control3D", function() { return Control3D; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Control3D", function() { return Control3D; });
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var _vector3WithInfo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../vector3WithInfo */ "./3D/vector3WithInfo.ts");
 /* harmony import */ var _vector3WithInfo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../vector3WithInfo */ "./3D/vector3WithInfo.ts");
 
 
@@ -13564,7 +13564,7 @@ var Control3D = /** @class */ (function () {
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CylinderPanel", function() { return CylinderPanel; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CylinderPanel", function() { return CylinderPanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _volumeBasedPanel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./volumeBasedPanel */ "./3D/controls/volumeBasedPanel.ts");
 /* harmony import */ var _volumeBasedPanel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./volumeBasedPanel */ "./3D/controls/volumeBasedPanel.ts");
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
@@ -13649,7 +13649,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HolographicButton", function() { return HolographicButton; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HolographicButton", function() { return HolographicButton; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _button3D__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./button3D */ "./3D/controls/button3D.ts");
 /* harmony import */ var _button3D__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./button3D */ "./3D/controls/button3D.ts");
-/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_2__);
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_2__);
 /* harmony import */ var _materials_fluentMaterial__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../materials/fluentMaterial */ "./3D/materials/fluentMaterial.ts");
 /* harmony import */ var _materials_fluentMaterial__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../materials/fluentMaterial */ "./3D/materials/fluentMaterial.ts");
 /* harmony import */ var _2D_controls_stackPanel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../2D/controls/stackPanel */ "./2D/controls/stackPanel.ts");
 /* harmony import */ var _2D_controls_stackPanel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../2D/controls/stackPanel */ "./2D/controls/stackPanel.ts");
@@ -14125,7 +14125,7 @@ var MeshButton3D = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PlanePanel", function() { return PlanePanel; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PlanePanel", function() { return PlanePanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
 /* harmony import */ var _volumeBasedPanel__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./volumeBasedPanel */ "./3D/controls/volumeBasedPanel.ts");
 /* harmony import */ var _volumeBasedPanel__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./volumeBasedPanel */ "./3D/controls/volumeBasedPanel.ts");
@@ -14180,7 +14180,7 @@ var PlanePanel = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ScatterPanel", function() { return ScatterPanel; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ScatterPanel", function() { return ScatterPanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _volumeBasedPanel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./volumeBasedPanel */ "./3D/controls/volumeBasedPanel.ts");
 /* harmony import */ var _volumeBasedPanel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./volumeBasedPanel */ "./3D/controls/volumeBasedPanel.ts");
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
@@ -14307,7 +14307,7 @@ var ScatterPanel = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SpherePanel", function() { return SpherePanel; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SpherePanel", function() { return SpherePanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _volumeBasedPanel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./volumeBasedPanel */ "./3D/controls/volumeBasedPanel.ts");
 /* harmony import */ var _volumeBasedPanel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./volumeBasedPanel */ "./3D/controls/volumeBasedPanel.ts");
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
@@ -14392,7 +14392,7 @@ var SpherePanel = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StackPanel3D", function() { return StackPanel3D; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StackPanel3D", function() { return StackPanel3D; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
 
 
@@ -14517,7 +14517,7 @@ var StackPanel3D = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VolumeBasedPanel", function() { return VolumeBasedPanel; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VolumeBasedPanel", function() { return VolumeBasedPanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
 
 
@@ -14708,7 +14708,7 @@ var VolumeBasedPanel = /** @class */ (function (_super) {
 "use strict";
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "GUI3DManager", function() { return GUI3DManager; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "GUI3DManager", function() { return GUI3DManager; });
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var _controls_container3D__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./controls/container3D */ "./3D/controls/container3D.ts");
 /* harmony import */ var _controls_container3D__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./controls/container3D */ "./3D/controls/container3D.ts");
 
 
@@ -14975,7 +14975,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FluentMaterialDefines", function() { return FluentMaterialDefines; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FluentMaterialDefines", function() { return FluentMaterialDefines; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FluentMaterial", function() { return FluentMaterial; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FluentMaterial", function() { return FluentMaterial; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/decorators */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/decorators */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _shaders_fluent_vertex__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./shaders/fluent.vertex */ "./3D/materials/shaders/fluent.vertex.ts");
 /* harmony import */ var _shaders_fluent_vertex__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./shaders/fluent.vertex */ "./3D/materials/shaders/fluent.vertex.ts");
 /* harmony import */ var _shaders_fluent_fragment__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./shaders/fluent.fragment */ "./3D/materials/shaders/fluent.fragment.ts");
 /* harmony import */ var _shaders_fluent_fragment__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./shaders/fluent.fragment */ "./3D/materials/shaders/fluent.fragment.ts");
@@ -15297,7 +15297,7 @@ __webpack_require__.r(__webpack_exports__);
 "use strict";
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fluentPixelShader", function() { return fluentPixelShader; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fluentPixelShader", function() { return fluentPixelShader; });
-/* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/effect */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/effect */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__);
 
 
 var name = 'fluentPixelShader';
 var name = 'fluentPixelShader';
@@ -15319,7 +15319,7 @@ var fluentPixelShader = { name: name, shader: shader };
 "use strict";
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fluentVertexShader", function() { return fluentVertexShader; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fluentVertexShader", function() { return fluentVertexShader; });
-/* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/effect */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/effect */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__);
 
 
 var name = 'fluentVertexShader';
 var name = 'fluentVertexShader';
@@ -15342,7 +15342,7 @@ var fluentVertexShader = { name: name, shader: shader };
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Vector3WithInfo", function() { return Vector3WithInfo; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Vector3WithInfo", function() { return Vector3WithInfo; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/tools");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__);
 
 
 
 
@@ -15636,14 +15636,14 @@ if (typeof globalObject !== "undefined") {
 
 
 /***/ }),
 /***/ }),
 
 
-/***/ "babylonjs/Misc/observable":
+/***/ "babylonjs/Misc/tools":
 /*!****************************************************************************************************!*\
 /*!****************************************************************************************************!*\
   !*** external {"root":"BABYLON","commonjs":"babylonjs","commonjs2":"babylonjs","amd":"babylonjs"} ***!
   !*** external {"root":"BABYLON","commonjs":"babylonjs","commonjs2":"babylonjs","amd":"babylonjs"} ***!
   \****************************************************************************************************/
   \****************************************************************************************************/
 /*! no static exports found */
 /*! no static exports found */
 /***/ (function(module, exports) {
 /***/ (function(module, exports) {
 
 
-module.exports = __WEBPACK_EXTERNAL_MODULE_babylonjs_Misc_observable__;
+module.exports = __WEBPACK_EXTERNAL_MODULE_babylonjs_Misc_tools__;
 
 
 /***/ })
 /***/ })
 
 

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/gui/babylon.gui.js.map


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

@@ -1 +1 @@
-{"engineOnly":251860,"sceneOnly":509803,"minGridMaterial":637523,"minStandardMaterial":763222}
+{"engineOnly":251860,"sceneOnly":509803,"minGridMaterial":638044,"minStandardMaterial":763791}

+ 151 - 12
dist/preview release/viewer/babylon.module.d.ts

@@ -11097,6 +11097,23 @@ declare module "babylonjs/Materials/materialHelper" {
          * Prepares the defines related to the light information passed in parameter
          * Prepares the defines related to the light information passed in parameter
          * @param scene The scene we are intending to draw
          * @param scene The scene we are intending to draw
          * @param mesh The mesh the effect is compiling for
          * @param mesh The mesh the effect is compiling for
+         * @param light The light the effect is compiling for
+         * @param lightIndex The index of the light
+         * @param defines The defines to update
+         * @param specularSupported Specifies whether specular is supported or not (override lights data)
+         * @param state Defines the current state regarding what is needed (normals, etc...)
+         */
+        static PrepareDefinesForLight(scene: Scene, mesh: AbstractMesh, light: Light, lightIndex: number, defines: any, specularSupported: boolean, state: {
+            needNormals: boolean;
+            needRebuild: boolean;
+            shadowEnabled: boolean;
+            specularEnabled: boolean;
+            lightmapMode: boolean;
+        }): void;
+        /**
+         * Prepares the defines related to the light information passed in parameter
+         * @param scene The scene we are intending to draw
+         * @param mesh The mesh the effect is compiling for
          * @param defines The defines to update
          * @param defines The defines to update
          * @param specularSupported Specifies whether specular is supported or not (override lights data)
          * @param specularSupported Specifies whether specular is supported or not (override lights data)
          * @param maxSimultaneousLights Specfies how manuy lights can be added to the effect at max
          * @param maxSimultaneousLights Specfies how manuy lights can be added to the effect at max
@@ -11105,10 +11122,18 @@ declare module "babylonjs/Materials/materialHelper" {
          */
          */
         static PrepareDefinesForLights(scene: Scene, mesh: AbstractMesh, defines: any, specularSupported: boolean, maxSimultaneousLights?: number, disableLighting?: boolean): boolean;
         static PrepareDefinesForLights(scene: Scene, mesh: AbstractMesh, defines: any, specularSupported: boolean, maxSimultaneousLights?: number, disableLighting?: boolean): boolean;
         /**
         /**
-         * Prepares the uniforms and samplers list to be used in the effect. This can automatically remove from the list uniforms
-         * that won t be acctive due to defines being turned off.
+         * Prepares the uniforms and samplers list to be used in the effect (for a specific light)
+         * @param lightIndex defines the light index
+         * @param uniformsList The uniform list
+         * @param samplersList The sampler list
+         * @param projectedLightTexture defines if projected texture must be used
+         * @param uniformBuffersList defines an optional list of uniform buffers
+         */
+        static PrepareUniformsAndSamplersForLight(lightIndex: number, uniformsList: string[], samplersList: string[], projectedLightTexture?: any, uniformBuffersList?: Nullable<string[]>): void;
+        /**
+         * Prepares the uniforms and samplers list to be used in the effect
          * @param uniformsListOrOptions The uniform names to prepare or an EffectCreationOptions containing the liist and extra information
          * @param uniformsListOrOptions The uniform names to prepare or an EffectCreationOptions containing the liist and extra information
-         * @param samplersList The samplers list
+         * @param samplersList The sampler list
          * @param defines The defines helping in the list generation
          * @param defines The defines helping in the list generation
          * @param maxSimultaneousLights The maximum number of simultanous light allowed in the effect
          * @param maxSimultaneousLights The maximum number of simultanous light allowed in the effect
          */
          */
@@ -11166,6 +11191,17 @@ declare module "babylonjs/Materials/materialHelper" {
         static BindLightProperties(light: Light, effect: Effect, lightIndex: number): void;
         static BindLightProperties(light: Light, effect: Effect, lightIndex: number): void;
         /**
         /**
          * Binds the lights information from the scene to the effect for the given mesh.
          * Binds the lights information from the scene to the effect for the given mesh.
+         * @param light Light to bind
+         * @param lightIndex Light index
+         * @param scene The scene where the light belongs to
+         * @param mesh The mesh we are binding the information to render
+         * @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
+         */
+        static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff?: boolean): void;
+        /**
+         * Binds the lights information from the scene to the effect for the given mesh.
          * @param scene The scene the lights belongs to
          * @param scene The scene the lights belongs to
          * @param mesh The mesh we are binding the information to render
          * @param mesh The mesh we are binding the information to render
          * @param effect The effect we are binding the data to
          * @param effect The effect we are binding the data to
@@ -14048,6 +14084,10 @@ declare module "babylonjs/Physics/physicsImpostor" {
          */
          */
         static MeshImpostor: number;
         static MeshImpostor: number;
         /**
         /**
+         * Capsule-Impostor type (Ammo.js plugin only)
+         */
+        static CapsuleImpostor: number;
+        /**
          * Cylinder-Imposter type
          * Cylinder-Imposter type
          */
          */
         static CylinderImpostor: number;
         static CylinderImpostor: number;
@@ -52928,6 +52968,7 @@ declare module "babylonjs/Materials/Node/nodeMaterialBuildState" {
     import { NodeMaterialBlockConnectionPointTypes } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPointTypes";
     import { NodeMaterialBlockConnectionPointTypes } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPointTypes";
     import { NodeMaterialBlockTargets } from "babylonjs/Materials/Node/nodeMaterialBlockTargets";
     import { NodeMaterialBlockTargets } from "babylonjs/Materials/Node/nodeMaterialBlockTargets";
     import { NodeMaterialBuildStateSharedData } from "babylonjs/Materials/Node/nodeMaterialBuildStateSharedData";
     import { NodeMaterialBuildStateSharedData } from "babylonjs/Materials/Node/nodeMaterialBuildStateSharedData";
+    import { Nullable } from "babylonjs/types";
     /**
     /**
      * Class used to store node based material build state
      * Class used to store node based material build state
      */
      */
@@ -52941,6 +52982,10 @@ declare module "babylonjs/Materials/Node/nodeMaterialBuildState" {
          */
          */
         uniforms: string[];
         uniforms: string[];
         /**
         /**
+         * Gets the list of emitted uniform buffers
+         */
+        uniformBuffers: string[];
+        /**
          * Gets the list of emitted samplers
          * Gets the list of emitted samplers
          */
          */
         samplers: string[];
         samplers: string[];
@@ -52955,6 +53000,12 @@ declare module "babylonjs/Materials/Node/nodeMaterialBuildState" {
          */
          */
         target: NodeMaterialBlockTargets;
         target: NodeMaterialBlockTargets;
         /**
         /**
+         * Gets the list of emitted counters
+         */
+        counters: {
+            [key: string]: number;
+        };
+        /**
          * Shared data between multiple NodeMaterialBuildState instances
          * Shared data between multiple NodeMaterialBuildState instances
          */
          */
         sharedData: NodeMaterialBuildStateSharedData;
         sharedData: NodeMaterialBuildStateSharedData;
@@ -53008,7 +53059,7 @@ declare module "babylonjs/Materials/Node/nodeMaterialBuildState" {
             }[];
             }[];
         }): void;
         }): void;
         /** @hidden */
         /** @hidden */
-        _emitVaryings(point: NodeMaterialConnectionPoint, define?: string, force?: boolean, fromFragment?: boolean, replacementName?: string): void;
+        _emitVaryings(point: NodeMaterialConnectionPoint, define?: string, force?: boolean, fromFragment?: boolean, replacementName?: string, type?: Nullable<NodeMaterialBlockConnectionPointTypes>): void;
         private _emitDefine;
         private _emitDefine;
         /** @hidden */
         /** @hidden */
         _emitUniformOrAttributes(point: NodeMaterialConnectionPoint, define?: string): void;
         _emitUniformOrAttributes(point: NodeMaterialConnectionPoint, define?: string): void;
@@ -54115,23 +54166,44 @@ declare module "babylonjs/Materials/Node/Blocks/Fragment/lightBlock" {
     import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
     import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
     import { NodeMaterialBuildState } from "babylonjs/Materials/Node/nodeMaterialBuildState";
     import { NodeMaterialBuildState } from "babylonjs/Materials/Node/nodeMaterialBuildState";
     import { NodeMaterialConnectionPoint } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint";
     import { NodeMaterialConnectionPoint } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint";
+    import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
+    import { NodeMaterial, NodeMaterialDefines } from "babylonjs/Materials/Node/nodeMaterial";
+    import { Effect } from "babylonjs/Materials/effect";
+    import { Mesh } from "babylonjs/Meshes/mesh";
     /**
     /**
      * Block used to add light in the fragment shader
      * Block used to add light in the fragment shader
      */
      */
     export class LightBlock extends NodeMaterialBlock {
     export class LightBlock extends NodeMaterialBlock {
+        private _lightId;
         /**
         /**
          * Create a new LightBlock
          * Create a new LightBlock
          * @param name defines the block name
          * @param name defines the block name
          */
          */
         constructor(name: string);
         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 light input component
         * Gets the light input component
         */
         */
         readonly light: NodeMaterialConnectionPoint;
         readonly light: NodeMaterialConnectionPoint;
         /**
         /**
-         * Gets the output component
+         * Gets the diffuse output component
          */
          */
-        readonly output: NodeMaterialConnectionPoint;
+        readonly diffuseOutput: NodeMaterialConnectionPoint;
+        /**
+         * Gets the specular output component
+         */
+        readonly specularOutput: NodeMaterialConnectionPoint;
+        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
+        private _injectVertexCode;
         protected _buildBlock(state: NodeMaterialBuildState): this;
         protected _buildBlock(state: NodeMaterialBuildState): this;
     }
     }
 }
 }
@@ -73718,6 +73790,23 @@ declare module BABYLON {
          * Prepares the defines related to the light information passed in parameter
          * Prepares the defines related to the light information passed in parameter
          * @param scene The scene we are intending to draw
          * @param scene The scene we are intending to draw
          * @param mesh The mesh the effect is compiling for
          * @param mesh The mesh the effect is compiling for
+         * @param light The light the effect is compiling for
+         * @param lightIndex The index of the light
+         * @param defines The defines to update
+         * @param specularSupported Specifies whether specular is supported or not (override lights data)
+         * @param state Defines the current state regarding what is needed (normals, etc...)
+         */
+        static PrepareDefinesForLight(scene: Scene, mesh: AbstractMesh, light: Light, lightIndex: number, defines: any, specularSupported: boolean, state: {
+            needNormals: boolean;
+            needRebuild: boolean;
+            shadowEnabled: boolean;
+            specularEnabled: boolean;
+            lightmapMode: boolean;
+        }): void;
+        /**
+         * Prepares the defines related to the light information passed in parameter
+         * @param scene The scene we are intending to draw
+         * @param mesh The mesh the effect is compiling for
          * @param defines The defines to update
          * @param defines The defines to update
          * @param specularSupported Specifies whether specular is supported or not (override lights data)
          * @param specularSupported Specifies whether specular is supported or not (override lights data)
          * @param maxSimultaneousLights Specfies how manuy lights can be added to the effect at max
          * @param maxSimultaneousLights Specfies how manuy lights can be added to the effect at max
@@ -73726,10 +73815,18 @@ declare module BABYLON {
          */
          */
         static PrepareDefinesForLights(scene: Scene, mesh: AbstractMesh, defines: any, specularSupported: boolean, maxSimultaneousLights?: number, disableLighting?: boolean): boolean;
         static PrepareDefinesForLights(scene: Scene, mesh: AbstractMesh, defines: any, specularSupported: boolean, maxSimultaneousLights?: number, disableLighting?: boolean): boolean;
         /**
         /**
-         * Prepares the uniforms and samplers list to be used in the effect. This can automatically remove from the list uniforms
-         * that won t be acctive due to defines being turned off.
+         * Prepares the uniforms and samplers list to be used in the effect (for a specific light)
+         * @param lightIndex defines the light index
+         * @param uniformsList The uniform list
+         * @param samplersList The sampler list
+         * @param projectedLightTexture defines if projected texture must be used
+         * @param uniformBuffersList defines an optional list of uniform buffers
+         */
+        static PrepareUniformsAndSamplersForLight(lightIndex: number, uniformsList: string[], samplersList: string[], projectedLightTexture?: any, uniformBuffersList?: Nullable<string[]>): void;
+        /**
+         * Prepares the uniforms and samplers list to be used in the effect
          * @param uniformsListOrOptions The uniform names to prepare or an EffectCreationOptions containing the liist and extra information
          * @param uniformsListOrOptions The uniform names to prepare or an EffectCreationOptions containing the liist and extra information
-         * @param samplersList The samplers list
+         * @param samplersList The sampler list
          * @param defines The defines helping in the list generation
          * @param defines The defines helping in the list generation
          * @param maxSimultaneousLights The maximum number of simultanous light allowed in the effect
          * @param maxSimultaneousLights The maximum number of simultanous light allowed in the effect
          */
          */
@@ -73787,6 +73884,17 @@ declare module BABYLON {
         static BindLightProperties(light: Light, effect: Effect, lightIndex: number): void;
         static BindLightProperties(light: Light, effect: Effect, lightIndex: number): void;
         /**
         /**
          * Binds the lights information from the scene to the effect for the given mesh.
          * Binds the lights information from the scene to the effect for the given mesh.
+         * @param light Light to bind
+         * @param lightIndex Light index
+         * @param scene The scene where the light belongs to
+         * @param mesh The mesh we are binding the information to render
+         * @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
+         */
+        static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff?: boolean): void;
+        /**
+         * Binds the lights information from the scene to the effect for the given mesh.
          * @param scene The scene the lights belongs to
          * @param scene The scene the lights belongs to
          * @param mesh The mesh we are binding the information to render
          * @param mesh The mesh we are binding the information to render
          * @param effect The effect we are binding the data to
          * @param effect The effect we are binding the data to
@@ -76583,6 +76691,10 @@ declare module BABYLON {
          */
          */
         static MeshImpostor: number;
         static MeshImpostor: number;
         /**
         /**
+         * Capsule-Impostor type (Ammo.js plugin only)
+         */
+        static CapsuleImpostor: number;
+        /**
          * Cylinder-Imposter type
          * Cylinder-Imposter type
          */
          */
         static CylinderImpostor: number;
         static CylinderImpostor: number;
@@ -113473,6 +113585,10 @@ declare module BABYLON {
          */
          */
         uniforms: string[];
         uniforms: string[];
         /**
         /**
+         * Gets the list of emitted uniform buffers
+         */
+        uniformBuffers: string[];
+        /**
          * Gets the list of emitted samplers
          * Gets the list of emitted samplers
          */
          */
         samplers: string[];
         samplers: string[];
@@ -113487,6 +113603,12 @@ declare module BABYLON {
          */
          */
         target: NodeMaterialBlockTargets;
         target: NodeMaterialBlockTargets;
         /**
         /**
+         * Gets the list of emitted counters
+         */
+        counters: {
+            [key: string]: number;
+        };
+        /**
          * Shared data between multiple NodeMaterialBuildState instances
          * Shared data between multiple NodeMaterialBuildState instances
          */
          */
         sharedData: NodeMaterialBuildStateSharedData;
         sharedData: NodeMaterialBuildStateSharedData;
@@ -113540,7 +113662,7 @@ declare module BABYLON {
             }[];
             }[];
         }): void;
         }): void;
         /** @hidden */
         /** @hidden */
-        _emitVaryings(point: NodeMaterialConnectionPoint, define?: string, force?: boolean, fromFragment?: boolean, replacementName?: string): void;
+        _emitVaryings(point: NodeMaterialConnectionPoint, define?: string, force?: boolean, fromFragment?: boolean, replacementName?: string, type?: Nullable<NodeMaterialBlockConnectionPointTypes>): void;
         private _emitDefine;
         private _emitDefine;
         /** @hidden */
         /** @hidden */
         _emitUniformOrAttributes(point: NodeMaterialConnectionPoint, define?: string): void;
         _emitUniformOrAttributes(point: NodeMaterialConnectionPoint, define?: string): void;
@@ -114556,19 +114678,36 @@ declare module BABYLON {
      * Block used to add light in the fragment shader
      * Block used to add light in the fragment shader
      */
      */
     export class LightBlock extends NodeMaterialBlock {
     export class LightBlock extends NodeMaterialBlock {
+        private _lightId;
         /**
         /**
          * Create a new LightBlock
          * Create a new LightBlock
          * @param name defines the block name
          * @param name defines the block name
          */
          */
         constructor(name: string);
         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 light input component
         * Gets the light input component
         */
         */
         readonly light: NodeMaterialConnectionPoint;
         readonly light: NodeMaterialConnectionPoint;
         /**
         /**
-         * Gets the output component
+         * Gets the diffuse output component
          */
          */
-        readonly output: NodeMaterialConnectionPoint;
+        readonly diffuseOutput: NodeMaterialConnectionPoint;
+        /**
+         * Gets the specular output component
+         */
+        readonly specularOutput: NodeMaterialConnectionPoint;
+        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
+        private _injectVertexCode;
         protected _buildBlock(state: NodeMaterialBuildState): this;
         protected _buildBlock(state: NodeMaterialBuildState): this;
     }
     }
 }
 }

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 17 - 17
dist/preview release/viewer/babylon.viewer.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
dist/preview release/viewer/babylon.viewer.max.js


+ 2 - 0
src/Materials/Node/Blocks/Dual/fogBlock.ts

@@ -119,6 +119,8 @@ export class FogBlock extends NodeMaterialBlock {
         state.sharedData.blocksWithDefines.push(this);
         state.sharedData.blocksWithDefines.push(this);
 
 
         if (state.target === NodeMaterialBlockTargets.Fragment) {
         if (state.target === NodeMaterialBlockTargets.Fragment) {
+            state.sharedData.bindableBlocks.push(this);
+
             state._emitFunctionFromInclude("fogFragmentDeclaration", `//${this.name}`, {
             state._emitFunctionFromInclude("fogFragmentDeclaration", `//${this.name}`, {
                 removeUniforms: true,
                 removeUniforms: true,
                 removeVaryings: true,
                 removeVaryings: true,

+ 114 - 6
src/Materials/Node/Blocks/Fragment/lightBlock.ts

@@ -3,11 +3,18 @@ import { NodeMaterialBlockTargets } from '../../nodeMaterialBlockTargets';
 import { NodeMaterialBlockConnectionPointTypes } from '../../nodeMaterialBlockConnectionPointTypes';
 import { NodeMaterialBlockConnectionPointTypes } from '../../nodeMaterialBlockConnectionPointTypes';
 import { NodeMaterialBuildState } from '../../nodeMaterialBuildState';
 import { NodeMaterialBuildState } from '../../nodeMaterialBuildState';
 import { NodeMaterialConnectionPoint } from '../../nodeMaterialBlockConnectionPoint';
 import { NodeMaterialConnectionPoint } from '../../nodeMaterialBlockConnectionPoint';
+import { MaterialHelper } from '../../../materialHelper';
+import { AbstractMesh } from '../../../../Meshes/abstractMesh';
+import { NodeMaterial, NodeMaterialDefines } from '../../nodeMaterial';
+import { Effect } from '../../../../Materials/effect';
+import { Mesh } from '../../../../Meshes/mesh';
 
 
 /**
 /**
  * Block used to add light in the fragment shader
  * Block used to add light in the fragment shader
  */
  */
 export class LightBlock extends NodeMaterialBlock {
 export class LightBlock extends NodeMaterialBlock {
+    private _lightId: number;
+
     /**
     /**
      * Create a new LightBlock
      * Create a new LightBlock
      * @param name defines the block name
      * @param name defines the block name
@@ -15,29 +22,130 @@ export class LightBlock extends NodeMaterialBlock {
     public constructor(name: string) {
     public constructor(name: string) {
         super(name, NodeMaterialBlockTargets.Fragment);
         super(name, NodeMaterialBlockTargets.Fragment);
 
 
+        this.registerInput("worldPosition", NodeMaterialBlockConnectionPointTypes.Vector4);
         this.registerInput("light", NodeMaterialBlockConnectionPointTypes.Light);
         this.registerInput("light", NodeMaterialBlockConnectionPointTypes.Light);
-        this.registerOutput("output", NodeMaterialBlockConnectionPointTypes.Float);
+        this.registerOutput("diffuseOutput", NodeMaterialBlockConnectionPointTypes.Color3);
+        this.registerOutput("specularOutput", NodeMaterialBlockConnectionPointTypes.Color3);
+    }
+
+    /**
+     * Gets the current class name
+     * @returns the class name
+     */
+    public getClassName() {
+        return "LightBlock";
+    }
+
+    /**
+     * Gets the world position input component
+     */
+    public get worldPosition(): NodeMaterialConnectionPoint {
+        return this._inputs[0];
     }
     }
 
 
     /**
     /**
     * Gets the light input component
     * Gets the light input component
     */
     */
     public get light(): NodeMaterialConnectionPoint {
     public get light(): NodeMaterialConnectionPoint {
-        return this._inputs[0];
+        return this._inputs[1];
     }
     }
 
 
     /**
     /**
-     * Gets the output component
+     * Gets the diffuse output component
      */
      */
-    public get output(): NodeMaterialConnectionPoint {
+    public get diffuseOutput(): NodeMaterialConnectionPoint {
         return this._outputs[0];
         return this._outputs[0];
     }
     }
 
 
+    /**
+     * Gets the specular output component
+     */
+    public get specularOutput(): NodeMaterialConnectionPoint {
+        return this._outputs[1];
+    }
+
+    public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
+        if (!this.light.value) {
+            return;
+        }
+
+        let state = {
+            needNormals: false,
+            needRebuild: false,
+            lightmapMode: false,
+            shadowEnabled: false,
+            specularEnabled: false
+        };
+
+        MaterialHelper.PrepareDefinesForLight(mesh.getScene(), mesh, this.light.value, this._lightId, defines, true, state);
+    }
+
+    public bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh) {
+        if (!mesh || !this.light.value) {
+            return;
+        }
+
+        MaterialHelper.BindLight(this.light.value, this._lightId, mesh.getScene(), mesh, effect, true, false);
+    }
+
+    private _injectVertexCode(state: NodeMaterialBuildState) {
+        let worldPos = this.worldPosition;
+
+        // Inject code in vertex
+        let varyingName = "v_" + worldPos.associatedVariableName;
+        state._emitVaryings(worldPos, undefined, true, false, varyingName, NodeMaterialBlockConnectionPointTypes.Vector3);
+
+        state.compilationString += `${varyingName} = ${worldPos.associatedVariableName}.xyz;\r\n`;
+    }
+
     protected _buildBlock(state: NodeMaterialBuildState) {
     protected _buildBlock(state: NodeMaterialBuildState) {
         super._buildBlock(state);
         super._buildBlock(state);
 
 
-        state._emitFunctionFromInclude("lightFragmentDeclaration", `//${this.name}`, {
-            replaceStrings: [{ search: /{X}/g, replace: "1" }]
+        // Vertex
+        this._injectVertexCode(state._vertexState);
+
+        // Fragment
+        state.sharedData.bindableBlocks.push(this);
+        state.sharedData.blocksWithDefines.push(this);
+
+        this._lightId = (state.counters["lightCounter"] | -1) + 1;
+        state.counters["lightCounter"] = this._lightId;
+
+        let comments = `//${this.name}`;
+        let worldPos = this.worldPosition;
+
+        state._emitFunctionFromInclude("lightsFragmentFunctions", comments, {
+            replaceStrings: [{ search: /vPositionW/g, replace: "v_" + worldPos.associatedVariableName }]
+        });
+
+        state._emitFunctionFromInclude("lightFragmentDeclaration", comments, {
+            replaceStrings: [{ search: /{X}/g, replace: this._lightId.toString() }]
+        });
+
+        // Uniforms and samplers
+        MaterialHelper.PrepareUniformsAndSamplersForLight(this._lightId, state.uniforms, state.samplers, undefined, state.uniformBuffers);
+
+        // Code
+        if (this._lightId === 0) {
+            state.compilationString += `lightingInfo info;\r\n`;
+            state.compilationString += `float shadow = 1.;\r\n`;
+            state.compilationString += `float glossiness = 0.;\r\n`;
+        }
+
+        let diffuseOutput = this.diffuseOutput;
+        let specularOutput = this.specularOutput;
+
+        state.compilationString += `vec3 ${diffuseOutput.associatedVariableName} = vec3(0., 0., 0.);\r\n`;
+        state.compilationString += `#ifdef SPECULARTERM\r\n`;
+        state.compilationString += `vec3 ${specularOutput.associatedVariableName} = vec3(0., 0., 0.);\r\n`;
+        state.compilationString += `#endif\r\n`;
+
+        state.compilationString += state._emitCodeFromInclude("lightFragment", comments, {
+            replaceStrings: [
+                { search: /{X}/g, replace: this._lightId.toString() },
+                { search: /diffuseBase/g, replace: diffuseOutput.associatedVariableName },
+                { search: /specularBase/g, replace: specularOutput.associatedVariableName },
+            ]
         });
         });
 
 
         return this;
         return this;

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

@@ -576,6 +576,17 @@ export class NodeMaterial extends PushMaterial {
                 }
                 }
             });
             });
 
 
+            // Uniform buffers
+            let mergedUniformBuffers = this._vertexCompilationState.uniformBuffers;
+
+            this._fragmentCompilationState.uniformBuffers.forEach((u) => {
+                let index = mergedUniformBuffers.indexOf(u);
+
+                if (index === -1) {
+                    mergedUniformBuffers.push(u);
+                }
+            });
+
             // Samplers
             // Samplers
             let mergedSamplers = this._vertexCompilationState.samplers;
             let mergedSamplers = this._vertexCompilationState.samplers;
 
 
@@ -604,6 +615,7 @@ export class NodeMaterial extends PushMaterial {
             }, <EffectCreationOptions>{
             }, <EffectCreationOptions>{
                 attributes: this._vertexCompilationState.attributes,
                 attributes: this._vertexCompilationState.attributes,
                 uniformsNames: mergedUniforms,
                 uniformsNames: mergedUniforms,
+                uniformBuffersNames: mergedUniformBuffers,
                 samplers: mergedSamplers,
                 samplers: mergedSamplers,
                 defines: join,
                 defines: join,
                 fallbacks: fallbacks,
                 fallbacks: fallbacks,

+ 11 - 2
src/Materials/Node/nodeMaterialBuildState.ts

@@ -4,6 +4,7 @@ import { NodeMaterialWellKnownValues } from './nodeMaterialWellKnownValues';
 import { NodeMaterialBlockTargets } from './nodeMaterialBlockTargets';
 import { NodeMaterialBlockTargets } from './nodeMaterialBlockTargets';
 import { NodeMaterialBuildStateSharedData } from './nodeMaterialBuildStateSharedData';
 import { NodeMaterialBuildStateSharedData } from './nodeMaterialBuildStateSharedData';
 import { Effect } from '../effect';
 import { Effect } from '../effect';
+import { Nullable } from '../../types';
 
 
 /**
 /**
  * Class used to store node based material build state
  * Class used to store node based material build state
@@ -18,6 +19,10 @@ export class NodeMaterialBuildState {
      */
      */
     public uniforms = new Array<string>();
     public uniforms = new Array<string>();
     /**
     /**
+     * Gets the list of emitted uniform buffers
+     */
+    public uniformBuffers = new Array<string>();
+    /**
      * Gets the list of emitted samplers
      * Gets the list of emitted samplers
      */
      */
     public samplers = new Array<string>();
     public samplers = new Array<string>();
@@ -29,6 +34,10 @@ export class NodeMaterialBuildState {
      * Gets the target of the compilation state
      * Gets the target of the compilation state
      */
      */
     public target: NodeMaterialBlockTargets;
     public target: NodeMaterialBlockTargets;
+    /**
+     * Gets the list of emitted counters
+     */
+    public counters: { [key: string]: number } = {};
 
 
     /**
     /**
      * Shared data between multiple NodeMaterialBuildState instances
      * Shared data between multiple NodeMaterialBuildState instances
@@ -261,7 +270,7 @@ export class NodeMaterialBuildState {
     }
     }
 
 
     /** @hidden */
     /** @hidden */
-    public _emitVaryings(point: NodeMaterialConnectionPoint, define: string = "", force = false, fromFragment = false, replacementName: string = "") {
+    public _emitVaryings(point: NodeMaterialConnectionPoint, define: string = "", force = false, fromFragment = false, replacementName: string = "", type: Nullable<NodeMaterialBlockConnectionPointTypes> = null) {
         let name = replacementName || point.associatedVariableName;
         let name = replacementName || point.associatedVariableName;
         if (point.isVarying || force) {
         if (point.isVarying || force) {
             if (this.sharedData.varyings.indexOf(name) !== -1) {
             if (this.sharedData.varyings.indexOf(name) !== -1) {
@@ -273,7 +282,7 @@ export class NodeMaterialBuildState {
             if (define) {
             if (define) {
                 this.sharedData.varyingDeclaration += `#ifdef ${define}\r\n`;
                 this.sharedData.varyingDeclaration += `#ifdef ${define}\r\n`;
             }
             }
-            this.sharedData.varyingDeclaration += `varying ${this._getGLType(point.type)} ${name};\r\n`;
+            this.sharedData.varyingDeclaration += `varying ${this._getGLType(type || point.type)} ${name};\r\n`;
             if (define) {
             if (define) {
                 this.sharedData.varyingDeclaration += `#endif\r\n`;
                 this.sharedData.varyingDeclaration += `#endif\r\n`;
             }
             }

+ 174 - 128
src/Materials/materialHelper.ts

@@ -276,6 +276,93 @@ export class MaterialHelper {
      * Prepares the defines related to the light information passed in parameter
      * Prepares the defines related to the light information passed in parameter
      * @param scene The scene we are intending to draw
      * @param scene The scene we are intending to draw
      * @param mesh The mesh the effect is compiling for
      * @param mesh The mesh the effect is compiling for
+     * @param light The light the effect is compiling for
+     * @param lightIndex The index of the light
+     * @param defines The defines to update
+     * @param specularSupported Specifies whether specular is supported or not (override lights data)
+     * @param state Defines the current state regarding what is needed (normals, etc...)
+     */
+    public static PrepareDefinesForLight(scene: Scene, mesh: AbstractMesh, light: Light, lightIndex: number, defines: any, specularSupported: boolean, state: {
+        needNormals: boolean,
+        needRebuild: boolean,
+        shadowEnabled: boolean,
+        specularEnabled: boolean,
+        lightmapMode: boolean
+    }) {
+        state.needNormals = true;
+
+        if (defines["LIGHT" + lightIndex] === undefined) {
+            state.needRebuild = true;
+        }
+
+        defines["LIGHT" + lightIndex] = true;
+
+        defines["SPOTLIGHT" + lightIndex] = false;
+        defines["HEMILIGHT" + lightIndex] = false;
+        defines["POINTLIGHT" + lightIndex] = false;
+        defines["DIRLIGHT" + lightIndex] = false;
+
+        light.prepareLightSpecificDefines(defines, lightIndex);
+
+        // FallOff.
+        defines["LIGHT_FALLOFF_PHYSICAL" + lightIndex] = false;
+        defines["LIGHT_FALLOFF_GLTF" + lightIndex] = false;
+        defines["LIGHT_FALLOFF_STANDARD" + lightIndex] = false;
+
+        switch (light.falloffType) {
+            case Light.FALLOFF_GLTF:
+                defines["LIGHT_FALLOFF_GLTF" + lightIndex] = true;
+                break;
+            case Light.FALLOFF_PHYSICAL:
+                defines["LIGHT_FALLOFF_PHYSICAL" + lightIndex] = true;
+                break;
+            case Light.FALLOFF_STANDARD:
+                defines["LIGHT_FALLOFF_STANDARD" + lightIndex] = true;
+                break;
+        }
+
+        // Specular
+        if (specularSupported && !light.specular.equalsFloats(0, 0, 0)) {
+            state.specularEnabled = true;
+        }
+
+        // Shadows
+        defines["SHADOW" + lightIndex] = false;
+        defines["SHADOWPCF" + lightIndex] = false;
+        defines["SHADOWPCSS" + lightIndex] = false;
+        defines["SHADOWPOISSON" + lightIndex] = false;
+        defines["SHADOWESM" + lightIndex] = false;
+        defines["SHADOWCUBE" + lightIndex] = false;
+        defines["SHADOWLOWQUALITY" + lightIndex] = false;
+        defines["SHADOWMEDIUMQUALITY" + lightIndex] = false;
+
+        if (mesh && mesh.receiveShadows && scene.shadowsEnabled && light.shadowEnabled) {
+            var shadowGenerator = light.getShadowGenerator();
+            if (shadowGenerator) {
+                const shadowMap = shadowGenerator.getShadowMap();
+                if (shadowMap) {
+                    if (shadowMap.renderList && shadowMap.renderList.length > 0) {
+                        state.shadowEnabled = true;
+                        shadowGenerator.prepareDefines(defines, lightIndex);
+                    }
+                }
+            }
+        }
+
+        if (light.lightmapMode != Light.LIGHTMAP_DEFAULT) {
+            state.lightmapMode = true;
+            defines["LIGHTMAPEXCLUDED" + lightIndex] = true;
+            defines["LIGHTMAPNOSPECULAR" + lightIndex] = (light.lightmapMode == Light.LIGHTMAP_SHADOWSONLY);
+        } else {
+            defines["LIGHTMAPEXCLUDED" + lightIndex] = false;
+            defines["LIGHTMAPNOSPECULAR" + lightIndex] = false;
+        }
+    }
+
+    /**
+     * Prepares the defines related to the light information passed in parameter
+     * @param scene The scene we are intending to draw
+     * @param mesh The mesh the effect is compiling for
      * @param defines The defines to update
      * @param defines The defines to update
      * @param specularSupported Specifies whether specular is supported or not (override lights data)
      * @param specularSupported Specifies whether specular is supported or not (override lights data)
      * @param maxSimultaneousLights Specfies how manuy lights can be added to the effect at max
      * @param maxSimultaneousLights Specfies how manuy lights can be added to the effect at max
@@ -288,82 +375,17 @@ export class MaterialHelper {
         }
         }
 
 
         var lightIndex = 0;
         var lightIndex = 0;
-        var needNormals = false;
-        var needRebuild = false;
-        var lightmapMode = false;
-        var shadowEnabled = false;
-        var specularEnabled = false;
+        let state = {
+            needNormals: false,
+            needRebuild: false,
+            lightmapMode: false,
+            shadowEnabled: false,
+            specularEnabled: false
+        };
 
 
         if (scene.lightsEnabled && !disableLighting) {
         if (scene.lightsEnabled && !disableLighting) {
             for (var light of mesh.lightSources) {
             for (var light of mesh.lightSources) {
-                needNormals = true;
-
-                if (defines["LIGHT" + lightIndex] === undefined) {
-                    needRebuild = true;
-                }
-
-                defines["LIGHT" + lightIndex] = true;
-
-                defines["SPOTLIGHT" + lightIndex] = false;
-                defines["HEMILIGHT" + lightIndex] = false;
-                defines["POINTLIGHT" + lightIndex] = false;
-                defines["DIRLIGHT" + lightIndex] = false;
-
-                light.prepareLightSpecificDefines(defines, lightIndex);
-
-                // FallOff.
-                defines["LIGHT_FALLOFF_PHYSICAL" + lightIndex] = false;
-                defines["LIGHT_FALLOFF_GLTF" + lightIndex] = false;
-                defines["LIGHT_FALLOFF_STANDARD" + lightIndex] = false;
-
-                switch (light.falloffType) {
-                    case Light.FALLOFF_GLTF:
-                        defines["LIGHT_FALLOFF_GLTF" + lightIndex] = true;
-                        break;
-                    case Light.FALLOFF_PHYSICAL:
-                        defines["LIGHT_FALLOFF_PHYSICAL" + lightIndex] = true;
-                        break;
-                    case Light.FALLOFF_STANDARD:
-                        defines["LIGHT_FALLOFF_STANDARD" + lightIndex] = true;
-                        break;
-                }
-
-                // Specular
-                if (specularSupported && !light.specular.equalsFloats(0, 0, 0)) {
-                    specularEnabled = true;
-                }
-
-                // Shadows
-                defines["SHADOW" + lightIndex] = false;
-                defines["SHADOWPCF" + lightIndex] = false;
-                defines["SHADOWPCSS" + lightIndex] = false;
-                defines["SHADOWPOISSON" + lightIndex] = false;
-                defines["SHADOWESM" + lightIndex] = false;
-                defines["SHADOWCUBE" + lightIndex] = false;
-                defines["SHADOWLOWQUALITY" + lightIndex] = false;
-                defines["SHADOWMEDIUMQUALITY" + lightIndex] = false;
-
-                if (mesh && mesh.receiveShadows && scene.shadowsEnabled && light.shadowEnabled) {
-                    var shadowGenerator = light.getShadowGenerator();
-                    if (shadowGenerator) {
-                        const shadowMap = shadowGenerator.getShadowMap();
-                        if (shadowMap) {
-                            if (shadowMap.renderList && shadowMap.renderList.length > 0) {
-                                shadowEnabled = true;
-                                shadowGenerator.prepareDefines(defines, lightIndex);
-                            }
-                        }
-                    }
-                }
-
-                if (light.lightmapMode != Light.LIGHTMAP_DEFAULT) {
-                    lightmapMode = true;
-                    defines["LIGHTMAPEXCLUDED" + lightIndex] = true;
-                    defines["LIGHTMAPNOSPECULAR" + lightIndex] = (light.lightmapMode == Light.LIGHTMAP_SHADOWSONLY);
-                } else {
-                    defines["LIGHTMAPEXCLUDED" + lightIndex] = false;
-                    defines["LIGHTMAPNOSPECULAR" + lightIndex] = false;
-                }
+                this.PrepareDefinesForLight(scene, mesh, light, lightIndex, defines, specularSupported, state);
 
 
                 lightIndex++;
                 lightIndex++;
                 if (lightIndex === maxSimultaneousLights) {
                 if (lightIndex === maxSimultaneousLights) {
@@ -372,8 +394,8 @@ export class MaterialHelper {
             }
             }
         }
         }
 
 
-        defines["SPECULARTERM"] = specularEnabled;
-        defines["SHADOWS"] = shadowEnabled;
+        defines["SPECULARTERM"] = state.specularEnabled;
+        defines["SHADOWS"] = state.shadowEnabled;
 
 
         // Resetting all other lights if any
         // Resetting all other lights if any
         for (var index = lightIndex; index < maxSimultaneousLights; index++) {
         for (var index = lightIndex; index < maxSimultaneousLights; index++) {
@@ -397,26 +419,61 @@ export class MaterialHelper {
         let caps = scene.getEngine().getCaps();
         let caps = scene.getEngine().getCaps();
 
 
         if (defines["SHADOWFLOAT"] === undefined) {
         if (defines["SHADOWFLOAT"] === undefined) {
-            needRebuild = true;
+            state.needRebuild = true;
         }
         }
 
 
-        defines["SHADOWFLOAT"] = shadowEnabled &&
+        defines["SHADOWFLOAT"] = state.shadowEnabled &&
             ((caps.textureFloatRender && caps.textureFloatLinearFiltering) ||
             ((caps.textureFloatRender && caps.textureFloatLinearFiltering) ||
                 (caps.textureHalfFloatRender && caps.textureHalfFloatLinearFiltering));
                 (caps.textureHalfFloatRender && caps.textureHalfFloatLinearFiltering));
-        defines["LIGHTMAPEXCLUDED"] = lightmapMode;
+        defines["LIGHTMAPEXCLUDED"] = state.lightmapMode;
 
 
-        if (needRebuild) {
+        if (state.needRebuild) {
             defines.rebuild();
             defines.rebuild();
         }
         }
 
 
-        return needNormals;
+        return state.needNormals;
+    }
+
+    /**
+     * Prepares the uniforms and samplers list to be used in the effect (for a specific light)
+     * @param lightIndex defines the light index
+     * @param uniformsList The uniform list
+     * @param samplersList The sampler list
+     * @param projectedLightTexture defines if projected texture must be used
+     * @param uniformBuffersList defines an optional list of uniform buffers
+     */
+    public static PrepareUniformsAndSamplersForLight(lightIndex: number, uniformsList: string[], samplersList: string[], projectedLightTexture?: any, uniformBuffersList: Nullable<string[]> = null) {
+        uniformsList.push(
+            "vLightData" + lightIndex,
+            "vLightDiffuse" + lightIndex,
+            "vLightSpecular" + lightIndex,
+            "vLightDirection" + lightIndex,
+            "vLightFalloff" + lightIndex,
+            "vLightGround" + lightIndex,
+            "lightMatrix" + lightIndex,
+            "shadowsInfo" + lightIndex,
+            "depthValues" + lightIndex,
+        );
+
+        if (uniformBuffersList) {
+            uniformBuffersList.push("Light" + lightIndex);
+        }
+
+        samplersList.push("shadowSampler" + lightIndex);
+        samplersList.push("depthSampler" + lightIndex);
+
+        if (projectedLightTexture) {
+            samplersList.push("projectionLightSampler" + lightIndex);
+            uniformsList.push(
+                "textureProjectionMatrix" + lightIndex,
+            );
+        }
     }
     }
 
 
     /**
     /**
-     * Prepares the uniforms and samplers list to be used in the effect. This can automatically remove from the list uniforms
-     * that won t be acctive due to defines being turned off.
+     * Prepares the uniforms and samplers list to be used in the effect
      * @param uniformsListOrOptions The uniform names to prepare or an EffectCreationOptions containing the liist and extra information
      * @param uniformsListOrOptions The uniform names to prepare or an EffectCreationOptions containing the liist and extra information
-     * @param samplersList The samplers list
+     * @param samplersList The sampler list
      * @param defines The defines helping in the list generation
      * @param defines The defines helping in the list generation
      * @param maxSimultaneousLights The maximum number of simultanous light allowed in the effect
      * @param maxSimultaneousLights The maximum number of simultanous light allowed in the effect
      */
      */
@@ -442,32 +499,7 @@ export class MaterialHelper {
             if (!defines["LIGHT" + lightIndex]) {
             if (!defines["LIGHT" + lightIndex]) {
                 break;
                 break;
             }
             }
-
-            uniformsList.push(
-                "vLightData" + lightIndex,
-                "vLightDiffuse" + lightIndex,
-                "vLightSpecular" + lightIndex,
-                "vLightDirection" + lightIndex,
-                "vLightFalloff" + lightIndex,
-                "vLightGround" + lightIndex,
-                "lightMatrix" + lightIndex,
-                "shadowsInfo" + lightIndex,
-                "depthValues" + lightIndex,
-            );
-
-            if (uniformBuffersList) {
-                uniformBuffersList.push("Light" + lightIndex);
-            }
-
-            samplersList.push("shadowSampler" + lightIndex);
-            samplersList.push("depthSampler" + lightIndex);
-
-            if (defines["PROJECTEDLIGHTTEXTURE" + lightIndex]) {
-                samplersList.push("projectionLightSampler" + lightIndex);
-                uniformsList.push(
-                    "textureProjectionMatrix" + lightIndex,
-                );
-            }
+            this.PrepareUniformsAndSamplersForLight(lightIndex, uniformsList, samplersList, defines["PROJECTEDLIGHTTEXTURE" + lightIndex], uniformBuffersList);
         }
         }
 
 
         if (defines["NUM_MORPH_INFLUENCERS"]) {
         if (defines["NUM_MORPH_INFLUENCERS"]) {
@@ -623,6 +655,38 @@ export class MaterialHelper {
 
 
     /**
     /**
      * Binds the lights information from the scene to the effect for the given mesh.
      * Binds the lights information from the scene to the effect for the given mesh.
+     * @param light Light to bind
+     * @param lightIndex Light index
+     * @param scene The scene where the light belongs to
+     * @param mesh The mesh we are binding the information to render
+     * @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
+     */
+    public static BindLight(light: Light, lightIndex: number, scene: Scene, mesh: AbstractMesh, effect: Effect, useSpecular: boolean, usePhysicalLightFalloff = false): void {
+        let iAsString = lightIndex.toString();
+
+        let scaledIntensity = light.getScaledIntensity();
+        light._uniformBuffer.bindToEffect(effect, "Light" + iAsString);
+
+        MaterialHelper.BindLightProperties(light, effect, lightIndex);
+
+        light.diffuse.scaleToRef(scaledIntensity, Tmp.Color3[0]);
+        light._uniformBuffer.updateColor4("vLightDiffuse", Tmp.Color3[0], usePhysicalLightFalloff ? light.radius : light.range, iAsString);
+        if (useSpecular) {
+            light.specular.scaleToRef(scaledIntensity, Tmp.Color3[1]);
+            light._uniformBuffer.updateColor3("vLightSpecular", Tmp.Color3[1], iAsString);
+        }
+
+        // Shadows
+        if (scene.shadowsEnabled) {
+            this.BindLightShadow(light, mesh, iAsString, effect);
+        }
+        light._uniformBuffer.update();
+    }
+
+    /**
+     * Binds the lights information from the scene to the effect for the given mesh.
      * @param scene The scene the lights belongs to
      * @param scene The scene the lights belongs to
      * @param mesh The mesh we are binding the information to render
      * @param mesh The mesh we are binding the information to render
      * @param effect The effect we are binding the data to
      * @param effect The effect we are binding the data to
@@ -636,25 +700,7 @@ export class MaterialHelper {
         for (var i = 0; i < len; i++) {
         for (var i = 0; i < len; i++) {
 
 
             let light = mesh.lightSources[i];
             let light = mesh.lightSources[i];
-            let iAsString = i.toString();
-
-            let scaledIntensity = light.getScaledIntensity();
-            light._uniformBuffer.bindToEffect(effect, "Light" + i);
-
-            MaterialHelper.BindLightProperties(light, effect, i);
-
-            light.diffuse.scaleToRef(scaledIntensity, Tmp.Color3[0]);
-            light._uniformBuffer.updateColor4("vLightDiffuse", Tmp.Color3[0], usePhysicalLightFalloff ? light.radius : light.range, iAsString);
-            if (defines["SPECULARTERM"]) {
-                light.specular.scaleToRef(scaledIntensity, Tmp.Color3[1]);
-                light._uniformBuffer.updateColor3("vLightSpecular", Tmp.Color3[1], iAsString);
-            }
-
-            // Shadows
-            if (scene.shadowsEnabled) {
-                this.BindLightShadow(light, mesh, iAsString, effect);
-            }
-            light._uniformBuffer.update();
+            this.BindLight(light, i, scene, mesh, effect, defines, usePhysicalLightFalloff);
         }
         }
     }
     }