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

Posted

技术标签:

【中文标题】OpenGL 包装器中的 Alpha/纹理问题【英文标题】:Alpha/texturing issues in an OpenGL wrapper 【发布时间】:2010-02-10 23:20:31 【问题描述】:

我正在为一些 OpenGL 函数编写一个包装器。目标是包装游戏 Neverwinter Nights 使用的上下文,以便应用后处理着色器效果。在学习了 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);

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

破答: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 的新手,我真的不知道出了什么问题(或如何解决它),而且我尝试过的任何方法都没有帮助。我错过了什么?

【问题讨论】:

尝试缩小导致问题的代码行(通过一一删除)。我敢打赌它会是createTextures()glBindTextureglCopyTexImage2D(但这只是猜测)。 createTextures 是对我的一个函数的调用,如果它不存在,它会创建必要的纹理(用于在渲染四边形时对其进行纹理化)。据我所知,glBindTexture 用于告诉四边形使用该特定纹理进行纹理处理。我错了吗?而 glCopyTexImage2D 是将后台缓冲区复制到我的纹理中(我知道这是有效的,因为我得到了一个带有错误渲染帧的叠加层)。 【参考方案1】:

我不太明白您的代码应该如何与无冬之夜代码集成。不过……

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

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

glDisable(GL_TEXTURE_2D);

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

【讨论】:

说我的代码没有集成。我已经使用 #pragma comment(linker, "/export:wglSwapLayerBuffes=nwshader.hook_wglSwapLayerBuffers") 编写了一个 DLL,将标准 OpenGL DLL(重命名为 hookgl32.DLL)的一些函数调用发送到我自己的DLL (nwshader.dll)。无冬之夜调用 OpenGL DLL,它已被我的重定向 DLL 替换。然后在我的代码中处理我需要包装的函数。我会尝试删除该呼叫。我正在查看的其中一个示例做了类似的事情,在渲染四边形的任一侧的 GL_TEXTURE_2D 上使用了 glEnable 和 Disable。 不知道我是怎么错过的(我猜是盯着同一个代码太久了),但是效果很好,谢谢! :D

以上是关于OpenGL 包装器中的 Alpha/纹理问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 Alpha 渲染纹理的问题

体素中的 OpenGL 3D 透明度

OpenGL ES iOS 入门实例

OpenGL中的完全透明圆环

片段着色器中未使用纹理数据 - OpenGL

顶点纹理获取(在顶点着色器中读取纹理)