소스 검색

Merge pull request #6794 from BabylonJS/master

Nightly
David Catuhe 6 년 전
부모
커밋
a19c0b9cbb
41개의 변경된 파일155091개의 추가작업 그리고 148633개의 파일을 삭제
  1. 1 1
      .vscode/launch.json
  2. 61 0
      Playground/babylon.d.txt
  3. 1862 765
      Playground/babylonWebGPU.d.txt
  4. 152204 147754
      Playground/js/babylonWebGpu.max.js
  5. 1 1
      Playground/js/babylonWebGpu.max.js.map
  6. 1 2
      dist/gui/readme.md
  7. 63 0
      dist/preview release/babylon.d.ts
  8. 1 1
      dist/preview release/babylon.js
  9. 279 58
      dist/preview release/babylon.max.js
  10. 1 1
      dist/preview release/babylon.max.js.map
  11. 135 0
      dist/preview release/babylon.module.d.ts
  12. 63 0
      dist/preview release/documentation.d.ts
  13. 1 1
      dist/preview release/nodeEditor/babylon.nodeEditor.d.ts
  14. 7 7
      dist/preview release/nodeEditor/babylon.nodeEditor.js
  15. 10 3
      dist/preview release/nodeEditor/babylon.nodeEditor.max.js
  16. 1 1
      dist/preview release/nodeEditor/babylon.nodeEditor.max.js.map
  17. 3 2
      dist/preview release/nodeEditor/babylon.nodeEditor.module.d.ts
  18. 1 1
      dist/preview release/packagesSizeBaseLine.json
  19. 135 0
      dist/preview release/viewer/babylon.module.d.ts
  20. 19 15
      dist/preview release/viewer/babylon.viewer.js
  21. 1 1
      dist/preview release/viewer/babylon.viewer.max.js
  22. 1 1
      nodeEditor/public/index.js
  23. 4 1
      nodeEditor/src/blockTools.ts
  24. 8 1
      nodeEditor/src/components/diagram/generic/genericNodeModel.tsx
  25. 1 1
      nodeEditor/src/components/nodeList/nodeListComponent.tsx
  26. 1 2
      src/Materials/Node/Blocks/Dual/fogBlock.ts
  27. 2 9
      src/Materials/Node/Blocks/Dual/lightBlock.ts
  28. 2 0
      src/Materials/Node/Blocks/Dual/textureBlock.ts
  29. 2 1
      src/Materials/Node/Blocks/Fragment/index.ts
  30. 182 0
      src/Materials/Node/Blocks/Fragment/perturbNormalBlock.ts
  31. 3 0
      src/Materials/Node/nodeMaterial.ts
  32. 1 1
      src/Materials/Node/nodeMaterialBlock.ts
  33. 19 0
      src/Materials/Node/nodeMaterialBuildState.ts
  34. 3 0
      src/Materials/Node/nodeMaterialBuildStateSharedData.ts
  35. 1 1
      src/Meshes/mesh.ts
  36. 5 0
      src/Shaders/ShadersInclude/bumpFragmentFunctions.fx
  37. BIN
      tests/validation/LogoV3.png
  38. BIN
      tests/validation/ReferenceImages/node-material3.png
  39. 5 0
      tests/validation/config.json
  40. 1 1
      tests/validation/index.css
  41. BIN
      tests/validation/logo.png

+ 1 - 1
.vscode/launch.json

@@ -2,7 +2,7 @@
     "version": "2.0.0",
     "configurations": [
         {
-            "name": "Node Material Editor (Chrome)",
+            "name": "Launch Node Material Editor (Chrome)",
             "type": "chrome",
             "request": "launch",
             "url": "http://localhost:1338/nodeEditor/public/index-local.html",

+ 61 - 0
Playground/babylon.d.txt

@@ -51445,6 +51445,8 @@ declare module BABYLON {
         SAMPLER3DGREENDEPTH: boolean;
         SAMPLER3DBGRMAP: boolean;
         IMAGEPROCESSINGPOSTPROCESS: boolean;
+        /** MISC. */
+        BUMPDIRECTUV: number;
         constructor();
         setValue(name: string, value: boolean): void;
     }
@@ -51905,6 +51907,12 @@ declare module BABYLON {
             [key: string]: string;
         };
         /**
+         * Gets the list of emitted extensions
+         */
+        extensions: {
+            [key: string]: string;
+        };
+        /**
          * Gets the target of the compilation state
          */
         target: NodeMaterialBlockTargets;
@@ -51939,6 +51947,7 @@ declare module BABYLON {
         /** @hidden */
private _getFreeDefineName(prefix: string): string;
         /** @hidden */
private _excludeVariableName(name: string): void;
         /** @hidden */
private _getGLType(type: NodeMaterialBlockConnectionPointTypes): string;
+        /** @hidden */
private _emitExtension(name: string, extension: string): void;
         /** @hidden */
private _emitFunction(name: string, code: string, comments: string): void;
         /** @hidden */
private _emitCodeFromInclude(includeName: string, comments: string, options?: {
             replaceStrings?: {
@@ -52667,6 +52676,58 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * Block used to pertub normals based on a normal map
+     */
+    export class PerturbNormalBlock extends NodeMaterialBlock {
+        private _tangentSpaceParameterName;
+        /** Gets or sets a boolean indicating that normal should be inverted on X axis */
+        invertX: boolean;
+        /** Gets or sets a boolean indicating that normal should be inverted on Y axis */
+        invertY: boolean;
+        /**
+         * Create a new PerturbNormalBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world position input component
+         */
+        readonly worldPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the world normal input component
+         */
+        readonly worldNormal: NodeMaterialConnectionPoint;
+        /**
+         * Gets the uv input component
+         */
+        readonly uv: NodeMaterialConnectionPoint;
+        /**
+        * Gets the normal map color input component
+        */
+        readonly normalMapColor: NodeMaterialConnectionPoint;
+        /**
+        * Gets the strength input component
+        */
+        readonly strength: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+        protected _dumpPropertiesCode(): string;
+        serialize(): any;
private _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
+    }
+}
+declare module BABYLON {
+    /**
      * Block used to add support for scene fog
      */
     export class FogBlock extends NodeMaterialBlock {

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1862 - 765
Playground/babylonWebGPU.d.txt


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 152204 - 147754
Playground/js/babylonWebGpu.max.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
Playground/js/babylonWebGpu.max.js.map


+ 1 - 2
dist/gui/readme.md

@@ -26,8 +26,7 @@ If using TypeScript, the typing needs to be added to tsconfig.json:
     ....
     "types": [
         "babylonjs",
-        "babylonjs-gui",
-        "angularFTW"
+        "babylonjs-gui"
     ],
     ....
 ```

+ 63 - 0
dist/preview release/babylon.d.ts

@@ -52237,6 +52237,8 @@ declare module BABYLON {
         SAMPLER3DGREENDEPTH: boolean;
         SAMPLER3DBGRMAP: boolean;
         IMAGEPROCESSINGPOSTPROCESS: boolean;
+        /** MISC. */
+        BUMPDIRECTUV: number;
         constructor();
         setValue(name: string, value: boolean): void;
     }
@@ -52700,6 +52702,12 @@ declare module BABYLON {
             [key: string]: string;
         };
         /**
+         * Gets the list of emitted extensions
+         */
+        extensions: {
+            [key: string]: string;
+        };
+        /**
          * Gets the target of the compilation state
          */
         target: NodeMaterialBlockTargets;
@@ -52746,6 +52754,8 @@ declare module BABYLON {
         /** @hidden */
         _getGLType(type: NodeMaterialBlockConnectionPointTypes): string;
         /** @hidden */
+        _emitExtension(name: string, extension: string): void;
+        /** @hidden */
         _emitFunction(name: string, code: string, comments: string): void;
         /** @hidden */
         _emitCodeFromInclude(includeName: string, comments: string, options?: {
@@ -53496,6 +53506,59 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * Block used to pertub normals based on a normal map
+     */
+    export class PerturbNormalBlock extends NodeMaterialBlock {
+        private _tangentSpaceParameterName;
+        /** Gets or sets a boolean indicating that normal should be inverted on X axis */
+        invertX: boolean;
+        /** Gets or sets a boolean indicating that normal should be inverted on Y axis */
+        invertY: boolean;
+        /**
+         * Create a new PerturbNormalBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world position input component
+         */
+        readonly worldPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the world normal input component
+         */
+        readonly worldNormal: NodeMaterialConnectionPoint;
+        /**
+         * Gets the uv input component
+         */
+        readonly uv: NodeMaterialConnectionPoint;
+        /**
+        * Gets the normal map color input component
+        */
+        readonly normalMapColor: NodeMaterialConnectionPoint;
+        /**
+        * Gets the strength input component
+        */
+        readonly strength: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+        protected _dumpPropertiesCode(): string;
+        serialize(): any;
+        _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
+    }
+}
+declare module BABYLON {
+    /**
      * Block used to add support for scene fog
      */
     export class FogBlock extends NodeMaterialBlock {

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/preview release/babylon.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 279 - 58
dist/preview release/babylon.max.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/preview release/babylon.max.js.map


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

@@ -54679,6 +54679,8 @@ declare module "babylonjs/Materials/Node/nodeMaterial" {
         SAMPLER3DGREENDEPTH: boolean;
         SAMPLER3DBGRMAP: boolean;
         IMAGEPROCESSINGPOSTPROCESS: boolean;
+        /** MISC. */
+        BUMPDIRECTUV: number;
         constructor();
         setValue(name: string, value: boolean): void;
     }
@@ -55161,6 +55163,12 @@ declare module "babylonjs/Materials/Node/nodeMaterialBuildState" {
             [key: string]: string;
         };
         /**
+         * Gets the list of emitted extensions
+         */
+        extensions: {
+            [key: string]: string;
+        };
+        /**
          * Gets the target of the compilation state
          */
         target: NodeMaterialBlockTargets;
@@ -55207,6 +55215,8 @@ declare module "babylonjs/Materials/Node/nodeMaterialBuildState" {
         /** @hidden */
         _getGLType(type: NodeMaterialBlockConnectionPointTypes): string;
         /** @hidden */
+        _emitExtension(name: string, extension: string): void;
+        /** @hidden */
         _emitFunction(name: string, code: string, comments: string): void;
         /** @hidden */
         _emitCodeFromInclude(includeName: string, comments: string, options?: {
@@ -56027,10 +56037,72 @@ declare module "babylonjs/Materials/Node/Blocks/Fragment/imageProcessingBlock" {
         protected _buildBlock(state: NodeMaterialBuildState): this;
     }
 }
+declare module "babylonjs/Materials/Node/Blocks/Fragment/perturbNormalBlock" {
+    import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
+    import { NodeMaterialBuildState } from "babylonjs/Materials/Node/nodeMaterialBuildState";
+    import { NodeMaterialConnectionPoint } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint";
+    import { NodeMaterial, NodeMaterialDefines } from "babylonjs/Materials/Node/nodeMaterial";
+    import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
+    import { Effect } from "babylonjs/Materials/effect";
+    import { Mesh } from "babylonjs/Meshes/mesh";
+    import { Scene } from "babylonjs/scene";
+    /**
+     * Block used to pertub normals based on a normal map
+     */
+    export class PerturbNormalBlock extends NodeMaterialBlock {
+        private _tangentSpaceParameterName;
+        /** Gets or sets a boolean indicating that normal should be inverted on X axis */
+        invertX: boolean;
+        /** Gets or sets a boolean indicating that normal should be inverted on Y axis */
+        invertY: boolean;
+        /**
+         * Create a new PerturbNormalBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world position input component
+         */
+        readonly worldPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the world normal input component
+         */
+        readonly worldNormal: NodeMaterialConnectionPoint;
+        /**
+         * Gets the uv input component
+         */
+        readonly uv: NodeMaterialConnectionPoint;
+        /**
+        * Gets the normal map color input component
+        */
+        readonly normalMapColor: NodeMaterialConnectionPoint;
+        /**
+        * Gets the strength input component
+        */
+        readonly strength: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+        protected _dumpPropertiesCode(): string;
+        serialize(): any;
+        _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
+    }
+}
 declare module "babylonjs/Materials/Node/Blocks/Fragment/index" {
     export * from "babylonjs/Materials/Node/Blocks/Fragment/fragmentOutputBlock";
     export * from "babylonjs/Materials/Node/Blocks/Fragment/alphaTestBlock";
     export * from "babylonjs/Materials/Node/Blocks/Fragment/imageProcessingBlock";
+    export * from "babylonjs/Materials/Node/Blocks/Fragment/perturbNormalBlock";
 }
 declare module "babylonjs/Materials/Node/Blocks/Dual/fogBlock" {
     import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
@@ -117738,6 +117810,8 @@ declare module BABYLON {
         SAMPLER3DGREENDEPTH: boolean;
         SAMPLER3DBGRMAP: boolean;
         IMAGEPROCESSINGPOSTPROCESS: boolean;
+        /** MISC. */
+        BUMPDIRECTUV: number;
         constructor();
         setValue(name: string, value: boolean): void;
     }
@@ -118201,6 +118275,12 @@ declare module BABYLON {
             [key: string]: string;
         };
         /**
+         * Gets the list of emitted extensions
+         */
+        extensions: {
+            [key: string]: string;
+        };
+        /**
          * Gets the target of the compilation state
          */
         target: NodeMaterialBlockTargets;
@@ -118247,6 +118327,8 @@ declare module BABYLON {
         /** @hidden */
         _getGLType(type: NodeMaterialBlockConnectionPointTypes): string;
         /** @hidden */
+        _emitExtension(name: string, extension: string): void;
+        /** @hidden */
         _emitFunction(name: string, code: string, comments: string): void;
         /** @hidden */
         _emitCodeFromInclude(includeName: string, comments: string, options?: {
@@ -118997,6 +119079,59 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * Block used to pertub normals based on a normal map
+     */
+    export class PerturbNormalBlock extends NodeMaterialBlock {
+        private _tangentSpaceParameterName;
+        /** Gets or sets a boolean indicating that normal should be inverted on X axis */
+        invertX: boolean;
+        /** Gets or sets a boolean indicating that normal should be inverted on Y axis */
+        invertY: boolean;
+        /**
+         * Create a new PerturbNormalBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world position input component
+         */
+        readonly worldPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the world normal input component
+         */
+        readonly worldNormal: NodeMaterialConnectionPoint;
+        /**
+         * Gets the uv input component
+         */
+        readonly uv: NodeMaterialConnectionPoint;
+        /**
+        * Gets the normal map color input component
+        */
+        readonly normalMapColor: NodeMaterialConnectionPoint;
+        /**
+        * Gets the strength input component
+        */
+        readonly strength: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+        protected _dumpPropertiesCode(): string;
+        serialize(): any;
+        _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
+    }
+}
+declare module BABYLON {
+    /**
      * Block used to add support for scene fog
      */
     export class FogBlock extends NodeMaterialBlock {

+ 63 - 0
dist/preview release/documentation.d.ts

@@ -52237,6 +52237,8 @@ declare module BABYLON {
         SAMPLER3DGREENDEPTH: boolean;
         SAMPLER3DBGRMAP: boolean;
         IMAGEPROCESSINGPOSTPROCESS: boolean;
+        /** MISC. */
+        BUMPDIRECTUV: number;
         constructor();
         setValue(name: string, value: boolean): void;
     }
@@ -52700,6 +52702,12 @@ declare module BABYLON {
             [key: string]: string;
         };
         /**
+         * Gets the list of emitted extensions
+         */
+        extensions: {
+            [key: string]: string;
+        };
+        /**
          * Gets the target of the compilation state
          */
         target: NodeMaterialBlockTargets;
@@ -52746,6 +52754,8 @@ declare module BABYLON {
         /** @hidden */
         _getGLType(type: NodeMaterialBlockConnectionPointTypes): string;
         /** @hidden */
+        _emitExtension(name: string, extension: string): void;
+        /** @hidden */
         _emitFunction(name: string, code: string, comments: string): void;
         /** @hidden */
         _emitCodeFromInclude(includeName: string, comments: string, options?: {
@@ -53496,6 +53506,59 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * Block used to pertub normals based on a normal map
+     */
+    export class PerturbNormalBlock extends NodeMaterialBlock {
+        private _tangentSpaceParameterName;
+        /** Gets or sets a boolean indicating that normal should be inverted on X axis */
+        invertX: boolean;
+        /** Gets or sets a boolean indicating that normal should be inverted on Y axis */
+        invertY: boolean;
+        /**
+         * Create a new PerturbNormalBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world position input component
+         */
+        readonly worldPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the world normal input component
+         */
+        readonly worldNormal: NodeMaterialConnectionPoint;
+        /**
+         * Gets the uv input component
+         */
+        readonly uv: NodeMaterialConnectionPoint;
+        /**
+        * Gets the normal map color input component
+        */
+        readonly normalMapColor: NodeMaterialConnectionPoint;
+        /**
+        * Gets the strength input component
+        */
+        readonly strength: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+        protected _dumpPropertiesCode(): string;
+        serialize(): any;
+        _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
+    }
+}
+declare module BABYLON {
+    /**
      * Block used to add support for scene fog
      */
     export class FogBlock extends NodeMaterialBlock {

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/preview release/nodeEditor/babylon.nodeEditor.d.ts


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 7 - 7
dist/preview release/nodeEditor/babylon.nodeEditor.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 10 - 3
dist/preview release/nodeEditor/babylon.nodeEditor.max.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/preview release/nodeEditor/babylon.nodeEditor.max.js.map


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 3 - 2
dist/preview release/nodeEditor/babylon.nodeEditor.module.d.ts


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

@@ -1 +1 @@
-{"engineOnly":167802,"sceneOnly":508293,"minGridMaterial":638479,"minStandardMaterial":767493}
+{"engineOnly":167802,"sceneOnly":508293,"minGridMaterial":638443,"minStandardMaterial":767573}

+ 135 - 0
dist/preview release/viewer/babylon.module.d.ts

@@ -54679,6 +54679,8 @@ declare module "babylonjs/Materials/Node/nodeMaterial" {
         SAMPLER3DGREENDEPTH: boolean;
         SAMPLER3DBGRMAP: boolean;
         IMAGEPROCESSINGPOSTPROCESS: boolean;
+        /** MISC. */
+        BUMPDIRECTUV: number;
         constructor();
         setValue(name: string, value: boolean): void;
     }
@@ -55161,6 +55163,12 @@ declare module "babylonjs/Materials/Node/nodeMaterialBuildState" {
             [key: string]: string;
         };
         /**
+         * Gets the list of emitted extensions
+         */
+        extensions: {
+            [key: string]: string;
+        };
+        /**
          * Gets the target of the compilation state
          */
         target: NodeMaterialBlockTargets;
@@ -55207,6 +55215,8 @@ declare module "babylonjs/Materials/Node/nodeMaterialBuildState" {
         /** @hidden */
         _getGLType(type: NodeMaterialBlockConnectionPointTypes): string;
         /** @hidden */
+        _emitExtension(name: string, extension: string): void;
+        /** @hidden */
         _emitFunction(name: string, code: string, comments: string): void;
         /** @hidden */
         _emitCodeFromInclude(includeName: string, comments: string, options?: {
@@ -56027,10 +56037,72 @@ declare module "babylonjs/Materials/Node/Blocks/Fragment/imageProcessingBlock" {
         protected _buildBlock(state: NodeMaterialBuildState): this;
     }
 }
+declare module "babylonjs/Materials/Node/Blocks/Fragment/perturbNormalBlock" {
+    import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
+    import { NodeMaterialBuildState } from "babylonjs/Materials/Node/nodeMaterialBuildState";
+    import { NodeMaterialConnectionPoint } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint";
+    import { NodeMaterial, NodeMaterialDefines } from "babylonjs/Materials/Node/nodeMaterial";
+    import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
+    import { Effect } from "babylonjs/Materials/effect";
+    import { Mesh } from "babylonjs/Meshes/mesh";
+    import { Scene } from "babylonjs/scene";
+    /**
+     * Block used to pertub normals based on a normal map
+     */
+    export class PerturbNormalBlock extends NodeMaterialBlock {
+        private _tangentSpaceParameterName;
+        /** Gets or sets a boolean indicating that normal should be inverted on X axis */
+        invertX: boolean;
+        /** Gets or sets a boolean indicating that normal should be inverted on Y axis */
+        invertY: boolean;
+        /**
+         * Create a new PerturbNormalBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world position input component
+         */
+        readonly worldPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the world normal input component
+         */
+        readonly worldNormal: NodeMaterialConnectionPoint;
+        /**
+         * Gets the uv input component
+         */
+        readonly uv: NodeMaterialConnectionPoint;
+        /**
+        * Gets the normal map color input component
+        */
+        readonly normalMapColor: NodeMaterialConnectionPoint;
+        /**
+        * Gets the strength input component
+        */
+        readonly strength: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+        protected _dumpPropertiesCode(): string;
+        serialize(): any;
+        _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
+    }
+}
 declare module "babylonjs/Materials/Node/Blocks/Fragment/index" {
     export * from "babylonjs/Materials/Node/Blocks/Fragment/fragmentOutputBlock";
     export * from "babylonjs/Materials/Node/Blocks/Fragment/alphaTestBlock";
     export * from "babylonjs/Materials/Node/Blocks/Fragment/imageProcessingBlock";
+    export * from "babylonjs/Materials/Node/Blocks/Fragment/perturbNormalBlock";
 }
 declare module "babylonjs/Materials/Node/Blocks/Dual/fogBlock" {
     import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
@@ -117738,6 +117810,8 @@ declare module BABYLON {
         SAMPLER3DGREENDEPTH: boolean;
         SAMPLER3DBGRMAP: boolean;
         IMAGEPROCESSINGPOSTPROCESS: boolean;
+        /** MISC. */
+        BUMPDIRECTUV: number;
         constructor();
         setValue(name: string, value: boolean): void;
     }
@@ -118201,6 +118275,12 @@ declare module BABYLON {
             [key: string]: string;
         };
         /**
+         * Gets the list of emitted extensions
+         */
+        extensions: {
+            [key: string]: string;
+        };
+        /**
          * Gets the target of the compilation state
          */
         target: NodeMaterialBlockTargets;
@@ -118247,6 +118327,8 @@ declare module BABYLON {
         /** @hidden */
         _getGLType(type: NodeMaterialBlockConnectionPointTypes): string;
         /** @hidden */
+        _emitExtension(name: string, extension: string): void;
+        /** @hidden */
         _emitFunction(name: string, code: string, comments: string): void;
         /** @hidden */
         _emitCodeFromInclude(includeName: string, comments: string, options?: {
@@ -118997,6 +119079,59 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * Block used to pertub normals based on a normal map
+     */
+    export class PerturbNormalBlock extends NodeMaterialBlock {
+        private _tangentSpaceParameterName;
+        /** Gets or sets a boolean indicating that normal should be inverted on X axis */
+        invertX: boolean;
+        /** Gets or sets a boolean indicating that normal should be inverted on Y axis */
+        invertY: boolean;
+        /**
+         * Create a new PerturbNormalBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world position input component
+         */
+        readonly worldPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the world normal input component
+         */
+        readonly worldNormal: NodeMaterialConnectionPoint;
+        /**
+         * Gets the uv input component
+         */
+        readonly uv: NodeMaterialConnectionPoint;
+        /**
+        * Gets the normal map color input component
+        */
+        readonly normalMapColor: NodeMaterialConnectionPoint;
+        /**
+        * Gets the strength input component
+        */
+        readonly strength: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+        protected _dumpPropertiesCode(): string;
+        serialize(): any;
+        _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
+    }
+}
+declare module BABYLON {
+    /**
      * Block used to add support for scene fog
      */
     export class FogBlock extends NodeMaterialBlock {

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 19 - 15
dist/preview release/viewer/babylon.viewer.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
dist/preview release/viewer/babylon.viewer.max.js


+ 1 - 1
nodeEditor/public/index.js

@@ -105,7 +105,7 @@ var showEditor = function() {
 // Let's start
 if (BABYLON.Engine.isSupported()) {
     var canvas = document.createElement("canvas");
-    var engine = new BABYLON.Engine(canvas, false);
+    var engine = new BABYLON.Engine(canvas, false, {disableWebGL2Support: true});
     var scene = new BABYLON.Scene(engine);
 
     nodeMaterial = new BABYLON.NodeMaterial("node");

+ 4 - 1
nodeEditor/src/blockTools.ts

@@ -37,6 +37,7 @@ import { ViewDirectionBlock } from 'babylonjs/Materials/Node/Blocks/viewDirectio
 import { LightInformationBlock } from 'babylonjs/Materials/Node/Blocks/Vertex/lightInformationBlock';
 import { MaxBlock } from 'babylonjs/Materials/Node/Blocks/maxBlock';
 import { MinBlock } from 'babylonjs/Materials/Node/Blocks/minBlock';
+import { PerturbNormalBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/perturbNormalBlock';
 
 export class BlockTools {
     public static GetBlockFromString(data: string) {
@@ -110,7 +111,9 @@ export class BlockTools {
             case "MaxBlock":
                 return new MaxBlock("Max");       
             case "MinBlock":
-                return new MinBlock("Min");                                                  
+                return new MinBlock("Min");        
+            case "PerturbNormalBlock":                                          
+                return new PerturbNormalBlock("Perturb normal");        
             case "CosBlock": {
                 let cosBlock = new TrigonometryBlock("Cos");
                 cosBlock.operation = TrigonometryBlockOperations.Cos;

+ 8 - 1
nodeEditor/src/components/diagram/generic/genericNodeModel.tsx

@@ -64,7 +64,14 @@ export class GenericNodeModel extends DefaultNodeModel {
                         globalState.onRebuildRequiredObservable.notifyObservers();
                     }} isSelected={() => (this.block as TransformBlock).complementW === 0} />
                 </LineContainerComponent>
-            }        
+            }                    
+            {
+                this.block!.getClassName() === "PerturbNormalBlock" &&
+                <LineContainerComponent title="PROPERTIES">
+                    <CheckBoxLineComponent label="Invert X axis" target={this.block} propertyName="invertX" onValueChanged={() => globalState.onRebuildRequiredObservable.notifyObservers()} />
+                    <CheckBoxLineComponent label="Invert Y axis" target={this.block} propertyName="invertY" onValueChanged={() => globalState.onRebuildRequiredObservable.notifyObservers()}/>                    
+                </LineContainerComponent>
+            }   
             </div>
         );
     }

+ 1 - 1
nodeEditor/src/components/nodeList/nodeListComponent.tsx

@@ -35,7 +35,7 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
             Output_Blocks: ["VertexOutputBlock", "FragmentOutputBlock", "AlphaTestBlock"],
             Range: ["ClampBlock", "RemapBlock", "NormalizeBlock"],
             Round: ["StepBlock", "RoundBlock", "CeilingBlock", "FloorBlock"],
-            Scene_Attributes: ["FogBlock", "CameraPositionBlock", "FogColorBlock", "ImageProcessingBlock", "LightBlock", "LightInformationBlock", "ReflectionTextureBlock", "ViewDirectionBlock"],
+            Scene_Attributes: ["FogBlock", "CameraPositionBlock", "FogColorBlock", "ImageProcessingBlock", "LightBlock", "LightInformationBlock", "ReflectionTextureBlock", "ViewDirectionBlock", "PerturbNormalBlock"],
             Trigonometry: ["CosBlock", "SinBlock", "AbsBlock", "ExpBlock", "Exp2Block"],
             Vector_Math: ["CrossBlock", "DotBlock", "TransformBlock", "FresnelBlock"],
         }

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

@@ -121,9 +121,8 @@ export class FogBlock extends NodeMaterialBlock {
     protected _buildBlock(state: NodeMaterialBuildState) {
         super._buildBlock(state);
 
-        state.sharedData.blocksWithDefines.push(this);
-
         if (state.target === NodeMaterialBlockTargets.Fragment) {
+            state.sharedData.blocksWithDefines.push(this);
             state.sharedData.bindableBlocks.push(this);
 
             state._emitFunctionFromInclude("fogFragmentDeclaration", `//${this.name}`, {

+ 2 - 9
src/Materials/Node/Blocks/Dual/lightBlock.ts

@@ -34,7 +34,7 @@ export class LightBlock extends NodeMaterialBlock {
         super(name, NodeMaterialBlockTargets.VertexAndFragment);
 
         this.registerInput("worldPosition", NodeMaterialBlockConnectionPointTypes.Vector4, false, NodeMaterialBlockTargets.Vertex);
-        this.registerInput("worldNormal", NodeMaterialBlockConnectionPointTypes.Vector4, false, NodeMaterialBlockTargets.Vertex);
+        this.registerInput("worldNormal", NodeMaterialBlockConnectionPointTypes.Vector4, false, NodeMaterialBlockTargets.Fragment);
 
         this.registerInput("cameraPosition", NodeMaterialBlockConnectionPointTypes.Vector3, false, NodeMaterialBlockTargets.Fragment);
         this.registerOutput("diffuseOutput", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
@@ -147,8 +147,6 @@ export class LightBlock extends NodeMaterialBlock {
 
     private _injectVertexCode(state: NodeMaterialBuildState) {
         let worldPos = this.worldPosition;
-        let worldNormal = this.worldNormal;
-
         let comments = `//${this.name}`;
 
         // Declaration
@@ -175,11 +173,6 @@ export class LightBlock extends NodeMaterialBlock {
             state.compilationString += `${worldPosVaryingName} = ${worldPos.associatedVariableName};\r\n`;
         }
 
-        let worldNormalVaryingName = "v_" + worldNormal.associatedVariableName;
-        if (state._emitVaryingFromString(worldNormalVaryingName, "vec4")) {
-            state.compilationString += `${worldNormalVaryingName} = ${worldNormal.associatedVariableName};\r\n`;
-        }
-
         if (this.light) {
             state.compilationString += state._emitCodeFromInclude("shadowsVertex", comments, {
                 replaceStrings: [
@@ -249,7 +242,7 @@ export class LightBlock extends NodeMaterialBlock {
             state.compilationString += `float glossiness = 0.;\r\n`;
             state.compilationString += `vec3 diffuseBase = vec3(0., 0., 0.);\r\n`;
             state.compilationString += `vec3 specularBase = vec3(0., 0., 0.);\r\n`;
-            state.compilationString += `vec3 normalW = v_${this.worldNormal.associatedVariableName}.xyz;\r\n`;
+            state.compilationString += `vec3 normalW = ${this.worldNormal.associatedVariableName}.xyz;\r\n`;
         }
 
         if (this.light) {

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

@@ -109,6 +109,8 @@ export class TextureBlock extends NodeMaterialBlock {
     }
 
     public get target() {
+        // TextureBlock has a special optimizations for uvs that come from the vertex shaders as they can be packed into a single varyings.
+        // But we need to detect uvs coming from fragment then
         if (!this.uv.isConnected) {
             return NodeMaterialBlockTargets.VertexAndFragment;
         }

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

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

+ 182 - 0
src/Materials/Node/Blocks/Fragment/perturbNormalBlock.ts

@@ -0,0 +1,182 @@
+import { NodeMaterialBlock } from '../../nodeMaterialBlock';
+import { NodeMaterialBlockConnectionPointTypes } from '../../nodeMaterialBlockConnectionPointTypes';
+import { NodeMaterialBuildState } from '../../nodeMaterialBuildState';
+import { NodeMaterialBlockTargets } from '../../nodeMaterialBlockTargets';
+import { NodeMaterialConnectionPoint } from '../../nodeMaterialBlockConnectionPoint';
+import { _TypeStore } from '../../../../Misc/typeStore';
+import { NodeMaterial, NodeMaterialDefines } from '../../nodeMaterial';
+import { AbstractMesh } from '../../../../Meshes/abstractMesh';
+import { InputBlock } from '../Input/inputBlock';
+import { Effect } from '../../../effect';
+import { Mesh } from '../../../../Meshes/mesh';
+import { Scene } from '../../../../scene';
+
+/**
+ * Block used to pertub normals based on a normal map
+ */
+export class PerturbNormalBlock extends NodeMaterialBlock {
+    private _tangentSpaceParameterName = "";
+
+    /** Gets or sets a boolean indicating that normal should be inverted on X axis */
+    public invertX = false;
+    /** Gets or sets a boolean indicating that normal should be inverted on Y axis */
+    public invertY = false;
+
+    /**
+     * Create a new PerturbNormalBlock
+     * @param name defines the block name
+     */
+    public constructor(name: string) {
+        super(name, NodeMaterialBlockTargets.Neutral);
+
+        // Vertex
+        this.registerInput("worldPosition", NodeMaterialBlockConnectionPointTypes.Vector4, false);
+        this.registerInput("worldNormal", NodeMaterialBlockConnectionPointTypes.Vector4, false);
+        this.registerInput("uv", NodeMaterialBlockConnectionPointTypes.Vector2, false);
+        this.registerInput("normalMapColor", NodeMaterialBlockConnectionPointTypes.Color3, false);
+        this.registerInput("strength", NodeMaterialBlockConnectionPointTypes.Float, false);
+
+        // Fragment
+        this.registerOutput("output", NodeMaterialBlockConnectionPointTypes.Vector4);
+    }
+
+    /**
+     * Gets the current class name
+     * @returns the class name
+     */
+    public getClassName() {
+        return "PerturbNormalBlock";
+    }
+
+    /**
+     * Gets the world position input component
+     */
+    public get worldPosition(): NodeMaterialConnectionPoint {
+        return this._inputs[0];
+    }
+
+    /**
+     * Gets the world normal input component
+     */
+    public get worldNormal(): NodeMaterialConnectionPoint {
+        return this._inputs[1];
+    }
+
+    /**
+     * Gets the uv input component
+     */
+    public get uv(): NodeMaterialConnectionPoint {
+        return this._inputs[2];
+    }
+
+    /**
+    * Gets the normal map color input component
+    */
+    public get normalMapColor(): NodeMaterialConnectionPoint {
+        return this._inputs[3];
+    }
+
+    /**
+    * Gets the strength input component
+    */
+    public get strength(): NodeMaterialConnectionPoint {
+        return this._inputs[4];
+    }
+
+    /**
+     * Gets the output component
+     */
+    public get output(): NodeMaterialConnectionPoint {
+        return this._outputs[0];
+    }
+
+    public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
+        defines.setValue("BUMP", true);
+    }
+
+    public bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh) {
+        effect.setFloat2(this._tangentSpaceParameterName, this.invertX ? -1 : 1, this.invertY ? -1 : 1);
+    }
+
+    public autoConfigure(material: NodeMaterial) {
+        if (!this.uv.isConnected) {
+            let uvInput = material.getInputBlockByPredicate((b) => b.isAttribute && b.name === "uv");
+
+            if (!uvInput) {
+                uvInput = new InputBlock("uv");
+                uvInput.setAsAttribute();
+            }
+            uvInput.output.connectTo(this.uv);
+        }
+
+        if (!this.strength.isConnected) {
+            let strengthInput = new InputBlock("strength");
+            strengthInput.value = 1.0;
+            strengthInput.output.connectTo(this.strength);
+        }
+    }
+
+    protected _buildBlock(state: NodeMaterialBuildState) {
+        super._buildBlock(state);
+
+        let comments = `//${this.name}`;
+        let uv = this.uv;
+        let worldPosition = this.worldPosition;
+        let worldNormal = this.worldNormal;
+
+        state.sharedData.blocksWithDefines.push(this);
+        state.sharedData.bindableBlocks.push(this);
+
+        this._tangentSpaceParameterName = state._getFreeDefineName("tangentSpaceParameter");
+
+        state._emitUniformFromString(this._tangentSpaceParameterName, "vec2");
+
+        state._emitExtension("bump", "#extension GL_OES_standard_derivatives : enable");
+        state._emitFunctionFromInclude("bumpFragmentFunctions", comments, {
+            replaceStrings: [
+                { search: /vBumpInfos.y/g, replace: `1.0 / ${this.strength.associatedVariableName}`},
+                { search: /vTangentSpaceParams/g, replace: this._tangentSpaceParameterName},
+                { search: /vPositionW/g, replace: worldPosition.associatedVariableName + ".xyz"}
+            ]
+        });
+        state.compilationString += this._declareOutput(this.output, state) + " = vec4(0.);\r\n";
+        state.compilationString += state._emitCodeFromInclude("bumpFragment", comments, {
+            replaceStrings: [
+                { search: /perturbNormal\(TBN,vBumpUV\+uvOffset\)/g, replace: `perturbNormal(TBN, ${this.normalMapColor.associatedVariableName})` },
+                { search: /vBumpInfos.y/g, replace: `1.0 / ${this.strength.associatedVariableName}`},
+                { search: /vBumpUV/g, replace: uv.associatedVariableName},
+                { search: /vPositionW/g, replace: worldPosition.associatedVariableName + ".xyz"},
+                { search: /normalW=/g, replace: this.output.associatedVariableName + ".xyz = " },
+                { search: /normalW/g, replace: worldNormal.associatedVariableName + ".xyz" }
+            ]
+        });
+
+        return this;
+    }
+
+    protected _dumpPropertiesCode() {
+        var codeString = `${this._codeVariableName}.invertX = ${this.invertX};\r\n`;
+
+        codeString += `${this._codeVariableName}.invertY = ${this.invertY};\r\n`;
+
+        return codeString;
+    }
+
+    public serialize(): any {
+        let serializationObject = super.serialize();
+
+        serializationObject.invertX = this.invertX;
+        serializationObject.invertY = this.invertY;
+
+        return serializationObject;
+    }
+
+    public _deserialize(serializationObject: any, scene: Scene, rootUrl: string) {
+        super._deserialize(serializationObject, scene, rootUrl);
+
+        this.invertX = serializationObject.invertX;
+        this.invertY = serializationObject.invertY;
+    }
+}
+
+_TypeStore.RegisteredTypes["BABYLON.PerturbNormalBlock"] = PerturbNormalBlock;

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

@@ -71,6 +71,9 @@ export class NodeMaterialDefines extends MaterialDefines implements IImageProces
     public SAMPLER3DBGRMAP = false;
     public IMAGEPROCESSINGPOSTPROCESS = false;
 
+    /** MISC. */
+    public BUMPDIRECTUV = 0;
+
     constructor() {
         super();
         this.rebuild();

+ 1 - 1
src/Materials/Node/nodeMaterialBlock.ts

@@ -399,7 +399,7 @@ export class NodeMaterialBlock {
         const otherBlockWasGeneratedInVertexShader = block._buildTarget === NodeMaterialBlockTargets.Vertex && block.target !== NodeMaterialBlockTargets.VertexAndFragment;
 
         if (localBlockIsFragment && (
-            ((block.target & this.target) === 0) ||
+            ((block.target & input.target) === 0) ||
             (this.target !== NodeMaterialBlockTargets.VertexAndFragment && otherBlockWasGeneratedInVertexShader)
             )) { // context switch! We need a varying
             if ((!block.isInput && state.target !== block._buildTarget) // block was already emitted by vertex shader

+ 19 - 0
src/Materials/Node/nodeMaterialBuildState.ts

@@ -31,6 +31,11 @@ export class NodeMaterialBuildState {
      */
     public functions: { [key: string]: string } = {};
     /**
+     * Gets the list of emitted extensions
+     */
+    public extensions: { [key: string]: string } = {};
+
+    /**
      * Gets the target of the compilation state
      */
     public target: NodeMaterialBlockTargets;
@@ -103,6 +108,11 @@ export class NodeMaterialBuildState {
             this.compilationString = `\r\n${emitComments ? "//Attributes\r\n" : ""}${this._attributeDeclaration}\r\n${this.compilationString}`;
         }
 
+        for (var extensionName in this.extensions) {
+            let extension = this.extensions[extensionName];
+            this.compilationString = `\r\n${extension}\r\n${this.compilationString}`;
+        }
+
         this._builtCompilationString = this.compilationString;
     }
 
@@ -170,6 +180,15 @@ export class NodeMaterialBuildState {
     }
 
     /** @hidden */
+    public _emitExtension(name: string, extension: string) {
+        if (this.extensions[name]) {
+            return;
+        }
+
+        this.extensions[name] = extension;
+    }
+
+    /** @hidden */
     public _emitFunction(name: string, code: string, comments: string) {
         if (this.functions[name]) {
             return;

+ 3 - 0
src/Materials/Node/nodeMaterialBuildStateSharedData.ts

@@ -126,6 +126,9 @@ export class NodeMaterialBuildStateSharedData {
         this.variableNames["specularBase"] = 0;
         this.variableNames["worldPos"] = 0;
 
+        // Exclude known varyings
+        this.variableNames["vTBN"] = 0;
+
         // Exclude defines
         this.defineNames["MAINUV0"] = 0;
         this.defineNames["MAINUV1"] = 0;

+ 1 - 1
src/Meshes/mesh.ts

@@ -688,7 +688,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
 
         if (internalDataInfo._LODLevels[internalDataInfo._LODLevels.length - 1].distance > distanceToCamera) {
             if (this.onLODLevelSelection) {
-                this.onLODLevelSelection(distanceToCamera, this, internalDataInfo._LODLevels[internalDataInfo._LODLevels.length - 1].mesh);
+                this.onLODLevelSelection(distanceToCamera, this, this);
             }
             return this;
         }

+ 5 - 0
src/Shaders/ShadersInclude/bumpFragmentFunctions.fx

@@ -61,6 +61,11 @@
 		return perturbNormal(cotangentFrame, texture2D(bumpSampler, uv).xyz, vBumpInfos.y);
 	}
 
+	vec3 perturbNormal(mat3 cotangentFrame, vec3 color)
+	{
+		return perturbNormal(cotangentFrame, color, vBumpInfos.y);
+	}
+
 	// Thanks to http://www.thetenthplanet.de/archives/1180
 	mat3 cotangent_frame(vec3 normal, vec3 p, vec2 uv)
 	{

BIN
tests/validation/LogoV3.png


BIN
tests/validation/ReferenceImages/node-material3.png


+ 5 - 0
tests/validation/config.json

@@ -12,6 +12,11 @@
             "referenceImage": "node-material2.png"
         },
         {
+            "title": "Node material #3",
+            "playgroundId": "#LWGVT0#2",
+            "referenceImage": "node-material3.png"
+        },          
+        {
             "title": "Basis loader",
             "playgroundId": "#4RN0VF#0",
             "referenceImage": "basis.png"

+ 1 - 1
tests/validation/index.css

@@ -7,7 +7,7 @@
 }
 
 body {
-    background: url("LogoV3.png");    
+    background: url("Logo.png");    
     background-position: center center;
     background-repeat: no-repeat;
 }

BIN
tests/validation/logo.png