Zai*_*yed 12 opengl framebuffer code-injection
从我年轻的时候起,我一直在"黑客攻击"我最喜欢的游戏之一,并且我已经设法能够拦截OpenGL调用并使用opengl32.dll包装器注入C++代码.我已经能够为此提出一些很酷的用途,但我目前的目标是在这款旧游戏中实现后处理glsl着色器,使其看起来更现代.该游戏最初是在90年代后期发布的,因此它对OpenGL及其渲染代码的使用是有限/原始/过时的.
我已经能够通过注入代码来初始化和使用glsl着色器程序来成功生成顶点和片段着色器,但我的问题在于生成一个帧缓冲区/将我的场景渲染到纹理以作为采样器发送到我的片段着色器.据我所知,我生产的纹理通常都是黑色的.
很难找到与我正在做的事情相关的资源并检查原始的opengl调用(我一直在尝试通过读取单帧游戏玩法的opengl跟踪来确定插入代码的位置),所以我没有去过能够绕过我做错的事情.
我已经尝试将代码放在很多地方,但是目前,我在游戏调用后绑定了framebuffer,wglSwapBuffers()并且在下一个glFlush()调用之前我立即解除绑定,但是我不确定是否有多个视口设置,或矩阵运算,或在这些时间之间创建的任何其他东西都会以某种方式搞乱帧缓冲.
这是初始化帧缓冲区的代码:
void initFB()
{
/* Texture */
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &fbo_texture);
glBindTexture(GL_TEXTURE_2D, fbo_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1920, 1080, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, 0);
/* Depth buffer */
glGenRenderbuffers(1, &fbo_depth);
glBindRenderbuffer(GL_RENDERBUFFER, fbo_depth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 1920, 1080);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo_depth);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
/* Framebuffer to link everything together */
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo_texture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo_depth);
GLenum status;
if ((status = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE) {
fprintf(stderr, "glCheckFramebufferStatus: error %p", status);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
Run Code Online (Sandbox Code Playgroud)
这是后面的代码wglSwapBuffers:
GLenum fboBuff[] = { GL_COLOR_ATTACHMENT0 };
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glDrawBuffers(1, fboBuff);
glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT);
Run Code Online (Sandbox Code Playgroud)
这是之前调用的代码glFlush():
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glPopAttrib(); // Restore our glEnable and glViewport states
... Draw an Overlay containing with fbo texture binded ...
Run Code Online (Sandbox Code Playgroud)
这是单帧的gl轨迹.
这是近800线,但训练有素的opengl眼睛应该能够看到什么时候进行的调用.我删除了数百行绘图调用,这是我至少理解的.
据我了解,您正在尝试更新旧游戏的图形部分,但您在原始代码中遇到了限制,导致您无法改造所需的部分。
虽然我没有相关的游戏编码经验,但当我尝试改造一个应用程序时,我会拆解该应用程序以研究其结构,并有选择地应用内存中的补丁来重定向某些功能和代码段我提供的替代品。
我会预加载一个共享库,该库将使用条件/无条件跳转/调用指令覆盖程序内存的某些部分,并有选择地执行 NOP,以便我的代码成为程序的组成部分。无论如何,它绝对不优雅,但它使我能够快速解决原始代码中的缺陷。