Explorar o código

Merge pull request #6379 from BabylonJS/shaderProcessor

Shader processor
David Catuhe %!s(int64=6) %!d(string=hai) anos
pai
achega
b8f3eba649
Modificáronse 35 ficheiros con 2871 adicións e 557 borrados
  1. 163 8
      Playground/babylon.d.txt
  2. 167 8
      dist/preview release/babylon.d.ts
  3. 1 1
      dist/preview release/babylon.js
  4. 931 270
      dist/preview release/babylon.max.js
  5. 1 1
      dist/preview release/babylon.max.js.map
  6. 367 16
      dist/preview release/babylon.module.d.ts
  7. 167 8
      dist/preview release/documentation.d.ts
  8. 7 7
      dist/preview release/inspector/babylon.inspector.bundle.max.js
  9. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.max.js.map
  10. 1 1
      dist/preview release/packagesSizeBaseLine.json
  11. 367 16
      dist/preview release/viewer/babylon.module.d.ts
  12. 66 22
      dist/preview release/viewer/babylon.viewer.js
  13. 1 1
      dist/preview release/viewer/babylon.viewer.max.js
  14. 4 3
      dist/preview release/what's new.md
  15. 4 0
      src/Engines/Processors/Expressions/Operators/index.ts
  16. 11 0
      src/Engines/Processors/Expressions/Operators/shaderDefineAndOperator.ts
  17. 40 0
      src/Engines/Processors/Expressions/Operators/shaderDefineArithmeticOperator.ts
  18. 19 0
      src/Engines/Processors/Expressions/Operators/shaderDefineIsDefinedOperator.ts
  19. 11 0
      src/Engines/Processors/Expressions/Operators/shaderDefineOrOperator.ts
  20. 2 0
      src/Engines/Processors/Expressions/index.ts
  21. 6 0
      src/Engines/Processors/Expressions/shaderDefineExpression.ts
  22. 7 0
      src/Engines/Processors/iShaderProcessor.ts
  23. 8 0
      src/Engines/Processors/index.ts
  24. 17 0
      src/Engines/Processors/shaderCodeConditionNode.ts
  25. 13 0
      src/Engines/Processors/shaderCodeCursor.ts
  26. 44 0
      src/Engines/Processors/shaderCodeNode.ts
  27. 11 0
      src/Engines/Processors/shaderCodeTestNode.ts
  28. 14 0
      src/Engines/Processors/shaderProcessingOptions.ts
  29. 337 0
      src/Engines/Processors/shaderProcessor.ts
  30. 39 0
      src/Engines/WebGL/webGL2ShaderProcessors.ts
  31. 11 3
      src/Engines/engine.ts
  32. 2 1
      src/Engines/index.ts
  33. 29 186
      src/Materials/effect.ts
  34. 1 1
      src/Shaders/ShadersInclude/lightFragment.fx
  35. 1 3
      src/Shaders/vrMultiviewToSingleview.fragment.fx

+ 163 - 8
Playground/babylon.d.txt

@@ -5274,6 +5274,139 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
+    /** @hidden */
+    export interface IShaderProcessor {
+        attributeProcessor?: (attribute: string) => string;
+        varyingProcessor?: (varying: string, isFragment: boolean) => string;
+        preProcessor?: (code: string, defines: string[], isFragment: boolean) => string;
+        postProcessor?: (code: string, defines: string[], isFragment: boolean) => string;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export interface ProcessingOptions {
+        defines: string;
+        indexParameters: any;
+        isFragment: boolean;
+        shouldUseHighPrecisionShader: boolean;
+        supportsUniformBuffers: boolean;
+        shadersRepository: string;
+        includesShadersStore: {
+            [key: string]: string;
+        };
+        processor?: IShaderProcessor;
+        version: string;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderCodeNode {
+        line: string;
+        children: ShaderCodeNode[];
+        additionalDefineKey?: string;
+        additionalDefineValue?: string;
+        isValid(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+        process(preprocessors: {
+            [key: string]: string;
+        }, options: ProcessingOptions): string;
+        private _lineStartsWith;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderCodeCursor {
+        lines: string[];
+        lineIndex: number;
+        readonly currentLine: string;
+        readonly canRead: boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderCodeConditionNode extends ShaderCodeNode {
+        process(preprocessors: {
+            [key: string]: string;
+        }, options: ProcessingOptions): string;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineExpression {
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderCodeTestNode extends ShaderCodeNode {
+        testExpression: ShaderDefineExpression;
+        isValid(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineIsDefinedOperator extends ShaderDefineExpression {
+        define: string;
+        not: boolean;
+        constructor(define: string, not?: boolean);
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineOrOperator extends ShaderDefineExpression {
+        leftOperand: ShaderDefineExpression;
+        rightOperand: ShaderDefineExpression;
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineAndOperator extends ShaderDefineExpression {
+        leftOperand: ShaderDefineExpression;
+        rightOperand: ShaderDefineExpression;
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineArithmeticOperator extends ShaderDefineExpression {
+        define: string;
+        operand: string;
+        testValue: string;
+        constructor(define: string, operand: string, testValue: string);
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderProcessor {
+        static Process(sourceCode: string, options: ProcessingOptions, callback: (migratedCode: string) => void): void;
+        private static _ProcessPrecision;
+        private static _ExtractOperation;
+        private static _BuildSubExpression;
+        private static _BuildExpression;
+        private static _MoveCursorWithinIf;
+        private static _MoveCursor;
+        private static _EvaluatePreProcessors;
+        private static _ProcessShaderConversion;
+        private static _ProcessIncludes;
+    }
+}
+declare module BABYLON {
     /**
      * Performance monitor tracks rolling average frame-time and frame-time variance over a user defined sliding-window
      */
@@ -6395,6 +6528,8 @@ declare module BABYLON {
         /** @hidden */
private _lodTextureMid: Nullable<BaseTexture>;
         /** @hidden */
private _lodTextureLow: Nullable<BaseTexture>;
         /** @hidden */
private _isRGBD: boolean;
+        /** @hidden */
private _linearSpecularLOD: boolean;
+        /** @hidden */
private _irradianceTexture: Nullable<BaseTexture>;
         /** @hidden */
private _webGLTexture: Nullable<WebGLTexture>;
         /** @hidden */
private _references: number;
         private _engine;
@@ -8042,7 +8177,7 @@ declare module BABYLON {
          * Flag the bone as dirty (Forcing it to update everything)
          */
         markAsDirty(): void;
-        private _markAsDirtyAndCompose;
+        /** @hidden */
private _markAsDirtyAndCompose(): void;
         private _markAsDirtyAndDecompose;
         /**
          * Translate the bone in local or world space
@@ -25634,6 +25769,18 @@ declare module BABYLON {
          */
         lodGenerationScale: number;
         /**
+         * With prefiltered texture, defined if the specular generation is based on a linear ramp.
+         * By default we are using a log2 of the linear roughness helping to keep a better resolution for
+         * average roughness values.
+         */
+        linearSpecularLOD: boolean;
+        /**
+         * In case a better definition than spherical harmonics is required for the diffuse part of the environment.
+         * You can set the irradiance texture to rely on a texture instead of the spherical approach.
+         * This texture need to have the same characteristics than its parent (Cube vs 2d, coordinates mode, Gamma/Linear, RGBD).
+         */
+        irradianceTexture: Nullable<BaseTexture>;
+        /**
          * Define if the texture is a render target.
          */
         isRenderTarget: boolean;
@@ -26427,6 +26574,14 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
+    /** @hidden */
+    export class WebGL2ShaderProcessor implements IShaderProcessor {
+        attributeProcessor(attribute: string): string;
+        varyingProcessor(varying: string, isFragment: boolean): string;
+        postProcessor(code: string, defines: string[], isFragment: boolean): string;
+    }
+}
+declare module BABYLON {
     /**
      * Settings for finer control over video usage
      */
@@ -26761,9 +26916,7 @@ declare module BABYLON {
          * @param predicate defines a predicate used to filter which materials should be affected
          */
         static MarkAllMaterialsAsDirty(flag: number, predicate?: (mat: Material) => boolean): void;
-        /**
-         * Hidden
-         */
private static _TextureLoaders: IInternalTextureLoader[];
+        /** @hidden */
private static _TextureLoaders: IInternalTextureLoader[];
         /** Defines that alpha blending is disabled */
         static readonly ALPHA_DISABLE: number;
         /** Defines that alpha blending to SRC ALPHA * SRC + DEST */
@@ -26982,6 +27135,7 @@ declare module BABYLON {
         /**
          * Method called to create the default rescale post process on each engine.
          */
private static _RescalePostProcessFactory: Nullable<(engine: Engine) => PostProcess>;
+        /** @hidden */
private _shaderProcessor: IShaderProcessor;
         /**
          * Gets or sets a boolean that indicates if textures must be forced to power of 2 size even if not required
          */
@@ -28507,7 +28661,7 @@ declare module BABYLON {
          */
         readonly isMoreFallbacks: boolean;
         /**
-         * Removes the defines that shoould be removed when falling back.
+         * Removes the defines that should be removed when falling back.
          * @param currentDefines defines the current define statements for the shader.
          * @param effect defines the current effect we try to compile
          * @returns The resulting defines with defines of the current rank removed.
@@ -28725,9 +28879,6 @@ declare module BABYLON {
         /** @hidden */
private _loadVertexShader(vertex: any, callback: (data: any) => void): void;
         /** @hidden */
private _loadFragmentShader(fragment: any, callback: (data: any) => void): void;
         /** @hidden */
private _dumpShadersSource(vertexCode: string, fragmentCode: string, defines: string): void;
-        private _processShaderConversion;
-        private _processIncludes;
-        private _processPrecision;
         /**
          * Recompiles the webGL program
          * @param vertexSourceCode The source code for the vertex shader.
@@ -44006,6 +44157,7 @@ declare module BABYLON {
         SS_LODINREFRACTIONALPHA: boolean;
         SS_GAMMAREFRACTION: boolean;
         SS_RGBDREFRACTION: boolean;
+        SS_LINEARSPECULARREFRACTION: boolean;
         SS_LINKREFRACTIONTOTRANSPARENCY: boolean;
         SS_MASK_FROM_THICKNESS_TEXTURE: boolean;
         /** @hidden */
private _areTexturesDirty: boolean;
@@ -44409,12 +44561,14 @@ declare module BABYLON {
         REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED: boolean;
         INVERTCUBICMAP: boolean;
         USESPHERICALFROMREFLECTIONMAP: boolean;
+        USEIRRADIANCEMAP: boolean;
         SPHERICAL_HARMONICS: boolean;
         USESPHERICALINVERTEX: boolean;
         REFLECTIONMAP_OPPOSITEZ: boolean;
         LODINREFLECTIONALPHA: boolean;
         GAMMAREFLECTION: boolean;
         RGBDREFLECTION: boolean;
+        LINEARSPECULARREFLECTION: boolean;
         RADIANCEOCCLUSION: boolean;
         HORIZONOCCLUSION: boolean;
         INSTANCES: boolean;
@@ -44483,6 +44637,7 @@ declare module BABYLON {
         SS_LODINREFRACTIONALPHA: boolean;
         SS_GAMMAREFRACTION: boolean;
         SS_RGBDREFRACTION: boolean;
+        SS_LINEARSPECULARREFRACTION: boolean;
         SS_LINKREFRACTIONTOTRANSPARENCY: boolean;
         SS_MASK_FROM_THICKNESS_TEXTURE: boolean;
         UNLIT: boolean;

+ 167 - 8
dist/preview release/babylon.d.ts

@@ -5291,6 +5291,139 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
+    /** @hidden */
+    export interface IShaderProcessor {
+        attributeProcessor?: (attribute: string) => string;
+        varyingProcessor?: (varying: string, isFragment: boolean) => string;
+        preProcessor?: (code: string, defines: string[], isFragment: boolean) => string;
+        postProcessor?: (code: string, defines: string[], isFragment: boolean) => string;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export interface ProcessingOptions {
+        defines: string;
+        indexParameters: any;
+        isFragment: boolean;
+        shouldUseHighPrecisionShader: boolean;
+        supportsUniformBuffers: boolean;
+        shadersRepository: string;
+        includesShadersStore: {
+            [key: string]: string;
+        };
+        processor?: IShaderProcessor;
+        version: string;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderCodeNode {
+        line: string;
+        children: ShaderCodeNode[];
+        additionalDefineKey?: string;
+        additionalDefineValue?: string;
+        isValid(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+        process(preprocessors: {
+            [key: string]: string;
+        }, options: ProcessingOptions): string;
+        private _lineStartsWith;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderCodeCursor {
+        lines: string[];
+        lineIndex: number;
+        readonly currentLine: string;
+        readonly canRead: boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderCodeConditionNode extends ShaderCodeNode {
+        process(preprocessors: {
+            [key: string]: string;
+        }, options: ProcessingOptions): string;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineExpression {
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderCodeTestNode extends ShaderCodeNode {
+        testExpression: ShaderDefineExpression;
+        isValid(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineIsDefinedOperator extends ShaderDefineExpression {
+        define: string;
+        not: boolean;
+        constructor(define: string, not?: boolean);
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineOrOperator extends ShaderDefineExpression {
+        leftOperand: ShaderDefineExpression;
+        rightOperand: ShaderDefineExpression;
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineAndOperator extends ShaderDefineExpression {
+        leftOperand: ShaderDefineExpression;
+        rightOperand: ShaderDefineExpression;
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineArithmeticOperator extends ShaderDefineExpression {
+        define: string;
+        operand: string;
+        testValue: string;
+        constructor(define: string, operand: string, testValue: string);
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderProcessor {
+        static Process(sourceCode: string, options: ProcessingOptions, callback: (migratedCode: string) => void): void;
+        private static _ProcessPrecision;
+        private static _ExtractOperation;
+        private static _BuildSubExpression;
+        private static _BuildExpression;
+        private static _MoveCursorWithinIf;
+        private static _MoveCursor;
+        private static _EvaluatePreProcessors;
+        private static _ProcessShaderConversion;
+        private static _ProcessIncludes;
+    }
+}
+declare module BABYLON {
     /**
      * Performance monitor tracks rolling average frame-time and frame-time variance over a user defined sliding-window
      */
@@ -6459,6 +6592,10 @@ declare module BABYLON {
         /** @hidden */
         _isRGBD: boolean;
         /** @hidden */
+        _linearSpecularLOD: boolean;
+        /** @hidden */
+        _irradianceTexture: Nullable<BaseTexture>;
+        /** @hidden */
         _webGLTexture: Nullable<WebGLTexture>;
         /** @hidden */
         _references: number;
@@ -8137,7 +8274,8 @@ declare module BABYLON {
          * Flag the bone as dirty (Forcing it to update everything)
          */
         markAsDirty(): void;
-        private _markAsDirtyAndCompose;
+        /** @hidden */
+        _markAsDirtyAndCompose(): void;
         private _markAsDirtyAndDecompose;
         /**
          * Translate the bone in local or world space
@@ -26126,6 +26264,18 @@ declare module BABYLON {
          */
         lodGenerationScale: number;
         /**
+         * With prefiltered texture, defined if the specular generation is based on a linear ramp.
+         * By default we are using a log2 of the linear roughness helping to keep a better resolution for
+         * average roughness values.
+         */
+        linearSpecularLOD: boolean;
+        /**
+         * In case a better definition than spherical harmonics is required for the diffuse part of the environment.
+         * You can set the irradiance texture to rely on a texture instead of the spherical approach.
+         * This texture need to have the same characteristics than its parent (Cube vs 2d, coordinates mode, Gamma/Linear, RGBD).
+         */
+        irradianceTexture: Nullable<BaseTexture>;
+        /**
          * Define if the texture is a render target.
          */
         isRenderTarget: boolean;
@@ -26927,6 +27077,14 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
+    /** @hidden */
+    export class WebGL2ShaderProcessor implements IShaderProcessor {
+        attributeProcessor(attribute: string): string;
+        varyingProcessor(varying: string, isFragment: boolean): string;
+        postProcessor(code: string, defines: string[], isFragment: boolean): string;
+    }
+}
+declare module BABYLON {
     /**
      * Settings for finer control over video usage
      */
@@ -27262,9 +27420,7 @@ declare module BABYLON {
          * @param predicate defines a predicate used to filter which materials should be affected
          */
         static MarkAllMaterialsAsDirty(flag: number, predicate?: (mat: Material) => boolean): void;
-        /**
-         * Hidden
-         */
+        /** @hidden */
         static _TextureLoaders: IInternalTextureLoader[];
         /** Defines that alpha blending is disabled */
         static readonly ALPHA_DISABLE: number;
@@ -27485,6 +27641,8 @@ declare module BABYLON {
          * Method called to create the default rescale post process on each engine.
          */
         static _RescalePostProcessFactory: Nullable<(engine: Engine) => PostProcess>;
+        /** @hidden */
+        _shaderProcessor: IShaderProcessor;
         /**
          * Gets or sets a boolean that indicates if textures must be forced to power of 2 size even if not required
          */
@@ -29063,7 +29221,7 @@ declare module BABYLON {
          */
         readonly isMoreFallbacks: boolean;
         /**
-         * Removes the defines that shoould be removed when falling back.
+         * Removes the defines that should be removed when falling back.
          * @param currentDefines defines the current define statements for the shader.
          * @param effect defines the current effect we try to compile
          * @returns The resulting defines with defines of the current rank removed.
@@ -29288,9 +29446,6 @@ declare module BABYLON {
         _loadFragmentShader(fragment: any, callback: (data: any) => void): void;
         /** @hidden */
         _dumpShadersSource(vertexCode: string, fragmentCode: string, defines: string): void;
-        private _processShaderConversion;
-        private _processIncludes;
-        private _processPrecision;
         /**
          * Recompiles the webGL program
          * @param vertexSourceCode The source code for the vertex shader.
@@ -44759,6 +44914,7 @@ declare module BABYLON {
         SS_LODINREFRACTIONALPHA: boolean;
         SS_GAMMAREFRACTION: boolean;
         SS_RGBDREFRACTION: boolean;
+        SS_LINEARSPECULARREFRACTION: boolean;
         SS_LINKREFRACTIONTOTRANSPARENCY: boolean;
         SS_MASK_FROM_THICKNESS_TEXTURE: boolean;
         /** @hidden */
@@ -45164,12 +45320,14 @@ declare module BABYLON {
         REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED: boolean;
         INVERTCUBICMAP: boolean;
         USESPHERICALFROMREFLECTIONMAP: boolean;
+        USEIRRADIANCEMAP: boolean;
         SPHERICAL_HARMONICS: boolean;
         USESPHERICALINVERTEX: boolean;
         REFLECTIONMAP_OPPOSITEZ: boolean;
         LODINREFLECTIONALPHA: boolean;
         GAMMAREFLECTION: boolean;
         RGBDREFLECTION: boolean;
+        LINEARSPECULARREFLECTION: boolean;
         RADIANCEOCCLUSION: boolean;
         HORIZONOCCLUSION: boolean;
         INSTANCES: boolean;
@@ -45238,6 +45396,7 @@ declare module BABYLON {
         SS_LODINREFRACTIONALPHA: boolean;
         SS_GAMMAREFRACTION: boolean;
         SS_RGBDREFRACTION: boolean;
+        SS_LINEARSPECULARREFRACTION: boolean;
         SS_LINKREFRACTIONTOTRANSPARENCY: boolean;
         SS_MASK_FROM_THICKNESS_TEXTURE: boolean;
         UNLIT: boolean;

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1 - 1
dist/preview release/babylon.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 931 - 270
dist/preview release/babylon.max.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1 - 1
dist/preview release/babylon.max.js.map


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

@@ -5293,6 +5293,150 @@ declare module "babylonjs/Meshes/dataBuffer" {
         readonly underlyingResource: any;
     }
 }
+declare module "babylonjs/Engines/Processors/iShaderProcessor" {
+    /** @hidden */
+    export interface IShaderProcessor {
+        attributeProcessor?: (attribute: string) => string;
+        varyingProcessor?: (varying: string, isFragment: boolean) => string;
+        preProcessor?: (code: string, defines: string[], isFragment: boolean) => string;
+        postProcessor?: (code: string, defines: string[], isFragment: boolean) => string;
+    }
+}
+declare module "babylonjs/Engines/Processors/shaderProcessingOptions" {
+    import { IShaderProcessor } from "babylonjs/Engines/Processors/iShaderProcessor";
+    /** @hidden */
+    export interface ProcessingOptions {
+        defines: string;
+        indexParameters: any;
+        isFragment: boolean;
+        shouldUseHighPrecisionShader: boolean;
+        supportsUniformBuffers: boolean;
+        shadersRepository: string;
+        includesShadersStore: {
+            [key: string]: string;
+        };
+        processor?: IShaderProcessor;
+        version: string;
+    }
+}
+declare module "babylonjs/Engines/Processors/shaderCodeNode" {
+    import { ProcessingOptions } from "babylonjs/Engines/Processors/shaderProcessingOptions";
+    /** @hidden */
+    export class ShaderCodeNode {
+        line: string;
+        children: ShaderCodeNode[];
+        additionalDefineKey?: string;
+        additionalDefineValue?: string;
+        isValid(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+        process(preprocessors: {
+            [key: string]: string;
+        }, options: ProcessingOptions): string;
+        private _lineStartsWith;
+    }
+}
+declare module "babylonjs/Engines/Processors/shaderCodeCursor" {
+    /** @hidden */
+    export class ShaderCodeCursor {
+        lines: string[];
+        lineIndex: number;
+        readonly currentLine: string;
+        readonly canRead: boolean;
+    }
+}
+declare module "babylonjs/Engines/Processors/shaderCodeConditionNode" {
+    import { ShaderCodeNode } from "babylonjs/Engines/Processors/shaderCodeNode";
+    import { ProcessingOptions } from "babylonjs/Engines/Processors/shaderProcessingOptions";
+    /** @hidden */
+    export class ShaderCodeConditionNode extends ShaderCodeNode {
+        process(preprocessors: {
+            [key: string]: string;
+        }, options: ProcessingOptions): string;
+    }
+}
+declare module "babylonjs/Engines/Processors/Expressions/shaderDefineExpression" {
+    /** @hidden */
+    export class ShaderDefineExpression {
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module "babylonjs/Engines/Processors/shaderCodeTestNode" {
+    import { ShaderCodeNode } from "babylonjs/Engines/Processors/shaderCodeNode";
+    import { ShaderDefineExpression } from "babylonjs/Engines/Processors/Expressions/shaderDefineExpression";
+    /** @hidden */
+    export class ShaderCodeTestNode extends ShaderCodeNode {
+        testExpression: ShaderDefineExpression;
+        isValid(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module "babylonjs/Engines/Processors/Expressions/Operators/shaderDefineIsDefinedOperator" {
+    import { ShaderDefineExpression } from "babylonjs/Engines/Processors/Expressions/shaderDefineExpression";
+    /** @hidden */
+    export class ShaderDefineIsDefinedOperator extends ShaderDefineExpression {
+        define: string;
+        not: boolean;
+        constructor(define: string, not?: boolean);
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module "babylonjs/Engines/Processors/Expressions/Operators/shaderDefineOrOperator" {
+    import { ShaderDefineExpression } from "babylonjs/Engines/Processors/Expressions/shaderDefineExpression";
+    /** @hidden */
+    export class ShaderDefineOrOperator extends ShaderDefineExpression {
+        leftOperand: ShaderDefineExpression;
+        rightOperand: ShaderDefineExpression;
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module "babylonjs/Engines/Processors/Expressions/Operators/shaderDefineAndOperator" {
+    import { ShaderDefineExpression } from "babylonjs/Engines/Processors/Expressions/shaderDefineExpression";
+    /** @hidden */
+    export class ShaderDefineAndOperator extends ShaderDefineExpression {
+        leftOperand: ShaderDefineExpression;
+        rightOperand: ShaderDefineExpression;
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module "babylonjs/Engines/Processors/Expressions/Operators/shaderDefineArithmeticOperator" {
+    import { ShaderDefineExpression } from "babylonjs/Engines/Processors/Expressions/shaderDefineExpression";
+    /** @hidden */
+    export class ShaderDefineArithmeticOperator extends ShaderDefineExpression {
+        define: string;
+        operand: string;
+        testValue: string;
+        constructor(define: string, operand: string, testValue: string);
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module "babylonjs/Engines/Processors/shaderProcessor" {
+    import { ProcessingOptions } from "babylonjs/Engines/Processors/shaderProcessingOptions";
+    /** @hidden */
+    export class ShaderProcessor {
+        static Process(sourceCode: string, options: ProcessingOptions, callback: (migratedCode: string) => void): void;
+        private static _ProcessPrecision;
+        private static _ExtractOperation;
+        private static _BuildSubExpression;
+        private static _BuildExpression;
+        private static _MoveCursorWithinIf;
+        private static _MoveCursor;
+        private static _EvaluatePreProcessors;
+        private static _ProcessShaderConversion;
+        private static _ProcessIncludes;
+    }
+}
 declare module "babylonjs/Misc/performanceMonitor" {
     /**
      * Performance monitor tracks rolling average frame-time and frame-time variance over a user defined sliding-window
@@ -6485,6 +6629,10 @@ declare module "babylonjs/Materials/Textures/internalTexture" {
         /** @hidden */
         _isRGBD: boolean;
         /** @hidden */
+        _linearSpecularLOD: boolean;
+        /** @hidden */
+        _irradianceTexture: Nullable<BaseTexture>;
+        /** @hidden */
         _webGLTexture: Nullable<WebGLTexture>;
         /** @hidden */
         _references: number;
@@ -8200,7 +8348,8 @@ declare module "babylonjs/Bones/bone" {
          * Flag the bone as dirty (Forcing it to update everything)
          */
         markAsDirty(): void;
-        private _markAsDirtyAndCompose;
+        /** @hidden */
+        _markAsDirtyAndCompose(): void;
         private _markAsDirtyAndDecompose;
         /**
          * Translate the bone in local or world space
@@ -26831,6 +26980,18 @@ declare module "babylonjs/Materials/Textures/baseTexture" {
          */
         lodGenerationScale: number;
         /**
+         * With prefiltered texture, defined if the specular generation is based on a linear ramp.
+         * By default we are using a log2 of the linear roughness helping to keep a better resolution for
+         * average roughness values.
+         */
+        linearSpecularLOD: boolean;
+        /**
+         * In case a better definition than spherical harmonics is required for the diffuse part of the environment.
+         * You can set the irradiance texture to rely on a texture instead of the spherical approach.
+         * This texture need to have the same characteristics than its parent (Cube vs 2d, coordinates mode, Gamma/Linear, RGBD).
+         */
+        irradianceTexture: Nullable<BaseTexture>;
+        /**
          * Define if the texture is a render target.
          */
         isRenderTarget: boolean;
@@ -27646,6 +27807,15 @@ declare module "babylonjs/Meshes/WebGL/webGLDataBuffer" {
         readonly underlyingResource: any;
     }
 }
+declare module "babylonjs/Engines/WebGL/webGL2ShaderProcessors" {
+    import { IShaderProcessor } from "babylonjs/Engines/Processors/iShaderProcessor";
+    /** @hidden */
+    export class WebGL2ShaderProcessor implements IShaderProcessor {
+        attributeProcessor(attribute: string): string;
+        varyingProcessor(varying: string, isFragment: boolean): string;
+        postProcessor(code: string, defines: string[], isFragment: boolean): string;
+    }
+}
 declare module "babylonjs/Materials/Textures/videoTexture" {
     import { Observable } from "babylonjs/Misc/observable";
     import { Nullable } from "babylonjs/types";
@@ -27800,6 +27970,7 @@ declare module "babylonjs/Engines/engine" {
     import { WebGLPipelineContext } from "babylonjs/Engines/WebGL/webGLPipelineContext";
     import { IPipelineContext } from "babylonjs/Engines/IPipelineContext";
     import { DataBuffer } from "babylonjs/Meshes/dataBuffer";
+    import { IShaderProcessor } from "babylonjs/Engines/Processors/iShaderProcessor";
     import { PostProcess } from "babylonjs/PostProcesses/postProcess";
     import { RenderTargetTexture } from "babylonjs/Materials/Textures/renderTargetTexture";
     /**
@@ -28011,9 +28182,7 @@ declare module "babylonjs/Engines/engine" {
          * @param predicate defines a predicate used to filter which materials should be affected
          */
         static MarkAllMaterialsAsDirty(flag: number, predicate?: (mat: Material) => boolean): void;
-        /**
-         * Hidden
-         */
+        /** @hidden */
         static _TextureLoaders: IInternalTextureLoader[];
         /** Defines that alpha blending is disabled */
         static readonly ALPHA_DISABLE: number;
@@ -28234,6 +28403,8 @@ declare module "babylonjs/Engines/engine" {
          * Method called to create the default rescale post process on each engine.
          */
         static _RescalePostProcessFactory: Nullable<(engine: Engine) => PostProcess>;
+        /** @hidden */
+        _shaderProcessor: IShaderProcessor;
         /**
          * Gets or sets a boolean that indicates if textures must be forced to power of 2 size even if not required
          */
@@ -29824,7 +29995,7 @@ declare module "babylonjs/Materials/effect" {
          */
         readonly isMoreFallbacks: boolean;
         /**
-         * Removes the defines that shoould be removed when falling back.
+         * Removes the defines that should be removed when falling back.
          * @param currentDefines defines the current define statements for the shader.
          * @param effect defines the current effect we try to compile
          * @returns The resulting defines with defines of the current rank removed.
@@ -30049,9 +30220,6 @@ declare module "babylonjs/Materials/effect" {
         _loadFragmentShader(fragment: any, callback: (data: any) => void): void;
         /** @hidden */
         _dumpShadersSource(vertexCode: string, fragmentCode: string, defines: string): void;
-        private _processShaderConversion;
-        private _processIncludes;
-        private _processPrecision;
         /**
          * Recompiles the webGL program
          * @param vertexSourceCode The source code for the vertex shader.
@@ -46575,6 +46743,7 @@ declare module "babylonjs/Materials/PBR/pbrSubSurfaceConfiguration" {
         SS_LODINREFRACTIONALPHA: boolean;
         SS_GAMMAREFRACTION: boolean;
         SS_RGBDREFRACTION: boolean;
+        SS_LINEARSPECULARREFRACTION: boolean;
         SS_LINKREFRACTIONTOTRANSPARENCY: boolean;
         SS_MASK_FROM_THICKNESS_TEXTURE: boolean;
         /** @hidden */
@@ -47050,12 +47219,14 @@ declare module "babylonjs/Materials/PBR/pbrBaseMaterial" {
         REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED: boolean;
         INVERTCUBICMAP: boolean;
         USESPHERICALFROMREFLECTIONMAP: boolean;
+        USEIRRADIANCEMAP: boolean;
         SPHERICAL_HARMONICS: boolean;
         USESPHERICALINVERTEX: boolean;
         REFLECTIONMAP_OPPOSITEZ: boolean;
         LODINREFLECTIONALPHA: boolean;
         GAMMAREFLECTION: boolean;
         RGBDREFLECTION: boolean;
+        LINEARSPECULARREFLECTION: boolean;
         RADIANCEOCCLUSION: boolean;
         HORIZONOCCLUSION: boolean;
         INSTANCES: boolean;
@@ -47124,6 +47295,7 @@ declare module "babylonjs/Materials/PBR/pbrBaseMaterial" {
         SS_LODINREFRACTIONALPHA: boolean;
         SS_GAMMAREFRACTION: boolean;
         SS_RGBDREFRACTION: boolean;
+        SS_LINEARSPECULARREFRACTION: boolean;
         SS_LINKREFRACTIONTOTRANSPARENCY: boolean;
         SS_MASK_FROM_THICKNESS_TEXTURE: boolean;
         UNLIT: boolean;
@@ -61599,6 +61771,26 @@ declare module "babylonjs/Animations/pathCursor" {
         onchange(f: (cursor: PathCursor) => void): PathCursor;
     }
 }
+declare module "babylonjs/Engines/Processors/Expressions/Operators/index" {
+    export * from "babylonjs/Engines/Processors/Expressions/Operators/shaderDefineAndOperator";
+    export * from "babylonjs/Engines/Processors/Expressions/Operators/shaderDefineArithmeticOperator";
+    export * from "babylonjs/Engines/Processors/Expressions/Operators/shaderDefineIsDefinedOperator";
+    export * from "babylonjs/Engines/Processors/Expressions/Operators/shaderDefineOrOperator";
+}
+declare module "babylonjs/Engines/Processors/Expressions/index" {
+    export * from "babylonjs/Engines/Processors/Expressions/shaderDefineExpression";
+    export * from "babylonjs/Engines/Processors/Expressions/Operators/index";
+}
+declare module "babylonjs/Engines/Processors/index" {
+    export * from "babylonjs/Engines/Processors/iShaderProcessor";
+    export * from "babylonjs/Engines/Processors/Expressions/index";
+    export * from "babylonjs/Engines/Processors/shaderCodeConditionNode";
+    export * from "babylonjs/Engines/Processors/shaderCodeCursor";
+    export * from "babylonjs/Engines/Processors/shaderCodeNode";
+    export * from "babylonjs/Engines/Processors/shaderCodeTestNode";
+    export * from "babylonjs/Engines/Processors/shaderProcessingOptions";
+    export * from "babylonjs/Engines/Processors/shaderProcessor";
+}
 declare module "babylonjs/Legacy/legacy" {
     import * as Babylon from "babylonjs/index";
     export * from "babylonjs/index";
@@ -67461,6 +67653,139 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
+    /** @hidden */
+    export interface IShaderProcessor {
+        attributeProcessor?: (attribute: string) => string;
+        varyingProcessor?: (varying: string, isFragment: boolean) => string;
+        preProcessor?: (code: string, defines: string[], isFragment: boolean) => string;
+        postProcessor?: (code: string, defines: string[], isFragment: boolean) => string;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export interface ProcessingOptions {
+        defines: string;
+        indexParameters: any;
+        isFragment: boolean;
+        shouldUseHighPrecisionShader: boolean;
+        supportsUniformBuffers: boolean;
+        shadersRepository: string;
+        includesShadersStore: {
+            [key: string]: string;
+        };
+        processor?: IShaderProcessor;
+        version: string;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderCodeNode {
+        line: string;
+        children: ShaderCodeNode[];
+        additionalDefineKey?: string;
+        additionalDefineValue?: string;
+        isValid(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+        process(preprocessors: {
+            [key: string]: string;
+        }, options: ProcessingOptions): string;
+        private _lineStartsWith;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderCodeCursor {
+        lines: string[];
+        lineIndex: number;
+        readonly currentLine: string;
+        readonly canRead: boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderCodeConditionNode extends ShaderCodeNode {
+        process(preprocessors: {
+            [key: string]: string;
+        }, options: ProcessingOptions): string;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineExpression {
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderCodeTestNode extends ShaderCodeNode {
+        testExpression: ShaderDefineExpression;
+        isValid(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineIsDefinedOperator extends ShaderDefineExpression {
+        define: string;
+        not: boolean;
+        constructor(define: string, not?: boolean);
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineOrOperator extends ShaderDefineExpression {
+        leftOperand: ShaderDefineExpression;
+        rightOperand: ShaderDefineExpression;
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineAndOperator extends ShaderDefineExpression {
+        leftOperand: ShaderDefineExpression;
+        rightOperand: ShaderDefineExpression;
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineArithmeticOperator extends ShaderDefineExpression {
+        define: string;
+        operand: string;
+        testValue: string;
+        constructor(define: string, operand: string, testValue: string);
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderProcessor {
+        static Process(sourceCode: string, options: ProcessingOptions, callback: (migratedCode: string) => void): void;
+        private static _ProcessPrecision;
+        private static _ExtractOperation;
+        private static _BuildSubExpression;
+        private static _BuildExpression;
+        private static _MoveCursorWithinIf;
+        private static _MoveCursor;
+        private static _EvaluatePreProcessors;
+        private static _ProcessShaderConversion;
+        private static _ProcessIncludes;
+    }
+}
+declare module BABYLON {
     /**
      * Performance monitor tracks rolling average frame-time and frame-time variance over a user defined sliding-window
      */
@@ -68629,6 +68954,10 @@ declare module BABYLON {
         /** @hidden */
         _isRGBD: boolean;
         /** @hidden */
+        _linearSpecularLOD: boolean;
+        /** @hidden */
+        _irradianceTexture: Nullable<BaseTexture>;
+        /** @hidden */
         _webGLTexture: Nullable<WebGLTexture>;
         /** @hidden */
         _references: number;
@@ -70307,7 +70636,8 @@ declare module BABYLON {
          * Flag the bone as dirty (Forcing it to update everything)
          */
         markAsDirty(): void;
-        private _markAsDirtyAndCompose;
+        /** @hidden */
+        _markAsDirtyAndCompose(): void;
         private _markAsDirtyAndDecompose;
         /**
          * Translate the bone in local or world space
@@ -88296,6 +88626,18 @@ declare module BABYLON {
          */
         lodGenerationScale: number;
         /**
+         * With prefiltered texture, defined if the specular generation is based on a linear ramp.
+         * By default we are using a log2 of the linear roughness helping to keep a better resolution for
+         * average roughness values.
+         */
+        linearSpecularLOD: boolean;
+        /**
+         * In case a better definition than spherical harmonics is required for the diffuse part of the environment.
+         * You can set the irradiance texture to rely on a texture instead of the spherical approach.
+         * This texture need to have the same characteristics than its parent (Cube vs 2d, coordinates mode, Gamma/Linear, RGBD).
+         */
+        irradianceTexture: Nullable<BaseTexture>;
+        /**
          * Define if the texture is a render target.
          */
         isRenderTarget: boolean;
@@ -89097,6 +89439,14 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
+    /** @hidden */
+    export class WebGL2ShaderProcessor implements IShaderProcessor {
+        attributeProcessor(attribute: string): string;
+        varyingProcessor(varying: string, isFragment: boolean): string;
+        postProcessor(code: string, defines: string[], isFragment: boolean): string;
+    }
+}
+declare module BABYLON {
     /**
      * Settings for finer control over video usage
      */
@@ -89432,9 +89782,7 @@ declare module BABYLON {
          * @param predicate defines a predicate used to filter which materials should be affected
          */
         static MarkAllMaterialsAsDirty(flag: number, predicate?: (mat: Material) => boolean): void;
-        /**
-         * Hidden
-         */
+        /** @hidden */
         static _TextureLoaders: IInternalTextureLoader[];
         /** Defines that alpha blending is disabled */
         static readonly ALPHA_DISABLE: number;
@@ -89655,6 +90003,8 @@ declare module BABYLON {
          * Method called to create the default rescale post process on each engine.
          */
         static _RescalePostProcessFactory: Nullable<(engine: Engine) => PostProcess>;
+        /** @hidden */
+        _shaderProcessor: IShaderProcessor;
         /**
          * Gets or sets a boolean that indicates if textures must be forced to power of 2 size even if not required
          */
@@ -91233,7 +91583,7 @@ declare module BABYLON {
          */
         readonly isMoreFallbacks: boolean;
         /**
-         * Removes the defines that shoould be removed when falling back.
+         * Removes the defines that should be removed when falling back.
          * @param currentDefines defines the current define statements for the shader.
          * @param effect defines the current effect we try to compile
          * @returns The resulting defines with defines of the current rank removed.
@@ -91458,9 +91808,6 @@ declare module BABYLON {
         _loadFragmentShader(fragment: any, callback: (data: any) => void): void;
         /** @hidden */
         _dumpShadersSource(vertexCode: string, fragmentCode: string, defines: string): void;
-        private _processShaderConversion;
-        private _processIncludes;
-        private _processPrecision;
         /**
          * Recompiles the webGL program
          * @param vertexSourceCode The source code for the vertex shader.
@@ -106929,6 +107276,7 @@ declare module BABYLON {
         SS_LODINREFRACTIONALPHA: boolean;
         SS_GAMMAREFRACTION: boolean;
         SS_RGBDREFRACTION: boolean;
+        SS_LINEARSPECULARREFRACTION: boolean;
         SS_LINKREFRACTIONTOTRANSPARENCY: boolean;
         SS_MASK_FROM_THICKNESS_TEXTURE: boolean;
         /** @hidden */
@@ -107334,12 +107682,14 @@ declare module BABYLON {
         REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED: boolean;
         INVERTCUBICMAP: boolean;
         USESPHERICALFROMREFLECTIONMAP: boolean;
+        USEIRRADIANCEMAP: boolean;
         SPHERICAL_HARMONICS: boolean;
         USESPHERICALINVERTEX: boolean;
         REFLECTIONMAP_OPPOSITEZ: boolean;
         LODINREFLECTIONALPHA: boolean;
         GAMMAREFLECTION: boolean;
         RGBDREFLECTION: boolean;
+        LINEARSPECULARREFLECTION: boolean;
         RADIANCEOCCLUSION: boolean;
         HORIZONOCCLUSION: boolean;
         INSTANCES: boolean;
@@ -107408,6 +107758,7 @@ declare module BABYLON {
         SS_LODINREFRACTIONALPHA: boolean;
         SS_GAMMAREFRACTION: boolean;
         SS_RGBDREFRACTION: boolean;
+        SS_LINEARSPECULARREFRACTION: boolean;
         SS_LINKREFRACTIONTOTRANSPARENCY: boolean;
         SS_MASK_FROM_THICKNESS_TEXTURE: boolean;
         UNLIT: boolean;

+ 167 - 8
dist/preview release/documentation.d.ts

@@ -5291,6 +5291,139 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
+    /** @hidden */
+    export interface IShaderProcessor {
+        attributeProcessor?: (attribute: string) => string;
+        varyingProcessor?: (varying: string, isFragment: boolean) => string;
+        preProcessor?: (code: string, defines: string[], isFragment: boolean) => string;
+        postProcessor?: (code: string, defines: string[], isFragment: boolean) => string;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export interface ProcessingOptions {
+        defines: string;
+        indexParameters: any;
+        isFragment: boolean;
+        shouldUseHighPrecisionShader: boolean;
+        supportsUniformBuffers: boolean;
+        shadersRepository: string;
+        includesShadersStore: {
+            [key: string]: string;
+        };
+        processor?: IShaderProcessor;
+        version: string;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderCodeNode {
+        line: string;
+        children: ShaderCodeNode[];
+        additionalDefineKey?: string;
+        additionalDefineValue?: string;
+        isValid(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+        process(preprocessors: {
+            [key: string]: string;
+        }, options: ProcessingOptions): string;
+        private _lineStartsWith;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderCodeCursor {
+        lines: string[];
+        lineIndex: number;
+        readonly currentLine: string;
+        readonly canRead: boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderCodeConditionNode extends ShaderCodeNode {
+        process(preprocessors: {
+            [key: string]: string;
+        }, options: ProcessingOptions): string;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineExpression {
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderCodeTestNode extends ShaderCodeNode {
+        testExpression: ShaderDefineExpression;
+        isValid(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineIsDefinedOperator extends ShaderDefineExpression {
+        define: string;
+        not: boolean;
+        constructor(define: string, not?: boolean);
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineOrOperator extends ShaderDefineExpression {
+        leftOperand: ShaderDefineExpression;
+        rightOperand: ShaderDefineExpression;
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineAndOperator extends ShaderDefineExpression {
+        leftOperand: ShaderDefineExpression;
+        rightOperand: ShaderDefineExpression;
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineArithmeticOperator extends ShaderDefineExpression {
+        define: string;
+        operand: string;
+        testValue: string;
+        constructor(define: string, operand: string, testValue: string);
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderProcessor {
+        static Process(sourceCode: string, options: ProcessingOptions, callback: (migratedCode: string) => void): void;
+        private static _ProcessPrecision;
+        private static _ExtractOperation;
+        private static _BuildSubExpression;
+        private static _BuildExpression;
+        private static _MoveCursorWithinIf;
+        private static _MoveCursor;
+        private static _EvaluatePreProcessors;
+        private static _ProcessShaderConversion;
+        private static _ProcessIncludes;
+    }
+}
+declare module BABYLON {
     /**
      * Performance monitor tracks rolling average frame-time and frame-time variance over a user defined sliding-window
      */
@@ -6459,6 +6592,10 @@ declare module BABYLON {
         /** @hidden */
         _isRGBD: boolean;
         /** @hidden */
+        _linearSpecularLOD: boolean;
+        /** @hidden */
+        _irradianceTexture: Nullable<BaseTexture>;
+        /** @hidden */
         _webGLTexture: Nullable<WebGLTexture>;
         /** @hidden */
         _references: number;
@@ -8137,7 +8274,8 @@ declare module BABYLON {
          * Flag the bone as dirty (Forcing it to update everything)
          */
         markAsDirty(): void;
-        private _markAsDirtyAndCompose;
+        /** @hidden */
+        _markAsDirtyAndCompose(): void;
         private _markAsDirtyAndDecompose;
         /**
          * Translate the bone in local or world space
@@ -26126,6 +26264,18 @@ declare module BABYLON {
          */
         lodGenerationScale: number;
         /**
+         * With prefiltered texture, defined if the specular generation is based on a linear ramp.
+         * By default we are using a log2 of the linear roughness helping to keep a better resolution for
+         * average roughness values.
+         */
+        linearSpecularLOD: boolean;
+        /**
+         * In case a better definition than spherical harmonics is required for the diffuse part of the environment.
+         * You can set the irradiance texture to rely on a texture instead of the spherical approach.
+         * This texture need to have the same characteristics than its parent (Cube vs 2d, coordinates mode, Gamma/Linear, RGBD).
+         */
+        irradianceTexture: Nullable<BaseTexture>;
+        /**
          * Define if the texture is a render target.
          */
         isRenderTarget: boolean;
@@ -26927,6 +27077,14 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
+    /** @hidden */
+    export class WebGL2ShaderProcessor implements IShaderProcessor {
+        attributeProcessor(attribute: string): string;
+        varyingProcessor(varying: string, isFragment: boolean): string;
+        postProcessor(code: string, defines: string[], isFragment: boolean): string;
+    }
+}
+declare module BABYLON {
     /**
      * Settings for finer control over video usage
      */
@@ -27262,9 +27420,7 @@ declare module BABYLON {
          * @param predicate defines a predicate used to filter which materials should be affected
          */
         static MarkAllMaterialsAsDirty(flag: number, predicate?: (mat: Material) => boolean): void;
-        /**
-         * Hidden
-         */
+        /** @hidden */
         static _TextureLoaders: IInternalTextureLoader[];
         /** Defines that alpha blending is disabled */
         static readonly ALPHA_DISABLE: number;
@@ -27485,6 +27641,8 @@ declare module BABYLON {
          * Method called to create the default rescale post process on each engine.
          */
         static _RescalePostProcessFactory: Nullable<(engine: Engine) => PostProcess>;
+        /** @hidden */
+        _shaderProcessor: IShaderProcessor;
         /**
          * Gets or sets a boolean that indicates if textures must be forced to power of 2 size even if not required
          */
@@ -29063,7 +29221,7 @@ declare module BABYLON {
          */
         readonly isMoreFallbacks: boolean;
         /**
-         * Removes the defines that shoould be removed when falling back.
+         * Removes the defines that should be removed when falling back.
          * @param currentDefines defines the current define statements for the shader.
          * @param effect defines the current effect we try to compile
          * @returns The resulting defines with defines of the current rank removed.
@@ -29288,9 +29446,6 @@ declare module BABYLON {
         _loadFragmentShader(fragment: any, callback: (data: any) => void): void;
         /** @hidden */
         _dumpShadersSource(vertexCode: string, fragmentCode: string, defines: string): void;
-        private _processShaderConversion;
-        private _processIncludes;
-        private _processPrecision;
         /**
          * Recompiles the webGL program
          * @param vertexSourceCode The source code for the vertex shader.
@@ -44759,6 +44914,7 @@ declare module BABYLON {
         SS_LODINREFRACTIONALPHA: boolean;
         SS_GAMMAREFRACTION: boolean;
         SS_RGBDREFRACTION: boolean;
+        SS_LINEARSPECULARREFRACTION: boolean;
         SS_LINKREFRACTIONTOTRANSPARENCY: boolean;
         SS_MASK_FROM_THICKNESS_TEXTURE: boolean;
         /** @hidden */
@@ -45164,12 +45320,14 @@ declare module BABYLON {
         REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED: boolean;
         INVERTCUBICMAP: boolean;
         USESPHERICALFROMREFLECTIONMAP: boolean;
+        USEIRRADIANCEMAP: boolean;
         SPHERICAL_HARMONICS: boolean;
         USESPHERICALINVERTEX: boolean;
         REFLECTIONMAP_OPPOSITEZ: boolean;
         LODINREFLECTIONALPHA: boolean;
         GAMMAREFLECTION: boolean;
         RGBDREFLECTION: boolean;
+        LINEARSPECULARREFLECTION: boolean;
         RADIANCEOCCLUSION: boolean;
         HORIZONOCCLUSION: boolean;
         INSTANCES: boolean;
@@ -45238,6 +45396,7 @@ declare module BABYLON {
         SS_LODINREFRACTIONALPHA: boolean;
         SS_GAMMAREFRACTION: boolean;
         SS_RGBDREFRACTION: boolean;
+        SS_LINEARSPECULARREFRACTION: boolean;
         SS_LINKREFRACTIONTOTRANSPARENCY: boolean;
         SS_MASK_FROM_THICKNESS_TEXTURE: boolean;
         UNLIT: boolean;

+ 7 - 7
dist/preview release/inspector/babylon.inspector.bundle.max.js

@@ -7,7 +7,7 @@
 		exports["babylonjs-inspector"] = factory(require("babylonjs-gui"), require("babylonjs-loaders"), require("babylonjs-serializers"), require("babylonjs"));
 	else
 		root["INSPECTOR"] = factory(root["BABYLON"]["GUI"], root["BABYLON"], root["BABYLON"], root["BABYLON"]);
-})((typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : this), function(__WEBPACK_EXTERNAL_MODULE_babylonjs_gui_2D_adtInstrumentation__, __WEBPACK_EXTERNAL_MODULE_babylonjs_loaders_glTF_index__, __WEBPACK_EXTERNAL_MODULE_babylonjs_serializers_glTF_2_0_index__, __WEBPACK_EXTERNAL_MODULE_babylonjs_Misc_observable__) {
+})((typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : this), function(__WEBPACK_EXTERNAL_MODULE_babylonjs_gui_2D_controls_image__, __WEBPACK_EXTERNAL_MODULE_babylonjs_loaders_glTF_index__, __WEBPACK_EXTERNAL_MODULE_babylonjs_serializers_glTF_2_0_index__, __WEBPACK_EXTERNAL_MODULE_babylonjs_Misc_observable__) {
 return /******/ (function(modules) { // webpackBootstrap
 /******/ 	// The module cache
 /******/ 	var installedModules = {};
@@ -36048,7 +36048,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _lineContainerComponent__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../lineContainerComponent */ "./components/actionTabs/lineContainerComponent.tsx");
 /* harmony import */ var _lines_textLineComponent__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../lines/textLineComponent */ "./components/actionTabs/lines/textLineComponent.tsx");
-/* harmony import */ var babylonjs_gui_2D_controls_control__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! babylonjs-gui/2D/controls/control */ "babylonjs-gui/2D/adtInstrumentation");
+/* harmony import */ var babylonjs_gui_2D_controls_control__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! babylonjs-gui/2D/controls/control */ "babylonjs-gui/2D/controls/image");
 /* harmony import */ var babylonjs_gui_2D_controls_control__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(babylonjs_gui_2D_controls_control__WEBPACK_IMPORTED_MODULE_4__);
 /* harmony import */ var _lines_sliderLineComponent__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../../lines/sliderLineComponent */ "./components/actionTabs/lines/sliderLineComponent.tsx");
 /* harmony import */ var _lines_floatLineComponent__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../../lines/floatLineComponent */ "./components/actionTabs/lines/floatLineComponent.tsx");
@@ -36349,7 +36349,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _commonControlPropertyGridComponent__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./commonControlPropertyGridComponent */ "./components/actionTabs/tabs/propertyGrids/gui/commonControlPropertyGridComponent.tsx");
 /* harmony import */ var _lineContainerComponent__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../lineContainerComponent */ "./components/actionTabs/lineContainerComponent.tsx");
-/* harmony import */ var babylonjs_gui_2D_controls_image__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! babylonjs-gui/2D/controls/image */ "babylonjs-gui/2D/adtInstrumentation");
+/* harmony import */ var babylonjs_gui_2D_controls_image__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! babylonjs-gui/2D/controls/image */ "babylonjs-gui/2D/controls/image");
 /* harmony import */ var babylonjs_gui_2D_controls_image__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(babylonjs_gui_2D_controls_image__WEBPACK_IMPORTED_MODULE_4__);
 /* harmony import */ var _lines_floatLineComponent__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../../lines/floatLineComponent */ "./components/actionTabs/lines/floatLineComponent.tsx");
 /* harmony import */ var _lines_checkBoxLineComponent__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../../lines/checkBoxLineComponent */ "./components/actionTabs/lines/checkBoxLineComponent.tsx");
@@ -36763,7 +36763,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react */ "../../node_modules/react/index.js");
 /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _commonControlPropertyGridComponent__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./commonControlPropertyGridComponent */ "./components/actionTabs/tabs/propertyGrids/gui/commonControlPropertyGridComponent.tsx");
-/* harmony import */ var babylonjs_gui_2D_controls_textBlock__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! babylonjs-gui/2D/controls/textBlock */ "babylonjs-gui/2D/adtInstrumentation");
+/* harmony import */ var babylonjs_gui_2D_controls_textBlock__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! babylonjs-gui/2D/controls/textBlock */ "babylonjs-gui/2D/controls/image");
 /* harmony import */ var babylonjs_gui_2D_controls_textBlock__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(babylonjs_gui_2D_controls_textBlock__WEBPACK_IMPORTED_MODULE_3__);
 /* harmony import */ var _lineContainerComponent__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../lineContainerComponent */ "./components/actionTabs/lineContainerComponent.tsx");
 /* harmony import */ var _lines_textInputLineComponent__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../../lines/textInputLineComponent */ "./components/actionTabs/lines/textInputLineComponent.tsx");
@@ -37891,7 +37891,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var _lines_optionsLineComponent__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../../lines/optionsLineComponent */ "./components/actionTabs/lines/optionsLineComponent.tsx");
 /* harmony import */ var _lines_fileButtonLineComponent__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../../lines/fileButtonLineComponent */ "./components/actionTabs/lines/fileButtonLineComponent.tsx");
 /* harmony import */ var _lines_valueLineComponent__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../../../lines/valueLineComponent */ "./components/actionTabs/lines/valueLineComponent.tsx");
-/* harmony import */ var babylonjs_gui_2D_adtInstrumentation__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! babylonjs-gui/2D/adtInstrumentation */ "babylonjs-gui/2D/adtInstrumentation");
+/* harmony import */ var babylonjs_gui_2D_adtInstrumentation__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! babylonjs-gui/2D/adtInstrumentation */ "babylonjs-gui/2D/controls/image");
 /* harmony import */ var babylonjs_gui_2D_adtInstrumentation__WEBPACK_IMPORTED_MODULE_12___default = /*#__PURE__*/__webpack_require__.n(babylonjs_gui_2D_adtInstrumentation__WEBPACK_IMPORTED_MODULE_12__);
 /* harmony import */ var _customPropertyGridComponent__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../customPropertyGridComponent */ "./components/actionTabs/tabs/propertyGrids/customPropertyGridComponent.tsx");
 
@@ -42463,14 +42463,14 @@ var Tools = /** @class */ (function () {
 
 /***/ }),
 
-/***/ "babylonjs-gui/2D/adtInstrumentation":
+/***/ "babylonjs-gui/2D/controls/image":
 /*!************************************************************************************************************************!*\
   !*** external {"root":["BABYLON","GUI"],"commonjs":"babylonjs-gui","commonjs2":"babylonjs-gui","amd":"babylonjs-gui"} ***!
   \************************************************************************************************************************/
 /*! no static exports found */
 /***/ (function(module, exports) {
 
-module.exports = __WEBPACK_EXTERNAL_MODULE_babylonjs_gui_2D_adtInstrumentation__;
+module.exports = __WEBPACK_EXTERNAL_MODULE_babylonjs_gui_2D_controls_image__;
 
 /***/ }),
 

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.max.js.map


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

@@ -1 +1 @@
-{"engineOnly":291259,"sceneOnly":501088,"minGridMaterial":628531,"minStandardMaterial":753356}
+{"engineOnly":296843,"sceneOnly":506672,"minGridMaterial":634115,"minStandardMaterial":759513}

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

@@ -5293,6 +5293,150 @@ declare module "babylonjs/Meshes/dataBuffer" {
         readonly underlyingResource: any;
     }
 }
+declare module "babylonjs/Engines/Processors/iShaderProcessor" {
+    /** @hidden */
+    export interface IShaderProcessor {
+        attributeProcessor?: (attribute: string) => string;
+        varyingProcessor?: (varying: string, isFragment: boolean) => string;
+        preProcessor?: (code: string, defines: string[], isFragment: boolean) => string;
+        postProcessor?: (code: string, defines: string[], isFragment: boolean) => string;
+    }
+}
+declare module "babylonjs/Engines/Processors/shaderProcessingOptions" {
+    import { IShaderProcessor } from "babylonjs/Engines/Processors/iShaderProcessor";
+    /** @hidden */
+    export interface ProcessingOptions {
+        defines: string;
+        indexParameters: any;
+        isFragment: boolean;
+        shouldUseHighPrecisionShader: boolean;
+        supportsUniformBuffers: boolean;
+        shadersRepository: string;
+        includesShadersStore: {
+            [key: string]: string;
+        };
+        processor?: IShaderProcessor;
+        version: string;
+    }
+}
+declare module "babylonjs/Engines/Processors/shaderCodeNode" {
+    import { ProcessingOptions } from "babylonjs/Engines/Processors/shaderProcessingOptions";
+    /** @hidden */
+    export class ShaderCodeNode {
+        line: string;
+        children: ShaderCodeNode[];
+        additionalDefineKey?: string;
+        additionalDefineValue?: string;
+        isValid(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+        process(preprocessors: {
+            [key: string]: string;
+        }, options: ProcessingOptions): string;
+        private _lineStartsWith;
+    }
+}
+declare module "babylonjs/Engines/Processors/shaderCodeCursor" {
+    /** @hidden */
+    export class ShaderCodeCursor {
+        lines: string[];
+        lineIndex: number;
+        readonly currentLine: string;
+        readonly canRead: boolean;
+    }
+}
+declare module "babylonjs/Engines/Processors/shaderCodeConditionNode" {
+    import { ShaderCodeNode } from "babylonjs/Engines/Processors/shaderCodeNode";
+    import { ProcessingOptions } from "babylonjs/Engines/Processors/shaderProcessingOptions";
+    /** @hidden */
+    export class ShaderCodeConditionNode extends ShaderCodeNode {
+        process(preprocessors: {
+            [key: string]: string;
+        }, options: ProcessingOptions): string;
+    }
+}
+declare module "babylonjs/Engines/Processors/Expressions/shaderDefineExpression" {
+    /** @hidden */
+    export class ShaderDefineExpression {
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module "babylonjs/Engines/Processors/shaderCodeTestNode" {
+    import { ShaderCodeNode } from "babylonjs/Engines/Processors/shaderCodeNode";
+    import { ShaderDefineExpression } from "babylonjs/Engines/Processors/Expressions/shaderDefineExpression";
+    /** @hidden */
+    export class ShaderCodeTestNode extends ShaderCodeNode {
+        testExpression: ShaderDefineExpression;
+        isValid(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module "babylonjs/Engines/Processors/Expressions/Operators/shaderDefineIsDefinedOperator" {
+    import { ShaderDefineExpression } from "babylonjs/Engines/Processors/Expressions/shaderDefineExpression";
+    /** @hidden */
+    export class ShaderDefineIsDefinedOperator extends ShaderDefineExpression {
+        define: string;
+        not: boolean;
+        constructor(define: string, not?: boolean);
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module "babylonjs/Engines/Processors/Expressions/Operators/shaderDefineOrOperator" {
+    import { ShaderDefineExpression } from "babylonjs/Engines/Processors/Expressions/shaderDefineExpression";
+    /** @hidden */
+    export class ShaderDefineOrOperator extends ShaderDefineExpression {
+        leftOperand: ShaderDefineExpression;
+        rightOperand: ShaderDefineExpression;
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module "babylonjs/Engines/Processors/Expressions/Operators/shaderDefineAndOperator" {
+    import { ShaderDefineExpression } from "babylonjs/Engines/Processors/Expressions/shaderDefineExpression";
+    /** @hidden */
+    export class ShaderDefineAndOperator extends ShaderDefineExpression {
+        leftOperand: ShaderDefineExpression;
+        rightOperand: ShaderDefineExpression;
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module "babylonjs/Engines/Processors/Expressions/Operators/shaderDefineArithmeticOperator" {
+    import { ShaderDefineExpression } from "babylonjs/Engines/Processors/Expressions/shaderDefineExpression";
+    /** @hidden */
+    export class ShaderDefineArithmeticOperator extends ShaderDefineExpression {
+        define: string;
+        operand: string;
+        testValue: string;
+        constructor(define: string, operand: string, testValue: string);
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module "babylonjs/Engines/Processors/shaderProcessor" {
+    import { ProcessingOptions } from "babylonjs/Engines/Processors/shaderProcessingOptions";
+    /** @hidden */
+    export class ShaderProcessor {
+        static Process(sourceCode: string, options: ProcessingOptions, callback: (migratedCode: string) => void): void;
+        private static _ProcessPrecision;
+        private static _ExtractOperation;
+        private static _BuildSubExpression;
+        private static _BuildExpression;
+        private static _MoveCursorWithinIf;
+        private static _MoveCursor;
+        private static _EvaluatePreProcessors;
+        private static _ProcessShaderConversion;
+        private static _ProcessIncludes;
+    }
+}
 declare module "babylonjs/Misc/performanceMonitor" {
     /**
      * Performance monitor tracks rolling average frame-time and frame-time variance over a user defined sliding-window
@@ -6485,6 +6629,10 @@ declare module "babylonjs/Materials/Textures/internalTexture" {
         /** @hidden */
         _isRGBD: boolean;
         /** @hidden */
+        _linearSpecularLOD: boolean;
+        /** @hidden */
+        _irradianceTexture: Nullable<BaseTexture>;
+        /** @hidden */
         _webGLTexture: Nullable<WebGLTexture>;
         /** @hidden */
         _references: number;
@@ -8200,7 +8348,8 @@ declare module "babylonjs/Bones/bone" {
          * Flag the bone as dirty (Forcing it to update everything)
          */
         markAsDirty(): void;
-        private _markAsDirtyAndCompose;
+        /** @hidden */
+        _markAsDirtyAndCompose(): void;
         private _markAsDirtyAndDecompose;
         /**
          * Translate the bone in local or world space
@@ -26831,6 +26980,18 @@ declare module "babylonjs/Materials/Textures/baseTexture" {
          */
         lodGenerationScale: number;
         /**
+         * With prefiltered texture, defined if the specular generation is based on a linear ramp.
+         * By default we are using a log2 of the linear roughness helping to keep a better resolution for
+         * average roughness values.
+         */
+        linearSpecularLOD: boolean;
+        /**
+         * In case a better definition than spherical harmonics is required for the diffuse part of the environment.
+         * You can set the irradiance texture to rely on a texture instead of the spherical approach.
+         * This texture need to have the same characteristics than its parent (Cube vs 2d, coordinates mode, Gamma/Linear, RGBD).
+         */
+        irradianceTexture: Nullable<BaseTexture>;
+        /**
          * Define if the texture is a render target.
          */
         isRenderTarget: boolean;
@@ -27646,6 +27807,15 @@ declare module "babylonjs/Meshes/WebGL/webGLDataBuffer" {
         readonly underlyingResource: any;
     }
 }
+declare module "babylonjs/Engines/WebGL/webGL2ShaderProcessors" {
+    import { IShaderProcessor } from "babylonjs/Engines/Processors/iShaderProcessor";
+    /** @hidden */
+    export class WebGL2ShaderProcessor implements IShaderProcessor {
+        attributeProcessor(attribute: string): string;
+        varyingProcessor(varying: string, isFragment: boolean): string;
+        postProcessor(code: string, defines: string[], isFragment: boolean): string;
+    }
+}
 declare module "babylonjs/Materials/Textures/videoTexture" {
     import { Observable } from "babylonjs/Misc/observable";
     import { Nullable } from "babylonjs/types";
@@ -27800,6 +27970,7 @@ declare module "babylonjs/Engines/engine" {
     import { WebGLPipelineContext } from "babylonjs/Engines/WebGL/webGLPipelineContext";
     import { IPipelineContext } from "babylonjs/Engines/IPipelineContext";
     import { DataBuffer } from "babylonjs/Meshes/dataBuffer";
+    import { IShaderProcessor } from "babylonjs/Engines/Processors/iShaderProcessor";
     import { PostProcess } from "babylonjs/PostProcesses/postProcess";
     import { RenderTargetTexture } from "babylonjs/Materials/Textures/renderTargetTexture";
     /**
@@ -28011,9 +28182,7 @@ declare module "babylonjs/Engines/engine" {
          * @param predicate defines a predicate used to filter which materials should be affected
          */
         static MarkAllMaterialsAsDirty(flag: number, predicate?: (mat: Material) => boolean): void;
-        /**
-         * Hidden
-         */
+        /** @hidden */
         static _TextureLoaders: IInternalTextureLoader[];
         /** Defines that alpha blending is disabled */
         static readonly ALPHA_DISABLE: number;
@@ -28234,6 +28403,8 @@ declare module "babylonjs/Engines/engine" {
          * Method called to create the default rescale post process on each engine.
          */
         static _RescalePostProcessFactory: Nullable<(engine: Engine) => PostProcess>;
+        /** @hidden */
+        _shaderProcessor: IShaderProcessor;
         /**
          * Gets or sets a boolean that indicates if textures must be forced to power of 2 size even if not required
          */
@@ -29824,7 +29995,7 @@ declare module "babylonjs/Materials/effect" {
          */
         readonly isMoreFallbacks: boolean;
         /**
-         * Removes the defines that shoould be removed when falling back.
+         * Removes the defines that should be removed when falling back.
          * @param currentDefines defines the current define statements for the shader.
          * @param effect defines the current effect we try to compile
          * @returns The resulting defines with defines of the current rank removed.
@@ -30049,9 +30220,6 @@ declare module "babylonjs/Materials/effect" {
         _loadFragmentShader(fragment: any, callback: (data: any) => void): void;
         /** @hidden */
         _dumpShadersSource(vertexCode: string, fragmentCode: string, defines: string): void;
-        private _processShaderConversion;
-        private _processIncludes;
-        private _processPrecision;
         /**
          * Recompiles the webGL program
          * @param vertexSourceCode The source code for the vertex shader.
@@ -46575,6 +46743,7 @@ declare module "babylonjs/Materials/PBR/pbrSubSurfaceConfiguration" {
         SS_LODINREFRACTIONALPHA: boolean;
         SS_GAMMAREFRACTION: boolean;
         SS_RGBDREFRACTION: boolean;
+        SS_LINEARSPECULARREFRACTION: boolean;
         SS_LINKREFRACTIONTOTRANSPARENCY: boolean;
         SS_MASK_FROM_THICKNESS_TEXTURE: boolean;
         /** @hidden */
@@ -47050,12 +47219,14 @@ declare module "babylonjs/Materials/PBR/pbrBaseMaterial" {
         REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED: boolean;
         INVERTCUBICMAP: boolean;
         USESPHERICALFROMREFLECTIONMAP: boolean;
+        USEIRRADIANCEMAP: boolean;
         SPHERICAL_HARMONICS: boolean;
         USESPHERICALINVERTEX: boolean;
         REFLECTIONMAP_OPPOSITEZ: boolean;
         LODINREFLECTIONALPHA: boolean;
         GAMMAREFLECTION: boolean;
         RGBDREFLECTION: boolean;
+        LINEARSPECULARREFLECTION: boolean;
         RADIANCEOCCLUSION: boolean;
         HORIZONOCCLUSION: boolean;
         INSTANCES: boolean;
@@ -47124,6 +47295,7 @@ declare module "babylonjs/Materials/PBR/pbrBaseMaterial" {
         SS_LODINREFRACTIONALPHA: boolean;
         SS_GAMMAREFRACTION: boolean;
         SS_RGBDREFRACTION: boolean;
+        SS_LINEARSPECULARREFRACTION: boolean;
         SS_LINKREFRACTIONTOTRANSPARENCY: boolean;
         SS_MASK_FROM_THICKNESS_TEXTURE: boolean;
         UNLIT: boolean;
@@ -61599,6 +61771,26 @@ declare module "babylonjs/Animations/pathCursor" {
         onchange(f: (cursor: PathCursor) => void): PathCursor;
     }
 }
+declare module "babylonjs/Engines/Processors/Expressions/Operators/index" {
+    export * from "babylonjs/Engines/Processors/Expressions/Operators/shaderDefineAndOperator";
+    export * from "babylonjs/Engines/Processors/Expressions/Operators/shaderDefineArithmeticOperator";
+    export * from "babylonjs/Engines/Processors/Expressions/Operators/shaderDefineIsDefinedOperator";
+    export * from "babylonjs/Engines/Processors/Expressions/Operators/shaderDefineOrOperator";
+}
+declare module "babylonjs/Engines/Processors/Expressions/index" {
+    export * from "babylonjs/Engines/Processors/Expressions/shaderDefineExpression";
+    export * from "babylonjs/Engines/Processors/Expressions/Operators/index";
+}
+declare module "babylonjs/Engines/Processors/index" {
+    export * from "babylonjs/Engines/Processors/iShaderProcessor";
+    export * from "babylonjs/Engines/Processors/Expressions/index";
+    export * from "babylonjs/Engines/Processors/shaderCodeConditionNode";
+    export * from "babylonjs/Engines/Processors/shaderCodeCursor";
+    export * from "babylonjs/Engines/Processors/shaderCodeNode";
+    export * from "babylonjs/Engines/Processors/shaderCodeTestNode";
+    export * from "babylonjs/Engines/Processors/shaderProcessingOptions";
+    export * from "babylonjs/Engines/Processors/shaderProcessor";
+}
 declare module "babylonjs/Legacy/legacy" {
     import * as Babylon from "babylonjs/index";
     export * from "babylonjs/index";
@@ -67461,6 +67653,139 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
+    /** @hidden */
+    export interface IShaderProcessor {
+        attributeProcessor?: (attribute: string) => string;
+        varyingProcessor?: (varying: string, isFragment: boolean) => string;
+        preProcessor?: (code: string, defines: string[], isFragment: boolean) => string;
+        postProcessor?: (code: string, defines: string[], isFragment: boolean) => string;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export interface ProcessingOptions {
+        defines: string;
+        indexParameters: any;
+        isFragment: boolean;
+        shouldUseHighPrecisionShader: boolean;
+        supportsUniformBuffers: boolean;
+        shadersRepository: string;
+        includesShadersStore: {
+            [key: string]: string;
+        };
+        processor?: IShaderProcessor;
+        version: string;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderCodeNode {
+        line: string;
+        children: ShaderCodeNode[];
+        additionalDefineKey?: string;
+        additionalDefineValue?: string;
+        isValid(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+        process(preprocessors: {
+            [key: string]: string;
+        }, options: ProcessingOptions): string;
+        private _lineStartsWith;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderCodeCursor {
+        lines: string[];
+        lineIndex: number;
+        readonly currentLine: string;
+        readonly canRead: boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderCodeConditionNode extends ShaderCodeNode {
+        process(preprocessors: {
+            [key: string]: string;
+        }, options: ProcessingOptions): string;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineExpression {
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderCodeTestNode extends ShaderCodeNode {
+        testExpression: ShaderDefineExpression;
+        isValid(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineIsDefinedOperator extends ShaderDefineExpression {
+        define: string;
+        not: boolean;
+        constructor(define: string, not?: boolean);
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineOrOperator extends ShaderDefineExpression {
+        leftOperand: ShaderDefineExpression;
+        rightOperand: ShaderDefineExpression;
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineAndOperator extends ShaderDefineExpression {
+        leftOperand: ShaderDefineExpression;
+        rightOperand: ShaderDefineExpression;
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderDefineArithmeticOperator extends ShaderDefineExpression {
+        define: string;
+        operand: string;
+        testValue: string;
+        constructor(define: string, operand: string, testValue: string);
+        isTrue(preprocessors: {
+            [key: string]: string;
+        }): boolean;
+    }
+}
+declare module BABYLON {
+    /** @hidden */
+    export class ShaderProcessor {
+        static Process(sourceCode: string, options: ProcessingOptions, callback: (migratedCode: string) => void): void;
+        private static _ProcessPrecision;
+        private static _ExtractOperation;
+        private static _BuildSubExpression;
+        private static _BuildExpression;
+        private static _MoveCursorWithinIf;
+        private static _MoveCursor;
+        private static _EvaluatePreProcessors;
+        private static _ProcessShaderConversion;
+        private static _ProcessIncludes;
+    }
+}
+declare module BABYLON {
     /**
      * Performance monitor tracks rolling average frame-time and frame-time variance over a user defined sliding-window
      */
@@ -68629,6 +68954,10 @@ declare module BABYLON {
         /** @hidden */
         _isRGBD: boolean;
         /** @hidden */
+        _linearSpecularLOD: boolean;
+        /** @hidden */
+        _irradianceTexture: Nullable<BaseTexture>;
+        /** @hidden */
         _webGLTexture: Nullable<WebGLTexture>;
         /** @hidden */
         _references: number;
@@ -70307,7 +70636,8 @@ declare module BABYLON {
          * Flag the bone as dirty (Forcing it to update everything)
          */
         markAsDirty(): void;
-        private _markAsDirtyAndCompose;
+        /** @hidden */
+        _markAsDirtyAndCompose(): void;
         private _markAsDirtyAndDecompose;
         /**
          * Translate the bone in local or world space
@@ -88296,6 +88626,18 @@ declare module BABYLON {
          */
         lodGenerationScale: number;
         /**
+         * With prefiltered texture, defined if the specular generation is based on a linear ramp.
+         * By default we are using a log2 of the linear roughness helping to keep a better resolution for
+         * average roughness values.
+         */
+        linearSpecularLOD: boolean;
+        /**
+         * In case a better definition than spherical harmonics is required for the diffuse part of the environment.
+         * You can set the irradiance texture to rely on a texture instead of the spherical approach.
+         * This texture need to have the same characteristics than its parent (Cube vs 2d, coordinates mode, Gamma/Linear, RGBD).
+         */
+        irradianceTexture: Nullable<BaseTexture>;
+        /**
          * Define if the texture is a render target.
          */
         isRenderTarget: boolean;
@@ -89097,6 +89439,14 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
+    /** @hidden */
+    export class WebGL2ShaderProcessor implements IShaderProcessor {
+        attributeProcessor(attribute: string): string;
+        varyingProcessor(varying: string, isFragment: boolean): string;
+        postProcessor(code: string, defines: string[], isFragment: boolean): string;
+    }
+}
+declare module BABYLON {
     /**
      * Settings for finer control over video usage
      */
@@ -89432,9 +89782,7 @@ declare module BABYLON {
          * @param predicate defines a predicate used to filter which materials should be affected
          */
         static MarkAllMaterialsAsDirty(flag: number, predicate?: (mat: Material) => boolean): void;
-        /**
-         * Hidden
-         */
+        /** @hidden */
         static _TextureLoaders: IInternalTextureLoader[];
         /** Defines that alpha blending is disabled */
         static readonly ALPHA_DISABLE: number;
@@ -89655,6 +90003,8 @@ declare module BABYLON {
          * Method called to create the default rescale post process on each engine.
          */
         static _RescalePostProcessFactory: Nullable<(engine: Engine) => PostProcess>;
+        /** @hidden */
+        _shaderProcessor: IShaderProcessor;
         /**
          * Gets or sets a boolean that indicates if textures must be forced to power of 2 size even if not required
          */
@@ -91233,7 +91583,7 @@ declare module BABYLON {
          */
         readonly isMoreFallbacks: boolean;
         /**
-         * Removes the defines that shoould be removed when falling back.
+         * Removes the defines that should be removed when falling back.
          * @param currentDefines defines the current define statements for the shader.
          * @param effect defines the current effect we try to compile
          * @returns The resulting defines with defines of the current rank removed.
@@ -91458,9 +91808,6 @@ declare module BABYLON {
         _loadFragmentShader(fragment: any, callback: (data: any) => void): void;
         /** @hidden */
         _dumpShadersSource(vertexCode: string, fragmentCode: string, defines: string): void;
-        private _processShaderConversion;
-        private _processIncludes;
-        private _processPrecision;
         /**
          * Recompiles the webGL program
          * @param vertexSourceCode The source code for the vertex shader.
@@ -106929,6 +107276,7 @@ declare module BABYLON {
         SS_LODINREFRACTIONALPHA: boolean;
         SS_GAMMAREFRACTION: boolean;
         SS_RGBDREFRACTION: boolean;
+        SS_LINEARSPECULARREFRACTION: boolean;
         SS_LINKREFRACTIONTOTRANSPARENCY: boolean;
         SS_MASK_FROM_THICKNESS_TEXTURE: boolean;
         /** @hidden */
@@ -107334,12 +107682,14 @@ declare module BABYLON {
         REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED: boolean;
         INVERTCUBICMAP: boolean;
         USESPHERICALFROMREFLECTIONMAP: boolean;
+        USEIRRADIANCEMAP: boolean;
         SPHERICAL_HARMONICS: boolean;
         USESPHERICALINVERTEX: boolean;
         REFLECTIONMAP_OPPOSITEZ: boolean;
         LODINREFLECTIONALPHA: boolean;
         GAMMAREFLECTION: boolean;
         RGBDREFLECTION: boolean;
+        LINEARSPECULARREFLECTION: boolean;
         RADIANCEOCCLUSION: boolean;
         HORIZONOCCLUSION: boolean;
         INSTANCES: boolean;
@@ -107408,6 +107758,7 @@ declare module BABYLON {
         SS_LODINREFRACTIONALPHA: boolean;
         SS_GAMMAREFRACTION: boolean;
         SS_RGBDREFRACTION: boolean;
+        SS_LINEARSPECULARREFRACTION: boolean;
         SS_LINKREFRACTIONTOTRANSPARENCY: boolean;
         SS_MASK_FROM_THICKNESS_TEXTURE: boolean;
         UNLIT: boolean;

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 66 - 22
dist/preview release/viewer/babylon.viewer.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1 - 1
dist/preview release/viewer/babylon.viewer.max.js


+ 4 - 3
dist/preview release/what's new.md

@@ -13,6 +13,9 @@
 - Unify preparation of instance attributes. Added `MaterialHelper.PushAttributesForInstances` ([MarkusBillharz](https://github.com/MarkusBillharz))
 - Added support for PBR [irradiance map](https://doc.babylonjs.com/how_to/physically_based_rendering_master#irradiance-map)
 
+### Engine
+- Added preprocessors for shaders to improve how shaders are compiled for WebGL1/2 or WebGPU ([Deltakosh](https://github.com/deltakosh/))
+
 ### Inspector
 - Added support for `ShadowGenerator` ([Deltakosh](https://github.com/deltakosh/))
 - Added support for scene normalization ([Deltakosh](https://github.com/deltakosh/))
@@ -23,13 +26,11 @@
 
 ### Tools
 - Added `Color3.toHSV()`, `Color3.toHSVToRef()` and `Color3.HSVtoRGBToRef()` ([Deltakosh](https://github.com/deltakosh/))
+- Added `ShadowGenerator.onAfterShadowMapRenderObservable` and `ShadowGenerator.onAfterShadowMapMeshRenderObservable` ([Deltakosh](https://github.com/deltakosh/))
 
 ### Meshes
 - Added new CreateTiledPlane and CreateTiledBox ([JohnK](https://github.com/BabylonJSGuide/))
 
-### Tools
-- Added `ShadowGenerator.onAfterShadowMapRenderObservable` and `ShadowGenerator.onAfterShadowMapMeshRenderObservable` ([Deltakosh](https://github.com/deltakosh/))
-
 ## Bug fixes
 - Added support for `AnimationGroup` serialization ([Drigax](https://github.com/drigax/))
 - Removing assetContainer from scene will also remove gui layers ([TrevorDev](https://github.com/TrevorDev))

+ 4 - 0
src/Engines/Processors/Expressions/Operators/index.ts

@@ -0,0 +1,4 @@
+export * from "./shaderDefineAndOperator";
+export * from "./shaderDefineArithmeticOperator";
+export * from "./shaderDefineIsDefinedOperator";
+export * from "./shaderDefineOrOperator";

+ 11 - 0
src/Engines/Processors/Expressions/Operators/shaderDefineAndOperator.ts

@@ -0,0 +1,11 @@
+import { ShaderDefineExpression } from '../shaderDefineExpression';
+
+/** @hidden */
+export class ShaderDefineAndOperator extends ShaderDefineExpression {
+    public leftOperand: ShaderDefineExpression;
+    public rightOperand: ShaderDefineExpression;
+
+    public isTrue(preprocessors: { [key: string]: string }): boolean {
+        return this.leftOperand.isTrue(preprocessors) && this.rightOperand.isTrue(preprocessors);
+    }
+}

+ 40 - 0
src/Engines/Processors/Expressions/Operators/shaderDefineArithmeticOperator.ts

@@ -0,0 +1,40 @@
+import { ShaderDefineExpression } from '../shaderDefineExpression';
+
+/** @hidden */
+export class ShaderDefineArithmeticOperator extends ShaderDefineExpression {
+    public constructor(public define: string, public operand: string, public testValue: string) {
+        super();
+    }
+
+    public isTrue(preprocessors: { [key: string]: string }) {
+        let value = preprocessors[this.define];
+
+        if (value === undefined) {
+            return false;
+        }
+
+        let condition = false;
+        let left = parseInt(value);
+        let right = parseInt(this.testValue);
+
+        switch (this.operand) {
+            case ">":
+                condition = left > right;
+                break;
+            case "<":
+                condition = left < right;
+                break;
+            case "<=":
+                condition = left <= right;
+                break;
+            case ">=":
+                condition = left >= right;
+                break;
+            case "==":
+                condition = left === right;
+                break;
+        }
+
+        return condition;
+    }
+}

+ 19 - 0
src/Engines/Processors/Expressions/Operators/shaderDefineIsDefinedOperator.ts

@@ -0,0 +1,19 @@
+import { ShaderDefineExpression } from "../shaderDefineExpression";
+
+/** @hidden */
+export class ShaderDefineIsDefinedOperator extends ShaderDefineExpression {
+
+    public constructor(public define: string, public not: boolean = false) {
+        super();
+    }
+
+    public isTrue(preprocessors: { [key: string]: string }) {
+        let condition = preprocessors[this.define] !== undefined;
+
+        if (this.not) {
+            condition = !condition;
+        }
+
+        return condition;
+    }
+}

+ 11 - 0
src/Engines/Processors/Expressions/Operators/shaderDefineOrOperator.ts

@@ -0,0 +1,11 @@
+import { ShaderDefineExpression } from '../shaderDefineExpression';
+
+/** @hidden */
+export class ShaderDefineOrOperator extends ShaderDefineExpression {
+    public leftOperand: ShaderDefineExpression;
+    public rightOperand: ShaderDefineExpression;
+
+    public isTrue(preprocessors: { [key: string]: string }): boolean {
+        return this.leftOperand.isTrue(preprocessors) || this.rightOperand.isTrue(preprocessors);
+    }
+}

+ 2 - 0
src/Engines/Processors/Expressions/index.ts

@@ -0,0 +1,2 @@
+export * from "./shaderDefineExpression";
+export * from "./Operators/index";

+ 6 - 0
src/Engines/Processors/Expressions/shaderDefineExpression.ts

@@ -0,0 +1,6 @@
+/** @hidden */
+export class ShaderDefineExpression {
+    public isTrue(preprocessors: { [key: string]: string }): boolean {
+        return true;
+    }
+}

+ 7 - 0
src/Engines/Processors/iShaderProcessor.ts

@@ -0,0 +1,7 @@
+/** @hidden */
+export interface IShaderProcessor {
+    attributeProcessor?: (attribute: string) => string;
+    varyingProcessor?: (varying: string, isFragment: boolean) => string;
+    preProcessor?: (code: string, defines: string[], isFragment: boolean) => string;
+    postProcessor?: (code: string, defines: string[], isFragment: boolean) => string;
+}

+ 8 - 0
src/Engines/Processors/index.ts

@@ -0,0 +1,8 @@
+export * from "./iShaderProcessor";
+export * from "./Expressions/index";
+export * from "./shaderCodeConditionNode";
+export * from "./shaderCodeCursor";
+export * from "./shaderCodeNode";
+export * from "./shaderCodeTestNode";
+export * from "./shaderProcessingOptions";
+export * from "./shaderProcessor";

+ 17 - 0
src/Engines/Processors/shaderCodeConditionNode.ts

@@ -0,0 +1,17 @@
+import { ShaderCodeNode } from './shaderCodeNode';
+import { ProcessingOptions } from './shaderProcessingOptions';
+
+/** @hidden */
+export class ShaderCodeConditionNode extends ShaderCodeNode {
+    process(preprocessors: { [key: string]: string }, options: ProcessingOptions) {
+        for (var index = 0; index < this.children.length; index++) {
+            let node = this.children[index];
+
+            if (node.isValid(preprocessors)) {
+                return node.process(preprocessors, options);
+            }
+        }
+
+        return "";
+    }
+}

+ 13 - 0
src/Engines/Processors/shaderCodeCursor.ts

@@ -0,0 +1,13 @@
+/** @hidden */
+export class ShaderCodeCursor {
+    lines: string[];
+    lineIndex: number;
+
+    get currentLine(): string {
+        return this.lines[this.lineIndex].trim();
+    }
+
+    get canRead(): boolean {
+        return this.lineIndex < this.lines.length - 1;
+    }
+}

+ 44 - 0
src/Engines/Processors/shaderCodeNode.ts

@@ -0,0 +1,44 @@
+import { ProcessingOptions } from './shaderProcessingOptions';
+
+/** @hidden */
+export class ShaderCodeNode {
+    line: string;
+    children: ShaderCodeNode[] = [];
+    additionalDefineKey?: string;
+    additionalDefineValue?: string;
+
+    isValid(preprocessors: { [key: string]: string }): boolean {
+        return true;
+    }
+
+    process(preprocessors: { [key: string]: string }, options: ProcessingOptions): string {
+        let result = "";
+        if (this.line) {
+            let value: string = this.line;
+            let processor = options.processor;
+            if (processor) {
+                if (processor.attributeProcessor && this._lineStartsWith("attribute")) {
+                    value = processor.attributeProcessor(this.line);
+                } else if (processor.varyingProcessor && this._lineStartsWith("varying")) {
+                    value = processor.varyingProcessor(this.line, options.isFragment);
+                }
+            }
+
+            result += value + "\r\n";
+        }
+
+        this.children.forEach((child) => {
+            result += child.process(preprocessors, options);
+        });
+
+        if (this.additionalDefineKey) {
+            preprocessors[this.additionalDefineKey] = this.additionalDefineValue || "true";
+        }
+
+        return result;
+    }
+
+    private _lineStartsWith(prefix: string) {
+        return (this.line.indexOf(prefix) === 0);
+    }
+}

+ 11 - 0
src/Engines/Processors/shaderCodeTestNode.ts

@@ -0,0 +1,11 @@
+import { ShaderCodeNode } from './shaderCodeNode';
+import { ShaderDefineExpression } from './Expressions/shaderDefineExpression';
+
+/** @hidden */
+export class ShaderCodeTestNode extends ShaderCodeNode {
+    public testExpression: ShaderDefineExpression;
+
+    public isValid(preprocessors: { [key: string]: string }) {
+        return this.testExpression.isTrue(preprocessors);
+    }
+}

+ 14 - 0
src/Engines/Processors/shaderProcessingOptions.ts

@@ -0,0 +1,14 @@
+import { IShaderProcessor } from './iShaderProcessor';
+
+/** @hidden */
+export interface ProcessingOptions {
+    defines: string;
+    indexParameters: any;
+    isFragment: boolean;
+    shouldUseHighPrecisionShader: boolean;
+    supportsUniformBuffers: boolean;
+    shadersRepository: string;
+    includesShadersStore: { [key: string]: string };
+    processor?: IShaderProcessor;
+    version: string;
+}

+ 337 - 0
src/Engines/Processors/shaderProcessor.ts

@@ -0,0 +1,337 @@
+import { Tools } from '../../Misc/tools';
+import { ShaderCodeNode } from './shaderCodeNode';
+import { ShaderCodeCursor } from './shaderCodeCursor';
+import { ShaderCodeConditionNode } from './shaderCodeConditionNode';
+import { ShaderCodeTestNode } from './shaderCodeTestNode';
+import { ShaderDefineIsDefinedOperator } from './Expressions/Operators/shaderDefineIsDefinedOperator';
+import { ShaderDefineOrOperator } from './Expressions/Operators/shaderDefineOrOperator';
+import { ShaderDefineAndOperator } from './Expressions/Operators/shaderDefineAndOperator';
+import { ShaderDefineExpression } from './Expressions/shaderDefineExpression';
+import { ShaderDefineArithmeticOperator } from './Expressions/Operators/shaderDefineArithmeticOperator';
+import { ProcessingOptions } from './shaderProcessingOptions';
+
+/** @hidden */
+export class ShaderProcessor {
+    public static Process(sourceCode: string, options: ProcessingOptions, callback: (migratedCode: string) => void) {
+        this._ProcessIncludes(sourceCode, options, (codeWithIncludes) => {
+            let migratedCode = this._ProcessShaderConversion(codeWithIncludes, options);
+            callback(migratedCode);
+        });
+    }
+
+    private static _ProcessPrecision(source: string, options: ProcessingOptions): string {
+        const shouldUseHighPrecisionShader = options.shouldUseHighPrecisionShader;
+
+        if (source.indexOf("precision highp float") === -1) {
+            if (!shouldUseHighPrecisionShader) {
+                source = "precision mediump float;\n" + source;
+            } else {
+                source = "precision highp float;\n" + source;
+            }
+        } else {
+            if (!shouldUseHighPrecisionShader) { // Moving highp to mediump
+                source = source.replace("precision highp float", "precision mediump float");
+            }
+        }
+
+        return source;
+    }
+
+    private static _ExtractOperation(expression: string) {
+        let regex = /defined\((.+)\)/;
+
+        let match = regex.exec(expression);
+
+        if (match && match.length) {
+            return new ShaderDefineIsDefinedOperator(match[1].trim(), expression[0] === "!");
+        }
+
+        let operators = ["==", ">=", "<=", "<", ">"];
+        let operator = "";
+        let indexOperator = 0;
+
+        for (operator of operators) {
+            indexOperator = expression.indexOf(operator);
+
+            if (indexOperator > -1) {
+                break;
+            }
+        }
+
+        if (indexOperator === -1) {
+            return new ShaderDefineIsDefinedOperator(expression);
+        }
+
+        let define = expression.substring(0, indexOperator).trim();
+        let value = expression.substring(indexOperator + operator.length).trim();
+
+        return new ShaderDefineArithmeticOperator(define, operator, value);
+    }
+
+    private static _BuildSubExpression(expression: string): ShaderDefineExpression {
+        let indexOr = expression.indexOf("||");
+        if (indexOr === -1) {
+            let indexAnd = expression.indexOf("&&");
+            if (indexAnd > -1) {
+                let andOperator = new ShaderDefineAndOperator();
+                let leftPart = expression.substring(0, indexAnd).trim();
+                let rightPart = expression.substring(indexAnd + 2).trim();
+
+                andOperator.leftOperand = this._BuildSubExpression(leftPart);
+                andOperator.rightOperand = this._BuildSubExpression(rightPart);
+
+                return andOperator;
+            } else {
+                return this._ExtractOperation(expression);
+            }
+        } else {
+            let orOperator = new ShaderDefineOrOperator();
+            let leftPart = expression.substring(0, indexOr).trim();
+            let rightPart = expression.substring(indexOr + 2).trim();
+
+            orOperator.leftOperand = this._BuildSubExpression(leftPart);
+            orOperator.rightOperand = this._BuildSubExpression(rightPart);
+
+            return orOperator;
+        }
+    }
+
+    private static _BuildExpression(line: string, start: number): ShaderCodeTestNode {
+        let node = new ShaderCodeTestNode();
+        let command = line.substring(0, start);
+        let expression = line.substring(start).trim();
+
+        if (command === "#ifdef") {
+            node.testExpression = new ShaderDefineIsDefinedOperator(expression);
+        } else if (command === "#ifndef") {
+            node.testExpression = new ShaderDefineIsDefinedOperator(expression, true);
+        } else {
+            node.testExpression = this._BuildSubExpression(expression);
+        }
+
+        return node;
+    }
+
+    private static _MoveCursorWithinIf(cursor: ShaderCodeCursor, rootNode: ShaderCodeConditionNode, ifNode: ShaderCodeNode) {
+        let line = cursor.currentLine;
+        while (this._MoveCursor(cursor, ifNode)) {
+            line = cursor.currentLine;
+            let first5 = line.substring(0, 5).toLowerCase();
+
+            if (first5 === "#else") {
+                let elseNode = new ShaderCodeNode();
+                rootNode.children.push(elseNode);
+                this._MoveCursor(cursor, elseNode);
+                return;
+            } else if (first5 === "#elif") {
+                let elifNode = this._BuildExpression(line, 5);
+
+                rootNode.children.push(elifNode);
+                ifNode = elifNode;
+            }
+        }
+    }
+
+    private static _MoveCursor(cursor: ShaderCodeCursor, rootNode: ShaderCodeNode): boolean {
+        while (cursor.canRead) {
+            cursor.lineIndex++;
+            let line = cursor.currentLine;
+            const keywords = /(#ifdef)|(#else)|(#elif)|(#endif)|(#ifndef)|(#if)/;
+            const matches = keywords.exec(line);
+
+            if (matches && matches.length) {
+                let keyword = matches[0];
+
+                switch (keyword) {
+                    case "#ifdef": {
+                        let newRootNode = new ShaderCodeConditionNode();
+                        rootNode.children.push(newRootNode);
+
+                        let ifNode = this._BuildExpression(line, 6);
+                        newRootNode.children.push(ifNode);
+                        this._MoveCursorWithinIf(cursor, newRootNode, ifNode);
+                        break;
+                    }
+                    case "#else":
+                    case "#elif":
+                        return true;
+                    case "#endif":
+                        return false;
+                    case "#ifndef": {
+                        let newRootNode = new ShaderCodeConditionNode();
+                        rootNode.children.push(newRootNode);
+
+                        let ifNode = this._BuildExpression(line, 7);
+                        newRootNode.children.push(ifNode);
+                        this._MoveCursorWithinIf(cursor, newRootNode, ifNode);
+                        break;
+                    }
+                    case "#if": {
+                        let newRootNode = new ShaderCodeConditionNode();
+                        let ifNode = this._BuildExpression(line, 3);
+                        rootNode.children.push(newRootNode);
+
+                        newRootNode.children.push(ifNode);
+                        this._MoveCursorWithinIf(cursor, newRootNode, ifNode);
+                        break;
+                    }
+                }
+            }
+            else {
+                let newNode = new ShaderCodeNode();
+                newNode.line = line;
+                rootNode.children.push(newNode);
+
+                // Detect additional defines
+                if (line[0] === "#" && line[1] === "d") {
+                    let split = line.replace(";", "").split(" ");
+                    newNode.additionalDefineKey = split[1];
+
+                    if (split.length === 3) {
+                        newNode.additionalDefineValue = split[2];
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    private static _EvaluatePreProcessors(sourceCode: string, preprocessors: { [key: string]: string }, options: ProcessingOptions): string {
+        const rootNode = new ShaderCodeNode();
+        let cursor = new ShaderCodeCursor();
+
+        cursor.lineIndex = -1;
+        cursor.lines = sourceCode.split("\n");
+
+        // Decompose
+        this._MoveCursor(cursor, rootNode);
+
+        // Recompose
+        return rootNode.process(preprocessors, options);
+    }
+
+    private static _ProcessShaderConversion(sourceCode: string, options: ProcessingOptions): string {
+
+        var preparedSourceCode = this._ProcessPrecision(sourceCode, options);
+
+        if (!options.processor) {
+            return preparedSourceCode;
+        }
+
+        // Already converted
+        if (preparedSourceCode.indexOf("#version 3") !== -1) {
+            return preparedSourceCode.replace("#version 300 es", "");
+        }
+
+        let defines = options.defines.split("\n");
+
+        let preprocessors: { [key: string]: string } = {};
+
+        for (var define of defines) {
+            let keyValue = define.replace("#define", "").replace(";", "").trim();
+            let split = keyValue.split(" ");
+            preprocessors[split[0]] = split.length > 1 ? split[1] : "";
+        }
+
+        preprocessors["GL_ES"] = "true";
+        preprocessors["__VERSION__"] = options.version;
+
+        if (options.processor.preProcessor) {
+            preparedSourceCode = options.processor.preProcessor(preparedSourceCode, defines, options.isFragment);
+        }
+
+        preparedSourceCode = this._EvaluatePreProcessors(preparedSourceCode, preprocessors, options);
+
+        // Add multiview setup to top of file when defined
+        if (options.processor.postProcessor) {
+            preparedSourceCode = options.processor.postProcessor(preparedSourceCode, defines, options.isFragment);
+        }
+
+        return preparedSourceCode;
+    }
+
+    private static _ProcessIncludes(sourceCode: string, options: ProcessingOptions, callback: (data: any) => void): void {
+        var regex = /#include<(.+)>(\((.*)\))*(\[(.*)\])*/g;
+        var match = regex.exec(sourceCode);
+
+        var returnValue = new String(sourceCode);
+
+        while (match != null) {
+            var includeFile = match[1];
+
+            // Uniform declaration
+            if (includeFile.indexOf("__decl__") !== -1) {
+                includeFile = includeFile.replace(/__decl__/, "");
+                if (options.supportsUniformBuffers) {
+                    includeFile = includeFile.replace(/Vertex/, "Ubo");
+                    includeFile = includeFile.replace(/Fragment/, "Ubo");
+                }
+                includeFile = includeFile + "Declaration";
+            }
+
+            if (options.includesShadersStore[includeFile]) {
+                // Substitution
+                var includeContent = options.includesShadersStore[includeFile];
+                if (match[2]) {
+                    var splits = match[3].split(",");
+
+                    for (var index = 0; index < splits.length; index += 2) {
+                        var source = new RegExp(splits[index], "g");
+                        var dest = splits[index + 1];
+
+                        includeContent = includeContent.replace(source, dest);
+                    }
+                }
+
+                if (match[4]) {
+                    var indexString = match[5];
+
+                    if (indexString.indexOf("..") !== -1) {
+                        var indexSplits = indexString.split("..");
+                        var minIndex = parseInt(indexSplits[0]);
+                        var maxIndex = parseInt(indexSplits[1]);
+                        var sourceIncludeContent = includeContent.slice(0);
+                        includeContent = "";
+
+                        if (isNaN(maxIndex)) {
+                            maxIndex = options.indexParameters[indexSplits[1]];
+                        }
+
+                        for (var i = minIndex; i < maxIndex; i++) {
+                            if (!options.supportsUniformBuffers) {
+                                // Ubo replacement
+                                sourceIncludeContent = sourceIncludeContent.replace(/light\{X\}.(\w*)/g, (str: string, p1: string) => {
+                                    return p1 + "{X}";
+                                });
+                            }
+                            includeContent += sourceIncludeContent.replace(/\{X\}/g, i.toString()) + "\n";
+                        }
+                    } else {
+                        if (!options.supportsUniformBuffers) {
+                            // Ubo replacement
+                            includeContent = includeContent.replace(/light\{X\}.(\w*)/g, (str: string, p1: string) => {
+                                return p1 + "{X}";
+                            });
+                        }
+                        includeContent = includeContent.replace(/\{X\}/g, indexString);
+                    }
+                }
+
+                // Replace
+                returnValue = returnValue.replace(match[0], includeContent);
+            } else {
+                var includeShaderUrl = options.shadersRepository + "ShadersInclude/" + includeFile + ".fx";
+
+                Tools.LoadFile(includeShaderUrl, (fileContent) => {
+                    options.includesShadersStore[includeFile] = fileContent as string;
+                    this._ProcessIncludes(<string>returnValue, options, callback);
+                });
+                return;
+            }
+
+            match = regex.exec(sourceCode);
+        }
+
+        callback(returnValue);
+    }
+}

+ 39 - 0
src/Engines/WebGL/webGL2ShaderProcessors.ts

@@ -0,0 +1,39 @@
+import { IShaderProcessor } from '../Processors/iShaderProcessor';
+
+/** @hidden */
+export class WebGL2ShaderProcessor implements IShaderProcessor {
+    public attributeProcessor(attribute: string) {
+        return attribute.replace("attribute", "in");
+    }
+
+    public varyingProcessor(varying: string, isFragment: boolean) {
+        return varying.replace("varying", isFragment ? "in" : "out");
+    }
+
+    public postProcessor(code: string, defines: string[], isFragment: boolean) {
+        const hasDrawBuffersExtension = code.search(/#extension.+GL_EXT_draw_buffers.+require/) !== -1;
+
+        // Remove extensions
+        var regex = /#extension.+(GL_OVR_multiview2|GL_OES_standard_derivatives|GL_EXT_shader_texture_lod|GL_EXT_frag_depth|GL_EXT_draw_buffers).+(enable|require)/g;
+        code = code.replace(regex, "");
+
+        // Replace instructions
+        code = code.replace(/texture2D\s*\(/g, "texture(");
+        if (isFragment) {
+            code = code.replace(/texture2DLodEXT\s*\(/g, "textureLod(");
+            code = code.replace(/textureCubeLodEXT\s*\(/g, "textureLod(");
+            code = code.replace(/textureCube\s*\(/g, "texture(");
+            code = code.replace(/gl_FragDepthEXT/g, "gl_FragDepth");
+            code = code.replace(/gl_FragColor/g, "glFragColor");
+            code = code.replace(/gl_FragData/g, "glFragData");
+            code = code.replace(/void\s+?main\s*\(/g, (hasDrawBuffersExtension ? "" : "out vec4 glFragColor;\n") + "void main(");
+        } else {
+            var hasMultiviewExtension = defines.indexOf("#define MULTIVIEW") !== -1;
+            if (hasMultiviewExtension) {
+                return "#extension GL_OVR_multiview2 : require\nlayout (num_views = 2) in;\n" + code;
+            }
+        }
+
+        return code;
+    }
+}

+ 11 - 3
src/Engines/engine.ts

@@ -31,6 +31,8 @@ import { WebGLPipelineContext } from './WebGL/webGLPipelineContext';
 import { IPipelineContext } from './IPipelineContext';
 import { DataBuffer } from '../Meshes/dataBuffer';
 import { WebGLDataBuffer } from '../Meshes/WebGL/webGLDataBuffer';
+import { IShaderProcessor } from './Processors/iShaderProcessor';
+import { WebGL2ShaderProcessor } from './WebGL/webGL2ShaderProcessors';
 
 declare type PostProcess = import("../PostProcesses/postProcess").PostProcess;
 declare type Texture = import("../Materials/Textures/texture").Texture;
@@ -288,9 +290,7 @@ export class Engine {
         }
     }
 
-    /**
-     * Hidden
-     */
+    /** @hidden */
     public static _TextureLoaders: IInternalTextureLoader[] = [];
 
     // Const statics
@@ -557,6 +557,9 @@ export class Engine {
 
     // Public members
 
+    /** @hidden */
+    public _shaderProcessor: IShaderProcessor;
+
     /**
      * Gets or sets a boolean that indicates if textures must be forced to power of 2 size even if not required
      */
@@ -1254,6 +1257,11 @@ export class Engine {
             this.initWebVR();
         }
 
+        // Shader processor
+        if (this.webGLVersion > 1) {
+            this._shaderProcessor = new WebGL2ShaderProcessor();
+        }
+
         // Detect if we are running on a faulty buggy OS.
         this._badOS = /iPad/i.test(navigator.userAgent) || /iPhone/i.test(navigator.userAgent);
 

+ 2 - 1
src/Engines/index.ts

@@ -4,4 +4,5 @@ export * from "./engineStore";
 export * from "./nullEngine";
 export * from "./Extensions/index";
 export * from "./IPipelineContext";
-export * from "./WebGL/webGLPipelineContext";
+export * from "./WebGL/webGLPipelineContext";
+export * from "./WebGL/webGL2ShaderProcessors";

+ 29 - 186
src/Materials/effect.ts

@@ -7,6 +7,7 @@ import { Logger } from "../Misc/logger";
 import { IDisposable } from '../scene';
 import { IPipelineContext } from '../Engines/IPipelineContext';
 import { DataBuffer } from '../Meshes/dataBuffer';
+import { ShaderProcessor } from '../Engines/Processors/shaderProcessor';
 
 declare type Engine = import("../Engines/engine").Engine;
 declare type InternalTexture = import("../Materials/Textures/internalTexture").InternalTexture;
@@ -78,7 +79,7 @@ export class EffectFallbacks {
     }
 
     /**
-     * Removes the defines that shoould be removed when falling back.
+     * Removes the defines that should be removed when falling back.
      * @param currentDefines defines the current define statements for the shader.
      * @param effect defines the current effect we try to compile
      * @returns The resulting defines with defines of the current rank removed.
@@ -333,8 +334,6 @@ export class Effect implements IDisposable {
             if (!vertexSource) {
                 vertexSource = baseName.vertexElement;
             }
-        } else if (baseName.vertexSource) {
-            vertexSource = "source:" + baseName.vertexSource;
         } else {
             vertexSource = baseName.vertex || baseName;
         }
@@ -345,31 +344,38 @@ export class Effect implements IDisposable {
             if (!fragmentSource) {
                 fragmentSource = baseName.fragmentElement;
             }
-        } else if (baseName.fragmentSource) {
-            fragmentSource = "source:" + baseName.fragmentSource;
         } else {
             fragmentSource = baseName.fragment || baseName;
         }
 
+        let processorOptions = {
+            defines: this.defines,
+            indexParameters: this._indexParameters,
+            isFragment: false,
+            shouldUseHighPrecisionShader: this._engine._shouldUseHighPrecisionShader,
+            processor: this._engine._shaderProcessor,
+            supportsUniformBuffers: this._engine.supportsUniformBuffers,
+            shadersRepository: Effect.ShadersRepository,
+            includesShadersStore: Effect.IncludesShadersStore,
+            version: (this._engine.webGLVersion * 100).toString()
+        };
+
         this._loadVertexShader(vertexSource, (vertexCode) => {
-            this._processIncludes(vertexCode, (vertexCodeWithIncludes) => {
-                this._processShaderConversion(vertexCodeWithIncludes, false, (migratedVertexCode) => {
-                    this._loadFragmentShader(fragmentSource, (fragmentCode) => {
-                        this._processIncludes(fragmentCode, (fragmentCodeWithIncludes) => {
-                            this._processShaderConversion(fragmentCodeWithIncludes, true, (migratedFragmentCode) => {
-                                if (baseName) {
-                                    var vertex = baseName.vertexElement || baseName.vertex || baseName;
-                                    var fragment = baseName.fragmentElement || baseName.fragment || baseName;
-
-                                    this._vertexSourceCode = "#define SHADER_NAME vertex:" + vertex + "\n" + migratedVertexCode;
-                                    this._fragmentSourceCode = "#define SHADER_NAME fragment:" + fragment + "\n" + migratedFragmentCode;
-                                } else {
-                                    this._vertexSourceCode = migratedVertexCode;
-                                    this._fragmentSourceCode = migratedFragmentCode;
-                                }
-                                this._prepareEffect();
-                            });
-                        });
+            this._loadFragmentShader(fragmentSource, (fragmentCode) => {
+                ShaderProcessor.Process(vertexCode, processorOptions, (migratedVertexCode) => {
+                    processorOptions.isFragment = true;
+                    ShaderProcessor.Process(fragmentCode, processorOptions, (migratedFragmentCode) => {
+                        if (baseName) {
+                            var vertex = baseName.vertexElement || baseName.vertex || baseName;
+                            var fragment = baseName.fragmentElement || baseName.fragment || baseName;
+
+                            this._vertexSourceCode = "#define SHADER_NAME vertex:" + vertex + "\n" + migratedVertexCode;
+                            this._fragmentSourceCode = "#define SHADER_NAME fragment:" + fragment + "\n" + migratedFragmentCode;
+                        } else {
+                            this._vertexSourceCode = migratedVertexCode;
+                            this._fragmentSourceCode = migratedFragmentCode;
+                        }
+                        this._prepareEffect();
                     });
                 });
             });
@@ -524,11 +530,6 @@ export class Effect implements IDisposable {
             }
         }
 
-        if (vertex.substr(0, 7) === "source:") {
-            callback(vertex.substr(7));
-            return;
-        }
-
         // Base64 encoded ?
         if (vertex.substr(0, 7) === "base64:") {
             var vertexBinary = window.atob(vertex.substr(7));
@@ -565,11 +566,6 @@ export class Effect implements IDisposable {
             }
         }
 
-        if (fragment.substr(0, 7) === "source:") {
-            callback(fragment.substr(7));
-            return;
-        }
-
         // Base64 encoded ?
         if (fragment.substr(0, 7) === "base64:") {
             var fragmentBinary = window.atob(fragment.substr(7));
@@ -630,159 +626,6 @@ export class Effect implements IDisposable {
         }
     }
 
-    private _processShaderConversion(sourceCode: string, isFragment: boolean, callback: (data: any) => void): void {
-
-        var preparedSourceCode = this._processPrecision(sourceCode);
-
-        if (this._engine.webGLVersion == 1) {
-            callback(preparedSourceCode);
-            return;
-        }
-
-        // Already converted
-        if (preparedSourceCode.indexOf("#version 3") !== -1) {
-            callback(preparedSourceCode.replace("#version 300 es", ""));
-            return;
-        }
-
-        var hasDrawBuffersExtension = preparedSourceCode.search(/#extension.+GL_EXT_draw_buffers.+require/) !== -1;
-
-        // Remove extensions
-        // #extension GL_OES_standard_derivatives : enable
-        // #extension GL_EXT_shader_texture_lod : enable
-        // #extension GL_EXT_frag_depth : enable
-        // #extension GL_EXT_draw_buffers : require
-        var regex = /#extension.+(GL_OVR_multiview2|GL_OES_standard_derivatives|GL_EXT_shader_texture_lod|GL_EXT_frag_depth|GL_EXT_draw_buffers).+(enable|require)/g;
-        var result = preparedSourceCode.replace(regex, "");
-
-        // Migrate to GLSL v300
-        result = result.replace(/varying(?![\n\r])\s/g, isFragment ? "in " : "out ");
-        result = result.replace(/attribute[ \t]/g, "in ");
-        result = result.replace(/[ \t]attribute/g, " in");
-
-        result = result.replace(/texture2D\s*\(/g, "texture(");
-        if (isFragment) {
-            result = result.replace(/texture2DLodEXT\s*\(/g, "textureLod(");
-            result = result.replace(/textureCubeLodEXT\s*\(/g, "textureLod(");
-            result = result.replace(/textureCube\s*\(/g, "texture(");
-            result = result.replace(/gl_FragDepthEXT/g, "gl_FragDepth");
-            result = result.replace(/gl_FragColor/g, "glFragColor");
-            result = result.replace(/gl_FragData/g, "glFragData");
-            result = result.replace(/void\s+?main\s*\(/g, (hasDrawBuffersExtension ? "" : "out vec4 glFragColor;\n") + "void main(");
-        }
-
-        // Add multiview setup to top of file when defined
-        var hasMultiviewExtension = this.defines.indexOf("#define MULTIVIEW\n") !== -1;
-        if (hasMultiviewExtension && !isFragment) {
-            result = "#extension GL_OVR_multiview2 : require\nlayout (num_views = 2) in;\n" + result;
-        }
-
-        callback(result);
-    }
-
-    private _processIncludes(sourceCode: string, callback: (data: any) => void): void {
-        var regex = /#include<(.+)>(\((.*)\))*(\[(.*)\])*/g;
-        var match = regex.exec(sourceCode);
-
-        var returnValue = new String(sourceCode);
-
-        while (match != null) {
-            var includeFile = match[1];
-
-            // Uniform declaration
-            if (includeFile.indexOf("__decl__") !== -1) {
-                includeFile = includeFile.replace(/__decl__/, "");
-                if (this._engine.supportsUniformBuffers) {
-                    includeFile = includeFile.replace(/Vertex/, "Ubo");
-                    includeFile = includeFile.replace(/Fragment/, "Ubo");
-                }
-                includeFile = includeFile + "Declaration";
-            }
-
-            if (Effect.IncludesShadersStore[includeFile]) {
-                // Substitution
-                var includeContent = Effect.IncludesShadersStore[includeFile];
-                if (match[2]) {
-                    var splits = match[3].split(",");
-
-                    for (var index = 0; index < splits.length; index += 2) {
-                        var source = new RegExp(splits[index], "g");
-                        var dest = splits[index + 1];
-
-                        includeContent = includeContent.replace(source, dest);
-                    }
-                }
-
-                if (match[4]) {
-                    var indexString = match[5];
-
-                    if (indexString.indexOf("..") !== -1) {
-                        var indexSplits = indexString.split("..");
-                        var minIndex = parseInt(indexSplits[0]);
-                        var maxIndex = parseInt(indexSplits[1]);
-                        var sourceIncludeContent = includeContent.slice(0);
-                        includeContent = "";
-
-                        if (isNaN(maxIndex)) {
-                            maxIndex = this._indexParameters[indexSplits[1]];
-                        }
-
-                        for (var i = minIndex; i < maxIndex; i++) {
-                            if (!this._engine.supportsUniformBuffers) {
-                                // Ubo replacement
-                                sourceIncludeContent = sourceIncludeContent.replace(/light\{X\}.(\w*)/g, (str: string, p1: string) => {
-                                    return p1 + "{X}";
-                                });
-                            }
-                            includeContent += sourceIncludeContent.replace(/\{X\}/g, i.toString()) + "\n";
-                        }
-                    } else {
-                        if (!this._engine.supportsUniformBuffers) {
-                            // Ubo replacement
-                            includeContent = includeContent.replace(/light\{X\}.(\w*)/g, (str: string, p1: string) => {
-                                return p1 + "{X}";
-                            });
-                        }
-                        includeContent = includeContent.replace(/\{X\}/g, indexString);
-                    }
-                }
-
-                // Replace
-                returnValue = returnValue.replace(match[0], includeContent);
-            } else {
-                var includeShaderUrl = Effect.ShadersRepository + "ShadersInclude/" + includeFile + ".fx";
-
-                this._engine._loadFile(includeShaderUrl, (fileContent) => {
-                    Effect.IncludesShadersStore[includeFile] = fileContent as string;
-                    this._processIncludes(<string>returnValue, callback);
-                });
-                return;
-            }
-
-            match = regex.exec(sourceCode);
-        }
-
-        callback(returnValue);
-    }
-
-    private _processPrecision(source: string): string {
-        const shouldUseHighPrecisionShader = this._engine._shouldUseHighPrecisionShader;
-
-        if (source.indexOf("precision highp float") === -1) {
-            if (!shouldUseHighPrecisionShader) {
-                source = "precision mediump float;\n" + source;
-            } else {
-                source = "precision highp float;\n" + source;
-            }
-        } else {
-            if (!shouldUseHighPrecisionShader) { // Moving highp to mediump
-                source = source.replace("precision highp float", "precision mediump float");
-            }
-        }
-
-        return source;
-    }
-
     /**
      * Recompiles the webGL program
      * @param vertexSourceCode The source code for the vertex shader.

+ 1 - 1
src/Shaders/ShadersInclude/lightFragment.fx

@@ -1,5 +1,5 @@
 #ifdef LIGHT{X}
-    #if defined(SHADOWONLY) || (defined(LIGHTMAP) && defined(LIGHTMAPEXCLUDED{X}) && defined(LIGHTMAPNOSPECULAR{X}))
+    #if defined(SHADOWONLY) || defined(LIGHTMAP) && defined(LIGHTMAPEXCLUDED{X}) && defined(LIGHTMAPNOSPECULAR{X})
         //No light calculation
     #else
         #ifdef PBR

+ 1 - 3
src/Shaders/vrMultiviewToSingleview.fragment.fx

@@ -1,6 +1,4 @@
-#ifdef GL_ES
-	precision mediump sampler2DArray;
-#endif
+precision mediump sampler2DArray;
 
 varying vec2 vUV;
 uniform sampler2DArray multiviewSampler;