Yeah adding corner geometry obviously isn’t the way to go here There used to be this one particular tech talk on YT that at least showed what this slide was all about.The guy indeed demonstrated the unchanged wireframe of the rather crappy mesh and with PADM it was like an instant-awe transformation. I’ve since then used CryEngine very little and stopped altogether the moment UE4 went out of beta so my personal experiments with PADM are kinda limited. I did manage to produce a rocky displaced plane with nice looks no problem but as to the under the hood how, no idea whatsoever!
That paper you linked is more of a different way of handling the parallax mapping itself but does not go into any detail on silhouettes that I could see. Most likely this is relying on the curvature thing since the tree roots are a perfect case for that. Basically if you know the current plane is going to bend by a certain amount, you can calculate when the ray would have exited the heightmap, or maybe the point at which the ray starts moving up in local space again and then you just kill it and return 0 alpha or something.
I think getting correct silhouettes and fixing POM on curved surfaces go hand in hand. This is what it currently looks like with POM on a curved surface:
The positions at the surface of the mesh are correct but the shader assumes that the height plane within each triangle is parallel to the surface polygon which is not the case when there is curvature. So it pulls the underlying surface along the curvature instead of actually curving.
It is almost like a lens effect when you spin around an object like this.
The root cause is stepping through the heightmap in tangent space. It may be possible to step in world space but it will cost more inside of the main loop. The other idea I have is to try to get the curvature of the surface at the point of entry (perhaps ddx,ddy on vertex normal) and then determine how much Z offset the ray needs to get at each step. So it has a chance to escape by bouncing off the plane. That may be cheaper but require more difficult math.
That’s very interesting. It may even open up an angle to another side-effect of ‘displacing’ (be it through pixel or a vertex shader) and that’s the texture stretching it produces. A while ago I asked on Answerhub whether it was possible to get rid of the horrible stretching that occurs when displacing vertexes over anything but low amounts and the answer was ‘nope’ ;_) but after many moons of trial and error I discovered there actually is an option of creating a mask out of the displacement distance and then tri-planar mapping this. It’s very iffy to get it looking correct but when it does, it looks quite nice. The old ‘relief-mapping’ example (with those nice skyscraper node trees for the stepping) included in the UE4 startercontent also has a somewhat similar approach by just coding in a side-texture that masks the stretching to a certain extend.
The stretching thing should be independent and it does happen with parallax as well.
Even a POM material does stretch if you gave it a vertical heightmap detail (aka no gradients) and that shows up even on a regular flat surface. You are correct that mapping a virtual texture is the best way to go about hiding that. And parallax shaders give you a nice version of the world space to use. You could create the mask manually using offset like you did, or you could actually perform a regular world aligned texture using the updated worldposition from the parallax (that uses similar math as pixel depth offset actually). You just need to make sure the normals match the heightmap and feed it the normals and it will automatically map a world aligned texture to the sides without any custom work.
The starter content version did it kind of differently than using a world aligned side texture. That was more like taking a bunch of offset slices but fading the slices with soft alpha and forcing some extra parallax on each slice to push them past the matched point.
FWIW, this whole fundamental problem with heightmaps is why full 3d displacement maps and advanced subdivision surfaces will eventually take over. I bet there are also cool tricks to try where you ‘relax’ the UVs of your mesh in order to store texture detail on vertical heightmap faces. You would need to store the relax delta so that you can deform the texture back into its UV space in the material but it may be possible to map the sides of steep elements using a method like that. Thats a lot of work though
I got a quick test working using curvature of the vertex normals combined with fresnel to bend the ray by adding to the z offset at each iteration.
The main issue with this technique is that it requires lots of extra steps otherwise the ray simply hits the end of the tracing wall. Or the code could be modified a bit further to automatically trace beyond the max distance using the curvature but that will be a little bit trickier.
The ‘deeper’ the height ratio is the more extra steps will be required. In my test, the height value was 0.5 meaning the texture is half as deep as it is wide. That is way deeper than most pom materials (I’d say the average is 0.05 or so).
The math is not fully solved yet so right now I am using a hand-set fudged number for the amount of z offset based on the curvature. Really that number needs to be made relative to the stepsize and properly solved. So this is one step closer but not quite to the point where I can check it in. Also the z offset isn’t being incremented properly yet either which adds a sort of fisheye effect (non-uniform uvs on the above cylinder make it look worse than it is though).
Sorry, which version of the node? Which function? Post your exact code with ‘code’ tags and take a screenshot of your node otherwise there are too many variables to answer.
Just FYI, the ‘[SM5] error X4532: cannot map expression to cs_5_0 instruction set’ error happens when you use an instruction that is only valid in a pixel shader. There’s a compute shader compiled for a misc feature that will trigger this error. To solve it, we have several built in functions that provide a workaround using the COMPUTESHADER define, for example:
So these things will cause the error (off the top of my head)
ddx / ddy (use DDX / DDY instead)
clip (surround with #if !COMPUTESHADER…#endif)
Tex.SampleGrad (use Texture2DSampleGrad instead)
I found this screenshot from Barzum last night that showed me how to use the new node. I’ve noticed also that it looks much better on the non lit side when you set the metalness to 1 instead of 0.