Альфа-смешивание OpenGL ES (iPhone) выглядит странно - PullRequest
6 голосов
/ 25 октября 2010

Я пишу игру для IPhone в Opengl ES, и у меня возникла проблема с альфа-смешиванием:

Я использую glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA) для достижения альфа-смешивания и пытаюсь создать сцену снесколько «слоев», поэтому я могу перемещать их отдельно вместо статичного изображения.Я создал предварительный просмотр в фотошопе, а затем попытался добиться того же результата в iphone, но при смешивании текстуры с полупрозрачными областями отображается черный ореол.

Я прикрепил изображение.Слева - скриншот с iphone, а справа - как он выглядит, когда я делаю композицию в фотошопе.Изображение состоит из градиента и изображения песка с заштрихованными краями.

Это ожидаемое поведение?Можно ли как-то избежать темных границ?

Спасибо.

РЕДАКТИРОВАТЬ : я загружаю часть 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 ]

6 голосов
/ 26 октября 2010

Мне нужно ответить на свой вопрос:

Я не мог заставить его работать с использованием каркаса ImageIO, поэтому я добавил libpng исходники в свой проект и загрузил изображение, используя его. Теперь он отлично работает, но я должен был решить следующую проблему:

Изображение загружалось и показывалось нормально в симуляторе, но не загружалось вообще на реальном устройстве. Я обнаружил в Интернете, что происходит то, что упорядочение пикселей в файлах формата PNG преобразуется из RGBA в BGRA, а значения цвета также предварительно умножаются на значение альфа-канала с помощью утилиты сжатия pngcrush (по соображениям эффективности для конкретного устройства при программировании с помощью интерфейса UIKit).

Утилита также переименовывает заголовок файла, делая новый файл PNG непригодным для использования libpng. Эти изменения выполняются автоматически при развертывании файлов PNG на iPhone. Хотя это нормально для UIKit, libpng (и другие библиотеки, не относящиеся к Apple), как правило, не могут затем читать файлы.

Простые решения:

  1. переименуйте файлы PNG с другим расширением.
  2. для вашего iPhone -device- build добавить следующий пользовательский параметр:

    IPHONE_OPTIMIZE_OPTIONS | -skip-PNGs

Я сделал второй, и теперь он отлично работает на симуляторе и устройстве.

3 голосов
/ 25 октября 2010

Ваш скриншот и макет Photoshop показывают, что цветовые каналы изображения предварительно умножаются на альфа-канал.

2 голосов
/ 11 сентября 2013

Я знаю, что этот пост является древним, однако у меня была идентичная проблема, и после попытки решения некоторых проблем и мучений в течение нескольких дней я обнаружил, что вы можете решить предварительно умноженную проблему png RGBA, используя следующие параметры смешивания:

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

Параметр GL_ONE заменил параметр GL_SRC_ALPHA в моем случае.

Теперь я могу использовать свои PNG-файлы RGBA без эффекта серых альфа-краев, из-за чего мой текст глифа выглядит неприятно.

Редактировать: Хорошо, еще одна вещь, для затухания и т. Д. (Настройка альфа-канала в коде), вам нужно будет предварительно умножить вручную, когда смешивание установлено, как указано выше, например,

glColor4f(r*a, g*a, b*a, a);
2 голосов
/ 25 октября 2010

Я понятия не имею, как выглядят ваши исходные изображения, но мне кажется, что они правильно смешиваются. С режимом смешивания у вас получится смешанное смешивание между слоями.

Версия для фотошопа выглядит так, как будто у вас есть правильная прозрачность для каждого слоя, но нет смешения. Я полагаю, вы могли бы поэкспериментировать с glAlphaFunc, если вы не хотите точно устанавливать альфа-значения пикселей

--- Код, относящийся к комментарию ниже (без предварительного альфа-умножения) ---

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;
}
...