How to limit decals ''bleeding'' on perpendicular surfaces

I’d like to know if it’s possible to prevent that kind of artifact when you put a decal on a wall. It always project some kind of artifact on perpendicular surfaces :

25fadb82ad505dab7eac13c966dffa66d99c80f9.jpeg

Where the red X are, this is very ugly and unrealistic. I can reduce the ‘‘thickness’’ of the area of effect but it’s not practical. I just want the decal to be invisible on perpendicular surfaces.

This is how you can mask out any normals that were up or down. To mask out anything perpendicular to the projection angle requires creating a blueprint container for your decal and creating a Material Instance Dynamic and setting the decals X rotation to be the value of a VectorParameter. Then in the material, just plug in that new vector value to one of the pins on the dot product.

2 Likes

Hi there,
I’ve got a similar problem regarding decals. I was trying to implement your solution RyanB but I think I didn’t understand everything correctly and it won’t work the way it should. Is it possible you post screens of full material and bluprint to show the final versions of both? It will be a huge help!

This only works if you are using decal blend mode set to translucent as dbuffer blend modes cant access the world normal

I’ve tried deciphering what RyanB has said… creating the blueprint for the decal to get the normals, pass them through as a vector parameter on a dynamic material instance.
In the material, trying to dot to compare the pixel world space normal with the decal normal, but it’s just not working.
The goal is to obviously “backface cull” decals that are projecting through when they shouldn’t. The pics I’ve attached show why simply scaling the box volume doesn’t work, it’s projecting onto the inside of a curved thin suface of a pipe.
I’ve tried to make this in as simple of an isolated case as possible. If anyone (or the almighty RyanB himself) can chime in with some insight that’d be awesome.

maskeddecal.jpg You can see the decal masked out on the underhang

Interesting
what does your rotvector from your blueprint look like?
and I’m not sure how you’re accessing the scene texture world normal through a deferred decal. That gave a material sm5 error for me.

I tried your method, it required changing the decal material to translucent blend mode, which got rid of a bunch of rendering options I’d need (accessible through the dbuffer blend modes). It also didn’t render the decals in shadows which was weird.

I’ve attached pics of another hacky method I’ve tried, I’m not happy with it and it has artifacts at glancing angles :frowning:

Really it does need to be able to access the underlying normal surface normal, like how the scenetexture world normal node does, but the PixelNormalWS doesn’t work the same way, it’s not culling it.

Is this method RyanB spoke of not actually technically possible?

It’s not working because in deferred decals, the PixelNormalWS node returns the decal projection direction, not the normal of the pixel receiving the decal. The only way to access that is by reading the WorldNormal SceneTexture (as long as you don’t plug anything into the Normal output: a decal cannot read and write to the normal buffer).

For something like this, I’d just use a mesh decal. I know it’s a little extra work and not quite a flexible, but totally resolves your issue.

How can any dbuffer decal read the SceneTexture WorldNormal?

Need hundreds of decals, that isn’t really viable :\

If the decal ouputs normals, then it’s writing to the WorldNormal texture with blending. A pixel shader cannot read a texture it’s writing to.

DBuffer decals, regardless of writing to normals or not, can never read the SceneTexture WorldNormal buffer. The error above shows they can only access SceneDepth, CustomDepth and CustomStencil.

I know this is an old post but it is the only thing that comes up when searching for this… you can do this effect without blueprints using the ObjectOrientation node.
DecalNormalBlending.png
…And this is the result
:


Hope this helps anyone in the future, good luck!

4 Likes

@Albarnie

​​​​​Thanks for the update, that’s a great solution and worked really well, but the only issue is you lose the ability to have any normal information in your decal. Any way you know of that will allow you to add the normal map back in while still using SceneTexture:WorldNormal.

This works with DBuffer ?, it doesn’t allow me to connect the dot node :frowning:

1 Like

Yeah that is the main caveat. To do this, Unreal Engine would have to implement a decal layer system similar to what Unity has in HDRP, which would also mean that you can blend the surface normal. This solution is best for things like blood splatters, puddles etc that don’t require normal detail.

Scene textures can only be used with GBuffer decals afaik

MUCH more straightforward… :slight_smile:

Thank you