views:

175

answers:

1

I'm in the process of writing a wrapper for some OpenGL functions. The goal is to wrap the context used by the game Neverwinter Nights, in order to apply post-processing shader effects. After learning OpenGL (this is my first attempt to use it) and much playing with DLLs and redirection, I have a somewhat working system.

However, when the post-processing fullscreen quad is active, all texturing and transparency drawn by the game are lost. This shouldn't be possible, because all my functions take effect after the game has completely finished its own rendering.

The code does not use renderbuffers or framebuffers (both refused to compile on my system in any way, with or with GLEW or GLee, despite being supported and usable by other programs). Eventually, I put together this code to handle copying the texture from the buffer and rendering a fullscreen quad:

extern "C" SEND BOOL WINAPI hook_wglSwapLayerBuffers(HDC h, UINT v)
{   
if ( frameCount > 250 )
{
    frameCount++;
    if ( frameCount == 750 ) frameCount = 0;

    if ( nwshader->thisframe == NULL )
    {
        createTextures();
    }

    glBindTexture(GL_TEXTURE_2D, nwshader->thisframe);
    glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, nwshader->width, nwshader->height, 0);

    glClearColor(0.0f, 0.5f, 0.0f, 0.5f);
    glClear(GL_COLOR_BUFFER_BIT);


    glEnable(GL_TEXTURE_2D);    
    glDisable(GL_DEPTH_TEST);   
    glBlendFunc(GL_ONE, GL_ZERO);
    glEnable(GL_BLEND);

    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    glOrtho( 0, nwshader->width , nwshader->height , 0, -1, 1 );
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();   


    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
    glBegin(GL_POLYGON);
        glTexCoord2f(0.0f, 1.0f);
        glVertex2d(0, 0);
        glTexCoord2f(0.0f, 0.0f);
        glVertex2d(0, nwshader->height);
        glTexCoord2f(1.0f, 0.0f);
        glVertex2d(nwshader->width, nwshader->height);
        glTexCoord2f(1.0f, 1.0f);
        glVertex2d(nwshader->width, 0);
    glEnd();


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

    glEnable(GL_DEPTH_TEST);
    glDisable(GL_TEXTURE_2D);

    glBindTexture(GL_TEXTURE_2D, 0);    
} else {
    frameCount++;
}

if ( h == grabbedDevice )
{
    Log->logline("Swapping buffer on cached device.");

}
return wglSwapLayerBuffers(h,v);
}

This code functions almost functions perfectly and has no notable slow-down. However, when it is active (I added the frameCount condition to turn it on and off every ~5 seconds), all alpha and texturing are completely ignored by the game renderer. I'm not turning off any kind of blending or texturing before this function (the only OpenGL calls are to create the nwshader->thisframe texture). I was able to catch a few screenshots of what's happening:

Broken A: http://i4.photobucket.com/albums/y145/peachykeen000/outside_brokenA.png
Broken B: http://i4.photobucket.com/albums/y145/peachykeen000/outside_brokenB.png
(note, in B, the smoke in the back is not broken, it is correctly transparent. So is the HUD.)
Broken Interior: http://i4.photobucket.com/albums/y145/peachykeen000/transparency_broken.png
Correct Interior (for comparison): http://i4.photobucket.com/albums/y145/peachykeen000/transparency_proper.png

The drawing of the quad also breaks menus, turning the whole thing into a black surface with a single white box. I suspect it is a problem with either depth or how the game is drawing certain objects, or a state that is not being reset properly. I've used GLintercept to dump a full log of all calls in a frame, and didn't see anything wrong (the call to wglSwapLayerBuffers is always last).

Being brand new to working with OpenGL, I really have no clue what's going wrong (or how to fix it) and nothing I've tried has helped. What am I missing?

+2  A: 

I don't quite understand how your code is supposed to integrate with the Neverwinter Nights code. However...

It seems like you're most likely changing some setting that the existing code didn't expect to change.

Based on the description of the problem, I'd try removing the following line:

glDisable(GL_TEXTURE_2D);

That line disables textures, which certainly sounds like the problem you're seeing.

Jon-Eric
My code doesn't integrate, per say. I've written a DLL using<br> #pragma comment(linker, "/export:wglSwapLayerBuffes=nwshader.hook_wglSwapLayerBuffers")<br>to send some function calls from the standard OpenGL DLL (renamed to hookgl32.DLL) into my own DLL (nwshader.dll). Neverwinter Nights calls the OpenGL DLL, which has been replaced with my redirection DLL. The functions I need to wrap are then handled in my code.I'll try removing that call. One of the samples I was looking at, which did a similar thing, used glEnable and Disable on GL_TEXTURE_2D on either side of rendering their quad.
peachykeen
Not sure how I missed it (too long staring at the same code, I guess), but that worked perfectly, thanks! :D
peachykeen