OpenGL alpha值会使纹理变白吗?

5
我正在尝试加载一个具有RGBA值的纹理,但是alpha值似乎只会使纹理更白,而不是调整透明度。我听说过这个问题在3D场景中很常见,但我只是用OpenGL进行2D渲染。有没有办法可以解决这个问题?
我使用以下代码初始化OpenGL:
glViewport(0, 0, winWidth, winHeight);
glDisable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST);
glClearColor(0, 0, 0, 0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, winWidth, 0, winHeight); // set origin to bottom left corner
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor3f(1, 1, 1);

截屏: 那张洗淡的小点图像应该是半透明的。黑色部分应该完全透明。如你所见,它后面有一张图像没有显示出来。

生成该纹理的代码相当冗长,因此我将描述我做了什么。它是一个40*30*4的unsigned char类型数组。每第四个字符设置为128(应该是50%透明度,对吧?)。

然后我将其传递到这个函数中,将数据加载到纹理中:

void Texture::Load(unsigned char* data, GLenum format) {
    glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, _texID);
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _w, _h, format, GL_UNSIGNED_BYTE, data);
    glDisable(GL_TEXTURE_2D);
}

我想我已经找到问题所在了。使用以下代码初始化全尺寸纹理:

glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, _texID);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glDisable(GL_TEXTURE_2D);

但是我猜glTexImage2D也需要是GL_RGBA格式?我不能使用两种不同的内部格式吗?或者至少不能使用大小不同的内部格式(3字节vs 4字节)?即使像这样初始化,GL_BGR也能正常工作...


+1 对于包含屏幕截图的OpenGL问题,应该是必须的。 :) - unwind
是的,现在回答起来变得容易多了。(顺便说一下,我已经编辑了我的帖子。) - aib
3个回答

5
为了帮助他人,我在此发布我的解决方案。
问题是,尽管我的Load函数是正确的,
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _w, _h, GL_RGBA, GL_UNSIGNED_BYTE, data);

我正在将GL_RGB传递给这个函数。
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);

需要指定正确的字节数(四个字节),这也适用于SubImage,虽然我认为如果格式具有相同数量的字节,则可以使用不同的格式(即混合使用GL_RGBGL_BGA是可以的,但不包括GL_RGBGL_RGBA)。


1

你的场景中是否有重叠的基元?

你知道你正在调用带有3个参数的glColor版本,它将alpha设置为1.0,对吧?

如果你能够发布一个屏幕截图或者描述一下当你绘制两个颜色相同但alpha值不同的基元时会发生什么,那将非常有帮助。实际上,任何能够演示问题的代码都可以帮助。

编辑:

我想象使用GL_RGB(作为internalformat的第三个参数)的TexImage将创建一个没有alpha通道或隐式初始化为1的3分量纹理,无论你提供什么样的像素数据。

GL_BGR不是这个参数的有效值,也许它会欺骗你的实现使用完整的4字节内部格式?(或2字节,如GL_LUMINANCE_ALPHA)或者你是指将GL_BGR传递给Texture::Load()函数,这与传递GL_RGB没有什么区别吧?


如果欺骗它使用4字节的内部格式,就不会有问题了。我认为GL_RGB最初的问题仅在于将其作为3字节的内部格式,而实际上我需要4字节。我的意思是,在我的加载函数中,GL_BGR可以工作,即使我在glTexImage2D中使用GL_RGB也是如此。我认为只有当传递正确数量的字节给glTexImage2D时才真正重要。如果我只传递“4”,那么可能会更少歧义。 - mpen

0

我认为这应该可以工作,但它假定图像具有 alpha 通道。如果您尝试加载没有 alpha 通道的图像,则会引发异常或应用程序可能会崩溃。对于非 alpha 通道图像,请在第二个参数上使用 GL_RGB 而不是 GL_RGBA,然后设置 GL_UNSIGNED_BYTE

void Texture::Load(unsigned char* data) {
  glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, _texID);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  glDisable(GL_TEXTURE_2D);
}

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