2010-07-08 125 views
3

我将纹理加载到具有各种Alpha值的RGBA格式的内存中。在OpenGL中绘制纹理,同时忽略Alpha通道

的图像加载为这样:

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的α,并且具有在整个255,0,0

的RGB值。然而,如果我与绘制它混合禁用我得到那个看起来像一个形象: 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]; 

但仍没有运气,它吸引黑变红仍。

+0

这两个解决方案建议看起来是正确的。查看调试器内存视图中[self.imageData bytes]返回的指针。你期望的价值是什么?你得到的结果表明他们不会是... – 2010-07-08 17:34:56

+1

你使用预乘alpha吗?如果是这样,那么淡入黑色就是纹理的RGB值。你的glBlendFunc是什么? – Alan 2010-07-08 17:38:47

+0

@Alan&brone 看完它们的字节后,这是正确的,图像正在通过XCode优化预倍增,并且字节内部并非我所期望的。 所以答案是我没有正确加载图像。 谢谢! – jcoplan 2010-07-08 18:04:19

回答

3

我已经加载到内存中的纹理是RGBA格式的各种alpha值

glDisable( GL_BLEND)

但是,如果我绘制它与禁用混合I GE牛逼,看起来像一个形象:www.ldeo.columbia.edu/~jcoplan/alpha/no_alpha.png

这是因为在你的源图像中的所有透明像素为黑色。这是你的纹理/图像的一个问题,或者可能与加载函数有关,但它不是OpenGL问题。

你也许可以尝试使用glTexEnv(GL_COMBINE ...)(即混合纹理颜色与基于Alpha通道的基础颜色),但由于我没有这样做过,我不完全确定,并且不能给你确切的操作数。这是可能的Direct3D9(使用D3DTOP_MODULATEALPHA_ADDCOLOR),所以很可能有办法在opengl中做到这一点。

+0

我不完全明白你的意思是我所有的透明像素是黑色的。 我试过一个GL_COMBINE,但没有运气,它仍然画黑到红色...... – jcoplan 2010-07-08 17:25:47

+0

@jcoplan:透明只是另一个通道。如果像素具有R255,G0,B0,A255,则它是不透明的红色。如果它有R255,G0,B0,A0,它是完全透明的红色。如果它有R0,G0,B0,A0,那么它是完全透明的黑色。在纹理颜色中,渐变是从transaprent BLACK(R0,G0,B0,A0)到非透明RED(R255G0B0A255)线性插值的渐变。这就是为什么你看到黑色部分。如果你想要另一个结果,你需要另一张图片。不过,我建议使用两个不同的图像。当渐变出现在A和RGB中时,在白色背景下可能看起来不太好。 – SigTerm 2010-07-08 17:51:19

+0

你是正确的,我没有正确加载图像。我正在遭受惊人的alpha前乘法。 – jcoplan 2010-07-08 18:04:58

1

你不应该禁用勾兑但适当的参数使用glBlendFunc

glBlendFunc(GL_ONE, GL_ZERO); 
+0

我想尝试,但图像仍然是这样看起来像这样: www.ldeo.columbia.edu/~jcoplan/alpha/no_alpha.png – jcoplan 2010-07-08 16:39:54

0

或者你可以告诉OpenGL使用

glPixelStorei(GL_UNPACK_ALIGNMENT, 4) 

你叫glTexImage2D设置为GL_RGB格式之前只上传图片的RGB通道。它会导致它跳过每个像素的第四个字节,即alpha通道。

+0

GL_UNPACK_ALIGNMENT影响*行*的对齐,而不是单个像素。见http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml – 2013-07-16 16:27:30

0

我有一个类似的问题,并发现这是因为iOS图像加载正在对RBG值进行预乘(如其他一些答案和评论中所述)。我很想知道是否有一种禁用前乘法的方法,但同时我使用从this threadthis thread派生的代码进行“不预乘”。

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