OpenGL 包装器中的 Alpha/纹理问题

发布于 2024-08-21 05:26:42 字数 3194 浏览 6 评论 0 原文

我正在为一些 OpenGL 函数编写包装器。目标是包装游戏《无冬之夜》使用的上下文,以便应用后处理着色器效果。在学习了 OpenGL(这是我第一次尝试使用它)并大量使用 DLL 和重定向之后,我有了一个可以正常工作的系统。

但是,当后处理全屏四边形处于活动状态时,游戏绘制的所有纹理和透明度都会丢失。这应该是不可能的,因为我所有的功能都是在游戏完全完成自己的渲染之后才生效的。

该代码不使用渲染缓冲区或帧缓冲区(两者都拒绝以任何方式在我的系统上编译,无论是否使用 GLEW 或 GLee,尽管其他程序都支持和使用)。最终,我将这段代码放在一起来处理从缓冲区复制纹理并渲染全屏四边形:

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);
}

这段代码的功能几乎完美,并且没有明显的减慢。然而,当它处于活动状态时(我添加了帧计数条件以每约 5 秒打开和关闭它),所有 alpha 和纹理都会被游戏渲染器完全忽略。我不会在此函数之前关闭任何类型的混合或纹理(唯一的 OpenGL 调用是创建 nwshader->thisframe 纹理)。 我能够捕捉到正在发生的事情的一些屏幕截图:

Broken A: http:// /i4.photobucket.com/albums/y145/peachykeen000/outside_brokenA.png
破碎的 B: http://i4.photobucket.com/albums/y145/peachykeen000 /outside_brokenB.png
(注意,在 B 中,后面的烟雾没有被破坏,它是正确透明的。HUD 也是如此。)
破碎的内部:http://i4.photobucket.com/albums/y145/peachykeen000 /transparency_broken.png
正确的内饰(用于比较):http://i4.photobucket.com/albums /y145/peachykeen000/transparency_proper.png

四边形的绘制也破坏了菜单,将整个东西变成带有单个白色框的黑色表面。我怀疑这是深度或游戏如何绘制某些对象的问题,或者是未正确重置的状态。我已经使用 GLintercept 转储帧中所有调用的完整日志,并且没有发现任何错误(对 wglSwapLayerBuffers 的调用始终是最后的)。

作为使用 OpenGL 的新手,我真的不知道出了什么问题(或如何修复它),并且我尝试过的任何方法都没有帮助。我缺少什么?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

爱情眠于流年 2024-08-28 05:26:42

我不太明白你的代码应该如何与无冬之夜代码集成。但是......

看起来您很可能更改了现有代码不希望更改的某些设置。

根据问题的描述,我尝试删除以下行:

glDisable(GL_TEXTURE_2D);

该行禁用纹理,这听起来确实像您所看到的问题。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文