c++ - 从 OpenGL 应用程序中提取颜色/深度缓冲区
问题描述
我正在考虑一个需要从 OpenGL 应用程序中提取颜色和深度缓冲区的项目,特别是游戏。它与修改完全无关,就操纵游戏本身而言或旨在用于“作弊”目的,但更多地只是用于数据收集。
所以现在我正在尝试找出可能的方法来完成它。当然,能够在 Windows 下使用 Direct3D 甚至会带来更多可用的应用程序,但由于我对 Linux 下的 OpenGL 非常熟悉,所以我会以这种方式开始。
由于有许多改装/作弊应用程序实际上操纵了不同种类的视频游戏的颜色/深度缓冲区(例如,自我射击游戏中的墙黑客),看来这肯定必须以某种方式成为可能。
现在的问题是,实现这一目标的最佳方法是什么?根据这个线程,直接读取 GPU 内存很可能无法正常工作,因为 OpenGL 中的内存映射完全依赖于供应商的实现,并且没有简单的方法可以获取相应数据的 VRAM 地址。
我能想到的替代方法现在可能被归类为静脉注射或静脉注射:
- Extravenous:从进程中提取 OpenGL 上下文并从第三个应用程序访问缓冲区、着色器等,而无需真正直接操作目标应用程序二进制文件。
- Intravenous:以这样的方式操作目标应用程序的二进制/代码,它将相应的缓冲区/数据写入内存中的特定位置或直接保存在某处。
后一种方法肯定可行,但可能需要付出更大的努力,并且需要针对每个应用程序完成。因此首先肯定是首选,但所描述的方式是否完全适用?当您拥有另一个 OpenGL 上下文值时,是否可以从不同进程访问 OpenGL 资源?有没有人有这方面的经验?
更新:
经过一番研究,我发现我正在寻找的东西很常见,通常称为“挂钩”或“拦截”。
对于 OpenGL 和 Direct3D,有许多不同的库和程序可以做到这一点:
- glintercept : OpenGL @ Windows
- Indicium-Supra : DirectX
- apitrace:OpenGL + Direct3D @ Windows、macOS、Linux
- D3D9拦截器:Direct3D
- Nvidia Nsight:Direct3D + OpenGL + Vulkan @ Windows、Linux
和许多其他人。
解决方案
这样做的事实上的标准方法是将自己连接到流程中并将应用程序(游戏)进行的图形 API 调用重定向到您自己的代码。然后,您的钩子可以记录它需要的任何数据并执行它想要的任何操作,然后再将调用传递给实际的 API 实现。有很多方法可以做到这一点,各有优缺点,从构建具有相同界面的假库并诱使游戏加载该库而不是实际的图形库(DLL 注入)到在加载过程中修改机器代码图像以使函数调用跳转到您的代码中。哪种方法适用且最适合您的案例将在很大程度上取决于许多因素,例如目标平台、目标应用程序、您想要连接的 API 等等。
然而,任何此类方法的主要问题在于,这正是作弊的数量。因此,许多视频游戏将带有内置保护,以防止这种东西正常工作。对于许多在线游戏,您甚至可能通过尝试执行此类操作而冒着因涉嫌作弊而暂停您的帐户的风险。但这只是需要注意的事情。根据我的经验,它仍然适用于许多游戏,尤其是单人游戏。
“从另一个进程中提取 OpenGL 上下文”将不起作用,至少在任何适当的操作系统上都不起作用。首先进行流程抽象的全部意义在于将应用程序彼此隔离……
由于我没有足够的声誉在评论中提出这个问题,所以让我在这里问你你的目标到底是什么。您想为单个帧获取一次此信息,还是想在一段时间内为多个帧记录此信息?您是否需要自定义应用程序形式的自动化解决方案?如果两者都不是,您也许可以只使用Nsight Graphics之类的图形调试工具来捕获和导出您想要的帧……
推荐阅读
- vim - Vim 在所有项目文件中搜索
- postgresql - postgresql如何在双引号内插入带有双引号的值
- regex - 用什么正则表达式在两个子字符串之间用换行符替换一些字符串?
- javascript - Three.js 和 CSS3 的结合用于动画与 3D 对象
- rest - 在 API 响应中转发对象的公共属性/变量是一种好习惯吗?
- terraform - terraform vsphere 提供程序在创建 vm 时挂起
- java - Tomcat - 将战争部署到远程 Tomcat 时出现 NoClassDefFoundError
- c# - 模拟服务和网络位置的问题
- css - 无法将 css 应用于 React className
- ios - 在自定义过渡期间使用 .scaleAspectFill 内容模式为图像视图的比例设置动画