gpt4 book ai didi

c++ - dll 注入(inject) : drawing simple game overlay with opengl

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:15:17 25 4
gpt4 key购买 nike

我正在尝试在 3d 桌面游戏中绘制自定义 opengl 叠加层(例如 steam 就是这样做的)。这个覆盖图基本上应该能够显示用户需要的一些变量的状态可以通过按一些键来影响。把它想象成一个游戏教练。目标首先是在屏幕上的特定点绘制一些图元。后来我想在游戏窗口中有一个看起来不错的“gui”组件。游戏使用 GDI32.dll 中的“SwapBuffers”方法。目前我能够将自定义 DLL 文件注入(inject)游戏并 Hook “SwapBuffers”方法。我的第一个想法是将覆盖图插入到该函数中。这可以通过将游戏的 3d 绘图模式切换为 2d 来完成,然后在屏幕上绘制 2d 叠加层并再次切换回来,如下所示:

//SwapBuffers_HOOK (HDC)
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glOrtho(0.0, 640, 480, 0.0, 1.0, -1.0);

//"OVERLAY"
glBegin(GL_QUADS);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex2f(0, 0);
glVertex2f(0.5f, 0);
glVertex2f(0.5f, 0.5f);
glVertex2f(0.0f, 0.5f);
glEnd();

glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();

SwapBuffers_OLD(HDC);

但是,这对游戏没有任何影响。

  • 我的方法是否正确合理(还要考虑我的 3d 到 2d 切换代码)?
  • 我想知道在 Hook 函数中设计和显示自定义叠加层的最佳方法是什么。 (我应该使用类似 Windows 窗体的东西还是应该用 opengl 函数组装我的组件 - 线,四边形...?)
  • SwapBuffers 方法是绘制叠加层的最佳位置吗?

任何类似的提示、源代码或教程也很受欢迎。顺便说一下,这款游戏是反恐精英 1.6,我不打算在线作弊。

谢谢。

编辑:

我可以通过使用“derHass”提议的新 opengl 上下文设法在游戏窗口中绘制一个简单的矩形。这是我所做的:

//1. At the beginning of the hooked gdiSwapBuffers(HDC hdc) method save the old context
GLboolean gdiSwapBuffersHOOKED(HDC hdc) {
HGLRC oldContext = wglGetCurrentContext();
//2. If the new context has not been already created - create it
//(we need the "hdc" parameter for the current window, so the initialition
//process is happening in this method - anyone has a better solution?)
//Then set the new context to the current one.
if (!contextCreated) {
thisContext = wglCreateContext(hdc);
wglMakeCurrent(hdc, thisContext);
initContext();
}
else {
wglMakeCurrent(hdc, thisContext);
}
//Draw the quad in the new context and switch back to the old one.
drawContext();
wglMakeCurrent(hdc, oldContext);
return gdiSwapBuffersOLD(hdc);
}

GLvoid drawContext() {
glColor3f(1.0f, 0, 0);
glBegin(GL_QUADS);
glVertex2f(0,190.0f);
glVertex2f(100.0f, 190.0f);
glVertex2f(100.0f,290.0f);
glVertex2f(0, 290.0f);
glEnd();
}

GLvoid initContext() {
contextCreated = true;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 640, 480, 0.0, 1.0, -1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(0, 0, 0, 1.0);
}

结果如下: cs overlay example它仍然非常简单,但我会尝试向其中添加更多细节、文本等。

谢谢。

最佳答案

如果游戏使用的是 OpenGL,那么原则上挂接到 SwapBuffers 是可行的方法。理论上,可能有几个不同的可绘制对象,您可能必须在交换缓冲区函数中决定哪些是正确的修改对象。

不过,这种 OpenGL 拦截有几个问题:

  1. OpenGL 是一个状态机。应用程序可能已经修改了现有的任何 GL 状态变量。您提供的代码远未完成,无法保证绘制某些内容。例如,如果应用程序碰巧启用了着色器,则所有矩阵设置可能都没有效果,屏幕上真正显示的内容取决于着色器。如果开启了深度测试,您的片段可能位于已绘制的内容后面。如果启用了多边形剔除,则您的图元可能会针对当前剔除模式错误缠绕。如果颜色 mask 设置为 GL_FALSE 或绘图缓冲区未设置为您期望的位置,则不会显示任何内容。

    另请注意,您“重置”矩阵的尝试也是错误的。您似乎假设当前矩阵模式是 GL_MODELVIEW。但这不一定是这种情况。它也可以是 GL_PROJECTIONGL_TEXTURE。您还可以将 glOrtho 应用于当前投影矩阵,而无需先加载恒等式,因此仅此一项就是屏幕上不显示任何内容的充分理由。

  2. 由于 OpenGL 是一个状态机,您还必须恢复您所触及的所有状态。您已经使用矩阵堆栈压入/弹出尝试过此操作。但是,例如,您未能恢复精确的矩阵模式。正如您在 1 中看到的,将需要更多的状态更改,因此恢复它会更复杂。由于您使用旧版 OpenGL,glPushAttrib()在这里可能会派上用场。

  3. SwapBuffers 不是 GL 函数,而是操作系统的 API 之一。它获取一个可绘制对象作为参数,并且仅间接引用任何 GL 上下文。 它可能会在另一个 GL 上下文绑定(bind)到线程时被调用,或者根本没有。如果你想安全地玩它,你还必须拦截 GL 上下文创建函数以及设为电流。在最坏的(尽管不太可能)情况下,应用程序在调用 SwapBuffers 时将 GL 上下文绑定(bind)到另一个线程,因此您无需更改 Hook 函数即可获取上下文.

将这些放在一起打开了另一种选择:您可以创建自己的 GL 上下文,在 Hook 的 SwapBuffers 调用期间临时绑定(bind)它,然后再次恢复原始绑定(bind)。这样,您根本不会干扰应用程序的 GL 状态。您仍然可以增加应用程序呈现的图像内容,因为帧缓冲区是可绘制对象的一部分,而不是 GL 上下文。这样做可能会对性能产生负面影响,但影响可能很小,您甚至都不会注意到。

由于您只想对单个特定应用程序执行此操作,另一种方法是通过观察应用程序在 SwapBuffers 调用期间实际设置的 GL 状态来找出所需的最小状态更改。类似 apitrace 的工具可以帮助您。

关于c++ - dll 注入(inject) : drawing simple game overlay with opengl,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34406076/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com