Would be a fantastic demo for 4.1
+ a PBR material if possible? :D
Not for 4.1 as some blocks will be missing but this is the goal for 4.2
I assume that the #ifdef parts of the shaders should be treated as regular "if" when converting to nme?
So, for something like:
#ifdef MULTIVIEW
if (gl_ViewID_OVR == 0u) {
gl_Position = viewProjection * worldPos;
} else {
gl_Position = viewProjectionR * worldPos;
}
#else
gl_Position = viewProjection * worldPos;
#endif
we would create a MULTIVIEW float constant, with either the value 0 or 1. Both parts of the #ifdef would be created in the editor and the output would be something like lerp(result2, result1, MULTIVIEW): is that what you had in mind?
Side question: I don't think gl_ViewID_OVR is available in the nme?
And what about gl_PointSize?
So we should not treat ALL the special cases. Multiview for instance is out of the equation.
Same for pointSize.
Let's chat here of the special cases but most of the time we will either ignore them or add special blocks later
Ok, going for the vertex shader first.
Should we support:
Here are all the defines we should handle:
Thanks!
The reflectionMap should already be done by the reflection texture block
No support for all the xxxDirectUV. the texture node handle that differently
Ok thanks.
I have an error I don't understand: https://nme.babylonjs.com/#JDCSVX#2
This one does work.
Now, link the output of the normalWorld block to the worldNormal input of the Reflection texture block and you get this error:
Shader compilation error: VERTEX SHADER ERROR: 0:35: 'normalOutput' : undeclared identifier ERROR: 0:35: 'constructor' : not enough data provided for construction
https://nme.babylonjs.com/#JDCSVX#3
It seems it should work?
Here are my comments after creating the vertex shader:
matricesIndicesExtra / matricesWeightsExtra blocks in the nme interface #ifdef NONUNIFORMSCALING
normalWorld = transposeMat3(inverseMat3(normalWorld));
#endif
as there are no transposeMat / inverseMat blocks
###___ANCHOR0___### in the vertex code generated by "Export shaders" (?)#ifdef FOG and there's no way to enable FOG in the nme interface (or I didn't find it).vTBN = mat3(finalWorld) * mat3(tbnTangent, tbnBitangent, tbnNormal);
we can't construct a matrix based on 3 vectors? More generally, I think we need a special block in the nme for bump, as there are a number of specific functions called in the fragment code (cotangent_frame, parallaxOcclusion, etc)?
If it can help: https://nme.babylonjs.com/#JDCSVX#4
I think we need a special block in the nme for bump, as there are a number of specific functions called in the fragment code (cotangent_frame, parallaxOcclusion, etc)?
the bump portion can be handled with the perturbNormal block
issue found for https://nme.babylonjs.com/#JDCSVX#3. I will send an update in a couple of hours :)
Thanks.
This one also has an error:

https://nme.babylonjs.com/#JDCSVX#5
It happened when connecting the output from "Perturb normal" to the input of "Reflection texture".
If I connect the output from "Normal world" to the input of "Reflection texture", it does work.
I also have an error with this one that uses morph targets:

PG: https://www.babylonjs-playground.com/#HPV2TZ#41
Node material to use: https://nme.babylonjs.com/#6E8GQ2
Can you create an issue for each?
Ok I fixed the #JDCSVX#5
And I fixed the second :)
Nightly incoming
Cool, thanks!
I think there are too many calculations done in the vertex shader for the reflection part compared to the existing standard shaders because I get this error when wiring the two sided lighting calculation (which uses gl_frontFacing):
FrontFacingBlock must only be used in a fragment shader
https://nme.babylonjs.com/#6E8GQ2#1
In the existing standard vertex shader, there is only this code related to reflection:
#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)
vDirectionW = normalize(vec3(finalWorld * vec4(positionUpdated, 0.0)));
#endif
Did you tried with the latest fix I did? I should have moved the bump computation to fragment only (like frontFacing block which is fragment only)
Btw: I see no error in the link you shared :(
Is the online nme updated with your changes?
It still does not work for me:
Yes apparently we are facing a deployment issue (cc @sebavan )
Np, I'm now using the local nme, I see the changes are in.
So, I don't have the error in the first link anymore, however I have a new one with the morph example:

This happens when you click on which node?
Hum, I think it happened when I bound:
but I don't have the error anymore... Maybe it was a transient error.
I also added the option to flag a float as boolean (from the UI standpoint only)
I can't see the option in my local nme, have you already committed it?
I added it in the list of tasks :D
Ok :)
So, now the shader works with morph targets, however I need to know how it is supposed to work when no morph target are there. For the time being, the shader does not work, I have a uniform grey color whereas I would expect to see my reflection texture when the mesh has no morph targets.
I would have supposed that the block:

would output updated position/normal/tangent/uv if the mesh has morph targets, else would output the unmodified position/normal/tangent/uv data. But it seems it outputs 0-vector data instead. Is it expected? Should I create a float like "HASMORPHTARGETS" and take the output from "MorphTargets" if it is one, else take the standard position/normal/... values instead?
I would have thought that all the blocks "Instances", "Bones", "MorphTargets", "Perturb normal" would output modified data if the corresponding feature is enabled on the mesh ("mesh has instances", "mesh has bones", ...) but else would output unmodified but still usable data. Is that not the case ?
It should be the case: https://nme.babylonjs.com/#C39T6E
It's a problem with the #define NORMAL / UV / ... not being set correctly I think.
Try:
var scrambleUp = function(data) {
for (index = 0; index < data.length; index ++) {
data[index] += 0.4 * Math.random();
}
}
var scrambleDown = function(data) {
for (index = 0; index < data.length; index ++) {
data[index] -= 0.4 * Math.random();
}
}
var createScene = function () {
// This creates a basic Babylon Scene object (non-mesh)
var scene = new BABYLON.Scene(engine);
// This creates and positions a free camera (non-mesh)
var camera = new BABYLON.ArcRotateCamera("camera1", 1.14, 1.13, 10, BABYLON.Vector3.Zero(), scene);
// This targets the camera to scene origin
camera.setTarget(BABYLON.Vector3.Zero());
// This attaches the camera to the canvas
camera.attachControl(canvas, true);
// This creates a light, aiming 0,1,0 - to the sky (non-mesh)
var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
// Default intensity is 1. Let's dim the light a small amount
light.intensity = 0.7;
// Our built-in 'sphere' shape. Params: name, subdivs, size, scene
var sphere = BABYLON.Mesh.CreateSphere("sphere1", 16, 2, scene, true);
var materialSphere = new BABYLON.StandardMaterial("mat", scene);
materialSphere.diffuseTexture = new BABYLON.Texture("textures/misc.jpg", scene);
var nodeMaterial = new BABYLON.NodeMaterial("node material", scene, { emitComments: true });
scene.debugLayer.show({
embedMode: true
});
scene.debugLayer.select(nodeMaterial);
sphere.material = nodeMaterial;
var sphere2 = BABYLON.Mesh.CreateSphere("sphere2", 16, 2, scene);
sphere2.setEnabled(false);
sphere2.updateMeshPositions(scrambleUp);
/*var manager = new BABYLON.MorphTargetManager();
sphere.morphTargetManager = manager;
var target0 = BABYLON.MorphTarget.FromMesh(sphere2, "sphere2", 0.25);
manager.addTarget(target0);
angle = 0;
scene.registerBeforeRender(function() {
target0.influence = Math.sin(angle)*Math.sin(angle);
angle += 0.01;
})*/
return scene;
};



I also think there's a problem with the "Perturb normal" block.
In the fragment shader, first line for this block is:
//Perturb normal
vec4 output7 = vec4(0.);
I think it should be initialized with the input "worldNormal" instead, so that if "BUMP" is not defined, we end up with the worldNormal unmodified. For the time being, if "BUMP" is not defined, we end up with a normal = vec4(0.) because of this line.
yep! I'm on it (thanks btw :))
I also think there's a problem with the "Perturb normal" block.
I do not think as BUMP is defined by the perturbNormal itself
It's a problem with the #define NORMAL / UV / ... not being set correctly I think.
I can repro..Looking for a fix now
Well actually no I cannot repro :(
(PG is back btw)
I do not see how this could fail: https://github.com/BabylonJS/Babylon.js/blob/master/src/Materials/Node/nodeMaterial.ts#L663
We are using the raw data of the mesh directly to flag the correct define
I do not think as BUMP is defined by the perturbNormal itself
Indeed, but how do you want the end user to use the material from the node editor?
I thought I would recreate the whole standard material with all the features in (morph, bones, instances, bump, reflection, etc) and the end user would disable some features by "some mean".
For some blocks, it's automatic because it depends on the mesh itself:
However, for other features like BUMP, it is the choice of the user to use it or not, it does not depend on the mesh itself: how do you let the user choose to use BUMP or not? Removing the block from the material seems complicated to me, I thought there would be some way to #define or not "BUMP" (and all other associated defines to BUMP: CLEARCOAT_BUMP, PARALLAX, ANISOTROPIC, PARALLAXOCCLUSION, etc).
If we keep the "Perturb normal" block even when bump is disabled, we should make sure we output the normal as given in the input.
Same thing for other features like Reflection.
Understood. The need here is to get the code with a "full fledged" std material. If the user does not want bump it can remove it from the node material.
In the future we could think about adding an "isEnabled" boolean per block
Well actually no I cannot repro :(
(PG is back btw)I do not see how this could fail: https://github.com/BabylonJS/Babylon.js/blob/master/src/Materials/Node/nodeMaterial.ts#L663
We are using the raw data of the mesh directly to flag the correct define
It does not work for me, I did the steps I explained in the previous post in the online Playground.
What I did:



In the future we could think about adding an "isEnabled" boolean per block
Ok!
It does not work for me, I did the steps I explained in the previous post in the online Playground.
I feel like it was fixed by another fix I did :) Let's wait for the next nightly to merge and see how it goes. I will publish it asap
Ok.
Another thing, I think the answer will be "no" but I still have to ask :)
Do you plan to allow to link two vectors bullets if the source one has more components than the destination one?
For eg, my source vector is "Vertex color" which is a vec4 whereas my destination is a bullet that is a vec3. Linking them would make the shader code to use vertexcolor.xyz automatically, instead of requiring the user to put a color splitter to get the xyz output needed. If the user needs something else than the automatic conversion (which would be x / xy / xyz when the destination is vec1, vec2, vec3), he still can use a splitter.
Color / vector splitter are quite big blocks in the graph, they take some room :)
Haha! You'll be surprised but we have all wwe need to support that :)
Node can define compatible inputs:
https://github.com/BabylonJS/Babylon.js/blob/master/src/Materials/Node/Blocks/Fragment/fragmentOutputBlock.ts#L23
Which blocks would you like to add compatible inputs? I can do it quite easliy
In fact that would be all blocks, with the rule explained above (source vector has more components than the destination vector) :p
But my use case was with "mesh.color" that I wanted to input to a multiply block.
Multiply block is an autodetect block so it will take the format of what you have (say you have the first input connected on a vec3 then the second one must be a vec3)
Indeed, but I need to multiply the diffuse.rgb with vertexcolor (vec4). I guess I have to use the splitter then.
yes :)
I downloaded the latest source code for the nme (I did get new sources from github), but my procedure above still not work.
When I do the first step (connecting the first node material to the sphere in the PG), I get this in the console (when loading the material into the node editor):

and my sphere is gray.
I need to load the second material then reload the first material to get the right display (and this time no error in the console).
Annoying bug: when using the "DEL" key in the X/Y or Z value of a Vector3, it deletes the currently selected block!
I will fix that!
Additional request: do you have an example of a PG with a standard material with all features enabled (bump, reflection, ambient, diffuse, etc)?
Additional request: do you have an example of a PG with a standard material with all features enabled (bump, reflection, ambient, diffuse, etc)?
Unfortunately no :(
Annoying bug: when using the "DEL" key in the X/Y or Z value of a Vector3, it deletes the currently selected block!
Will be fixed by next nightly.
Checking the other issue now
Ok your repro actually works..Working on a real fix now
For the sake of testing I'm adding this construct:
BABYLON.NodeMaterial.ParseFromSnippetAsync("WTSLCL", scene).then(nodeMaterial => {})
cc @PatrickRyanMS and @PirateJC FYI
It is live
@Popov72 : https://playground.babylonjs.com/#IY2BBD#1
It works, and ParseFromSnippetAsync is very cool too.
Thanks!
"Is boolean" is cool too :)!
It seems CTRL+C / CTRL+V does not work for frames.
Try here: https://nme.babylonjs.com/#WTSLCL
Do you plan to also implement "undo" / "redo"?
no undo/redo for now..Maybe in the future through upworks ;)
It seems CTRL+C / CTRL+V does not work for frames.
yeah it acts weirdly...WIll check asap
Will be fixed by next nightly
Ah, we can't set the alpha value of a color4 in the GUI!
What do you mean?
I have a Color4 block and what I can edit is:

I can't edit the alpha value (not in the color chooser either).
ok make sense! will fix that
Also, I can't clamp a vector, the Clamp block assumes the input/output to be float: it should be like multiply and adapt to its input.
Some comments/questions:
Another one:
At the end of the fragment shader there is:
#ifdef IMAGEPROCESSINGPOSTPROCESS
color.rgb = toLinearSpace(color.rgb);
#else
#ifdef IMAGEPROCESSING
color.rgb = toLinearSpace(color.rgb);
color = applyImageProcessing(color);
#endif
#endif
We do have a ImageProcessing node but I can't see a node for "toLinearSpace"?
How the Light information block is supposed to be used? It seems it is not needed (at least for the standard material)?
Not required for stdmaterial
I think I don't handle Refraction, as I saw it's a block planned for nme v2?
Correct
I don't think I can handle all the things related to Fresnel?
We need to create the block
We do have a ImageProcessing node but I can't see a node for "toLinearSpace"?
We need to create the block
Thanks for your answers.
This one is annoying:
Also, I can't clamp a vector, the Clamp block assumes the input/output to be float: it should be like multiply and adapt to its input.
Do you think you can so something for it, or should I create 3 clamps, one for each component? (will need to do a Vector Splitter, 3 clamps and a Vector Merger). Going to bed now, so no hurry ;)
The clamp is now autodetect ;D
I LOVE THIS! I have always split and multi-clamped but consolidation for the win!!
ok make sense! will fix that
Also, it seems the alpha value of a color4 is 0 by default, 1 would be a better value I think, else the color is not really usable "as is".
Well my experience is that when drag n dorpping a color4 I get alpha to 1 (as expected):

Checking the other error (at least this issue will be really useful to stabilize nme before the release:))
Well can you please create one issue by problem? The discussion here makes it really complicated to track :)
Thanks for creating the issues!
Thanks for creating the issues!
All done !
Here it is: https://nme.babylonjs.com/#PRXLT5
PG to test with: https://playground.babylonjs.com/#ZCJ2QX
I tried to make things as clearer as possible by making frames and moving them to limit line crossings, but I'm sure it's still possible to do better.
I added a number of float-const-boolean to enable/disable some parts of the rendering (corresponding to #define in the shaders), as it was easier for me for testing purpose: people can still remove the parts they don't want to use in the graph if they want to simplify the material. However, if drivers are good enough, they should be able to optimize something like lerp(a, b, 0) or lerp(a, b, 1) by not doing the lerp, keeping only the right operand and removing the calculations leading to the other operand if it is not used elsewhere.
I hope I did not make mistakes, I tried to closely follow the shader code and used namings as found in the code.
I think the single most important thing to explain to people about this material is that it is a transparency material by defaut (so, don't write in the zbuffer - only sorted / don't cast shadows by default), because something is connected to fragmentOutput.a! If people don't want / don't need transparency, they should remove the link to this input.
This is PERFECT!!!! Here are the next steps for me:
Is it expected that to get the same texture orientation in the nme compared to using a StandardMaterial we have to rotate U and V coordinates by 180掳?
we should have the same orientation out of the box
Also, if I'm not mistaken, there's no equivalent of the glossPower input of the Lights block in the standard material, so I must set it to 1 to be able to compare.
Correct
Is it possible to put this texture (name: opacity.png) into the Playground/textures directory? I didn't really find a suitable texture for opacity in the textures/ directory...

sure! just do a PR to add it
Done.
Here is the PG:
This is PERFECT!!!! Thanks a lot buddy!!! Now a good doc explaining all of that and we call it done
PR done for the updated doc.
Congratulation buddy! this is perfect! Closing now!
PR done for the updated doc.
Just to bring you up to date: I've modify your opacity.png to make it more "realtime" compliant ;)
Thanks, I'm working exclusively on desktop and 100ko is small for me :p
it was more about power of two width & height, plus make it tiling ^^
Most helpful comment
The clamp is now autodetect ;D