UNPKG

@babylonjs/core

Version:

Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.

173 lines 7.95 kB
import { NodeMaterialBlock } from "../../nodeMaterialBlock.js"; import { NodeMaterialBlockConnectionPointTypes } from "../../Enums/nodeMaterialBlockConnectionPointTypes.js"; import { NodeMaterialBlockTargets } from "../../Enums/nodeMaterialBlockTargets.js"; import { RegisterClass } from "../../../../Misc/typeStore.js"; import { NodeMaterialConnectionPointCustomObject } from "../../nodeMaterialConnectionPointCustomObject.js"; import { NodeMaterialSystemValues } from "../../Enums/nodeMaterialSystemValues.js"; import { InputBlock } from "../Input/inputBlock.js"; /** * Block used to implement TBN matrix */ export class TBNBlock extends NodeMaterialBlock { /** * Create a new TBNBlock * @param name defines the block name */ constructor(name) { super(name, NodeMaterialBlockTargets.Fragment, true); this.registerInput("normal", NodeMaterialBlockConnectionPointTypes.AutoDetect, false); this.normal.addExcludedConnectionPointFromAllowedTypes(NodeMaterialBlockConnectionPointTypes.Color4 | NodeMaterialBlockConnectionPointTypes.Vector4 | NodeMaterialBlockConnectionPointTypes.Vector3); this.registerInput("tangent", NodeMaterialBlockConnectionPointTypes.Vector4, false); this.registerInput("world", NodeMaterialBlockConnectionPointTypes.Matrix, false); this.registerOutput("TBN", NodeMaterialBlockConnectionPointTypes.Object, NodeMaterialBlockTargets.Fragment, new NodeMaterialConnectionPointCustomObject("TBN", this, 1 /* NodeMaterialConnectionPointDirection.Output */, TBNBlock, "TBNBlock")); this.registerOutput("row0", NodeMaterialBlockConnectionPointTypes.Vector3, NodeMaterialBlockTargets.Fragment); this.registerOutput("row1", NodeMaterialBlockConnectionPointTypes.Vector3, NodeMaterialBlockTargets.Fragment); this.registerOutput("row2", NodeMaterialBlockConnectionPointTypes.Vector3, NodeMaterialBlockTargets.Fragment); } /** * Gets the current class name * @returns the class name */ getClassName() { return "TBNBlock"; } /** * Initialize the block and prepare the context for build * @param state defines the state that will be used for the build */ initialize(state) { state._excludeVariableName("tbnNormal"); state._excludeVariableName("tbnTangent"); state._excludeVariableName("tbnBitangent"); state._excludeVariableName("TBN"); } /** * Gets the normal input component */ get normal() { return this._inputs[0]; } /** * Gets the tangent input component */ get tangent() { return this._inputs[1]; } /** * Gets the world matrix input component */ get world() { return this._inputs[2]; } /** * Gets the TBN output component */ // eslint-disable-next-line @typescript-eslint/naming-convention get TBN() { return this._outputs[0]; } /** * Gets the row0 of the output matrix */ get row0() { return this._outputs[1]; } /** * Gets the row1 of the output matrix */ get row1() { return this._outputs[2]; } /** * Gets the row2 of the output matrix */ get row2() { return this._outputs[3]; } get target() { return NodeMaterialBlockTargets.Fragment; } set target(value) { } autoConfigure(material, additionalFilteringInfo = () => true) { if (!this.world.isConnected) { let worldInput = material.getInputBlockByPredicate((b) => b.isSystemValue && b.systemValue === NodeMaterialSystemValues.World && additionalFilteringInfo(b)); if (!worldInput) { worldInput = new InputBlock("world"); worldInput.setAsSystemValue(NodeMaterialSystemValues.World); } worldInput.output.connectTo(this.world); } if (!this.normal.isConnected) { let normalInput = material.getInputBlockByPredicate((b) => b.isAttribute && b.name === "normal" && additionalFilteringInfo(b)); if (!normalInput) { normalInput = new InputBlock("normal"); normalInput.setAsAttribute("normal"); } normalInput.output.connectTo(this.normal); } if (!this.tangent.isConnected) { let tangentInput = material.getInputBlockByPredicate((b) => b.isAttribute && b.name === "tangent" && b.type === NodeMaterialBlockConnectionPointTypes.Vector4 && additionalFilteringInfo(b)); if (!tangentInput) { tangentInput = new InputBlock("tangent"); tangentInput.setAsAttribute("tangent"); } tangentInput.output.connectTo(this.tangent); } } prepareDefines(mesh, nodeMaterial, defines) { const normal = this.normal; const tangent = this.tangent; let normalAvailable = normal.isConnected; if (normal.connectInputBlock?.isAttribute && !mesh.isVerticesDataPresent(normal.connectInputBlock?.name)) { normalAvailable = false; } let tangentAvailable = tangent.isConnected; if (tangent.connectInputBlock?.isAttribute && !mesh.isVerticesDataPresent(tangent.connectInputBlock?.name)) { tangentAvailable = false; } const useTBNBlock = normalAvailable && tangentAvailable; defines.setValue("TBNBLOCK", useTBNBlock, true); } _buildBlock(state) { super._buildBlock(state); const normal = this.normal; const tangent = this.tangent; const world = this.world; const TBN = this.TBN; const row0 = this.row0; const row1 = this.row1; const row2 = this.row2; const isWebGPU = state.shaderLanguage === 1 /* ShaderLanguage.WGSL */; const mat3 = isWebGPU ? "mat3x3f" : "mat3"; const fSuffix = isWebGPU ? "f" : ""; // Fragment if (state.target === NodeMaterialBlockTargets.Fragment) { state.compilationString += ` // ${this.name} ${state._declareLocalVar("tbnNormal", NodeMaterialBlockConnectionPointTypes.Vector3)} = normalize(${normal.associatedVariableName}).xyz; ${state._declareLocalVar("tbnTangent", NodeMaterialBlockConnectionPointTypes.Vector3)} = normalize(${tangent.associatedVariableName}.xyz); ${state._declareLocalVar("tbnBitangent", NodeMaterialBlockConnectionPointTypes.Vector3)} = cross(tbnNormal, tbnTangent) * ${tangent.associatedVariableName}.w; ${isWebGPU ? "var" : "mat3"} ${TBN.associatedVariableName} = ${mat3}(${world.associatedVariableName}[0].xyz, ${world.associatedVariableName}[1].xyz, ${world.associatedVariableName}[2].xyz) * ${mat3}(tbnTangent, tbnBitangent, tbnNormal); `; if (row0.hasEndpoints) { state.compilationString += state._declareOutput(row0) + ` = vec3${fSuffix}(${TBN.associatedVariableName}[0][0], ${TBN.associatedVariableName}[0][1], ${TBN.associatedVariableName}[0][2]);\n`; } if (row1.hasEndpoints) { state.compilationString += state._declareOutput(row1) + ` = vec3${fSuffix}(${TBN.associatedVariableName}[1[0], ${TBN.associatedVariableName}[1][1], ${TBN.associatedVariableName}[1][2]);\n`; } if (row2.hasEndpoints) { state.compilationString += state._declareOutput(row2) + ` = vec3${fSuffix}(${TBN.associatedVariableName}[2][0], ${TBN.associatedVariableName}[2][1], ${TBN.associatedVariableName}[2][2]);\n`; } state.sharedData.blocksWithDefines.push(this); } return this; } } RegisterClass("BABYLON.TBNBlock", TBNBlock); //# sourceMappingURL=TBNBlock.js.map