Browse Source

More fixes

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

+ 153 - 42
localDev/src/webgl-debug.js

@@ -103,102 +103,213 @@ var createNodeMaterial = function(scene) {
     var nodeMaterial = new BABYLON.NodeMaterial("node", scene, { emitComments: true });
     // nodeMaterial.setToDefault();
     // Blocks
-  
+
     // Vertex
     var positionInput = new BABYLON.InputBlock("position");
     positionInput.setAsAttribute("position");
-  
+
     var worldInput = new BABYLON.InputBlock("world");
     worldInput.setAsWellKnownValue(BABYLON.NodeMaterialWellKnownValues.World);
-  
+
     var worldPos = new BABYLON.Vector4TransformBlock("worldPos");
     positionInput.connectTo(worldPos);
     worldInput.connectTo(worldPos);
-  
+
     var normalInput = new BABYLON.InputBlock("normal");
     normalInput.setAsAttribute("normal");
-  
+
     var worldNormal = new BABYLON.Vector4TransformBlock("worldNormal");
     normalInput.connectTo(worldNormal);
     worldInput.connectTo(worldNormal);
-  
+
     var viewProjectionInput = new BABYLON.InputBlock("viewProjection");
     viewProjectionInput.setAsWellKnownValue(BABYLON.NodeMaterialWellKnownValues.ViewProjection);
-  
+
     var worldPosdMultipliedByViewProjection = new BABYLON.Vector4TransformBlock("worldPos * viewProjectionTransform");
     worldPos.connectTo(worldPosdMultipliedByViewProjection);
     viewProjectionInput.connectTo(worldPosdMultipliedByViewProjection);
-  
+
     var vertexOutput = new BABYLON.VertexOutputBlock("vertexOutput");
     worldPosdMultipliedByViewProjection.connectTo(vertexOutput);
-  
+
     // Pixel
     var colorInput = new BABYLON.InputBlock("color");
     colorInput.value = new BABYLON.Color4(1, 0, 0, 1);
-  
+
     var colorMultiplier2 = new BABYLON.MultiplyBlock("color multiplier2");
-    
+
     var diffuseTextureBlock = new BABYLON.TextureBlock("diffuseTexture");
     diffuseTextureBlock.texture = new BABYLON.Texture("/playground/textures/bloc.jpg");
-  
+
     diffuseTextureBlock.connectTo(colorMultiplier2);
     colorInput.connectTo(colorMultiplier2);
-  
+
     var pixelOutput = new BABYLON.FragmentOutputBlock("pixelOutput");
     colorMultiplier2.connectTo(pixelOutput);
-  
+
     // Add to nodes
     nodeMaterial.addOutputNode(vertexOutput);
     nodeMaterial.addOutputNode(pixelOutput);
-  
+
     // Build
     nodeMaterial.build(true);
-  
+
     scene.debugLayer.show();
     scene.debugLayer.select(nodeMaterial);
-  
+
     return nodeMaterial;
-  }
-  
-  var createScene = function() {
-  
+}
+
+var createScene = function() {
+
     // This creates a basic Babylon Scene object (non-mesh)
     var scene = new BABYLON.Scene(engine);
-  
+
     // This creates and positions a free camera (non-mesh)
     var camera = new BABYLON.ArcRotateCamera("camera1", 1.14, 1.13, 10, BABYLON.Vector3.Zero(), scene);
-  
+
     // This targets the camera to scene origin
     camera.setTarget(BABYLON.Vector3.Zero());
-  
+
     // This attaches the camera to the canvas
     camera.attachControl(canvas, true);
-  
+
     // This creates a light, aiming 0,1,0 - to the sky (non-mesh)
     var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
-  
+
     // Default intensity is 1. Let's dim the light a small amount
     light.intensity = 0.7;
-  
+
     var light2 = new BABYLON.PointLight("light2", new BABYLON.Vector3(0, -11, 5), scene);
-  
+
     // Default intensity is 1. Let's dim the light a small amount
     light2.intensity = 0.7;
-  
+
     // Our built-in 'sphere' shape. Params: name, subdivs, size, scene
     var sphere = BABYLON.Mesh.CreateSphere("sphere1", 16, 2, scene);
-  
+
     sphere.material = createNodeMaterial(scene);
-  
-  
+
+
     return scene;
-  
-  };
-  
-
-  // Must test:
-  - fog
-  - morph
-  - bones
-  - multi textures
-  - Direct connection from attributes to fragment output
+
+};
+
+
+/*
+    - morph
+    - bones
+    */
+
+
+var createNodeMaterial = function(scene) {
+    var nodeMaterial = new BABYLON.NodeMaterial("node", scene, { emitComments: true });
+    // nodeMaterial.setToDefault();
+    // Blocks
+
+    // Vertex
+    var positionInput = new BABYLON.InputBlock("position");
+    positionInput.setAsAttribute("position");
+
+    var worldInput = new BABYLON.InputBlock("world");
+    worldInput.setAsWellKnownValue(BABYLON.NodeMaterialWellKnownValues.World);
+
+    var worldPos = new BABYLON.Vector4TransformBlock("worldPos");
+    positionInput.connectTo(worldPos);
+    worldInput.connectTo(worldPos);
+
+    var normalInput = new BABYLON.InputBlock("normal");
+    normalInput.setAsAttribute("normal");
+
+    var worldNormal = new BABYLON.Vector4TransformBlock("worldNormal");
+    normalInput.connectTo(worldNormal);
+    worldInput.connectTo(worldNormal);
+
+    var viewProjectionInput = new BABYLON.InputBlock("viewProjection");
+    viewProjectionInput.setAsWellKnownValue(BABYLON.NodeMaterialWellKnownValues.ViewProjection);
+
+    var worldPosdMultipliedByViewProjection = new BABYLON.Vector4TransformBlock("worldPos * viewProjectionTransform");
+    worldPos.connectTo(worldPosdMultipliedByViewProjection);
+    viewProjectionInput.connectTo(worldPosdMultipliedByViewProjection);
+
+    var vertexOutput = new BABYLON.VertexOutputBlock("vertexOutput");
+    worldPosdMultipliedByViewProjection.connectTo(vertexOutput);
+
+    // Pixel
+    var colorInput = new BABYLON.InputBlock("color");
+    colorInput.value = new BABYLON.Color4(1, 0, 0, 1);
+
+    var colorMultiplier = new BABYLON.MultiplyBlock("color multiplier");
+
+    var diffuseTextureBlock = new BABYLON.TextureBlock("diffuseTexture");
+    diffuseTextureBlock.texture = new BABYLON.Texture("/playground/textures/bloc.jpg");
+
+    var diffuse2TextureBlock = new BABYLON.TextureBlock("diffuseTexture2");
+    diffuse2TextureBlock.texture = new BABYLON.Texture("/playground/textures/crate.png");
+
+    diffuseTextureBlock.connectTo(colorMultiplier);
+    diffuse2TextureBlock.connectTo(colorMultiplier);
+
+    var colorMultiplier2 = new BABYLON.MultiplyBlock("color multiplier2");
+
+    colorMultiplier.connectTo(colorMultiplier2);
+    colorInput.connectTo(colorMultiplier2);
+
+    var fog = new BABYLON.FogBlock("fog");
+    worldPos.connectTo(fog);
+    colorMultiplier2.connectTo(fog);
+
+    var pixelOutput = new BABYLON.FragmentOutputBlock("pixelOutput");
+    fog.connectTo(pixelOutput);
+
+    // Add to nodes
+    nodeMaterial.addOutputNode(vertexOutput);
+    nodeMaterial.addOutputNode(pixelOutput);
+
+    // Build
+    nodeMaterial.build(true);
+
+    scene.debugLayer.show();
+    scene.debugLayer.select(nodeMaterial);
+
+    return nodeMaterial;
+}
+
+var createScene = function() {
+
+    // This creates a basic Babylon Scene object (non-mesh)
+    var scene = new BABYLON.Scene(engine);
+
+    // This creates and positions a free camera (non-mesh)
+    var camera = new BABYLON.ArcRotateCamera("camera1", 1.14, 1.13, 10, BABYLON.Vector3.Zero(), scene);
+
+    // This targets the camera to scene origin
+    camera.setTarget(BABYLON.Vector3.Zero());
+
+    // This attaches the camera to the canvas
+    camera.attachControl(canvas, true);
+
+    // This creates a light, aiming 0,1,0 - to the sky (non-mesh)
+    var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
+
+    // Default intensity is 1. Let's dim the light a small amount
+    light.intensity = 0.7;
+
+    var light2 = new BABYLON.PointLight("light2", new BABYLON.Vector3(0, -11, 5), scene);
+
+    // Default intensity is 1. Let's dim the light a small amount
+    light2.intensity = 0.7;
+
+    // Our built-in 'sphere' shape. Params: name, subdivs, size, scene
+    var sphere = BABYLON.Mesh.CreateSphere("sphere1", 16, 2, scene);
+
+    sphere.material = createNodeMaterial(scene);
+
+    scene.fogMode = BABYLON.Scene.FOGMODE_LINEAR;
+    scene.fogColor = scene.clearColor.clone();
+    scene.fogStart = 2.0;
+    scene.fogEnd = 40.0;
+
+    return scene;
+
+};

+ 8 - 9
src/Materials/Node/Blocks/Dual/fogBlock.ts

@@ -15,6 +15,7 @@ import { InputBlock } from '../Input/inputBlock';
  * Block used to add support for scene fog
  */
 export class FogBlock extends NodeMaterialBlock {
+    private _fogDistanceName: string;
     /**
      * Create a new FogBlock
      * @param name defines the block name
@@ -26,8 +27,6 @@ export class FogBlock extends NodeMaterialBlock {
         this.registerInput("worldPosition", NodeMaterialBlockConnectionPointTypes.Vector4, false, NodeMaterialBlockTargets.Vertex);
         this.registerInput("view", NodeMaterialBlockConnectionPointTypes.Matrix, false, NodeMaterialBlockTargets.Vertex);
 
-        this.registerOutput("vFogDistance", NodeMaterialBlockConnectionPointTypes.Vector3, NodeMaterialBlockTargets.Vertex);
-
         // Fragment
         this.registerInput("color", NodeMaterialBlockConnectionPointTypes.Color3OrColor4, false, NodeMaterialBlockTargets.Fragment);
         this.registerInput("fogColor", NodeMaterialBlockConnectionPointTypes.Color3, false, NodeMaterialBlockTargets.Fragment);
@@ -93,12 +92,12 @@ export class FogBlock extends NodeMaterialBlock {
             viewInput.output.connectTo(this.view);
         }
         if (!this.fogColor.isConnected) {
-            let fogColorInput = new InputBlock("fogColor");
+            let fogColorInput = new InputBlock("fogColor", undefined, NodeMaterialBlockConnectionPointTypes.Color3);
             fogColorInput.setAsWellKnownValue(NodeMaterialWellKnownValues.Automatic);
             fogColorInput.output.connectTo(this.fogColor);
         }
         if (!this.fogParameters.isConnected) {
-            let fogParametersInput = new InputBlock("fogParameters");
+            let fogParametersInput = new InputBlock("fogParameters", undefined, NodeMaterialBlockConnectionPointTypes.Vector4);
             fogParametersInput.setAsWellKnownValue(NodeMaterialWellKnownValues.Automatic);
             fogParametersInput.output.connectTo(this.fogParameters);
         }
@@ -138,19 +137,19 @@ export class FogBlock extends NodeMaterialBlock {
             let color = this.color;
             let fogColor = this.fogColor;
             let fogParameters = this.fogParameters;
-            let output = this._outputs[1];
-            let vFogDistance = this._outputs[0];
+            let output = this._outputs[0];
 
             state.compilationString += `#ifdef FOG\r\n`;
-            state.compilationString += `float ${tempFogVariablename} = CalcFogFactor(${vFogDistance.associatedVariableName}, ${fogParameters.associatedVariableName});\r\n`;
+            state.compilationString += `float ${tempFogVariablename} = CalcFogFactor(${this._fogDistanceName}, ${fogParameters.associatedVariableName});\r\n`;
             state.compilationString += this._declareOutput(output, state) + ` = ${tempFogVariablename} * ${color.associatedVariableName}.rgb + (1.0 - ${tempFogVariablename}) * ${fogColor.associatedVariableName};\r\n`;
             state.compilationString += `#else\r\n${this._declareOutput(output, state)} =  ${color.associatedVariableName}.rgb;\r\n`;
             state.compilationString += `#endif\r\n`;
         } else {
             let worldPos = this.worldPosition;
             let view = this.view;
-            let vFogDistance = this._outputs[0];
-            state.compilationString += this._declareOutput(vFogDistance, state) + ` = (${view.associatedVariableName} * ${worldPos.associatedVariableName}).xyz;\r\n`;
+            this._fogDistanceName = state._getFreeVariableName("vFogDistance");
+            state._emitVaryingFromString(this._fogDistanceName, "vec3");
+            state.compilationString += `${this._fogDistanceName} = (${view.associatedVariableName} * ${worldPos.associatedVariableName}).xyz;\r\n`;
         }
 
         return this;

+ 1 - 1
src/Materials/Node/Blocks/Dual/lightBlock.ts

@@ -143,7 +143,7 @@ export class LightBlock extends NodeMaterialBlock {
         let worldPosVaryingName = "v_" + worldPos.associatedVariableName;
         state._emitVaryingFromString(worldPosVaryingName, "vec3");
 
-        let worldNormalVaryingName = "v_" + worldNormal.associatedVariableName;     
+        let worldNormalVaryingName = "v_" + worldNormal.associatedVariableName;
         state._emitVaryingFromString(worldNormalVaryingName, "vec3");
 
         state.compilationString += `${worldPosVaryingName} = ${worldPos.associatedVariableName}.xyz;\r\n`;

+ 2 - 2
src/Materials/Node/Blocks/Fragment/fragmentOutputBlock.ts

@@ -19,7 +19,7 @@ export class FragmentOutputBlock extends NodeMaterialBlock {
     public constructor(name: string) {
         super(name, NodeMaterialBlockTargets.Fragment, true);
 
-        this.registerInput("color", NodeMaterialBlockConnectionPointTypes.Vector2OrColor3OrColor4);
+        this.registerInput("color", NodeMaterialBlockConnectionPointTypes.Vector2OrVector3OrColor3OrVector4OrColor4);
     }
 
     /**
@@ -45,7 +45,7 @@ export class FragmentOutputBlock extends NodeMaterialBlock {
 
         if (input.connectedPoint && input.connectedPoint!.type === NodeMaterialBlockConnectionPointTypes.Vector2) {
             state.compilationString += `gl_FragColor = vec4(${input.associatedVariableName}.r, ${input.associatedVariableName}.g, 0., 1.0);\r\n`;
-        } else if (input.connectedPoint && input.connectedPoint!.type === NodeMaterialBlockConnectionPointTypes.Color3) {
+        } else if (input.connectedPoint && (input.connectedPoint!.type === NodeMaterialBlockConnectionPointTypes.Color3 || input.connectedPoint!.type === NodeMaterialBlockConnectionPointTypes.Vector3)) {
             state.compilationString += `gl_FragColor = vec4(${input.associatedVariableName}, 1.0);\r\n`;
         } else {
             state.compilationString += `gl_FragColor = ${input.associatedVariableName};\r\n`;

+ 7 - 7
src/Materials/Node/Blocks/Fragment/textureBlock.ts

@@ -15,7 +15,6 @@ import { Mesh } from '../../../../Meshes/mesh';
  */
 export class TextureBlock extends NodeMaterialBlock {
     private _defineName: string;
-    private _mainUVDefineName: string;
     private _samplerName: string;
     private _transformedUVName: string;
     private _textureTransformName: string;
@@ -32,7 +31,7 @@ export class TextureBlock extends NodeMaterialBlock {
      * @param name defines the block name
      */
     public constructor(name: string) {
-        super(name, NodeMaterialBlockTargets.Fragment);
+        super(name, NodeMaterialBlockTargets.VertexAndFragment);
 
         this.registerInput("uv", NodeMaterialBlockConnectionPointTypes.Vector2, false);
 
@@ -76,10 +75,8 @@ export class TextureBlock extends NodeMaterialBlock {
 
         if (!this.texture.getTextureMatrix().isIdentityAs3x2()) {
             defines.setValue(this._defineName, true);
-            defines.setValue(this._mainUVDefineName, false);
         } else {
             defines.setValue(this._defineName, false);
-            defines.setValue(this._mainUVDefineName, true);
         }
     }
 
@@ -106,7 +103,6 @@ export class TextureBlock extends NodeMaterialBlock {
 
         // Inject code in vertex
         this._defineName = state._getFreeDefineName("UVTRANSFORM");
-        this._mainUVDefineName = ("vMain" + uvInput.associatedVariableName).toUpperCase();
 
         this._mainUVName = "vMain" + uvInput.associatedVariableName;
         this._transformedUVName = state._getFreeVariableName("transformedUV");
@@ -114,9 +110,9 @@ export class TextureBlock extends NodeMaterialBlock {
         this._textureInfoName = state._getFreeVariableName("textureInfoName");
 
         state._emitVaryingFromString(this._transformedUVName, "vec2", this._defineName);
-        state._emitVaryingFromString(this._mainUVName, "vec2", this._mainUVDefineName);
+        state._emitVaryingFromString(this._mainUVName, "vec2", this._defineName, true);
 
-        state._emitUniformFromString(this._transformedUVName, "mat4", this._defineName)
+        state._emitUniformFromString(this._textureTransformName, "mat4", this._defineName)
 
         if (state.sharedData.emitComments) {
             state.compilationString += `\r\n//${this.name}\r\n`;
@@ -131,6 +127,10 @@ export class TextureBlock extends NodeMaterialBlock {
     protected _buildBlock(state: NodeMaterialBuildState) {
         super._buildBlock(state);
 
+        if (state.target !== NodeMaterialBlockTargets.Fragment) {
+            return;
+        }
+
         state.sharedData.blockingBlocks.push(this);
 
         this._samplerName = state._getFreeVariableName(this.name + "Sampler");

+ 4 - 1
src/Materials/Node/nodeMaterial.ts

@@ -75,7 +75,10 @@ export class NodeMaterialDefines extends MaterialDefines implements IImageProces
             this._keys.push(name);
         }
 
-        this[name] = value;
+        if (this[name] !== value) {
+            this[name] = value;
+            this.markAsUnprocessed();
+        }
     }
 }
 

+ 43 - 9
src/Materials/Node/nodeMaterialBlock.ts

@@ -7,12 +7,14 @@ import { Effect, EffectFallbacks } from '../effect';
 import { AbstractMesh } from '../../Meshes/abstractMesh';
 import { Mesh } from '../../Meshes/mesh';
 import { NodeMaterial, NodeMaterialDefines } from './nodeMaterial';
+import { InputBlock } from './Blocks';
 
 /**
  * Defines a block that can be used inside a node based material
  */
 export class NodeMaterialBlock {
     private _buildId: number;
+    private _buildTarget: NodeMaterialBlockTargets;
     private _target: NodeMaterialBlockTargets;
     private _isFinalMerger = false;
     private _isInput = false;
@@ -306,6 +308,18 @@ export class NodeMaterialBlock {
         // Do nothing
     }
 
+
+    /**
+     * Initialize defines for shader compilation
+     * @param mesh defines the mesh to be rendered
+     * @param nodeMaterial defines the node material requesting the update
+     * @param defines defines the material defines to be prepared
+     * @param useInstances specifies that instances should be used
+     */
+    public initializeDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, useInstances: boolean = false) {
+        // Do nothing
+    }
+
     /**
      * Lets the block try to connect some inputs automatically
      */
@@ -336,14 +350,31 @@ export class NodeMaterialBlock {
         return true;
     }
 
+    private _processBuild(block: NodeMaterialBlock, state: NodeMaterialBuildState, input: NodeMaterialConnectionPoint) {
+        block.build(state);
+
+        if (state._vertexState && (block.target & this.target) === 0) { // context switch! We need a varying
+            if ((!block.isInput && state.target !== block._buildTarget) // block was already emitted by vertex shader
+                || (block.isInput && (block as InputBlock).isAttribute) // block is an attribute
+            ) {
+                let connectedPoint = input.connectedPoint!;
+                state._vertexState._emitVaryingFromString("v_" + connectedPoint.associatedVariableName, state._getGLType(connectedPoint.type));
+                state._vertexState.compilationString += `${"v_" + connectedPoint.associatedVariableName} = ${connectedPoint.associatedVariableName};\r\n`;
+                input.associatedVariableName = "v_" + connectedPoint.associatedVariableName;
+                input._enforceAssociatedVariableName = true;
+            }
+        }
+    }
+
     /**
      * Compile the current node and generate the shader code
      * @param state defines the current compilation state (uniforms, samplers, current string)
-     * @returns the current block
+     * @param contextSwitched indicates that the previous block was built for a different context (vertex vs. fragment)
+     * @returns true if already built
      */
-    public build(state: NodeMaterialBuildState) {
+    public build(state: NodeMaterialBuildState, contextSwitched = false): boolean {
         if (this._buildId === state.sharedData.buildId) {
-            return;
+            return true;
         }
 
         // Check if "parent" blocks are compiled
@@ -364,13 +395,13 @@ export class NodeMaterialBlock {
             }
 
             let block = input.connectedPoint.ownerBlock;
-            if (block && block !== this && block.buildId !== state.sharedData.buildId) {
-                block.build(state);
+            if (block && block !== this) {
+                this._processBuild(block, state, input);
             }
         }
 
         if (this._buildId === state.sharedData.buildId) {
-            return; // Need to check again as inputs can be connected multiple time to this endpoint
+            return true; // Need to check again as inputs can be connected multiple time to this endpoint
         }
 
         // Logs
@@ -413,6 +444,7 @@ export class NodeMaterialBlock {
         this._buildBlock(state);
 
         this._buildId = state.sharedData.buildId;
+        this._buildTarget = state.target;
 
         // Compile connected blocks
         for (var output of this._outputs) {
@@ -420,12 +452,14 @@ export class NodeMaterialBlock {
                 continue;
             }
 
-            for (var block of output.connectedBlocks) {
+            for (var endpoint of output.endpoints) {
+                let block = endpoint.ownerBlock;
+
                 if (block && (block.target & state.target) !== 0) {
-                    block.build(state);
+                    this._processBuild(block, state, endpoint);
                 }
             }
         }
-        return this;
+        return false;
     }
 }

+ 12 - 1
src/Materials/Node/nodeMaterialBlockConnectionPoint.ts

@@ -22,6 +22,9 @@ export class NodeMaterialConnectionPoint {
 
     private _type = NodeMaterialBlockConnectionPointTypes.Float;
 
+    /** @hidden */
+    public _enforceAssociatedVariableName = false;
+
     /**
      * Gets or sets the associated variable name in the shader
      */
@@ -30,7 +33,7 @@ export class NodeMaterialConnectionPoint {
             return (this._ownerBlock as InputBlock).associatedVariableName;
         }
 
-        if (this._connectedPoint) {
+        if (!this._enforceAssociatedVariableName && this._connectedPoint) {
             return this._connectedPoint.associatedVariableName;
         }
 
@@ -142,6 +145,11 @@ export class NodeMaterialConnectionPoint {
         return this._endpoints.map((e) => e.ownerBlock);
     }
 
+    /** Gets the list of connected endpoints */
+    public get endpoints() {
+        return this, this._endpoints;
+    }
+
     /**
      * Creates a new connection point
      * @param name defines the connection point name
@@ -213,6 +221,8 @@ export class NodeMaterialConnectionPoint {
 
         this._endpoints.push(connectionPoint);
         connectionPoint._connectedPoint = this;
+
+        this._enforceAssociatedVariableName = false;
         return this;
     }
 
@@ -230,6 +240,7 @@ export class NodeMaterialConnectionPoint {
 
         this._endpoints.splice(index, 1);
         endpoint._connectedPoint = null;
+        this._enforceAssociatedVariableName = false;
         return this;
     }
 }

+ 3 - 1
src/Materials/Node/nodeMaterialBlockConnectionPointTypes.ts

@@ -28,8 +28,10 @@ export enum NodeMaterialBlockConnectionPointTypes {
     Color3OrColor4 = Color3 | Color4,
     /** Vector2 or Color3 or Color4 */
     Vector2OrColor3OrColor4 = Vector2 | Color3 | Color4,
-    /** Vector3 or Color3 */
+    /** Vector3 or Color3 or Color4 or Vector4 */
     Vector3OrColor3OrVector4OrColor4 = Vector3 | Color3 | Vector4 | Color4,
+    /** Vector2 or Vector3 or Color3 or Color4 or Vector4 */
+    Vector2OrVector3OrColor3OrVector4OrColor4 = Vector2 | Vector3 | Color3 | Vector4 | Color4,
     /** Detect type based on connection */
     AutoDetect = 1024,
     /** Output type that will be defined by input type */

+ 6 - 8
src/Materials/Node/nodeMaterialBuildState.ts

@@ -1,9 +1,7 @@
-import { NodeMaterialConnectionPoint } from './nodeMaterialBlockConnectionPoint';
 import { NodeMaterialBlockConnectionPointTypes } from './nodeMaterialBlockConnectionPointTypes';
 import { NodeMaterialBlockTargets } from './nodeMaterialBlockTargets';
 import { NodeMaterialBuildStateSharedData } from './nodeMaterialBuildStateSharedData';
 import { Effect } from '../effect';
-import { Nullable } from '../../types';
 
 /**
  * Class used to store node based material build state
@@ -275,7 +273,7 @@ export class NodeMaterialBuildState {
     }
 
     /** @hidden */
-    public _emitVaryingFromString(name: string, type: string, define: string = "") {
+    public _emitVaryingFromString(name: string, type: string, define: string = "", notDefine = false) {
         if (this.sharedData.varyings.indexOf(name) !== -1) {
             return;
         }
@@ -283,7 +281,7 @@ export class NodeMaterialBuildState {
         this.sharedData.varyings.push(name);
 
         if (define) {
-            this.sharedData.varyingDeclaration += `#ifdef ${define}\r\n`;
+            this.sharedData.varyingDeclaration += `${notDefine ? "#ifndef" : "#ifdef"} ${define}\r\n`;
         }
         this.sharedData.varyingDeclaration += `varying ${type} ${name};\r\n`;
         if (define) {
@@ -291,17 +289,17 @@ export class NodeMaterialBuildState {
         }
     }
 
-    
+
     /** @hidden */
-    public _emitUniformFromString(name: string, type: string, define: string = "") {
+    public _emitUniformFromString(name: string, type: string, define: string = "", notDefine = false) {
         if (this.uniforms.indexOf(name) !== -1) {
             return;
         }
 
         this.uniforms.push(name);
-        
+
         if (define) {
-            this._uniformDeclaration += `#ifdef ${define}\r\n`;
+            this._uniformDeclaration += `${notDefine ? "#ifndef" : "#ifdef"} ${define}\r\n`;
         }
         this._uniformDeclaration += `uniform ${type} ${name};\r\n`;
         if (define) {