2010-10-25 4 views
6

Я пишу игру для IPhone в OpenGL ES, и я испытываю проблемы с альфа-смешивания:OpenGL ES (IPhone) альфа-смешивание выглядит странно

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

Прикрепленный файл. В левой части экрана находится скриншот из iphone, а справа - это то, на что похоже, когда я делаю композицию в Photoshop. Изображение составлено градиентом и песочным изображением с пернатыми краями.

Ожидаемое поведение? Есть ли способ избежать темных границ?

Спасибо.

EDIT: Я загружаю часть 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

ответ

6

мне нужно ответить на мой собственный вопрос:

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

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

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

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

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

    IPHONE_OPTIMIZE_OPTIONS | -skip-PNGs

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

2

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

Версия для фотошоп выглядит так, будто у вас есть соответствующая прозрачность для каждого слоя, но не для смешивания. Я предполагаю, что вы могли бы экспериментировать с 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; 
} 
+0

Я загрузил исходное исходное изображение. Фон - это форма. Почему вы говорите, что в режиме смешивания я собираюсь получить грязные смеси между слоями? – Damian

+0

, увидев исходные исходные изображения, вы не делаете то, что, как я думал, вы делали. Я считаю, что проблема заключается в том, что API премультипирует альфу. Вы можете быстро обойти это, используя вместо этого blend mode glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA). Я понимаю, что это одна из неприятностей API iphone. – Montdidier

+0

Использование glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA) не позволит мне изменить общую альфу изображения с помощью glColor. – Damian

3

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

+0

Irpetrich: Я загрузил исходное изображение и кучу кода, который я использую для его загрузки. Вы правы, вот как это выглядит, но почему/где цветовые каналы преумножимы? – Damian

+0

Они умножаются, потому что это формат, который лучше всего использует GPU от iPhone. Все PNG преобразуются в предварительно умноженное RGBA при чтении с использованием UIImage. Возможно, вы сможете обойти это, используя новую общедоступную среду ImageIO или просто сохраняя свой альфа-канал на отдельном изображении. – rpetrich

1

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

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 

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

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

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

glColor4f(r*a, g*a, b*a, a); 
Смежные вопросы