3

我有一个纹理加载到内存中,它是具有各种 alpha 值的 RGBA 格式。

图像加载如下:

 GLuint texture = 0;
 glGenTextures(1, &texture);
 glBindTexture(GL_TEXTURE_2D, texture);
 self.texNum = texture;

 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR); 
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR); 

 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self.imageWidth, self.imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, [self.imageData bytes]);

我想知道如何绘制此纹理,以便将图像中的 alpha 通道视为全 1,并且将纹理绘制为 RGB 图像。

考虑基本图像:

http://www.ldeo.columbia.edu/~jcoplan/alpha/base.png

此图像是从 0 到 255 alpha 的渐变,并且整个 RGB 值为 255,0,0

但是,如果我在禁用混合的情况下绘制它,我会得到一个看起来像这样的图像:www.ldeo.columbia.edu/~jcoplan/alpha/no_alpha.png

当我真正想要的是一个看起来像这样的图像时:www.ldeo.columbia.edu/~jcoplan/alpha/correct.png

我真的很感激一些建议让它完全忽略 alpha 通道。请注意,我最初不能将图像作为 RGB 加载,因为我在其他点确实需要 alpha 通道。

编辑:我尝试使用 GL_COMBINE 来解决我的问题:

glColorf(1,1,1,1);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);

glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);

glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); 
[self drawTexture];

但仍然没有运气,它仍然将黑色绘制为红色。

4

4 回答 4

3

我有一个纹理加载到内存中,它是具有各种 alpha 值的 RGBA 格式

glDisable(GL_BLEND)

但是,如果我在禁用混合的情况下绘制它,我会得到一个看起来像这样的图像:www.ldeo.columbia.edu/~jcoplan/alpha/no_alpha.png

发生这种情况是因为在您的源图像中所有透明像素都是黑色的。这是您的纹理/图像的问题,或者可能是加载器功能的问题,但这不是 OpenGL 问题。

您可能可以尝试使用 glTexEnv(GL_COMBINE...) 修复它(即将纹理颜色与基于 alpha 通道的基础颜色混合),但由于我没有做过类似的事情,我不完全确定,并且可以t 给你精确的操作数。在 Direct3D9 中是可能的(使用 D3DTOP_MODULATEALPHA_ADDCOLOR),所以很可能在 opengl 中有一种方法可以做到这一点。

于 2010-07-08T16:49:37.527 回答
1

您不应该禁用混合,而是使用带有适当参数的glBlendFunc :

glBlendFunc(GL_ONE, GL_ZERO);
于 2010-07-08T16:36:51.863 回答
0

我遇到了类似的问题,发现这是因为 iOS 图像加载对 RBG 值进行了预乘(如此处的其他一些答案和评论中所述)。我很想知道是否有禁用预乘的方法,但与此同时,我正在使用从这个线程这个线程派生的代码“取消预乘” 。

    // un pre-multiply
    uint8_t *imageBytes = (uint8_t *)imageData ;
    int byteCount = width*height*4 ;
    for (int i=0; i < byteCount; i+= 4) {
        uint8_t a = imageBytes[i+3] ;
        if (a!=255 && a!=0 ){
            float alphaFactor = 255.0/a ;
            imageBytes[i] *= alphaFactor ; 
            imageBytes[i+1] *= alphaFactor ; 
            imageBytes[i+2] *= alphaFactor ; 
        }
    }
于 2011-12-22T22:55:10.773 回答
0

或者你可以告诉 OpenGL 只上传图像的 RGB 通道,使用

glPixelStorei(GL_UNPACK_ALIGNMENT, 4)

在您调用glTexImage2D格式设置为GL_RGB. 它将导致它跳过每个像素的第四个字节,即 alpha 通道。

于 2010-07-09T00:12:31.600 回答