6

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

替代文字 替代文字

4

4 回答 4

6

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

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

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

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

简单的解决方案是:

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

    IPHONE_OPTIMIZE_OPTIONS | -skip-PNGs

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

于 2010-10-26T11:56:49.557 回答
3

您的屏幕截图和 Photoshop 模型表明图像的颜色通道正在与 Alpha 通道进行预乘。

于 2010-10-25T08:05:59.787 回答
2

我知道这篇文章很古老,但是我遇到了同样的问题,在尝试了一些解决方案并苦恼了几天后,我发现您可以通过使用以下混合参数来解决预乘 RGBA png 问题;

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

在我的情况下,GL_ONE参数替换了参数。GL_SRC_ALPHA

我现在可以使用没有灰色 alpha 边缘效果的 RGBA PNG,这让我的字形文本看起来很讨厌。

编辑:好的,还有一件事,对于淡入淡出等(在代码中设置 alpha 通道),当混合设置如上所述时,您需要手动预乘,就像这样;

glColor4f(r*a, g*a, b*a, a);
于 2013-09-11T18:22:09.793 回答
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;
}
于 2010-10-25T06:10:39.880 回答