Masked deferred decals

In this article I will describe method of improving Unity 5 deferred decals sample (link).

Since deferred decals are modifying g-buffer, they are projecting on almost everything. Sometimes we need to select what objects will not be affected by decals – player, enemies, etc…

The following image shows the problem:

Arrows shows us, that the decal is projected also on the boots, which is not what we want. We want to separate them and apply decal only on the floor plane. To do this, we will use method from the previous article about modifying G-Buffer.

Decal mask

Separating what should be affected will be done on a per-material basis. Each material will hold float property indicating influence of the decals on a given material.

As a first step, we will modify standard.shader. In the property area we will add following code:

Then, in the UnityStandardInput.cginc, we need to add:

After this, in the UnityStandardCore.cginc, we will modify G-Buffer RT2 alpha (normals + unused low precision alpha). It does not matter that RT2 alpha is low precision, as we will use _DecalFactor mostly as a “binary”, where value of 0.0 means no decal and 1.0 full decal influence.

Modified fragDeferred normal output:

Now we are able to set _DecalFactor property per-material, using material.SetFloat(“_DecalFactor”, value);. We want to be able to define it from the editor, too…

Editor GUI

To show the decal mask custom property, we will need to modify StandardShaderGUI.cs in the following way:

Please note that the previous snippet is pseudo-code to help reader identify, what should be inserted and where…

After modifying standard shader GUI, in the material inspector (of materials with Standard shader) we will see this:

mask_decals_customprop Default value of 1 means that the material should take decal, 0 means no decal.

Visualizing mask

We will assign our boots model material with Decal factor set to 0 and our floor plane material with Decal factor 1.

After this, we can start Frame debugger, and visualize G-Buffer RT2 alpha. It should look like this:

Modifying decal shader

Since in the G-Buffer normal render target we have our decal factor written in the alpha channel, we can simply clip the decal fragment.

Note that _NormalsCopy should also be set for DecalShaderDiffuseOnly variant in the similar way as it is for DecalShaderDiffuseNormals from the DeferredDecalsRenderer.cs.

Final result

After applying the mask, we can now see that our model is not affected by decals anymore:

mask_decals_final

  • TJHeuvel

    Thanks for the clear explanation, helped me out a ton!