CustomPassUtils.RenderFromCamera not rendering UI

I am using custom pass to render from a disabled camera. This works perfect for opaque and transparent geometry, but it doesn’t render UI elements. Any help with this would be appreciated!

using UnityEngine;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
using System.Reflection;

#if UNITY_EDITOR

using UnityEditor.Rendering.HighDefinition;

[CustomPassDrawer(typeof(RenderFromCamera))]
class FPSForegroundEditor : CustomPassDrawer
{
    protected override PassUIFlag commonPassUIFlags => PassUIFlag.Name;
}

#endif

class RenderFromCamera : CustomPass
{
 
    public LayerMask foregroundMask;
    public Camera UICamera;
    public RenderTexture targetRenderTexture;
    public Material overrideMaterial;
    public ClearFlag clearFlag = ClearFlag.None;
    public RenderQueueType renderQue = RenderQueueType.All;
    public CompareFunction depthState = CompareFunction.NotEqual;
    protected override bool executeInSceneView => false;
    FieldInfo cullingResultField, hdCamField;


    protected override void AggregateCullingParameters(ref ScriptableCullingParameters cullingParameters, HDCamera hdCamera)
        => cullingParameters.cullingMask |= (uint)foregroundMask.value;

    protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd)
    {
        cullingResultField = typeof(CustomPassContext).GetField(nameof(CustomPassContext.cullingResults));
    }

    protected override void Execute(CustomPassContext ctx)
    {
        if (ctx.hdCamera.camera.cameraType == CameraType.SceneView)
            return;

        UICamera.enabled = false;
  
        var depthTestOverride = new RenderStateBlock(RenderStateMask.Depth)
        {
            depthState = new DepthState(true, depthState),
        };

        UICamera.TryGetCullingParameters(out var cullingParams);

        cullingResultField.SetValueDirect(__makeref(ctx), ctx.renderContext.Cull(ref cullingParams));

        CustomPassUtils.RenderFromCamera(ctx, UICamera, /*targetRenderTexture*/ctx.cameraColorBuffer, clearFlag, foregroundMask, renderQue, overrideRenderState: depthTestOverride);
    }

    protected override void Cleanup()
    {
    }
}

Anyone?

@antoinel_unity Can you please give some input on this? Would really appreciate it, thanks!

Hello,

So there are a couple of things to check to make sure your effect is working:

  • Only the canvas render mode “Screen Space UI - Camera” mode is supported, the overlay renders directly to the screen so you can’t capture it in a render target (it’s rendered after the camera)
  • Screen Space Camera UI can only be rendered if the “Render Camera” is enabled, in your case you disable it in the script so that’s not good. As an alternative to cutting the cost of the HDRP camera, you can enable “fullscreen passthrough” in the camera settings.
  • Make sure you also send a depth buffer with a stencil to the DrawRenderers call otherwise all the UI masking features will not work
  • UI Toolkit UI is not supported because it writes directly to the screen like “Screen Space- Overlay” mode

Alternatively, you can also use this package: GitHub - alelievr/HDRP-UI-Camera-Stacking: Optimized implementation of camera stacking for UI only in HDRP. it’s simpler to use for camera stacking purposes.

1 Like