2010-10-25 17 views
6

Sto scrivendo un gioco per iPhone in OpenGL ES, e sto vivendo un problema con alpha blending:OpenGL ES (iPhone) alpha blending sembra strano

sto usando glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA) per ottenere alpha blending e cercando per comporre una scena con diversi "livelli" in modo da poterli spostare separatamente invece di avere un'immagine statica. Ho creato un'anteprima in Photoshop e poi ho cercato di ottenere lo stesso risultato nell'iPhone, ma viene visualizzato un alone nero quando mischio una texture con regioni semitrasparenti.

Ho allegato un'immagine. A sinistra c'è lo screenshot dell'iPhone, e nella parte destra è ciò che appare quando compongo la composizione in Photoshop. L'immagine è composta da un gradiente e un'immagine di sabbia con bordi sfumati.

È questo il comportamento previsto? C'è un modo per evitare i confini scuri?

Grazie.

MODIFICA: Sto caricando la parte del png contenente la sabbia. Il png completo è 512x512 e ha anche altre immagini.

Sto caricando l'immagine utilizzando il seguente codice:

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

risposta

6

ho bisogno di rispondere alla mia domanda:

non ho potuto farlo funzionare utilizzando il framework ImageIO così ho aggiunto libpng fonti al mio progetto e caricato l'immagine di utilizzarlo. Funziona perfettamente ora, ma dovevo risolvere il seguente problema:

L'immagine è stata caricata e mostrata correttamente nel simulatore ma non si caricava affatto sul dispositivo reale. Ho trovato sul Web che ciò che sta succedendo è che l'ordine dei pixel nei file di formato immagine PNG viene convertito da RGBA a BGRA, e i valori dei colori sono pre-moltiplicati anche dal valore del canale alfa, da un'utilità di compressione 'pngcrush' (per motivi di efficienza specifici del dispositivo, quando si programma con l'interfaccia UIKit).

L'utilità inoltre rinomina un'intestazione del file, rendendo inutilizzabile il nuovo file PNG da libpng. Queste modifiche vengono eseguite automaticamente quando i file PNG vengono distribuiti su iPhone. Mentre questo è perfetto per UIKit, libpng (e altre librerie non Apple) generalmente non possono leggere i file.

Le soluzioni semplici sono:

  1. rinominare i file PNG con una diversa estensione.
  2. per il vostro iPhone -device- costruire aggiungere la seguente impostazione definita dall'utente:

    IPHONE_OPTIMIZE_OPTIONS | -skip-PNGs

ho fatto il secondo e funziona perfettamente sul simulatore e dispositivo ora.

2

Non ho idea di quello che le immagini sorgente originali assomigliano, ma a me sembra che si sta mescolando correttamente. Con la modalità di fusione hai le miscele afose tra gli strati.

La versione di Photoshop sembra avere la trasparenza appropriata per ogni livello, ma non per la fusione. Suppongo che potresti esperire con glAlphaFunc se non vuoi impostare in modo esplicito l'alfa pixel esattamente.

--- Codice in materia di commentare qui sotto (la rimozione alpha pre-moltiplicazione) ---

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

Ho caricato l'immagine di origine originale. Lo sfondo è una forma. Perché dici che con la modalità di fusione ho ottenuto miscele afose tra gli strati? – Damian

+0

dopo aver visto le immagini originali, non stai facendo quello che pensavo stavi facendo. Quello che penso sia il problema è che l'API sta premoltiplicando l'alfa. È possibile ovviare rapidamente a questo problema utilizzando la modalità di fusione glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA). Capisco che sia uno dei fastidi dell'iPhone. – Montdidier

+0

L'utilizzo di glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA) non consente di modificare l'alfa globale dell'immagine utilizzando glColor. – Damian

3

tuo screenshot e photoshop mockup suggeriscono che i canali dei colori dell'immagine vengono premoltiplicati contro il canale alfa.

+0

Irpetrich: Ho caricato l'immagine sorgente e il codice del codice che uso per caricarlo. Hai ragione, è quello che sembra, ma perché/dove i canali di colore sono premoltiplicati? – Damian

+0

Si stanno moltiplicando perché quello è il formato che la GPU dell'iPhone gestisce meglio: tutti i PNG vengono convertiti in RGBA premoltiplicati quando letti utilizzando UIImage. Potresti riuscire a ovviare a questo problema usando il nuovo framework ImageIO pubblico o semplicemente memorizzando il tuo canale alfa in un'immagine separata. – rpetrich

1

Sono consapevole che questo post è antico, tuttavia ho avuto il problema identico e dopo aver tentato alcune delle soluzioni e agonizzante per giorni ho scoperto che è possibile risolvere il problema PNG pre-moltiplicato utilizzando i seguenti parametri di fusione;

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 

Il parametro GL_ONE sostituito il parametro GL_SRC_ALPHA nel mio caso.

Ora posso usare i miei PNG RGBA senza l'effetto di bordi alfa grigio che ha reso il mio testo glifo brutto.

Modifica: OK, un'altra cosa, per la dissolvenza ecc. (Impostazione del canale alfa nel codice), sarà necessario pre-moltiplicare manualmente quando la fusione è impostata come sopra, in questo modo;

glColor4f(r*a, g*a, b*a, a); 
Problemi correlati