POM material


Have anyone make a POM material can i have a tutorial ? like this


There are already examples of Parallax Occlusion materials in UE4. If you look at the starter content, the Cobble material uses POM as does one of the other rock/cement materials. That should give you everything you need.

Bear in mind, they are both complex and expensive.

I have tried to replace texture from the cobble stone material but the result is really bad.Have you already make POM material in UE 4.I can’t have the same result as cryengine.

To be fair the material from the starter content is pretty complex and not easy to modify even if you now the basics of the material editor. The parallax pass already combines 2 different diffuse textures with different tiling and many nodes aren’t parameterized which won’t let you easily swap textures or adjust values (like the height ratio).

Also it’s not actually POM, but a multi layered parallax mapping which also handles self occlusion. Still it’s based on a regular parallex effect which means depth decreases at acute view angles. It also seems to scale bad with multiple textures because each parallaxed texture needs to be part of the loop instead of the loop returning parallax texcoords which you could plug into as many texture sample nodes as you want.

Its also not supporting silhouette, which the cryengine version does. So you cant have stuff really sticking out like in the example shown by you above. So besides the fact its a very complex shader, its also quite limited and therefore not really ideal :frowning:

I decided to take a break and tackle something a little easier. So heres what I have come up with so far for parallax occlusion mapping. No self shadowing (Not sure if this can be done nicely without actually modifying shader code). Has optional silhouette. The only extra map required is a height map. I’ll clean up the material network and post if people are interested.


Interested in the Mat-Tree? Hell yes! Looks awesome!!

I sure would like to see it!:cool:

Ehamloptiran! Literally everything you consider turns to gold! You are unbelieveable! (Think I’m maxing out my exclai

Okay here is the material graph, theres a lot that can be improved, but this is a pretty good starting point


Custom code blocks are as follows:


float CurrRayHeight = 1.0;
float2 CurrOffset = float2( 0, 0 );
float2 LastOffset = float2( 0, 0 );

float LastSampledHeight = 1;
float CurrSampledHeight = 1;

int CurrSample = 0;

while ( CurrSample < (int) InNumSamples )
	float4 Temp = Material.Texture2D_0.SampleGrad( Material.Texture2D_0Sampler, InTexCoord + CurrOffset, InDX, InDY );
	CurrSampledHeight = ( ( Temp.r * InChannelMask.r ) + ( Temp.g * InChannelMask.g ) + ( Temp.b * InChannelMask.b ) );
	if ( CurrSampledHeight > CurrRayHeight )
		float Delta1 = CurrSampledHeight - CurrRayHeight;
		float Delta2 = ( CurrRayHeight + InStepSize ) - LastSampledHeight;

		float Ratio = Delta1/( Delta1 + Delta2 );

		CurrOffset = ( Ratio ) * LastOffset + ( 1.0 - Ratio ) * CurrOffset;

		CurrSample = InNumSamples + 1;

		CurrRayHeight -= InStepSize;

		LastOffset = CurrOffset;
		CurrOffset += InStepSize * InMaxOffset;

		LastSampledHeight = CurrSampledHeight;

return CurrOffset;

Output Type: CMOT Float 2
Inputs are:

  1. InNumSamples
  2. InStepSize
  3. InTexCoord
  4. InDX
  5. InDY
  6. NormalHeightMap (Not actually used, just there to ensure texture doesn’t get optimized out)
  7. InMaxOffset
  8. InChannelMask


if( InUseSilhouette > 0.0f )
clip( InFinalCoords );
clip( 1.0f - InFinalCoords );

return InFinalCoords;

Output Type: CMOT Float 2
Inputs are:

  1. InFinalCoords
  2. InUseSilhouette

**NOTE: **Make sure that the height map is the first texture you drop into the material graph as the above custom code block accesses that texture directly via Material.Texture2D_0 and Material.Texture2D_0Sampler If you don’t drop it in first, it will be referencing the wrong texture. To fix that you will need to change those two values to whichever one is assigned to the heightmap.

Thanks for sharing! It would be nice if Epic would integrate this as a material function in a future release.

To be able to benefit from approximate soft self shadowing I am thinking of moving this into the vertex factories and lighting code, as right now even if I could get it to work, it would only get shadows from one light source. So if I do end up getting there, then maybe it can be merged into the engine itself.

Wow, this is fantastic. I can’t find the “World to Tangent” node anywhere though, but I’m a total noob with this sort of high level material

Thanks for sharing! Excellent work; Iam going to try this out this evening :slight_smile:
Regarding the self-shadowing (which would be a huge benefit, without any doubt!): I asked this in a separate topic and got an answer from Eric Ketchum who directed me to this page. Apparently the light vector isn’t directly available as in UDK and a workaround would be to make use of dynamic material instances…

Which is similar to what I am doing at the moment, using Material Parameter Collection to update the Light Vector, but this will only work for one or a limited number of lights. Where as if I integrate it into the pipeline directly, then we can any number of lights casting shadows onto the POM material.


Sorry didnt see your post. Search for transform. Then Source will be ‘World’ and Destination will be ‘Tangent’

No problem. Thanks for the reply - I found it, I was only finding the opposite before, not realising you could change the destination and target. Much appreciated.

Having issues currently, sadly…but I assume I’ve done something wrong. This is my first time using a custom node. I’ve used the same graph as you, but I get the error “[SM5] (Note Add) Arithmetic between types float 2 and float 3 are undefinied” - this is referring to the Add node that adds the CalcParallax node with the TexCoord node.

Actually sorry I forgot to mention (I have updated the original post). The output type needs to be set to CMOT Float 2 for both custom nodes

Also I’ve decided to upload some height maps that I have been using for testing, so others can test and maybe help improve the shader. Located here:

Three of the height maps are to be used with existing Brick, Cobblestone textures, others have their own normal maps.



Good job there Ehamloptiran, thanks for sharing.

Is there a specific reason you are transforming the camera vector and vertex normals to tangenst space for the angle based sample count? Should work just well in world space. (not much of a instruction saving since the tangent camera vector is required anyway but still a little bit)