Proper parallax mapping over geometry edges

MirceaKitsuneMirceaKitsune Posts: 43Member
edited May 15 in Shaders

I was looking at the Unreal 5 unveiling video last night. It got me thinking about pushing conventional shaders to obtain such fine detail on tiny areas... something that looks similar to Nanite as far as the viewer can perceive, but of course without billions of vertices for every little crack. To achieve such accuracy you need two things: Normal mapping but also parallax mapping. I got curious to check what parallax implementation Godot has, and sure enough it's looking great with the right textures! But I'm seeing the same issue I've always noticed with almost all parallax implementations: Edge cutoff.

The depth effect will only act within the geometry of the mesh the surface is on. If you're looking sideways at a face, the effect won't pop either in or out; You still see the outline of the object's model, the illusion of displacement will always be contained within that. This can easily be noticed in the default material demo with large gaps:

I've always considered this the deal-breaker of displacement mapping: You can use it to improve all these fine dimples and scratches, but if a larger detail falls on the rim of a mesh you're going to notice the effect is fake which ruins the whole thing. Yet I'm fairly certain there are implementations that worked around this issue; I don't remember if it was the Darkplaces engine (Nexuiz / Xonotic) but I'm sure I once saw parallax mapping on a brick wall where the bricks popped out of the plane geometry the wall was on and correctly acted on the edges.

Thinking of it technically from my very limited experience with shader code: I can tell some wizardry is likely needed to draw parts of a texture out of the triangle it's drawn on... don't know if GLSL would even allow this easily and with acceptable performance too. The opposite might work however: Couldn't we reverse the effect and displace the texture inward, then use transparency to mask out parts displaced to below the containment of the mesh?


  • cyberealitycybereality Posts: 927Moderator
    edited May 15

    I think you're looking for Prism Parallax Occlusion Mapping. You can also search for Silhouette Parallax Occlusion Mapping, maybe that will come up with some others.

    This is one (short) paper that describes the idea.

    This paper also looks interesting, though I just skimmed through it.

  • MirceaKitsuneMirceaKitsune Posts: 43Member

    @cybereality said:
    I think you're looking for Prism Parallax Occlusion Mapping. You can also search for Silhouette Parallax Occlusion Mapping, maybe that will come up with some others.

    This is one (short) paper that describes the idea.

    This paper also looks interesting, though I just skimmed through it.

    Wonderful, thanks! Are there any limitations that prevent either of these options from being used in Godot, or is it an aspect that simply didn't draw attention and no one thought of implementing it yet? Curious if any of the developers might be reading this and could either clarify or make it a reality for Godot 4.0.

  • cyberealitycybereality Posts: 927Moderator

    Well you can write your own shaders, I don't see any reason it's not possible in Godot. AFAIK you just need a height map and some math, so shouldn't be too hard. For some reason this seemed really impressive like 10 years about but doesn't seem like it got much use in real games. I mean, I know some games did use POM (like the latest Deus Ex did heavily in the city) but maybe it's too intensive or tessellation looks better. I don't know. It never seemed to catch on like some other things did.

  • MegalomaniakMegalomaniak Posts: 2,649Admin

    The methods that deal with the silhouette better also tend to be more performance costly. Defaults implemented in godot tend to favor performance more since it's a cross-platform engine targeting also very low-end devices such as phones.

    As @cybereality noted, you can implement a custom shader if the default SpatialMaterial doesn't cut it for you. Only limitation is the feature set of the renderer/API you use, currently those would be the GLES 2 and 3 renderers, Vulkan will lift limitations, but primarily by offering a way to override parts of the render pipeline and implement features you need yourself.

    The Vulkan API might be able to offer cutting edge features, but the Vulkan renderer will likely not be implementing everything out of the box, at least initially.

  • MirceaKitsuneMirceaKitsune Posts: 43Member

    On using custom shaders: I always saw that as means of implementing more game-specific functionalities, with common shading techniques remaining builtin to the engine. If I ever find I really need better parallax, I may look for a way to add that to Godot manually and take this route... just not a fan of the idea of overriding builtin shaders to work around what feels like missing features in them.

    Indeed I imagine performance cost would be a little bigger. And I agree that defaulting to performance friendly configurations is the best route... at the same time, it would be sad to see noticeable visual improvements being kept out; I'm hoping Godot is aiming to compete at least with engines like the (now older) UE4 or Unity, providing a FOSS alternative to their seemingly proprietary level of fidelity.

    Easiest solution in this case would seem like implementing this as an optional feature in the depth panel, just like how Deep Parallax is currently a non-default but available option. I'd imagine a menu with 3 options here: Simple Parallax, Deep Parallax, and Projected Parallax (or whatever this technique would be called).

Leave a Comment

BoldItalicStrikethroughOrdered listUnordered list
Align leftAlign centerAlign rightToggle HTML viewToggle full pageToggle lights
Drop image/file