Render material output only to normalmap in gbuffer skip basecolor

Hi there,

i was wondering if it’s possible to only manipulate the roughtness+normal data stored in the gbuffer but skip the basecolor? Basically identical to what’s possible for deffered decals, but use it with regular meshes.
I’ve already tried setting the material domain to deferred decal, but that didn’t seem to work for static meshes.

Thanks

I don’t think there is any way to do that with a regular material. The gbuffer uses multiple render targets in such a way that it only needs one base pass to be rendered for the scene. If the gbuffer were broken down into separate passes for each layer, you could do what you are asking but that would be very slow. One of the basics of deferred rendering is using MRTs to avoid multiple scene passes. Gbuffer decals are a project setting since they add overhead to the deferred renderer that not all project have the budget for. So it is unlikely that doing something similar right in the base pass will ever happen. Even adding more features like that to project settings is not the preferred way of doing things so a strong case must be made for it in each case.

It is possible though at some point that we will add support for deferred decals on static mesh geometry. It should be possible to do what you are asking using that method but it is currently not scheduled.

Hi Ryan, thanks for the reply! I actually understand how a deferred renderer works :). Unfortunately I don’t know how UE4 handles this internally but I don’t see why this should cause any performance issues or a fall back to a multi-pass approach.
In a single pass, the easy way would be to have a bit-mask that decides which render targets will be bound and written to for the next drawcall, then simply mask out basecolor.
The other way (if all targets must be bound) would be to use blending and write alpha values of 0 to the render target(s) that should be skipped.
Again, I do not know UE4’s internals but my guess is that you’re using any of the two methods for deferred decals.

That’s from the documentation of the Decal Actor. Basically this is what I want for regular materials.

I wasn’t referring to so called dbuffer-decals, which have to be enabled on a per-project basis. I was referring to regular deferred decals that are always enabled.

I am not sure if I understand you correctly, but according to the documentation one of the limitations is that it ONLY works on static mesh geometric (“We currently only support deferred decals and they only work on static objects.”)

I guess I didn’t communicate clearly what I am trying to do, English is not my mothers-tongue so I am sorry for that.
So I’ll try this again:

I have a static mesh with a material applied, and I only want to manipulate the normal data inside the g-buffer, identical to how deferred decals are being rendered with DBM_NORMAL set.
Consider this case, a FBX file: mesh 0 is a wall model and mesh 1 is a grunge layer made up of quads around the edges of the wall. However the grunge layer in mesh 1 should only modify the roughness and normal data not the color of the wall stored inside mesh 0.

EDIT: from looking at the code, UE4 is actually using method#1 with switching render targets. Here is some code from the engine PostProcessDefferedDecals.cpp:960 where render commands are inserted to change the active render target:



switch(CurrentRenderTargetMode)
				{
					case RTM_SceneColorAndGBuffer:
						{							
							TargetsToResolve[SceneColorIndex] = GSceneRenderTargets.GetSceneColor()->GetRenderTargetItem().TargetableTexture;
							TargetsToResolve[GBufferAIndex] = GSceneRenderTargets.GBufferA->GetRenderTargetItem().TargetableTexture;
							TargetsToResolve[GBufferBIndex] = GSceneRenderTargets.GBufferB->GetRenderTargetItem().TargetableTexture;
							TargetsToResolve[GBufferCIndex] = GSceneRenderTargets.GBufferC->GetRenderTargetItem().TargetableTexture;
							
							SetRenderTargets(RHICmdList, 4, TargetsToResolve, GSceneRenderTargets.GetSceneDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite);
						}
						break;

					case RTM_GBufferNormal:
						TargetsToResolve[GBufferAIndex] = GSceneRenderTargets.GBufferA->GetRenderTargetItem().TargetableTexture;
						SetRenderTarget(RHICmdList, TargetsToResolve[GBufferAIndex], GSceneRenderTargets.GetSceneDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite);
						break;
...
}


I still hope that there is a simple mechanism for materials to access similar functionality.

I think that line about only working on static mesh geometry is old. Checking with rendering guys. But regardless, you are intepreting that line wrong. That has to do with what it works to project onto, not saying you can actually apply a deferrred decal to a regular mesh.

Actually you can apply a deferred decal mat to a regular mesh but what happens is the engine uses a regular material on it instead. Just tried.

cc4527af59523226d928cf07beaf0c847ee1c8bd.jpeg

This is a normal-only decal projecting onto static meshes and a skeletal mesh. I applied the same decal material to the left cube but you can see the engine has used a separate compiled material and assumed 0 basecolor among a few other things. The feature I was talking about would basically let you apply the decals to a mesh like that cube and have it still behave like the decal. I think if we had that, you could do what you want and it wouldn’t matter than it wasn’t inside of regular materials.

No, I actually understood that correctly. What you mean is using a static mesh as a decal projector with a decal material. I did understand that as “only static meshes can receive decals from a decal projector/actor”, NOT act as a projector (with a deferred decal material). I actually understand the whole process behind that, being that deferred decals are rendered during a post process pass etc.

I only used the decal actors and handling as an example of what I intend to do. I actually tried the same what you did initally and got the same results.

If you’re in touch with the render guys, could you check if there is a way to bind only the normal and rougness render targets when a specified material is rendered?

Rendering guy answer :wink:

Ryan answered this very well but I can go a bit more in detail.

No, we don’t have the requested functionality yet. At the moment the base pass is always outputting to all MRT. This is mostly for simplicity (code and usage) but it also gives us the flexibility to rearrange the GBuffer layout. Decals use a subset of the GBuffer and lock us into some layout but because of the few fixed modes we still have some flexibility. Exposing the actual MRT layout would lock us completely.
Ryan is right - we consider making non deferred decals - maybe if the form you want it (custom meshes instead of clipped mesh portions).

The documentation comment about the static is misleading/wrong - it means deferred decals don’t skin/transform with skeletal meshes or animated objects so it’s best use on static objects.

Hi Martin, thanks for the reply and for clarifying this. It would be awesome if there would be a way to write only to specific render targets in the future. I guess this thread can be closed now.