|
@@ -0,0 +1,139 @@
|
|
|
+import { NodeMaterialBlock } from '../../nodeMaterialBlock';
|
|
|
+import { NodeMaterialBlockConnectionPointTypes } from '../../nodeMaterialBlockConnectionPointTypes';
|
|
|
+import { NodeMaterialBuildState } from '../../nodeMaterialBuildState';
|
|
|
+import { NodeMaterialBlockTargets } from '../../nodeMaterialBlockTargets';
|
|
|
+import { NodeMaterialConnectionPoint } from '../../nodeMaterialBlockConnectionPoint';
|
|
|
+import { _TypeStore } from '../../../../Misc/typeStore';
|
|
|
+import { NodeMaterial, NodeMaterialDefines } from '../../nodeMaterial';
|
|
|
+import { AbstractMesh } from '../../../../Meshes/abstractMesh';
|
|
|
+import { InputBlock } from '../Input/inputBlock';
|
|
|
+
|
|
|
+/**
|
|
|
+ * Block used to pertub normals based on a normal map
|
|
|
+ */
|
|
|
+export class PertubNormalBlock extends NodeMaterialBlock {
|
|
|
+ /**
|
|
|
+ * Create a new PertubNormalBlock
|
|
|
+ * @param name defines the block name
|
|
|
+ */
|
|
|
+ public constructor(name: string) {
|
|
|
+ super(name, NodeMaterialBlockTargets.Fragment);
|
|
|
+
|
|
|
+ // Vertex
|
|
|
+ this.registerInput("worldPosition", NodeMaterialBlockConnectionPointTypes.Vector4, false, NodeMaterialBlockTargets.Fragment);
|
|
|
+ this.registerInput("worldNormal", NodeMaterialBlockConnectionPointTypes.Vector4, false, NodeMaterialBlockTargets.Fragment);
|
|
|
+ this.registerInput("uv", NodeMaterialBlockConnectionPointTypes.Vector2, false, NodeMaterialBlockTargets.Fragment);
|
|
|
+ this.registerInput("normalMapColor", NodeMaterialBlockConnectionPointTypes.Color3, false, NodeMaterialBlockTargets.Fragment);
|
|
|
+ this.registerInput("strength", NodeMaterialBlockConnectionPointTypes.Float, false, NodeMaterialBlockTargets.Fragment);
|
|
|
+
|
|
|
+ // Fragment
|
|
|
+ this.registerOutput("output", NodeMaterialBlockConnectionPointTypes.Vector4, NodeMaterialBlockTargets.Fragment);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Gets the current class name
|
|
|
+ * @returns the class name
|
|
|
+ */
|
|
|
+ public getClassName() {
|
|
|
+ return "PertubNormalBlock";
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 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 uv input component
|
|
|
+ */
|
|
|
+ public get uv(): NodeMaterialConnectionPoint {
|
|
|
+ return this._inputs[2];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Gets the normal map color input component
|
|
|
+ */
|
|
|
+ public get normalMapColor(): NodeMaterialConnectionPoint {
|
|
|
+ return this._inputs[3];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Gets the strength input component
|
|
|
+ */
|
|
|
+ public get strength(): NodeMaterialConnectionPoint {
|
|
|
+ return this._inputs[4];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Gets the output component
|
|
|
+ */
|
|
|
+ public get output(): NodeMaterialConnectionPoint {
|
|
|
+ return this._outputs[0];
|
|
|
+ }
|
|
|
+
|
|
|
+ public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
|
|
|
+ defines.setValue("BUMP", true);
|
|
|
+ }
|
|
|
+
|
|
|
+ public autoConfigure(material: NodeMaterial) {
|
|
|
+ if (!this.uv.isConnected) {
|
|
|
+ let uvInput = material.getInputBlockByPredicate((b) => b.isAttribute && b.name === "uv");
|
|
|
+
|
|
|
+ if (!uvInput) {
|
|
|
+ uvInput = new InputBlock("uv");
|
|
|
+ uvInput.setAsAttribute();
|
|
|
+ }
|
|
|
+ uvInput.output.connectTo(this.uv);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!this.strength.isConnected) {
|
|
|
+ let strengthInput = new InputBlock("strength");
|
|
|
+ strengthInput.value = 1.0;
|
|
|
+ strengthInput.output.connectTo(this.strength);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ protected _buildBlock(state: NodeMaterialBuildState) {
|
|
|
+ super._buildBlock(state);
|
|
|
+
|
|
|
+ let comments = `//${this.name}`;
|
|
|
+ let uv = this.uv;
|
|
|
+ let worldPosition = this.worldPosition;
|
|
|
+ let worldNormal = this.worldNormal;
|
|
|
+
|
|
|
+ state.sharedData.blocksWithDefines.push(this);
|
|
|
+
|
|
|
+ state._emitExtension("bump", "#extension GL_OES_standard_derivatives : enable");
|
|
|
+ state._emitFunctionFromInclude("bumpFragmentFunctions", comments, {
|
|
|
+ replaceStrings: [
|
|
|
+ { search: /vBumpInfos.y/g, replace: `1.0 / ${this.strength.associatedVariableName}`},
|
|
|
+ { search: /vTangentSpaceParams/g, replace: "vec2(1.0, 1.0)"},
|
|
|
+ { search: /vPositionW/g, replace: worldPosition.associatedVariableName + ".xyz"}
|
|
|
+ ]
|
|
|
+ });
|
|
|
+ state.compilationString += this._declareOutput(this.output, state) + " = vec4(0.);\r\n";
|
|
|
+ state.compilationString += state._emitCodeFromInclude("bumpFragment", comments, {
|
|
|
+ replaceStrings: [
|
|
|
+ { search: /perturbNormal\(TBN,vBumpUV\+uvOffset\)/g, replace: `perturbNormal(TBN, ${this.normalMapColor.associatedVariableName})` },
|
|
|
+ { search: /vBumpInfos.y/g, replace: `1.0 / ${this.strength.associatedVariableName}`},
|
|
|
+ { search: /vBumpUV/g, replace: uv.associatedVariableName},
|
|
|
+ { search: /vPositionW/g, replace: worldPosition.associatedVariableName + ".xyz"},
|
|
|
+ { search: /normalW=/g, replace: this.output.associatedVariableName + ".xyz = " },
|
|
|
+ { search: /normalW/g, replace: worldNormal.associatedVariableName + ".xyz" }
|
|
|
+ ]
|
|
|
+ });
|
|
|
+
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+_TypeStore.RegisteredTypes["BABYLON.PertubNormalBlock"] = PertubNormalBlock;
|