浏览代码

Add the particle uv & color inputs

Popov72 5 年之前
父节点
当前提交
94b6732cc0

+ 10 - 0
nodeEditor/src/blockTools.ts

@@ -468,8 +468,18 @@ export class BlockTools {
                 return new SubSurfaceBlock("SubSurface");
             case "CurrentScreenBlock":
                 return new CurrentScreenBlock("CurrentScreen");
+            case "ParticleUVBlock": {
+                let uv = new InputBlock("uv");
+                uv.setAsAttribute("particle_uv");
+                return uv;
+            }
             case "ParticleTextureBlock":
                 return new ParticleTextureBlock("ParticleTexture");
+            case "ParticleColorBlock": {
+                let color = new InputBlock("Color");
+                color.setAsAttribute("particle_color");
+                return color;
+            }
         }
 
         return null;

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

@@ -133,7 +133,9 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
         "SubSurfaceBlock": "PBR SubSurface block",
         "Position2DBlock": "A Vector2 representing the position of each vertex of the screen quad",
         "CurrentScreenBlock": "The screen buffer used as input for the post process",
+        "ParticleUVBlock": "The particle uv texture coordinate",
         "ParticleTextureBlock": "The particle texture",
+        "ParticleColorBlock": "The particle color",
     };
 
     constructor(props: INodeListComponentProps) {

+ 14 - 2
nodeEditor/src/diagram/display/inputDisplayManager.ts

@@ -9,6 +9,18 @@ import { Color3 } from 'babylonjs/Maths/math.color';
 import { BlockTools } from '../../blockTools';
 import { StringTools } from '../../stringTools';
 
+const inputNameToAttributeValue: { [name: string] : string } = {
+    "position2d" : "position",
+    "particle_uv" : "uv",
+    "particle_color" : "color",
+};
+
+const inputNameToAttributeName: { [name: string] : string } = {
+    "position2d" : "postprocess",
+    "particle_uv" : "particle",
+    "particle_color" : "particle",
+};
+
 export class InputDisplayManager implements IDisplayManager {
     public getHeaderClass(block: NodeMaterialBlock) {
         let inputBlock = block as InputBlock;
@@ -64,8 +76,8 @@ export class InputDisplayManager implements IDisplayManager {
         let inputBlock = block as InputBlock;
 
         if (inputBlock.isAttribute) {
-            const attrVal = inputBlock.name === 'position2d' ? 'position' : inputBlock.name;
-            const attrName = inputBlock.name === 'position2d' ? 'postprocess' : 'mesh';
+            const attrVal = inputNameToAttributeValue[inputBlock.name] ?? inputBlock.name;
+            const attrName = inputNameToAttributeName[inputBlock.name] ?? 'mesh';
             value = attrName + "." + attrVal;
         } else if (inputBlock.isSystemValue) {
             switch (inputBlock.systemValue) {

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

@@ -173,11 +173,13 @@ export class TextureBlock extends NodeMaterialBlock {
                     uvInput.connectTo(this);
                 }
             } else {
-                let uvInput = material.getInputBlockByPredicate((b) => b.isAttribute && b.name === "uv");
+                const attributeName = material.mode === NodeMaterialModes.Particle ? "particle_uv" : "uv";
+
+                let uvInput = material.getInputBlockByPredicate((b) => b.isAttribute && b.name === attributeName);
 
                 if (!uvInput) {
                     uvInput = new InputBlock("uv");
-                    uvInput.setAsAttribute();
+                    uvInput.setAsAttribute(attributeName);
                 }
                 uvInput.output.connectTo(this.uv);
             }

+ 35 - 8
src/Materials/Node/Blocks/Input/inputBlock.ts

@@ -15,6 +15,17 @@ import { AnimatedInputBlockTypes } from './animatedInputBlockTypes';
 import { Observable } from '../../../../Misc/observable';
 import { MaterialHelper } from '../../../../Materials/materialHelper';
 
+const remapAttributeName: { [name: string]: string }  = {
+    "position2d": "position",
+    "particle_uv": "vUV",
+    "particle_color": "vColor",
+};
+
+export const attributeInFragmentOnly: { [name: string]: boolean }  = {
+    "particle_uv": true,
+    "particle_color": true,
+};
+
 /**
  * Block used to expose an input value
  */
@@ -96,6 +107,7 @@ export class InputBlock extends NodeMaterialBlock {
                     case "uv":
                     case "uv2":
                     case "position2d":
+                    case "particle_uv":
                         this._type = NodeMaterialBlockConnectionPointTypes.Vector2;
                         return this._type;
                     case "matricesIndices":
@@ -107,6 +119,7 @@ export class InputBlock extends NodeMaterialBlock {
                         this._type = NodeMaterialBlockConnectionPointTypes.Vector4;
                         return this._type;
                     case "color":
+                    case "particle_color":
                         this._type = NodeMaterialBlockConnectionPointTypes.Color4;
                         return this._type;
                 }
@@ -393,6 +406,11 @@ export class InputBlock extends NodeMaterialBlock {
         return "";
     }
 
+    /** @hidden */
+    public get _noContextSwitch(): boolean {
+        return attributeInFragmentOnly[this.name];
+    }
+
     private _emit(state: NodeMaterialBuildState, define?: string) {
         // Uniforms
         if (this.isUniform) {
@@ -444,10 +462,14 @@ export class InputBlock extends NodeMaterialBlock {
 
         // Attribute
         if (this.isAttribute) {
-            this.associatedVariableName = this.name === 'position2d' ? 'position' : this.name;
+            this.associatedVariableName = remapAttributeName[this.name] ?? this.name;
 
             if (this.target === NodeMaterialBlockTargets.Vertex && state._vertexState) { // Attribute for fragment need to be carried over by varyings
-                this._emit(state._vertexState, define);
+                if (attributeInFragmentOnly[this.name]) {
+                    state._emitVaryingFromString(this.associatedVariableName, state._getGLType(this.type), define);
+                } else {
+                    this._emit(state._vertexState, define);
+                }
                 return;
             }
 
@@ -456,12 +478,17 @@ export class InputBlock extends NodeMaterialBlock {
             }
 
             state.attributes.push(this.associatedVariableName);
-            if (define) {
-                state._attributeDeclaration += this._emitDefine(define);
-            }
-            state._attributeDeclaration += `attribute ${state._getGLType(this.type)} ${this.associatedVariableName};\r\n`;
-            if (define) {
-                state._attributeDeclaration += `#endif\r\n`;
+
+            if (attributeInFragmentOnly[this.name]) {
+                state._emitVaryingFromString(this.associatedVariableName, state._getGLType(this.type), define);
+            } else {
+                if (define) {
+                    state._attributeDeclaration += this._emitDefine(define);
+                }
+                state._attributeDeclaration += `attribute ${state._getGLType(this.type)} ${this.associatedVariableName};\r\n`;
+                if (define) {
+                    state._attributeDeclaration += `#endif\r\n`;
+                }
             }
         }
     }

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

@@ -425,7 +425,7 @@ export class NodeMaterialBlock {
             (this.target !== NodeMaterialBlockTargets.VertexAndFragment && otherBlockWasGeneratedInVertexShader)
             )) { // context switch! We need a varying
             if ((!block.isInput && state.target !== block._buildTarget) // block was already emitted by vertex shader
-                || (block.isInput && (block as InputBlock).isAttribute) // block is an attribute
+                || (block.isInput && (block as InputBlock).isAttribute && !(block as InputBlock)._noContextSwitch) // block is an attribute
             ) {
                 let connectedPoint = input.connectedPoint!;
                 if (state._vertexState._emitVaryingFromString("v_" + connectedPoint.associatedVariableName, state._getGLType(connectedPoint.type))) {