|
@@ -43,6 +43,7 @@ export class ClearCoatBlock extends NodeMaterialBlock {
|
|
|
this.registerInput("tintAtDistance", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
|
|
|
this.registerInput("tintThickness", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
|
|
|
this.registerInput("tintTexture", NodeMaterialBlockConnectionPointTypes.Color4, true, NodeMaterialBlockTargets.Fragment);
|
|
|
+ this.registerInput("worldTangent", NodeMaterialBlockConnectionPointTypes.Vector4, true);
|
|
|
|
|
|
this.registerOutput("clearcoat", NodeMaterialBlockConnectionPointTypes.Object, NodeMaterialBlockTargets.Fragment,
|
|
|
new NodeMaterialConnectionPointCustomObject("clearcoat", this, NodeMaterialConnectionPointDirection.Output, ClearCoatBlock, "ClearCoatBlock"));
|
|
@@ -139,6 +140,13 @@ export class ClearCoatBlock extends NodeMaterialBlock {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
+ * Gets the world tangent input component
|
|
|
+ */
|
|
|
+ public get worldTangent(): NodeMaterialConnectionPoint {
|
|
|
+ return this._inputs[10];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
* Gets the clear coat object output component
|
|
|
*/
|
|
|
public get clearcoat(): NodeMaterialConnectionPoint {
|
|
@@ -188,15 +196,44 @@ export class ClearCoatBlock extends NodeMaterialBlock {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private _generateTBNSpace(state: NodeMaterialBuildState, worldPositionVarName: string, worldNormalVarName: string) {
|
|
|
+ let code = "";
|
|
|
+
|
|
|
+ let comments = `//${this.name}`;
|
|
|
+ let worldTangent = this.worldTangent;
|
|
|
+
|
|
|
+ state._emitExtension("derivatives", "#extension GL_OES_standard_derivatives : enable");
|
|
|
+
|
|
|
+ let tangentReplaceString = { search: /defined\(TANGENT\)/g, replace: worldTangent.isConnected ? "defined(TANGENT)" : "defined(IGNORE)" };
|
|
|
+
|
|
|
+ if (worldTangent.isConnected) {
|
|
|
+ code += `vec3 tbnNormal = normalize(${worldNormalVarName}.xyz);\r\n`;
|
|
|
+ code += `vec3 tbnTangent = normalize(${worldTangent.associatedVariableName}.xyz);\r\n`;
|
|
|
+ code += `vec3 tbnBitangent = cross(tbnNormal, tbnTangent);\r\n`;
|
|
|
+ code += `mat3 vTBN = mat3(tbnTangent, tbnBitangent, tbnNormal);\r\n`;
|
|
|
+ }
|
|
|
+
|
|
|
+ state._emitFunctionFromInclude("bumpFragmentMainFunctions", comments, {
|
|
|
+ replaceStrings: [
|
|
|
+ tangentReplaceString,
|
|
|
+ ]
|
|
|
+ });
|
|
|
+
|
|
|
+ return code;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Gets the main code of the block (fragment side)
|
|
|
* @param state current state of the node material building
|
|
|
* @param ccBlock instance of a ClearCoatBlock or null if the code must be generated without an active clear coat module
|
|
|
* @param reflectionBlock instance of a ReflectionBlock null if the code must be generated without an active reflection module
|
|
|
* @param worldPosVarName name of the variable holding the world position
|
|
|
+ * @param generateTBNSpace if true, the code needed to create the TBN coordinate space is generated
|
|
|
+ * @param vTBNAvailable indicate that the vTBN variable is already existing because it has already been generated by another block (PerturbNormal or Anisotropy)
|
|
|
+ * @param worldNormalVarName name of the variable holding the world normal
|
|
|
* @returns the shader code
|
|
|
*/
|
|
|
- public static GetCode(state: NodeMaterialBuildState, ccBlock: Nullable<ClearCoatBlock>, reflectionBlock: Nullable<ReflectionBlock>, worldPosVarName: string): string {
|
|
|
+ public static GetCode(state: NodeMaterialBuildState, ccBlock: Nullable<ClearCoatBlock>, reflectionBlock: Nullable<ReflectionBlock>, worldPosVarName: string, generateTBNSpace: boolean, vTBNAvailable: boolean, worldNormalVarName: string): string {
|
|
|
let code = "";
|
|
|
|
|
|
const intensity = ccBlock?.intensity.isConnected ? ccBlock.intensity.associatedVariableName : "1.";
|
|
@@ -215,7 +252,12 @@ export class ClearCoatBlock extends NodeMaterialBlock {
|
|
|
state._emitUniformFromString("vClearCoatTangentSpaceParams", "vec2");
|
|
|
}
|
|
|
|
|
|
- code = `clearcoatOutParams clearcoatOut;
|
|
|
+ if (generateTBNSpace && ccBlock) {
|
|
|
+ code += ccBlock._generateTBNSpace(state, worldPosVarName, worldNormalVarName);
|
|
|
+ vTBNAvailable = ccBlock.worldTangent.isConnected;
|
|
|
+ }
|
|
|
+
|
|
|
+ code += `clearcoatOutParams clearcoatOut;
|
|
|
|
|
|
#ifdef CLEARCOAT
|
|
|
vec2 vClearCoatParams = vec2(${intensity}, ${roughness});
|
|
@@ -242,7 +284,7 @@ export class ClearCoatBlock extends NodeMaterialBlock {
|
|
|
vec2(0., 1.),
|
|
|
${bumpTexture},
|
|
|
${uv},
|
|
|
- #if defined(TANGENT) && defined(NORMAL)
|
|
|
+ #if defined(${vTBNAvailable ? "TANGENT" : "IGNORE"}) && defined(NORMAL)
|
|
|
vTBN,
|
|
|
#else
|
|
|
vClearCoatTangentSpaceParams,
|