Issues with PBR Material on BabylonJS version 4

Hi :smiley:

I’m facing some issues here with Babylon version 4 (tried 4.0.3 and 4.1.0-alpha26). I’m using the PBRMetallicRoughnessMaterial material that is working well with the version 3.3.0, as you can see in this image:

downloa01d

But with version 4, the environment texture is not being applied to the object:

image

If I remove the line of code that is setting the environment texture on Babylon version 4, the material seems ok:

image

Here is the code I’m using to create the scene in both versions of Babylon:

I tried to find changes in the BabylonJS version 4, but the examples on the Playground with PBR are identical for both versions.

Am I doing something wrong?

Thanks for helping!

1 Like

Pinging @sebavan (please be patient as seb will be back on monday)

1 Like

Am I wrong if I suppose that you’re envTexture isn’t HDR? (App.url + '/objects/skybox/skybox') + your hemilight could also help to burn white values (by the way, you don’t really have pure white materials values IRL).

https://www.babylonjs-playground.com/#I4SMJ4#3

1 Like

Hi @Deltakosh and @Vinc3r, thanks for responding…

@Vinc3r… I removed the HemiLight and yes, it worked well :smiley: but I don’t understand why it is working with the HemiLight on v3… is there any difference? I was using the HemiLight to control if the scene is more or less bright;

About the texture, It is a simple six textures cubemap, but is working well here (Apparently it is supported with PBR too: Use a HDR environment (for PBR) - Babylon.js Documentation).

Thanks very much!

Not here to comment on the change happening, but with PBR I have developed the method of always wanting the environment texture to be as bright as possible to avoid lights, which can only add to fragment processing and probably JS too.

If you can do that, then with a simple, little loop, you can adjust light down to any 0 - 1 ratio value. This only need run once after all your materials are loaded.

for (const mat of this._scene.materials) {
    if (!(mat instanceof(BABYLON.PBRMaterial)) || mat.name === 'skyBox' ) continue;

    mat.environmentIntensity = value;
}

The human in this scene is multimaterial. Use the slider to the left to the effect. There are no lights in this scene.

You can also click on a material, and adjust any material to have a different value from the rest. If coming from Blender / .babylon, then you can take these values and plug them into the custom exporter properties to generate them that way out of the box.

2 Likes

Thanks, @JCPalmer, that is a good approach. I’ll try it here. I have one question: What you do if you need shadows in someplace?

Good question. First, I assume you are taking about dynamic shadows, not the baked ones. If I wanted one, of course I would add a light. Shadows can seem really faint in a PBR scene due to the environment texture. To avoid that, I would set the intensity on the shadow receiving mesh low enough, so that does not happen.

To avoid all other meshes to being affected in brightness or performance wise, I would set the light to only be used on the shadow receiving mesh. To do that in the Blender / .babylon exporter, I would make a collection witch had the light & all the receiving meshes. In the light’s exporter properties, check This collection Only box in addition to setting for the kind of shadow map you wish.

Wow, interesting… I’ll try it here. I noticed that the shadows are very faint with PBR, but I didn’t know why. Thank you :smiley:

1 Like

Hey guys, although without a HemiLight it worked well, I needed to add a directional light to get a similar and better effect. But, after a lot of tries, I can’t make the same beautiful effect as it is on version 3.3. Any idea about it?

The original with v3.3 and Hemilight:
image

On v4, without any light (controlling only the bright with environmentIntensity):
image
It makes a little difficult to see the object shape and shading.

On v4, using directional light to improve the object shading and see the shape:
image

As you can see, the example on v3.3 with the HemiLight seems way better. I think it is because of the groundColor effect that hemiLight provides.

But as hemiLight seems to don’t work more on v4 with PBR, I’m looking for a way to simulate that effect. Someone here knows how to make it? Am I making something wrong?

EDIT: I tried to reduce HemiLight intensity, changed the diffuse and specular, but without success, it always burns the white values on v4. I needed to reduce the PBR material baseColor too. On v3 it was pure white, but on v4 I’m using a soft gray to make it less bright.

EDIT 2: I was able to use pure white again by changing the material to PBRMaterial instead of PBRMetallicRoughnessMaterial and reducing the environmentIntensity. But it still doesn’t work well with HemiLight, I keep using DirectionalLight, and the result is similar to the last image, just a little sharper and darken, as you can see in this image:

image

Thanks again :smiley:

Pinging @sebavan, @Deltakosh, @JCPalmer, @Vinc3r

Let s add @PatrickRyan who might help on the setup.

2 Likes

@TiagoSilvaPereira I’m happy to help you with a setup but would prefer to be setting up a scene with your assets. Is there any way you can share a playground with us? If not, would you be able to share the skybox and obj with us so we can recreate and debug mirroring your scene rather than making assumptions? If you can’t post them here, you can reach out to us privately or through email if you prefer. Thanks for the help!

2 Likes

Thank you @PatrickRyan, for sure, here is the playground: Babylon.js Playground

If you try with v3.3, this is exactly the scene I’m trying to do. But if you change to v4, you will notice that the scene is no more like in v3.3.

Thank you very much for helping :smiley:

EDIT: Fixed the playground link

@TiagoSilvaPereira, it appears that you may have not clicked the save button on the playground as the link you shared takes me to a default playground:

Sorry @PatrickRyan here is the correct link Babylon.js Playground

Thanks

1 Like

@PatrickRyan changed it to start the camera in a best position: Babylon.js Playground

1 Like

@TiagoSilvaPereira, there were a few things that I needed to drill down on. The first was the mesh itself. When I looked at the mug, the mesh around the handle was not manifold and the geometry flow isn’t super clean. It’s also UVed with a lot of cuts where we don’t need them. I quickly merged vertices to make it manifold and did a quick unwrap so that we could smooth the normals and prevent any seam artifacts in the render. Here is the original:

This is the repaired version. I didn’t take the time to rework the edge flow as it would have been faster to rebuild it:

Notice the seams are hidden under the handle and inside the mug to deemphasize them. The other thing I noticed from the assets is that your skybox texture is a LDR (low dynamic range) 8 bit image. This is problematic for two reasons. The first is that the image does not contain any values over 1.0 which means that there really is no light coming from the image. The other issue is that this image would be in gamma color space, rather than linear which is what is needed for IBL.

I downloaded a similar environment from HDRI Haven so that I could illustrate what is happening. The only issue is that the environments from HDRI Haven often are super high in contrast pushing 22 EVs. So I did need to pull down the brightest pixels by 5 EVs. There is another thread on this that explains how I went about reducing the offending pixels and why so I won’t go into it here.

What I will illustrate is the range of values in an HDR image as well as your LDR image:
image
This is the info panel from Lys which is a good way to illustrate how large the values get. This is post EV reduction because the original was in the hundreds of thousands for max value. This will screw up the spherical harmonics and cause the render to be way off. The statistics from the skybox you were using looks like this:

image

This angle is looking out the window which should have the brightest pixels in your image, but the max value in each channel is only 1.0. To take advantage of the environment for your light, you need to convert the HDR image into a precomputed DDS. The reason is that we need to create a mip chain so that the roughness level of the material can fetch the correct mip texture for the light computation.

With a standard LDR image, you don’t get the mip chain, spherical harmonics, or any of the other things that the PBR rendering pipeline needs. You also need to call the IBL slightly different than you were calling it in your playground:

BABYLON.CubeTexture.CreateFromPrefilteredData("link/to/DDS", scene);

This sets up the engine to know that there is the mip data to supply all of the information that the PBRmaterial expects. I did disable the analytical lights in the scene because you won’t need them for what you showed as an example. If you want to add a ground plane to catch shadow you will want to add a directional light and cull the mug mesh from the directional light. The reason is that the directional light will cast the shadow, but you don’t need the light information on the mug mesh itself. The setup for PBR shadows is the same as for the standard material.

So here is the final render with the IBL correctly configured and the updated playground for you:
https://www.babylonjs-playground.com/#B1M547#1

Hope this helps and is clear. If you have any other questions, please feel free to grab me.

8 Likes

Superb write-up @PatrickRyan

2 Likes

I knew @PatrickRyan would blow my mind again with his answer :slight_smile:

2 Likes

Hi @PatrickRyan I can’t thank you enough, I’ve learned a lot with this information. I’ll try to adapt my scene to use a real HDR image. It really blew my mind, I never imagined these details about the mesh :joy:

Just one more question that doesn’t leave my mind:

Have there been any changes from v3.3 to 4 in this regard?

It seems to me that even using LDR in v3.3 it was possible to have a reasonable scene but it seems to be quite different with v4 (It was cool for noobies like me :grin:, but from the good side, now I’m enforced to make the things in the right way).

Thanks very much and sorry for bothering you with these details.

Best Regards

1 Like

I am handing back to @sebavan as there is a difference in how the engines are handling the texture clone, though you don’t need to clone the texture here as the meshes can share an environment texture. We looked at it and are seeing something that is wrong, but @sebavan is taking a deep dive into it.

1 Like