OpenGL/D3D : How do I get a screen grab of a game running full screen in Windows?

标签 opengl screen-scraping direct3d10

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

我已经尝试过 GDI、D3D 和 OpenGL 方法(例如 glReadPixels),要么接收到空白屏幕,要么在捕获流中闪烁。

有任何想法吗?

就其值(value)而言,与我想要实现的目标类似的典型示例是 Fraps。

最佳答案

有几种方法可以解决这个问题。它们中的大多数都是 icky,这完全取决于您想要定位哪种图形 API,以及目标应用程序使用哪些功能。
大多数 DirectX、GDI+ 和 OpenGL 应用程序都是双重或三重缓冲的,因此它们都调用:

void SwapBuffers(HDC hdc)
在某一点。每当应绘制窗口时,它们还会在其消息队列中生成 WM_PAINT 消息。这为您提供了两种选择。
  • 您可以将全局 Hook 或线程本地 Hook 安装到目标进程中并捕获 WM_PAINT 消息。这允许您在绘制发生之前从设备上下文中复制内容。可以通过枚举系统上的所有进程并查找已知的窗口名称或已知的模块句柄来找到该进程。
  • 您可以将代码注入(inject)到目标进程的 SwapBuffers 本地副本中。在 Linux 上,这很容易通过 LD_PRELOAD 环境变量或通过显式调用 ld-linux.so.2 来实现,但在 Windows 上没有等价物。幸运的是,有一个来自 Microsoft Research 的框架可以为您执行此操作,称为 。绕道 .您可以在这里找到:link .

  • 演示场景组 Farbrausch 制作了一个名为 kkapture 的演示捕获工具,它利用了 Detours 库。然而,他们的工具针对不需要用户输入的应用程序,因此他们基本上通过 Hook 所有可能的时间函数(如 timeGetTime()、GetTickCount() 和 QueryPerformanceCounter())以固定帧速率运行演示。这完全是拉德。 ryg(我认为?)关于 kkapture 内部的演示文稿可以在 here 找到。 .我认为你对此很感兴趣。
    有关 Windows Hook 的更多信息,请参阅 herehere .
    编辑:
    这个想法引起了我的兴趣,所以我使用 Detours 来连接 OpenGL 应用程序并弄乱图形。这是添加了绿色雾的 Quake 2:Quake 2 Hook
    关于 Detours 如何工作的更多信息,因为我现在已经亲身使用了它:
    Detours 在两个层面上起作用。实际的 Hook 仅在与目标进程相同的进程空间中起作用。因此,Detours 具有将 DLL 注入(inject)进程并强制其 DLLMain 也运行的函数,以及应该在该 DLL 中使用的函数。当 DLLMain 运行时,DLL 应该调用 DetourAttach() 来指定要 Hook 的函数,以及“detour”函数,这是您要覆盖的代码。
    所以它基本上是这样工作的:
  • 您有一个启动器应用程序,其唯一任务是调用 DetourCreateProcessWithDll()。它的工作方式与 CreateProcessW 相同,只是有一些额外的参数。这会将 DLL 注入(inject)进程并调用其 DllMain()。
  • 您实现一个调用 Detour 函数并设置蹦床函数的 DLL。这意味着调用 DetourTransactionBegin()、DetourUpdateThread()、DetourAttach(),然后是 DetourTransactionEnd()。
  • 使用启动器将您实现的 DLL 注入(inject)到进程中。

  • 不过有一些警告。运行 DllMain 时,稍后使用 LoadLibrary() 导入的库尚不可见。因此,您不一定能在 DLL 附件事件期间设置所有内容。一种解决方法是跟踪到目前为止被覆盖的所有函数,并尝试在这些函数中初始化您已经可以调用的其他函数。这样,一旦 LoadLibrary 将新函数映射到进程的内存空间,您就会发现它们。我不太确定这对 wglGetProcAddress 有多好。 (也许这里的其他人对此有想法?)
    一些 LoadLibrary() 调用似乎失败了。我用 Quake 2 进行了测试,但 DirectSound 和 waveOut API 由于某种原因未能初始化。我还在调查这个。

    关于OpenGL/D3D : How do I get a screen grab of a game running full screen in Windows?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3486729/

    相关文章:

    python - 使用 scrapy 进行抓取

    c++ - 创建 DirectX 10 设备和交换链的问题

    c++ - 用于投影的 D3DX vector 数学函数?

    java - 如何引用位于单独库 jar 文件中的 OpenGL 着色器文件?

    java - 创建玩家乒乓 block 时的类(class)组织问题

    python - 用 Python 抓取 Ajax

    带有由 Javascript 填充的选项的 Python Mechanize 表单

    c++ - 创建具有所有语义类型的 Direct3D 顶点是否会降低性能?

    c++ - 如何在 OpenGL 中改变颜色?

    c++ - OpenGL相机运动程序顶点着色器问题