浏览代码

Merge pull request #9138 from Popov72/nme-postprocess

NME: improvements to post processes
Popov72 4 年之前
父节点
当前提交
5ad4d5c99d

+ 1 - 0
dist/preview release/what's new.md

@@ -358,3 +358,4 @@
 - `SceneLoaderProgress` class is now `ISceneLoaderProgress` interface ([bghgary](https://github.com/bghgary))
 - Rendering of transparent meshes: stencil state is now set to the value registered in the engine (when calling `engine.setStencilBuffer(value)`) instead of being set to `false` unconditionally. This change may affect the highlight layer when using transparent meshes. If you are impacted, you may need to exclude the transparent mesh(es) from the layer ([Popov72](https://github.com/Popov72))
 - Fix width/height GUI container computation to take into account paddings when `adaptWithToChildren = true` ([Popov72](https://github.com/Popov72))
+- `smoothstep` in NME is now taking any type of parameters for its `value` input. If you use generated code from the NME ("Generate code" button), you may have to move the smoothstep output connection AFTER the input connections ([Popov72](https://github.com/Popov72))

+ 145 - 136
nodeEditor/src/sharedComponents/floatLineComponent.tsx

@@ -1,136 +1,145 @@
-import * as React from "react";
-
-import { Observable } from "babylonjs/Misc/observable";
-import { PropertyChangedEvent } from "./propertyChangedEvent";
-import { GlobalState } from '../globalState';
-
-interface IFloatLineComponentProps {
-    label: string;
-    target: any;
-    propertyName: string;
-    onChange?: (newValue: number) => void;
-    isInteger?: boolean;
-    onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
-    additionalClass?: string;
-    step?: string,
-    digits?: number;
-    globalState: GlobalState
-    min?: number
-    max?: number
-    smallUI?: boolean;
-    onEnter?: (newValue:number) => void;
-}
-
-export class FloatLineComponent extends React.Component<IFloatLineComponentProps, { value: string }> {
-    private _localChange = false;
-    private _store: number;
-
-    constructor(props: IFloatLineComponentProps) {
-        super(props);
-        let currentValue = this.props.target[this.props.propertyName];
-        this.state = { value: currentValue ? (this.props.isInteger ? currentValue.toFixed(0) : currentValue.toFixed(this.props.digits || 2)) : "0" };
-        this._store = currentValue;
-    }
-
-    shouldComponentUpdate(nextProps: IFloatLineComponentProps, nextState: { value: string }) {
-        if (this._localChange) {
-            this._localChange = false;
-            return true;
-        }
-
-        const newValue = nextProps.target[nextProps.propertyName];
-        const newValueString = newValue ? this.props.isInteger ? newValue.toFixed(0) : newValue.toFixed(this.props.digits || 2) : "0";
-
-        if (newValueString !== nextState.value) {
-            nextState.value = newValueString;
-            return true;
-        }
-        return false;
-    }
-
-    raiseOnPropertyChanged(newValue: number, previousValue: number) {
-        if (this.props.onChange) {
-            this.props.onChange(newValue);
-        }
-
-        if (!this.props.onPropertyChangedObservable) {
-            return;
-        }
-        this.props.onPropertyChangedObservable.notifyObservers({
-            object: this.props.target,
-            property: this.props.propertyName,
-            value: newValue,
-            initialValue: previousValue
-        });
-    }
-
-    updateValue(valueString: string) {
-
-        if (/[^0-9\.\-]/g.test(valueString)) {
-            return;
-        }
-
-        valueString = valueString.replace(/(.+\...).+/, "$1");
-
-        let valueAsNumber: number;
-
-        if (this.props.isInteger) {
-            valueAsNumber = parseInt(valueString);
-        } else {
-            valueAsNumber = parseFloat(valueString);
-        }
-
-        this._localChange = true;
-        this.setState({ value: valueString});
-
-        if (isNaN(valueAsNumber)) {
-            return;
-        }
-        if(this.props.max != undefined && (valueAsNumber > this.props.max)) {
-            valueAsNumber = this.props.max;
-        }
-        if(this.props.min != undefined && (valueAsNumber < this.props.min)) {
-            valueAsNumber = this.props.min;
-        }
-
-        this.props.target[this.props.propertyName] = valueAsNumber;
-        this.raiseOnPropertyChanged(valueAsNumber, this._store);
-
-        this._store = valueAsNumber;
-    }
-
-    render() {
-        let className = this.props.smallUI ? "short": "value";
-
-        return (
-            <div>
-                {
-                    <div className={this.props.additionalClass ? this.props.additionalClass + " floatLine" : "floatLine"}>
-                        <div className="label">
-                            {this.props.label}
-                        </div>
-                        <div className={className}>
-                            <input type="number" step={this.props.step || "0.01"} className="numeric-input"
-                            onBlur={evt => {
-                                this.props.globalState.blockKeyboardEvents = false;
-                                if(this.props.onEnter) {
-                                    this.props.onEnter(this._store);
-                                }
-                            }}
-                            onKeyDown={evt => {
-                                if (evt.keyCode !== 13) {
-                                    return;
-                                }
-                                if(this.props.onEnter) {
-                                    this.props.onEnter(this._store);
-                                }
-                            }}
-                            onFocus={() => this.props.globalState.blockKeyboardEvents = true}
-                            value={this.state.value} onChange={evt => this.updateValue(evt.target.value)} />
-                        </div>
-                    </div>
-                }
-            </div>
-        );
-    }
-}
+import * as React from "react";
+
+import { Observable } from "babylonjs/Misc/observable";
+import { PropertyChangedEvent } from "./propertyChangedEvent";
+import { GlobalState } from '../globalState';
+
+interface IFloatLineComponentProps {
+    label: string;
+    target: any;
+    propertyName: string;
+    onChange?: (newValue: number) => void;
+    isInteger?: boolean;
+    onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
+    additionalClass?: string;
+    step?: string;
+    digits?: number;
+    globalState: GlobalState;
+    min?: number
+    max?: number
+    smallUI?: boolean;
+    onEnter?: (newValue:number) => void;
+}
+
+export class FloatLineComponent extends React.Component<IFloatLineComponentProps, { value: string }> {
+    private _localChange = false;
+    private _store: number;
+    private _regExp: RegExp;
+
+    constructor(props: IFloatLineComponentProps) {
+        super(props);
+        let currentValue = this.props.target[this.props.propertyName];
+        this.state = { value: currentValue ? (this.props.isInteger ? currentValue.toFixed(0) : currentValue.toFixed(this.props.digits || 2)) : "0" };
+        this._store = currentValue;
+
+        let rexp = "(.*\\.";
+        let numDigits = this.props.digits || 2;
+        while (numDigits--) {
+            rexp += ".";
+        }
+        rexp += ").+";
+
+        this._regExp = new RegExp(rexp);
+    }
+
+    shouldComponentUpdate(nextProps: IFloatLineComponentProps, nextState: { value: string }) {
+        if (this._localChange) {
+            this._localChange = false;
+            return true;
+        }
+
+        const newValue = nextProps.target[nextProps.propertyName];
+        const newValueString = newValue ? this.props.isInteger ? newValue.toFixed(0) : newValue.toFixed(this.props.digits || 2) : "0";
+
+        if (newValueString !== nextState.value) {
+            nextState.value = newValueString;
+            return true;
+        }
+        return false;
+    }
+
+    raiseOnPropertyChanged(newValue: number, previousValue: number) {
+        if (this.props.onChange) {
+            this.props.onChange(newValue);
+        }
+
+        if (!this.props.onPropertyChangedObservable) {
+            return;
+        }
+        this.props.onPropertyChangedObservable.notifyObservers({
+            object: this.props.target,
+            property: this.props.propertyName,
+            value: newValue,
+            initialValue: previousValue
+        });
+    }
+
+    updateValue(valueString: string) {
+        if (/[^0-9\.\-]/g.test(valueString)) {
+            return;
+        }
+
+        valueString = valueString.replace(this._regExp, "$1");
+
+        let valueAsNumber: number;
+
+        if (this.props.isInteger) {
+            valueAsNumber = parseInt(valueString);
+        } else {
+            valueAsNumber = parseFloat(valueString);
+        }
+
+        this._localChange = true;
+        this.setState({ value: valueString});
+
+        if (isNaN(valueAsNumber)) {
+            return;
+        }
+        if(this.props.max != undefined && (valueAsNumber > this.props.max)) {
+            valueAsNumber = this.props.max;
+        }
+        if(this.props.min != undefined && (valueAsNumber < this.props.min)) {
+            valueAsNumber = this.props.min;
+        }
+
+        this.props.target[this.props.propertyName] = valueAsNumber;
+        this.raiseOnPropertyChanged(valueAsNumber, this._store);
+
+        this._store = valueAsNumber;
+    }
+
+    render() {
+        let className = this.props.smallUI ? "short": "value";
+
+        return (
+            <div>
+                {
+                    <div className={this.props.additionalClass ? this.props.additionalClass + " floatLine" : "floatLine"}>
+                        <div className="label">
+                            {this.props.label}
+                        </div>
+                        <div className={className}>
+                            <input type="number" step={this.props.step || "0.01"} className="numeric-input"
+                            onBlur={(evt) => {
+                                this.props.globalState.blockKeyboardEvents = false;
+                                if(this.props.onEnter) {
+                                    this.props.onEnter(this._store);
+                                }
+                            }}
+                            onKeyDown={evt => {
+                                if (evt.keyCode !== 13) {
+                                    return;
+                                }
+                                if(this.props.onEnter) {
+                                    this.props.onEnter(this._store);
+                                }
+                            }}
+                            onFocus={() => this.props.globalState.blockKeyboardEvents = true}
+                            value={this.state.value} onChange={(evt) => this.updateValue(evt.target.value)} />
+                        </div>
+                    </div>
+                }
+            </div>
+        );
+    }
+}

+ 10 - 34
src/Materials/Node/Blocks/Dual/currentScreenBlock.ts

@@ -47,7 +47,7 @@ export class CurrentScreenBlock extends NodeMaterialBlock {
     public constructor(name: string) {
         super(name, NodeMaterialBlockTargets.VertexAndFragment);
 
-        this._isUnique = true;
+        this._isUnique = false;
 
         this.registerInput("uv", NodeMaterialBlockConnectionPointTypes.Vector2, false, NodeMaterialBlockTargets.VertexAndFragment);
 
@@ -61,7 +61,7 @@ export class CurrentScreenBlock extends NodeMaterialBlock {
         this._inputs[0].acceptedConnectionPointTypes.push(NodeMaterialBlockConnectionPointTypes.Vector3);
         this._inputs[0].acceptedConnectionPointTypes.push(NodeMaterialBlockConnectionPointTypes.Vector4);
 
-        this._inputs[0]._prioritizeVertex = true;
+        this._inputs[0]._prioritizeVertex = false;
     }
 
     /**
@@ -130,8 +130,6 @@ export class CurrentScreenBlock extends NodeMaterialBlock {
     }
 
     public get target() {
-        // TextureBlock has a special optimizations for uvs that come from the vertex shaders as they can be packed into a single varyings.
-        // But we need to detect uvs coming from fragment then
         if (!this.uv.isConnected) {
             return NodeMaterialBlockTargets.VertexAndFragment;
         }
@@ -140,32 +138,7 @@ export class CurrentScreenBlock extends NodeMaterialBlock {
             return NodeMaterialBlockTargets.VertexAndFragment;
         }
 
-        let parent = this.uv.connectedPoint;
-
-        while (parent) {
-            if (parent.target === NodeMaterialBlockTargets.Fragment) {
-                return NodeMaterialBlockTargets.Fragment;
-            }
-
-            if (parent.target === NodeMaterialBlockTargets.Vertex) {
-                return NodeMaterialBlockTargets.VertexAndFragment;
-            }
-
-            if (parent.target === NodeMaterialBlockTargets.Neutral || parent.target === NodeMaterialBlockTargets.VertexAndFragment) {
-                let parentBlock = parent.ownerBlock;
-
-                parent = null;
-                for (var input of parentBlock.inputs) {
-                    if (input.connectedPoint) {
-                        parent = input.connectedPoint;
-                        break;
-                    }
-                }
-            }
-
-        }
-
-        return NodeMaterialBlockTargets.VertexAndFragment;
+        return NodeMaterialBlockTargets.Fragment;
     }
 
     public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
@@ -261,18 +234,21 @@ export class CurrentScreenBlock extends NodeMaterialBlock {
     protected _buildBlock(state: NodeMaterialBuildState) {
         super._buildBlock(state);
 
-        if (state.target === NodeMaterialBlockTargets.Vertex) {
-            this._tempTextureRead = state._getFreeVariableName("tempTextureRead");
-
-            state._emit2DSampler(this._samplerName);
+        this._tempTextureRead = state._getFreeVariableName("tempTextureRead");
 
+        if (state.sharedData.blockingBlocks.indexOf(this) < 0) {
             state.sharedData.blockingBlocks.push(this);
+        }
+        if (state.sharedData.textureBlocks.indexOf(this) < 0) {
             state.sharedData.textureBlocks.push(this);
+        }
+        if (state.sharedData.blocksWithDefines.indexOf(this) < 0) {
             state.sharedData.blocksWithDefines.push(this);
         }
 
         if (state.target !== NodeMaterialBlockTargets.Fragment) {
             // Vertex
+            state._emit2DSampler(this._samplerName);
             this._injectVertexCode(state);
             return;
         }

+ 1 - 1
src/Materials/Node/Blocks/Particle/particleTextureBlock.ts

@@ -46,7 +46,7 @@ export class ParticleTextureBlock extends NodeMaterialBlock {
     public constructor(name: string) {
         super(name, NodeMaterialBlockTargets.Fragment);
 
-        this._isUnique = true;
+        this._isUnique = false;
 
         this.registerInput("uv", NodeMaterialBlockConnectionPointTypes.Vector2, false, NodeMaterialBlockTargets.VertexAndFragment);
 

+ 3 - 2
src/Materials/Node/Blocks/smoothStepBlock.ts

@@ -15,11 +15,12 @@ export class SmoothStepBlock extends NodeMaterialBlock {
     public constructor(name: string) {
         super(name, NodeMaterialBlockTargets.Neutral);
 
-        this.registerInput("value", NodeMaterialBlockConnectionPointTypes.Float);
+        this.registerInput("value", NodeMaterialBlockConnectionPointTypes.AutoDetect);
         this.registerInput("edge0", NodeMaterialBlockConnectionPointTypes.Float);
         this.registerInput("edge1", NodeMaterialBlockConnectionPointTypes.Float);
-        this.registerOutput("output", NodeMaterialBlockConnectionPointTypes.Float);
+        this.registerOutput("output", NodeMaterialBlockConnectionPointTypes.BasedOnInput);
 
+        this._outputs[0]._typeConnectionSource = this._inputs[0];
     }
 
     /**

+ 4 - 2
src/Materials/Node/nodeMaterialBuildState.ts

@@ -171,8 +171,10 @@ export class NodeMaterialBuildState {
 
     /** @hidden */
     public _emit2DSampler(name: string) {
-        this._samplerDeclaration += `uniform sampler2D ${name};\r\n`;
-        this.samplers.push(name);
+        if (this.samplers.indexOf(name) < 0) {
+            this._samplerDeclaration += `uniform sampler2D ${name};\r\n`;
+            this.samplers.push(name);
+        }
     }
 
     /** @hidden */

+ 1 - 1
tests/validation/config.json

@@ -74,7 +74,7 @@
         },                     
         {
             "title": "Node material #6",
-            "playgroundId": "#2XY3Z4#0",
+            "playgroundId": "#2XY3Z4#1",
             "referenceImage": "node-material6.png"
         },    
         {