David Catuhe пре 6 година
родитељ
комит
4897e91bd3

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

@@ -23,6 +23,7 @@ import { Vector3TransformBlock } from 'babylonjs/Materials/Node/Blocks/vector3Tr
 import { Vector4TransformBlock } from 'babylonjs/Materials/Node/Blocks/vector4TransformBlock';
 import { NodeMaterialBlock } from 'babylonjs/Materials/Node/nodeMaterialBlock';
 import { ScaleBlock } from 'babylonjs/Materials/Node/Blocks/scaleBlock';
+import { LightBlock } from 'babylonjs/Materials/Node/Blocks/Dual/lightBlock';
 
 require("./nodeList.scss");
 
@@ -37,7 +38,7 @@ export class NodeListComponent extends React.Component<INodeListComponentProps>
         // Block types used to create the menu from
         const allBlocks = {
             Vertex: [BonesBlock, InstancesBlock, MorphTargetsBlock],
-            Fragment: [AlphaTestBlock, , ImageProcessingBlock, RGBAMergerBlock, RGBASplitterBlock, TextureBlock],
+            Fragment: [AlphaTestBlock, , ImageProcessingBlock, RGBAMergerBlock, RGBASplitterBlock, TextureBlock, LightBlock],
             Outputs: [VertexOutputBlock, FragmentOutputBlock],
             Dual: [FogBlock],
             Math: [AddBlock, ClampBlock, MatrixMultiplicationBlock, MultiplyBlock, ScaleBlock, Vector2TransformBlock, Vector3TransformBlock, Vector4TransformBlock],

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

@@ -1,2 +1,3 @@
 
-export * from "./fogBlock";
+export * from "./fogBlock";
+export * from "./lightBlock";

+ 32 - 10
src/Materials/Node/Blocks/Fragment/lightBlock.ts

@@ -6,8 +6,9 @@ import { NodeMaterialConnectionPoint } from '../../nodeMaterialBlockConnectionPo
 import { MaterialHelper } from '../../../materialHelper';
 import { AbstractMesh } from '../../../../Meshes/abstractMesh';
 import { NodeMaterial, NodeMaterialDefines } from '../../nodeMaterial';
-import { Effect } from '../../../../Materials/effect';
+import { Effect } from '../../../effect';
 import { Mesh } from '../../../../Meshes/mesh';
+import { NodeMaterialWellKnownValues } from '../../nodeMaterialWellKnownValues';
 
 /**
  * Block used to add light in the fragment shader
@@ -20,13 +21,15 @@ export class LightBlock extends NodeMaterialBlock {
      * @param name defines the block name
      */
     public constructor(name: string) {
-        super(name, NodeMaterialBlockTargets.Fragment);
+        super(name, NodeMaterialBlockTargets.VertexAndFragment);
 
-        this.registerInput("worldPosition", NodeMaterialBlockConnectionPointTypes.Vector4);
-        this.registerInput("worldNormal", NodeMaterialBlockConnectionPointTypes.Vector4);
-        this.registerInput("light", NodeMaterialBlockConnectionPointTypes.Light);
-        this.registerOutput("diffuseOutput", NodeMaterialBlockConnectionPointTypes.Color3);
-        this.registerOutput("specularOutput", NodeMaterialBlockConnectionPointTypes.Color3);
+        this.registerInput("worldPosition", NodeMaterialBlockConnectionPointTypes.Vector4, false, NodeMaterialBlockTargets.Vertex);
+        this.registerInput("worldNormal", NodeMaterialBlockConnectionPointTypes.Vector4, false, NodeMaterialBlockTargets.Vertex);
+
+        this.registerInput("light", NodeMaterialBlockConnectionPointTypes.Light, false, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("cameraPosition", NodeMaterialBlockConnectionPointTypes.Vector3, false, NodeMaterialBlockTargets.Fragment);
+        this.registerOutput("diffuseOutput", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
+        this.registerOutput("specularOutput", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
     }
 
     /**
@@ -59,6 +62,13 @@ export class LightBlock extends NodeMaterialBlock {
     }
 
     /**
+    * Gets the camera (or eye) position component
+    */
+    public get cameraPosition(): NodeMaterialConnectionPoint {
+        return this._inputs[3];
+    }
+
+    /**
      * Gets the diffuse output component
      */
     public get diffuseOutput(): NodeMaterialConnectionPoint {
@@ -72,6 +82,12 @@ export class LightBlock extends NodeMaterialBlock {
         return this._outputs[1];
     }
 
+    public autoConfigure() {
+        if (this.cameraPosition.isUndefined) {
+            this.cameraPosition.setAsWellKnownValue(NodeMaterialWellKnownValues.CameraPosition);
+        }
+    }
+
     public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
         if (!this.light.value) {
             return;
@@ -118,6 +134,10 @@ export class LightBlock extends NodeMaterialBlock {
     protected _buildBlock(state: NodeMaterialBuildState) {
         super._buildBlock(state);
 
+        if (state.target !== NodeMaterialBlockTargets.Fragment) {
+            return;
+        }
+
         // Vertex
         this._injectVertexCode(state._vertexState);
 
@@ -125,7 +145,7 @@ export class LightBlock extends NodeMaterialBlock {
         state.sharedData.bindableBlocks.push(this);
         state.sharedData.blocksWithDefines.push(this);
 
-        this._lightId = (state.counters["lightCounter"] | -1) + 1;
+        this._lightId = (state.counters["lightCounter"] !== undefined ? state.counters["lightCounter"] : -1) + 1;
         state.counters["lightCounter"] = this._lightId;
 
         let comments = `//${this.name}`;
@@ -139,15 +159,16 @@ export class LightBlock extends NodeMaterialBlock {
             ]
         });
 
-        state._emitFunctionFromInclude("lightFragmentDeclaration", comments, {
+        state._emitFunctionFromInclude(state.supportUniformBuffers ? "lightUboDeclaration" : "lightFragmentDeclaration", comments, {
             replaceStrings: [{ search: /{X}/g, replace: this._lightId.toString() }]
-        });
+        }, this._lightId.toString());
 
         // Uniforms and samplers
         MaterialHelper.PrepareUniformsAndSamplersForLight(this._lightId, state.uniforms, state.samplers, undefined, state.uniformBuffers);
 
         // Code
         if (this._lightId === 0) {
+            state.compilationString += `vec3 viewDirectionW = normalize(${this.cameraPosition.associatedVariableName} - ${"v_" + worldPos.associatedVariableName});\r\n`;
             state.compilationString += `lightingInfo info;\r\n`;
             state.compilationString += `float shadow = 1.;\r\n`;
             state.compilationString += `float glossiness = 0.;\r\n`;
@@ -166,6 +187,7 @@ export class LightBlock extends NodeMaterialBlock {
                 { search: /{X}/g, replace: this._lightId.toString() },
                 { search: /diffuseBase/g, replace: diffuseOutput.associatedVariableName },
                 { search: /specularBase/g, replace: specularOutput.associatedVariableName },
+                { search: /normalW/g, replace: "v_" + worldNormal.associatedVariableName }
             ]
         });
 

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

@@ -6,5 +6,4 @@ export * from "./rgbMergerBlock";
 export * from "./rgbaSplitterBlock";
 export * from "./rgbSplitterBlock";
 export * from "./textureBlock";
-export * from "./imageProcessingBlock";
-export * from "./lightBlock";
+export * from "./imageProcessingBlock";

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

@@ -411,6 +411,8 @@ export class NodeMaterial extends PushMaterial {
      */
     public build(verbose: boolean = false) {
         this._buildWasSuccessful = false;
+        var engine = this.getScene().getEngine();
+
         if (this._vertexOutputNodes.length === 0) {
             throw "You must define at least one vertexOutputNode";
         }
@@ -421,8 +423,10 @@ export class NodeMaterial extends PushMaterial {
 
         // Compilation state
         this._vertexCompilationState = new NodeMaterialBuildState();
+        this._vertexCompilationState.supportUniformBuffers = engine.supportsUniformBuffers;
         this._vertexCompilationState.target = NodeMaterialBlockTargets.Vertex;
         this._fragmentCompilationState = new NodeMaterialBuildState();
+        this._fragmentCompilationState.supportUniformBuffers = engine.supportsUniformBuffers;
         this._fragmentCompilationState.target = NodeMaterialBlockTargets.Fragment;
 
         // Shared data

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

@@ -383,6 +383,9 @@ export class NodeMaterialConnectionPoint {
                 case NodeMaterialWellKnownValues.ViewProjection:
                     effect.setMatrix(variableName, scene.getTransformMatrix());
                     break;
+                case NodeMaterialWellKnownValues.CameraPosition:
+                    effect.setVector3(variableName, scene.activeCamera!.globalPosition);
+                    break;
             }
             return;
         }

+ 18 - 15
src/Materials/Node/nodeMaterialBuildState.ts

@@ -10,6 +10,8 @@ import { Nullable } from '../../types';
  * Class used to store node based material build state
  */
 export class NodeMaterialBuildState {
+    /** Gets or sets a boolean indicating if the current state can emit uniform buffers */
+    public supportUniformBuffers = false;
     /**
      * Gets the list of emitted attributes
      */
@@ -216,55 +218,56 @@ export class NodeMaterialBuildState {
         removeVaryings?: boolean,
         removeIfDef?: boolean,
         replaceStrings?: { search: RegExp, replace: string }[],
-    }) {
-        if (this.functions[includeName]) {
+    }, storeKey: string = "") {
+        let key = includeName + storeKey;
+        if (this.functions[key]) {
             return;
         }
 
         if (!options || (!options.removeAttributes && !options.removeUniforms && !options.removeVaryings && !options.removeIfDef && !options.replaceStrings)) {
 
             if (options && options.repeatKey) {
-                this.functions[includeName] = `#include<${includeName}>[0..${options.repeatKey}]\r\n`;
+                this.functions[key] = `#include<${includeName}>[0..${options.repeatKey}]\r\n`;
             } else {
-                this.functions[includeName] = `#include<${includeName}>\r\n`;
+                this.functions[key] = `#include<${includeName}>\r\n`;
             }
 
             if (this.sharedData.emitComments) {
-                this.functions[includeName] = comments + `\r\n` + this.functions[includeName];
+                this.functions[key] = comments + `\r\n` + this.functions[key];
             }
 
             return;
         }
 
-        this.functions[includeName] = Effect.IncludesShadersStore[includeName];
+        this.functions[key] = Effect.IncludesShadersStore[includeName];
 
         if (this.sharedData.emitComments) {
-            this.functions[includeName] = comments + `\r\n` + this.functions[includeName];
+            this.functions[key] = comments + `\r\n` + this.functions[key];
         }
 
         if (options.removeIfDef) {
-            this.functions[includeName] = this.functions[includeName].replace(/^\s*?#ifdef.+$/gm, "");
-            this.functions[includeName] = this.functions[includeName].replace(/^\s*?#endif.*$/gm, "");
-            this.functions[includeName] = this.functions[includeName].replace(/^\s*?#else.*$/gm, "");
-            this.functions[includeName] = this.functions[includeName].replace(/^\s*?#elif.*$/gm, "");
+            this.functions[key] = this.functions[key].replace(/^\s*?#ifdef.+$/gm, "");
+            this.functions[key] = this.functions[key].replace(/^\s*?#endif.*$/gm, "");
+            this.functions[key] = this.functions[key].replace(/^\s*?#else.*$/gm, "");
+            this.functions[key] = this.functions[key].replace(/^\s*?#elif.*$/gm, "");
         }
 
         if (options.removeAttributes) {
-            this.functions[includeName] = this.functions[includeName].replace(/^\s*?attribute.+$/gm, "");
+            this.functions[key] = this.functions[key].replace(/^\s*?attribute.+$/gm, "");
         }
 
         if (options.removeUniforms) {
-            this.functions[includeName] = this.functions[includeName].replace(/^\s*?uniform.+$/gm, "");
+            this.functions[key] = this.functions[key].replace(/^\s*?uniform.+$/gm, "");
         }
 
         if (options.removeVaryings) {
-            this.functions[includeName] = this.functions[includeName].replace(/^\s*?varying.+$/gm, "");
+            this.functions[key] = this.functions[key].replace(/^\s*?varying.+$/gm, "");
         }
 
         if (options.replaceStrings) {
             for (var index = 0; index < options.replaceStrings.length; index++) {
                 let replaceString = options.replaceStrings[index];
-                this.functions[includeName] = this.functions[includeName].replace(replaceString.search, replaceString.replace);
+                this.functions[key] = this.functions[key].replace(replaceString.search, replaceString.replace);
             }
         }
     }

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

@@ -14,6 +14,8 @@ export enum NodeMaterialWellKnownValues {
     WorldView = 5,
     /** WorldViewProjection */
     WorldViewProjection = 6,
+    /** CameraPosition */
+    CameraPosition = 7,
     /** Will be filled by the block itself */
-    Automatic = 7
+    Automatic = 8
 }