Ho "hacking" uno dei miei giochi preferiti da quando ero più giovane, e sono riuscito a essere in grado di intercettare chiamate OpenGL e iniettare codice C++ utilizzando un wrapper opengl32.dll. Sono stato in grado di trovare una serie di fantastici usi per questo, ma il mio obiettivo attuale è quello di implementare gli shaders glsl in questo vecchio gioco per renderlo un po 'più moderno. Il gioco è stato originariamente rilasciato alla fine degli anni '90, quindi il suo uso di OpenGL e del suo codice di rendering è limitato/primitivo/obsoleto.Iniezione di un frame buffer
Sono stato in grado di produrre vertex e frammenti di shader iniettando il codice per inizializzare e utilizzare i programmi glsl shader, ma il mio problema consiste nel produrre un framebuffer/renderizzare la mia scena su una texture da inviare al mio framment shader come campionatore . Per quanto ne so, la consistenza che produco è solitamente tutta nera.
È difficile trovare risorse che siano rilevanti per quello che sto facendo ed esaminare le chiamate open source (ho cercato di determinare dove inserire il codice leggendo una traccia opengl di un singolo frame di gameplay), quindi non sono stato in grado di avvolgere la mia mente su quello che sto facendo male.
Ho provato a mettere il codice in molti luoghi, ma al momento, sto vincolante il framebuffer dopo la partita chiama wglSwapBuffers()
e io sono non vincolante immediatamente prima della prossima glFlush()
chiamata viene effettuata, ma non sono sicuro se l'installazione di più finestre, operazioni con matrici o qualsiasi altra cosa creata tra questi tempi è in qualche modo un problema con il framebuffer.
Questo è il codice per inizializzare il framebuffer:
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);
}
Questo è il codice chiamato dopo wglSwapBuffers
:
GLenum fboBuff[] = { GL_COLOR_ATTACHMENT0 };
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glDrawBuffers(1, fboBuff);
glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT);
Questo è il codice chiamato prima glFlush()
:
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glPopAttrib(); // Restore our glEnable and glViewport states
... Draw an Overlay containing with fbo texture binded ...
Here è la traccia gl di un singolo fotogramma.
Sono quasi 800 linee, ma un occhio esperto dovrebbe essere in grado di vedere quali chiamate vengono fatte quando. Ho rimosso diverse centinaia di righe di chiamate di disegno che non capisco.
Forse provare ad aggiornare la texture tramite glReadPixels invece solo per vedere se il resto del codice è corretto? –