Reputation: 11
Post-processed (On the Camera) enter image description here
Not Post-processed (When taking a screen captrue) enter image description here
The following code is for screen capture with an in-game camera at runtime.
private static IEnumerator RecordFrame(RectTransform rectTransform = null, RawImage rawImage = null)
{
// Disable UI to hide
TurnOffOtherCameras();
// Save Texture in the Last Frame
yield return new WaitForEndOfFrame();
CaptureScreenAndSave(rectTransform, rawImage);
TurnOnOtherCameras();
}
private static async UniTask<bool> CaptureScreenAndSave(RectTransform rectTransform = null, RawImage rawImage = null)
{
...
// This is the main ScreenCaptrue logic
string totalPath = TotalPath;
Texture2D screenTex = null;
int pixelWidth, pixelHeight;
pixelWidth = rectTransform == null ? _camera.pixelWidth : (int)rectTransform.rect.width;
pixelHeight = rectTransform == null ? _camera.pixelHeight : (int)rectTransform.rect.height;
var rt = new RenderTexture(pixelWidth, pixelHeight, 24, RenderTextureFormat.ARGB32);
var prev = _camera.targetTexture;
_camera.targetTexture = rt;
_camera.Render();
screenTex = new Texture2D(pixelWidth, pixelHeight, TextureFormat.ARGB32, false);
RenderTexture.active = rt;
Rect area = new Rect(0f, 0f, pixelWidth, pixelHeight);
screenTex.ReadPixels(area, 0, 0);
screenTex.Apply();
_camera.targetTexture = prev;
if (Directory.Exists(FolderPath) == false)
{
Directory.CreateDirectory(FolderPath);
}
File.WriteAllBytes(totalPath, screenTex.EncodeToPNG());
...
}
The reason why post-processing effects are not applied even when waiting for the last frame with a coroutine and WaitForEndOfFrame is quite intriguing. As far as I know, the rendering order is supposed to be camera rendering, scene rendering, and then the application of post-processing. Why might it not be working?
https://docs.unity3d.com/kr/2022.1/Manual/ExecutionOrder.html
Because the rendering pipeline is URP, I understand that it cannot be resolved using OnRenderImage. Additionally, callbacks such as RenderPipelineManager.endCameraRendering and endFrameRendering didn't yield the desired post-processing results.
There is a ScreenCapture class supported by Unity Engine, and there is a way to solve it using this, but it was too buggy and resolution issue to use. https://forum.unity.com/threads/how-to-capture-screenshot-with-post-processing.701432/
Instead of OnRenderImage, URP can use Scriptable RenderPass to implement it similar to OnRenderImage If anyone is familiar with this and can provide insights, it would be greatly appreciated.
Upvotes: 0
Views: 573
Reputation: 11
I have identified the cause of this issue.
It wasn't the rendering order but rather the RenderTextureFormat and TextureFormat that were the cause.
In my code, when creating RenderTexture and Texture, I was using ARGB32. ARGB32 stores each channel with 8-bit integers, so it has a range of 0-255.
This is suitable for storing Low Dynamic Range (LDR) images. Therefore, using ARGB32 results in the loss of HDR information, making the screen capture appear as if post-processing is not applied.
Therefore, if you want to include post-processing, it is recommended to use ARGBHalf. ARGBHalf stores each channel with 16-bit floating-point numbers, allowing for a much wider range of values to be stored. This supports HDR processing.
By changing RenderTextureFormat to ARGBHalf and TextureFormat to RGBAHalf, post-processing is applied correctly.
This is the result:
Upvotes: 1