diff --git a/dist/preview release/what's new.md b/dist/preview release/what's new.md
index aa53719685a..f098dafebe6 100644
--- a/dist/preview release/what's new.md
+++ b/dist/preview release/what's new.md
@@ -78,6 +78,7 @@
- Increased float precision to 4 ([msDestiny14](https://github.com/msDestiny14))
- Added ability to make input node's properties visible in the properties of a custom frame ([msDestiny14](https://github.com/msDestiny14))
+- NME `TextureBlock`: add an output for the texture level and a switch to disable the internal multiplication (level * texture) ([#10192](https://github.com/BabylonJS/Babylon.js/pull/10192)) ([rassie](https://github.com/rassie))
### GUIEditor
diff --git a/nodeEditor/src/diagram/properties/texturePropertyTabComponent.tsx b/nodeEditor/src/diagram/properties/texturePropertyTabComponent.tsx
index 4242b5adce9..0063d31060c 100644
--- a/nodeEditor/src/diagram/properties/texturePropertyTabComponent.tsx
+++ b/nodeEditor/src/diagram/properties/texturePropertyTabComponent.tsx
@@ -234,6 +234,17 @@ export class TexturePropertyTabComponent extends React.Component
}
+ {
+ texture &&
+ {
+ this.props.globalState.onUpdateRequiredObservable.notifyObservers();
+ }}
+ />
+ }
{
texture && texture.updateSamplingMode &&
{
@@ -355,4 +366,4 @@ export class TexturePropertyTabComponent extends React.Component
);
}
-}
\ No newline at end of file
+}
diff --git a/src/Materials/Node/Blocks/Dual/textureBlock.ts b/src/Materials/Node/Blocks/Dual/textureBlock.ts
index 463aea01f6b..507d2ad9b2e 100644
--- a/src/Materials/Node/Blocks/Dual/textureBlock.ts
+++ b/src/Materials/Node/Blocks/Dual/textureBlock.ts
@@ -73,6 +73,11 @@ export class TextureBlock extends NodeMaterialBlock {
*/
public convertToLinearSpace = false;
+ /**
+ * Gets or sets a boolean indicating if multiplication of texture with level should be disabled
+ */
+ public disableLevelMultiplication = false;
+
/**
* Create a new TextureBlock
* @param name defines the block name
@@ -91,6 +96,8 @@ export class TextureBlock extends NodeMaterialBlock {
this.registerOutput("b", NodeMaterialBlockConnectionPointTypes.Float, NodeMaterialBlockTargets.Neutral);
this.registerOutput("a", NodeMaterialBlockConnectionPointTypes.Float, NodeMaterialBlockTargets.Neutral);
+ this.registerOutput("level", NodeMaterialBlockConnectionPointTypes.Float, NodeMaterialBlockTargets.Neutral);
+
this._inputs[0].acceptedConnectionPointTypes.push(NodeMaterialBlockConnectionPointTypes.Vector3);
this._inputs[0].acceptedConnectionPointTypes.push(NodeMaterialBlockConnectionPointTypes.Vector4);
@@ -154,6 +161,13 @@ export class TextureBlock extends NodeMaterialBlock {
return this._outputs[5];
}
+ /**
+ * Gets the level output component
+ */
+ public get level(): NodeMaterialConnectionPoint {
+ return this._outputs[6];
+ }
+
public get target() {
if (this._fragmentOnly) {
return NodeMaterialBlockTargets.Fragment;
@@ -291,6 +305,8 @@ export class TextureBlock extends NodeMaterialBlock {
this._textureTransformName = state._getFreeVariableName("textureTransform");
this._textureInfoName = state._getFreeVariableName("textureInfoName");
+ this.level.associatedVariableName = this._textureInfoName;
+
state._emitVaryingFromString(this._transformedUVName, "vec2", this._defineName);
state._emitVaryingFromString(this._mainUVName, "vec2", this._mainUVDefineName);
@@ -309,7 +325,7 @@ export class TextureBlock extends NodeMaterialBlock {
this._writeTextureRead(state, true);
for (var output of this._outputs) {
- if (output.hasEndpoints) {
+ if (output.hasEndpoints && output.name !== "level") {
this._writeOutput(state, output, output.name, true);
}
}
@@ -371,8 +387,11 @@ export class TextureBlock extends NodeMaterialBlock {
this._generateConversionCode(state, output, swizzle);
return;
}
+ let complement = "";
- const complement = ` * ${this._textureInfoName}`;
+ if (!this.disableLevelMultiplication) {
+ complement = ` * ${this._textureInfoName}`;
+ }
state.compilationString += `${this._declareOutput(output, state)} = ${this._tempTextureRead}.${swizzle}${complement};\r\n`;
this._generateConversionCode(state, output, swizzle);
@@ -425,7 +444,7 @@ export class TextureBlock extends NodeMaterialBlock {
this._writeTextureRead(state);
for (var output of this._outputs) {
- if (output.hasEndpoints) {
+ if (output.hasEndpoints && output.name !== "level") {
this._writeOutput(state, output, output.name);
}
}
@@ -438,6 +457,7 @@ export class TextureBlock extends NodeMaterialBlock {
codeString += `${this._codeVariableName}.convertToGammaSpace = ${this.convertToGammaSpace};\r\n`;
codeString += `${this._codeVariableName}.convertToLinearSpace = ${this.convertToLinearSpace};\r\n`;
+ codeString += `${this._codeVariableName}.disableLevelMultiplication = ${this.disableLevelMultiplication};\r\n`;
if (!this.texture) {
return codeString;
@@ -464,6 +484,7 @@ export class TextureBlock extends NodeMaterialBlock {
serializationObject.convertToGammaSpace = this.convertToGammaSpace;
serializationObject.convertToLinearSpace = this.convertToLinearSpace;
serializationObject.fragmentOnly = this._fragmentOnly;
+ serializationObject.disableLevelMultiplication = this.disableLevelMultiplication;
if (this.texture && !this.texture.isRenderTarget && this.texture.getClassName() !== "VideoTexture") {
serializationObject.texture = this.texture.serialize();
}
@@ -477,6 +498,7 @@ export class TextureBlock extends NodeMaterialBlock {
this.convertToGammaSpace = serializationObject.convertToGammaSpace;
this.convertToLinearSpace = !!serializationObject.convertToLinearSpace;
this._fragmentOnly = !!serializationObject.fragmentOnly;
+ this.disableLevelMultiplication = !!serializationObject.disableLevelMultiplication;
if (serializationObject.texture && !NodeMaterial.IgnoreTexturesAtLoadTime && serializationObject.texture.url !== undefined) {
rootUrl = serializationObject.texture.url.indexOf("data:") === 0 ? "" : rootUrl;
diff --git a/src/Materials/Node/Blocks/Fragment/perturbNormalBlock.ts b/src/Materials/Node/Blocks/Fragment/perturbNormalBlock.ts
index 9f8c14b79e2..3b47dc2410f 100644
--- a/src/Materials/Node/Blocks/Fragment/perturbNormalBlock.ts
+++ b/src/Materials/Node/Blocks/Fragment/perturbNormalBlock.ts
@@ -177,18 +177,18 @@ export class PerturbNormalBlock extends NodeMaterialBlock {
state._emitFunctionFromInclude("bumpFragmentFunctions", comments, {
replaceStrings: [
{ search: /vBumpInfos.y/g, replace: replaceForBumpInfos},
- { search: /vTangentSpaceParams/g, replace: this._tangentSpaceParameterName},
{ search: /vPositionW/g, replace: worldPosition.associatedVariableName + ".xyz"},
{ search: /varying vec2 vBumpUV;/g, replace: ""},
- { search: /uniform sampler2D bumpSampler;[\s\S]*?\}/g, replace: ""},
+ { search: /uniform sampler2D bumpSampler;/g, replace: ""},
]
});
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: replaceForBumpInfos},
+ { search: /perturbNormal\(TBN,texture2D\(bumpSampler,vBumpUV\+uvOffset\).xyz,vBumpInfos.y\)/g, replace: `perturbNormal(TBN, ${this.normalMapColor.associatedVariableName}, vBumpInfos.y)` },
+ { search: /vTangentSpaceParams/g, replace: this._tangentSpaceParameterName},
+ { search: /vBumpInfos.y/g, replace: replaceForBumpInfos },
{ search: /vBumpUV/g, replace: uv.associatedVariableName},
{ search: /vPositionW/g, replace: worldPosition.associatedVariableName + ".xyz"},
{ search: /normalW=/g, replace: this.output.associatedVariableName + ".xyz = " },
@@ -226,4 +226,4 @@ export class PerturbNormalBlock extends NodeMaterialBlock {
}
}
-_TypeStore.RegisteredTypes["BABYLON.PerturbNormalBlock"] = PerturbNormalBlock;
\ No newline at end of file
+_TypeStore.RegisteredTypes["BABYLON.PerturbNormalBlock"] = PerturbNormalBlock;
diff --git a/src/Shaders/ShadersInclude/bumpFragment.fx b/src/Shaders/ShadersInclude/bumpFragment.fx
index b1bc9954f7f..bbda64afdeb 100644
--- a/src/Shaders/ShadersInclude/bumpFragment.fx
+++ b/src/Shaders/ShadersInclude/bumpFragment.fx
@@ -14,7 +14,7 @@
#elif defined(BUMP)
// flip the uv for the backface
vec2 TBNUV = gl_FrontFacing ? vBumpUV : -vBumpUV;
- mat3 TBN = cotangent_frame(normalW * normalScale, vPositionW, TBNUV);
+ mat3 TBN = cotangent_frame(normalW * normalScale, vPositionW, TBNUV, vTangentSpaceParams);
#else
// flip the uv for the backface
vec2 TBNUV = gl_FrontFacing ? vDetailUV : -vDetailUV;
@@ -52,7 +52,7 @@
normalW = normalize(texture2D(bumpSampler, vBumpUV).xyz * 2.0 - 1.0);
normalW = normalize(mat3(normalMatrix) * normalW);
#elif !defined(DETAIL)
- normalW = perturbNormal(TBN, vBumpUV + uvOffset);
+ normalW = perturbNormal(TBN, texture2D(bumpSampler, vBumpUV + uvOffset).xyz, vBumpInfos.y);
#else
vec3 bumpNormal = texture2D(bumpSampler, vBumpUV + uvOffset).xyz * 2.0 - 1.0;
// Reference for normal blending: https://blog.selfshadow.com/publications/blending-in-detail/
@@ -70,4 +70,4 @@
#elif defined(DETAIL)
detailNormal.xy *= vDetailInfos.z;
normalW = perturbNormalBase(TBN, detailNormal, vDetailInfos.z);
-#endif
\ No newline at end of file
+#endif
diff --git a/src/Shaders/ShadersInclude/bumpFragmentFunctions.fx b/src/Shaders/ShadersInclude/bumpFragmentFunctions.fx
index d4846d048f4..29cf60660c4 100644
--- a/src/Shaders/ShadersInclude/bumpFragmentFunctions.fx
+++ b/src/Shaders/ShadersInclude/bumpFragmentFunctions.fx
@@ -7,11 +7,6 @@
varying vec2 vBumpUV;
#endif
uniform sampler2D bumpSampler;
-
- vec3 perturbNormal(mat3 cotangentFrame, vec2 uv)
- {
- return perturbNormal(cotangentFrame, texture2D(bumpSampler, uv).xyz, vBumpInfos.y);
- }
#endif
#if defined(DETAIL)
@@ -25,19 +20,6 @@
uniform sampler2D detailSampler;
#endif
-#if defined(BUMP)
- vec3 perturbNormal(mat3 cotangentFrame, vec3 color)
- {
- return perturbNormal(cotangentFrame, color, vBumpInfos.y);
- }
-
- // Thanks to http://www.thetenthplanet.de/archives/1180
- mat3 cotangent_frame(vec3 normal, vec3 p, vec2 uv)
- {
- return cotangent_frame(normal, p, uv, vTangentSpaceParams);
- }
-#endif
-
#if defined(BUMP) && defined(PARALLAX)
const float minSamples = 4.;
const float maxSamples = 15.;
@@ -96,4 +78,4 @@
vec2 texCoordOffset = heightScale * viewDir.xy * height;
return -texCoordOffset;
}
-#endif
\ No newline at end of file
+#endif