The Problems with tangent space?

Bottles and glasses are moulds I meshed with MAYA. Perfume bottles are the models I imported from outside. I have layout UV for them, but none of them have baked normal maps. I have studied for a long time and found that they should be related to tangent space, but I can not solve them. If you adjust in MAYA, or what other ways can you do the same tangent space with perfume bottles?

To be fully sure of your tangent space, you should export it from maya. @PatrickRyan might be able to help providing feedback on how he generate them.

Thank u! I expect Master @PatrickRyan to see my problems

@lajaylar if it is a simple matter of retaining the tangents created in Maya rather than letting Babylon calculate the tangents on the mesh, you want to check the “export tangents” box on the Babylon Exporter window.

Although I don’t know if I am understanding your concern fully. What is it that you are seeing in your scene that does not render as expected? It’s a little hard to tell what you are seeing in the split debug capture.

Is there something happening on the bottle and glass that isn’t happening on the perfume bottle?

The only thing I think I see, though it’s hard to tell without a playground, is hard normals on your bottle. If your vertex normals are split (mesh rendering hard edges in Maya) you will see faceting in the render. If this is the case, select all edges you want to be soft (averaged normals) and under mesh rendering in the modeling menu set, you will find soften edges. I am not in front of my computer right now so I am trying to remember the names so I may be off, but they would be generally named this way.

Please let me know if this doesn’t solve your problem and if not, please describe more of what you are seeing or share a playground and I would be happy to dig in more.

Dear Master! Thank you for your attention!
I can’t upload zip,I m new user,but the problem is not soften edges.
Can I send you the source file?

@lajaylar, I am happy to look at your file. You can either try to DM it to me here on the forum, or you can simply raise your trust level on discourse (which will help you overall to use the forum) with a couple of simple things:

Get to trust level 1 by…

  • Entering at least 5 topics
  • Reading at least 30 posts
  • Spend a total of 10 minutes reading posts

Users at trust level 1 can…

  • Use all core Discourse functions; all new user restrictions are removed
  • Send PMs
  • Upload images and attachments if enabled
  • Edit wiki posts
  • Flag posts
  • Mute other users

This is a pretty low bar to entry, but I think it’s well worth taking the 10 minutes to do so that you can enjoy more features on the forum.

1 Like (630.2 KB)
Dear Master:
Thank you for reminding me,I have uploaded FBX, the babylon file and NME, and there is a rendering img in it. Based on your video tutorial on youtube, I will try my best to make an effect similar to the renderings. And thanks master to give advice

1 Like

Happy to look into it. Give me a little time to dig into your assets as I see what you are going for. I will report back asap.


@lajaylar, I apologize for the delay in my response. I needed to spend some time prototyping this out since what you are doing is something that is very hard to do with real-time rendering since we cannot rely on ray tracing to determine how to bend light through a thick glass substrate. Let me break down what I did.

First, I got a reference for what to expect with actual glass so we could understand what we need to do in the shader. Consider this image:

The thing to notice is that the bottom of the drinking glass is very thick and so has the most refraction. Even toward the sides, or fresnel, of the drinking glass, where you are looking through the middle of the glass material walls of the vessel, you see more refraction. But toward the middle, f0, the amount of the material you are looking through is the thinnest and with the least refraction.

The other part is that we see both the interior faces and exterior faces of the drinking glass at once, and they will all catch specular reflections. So when we set it up with the following process, this is what we get:

Now there are two ways to accomplish this and you may need to use one over another based on what you are trying to do. The first way is by splitting your mesh into two, one outer and one inner as we need to be able to separate the meshes to ensure they render correctly. I added another loop just below the last loop in the inside rim and split the mesh there. This is because I wanted to ensure that split normals at the edges of the two meshes would be the same. If I split it where the normals are averaged, we would see a hard edge between the meshes. This position reduces this issue:

Next, I reworked the UVs to make sure everything was straight because I needed to pass a small texture for the refraction intensity of the bottom of the drinking glass.

The exterior mesh is at the bottom and the interior on top. This layout would also allow you to add normal detail or roughness detail (fingerprints, imperfections, etc) to the glass to make it more realistic. However, I just used a 1 x 512 pixel image to denote how thick the bottom of the drinking glass is. The texture starts at the bottom as black and quickly ramps to white at the edge of the bottom’s thickness. We will use this as the gradient on a lerp between refraction values.

Next, we build a shader that mixes the mask we created above for the thickness of the bottom and mix it with fresnel on the mesh. So this is what we get:

The black parts on the mesh are the parts that have both the higher refraction value and the higher opacity value. The white area has lower refraction and opacity values. This will reinforce the mesh looking like it was made of glass with thickness.

The rest of the shader looks like this. Nothing else is really out of the ordinary and you can see that we are loading in the texture to mix with fresnel and then lerp between two values for refraction, opacity, and thickness. Other than that, the rest of the shader is pretty much the same as any other PBR shader.

Now the only thing we have to do is to make sure that since both of these meshes render in the right order. We do this with mesh.alphaIndex setting them in the order they will need to render from low to high. In our case, the interior mesh is mesh.alphaIndex = 0 and the exterior is mesh.alphaIndex = 1.

This allows us to always render them in the correct order. You will note in the playground there is one more parameter I set on the material, which is material.needDepthPrePass = true which is there for the refraction in the shader. In some rotations you could see some artifacts on the mesh due to the mesh not being convex (since we split it to help render the inside faces). This setting has a small cost, but does ensure that no small artifacts render in the refractions.

The other method we could use with just a single mesh is set up almost the same way. However there are a few key differences. You will use a mesh like the original, only it would be combined into one with the same UVs and thickness texture. The shader would also be the same, but you may need to adjust the opacity values due to this method to get it to look correct.

The big difference is that you need to turn off backface culling to render the interior with material.backFaceCulling = false and then enable a separate culling pass with material.separateCullingPass = true. This will still render all of the faces like the split mesh route, but you are also rendering backfaces, so you will note that your alpha looks different. You would then just dial in your alpha values to compensate.

As for when to use one method over the other, you need to consider all that you are putting in the scene as well as if you want to do things like possibly color the interior shape to imply liquid contained within like in your perfume bottle example. This could be a separate material and shader, since you have two meshes. If you want to do something like that with one mesh, you will need some sort of mask to isolate the interior either through a texture or through something like vertex color.

In any case, you should be able to take these methods and run with them to get a render the way you want it. Remember, there are limitations with real time rendering since we don’t have the time to ray trace, especially when on a mobile device, but you should be able to use tricks like this to get close.

You can see playground with both single mesh and multiple mesh below as well as the edited fbx of your original file. Let me know if you have more questions.

Two mesh refraction on glass
One mesh refration on glass (38.7 KB)



Dear Master:

Thank you very much for providing me with such a detailed and specific tutorial, which surprised me. Because the tutorial involves too much knowledge, I spent more than a week to understand the tutorial, every detail, every node, and summed up a lot of experience. Now I can basically understand the content of the tutorial provided by Master yours, But I had some strange and interesting questions;

I found that Fresnel is related to the size of the model. Models of different sizes will directly affect the parameters of “bias” and “power” in Fresnel nodes. Therefore, I spent a long time to understand how large the model is most suitable for export. The second problem I can’t solve at present is that Fresnel will not affect the model when the size is the same in ScalingX, ScalingY,ScalingZ,This kind of situation only appears in my own debug with vscode, but has not happened in the case of Playground provided by Master yours. For this,I am very confused, also did a lot of tests;

I found that when the parameters of scalingX, scalingY, scalingZ of the model are the same, Fresnel cannot affect the model, but as long as you adjust it properly, Fresnel will appear. For this reason, I can only solve this problem temporarily through some code .

I upgraded the version to and checked all the parameters, but It’s still unresolved。

I just came into contact with BabylonJS at the beginning of this year. In less than a week, I fell in love with BabylonJS and resolutely gave up some other frameworks such as thressjs. The real-time effects, lots of cases and IDE tools that he can provide are the most comprehensive of all frameworks I have ever seen. This is very Microsoft style, although in our country, few people use it, But I think BabylonJS will become more and more famous in the future. Thank you again. I hope you can give more video cases on Youtube, and look forward to and always pay attention to your developers.

This is my first project with BabylonJS . I feel very honored and happy for using BabylonJS to develop the project。


Your visual looks Stunning !!! and I can not emphasize enough how I enjoy your enthusiasm for the framework :slight_smile:

@sebavan Thank you for your help. :grin: :grin:

1 Like