Does anyone know how to make an actual outline shader in the NME? and also is there anywhere I can learn NME in full besides BabylonJS youtube?
I am interested in making awesome shaders but I don’t know much about it(besides all what I learnt from youtube)… Thanks
I also associate myself with this question.
NME is a great tool but it is difficult to use without some basic textual guides or documentation with examples.
I believe there will be a huge benefit for everybody from NME Shader Library, at least with some basics and most needed shaders (like fire, water, plasma, outline etc).
Actually there should be already a lot of NME snippets, ready for the use, but currently it is impossible to browse and view them.
I’d like to provide some input to this as well, as a shader beginner. My issues with the NME have been;
- Lack of tutorials (other than the youtube ones)
- Lack of examples or as you said, a library of examples and snippets that the user could start with
- And the most crucial one; how to actually use the shaders in your projects. For example; I make a mesh in Blender and then export it as glb format. Now I would like to apply some shader to the model. For this to work, I have to change the PBRMaterial somehow to apply the shader onto it. The problem is that no documentation tells you how to achieve this kind of functionality. Sure, you can load a snippet from the NME server, but this is not viable in the real world example where you are making a game for example. In real world you would like to save the node material data locally and then apply it easily to a model of your choice.
Solutions for these problems:
- Create a example/snippet library for NME, similar to what playground has
- Provide instructions on how to apply NME shaders to models after loading the NME data from the server to your local environment to a loaded model that already has material from a 3d software export
Tagging @PirateJC as this would be an amazing addition !!!
The idea of having a example/snippet library for NME is awesome. I LOVE that! We’ll add this to the list and figure out a good solution to make this happen.
@Panuchka - Thanks for flagging the question about how to load a node material from a file and apply it to a 3D object created in a different application. In trying to answer this question I agree that the documentation isn’t clear and is out of date. I’ll work on changes to this shortly to make it more clear in the future.
For now check this playground out:
In this playground I’m loading an asset (several meshes created in Blender)
I also created a shader in the Node Material Editor and saved the file directly.
Once the mesh (cannon) and the shader have been loaded into the scene, I simply assign the shader to be the material of the mesh.
So here are the key lines of code:
- Loading the mesh
let cannonMeshes = await BABYLON.SceneLoader.ImportMeshAsync("", "https://piratejc.github.io/assets/pirateFort/", "cannon.glb", scene);
let cannon = cannonMeshes.meshes[1];
- Loading the saved shader:
let nodeMaterial = await BABYLON.NodeMaterial.ParseFromFileAsync("hypnosis", "https://piratejc.github.io/assets/hypnosis.json", scene);
- Assigning the shader to the material of the mesh:
cannon.material = nodeMaterial;
That’s really it. I 100% agree that the documentation isn’t super clear about this, so I’ll update it right now.
Ok I’ve made the update to the Node Material Page.
Should be live in a few minutes.
Thank you for taking time to answer this issue and adding to the docs!
However, I would like to elaborate a bit more about the “real use case” I have and which has left me, a shader noob, a bit baffled.
I am building a game where I’ve had a question; what would the game and the assets look if I had some sort of toon shading on them? Would it look cool? Time to investigate; soon I found the toon shader tutorial in Babylon Youtube channel, which used the NME and I thought that it would be a nice learning exercise for me. After finishing creating the shader in NME, I was eager to attach it to my 3d models… But exactly how would I do that? For example, I have this character in the game: https://playground.babylonjs.com/#S7E00P#49
How would I approach in giving the character, which consists of many different meshes, a shader? Trying to put the hypnosis shader to it somehow breaks the animations
Also if I try the toon shader in similar way, it doesn’t work out of the box. Maybe there are some stuff that I have missed shader-wise… I had a thread about this a while ago: Applying node material editor shader to glb models
In the thread I used the wall/floor meshes of the game as test meshes, but if I try the same process with the real character, it doesn’t work at all: https://playground.babylonjs.com/#S7E00P#168 Ps. Sorry for the missing clothing
Anyways, after trying a while with the toon shader, I gave up and decided to look into it later So that is my rocky road with NME… I think other users might have these problems as well, if they are newbies like me, or try to add shaders to complex models…
So all in all, these are my “pressure points” and questions with NME and applying shader to a mesh:
- In general, applying a shader to a complex model seems really complicated
- If the model has a PBRMaterial, can you “just replace” it with a NodeMaterial? If the model has, for example, normal data/texture, does it break?
- Also a minor note, would it be possible to store the json in a regular javascript/typescript object and ask it from there instead of loading it async from server? I would prefer this to be ready without async waiting in my game, for example… Maybe it can be already done, but I haven’t found the right part in docs.
Thanks for reading
Thanks for elaborating.
As you gain more experience with NME, my sincere hope is that you’ll find it becoming increasingly more clear how to approach it. I myself went through a very similar journey about 2 years ago. I was a COMPLETE shader rookie. Having spent a lot of time with NME I’ve grown quite a bit more proficient.
I know that’s probably not the most satisfying answer in the world, but let me say it like this: I think you’ll find that it gets easier to understand the more you use it.
As for your direct questions:
It certainly can be depending on the specifics of your assets and the shader you’re trying to create. In the example of a toon shader though, it shouldn’t be prohibitively difficult. I’ll have to dig into this a little more to understand the complexities.
NME does not support PBR out of the box. You have to use the PBRMetallicRoughness node to add PBR functionality to a node material. The incredibly talented @PatrickRyan made a video series explaining this in depth. Please check it out for more information.
Sure theoretically this is possible, though I’ve never done it myself.
A bit of a clarification; I am not sure if I actually need the PBRMaterial, but the materials are mapped as that material type when I import a glb/gltf into Babylon. Not sure if that is because I use that kind of node in Blender or what…
But anyway, the main thing would be to preserve the textures (diffuse, normal) from the model and apply the, for example, toon shader easily. If the toon shader is used in a game, it pretty much needs to be applied to all meshes of the game for similar look, therefore it should be streamlined somehow…
If you look into it more, be free to test with the model in the playground below I really appreciate any help with this: https://playground.babylonjs.com/#S7E00P#49
I’m sure that happens sooner or later!
I did a quick implementation of creating a node material from a json object directly stored in a PG rather than from an external link. Basically you create your shader using NME, then save out a json file and minify it. You could use the prettified version of the json file, but it will be really long due to all of the node positional data we need to save for the editor. Then just create an object using the json data and create your node material by parsing the json object.
The reason you get PBR materials when you import a glTF is that the format standard calls for PBR Metallic Rough materials, so all DCC tools are doing a conversion of whatever material you have in the scene to a PBR material when saving the glTF. When creating your node materials for custom shading solutions, if you have PBR textures you want to pass to the node material from the glTF, you will need to know mesh names for each material. Then you can get the texture attached to a particular parameter of the material (like roughness) and assign it to your new node material. You will need to set up your node material to accept textures from whatever lighting model your textures are authored for (PBR Metal-Rough in the case of glTF) and then get the individual nodes by name and assign the corresponding texture to it.
This is a more complex model which has several meshes that each need a different shader based on the requirements of the material. One mesh needs UI mixed with the texture to display the time and date, one needs a standard plastic, but in the original shader we did a dissolve between different material types, and the last is the metallic base that needed no special treatment. But you can see how I either import the textures directly or pull them from the loaded model and then assign to the node material before assigning the correct node material to each mesh in the scene.
This is a common method for loading meshes and assigning their textures to a node material. It does take some knowledge of the mesh (mesh name at minimum) so you can get the correct textures, but you could certainly come up with an abstraction scheme for your mesh names to make sure that any compatible model could be assigned the same node material. Hope this helps explain things a bit but feel free to ping us with more questions.
Hi @Panuchka just checking in, do you have more questions?
I saw some discussion about NME here. I just forced myself to understand NME to understanding the trailing effect implemented as a node material. As the fresh feedback from a beginner on this topic, I felt there were 2 issues made it hard to understand the node material.
-
Different levels of abstractions could be mixed in a single layer and making the node graph complex. E.g. Math operators could be nodes. But many cases multiple operations make a meaningful task in the pipeline. Also vertex shader and fragment shader pipelines are mixed, making it harder to understand. I ended up with exporting the node material as shader code to read it.
-
After exporting the node material as shader code, there is another minor issue. It is not straightforward to map the uniforms in the node graph to the variables in the code. E.g. there could be multiple float uniforms in the node editor. In the shader code they will be named u_Float1, u_Float2, …u_Float5. But it is not easy to map these uniforms to the values in the node editor. It would be great if the node editor also label these nodes (Float1, Float2, …).
Tagging @PirateJC for more NME feedback
@slin - Thank you for sharing your valuable perspective on this as someone who just recently jumped right into NME.
The reason that the vertex shader and fragment shader are together in NME is because in many cases you’ll want to the two systems to work together using different parts of your node tree.
You can see this clearly at play in the caustics YouTube series.
As for exporting the node material as shader code. This is interesting perspective for sure. We don’t hear a lot of feedback from folks about this part, so it’s really good to hear that it can be improved. Thanks for sharing your thoughts on it. We’ll take a look at it as we get into planning for the next release.
And additional point. For example, if I use NodeMaterial with import like this:
import { NodeMaterial } from '@babylonjs/core/Materials/Node/nodeMaterial';
than I got an error (in my case):
caught (in promise) Build of NodeMaterial failed:
input vector from block WorldPos[TransformBlock] is not connected and is not optional.
input rgba from block FragmentOutput[FragmentOutputBlock] is not connected and is not optional.
But with this import all fine:
import { NodeMaterial } from '@babylonjs/core/Materials/Node';
cc @RaananW in case he has a way to improve it ?
Sadly no better way with the current architecture. I hope to have a better solution for 7.0.
Hi
I’d like to point out that the original post by @TheScientist which was about creating outline shaders was not fully addressed.
I have been looking all over, trying to make a shader that will create an outline around the mesh once I click on it. And I would like this outline to penetrate through all opaque meshes in front of it and never be hidden by anything. The selected mesh may be hidden but not the outline shader.
Please let me know the best ways to achieve this.
Tagging for feedback @PirateJC
Thank you
Welcome aboard!
You could reuse the PG from:
and make the outline always visible by setting the depth function to “always”:
In the PG above, I used the node material from Fresnel effect to the model - #17 by PatrickRyan for the outline effect.
The disadvantage of this technique is that you have to clone the meshes in order to draw them a second time, using the outline shader.
However, I’ll show a way of doing this without cloning meshes once a PR in progress is merged into the repo.
Thanks a lot!
Also we would love to have some in-depth docs and tutorials for making commonly used shaders with NME. It’s very powerful because of the bare-bones tools it provides, so it’s also complex for beginners to get started with and to learn about shaders from scratch.
Thanks again