Issues with Camera.Render() and Post Processing

I’m working on a tool that captures an image to a render texture for everything on a specific layer. The background must be transparent, which I set with clear flags using Color.clear. The render texture is then converted into a sprite and used in the game or saved out to a png. The issue I’m having is that I can’t seem to get post processing to apply to the result of the Camera.Render() call. I get all the opaques and transparents just fine. I’ve flipped every lever I can think of in the player settings, on the renderers, on the render texture, and on the camera. I tried ensuring the post processing was on the same layer. I’ve tried manually adding a Volume to the camera’s object and copying the settings from the existing global volume. I’ve tried creating a new Volume manually with the post processing I want. I want it to render out the full camera stack, as if it was doing a screenshot, but only a certain layer. So if there’s a bloom pass, it should get done, if there’s tone mapping applied, it should be applied, etc.

My post processing does work in my scene just fine for normal gameplay. Using the screenshot tools, the post processing is captured just fine.

Here’s some snippets of some important parts of the system, which may help.

public static bool CaptureToRenderTexture(Camera sourceCamera, Transform anchor, RenderTexture rTex) {
    if (sourceCamera == null) return false;

   // Clear any stale data
   rTex.Clear();

   // Configure camera
   var glamourCam = new GameObject(
      name: "GlamourCam",
      components: new System.Type[1] { typeof(Camera) }
   ).GetComponent<Camera>();

   glamourCam.CopyFrom(sourceCamera);
   glamourCam.transform.SetPositionAndRotation(anchor.position, anchor.rotation);
   glamourCam.tag = "GlamourCam";
   glamourCam.cullingMask = 1 << LayerMask.NameToLayer("Glamour");
   glamourCam.clearFlags = CameraClearFlags.SolidColor;
   glamourCam.backgroundColor = Color.clear;
   glamourCam.targetTexture = rTex;

   // Work
   glamourCam.Render();

   // Cleanup & Return
   GameObject.Destroy(glamourCam.gameObject);
   return true;
}

public static Texture2D CaptureToTexture2D(Camera sourceCamera, (int width, int height) resolution, Transform anchor) {
   RenderTexture rTex = new(resolution.width, resolution.height, 24);
   rTex.Create();

   if (!CaptureToRenderTexture(sourceCamera, anchor, rTex)) {
      rTex.Release();
      return null;
   }

   var tex = rTex.ConvertToTexture2D();

   rTex.Release();
   return tex;
}

public static void Clear(this RenderTexture rt) {
   RenderTexture.active = rt;
   GL.Clear(true, true, Color.clear);
   RenderTexture.active = null;
}

public static Texture2D ConvertToTexture2D(this RenderTexture rTex) {
   Texture2D tex = new(rTex.width, rTex.height, TextureFormat.RGBA32, false);
   RenderTexture.active = rTex;
   tex.ReadPixels(new Rect(0, 0, rTex.width, rTex.height), 0, 0);
   tex.Apply();
   RenderTexture.active = null;
   return tex;
}

public static Sprite ConvertToSprite(this Texture2D tex) =>
   Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f));

Here’s the global volume I’d like to use.

This is the camera that the settings are copied from.

Here’s the renderer used.

And here’s the pipeline asset. HDR is on.

1 Like

Bump. Still having issues with this, could really use some help!

Bump, still seeing this issue. I’ve not been able to repro it in another project. Not sure what’s going on, could really use some assistance!

Be sure to also add a UniversalAdditionalCameraData component to your glamourCam, as this actually holds URP-specific properties, such as post processing being enabled or not.

It may get added automatically, but post processing would be disabled by default.

Thanks for the reply!
With the inclusion of UniversalAdditionalCameraData, we still see the same behavior. We stopped creating a new camera and are relying on an existing scene camera which has the UACD component attached.

Hi, I know this is an old post, but I think this is a similar problem to this one How to get post processing on Camera.Render() in URP and thought the solution could be helpful on here as well:

I had a similar problem on unity version 2022.3.62 LTS, and I followed this solution on this post:
Unity RenderTexture - 스크린 캡쳐시 PostProcessing 효과 적용안되는 버그 수정 | Sehyup

I changed the RenderTextureFormat.ARGB32 in RenderTexture.GetTemporary to RenderTextureFormat.ARGBHalf,
and TextureFormat.RGB24 in new Texture2D to TextureFormat.RGBAHalf!

Translation about why this works on this post:

  • ARGB32 stores each channel as an 8-bit integer, with values ranging from 0 to 255. This makes it suitable for storing LDR (Low Dynamic Range) images.

  • Therefore, post-processing effects (bloom, tone mapping, etc.) often require a high dynamic range and precision, and the ARGB32 format cannot store this high range, which is why post-processing effects were not properly applied to RenderTexture.

  • For ARGBHalf and RGBAHalf, each channel is stored as a 16-bit floating point, allowing for a much wider range of values than ARGB32. This means it supports HDR processing, which is typically required by post-processing effects.