我正在Unity中编写一个应用程序,需要每帧(约60fps)从摄像机捕获图像,并将结果数据发送到本地运行的另一个服务。
问题是,我知道在使用GetPixels()
方法时,从相机捕获渲染数据会导致大量帧速率下降(as explained in this article)。文章解释了" GetPixels()阻止ReadPixels()完成"和#34; ReadPixels()在刷新GPU时阻塞#34;这就是为什么GPU和CPU必须同步,导致滞后。
我已经制作了一个带有脚本的示例项目,它只是将帧作为PNG输出到文件中,以复制我想要创建的程序的功能。我已尽力实现本文中描述的内容,即允许GPU渲染帧,然后在调用GetPixels()
之前等待几帧,以免导致GPU和CPU强制同步。但是,我真的没有取得任何进展。该项目仍然以大约10-15fps的速度播放。
如何在Unity中实现每秒60帧的实时捕获?
using System;
using System.Collections;
using System.IO;
using UnityEngine;
namespace Assets
{
public class MyClass: MonoBehaviour
{
private const float reportInterval = 0.5f;
private int screenshotCount = 0;
private const float maxElapsedSecond = 20;
private string screenshotsDirectory = "UnityHeadlessRenderingScreenshots";
public Camera camOV;
public RenderTexture currentRT;
private int frameCount = 0;
private Texture2D resultantImage;
public void Start()
{
camOV.forceIntoRenderTexture = true;
if (Directory.Exists(screenshotsDirectory))
{
Directory.Delete(screenshotsDirectory, true);
}
if (!Application.isEditor)
{
Directory.CreateDirectory(screenshotsDirectory);
camOV.targetTexture = currentRT;
}
}
// Update is called once per frame
public void Update()
{
//Taking Screenshots
frameCount += 1;
if (frameCount == 1)
{
TakeScreenShot();
}
else if (frameCount == 3)
{
ReadPixelsOut("SS_"+screenshotCount+".png");
}
if (frameCount >= 3)
{
frameCount = 0;
}
}
public void TakeScreenShot()
{
screenshotCount += 1;
RenderTexture.active = camOV.targetTexture;
camOV.Render();
resultantImage = new Texture2D(camOV.targetTexture.width, camOV.targetTexture.height, TextureFormat.RGB24, false);
resultantImage.ReadPixels(new Rect(0, 0, camOV.targetTexture.width, camOV.targetTexture.height), 0, 0);
resultantImage.Apply();
}
private void ReadPixelsOut(string filename)
{
if (resultantImage != null)
{
resultantImage.GetPixels();
RenderTexture.active = currentRT;
byte[] bytes = resultantImage.EncodeToPNG();
// save on disk
var path = screenshotsDirectory + "/" + filename;
File.WriteAllBytes(path, bytes);
Destroy(resultantImage);
}
}
}
}
文章暗示这是可能的,但我还没有设法让它发挥作用。
非常感谢您的帮助。
答案 0 :(得分:0)
我不确定OP是否还需要答案。但如果将来有人遇到同样的问题,让我分享一下我找到的东西。
https://github.com/unity3d-jp/FrameCapturer
这是一个专为在Unity编辑器中渲染动画视频而设计的插件。但它也可以独立工作。在我的情况下,我采取了一些部分,并使我的应用程序流动作Jpeg。我用30fps做到了,从未尝试过60fps