How to prevent DecalGeometry from going through mesh?

I’ll use this JS Fiddle to illustrate my point:

When you click on the blue mesh a DecalGeometry is applied on it, the issue is that the Decal is also visible on the other side of the mesh because the size of the decal box is thicker than the mesh itself.
(In this example the thickness of the mesh is 0.2 and the thickness of the decal is 1)

How to prevent the DecalGeometry from appearing on both side of the mesh even if the decal box is thicker than the mesh?

I really want the decal to appear only on the side we click on.

Thanks

The only way to prevent this issue from happening right now is to lower the size of the decal projector.

Alternatively, you could try to prevent this with a custom modification of DecalGeometry by comparing the vertex normal in world space with the viewing direction. If the result is greater zero, you discard the vertex in clipGeometry() (because it means you see the vertex from behind).

Thank you so much for your help @Mugen87. You are helping immensely here! :grinning:

1 Like

Hey @Mugen87,

I’ve been looking at the DecalGeometry source code, and I’m not really sure how to implement the alternative solution you mentioned. (Comparing the vertex normal in world space with the viewing direction).
Would you give me some guidance on how to achieve this code-wise please?

Thank you so much!

Check out this update version of DecalGeometry: https://jsfiddle.net/agod5rh8/

Especially the updated version of pushDecalVertex(). This function is actually a better place for the check than clipGeometry().

1 Like

Waouw thank you so much @Mugen87, you just made my day! :grinning:

1 Like

Does this need an update for newer three js versions ?

the changes i noticed were

in the constructor

...
constructor(camera, mesh, position, orientation, size)
...
const viewDirection = new Vector3()
camera.getWorldDirection(viewDirection)
...

and in pushDecalVertex function

// transform the vertex to world space, then to projector space
			normal.transformDirection(mesh.matrixWorld)

			if (normal.dot(viewDirection) <= 0) {
				vertex.applyMatrix4(mesh.matrixWorld)
				vertex.applyMatrix4(projectorMatrixInverse)

				decalVertices.push(new DecalVertex(vertex.clone(), normal.clone()))
			}

sometimes it works sometimes there’s glitches in the decal and or no decal or an error saying one of the position arrays is undefined

I’ve updated both fiddles to the latest version of three.js. Does the issue you are describing still occur?

1 Like

works great on most flat glb models but on this sketchfab car model it’s glitchy
or refuses to decal Or i get this error

TypeError: Cannot read properties of undefined (reading 'position')

on this line var d3 = inVertices[i + 2].position.dot(plane) - s

Default decal geometry has no problem with this car model but it stamps through all the surfaces the signboard

will try to setup the fiddle with this model

fiddle is setup with the faulty model

@Mugen87 know what’s the issue with this model ?