OpenGL/D3D:如何在Windows中全屏运行游戏的屏幕抓取?

The*_*ley 11 opengl screen-scraping direct3d10

假设我有一个全屏运行的OpenGL游戏(Left 4 Dead 2).我想以编程方式获取它的屏幕抓取然后将其写入视频文件.

我尝试过GDI,D3D和OpenGL方法(例如glReadPixels),并在捕获流中接收空白屏幕或闪烁.

有任何想法吗?

对于它的价值,一个类似于我想要实现的东西的典型例子是Fraps.

小智 14

有一些方法可以解决这个问题.它们中的大多数都很蹩脚,它完全取决于您要定位的图形API类型以及目标应用程序使用的功能.大多数DirectX,GDI +和OpenGL应用程序都是双缓冲或三缓冲,因此它们都调用:

void SwapBuffers(HDC hdc)
Run Code Online (Sandbox Code Playgroud)

在某一点.每当绘制窗口时,它们还在其消息队列中生成WM_PAINT消息.这为您提供了两个选择.

  • 您可以在目标进程中安装全局钩子或线程本地钩子并捕获WM_PAINT消息.这允许您在绘画发生之前从设备上下文中复制内容.可以通过枚举系统上的所有进程并查找已知的窗口名称或已知的模块句柄来找到该过程.

  • 您可以将代码注入目标进程的SwapBuffers本地副本.在Linux上,这将是很容易通过LD_PRELOAD环境变量,或致电LD-linux.so.2明确的事情,但在Windows上没有equivalient.幸运的是,微软研究院的一个框架可以为你做这个叫做Detours的框架.你可以在这里找到:链接.

demoscene组织Farbrausch制作了一个名为kkapture的演示捕获工具,该工具使用了Detours库.他们的工具然而针对不需要用户输入的应用程序,所以他们基本上挂接到所有可能的时间功能,如timeGetTime()的GetTickCount()和QueryPerformanceCounter的()运行在固定帧率演示.这完全是拉.ryg(我认为?)关于kkapture的内部结构的演示文稿可以在这里找到.我觉得你很感兴趣.

有关Windows挂钩的更多信息,请参阅此处此处.

编辑:

这个想法引起了我的兴趣,因此我使用Detours来加入OpenGL应用程序并弄乱图形.这里是添加绿雾的Quake 2: 雷神之锤2

关于Detours如何工作的更多信息,因为我现在第一手使用它:

Detours有两个层次.实际挂钩仅在与目标进程相同的进程空间中工作.所以Detours有一个函数,用于将DLL注入进程并强制其DLLMain运行,以及应该在该DLL中使用的函数.当运行DLLMain时,DLL应调用DetourAttach()来指定要挂钩的函数,以及"绕行"函数,这是您要覆盖的代码.

所以它基本上是这样的:

  • 你有一个启动器应用程序,唯一的任务是调用DetourCreateProcessWithDll().它的工作方式与CreateProcessW相同,只需要一些额外的参数.这会将DLL注入进程并调用其DllMain().
  • 您实现了一个调用Detour函数并设置trampoline函数的DLL.这意味着调用DetourTransactionBegin(),DetourUpdateThread(),DetourAttach(),然后调用DetourTransactionEnd().
  • 使用启动程序将您实现的DLL注入进程.

但有一些警告.运行DllMain时,稍后使用LoadLibrary()导入的库尚不可见.因此,您无法在DLL附件事件期间设置所有内容.解决方法是跟踪到目前为止被覆盖的所有函数,并尝试初始化您已经可以调用的这些函数中的其他函数.这样,只要LoadLibrary将它们映射到进程的内存空间,您就会发现新函数.我不太确定这对wglGetProcAddress有多好.(也许这里的其他人有关于此的想法?)

一些LoadLibrary()调用似乎失败了.我使用Quake 2进行了测试,而DirectSound和waveOut API由于某种原因未能初始化.我还在调查这个.


sum*_*ame 0

我发现了一个名为 taksi 的 sourceforge 项目:

http://taksi.sourceforge.net/

不过,Taksi 不提供音频捕获功能。