OpenGL ES(IPhone)alpha混合看起来很奇怪

时间:2010-10-25 05:06:41

标签: iphone opengl-es alphablending

我正在为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];

alt text alt text

4 个答案:

答案 0 :(得分:6)

我需要回答我自己的问题:

我无法使用ImageIO框架使其工作,因此我将libpng源添加到我的项目中并使用它加载图像。它现在完美无缺,但是我要解决以下问题:

图像已加载并在模拟器中显示正常但在真实设备上根本没有加载。我在网上发现,PNG图像格式文件中的像素排序从RGBA转换为BGRA,颜色值也通过压缩实用程序'pngcrush'预先乘以alpha通道值。 (出于设备特定的效率原因,使用UIKit接口进行编程时)。

该实用程序还重命名文件的标题,使新的PNG文件无法通过libpng使用。将PNG文件部署到iPhone上时,这些更改会自动完成。虽然这对UIKit来说很好,但libpng(和其他非Apple库)通常无法读取文件。

简单的解决方案是:

  1. 使用不同的扩展名重命名您的PNG文件。
  2. 适用于您的iPhone -device- build添加以下用户定义的设置:

    IPHONE_OPTIMIZE_OPTIONS | -skip-PNGs

  3. 我做了第二次,它现在在模拟器和设备上运行完美。

答案 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);