How to Create Rich Surface Details Like Crimson Desert Using POM Silhouettes
Surface Forge creator ArghanionsPuzzlebox explains how to recreate Crimson Desert-inspired POM silhouettes, self-shadowing, UV rotation fixes, and production-ready displacement workflows in Unreal Engine 5.
One of the most visually striking aspects of Pearl Abyss' best-selling action-adventure epic, Crimson Desert, isn't necessarily its characters or environments, but the extraordinary amount of depth present across nearly every surface in the game.
Brick walls, stone pathways, architectural details, and environmental assets all appear to exhibit convincing geometric richness, creating a level of material depth that feels far beyond what traditional normal maps can achieve. That observation led Surface Forge creator ArghanionsPuzzlebox down a technical rabbit hole.
Initially inspired by Crimson Desert's implementation of screen-space displacement techniques, the investigation evolved into a deeper exploration of what modern Parallax Occlusion Mapping (POM) can still accomplish inside Unreal Engine 5 when combined with proper self-shadowing, silhouette generation, and production-focused optimization strategies.
In this interview, ArghanionsPuzzlebox breaks down the research process behind recreating a Crimson Desert-inspired POM silhouette effect
What drew you to Crimson Desert’s implementation, and why was it worth breaking down?
What stood out to me was the sheer amount of depth on every surface in Crimson Desert and how much richness it added to the environment. It wasn’t just on ground planes or specific hero surfaces — it was everywhere, and it looked stable. The displacement created perceived 3D geometry that held up at every viewing angle, which immediately told me this wasn’t standard POM.
That scalability is what made me curious. Normally, geometry-based displacement can be very difficult to manage in production because its performance cost is non-linear. You might have well-optimised parts of a mesh sitting next to badly-optimised parts, and there’s no easy way to predict where the cost will spike. With what Crimson Desert was doing, the effect looked “screen space” to me — consistent, predictable, and applied universally. I wanted to understand how that was possible and whether I could achieve something similar.
Community research later confirmed that Pearl Abyss’s Black Space Engine uses Screen Space Displacement Mapping internally, which validated the instinct. But in the process of studying it, I found that traditional POM still had untapped potential — especially around silhouettes, self-shadowing, and UV rotation handling — which became the foundation of Surface Forge.
Where does POM make the most sense in a modern production pipeline?
POM sits in a sweet spot between normal maps and geometry displacement. Normal maps are cheap but flat — they can’t give you self-occlusion, self-shadowing, or silhouettes. Geometry displacement gives you all of that, but at a mesh complexity cost that scales unpredictably. POM’s cost is per-pixel and predictable. You know exactly what you’re paying — it’s the step count times the pixel coverage. It doesn’t generate triangles, doesn’t affect the geometry pipeline, and doesn’t interact with LOD systems in unexpected ways.
For interior environments, architectural visualisation, tiled surfaces like brick, stone, tiles, and cobblestone — anything where the surface is mostly flat but needs convincing depth — POM is arguably the best tool for the job. It also works brilliantly on decals, which is something tessellation and Nanite displacement simply cannot do. A POM decal can add depth to any surface you project onto.
Crucially, POM and Nanite displacement aren’t mutually exclusive. They’re complementary. You can use Nanite for the macro geometry that affects silhouettes and catches real light, and then use POM to add the fine self-shadowing detail — those deep dark crevices and sharp shadow lines that would cost a fortune in polygons. Surface Forge 1.0 will include a shadow-only POM mode specifically designed for this pairing: Nanite handles the geometry, POM provides the self-shadowing.
The self-shadow method is one of the areas I’ve spent the most time on, and it’s now almost entirely fixed and accurate. What makes it powerful as an art direction tool is the level of control it gives you. The shadow intensity, penumbra softness, and step crispness are all independently adjustable — completely decoupled from the displacement depth. Nanite displacement gives you physically correct shadows from scene lights, which sounds good on paper, but means you can’t dial the shadow character independently. With POM shadows, you can art direct the look in ways that pure geometry can’t match.
What are the biggest pitfalls developers run into with POM in Unreal Engine 5?
The first thing most people miss is self-shadowing. Without it, POM looks flat — you get the parallax displacement but no shadow information, so the depth illusion is only half there. Getting self-shadowing set up requires a second ray march along the light direction, which many tutorials skip entirely.
Once developers do set up shadows, the next pitfall is rotation. If you rotate UVs or the mesh, the shadow direction flips or points the wrong way. This is because the light direction needs to be rotated in tangent space after the world-to-tangent transform, not before. It’s a subtle distinction but getting it wrong means your shadows face the opposite direction at certain rotations. I spent a significant amount of time tracing through the node chain to find and fix this in Surface Forge.
Normal correction after rotation is another common issue — not strictly a POM problem, but it trips people up in POM setups specifically because they’re already dealing with rotated UVs and the normal map needs to be rotated to match.
On the performance side, a lot of developers don’t realise that step count dithering with Temporal AA can massively reduce the per-pixel cost. Instead of running 64 or 128 uniform steps on every pixel, you vary the step count per pixel using a dither pattern with some random noise mixed in. Each individual frame looks noisy at low step counts, but TAA accumulates the result across frames and resolves it into a smooth image. You end up getting the visual quality of a high step count at a fraction of the average per-pixel cost. It’s almost free to set up — just a few nodes before the step count input.
Finally, there’s a widespread misconception about distance fade. People assume that lerping POM intensity to zero at distance saves performance, but the GPU still executes every instruction in the shader — it just multiplies the result by zero. To actually reclaim performance, you need separate material instances with StaticSwitches that compile out the POM path entirely. The fade needs to happen at the material LOD level, not inside the shader.
How does your silhouette approach differ from traditional POM technically?
Traditional POM has a very sharp cutoff at mesh edges. The displacement just stops abruptly, and the illusion breaks instantly — you see the flat polygon edge and the effect looks like a painted-on texture that suddenly ends. My approach adds a silhouette cutout at every edge of the mesh by detecting where the POM displacement has overshot the mesh boundary and masking those pixels via opacity.
The technical challenge was making this work with UV rotation and tiling. The naïve approach — checking the final displaced UVs against some bounds — breaks immediately when you rotate or tile, because the final UVs have gone through multiple transforms (tiling, rotation, reference plane offset, POM displacement). You can’t reconstruct valid bounds in that transformed space.
The solution I landed on was to work in raw mesh UV space instead. I take the POM offset vector, inverse-rotate it back to the unrotated space, scale it by the inverse of the tiling factor, and then check whether it pushes past the fixed [0,1] mesh UV bounds. This works at any rotation angle and any tiling value because the bounds are always [0,1] in that space. The result is a silhouette that follows the POM displacement naturally — tall areas overshoot less, low areas overshoot more — giving the mesh a perceived thickness rather than a flat cutoff.
How does this compare to tessellation, Nanite geometry, or other displacement workflows?
Each approach has its place. Geometry displacement via tessellation or Nanite gives you physically correct silhouettes and real light interaction, but the cost scales with mesh complexity and is hard to predict. POM’s cost is purely per-pixel — it’s consistent regardless of mesh topology. In many cases, POM can actually be more performant than displacement because you’re not generating any geometry; it’s just a pixel shader operation.
Where it gets really interesting is layering. POM and displacement aren’t competing — they’re complementary. You could have a layer using Nanite displacement for the macro geometry, giving you real height and correct silhouettes, and then a second layer using POM for the fine detail — deep crevices with dark, dramatic shadows that would cost a fortune in polygons. Think of a stone surface with pebbles that have real geometric height from displacement, but between them you have dark cracks rendered with POM for that extra depth and shadow richness.
There are also use cases that geometry displacement simply can’t touch. Decals, for example — you can’t displace geometry through a decal, but POM on a decal gives you depth on any surface you project onto. That’s a powerful tool for environment artists who want to add detail without modifying the underlying mesh.
Displacement does have clear advantages for viewing angle artefacts — real geometry holds up at extreme angles where POM can start to show its limits. But if trimmed and placed correctly in environments, POM can add an unparalleled richness, especially when the self-shadowing is properly set up and art directed.
What are some key considerations for environment artists integrating POM into their projects?
Heightmap quality comes first: POM is only as good as the heightmap driving it. If the heightmap has harsh transitions or isn’t authored with depth in mind, no amount of step count will make it look right. Smooth gradients with clear height information give you clean displacement and accurate shadows.
Use step count dithering with TAA: Don’t brute-force 128 steps everywhere. Vary the step count per pixel using a dither pattern and let Temporal AA resolve the result. You get the visual quality of high step counts at a fraction of the per-pixel cost.
Keep the height ratio conservative: Going too high with displacement depth is the fastest way to break the illusion. A subtle value with good shadow intensity looks far more convincing than an aggressive displacement that exposes all the artefacts. Let the shadows do the heavy lifting for perceived depth.
UV layout matters for silhouettes: If you want silhouette clipping to work correctly with rotation and tiling, your mesh UVs need to be clean 0–1 per face. Overlapping UVs or non-standard layouts will confuse the bounds checking.
Use StaticSwitch for LOD, not dynamic branching: Distance fade via lerp doesn’t save any GPU cost — the shader still runs all instructions and multiplies the result by zero. Separate material instances with StaticSwitches that compile out the POM entirely at distance is the only way to actually reclaim performance.
Self-shadowing is what sells the depth: Without shadows, POM looks flat. Invest the time to set up the light trace chain correctly, make sure rotation is handled in tangent space, and use the penumbra and intensity controls to art direct the shadow character. This is where POM goes from a tech demo to a production tool.
Subscribe to 80 Level Newsletters
Latest news, hand-picked articles, and updates
You can check out the entire tutorial embedded above or here for the full breakdown.
Don't forget to subscribe to our Newsletter, join our 80 Level Talent platform, and follow us on Twitter, LinkedIn, Telegram, and Instagram, where we share breakdowns, the latest news, awesome artworks, and more.
Are you a fan of what we do here at 80 Level? Then make sure to set us as a Preferred Source on Google to see more of our content in your feed.