OpenGL透明纹理覆盖在其他纹理之上

7
我得到了2个png图片,这些图片被用作在Qt/C++ 2D OpenGL应用程序中的纹理。第一个用作某种“中间”地带,第二个用作渲染“在顶部”的“对象”(注意:它们目前都有相同的z值,在定义的顺序下呈现可以获得期望的行为)。“对象”纹理部分是半透明的,“中间地带”纹理大多是实心的。问题是,“对象”纹理的半透明部分显示出的是实心的背景色而不是“中间地带”的纹理。

有什么提示可以解决这个问题吗?

以下OpenGL标志用于我的纹理渲染:

glEnable (GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

感谢您的任何帮助。
编辑:
更多代码:
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);

glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.1f);

glEnable(GL_TEXTURE_2D);
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBindTexture(GL_TEXTURE_2D, c->_texture);

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

glBegin(GL_QUADS);
{
    glTexCoord2i(0,0);
    glVertex2i(-128,-128);

    glTexCoord2i(0,1);
    glVertex2i(-128,128);

    glTexCoord2i(1,1);
    glVertex2i(128,128);

    glTexCoord2i(1,0);
    glVertex2i(128,-128);

}
glEnd();

glDisable(GL_TEXTURE_2D);

glDisable(GL_ALPHA_TEST);
glDisable(GL_DEPTH_TEST);

编辑:我如何加载纹理,据我所知它会带有 alpha 通道。

QImage img("./images/dummycar.png","PNG");
QImage t(QGLWidget::convertToGLFormat(img));
glGenTextures(1, &_texture);
glBindTexture(GL_TEXTURE_2D, _texture);
glTexImage2D( GL_TEXTURE_2D, 0, 3, t.width(), t.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, t.bits() );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

截图:http://img824.imageshack.us/img824/1912/blackbox.png

Skyimage是“中间层”,背景为纯黑色。


带有解释的截图会更好。 - SigTerm
3个回答

7
glTexImage2D( GL_TEXTURE_2D, 0, 3, t.width(), t.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, t.bits() );

您在internalFormat中指定了3个通道,因此这是RGB而不是RGBA。请尝试在该位置使用GL_RGBA


2
我知道那是些愚蠢的事情。非常感谢,你救了我的一天 :) - drahnr

4
你尝试过调整 glAlphaFunc 吗?你可以使用它来根据 alpha 值丢弃对象纹理的半透明部分。
还有 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND) 或者 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE),你觉得呢?
希望这能帮到你。

那个方法没有起作用。我尝试了 glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.1f);,但是没有变化。GL_MODULATE 没有改变任何东西,GL_BLEND 改变了颜色,但是我的物体周围的“框”仍然存在。 - drahnr
1
这对我非常有帮助。使用BB,当我启用alpha测试并使用GL_GREATER时,它就像魔法一样运行良好。 - bobobobo

3
如果您为每个对象渲染一个纹理,则需要使用glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE)。
如果纹理仍然有“框”,即使在此之后,那么它是没有带有alpha通道的加载。
这对我完美地起作用:
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glBindTexture(GL_TEXTURE_2D, texture2->tex);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glColor4f(0.5f, 1.0f, 0.5f, 0.5f);
    glBegin(GL_TRIANGLE_FAN);
    glTexCoord2f(0, 0);
    glVertex2f(x, y);
    glTexCoord2f(1, 0);
    glVertex2f(x + texture2->width, y);
    glTexCoord2f(1, 1);
    glVertex2f(x + texture2->width, y+ texture2->height);
    glTexCoord2f(0, 1);
    glVertex2f(x, y + texture2->height);
    glEnd();
    glDisable(GL_BLEND);

半透明纹理,由上一颜色着色。

如果“纹理周围有一个框”不描述你的问题,请贴出屏幕截图。

--编辑--

根据你的屏幕截图更新数据。

你需要先渲染背景,然后再渲染汽车。 因为即使表面是透明的,它也会用值填充z缓冲区,所以你看到了背景颜色,而背景在汽车下面,变得不可见。

当你渲染半透明对象时,你需要遵循以下规则。

  1. 所有不透明的对象都应该在半透明对象之前渲染。始终如此。

  2. 所有透明对象应该按照从后到前的顺序渲染。最远的物体应该先渲染,最近的物体应该第二个渲染。

  3. 如果无法按照从后到前的顺序进行渲染(具有GL_ADD混合的未排序粒子),则应使用glDepthMask(GL_FALSE)禁用写入深度缓冲区。如果不这样做,你将得到丑陋的伪影(例如屏幕截图上的一个)。


这个显示底层纹理吗?到目前为止,它对我也起作用,但我的问题是,我想看到另一个纹理对象——我绘制的那个之外。但是现在我得到的是背景颜色(黑色)。截图:http://img824.imageshack.us/img824/1912/blackbox.png - drahnr
@soxs060389:我已经更新了我的回答。你应该先渲染地面,然后再渲染汽车。如果你反过来做,它是不会起作用的。 - SigTerm
我从零点开始就一直在做那件事情。汽车始终是最后一个要渲染的物品。 - drahnr
@soxs060389:“然后它是没有 alpha 通道加载的。” 当我回答时,纹理加载代码不在这里。 - SigTerm
我知道,但是我很感激你的帮助。我对OpenGL混合/纹理等方面还很陌生。 - drahnr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接