How to recreate PBR with the NodeMaterial

Hey,

I have a model and it has 12 meshes in it. All the meshes material are made of PBR material. I m trying to recreate the PBR material with nodeMaterial. Any help how to map from PBR to NodeMaterial?

@Deltakosh - When I search on the forum if there is similar question, I found this question -
Cast from nodematerial to PBRMaterial - Questions - Babylon.js (babylonjs.com) and you mentioned a suggestion on the question, what I needed now. Can you give me a hint how I can implement it?

Thanks in advance.

It is all in the doc Node Material | Babylon.js Documentation

2 Likes

@sebavan Thanks for the link.

Some of the mapping I tried works → albedoColor to baseColor, metallicTexture to metallic & Roughness, abmientTexture to ambientColor from PRBMaterial to PBRMetallicRoughnessMaterial.
But I m a kind of lost where/how to map albedoTexture, reflectionTexture, reflectionColor, and bumpTexture values of PBRMaterial on PBRMetallicRoughnessMaterial?

thanks

albedoTexture, you need to multiply with your albedoColor before placing inside of the baseColor node.

reflectionnTexture is using the reflection block


which either use the environmentTexture or your own defined ones

reflectionColor is indeed defined on the previous block

bumpTexture is used through the perturb normal block:

2 Likes

@sebavan Thank you so much. Let me try to implement it and if I have a question, I will come back again. :slight_smile:

1 Like

@sebavan I would like to thank you so much again. Every thing works. I have one minor question - I can’t open the node material editor from Inspector.

The node material build successfully and gives me the expected output. And also I was able to generate the code using nodeMaterial.generateCode(); from the function. I get the texture file from the back-end API, does that create an issue?

Here is the error message I get

NodeMaterialError

Here is the graph I constructed based on the generated code.

Here is the generated code

var nodeMaterial = new BABYLON.NodeMaterial("NM_plasticsFoot");

// InputBlock
var position = new BABYLON.InputBlock("position");
position.setAsAttribute("position");

// TransformBlock
var WorldPos = new BABYLON.TransformBlock("WorldPos");
WorldPos.complementZ = 0;
WorldPos.complementW = 1;

// InputBlock
var World = new BABYLON.InputBlock("World");
World.setAsSystemValue(BABYLON.NodeMaterialSystemValues.World);

// TransformBlock
var Worldnormal = new BABYLON.TransformBlock("World normal");
Worldnormal.complementZ = 0;
Worldnormal.complementW = 0;

// InputBlock
var normal = new BABYLON.InputBlock("normal");
normal.setAsAttribute("normal");

// PBRMetallicRoughnessBlock
var PBRMetallicRoughness = new BABYLON.PBRMetallicRoughnessBlock("PBRMetallicRoughness");
PBRMetallicRoughness.lightFalloff = 0;
PBRMetallicRoughness.useAlphaTest = false;
PBRMetallicRoughness.alphaTestCutoff = 0.5;
PBRMetallicRoughness.useAlphaBlending = false;
PBRMetallicRoughness.useRadianceOverAlpha = true;
PBRMetallicRoughness.useSpecularOverAlpha = true;
PBRMetallicRoughness.enableSpecularAntiAliasing = false;
PBRMetallicRoughness.realTimeFiltering = false;
PBRMetallicRoughness.realTimeFilteringQuality = 8;
PBRMetallicRoughness.useEnergyConservation = true;
PBRMetallicRoughness.useRadianceOcclusion = true;
PBRMetallicRoughness.useHorizonOcclusion = true;
PBRMetallicRoughness.unlit = false;
PBRMetallicRoughness.forceNormalForward = false;
PBRMetallicRoughness.debugMode = 0;
PBRMetallicRoughness.debugLimit = 0;
PBRMetallicRoughness.debugFactor = 1;

// InputBlock
var view = new BABYLON.InputBlock("view");
view.setAsSystemValue(BABYLON.NodeMaterialSystemValues.View);

// InputBlock
var cameraPosition = new BABYLON.InputBlock("cameraPosition");
cameraPosition.setAsSystemValue(BABYLON.NodeMaterialSystemValues.CameraPosition);

// InputBlock
var baseColorFactor = new BABYLON.InputBlock("baseColorFactor");
baseColorFactor.value = new BABYLON.Color3(0.04026846, 0.04026846, 0.04026846);
baseColorFactor.isConstant = false;

// TextureBlock
var MetallicRoughnessTexture = new BABYLON.TextureBlock("MetallicRoughnessTexture");
MetallicRoughnessTexture.texture = new BABYLON.Texture("api_url_to get_the_texture", null);
MetallicRoughnessTexture.texture.wrapU = 1;
MetallicRoughnessTexture.texture.wrapV = 1;
MetallicRoughnessTexture.texture.uAng = 0;
MetallicRoughnessTexture.texture.vAng = 0;
MetallicRoughnessTexture.texture.wAng = 0;
MetallicRoughnessTexture.texture.uOffset = 0;
MetallicRoughnessTexture.texture.vOffset = 0;
MetallicRoughnessTexture.texture.uScale = 1;
MetallicRoughnessTexture.texture.vScale = 1;
MetallicRoughnessTexture.convertToGammaSpace = false;
MetallicRoughnessTexture.convertToLinearSpace = true;

// InputBlock
var uv = new BABYLON.InputBlock("uv");
uv.setAsAttribute("uv");

// TextureBlock
var AmbientTexture = new BABYLON.TextureBlock("AmbientTexture");
AmbientTexture.texture = new BABYLON.Texture("api_url_to get_the_texture", null);
AmbientTexture.texture.wrapU = 1;
AmbientTexture.texture.wrapV = 1;
AmbientTexture.texture.uAng = 0;
AmbientTexture.texture.vAng = 0;
AmbientTexture.texture.wAng = 0;
AmbientTexture.texture.uOffset = 0;
AmbientTexture.texture.vOffset = 0;
AmbientTexture.texture.uScale = 1;
AmbientTexture.texture.vScale = 1;
AmbientTexture.convertToGammaSpace = false;
AmbientTexture.convertToLinearSpace = true;

// ScaleBlock
var Scale = new BABYLON.ScaleBlock("Scale");
Scale.visibleInInspector = false;

// InputBlock
var Vector = new BABYLON.InputBlock("Vector3");
Vector.value = new BABYLON.Vector3(0.76, 0.76, 0.76);
Vector.isConstant = false;

// ColorSplitterBlock
var ColorSplitter = new BABYLON.ColorSplitterBlock("ColorSplitter");
ColorSplitter.visibleInInspector = false;

// ReflectionBlock
var Reflection = new BABYLON.ReflectionBlock("Reflection");
Reflection.useSphericalHarmonics = true;
Reflection.forceIrradianceInFragment = false;

// FragmentOutputBlock
var FragmentOutput = new BABYLON.FragmentOutputBlock("FragmentOutput");
FragmentOutput.visibleInInspector = false;

// TransformBlock
var WorldPosViewProjectionTransform = new BABYLON.TransformBlock("WorldPos * ViewProjectionTransform");
WorldPosViewProjectionTransform.complementZ = 0;
WorldPosViewProjectionTransform.complementW = 1;

// InputBlock
var ViewProjection = new BABYLON.InputBlock("ViewProjection");
ViewProjection.setAsSystemValue(BABYLON.NodeMaterialSystemValues.ViewProjection);

// VertexOutputBlock
var VertexOutput = new BABYLON.VertexOutputBlock("VertexOutput");
VertexOutput.visibleInInspector = false;

// Connections
position.output.connectTo(WorldPos.vector);
World.output.connectTo(WorldPos.transform);
WorldPos.output.connectTo(WorldPosViewProjectionTransform.vector);
ViewProjection.output.connectTo(WorldPosViewProjectionTransform.transform);
WorldPosViewProjectionTransform.output.connectTo(VertexOutput.vector);

WorldPos.output.connectTo(PBRMetallicRoughness.worldPosition);
normal.output.connectTo(Worldnormal.vector);
World.output.connectTo(Worldnormal.transform);
Worldnormal.output.connectTo(PBRMetallicRoughness.worldNormal);

view.output.connectTo(PBRMetallicRoughness.view);
cameraPosition.output.connectTo(PBRMetallicRoughness.cameraPosition);
baseColorFactor.output.connectTo(PBRMetallicRoughness.baseColor);

uv.output.connectTo(MetallicRoughnessTexture.uv);
MetallicRoughnessTexture.b.connectTo(PBRMetallicRoughness.metallic);
Vector.output.connectTo(Scale.input);
MetallicRoughnessTexture.g.connectTo(Scale.factor);
Scale.output.connectTo(ColorSplitter.rgbIn);
ColorSplitter.g.connectTo(PBRMetallicRoughness.roughness);

uv.output.connectTo(AmbientTexture.uv);
AmbientTexture.rgb.connectTo(PBRMetallicRoughness.ambientColor);

position.output.connectTo(Reflection.position);
World.output.connectTo(Reflection.world);
Reflection.reflection.connectTo(PBRMetallicRoughness.reflection);

PBRMetallicRoughness.lighting.connectTo(FragmentOutput.rgb);

// Output nodes
nodeMaterial.addOutputNode(VertexOutput);
nodeMaterial.addOutputNode(FragmentOutput);
nodeMaterial.build();

Thanks in advance. :slight_smile:

Could you repro in the playgound? So that @Evgeni_Popov may have a look :wink:

I reproduced the material here: Babylon.js Playground (babylonjs-playground.com)

and I can open it in nme from the inspector:

Do you mind updating that PG so we can have a look?

3 Likes

@Deltakosh Thank you for the playground. Here is my update - NodeMaterial_generation_from_code | Babylon.js Playground (babylonjs-playground.com)

I tried to apply the general framework of my project code base with a test data on the playground and I am able to open the node material editor. I can’t reproduce the error I m facing on my end. My project is based on typescript, hopefully that wouldn’t cause the problem.

I will keep looking and post my update.

Thanks again!

1 Like

No TS cannot cause that issue for sure (we are also developing with TS)

Please keep us updated if you find what is the culprit :wink:

1 Like