Author Topic: 'Height blend' node for Substance Designer  (Read 6401 times)

I've been working on an implementation of the Unreal Engine 'Height Lerp' node within substance designer.  (Not at all unique to Unreal Engine, but that's where I've used it most)

For people who haven't seen / heard of this technique before - here's the explanation.  For anyone who just wants to try the node - the download is at the bottom.

Lets say I have two ground textures:

Forest floor:

Rocky ground:

And I want to transition from one to the other using a gradient mask:

It looks pretty awful:

What would be better is if we took the height maps of the two textures into account when creating the blend, so the transition was more natural, and we didn't get unrealistic semi-transparent blend areas.

I found the algorithm, and the above image, in a great article here:

The algorithm implemented in a pixel processor node gives a blend map that looks like this:

For a much more natural looking blended texture:

This 'semi-transparent' texture blending has always been something that bothered me about the 'make it tile' node:

So I've altered it to do a height-based blend instead:

You can download a .zip file containing both nodes (a basic 'height blend' node, and my altered 'make it tile' node) here:

Maybe it will be of use to someone - let me know if you have a use for it, or have a suggestion to improve it.  I'd like to get some other hands on it before uploading to substance share.


Hey Alex Kenyon,

awesome work, I always wanted to do a Height Blend, too, but you came first :P
Great work, but it may fit in the Tutorial section more, I think? Or the Showcase Section.
I can move the topic for you, if you like.

Best Regards
Environment Artist - Twitter

Please move it to wherever you think this topic best fits - no worries!

I was hoping to get some confirmation that the nodes were working for people other than myself, before widely sharing - but maybe I chose the wrong sub-forum to do this?


That's pretty neat. I was a bit confused about the inputs and outputs first.

Some suggestions before you put this on Substance Share:

- By default it should take one of the height inputs as the blend mask, with a boolean switch exposed to alterate between input 1 and 2. The blend mask should be an optional input. I think that would be the best so it works out of the box for the users without tinkering.

actualy, after further inspection screw that, it's fine

- pixel processor should be set to greyscale

- expose lerp values

- add comments what the node and the inputs do

Other then that great work! This should be quite useful.
Last Edit: July 22, 2016, 03:46:29 pm

Not sure make it tile works on my side. I see only a kind of wrap/offset  in terms of Photoshop.

Also I am lost after  your pixel processor does "max" of  two layers with added gradient.  Could you elaborate please what further math operations do.    The mask BTW still seems not very clean with a lot of translucent pixels.

Tried to recreate your scheme in Blender, where "M" bypass  allows to see instantly what each branch or nodes do and still not sure I understand.

From what I always do after adding gradient in such cases is  "minus" one of the initial layers from "max" of them  and then use ">" than 0  to find a precise mask. 

Same way in Photoshop with lighten/subtract  layer blending and then levels.   

Are you trying to equalize depth of layers somehow?
Last Edit: July 23, 2016, 07:20:38 pm

kir238 i have exposed the values on my side. the one that is 0.2 by default i believe works well as a falloff to get smoother or crisper masks. lower value = crisper

- pixel processor should be set to greyscale

- expose lerp values

- add comments what the node and the inputs do

Thanks for the input - will do that when I get some time.


It's a node-based version of this algorithm, which I found in the page I linked to:

Code: [Select]
float3 blend(float4 texture1, float a1, float4 texture2, float a2)
    float depth = 0.2;
    float ma = max(texture1.a + a1, texture2.a + a2) - depth;

    float b1 = max(texture1.a + a1 - ma, 0);
    float b2 = max(texture2.a + a2 - ma, 0);

    return (texture1.rgb * b1 + texture2.rgb * b2) / (b1 + b2);

There's a pretty elegant explanation here:

I did tweak the setup a bit to make the transition less abrupt, will need to expose this as well.

Thanks for additional explanation and the link.  Still I can't say what exactly the last part does. In my own example it rather do some extra mess.

I am accustomed to do such kind of Z combine  in Photoshop.  Looks like it works quicker there with hi-res images.    I just use levels to keep the mask smooth.