首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >虚幻引擎:在不阻塞游戏线程的情况下访问/保存游戏中的映像到磁盘。

虚幻引擎:在不阻塞游戏线程的情况下访问/保存游戏中的映像到磁盘。
EN

Stack Overflow用户
提问于 2017-04-04 22:22:20
回答 4查看 5.9K关注 0票数 5

我正在研究一种基于非真实的开源无人机仿真(Microsoft AirSim),在这里,我试图从附在无人机上的摄像机中获取并保存图像。下面的图片给出了游戏的样子。底部最右边的视图是摄像机的实际视图,另外两个是同一图像的处理版本。

现在,它的设置方式是这样的:有一个相机资产,它作为捕获组件在代码中被读取。屏幕截图中的三个视图链接到此捕获组件。当无人驾驶飞机在游戏中飞行时,观看的画面就没有任何问题。但是当涉及到记录屏幕截图时,当前的代码从这个捕获组件中设置一个TextureRenderTargetResource,然后调用ReadPixels并将数据保存为一个图像(请参阅下面的代码流)。使用ReadPixels()就是直接阻塞游戏线程,使整个游戏慢下来很多:当我开始录制时,从~120FPS下降到小于10个FPS。

代码语言:javascript
复制
bool saveImage() {
  USceneCaptureComponent2D* capture = getCaptureComponent(camera_type, true);
  FTextureRenderTargetResource* RenderResource = capture->TextureTarget->GameThread_GetRenderTargetResource();
  width = capture->TextureTarget->GetSurfaceWidth();
  height = capture->TextureTarget->GetSurfaceHeight();

  TArray<FColor> imageColor;
  imageColor.AddUninitialized(width * height);
  RenderResource->ReadPixels(bmp);
}

看看这篇文章,ReadPixels()显然“会阻塞游戏线程,直到呈现线程赶上为止”。本文包含了读取像素的“非阻塞”方法的示例代码(通过删除FlushRenderingCommands()并使用RenderCommandFence标志来确定任务何时完成),但是它并没有显著提高性能:图像保存的速度略高,但游戏线程仍然运行在大约20个FPS,因此很难控制无人机。是否有更有效的异步方法可以实现我试图在一个单独线程中完成的任务?我也有点困惑,为什么代码可以在屏幕上尽可能快地播放这些图像,但是保存这些图像似乎要复杂得多。这是好的,即使图像被保存到磁盘仅在15赫兹左右,只要它不干扰游戏的本地FPS太多。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-04-10 07:18:42

您可以将保存到磁盘操作从游戏线程移动到其他线程。

请查看Async.h以了解详情

线程的限制是不能在其他线程中修改/添加/删除uobject/uactor。用于UE4的多线程

票数 1
EN

Stack Overflow用户

发布于 2017-04-07 21:43:18

(...)显然,ReadPixels()“将阻止游戏线程,直到呈现线程赶上”。

使用尝试访问和复制GPU纹理数据的函数总是很痛苦的。我发现这些功能的完成时间取决于硬件或驱动程序版本。您可以尝试在不同(最好是更快或更新的) GPU平台上运行您的代码。

回到代码:为了绕过单线程问题,我尝试使用UTextureRenderTarget2D方法将UTexture2D复制到TextureRenderTarget2D::ConstructTexture2D。当你得到你的图像复制(我希望它要快得多),你可以把它推到消费者线程在15 FPS的比率。线程可以使用FRunnable或异步引擎模块创建(使用所谓的任务图)。使用者线程可以使用纹理的PlatformData->Mips[0]->BulkData访问克隆的纹理。确保您正在读取BulkData->Lock(...)BulkData->Unlock()调用之间的纹理数据。

我不确定,但这可能会有所帮助,因为渲染线程不会使用复制的纹理,因此您可以锁定它的数据,而不会对呈现线程进行任何阻塞。我只担心线程安全的锁和解锁操作(没有找到任何线索),应该是可能的,除非有引擎RHI呼叫。

这里是一些可能有用的相关代码。

票数 1
EN

Stack Overflow用户

发布于 2020-04-10 21:30:37

我已经迟到了,不过万一还有人对此有异议:我建立了一个非阻塞版本,灵感来自AirSim和UnrealCV的插件代码,因为我有一些严重的编译和版本问题。但需要一个平稳运行的相机,同时自己拍摄图像。这也是基于异步类的非真实API提供的,这是被接受的答案。我为此设置了一个教程回购:https://github.com/TimmHess/UnrealImageCapture

希望能帮上忙。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43218678

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档