Optimising nodes to blend multiples materials

Hello, I need a way to optimise a node material because it take to much fps in real time (around 40fps).

On my main sand area I use a vertex color map to set different colors as different materials with a node material logic (Soil white, arid blue, green beach, red dry and black dune, see sceenshot), but it kill the framerate and loosing the blend of sand material would make the area looking a lot less good.

I was thinking about the blend of material with stencil textures but I already use more than one texture slot to setup textures scaled tree time differently from far, middle and close range, and using stencil would only accept one of the scale.

All parts of a node material are executed, even if they aren’t visible. Inside each of those materials are various textures, specular models etc. So the cost of that node shader is the cost of … 5 normal materials.

If you can, favour having a single material and adjusting the inputs to it based on the vertex color. This means only a single lighting model is evaluated, and means texture samples can be shared between matetials (by storing different data in different color channels).
If you need to do more than adjust the colour, have a look at the extended material node.

1 Like

for things like terrain shaders - it’s better to have 1 complex material that takes a bit to draw that is flexible than trying to bake everything to disk and stream it - like realtime FX.

I would say - the more % of the screen that will be using the single shader, the more complex it can be.

like if your whole scene is a terrain kit - building kit + dynamic assets - it’s not that many draw call batches if you know how to run them.

check using multiple levels of sine((dot(up, normal)*multi)+offset) multiplied to leave a single graident where you want it,
and baked noise

1 Like

I would really like to only have one material.

Edit :
So in the node, I changed each shader for a group, then in each group I configured their three texture scales, grouped all of this to duplicate it and do the same for the normal map, and finally desaturated a little the color group because the three textures used for the scales saturate too much while overlapping.



Yup, that looks like what I had in mind. Did you see any performance improvement from that change?


Texture samples are also pretty expensive. It may be possible to share ImageTexture nodes between the “materials” to reduce the number samples required?
One handy trick is if a texture is black/white, you can put three of them in a single image and use the “Split RGB” node to get the textures back again. This is useful if you’re (for example) using specular intensity maps instead of specular color maps.


You can combine all those extra “Vector inputs” if you like :slight_smile: Inside the group make them all come from the same one, select the “Group Input” node then push “T” and use the “X” button to delete the un-needed inputs:

Hello, to continue to try optimise a little more I deleted the nodes “rgb to bw”, “rgb curves” and “separate rgb” from inside the two color and normal groups to recreate only one of these batch of nodes outside of the groups, and also deleted the middle texture scale batch of nodes in all texture groups to only keep the far and close scale for now.

Yes I have a performance boost with nodes taking around 15fps instead of 40, thank you.
I already deleted some unneeded group inputs but will see about conbine some, What do you mean by “It may be possible to share ImageTexture nodes between the “materials” to reduce the number samples required?”

Well here’s your dune col texture:
dune_col

It’s mostly two colors: a light brown and a darker brown. So if we desaturate the image:
dune_col_desat

Then in the nodes we can re-color it with a mix node:

We’ve reduced the texture from three color channels to one color channel, which means we can do things with the other color channels. Consider the following texture:

ARRGH! There is no way to get BA to preserve transparency.
Link

It has a different "noise type in each color channel, which means that:

In this way, a single texture can contain multiple “materials”
Obviously this trick doesn’t work for every texture, but it works often enough to be a handy one to know.

1 Like

That is pretty cool, thanks for sharing!

Hello, thank you for the idea but I will stay with colored textures for now, I tried less colors in gimp some time ago and even if it wasn’t much, their quality wasn’t as good as with their full color.

I still need to optimize but it probably need to be in another way, because now my issue is going from 40fps while looking the ground to 20 fps while flying above the artificial area.

never underestimate the power of some baked noise too - it can be huge - but it’s better than trying to generate it on the GPU in realtime


Hello,

I have one thing related to fps that happened shortly after the change in my node, it don’t seem related but since it happened by surprise I wonder the cause.
While I was moving in my map in real time I thought the lack of door was a huge flaw, so I made them spawn by adding some code in the sub areas scripts, then I scripted the doors to open and close depending of their distance to the camera.
And now I’m around 100 fps instead of 30 ? I deleted nothing and the layers activated here are the same as when I tested multiple times before.

Sorry @BluePrintRandom but I don’t really understand your node, I don’t generate anything like noise in real time and don’t plan to bake much in my game, I’m on blender 2.79 and not upbge.

https://www.youtube.com/watch?v=Xe-QYqvILlY this is in upbge 0.2.4 (based on blender 2.79.6)

this little engine is a brute - and using noise + mathematics to mix textures ends up looking very natural if you use the right math :3

in 2.79 you can use nodes to get the normal in worldspace, try

sine((dot(up,normal)*mulit)+offset)

also noise + vertex color can yield noisy borders