2010-10-25 20 views
6

Estoy escribiendo un juego para iPhone en OpenGL ES, y yo estoy experimentando un problema con mezcla alfa:OpenGL ES (iPhone) mezcla alfa ve raro

estoy usando glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA) para lograr la mezcla alfa y tratando para componer una escena con varias "capas", así puedo moverlas por separado en lugar de tener una imagen estática. Creé una vista previa en photoshop y luego traté de lograr el mismo resultado en el iphone, pero se muestra un halo negro cuando combino una textura con regiones semitransparentes.

Adjunté una imagen. En la izquierda está la captura de pantalla del iphone, y en la derecha está lo que parece cuando hago la composición en photoshop. La imagen está compuesta por un degradado y una imagen de arena con bordes emplumados.

¿Es este el comportamiento esperado? ¿Hay alguna manera de evitar las fronteras oscuras?

Gracias.

EDIT: Estoy cargando la parte del png que contiene la arena. El png completo es de 512x512 y tiene otras imágenes también.

Estoy cargando la imagen utilizando el siguiente código:

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

Respuesta

6

tengo que responder a mi propia pregunta:

no pude hacer que funcione usando marco ImageIO por lo que añade libpng fuentes a mi proyecto y carga la imagen de usarlo. Funciona perfecto ahora, pero tenía que resolver el siguiente problema:

La imagen se cargó y se mostró bien en el simulador, pero no se estaba cargando en absoluto en el dispositivo real. Encontré en la web que lo que sucede es que el orden de píxeles en archivos de formato de imagen PNG se convierte de RGBA a BGRA, y los valores de color también se multiplican previamente por el valor del canal alfa, mediante una utilidad de compresión 'pngcrush' (por razones de eficiencia específica del dispositivo, cuando se programa con la interfaz UIKit).

La utilidad también cambia el nombre de un encabezado del archivo, haciendo que el nuevo archivo PNG no se pueda usar mediante libpng. Estos cambios se realizan automáticamente cuando se implementan archivos PNG en el iPhone. Si bien esto está bien para el UIKit, libpng (y otras bibliotecas que no son de Apple) generalmente no pueden leer los archivos.

Las soluciones simples son:

  1. cambiar el nombre de archivos PNG con una extensión diferente.
  2. para su iPhone -device- construir añadir la configuración definida por el usuario siguiente:

    IPHONE_OPTIMIZE_OPTIONS | -skip-PNGs

lo hice el segundo y funciona perfecto en el simulador y el dispositivo ahora.

2

no tengo ni idea de lo que sus imágenes fuente originales se parecen, pero me parece que se se está mezclando correctamente Con el modo de fusión, obtendrás mezclas sofocantes entre las capas.

La versión de photoshop parece que tiene la transparencia adecuada para cada capa, pero no para la mezcla. Supongo que podrías experimentar con glAlphaFunc si no quisieras establecer explícitamente el pixel alphas exactamente.

--- Código relativo a comentar a continuación (la eliminación de alfa multiplicación previa) ---

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

He subido la imagen de la fuente original. El fondo es una forma. ¿Por qué dices eso con el modo de fusión que tengo Voy a obtener mezclas bochornosas entre las capas? – Damian

+0

después de ver las imágenes fuente originales, no estás haciendo lo que pensé que estabas haciendo. Lo que creo que es el problema es que la API está premultiplicando el alfa. Puede solucionar esto rápidamente utilizando en su lugar el modo de combinación glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA). Entiendo que es una de las molestias de la API de iPhone. – Montdidier

+0

Usar glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA) no me permitirá cambiar el alfa general de la imagen con glColor. – Damian

3

su pantalla y la maqueta photoshop sugieren que los canales de color de la imagen están siendo premultiplicados contra el canal alfa.

+0

Irpetrich: Cargué la imagen fuente y el código que uso para cargarlo. Tiene razón, eso es lo que parece, pero ¿por qué/dónde se están premultiplicando los canales de color? – Damian

+0

Se están multiplicando porque ese es el formato que maneja mejor la GPU del iPhone: todos los PNG se convierten a RGBA premultiplicado cuando se leen utilizando UIImage. Es posible que pueda solucionar este problema utilizando el nuevo marco público de ImageIO o simplemente almacenando su canal alfa en una imagen separada. – rpetrich

1

Soy consciente de que esta publicación es antigua, sin embargo tuve el mismo problema y después de intentar algunas de las soluciones y agonizar durante días, descubrí que puede resolver el problema RGBA png pre-multiplicado utilizando los siguientes parámetros de fusión;

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 

El parámetro GL_ONE sustituirá el parámetro GL_SRC_ALPHA en mi caso.

Ahora puedo usar mis PNG RGBA sin el efecto de bordes alfa gris que hizo que mi texto de glifo pareciera desagradable.

Edit: Bien, una cosa más, para el desvanecimiento, etc. (estableciendo el canal alfa en el código), tendrá que pre-multiplicar manualmente cuando la fusión se establece como arriba, como tal;

glColor4f(r*a, g*a, b*a, a); 
Cuestiones relacionadas