当我尝试使用OpenGL绘制具有透明度的PNG图像时,我周围会出现一个奇怪的黑色边框:
但原始图像干净且正常:
我的代码:
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);
答案 0 :(得分: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;
}
我在这里解释了很多代码,希望它仍然有用。
答案 1 :(得分:1)
假设您的TexEnv是默认GL_MODULEATE
,请在绘制之前尝试glColor4ub(255, 255, 255, 255)
。
答案 2 :(得分:1)
问题在于您的图像具有预乘alpha,其中每个像素的颜色乘以其alpha值。 iPhone上的UIKit更喜欢预乘的alpha图像 - 混合它们的速度更快 - 但是OpenGL并没有假设,所以你的alpha通道的透明效果有点被应用两次,这导致你的图像中的半透明像素显得比他们实际上是。尝试关闭项目构建设置中的“压缩PNG文件”选项。
答案 3 :(得分: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);