I had issues finding information about decals, so maybe this question will help others. The implementation is for a forward renderer.

Could somebody confirm if i got decal implementation right?

  • You define a cube of any dimension that'll define the projection volume in common space. You check for triangle intersection with the defined cube to recieve triangles that the projection will affect.
  • You clip these triangles and save them.
  • You then use matrix tricks to calculate UV coordinates for the saved triangles that'll reference the texture you're projecting.
  • To do this you take the vectors representing height, width and depth of the cube in common space, so that f.e. the bottom left corner is the origin.
  • You put that in a matrix as the i, j, k unit vectors, set the translation for the cube, then you inverse this matrix.
  • You multiply the vertices of the saved triangles by this matrix, that way you get their coordinates inside of a 0 to 1 size cube that you use as the UV coordinates.
  • This way you have the original triangles you're projecting onto and you have UV coordinates for them (the UV coordinates are referencing the texture you're projecting).
  • Then you rerender the saved triangles onto the scene and they overwrite the area of projection with the projected image.

Now the questions that i couldn't find answers for. Is the last point right? I've never done software clipping, but it seems error prone enough, due to limited precision, that the'll be some z fighting occuring for the projected texture. Also is the way of getting UV coordinates correct?


2 Answers 2


Take a look at this article:


It seems he is using the exact same approach you're using. He doesn't talk about z-fighting, but it could definitely become an issue at larger distances.

My suggestion would be to disable decals after a certain distance if the z-fighting becomes very visible.

  • \$\begingroup\$ i've seen this article multiple times, the thing is that it doesn't talk at all about what i'm asking about, like you've mentioned, the z fighting isn't really an issue of distance, it's just that you're trying to render right on top of existing geometry and due to limited precision, can/cannot you be sure that'll be on top or exactly in the same place \$\endgroup\$
    – dreta
    Jul 11, 2012 at 10:35
  • 2
    \$\begingroup\$ When drawing decals, you could always set the depth buffer comparison function to less-than-or-equal rather than less-than so decals are always drawn just on top of the surface they are affecting. \$\endgroup\$
    – jmegaffin
    May 6, 2013 at 19:12
  • \$\begingroup\$ @jmegaffin Smart! Microsoft suggests using the stencil buffer to mask out the area where the decal falls on st it is always rendered on top. About your method, can we really be that specific about the granularity we set the depth buffer on? \$\endgroup\$
    – KeyC0de
    Nov 7, 2020 at 17:52

What I did to solve the Z fighting was to bump the vertex's Z value by a small amount, in my decal shader, after it's in screen coordinates.

OK..... I use fitted mesh decals. I create a mesh n x n with Y sitting on the terrain. I use code to find the Y on the terrains polygon mesh. After all the transfroms, I'm drawing over the top of existing geometry in screen coordinates. The depth buffer is in screen coordinates so by moving the Z of the decals polygons a slight bit towards the screen, it stops the Z fighting. By doing this I reduced the amount of polygons making up my fitted decals meshes by half. This is old 120 code

 vec4 v = gl_ModelViewProjectionMatrix * gl_Vertex;
 v.z -= .03;
 gl_Position = v;

Hope this explains it better.. (as requested)

All wire frame.

Wire terrain only.

  • 1
    \$\begingroup\$ This answer seems particularly short and unspecific. Could you clarify your answer? \$\endgroup\$
    – Gnemlock
    Jan 28, 2017 at 0:54
  • 1
    \$\begingroup\$ Its not hard to understand.. I move the vertex by just a bit in the Z directing in screen space. Because in OpenGL you are always looking in positive Z in screen space, moving the Z negative a small amount fixes the Z fighting. There is an issue with this however.. As you zoom out, the z can move the decal much more than needed.. A fix is to scale the shift amount by the eye to vertex distance. \$\endgroup\$
    – Mike O
    Sep 19, 2017 at 17:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .