后期处理(在相机上) 在此输入图片描述
未进行后期处理(截屏时) 在此输入图片描述
以下代码用于在运行时使用游戏内相机进行屏幕捕获。
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());
...
}
即使使用协程和 WaitForEndOfFrame 等待最后一帧,后处理效果也不会应用的原因非常有趣。据我所知,渲染顺序应该是相机渲染,场景渲染,然后应用后处理。为什么它可能不起作用?
https://docs.unity3d.com/kr/2022.1/Manual/ExecutionOrder.html
因为渲染管线是URP,我理解使用OnRenderImage无法解决。 此外,诸如 RenderPipelineManager.endCameraRendering 和 endFrameRendering 之类的回调没有产生所需的后处理结果。
Unity Engine 支持一个 ScreenCapture 类,并且有一种方法可以使用它来解决它,但它的 bug 和分辨率问题太多,无法使用。 https://forum.unity.com/threads/how-to-capture-screenshot-with-post-processing.701432/
URP可以使用Scriptable RenderPass来代替OnRenderImage来实现类似OnRenderImage 如果有人熟悉这一点并可以提供见解,将不胜感激。
我已经确定了此问题的原因。
原因不是渲染顺序,而是 RenderTextureFormat 和 TextureFormat。
在我的代码中,当创建RenderTexture和Texture时,我使用的是ARGB32。 ARGB32将每个通道存储为8位整数,因此其范围为0-255。
这适合存储低动态范围 (LDR) 图像。因此,使用 ARGB32 会导致 HDR 信息丢失,使得屏幕捕获看起来好像没有应用后处理。
因此,如果要包含后处理,建议使用ARGBHalf。 ARGBHalf 用 16 位浮点数存储每个通道,允许存储更广泛的值。这支持 HDR 处理。
通过将RenderTextureFormat更改为ARGBHalf并将TextureFormat更改为RGBAHalf,可以正确应用后处理。