TL;DR - I fixed the problem, I’m sharing how I did it.
Hello, I recently ran into an issue that I thought was worth mentioning.
When using the World Coordinate mode on the Parallax Occlusion Mapping node, the outputted parallax UVs have a “twisting” effect when nearly aligned on the X axis. When the vertex normal swaps between positive/negative on the Y axis, the parallax effect appears to do a 180, causing it to pop outwards.
Here are 3 images demonstrating the effect. This is a test material to make the parallax effect obvious, which I color coded based on the axis that is being projected. Red is X, Green is Y, and Blue is Z. You can see that the Y and Z images are projected correctly, where as X has the twisting effect I mentioned. Images were taken in the preview viewport of the shader editor. If placed on an object on the world, the 180d pop out effect can be observed.
I’m projecting the different axis by simply grabbing 2 of the 3 values from absolute world position based on the VertexNormalWS value. X is YZ, Y is XZ, and Z is XY, and of course I flip values based on the sign of VertexNormalWS.
I eventually discovered the cause of the twisting effect and I fixed it, perhaps there is a better way to fix it than I did(Or even achieve what I was trying to achieve). But I thought I would share my discovery here.
If you open up the ParallaxOcclusionMapping node, you will see a TransformToZVector node. Open it.
Inside, you will see a CreateThirdOrthagonalVector node. This node takes the VertexNormalWS, and a constant of 1,0,0(positive X axis), to create a 3rd vector.
At this point I decided to edit it and change the constant to the Y axis, 0,1,0. Once I did that, the twisting issue moved over to the Y face and the X face was now projected correctly. Now I’m not that great at vector math, but I believe this is happening because the 3rd generated vector is flipping because the VertexNormalWS and constant vector are aligned(Positive or negative, doesn’t matter).
So I saved a copy of TransformToZVector and added an input here so that I can specify the constant myself. I then saved a copy of ParallaxOcclusionMapping and added an input there as well, to be plugged into my custom TransformToZVector. If the material is to be projected onto the X axis, then I send a value of 0,1,0. Otherwise I send the default of 1,0,0.
I’m sure there’s a better way to do this, but I thought I would share my experience in case anyone else is having the same problem.