Я "взламывал" одну из своих любимых игр с того момента, когда был моложе, и мне удалось перехватить вызовы OpenGL и ввести код С++ с помощью обертки opengl32.dll. Я смог придумать для этого несколько интересных применений, но моя текущая цель - внедрить пост-обработчики glsl-шейдеров в эту старую игру, чтобы она выглядела немного более современной. Игра была первоначально выпущена в конце 90-х, поэтому ее использование OpenGL и его кода рендеринга ограничено/примитивно/устарело.
Мне удалось успешно создать шейдеры вершин и фрагментов, введя код для инициализации и использования glsl-шейдерных программ, но моя проблема заключается в создании фреймбуфера/рендеринга моей сцены на текстуру для отправки в мой шейдер фрагмента в качестве сэмплера. Насколько я могу судить, текстура, которую я производим, обычно черная.
Трудно найти ресурсы, которые имеют отношение к тому, что я делаю, и изучить необработанные вызовы opengl (я пытался определить, куда вставлять код, читая трассировку opengl одного кадра игрового процесса), поэтому я раю я не мог окутать голову в то, что я делаю неправильно.
Я попытался поместить код во многих местах, но в настоящее время я привязываю фреймбуфер после того, как игра вызывает wglSwapBuffers()
, и я отключаю его непосредственно перед следующим вызовом glFlush()
, но я ' m не уверен, что множественная настройка видовых экранов, или операции с матрицами, или что-то еще, созданное между этими временами, каким-то образом возится с фреймбуфером.
Это код для инициализации фреймбуфера:
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);
}
Это код, который вызывается после wglSwapBuffers
:
GLenum fboBuff[] = { GL_COLOR_ATTACHMENT0 };
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glDrawBuffers(1, fboBuff);
glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT);
Это код, который вызывается до glFlush()
:
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glPopAttrib(); // Restore our glEnable and glViewport states
... Draw an Overlay containing with fbo texture binded ...
Здесь - трассировка gl одного кадра.
Это почти 800 строк, но обученный глаз opengl должен уметь видеть, какие вызовы возникают, когда. Я удалил несколько сотен строк вызовов, которые я, по крайней мере, понимаю.