Projected Decals Stretching

Started by
2 comments, last by Stephany 9 years ago

I've been using a projected decal system (very similar to the one described in Game Programming Gems 2), where the decal is projected along a vector onto triangles that intersect the projected 3D box. I'm able to find and clip the triangles without much issue. But I'm having some problems generating the UV coordinates in a way that doesn't stretch significantly across surfaces that run parallel to the projection vector.

This makes sense - I'm doing a 2D planar map onto 3D geometry, so the 3D parts are not going to come out looking all that great. But I'm trying to figure out a way to improve the situation.

To compute the UV coordinates, I find the local/relative position of each vertex between the clipping planes. For example, if a vertex is very close to the right clipping plane, it will get horizontal UV coordinate very close to 1.0. The problem is that the front and back clipping planes have no influence on the UV coordinates, allowing the decal to span whatever distance along that axis without the UV coordinates changing in any way. Here are some images. The top one is just a simple projection onto a flat surface (mostly). The bottom two show the stretching problem:

decals_01.jpg
decals_02.jpg
decals_03.jpg

I've been trying to come up with something that at least improves this, like trying to use the depth (Z +/-) of the vertices to move the UV (x/y) coordinates farther outward in whatever direction they were already closest to. It helped a little with the stretching, but caused some pretty bad distortion. The idea still seams sound in my mind (the UV coordinates become closer to the UV edge as the vertices extend into the Z axis) - but if it is so, I haven't been able to apply it correctly.

One other possibilty is to (some how) compute the average normal of all triangle surfaces and project the decal using the average. Then the stretching is somewhat averaged throughout the whole decal. But I have no idea how to compute an average normal that uses each triangle's surface size to increase how much its normal influences the average (smaller triangles should have less influence on the average than larger ones).

Does anyone have any ideas on how to solve this issue? Some way to UV-map vertices that allows the Z axis to influence the coordinates? Or just any idea to help prevent the stretching?

Thanks for any advice

Advertisement

To avoid this effect in my deferred decal I do a normal gradient :


float4 DecalNormal = mul( float4( GBufferBData.rgb, 0.0f ), DecalMatrix );
DecalTexCoord.xy -= DecalTexCoord.z * DecalNormal.xy;

Your projected decals look exactly like projections should, with the same extreme stretching you'd get from aiming a projector wrong into a room's ceiling and side walls: your problem is that you need something different.

To apply "stickers" onto surfaces you should use far smaller decals (more geometry but less fragments) and, for each small decal, use a projection vector that is approximately perpendicular to the target surface. In extreme cases, like "-X" in the last figure, no single direction allows good projection of a large decal and you might need to split it according to the target surface or to balance stretching of different portions.

Omae Wa Mou Shindeiru

To avoid this effect in my deferred decal I do a normal gradient :


float4 DecalNormal = mul( float4( GBufferBData.rgb, 0.0f ), DecalMatrix );
DecalTexCoord.xy -= DecalTexCoord.z * DecalNormal.xy;

I considered something like this. I ran a small test where I performed an entire quaternion rotation for each triangle to move the projection direction onto its surface, and the result wasn't that bad. The only issue was that the texture was split up between the triangles, which may have been solved with some UV welding, but I figured it was too much (rotations + welding) and moved on. However, computing the shared/average normals for each vertex would basically do the same thing without the problem.

Your projected decals look exactly like projections should, with the same extreme stretching you'd get from aiming a projector wrong into a room's ceiling and side walls: your problem is that you need something different.

To apply "stickers" onto surfaces you should use far smaller decals (more geometry but less fragments) and, for each small decal, use a projection vector that is approximately perpendicular to the target surface. In extreme cases, like "-X" in the last figure, no single direction allows good projection of a large decal and you might need to split it according to the target surface or to balance stretching of different portions.

Yeah, my normal decals are not this large. I'm trying to work something out to be used for explosion scorch marks, and possibly some casted shadows. This type of clipping and stretching isn't that noticable on bullet decals.

Thanks for the advice guys

This topic is closed to new replies.

Advertisement