Can I expose height map to post process material?

Our game is using pre-rendered isometric graphics with normals and dynamic lighting. We want to dynamically add a height fog effect based on a pre-rendered height map, so that low areas get the most obscured by fog.

With an emissive material we could blend the fog with the base color directly, but with normals and lighting we need to do it in post process.

Is there a way to expose a materials height map (that is not connected to the material node) to a post process material? In other words for every pixel in screen space store a height value that is not used until post processing.

I’m also interested in hearing about other methods to achieve the same or similar effect.

Well my brain isn’t up to the task of doing the maths for you, but you need that world-space pixel position in the PP somehow. It seems doable from what a genius tech programmer friend of mine says. Some links that might help:

Someone trying to do it in Unity (problem is getting that ViewProjectionInverseMatrix matrix):

Chosker mentions in this thread how he reconstructed it in UE3 using the custom node (which I’m not sure if you have yet in UE4):

but also in that thread they mention you can access the depth buffer directly or something in UE4 which might make it easier?

No need for extra math here, you can directly access the worldposition via post process materials. Then use its blue channel, which is the z-position/height of every pixel, to create some fog effect.

The problem (if I’m not mistaken) is that there is no actual height in my scene. The scene is entirely pre rendered to 2D sprites. That is why I got a pre rendered map for the height data of each sprite. But as this information is not part of the rendering I cannot just reference it in a post process material.

I guess I could manually compose a screen space height map by using the sprite maps of all objects on screen in combination with their positions. But I was hoping for a simpler way.

Makes sense, I was expecting something like this.
You can however also map textures in a post process using the world position. I’m not sure if this would be suitable for your level since there are multiple sprites and height maps but it usually works given the position and size of the geometry.
Another workaround would be to connect those height maps to an unused material slot, so that you can access it in a post process from the gbuffer.

Can you post any screenshots of what your scene looks like exactly?

Could you please elaborate a bit on this?

This sounded like a fantastic solution, but it seems like any value assigned to unused (greyed out) slots are discarded.

I’ll ask our artist for a suitable example…

There are a couple of pins that I haven’t been able to find any explanation for, and that might be useful in some way. Anyone who knows something about them?

PostProcessInput on the Scene Texture node (for post processing materials), apart from #1 that is the standard selection for the rendered result.


CustomisedUVs on the MakeMaterialAttributes node.


Lets say you have a heightmap which should be projected along the world z-axis (top-down) onto your level you can use the red+green channel of the absolute world position as texture coordinates. Therefore you would need to specify the position in world space as well as the absolute size to match the mapping.

Here’s a quick example of a landcape with a complete black material, the textur projection (as well as shading) is done via a post process.

That’s right. I was assuming you do some kind of stylized rendering where you might use the roughness input with a specularity of zero.
You could also plug the height into the specular input and then scratch the specularity from the shader files.
It really depends on your current material setup, which is why I was asking for some pics.

Here is a current test render from inside UE4:


The layout are based on 2D isometric tiles with further 2D object placed on top. The material is this far very simple, with maps for base color and normals, and constants for roughness and metal. We use masked blend mode.

Modifying the shader files to just ignore the value for one input while still “saving” it for use in post process seems like it would solve my problems. The inputs that we are least likely to use are Specular and World position offset. But I got no idea how to do this. Would be grateful for guidance!

Open DeferredShadingCommon.usf and look for this line (417):
ret.SpecularColor = lerp( 0.08 *, ret.BaseColor, ret.Metallic );
Replace with a constant, like 0.5 which should be the default value.
This should do it.

I found this similar expression on line (422):
GBuffer.SpecularColor = lerp( 0.08 *, GBuffer.BaseColor, GBuffer.Metallic );

Editing it seems to work as you suggested. A big thank you!

Glad it’s working for you. The code line might differ due to a different version of the engine, mine’s from 4.2.

Hello, im trying to do the same thing in pixel engine,