Просмотр исходного кода

Merge branch 'master' of https://github.com/BabylonJS/Babylon.js into fix-frame-bugs

Kyle Belfort 5 лет назад
Родитель
Сommit
4fb4214deb
42 измененных файлов с 1968 добавлено и 549 удалено
  1. 1 0
      Tools/Gulp/helpers/gulp-processShaders.js
  2. 175 27
      dist/preview release/babylon.d.ts
  3. 2 2
      dist/preview release/babylon.js
  4. 367 56
      dist/preview release/babylon.module.d.ts
  5. 183 29
      dist/preview release/documentation.d.ts
  6. 2 0
      dist/preview release/gui/babylon.gui.d.ts
  7. 1 1
      dist/preview release/gui/babylon.gui.min.js
  8. 4 0
      dist/preview release/gui/babylon.gui.module.d.ts
  9. 2 2
      dist/preview release/materialsLibrary/babylon.customMaterial.min.js
  10. 6 2
      dist/preview release/materialsLibrary/babylonjs.materials.d.ts
  11. 1 1
      dist/preview release/materialsLibrary/babylonjs.materials.min.js
  12. 14 6
      dist/preview release/materialsLibrary/babylonjs.materials.module.d.ts
  13. 1 1
      dist/preview release/packagesSizeBaseLine.json
  14. 367 56
      dist/preview release/viewer/babylon.module.d.ts
  15. 1 0
      dist/preview release/what's new.md
  16. 13 1
      gui/src/2D/controls/scrollViewers/scrollViewer.ts
  17. 15 6
      materialsLibrary/src/custom/customMaterial.ts
  18. 14 5
      materialsLibrary/src/custom/pbrCustomMaterial.ts
  19. 2 0
      src/Culling/ray.ts
  20. 8 1
      src/Engines/Processors/shaderProcessor.ts
  21. 2 2
      src/Engines/thinEngine.ts
  22. 13 5
      src/Lights/Shadows/cascadedShadowGenerator.ts
  23. 218 180
      src/Lights/Shadows/shadowGenerator.ts
  24. 9 0
      src/Materials/Node/nodeMaterial.ts
  25. 13 5
      src/Materials/PBR/pbrBaseMaterial.ts
  26. 42 1
      src/Materials/effect.ts
  27. 2 1
      src/Materials/index.ts
  28. 28 0
      src/Materials/material.ts
  29. 93 48
      src/Materials/shaderMaterial.ts
  30. 234 0
      src/Materials/shadowDepthWrapper.ts
  31. 9 6
      src/Materials/standardMaterial.ts
  32. 3 1
      src/Meshes/subMesh.ts
  33. 2 0
      src/Meshes/transformNode.ts
  34. 22 0
      src/Shaders/ShadersInclude/shadowMapFragment.fx
  35. 17 0
      src/Shaders/ShadersInclude/shadowMapFragmentDeclaration.fx
  36. 16 0
      src/Shaders/ShadersInclude/shadowMapVertexDeclaration.fx
  37. 16 0
      src/Shaders/ShadersInclude/shadowMapVertexMetric.fx
  38. 15 0
      src/Shaders/ShadersInclude/shadowMapVertexNormalBias.fx
  39. 12 10
      src/Shaders/default.vertex.fx
  40. 12 10
      src/Shaders/pbr.vertex.fx
  41. 2 39
      src/Shaders/shadowMap.fragment.fx
  42. 9 45
      src/Shaders/shadowMap.vertex.fx

+ 1 - 0
Tools/Gulp/helpers/gulp-processShaders.js

@@ -109,6 +109,7 @@ function main(isCore) {
             if (isCore) {
             if (isCore) {
                 if (isInclude) {
                 if (isInclude) {
                     effectLocation = "../../Materials/effect";
                     effectLocation = "../../Materials/effect";
+                    includeText = includeText.replace(/ShadersInclude\//g, "");
                 }
                 }
                 else {
                 else {
                     effectLocation = "../Materials/effect";
                     effectLocation = "../Materials/effect";

+ 175 - 27
dist/preview release/babylon.d.ts

@@ -9344,6 +9344,13 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /** @hidden */
     /** @hidden */
+    export var shadowMapFragmentDeclaration: {
+        name: string;
+        shader: string;
+    };
+}
+declare module BABYLON {
+    /** @hidden */
     export var clipPlaneFragmentDeclaration: {
     export var clipPlaneFragmentDeclaration: {
         name: string;
         name: string;
         shader: string;
         shader: string;
@@ -9358,6 +9365,13 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /** @hidden */
     /** @hidden */
+    export var shadowMapFragment: {
+        name: string;
+        shader: string;
+    };
+}
+declare module BABYLON {
+    /** @hidden */
     export var shadowMapPixelShader: {
     export var shadowMapPixelShader: {
         name: string;
         name: string;
         shader: string;
         shader: string;
@@ -9400,6 +9414,13 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /** @hidden */
     /** @hidden */
+    export var shadowMapVertexDeclaration: {
+        name: string;
+        shader: string;
+    };
+}
+declare module BABYLON {
+    /** @hidden */
     export var clipPlaneVertexDeclaration: {
     export var clipPlaneVertexDeclaration: {
         name: string;
         name: string;
         shader: string;
         shader: string;
@@ -9428,6 +9449,20 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /** @hidden */
     /** @hidden */
+    export var shadowMapVertexNormalBias: {
+        name: string;
+        shader: string;
+    };
+}
+declare module BABYLON {
+    /** @hidden */
+    export var shadowMapVertexMetric: {
+        name: string;
+        shader: string;
+    };
+}
+declare module BABYLON {
+    /** @hidden */
     export var clipPlaneVertex: {
     export var clipPlaneVertex: {
         name: string;
         name: string;
         shader: string;
         shader: string;
@@ -9475,6 +9510,7 @@ declare module BABYLON {
         length?: number);
         length?: number);
         /**
         /**
          * Checks if the ray intersects a box
          * Checks if the ray intersects a box
+         * This does not account for the ray lenght by design to improve perfs.
          * @param minimum bound of the box
          * @param minimum bound of the box
          * @param maximum bound of the box
          * @param maximum bound of the box
          * @param intersectionTreshold extra extend to be added to the box in all direction
          * @param intersectionTreshold extra extend to be added to the box in all direction
@@ -9483,6 +9519,7 @@ declare module BABYLON {
         intersectsBoxMinMax(minimum: DeepImmutable<Vector3>, maximum: DeepImmutable<Vector3>, intersectionTreshold?: number): boolean;
         intersectsBoxMinMax(minimum: DeepImmutable<Vector3>, maximum: DeepImmutable<Vector3>, intersectionTreshold?: number): boolean;
         /**
         /**
          * Checks if the ray intersects a box
          * Checks if the ray intersects a box
+         * This does not account for the ray lenght by design to improve perfs.
          * @param box the bounding box to check
          * @param box the bounding box to check
          * @param intersectionTreshold extra extend to be added to the BoundingBox in all direction
          * @param intersectionTreshold extra extend to be added to the BoundingBox in all direction
          * @returns if the box was hit
          * @returns if the box was hit
@@ -15476,6 +15513,7 @@ declare module BABYLON {
         private _cachedWorldViewProjectionMatrix;
         private _cachedWorldViewProjectionMatrix;
         private _renderId;
         private _renderId;
         private _multiview;
         private _multiview;
+        private _cachedDefines;
         /**
         /**
          * Instantiate a new shader material.
          * Instantiate a new shader material.
          * The ShaderMaterial object has the necessary methods to pass data from your scene to the Vertex and Fragment Shaders and returns a material that can be applied to any mesh.
          * The ShaderMaterial object has the necessary methods to pass data from your scene to the Vertex and Fragment Shaders and returns a material that can be applied to any mesh.
@@ -15675,14 +15713,24 @@ declare module BABYLON {
         /**
         /**
          * Binds the world matrix to the material
          * Binds the world matrix to the material
          * @param world defines the world transformation matrix
          * @param world defines the world transformation matrix
+         * @param effectOverride - If provided, use this effect instead of internal effect
          */
          */
-        bindOnlyWorldMatrix(world: Matrix): void;
+        bindOnlyWorldMatrix(world: Matrix, effectOverride?: Nullable<Effect>): void;
+        /**
+         * Binds the submesh to this material by preparing the effect and shader to draw
+         * @param world defines the world transformation matrix
+         * @param mesh defines the mesh containing the submesh
+         * @param subMesh defines the submesh to bind the material to
+         */
+        bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         /**
         /**
          * Binds the material to the mesh
          * Binds the material to the mesh
          * @param world defines the world transformation matrix
          * @param world defines the world transformation matrix
          * @param mesh defines the mesh to bind the material to
          * @param mesh defines the mesh to bind the material to
+         * @param effectOverride - If provided, use this effect instead of internal effect
          */
          */
-        bind(world: Matrix, mesh?: Mesh): void;
+        bind(world: Matrix, mesh?: Mesh, effectOverride?: Nullable<Effect>): void;
+        protected _afterBind(mesh?: Mesh): void;
         /**
         /**
          * Gets the active textures from the material
          * Gets the active textures from the material
          * @returns an array of textures
          * @returns an array of textures
@@ -16742,7 +16790,7 @@ declare module BABYLON {
         protected _initializeShadowMap(): void;
         protected _initializeShadowMap(): void;
         protected _initializeBlurRTTAndPostProcesses(): void;
         protected _initializeBlurRTTAndPostProcesses(): void;
         protected _renderForShadowMap(opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void;
         protected _renderForShadowMap(opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void;
-        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect): void;
+        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect, matriceNames: any): void;
         protected _renderSubMeshForShadowMap(subMesh: SubMesh): void;
         protected _renderSubMeshForShadowMap(subMesh: SubMesh): void;
         protected _applyFilterValues(): void;
         protected _applyFilterValues(): void;
         /**
         /**
@@ -16762,6 +16810,7 @@ declare module BABYLON {
             useInstances: boolean;
             useInstances: boolean;
         }>): Promise<void>;
         }>): Promise<void>;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
+        private _prepareShadowDefines;
         /**
         /**
          * Determine wheter the shadow generator is ready or not (mainly all effects and related post processes needs to be ready).
          * Determine wheter the shadow generator is ready or not (mainly all effects and related post processes needs to be ready).
          * @param subMesh The submesh we want to render in the shadow map
          * @param subMesh The submesh we want to render in the shadow map
@@ -20953,6 +21002,82 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /**
     /**
+     * Class used to manipulate GUIDs
+     */
+    export class GUID {
+        /**
+         * Implementation from http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#answer-2117523
+         * Be aware Math.random() could cause collisions, but:
+         * "All but 6 of the 128 bits of the ID are randomly generated, which means that for any two ids, there's a 1 in 2^^122 (or 5.3x10^^36) chance they'll collide"
+         * @returns a pseudo random id
+         */
+        static RandomId(): string;
+    }
+}
+declare module BABYLON {
+    /**
+     * Options to be used when creating a shadow depth material
+     */
+    export interface IIOptionShadowDepthMaterial {
+        /** Variables in the vertex shader code that need to have their names remapped.
+         * The format is: ["var_name", "var_remapped_name", "var_name", "var_remapped_name", ...]
+         * "var_name" should be either: worldPos or vNormalW
+         * So, if the variable holding the world position in your vertex shader is not named worldPos, you must tell the system
+         * the name to use instead by using: ["worldPos", "myWorldPosVar"] assuming the variable is named myWorldPosVar in your code.
+         * If the normal must also be remapped: ["worldPos", "myWorldPosVar", "vNormalW", "myWorldNormal"]
+        */
+        remappedVariables?: string[];
+        /** Set standalone to true if the base material wrapped by ShadowDepthMaterial is not used for a regular object but for depth shadow generation only */
+        standalone?: boolean;
+    }
+    /**
+     * Class that can be used to wrap a base material to generate accurate shadows when using custom vertex/fragment code in the base material
+     */
+    export class ShadowDepthWrapper {
+        private _scene;
+        private _options?;
+        private _baseMaterial;
+        private _onEffectCreatedObserver;
+        private _subMeshToEffect;
+        private _subMeshToDepthEffect;
+        private _meshes;
+        /** @hidden */
+        _matriceNames: any;
+        /**
+         * Instantiate a new shadow depth wrapper.
+         * It works by injecting some specific code in the vertex/fragment shaders of the base material and is used by a shadow generator to
+         * generate the shadow depth map. For more information, please refer to the documentation:
+         * https://doc.babylonjs.com/babylon101/shadows
+         * @param baseMaterial Material to wrap
+         * @param scene Define the scene the material belongs to
+         * @param options Options used to create the wrapper
+         */
+        constructor(baseMaterial: Material, scene: Scene, options?: IIOptionShadowDepthMaterial);
+        /**
+         * Gets the effect to use to generate the depth map
+         * @param subMesh subMesh to get the effect for
+         * @param shadowGenerator shadow generator to get the effect for
+         * @returns the effect to use to generate the depth map for the subMesh + shadow generator specified
+         */
+        getEffect(subMesh: Nullable<SubMesh>, shadowGenerator: ShadowGenerator): Nullable<Effect>;
+        /**
+         * Specifies that the submesh is ready to be used for depth rendering
+         * @param subMesh submesh to check
+         * @param defines the list of defines to take into account when checking the effect
+         * @param shadowGenerator combined with subMesh, it defines the effect to check
+         * @param useInstances specifies that instances should be used
+         * @returns a boolean indicating that the submesh is ready or not
+         */
+        isReadyForSubMesh(subMesh: SubMesh, defines: string[], shadowGenerator: ShadowGenerator, useInstances: boolean): boolean;
+        /**
+         * Disposes the resources
+         */
+        dispose(): void;
+        private _makeEffect;
+    }
+}
+declare module BABYLON {
+    /**
      * Options for compiling materials.
      * Options for compiling materials.
      */
      */
     export interface IMaterialCompilationOptions {
     export interface IMaterialCompilationOptions {
@@ -21055,6 +21180,14 @@ declare module BABYLON {
          */
          */
         static readonly MATERIAL_ALPHATESTANDBLEND: number;
         static readonly MATERIAL_ALPHATESTANDBLEND: number;
         /**
         /**
+         * Custom callback helping to override the default shader used in the material.
+         */
+        customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: MaterialDefines | string[], attributes?: string[]) => string;
+        /**
+         * Custom shadow depth material to use for shadow rendering instead of the in-built one
+         */
+        shadowDepthWrapper: Nullable<ShadowDepthWrapper>;
+        /**
          * The ID of the material
          * The ID of the material
          */
          */
         id: string;
         id: string;
@@ -21177,6 +21310,17 @@ declare module BABYLON {
         * An event triggered when the material is unbound
         * An event triggered when the material is unbound
         */
         */
         get onUnBindObservable(): Observable<Material>;
         get onUnBindObservable(): Observable<Material>;
+        protected _onEffectCreatedObservable: Nullable<Observable<{
+            effect: Effect;
+            subMesh: Nullable<SubMesh>;
+        }>>;
+        /**
+        * An event triggered when the effect is (re)created
+        */
+        get onEffectCreatedObservable(): Observable<{
+            effect: Effect;
+            subMesh: Nullable<SubMesh>;
+        }>;
         /**
         /**
          * Stores the value of the alpha mode
          * Stores the value of the alpha mode
          */
          */
@@ -21678,6 +21822,8 @@ declare module BABYLON {
         _materialDefines: Nullable<MaterialDefines>;
         _materialDefines: Nullable<MaterialDefines>;
         /** @hidden */
         /** @hidden */
         _materialEffect: Nullable<Effect>;
         _materialEffect: Nullable<Effect>;
+        /** @hidden */
+        _effectOverride: Nullable<Effect>;
         /**
         /**
          * Gets material defines used by the effect associated to the sub mesh
          * Gets material defines used by the effect associated to the sub mesh
          */
          */
@@ -27026,10 +27172,6 @@ declare module BABYLON {
          * corresponding to low luminance, medium luminance, and high luminance areas respectively.
          * corresponding to low luminance, medium luminance, and high luminance areas respectively.
          */
          */
         set cameraColorCurves(value: Nullable<ColorCurves>);
         set cameraColorCurves(value: Nullable<ColorCurves>);
-        /**
-         * Custom callback helping to override the default shader used in the material.
-         */
-        customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: StandardMaterialDefines, attributes?: string[]) => string;
         protected _renderTargets: SmartArray<RenderTargetTexture>;
         protected _renderTargets: SmartArray<RenderTargetTexture>;
         protected _worldViewProjectionMatrix: Matrix;
         protected _worldViewProjectionMatrix: Matrix;
         protected _globalAmbientColor: Color3;
         protected _globalAmbientColor: Color3;
@@ -29945,20 +30087,6 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /**
     /**
-     * Class used to manipulate GUIDs
-     */
-    export class GUID {
-        /**
-         * Implementation from http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#answer-2117523
-         * Be aware Math.random() could cause collisions, but:
-         * "All but 6 of the 128 bits of the ID are randomly generated, which means that for any two ids, there's a 1 in 2^^122 (or 5.3x10^^36) chance they'll collide"
-         * @returns a pseudo random id
-         */
-        static RandomId(): string;
-    }
-}
-declare module BABYLON {
-    /**
      * Base class of all the textures in babylon.
      * Base class of all the textures in babylon.
      * It groups all the common properties the materials, post process, lights... might need
      * It groups all the common properties the materials, post process, lights... might need
      * in order to make a correct use of the texture.
      * in order to make a correct use of the texture.
@@ -30419,6 +30547,7 @@ declare module BABYLON {
         private static _uniqueIdSeed;
         private static _uniqueIdSeed;
         private _engine;
         private _engine;
         private _uniformBuffersNames;
         private _uniformBuffersNames;
+        private _uniformBuffersNamesList;
         private _uniformsNames;
         private _uniformsNames;
         private _samplerList;
         private _samplerList;
         private _samplers;
         private _samplers;
@@ -30520,10 +30649,25 @@ declare module BABYLON {
         getUniform(uniformName: string): Nullable<WebGLUniformLocation>;
         getUniform(uniformName: string): Nullable<WebGLUniformLocation>;
         /**
         /**
          * Returns an array of sampler variable names
          * Returns an array of sampler variable names
-         * @returns The array of sampler variable neames.
+         * @returns The array of sampler variable names.
          */
          */
         getSamplers(): string[];
         getSamplers(): string[];
         /**
         /**
+         * Returns an array of uniform variable names
+         * @returns The array of uniform variable names.
+         */
+        getUniformNames(): string[];
+        /**
+         * Returns an array of uniform buffer variable names
+         * @returns The array of uniform buffer variable names.
+         */
+        getUniformBuffersNames(): string[];
+        /**
+         * Returns the index parameters used to create the effect
+         * @returns The index parameters object
+         */
+        getIndexParameters(): any;
+        /**
          * The error from the last compilation.
          * The error from the last compilation.
          * @returns the error string.
          * @returns the error string.
          */
          */
@@ -30541,6 +30685,14 @@ declare module BABYLON {
         private _checkIsReady;
         private _checkIsReady;
         private _loadShader;
         private _loadShader;
         /**
         /**
+         * Gets the vertex shader source code of this effect
+         */
+        get vertexSourceCode(): string;
+        /**
+         * Gets the fragment shader source code of this effect
+         */
+        get fragmentSourceCode(): string;
+        /**
          * Recompiles the webGL program
          * Recompiles the webGL program
          * @param vertexSourceCode The source code for the vertex shader.
          * @param vertexSourceCode The source code for the vertex shader.
          * @param fragmentSourceCode The source code for the fragment shader.
          * @param fragmentSourceCode The source code for the fragment shader.
@@ -51952,10 +52104,6 @@ declare module BABYLON {
          * Defines the SubSurface parameters for the material.
          * Defines the SubSurface parameters for the material.
          */
          */
         readonly subSurface: PBRSubSurfaceConfiguration;
         readonly subSurface: PBRSubSurfaceConfiguration;
-        /**
-         * Custom callback helping to override the default shader used in the material.
-         */
-        customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: PBRMaterialDefines, attributes?: string[]) => string;
         protected _rebuildInParallel: boolean;
         protected _rebuildInParallel: boolean;
         /**
         /**
          * Instantiates a new PBRMaterial instance.
          * Instantiates a new PBRMaterial instance.
@@ -54966,7 +55114,7 @@ declare module BABYLON {
         protected _initializeGenerator(): void;
         protected _initializeGenerator(): void;
         protected _createTargetRenderTexture(): void;
         protected _createTargetRenderTexture(): void;
         protected _initializeShadowMap(): void;
         protected _initializeShadowMap(): void;
-        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect): void;
+        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect, matriceNames: any): void;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
         /**
         /**
          * Prepare all the defines in a material relying on a shadow map at the specified light index.
          * Prepare all the defines in a material relying on a shadow map at the specified light index.

Разница между файлами не показана из-за своего большого размера
+ 2 - 2
dist/preview release/babylon.js


+ 367 - 56
dist/preview release/babylon.module.d.ts

@@ -9474,6 +9474,14 @@ declare module "babylonjs/Shaders/ShadersInclude/packingFunctions" {
         shader: string;
         shader: string;
     };
     };
 }
 }
+declare module "babylonjs/Shaders/ShadersInclude/shadowMapFragmentDeclaration" {
+    import "babylonjs/Shaders/ShadersInclude/packingFunctions";
+    /** @hidden */
+    export var shadowMapFragmentDeclaration: {
+        name: string;
+        shader: string;
+    };
+}
 declare module "babylonjs/Shaders/ShadersInclude/clipPlaneFragmentDeclaration" {
 declare module "babylonjs/Shaders/ShadersInclude/clipPlaneFragmentDeclaration" {
     /** @hidden */
     /** @hidden */
     export var clipPlaneFragmentDeclaration: {
     export var clipPlaneFragmentDeclaration: {
@@ -9488,10 +9496,18 @@ declare module "babylonjs/Shaders/ShadersInclude/clipPlaneFragment" {
         shader: string;
         shader: string;
     };
     };
 }
 }
+declare module "babylonjs/Shaders/ShadersInclude/shadowMapFragment" {
+    /** @hidden */
+    export var shadowMapFragment: {
+        name: string;
+        shader: string;
+    };
+}
 declare module "babylonjs/Shaders/shadowMap.fragment" {
 declare module "babylonjs/Shaders/shadowMap.fragment" {
-    import "babylonjs/Shaders/ShadersInclude/packingFunctions";
+    import "babylonjs/Shaders/ShadersInclude/shadowMapFragmentDeclaration";
     import "babylonjs/Shaders/ShadersInclude/clipPlaneFragmentDeclaration";
     import "babylonjs/Shaders/ShadersInclude/clipPlaneFragmentDeclaration";
     import "babylonjs/Shaders/ShadersInclude/clipPlaneFragment";
     import "babylonjs/Shaders/ShadersInclude/clipPlaneFragment";
+    import "babylonjs/Shaders/ShadersInclude/shadowMapFragment";
     /** @hidden */
     /** @hidden */
     export var shadowMapPixelShader: {
     export var shadowMapPixelShader: {
         name: string;
         name: string;
@@ -9533,6 +9549,13 @@ declare module "babylonjs/Shaders/ShadersInclude/helperFunctions" {
         shader: string;
         shader: string;
     };
     };
 }
 }
+declare module "babylonjs/Shaders/ShadersInclude/shadowMapVertexDeclaration" {
+    /** @hidden */
+    export var shadowMapVertexDeclaration: {
+        name: string;
+        shader: string;
+    };
+}
 declare module "babylonjs/Shaders/ShadersInclude/clipPlaneVertexDeclaration" {
 declare module "babylonjs/Shaders/ShadersInclude/clipPlaneVertexDeclaration" {
     /** @hidden */
     /** @hidden */
     export var clipPlaneVertexDeclaration: {
     export var clipPlaneVertexDeclaration: {
@@ -9561,6 +9584,20 @@ declare module "babylonjs/Shaders/ShadersInclude/bonesVertex" {
         shader: string;
         shader: string;
     };
     };
 }
 }
+declare module "babylonjs/Shaders/ShadersInclude/shadowMapVertexNormalBias" {
+    /** @hidden */
+    export var shadowMapVertexNormalBias: {
+        name: string;
+        shader: string;
+    };
+}
+declare module "babylonjs/Shaders/ShadersInclude/shadowMapVertexMetric" {
+    /** @hidden */
+    export var shadowMapVertexMetric: {
+        name: string;
+        shader: string;
+    };
+}
 declare module "babylonjs/Shaders/ShadersInclude/clipPlaneVertex" {
 declare module "babylonjs/Shaders/ShadersInclude/clipPlaneVertex" {
     /** @hidden */
     /** @hidden */
     export var clipPlaneVertex: {
     export var clipPlaneVertex: {
@@ -9574,10 +9611,13 @@ declare module "babylonjs/Shaders/shadowMap.vertex" {
     import "babylonjs/Shaders/ShadersInclude/morphTargetsVertexDeclaration";
     import "babylonjs/Shaders/ShadersInclude/morphTargetsVertexDeclaration";
     import "babylonjs/Shaders/ShadersInclude/instancesDeclaration";
     import "babylonjs/Shaders/ShadersInclude/instancesDeclaration";
     import "babylonjs/Shaders/ShadersInclude/helperFunctions";
     import "babylonjs/Shaders/ShadersInclude/helperFunctions";
+    import "babylonjs/Shaders/ShadersInclude/shadowMapVertexDeclaration";
     import "babylonjs/Shaders/ShadersInclude/clipPlaneVertexDeclaration";
     import "babylonjs/Shaders/ShadersInclude/clipPlaneVertexDeclaration";
     import "babylonjs/Shaders/ShadersInclude/morphTargetsVertex";
     import "babylonjs/Shaders/ShadersInclude/morphTargetsVertex";
     import "babylonjs/Shaders/ShadersInclude/instancesVertex";
     import "babylonjs/Shaders/ShadersInclude/instancesVertex";
     import "babylonjs/Shaders/ShadersInclude/bonesVertex";
     import "babylonjs/Shaders/ShadersInclude/bonesVertex";
+    import "babylonjs/Shaders/ShadersInclude/shadowMapVertexNormalBias";
+    import "babylonjs/Shaders/ShadersInclude/shadowMapVertexMetric";
     import "babylonjs/Shaders/ShadersInclude/clipPlaneVertex";
     import "babylonjs/Shaders/ShadersInclude/clipPlaneVertex";
     /** @hidden */
     /** @hidden */
     export var shadowMapVertexShader: {
     export var shadowMapVertexShader: {
@@ -9628,6 +9668,7 @@ declare module "babylonjs/Culling/ray" {
         length?: number);
         length?: number);
         /**
         /**
          * Checks if the ray intersects a box
          * Checks if the ray intersects a box
+         * This does not account for the ray lenght by design to improve perfs.
          * @param minimum bound of the box
          * @param minimum bound of the box
          * @param maximum bound of the box
          * @param maximum bound of the box
          * @param intersectionTreshold extra extend to be added to the box in all direction
          * @param intersectionTreshold extra extend to be added to the box in all direction
@@ -9636,6 +9677,7 @@ declare module "babylonjs/Culling/ray" {
         intersectsBoxMinMax(minimum: DeepImmutable<Vector3>, maximum: DeepImmutable<Vector3>, intersectionTreshold?: number): boolean;
         intersectsBoxMinMax(minimum: DeepImmutable<Vector3>, maximum: DeepImmutable<Vector3>, intersectionTreshold?: number): boolean;
         /**
         /**
          * Checks if the ray intersects a box
          * Checks if the ray intersects a box
+         * This does not account for the ray lenght by design to improve perfs.
          * @param box the bounding box to check
          * @param box the bounding box to check
          * @param intersectionTreshold extra extend to be added to the BoundingBox in all direction
          * @param intersectionTreshold extra extend to be added to the BoundingBox in all direction
          * @returns if the box was hit
          * @returns if the box was hit
@@ -15796,12 +15838,14 @@ declare module "babylonjs/Meshes/instancedMesh" {
     }
     }
 }
 }
 declare module "babylonjs/Materials/shaderMaterial" {
 declare module "babylonjs/Materials/shaderMaterial" {
+    import { Nullable } from "babylonjs/types";
     import { Scene } from "babylonjs/scene";
     import { Scene } from "babylonjs/scene";
     import { Matrix, Vector3, Vector2, Vector4 } from "babylonjs/Maths/math.vector";
     import { Matrix, Vector3, Vector2, Vector4 } from "babylonjs/Maths/math.vector";
     import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
     import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
     import { Mesh } from "babylonjs/Meshes/mesh";
     import { Mesh } from "babylonjs/Meshes/mesh";
-    import { BaseSubMesh } from "babylonjs/Meshes/subMesh";
+    import { SubMesh, BaseSubMesh } from "babylonjs/Meshes/subMesh";
     import { BaseTexture } from "babylonjs/Materials/Textures/baseTexture";
     import { BaseTexture } from "babylonjs/Materials/Textures/baseTexture";
+    import { Effect } from "babylonjs/Materials/effect";
     import { Material } from "babylonjs/Materials/material";
     import { Material } from "babylonjs/Materials/material";
     import { Color3, Color4 } from "babylonjs/Maths/math.color";
     import { Color3, Color4 } from "babylonjs/Maths/math.color";
     /**
     /**
@@ -15870,6 +15914,7 @@ declare module "babylonjs/Materials/shaderMaterial" {
         private _cachedWorldViewProjectionMatrix;
         private _cachedWorldViewProjectionMatrix;
         private _renderId;
         private _renderId;
         private _multiview;
         private _multiview;
+        private _cachedDefines;
         /**
         /**
          * Instantiate a new shader material.
          * Instantiate a new shader material.
          * The ShaderMaterial object has the necessary methods to pass data from your scene to the Vertex and Fragment Shaders and returns a material that can be applied to any mesh.
          * The ShaderMaterial object has the necessary methods to pass data from your scene to the Vertex and Fragment Shaders and returns a material that can be applied to any mesh.
@@ -16069,14 +16114,24 @@ declare module "babylonjs/Materials/shaderMaterial" {
         /**
         /**
          * Binds the world matrix to the material
          * Binds the world matrix to the material
          * @param world defines the world transformation matrix
          * @param world defines the world transformation matrix
+         * @param effectOverride - If provided, use this effect instead of internal effect
          */
          */
-        bindOnlyWorldMatrix(world: Matrix): void;
+        bindOnlyWorldMatrix(world: Matrix, effectOverride?: Nullable<Effect>): void;
+        /**
+         * Binds the submesh to this material by preparing the effect and shader to draw
+         * @param world defines the world transformation matrix
+         * @param mesh defines the mesh containing the submesh
+         * @param subMesh defines the submesh to bind the material to
+         */
+        bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         /**
         /**
          * Binds the material to the mesh
          * Binds the material to the mesh
          * @param world defines the world transformation matrix
          * @param world defines the world transformation matrix
          * @param mesh defines the mesh to bind the material to
          * @param mesh defines the mesh to bind the material to
+         * @param effectOverride - If provided, use this effect instead of internal effect
          */
          */
-        bind(world: Matrix, mesh?: Mesh): void;
+        bind(world: Matrix, mesh?: Mesh, effectOverride?: Nullable<Effect>): void;
+        protected _afterBind(mesh?: Mesh): void;
         /**
         /**
          * Gets the active textures from the material
          * Gets the active textures from the material
          * @returns an array of textures
          * @returns an array of textures
@@ -17204,7 +17259,7 @@ declare module "babylonjs/Lights/Shadows/shadowGenerator" {
         protected _initializeShadowMap(): void;
         protected _initializeShadowMap(): void;
         protected _initializeBlurRTTAndPostProcesses(): void;
         protected _initializeBlurRTTAndPostProcesses(): void;
         protected _renderForShadowMap(opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void;
         protected _renderForShadowMap(opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void;
-        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect): void;
+        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect, matriceNames: any): void;
         protected _renderSubMeshForShadowMap(subMesh: SubMesh): void;
         protected _renderSubMeshForShadowMap(subMesh: SubMesh): void;
         protected _applyFilterValues(): void;
         protected _applyFilterValues(): void;
         /**
         /**
@@ -17224,6 +17279,7 @@ declare module "babylonjs/Lights/Shadows/shadowGenerator" {
             useInstances: boolean;
             useInstances: boolean;
         }>): Promise<void>;
         }>): Promise<void>;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
+        private _prepareShadowDefines;
         /**
         /**
          * Determine wheter the shadow generator is ready or not (mainly all effects and related post processes needs to be ready).
          * Determine wheter the shadow generator is ready or not (mainly all effects and related post processes needs to be ready).
          * @param subMesh The submesh we want to render in the shadow map
          * @param subMesh The submesh we want to render in the shadow map
@@ -21585,6 +21641,88 @@ declare module "babylonjs/Materials/Textures/renderTargetTexture" {
         getViewCount(): number;
         getViewCount(): number;
     }
     }
 }
 }
+declare module "babylonjs/Misc/guid" {
+    /**
+     * Class used to manipulate GUIDs
+     */
+    export class GUID {
+        /**
+         * Implementation from http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#answer-2117523
+         * Be aware Math.random() could cause collisions, but:
+         * "All but 6 of the 128 bits of the ID are randomly generated, which means that for any two ids, there's a 1 in 2^^122 (or 5.3x10^^36) chance they'll collide"
+         * @returns a pseudo random id
+         */
+        static RandomId(): string;
+    }
+}
+declare module "babylonjs/Materials/shadowDepthWrapper" {
+    import { Nullable } from "babylonjs/types";
+    import { Scene } from "babylonjs/scene";
+    import { SubMesh } from "babylonjs/Meshes/subMesh";
+    import { Material } from "babylonjs/Materials/material";
+    import { Effect } from "babylonjs/Materials/effect";
+    import { ShadowGenerator } from "babylonjs/Lights/Shadows/shadowGenerator";
+    /**
+     * Options to be used when creating a shadow depth material
+     */
+    export interface IIOptionShadowDepthMaterial {
+        /** Variables in the vertex shader code that need to have their names remapped.
+         * The format is: ["var_name", "var_remapped_name", "var_name", "var_remapped_name", ...]
+         * "var_name" should be either: worldPos or vNormalW
+         * So, if the variable holding the world position in your vertex shader is not named worldPos, you must tell the system
+         * the name to use instead by using: ["worldPos", "myWorldPosVar"] assuming the variable is named myWorldPosVar in your code.
+         * If the normal must also be remapped: ["worldPos", "myWorldPosVar", "vNormalW", "myWorldNormal"]
+        */
+        remappedVariables?: string[];
+        /** Set standalone to true if the base material wrapped by ShadowDepthMaterial is not used for a regular object but for depth shadow generation only */
+        standalone?: boolean;
+    }
+    /**
+     * Class that can be used to wrap a base material to generate accurate shadows when using custom vertex/fragment code in the base material
+     */
+    export class ShadowDepthWrapper {
+        private _scene;
+        private _options?;
+        private _baseMaterial;
+        private _onEffectCreatedObserver;
+        private _subMeshToEffect;
+        private _subMeshToDepthEffect;
+        private _meshes;
+        /** @hidden */
+        _matriceNames: any;
+        /**
+         * Instantiate a new shadow depth wrapper.
+         * It works by injecting some specific code in the vertex/fragment shaders of the base material and is used by a shadow generator to
+         * generate the shadow depth map. For more information, please refer to the documentation:
+         * https://doc.babylonjs.com/babylon101/shadows
+         * @param baseMaterial Material to wrap
+         * @param scene Define the scene the material belongs to
+         * @param options Options used to create the wrapper
+         */
+        constructor(baseMaterial: Material, scene: Scene, options?: IIOptionShadowDepthMaterial);
+        /**
+         * Gets the effect to use to generate the depth map
+         * @param subMesh subMesh to get the effect for
+         * @param shadowGenerator shadow generator to get the effect for
+         * @returns the effect to use to generate the depth map for the subMesh + shadow generator specified
+         */
+        getEffect(subMesh: Nullable<SubMesh>, shadowGenerator: ShadowGenerator): Nullable<Effect>;
+        /**
+         * Specifies that the submesh is ready to be used for depth rendering
+         * @param subMesh submesh to check
+         * @param defines the list of defines to take into account when checking the effect
+         * @param shadowGenerator combined with subMesh, it defines the effect to check
+         * @param useInstances specifies that instances should be used
+         * @returns a boolean indicating that the submesh is ready or not
+         */
+        isReadyForSubMesh(subMesh: SubMesh, defines: string[], shadowGenerator: ShadowGenerator, useInstances: boolean): boolean;
+        /**
+         * Disposes the resources
+         */
+        dispose(): void;
+        private _makeEffect;
+    }
+}
 declare module "babylonjs/Materials/material" {
 declare module "babylonjs/Materials/material" {
     import { IAnimatable } from "babylonjs/Animations/animatable.interface";
     import { IAnimatable } from "babylonjs/Animations/animatable.interface";
     import { SmartArray } from "babylonjs/Misc/smartArray";
     import { SmartArray } from "babylonjs/Misc/smartArray";
@@ -21600,6 +21738,7 @@ declare module "babylonjs/Materials/material" {
     import { RenderTargetTexture } from "babylonjs/Materials/Textures/renderTargetTexture";
     import { RenderTargetTexture } from "babylonjs/Materials/Textures/renderTargetTexture";
     import { MaterialDefines } from "babylonjs/Materials/materialDefines";
     import { MaterialDefines } from "babylonjs/Materials/materialDefines";
     import { IInspectable } from "babylonjs/Misc/iInspectable";
     import { IInspectable } from "babylonjs/Misc/iInspectable";
+    import { ShadowDepthWrapper } from "babylonjs/Materials/shadowDepthWrapper";
     import { Mesh } from "babylonjs/Meshes/mesh";
     import { Mesh } from "babylonjs/Meshes/mesh";
     import { Animation } from "babylonjs/Animations/animation";
     import { Animation } from "babylonjs/Animations/animation";
     /**
     /**
@@ -21705,6 +21844,14 @@ declare module "babylonjs/Materials/material" {
          */
          */
         static readonly MATERIAL_ALPHATESTANDBLEND: number;
         static readonly MATERIAL_ALPHATESTANDBLEND: number;
         /**
         /**
+         * Custom callback helping to override the default shader used in the material.
+         */
+        customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: MaterialDefines | string[], attributes?: string[]) => string;
+        /**
+         * Custom shadow depth material to use for shadow rendering instead of the in-built one
+         */
+        shadowDepthWrapper: Nullable<ShadowDepthWrapper>;
+        /**
          * The ID of the material
          * The ID of the material
          */
          */
         id: string;
         id: string;
@@ -21827,6 +21974,17 @@ declare module "babylonjs/Materials/material" {
         * An event triggered when the material is unbound
         * An event triggered when the material is unbound
         */
         */
         get onUnBindObservable(): Observable<Material>;
         get onUnBindObservable(): Observable<Material>;
+        protected _onEffectCreatedObservable: Nullable<Observable<{
+            effect: Effect;
+            subMesh: Nullable<SubMesh>;
+        }>>;
+        /**
+        * An event triggered when the effect is (re)created
+        */
+        get onEffectCreatedObservable(): Observable<{
+            effect: Effect;
+            subMesh: Nullable<SubMesh>;
+        }>;
         /**
         /**
          * Stores the value of the alpha mode
          * Stores the value of the alpha mode
          */
          */
@@ -22349,6 +22507,8 @@ declare module "babylonjs/Meshes/subMesh" {
         _materialDefines: Nullable<MaterialDefines>;
         _materialDefines: Nullable<MaterialDefines>;
         /** @hidden */
         /** @hidden */
         _materialEffect: Nullable<Effect>;
         _materialEffect: Nullable<Effect>;
+        /** @hidden */
+        _effectOverride: Nullable<Effect>;
         /**
         /**
          * Gets material defines used by the effect associated to the sub mesh
          * Gets material defines used by the effect associated to the sub mesh
          */
          */
@@ -27863,10 +28023,6 @@ declare module "babylonjs/Materials/standardMaterial" {
          * corresponding to low luminance, medium luminance, and high luminance areas respectively.
          * corresponding to low luminance, medium luminance, and high luminance areas respectively.
          */
          */
         set cameraColorCurves(value: Nullable<ColorCurves>);
         set cameraColorCurves(value: Nullable<ColorCurves>);
-        /**
-         * Custom callback helping to override the default shader used in the material.
-         */
-        customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: StandardMaterialDefines, attributes?: string[]) => string;
         protected _renderTargets: SmartArray<RenderTargetTexture>;
         protected _renderTargets: SmartArray<RenderTargetTexture>;
         protected _worldViewProjectionMatrix: Matrix;
         protected _worldViewProjectionMatrix: Matrix;
         protected _globalAmbientColor: Color3;
         protected _globalAmbientColor: Color3;
@@ -30866,20 +31022,6 @@ declare module "babylonjs/Misc/decorators" {
         static Instanciate<T>(creationFunction: () => T, source: T): T;
         static Instanciate<T>(creationFunction: () => T, source: T): T;
     }
     }
 }
 }
-declare module "babylonjs/Misc/guid" {
-    /**
-     * Class used to manipulate GUIDs
-     */
-    export class GUID {
-        /**
-         * Implementation from http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#answer-2117523
-         * Be aware Math.random() could cause collisions, but:
-         * "All but 6 of the 128 bits of the ID are randomly generated, which means that for any two ids, there's a 1 in 2^^122 (or 5.3x10^^36) chance they'll collide"
-         * @returns a pseudo random id
-         */
-        static RandomId(): string;
-    }
-}
 declare module "babylonjs/Materials/Textures/baseTexture" {
 declare module "babylonjs/Materials/Textures/baseTexture" {
     import { Observable } from "babylonjs/Misc/observable";
     import { Observable } from "babylonjs/Misc/observable";
     import { Nullable } from "babylonjs/types";
     import { Nullable } from "babylonjs/types";
@@ -31363,6 +31505,7 @@ declare module "babylonjs/Materials/effect" {
         private static _uniqueIdSeed;
         private static _uniqueIdSeed;
         private _engine;
         private _engine;
         private _uniformBuffersNames;
         private _uniformBuffersNames;
+        private _uniformBuffersNamesList;
         private _uniformsNames;
         private _uniformsNames;
         private _samplerList;
         private _samplerList;
         private _samplers;
         private _samplers;
@@ -31464,10 +31607,25 @@ declare module "babylonjs/Materials/effect" {
         getUniform(uniformName: string): Nullable<WebGLUniformLocation>;
         getUniform(uniformName: string): Nullable<WebGLUniformLocation>;
         /**
         /**
          * Returns an array of sampler variable names
          * Returns an array of sampler variable names
-         * @returns The array of sampler variable neames.
+         * @returns The array of sampler variable names.
          */
          */
         getSamplers(): string[];
         getSamplers(): string[];
         /**
         /**
+         * Returns an array of uniform variable names
+         * @returns The array of uniform variable names.
+         */
+        getUniformNames(): string[];
+        /**
+         * Returns an array of uniform buffer variable names
+         * @returns The array of uniform buffer variable names.
+         */
+        getUniformBuffersNames(): string[];
+        /**
+         * Returns the index parameters used to create the effect
+         * @returns The index parameters object
+         */
+        getIndexParameters(): any;
+        /**
          * The error from the last compilation.
          * The error from the last compilation.
          * @returns the error string.
          * @returns the error string.
          */
          */
@@ -31485,6 +31643,14 @@ declare module "babylonjs/Materials/effect" {
         private _checkIsReady;
         private _checkIsReady;
         private _loadShader;
         private _loadShader;
         /**
         /**
+         * Gets the vertex shader source code of this effect
+         */
+        get vertexSourceCode(): string;
+        /**
+         * Gets the fragment shader source code of this effect
+         */
+        get fragmentSourceCode(): string;
+        /**
          * Recompiles the webGL program
          * Recompiles the webGL program
          * @param vertexSourceCode The source code for the vertex shader.
          * @param vertexSourceCode The source code for the vertex shader.
          * @param fragmentSourceCode The source code for the fragment shader.
          * @param fragmentSourceCode The source code for the fragment shader.
@@ -54184,10 +54350,6 @@ declare module "babylonjs/Materials/PBR/pbrBaseMaterial" {
          * Defines the SubSurface parameters for the material.
          * Defines the SubSurface parameters for the material.
          */
          */
         readonly subSurface: PBRSubSurfaceConfiguration;
         readonly subSurface: PBRSubSurfaceConfiguration;
-        /**
-         * Custom callback helping to override the default shader used in the material.
-         */
-        customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: PBRMaterialDefines, attributes?: string[]) => string;
         protected _rebuildInParallel: boolean;
         protected _rebuildInParallel: boolean;
         /**
         /**
          * Instantiates a new PBRMaterial instance.
          * Instantiates a new PBRMaterial instance.
@@ -57408,7 +57570,7 @@ declare module "babylonjs/Lights/Shadows/cascadedShadowGenerator" {
         protected _initializeGenerator(): void;
         protected _initializeGenerator(): void;
         protected _createTargetRenderTexture(): void;
         protected _createTargetRenderTexture(): void;
         protected _initializeShadowMap(): void;
         protected _initializeShadowMap(): void;
-        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect): void;
+        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect, matriceNames: any): void;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
         /**
         /**
          * Prepare all the defines in a material relying on a shadow map at the specified light index.
          * Prepare all the defines in a material relying on a shadow map at the specified light index.
@@ -63903,6 +64065,7 @@ declare module "babylonjs/Materials/index" {
     export * from "babylonjs/Materials/materialFlags";
     export * from "babylonjs/Materials/materialFlags";
     export * from "babylonjs/Materials/Node/index";
     export * from "babylonjs/Materials/Node/index";
     export * from "babylonjs/Materials/effectRenderer";
     export * from "babylonjs/Materials/effectRenderer";
+    export * from "babylonjs/Materials/shadowDepthWrapper";
 }
 }
 declare module "babylonjs/Maths/index" {
 declare module "babylonjs/Maths/index" {
     export * from "babylonjs/Maths/math.scalar";
     export * from "babylonjs/Maths/math.scalar";
@@ -83650,6 +83813,13 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /** @hidden */
     /** @hidden */
+    export var shadowMapFragmentDeclaration: {
+        name: string;
+        shader: string;
+    };
+}
+declare module BABYLON {
+    /** @hidden */
     export var clipPlaneFragmentDeclaration: {
     export var clipPlaneFragmentDeclaration: {
         name: string;
         name: string;
         shader: string;
         shader: string;
@@ -83664,6 +83834,13 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /** @hidden */
     /** @hidden */
+    export var shadowMapFragment: {
+        name: string;
+        shader: string;
+    };
+}
+declare module BABYLON {
+    /** @hidden */
     export var shadowMapPixelShader: {
     export var shadowMapPixelShader: {
         name: string;
         name: string;
         shader: string;
         shader: string;
@@ -83706,6 +83883,13 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /** @hidden */
     /** @hidden */
+    export var shadowMapVertexDeclaration: {
+        name: string;
+        shader: string;
+    };
+}
+declare module BABYLON {
+    /** @hidden */
     export var clipPlaneVertexDeclaration: {
     export var clipPlaneVertexDeclaration: {
         name: string;
         name: string;
         shader: string;
         shader: string;
@@ -83734,6 +83918,20 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /** @hidden */
     /** @hidden */
+    export var shadowMapVertexNormalBias: {
+        name: string;
+        shader: string;
+    };
+}
+declare module BABYLON {
+    /** @hidden */
+    export var shadowMapVertexMetric: {
+        name: string;
+        shader: string;
+    };
+}
+declare module BABYLON {
+    /** @hidden */
     export var clipPlaneVertex: {
     export var clipPlaneVertex: {
         name: string;
         name: string;
         shader: string;
         shader: string;
@@ -83781,6 +83979,7 @@ declare module BABYLON {
         length?: number);
         length?: number);
         /**
         /**
          * Checks if the ray intersects a box
          * Checks if the ray intersects a box
+         * This does not account for the ray lenght by design to improve perfs.
          * @param minimum bound of the box
          * @param minimum bound of the box
          * @param maximum bound of the box
          * @param maximum bound of the box
          * @param intersectionTreshold extra extend to be added to the box in all direction
          * @param intersectionTreshold extra extend to be added to the box in all direction
@@ -83789,6 +83988,7 @@ declare module BABYLON {
         intersectsBoxMinMax(minimum: DeepImmutable<Vector3>, maximum: DeepImmutable<Vector3>, intersectionTreshold?: number): boolean;
         intersectsBoxMinMax(minimum: DeepImmutable<Vector3>, maximum: DeepImmutable<Vector3>, intersectionTreshold?: number): boolean;
         /**
         /**
          * Checks if the ray intersects a box
          * Checks if the ray intersects a box
+         * This does not account for the ray lenght by design to improve perfs.
          * @param box the bounding box to check
          * @param box the bounding box to check
          * @param intersectionTreshold extra extend to be added to the BoundingBox in all direction
          * @param intersectionTreshold extra extend to be added to the BoundingBox in all direction
          * @returns if the box was hit
          * @returns if the box was hit
@@ -89782,6 +89982,7 @@ declare module BABYLON {
         private _cachedWorldViewProjectionMatrix;
         private _cachedWorldViewProjectionMatrix;
         private _renderId;
         private _renderId;
         private _multiview;
         private _multiview;
+        private _cachedDefines;
         /**
         /**
          * Instantiate a new shader material.
          * Instantiate a new shader material.
          * The ShaderMaterial object has the necessary methods to pass data from your scene to the Vertex and Fragment Shaders and returns a material that can be applied to any mesh.
          * The ShaderMaterial object has the necessary methods to pass data from your scene to the Vertex and Fragment Shaders and returns a material that can be applied to any mesh.
@@ -89981,14 +90182,24 @@ declare module BABYLON {
         /**
         /**
          * Binds the world matrix to the material
          * Binds the world matrix to the material
          * @param world defines the world transformation matrix
          * @param world defines the world transformation matrix
+         * @param effectOverride - If provided, use this effect instead of internal effect
          */
          */
-        bindOnlyWorldMatrix(world: Matrix): void;
+        bindOnlyWorldMatrix(world: Matrix, effectOverride?: Nullable<Effect>): void;
+        /**
+         * Binds the submesh to this material by preparing the effect and shader to draw
+         * @param world defines the world transformation matrix
+         * @param mesh defines the mesh containing the submesh
+         * @param subMesh defines the submesh to bind the material to
+         */
+        bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         /**
         /**
          * Binds the material to the mesh
          * Binds the material to the mesh
          * @param world defines the world transformation matrix
          * @param world defines the world transformation matrix
          * @param mesh defines the mesh to bind the material to
          * @param mesh defines the mesh to bind the material to
+         * @param effectOverride - If provided, use this effect instead of internal effect
          */
          */
-        bind(world: Matrix, mesh?: Mesh): void;
+        bind(world: Matrix, mesh?: Mesh, effectOverride?: Nullable<Effect>): void;
+        protected _afterBind(mesh?: Mesh): void;
         /**
         /**
          * Gets the active textures from the material
          * Gets the active textures from the material
          * @returns an array of textures
          * @returns an array of textures
@@ -91048,7 +91259,7 @@ declare module BABYLON {
         protected _initializeShadowMap(): void;
         protected _initializeShadowMap(): void;
         protected _initializeBlurRTTAndPostProcesses(): void;
         protected _initializeBlurRTTAndPostProcesses(): void;
         protected _renderForShadowMap(opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void;
         protected _renderForShadowMap(opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void;
-        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect): void;
+        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect, matriceNames: any): void;
         protected _renderSubMeshForShadowMap(subMesh: SubMesh): void;
         protected _renderSubMeshForShadowMap(subMesh: SubMesh): void;
         protected _applyFilterValues(): void;
         protected _applyFilterValues(): void;
         /**
         /**
@@ -91068,6 +91279,7 @@ declare module BABYLON {
             useInstances: boolean;
             useInstances: boolean;
         }>): Promise<void>;
         }>): Promise<void>;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
+        private _prepareShadowDefines;
         /**
         /**
          * Determine wheter the shadow generator is ready or not (mainly all effects and related post processes needs to be ready).
          * Determine wheter the shadow generator is ready or not (mainly all effects and related post processes needs to be ready).
          * @param subMesh The submesh we want to render in the shadow map
          * @param subMesh The submesh we want to render in the shadow map
@@ -95259,6 +95471,82 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /**
     /**
+     * Class used to manipulate GUIDs
+     */
+    export class GUID {
+        /**
+         * Implementation from http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#answer-2117523
+         * Be aware Math.random() could cause collisions, but:
+         * "All but 6 of the 128 bits of the ID are randomly generated, which means that for any two ids, there's a 1 in 2^^122 (or 5.3x10^^36) chance they'll collide"
+         * @returns a pseudo random id
+         */
+        static RandomId(): string;
+    }
+}
+declare module BABYLON {
+    /**
+     * Options to be used when creating a shadow depth material
+     */
+    export interface IIOptionShadowDepthMaterial {
+        /** Variables in the vertex shader code that need to have their names remapped.
+         * The format is: ["var_name", "var_remapped_name", "var_name", "var_remapped_name", ...]
+         * "var_name" should be either: worldPos or vNormalW
+         * So, if the variable holding the world position in your vertex shader is not named worldPos, you must tell the system
+         * the name to use instead by using: ["worldPos", "myWorldPosVar"] assuming the variable is named myWorldPosVar in your code.
+         * If the normal must also be remapped: ["worldPos", "myWorldPosVar", "vNormalW", "myWorldNormal"]
+        */
+        remappedVariables?: string[];
+        /** Set standalone to true if the base material wrapped by ShadowDepthMaterial is not used for a regular object but for depth shadow generation only */
+        standalone?: boolean;
+    }
+    /**
+     * Class that can be used to wrap a base material to generate accurate shadows when using custom vertex/fragment code in the base material
+     */
+    export class ShadowDepthWrapper {
+        private _scene;
+        private _options?;
+        private _baseMaterial;
+        private _onEffectCreatedObserver;
+        private _subMeshToEffect;
+        private _subMeshToDepthEffect;
+        private _meshes;
+        /** @hidden */
+        _matriceNames: any;
+        /**
+         * Instantiate a new shadow depth wrapper.
+         * It works by injecting some specific code in the vertex/fragment shaders of the base material and is used by a shadow generator to
+         * generate the shadow depth map. For more information, please refer to the documentation:
+         * https://doc.babylonjs.com/babylon101/shadows
+         * @param baseMaterial Material to wrap
+         * @param scene Define the scene the material belongs to
+         * @param options Options used to create the wrapper
+         */
+        constructor(baseMaterial: Material, scene: Scene, options?: IIOptionShadowDepthMaterial);
+        /**
+         * Gets the effect to use to generate the depth map
+         * @param subMesh subMesh to get the effect for
+         * @param shadowGenerator shadow generator to get the effect for
+         * @returns the effect to use to generate the depth map for the subMesh + shadow generator specified
+         */
+        getEffect(subMesh: Nullable<SubMesh>, shadowGenerator: ShadowGenerator): Nullable<Effect>;
+        /**
+         * Specifies that the submesh is ready to be used for depth rendering
+         * @param subMesh submesh to check
+         * @param defines the list of defines to take into account when checking the effect
+         * @param shadowGenerator combined with subMesh, it defines the effect to check
+         * @param useInstances specifies that instances should be used
+         * @returns a boolean indicating that the submesh is ready or not
+         */
+        isReadyForSubMesh(subMesh: SubMesh, defines: string[], shadowGenerator: ShadowGenerator, useInstances: boolean): boolean;
+        /**
+         * Disposes the resources
+         */
+        dispose(): void;
+        private _makeEffect;
+    }
+}
+declare module BABYLON {
+    /**
      * Options for compiling materials.
      * Options for compiling materials.
      */
      */
     export interface IMaterialCompilationOptions {
     export interface IMaterialCompilationOptions {
@@ -95361,6 +95649,14 @@ declare module BABYLON {
          */
          */
         static readonly MATERIAL_ALPHATESTANDBLEND: number;
         static readonly MATERIAL_ALPHATESTANDBLEND: number;
         /**
         /**
+         * Custom callback helping to override the default shader used in the material.
+         */
+        customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: MaterialDefines | string[], attributes?: string[]) => string;
+        /**
+         * Custom shadow depth material to use for shadow rendering instead of the in-built one
+         */
+        shadowDepthWrapper: Nullable<ShadowDepthWrapper>;
+        /**
          * The ID of the material
          * The ID of the material
          */
          */
         id: string;
         id: string;
@@ -95483,6 +95779,17 @@ declare module BABYLON {
         * An event triggered when the material is unbound
         * An event triggered when the material is unbound
         */
         */
         get onUnBindObservable(): Observable<Material>;
         get onUnBindObservable(): Observable<Material>;
+        protected _onEffectCreatedObservable: Nullable<Observable<{
+            effect: Effect;
+            subMesh: Nullable<SubMesh>;
+        }>>;
+        /**
+        * An event triggered when the effect is (re)created
+        */
+        get onEffectCreatedObservable(): Observable<{
+            effect: Effect;
+            subMesh: Nullable<SubMesh>;
+        }>;
         /**
         /**
          * Stores the value of the alpha mode
          * Stores the value of the alpha mode
          */
          */
@@ -95984,6 +96291,8 @@ declare module BABYLON {
         _materialDefines: Nullable<MaterialDefines>;
         _materialDefines: Nullable<MaterialDefines>;
         /** @hidden */
         /** @hidden */
         _materialEffect: Nullable<Effect>;
         _materialEffect: Nullable<Effect>;
+        /** @hidden */
+        _effectOverride: Nullable<Effect>;
         /**
         /**
          * Gets material defines used by the effect associated to the sub mesh
          * Gets material defines used by the effect associated to the sub mesh
          */
          */
@@ -101332,10 +101641,6 @@ declare module BABYLON {
          * corresponding to low luminance, medium luminance, and high luminance areas respectively.
          * corresponding to low luminance, medium luminance, and high luminance areas respectively.
          */
          */
         set cameraColorCurves(value: Nullable<ColorCurves>);
         set cameraColorCurves(value: Nullable<ColorCurves>);
-        /**
-         * Custom callback helping to override the default shader used in the material.
-         */
-        customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: StandardMaterialDefines, attributes?: string[]) => string;
         protected _renderTargets: SmartArray<RenderTargetTexture>;
         protected _renderTargets: SmartArray<RenderTargetTexture>;
         protected _worldViewProjectionMatrix: Matrix;
         protected _worldViewProjectionMatrix: Matrix;
         protected _globalAmbientColor: Color3;
         protected _globalAmbientColor: Color3;
@@ -104251,20 +104556,6 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /**
     /**
-     * Class used to manipulate GUIDs
-     */
-    export class GUID {
-        /**
-         * Implementation from http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#answer-2117523
-         * Be aware Math.random() could cause collisions, but:
-         * "All but 6 of the 128 bits of the ID are randomly generated, which means that for any two ids, there's a 1 in 2^^122 (or 5.3x10^^36) chance they'll collide"
-         * @returns a pseudo random id
-         */
-        static RandomId(): string;
-    }
-}
-declare module BABYLON {
-    /**
      * Base class of all the textures in babylon.
      * Base class of all the textures in babylon.
      * It groups all the common properties the materials, post process, lights... might need
      * It groups all the common properties the materials, post process, lights... might need
      * in order to make a correct use of the texture.
      * in order to make a correct use of the texture.
@@ -104725,6 +105016,7 @@ declare module BABYLON {
         private static _uniqueIdSeed;
         private static _uniqueIdSeed;
         private _engine;
         private _engine;
         private _uniformBuffersNames;
         private _uniformBuffersNames;
+        private _uniformBuffersNamesList;
         private _uniformsNames;
         private _uniformsNames;
         private _samplerList;
         private _samplerList;
         private _samplers;
         private _samplers;
@@ -104826,10 +105118,25 @@ declare module BABYLON {
         getUniform(uniformName: string): Nullable<WebGLUniformLocation>;
         getUniform(uniformName: string): Nullable<WebGLUniformLocation>;
         /**
         /**
          * Returns an array of sampler variable names
          * Returns an array of sampler variable names
-         * @returns The array of sampler variable neames.
+         * @returns The array of sampler variable names.
          */
          */
         getSamplers(): string[];
         getSamplers(): string[];
         /**
         /**
+         * Returns an array of uniform variable names
+         * @returns The array of uniform variable names.
+         */
+        getUniformNames(): string[];
+        /**
+         * Returns an array of uniform buffer variable names
+         * @returns The array of uniform buffer variable names.
+         */
+        getUniformBuffersNames(): string[];
+        /**
+         * Returns the index parameters used to create the effect
+         * @returns The index parameters object
+         */
+        getIndexParameters(): any;
+        /**
          * The error from the last compilation.
          * The error from the last compilation.
          * @returns the error string.
          * @returns the error string.
          */
          */
@@ -104847,6 +105154,14 @@ declare module BABYLON {
         private _checkIsReady;
         private _checkIsReady;
         private _loadShader;
         private _loadShader;
         /**
         /**
+         * Gets the vertex shader source code of this effect
+         */
+        get vertexSourceCode(): string;
+        /**
+         * Gets the fragment shader source code of this effect
+         */
+        get fragmentSourceCode(): string;
+        /**
          * Recompiles the webGL program
          * Recompiles the webGL program
          * @param vertexSourceCode The source code for the vertex shader.
          * @param vertexSourceCode The source code for the vertex shader.
          * @param fragmentSourceCode The source code for the fragment shader.
          * @param fragmentSourceCode The source code for the fragment shader.
@@ -126258,10 +126573,6 @@ declare module BABYLON {
          * Defines the SubSurface parameters for the material.
          * Defines the SubSurface parameters for the material.
          */
          */
         readonly subSurface: PBRSubSurfaceConfiguration;
         readonly subSurface: PBRSubSurfaceConfiguration;
-        /**
-         * Custom callback helping to override the default shader used in the material.
-         */
-        customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: PBRMaterialDefines, attributes?: string[]) => string;
         protected _rebuildInParallel: boolean;
         protected _rebuildInParallel: boolean;
         /**
         /**
          * Instantiates a new PBRMaterial instance.
          * Instantiates a new PBRMaterial instance.
@@ -129272,7 +129583,7 @@ declare module BABYLON {
         protected _initializeGenerator(): void;
         protected _initializeGenerator(): void;
         protected _createTargetRenderTexture(): void;
         protected _createTargetRenderTexture(): void;
         protected _initializeShadowMap(): void;
         protected _initializeShadowMap(): void;
-        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect): void;
+        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect, matriceNames: any): void;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
         /**
         /**
          * Prepare all the defines in a material relying on a shadow map at the specified light index.
          * Prepare all the defines in a material relying on a shadow map at the specified light index.

+ 183 - 29
dist/preview release/documentation.d.ts

@@ -9344,6 +9344,13 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /** @hidden */
     /** @hidden */
+    export var shadowMapFragmentDeclaration: {
+        name: string;
+        shader: string;
+    };
+}
+declare module BABYLON {
+    /** @hidden */
     export var clipPlaneFragmentDeclaration: {
     export var clipPlaneFragmentDeclaration: {
         name: string;
         name: string;
         shader: string;
         shader: string;
@@ -9358,6 +9365,13 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /** @hidden */
     /** @hidden */
+    export var shadowMapFragment: {
+        name: string;
+        shader: string;
+    };
+}
+declare module BABYLON {
+    /** @hidden */
     export var shadowMapPixelShader: {
     export var shadowMapPixelShader: {
         name: string;
         name: string;
         shader: string;
         shader: string;
@@ -9400,6 +9414,13 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /** @hidden */
     /** @hidden */
+    export var shadowMapVertexDeclaration: {
+        name: string;
+        shader: string;
+    };
+}
+declare module BABYLON {
+    /** @hidden */
     export var clipPlaneVertexDeclaration: {
     export var clipPlaneVertexDeclaration: {
         name: string;
         name: string;
         shader: string;
         shader: string;
@@ -9428,6 +9449,20 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /** @hidden */
     /** @hidden */
+    export var shadowMapVertexNormalBias: {
+        name: string;
+        shader: string;
+    };
+}
+declare module BABYLON {
+    /** @hidden */
+    export var shadowMapVertexMetric: {
+        name: string;
+        shader: string;
+    };
+}
+declare module BABYLON {
+    /** @hidden */
     export var clipPlaneVertex: {
     export var clipPlaneVertex: {
         name: string;
         name: string;
         shader: string;
         shader: string;
@@ -9475,6 +9510,7 @@ declare module BABYLON {
         length?: number);
         length?: number);
         /**
         /**
          * Checks if the ray intersects a box
          * Checks if the ray intersects a box
+         * This does not account for the ray lenght by design to improve perfs.
          * @param minimum bound of the box
          * @param minimum bound of the box
          * @param maximum bound of the box
          * @param maximum bound of the box
          * @param intersectionTreshold extra extend to be added to the box in all direction
          * @param intersectionTreshold extra extend to be added to the box in all direction
@@ -9483,6 +9519,7 @@ declare module BABYLON {
         intersectsBoxMinMax(minimum: DeepImmutable<Vector3>, maximum: DeepImmutable<Vector3>, intersectionTreshold?: number): boolean;
         intersectsBoxMinMax(minimum: DeepImmutable<Vector3>, maximum: DeepImmutable<Vector3>, intersectionTreshold?: number): boolean;
         /**
         /**
          * Checks if the ray intersects a box
          * Checks if the ray intersects a box
+         * This does not account for the ray lenght by design to improve perfs.
          * @param box the bounding box to check
          * @param box the bounding box to check
          * @param intersectionTreshold extra extend to be added to the BoundingBox in all direction
          * @param intersectionTreshold extra extend to be added to the BoundingBox in all direction
          * @returns if the box was hit
          * @returns if the box was hit
@@ -15476,6 +15513,7 @@ declare module BABYLON {
         private _cachedWorldViewProjectionMatrix;
         private _cachedWorldViewProjectionMatrix;
         private _renderId;
         private _renderId;
         private _multiview;
         private _multiview;
+        private _cachedDefines;
         /**
         /**
          * Instantiate a new shader material.
          * Instantiate a new shader material.
          * The ShaderMaterial object has the necessary methods to pass data from your scene to the Vertex and Fragment Shaders and returns a material that can be applied to any mesh.
          * The ShaderMaterial object has the necessary methods to pass data from your scene to the Vertex and Fragment Shaders and returns a material that can be applied to any mesh.
@@ -15675,14 +15713,24 @@ declare module BABYLON {
         /**
         /**
          * Binds the world matrix to the material
          * Binds the world matrix to the material
          * @param world defines the world transformation matrix
          * @param world defines the world transformation matrix
+         * @param effectOverride - If provided, use this effect instead of internal effect
          */
          */
-        bindOnlyWorldMatrix(world: Matrix): void;
+        bindOnlyWorldMatrix(world: Matrix, effectOverride?: Nullable<Effect>): void;
+        /**
+         * Binds the submesh to this material by preparing the effect and shader to draw
+         * @param world defines the world transformation matrix
+         * @param mesh defines the mesh containing the submesh
+         * @param subMesh defines the submesh to bind the material to
+         */
+        bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         /**
         /**
          * Binds the material to the mesh
          * Binds the material to the mesh
          * @param world defines the world transformation matrix
          * @param world defines the world transformation matrix
          * @param mesh defines the mesh to bind the material to
          * @param mesh defines the mesh to bind the material to
+         * @param effectOverride - If provided, use this effect instead of internal effect
          */
          */
-        bind(world: Matrix, mesh?: Mesh): void;
+        bind(world: Matrix, mesh?: Mesh, effectOverride?: Nullable<Effect>): void;
+        protected _afterBind(mesh?: Mesh): void;
         /**
         /**
          * Gets the active textures from the material
          * Gets the active textures from the material
          * @returns an array of textures
          * @returns an array of textures
@@ -16742,7 +16790,7 @@ declare module BABYLON {
         protected _initializeShadowMap(): void;
         protected _initializeShadowMap(): void;
         protected _initializeBlurRTTAndPostProcesses(): void;
         protected _initializeBlurRTTAndPostProcesses(): void;
         protected _renderForShadowMap(opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void;
         protected _renderForShadowMap(opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void;
-        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect): void;
+        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect, matriceNames: any): void;
         protected _renderSubMeshForShadowMap(subMesh: SubMesh): void;
         protected _renderSubMeshForShadowMap(subMesh: SubMesh): void;
         protected _applyFilterValues(): void;
         protected _applyFilterValues(): void;
         /**
         /**
@@ -16762,6 +16810,7 @@ declare module BABYLON {
             useInstances: boolean;
             useInstances: boolean;
         }>): Promise<void>;
         }>): Promise<void>;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
+        private _prepareShadowDefines;
         /**
         /**
          * Determine wheter the shadow generator is ready or not (mainly all effects and related post processes needs to be ready).
          * Determine wheter the shadow generator is ready or not (mainly all effects and related post processes needs to be ready).
          * @param subMesh The submesh we want to render in the shadow map
          * @param subMesh The submesh we want to render in the shadow map
@@ -20953,6 +21002,82 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /**
     /**
+     * Class used to manipulate GUIDs
+     */
+    export class GUID {
+        /**
+         * Implementation from http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#answer-2117523
+         * Be aware Math.random() could cause collisions, but:
+         * "All but 6 of the 128 bits of the ID are randomly generated, which means that for any two ids, there's a 1 in 2^^122 (or 5.3x10^^36) chance they'll collide"
+         * @returns a pseudo random id
+         */
+        static RandomId(): string;
+    }
+}
+declare module BABYLON {
+    /**
+     * Options to be used when creating a shadow depth material
+     */
+    export interface IIOptionShadowDepthMaterial {
+        /** Variables in the vertex shader code that need to have their names remapped.
+         * The format is: ["var_name", "var_remapped_name", "var_name", "var_remapped_name", ...]
+         * "var_name" should be either: worldPos or vNormalW
+         * So, if the variable holding the world position in your vertex shader is not named worldPos, you must tell the system
+         * the name to use instead by using: ["worldPos", "myWorldPosVar"] assuming the variable is named myWorldPosVar in your code.
+         * If the normal must also be remapped: ["worldPos", "myWorldPosVar", "vNormalW", "myWorldNormal"]
+        */
+        remappedVariables?: string[];
+        /** Set standalone to true if the base material wrapped by ShadowDepthMaterial is not used for a regular object but for depth shadow generation only */
+        standalone?: boolean;
+    }
+    /**
+     * Class that can be used to wrap a base material to generate accurate shadows when using custom vertex/fragment code in the base material
+     */
+    export class ShadowDepthWrapper {
+        private _scene;
+        private _options?;
+        private _baseMaterial;
+        private _onEffectCreatedObserver;
+        private _subMeshToEffect;
+        private _subMeshToDepthEffect;
+        private _meshes;
+        /** @hidden */
+        _matriceNames: any;
+        /**
+         * Instantiate a new shadow depth wrapper.
+         * It works by injecting some specific code in the vertex/fragment shaders of the base material and is used by a shadow generator to
+         * generate the shadow depth map. For more information, please refer to the documentation:
+         * https://doc.babylonjs.com/babylon101/shadows
+         * @param baseMaterial Material to wrap
+         * @param scene Define the scene the material belongs to
+         * @param options Options used to create the wrapper
+         */
+        constructor(baseMaterial: Material, scene: Scene, options?: IIOptionShadowDepthMaterial);
+        /**
+         * Gets the effect to use to generate the depth map
+         * @param subMesh subMesh to get the effect for
+         * @param shadowGenerator shadow generator to get the effect for
+         * @returns the effect to use to generate the depth map for the subMesh + shadow generator specified
+         */
+        getEffect(subMesh: Nullable<SubMesh>, shadowGenerator: ShadowGenerator): Nullable<Effect>;
+        /**
+         * Specifies that the submesh is ready to be used for depth rendering
+         * @param subMesh submesh to check
+         * @param defines the list of defines to take into account when checking the effect
+         * @param shadowGenerator combined with subMesh, it defines the effect to check
+         * @param useInstances specifies that instances should be used
+         * @returns a boolean indicating that the submesh is ready or not
+         */
+        isReadyForSubMesh(subMesh: SubMesh, defines: string[], shadowGenerator: ShadowGenerator, useInstances: boolean): boolean;
+        /**
+         * Disposes the resources
+         */
+        dispose(): void;
+        private _makeEffect;
+    }
+}
+declare module BABYLON {
+    /**
      * Options for compiling materials.
      * Options for compiling materials.
      */
      */
     export interface IMaterialCompilationOptions {
     export interface IMaterialCompilationOptions {
@@ -21055,6 +21180,14 @@ declare module BABYLON {
          */
          */
         static readonly MATERIAL_ALPHATESTANDBLEND: number;
         static readonly MATERIAL_ALPHATESTANDBLEND: number;
         /**
         /**
+         * Custom callback helping to override the default shader used in the material.
+         */
+        customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: MaterialDefines | string[], attributes?: string[]) => string;
+        /**
+         * Custom shadow depth material to use for shadow rendering instead of the in-built one
+         */
+        shadowDepthWrapper: Nullable<ShadowDepthWrapper>;
+        /**
          * The ID of the material
          * The ID of the material
          */
          */
         id: string;
         id: string;
@@ -21177,6 +21310,17 @@ declare module BABYLON {
         * An event triggered when the material is unbound
         * An event triggered when the material is unbound
         */
         */
         get onUnBindObservable(): Observable<Material>;
         get onUnBindObservable(): Observable<Material>;
+        protected _onEffectCreatedObservable: Nullable<Observable<{
+            effect: Effect;
+            subMesh: Nullable<SubMesh>;
+        }>>;
+        /**
+        * An event triggered when the effect is (re)created
+        */
+        get onEffectCreatedObservable(): Observable<{
+            effect: Effect;
+            subMesh: Nullable<SubMesh>;
+        }>;
         /**
         /**
          * Stores the value of the alpha mode
          * Stores the value of the alpha mode
          */
          */
@@ -21678,6 +21822,8 @@ declare module BABYLON {
         _materialDefines: Nullable<MaterialDefines>;
         _materialDefines: Nullable<MaterialDefines>;
         /** @hidden */
         /** @hidden */
         _materialEffect: Nullable<Effect>;
         _materialEffect: Nullable<Effect>;
+        /** @hidden */
+        _effectOverride: Nullable<Effect>;
         /**
         /**
          * Gets material defines used by the effect associated to the sub mesh
          * Gets material defines used by the effect associated to the sub mesh
          */
          */
@@ -27026,10 +27172,6 @@ declare module BABYLON {
          * corresponding to low luminance, medium luminance, and high luminance areas respectively.
          * corresponding to low luminance, medium luminance, and high luminance areas respectively.
          */
          */
         set cameraColorCurves(value: Nullable<ColorCurves>);
         set cameraColorCurves(value: Nullable<ColorCurves>);
-        /**
-         * Custom callback helping to override the default shader used in the material.
-         */
-        customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: StandardMaterialDefines, attributes?: string[]) => string;
         protected _renderTargets: SmartArray<RenderTargetTexture>;
         protected _renderTargets: SmartArray<RenderTargetTexture>;
         protected _worldViewProjectionMatrix: Matrix;
         protected _worldViewProjectionMatrix: Matrix;
         protected _globalAmbientColor: Color3;
         protected _globalAmbientColor: Color3;
@@ -29945,20 +30087,6 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /**
     /**
-     * Class used to manipulate GUIDs
-     */
-    export class GUID {
-        /**
-         * Implementation from http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#answer-2117523
-         * Be aware Math.random() could cause collisions, but:
-         * "All but 6 of the 128 bits of the ID are randomly generated, which means that for any two ids, there's a 1 in 2^^122 (or 5.3x10^^36) chance they'll collide"
-         * @returns a pseudo random id
-         */
-        static RandomId(): string;
-    }
-}
-declare module BABYLON {
-    /**
      * Base class of all the textures in babylon.
      * Base class of all the textures in babylon.
      * It groups all the common properties the materials, post process, lights... might need
      * It groups all the common properties the materials, post process, lights... might need
      * in order to make a correct use of the texture.
      * in order to make a correct use of the texture.
@@ -30419,6 +30547,7 @@ declare module BABYLON {
         private static _uniqueIdSeed;
         private static _uniqueIdSeed;
         private _engine;
         private _engine;
         private _uniformBuffersNames;
         private _uniformBuffersNames;
+        private _uniformBuffersNamesList;
         private _uniformsNames;
         private _uniformsNames;
         private _samplerList;
         private _samplerList;
         private _samplers;
         private _samplers;
@@ -30520,10 +30649,25 @@ declare module BABYLON {
         getUniform(uniformName: string): Nullable<WebGLUniformLocation>;
         getUniform(uniformName: string): Nullable<WebGLUniformLocation>;
         /**
         /**
          * Returns an array of sampler variable names
          * Returns an array of sampler variable names
-         * @returns The array of sampler variable neames.
+         * @returns The array of sampler variable names.
          */
          */
         getSamplers(): string[];
         getSamplers(): string[];
         /**
         /**
+         * Returns an array of uniform variable names
+         * @returns The array of uniform variable names.
+         */
+        getUniformNames(): string[];
+        /**
+         * Returns an array of uniform buffer variable names
+         * @returns The array of uniform buffer variable names.
+         */
+        getUniformBuffersNames(): string[];
+        /**
+         * Returns the index parameters used to create the effect
+         * @returns The index parameters object
+         */
+        getIndexParameters(): any;
+        /**
          * The error from the last compilation.
          * The error from the last compilation.
          * @returns the error string.
          * @returns the error string.
          */
          */
@@ -30541,6 +30685,14 @@ declare module BABYLON {
         private _checkIsReady;
         private _checkIsReady;
         private _loadShader;
         private _loadShader;
         /**
         /**
+         * Gets the vertex shader source code of this effect
+         */
+        get vertexSourceCode(): string;
+        /**
+         * Gets the fragment shader source code of this effect
+         */
+        get fragmentSourceCode(): string;
+        /**
          * Recompiles the webGL program
          * Recompiles the webGL program
          * @param vertexSourceCode The source code for the vertex shader.
          * @param vertexSourceCode The source code for the vertex shader.
          * @param fragmentSourceCode The source code for the fragment shader.
          * @param fragmentSourceCode The source code for the fragment shader.
@@ -51952,10 +52104,6 @@ declare module BABYLON {
          * Defines the SubSurface parameters for the material.
          * Defines the SubSurface parameters for the material.
          */
          */
         readonly subSurface: PBRSubSurfaceConfiguration;
         readonly subSurface: PBRSubSurfaceConfiguration;
-        /**
-         * Custom callback helping to override the default shader used in the material.
-         */
-        customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: PBRMaterialDefines, attributes?: string[]) => string;
         protected _rebuildInParallel: boolean;
         protected _rebuildInParallel: boolean;
         /**
         /**
          * Instantiates a new PBRMaterial instance.
          * Instantiates a new PBRMaterial instance.
@@ -54966,7 +55114,7 @@ declare module BABYLON {
         protected _initializeGenerator(): void;
         protected _initializeGenerator(): void;
         protected _createTargetRenderTexture(): void;
         protected _createTargetRenderTexture(): void;
         protected _initializeShadowMap(): void;
         protected _initializeShadowMap(): void;
-        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect): void;
+        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect, matriceNames: any): void;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
         /**
         /**
          * Prepare all the defines in a material relying on a shadow map at the specified light index.
          * Prepare all the defines in a material relying on a shadow map at the specified light index.
@@ -74197,6 +74345,8 @@ declare module BABYLON.GUI {
         private _barImageHeight;
         private _barImageHeight;
         private _horizontalBarImageHeight;
         private _horizontalBarImageHeight;
         private _verticalBarImageHeight;
         private _verticalBarImageHeight;
+        private _oldWindowContentsWidth;
+        private _oldWindowContentsHeight;
         /**
         /**
          * Gets the horizontal scrollbar
          * Gets the horizontal scrollbar
          */
          */
@@ -79748,6 +79898,7 @@ declare module BABYLON {
         Vertex_MainBegin: string;
         Vertex_MainBegin: string;
         Vertex_Before_PositionUpdated: string;
         Vertex_Before_PositionUpdated: string;
         Vertex_Before_NormalUpdated: string;
         Vertex_Before_NormalUpdated: string;
+        Vertex_After_WorldPosComputed: string;
         Vertex_MainEnd: string;
         Vertex_MainEnd: string;
     }
     }
     export class CustomMaterial extends BABYLON.StandardMaterial {
     export class CustomMaterial extends BABYLON.StandardMaterial {
@@ -79764,7 +79915,7 @@ declare module BABYLON {
         VertexShader: string;
         VertexShader: string;
         AttachAfterBind(mesh: BABYLON.Mesh, effect: BABYLON.Effect): void;
         AttachAfterBind(mesh: BABYLON.Mesh, effect: BABYLON.Effect): void;
         ReviewUniform(name: string, arr: string[]): string[];
         ReviewUniform(name: string, arr: string[]): string[];
-        Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: BABYLON.StandardMaterialDefines, attributes?: string[]): string;
+        Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: BABYLON.MaterialDefines | string[], attributes?: string[]): string;
         constructor(name: string, scene: BABYLON.Scene);
         constructor(name: string, scene: BABYLON.Scene);
         AddUniform(name: string, kind: string, param: any): CustomMaterial;
         AddUniform(name: string, kind: string, param: any): CustomMaterial;
         AddAttribute(name: string): CustomMaterial;
         AddAttribute(name: string): CustomMaterial;
@@ -79781,6 +79932,7 @@ declare module BABYLON {
         Vertex_MainBegin(shaderPart: string): CustomMaterial;
         Vertex_MainBegin(shaderPart: string): CustomMaterial;
         Vertex_Before_PositionUpdated(shaderPart: string): CustomMaterial;
         Vertex_Before_PositionUpdated(shaderPart: string): CustomMaterial;
         Vertex_Before_NormalUpdated(shaderPart: string): CustomMaterial;
         Vertex_Before_NormalUpdated(shaderPart: string): CustomMaterial;
+        Vertex_After_WorldPosComputed(shaderPart: string): CustomMaterial;
         Vertex_MainEnd(shaderPart: string): CustomMaterial;
         Vertex_MainEnd(shaderPart: string): CustomMaterial;
     }
     }
 }
 }
@@ -79802,6 +79954,7 @@ declare module BABYLON {
         Vertex_MainBegin: string;
         Vertex_MainBegin: string;
         Vertex_Before_PositionUpdated: string;
         Vertex_Before_PositionUpdated: string;
         Vertex_Before_NormalUpdated: string;
         Vertex_Before_NormalUpdated: string;
+        Vertex_After_WorldPosComputed: string;
         Vertex_MainEnd: string;
         Vertex_MainEnd: string;
     }
     }
     export class PBRCustomMaterial extends BABYLON.PBRMaterial {
     export class PBRCustomMaterial extends BABYLON.PBRMaterial {
@@ -79818,7 +79971,7 @@ declare module BABYLON {
         VertexShader: string;
         VertexShader: string;
         AttachAfterBind(mesh: BABYLON.Mesh, effect: BABYLON.Effect): void;
         AttachAfterBind(mesh: BABYLON.Mesh, effect: BABYLON.Effect): void;
         ReviewUniform(name: string, arr: string[]): string[];
         ReviewUniform(name: string, arr: string[]): string[];
-        Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: BABYLON.PBRMaterialDefines, attributes?: string[]): string;
+        Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: BABYLON.MaterialDefines | string[], attributes?: string[]): string;
         constructor(name: string, scene: BABYLON.Scene);
         constructor(name: string, scene: BABYLON.Scene);
         AddUniform(name: string, kind: string, param: any): PBRCustomMaterial;
         AddUniform(name: string, kind: string, param: any): PBRCustomMaterial;
         AddAttribute(name: string): PBRCustomMaterial;
         AddAttribute(name: string): PBRCustomMaterial;
@@ -79837,6 +79990,7 @@ declare module BABYLON {
         Vertex_MainBegin(shaderPart: string): PBRCustomMaterial;
         Vertex_MainBegin(shaderPart: string): PBRCustomMaterial;
         Vertex_Before_PositionUpdated(shaderPart: string): PBRCustomMaterial;
         Vertex_Before_PositionUpdated(shaderPart: string): PBRCustomMaterial;
         Vertex_Before_NormalUpdated(shaderPart: string): PBRCustomMaterial;
         Vertex_Before_NormalUpdated(shaderPart: string): PBRCustomMaterial;
+        Vertex_After_WorldPosComputed(shaderPart: string): PBRCustomMaterial;
         Vertex_MainEnd(shaderPart: string): PBRCustomMaterial;
         Vertex_MainEnd(shaderPart: string): PBRCustomMaterial;
     }
     }
 }
 }

+ 2 - 0
dist/preview release/gui/babylon.gui.d.ts

@@ -3057,6 +3057,8 @@ declare module BABYLON.GUI {
         private _barImageHeight;
         private _barImageHeight;
         private _horizontalBarImageHeight;
         private _horizontalBarImageHeight;
         private _verticalBarImageHeight;
         private _verticalBarImageHeight;
+        private _oldWindowContentsWidth;
+        private _oldWindowContentsHeight;
         /**
         /**
          * Gets the horizontal scrollbar
          * Gets the horizontal scrollbar
          */
          */

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js


+ 4 - 0
dist/preview release/gui/babylon.gui.module.d.ts

@@ -3186,6 +3186,8 @@ declare module "babylonjs-gui/2D/controls/scrollViewers/scrollViewer" {
         private _barImageHeight;
         private _barImageHeight;
         private _horizontalBarImageHeight;
         private _horizontalBarImageHeight;
         private _verticalBarImageHeight;
         private _verticalBarImageHeight;
+        private _oldWindowContentsWidth;
+        private _oldWindowContentsHeight;
         /**
         /**
          * Gets the horizontal scrollbar
          * Gets the horizontal scrollbar
          */
          */
@@ -7426,6 +7428,8 @@ declare module BABYLON.GUI {
         private _barImageHeight;
         private _barImageHeight;
         private _horizontalBarImageHeight;
         private _horizontalBarImageHeight;
         private _verticalBarImageHeight;
         private _verticalBarImageHeight;
+        private _oldWindowContentsWidth;
+        private _oldWindowContentsHeight;
         /**
         /**
          * Gets the horizontal scrollbar
          * Gets the horizontal scrollbar
          */
          */

Разница между файлами не показана из-за своего большого размера
+ 2 - 2
dist/preview release/materialsLibrary/babylon.customMaterial.min.js


+ 6 - 2
dist/preview release/materialsLibrary/babylonjs.materials.d.ts

@@ -60,6 +60,7 @@ declare module BABYLON {
         Vertex_MainBegin: string;
         Vertex_MainBegin: string;
         Vertex_Before_PositionUpdated: string;
         Vertex_Before_PositionUpdated: string;
         Vertex_Before_NormalUpdated: string;
         Vertex_Before_NormalUpdated: string;
+        Vertex_After_WorldPosComputed: string;
         Vertex_MainEnd: string;
         Vertex_MainEnd: string;
     }
     }
     export class CustomMaterial extends BABYLON.StandardMaterial {
     export class CustomMaterial extends BABYLON.StandardMaterial {
@@ -76,7 +77,7 @@ declare module BABYLON {
         VertexShader: string;
         VertexShader: string;
         AttachAfterBind(mesh: BABYLON.Mesh, effect: BABYLON.Effect): void;
         AttachAfterBind(mesh: BABYLON.Mesh, effect: BABYLON.Effect): void;
         ReviewUniform(name: string, arr: string[]): string[];
         ReviewUniform(name: string, arr: string[]): string[];
-        Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: BABYLON.StandardMaterialDefines, attributes?: string[]): string;
+        Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: BABYLON.MaterialDefines | string[], attributes?: string[]): string;
         constructor(name: string, scene: BABYLON.Scene);
         constructor(name: string, scene: BABYLON.Scene);
         AddUniform(name: string, kind: string, param: any): CustomMaterial;
         AddUniform(name: string, kind: string, param: any): CustomMaterial;
         AddAttribute(name: string): CustomMaterial;
         AddAttribute(name: string): CustomMaterial;
@@ -93,6 +94,7 @@ declare module BABYLON {
         Vertex_MainBegin(shaderPart: string): CustomMaterial;
         Vertex_MainBegin(shaderPart: string): CustomMaterial;
         Vertex_Before_PositionUpdated(shaderPart: string): CustomMaterial;
         Vertex_Before_PositionUpdated(shaderPart: string): CustomMaterial;
         Vertex_Before_NormalUpdated(shaderPart: string): CustomMaterial;
         Vertex_Before_NormalUpdated(shaderPart: string): CustomMaterial;
+        Vertex_After_WorldPosComputed(shaderPart: string): CustomMaterial;
         Vertex_MainEnd(shaderPart: string): CustomMaterial;
         Vertex_MainEnd(shaderPart: string): CustomMaterial;
     }
     }
 }
 }
@@ -114,6 +116,7 @@ declare module BABYLON {
         Vertex_MainBegin: string;
         Vertex_MainBegin: string;
         Vertex_Before_PositionUpdated: string;
         Vertex_Before_PositionUpdated: string;
         Vertex_Before_NormalUpdated: string;
         Vertex_Before_NormalUpdated: string;
+        Vertex_After_WorldPosComputed: string;
         Vertex_MainEnd: string;
         Vertex_MainEnd: string;
     }
     }
     export class PBRCustomMaterial extends BABYLON.PBRMaterial {
     export class PBRCustomMaterial extends BABYLON.PBRMaterial {
@@ -130,7 +133,7 @@ declare module BABYLON {
         VertexShader: string;
         VertexShader: string;
         AttachAfterBind(mesh: BABYLON.Mesh, effect: BABYLON.Effect): void;
         AttachAfterBind(mesh: BABYLON.Mesh, effect: BABYLON.Effect): void;
         ReviewUniform(name: string, arr: string[]): string[];
         ReviewUniform(name: string, arr: string[]): string[];
-        Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: BABYLON.PBRMaterialDefines, attributes?: string[]): string;
+        Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: BABYLON.MaterialDefines | string[], attributes?: string[]): string;
         constructor(name: string, scene: BABYLON.Scene);
         constructor(name: string, scene: BABYLON.Scene);
         AddUniform(name: string, kind: string, param: any): PBRCustomMaterial;
         AddUniform(name: string, kind: string, param: any): PBRCustomMaterial;
         AddAttribute(name: string): PBRCustomMaterial;
         AddAttribute(name: string): PBRCustomMaterial;
@@ -149,6 +152,7 @@ declare module BABYLON {
         Vertex_MainBegin(shaderPart: string): PBRCustomMaterial;
         Vertex_MainBegin(shaderPart: string): PBRCustomMaterial;
         Vertex_Before_PositionUpdated(shaderPart: string): PBRCustomMaterial;
         Vertex_Before_PositionUpdated(shaderPart: string): PBRCustomMaterial;
         Vertex_Before_NormalUpdated(shaderPart: string): PBRCustomMaterial;
         Vertex_Before_NormalUpdated(shaderPart: string): PBRCustomMaterial;
+        Vertex_After_WorldPosComputed(shaderPart: string): PBRCustomMaterial;
         Vertex_MainEnd(shaderPart: string): PBRCustomMaterial;
         Vertex_MainEnd(shaderPart: string): PBRCustomMaterial;
     }
     }
 }
 }

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/materialsLibrary/babylonjs.materials.min.js


+ 14 - 6
dist/preview release/materialsLibrary/babylonjs.materials.module.d.ts

@@ -79,7 +79,7 @@ declare module "babylonjs-materials/cell/index" {
 declare module "babylonjs-materials/custom/customMaterial" {
 declare module "babylonjs-materials/custom/customMaterial" {
     import { Texture } from "babylonjs/Materials/Textures/texture";
     import { Texture } from "babylonjs/Materials/Textures/texture";
     import { Effect } from "babylonjs/Materials/effect";
     import { Effect } from "babylonjs/Materials/effect";
-    import { StandardMaterialDefines } from "babylonjs/Materials/standardMaterial";
+    import { MaterialDefines } from "babylonjs/Materials/materialDefines";
     import { StandardMaterial } from "babylonjs/Materials/standardMaterial";
     import { StandardMaterial } from "babylonjs/Materials/standardMaterial";
     import { Mesh } from "babylonjs/Meshes/mesh";
     import { Mesh } from "babylonjs/Meshes/mesh";
     import { Scene } from "babylonjs/scene";
     import { Scene } from "babylonjs/scene";
@@ -103,6 +103,7 @@ declare module "babylonjs-materials/custom/customMaterial" {
         Vertex_MainBegin: string;
         Vertex_MainBegin: string;
         Vertex_Before_PositionUpdated: string;
         Vertex_Before_PositionUpdated: string;
         Vertex_Before_NormalUpdated: string;
         Vertex_Before_NormalUpdated: string;
+        Vertex_After_WorldPosComputed: string;
         Vertex_MainEnd: string;
         Vertex_MainEnd: string;
     }
     }
     export class CustomMaterial extends StandardMaterial {
     export class CustomMaterial extends StandardMaterial {
@@ -119,7 +120,7 @@ declare module "babylonjs-materials/custom/customMaterial" {
         VertexShader: string;
         VertexShader: string;
         AttachAfterBind(mesh: Mesh, effect: Effect): void;
         AttachAfterBind(mesh: Mesh, effect: Effect): void;
         ReviewUniform(name: string, arr: string[]): string[];
         ReviewUniform(name: string, arr: string[]): string[];
-        Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: StandardMaterialDefines, attributes?: string[]): string;
+        Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: MaterialDefines | string[], attributes?: string[]): string;
         constructor(name: string, scene: Scene);
         constructor(name: string, scene: Scene);
         AddUniform(name: string, kind: string, param: any): CustomMaterial;
         AddUniform(name: string, kind: string, param: any): CustomMaterial;
         AddAttribute(name: string): CustomMaterial;
         AddAttribute(name: string): CustomMaterial;
@@ -136,13 +137,14 @@ declare module "babylonjs-materials/custom/customMaterial" {
         Vertex_MainBegin(shaderPart: string): CustomMaterial;
         Vertex_MainBegin(shaderPart: string): CustomMaterial;
         Vertex_Before_PositionUpdated(shaderPart: string): CustomMaterial;
         Vertex_Before_PositionUpdated(shaderPart: string): CustomMaterial;
         Vertex_Before_NormalUpdated(shaderPart: string): CustomMaterial;
         Vertex_Before_NormalUpdated(shaderPart: string): CustomMaterial;
+        Vertex_After_WorldPosComputed(shaderPart: string): CustomMaterial;
         Vertex_MainEnd(shaderPart: string): CustomMaterial;
         Vertex_MainEnd(shaderPart: string): CustomMaterial;
     }
     }
 }
 }
 declare module "babylonjs-materials/custom/pbrCustomMaterial" {
 declare module "babylonjs-materials/custom/pbrCustomMaterial" {
     import { Texture } from "babylonjs/Materials/Textures/texture";
     import { Texture } from "babylonjs/Materials/Textures/texture";
     import { Effect } from "babylonjs/Materials/effect";
     import { Effect } from "babylonjs/Materials/effect";
-    import { PBRMaterialDefines } from "babylonjs/Materials/PBR/pbrBaseMaterial";
+    import { MaterialDefines } from "babylonjs/Materials/materialDefines";
     import { PBRMaterial } from "babylonjs/Materials/PBR/pbrMaterial";
     import { PBRMaterial } from "babylonjs/Materials/PBR/pbrMaterial";
     import { Mesh } from "babylonjs/Meshes/mesh";
     import { Mesh } from "babylonjs/Meshes/mesh";
     import { Scene } from "babylonjs/scene";
     import { Scene } from "babylonjs/scene";
@@ -163,6 +165,7 @@ declare module "babylonjs-materials/custom/pbrCustomMaterial" {
         Vertex_MainBegin: string;
         Vertex_MainBegin: string;
         Vertex_Before_PositionUpdated: string;
         Vertex_Before_PositionUpdated: string;
         Vertex_Before_NormalUpdated: string;
         Vertex_Before_NormalUpdated: string;
+        Vertex_After_WorldPosComputed: string;
         Vertex_MainEnd: string;
         Vertex_MainEnd: string;
     }
     }
     export class PBRCustomMaterial extends PBRMaterial {
     export class PBRCustomMaterial extends PBRMaterial {
@@ -179,7 +182,7 @@ declare module "babylonjs-materials/custom/pbrCustomMaterial" {
         VertexShader: string;
         VertexShader: string;
         AttachAfterBind(mesh: Mesh, effect: Effect): void;
         AttachAfterBind(mesh: Mesh, effect: Effect): void;
         ReviewUniform(name: string, arr: string[]): string[];
         ReviewUniform(name: string, arr: string[]): string[];
-        Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: PBRMaterialDefines, attributes?: string[]): string;
+        Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: MaterialDefines | string[], attributes?: string[]): string;
         constructor(name: string, scene: Scene);
         constructor(name: string, scene: Scene);
         AddUniform(name: string, kind: string, param: any): PBRCustomMaterial;
         AddUniform(name: string, kind: string, param: any): PBRCustomMaterial;
         AddAttribute(name: string): PBRCustomMaterial;
         AddAttribute(name: string): PBRCustomMaterial;
@@ -198,6 +201,7 @@ declare module "babylonjs-materials/custom/pbrCustomMaterial" {
         Vertex_MainBegin(shaderPart: string): PBRCustomMaterial;
         Vertex_MainBegin(shaderPart: string): PBRCustomMaterial;
         Vertex_Before_PositionUpdated(shaderPart: string): PBRCustomMaterial;
         Vertex_Before_PositionUpdated(shaderPart: string): PBRCustomMaterial;
         Vertex_Before_NormalUpdated(shaderPart: string): PBRCustomMaterial;
         Vertex_Before_NormalUpdated(shaderPart: string): PBRCustomMaterial;
+        Vertex_After_WorldPosComputed(shaderPart: string): PBRCustomMaterial;
         Vertex_MainEnd(shaderPart: string): PBRCustomMaterial;
         Vertex_MainEnd(shaderPart: string): PBRCustomMaterial;
     }
     }
 }
 }
@@ -1615,6 +1619,7 @@ declare module BABYLON {
         Vertex_MainBegin: string;
         Vertex_MainBegin: string;
         Vertex_Before_PositionUpdated: string;
         Vertex_Before_PositionUpdated: string;
         Vertex_Before_NormalUpdated: string;
         Vertex_Before_NormalUpdated: string;
+        Vertex_After_WorldPosComputed: string;
         Vertex_MainEnd: string;
         Vertex_MainEnd: string;
     }
     }
     export class CustomMaterial extends BABYLON.StandardMaterial {
     export class CustomMaterial extends BABYLON.StandardMaterial {
@@ -1631,7 +1636,7 @@ declare module BABYLON {
         VertexShader: string;
         VertexShader: string;
         AttachAfterBind(mesh: BABYLON.Mesh, effect: BABYLON.Effect): void;
         AttachAfterBind(mesh: BABYLON.Mesh, effect: BABYLON.Effect): void;
         ReviewUniform(name: string, arr: string[]): string[];
         ReviewUniform(name: string, arr: string[]): string[];
-        Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: BABYLON.StandardMaterialDefines, attributes?: string[]): string;
+        Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: BABYLON.MaterialDefines | string[], attributes?: string[]): string;
         constructor(name: string, scene: BABYLON.Scene);
         constructor(name: string, scene: BABYLON.Scene);
         AddUniform(name: string, kind: string, param: any): CustomMaterial;
         AddUniform(name: string, kind: string, param: any): CustomMaterial;
         AddAttribute(name: string): CustomMaterial;
         AddAttribute(name: string): CustomMaterial;
@@ -1648,6 +1653,7 @@ declare module BABYLON {
         Vertex_MainBegin(shaderPart: string): CustomMaterial;
         Vertex_MainBegin(shaderPart: string): CustomMaterial;
         Vertex_Before_PositionUpdated(shaderPart: string): CustomMaterial;
         Vertex_Before_PositionUpdated(shaderPart: string): CustomMaterial;
         Vertex_Before_NormalUpdated(shaderPart: string): CustomMaterial;
         Vertex_Before_NormalUpdated(shaderPart: string): CustomMaterial;
+        Vertex_After_WorldPosComputed(shaderPart: string): CustomMaterial;
         Vertex_MainEnd(shaderPart: string): CustomMaterial;
         Vertex_MainEnd(shaderPart: string): CustomMaterial;
     }
     }
 }
 }
@@ -1669,6 +1675,7 @@ declare module BABYLON {
         Vertex_MainBegin: string;
         Vertex_MainBegin: string;
         Vertex_Before_PositionUpdated: string;
         Vertex_Before_PositionUpdated: string;
         Vertex_Before_NormalUpdated: string;
         Vertex_Before_NormalUpdated: string;
+        Vertex_After_WorldPosComputed: string;
         Vertex_MainEnd: string;
         Vertex_MainEnd: string;
     }
     }
     export class PBRCustomMaterial extends BABYLON.PBRMaterial {
     export class PBRCustomMaterial extends BABYLON.PBRMaterial {
@@ -1685,7 +1692,7 @@ declare module BABYLON {
         VertexShader: string;
         VertexShader: string;
         AttachAfterBind(mesh: BABYLON.Mesh, effect: BABYLON.Effect): void;
         AttachAfterBind(mesh: BABYLON.Mesh, effect: BABYLON.Effect): void;
         ReviewUniform(name: string, arr: string[]): string[];
         ReviewUniform(name: string, arr: string[]): string[];
-        Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: BABYLON.PBRMaterialDefines, attributes?: string[]): string;
+        Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: BABYLON.MaterialDefines | string[], attributes?: string[]): string;
         constructor(name: string, scene: BABYLON.Scene);
         constructor(name: string, scene: BABYLON.Scene);
         AddUniform(name: string, kind: string, param: any): PBRCustomMaterial;
         AddUniform(name: string, kind: string, param: any): PBRCustomMaterial;
         AddAttribute(name: string): PBRCustomMaterial;
         AddAttribute(name: string): PBRCustomMaterial;
@@ -1704,6 +1711,7 @@ declare module BABYLON {
         Vertex_MainBegin(shaderPart: string): PBRCustomMaterial;
         Vertex_MainBegin(shaderPart: string): PBRCustomMaterial;
         Vertex_Before_PositionUpdated(shaderPart: string): PBRCustomMaterial;
         Vertex_Before_PositionUpdated(shaderPart: string): PBRCustomMaterial;
         Vertex_Before_NormalUpdated(shaderPart: string): PBRCustomMaterial;
         Vertex_Before_NormalUpdated(shaderPart: string): PBRCustomMaterial;
+        Vertex_After_WorldPosComputed(shaderPart: string): PBRCustomMaterial;
         Vertex_MainEnd(shaderPart: string): PBRCustomMaterial;
         Vertex_MainEnd(shaderPart: string): PBRCustomMaterial;
     }
     }
 }
 }

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

@@ -1 +1 @@
-{"thinEngineOnly":114719,"engineOnly":151377,"sceneOnly":508946,"minGridMaterial":641242,"minStandardMaterial":782423}
+{"thinEngineOnly":114719,"engineOnly":151377,"sceneOnly":508981,"minGridMaterial":641277,"minStandardMaterial":782458}

+ 367 - 56
dist/preview release/viewer/babylon.module.d.ts

@@ -9474,6 +9474,14 @@ declare module "babylonjs/Shaders/ShadersInclude/packingFunctions" {
         shader: string;
         shader: string;
     };
     };
 }
 }
+declare module "babylonjs/Shaders/ShadersInclude/shadowMapFragmentDeclaration" {
+    import "babylonjs/Shaders/ShadersInclude/packingFunctions";
+    /** @hidden */
+    export var shadowMapFragmentDeclaration: {
+        name: string;
+        shader: string;
+    };
+}
 declare module "babylonjs/Shaders/ShadersInclude/clipPlaneFragmentDeclaration" {
 declare module "babylonjs/Shaders/ShadersInclude/clipPlaneFragmentDeclaration" {
     /** @hidden */
     /** @hidden */
     export var clipPlaneFragmentDeclaration: {
     export var clipPlaneFragmentDeclaration: {
@@ -9488,10 +9496,18 @@ declare module "babylonjs/Shaders/ShadersInclude/clipPlaneFragment" {
         shader: string;
         shader: string;
     };
     };
 }
 }
+declare module "babylonjs/Shaders/ShadersInclude/shadowMapFragment" {
+    /** @hidden */
+    export var shadowMapFragment: {
+        name: string;
+        shader: string;
+    };
+}
 declare module "babylonjs/Shaders/shadowMap.fragment" {
 declare module "babylonjs/Shaders/shadowMap.fragment" {
-    import "babylonjs/Shaders/ShadersInclude/packingFunctions";
+    import "babylonjs/Shaders/ShadersInclude/shadowMapFragmentDeclaration";
     import "babylonjs/Shaders/ShadersInclude/clipPlaneFragmentDeclaration";
     import "babylonjs/Shaders/ShadersInclude/clipPlaneFragmentDeclaration";
     import "babylonjs/Shaders/ShadersInclude/clipPlaneFragment";
     import "babylonjs/Shaders/ShadersInclude/clipPlaneFragment";
+    import "babylonjs/Shaders/ShadersInclude/shadowMapFragment";
     /** @hidden */
     /** @hidden */
     export var shadowMapPixelShader: {
     export var shadowMapPixelShader: {
         name: string;
         name: string;
@@ -9533,6 +9549,13 @@ declare module "babylonjs/Shaders/ShadersInclude/helperFunctions" {
         shader: string;
         shader: string;
     };
     };
 }
 }
+declare module "babylonjs/Shaders/ShadersInclude/shadowMapVertexDeclaration" {
+    /** @hidden */
+    export var shadowMapVertexDeclaration: {
+        name: string;
+        shader: string;
+    };
+}
 declare module "babylonjs/Shaders/ShadersInclude/clipPlaneVertexDeclaration" {
 declare module "babylonjs/Shaders/ShadersInclude/clipPlaneVertexDeclaration" {
     /** @hidden */
     /** @hidden */
     export var clipPlaneVertexDeclaration: {
     export var clipPlaneVertexDeclaration: {
@@ -9561,6 +9584,20 @@ declare module "babylonjs/Shaders/ShadersInclude/bonesVertex" {
         shader: string;
         shader: string;
     };
     };
 }
 }
+declare module "babylonjs/Shaders/ShadersInclude/shadowMapVertexNormalBias" {
+    /** @hidden */
+    export var shadowMapVertexNormalBias: {
+        name: string;
+        shader: string;
+    };
+}
+declare module "babylonjs/Shaders/ShadersInclude/shadowMapVertexMetric" {
+    /** @hidden */
+    export var shadowMapVertexMetric: {
+        name: string;
+        shader: string;
+    };
+}
 declare module "babylonjs/Shaders/ShadersInclude/clipPlaneVertex" {
 declare module "babylonjs/Shaders/ShadersInclude/clipPlaneVertex" {
     /** @hidden */
     /** @hidden */
     export var clipPlaneVertex: {
     export var clipPlaneVertex: {
@@ -9574,10 +9611,13 @@ declare module "babylonjs/Shaders/shadowMap.vertex" {
     import "babylonjs/Shaders/ShadersInclude/morphTargetsVertexDeclaration";
     import "babylonjs/Shaders/ShadersInclude/morphTargetsVertexDeclaration";
     import "babylonjs/Shaders/ShadersInclude/instancesDeclaration";
     import "babylonjs/Shaders/ShadersInclude/instancesDeclaration";
     import "babylonjs/Shaders/ShadersInclude/helperFunctions";
     import "babylonjs/Shaders/ShadersInclude/helperFunctions";
+    import "babylonjs/Shaders/ShadersInclude/shadowMapVertexDeclaration";
     import "babylonjs/Shaders/ShadersInclude/clipPlaneVertexDeclaration";
     import "babylonjs/Shaders/ShadersInclude/clipPlaneVertexDeclaration";
     import "babylonjs/Shaders/ShadersInclude/morphTargetsVertex";
     import "babylonjs/Shaders/ShadersInclude/morphTargetsVertex";
     import "babylonjs/Shaders/ShadersInclude/instancesVertex";
     import "babylonjs/Shaders/ShadersInclude/instancesVertex";
     import "babylonjs/Shaders/ShadersInclude/bonesVertex";
     import "babylonjs/Shaders/ShadersInclude/bonesVertex";
+    import "babylonjs/Shaders/ShadersInclude/shadowMapVertexNormalBias";
+    import "babylonjs/Shaders/ShadersInclude/shadowMapVertexMetric";
     import "babylonjs/Shaders/ShadersInclude/clipPlaneVertex";
     import "babylonjs/Shaders/ShadersInclude/clipPlaneVertex";
     /** @hidden */
     /** @hidden */
     export var shadowMapVertexShader: {
     export var shadowMapVertexShader: {
@@ -9628,6 +9668,7 @@ declare module "babylonjs/Culling/ray" {
         length?: number);
         length?: number);
         /**
         /**
          * Checks if the ray intersects a box
          * Checks if the ray intersects a box
+         * This does not account for the ray lenght by design to improve perfs.
          * @param minimum bound of the box
          * @param minimum bound of the box
          * @param maximum bound of the box
          * @param maximum bound of the box
          * @param intersectionTreshold extra extend to be added to the box in all direction
          * @param intersectionTreshold extra extend to be added to the box in all direction
@@ -9636,6 +9677,7 @@ declare module "babylonjs/Culling/ray" {
         intersectsBoxMinMax(minimum: DeepImmutable<Vector3>, maximum: DeepImmutable<Vector3>, intersectionTreshold?: number): boolean;
         intersectsBoxMinMax(minimum: DeepImmutable<Vector3>, maximum: DeepImmutable<Vector3>, intersectionTreshold?: number): boolean;
         /**
         /**
          * Checks if the ray intersects a box
          * Checks if the ray intersects a box
+         * This does not account for the ray lenght by design to improve perfs.
          * @param box the bounding box to check
          * @param box the bounding box to check
          * @param intersectionTreshold extra extend to be added to the BoundingBox in all direction
          * @param intersectionTreshold extra extend to be added to the BoundingBox in all direction
          * @returns if the box was hit
          * @returns if the box was hit
@@ -15796,12 +15838,14 @@ declare module "babylonjs/Meshes/instancedMesh" {
     }
     }
 }
 }
 declare module "babylonjs/Materials/shaderMaterial" {
 declare module "babylonjs/Materials/shaderMaterial" {
+    import { Nullable } from "babylonjs/types";
     import { Scene } from "babylonjs/scene";
     import { Scene } from "babylonjs/scene";
     import { Matrix, Vector3, Vector2, Vector4 } from "babylonjs/Maths/math.vector";
     import { Matrix, Vector3, Vector2, Vector4 } from "babylonjs/Maths/math.vector";
     import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
     import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
     import { Mesh } from "babylonjs/Meshes/mesh";
     import { Mesh } from "babylonjs/Meshes/mesh";
-    import { BaseSubMesh } from "babylonjs/Meshes/subMesh";
+    import { SubMesh, BaseSubMesh } from "babylonjs/Meshes/subMesh";
     import { BaseTexture } from "babylonjs/Materials/Textures/baseTexture";
     import { BaseTexture } from "babylonjs/Materials/Textures/baseTexture";
+    import { Effect } from "babylonjs/Materials/effect";
     import { Material } from "babylonjs/Materials/material";
     import { Material } from "babylonjs/Materials/material";
     import { Color3, Color4 } from "babylonjs/Maths/math.color";
     import { Color3, Color4 } from "babylonjs/Maths/math.color";
     /**
     /**
@@ -15870,6 +15914,7 @@ declare module "babylonjs/Materials/shaderMaterial" {
         private _cachedWorldViewProjectionMatrix;
         private _cachedWorldViewProjectionMatrix;
         private _renderId;
         private _renderId;
         private _multiview;
         private _multiview;
+        private _cachedDefines;
         /**
         /**
          * Instantiate a new shader material.
          * Instantiate a new shader material.
          * The ShaderMaterial object has the necessary methods to pass data from your scene to the Vertex and Fragment Shaders and returns a material that can be applied to any mesh.
          * The ShaderMaterial object has the necessary methods to pass data from your scene to the Vertex and Fragment Shaders and returns a material that can be applied to any mesh.
@@ -16069,14 +16114,24 @@ declare module "babylonjs/Materials/shaderMaterial" {
         /**
         /**
          * Binds the world matrix to the material
          * Binds the world matrix to the material
          * @param world defines the world transformation matrix
          * @param world defines the world transformation matrix
+         * @param effectOverride - If provided, use this effect instead of internal effect
          */
          */
-        bindOnlyWorldMatrix(world: Matrix): void;
+        bindOnlyWorldMatrix(world: Matrix, effectOverride?: Nullable<Effect>): void;
+        /**
+         * Binds the submesh to this material by preparing the effect and shader to draw
+         * @param world defines the world transformation matrix
+         * @param mesh defines the mesh containing the submesh
+         * @param subMesh defines the submesh to bind the material to
+         */
+        bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         /**
         /**
          * Binds the material to the mesh
          * Binds the material to the mesh
          * @param world defines the world transformation matrix
          * @param world defines the world transformation matrix
          * @param mesh defines the mesh to bind the material to
          * @param mesh defines the mesh to bind the material to
+         * @param effectOverride - If provided, use this effect instead of internal effect
          */
          */
-        bind(world: Matrix, mesh?: Mesh): void;
+        bind(world: Matrix, mesh?: Mesh, effectOverride?: Nullable<Effect>): void;
+        protected _afterBind(mesh?: Mesh): void;
         /**
         /**
          * Gets the active textures from the material
          * Gets the active textures from the material
          * @returns an array of textures
          * @returns an array of textures
@@ -17204,7 +17259,7 @@ declare module "babylonjs/Lights/Shadows/shadowGenerator" {
         protected _initializeShadowMap(): void;
         protected _initializeShadowMap(): void;
         protected _initializeBlurRTTAndPostProcesses(): void;
         protected _initializeBlurRTTAndPostProcesses(): void;
         protected _renderForShadowMap(opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void;
         protected _renderForShadowMap(opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void;
-        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect): void;
+        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect, matriceNames: any): void;
         protected _renderSubMeshForShadowMap(subMesh: SubMesh): void;
         protected _renderSubMeshForShadowMap(subMesh: SubMesh): void;
         protected _applyFilterValues(): void;
         protected _applyFilterValues(): void;
         /**
         /**
@@ -17224,6 +17279,7 @@ declare module "babylonjs/Lights/Shadows/shadowGenerator" {
             useInstances: boolean;
             useInstances: boolean;
         }>): Promise<void>;
         }>): Promise<void>;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
+        private _prepareShadowDefines;
         /**
         /**
          * Determine wheter the shadow generator is ready or not (mainly all effects and related post processes needs to be ready).
          * Determine wheter the shadow generator is ready or not (mainly all effects and related post processes needs to be ready).
          * @param subMesh The submesh we want to render in the shadow map
          * @param subMesh The submesh we want to render in the shadow map
@@ -21585,6 +21641,88 @@ declare module "babylonjs/Materials/Textures/renderTargetTexture" {
         getViewCount(): number;
         getViewCount(): number;
     }
     }
 }
 }
+declare module "babylonjs/Misc/guid" {
+    /**
+     * Class used to manipulate GUIDs
+     */
+    export class GUID {
+        /**
+         * Implementation from http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#answer-2117523
+         * Be aware Math.random() could cause collisions, but:
+         * "All but 6 of the 128 bits of the ID are randomly generated, which means that for any two ids, there's a 1 in 2^^122 (or 5.3x10^^36) chance they'll collide"
+         * @returns a pseudo random id
+         */
+        static RandomId(): string;
+    }
+}
+declare module "babylonjs/Materials/shadowDepthWrapper" {
+    import { Nullable } from "babylonjs/types";
+    import { Scene } from "babylonjs/scene";
+    import { SubMesh } from "babylonjs/Meshes/subMesh";
+    import { Material } from "babylonjs/Materials/material";
+    import { Effect } from "babylonjs/Materials/effect";
+    import { ShadowGenerator } from "babylonjs/Lights/Shadows/shadowGenerator";
+    /**
+     * Options to be used when creating a shadow depth material
+     */
+    export interface IIOptionShadowDepthMaterial {
+        /** Variables in the vertex shader code that need to have their names remapped.
+         * The format is: ["var_name", "var_remapped_name", "var_name", "var_remapped_name", ...]
+         * "var_name" should be either: worldPos or vNormalW
+         * So, if the variable holding the world position in your vertex shader is not named worldPos, you must tell the system
+         * the name to use instead by using: ["worldPos", "myWorldPosVar"] assuming the variable is named myWorldPosVar in your code.
+         * If the normal must also be remapped: ["worldPos", "myWorldPosVar", "vNormalW", "myWorldNormal"]
+        */
+        remappedVariables?: string[];
+        /** Set standalone to true if the base material wrapped by ShadowDepthMaterial is not used for a regular object but for depth shadow generation only */
+        standalone?: boolean;
+    }
+    /**
+     * Class that can be used to wrap a base material to generate accurate shadows when using custom vertex/fragment code in the base material
+     */
+    export class ShadowDepthWrapper {
+        private _scene;
+        private _options?;
+        private _baseMaterial;
+        private _onEffectCreatedObserver;
+        private _subMeshToEffect;
+        private _subMeshToDepthEffect;
+        private _meshes;
+        /** @hidden */
+        _matriceNames: any;
+        /**
+         * Instantiate a new shadow depth wrapper.
+         * It works by injecting some specific code in the vertex/fragment shaders of the base material and is used by a shadow generator to
+         * generate the shadow depth map. For more information, please refer to the documentation:
+         * https://doc.babylonjs.com/babylon101/shadows
+         * @param baseMaterial Material to wrap
+         * @param scene Define the scene the material belongs to
+         * @param options Options used to create the wrapper
+         */
+        constructor(baseMaterial: Material, scene: Scene, options?: IIOptionShadowDepthMaterial);
+        /**
+         * Gets the effect to use to generate the depth map
+         * @param subMesh subMesh to get the effect for
+         * @param shadowGenerator shadow generator to get the effect for
+         * @returns the effect to use to generate the depth map for the subMesh + shadow generator specified
+         */
+        getEffect(subMesh: Nullable<SubMesh>, shadowGenerator: ShadowGenerator): Nullable<Effect>;
+        /**
+         * Specifies that the submesh is ready to be used for depth rendering
+         * @param subMesh submesh to check
+         * @param defines the list of defines to take into account when checking the effect
+         * @param shadowGenerator combined with subMesh, it defines the effect to check
+         * @param useInstances specifies that instances should be used
+         * @returns a boolean indicating that the submesh is ready or not
+         */
+        isReadyForSubMesh(subMesh: SubMesh, defines: string[], shadowGenerator: ShadowGenerator, useInstances: boolean): boolean;
+        /**
+         * Disposes the resources
+         */
+        dispose(): void;
+        private _makeEffect;
+    }
+}
 declare module "babylonjs/Materials/material" {
 declare module "babylonjs/Materials/material" {
     import { IAnimatable } from "babylonjs/Animations/animatable.interface";
     import { IAnimatable } from "babylonjs/Animations/animatable.interface";
     import { SmartArray } from "babylonjs/Misc/smartArray";
     import { SmartArray } from "babylonjs/Misc/smartArray";
@@ -21600,6 +21738,7 @@ declare module "babylonjs/Materials/material" {
     import { RenderTargetTexture } from "babylonjs/Materials/Textures/renderTargetTexture";
     import { RenderTargetTexture } from "babylonjs/Materials/Textures/renderTargetTexture";
     import { MaterialDefines } from "babylonjs/Materials/materialDefines";
     import { MaterialDefines } from "babylonjs/Materials/materialDefines";
     import { IInspectable } from "babylonjs/Misc/iInspectable";
     import { IInspectable } from "babylonjs/Misc/iInspectable";
+    import { ShadowDepthWrapper } from "babylonjs/Materials/shadowDepthWrapper";
     import { Mesh } from "babylonjs/Meshes/mesh";
     import { Mesh } from "babylonjs/Meshes/mesh";
     import { Animation } from "babylonjs/Animations/animation";
     import { Animation } from "babylonjs/Animations/animation";
     /**
     /**
@@ -21705,6 +21844,14 @@ declare module "babylonjs/Materials/material" {
          */
          */
         static readonly MATERIAL_ALPHATESTANDBLEND: number;
         static readonly MATERIAL_ALPHATESTANDBLEND: number;
         /**
         /**
+         * Custom callback helping to override the default shader used in the material.
+         */
+        customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: MaterialDefines | string[], attributes?: string[]) => string;
+        /**
+         * Custom shadow depth material to use for shadow rendering instead of the in-built one
+         */
+        shadowDepthWrapper: Nullable<ShadowDepthWrapper>;
+        /**
          * The ID of the material
          * The ID of the material
          */
          */
         id: string;
         id: string;
@@ -21827,6 +21974,17 @@ declare module "babylonjs/Materials/material" {
         * An event triggered when the material is unbound
         * An event triggered when the material is unbound
         */
         */
         get onUnBindObservable(): Observable<Material>;
         get onUnBindObservable(): Observable<Material>;
+        protected _onEffectCreatedObservable: Nullable<Observable<{
+            effect: Effect;
+            subMesh: Nullable<SubMesh>;
+        }>>;
+        /**
+        * An event triggered when the effect is (re)created
+        */
+        get onEffectCreatedObservable(): Observable<{
+            effect: Effect;
+            subMesh: Nullable<SubMesh>;
+        }>;
         /**
         /**
          * Stores the value of the alpha mode
          * Stores the value of the alpha mode
          */
          */
@@ -22349,6 +22507,8 @@ declare module "babylonjs/Meshes/subMesh" {
         _materialDefines: Nullable<MaterialDefines>;
         _materialDefines: Nullable<MaterialDefines>;
         /** @hidden */
         /** @hidden */
         _materialEffect: Nullable<Effect>;
         _materialEffect: Nullable<Effect>;
+        /** @hidden */
+        _effectOverride: Nullable<Effect>;
         /**
         /**
          * Gets material defines used by the effect associated to the sub mesh
          * Gets material defines used by the effect associated to the sub mesh
          */
          */
@@ -27863,10 +28023,6 @@ declare module "babylonjs/Materials/standardMaterial" {
          * corresponding to low luminance, medium luminance, and high luminance areas respectively.
          * corresponding to low luminance, medium luminance, and high luminance areas respectively.
          */
          */
         set cameraColorCurves(value: Nullable<ColorCurves>);
         set cameraColorCurves(value: Nullable<ColorCurves>);
-        /**
-         * Custom callback helping to override the default shader used in the material.
-         */
-        customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: StandardMaterialDefines, attributes?: string[]) => string;
         protected _renderTargets: SmartArray<RenderTargetTexture>;
         protected _renderTargets: SmartArray<RenderTargetTexture>;
         protected _worldViewProjectionMatrix: Matrix;
         protected _worldViewProjectionMatrix: Matrix;
         protected _globalAmbientColor: Color3;
         protected _globalAmbientColor: Color3;
@@ -30866,20 +31022,6 @@ declare module "babylonjs/Misc/decorators" {
         static Instanciate<T>(creationFunction: () => T, source: T): T;
         static Instanciate<T>(creationFunction: () => T, source: T): T;
     }
     }
 }
 }
-declare module "babylonjs/Misc/guid" {
-    /**
-     * Class used to manipulate GUIDs
-     */
-    export class GUID {
-        /**
-         * Implementation from http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#answer-2117523
-         * Be aware Math.random() could cause collisions, but:
-         * "All but 6 of the 128 bits of the ID are randomly generated, which means that for any two ids, there's a 1 in 2^^122 (or 5.3x10^^36) chance they'll collide"
-         * @returns a pseudo random id
-         */
-        static RandomId(): string;
-    }
-}
 declare module "babylonjs/Materials/Textures/baseTexture" {
 declare module "babylonjs/Materials/Textures/baseTexture" {
     import { Observable } from "babylonjs/Misc/observable";
     import { Observable } from "babylonjs/Misc/observable";
     import { Nullable } from "babylonjs/types";
     import { Nullable } from "babylonjs/types";
@@ -31363,6 +31505,7 @@ declare module "babylonjs/Materials/effect" {
         private static _uniqueIdSeed;
         private static _uniqueIdSeed;
         private _engine;
         private _engine;
         private _uniformBuffersNames;
         private _uniformBuffersNames;
+        private _uniformBuffersNamesList;
         private _uniformsNames;
         private _uniformsNames;
         private _samplerList;
         private _samplerList;
         private _samplers;
         private _samplers;
@@ -31464,10 +31607,25 @@ declare module "babylonjs/Materials/effect" {
         getUniform(uniformName: string): Nullable<WebGLUniformLocation>;
         getUniform(uniformName: string): Nullable<WebGLUniformLocation>;
         /**
         /**
          * Returns an array of sampler variable names
          * Returns an array of sampler variable names
-         * @returns The array of sampler variable neames.
+         * @returns The array of sampler variable names.
          */
          */
         getSamplers(): string[];
         getSamplers(): string[];
         /**
         /**
+         * Returns an array of uniform variable names
+         * @returns The array of uniform variable names.
+         */
+        getUniformNames(): string[];
+        /**
+         * Returns an array of uniform buffer variable names
+         * @returns The array of uniform buffer variable names.
+         */
+        getUniformBuffersNames(): string[];
+        /**
+         * Returns the index parameters used to create the effect
+         * @returns The index parameters object
+         */
+        getIndexParameters(): any;
+        /**
          * The error from the last compilation.
          * The error from the last compilation.
          * @returns the error string.
          * @returns the error string.
          */
          */
@@ -31485,6 +31643,14 @@ declare module "babylonjs/Materials/effect" {
         private _checkIsReady;
         private _checkIsReady;
         private _loadShader;
         private _loadShader;
         /**
         /**
+         * Gets the vertex shader source code of this effect
+         */
+        get vertexSourceCode(): string;
+        /**
+         * Gets the fragment shader source code of this effect
+         */
+        get fragmentSourceCode(): string;
+        /**
          * Recompiles the webGL program
          * Recompiles the webGL program
          * @param vertexSourceCode The source code for the vertex shader.
          * @param vertexSourceCode The source code for the vertex shader.
          * @param fragmentSourceCode The source code for the fragment shader.
          * @param fragmentSourceCode The source code for the fragment shader.
@@ -54184,10 +54350,6 @@ declare module "babylonjs/Materials/PBR/pbrBaseMaterial" {
          * Defines the SubSurface parameters for the material.
          * Defines the SubSurface parameters for the material.
          */
          */
         readonly subSurface: PBRSubSurfaceConfiguration;
         readonly subSurface: PBRSubSurfaceConfiguration;
-        /**
-         * Custom callback helping to override the default shader used in the material.
-         */
-        customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: PBRMaterialDefines, attributes?: string[]) => string;
         protected _rebuildInParallel: boolean;
         protected _rebuildInParallel: boolean;
         /**
         /**
          * Instantiates a new PBRMaterial instance.
          * Instantiates a new PBRMaterial instance.
@@ -57408,7 +57570,7 @@ declare module "babylonjs/Lights/Shadows/cascadedShadowGenerator" {
         protected _initializeGenerator(): void;
         protected _initializeGenerator(): void;
         protected _createTargetRenderTexture(): void;
         protected _createTargetRenderTexture(): void;
         protected _initializeShadowMap(): void;
         protected _initializeShadowMap(): void;
-        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect): void;
+        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect, matriceNames: any): void;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
         /**
         /**
          * Prepare all the defines in a material relying on a shadow map at the specified light index.
          * Prepare all the defines in a material relying on a shadow map at the specified light index.
@@ -63903,6 +64065,7 @@ declare module "babylonjs/Materials/index" {
     export * from "babylonjs/Materials/materialFlags";
     export * from "babylonjs/Materials/materialFlags";
     export * from "babylonjs/Materials/Node/index";
     export * from "babylonjs/Materials/Node/index";
     export * from "babylonjs/Materials/effectRenderer";
     export * from "babylonjs/Materials/effectRenderer";
+    export * from "babylonjs/Materials/shadowDepthWrapper";
 }
 }
 declare module "babylonjs/Maths/index" {
 declare module "babylonjs/Maths/index" {
     export * from "babylonjs/Maths/math.scalar";
     export * from "babylonjs/Maths/math.scalar";
@@ -83650,6 +83813,13 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /** @hidden */
     /** @hidden */
+    export var shadowMapFragmentDeclaration: {
+        name: string;
+        shader: string;
+    };
+}
+declare module BABYLON {
+    /** @hidden */
     export var clipPlaneFragmentDeclaration: {
     export var clipPlaneFragmentDeclaration: {
         name: string;
         name: string;
         shader: string;
         shader: string;
@@ -83664,6 +83834,13 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /** @hidden */
     /** @hidden */
+    export var shadowMapFragment: {
+        name: string;
+        shader: string;
+    };
+}
+declare module BABYLON {
+    /** @hidden */
     export var shadowMapPixelShader: {
     export var shadowMapPixelShader: {
         name: string;
         name: string;
         shader: string;
         shader: string;
@@ -83706,6 +83883,13 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /** @hidden */
     /** @hidden */
+    export var shadowMapVertexDeclaration: {
+        name: string;
+        shader: string;
+    };
+}
+declare module BABYLON {
+    /** @hidden */
     export var clipPlaneVertexDeclaration: {
     export var clipPlaneVertexDeclaration: {
         name: string;
         name: string;
         shader: string;
         shader: string;
@@ -83734,6 +83918,20 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /** @hidden */
     /** @hidden */
+    export var shadowMapVertexNormalBias: {
+        name: string;
+        shader: string;
+    };
+}
+declare module BABYLON {
+    /** @hidden */
+    export var shadowMapVertexMetric: {
+        name: string;
+        shader: string;
+    };
+}
+declare module BABYLON {
+    /** @hidden */
     export var clipPlaneVertex: {
     export var clipPlaneVertex: {
         name: string;
         name: string;
         shader: string;
         shader: string;
@@ -83781,6 +83979,7 @@ declare module BABYLON {
         length?: number);
         length?: number);
         /**
         /**
          * Checks if the ray intersects a box
          * Checks if the ray intersects a box
+         * This does not account for the ray lenght by design to improve perfs.
          * @param minimum bound of the box
          * @param minimum bound of the box
          * @param maximum bound of the box
          * @param maximum bound of the box
          * @param intersectionTreshold extra extend to be added to the box in all direction
          * @param intersectionTreshold extra extend to be added to the box in all direction
@@ -83789,6 +83988,7 @@ declare module BABYLON {
         intersectsBoxMinMax(minimum: DeepImmutable<Vector3>, maximum: DeepImmutable<Vector3>, intersectionTreshold?: number): boolean;
         intersectsBoxMinMax(minimum: DeepImmutable<Vector3>, maximum: DeepImmutable<Vector3>, intersectionTreshold?: number): boolean;
         /**
         /**
          * Checks if the ray intersects a box
          * Checks if the ray intersects a box
+         * This does not account for the ray lenght by design to improve perfs.
          * @param box the bounding box to check
          * @param box the bounding box to check
          * @param intersectionTreshold extra extend to be added to the BoundingBox in all direction
          * @param intersectionTreshold extra extend to be added to the BoundingBox in all direction
          * @returns if the box was hit
          * @returns if the box was hit
@@ -89782,6 +89982,7 @@ declare module BABYLON {
         private _cachedWorldViewProjectionMatrix;
         private _cachedWorldViewProjectionMatrix;
         private _renderId;
         private _renderId;
         private _multiview;
         private _multiview;
+        private _cachedDefines;
         /**
         /**
          * Instantiate a new shader material.
          * Instantiate a new shader material.
          * The ShaderMaterial object has the necessary methods to pass data from your scene to the Vertex and Fragment Shaders and returns a material that can be applied to any mesh.
          * The ShaderMaterial object has the necessary methods to pass data from your scene to the Vertex and Fragment Shaders and returns a material that can be applied to any mesh.
@@ -89981,14 +90182,24 @@ declare module BABYLON {
         /**
         /**
          * Binds the world matrix to the material
          * Binds the world matrix to the material
          * @param world defines the world transformation matrix
          * @param world defines the world transformation matrix
+         * @param effectOverride - If provided, use this effect instead of internal effect
          */
          */
-        bindOnlyWorldMatrix(world: Matrix): void;
+        bindOnlyWorldMatrix(world: Matrix, effectOverride?: Nullable<Effect>): void;
+        /**
+         * Binds the submesh to this material by preparing the effect and shader to draw
+         * @param world defines the world transformation matrix
+         * @param mesh defines the mesh containing the submesh
+         * @param subMesh defines the submesh to bind the material to
+         */
+        bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         /**
         /**
          * Binds the material to the mesh
          * Binds the material to the mesh
          * @param world defines the world transformation matrix
          * @param world defines the world transformation matrix
          * @param mesh defines the mesh to bind the material to
          * @param mesh defines the mesh to bind the material to
+         * @param effectOverride - If provided, use this effect instead of internal effect
          */
          */
-        bind(world: Matrix, mesh?: Mesh): void;
+        bind(world: Matrix, mesh?: Mesh, effectOverride?: Nullable<Effect>): void;
+        protected _afterBind(mesh?: Mesh): void;
         /**
         /**
          * Gets the active textures from the material
          * Gets the active textures from the material
          * @returns an array of textures
          * @returns an array of textures
@@ -91048,7 +91259,7 @@ declare module BABYLON {
         protected _initializeShadowMap(): void;
         protected _initializeShadowMap(): void;
         protected _initializeBlurRTTAndPostProcesses(): void;
         protected _initializeBlurRTTAndPostProcesses(): void;
         protected _renderForShadowMap(opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void;
         protected _renderForShadowMap(opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void;
-        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect): void;
+        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect, matriceNames: any): void;
         protected _renderSubMeshForShadowMap(subMesh: SubMesh): void;
         protected _renderSubMeshForShadowMap(subMesh: SubMesh): void;
         protected _applyFilterValues(): void;
         protected _applyFilterValues(): void;
         /**
         /**
@@ -91068,6 +91279,7 @@ declare module BABYLON {
             useInstances: boolean;
             useInstances: boolean;
         }>): Promise<void>;
         }>): Promise<void>;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
+        private _prepareShadowDefines;
         /**
         /**
          * Determine wheter the shadow generator is ready or not (mainly all effects and related post processes needs to be ready).
          * Determine wheter the shadow generator is ready or not (mainly all effects and related post processes needs to be ready).
          * @param subMesh The submesh we want to render in the shadow map
          * @param subMesh The submesh we want to render in the shadow map
@@ -95259,6 +95471,82 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /**
     /**
+     * Class used to manipulate GUIDs
+     */
+    export class GUID {
+        /**
+         * Implementation from http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#answer-2117523
+         * Be aware Math.random() could cause collisions, but:
+         * "All but 6 of the 128 bits of the ID are randomly generated, which means that for any two ids, there's a 1 in 2^^122 (or 5.3x10^^36) chance they'll collide"
+         * @returns a pseudo random id
+         */
+        static RandomId(): string;
+    }
+}
+declare module BABYLON {
+    /**
+     * Options to be used when creating a shadow depth material
+     */
+    export interface IIOptionShadowDepthMaterial {
+        /** Variables in the vertex shader code that need to have their names remapped.
+         * The format is: ["var_name", "var_remapped_name", "var_name", "var_remapped_name", ...]
+         * "var_name" should be either: worldPos or vNormalW
+         * So, if the variable holding the world position in your vertex shader is not named worldPos, you must tell the system
+         * the name to use instead by using: ["worldPos", "myWorldPosVar"] assuming the variable is named myWorldPosVar in your code.
+         * If the normal must also be remapped: ["worldPos", "myWorldPosVar", "vNormalW", "myWorldNormal"]
+        */
+        remappedVariables?: string[];
+        /** Set standalone to true if the base material wrapped by ShadowDepthMaterial is not used for a regular object but for depth shadow generation only */
+        standalone?: boolean;
+    }
+    /**
+     * Class that can be used to wrap a base material to generate accurate shadows when using custom vertex/fragment code in the base material
+     */
+    export class ShadowDepthWrapper {
+        private _scene;
+        private _options?;
+        private _baseMaterial;
+        private _onEffectCreatedObserver;
+        private _subMeshToEffect;
+        private _subMeshToDepthEffect;
+        private _meshes;
+        /** @hidden */
+        _matriceNames: any;
+        /**
+         * Instantiate a new shadow depth wrapper.
+         * It works by injecting some specific code in the vertex/fragment shaders of the base material and is used by a shadow generator to
+         * generate the shadow depth map. For more information, please refer to the documentation:
+         * https://doc.babylonjs.com/babylon101/shadows
+         * @param baseMaterial Material to wrap
+         * @param scene Define the scene the material belongs to
+         * @param options Options used to create the wrapper
+         */
+        constructor(baseMaterial: Material, scene: Scene, options?: IIOptionShadowDepthMaterial);
+        /**
+         * Gets the effect to use to generate the depth map
+         * @param subMesh subMesh to get the effect for
+         * @param shadowGenerator shadow generator to get the effect for
+         * @returns the effect to use to generate the depth map for the subMesh + shadow generator specified
+         */
+        getEffect(subMesh: Nullable<SubMesh>, shadowGenerator: ShadowGenerator): Nullable<Effect>;
+        /**
+         * Specifies that the submesh is ready to be used for depth rendering
+         * @param subMesh submesh to check
+         * @param defines the list of defines to take into account when checking the effect
+         * @param shadowGenerator combined with subMesh, it defines the effect to check
+         * @param useInstances specifies that instances should be used
+         * @returns a boolean indicating that the submesh is ready or not
+         */
+        isReadyForSubMesh(subMesh: SubMesh, defines: string[], shadowGenerator: ShadowGenerator, useInstances: boolean): boolean;
+        /**
+         * Disposes the resources
+         */
+        dispose(): void;
+        private _makeEffect;
+    }
+}
+declare module BABYLON {
+    /**
      * Options for compiling materials.
      * Options for compiling materials.
      */
      */
     export interface IMaterialCompilationOptions {
     export interface IMaterialCompilationOptions {
@@ -95361,6 +95649,14 @@ declare module BABYLON {
          */
          */
         static readonly MATERIAL_ALPHATESTANDBLEND: number;
         static readonly MATERIAL_ALPHATESTANDBLEND: number;
         /**
         /**
+         * Custom callback helping to override the default shader used in the material.
+         */
+        customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: MaterialDefines | string[], attributes?: string[]) => string;
+        /**
+         * Custom shadow depth material to use for shadow rendering instead of the in-built one
+         */
+        shadowDepthWrapper: Nullable<ShadowDepthWrapper>;
+        /**
          * The ID of the material
          * The ID of the material
          */
          */
         id: string;
         id: string;
@@ -95483,6 +95779,17 @@ declare module BABYLON {
         * An event triggered when the material is unbound
         * An event triggered when the material is unbound
         */
         */
         get onUnBindObservable(): Observable<Material>;
         get onUnBindObservable(): Observable<Material>;
+        protected _onEffectCreatedObservable: Nullable<Observable<{
+            effect: Effect;
+            subMesh: Nullable<SubMesh>;
+        }>>;
+        /**
+        * An event triggered when the effect is (re)created
+        */
+        get onEffectCreatedObservable(): Observable<{
+            effect: Effect;
+            subMesh: Nullable<SubMesh>;
+        }>;
         /**
         /**
          * Stores the value of the alpha mode
          * Stores the value of the alpha mode
          */
          */
@@ -95984,6 +96291,8 @@ declare module BABYLON {
         _materialDefines: Nullable<MaterialDefines>;
         _materialDefines: Nullable<MaterialDefines>;
         /** @hidden */
         /** @hidden */
         _materialEffect: Nullable<Effect>;
         _materialEffect: Nullable<Effect>;
+        /** @hidden */
+        _effectOverride: Nullable<Effect>;
         /**
         /**
          * Gets material defines used by the effect associated to the sub mesh
          * Gets material defines used by the effect associated to the sub mesh
          */
          */
@@ -101332,10 +101641,6 @@ declare module BABYLON {
          * corresponding to low luminance, medium luminance, and high luminance areas respectively.
          * corresponding to low luminance, medium luminance, and high luminance areas respectively.
          */
          */
         set cameraColorCurves(value: Nullable<ColorCurves>);
         set cameraColorCurves(value: Nullable<ColorCurves>);
-        /**
-         * Custom callback helping to override the default shader used in the material.
-         */
-        customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: StandardMaterialDefines, attributes?: string[]) => string;
         protected _renderTargets: SmartArray<RenderTargetTexture>;
         protected _renderTargets: SmartArray<RenderTargetTexture>;
         protected _worldViewProjectionMatrix: Matrix;
         protected _worldViewProjectionMatrix: Matrix;
         protected _globalAmbientColor: Color3;
         protected _globalAmbientColor: Color3;
@@ -104251,20 +104556,6 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /**
     /**
-     * Class used to manipulate GUIDs
-     */
-    export class GUID {
-        /**
-         * Implementation from http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#answer-2117523
-         * Be aware Math.random() could cause collisions, but:
-         * "All but 6 of the 128 bits of the ID are randomly generated, which means that for any two ids, there's a 1 in 2^^122 (or 5.3x10^^36) chance they'll collide"
-         * @returns a pseudo random id
-         */
-        static RandomId(): string;
-    }
-}
-declare module BABYLON {
-    /**
      * Base class of all the textures in babylon.
      * Base class of all the textures in babylon.
      * It groups all the common properties the materials, post process, lights... might need
      * It groups all the common properties the materials, post process, lights... might need
      * in order to make a correct use of the texture.
      * in order to make a correct use of the texture.
@@ -104725,6 +105016,7 @@ declare module BABYLON {
         private static _uniqueIdSeed;
         private static _uniqueIdSeed;
         private _engine;
         private _engine;
         private _uniformBuffersNames;
         private _uniformBuffersNames;
+        private _uniformBuffersNamesList;
         private _uniformsNames;
         private _uniformsNames;
         private _samplerList;
         private _samplerList;
         private _samplers;
         private _samplers;
@@ -104826,10 +105118,25 @@ declare module BABYLON {
         getUniform(uniformName: string): Nullable<WebGLUniformLocation>;
         getUniform(uniformName: string): Nullable<WebGLUniformLocation>;
         /**
         /**
          * Returns an array of sampler variable names
          * Returns an array of sampler variable names
-         * @returns The array of sampler variable neames.
+         * @returns The array of sampler variable names.
          */
          */
         getSamplers(): string[];
         getSamplers(): string[];
         /**
         /**
+         * Returns an array of uniform variable names
+         * @returns The array of uniform variable names.
+         */
+        getUniformNames(): string[];
+        /**
+         * Returns an array of uniform buffer variable names
+         * @returns The array of uniform buffer variable names.
+         */
+        getUniformBuffersNames(): string[];
+        /**
+         * Returns the index parameters used to create the effect
+         * @returns The index parameters object
+         */
+        getIndexParameters(): any;
+        /**
          * The error from the last compilation.
          * The error from the last compilation.
          * @returns the error string.
          * @returns the error string.
          */
          */
@@ -104847,6 +105154,14 @@ declare module BABYLON {
         private _checkIsReady;
         private _checkIsReady;
         private _loadShader;
         private _loadShader;
         /**
         /**
+         * Gets the vertex shader source code of this effect
+         */
+        get vertexSourceCode(): string;
+        /**
+         * Gets the fragment shader source code of this effect
+         */
+        get fragmentSourceCode(): string;
+        /**
          * Recompiles the webGL program
          * Recompiles the webGL program
          * @param vertexSourceCode The source code for the vertex shader.
          * @param vertexSourceCode The source code for the vertex shader.
          * @param fragmentSourceCode The source code for the fragment shader.
          * @param fragmentSourceCode The source code for the fragment shader.
@@ -126258,10 +126573,6 @@ declare module BABYLON {
          * Defines the SubSurface parameters for the material.
          * Defines the SubSurface parameters for the material.
          */
          */
         readonly subSurface: PBRSubSurfaceConfiguration;
         readonly subSurface: PBRSubSurfaceConfiguration;
-        /**
-         * Custom callback helping to override the default shader used in the material.
-         */
-        customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: PBRMaterialDefines, attributes?: string[]) => string;
         protected _rebuildInParallel: boolean;
         protected _rebuildInParallel: boolean;
         /**
         /**
          * Instantiates a new PBRMaterial instance.
          * Instantiates a new PBRMaterial instance.
@@ -129272,7 +129583,7 @@ declare module BABYLON {
         protected _initializeGenerator(): void;
         protected _initializeGenerator(): void;
         protected _createTargetRenderTexture(): void;
         protected _createTargetRenderTexture(): void;
         protected _initializeShadowMap(): void;
         protected _initializeShadowMap(): void;
-        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect): void;
+        protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect, matriceNames: any): void;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
         protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void;
         /**
         /**
          * Prepare all the defines in a material relying on a shadow map at the specified light index.
          * Prepare all the defines in a material relying on a shadow map at the specified light index.

+ 1 - 0
dist/preview release/what's new.md

@@ -3,6 +3,7 @@
 ## Major updates
 ## Major updates
 
 
 - Added particle editor to the Inspector ([Deltakosh](https://github.com/deltakosh)
 - Added particle editor to the Inspector ([Deltakosh](https://github.com/deltakosh)
+- Added the `ShadowDepthWrapper` class to support accurate shadow generation for custom as well as node material shaders ([Popov72](https://github.com/Popov72))
 
 
 ## Updates
 ## Updates
 
 

+ 13 - 1
gui/src/2D/controls/scrollViewers/scrollViewer.ts

@@ -44,6 +44,9 @@ export class ScrollViewer extends Rectangle {
     private _barImageHeight: number = 1;
     private _barImageHeight: number = 1;
     private _horizontalBarImageHeight: number = 1;
     private _horizontalBarImageHeight: number = 1;
     private _verticalBarImageHeight: number = 1;
     private _verticalBarImageHeight: number = 1;
+    private _oldWindowContentsWidth: number = 0;
+    private _oldWindowContentsHeight: number = 0;
+
     /**
     /**
      * Gets the horizontal scrollbar
      * Gets the horizontal scrollbar
      */
      */
@@ -261,6 +264,8 @@ export class ScrollViewer extends Rectangle {
         super._postMeasure();
         super._postMeasure();
 
 
         this._updateScroller();
         this._updateScroller();
+
+        this._setWindowPosition(false);
     }
     }
 
 
     /**
     /**
@@ -556,11 +561,18 @@ export class ScrollViewer extends Rectangle {
         vb.backgroundImage = value;
         vb.backgroundImage = value;
     }
     }
 
 
-    private _setWindowPosition(): void {
+    private _setWindowPosition(force = true): void {
         let ratio = this.host.idealRatio;
         let ratio = this.host.idealRatio;
         let windowContentsWidth = this._window._currentMeasure.width;
         let windowContentsWidth = this._window._currentMeasure.width;
         let windowContentsHeight = this._window._currentMeasure.height;
         let windowContentsHeight = this._window._currentMeasure.height;
 
 
+        if (!force && this._oldWindowContentsWidth === windowContentsWidth && this._oldWindowContentsHeight === windowContentsHeight) {
+            return;
+        }
+
+        this._oldWindowContentsWidth = windowContentsWidth;
+        this._oldWindowContentsHeight = windowContentsHeight;
+
         const _endLeft = this._clientWidth - windowContentsWidth;
         const _endLeft = this._clientWidth - windowContentsWidth;
         const _endTop = this._clientHeight - windowContentsHeight;
         const _endTop = this._clientHeight - windowContentsHeight;
 
 

+ 15 - 6
materialsLibrary/src/custom/customMaterial.ts

@@ -1,6 +1,6 @@
 import { Texture } from "babylonjs/Materials/Textures/texture";
 import { Texture } from "babylonjs/Materials/Textures/texture";
 import { Effect } from "babylonjs/Materials/effect";
 import { Effect } from "babylonjs/Materials/effect";
-import { StandardMaterialDefines } from "babylonjs/Materials/standardMaterial";
+import { MaterialDefines } from "babylonjs/Materials/materialDefines";
 import { StandardMaterial } from "babylonjs/Materials/standardMaterial";
 import { StandardMaterial } from "babylonjs/Materials/standardMaterial";
 import { Mesh } from "babylonjs/Meshes/mesh";
 import { Mesh } from "babylonjs/Meshes/mesh";
 import { Scene } from "babylonjs/scene";
 import { Scene } from "babylonjs/scene";
@@ -43,6 +43,9 @@ export class ShaderSpecialParts {
     // normalUpdated
     // normalUpdated
     public Vertex_Before_NormalUpdated: string;
     public Vertex_Before_NormalUpdated: string;
 
 
+    // worldPosComputed
+    public Vertex_After_WorldPosComputed: string;
+
     // mainEnd
     // mainEnd
     public Vertex_MainEnd: string;
     public Vertex_MainEnd: string;
 }
 }
@@ -62,7 +65,7 @@ export class CustomMaterial extends StandardMaterial {
     public VertexShader: string;
     public VertexShader: string;
 
 
     public AttachAfterBind(mesh: Mesh, effect: Effect) {
     public AttachAfterBind(mesh: Mesh, effect: Effect) {
-        for (var el in this._newUniformInstances) {
+         for (var el in this._newUniformInstances) {
             var ea = el.toString().split('-');
             var ea = el.toString().split('-');
             if (ea[0] == 'vec2') {
             if (ea[0] == 'vec2') {
                 effect.setVector2(ea[1], this._newUniformInstances[el]);
                 effect.setVector2(ea[1], this._newUniformInstances[el]);
@@ -90,14 +93,14 @@ export class CustomMaterial extends StandardMaterial {
 
 
     public ReviewUniform(name: string, arr: string[]): string[] {
     public ReviewUniform(name: string, arr: string[]): string[] {
         if (name == "uniform") {
         if (name == "uniform") {
-            for (var ind in this._newUniforms) {
+            for (var ind = 0; ind < this._newUniforms.length ; ind ++) {
                 if (this._customUniform[ind].indexOf('sampler') == -1) {
                 if (this._customUniform[ind].indexOf('sampler') == -1) {
                     arr.push(this._newUniforms[ind]);
                     arr.push(this._newUniforms[ind]);
                 }
                 }
             }
             }
         }
         }
         if (name == "sampler") {
         if (name == "sampler") {
-            for (var ind in this._newUniforms) {
+            for (var ind = 0; ind < this._newUniforms.length ; ind ++) {
                 if (this._customUniform[ind].indexOf('sampler') != -1) {
                 if (this._customUniform[ind].indexOf('sampler') != -1) {
                     arr.push(this._newUniforms[ind]);
                     arr.push(this._newUniforms[ind]);
                 }
                 }
@@ -106,7 +109,7 @@ export class CustomMaterial extends StandardMaterial {
         return arr;
         return arr;
     }
     }
 
 
-    public Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: StandardMaterialDefines, attributes?: string[]): string {
+    public Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: MaterialDefines | string[], attributes?: string[]): string {
 
 
         if (attributes && this._customAttributes && this._customAttributes.length > 0) {
         if (attributes && this._customAttributes && this._customAttributes.length > 0) {
             attributes.push(...this._customAttributes);
             attributes.push(...this._customAttributes);
@@ -139,6 +142,7 @@ export class CustomMaterial extends StandardMaterial {
             .replace('#define CUSTOM_VERTEX_MAIN_BEGIN', (this.CustomParts.Vertex_MainBegin ? this.CustomParts.Vertex_MainBegin : ""))
             .replace('#define CUSTOM_VERTEX_MAIN_BEGIN', (this.CustomParts.Vertex_MainBegin ? this.CustomParts.Vertex_MainBegin : ""))
             .replace('#define CUSTOM_VERTEX_UPDATE_POSITION', (this.CustomParts.Vertex_Before_PositionUpdated ? this.CustomParts.Vertex_Before_PositionUpdated : ""))
             .replace('#define CUSTOM_VERTEX_UPDATE_POSITION', (this.CustomParts.Vertex_Before_PositionUpdated ? this.CustomParts.Vertex_Before_PositionUpdated : ""))
             .replace('#define CUSTOM_VERTEX_UPDATE_NORMAL', (this.CustomParts.Vertex_Before_NormalUpdated ? this.CustomParts.Vertex_Before_NormalUpdated : ""))
             .replace('#define CUSTOM_VERTEX_UPDATE_NORMAL', (this.CustomParts.Vertex_Before_NormalUpdated ? this.CustomParts.Vertex_Before_NormalUpdated : ""))
+            .replace('#define CUSTOM_VERTEX_UPDATE_WORLDPOS', (this.CustomParts.Vertex_After_WorldPosComputed ? this.CustomParts.Vertex_After_WorldPosComputed : ""))
             .replace('#define CUSTOM_VERTEX_MAIN_END', (this.CustomParts.Vertex_MainEnd ? this.CustomParts.Vertex_MainEnd : ""));
             .replace('#define CUSTOM_VERTEX_MAIN_END', (this.CustomParts.Vertex_MainEnd ? this.CustomParts.Vertex_MainEnd : ""));
 
 
         Effect.ShadersStore[name + "PixelShader"] = this.FragmentShader
         Effect.ShadersStore[name + "PixelShader"] = this.FragmentShader
@@ -262,10 +266,15 @@ export class CustomMaterial extends StandardMaterial {
         return this;
         return this;
     }
     }
 
 
+    public Vertex_After_WorldPosComputed(shaderPart: string): CustomMaterial {
+        this.CustomParts.Vertex_After_WorldPosComputed = shaderPart;
+        return this;
+    }
+
     public Vertex_MainEnd(shaderPart: string): CustomMaterial {
     public Vertex_MainEnd(shaderPart: string): CustomMaterial {
         this.CustomParts.Vertex_MainEnd = shaderPart;
         this.CustomParts.Vertex_MainEnd = shaderPart;
         return this;
         return this;
     }
     }
 }
 }
 
 
-_TypeStore.RegisteredTypes["BABYLON.CustomMaterial"] = CustomMaterial;
+_TypeStore.RegisteredTypes["BABYLON.CustomMaterial"] = CustomMaterial;

+ 14 - 5
materialsLibrary/src/custom/pbrCustomMaterial.ts

@@ -1,6 +1,6 @@
 import { Texture } from "babylonjs/Materials/Textures/texture";
 import { Texture } from "babylonjs/Materials/Textures/texture";
 import { Effect } from "babylonjs/Materials/effect";
 import { Effect } from "babylonjs/Materials/effect";
-import { PBRMaterialDefines } from "babylonjs/Materials/PBR/pbrBaseMaterial";
+import { MaterialDefines } from "babylonjs/Materials/materialDefines";
 import { PBRMaterial } from "babylonjs/Materials/PBR/pbrMaterial";
 import { PBRMaterial } from "babylonjs/Materials/PBR/pbrMaterial";
 import { Mesh } from "babylonjs/Meshes/mesh";
 import { Mesh } from "babylonjs/Meshes/mesh";
 import { Scene } from "babylonjs/scene";
 import { Scene } from "babylonjs/scene";
@@ -39,6 +39,9 @@ export class ShaderAlebdoParts {
     // normalUpdated
     // normalUpdated
     public Vertex_Before_NormalUpdated: string;
     public Vertex_Before_NormalUpdated: string;
 
 
+    // worldPosComputed
+    public Vertex_After_WorldPosComputed: string;
+
     // mainEnd
     // mainEnd
     public Vertex_MainEnd: string;
     public Vertex_MainEnd: string;
 }
 }
@@ -86,14 +89,14 @@ export class PBRCustomMaterial extends PBRMaterial {
 
 
     public ReviewUniform(name: string, arr: string[]): string[] {
     public ReviewUniform(name: string, arr: string[]): string[] {
         if (name == "uniform") {
         if (name == "uniform") {
-            for (var ind in this._newUniforms) {
+            for (var ind = 0; ind < this._newUniforms.length ; ind ++) {
                 if (this._customUniform[ind].indexOf('sampler') == -1) {
                 if (this._customUniform[ind].indexOf('sampler') == -1) {
                     arr.push(this._newUniforms[ind]);
                     arr.push(this._newUniforms[ind]);
                 }
                 }
             }
             }
         }
         }
         if (name == "sampler") {
         if (name == "sampler") {
-            for (var ind in this._newUniforms) {
+            for (var ind = 0; ind < this._newUniforms.length ; ind ++) {
                 if (this._customUniform[ind].indexOf('sampler') != -1) {
                 if (this._customUniform[ind].indexOf('sampler') != -1) {
                     arr.push(this._newUniforms[ind]);
                     arr.push(this._newUniforms[ind]);
                 }
                 }
@@ -102,7 +105,7 @@ export class PBRCustomMaterial extends PBRMaterial {
         return arr;
         return arr;
     }
     }
 
 
-    public Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: PBRMaterialDefines, attributes?: string[]): string {
+    public Builder(shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: MaterialDefines | string[], attributes?: string[]): string {
 
 
         if (attributes && this._customAttributes && this._customAttributes.length > 0) {
         if (attributes && this._customAttributes && this._customAttributes.length > 0) {
             attributes.push(...this._customAttributes);
             attributes.push(...this._customAttributes);
@@ -135,6 +138,7 @@ export class PBRCustomMaterial extends PBRMaterial {
             .replace('#define CUSTOM_VERTEX_MAIN_BEGIN', (this.CustomParts.Vertex_MainBegin ? this.CustomParts.Vertex_MainBegin : ""))
             .replace('#define CUSTOM_VERTEX_MAIN_BEGIN', (this.CustomParts.Vertex_MainBegin ? this.CustomParts.Vertex_MainBegin : ""))
             .replace('#define CUSTOM_VERTEX_UPDATE_POSITION', (this.CustomParts.Vertex_Before_PositionUpdated ? this.CustomParts.Vertex_Before_PositionUpdated : ""))
             .replace('#define CUSTOM_VERTEX_UPDATE_POSITION', (this.CustomParts.Vertex_Before_PositionUpdated ? this.CustomParts.Vertex_Before_PositionUpdated : ""))
             .replace('#define CUSTOM_VERTEX_UPDATE_NORMAL', (this.CustomParts.Vertex_Before_NormalUpdated ? this.CustomParts.Vertex_Before_NormalUpdated : ""))
             .replace('#define CUSTOM_VERTEX_UPDATE_NORMAL', (this.CustomParts.Vertex_Before_NormalUpdated ? this.CustomParts.Vertex_Before_NormalUpdated : ""))
+            .replace('#define CUSTOM_VERTEX_UPDATE_WORLDPOS', (this.CustomParts.Vertex_After_WorldPosComputed ? this.CustomParts.Vertex_After_WorldPosComputed : ""))
             .replace('#define CUSTOM_VERTEX_MAIN_END', (this.CustomParts.Vertex_MainEnd ? this.CustomParts.Vertex_MainEnd : ""));
             .replace('#define CUSTOM_VERTEX_MAIN_END', (this.CustomParts.Vertex_MainEnd ? this.CustomParts.Vertex_MainEnd : ""));
 
 
         Effect.ShadersStore[name + "PixelShader"] = this.FragmentShader
         Effect.ShadersStore[name + "PixelShader"] = this.FragmentShader
@@ -270,10 +274,15 @@ export class PBRCustomMaterial extends PBRMaterial {
         return this;
         return this;
     }
     }
 
 
+    public Vertex_After_WorldPosComputed(shaderPart: string): PBRCustomMaterial {
+        this.CustomParts.Vertex_After_WorldPosComputed = shaderPart;
+        return this;
+    }
+
     public Vertex_MainEnd(shaderPart: string): PBRCustomMaterial {
     public Vertex_MainEnd(shaderPart: string): PBRCustomMaterial {
         this.CustomParts.Vertex_MainEnd = shaderPart;
         this.CustomParts.Vertex_MainEnd = shaderPart;
         return this;
         return this;
     }
     }
 }
 }
 
 
-_TypeStore.RegisteredTypes["BABYLON.PBRCustomMaterial"] = PBRCustomMaterial;
+_TypeStore.RegisteredTypes["BABYLON.PBRCustomMaterial"] = PBRCustomMaterial;

+ 2 - 0
src/Culling/ray.ts

@@ -34,6 +34,7 @@ export class Ray {
     // Methods
     // Methods
     /**
     /**
      * Checks if the ray intersects a box
      * Checks if the ray intersects a box
+     * This does not account for the ray lenght by design to improve perfs.
      * @param minimum bound of the box
      * @param minimum bound of the box
      * @param maximum bound of the box
      * @param maximum bound of the box
      * @param intersectionTreshold extra extend to be added to the box in all direction
      * @param intersectionTreshold extra extend to be added to the box in all direction
@@ -135,6 +136,7 @@ export class Ray {
 
 
     /**
     /**
      * Checks if the ray intersects a box
      * Checks if the ray intersects a box
+     * This does not account for the ray lenght by design to improve perfs.
      * @param box the bounding box to check
      * @param box the bounding box to check
      * @param intersectionTreshold extra extend to be added to the BoundingBox in all direction
      * @param intersectionTreshold extra extend to be added to the BoundingBox in all direction
      * @returns if the box was hit
      * @returns if the box was hit

+ 8 - 1
src/Engines/Processors/shaderProcessor.ts

@@ -288,6 +288,7 @@ export class ShaderProcessor {
         var match = regex.exec(sourceCode);
         var match = regex.exec(sourceCode);
 
 
         var returnValue = new String(sourceCode);
         var returnValue = new String(sourceCode);
+        var keepProcessing = false;
 
 
         while (match != null) {
         while (match != null) {
             var includeFile = match[1];
             var includeFile = match[1];
@@ -352,6 +353,8 @@ export class ShaderProcessor {
 
 
                 // Replace
                 // Replace
                 returnValue = returnValue.replace(match[0], includeContent);
                 returnValue = returnValue.replace(match[0], includeContent);
+
+                keepProcessing = keepProcessing || includeContent.indexOf("#include<") >= 0;
             } else {
             } else {
                 var includeShaderUrl = options.shadersRepository + "ShadersInclude/" + includeFile + ".fx";
                 var includeShaderUrl = options.shadersRepository + "ShadersInclude/" + includeFile + ".fx";
 
 
@@ -365,7 +368,11 @@ export class ShaderProcessor {
             match = regex.exec(sourceCode);
             match = regex.exec(sourceCode);
         }
         }
 
 
-        callback(returnValue);
+        if (keepProcessing) {
+            this._ProcessIncludes(returnValue.toString(), options, callback);
+        } else {
+            callback(returnValue);
+        }
     }
     }
 
 
     /**
     /**

+ 2 - 2
src/Engines/thinEngine.ts

@@ -2012,8 +2012,8 @@ export class ThinEngine {
     public createEffect(baseName: any, attributesNamesOrOptions: string[] | IEffectCreationOptions, uniformsNamesOrEngine: string[] | ThinEngine, samplers?: string[], defines?: string,
     public createEffect(baseName: any, attributesNamesOrOptions: string[] | IEffectCreationOptions, uniformsNamesOrEngine: string[] | ThinEngine, samplers?: string[], defines?: string,
         fallbacks?: IEffectFallbacks,
         fallbacks?: IEffectFallbacks,
         onCompiled?: Nullable<(effect: Effect) => void>, onError?: Nullable<(effect: Effect, errors: string) => void>, indexParameters?: any): Effect {
         onCompiled?: Nullable<(effect: Effect) => void>, onError?: Nullable<(effect: Effect, errors: string) => void>, indexParameters?: any): Effect {
-        var vertex = baseName.vertexElement || baseName.vertex || baseName;
-        var fragment = baseName.fragmentElement || baseName.fragment || baseName;
+        var vertex = baseName.vertexElement || baseName.vertex || baseName.vertexToken || baseName;
+        var fragment = baseName.fragmentElement || baseName.fragment || baseName.fragmentToken || baseName;
 
 
         var name = vertex + "+" + fragment + "@" + (defines ? defines : (<IEffectCreationOptions>attributesNamesOrOptions).defines);
         var name = vertex + "+" + fragment + "@" + (defines ? defines : (<IEffectCreationOptions>attributesNamesOrOptions).defines);
         if (this._compiledEffects[name]) {
         if (this._compiledEffects[name]) {

+ 13 - 5
src/Lights/Shadows/cascadedShadowGenerator.ts

@@ -797,6 +797,12 @@ export class CascadedShadowGenerator extends ShadowGenerator {
 
 
         this._shadowMap.onBeforeRenderObservable.add((layer: number) => {
         this._shadowMap.onBeforeRenderObservable.add((layer: number) => {
             this._currentLayer = layer;
             this._currentLayer = layer;
+            if (this._scene.getSceneUniformBuffer().useUbo) {
+                const sceneUBO = this._scene.getSceneUniformBuffer();
+                sceneUBO.updateMatrix("viewProjection", this.getCascadeTransformMatrix(layer)!);
+                sceneUBO.updateMatrix("view", this.getCascadeViewMatrix(layer)!);
+                sceneUBO.update();
+            }
         });
         });
 
 
         this._shadowMap.onBeforeBindObservable.add(() => {
         this._shadowMap.onBeforeBindObservable.add(() => {
@@ -809,14 +815,16 @@ export class CascadedShadowGenerator extends ShadowGenerator {
         this._splitFrustum();
         this._splitFrustum();
     }
     }
 
 
-    protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect): void {
-        effect.setMatrix("viewProjection", this.getCascadeTransformMatrix(this._currentLayer)!);
+    protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect, matriceNames: any): void {
+        effect.setMatrix(matriceNames?.viewProjection ?? "viewProjection", this.getCascadeTransformMatrix(this._currentLayer)!);
+
+        effect.setMatrix(matriceNames?.view ?? "view", this.getCascadeViewMatrix(this._currentLayer)!);
+
+        effect.setMatrix(matriceNames?.projection ?? "projection", this.getCascadeProjectionMatrix(this._currentLayer)!);
     }
     }
 
 
     protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void {
     protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void {
-        if (this._depthClamp && this._filter !== ShadowGenerator.FILTER_PCSS) {
-            defines.push("#define DEPTHCLAMP");
-        }
+        defines.push("#define SM_DEPTHCLAMP " + (this._depthClamp && this._filter !== ShadowGenerator.FILTER_PCSS ? "1" : "0"));
     }
     }
 
 
     /**
     /**

+ 218 - 180
src/Lights/Shadows/shadowGenerator.ts

@@ -885,10 +885,23 @@ export class ShadowGenerator implements IShadowGenerator {
             if (this._filter === ShadowGenerator.FILTER_PCF) {
             if (this._filter === ShadowGenerator.FILTER_PCF) {
                 engine.setColorWrite(false);
                 engine.setColorWrite(false);
             }
             }
+            if (this._scene.getSceneUniformBuffer().useUbo) {
+                const sceneUBO = this._scene.getSceneUniformBuffer();
+                sceneUBO.updateMatrix("viewProjection", this.getTransformMatrix());
+                sceneUBO.updateMatrix("view", this._viewMatrix);
+                sceneUBO.update();
+            }
         });
         });
 
 
         // Blur if required afer render.
         // Blur if required afer render.
         this._shadowMap.onAfterUnbindObservable.add(() => {
         this._shadowMap.onAfterUnbindObservable.add(() => {
+            if (this._scene.getSceneUniformBuffer().useUbo) {
+                const sceneUBO = this._scene.getSceneUniformBuffer();
+                sceneUBO.updateMatrix("viewProjection", this._scene.getTransformMatrix());
+                sceneUBO.updateMatrix("view", this._scene.getViewMatrix());
+                sceneUBO.update();
+            }
+
             if (this._filter === ShadowGenerator.FILTER_PCF) {
             if (this._filter === ShadowGenerator.FILTER_PCF) {
                 engine.setColorWrite(true);
                 engine.setColorWrite(true);
             }
             }
@@ -1004,7 +1017,12 @@ export class ShadowGenerator implements IShadowGenerator {
         }
         }
     }
     }
 
 
-    protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect): void {
+    protected _bindCustomEffectForRenderSubMeshForShadowMap(subMesh: SubMesh, effect: Effect, matriceNames: any): void {
+        effect.setMatrix(matriceNames?.viewProjection ?? "viewProjection", this.getTransformMatrix());
+
+        effect.setMatrix(matriceNames?.view ?? "view", this._viewMatrix);
+
+        effect.setMatrix(matriceNames?.projection ?? "projection", this._projectionMatrix);
     }
     }
 
 
     protected _renderSubMeshForShadowMap(subMesh: SubMesh): void {
     protected _renderSubMeshForShadowMap(subMesh: SubMesh): void {
@@ -1033,57 +1051,68 @@ export class ShadowGenerator implements IShadowGenerator {
 
 
         var hardwareInstancedRendering = (engine.getCaps().instancedArrays) && (batch.visibleInstances[subMesh._id] !== null) && (batch.visibleInstances[subMesh._id] !== undefined);
         var hardwareInstancedRendering = (engine.getCaps().instancedArrays) && (batch.visibleInstances[subMesh._id] !== null) && (batch.visibleInstances[subMesh._id] !== undefined);
         if (this.isReady(subMesh, hardwareInstancedRendering)) {
         if (this.isReady(subMesh, hardwareInstancedRendering)) {
-            engine.enableEffect(this._effect);
-            renderingMesh._bind(subMesh, this._effect, material.fillMode);
+            const shadowDepthWrapper = renderingMesh.material?.shadowDepthWrapper;
+
+            let effect = shadowDepthWrapper?.getEffect(subMesh, this) ?? this._effect;
+
+            engine.enableEffect(effect);
 
 
-            this._effect.setFloat3("biasAndScale", this.bias, this.normalBias, this.depthScale);
+            renderingMesh._bind(subMesh, effect, material.fillMode);
+
+            effect.setFloat3("biasAndScaleSM", this.bias, this.normalBias, this.depthScale);
 
 
-            this._effect.setMatrix("viewProjection", this.getTransformMatrix());
             if (this.getLight().getTypeID() === Light.LIGHTTYPEID_DIRECTIONALLIGHT) {
             if (this.getLight().getTypeID() === Light.LIGHTTYPEID_DIRECTIONALLIGHT) {
-                this._effect.setVector3("lightData", this._cachedDirection);
+                effect.setVector3("lightDataSM", this._cachedDirection);
             }
             }
             else {
             else {
-                this._effect.setVector3("lightData", this._cachedPosition);
+                effect.setVector3("lightDataSM", this._cachedPosition);
             }
             }
 
 
             if (scene.activeCamera) {
             if (scene.activeCamera) {
-                this._effect.setFloat2("depthValues", this.getLight().getDepthMinZ(scene.activeCamera), this.getLight().getDepthMinZ(scene.activeCamera) + this.getLight().getDepthMaxZ(scene.activeCamera));
+                effect.setFloat2("depthValuesSM", this.getLight().getDepthMinZ(scene.activeCamera), this.getLight().getDepthMinZ(scene.activeCamera) + this.getLight().getDepthMaxZ(scene.activeCamera));
             }
             }
 
 
-            // Alpha test
-            if (material && material.needAlphaTesting()) {
-                var alphaTexture = material.getAlphaTestTexture();
-                if (alphaTexture) {
-                    this._effect.setTexture("diffuseSampler", alphaTexture);
-                    this._effect.setMatrix("diffuseMatrix", alphaTexture.getTextureMatrix() || this._defaultTextureMatrix);
+            if (shadowDepthWrapper) {
+                subMesh._effectOverride = effect;
+                material.bindForSubMesh(effectiveMesh.getWorldMatrix(), renderingMesh, subMesh);
+                subMesh._effectOverride = null;
+            } else {
+                effect.setMatrix("viewProjection", this.getTransformMatrix());
+                // Alpha test
+                if (material && material.needAlphaTesting()) {
+                    var alphaTexture = material.getAlphaTestTexture();
+                    if (alphaTexture) {
+                        effect.setTexture("diffuseSampler", alphaTexture);
+                        effect.setMatrix("diffuseMatrix", alphaTexture.getTextureMatrix() || this._defaultTextureMatrix);
+                    }
                 }
                 }
-            }
 
 
-            // Bones
-            if (renderingMesh.useBones && renderingMesh.computeBonesUsingShaders && renderingMesh.skeleton) {
-                const skeleton = renderingMesh.skeleton;
+                // Bones
+                if (renderingMesh.useBones && renderingMesh.computeBonesUsingShaders && renderingMesh.skeleton) {
+                    const skeleton = renderingMesh.skeleton;
 
 
-                if (skeleton.isUsingTextureForMatrices) {
-                    const boneTexture = skeleton.getTransformMatrixTexture(renderingMesh);
+                    if (skeleton.isUsingTextureForMatrices) {
+                        const boneTexture = skeleton.getTransformMatrixTexture(renderingMesh);
 
 
-                    if (!boneTexture) {
-                        return;
-                    }
+                        if (!boneTexture) {
+                            return;
+                        }
 
 
-                    this._effect.setTexture("boneSampler", boneTexture);
-                    this._effect.setFloat("boneTextureWidth", 4.0 * (skeleton.bones.length + 1));
-                } else {
-                    this._effect.setMatrices("mBones", skeleton.getTransformMatrices((renderingMesh)));
+                        effect.setTexture("boneSampler", boneTexture);
+                        effect.setFloat("boneTextureWidth", 4.0 * (skeleton.bones.length + 1));
+                    } else {
+                        effect.setMatrices("mBones", skeleton.getTransformMatrices((renderingMesh)));
+                    }
                 }
                 }
-            }
 
 
-            // Morph targets
-            MaterialHelper.BindMorphTargetParameters(renderingMesh, this._effect);
+                // Morph targets
+                MaterialHelper.BindMorphTargetParameters(renderingMesh, effect);
 
 
-            // Clip planes
-            MaterialHelper.BindClipPlane(this._effect, scene);
+                // Clip planes
+                MaterialHelper.BindClipPlane(effect, scene);
+            }
 
 
-            this._bindCustomEffectForRenderSubMeshForShadowMap(subMesh, this._effect);
+            this._bindCustomEffectForRenderSubMeshForShadowMap(subMesh, effect, shadowDepthWrapper?._matriceNames);
 
 
             if (this.forceBackFacesOnly) {
             if (this.forceBackFacesOnly) {
                 engine.setState(true, 0, false, true);
                 engine.setState(true, 0, false, true);
@@ -1091,20 +1120,19 @@ export class ShadowGenerator implements IShadowGenerator {
 
 
             // Observables
             // Observables
             this.onBeforeShadowMapRenderMeshObservable.notifyObservers(renderingMesh);
             this.onBeforeShadowMapRenderMeshObservable.notifyObservers(renderingMesh);
-            this.onBeforeShadowMapRenderObservable.notifyObservers(this._effect);
+            this.onBeforeShadowMapRenderObservable.notifyObservers(effect);
 
 
             // Draw
             // Draw
-            renderingMesh._processRendering(effectiveMesh, subMesh, this._effect, material.fillMode, batch, hardwareInstancedRendering,
-                (isInstance, world) => this._effect.setMatrix("world", world));
+            renderingMesh._processRendering(effectiveMesh, subMesh, effect, material.fillMode, batch, hardwareInstancedRendering,
+                (isInstance, world) => effect.setMatrix("world", world));
 
 
             if (this.forceBackFacesOnly) {
             if (this.forceBackFacesOnly) {
                 engine.setState(true, 0, false, false);
                 engine.setState(true, 0, false, false);
             }
             }
 
 
             // Observables
             // Observables
-            this.onAfterShadowMapRenderObservable.notifyObservers(this._effect);
+            this.onAfterShadowMapRenderObservable.notifyObservers(effect);
             this.onAfterShadowMapRenderMeshObservable.notifyObservers(renderingMesh);
             this.onAfterShadowMapRenderMeshObservable.notifyObservers(renderingMesh);
-
         } else {
         } else {
             // Need to reset refresh rate of the shadowMap
             // Need to reset refresh rate of the shadowMap
             if (this._shadowMap) {
             if (this._shadowMap) {
@@ -1201,6 +1229,27 @@ export class ShadowGenerator implements IShadowGenerator {
     protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void {
     protected _isReadyCustomDefines(defines: any, subMesh: SubMesh, useInstances: boolean): void {
     }
     }
 
 
+    private _prepareShadowDefines(subMesh: SubMesh, useInstances: boolean, defines: string[]): string[] {
+        defines.push("#define SM_FLOAT " + (this._textureType !== Constants.TEXTURETYPE_UNSIGNED_INT ? "1" : "0"));
+
+        defines.push("#define SM_ESM " + (this.useExponentialShadowMap || this.useBlurExponentialShadowMap ? "1" : "0"));
+
+        defines.push("#define SM_DEPTHTEXTURE " + (this.usePercentageCloserFiltering || this.useContactHardeningShadow ? "1" : "0"));
+
+        var mesh = subMesh.getMesh();
+
+        // Normal bias.
+        defines.push("#define SM_NORMALBIAS " + (this.normalBias && mesh.isVerticesDataPresent(VertexBuffer.NormalKind) ? "1" : "0"));
+        defines.push("#define SM_DIRECTIONINLIGHTDATA " + (this.getLight().getTypeID() === Light.LIGHTTYPEID_DIRECTIONALLIGHT ? "1" : "0"));
+
+        // Point light
+        defines.push("#define SM_USEDISTANCE " + (this._light.needCube() ? "1" : "0"));
+
+        this._isReadyCustomDefines(defines, subMesh, useInstances);
+
+        return defines;
+    }
+
     /**
     /**
      * Determine wheter the shadow generator is ready or not (mainly all effects and related post processes needs to be ready).
      * Determine wheter the shadow generator is ready or not (mainly all effects and related post processes needs to be ready).
      * @param subMesh The submesh we want to render in the shadow map
      * @param subMesh The submesh we want to render in the shadow map
@@ -1208,182 +1257,171 @@ export class ShadowGenerator implements IShadowGenerator {
      * @returns true if ready otherwise, false
      * @returns true if ready otherwise, false
      */
      */
     public isReady(subMesh: SubMesh, useInstances: boolean): boolean {
     public isReady(subMesh: SubMesh, useInstances: boolean): boolean {
-        var defines = [];
+        const material = subMesh.getMaterial(),
+              shadowDepthWrapper = material?.shadowDepthWrapper;
 
 
-        if (this._textureType !== Constants.TEXTURETYPE_UNSIGNED_INT) {
-            defines.push("#define FLOAT");
-        }
+        const defines: string[] = [];
 
 
-        if (this.useExponentialShadowMap || this.useBlurExponentialShadowMap) {
-            defines.push("#define ESM");
-        }
-        else if (this.usePercentageCloserFiltering || this.useContactHardeningShadow) {
-            defines.push("#define DEPTHTEXTURE");
-        }
+        this._prepareShadowDefines(subMesh, useInstances, defines);
 
 
-        var attribs = [VertexBuffer.PositionKind];
+        if (shadowDepthWrapper) {
+            if (!shadowDepthWrapper.isReadyForSubMesh(subMesh, defines, this, useInstances)) {
+                return false;
+            }
+        } else {
+            var attribs = [VertexBuffer.PositionKind];
 
 
-        var mesh = subMesh.getMesh();
-        var material = subMesh.getMaterial();
+            var mesh = subMesh.getMesh();
 
 
-        // Normal bias.
-        if (this.normalBias && mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
-            attribs.push(VertexBuffer.NormalKind);
-            defines.push("#define NORMAL");
-            if (mesh.nonUniformScaling) {
-                defines.push("#define NONUNIFORMSCALING");
-            }
-            if (this.getLight().getTypeID() === Light.LIGHTTYPEID_DIRECTIONALLIGHT) {
-                defines.push("#define DIRECTIONINLIGHTDATA");
+            // Normal bias.
+            if (this.normalBias && mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
+                attribs.push(VertexBuffer.NormalKind);
+                defines.push("#define NORMAL");
+                if (mesh.nonUniformScaling) {
+                    defines.push("#define NONUNIFORMSCALING");
+                }
             }
             }
-        }
 
 
-        // Alpha test
-        if (material && material.needAlphaTesting()) {
-            var alphaTexture = material.getAlphaTestTexture();
-            if (alphaTexture) {
-                defines.push("#define ALPHATEST");
-                if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
-                    attribs.push(VertexBuffer.UVKind);
-                    defines.push("#define UV1");
-                }
-                if (mesh.isVerticesDataPresent(VertexBuffer.UV2Kind)) {
-                    if (alphaTexture.coordinatesIndex === 1) {
-                        attribs.push(VertexBuffer.UV2Kind);
-                        defines.push("#define UV2");
+            // Alpha test
+            if (material && material.needAlphaTesting()) {
+                var alphaTexture = material.getAlphaTestTexture();
+                if (alphaTexture) {
+                    defines.push("#define ALPHATEST");
+                    if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
+                        attribs.push(VertexBuffer.UVKind);
+                        defines.push("#define UV1");
+                    }
+                    if (mesh.isVerticesDataPresent(VertexBuffer.UV2Kind)) {
+                        if (alphaTexture.coordinatesIndex === 1) {
+                            attribs.push(VertexBuffer.UV2Kind);
+                            defines.push("#define UV2");
+                        }
                     }
                     }
                 }
                 }
             }
             }
-        }
 
 
-        // Bones
-        const fallbacks = new EffectFallbacks();
-        if (mesh.useBones && mesh.computeBonesUsingShaders && mesh.skeleton) {
-            attribs.push(VertexBuffer.MatricesIndicesKind);
-            attribs.push(VertexBuffer.MatricesWeightsKind);
-            if (mesh.numBoneInfluencers > 4) {
-                attribs.push(VertexBuffer.MatricesIndicesExtraKind);
-                attribs.push(VertexBuffer.MatricesWeightsExtraKind);
-            }
-            const skeleton = mesh.skeleton;
-            defines.push("#define NUM_BONE_INFLUENCERS " + mesh.numBoneInfluencers);
-            if (mesh.numBoneInfluencers > 0) {
-                fallbacks.addCPUSkinningFallback(0, mesh);
-            }
+            // Bones
+            const fallbacks = new EffectFallbacks();
+            if (mesh.useBones && mesh.computeBonesUsingShaders && mesh.skeleton) {
+                attribs.push(VertexBuffer.MatricesIndicesKind);
+                attribs.push(VertexBuffer.MatricesWeightsKind);
+                if (mesh.numBoneInfluencers > 4) {
+                    attribs.push(VertexBuffer.MatricesIndicesExtraKind);
+                    attribs.push(VertexBuffer.MatricesWeightsExtraKind);
+                }
+                const skeleton = mesh.skeleton;
+                defines.push("#define NUM_BONE_INFLUENCERS " + mesh.numBoneInfluencers);
+                if (mesh.numBoneInfluencers > 0) {
+                    fallbacks.addCPUSkinningFallback(0, mesh);
+                }
+
+                if (skeleton.isUsingTextureForMatrices) {
+                    defines.push("#define BONETEXTURE");
+                } else {
+                    defines.push("#define BonesPerMesh " + (skeleton.bones.length + 1));
+                }
 
 
-            if (skeleton.isUsingTextureForMatrices) {
-                defines.push("#define BONETEXTURE");
             } else {
             } else {
-                defines.push("#define BonesPerMesh " + (skeleton.bones.length + 1));
+                defines.push("#define NUM_BONE_INFLUENCERS 0");
             }
             }
 
 
-        } else {
-            defines.push("#define NUM_BONE_INFLUENCERS 0");
-        }
-
-        // Morph targets
-        var manager = (<Mesh>mesh).morphTargetManager;
-        let morphInfluencers = 0;
-        if (manager) {
-            if (manager.numInfluencers > 0) {
-                defines.push("#define MORPHTARGETS");
-                morphInfluencers = manager.numInfluencers;
-                defines.push("#define NUM_MORPH_INFLUENCERS " + morphInfluencers);
-                MaterialHelper.PrepareAttributesForMorphTargetsInfluencers(attribs, mesh, morphInfluencers);
+            // Morph targets
+            var manager = (<Mesh>mesh).morphTargetManager;
+            let morphInfluencers = 0;
+            if (manager) {
+                if (manager.numInfluencers > 0) {
+                    defines.push("#define MORPHTARGETS");
+                    morphInfluencers = manager.numInfluencers;
+                    defines.push("#define NUM_MORPH_INFLUENCERS " + morphInfluencers);
+                    MaterialHelper.PrepareAttributesForMorphTargetsInfluencers(attribs, mesh, morphInfluencers);
+                }
             }
             }
-        }
 
 
-        // ClipPlanes
-        const scene = this._scene;
-        if (scene.clipPlane) {
-            defines.push("#define CLIPPLANE");
-        }
-        if (scene.clipPlane2) {
-            defines.push("#define CLIPPLANE2");
-        }
-        if (scene.clipPlane3) {
-            defines.push("#define CLIPPLANE3");
-        }
-        if (scene.clipPlane4) {
-            defines.push("#define CLIPPLANE4");
-        }
-        if (scene.clipPlane5) {
-            defines.push("#define CLIPPLANE5");
-        }
-        if (scene.clipPlane6) {
-            defines.push("#define CLIPPLANE6");
-        }
+            // ClipPlanes
+            const scene = this._scene;
+            if (scene.clipPlane) {
+                defines.push("#define CLIPPLANE");
+            }
+            if (scene.clipPlane2) {
+                defines.push("#define CLIPPLANE2");
+            }
+            if (scene.clipPlane3) {
+                defines.push("#define CLIPPLANE3");
+            }
+            if (scene.clipPlane4) {
+                defines.push("#define CLIPPLANE4");
+            }
+            if (scene.clipPlane5) {
+                defines.push("#define CLIPPLANE5");
+            }
+            if (scene.clipPlane6) {
+                defines.push("#define CLIPPLANE6");
+            }
 
 
-        // Instances
-        if (useInstances) {
-            defines.push("#define INSTANCES");
-            MaterialHelper.PushAttributesForInstances(attribs);
-        }
+            // Instances
+            if (useInstances) {
+                defines.push("#define INSTANCES");
+                MaterialHelper.PushAttributesForInstances(attribs);
+            }
 
 
-        if (this.customShaderOptions) {
-            if (this.customShaderOptions.defines) {
-                for (var define of this.customShaderOptions.defines) {
-                    if (defines.indexOf(define) === -1) {
-                        defines.push(define);
+            if (this.customShaderOptions) {
+                if (this.customShaderOptions.defines) {
+                    for (var define of this.customShaderOptions.defines) {
+                        if (defines.indexOf(define) === -1) {
+                            defines.push(define);
+                        }
                     }
                     }
                 }
                 }
             }
             }
-        }
-
-        // Point light
-        if (this._light.needCube()) {
-            defines.push("#define USEDISTANCE");
-        }
 
 
-        this._isReadyCustomDefines(defines, subMesh, useInstances);
-
-        // Get correct effect
-        var join = defines.join("\n");
-        if (this._cachedDefines !== join) {
-            this._cachedDefines = join;
-
-            let shaderName = "shadowMap";
-            let uniforms = ["world", "mBones", "viewProjection", "diffuseMatrix", "lightData", "depthValues", "biasAndScale", "morphTargetInfluences", "boneTextureWidth",
-                            "vClipPlane", "vClipPlane2", "vClipPlane3", "vClipPlane4", "vClipPlane5", "vClipPlane6"];
-            let samplers = ["diffuseSampler", "boneSampler"];
-
-            // Custom shader?
-            if (this.customShaderOptions) {
-                shaderName = this.customShaderOptions.shaderName;
-
-                if (this.customShaderOptions.attributes) {
-                    for (var attrib of this.customShaderOptions.attributes) {
-                        if (attribs.indexOf(attrib) === -1) {
-                            attribs.push(attrib);
+            // Get correct effect
+            var join = defines.join("\n");
+            if (this._cachedDefines !== join) {
+                this._cachedDefines = join;
+
+                let shaderName = "shadowMap";
+                let uniforms = ["world", "mBones", "viewProjection", "diffuseMatrix", "lightDataSM", "depthValuesSM", "biasAndScaleSM", "morphTargetInfluences", "boneTextureWidth",
+                                "vClipPlane", "vClipPlane2", "vClipPlane3", "vClipPlane4", "vClipPlane5", "vClipPlane6"];
+                let samplers = ["diffuseSampler", "boneSampler"];
+
+                // Custom shader?
+                if (this.customShaderOptions) {
+                    shaderName = this.customShaderOptions.shaderName;
+
+                    if (this.customShaderOptions.attributes) {
+                        for (var attrib of this.customShaderOptions.attributes) {
+                            if (attribs.indexOf(attrib) === -1) {
+                                attribs.push(attrib);
+                            }
                         }
                         }
                     }
                     }
-                }
 
 
-                if (this.customShaderOptions.uniforms) {
-                    for (var uniform of this.customShaderOptions.uniforms) {
-                        if (uniforms.indexOf(uniform) === -1) {
-                            uniforms.push(uniform);
+                    if (this.customShaderOptions.uniforms) {
+                        for (var uniform of this.customShaderOptions.uniforms) {
+                            if (uniforms.indexOf(uniform) === -1) {
+                                uniforms.push(uniform);
+                            }
                         }
                         }
                     }
                     }
-                }
 
 
-                if (this.customShaderOptions.samplers) {
-                    for (var sampler of this.customShaderOptions.samplers) {
-                        if (samplers.indexOf(sampler) === -1) {
-                            samplers.push(sampler);
+                    if (this.customShaderOptions.samplers) {
+                        for (var sampler of this.customShaderOptions.samplers) {
+                            if (samplers.indexOf(sampler) === -1) {
+                                samplers.push(sampler);
+                            }
                         }
                         }
                     }
                     }
                 }
                 }
-            }
 
 
-            this._effect = this._scene.getEngine().createEffect(shaderName,
-                attribs, uniforms,
-                samplers, join,
-                fallbacks, undefined, undefined, { maxSimultaneousMorphTargets: morphInfluencers });
-        }
+                this._effect = this._scene.getEngine().createEffect(shaderName,
+                    attribs, uniforms,
+                    samplers, join,
+                    fallbacks, undefined, undefined, { maxSimultaneousMorphTargets: morphInfluencers });
+            }
 
 
-        if (!this._effect.isReady()) {
-            return false;
+            if (!this._effect.isReady()) {
+                return false;
+            }
         }
         }
 
 
         if (this.useBlurExponentialShadowMap || this.useBlurCloseExponentialShadowMap) {
         if (this.useBlurExponentialShadowMap || this.useBlurCloseExponentialShadowMap) {

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

@@ -29,6 +29,9 @@ import { TextureBlock } from './Blocks/Dual/textureBlock';
 import { ReflectionTextureBlock } from './Blocks/Dual/reflectionTextureBlock';
 import { ReflectionTextureBlock } from './Blocks/Dual/reflectionTextureBlock';
 import { EffectFallbacks } from '../effectFallbacks';
 import { EffectFallbacks } from '../effectFallbacks';
 import { WebRequest } from '../../Misc/webRequest';
 import { WebRequest } from '../../Misc/webRequest';
+import { Effect } from '../effect';
+
+const onCreatedEffectParameters = { effect: null as unknown as Effect, subMesh: null as unknown as Nullable<SubMesh> };
 
 
 // declare NODEEDITOR namespace for compilation issue
 // declare NODEEDITOR namespace for compilation issue
 declare var NODEEDITOR: any;
 declare var NODEEDITOR: any;
@@ -818,6 +821,12 @@ export class NodeMaterial extends PushMaterial {
             }, engine);
             }, engine);
 
 
             if (effect) {
             if (effect) {
+                if (this._onEffectCreatedObservable) {
+                    onCreatedEffectParameters.effect = effect;
+                    onCreatedEffectParameters.subMesh = subMesh;
+                    this._onEffectCreatedObservable.notifyObservers(onCreatedEffectParameters);
+                }
+
                 // Use previous effect while new one is compiling
                 // Use previous effect while new one is compiling
                 if (this.allowShaderHotSwapping && previousEffect && !effect.isReady()) {
                 if (this.allowShaderHotSwapping && previousEffect && !effect.isReady()) {
                     effect = previousEffect;
                     effect = previousEffect;

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

@@ -39,6 +39,8 @@ import "../../Shaders/pbr.fragment";
 import "../../Shaders/pbr.vertex";
 import "../../Shaders/pbr.vertex";
 import { EffectFallbacks } from '../effectFallbacks';
 import { EffectFallbacks } from '../effectFallbacks';
 
 
+const onCreatedEffectParameters = { effect: null as unknown as Effect, subMesh: null as unknown as Nullable<SubMesh> };
+
 /**
 /**
  * Manages the defines for the PBR Material.
  * Manages the defines for the PBR Material.
  * @hidden
  * @hidden
@@ -745,11 +747,6 @@ export abstract class PBRBaseMaterial extends PushMaterial {
      */
      */
     public readonly subSurface = new PBRSubSurfaceConfiguration(this._markAllSubMeshesAsTexturesDirty.bind(this));
     public readonly subSurface = new PBRSubSurfaceConfiguration(this._markAllSubMeshesAsTexturesDirty.bind(this));
 
 
-    /**
-     * Custom callback helping to override the default shader used in the material.
-     */
-    public customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: PBRMaterialDefines, attributes?: string[]) => string;
-
     protected _rebuildInParallel = false;
     protected _rebuildInParallel = false;
 
 
     /**
     /**
@@ -987,6 +984,12 @@ export abstract class PBRBaseMaterial extends PushMaterial {
         let effect = this._prepareEffect(mesh, defines, this.onCompiled, this.onError, useInstances);
         let effect = this._prepareEffect(mesh, defines, this.onCompiled, this.onError, useInstances);
 
 
         if (effect) {
         if (effect) {
+            if (this._onEffectCreatedObservable) {
+                onCreatedEffectParameters.effect = effect;
+                onCreatedEffectParameters.subMesh = subMesh;
+                this._onEffectCreatedObservable.notifyObservers(onCreatedEffectParameters);
+            }
+
             // Use previous effect while new one is compiling
             // Use previous effect while new one is compiling
             if (this.allowShaderHotSwapping && previousEffect && !effect.isReady()) {
             if (this.allowShaderHotSwapping && previousEffect && !effect.isReady()) {
                 effect = previousEffect;
                 effect = previousEffect;
@@ -1513,6 +1516,11 @@ export abstract class PBRBaseMaterial extends PushMaterial {
 
 
         const defines = new PBRMaterialDefines();
         const defines = new PBRMaterialDefines();
         const effect = this._prepareEffect(mesh, defines, undefined, undefined, localOptions.useInstances, localOptions.clipPlane)!;
         const effect = this._prepareEffect(mesh, defines, undefined, undefined, localOptions.useInstances, localOptions.clipPlane)!;
+        if (this._onEffectCreatedObservable) {
+            onCreatedEffectParameters.effect = effect;
+            onCreatedEffectParameters.subMesh = null;
+            this._onEffectCreatedObservable.notifyObservers(onCreatedEffectParameters);
+        }
         if (effect.isReady()) {
         if (effect.isReady()) {
             if (onCompiled) {
             if (onCompiled) {
                 onCompiled(this);
                 onCompiled(this);

+ 42 - 1
src/Materials/effect.ts

@@ -139,6 +139,7 @@ export class Effect implements IDisposable {
     private static _uniqueIdSeed = 0;
     private static _uniqueIdSeed = 0;
     private _engine: Engine;
     private _engine: Engine;
     private _uniformBuffersNames: { [key: string]: number } = {};
     private _uniformBuffersNames: { [key: string]: number } = {};
+    private _uniformBuffersNamesList: string[];
     private _uniformsNames: string[];
     private _uniformsNames: string[];
     private _samplerList: string[];
     private _samplerList: string[];
     private _samplers: { [key: string]: number } = {};
     private _samplers: { [key: string]: number } = {};
@@ -203,6 +204,7 @@ export class Effect implements IDisposable {
             this._transformFeedbackVaryings = options.transformFeedbackVaryings || null;
             this._transformFeedbackVaryings = options.transformFeedbackVaryings || null;
 
 
             if (options.uniformBuffersNames) {
             if (options.uniformBuffersNames) {
+                this._uniformBuffersNamesList = options.uniformBuffersNames.slice();
                 for (var i = 0; i < options.uniformBuffersNames.length; i++) {
                 for (var i = 0; i < options.uniformBuffersNames.length; i++) {
                     this._uniformBuffersNames[options.uniformBuffersNames[i]] = i;
                     this._uniformBuffersNames[options.uniformBuffersNames[i]] = i;
                 }
                 }
@@ -213,6 +215,7 @@ export class Effect implements IDisposable {
             this._uniformsNames = (<string[]>uniformsNamesOrEngine).concat(<string[]>samplers);
             this._uniformsNames = (<string[]>uniformsNamesOrEngine).concat(<string[]>samplers);
             this._samplerList = samplers ? <string[]>samplers.slice() : [];
             this._samplerList = samplers ? <string[]>samplers.slice() : [];
             this._attributesNames = (<string[]>attributesNamesOrOptions);
             this._attributesNames = (<string[]>attributesNamesOrOptions);
+            this._uniformBuffersNamesList = [];
 
 
             this.onError = onError;
             this.onError = onError;
             this.onCompiled = onCompiled;
             this.onCompiled = onCompiled;
@@ -393,13 +396,37 @@ export class Effect implements IDisposable {
 
 
     /**
     /**
      * Returns an array of sampler variable names
      * Returns an array of sampler variable names
-     * @returns The array of sampler variable neames.
+     * @returns The array of sampler variable names.
      */
      */
     public getSamplers(): string[] {
     public getSamplers(): string[] {
         return this._samplerList;
         return this._samplerList;
     }
     }
 
 
     /**
     /**
+     * Returns an array of uniform variable names
+     * @returns The array of uniform variable names.
+     */
+    public getUniformNames(): string[] {
+        return this._uniformsNames;
+    }
+
+    /**
+     * Returns an array of uniform buffer variable names
+     * @returns The array of uniform buffer variable names.
+     */
+    public getUniformBuffersNames(): string[] {
+        return this._uniformBuffersNamesList;
+    }
+
+    /**
+     * Returns the index parameters used to create the effect
+     * @returns The index parameters object
+     */
+    public getIndexParameters(): any {
+        return this._indexParameters;
+    }
+
+    /**
      * The error from the last compilation.
      * The error from the last compilation.
      * @returns the error string.
      * @returns the error string.
      */
      */
@@ -498,6 +525,20 @@ export class Effect implements IDisposable {
     }
     }
 
 
     /**
     /**
+     * Gets the vertex shader source code of this effect
+     */
+    public get vertexSourceCode(): string {
+        return this._vertexSourceCodeOverride && this._fragmentSourceCodeOverride ? this._vertexSourceCodeOverride : this._vertexSourceCode;
+    }
+
+    /**
+     * Gets the fragment shader source code of this effect
+     */
+    public get fragmentSourceCode(): string {
+        return this._vertexSourceCodeOverride && this._fragmentSourceCodeOverride ? this._fragmentSourceCodeOverride : this._fragmentSourceCode;
+    }
+
+    /**
      * Recompiles the webGL program
      * Recompiles the webGL program
      * @param vertexSourceCode The source code for the vertex shader.
      * @param vertexSourceCode The source code for the vertex shader.
      * @param fragmentSourceCode The source code for the fragment shader.
      * @param fragmentSourceCode The source code for the fragment shader.

+ 2 - 1
src/Materials/index.ts

@@ -17,4 +17,5 @@ export * from "./Textures/index";
 export * from "./uniformBuffer";
 export * from "./uniformBuffer";
 export * from "./materialFlags";
 export * from "./materialFlags";
 export * from "./Node/index";
 export * from "./Node/index";
-export * from "./effectRenderer";
+export * from "./effectRenderer";
+export * from "./shadowDepthWrapper";

+ 28 - 0
src/Materials/material.ts

@@ -19,6 +19,7 @@ import { Constants } from "../Engines/constants";
 import { Logger } from "../Misc/logger";
 import { Logger } from "../Misc/logger";
 import { IInspectable } from '../Misc/iInspectable';
 import { IInspectable } from '../Misc/iInspectable';
 import { Plane } from '../Maths/math.plane';
 import { Plane } from '../Maths/math.plane';
+import { ShadowDepthWrapper } from './shadowDepthWrapper';
 
 
 declare type Mesh = import("../Meshes/mesh").Mesh;
 declare type Mesh = import("../Meshes/mesh").Mesh;
 declare type Animation = import("../Animations/animation").Animation;
 declare type Animation = import("../Animations/animation").Animation;
@@ -144,6 +145,16 @@ export class Material implements IAnimatable {
     public static readonly MATERIAL_ALPHATESTANDBLEND = 3;
     public static readonly MATERIAL_ALPHATESTANDBLEND = 3;
 
 
     /**
     /**
+     * Custom callback helping to override the default shader used in the material.
+     */
+    public customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: MaterialDefines | string[], attributes?: string[]) => string;
+
+    /**
+     * Custom shadow depth material to use for shadow rendering instead of the in-built one
+     */
+    public shadowDepthWrapper: Nullable<ShadowDepthWrapper> = null;
+
+    /**
      * The ID of the material
      * The ID of the material
      */
      */
     @serialize()
     @serialize()
@@ -346,6 +357,19 @@ export class Material implements IAnimatable {
         return this._onUnBindObservable;
         return this._onUnBindObservable;
     }
     }
 
 
+    protected _onEffectCreatedObservable: Nullable<Observable<{ effect: Effect, subMesh: Nullable<SubMesh>}>>;
+
+    /**
+    * An event triggered when the effect is (re)created
+    */
+    public get onEffectCreatedObservable(): Observable<{ effect: Effect, subMesh: Nullable<SubMesh>}> {
+        if (!this._onEffectCreatedObservable) {
+            this._onEffectCreatedObservable = new Observable<{effect: Effect, subMesh: Nullable<SubMesh>}>();
+        }
+
+        return this._onEffectCreatedObservable;
+    }
+
     /**
     /**
      * Stores the value of the alpha mode
      * Stores the value of the alpha mode
      */
      */
@@ -1273,6 +1297,10 @@ export class Material implements IAnimatable {
         if (this._onUnBindObservable) {
         if (this._onUnBindObservable) {
             this._onUnBindObservable.clear();
             this._onUnBindObservable.clear();
         }
         }
+
+        if (this._onEffectCreatedObservable) {
+            this._onEffectCreatedObservable.clear();
+        }
     }
     }
 
 
     /** @hidden */
     /** @hidden */

+ 93 - 48
src/Materials/shaderMaterial.ts

@@ -1,19 +1,22 @@
 import { SerializationHelper } from "../Misc/decorators";
 import { SerializationHelper } from "../Misc/decorators";
+import { Nullable } from "../types";
 import { Scene } from "../scene";
 import { Scene } from "../scene";
 import { Matrix, Vector3, Vector2, Vector4 } from "../Maths/math.vector";
 import { Matrix, Vector3, Vector2, Vector4 } from "../Maths/math.vector";
 import { AbstractMesh } from "../Meshes/abstractMesh";
 import { AbstractMesh } from "../Meshes/abstractMesh";
 import { Mesh } from "../Meshes/mesh";
 import { Mesh } from "../Meshes/mesh";
-import { BaseSubMesh } from "../Meshes/subMesh";
+import { SubMesh, BaseSubMesh } from "../Meshes/subMesh";
 import { VertexBuffer } from "../Meshes/buffer";
 import { VertexBuffer } from "../Meshes/buffer";
 import { BaseTexture } from "../Materials/Textures/baseTexture";
 import { BaseTexture } from "../Materials/Textures/baseTexture";
 import { Texture } from "../Materials/Textures/texture";
 import { Texture } from "../Materials/Textures/texture";
 import { MaterialHelper } from "./materialHelper";
 import { MaterialHelper } from "./materialHelper";
-import { IEffectCreationOptions } from "./effect";
+import { Effect, IEffectCreationOptions } from "./effect";
 import { Material } from "./material";
 import { Material } from "./material";
 import { _TypeStore } from '../Misc/typeStore';
 import { _TypeStore } from '../Misc/typeStore';
 import { Color3, Color4 } from '../Maths/math.color';
 import { Color3, Color4 } from '../Maths/math.color';
 import { EffectFallbacks } from './effectFallbacks';
 import { EffectFallbacks } from './effectFallbacks';
 
 
+const onCreatedEffectParameters = { effect: null as unknown as Effect, subMesh: null as unknown as Nullable<SubMesh> };
+
 /**
 /**
  * Defines the options associated with the creation of a shader material.
  * Defines the options associated with the creation of a shader material.
  */
  */
@@ -87,6 +90,7 @@ export class ShaderMaterial extends Material {
     private _cachedWorldViewProjectionMatrix = new Matrix();
     private _cachedWorldViewProjectionMatrix = new Matrix();
     private _renderId: number;
     private _renderId: number;
     private _multiview: boolean = false;
     private _multiview: boolean = false;
+    private _cachedDefines: string;
 
 
     /**
     /**
      * Instantiate a new shader material.
      * Instantiate a new shader material.
@@ -571,21 +575,42 @@ export class ShaderMaterial extends Material {
             defines.push("#define ALPHATEST");
             defines.push("#define ALPHATEST");
         }
         }
 
 
+        let shaderName = this._shaderPath,
+            uniforms = this._options.uniforms,
+            uniformBuffers = this._options.uniformBuffers,
+            samplers = this._options.samplers;
+
+        if (this.customShaderNameResolve) {
+            uniforms = uniforms.slice();
+            uniformBuffers = uniformBuffers.slice();
+            samplers = samplers.slice();
+            shaderName = this.customShaderNameResolve(shaderName, uniforms, uniformBuffers, samplers, defines, attribs);
+        }
+
         var previousEffect = this._effect;
         var previousEffect = this._effect;
         var join = defines.join("\n");
         var join = defines.join("\n");
 
 
-        this._effect = engine.createEffect(this._shaderPath, <IEffectCreationOptions>{
-            attributes: attribs,
-            uniformsNames: this._options.uniforms,
-            uniformBuffersNames: this._options.uniformBuffers,
-            samplers: this._options.samplers,
-            defines: join,
-            fallbacks: fallbacks,
-            onCompiled: this.onCompiled,
-            onError: this.onError
-        }, engine);
-
-        if (!this._effect.isReady()) {
+        if (this._cachedDefines !== join) {
+            this._cachedDefines = join;
+
+            this._effect = engine.createEffect(shaderName, <IEffectCreationOptions>{
+                attributes: attribs,
+                uniformsNames: uniforms,
+                uniformBuffersNames: uniformBuffers,
+                samplers: samplers,
+                defines: join,
+                fallbacks: fallbacks,
+                onCompiled: this.onCompiled,
+                onError: this.onError
+            }, engine);
+
+            if (this._onEffectCreatedObservable) {
+                onCreatedEffectParameters.effect = this._effect;
+                this._onEffectCreatedObservable.notifyObservers(onCreatedEffectParameters);
+            }
+        }
+
+        if (!this._effect?.isReady() ?? true) {
             return false;
             return false;
         }
         }
 
 
@@ -602,163 +627,183 @@ export class ShaderMaterial extends Material {
     /**
     /**
      * Binds the world matrix to the material
      * Binds the world matrix to the material
      * @param world defines the world transformation matrix
      * @param world defines the world transformation matrix
+     * @param effectOverride - If provided, use this effect instead of internal effect
      */
      */
-    public bindOnlyWorldMatrix(world: Matrix): void {
+    public bindOnlyWorldMatrix(world: Matrix, effectOverride?: Nullable<Effect>): void {
         var scene = this.getScene();
         var scene = this.getScene();
 
 
-        if (!this._effect) {
+        const effect = effectOverride ?? this._effect;
+
+        if (!effect) {
             return;
             return;
         }
         }
 
 
         if (this._options.uniforms.indexOf("world") !== -1) {
         if (this._options.uniforms.indexOf("world") !== -1) {
-            this._effect.setMatrix("world", world);
+            effect.setMatrix("world", world);
         }
         }
 
 
         if (this._options.uniforms.indexOf("worldView") !== -1) {
         if (this._options.uniforms.indexOf("worldView") !== -1) {
             world.multiplyToRef(scene.getViewMatrix(), this._cachedWorldViewMatrix);
             world.multiplyToRef(scene.getViewMatrix(), this._cachedWorldViewMatrix);
-            this._effect.setMatrix("worldView", this._cachedWorldViewMatrix);
+            effect.setMatrix("worldView", this._cachedWorldViewMatrix);
         }
         }
 
 
         if (this._options.uniforms.indexOf("worldViewProjection") !== -1) {
         if (this._options.uniforms.indexOf("worldViewProjection") !== -1) {
             world.multiplyToRef(scene.getTransformMatrix(), this._cachedWorldViewProjectionMatrix);
             world.multiplyToRef(scene.getTransformMatrix(), this._cachedWorldViewProjectionMatrix);
-            this._effect.setMatrix("worldViewProjection", this._cachedWorldViewProjectionMatrix);
-
+            effect.setMatrix("worldViewProjection", this._cachedWorldViewProjectionMatrix);
         }
         }
     }
     }
 
 
     /**
     /**
+     * Binds the submesh to this material by preparing the effect and shader to draw
+     * @param world defines the world transformation matrix
+     * @param mesh defines the mesh containing the submesh
+     * @param subMesh defines the submesh to bind the material to
+     */
+    public bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void {
+        this.bind(world, mesh, subMesh._effectOverride);
+    }
+
+    /**
      * Binds the material to the mesh
      * Binds the material to the mesh
      * @param world defines the world transformation matrix
      * @param world defines the world transformation matrix
      * @param mesh defines the mesh to bind the material to
      * @param mesh defines the mesh to bind the material to
+     * @param effectOverride - If provided, use this effect instead of internal effect
      */
      */
-    public bind(world: Matrix, mesh?: Mesh): void {
+    public bind(world: Matrix, mesh?: Mesh, effectOverride?: Nullable<Effect>): void {
         // Std values
         // Std values
-        this.bindOnlyWorldMatrix(world);
+        this.bindOnlyWorldMatrix(world, effectOverride);
+
+        const effect = effectOverride ?? this._effect;
 
 
-        if (this._effect && this.getScene().getCachedMaterial() !== this) {
+        if (effect && this.getScene().getCachedMaterial() !== this) {
             if (this._options.uniforms.indexOf("view") !== -1) {
             if (this._options.uniforms.indexOf("view") !== -1) {
-                this._effect.setMatrix("view", this.getScene().getViewMatrix());
+                effect.setMatrix("view", this.getScene().getViewMatrix());
             }
             }
 
 
             if (this._options.uniforms.indexOf("projection") !== -1) {
             if (this._options.uniforms.indexOf("projection") !== -1) {
-                this._effect.setMatrix("projection", this.getScene().getProjectionMatrix());
+                effect.setMatrix("projection", this.getScene().getProjectionMatrix());
             }
             }
 
 
             if (this._options.uniforms.indexOf("viewProjection") !== -1) {
             if (this._options.uniforms.indexOf("viewProjection") !== -1) {
-                this._effect.setMatrix("viewProjection", this.getScene().getTransformMatrix());
+                effect.setMatrix("viewProjection", this.getScene().getTransformMatrix());
                 if (this._multiview) {
                 if (this._multiview) {
-                    this._effect.setMatrix("viewProjectionR", this.getScene()._transformMatrixR);
+                    effect.setMatrix("viewProjectionR", this.getScene()._transformMatrixR);
                 }
                 }
             }
             }
 
 
             if (this.getScene().activeCamera && this._options.uniforms.indexOf("cameraPosition") !== -1) {
             if (this.getScene().activeCamera && this._options.uniforms.indexOf("cameraPosition") !== -1) {
-                this._effect.setVector3("cameraPosition", this.getScene().activeCamera!.globalPosition);
+                effect.setVector3("cameraPosition", this.getScene().activeCamera!.globalPosition);
             }
             }
 
 
             // Bones
             // Bones
-            MaterialHelper.BindBonesParameters(mesh, this._effect);
+            MaterialHelper.BindBonesParameters(mesh, effect);
 
 
             var name: string;
             var name: string;
             // Texture
             // Texture
             for (name in this._textures) {
             for (name in this._textures) {
-                this._effect.setTexture(name, this._textures[name]);
+                effect.setTexture(name, this._textures[name]);
             }
             }
 
 
             // Texture arrays
             // Texture arrays
             for (name in this._textureArrays) {
             for (name in this._textureArrays) {
-                this._effect.setTextureArray(name, this._textureArrays[name]);
+                effect.setTextureArray(name, this._textureArrays[name]);
             }
             }
 
 
             // Int
             // Int
             for (name in this._ints) {
             for (name in this._ints) {
-                this._effect.setInt(name, this._ints[name]);
+                effect.setInt(name, this._ints[name]);
             }
             }
 
 
             // Float
             // Float
             for (name in this._floats) {
             for (name in this._floats) {
-                this._effect.setFloat(name, this._floats[name]);
+                effect.setFloat(name, this._floats[name]);
             }
             }
 
 
             // Floats
             // Floats
             for (name in this._floatsArrays) {
             for (name in this._floatsArrays) {
-                this._effect.setArray(name, this._floatsArrays[name]);
+                effect.setArray(name, this._floatsArrays[name]);
             }
             }
 
 
             // Color3
             // Color3
             for (name in this._colors3) {
             for (name in this._colors3) {
-                this._effect.setColor3(name, this._colors3[name]);
+                effect.setColor3(name, this._colors3[name]);
             }
             }
 
 
             // Color3Array
             // Color3Array
             for (name in this._colors3Arrays) {
             for (name in this._colors3Arrays) {
-                this._effect.setArray3(name, this._colors3Arrays[name]);
+                effect.setArray3(name, this._colors3Arrays[name]);
             }
             }
 
 
             // Color4
             // Color4
             for (name in this._colors4) {
             for (name in this._colors4) {
                 var color = this._colors4[name];
                 var color = this._colors4[name];
-                this._effect.setFloat4(name, color.r, color.g, color.b, color.a);
+                effect.setFloat4(name, color.r, color.g, color.b, color.a);
             }
             }
 
 
             // Color4Array
             // Color4Array
             for (name in this._colors4Arrays) {
             for (name in this._colors4Arrays) {
-                this._effect.setArray4(name, this._colors4Arrays[name]);
+                effect.setArray4(name, this._colors4Arrays[name]);
             }
             }
 
 
             // Vector2
             // Vector2
             for (name in this._vectors2) {
             for (name in this._vectors2) {
-                this._effect.setVector2(name, this._vectors2[name]);
+                effect.setVector2(name, this._vectors2[name]);
             }
             }
 
 
             // Vector3
             // Vector3
             for (name in this._vectors3) {
             for (name in this._vectors3) {
-                this._effect.setVector3(name, this._vectors3[name]);
+                effect.setVector3(name, this._vectors3[name]);
             }
             }
 
 
             // Vector4
             // Vector4
             for (name in this._vectors4) {
             for (name in this._vectors4) {
-                this._effect.setVector4(name, this._vectors4[name]);
+                effect.setVector4(name, this._vectors4[name]);
             }
             }
 
 
             // Matrix
             // Matrix
             for (name in this._matrices) {
             for (name in this._matrices) {
-                this._effect.setMatrix(name, this._matrices[name]);
+                effect.setMatrix(name, this._matrices[name]);
             }
             }
 
 
             // MatrixArray
             // MatrixArray
             for (name in this._matrixArrays) {
             for (name in this._matrixArrays) {
-                this._effect.setMatrices(name, this._matrixArrays[name]);
+                effect.setMatrices(name, this._matrixArrays[name]);
             }
             }
 
 
             // Matrix 3x3
             // Matrix 3x3
             for (name in this._matrices3x3) {
             for (name in this._matrices3x3) {
-                this._effect.setMatrix3x3(name, this._matrices3x3[name]);
+                effect.setMatrix3x3(name, this._matrices3x3[name]);
             }
             }
 
 
             // Matrix 2x2
             // Matrix 2x2
             for (name in this._matrices2x2) {
             for (name in this._matrices2x2) {
-                this._effect.setMatrix2x2(name, this._matrices2x2[name]);
+                effect.setMatrix2x2(name, this._matrices2x2[name]);
             }
             }
 
 
             // Vector2Array
             // Vector2Array
             for (name in this._vectors2Arrays) {
             for (name in this._vectors2Arrays) {
-                this._effect.setArray2(name, this._vectors2Arrays[name]);
+                effect.setArray2(name, this._vectors2Arrays[name]);
             }
             }
 
 
             // Vector3Array
             // Vector3Array
             for (name in this._vectors3Arrays) {
             for (name in this._vectors3Arrays) {
-                this._effect.setArray3(name, this._vectors3Arrays[name]);
+                effect.setArray3(name, this._vectors3Arrays[name]);
             }
             }
 
 
             // Vector4Array
             // Vector4Array
             for (name in this._vectors4Arrays) {
             for (name in this._vectors4Arrays) {
-                this._effect.setArray4(name, this._vectors4Arrays[name]);
+                effect.setArray4(name, this._vectors4Arrays[name]);
             }
             }
         }
         }
 
 
         this._afterBind(mesh);
         this._afterBind(mesh);
     }
     }
 
 
+    protected _afterBind(mesh?: Mesh): void {
+        super._afterBind(mesh);
+        this.getScene()._cachedEffect = this._effect;
+    }
+
     /**
     /**
      * Gets the active textures from the material
      * Gets the active textures from the material
      * @returns an array of textures
      * @returns an array of textures

+ 234 - 0
src/Materials/shadowDepthWrapper.ts

@@ -0,0 +1,234 @@
+import { Observer } from "../Misc/observable";
+import { Nullable } from "../types";
+import { Scene } from "../scene";
+import { SubMesh } from "../Meshes/subMesh";
+import { Material } from "./material";
+import { _TypeStore } from "../Misc/typeStore";
+import { Effect, IEffectCreationOptions } from './effect';
+import { AbstractMesh } from '../Meshes/abstractMesh';
+import { Node } from '../node';
+import { ShadowGenerator } from '../Lights/Shadows/shadowGenerator';
+import { GUID } from '../Misc/guid';
+
+/**
+ * Options to be used when creating a shadow depth material
+ */
+export interface IIOptionShadowDepthMaterial {
+    /** Variables in the vertex shader code that need to have their names remapped.
+     * The format is: ["var_name", "var_remapped_name", "var_name", "var_remapped_name", ...]
+     * "var_name" should be either: worldPos or vNormalW
+     * So, if the variable holding the world position in your vertex shader is not named worldPos, you must tell the system
+     * the name to use instead by using: ["worldPos", "myWorldPosVar"] assuming the variable is named myWorldPosVar in your code.
+     * If the normal must also be remapped: ["worldPos", "myWorldPosVar", "vNormalW", "myWorldNormal"]
+    */
+    remappedVariables?: string[];
+
+    /** Set standalone to true if the base material wrapped by ShadowDepthMaterial is not used for a regular object but for depth shadow generation only */
+    standalone?: boolean;
+}
+
+class MapMap<Ka, Kb, V> {
+    readonly mm = new Map<Ka, Map<Kb, V>>();
+
+    get(a: Ka, b: Kb): V | undefined {
+        const m = this.mm.get(a);
+        if (m !== undefined) {
+            return m.get(b);
+        }
+        return undefined;
+    }
+
+    set(a: Ka, b: Kb, v: V): void {
+        let m = this.mm.get(a);
+        if (m === undefined) {
+            this.mm.set(a, (m = new Map()));
+        }
+        m.set(b, v);
+    }
+}
+
+/**
+ * Class that can be used to wrap a base material to generate accurate shadows when using custom vertex/fragment code in the base material
+ */
+export class ShadowDepthWrapper {
+
+    private _scene: Scene;
+    private _options?: IIOptionShadowDepthMaterial;
+    private _baseMaterial: Material;
+    private _onEffectCreatedObserver: Nullable<Observer<{ effect: Effect, subMesh: Nullable<SubMesh>}>>;
+    private _subMeshToEffect: Map<Nullable<SubMesh>, Effect>;
+    private _subMeshToDepthEffect: MapMap<Nullable<SubMesh>, ShadowGenerator, { depthEffect: Nullable<Effect>, depthDefines: string, token: string }>; // key is (subMesh + shadowGenerator)
+    private _meshes: Map<AbstractMesh, Nullable<Observer<Node>>>;
+
+    /** @hidden */
+    public _matriceNames: any;
+
+    /**
+     * Instantiate a new shadow depth wrapper.
+     * It works by injecting some specific code in the vertex/fragment shaders of the base material and is used by a shadow generator to
+     * generate the shadow depth map. For more information, please refer to the documentation:
+     * https://doc.babylonjs.com/babylon101/shadows
+     * @param baseMaterial Material to wrap
+     * @param scene Define the scene the material belongs to
+     * @param options Options used to create the wrapper
+     */
+    constructor(baseMaterial: Material, scene: Scene, options?: IIOptionShadowDepthMaterial) {
+        this._baseMaterial = baseMaterial;
+        this._scene = scene;
+        this._options = options;
+
+        this._subMeshToEffect = new Map();
+        this._subMeshToDepthEffect = new MapMap();
+        this._meshes = new Map();
+
+        const prefix = baseMaterial.getClassName() === "NodeMaterial" ? "u_" : "";
+
+        this._matriceNames = {
+            "view": prefix + "view",
+            "projection": prefix + "projection",
+            "viewProjection": prefix + "viewProjection",
+        };
+
+        // Register for onEffectCreated to store the effect of the base material when it is (re)generated. This effect will be used
+        // to create the depth effect later on
+        this._onEffectCreatedObserver = this._baseMaterial.onEffectCreatedObservable.add((params: { effect: Effect, subMesh: Nullable<SubMesh> }) => {
+            const mesh = params.subMesh?.getMesh();
+
+            if (mesh && !this._meshes.has(mesh)) {
+                // Register for mesh onDispose to clean up our internal maps when a mesh is disposed
+                this._meshes.set(mesh,
+                    mesh.onDisposeObservable.add((mesh: Node) => {
+                        const iterator = this._subMeshToEffect.keys();
+                        for (let key = iterator.next(); key.done !== true; key = iterator.next()) {
+                            const subMesh = key.value;
+                            if (subMesh?.getMesh() === mesh as AbstractMesh) {
+                                this._subMeshToEffect.delete(subMesh);
+                                this._subMeshToDepthEffect.mm.delete(subMesh);
+                            }
+                        }
+                    })
+                );
+            }
+
+            this._subMeshToEffect.set(params.subMesh, params.effect);
+            this._subMeshToDepthEffect.mm.delete(params.subMesh); // trigger a depth effect recreation
+        });
+    }
+
+    /**
+     * Gets the effect to use to generate the depth map
+     * @param subMesh subMesh to get the effect for
+     * @param shadowGenerator shadow generator to get the effect for
+     * @returns the effect to use to generate the depth map for the subMesh + shadow generator specified
+     */
+    public getEffect(subMesh: Nullable<SubMesh>, shadowGenerator: ShadowGenerator): Nullable<Effect> {
+        return this._subMeshToDepthEffect.mm.get(subMesh)?.get(shadowGenerator)?.depthEffect ?? this._subMeshToDepthEffect.mm.get(null)?.get(shadowGenerator)?.depthEffect ?? null;
+    }
+
+    /**
+     * Specifies that the submesh is ready to be used for depth rendering
+     * @param subMesh submesh to check
+     * @param defines the list of defines to take into account when checking the effect
+     * @param shadowGenerator combined with subMesh, it defines the effect to check
+     * @param useInstances specifies that instances should be used
+     * @returns a boolean indicating that the submesh is ready or not
+     */
+    public isReadyForSubMesh(subMesh: SubMesh, defines: string[], shadowGenerator: ShadowGenerator, useInstances: boolean): boolean {
+        if (this._options?.standalone) {
+            // will ensure the effect is (re)created for the base material
+            this._baseMaterial.isReadyForSubMesh(subMesh.getMesh(), subMesh, useInstances);
+        }
+
+        return this._makeEffect(subMesh, defines, shadowGenerator)?.isReady() ?? false;
+    }
+
+    /**
+     * Disposes the resources
+     */
+    public dispose(): void {
+        this._baseMaterial.onEffectCreatedObservable.remove(this._onEffectCreatedObserver);
+        this._onEffectCreatedObserver = null;
+
+        const iterator = this._meshes.entries();
+        for (let entry = iterator.next(); entry.done !== true; entry = iterator.next()) {
+            const [mesh, observer] = entry.value;
+
+            mesh.onDisposeObservable.remove(observer);
+        }
+    }
+
+    private _makeEffect(subMesh: Nullable<SubMesh>, defines: string[], shadowGenerator: ShadowGenerator): Nullable<Effect> {
+        const origEffect = this._subMeshToEffect.get(subMesh) ?? this._subMeshToEffect.get(null);
+
+        if (!origEffect) {
+            return null;
+        }
+
+        let params = this._subMeshToDepthEffect.get(subMesh, shadowGenerator);
+        if (!params) {
+            params = {
+                depthEffect: null,
+                depthDefines: "",
+                token: GUID.RandomId()
+            };
+            this._subMeshToDepthEffect.set(subMesh, shadowGenerator, params);
+        }
+
+        let join = defines.join("\n");
+
+        if (params.depthEffect) {
+            if (join === params.depthDefines) {
+                // we already created the depth effect and it is still up to date for this submesh + shadow generator
+                return params.depthEffect;
+            }
+        }
+
+        params.depthDefines = join;
+
+        // the depth effect is either out of date or has not been created yet
+        let vertexCode = origEffect.vertexSourceCode,
+            fragmentCode = origEffect.fragmentSourceCode;
+
+        const vertexNormalBiasCode = this._options && this._options.remappedVariables ? `#include<shadowMapVertexNormalBias>(${this._options.remappedVariables.join(",")})` : Effect.IncludesShadersStore["shadowMapVertexNormalBias"],
+              vertexMetricCode = this._options && this._options.remappedVariables ? `#include<shadowMapVertexMetric>(${this._options.remappedVariables.join(",")})` : Effect.IncludesShadersStore["shadowMapVertexMetric"],
+              fragmentBlockCode = Effect.IncludesShadersStore["shadowMapFragment"];
+
+        vertexCode = vertexCode.replace(/void\s+?main/g, Effect.IncludesShadersStore["shadowMapVertexDeclaration"] + "\r\nvoid main");
+        vertexCode = vertexCode.replace(/#define SHADOWDEPTH_NORMALBIAS/g, vertexNormalBiasCode);
+
+        if (vertexCode.indexOf("#define SHADOWDEPTH_METRIC") !== -1) {
+            vertexCode = vertexCode.replace(/#define SHADOWDEPTH_METRIC/g, vertexMetricCode);
+        } else {
+            vertexCode = vertexCode.replace(/}\s*$/g, vertexMetricCode + "\r\n}");
+        }
+        vertexCode = vertexCode.replace(/#define SHADER_NAME.*?\n|out vec4 glFragColor;\n/g, "");
+
+        fragmentCode = fragmentCode.replace(/void\s+?main/g, Effect.IncludesShadersStore["shadowMapFragmentDeclaration"] + "\r\nvoid main");
+        if (fragmentCode.indexOf("#define SHADOWDEPTH_FRAGMENT") !== -1) {
+            fragmentCode = vertexCode.replace(/#define SHADOWDEPTH_FRAGMENT/g, fragmentBlockCode);
+        } else {
+            fragmentCode = fragmentCode.replace(/}\s*$/g, fragmentBlockCode + "\r\n}");
+        }
+        fragmentCode = fragmentCode.replace(/#define SHADER_NAME.*?\n|out vec4 glFragColor;\n/g, "");
+
+        const uniforms = origEffect.getUniformNames().slice();
+
+        uniforms.push("biasAndScaleSM", "depthValuesSM", "lightDataSM");
+
+        params.depthEffect = this._scene.getEngine().createEffect({
+            vertexSource: vertexCode,
+            fragmentSource: fragmentCode,
+            vertexToken: params.token,
+            fragmentToken: params.token,
+        }, <IEffectCreationOptions>{
+            attributes: origEffect.getAttributesNames(),
+            uniformsNames: uniforms,
+            uniformBuffersNames: origEffect.getUniformBuffersNames(),
+            samplers: origEffect.getSamplers(),
+            defines: join + "\n" + origEffect.defines,
+            indexParameters: origEffect.getIndexParameters(),
+        }, this._scene.getEngine());
+
+        return params.depthEffect;
+    }
+}

+ 9 - 6
src/Materials/standardMaterial.ts

@@ -31,7 +31,9 @@ import "../Shaders/default.fragment";
 import "../Shaders/default.vertex";
 import "../Shaders/default.vertex";
 import { Constants } from "../Engines/constants";
 import { Constants } from "../Engines/constants";
 import { EffectFallbacks } from './effectFallbacks';
 import { EffectFallbacks } from './effectFallbacks';
-import { IEffectCreationOptions } from './effect';
+import { Effect, IEffectCreationOptions } from './effect';
+
+const onCreatedEffectParameters = { effect: null as unknown as Effect, subMesh: null as unknown as Nullable<SubMesh> };
 
 
 /** @hidden */
 /** @hidden */
 export class StandardMaterialDefines extends MaterialDefines implements IImageProcessingConfigurationDefines {
 export class StandardMaterialDefines extends MaterialDefines implements IImageProcessingConfigurationDefines {
@@ -662,11 +664,6 @@ export class StandardMaterial extends PushMaterial {
         this._imageProcessingConfiguration.colorCurves = value;
         this._imageProcessingConfiguration.colorCurves = value;
     }
     }
 
 
-    /**
-     * Custom callback helping to override the default shader used in the material.
-     */
-    public customShaderNameResolve: (shaderName: string, uniforms: string[], uniformBuffers: string[], samplers: string[], defines: StandardMaterialDefines, attributes?: string[]) => string;
-
     protected _renderTargets = new SmartArray<RenderTargetTexture>(16);
     protected _renderTargets = new SmartArray<RenderTargetTexture>(16);
     protected _worldViewProjectionMatrix = Matrix.Zero();
     protected _worldViewProjectionMatrix = Matrix.Zero();
     protected _globalAmbientColor = new Color3(0, 0, 0);
     protected _globalAmbientColor = new Color3(0, 0, 0);
@@ -1180,6 +1177,12 @@ export class StandardMaterial extends PushMaterial {
             }, engine);
             }, engine);
 
 
             if (effect) {
             if (effect) {
+                if (this._onEffectCreatedObservable) {
+                    onCreatedEffectParameters.effect = effect;
+                    onCreatedEffectParameters.subMesh = subMesh;
+                    this._onEffectCreatedObservable.notifyObservers(onCreatedEffectParameters);
+                }
+
                 // Use previous effect while new one is compiling
                 // Use previous effect while new one is compiling
                 if (this.allowShaderHotSwapping && previousEffect && !effect.isReady()) {
                 if (this.allowShaderHotSwapping && previousEffect && !effect.isReady()) {
                     effect = previousEffect;
                     effect = previousEffect;

+ 3 - 1
src/Meshes/subMesh.ts

@@ -27,6 +27,8 @@ export class BaseSubMesh {
     public _materialDefines: Nullable<MaterialDefines> = null;
     public _materialDefines: Nullable<MaterialDefines> = null;
     /** @hidden */
     /** @hidden */
     public _materialEffect: Nullable<Effect> = null;
     public _materialEffect: Nullable<Effect> = null;
+    /** @hidden */
+    public _effectOverride: Nullable<Effect> = null;
 
 
     /**
     /**
      * Gets material defines used by the effect associated to the sub mesh
      * Gets material defines used by the effect associated to the sub mesh
@@ -46,7 +48,7 @@ export class BaseSubMesh {
      * Gets associated effect
      * Gets associated effect
      */
      */
     public get effect(): Nullable<Effect> {
     public get effect(): Nullable<Effect> {
-        return this._materialEffect;
+        return this._effectOverride ?? this._materialEffect;
     }
     }
 
 
     /**
     /**

+ 2 - 0
src/Meshes/transformNode.ts

@@ -520,6 +520,8 @@ export class TransformNode extends Node {
             this.position.y = absolutePositionY;
             this.position.y = absolutePositionY;
             this.position.z = absolutePositionZ;
             this.position.z = absolutePositionZ;
         }
         }
+
+        this._absolutePosition.copyFrom(absolutePosition);
         return this;
         return this;
     }
     }
 
 

+ 22 - 0
src/Shaders/ShadersInclude/shadowMapFragment.fx

@@ -0,0 +1,22 @@
+    float depthSM = vDepthMetricSM;
+
+#if SM_DEPTHCLAMP == 1
+    #if SM_USEDISTANCE == 1
+        depthSM = clamp(((length(vPositionWSM - lightDataSM) + depthValuesSM.x) / (depthValuesSM.y)) + biasAndScaleSM.x, 0.0, 1.0);
+    #else
+        depthSM = clamp(((zSM + depthValuesSM.x) / (depthValuesSM.y)) + biasAndScaleSM.x, 0.0, 1.0);
+    #endif
+    gl_FragDepth = depthSM;
+#elif SM_USEDISTANCE == 1
+    depthSM = (length(vPositionWSM - lightDataSM) + depthValuesSM.x) / (depthValuesSM.y) + biasAndScaleSM.x;
+#endif
+
+#if SM_ESM == 1
+    depthSM = clamp(exp(-min(87., biasAndScaleSM.z * depthSM)), 0., 1.);
+#endif
+
+#if SM_FLOAT == 1
+    gl_FragColor = vec4(depthSM, 1.0, 1.0, 1.0);
+#else
+    gl_FragColor = pack(depthSM);
+#endif

+ 17 - 0
src/Shaders/ShadersInclude/shadowMapFragmentDeclaration.fx

@@ -0,0 +1,17 @@
+#if SM_FLOAT == 0
+	#include<packingFunctions>
+#endif
+
+varying float vDepthMetricSM;
+
+#if SM_USEDISTANCE == 1
+    uniform vec3 lightDataSM;
+    varying vec3 vPositionWSM;
+#endif
+
+uniform vec3 biasAndScaleSM;
+uniform vec2 depthValuesSM;
+
+#if SM_DEPTHCLAMP == 1
+    varying float zSM;
+#endif

+ 16 - 0
src/Shaders/ShadersInclude/shadowMapVertexDeclaration.fx

@@ -0,0 +1,16 @@
+#if SM_NORMALBIAS == 1
+    uniform vec3 lightDataSM;
+#endif
+
+uniform vec3 biasAndScaleSM;
+uniform vec2 depthValuesSM;
+
+varying float vDepthMetricSM;
+
+#if SM_USEDISTANCE == 1
+    varying vec3 vPositionWSM;
+#endif
+
+#if SM_DEPTHCLAMP == 1
+    varying float zSM;
+#endif

+ 16 - 0
src/Shaders/ShadersInclude/shadowMapVertexMetric.fx

@@ -0,0 +1,16 @@
+#if SM_USEDISTANCE == 1
+    vPositionWSM = worldPos.xyz;
+#endif
+
+#if SM_DEPTHTEXTURE == 1
+    // Depth texture Linear bias.
+    gl_Position.z += biasAndScaleSM.x * gl_Position.w;
+#endif
+
+#if SM_DEPTHCLAMP == 1
+    zSM = gl_Position.z;
+    gl_Position.z = 0.0;
+#elif SM_USEDISTANCE == 0
+    // Color Texture Linear bias.
+    vDepthMetricSM = ((gl_Position.z + depthValuesSM.x) / (depthValuesSM.y)) + biasAndScaleSM.x;
+#endif

+ 15 - 0
src/Shaders/ShadersInclude/shadowMapVertexNormalBias.fx

@@ -0,0 +1,15 @@
+// Normal inset Bias.
+#if SM_NORMALBIAS == 1
+    #if SM_DIRECTIONINLIGHTDATA == 1
+        vec3 worldLightDirSM = normalize(-lightDataSM.xyz);
+    #else
+        vec3 directionToLightSM = lightDataSM.xyz - worldPos.xyz;
+        vec3 worldLightDirSM = normalize(directionToLightSM);
+    #endif
+
+    float ndlSM = dot(vNormalW, worldLightDirSM);
+    float sinNLSM = sqrt(1.0 - ndlSM * ndlSM);
+    float normalBiasSM = biasAndScaleSM.y * sinNLSM;
+
+    worldPos.xyz -= vNormalW * normalBiasSM;
+#endif

+ 12 - 10
src/Shaders/default.vertex.fx

@@ -124,6 +124,18 @@ void main(void) {
 
 
 	vec4 worldPos = finalWorld * vec4(positionUpdated, 1.0);
 	vec4 worldPos = finalWorld * vec4(positionUpdated, 1.0);
 
 
+#ifdef NORMAL
+	mat3 normalWorld = mat3(finalWorld);
+
+	#ifdef NONUNIFORMSCALING
+		normalWorld = transposeMat3(inverseMat3(normalWorld));
+	#endif
+
+	vNormalW = normalize(normalWorld * normalUpdated);
+#endif
+
+#define CUSTOM_VERTEX_UPDATE_WORLDPOS
+
 #ifdef MULTIVIEW
 #ifdef MULTIVIEW
 	if (gl_ViewID_OVR == 0u) {
 	if (gl_ViewID_OVR == 0u) {
 		gl_Position = viewProjection * worldPos;
 		gl_Position = viewProjection * worldPos;
@@ -136,16 +148,6 @@ void main(void) {
 
 
 	vPositionW = vec3(worldPos);
 	vPositionW = vec3(worldPos);
 
 
-#ifdef NORMAL
-	mat3 normalWorld = mat3(finalWorld);
-
-	#ifdef NONUNIFORMSCALING
-		normalWorld = transposeMat3(inverseMat3(normalWorld));
-	#endif
-
-	vNormalW = normalize(normalWorld * normalUpdated);
-#endif
-
 #if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)
 #if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)
 	vDirectionW = normalize(vec3(finalWorld * vec4(positionUpdated, 0.0)));
 	vDirectionW = normalize(vec3(finalWorld * vec4(positionUpdated, 0.0)));
 #endif
 #endif

+ 12 - 10
src/Shaders/pbr.vertex.fx

@@ -163,16 +163,6 @@ void main(void) {
 #include<instancesVertex>
 #include<instancesVertex>
 #include<bonesVertex>
 #include<bonesVertex>
 
 
-#ifdef MULTIVIEW
-	if (gl_ViewID_OVR == 0u) {
-		gl_Position = viewProjection * finalWorld * vec4(positionUpdated, 1.0);
-	} else {
-		gl_Position = viewProjectionR * finalWorld * vec4(positionUpdated, 1.0);
-	}
-#else
-	gl_Position = viewProjection * finalWorld * vec4(positionUpdated, 1.0);
-#endif
-
 #if DEBUGMODE > 0
 #if DEBUGMODE > 0
     vClipSpacePosition = gl_Position;
     vClipSpacePosition = gl_Position;
 #endif
 #endif
@@ -198,6 +188,18 @@ void main(void) {
     #endif
     #endif
 #endif
 #endif
 
 
+#define CUSTOM_VERTEX_UPDATE_WORLDPOS
+
+#ifdef MULTIVIEW
+	if (gl_ViewID_OVR == 0u) {
+		gl_Position = viewProjection * worldPos;
+	} else {
+		gl_Position = viewProjectionR * worldPos;
+	}
+#else
+	gl_Position = viewProjection * worldPos;
+#endif
+
 #if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)
 #if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)
     vDirectionW = normalize(vec3(finalWorld * vec4(positionUpdated, 0.0)));
     vDirectionW = normalize(vec3(finalWorld * vec4(positionUpdated, 0.0)));
 #endif
 #endif

+ 2 - 39
src/Shaders/shadowMap.fragment.fx

@@ -1,26 +1,10 @@
-#ifndef FLOAT
-	#include<packingFunctions>
-#endif
-
-varying float vDepthMetric;
-
-#ifdef USEDISTANCE
-uniform vec3 lightData;
-varying vec3 vPositionW;
-#endif
+#include<shadowMapFragmentDeclaration>
 
 
 #ifdef ALPHATEST
 #ifdef ALPHATEST
 varying vec2 vUV;
 varying vec2 vUV;
 uniform sampler2D diffuseSampler;
 uniform sampler2D diffuseSampler;
 #endif
 #endif
 
 
-uniform vec3 biasAndScale;
-uniform vec2 depthValues;
-
-#ifdef DEPTHCLAMP
-varying float z;
-#endif
-
 #include<clipPlaneFragmentDeclaration>
 #include<clipPlaneFragmentDeclaration>
 
 
 void main(void)
 void main(void)
@@ -32,26 +16,5 @@ void main(void)
         discard;
         discard;
 #endif
 #endif
 
 
-    float depth = vDepthMetric;
-
-#ifdef DEPTHCLAMP
-    #ifdef USEDISTANCE
-        depth = clamp(((length(vPositionW - lightData) + depthValues.x) / (depthValues.y)) + biasAndScale.x, 0.0, 1.0);
-    #else
-        depth = clamp(((z + depthValues.x) / (depthValues.y)) + biasAndScale.x, 0.0, 1.0);
-    #endif
-    gl_FragDepth = depth;
-#elif defined(USEDISTANCE)
-    depth = (length(vPositionW - lightData) + depthValues.x) / (depthValues.y) + biasAndScale.x;
-#endif
-
-#ifdef ESM
-    depth = clamp(exp(-min(87., biasAndScale.z * depth)), 0., 1.);
-#endif
-
-#ifdef FLOAT
-    gl_FragColor = vec4(depth, 1.0, 1.0, 1.0);
-#else
-    gl_FragColor = pack(depth);
-#endif
+#include<shadowMapFragment>
 }
 }

+ 9 - 45
src/Shaders/shadowMap.vertex.fx

@@ -3,7 +3,6 @@ attribute vec3 position;
 
 
 #ifdef NORMAL
 #ifdef NORMAL
     attribute vec3 normal;
     attribute vec3 normal;
-    uniform vec3 lightData;
 #endif
 #endif
 
 
 #include<bonesDeclaration>
 #include<bonesDeclaration>
@@ -16,14 +15,6 @@ attribute vec3 position;
 #include<helperFunctions>
 #include<helperFunctions>
 
 
 uniform mat4 viewProjection;
 uniform mat4 viewProjection;
-uniform vec3 biasAndScale;
-uniform vec2 depthValues;
-
-varying float vDepthMetric;
-
-#ifdef USEDISTANCE
-varying vec3 vPositionW;
-#endif
 
 
 #ifdef ALPHATEST
 #ifdef ALPHATEST
 varying vec2 vUV;
 varying vec2 vUV;
@@ -36,9 +27,7 @@ attribute vec2 uv2;
 #endif
 #endif
 #endif
 #endif
 
 
-#ifdef DEPTHCLAMP
-varying float z;
-#endif
+#include<shadowMapVertexDeclaration>
 
 
 #include<clipPlaneVertexDeclaration>
 #include<clipPlaneVertexDeclaration>
 
 
@@ -48,6 +37,9 @@ vec3 positionUpdated = position;
 #ifdef UV1
 #ifdef UV1
     vec2 uvUpdated = uv;
     vec2 uvUpdated = uv;
 #endif  
 #endif  
+#ifdef NORMAL	
+	vec3 normalUpdated = normal;
+#endif
 
 
 #include<morphTargetsVertex>[0..maxSimultaneousMorphTargets]
 #include<morphTargetsVertex>[0..maxSimultaneousMorphTargets]
 
 
@@ -56,50 +48,22 @@ vec3 positionUpdated = position;
 
 
 vec4 worldPos = finalWorld * vec4(positionUpdated, 1.0);
 vec4 worldPos = finalWorld * vec4(positionUpdated, 1.0);
 
 
-// Normal inset Bias.
 #ifdef NORMAL
 #ifdef NORMAL
-    mat3 normalWorld = mat3(finalWorld);
+    mat3 normWorldSM = mat3(finalWorld);
 
 
     #ifdef NONUNIFORMSCALING
     #ifdef NONUNIFORMSCALING
-        normalWorld = transposeMat3(inverseMat3(normalWorld));
-    #endif
-
-    vec3 worldNor = normalize(normalWorld * normal);
-
-    #ifdef DIRECTIONINLIGHTDATA
-        vec3 worldLightDir = normalize(-lightData.xyz);
-    #else
-        vec3 directionToLight = lightData.xyz - worldPos.xyz;
-        vec3 worldLightDir = normalize(directionToLight);
+        normWorldSM = transposeMat3(inverseMat3(normWorldSM));
     #endif
     #endif
 
 
-    float ndl = dot(worldNor, worldLightDir);
-    float sinNL = sqrt(1.0 - ndl * ndl);
-    float normalBias = biasAndScale.y * sinNL;
-
-    worldPos.xyz -= worldNor * normalBias;
+    vec3 vNormalW = normalize(normWorldSM * normalUpdated);
 #endif
 #endif
 
 
-#ifdef USEDISTANCE
-vPositionW = worldPos.xyz;
-#endif
+#include<shadowMapVertexNormalBias>
 
 
 // Projection.
 // Projection.
 gl_Position = viewProjection * worldPos;
 gl_Position = viewProjection * worldPos;
 
 
-
-#ifdef DEPTHTEXTURE
-    // Depth texture Linear bias.
-    gl_Position.z += biasAndScale.x * gl_Position.w;
-#endif
-
-#ifdef DEPTHCLAMP
-    z = gl_Position.z;
-    gl_Position.z = 0.0;
-#elif !defined(USEDISTANCE)
-    // Color Texture Linear bias.
-    vDepthMetric = ((gl_Position.z + depthValues.x) / (depthValues.y)) + biasAndScale.x;
-#endif
+#include<shadowMapVertexMetric>
 
 
 #ifdef ALPHATEST
 #ifdef ALPHATEST
     #ifdef UV1
     #ifdef UV1