For the seventh project at the game assembly I created a decal renderer for use by the Technical Artists and Graphical Artists. The renderer projects decals onto the G-Buffer using an albedo texture and optional normal and material textures. The optional textures mean the decals can use the material or normal of the surface they are projected onto.
The renderer both stores decal types and accepts/executes decal render commands.
A decal type is created by assigning textures to a struct that are retrieved from a texture library, which is shared by all objects in the graphics engine to avoid duplicates on the GPU.
In the main loop following the deferred rendering the G-Buffer is copied, as the decal shader needs to read from it to properly project.
The decal renderer then renders (instanced) a frustum like mesh for every decal type. I chose this geometry in order to have a fragment where, as few pixels as possible were shaded while avoiding cutoff that might appear from extreme angles.
When projecting any given pixel in the decals frustum I use the world position in the G-Buffer to create a vector from the decals position to the pixel. Using a dot product I project the toWorld vector onto the right and up vectors of the decals space. I then divide it by its scale to normalize the projected coordinates and add 0.5 to bring it into UV-space.
In order to have the decal use the G-Buffer when relevant texture is missing I lerp towards the decals textures if their lengths are not equal to zero, as DirectX return 0 when a shader resource is not bound.
One issue we had in the game I implemented the decals for was that the players arms would at times have decals projected onto them. The decals make no difference on what surfaces to project onto and not. I would like to implement either a way of projecting onto a specific mesh instance or to filter out certain meshes.
A simple and efficient way of filtering out certain meshes would be to stencil them out, however that would mean you would entirely exclude a mesh type of receiving decals. This could be a non-issue depending on what game you are making.
Another way would be adding a target to the G-Buffer where you’d write out mesh and instance ids and then have the decal instances be associated with the two and discarding any pixels that don’t match them. This could be particularly useful when applying decals to a single character or certain environment pieces.