dll注入:使用opengl绘制简单的游戏覆盖图
dll injection: drawing simple game overlay with opengl
我正试图在一个3d桌面游戏中绘制一个自定义的opengl覆盖(例如steam)。这个覆盖基本上应该能够显示用户可以通过按下某些键进行影响。把它想象成一个游戏教练。目标首先是在屏幕上的特定点绘制一些图元。稍后,我想在游戏窗口中有一个好看的"gui"组件。游戏使用GDI32.dll中的"SwapBuffers"方法。目前,我可以在游戏中注入一个自定义DLL文件,并挂接"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切换代码)
- 我想知道在挂钩函数中设计和显示自定义覆盖的最佳方法是什么。(我应该使用类似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覆盖示例它仍然很简单,但我会尝试添加一些更多的细节,文本等。
谢谢。
如果游戏使用OpenGL,那么原则上挂接SwapBuffers
是可行的。理论上,可能有几种不同的可提取项,您可能必须在交换缓冲区函数中决定修改哪一个是正确的。
不过,这种OpenGL拦截有几个问题:
-
OpenGL是一个状态机。应用程序可能已经修改了任何GL状态变量。您提供的代码还远远不能保证某些东西是绘制的。例如,如果应用程序恰好启用了着色器,则所有矩阵设置可能都没有效果,屏幕上实际显示的内容取决于着色器。如果进行深度测试,您的碎片可能位于已经绘制的碎片后面。如果多边形剔除处于启用状态,则基本体可能会错误地缠绕到当前剔除模式。如果颜色遮罩设置为
GL_FALSE
,或者绘制缓冲区未设置为预期位置,则不会显示任何内容。还要注意,您试图"重置"矩阵也是错误的。您似乎认为当前的矩阵模式是
GL_MODELVIEW
。但事实并非如此。它也可以是GL_PROJECTION
或GL_TEXTURE
。您还可以将glOrtho
应用于当前投影矩阵,而无需首先加载标识,因此仅此一点就是屏幕上不显示任何内容的充分理由。 -
由于OpenGL是一个状态机,您还必须恢复您所接触的所有状态。您已经在矩阵堆栈推送/弹出中尝试过了。但例如,您未能恢复精确的矩阵模式。正如您在1中看到的,将需要更多的状态更改,因此恢复它将更加复杂。由于您使用的是传统的OpenGL,
glPushAttrib()
可能会在这里派上用场。 -
SwapBuffers
不是GL函数,而是操作系统的API之一。它获得一个drawable作为参数,并且只间接引用任何GL上下文它可能在另一个GL上下文绑定到线程时被调用,或者根本没有如果你想安全起见,你还必须拦截GL上下文创建函数以及MakeCurrent
。在最坏的情况下(尽管可能性很小),应用程序在调用SwapBuffers
时将GL上下文绑定到另一个线程,因此在挂钩函数中访问上下文不会有任何更改。
将这些放在一起打开了另一种选择:您可以创建自己的GL上下文,在挂接的SwapBuffers
调用期间临时绑定它,然后再次恢复原始绑定。这样,您就根本不会干扰应用程序的GL状态。您仍然可以增加应用程序渲染的图像内容,因为帧缓冲区是可绘制内容的一部分,而不是GL上下文。这样做可能会对性能产生负面影响,但它可能太小,以至于你永远不会注意到
由于您只想对单个特定应用程序执行此操作,因此另一种方法是通过观察应用程序在SwapBuffers调用期间实际设置的GL状态来找出必要的最小状态更改。像apitrace这样的工具可以帮助你做到这一点。
- 我应该在简单的策略游戏中为各个派系使用类吗 - C++
- 简单的游戏数据库问题
- X 变量在最后一次尝试简单猜谜游戏时发生变化,C++
- 简单的比赛游戏与 C++ 中的动态数组
- 简单的游戏,同时循环和检查字符串
- 生活的游戏邻居检查(更简单的方法可能吗?)
- 如何简单地管理我的游戏状态?C++
- 循环麻烦.C 简单游戏
- 简单的单词猜测游戏
- 我简单的 c++ 文本游戏不起作用。我正在使用随机数生成,我很困惑
- OpenGL - 简单3D游戏的低FPS
- 简单的战舰游戏建议
- 我需要哪种语言/课程来制作简单的纸牌游戏
- 如何创建一个简单的侧滚动游戏
- 为什么c++游戏与unity3d相比如此简单
- 变量的值在使用C++的简单文本 RPG 游戏中不会更改
- 我的简单游戏的计时器非常关闭...C++
- 组织X11和Win32简单游戏代码的最佳方式是什么
- 如何得到每个子弹的起点?Libgdx简单游戏
- 一个用c++编写的简单游戏循环程序