Fresnel effect to the model

Hello, Everyone.
I am a new to BabylonJS. I have little experience in three.js but I am trying to add fresnel effect with babylon.js.
I could import GLB model using Babylon.js but I have no idea to apply the fresnel effect to this model.
Please guide me here.
Thanks for reading my question!

Welcome to the forum !!!

Could you share a playground of where you are at with your code ? and we could try to update it to add fresnel ?

@sebavan Thanks for your reply!!!
Yep, I will share it. I was working on my local.
Let me uplode it to playground.

I found this. I think we can use this.
Please guide me! @sebavan

You should try to mix it with the previous doc https://playground.babylonjs.com/#WGZLGJ#7433

1 Like

Okay, let me try. :muscle:

so sick!! thanks @sebavan
but I would like to show the model fully and wanna add fresnel effect.
How can I do that?

These are what I want. :smiley:
in3d-walk-cycle
walk-cycle01

You need to create your own material either with a custom shader or NME Node Material | Babylon.js Documentation

1 Like

Thank you for your kind guide. As a newbie to babylon.js and this, I’d love to hear more of your solutions. Could you please elaborate?

Please have a look into the documentation I provided it should detail how to create a material. You can also have a peak in the forum for previously answered question with the same kind of material [NME] Is this emission shader possible with pure node material blocks? - #3 by PatrickRyan

Then, you could modify the playground above until you are stuck and the community will help unblock you.

1 Like

Thanks!!! @sebavan
Great support for me.
Thanks again.

Hello @sebavan , thanks for your kind support.
I also tried to make this kinda effect, but I couldn’t do it.
A few days ago, I finally found it. But I have a question regarding the effect.
I tried to add this effect to my avatar model, but the shader material replaced the original materials.

I am trying to change the parameters on inspect mode, but I didn’t find a solution.
is there any way to implement it? So put a transparent shader material over origin material
I would be appreciated for your help.

You would need to combine the previous material and this one Node Material and PBR | Babylon.js Documentation

Thanks for your reply.
Btw, I don’t have enough experience in Babylon.js, so I would like you to share an example like playground.
Anyway, I am checking the above documentation.
Regards.

No worries, you will gain experience as you learn.

Currently you need to focus on NME The Node Material Editor | Babylon.js Documentation and how it works. Once you are all good with it the previous NME PBR doc will help you create the base color of your object that you will be able to “remix” with the post from @PatrickRyan about the fresnel effect.

The forum is here to help and assist on each step where you ll be stuck no worries.

1 Like

@Proverse, what you are running into is that you need to create a new shader that can use the PBR textures that come with your glTF asset. The reason you don’t see any of the original textures is that you are replacing the materials with a shader that uses grey as the diffuse color. The fresnel shader you have attached is also a blinn-phong lighting model, not a PBR lighting model. We need to rework the shader a bit to accept PBR textures.

As you can see we left the vertex blocks and the fragment blocks as they were in the original shader, but replaced the Light blocks - which is blinn phong - with PBR blocks so that we match the texture format in the asset.

From there we just need to load the shader (which I did from the snippet server for ease) and clone for each mesh that needs a fresnel material. In this case you have five meshes that make up the character, so you will clone the original node material five times. Each of the new materials must have the base color, orm, and normal textures from the original materials assigned. You will see that in lines 41-61 in the playground, but an example would be:

            materials.look_0.getBlockByName("baseColorTex").texture = meshes.look_0.material.albedoTexture;
            materials.look_0.getBlockByName("ormTex").texture = meshes.look_0.material.metallicTexture;
            materials.look_0.getBlockByName("normalTex").texture = meshes.look_0.material.bumpTexture;

We are getting the texture block in the node material by name and then assigning the same texure from the original material as matches the current texture channel. One thing to note is that you have some meshes that don’t have all of the needed PBR textures to render correctly. The body mesh is missing a normal texture and both hair meshes are missing the ORM (Ambient Occlusion, Roughness, Metallic channel-packed texture). If you want these to render correctly, you will either need to add these missing textures or create alternate fresnel node materials that either skip the perturb normal blocks (in the case of a missing normal texture) or use float number factors for AO, Roughness, and Metal (in the case of a missing ORM). The missing normal will just waste calculations that don’t need to be there, but a missing ORM will look wrong as you need to assign the AO, Roughness, and Metallic values as they need to render correctly. Using a missing texture block will pass incorrect values for these parameters which will render wrong.

For ease in explaining the process, I did not create any additional node materials to handle the cases of missing textures. But you should be aware that those alterations need to be made to render as physically accurate.

Your updated playground should have everything you need to follow along with the process. But please feel free to ping back with more questions.

6 Likes

@PatrickRyan, thanks for your kind answer.
I am checking your solution now, but it will take some time for me to fully understand it.
But this is exactly what I wanted to implement.
I am really appreciated the support of the community.
I will ask you if I have some questions
Thank you again.

1 Like

Sorry to still be a noob with this. I’m learning NME only slowly (very slowly :hourglass_flowing_sand: :sweat_smile:.

I’m planning on using this fx as a base to display some meshes in my scene. Problem is these meshes have different scaling. In fact they will need to adapt to a given size on top of my displays. Now, I know how to access the blocks and resize the fx (edge and falloff).
Currently inside my assetsManager onSuccess, I go something like this:

let glowedge = scene.getMaterialByName("bodyMat").getBlockByName("edge").value;
let glowfall = scene.getMaterialByName("bodyMat").getBlockByName("falloff").value;

scene.getMaterialByName(“bodyMat”).getBlockByName(“edge”).value = (glowedge * task.loadedMeshes[0].scaling.x);
scene.getMaterialByName(“bodyMat”).getBlockByName(“falloff”).value = (glowfall * task.loadedMeshes[0].scaling.x);

Only one mesh is loaded at the time (and disposed before the next is shown), so they can all share the same material. And so, that works fine of course, but still…is not very sexy (in terms of code, I mean).

Question is: Where do I pass this value of mesh scaling within the node material so that the material would adapt to the scaling of the mesh (any mesh)?

Thanks and sorry to still be a pain with this :wink:
Meanwhile, have a great day :sunglasses:


Here a SS of the use case (WIP)

Edit: Thanks @Evgeni_Popov for fixing my post (copy/paste error :face_with_hand_over_mouth:
But then, I said my version works but it doesn’t. It works as long as the mesh scaling is kept within a reasonable range. The factor between edge and falloff is incorrect and cannot be applied to a mesh scaled i.e. 50. So my maths are clearly also wrong there.

You could try to update the node material property in material.onBindObservable. However, this observer is called a bit too late for the change to the property to be taken into account in this frame. So, you would need something like this:

nodeMaterial.onBindObservable.add((mesh) => {
    const inputBlock = nodeMaterial.getBlockByName("blockname");
    inputBlock.value = mesh.scaling.x;
    inputBlock._transmit(nodeMaterial.getEffect(), scene, nodeMaterial);
});

Warning: untested code!!

2 Likes