2011-08-31 122 views
1

绘制当我试图绘制PNG图片的透明度,使用OpenGL,我得到一个奇怪的黑色边框周围:黑色边框,用OpenGL

Two images with borders

但原始图像干净,正常:

Normal icons

我的代码:

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

UIImage* allIcons = [[appDelegate load_image_from_zip: pl.icons[ico_index]] retain]; 

       CGRect rect = CGRectMake(0, 0, allIcons.size.width/nIcons, allIcons.size.height); 
       UIGraphicsBeginImageContext(rect.size); 

       CGContextRef currentContext = UIGraphicsGetCurrentContext(); 

       CGContextTranslateCTM (currentContext, 0, allIcons.size.height); 
       CGContextScaleCTM (currentContext, 1, -1); 

       CGRect clippedRect = CGRectMake(0, 0, rect.size.width, rect.size.height); 
       CGContextClipToRect(currentContext, clippedRect); 
       CGRect drawRect = CGRectMake(rect.origin.x * -1, rect.origin.y * -1, allIcons.size.width, allIcons.size.height); 
       CGContextDrawImage(currentContext, drawRect, allIcons.CGImage); 

回答

1

假设您的TexEnv是默认GL_MODULEATE在绘制之前尝试glColor4ub(255, 255, 255, 255)

1

问题是,您的图像预乘alpha,其中每个像素的颜色已乘以其alpha值。 iPhone上的UIKit更喜欢预乘Alpha图像 - 将它们混合的速度更快 - 但OpenGL并不认为,所以Alpha通道的透明度效果会导致两次应用,这会导致图像中半透明像素显得比黑暗他们实际上是。尝试关闭项目构建设置中的“压缩PNG文件”选项。

0

尝试这些

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

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

这是可怕的预乘alpha的问题。在找出答案之前,我为此奋斗了好一个星期。告诉你的项目不压缩.png文件并不能解决问题,因为各种API调用将重新乘以alpha。这是我解决它的方式。

当设置混合模式和颜色:

blendFuncSource = premultAlpha ? GL_ONE : GL_SRC_ALPHA; 
blendFuncDestination = GL_ONE_MINUS_SRC_ALPHA; 

if (premultAlpha) 
{ 
    glColor4f(colorfilter.red*colorfilter.alpha, colorfilter.green*colorfilter.alpha, colorfilter.blue*colorfilter.alpha, colorfilter.alpha); 
} 
else 
{ 
    glColor4f(colorfilter.red, colorfilter.green, colorfilter.blue, colorfilter.alpha); 
} 

你需要弄清楚你的图像使用预乘alpha。你可以做到这一点我检查PNG头在加载时:

CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(image); 

...

switch(bitmapInfo & kCGBitmapAlphaInfoMask) 
{ 
case kCGImageAlphaPremultipliedFirst: 
    premultAlpha = YES; 
    srcFormat = GL_BGRA; 
    break; 

case kCGImageAlphaFirst: 
    srcFormat = GL_BGRA; 
    break; 

case kCGImageAlphaNoneSkipFirst: 
    srcFormat = GL_BGRA; 
    break; 

default: 
    srcFormat = GL_RGBA; 
} 

我在这里复述了大量的代码,希望它仍然是有帮助的。