Browse Source

new videwDirection block

David Catuhe 6 years ago
parent
commit
9cf21d7395

+ 115 - 50
dist/preview release/babylon.d.ts

@@ -51880,7 +51880,7 @@ declare module BABYLON {
          * Gets the b output component
          * Gets the b output component
          */
          */
         readonly b: NodeMaterialConnectionPoint;
         readonly b: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         isReady(): boolean;
         isReady(): boolean;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
@@ -52025,6 +52025,18 @@ declare module BABYLON {
          */
          */
         getBlockByName(name: string): Nullable<NodeMaterialBlock>;
         getBlockByName(name: string): Nullable<NodeMaterialBlock>;
         /**
         /**
+         * Get a block by its name
+         * @param predicate defines the predicate used to find the good candidate
+         * @returns the required block or null if not found
+         */
+        getBlockByPredicate(predicate: (block: NodeMaterialBlock) => boolean): Nullable<NodeMaterialBlock>;
+        /**
+         * Get an input block by its name
+         * @param predicate defines the predicate used to find the good candidate
+         * @returns the required input block or null if not found
+         */
+        getInputBlockByPredicate(predicate: (block: InputBlock) => boolean): Nullable<InputBlock>;
+        /**
          * Gets the list of input blocks attached to this material
          * Gets the list of input blocks attached to this material
          * @returns an array of InputBlocks
          * @returns an array of InputBlocks
          */
          */
@@ -52239,7 +52251,7 @@ declare module BABYLON {
          */
          */
         readonly a: NodeMaterialConnectionPoint;
         readonly a: NodeMaterialConnectionPoint;
         readonly target: NodeMaterialBlockTargets;
         readonly target: NodeMaterialBlockTargets;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         initializeDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         initializeDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         isReady(): boolean;
         isReady(): boolean;
@@ -52951,7 +52963,7 @@ declare module BABYLON {
          * Gets the output component
          * Gets the output component
          */
          */
         readonly output: NodeMaterialConnectionPoint;
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         provideFallbacks(mesh: AbstractMesh, fallbacks: EffectFallbacks): void;
         provideFallbacks(mesh: AbstractMesh, fallbacks: EffectFallbacks): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
@@ -52998,7 +53010,7 @@ declare module BABYLON {
          * Gets the output component
          * Gets the output component
          */
          */
         readonly output: NodeMaterialConnectionPoint;
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         protected _buildBlock(state: NodeMaterialBuildState): this;
         protected _buildBlock(state: NodeMaterialBuildState): this;
     }
     }
@@ -53053,7 +53065,7 @@ declare module BABYLON {
          */
          */
         readonly uvOutput: NodeMaterialConnectionPoint;
         readonly uvOutput: NodeMaterialConnectionPoint;
         initialize(state: NodeMaterialBuildState): void;
         initialize(state: NodeMaterialBuildState): void;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         replaceRepeatableContent(vertexShaderState: NodeMaterialBuildState, fragmentShaderState: NodeMaterialBuildState, mesh: AbstractMesh, defines: NodeMaterialDefines): void;
         replaceRepeatableContent(vertexShaderState: NodeMaterialBuildState, fragmentShaderState: NodeMaterialBuildState, mesh: AbstractMesh, defines: NodeMaterialDefines): void;
@@ -53095,49 +53107,6 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /**
     /**
-     * Block used to compute fresnel value
-     */
-    export class FresnelBlock extends NodeMaterialBlock {
-        /**
-         * Create a new FresnelBlock
-         * @param name defines the block name
-         */
-        constructor(name: string);
-        /**
-         * Gets the current class name
-         * @returns the class name
-         */
-        getClassName(): string;
-        /**
-         * Gets the world position input component
-         */
-        readonly worldPosition: NodeMaterialConnectionPoint;
-        /**
-         * Gets the world normal input component
-         */
-        readonly worldNormal: NodeMaterialConnectionPoint;
-        /**
-        * Gets the camera (or eye) position component
-        */
-        readonly cameraPosition: NodeMaterialConnectionPoint;
-        /**
-        * Gets the bias input component
-        */
-        readonly bias: NodeMaterialConnectionPoint;
-        /**
-        * Gets the camera (or eye) position component
-        */
-        readonly power: NodeMaterialConnectionPoint;
-        /**
-         * Gets the fresnel output component
-         */
-        readonly fresnel: NodeMaterialConnectionPoint;
-        autoConfigure(material: NodeMaterial): void;
-        protected _buildBlock(state: NodeMaterialBuildState): this | undefined;
-    }
-}
-declare module BABYLON {
-    /**
      * Block used to add image processing support to fragment shader
      * Block used to add image processing support to fragment shader
      */
      */
     export class ImageProcessingBlock extends NodeMaterialBlock {
     export class ImageProcessingBlock extends NodeMaterialBlock {
@@ -53207,7 +53176,7 @@ declare module BABYLON {
          * Gets the output component
          * Gets the output component
          */
          */
         readonly output: NodeMaterialConnectionPoint;
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         protected _buildBlock(state: NodeMaterialBuildState): this;
         protected _buildBlock(state: NodeMaterialBuildState): this;
@@ -53253,7 +53222,7 @@ declare module BABYLON {
          * Gets the specular output component
          * Gets the specular output component
          */
          */
         readonly specularOutput: NodeMaterialConnectionPoint;
         readonly specularOutput: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
@@ -53878,6 +53847,102 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /**
     /**
+     * Block used to get the opposite of a value
+     */
+    export class OppositeBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new OppositeBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the input component
+         */
+        readonly input: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to get the view direction
+     */
+    export class ViewDirectionBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new ViewDirectionBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world position component
+         */
+        readonly worldPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the camera position component
+         */
+        readonly cameraPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to compute fresnel value
+     */
+    export class FresnelBlock extends NodeMaterialBlock {
+        /**
+         * Create a new FresnelBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world normal input component
+         */
+        readonly worldNormal: NodeMaterialConnectionPoint;
+        /**
+        * Gets the view direction input component
+        */
+        readonly viewDirection: NodeMaterialConnectionPoint;
+        /**
+        * Gets the bias input component
+        */
+        readonly bias: NodeMaterialConnectionPoint;
+        /**
+        * Gets the camera (or eye) position component
+        */
+        readonly power: NodeMaterialConnectionPoint;
+        /**
+         * Gets the fresnel output component
+         */
+        readonly fresnel: NodeMaterialConnectionPoint;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
      * Effect Render Options
      * Effect Render Options
      */
      */
     export interface IEffectRendererOptions {
     export interface IEffectRendererOptions {

File diff suppressed because it is too large
+ 2 - 2
dist/preview release/babylon.js


File diff suppressed because it is too large
+ 491 - 238
dist/preview release/babylon.max.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/babylon.max.js.map


+ 244 - 105
dist/preview release/babylon.module.d.ts

@@ -54292,7 +54292,7 @@ declare module "babylonjs/Materials/Node/Blocks/Dual/reflectionTextureBlock" {
          * Gets the b output component
          * Gets the b output component
          */
          */
         readonly b: NodeMaterialConnectionPoint;
         readonly b: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         isReady(): boolean;
         isReady(): boolean;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
@@ -54453,6 +54453,18 @@ declare module "babylonjs/Materials/Node/nodeMaterial" {
          */
          */
         getBlockByName(name: string): Nullable<NodeMaterialBlock>;
         getBlockByName(name: string): Nullable<NodeMaterialBlock>;
         /**
         /**
+         * Get a block by its name
+         * @param predicate defines the predicate used to find the good candidate
+         * @returns the required block or null if not found
+         */
+        getBlockByPredicate(predicate: (block: NodeMaterialBlock) => boolean): Nullable<NodeMaterialBlock>;
+        /**
+         * Get an input block by its name
+         * @param predicate defines the predicate used to find the good candidate
+         * @returns the required input block or null if not found
+         */
+        getInputBlockByPredicate(predicate: (block: InputBlock) => boolean): Nullable<InputBlock>;
+        /**
          * Gets the list of input blocks attached to this material
          * Gets the list of input blocks attached to this material
          * @returns an array of InputBlocks
          * @returns an array of InputBlocks
          */
          */
@@ -54678,7 +54690,7 @@ declare module "babylonjs/Materials/Node/Blocks/Dual/textureBlock" {
          */
          */
         readonly a: NodeMaterialConnectionPoint;
         readonly a: NodeMaterialConnectionPoint;
         readonly target: NodeMaterialBlockTargets;
         readonly target: NodeMaterialBlockTargets;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         initializeDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         initializeDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         isReady(): boolean;
         isReady(): boolean;
@@ -55431,7 +55443,7 @@ declare module "babylonjs/Materials/Node/Blocks/Vertex/bonesBlock" {
          * Gets the output component
          * Gets the output component
          */
          */
         readonly output: NodeMaterialConnectionPoint;
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         provideFallbacks(mesh: AbstractMesh, fallbacks: EffectFallbacks): void;
         provideFallbacks(mesh: AbstractMesh, fallbacks: EffectFallbacks): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
@@ -55483,7 +55495,7 @@ declare module "babylonjs/Materials/Node/Blocks/Vertex/instancesBlock" {
          * Gets the output component
          * Gets the output component
          */
          */
         readonly output: NodeMaterialConnectionPoint;
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         protected _buildBlock(state: NodeMaterialBuildState): this;
         protected _buildBlock(state: NodeMaterialBuildState): this;
     }
     }
@@ -55545,7 +55557,7 @@ declare module "babylonjs/Materials/Node/Blocks/Vertex/morphTargetsBlock" {
          */
          */
         readonly uvOutput: NodeMaterialConnectionPoint;
         readonly uvOutput: NodeMaterialConnectionPoint;
         initialize(state: NodeMaterialBuildState): void;
         initialize(state: NodeMaterialBuildState): void;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         replaceRepeatableContent(vertexShaderState: NodeMaterialBuildState, fragmentShaderState: NodeMaterialBuildState, mesh: AbstractMesh, defines: NodeMaterialDefines): void;
         replaceRepeatableContent(vertexShaderState: NodeMaterialBuildState, fragmentShaderState: NodeMaterialBuildState, mesh: AbstractMesh, defines: NodeMaterialDefines): void;
@@ -55595,53 +55607,6 @@ declare module "babylonjs/Materials/Node/Blocks/Fragment/alphaTestBlock" {
         _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
         _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
     }
     }
 }
 }
-declare module "babylonjs/Materials/Node/Blocks/Fragment/fresnelBlock" {
-    import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
-    import { NodeMaterialBuildState } from "babylonjs/Materials/Node/nodeMaterialBuildState";
-    import { NodeMaterialConnectionPoint } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint";
-    import { NodeMaterial } from "babylonjs/Materials/Node/nodeMaterial";
-    /**
-     * Block used to compute fresnel value
-     */
-    export class FresnelBlock extends NodeMaterialBlock {
-        /**
-         * Create a new FresnelBlock
-         * @param name defines the block name
-         */
-        constructor(name: string);
-        /**
-         * Gets the current class name
-         * @returns the class name
-         */
-        getClassName(): string;
-        /**
-         * Gets the world position input component
-         */
-        readonly worldPosition: NodeMaterialConnectionPoint;
-        /**
-         * Gets the world normal input component
-         */
-        readonly worldNormal: NodeMaterialConnectionPoint;
-        /**
-        * Gets the camera (or eye) position component
-        */
-        readonly cameraPosition: NodeMaterialConnectionPoint;
-        /**
-        * Gets the bias input component
-        */
-        readonly bias: NodeMaterialConnectionPoint;
-        /**
-        * Gets the camera (or eye) position component
-        */
-        readonly power: NodeMaterialConnectionPoint;
-        /**
-         * Gets the fresnel output component
-         */
-        readonly fresnel: NodeMaterialConnectionPoint;
-        autoConfigure(material: NodeMaterial): void;
-        protected _buildBlock(state: NodeMaterialBuildState): this | undefined;
-    }
-}
 declare module "babylonjs/Materials/Node/Blocks/Fragment/imageProcessingBlock" {
 declare module "babylonjs/Materials/Node/Blocks/Fragment/imageProcessingBlock" {
     import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
     import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
     import { NodeMaterialBuildState } from "babylonjs/Materials/Node/nodeMaterialBuildState";
     import { NodeMaterialBuildState } from "babylonjs/Materials/Node/nodeMaterialBuildState";
@@ -55686,7 +55651,6 @@ declare module "babylonjs/Materials/Node/Blocks/Fragment/imageProcessingBlock" {
 declare module "babylonjs/Materials/Node/Blocks/Fragment/index" {
 declare module "babylonjs/Materials/Node/Blocks/Fragment/index" {
     export * from "babylonjs/Materials/Node/Blocks/Fragment/fragmentOutputBlock";
     export * from "babylonjs/Materials/Node/Blocks/Fragment/fragmentOutputBlock";
     export * from "babylonjs/Materials/Node/Blocks/Fragment/alphaTestBlock";
     export * from "babylonjs/Materials/Node/Blocks/Fragment/alphaTestBlock";
-    export * from "babylonjs/Materials/Node/Blocks/Fragment/fresnelBlock";
     export * from "babylonjs/Materials/Node/Blocks/Fragment/imageProcessingBlock";
     export * from "babylonjs/Materials/Node/Blocks/Fragment/imageProcessingBlock";
 }
 }
 declare module "babylonjs/Materials/Node/Blocks/Dual/fogBlock" {
 declare module "babylonjs/Materials/Node/Blocks/Dual/fogBlock" {
@@ -55733,7 +55697,7 @@ declare module "babylonjs/Materials/Node/Blocks/Dual/fogBlock" {
          * Gets the output component
          * Gets the output component
          */
          */
         readonly output: NodeMaterialConnectionPoint;
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         protected _buildBlock(state: NodeMaterialBuildState): this;
         protected _buildBlock(state: NodeMaterialBuildState): this;
@@ -55789,7 +55753,7 @@ declare module "babylonjs/Materials/Node/Blocks/Dual/lightBlock" {
          * Gets the specular output component
          * Gets the specular output component
          */
          */
         readonly specularOutput: NodeMaterialConnectionPoint;
         readonly specularOutput: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
@@ -56476,6 +56440,113 @@ declare module "babylonjs/Materials/Node/Blocks/stepBlock" {
         protected _buildBlock(state: NodeMaterialBuildState): this;
         protected _buildBlock(state: NodeMaterialBuildState): this;
     }
     }
 }
 }
+declare module "babylonjs/Materials/Node/Blocks/oppositeBlock" {
+    import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
+    import { NodeMaterialBuildState } from "babylonjs/Materials/Node/nodeMaterialBuildState";
+    import { NodeMaterialConnectionPoint } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint";
+    /**
+     * Block used to get the opposite of a value
+     */
+    export class OppositeBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new OppositeBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the input component
+         */
+        readonly input: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module "babylonjs/Materials/Node/Blocks/viewDirectionBlock" {
+    import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
+    import { NodeMaterialBuildState } from "babylonjs/Materials/Node/nodeMaterialBuildState";
+    import { NodeMaterialConnectionPoint } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint";
+    import { NodeMaterial } from "babylonjs/Materials/Node/nodeMaterial";
+    /**
+     * Block used to get the view direction
+     */
+    export class ViewDirectionBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new ViewDirectionBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world position component
+         */
+        readonly worldPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the camera position component
+         */
+        readonly cameraPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module "babylonjs/Materials/Node/Blocks/fresnelBlock" {
+    import { NodeMaterialBlock } from "babylonjs/Materials/Node/nodeMaterialBlock";
+    import { NodeMaterialBuildState } from "babylonjs/Materials/Node/nodeMaterialBuildState";
+    import { NodeMaterialConnectionPoint } from "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint";
+    import { NodeMaterial } from "babylonjs/Materials/Node/nodeMaterial";
+    /**
+     * Block used to compute fresnel value
+     */
+    export class FresnelBlock extends NodeMaterialBlock {
+        /**
+         * Create a new FresnelBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world normal input component
+         */
+        readonly worldNormal: NodeMaterialConnectionPoint;
+        /**
+        * Gets the view direction input component
+        */
+        readonly viewDirection: NodeMaterialConnectionPoint;
+        /**
+        * Gets the bias input component
+        */
+        readonly bias: NodeMaterialConnectionPoint;
+        /**
+        * Gets the camera (or eye) position component
+        */
+        readonly power: NodeMaterialConnectionPoint;
+        /**
+         * Gets the fresnel output component
+         */
+        readonly fresnel: NodeMaterialConnectionPoint;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
 declare module "babylonjs/Materials/Node/Blocks/index" {
 declare module "babylonjs/Materials/Node/Blocks/index" {
     export * from "babylonjs/Materials/Node/Blocks/Vertex/index";
     export * from "babylonjs/Materials/Node/Blocks/Vertex/index";
     export * from "babylonjs/Materials/Node/Blocks/Fragment/index";
     export * from "babylonjs/Materials/Node/Blocks/Fragment/index";
@@ -56499,6 +56570,9 @@ declare module "babylonjs/Materials/Node/Blocks/index" {
     export * from "babylonjs/Materials/Node/Blocks/divideBlock";
     export * from "babylonjs/Materials/Node/Blocks/divideBlock";
     export * from "babylonjs/Materials/Node/Blocks/subtractBlock";
     export * from "babylonjs/Materials/Node/Blocks/subtractBlock";
     export * from "babylonjs/Materials/Node/Blocks/stepBlock";
     export * from "babylonjs/Materials/Node/Blocks/stepBlock";
+    export * from "babylonjs/Materials/Node/Blocks/oppositeBlock";
+    export * from "babylonjs/Materials/Node/Blocks/viewDirectionBlock";
+    export * from "babylonjs/Materials/Node/Blocks/fresnelBlock";
 }
 }
 declare module "babylonjs/Materials/Node/Optimizers/index" {
 declare module "babylonjs/Materials/Node/Optimizers/index" {
     export * from "babylonjs/Materials/Node/Optimizers/nodeMaterialOptimizer";
     export * from "babylonjs/Materials/Node/Optimizers/nodeMaterialOptimizer";
@@ -116803,7 +116877,7 @@ declare module BABYLON {
          * Gets the b output component
          * Gets the b output component
          */
          */
         readonly b: NodeMaterialConnectionPoint;
         readonly b: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         isReady(): boolean;
         isReady(): boolean;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
@@ -116948,6 +117022,18 @@ declare module BABYLON {
          */
          */
         getBlockByName(name: string): Nullable<NodeMaterialBlock>;
         getBlockByName(name: string): Nullable<NodeMaterialBlock>;
         /**
         /**
+         * Get a block by its name
+         * @param predicate defines the predicate used to find the good candidate
+         * @returns the required block or null if not found
+         */
+        getBlockByPredicate(predicate: (block: NodeMaterialBlock) => boolean): Nullable<NodeMaterialBlock>;
+        /**
+         * Get an input block by its name
+         * @param predicate defines the predicate used to find the good candidate
+         * @returns the required input block or null if not found
+         */
+        getInputBlockByPredicate(predicate: (block: InputBlock) => boolean): Nullable<InputBlock>;
+        /**
          * Gets the list of input blocks attached to this material
          * Gets the list of input blocks attached to this material
          * @returns an array of InputBlocks
          * @returns an array of InputBlocks
          */
          */
@@ -117162,7 +117248,7 @@ declare module BABYLON {
          */
          */
         readonly a: NodeMaterialConnectionPoint;
         readonly a: NodeMaterialConnectionPoint;
         readonly target: NodeMaterialBlockTargets;
         readonly target: NodeMaterialBlockTargets;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         initializeDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         initializeDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         isReady(): boolean;
         isReady(): boolean;
@@ -117874,7 +117960,7 @@ declare module BABYLON {
          * Gets the output component
          * Gets the output component
          */
          */
         readonly output: NodeMaterialConnectionPoint;
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         provideFallbacks(mesh: AbstractMesh, fallbacks: EffectFallbacks): void;
         provideFallbacks(mesh: AbstractMesh, fallbacks: EffectFallbacks): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
@@ -117921,7 +118007,7 @@ declare module BABYLON {
          * Gets the output component
          * Gets the output component
          */
          */
         readonly output: NodeMaterialConnectionPoint;
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances?: boolean): void;
         protected _buildBlock(state: NodeMaterialBuildState): this;
         protected _buildBlock(state: NodeMaterialBuildState): this;
     }
     }
@@ -117976,7 +118062,7 @@ declare module BABYLON {
          */
          */
         readonly uvOutput: NodeMaterialConnectionPoint;
         readonly uvOutput: NodeMaterialConnectionPoint;
         initialize(state: NodeMaterialBuildState): void;
         initialize(state: NodeMaterialBuildState): void;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         replaceRepeatableContent(vertexShaderState: NodeMaterialBuildState, fragmentShaderState: NodeMaterialBuildState, mesh: AbstractMesh, defines: NodeMaterialDefines): void;
         replaceRepeatableContent(vertexShaderState: NodeMaterialBuildState, fragmentShaderState: NodeMaterialBuildState, mesh: AbstractMesh, defines: NodeMaterialDefines): void;
@@ -118018,49 +118104,6 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /**
     /**
-     * Block used to compute fresnel value
-     */
-    export class FresnelBlock extends NodeMaterialBlock {
-        /**
-         * Create a new FresnelBlock
-         * @param name defines the block name
-         */
-        constructor(name: string);
-        /**
-         * Gets the current class name
-         * @returns the class name
-         */
-        getClassName(): string;
-        /**
-         * Gets the world position input component
-         */
-        readonly worldPosition: NodeMaterialConnectionPoint;
-        /**
-         * Gets the world normal input component
-         */
-        readonly worldNormal: NodeMaterialConnectionPoint;
-        /**
-        * Gets the camera (or eye) position component
-        */
-        readonly cameraPosition: NodeMaterialConnectionPoint;
-        /**
-        * Gets the bias input component
-        */
-        readonly bias: NodeMaterialConnectionPoint;
-        /**
-        * Gets the camera (or eye) position component
-        */
-        readonly power: NodeMaterialConnectionPoint;
-        /**
-         * Gets the fresnel output component
-         */
-        readonly fresnel: NodeMaterialConnectionPoint;
-        autoConfigure(material: NodeMaterial): void;
-        protected _buildBlock(state: NodeMaterialBuildState): this | undefined;
-    }
-}
-declare module BABYLON {
-    /**
      * Block used to add image processing support to fragment shader
      * Block used to add image processing support to fragment shader
      */
      */
     export class ImageProcessingBlock extends NodeMaterialBlock {
     export class ImageProcessingBlock extends NodeMaterialBlock {
@@ -118130,7 +118173,7 @@ declare module BABYLON {
          * Gets the output component
          * Gets the output component
          */
          */
         readonly output: NodeMaterialConnectionPoint;
         readonly output: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         protected _buildBlock(state: NodeMaterialBuildState): this;
         protected _buildBlock(state: NodeMaterialBuildState): this;
@@ -118176,7 +118219,7 @@ declare module BABYLON {
          * Gets the specular output component
          * Gets the specular output component
          */
          */
         readonly specularOutput: NodeMaterialConnectionPoint;
         readonly specularOutput: NodeMaterialConnectionPoint;
-        autoConfigure(): void;
+        autoConfigure(material: NodeMaterial): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
@@ -118801,6 +118844,102 @@ declare module BABYLON {
 }
 }
 declare module BABYLON {
 declare module BABYLON {
     /**
     /**
+     * Block used to get the opposite of a value
+     */
+    export class OppositeBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new OppositeBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the input component
+         */
+        readonly input: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to get the view direction
+     */
+    export class ViewDirectionBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new ViewDirectionBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world position component
+         */
+        readonly worldPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the camera position component
+         */
+        readonly cameraPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to compute fresnel value
+     */
+    export class FresnelBlock extends NodeMaterialBlock {
+        /**
+         * Create a new FresnelBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world normal input component
+         */
+        readonly worldNormal: NodeMaterialConnectionPoint;
+        /**
+        * Gets the view direction input component
+        */
+        readonly viewDirection: NodeMaterialConnectionPoint;
+        /**
+        * Gets the bias input component
+        */
+        readonly bias: NodeMaterialConnectionPoint;
+        /**
+        * Gets the camera (or eye) position component
+        */
+        readonly power: NodeMaterialConnectionPoint;
+        /**
+         * Gets the fresnel output component
+         */
+        readonly fresnel: NodeMaterialConnectionPoint;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
      * Effect Render Options
      * Effect Render Options
      */
      */
     export interface IEffectRendererOptions {
     export interface IEffectRendererOptions {

+ 0 - 817
localDev/fresnel.json

@@ -1,817 +0,0 @@
-{
-  "tags": null,
-  "id": "dummy node",
-  "uniqueId": 78,
-  "name": "dummy node",
-  "checkReadyOnEveryCall": false,
-  "checkReadyOnlyOnce": false,
-  "state": "",
-  "alpha": 1,
-  "backFaceCulling": true,
-  "sideOrientation": 1,
-  "alphaMode": 2,
-  "_needDepthPrePass": false,
-  "disableDepthWrite": false,
-  "forceDepthWrite": false,
-  "separateCullingPass": false,
-  "fogEnabled": true,
-  "pointSize": 1,
-  "zOffset": 0,
-  "wireframe": false,
-  "pointsCloud": false,
-  "fillMode": 0,
-  "customType": "BABYLON.NodeMaterial",
-  "outputNodes": [
-    200,
-    213,
-    226
-  ],
-  "blocks": [
-    {
-      "customType": "BABYLON.VertexOutputBlock",
-      "id": 200,
-      "name": "vertexOutput",
-      "inputs": [
-        {
-          "name": "vector",
-          "inputName": "vector",
-          "targetBlockId": 201,
-          "targetConnectionName": "output"
-        }
-      ]
-    },
-    {
-      "customType": "BABYLON.TransformBlock",
-      "id": 201,
-      "name": "worldPos * viewProjectionTransform",
-      "inputs": [
-        {
-          "name": "vector",
-          "inputName": "vector",
-          "targetBlockId": 202,
-          "targetConnectionName": "output"
-        },
-        {
-          "name": "transform",
-          "inputName": "transform",
-          "targetBlockId": 212,
-          "targetConnectionName": "output"
-        }
-      ],
-      "complementZ": 0,
-      "complementW": 1
-    },
-    {
-      "customType": "BABYLON.TransformBlock",
-      "id": 202,
-      "name": "worldPos",
-      "inputs": [
-        {
-          "name": "vector",
-          "inputName": "vector",
-          "targetBlockId": 203,
-          "targetConnectionName": "positionOutput"
-        },
-        {
-          "name": "transform",
-          "inputName": "transform",
-          "targetBlockId": 208,
-          "targetConnectionName": "output"
-        }
-      ],
-      "complementZ": 0,
-      "complementW": 1
-    },
-    {
-      "customType": "BABYLON.MorphTargetsBlock",
-      "id": 203,
-      "name": "morphTargets",
-      "inputs": [
-        {
-          "name": "position",
-          "inputName": "position",
-          "targetBlockId": 204,
-          "targetConnectionName": "output"
-        },
-        {
-          "name": "normal",
-          "inputName": "normal",
-          "targetBlockId": 205,
-          "targetConnectionName": "output"
-        },
-        {
-          "name": "tangent",
-          "inputName": "tangent",
-          "targetBlockId": 206,
-          "targetConnectionName": "output"
-        },
-        {
-          "name": "uv",
-          "inputName": "uv",
-          "targetBlockId": 207,
-          "targetConnectionName": "output"
-        }
-      ]
-    },
-    {
-      "customType": "BABYLON.InputBlock",
-      "id": 204,
-      "name": "position",
-      "inputs": [],
-      "type": 8,
-      "mode": 1,
-      "wellKnownValue": null,
-      "animationType": 0,
-      "visibleInInspector": false
-    },
-    {
-      "customType": "BABYLON.InputBlock",
-      "id": 205,
-      "name": "normal",
-      "inputs": [],
-      "type": 8,
-      "mode": 1,
-      "wellKnownValue": null,
-      "animationType": 0,
-      "visibleInInspector": false
-    },
-    {
-      "customType": "BABYLON.InputBlock",
-      "id": 206,
-      "name": "tangent",
-      "inputs": [],
-      "type": 8,
-      "mode": 1,
-      "wellKnownValue": null,
-      "animationType": 0,
-      "visibleInInspector": false
-    },
-    {
-      "customType": "BABYLON.InputBlock",
-      "id": 207,
-      "name": "uv",
-      "inputs": [],
-      "type": 4,
-      "mode": 1,
-      "wellKnownValue": null,
-      "animationType": 0,
-      "visibleInInspector": false
-    },
-    {
-      "customType": "BABYLON.BonesBlock",
-      "id": 208,
-      "name": "bonesBlock",
-      "inputs": [
-        {
-          "name": "matricesIndices",
-          "inputName": "matricesIndices",
-          "targetBlockId": 209,
-          "targetConnectionName": "output"
-        },
-        {
-          "name": "matricesWeights",
-          "inputName": "matricesWeights",
-          "targetBlockId": 210,
-          "targetConnectionName": "output"
-        },
-        {
-          "name": "matricesIndicesExtra"
-        },
-        {
-          "name": "matricesWeightsExtra"
-        },
-        {
-          "name": "world",
-          "inputName": "world",
-          "targetBlockId": 211,
-          "targetConnectionName": "output"
-        }
-      ]
-    },
-    {
-      "customType": "BABYLON.InputBlock",
-      "id": 209,
-      "name": "matricesIndices",
-      "inputs": [],
-      "type": 16,
-      "mode": 1,
-      "wellKnownValue": null,
-      "animationType": 0,
-      "visibleInInspector": false
-    },
-    {
-      "customType": "BABYLON.InputBlock",
-      "id": 210,
-      "name": "matricesWeights",
-      "inputs": [],
-      "type": 16,
-      "mode": 1,
-      "wellKnownValue": null,
-      "animationType": 0,
-      "visibleInInspector": false
-    },
-    {
-      "customType": "BABYLON.InputBlock",
-      "id": 211,
-      "name": "world",
-      "inputs": [],
-      "type": 128,
-      "mode": 0,
-      "wellKnownValue": 1,
-      "animationType": 0,
-      "visibleInInspector": false,
-      "valueType": "BABYLON.Matrix",
-      "value": {
-        "0": 1,
-        "1": 0,
-        "2": 0,
-        "3": 0,
-        "4": 0,
-        "5": 1,
-        "6": 0,
-        "7": 0,
-        "8": 0,
-        "9": 0,
-        "10": 1,
-        "11": 0,
-        "12": 0,
-        "13": 0,
-        "14": 0,
-        "15": 1
-      }
-    },
-    {
-      "customType": "BABYLON.InputBlock",
-      "id": 212,
-      "name": "viewProjection",
-      "inputs": [],
-      "type": 128,
-      "mode": 0,
-      "wellKnownValue": 4,
-      "animationType": 0,
-      "visibleInInspector": false
-    },
-    {
-      "customType": "BABYLON.FogBlock",
-      "id": 213,
-      "name": "fog",
-      "inputs": [
-        {
-          "name": "worldPosition",
-          "inputName": "worldPosition",
-          "targetBlockId": 202,
-          "targetConnectionName": "output"
-        },
-        {
-          "name": "view",
-          "inputName": "view",
-          "targetBlockId": 214,
-          "targetConnectionName": "output"
-        },
-        {
-          "name": "input",
-          "inputName": "input",
-          "targetBlockId": 215,
-          "targetConnectionName": "rgb"
-        },
-        {
-          "name": "fogColor",
-          "inputName": "fogColor",
-          "targetBlockId": 225,
-          "targetConnectionName": "output"
-        }
-      ]
-    },
-    {
-      "customType": "BABYLON.InputBlock",
-      "id": 214,
-      "name": "view",
-      "inputs": [],
-      "type": 128,
-      "mode": 0,
-      "wellKnownValue": 2,
-      "animationType": 0,
-      "visibleInInspector": false
-    },
-    {
-      "customType": "BABYLON.ColorSplitterBlock",
-      "id": 215,
-      "name": "color4 splitter",
-      "inputs": [
-        {
-          "name": "rgba",
-          "inputName": "rgba",
-          "targetBlockId": 216,
-          "targetConnectionName": "output"
-        },
-        {
-          "name": "rgb "
-        }
-      ]
-    },
-    {
-      "customType": "BABYLON.ScaleBlock",
-      "id": 216,
-      "name": "color scale",
-      "inputs": [
-        {
-          "name": "input",
-          "inputName": "input",
-          "targetBlockId": 217,
-          "targetConnectionName": "output"
-        },
-        {
-          "name": "factor",
-          "inputName": "factor",
-          "targetBlockId": 224,
-          "targetConnectionName": "output"
-        }
-      ]
-    },
-    {
-      "customType": "BABYLON.MultiplyBlock",
-      "id": 217,
-      "name": "color multiplier",
-      "inputs": [
-        {
-          "name": "left",
-          "inputName": "left",
-          "targetBlockId": 218,
-          "targetConnectionName": "rgba"
-        },
-        {
-          "name": "right",
-          "inputName": "right",
-          "targetBlockId": 221,
-          "targetConnectionName": "rgba"
-        }
-      ]
-    },
-    {
-      "customType": "BABYLON.TextureBlock",
-      "id": 218,
-      "name": "diffuseTexture",
-      "inputs": [
-        {
-          "name": "uv",
-          "inputName": "uv",
-          "targetBlockId": 220,
-          "targetConnectionName": "output"
-        }
-      ],
-      "texture": {
-        "tags": null,
-        "url": "/playground/textures/bloc.jpg",
-        "uOffset": 0,
-        "vOffset": 0,
-        "uScale": 1,
-        "vScale": 1,
-        "uAng": 0,
-        "vAng": 0,
-        "wAng": 0,
-        "uRotationCenter": 0.5,
-        "vRotationCenter": 0.5,
-        "wRotationCenter": 0.5,
-        "isBlocking": true,
-        "uniqueId": 88,
-        "name": "/playground/textures/bloc.jpg",
-        "hasAlpha": false,
-        "getAlphaFromRGB": false,
-        "level": 1,
-        "coordinatesIndex": 0,
-        "coordinatesMode": 0,
-        "wrapU": 1,
-        "wrapV": 1,
-        "wrapR": 1,
-        "anisotropicFilteringLevel": 4,
-        "isCube": false,
-        "is3D": false,
-        "gammaSpace": true,
-        "invertZ": false,
-        "lodLevelInAlpha": false,
-        "lodGenerationOffset": 0,
-        "lodGenerationScale": 0,
-        "linearSpecularLOD": false,
-        "isRenderTarget": false,
-        "animations": [],
-        "invertY": true,
-        "samplingMode": 3
-      }
-    },
-    {
-      "customType": "BABYLON.InputBlock",
-      "id": 220,
-      "name": "uv",
-      "inputs": [],
-      "type": 4,
-      "mode": 1,
-      "wellKnownValue": null,
-      "animationType": 0,
-      "visibleInInspector": false
-    },
-    {
-      "customType": "BABYLON.TextureBlock",
-      "id": 221,
-      "name": "diffuseTexture2",
-      "inputs": [
-        {
-          "name": "uv",
-          "inputName": "uv",
-          "targetBlockId": 223,
-          "targetConnectionName": "output"
-        }
-      ],
-      "texture": {
-        "tags": null,
-        "url": "/playground/textures/crate.png",
-        "uOffset": 0,
-        "vOffset": 0,
-        "uScale": 1,
-        "vScale": 1,
-        "uAng": 0,
-        "vAng": 0,
-        "wAng": 0,
-        "uRotationCenter": 0.5,
-        "vRotationCenter": 0.5,
-        "wRotationCenter": 0.5,
-        "isBlocking": true,
-        "uniqueId": 90,
-        "name": "/playground/textures/crate.png",
-        "hasAlpha": false,
-        "getAlphaFromRGB": false,
-        "level": 1,
-        "coordinatesIndex": 0,
-        "coordinatesMode": 0,
-        "wrapU": 1,
-        "wrapV": 1,
-        "wrapR": 1,
-        "anisotropicFilteringLevel": 4,
-        "isCube": false,
-        "is3D": false,
-        "gammaSpace": true,
-        "invertZ": false,
-        "lodLevelInAlpha": false,
-        "lodGenerationOffset": 0,
-        "lodGenerationScale": 0,
-        "linearSpecularLOD": false,
-        "isRenderTarget": false,
-        "animations": [],
-        "invertY": true,
-        "samplingMode": 3
-      }
-    },
-    {
-      "customType": "BABYLON.InputBlock",
-      "id": 223,
-      "name": "uv",
-      "inputs": [],
-      "type": 4,
-      "mode": 1,
-      "wellKnownValue": null,
-      "animationType": 0,
-      "visibleInInspector": false
-    },
-    {
-      "customType": "BABYLON.InputBlock",
-      "id": 224,
-      "name": "time",
-      "inputs": [],
-      "type": 1,
-      "mode": 0,
-      "wellKnownValue": null,
-      "animationType": 0,
-      "visibleInInspector": false,
-      "valueType": "number",
-      "value": 1
-    },
-    {
-      "customType": "BABYLON.InputBlock",
-      "id": 225,
-      "name": "fogColor",
-      "inputs": [],
-      "type": 32,
-      "mode": 0,
-      "wellKnownValue": 8,
-      "animationType": 0,
-      "visibleInInspector": false,
-      "valueType": "BABYLON.Color3",
-      "value": [
-        1,
-        1,
-        1
-      ]
-    },
-    {
-      "customType": "BABYLON.FragmentOutputBlock",
-      "id": 226,
-      "name": "pixelOutput",
-      "inputs": [
-        {
-          "name": "rgba"
-        },
-        {
-          "name": "rgb",
-          "inputName": "rgb",
-          "targetBlockId": 524,
-          "targetConnectionName": "output"
-        },
-        {
-          "name": "a"
-        }
-      ]
-    },
-    {
-      "customType": "BABYLON.ScaleBlock",
-      "id": 524,
-      "name": "Scale",
-      "inputs": [
-        {
-          "name": "input",
-          "inputName": "input",
-          "targetBlockId": 213,
-          "targetConnectionName": "output"
-        },
-        {
-          "name": "factor",
-          "inputName": "factor",
-          "targetBlockId": 228,
-          "targetConnectionName": "fresnel"
-        }
-      ]
-    },
-    {
-      "customType": "BABYLON.FresnelBlock",
-      "id": 228,
-      "name": "Fresnel",
-      "inputs": [
-        {
-          "name": "worldPosition",
-          "inputName": "worldPosition",
-          "targetBlockId": 202,
-          "targetConnectionName": "output"
-        },
-        {
-          "name": "worldNormal",
-          "inputName": "worldNormal",
-          "targetBlockId": 229,
-          "targetConnectionName": "output"
-        },
-        {
-          "name": "cameraPosition",
-          "inputName": "cameraPosition",
-          "targetBlockId": 231,
-          "targetConnectionName": "output"
-        },
-        {
-          "name": "bias",
-          "inputName": "bias",
-          "targetBlockId": 232,
-          "targetConnectionName": "output"
-        },
-        {
-          "name": "power",
-          "inputName": "power",
-          "targetBlockId": 233,
-          "targetConnectionName": "output"
-        }
-      ]
-    },
-    {
-      "customType": "BABYLON.TransformBlock",
-      "id": 229,
-      "name": "Transform",
-      "inputs": [
-        {
-          "name": "vector",
-          "inputName": "vector",
-          "targetBlockId": 230,
-          "targetConnectionName": "output"
-        },
-        {
-          "name": "transform",
-          "inputName": "transform",
-          "targetBlockId": 208,
-          "targetConnectionName": "output"
-        }
-      ],
-      "complementZ": 0,
-      "complementW": 1
-    },
-    {
-      "customType": "BABYLON.InputBlock",
-      "id": 230,
-      "name": "normal",
-      "inputs": [],
-      "type": 8,
-      "mode": 1,
-      "wellKnownValue": null,
-      "animationType": 0,
-      "visibleInInspector": false
-    },
-    {
-      "customType": "BABYLON.InputBlock",
-      "id": 231,
-      "name": "Vector3",
-      "inputs": [],
-      "type": 8,
-      "mode": 0,
-      "wellKnownValue": 7,
-      "animationType": 0,
-      "visibleInInspector": false,
-      "valueType": "BABYLON.Vector3",
-      "value": [
-        0,
-        0,
-        0
-      ]
-    },
-    {
-      "customType": "BABYLON.InputBlock",
-      "id": 232,
-      "name": "Float",
-      "inputs": [],
-      "type": 1,
-      "mode": 0,
-      "wellKnownValue": null,
-      "animationType": 0,
-      "visibleInInspector": false,
-      "valueType": "number",
-      "value": 0
-    },
-    {
-      "customType": "BABYLON.InputBlock",
-      "id": 233,
-      "name": "Float",
-      "inputs": [],
-      "type": 1,
-      "mode": 0,
-      "wellKnownValue": null,
-      "animationType": 0,
-      "visibleInInspector": false,
-      "valueType": "number",
-      "value": 1
-    }
-  ],
-  "locations": [
-    {
-      "blockId": 200,
-      "x": 1500,
-      "y": 561.5
-    },
-    {
-      "blockId": 201,
-      "x": 1250,
-      "y": 548.5
-    },
-    {
-      "blockId": 202,
-      "x": 1000,
-      "y": 465
-    },
-    {
-      "blockId": 203,
-      "x": 750,
-      "y": 172
-    },
-    {
-      "blockId": 204,
-      "x": 500,
-      "y": 0
-    },
-    {
-      "blockId": 205,
-      "x": 500,
-      "y": 158
-    },
-    {
-      "blockId": 206,
-      "x": 500,
-      "y": 316
-    },
-    {
-      "blockId": 207,
-      "x": 500,
-      "y": 474
-    },
-    {
-      "blockId": 208,
-      "x": 750,
-      "y": 639
-    },
-    {
-      "blockId": 209,
-      "x": 500,
-      "y": 632
-    },
-    {
-      "blockId": 210,
-      "x": 500,
-      "y": 790
-    },
-    {
-      "blockId": 211,
-      "x": 500,
-      "y": 948
-    },
-    {
-      "blockId": 212,
-      "x": 1000,
-      "y": 842
-    },
-    {
-      "blockId": 213,
-      "x": 1473,
-      "y": 1109
-    },
-    {
-      "blockId": 214,
-      "x": 1000,
-      "y": 1000
-    },
-    {
-      "blockId": 215,
-      "x": 1000,
-      "y": 1158
-    },
-    {
-      "blockId": 216,
-      "x": 750,
-      "y": 1221
-    },
-    {
-      "blockId": 217,
-      "x": 500,
-      "y": 1137.5
-    },
-    {
-      "blockId": 218,
-      "x": 250,
-      "y": 931.5
-    },
-    {
-      "blockId": 220,
-      "x": 0,
-      "y": 999.5
-    },
-    {
-      "blockId": 221,
-      "x": 250,
-      "y": 1225.5
-    },
-    {
-      "blockId": 223,
-      "x": 0,
-      "y": 1293.5
-    },
-    {
-      "blockId": 224,
-      "x": 500,
-      "y": 1313.5
-    },
-    {
-      "blockId": 225,
-      "x": 1000,
-      "y": 1460
-    },
-    {
-      "blockId": 226,
-      "x": 2470.619469026549,
-      "y": 953.8318584070795
-    },
-    {
-      "blockId": 228,
-      "x": 1721.8141602372705,
-      "y": 789.0458809677541
-    },
-    {
-      "blockId": 229,
-      "x": 1176.0973460779783,
-      "y": 704.7538455695241
-    },
-    {
-      "blockId": 230,
-      "x": 989.1946912107215,
-      "y": 592.1874738881081
-    },
-    {
-      "blockId": 231,
-      "x": 1432.91148916599,
-      "y": 680.329066808462
-    },
-    {
-      "blockId": 232,
-      "x": 1411.6725511128925,
-      "y": 834.3113676934179
-    },
-    {
-      "blockId": 233,
-      "x": 1369.1946750066977,
-      "y": 962.8688898173117
-    },
-    {
-      "blockId": 524,
-      "x": 2063,
-      "y": 1078
-    }
-  ]
-}

+ 7 - 1
nodeEditor/src/blockTools.ts

@@ -24,7 +24,7 @@ import { DotBlock } from 'babylonjs/Materials/Node/Blocks/dotBlock';
 import { MultiplyBlock } from 'babylonjs/Materials/Node/Blocks/multiplyBlock';
 import { MultiplyBlock } from 'babylonjs/Materials/Node/Blocks/multiplyBlock';
 import { TransformBlock } from 'babylonjs/Materials/Node/Blocks/transformBlock';
 import { TransformBlock } from 'babylonjs/Materials/Node/Blocks/transformBlock';
 import { NodeMaterialBlockConnectionPointTypes } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPointTypes';
 import { NodeMaterialBlockConnectionPointTypes } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPointTypes';
-import { FresnelBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/fresnelBlock';
+import { FresnelBlock } from 'babylonjs/Materials/Node/Blocks/fresnelBlock';
 import { LerpBlock } from 'babylonjs/Materials/Node/Blocks/lerpBlock';
 import { LerpBlock } from 'babylonjs/Materials/Node/Blocks/lerpBlock';
 import { DivideBlock } from 'babylonjs/Materials/Node/Blocks/divideBlock';
 import { DivideBlock } from 'babylonjs/Materials/Node/Blocks/divideBlock';
 import { SubtractBlock } from 'babylonjs/Materials/Node/Blocks/subtractBlock';
 import { SubtractBlock } from 'babylonjs/Materials/Node/Blocks/subtractBlock';
@@ -32,6 +32,8 @@ import { StepBlock } from 'babylonjs/Materials/Node/Blocks/stepBlock';
 import { InputBlock } from 'babylonjs/Materials/Node/Blocks/Input/inputBlock';
 import { InputBlock } from 'babylonjs/Materials/Node/Blocks/Input/inputBlock';
 import { NodeMaterialWellKnownValues } from 'babylonjs/Materials/Node/nodeMaterialWellKnownValues';
 import { NodeMaterialWellKnownValues } from 'babylonjs/Materials/Node/nodeMaterialWellKnownValues';
 import { AnimatedInputBlockTypes } from 'babylonjs/Materials/Node/Blocks/Input/animatedInputBlockTypes';
 import { AnimatedInputBlockTypes } from 'babylonjs/Materials/Node/Blocks/Input/animatedInputBlockTypes';
+import { OppositeBlock } from 'babylonjs/Materials/Node/Blocks/oppositeBlock';
+import { ViewDirectionBlock } from 'babylonjs/Materials/Node/Blocks/viewDirectionBlock';
 
 
 export class BlockTools {
 export class BlockTools {
     public static GetBlockFromString(data: string) {
     public static GetBlockFromString(data: string) {
@@ -96,6 +98,10 @@ export class BlockTools {
                 return new SubtractBlock("Subtract"); 
                 return new SubtractBlock("Subtract"); 
             case "StepBlock":
             case "StepBlock":
                 return new StepBlock("Step");        
                 return new StepBlock("Step");        
+            case "OppositeBlock":
+                return new OppositeBlock("Opposite");      
+            case "ViewDirectionBlock":
+                return new ViewDirectionBlock("View direction");                    
             case "CosBlock": {
             case "CosBlock": {
                 let cosBlock = new TrigonometryBlock("Cos");
                 let cosBlock = new TrigonometryBlock("Cos");
                 cosBlock.operation = TrigonometryBlockOperations.Cos;
                 cosBlock.operation = TrigonometryBlockOperations.Cos;

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

@@ -26,7 +26,7 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
         // Block types used to create the menu from
         // Block types used to create the menu from
         const allBlocks = {
         const allBlocks = {
             Animation: ["BonesBlock", "MorphTargetsBlock"],
             Animation: ["BonesBlock", "MorphTargetsBlock"],
-            Basic_Math: ["AddBlock",  "DivideBlock", "MultiplyBlock", "ScaleBlock", "SubtractBlock"],
+            Basic_Math: ["AddBlock",  "DivideBlock", "MultiplyBlock", "ScaleBlock", "SubtractBlock", "OppositeBlock"],
             Conversion_Blocks: ["ColorMergerBlock", "ColorSplitterBlock", "VectorMergerBlock", "VectorSplitterBlock"],
             Conversion_Blocks: ["ColorMergerBlock", "ColorSplitterBlock", "VectorMergerBlock", "VectorSplitterBlock"],
             Inputs: ["Float", "Vector2", "Vector3", "Vector4", "Color3", "Color4", "TextureBlock", "TimeBlock"],
             Inputs: ["Float", "Vector2", "Vector3", "Vector4", "Color3", "Color4", "TextureBlock", "TimeBlock"],
             Interpolation: ["LerpBlock"],
             Interpolation: ["LerpBlock"],
@@ -35,7 +35,7 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
             Output_Blocks: ["VertexOutputBlock", "FragmentOutputBlock", "AlphaTestBlock"],
             Output_Blocks: ["VertexOutputBlock", "FragmentOutputBlock", "AlphaTestBlock"],
             Range: ["ClampBlock", "RemapBlock", "NormalizeBlock"],
             Range: ["ClampBlock", "RemapBlock", "NormalizeBlock"],
             Round: ["StepBlock", "RoundBlock", "CeilingBlock", "FloorBlock"],
             Round: ["StepBlock", "RoundBlock", "CeilingBlock", "FloorBlock"],
-            Scene_Attributes: ["FogBlock", "CameraPositionBlock", "FogColorBlock", "ImageProcessingBlock", "LightBlock", "ReflectionTextureBlock"],
+            Scene_Attributes: ["FogBlock", "CameraPositionBlock", "FogColorBlock", "ImageProcessingBlock", "LightBlock", "ReflectionTextureBlock", "ViewDirectionBlock"],
             Trigonometry: ["CosBlock", "SinBlock", "AbsBlock", "ExpBlock", "Exp2Block"],
             Trigonometry: ["CosBlock", "SinBlock", "AbsBlock", "ExpBlock", "Exp2Block"],
             Vector_Math: ["CrossBlock", "DotBlock", "TransformBlock", "FresnelBlock"],
             Vector_Math: ["CrossBlock", "DotBlock", "TransformBlock", "FresnelBlock"],
         }
         }

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

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

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

@@ -84,10 +84,14 @@ export class LightBlock extends NodeMaterialBlock {
         return this._outputs[1];
         return this._outputs[1];
     }
     }
 
 
-    public autoConfigure() {
+    public autoConfigure(material: NodeMaterial) {
         if (!this.cameraPosition.isConnected) {
         if (!this.cameraPosition.isConnected) {
-            let cameraPositionInput = new InputBlock("cameraPosition");
-            cameraPositionInput.setAsWellKnownValue(NodeMaterialWellKnownValues.CameraPosition);
+            let cameraPositionInput = material.getInputBlockByPredicate(b => b.wellKnownValue === NodeMaterialWellKnownValues.CameraPosition)
+            
+            if (!cameraPositionInput) {
+                cameraPositionInput = new InputBlock("cameraPosition");
+                cameraPositionInput.setAsWellKnownValue(NodeMaterialWellKnownValues.CameraPosition);
+            }
             cameraPositionInput.output.connectTo(this.cameraPosition);
             cameraPositionInput.output.connectTo(this.cameraPosition);
         }
         }
     }
     }

+ 25 - 9
src/Materials/Node/Blocks/Dual/reflectionTextureBlock.ts

@@ -144,28 +144,44 @@ export class ReflectionTextureBlock extends NodeMaterialBlock {
         return this._outputs[3];
         return this._outputs[3];
     }
     }
 
 
-    public autoConfigure() {
+    public autoConfigure(material: NodeMaterial) {
         if (!this.position.isConnected) {
         if (!this.position.isConnected) {
-            let positionInput = new InputBlock("position");
-            positionInput.setAsAttribute();
+            let positionInput = material.getInputBlockByPredicate(b => b.isAttribute && b.name === "position");
+           
+            if (!positionInput) {
+                positionInput = new InputBlock("position");
+                positionInput.setAsAttribute();
+            }
             positionInput.output.connectTo(this.position);
             positionInput.output.connectTo(this.position);
         }
         }
 
 
         if (!this.world.isConnected) {
         if (!this.world.isConnected) {
-            let worldInput = new InputBlock("world");
-            worldInput.setAsWellKnownValue(NodeMaterialWellKnownValues.World);
+            let worldInput = material.getInputBlockByPredicate(b => b.wellKnownValue === NodeMaterialWellKnownValues.World);
+            
+            if (!worldInput) {
+                worldInput = new InputBlock("world");
+                worldInput.setAsWellKnownValue(NodeMaterialWellKnownValues.World);
+            }
             worldInput.output.connectTo(this.world);
             worldInput.output.connectTo(this.world);
         }
         }
 
 
         if (!this.cameraPosition.isConnected) {
         if (!this.cameraPosition.isConnected) {
-            let cameraPositionInput = new InputBlock("cameraPosition");
-            cameraPositionInput.setAsWellKnownValue(NodeMaterialWellKnownValues.CameraPosition);
+            let cameraPositionInput = material.getInputBlockByPredicate(b => b.wellKnownValue === NodeMaterialWellKnownValues.CameraPosition);
+
+            if (!cameraPositionInput) {
+                cameraPositionInput = new InputBlock("cameraPosition");
+                cameraPositionInput.setAsWellKnownValue(NodeMaterialWellKnownValues.CameraPosition);
+            }
             cameraPositionInput.output.connectTo(this.cameraPosition);
             cameraPositionInput.output.connectTo(this.cameraPosition);
         }
         }
 
 
         if (!this.view.isConnected) {
         if (!this.view.isConnected) {
-            let viewInput = new InputBlock("view");
-            viewInput.setAsWellKnownValue(NodeMaterialWellKnownValues.View);
+            let viewInput = material.getInputBlockByPredicate(b => b.wellKnownValue === NodeMaterialWellKnownValues.View);
+
+            if (!viewInput) {
+                viewInput = new InputBlock("view");
+                viewInput.setAsWellKnownValue(NodeMaterialWellKnownValues.View);
+            }
             viewInput.output.connectTo(this.view);
             viewInput.output.connectTo(this.view);
         }
         }
     }
     }

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

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

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

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

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

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

+ 20 - 8
src/Materials/Node/Blocks/Vertex/bonesBlock.ts

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

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

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

+ 26 - 10
src/Materials/Node/Blocks/Vertex/morphTargetsBlock.ts

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

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

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

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

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

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

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

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

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

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

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