我正在为Opengl ES中的iPhone编写游戏,我遇到了alpha混合的问题:
我正在使用glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA)
来实现Alpha混合并尝试使用多个“图层”构建场景,这样我就可以单独移动它们而不是静态图像。我在photoshop中创建了一个预览版,然后尝试在iphone中获得相同的效果,但是当我将纹理与半透明区域混合时会显示黑色光环。
我附上了一张图片。左边是iphone的屏幕截图,右边是我在photoshop中制作作品时的样子。图像由渐变和带有羽化边缘的沙子图像组成。
这是预期的行为吗?有什么办法可以避开黑暗的边界吗?
感谢。
编辑:我正在上传包含沙子的png部分。完整的png是512x512,还有其他图像。
我正在使用以下代码加载图像:
NSString *path = [NSString stringWithUTF8String:filePath];
NSData *texData = [[NSData alloc] initWithContentsOfFile:path];
UIImage *image = [[UIImage alloc] initWithData:texData];
if (image == nil) NSLog(@"ERROR LOADING TEXTURE IMAGE");
GLuint width = CGImageGetWidth(image.CGImage);
GLuint height = CGImageGetHeight(image.CGImage);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
void *imageData = malloc( height * width * 4 );
CGContextRef context = CGBitmapContextCreate( imageData, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big );
CGColorSpaceRelease( colorSpace );
CGContextClearRect( context, CGRectMake( 0, 0, width, height ) );
CGContextTranslateCTM( context, 0, height - height );
CGContextDrawImage( context, CGRectMake( 0, 0, width, height ), image.CGImage );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
CGContextRelease(context);
free(imageData);
[image release];
[texData release];
答案 0 :(得分:6)
我需要回答我自己的问题:
我无法使用ImageIO框架使其工作,因此我将libpng源添加到我的项目中并使用它加载图像。它现在完美无缺,但是我要解决以下问题:
图像已加载并在模拟器中显示正常但在真实设备上根本没有加载。我在网上发现,PNG图像格式文件中的像素排序从RGBA转换为BGRA,颜色值也通过压缩实用程序'pngcrush'预先乘以alpha通道值。 (出于设备特定的效率原因,使用UIKit接口进行编程时)。
该实用程序还重命名文件的标题,使新的PNG文件无法通过libpng使用。将PNG文件部署到iPhone上时,这些更改会自动完成。虽然这对UIKit来说很好,但libpng(和其他非Apple库)通常无法读取文件。
简单的解决方案是:
适用于您的iPhone -device- build添加以下用户定义的设置:
IPHONE_OPTIMIZE_OPTIONS | -skip-PNGs
我做了第二次,它现在在模拟器和设备上运行完美。
答案 1 :(得分:3)
你的截图和photoshop样机表明图像的颜色通道正在与alpha通道进行预乘。
答案 2 :(得分:2)
我不知道您的原始源图像是什么样的,但对我而言,它看起来是正确混合的。使用混合模式,您将在各层之间获得闷热的混合。
photoshop版本看起来你对每一层都有适当的透明度,但不是混合。我想如果你不想明确地设置像素alpha,你可以用glAlphaFunc来体验。
---与下面的评论相关的代码(删除alpha预乘)---
int pixelcount = width * height;
unsigned char* off = pixeldata;
for (int pi=0; pi<pixelcount; ++pi)
{
unsigned char alpha = off[3];
if( alpha!=255 && alpha!=0 )
{
off[0] = ((int)off[0])*255/alpha;
off[1] = ((int)off[1])*255/alpha;
off[2] = ((int)off[2])*255/alpha;
}
off += 4;
}
答案 3 :(得分:2)
我知道这篇文章是古老的,但我遇到了同样的问题,在尝试了一些解决方案并痛苦了几天后,我发现你可以通过使用以下混合参数来解决预乘的RGBA png问题;
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
在我的情况下,GL_ONE
参数替换了GL_SRC_ALPHA
参数。
我现在可以使用我的RGBA PNG而没有灰色的alpha边缘效果,这使得我的字形文本看起来很讨厌。
编辑: 好的,还有一件事,对于褪色等(在代码中设置alpha通道),你需要在如上设置混合时手动预乘,就像这样;
glColor4f(r*a, g*a, b*a, a);