Domanda

Sto sviluppando un'applicazione OpenGL per iPhone e devo usare alcune texture con trasparenza. Ho salvato le immagini come PNG. Ho già tutto il codice per caricare i PNG come trame OpenGL e renderli. Funziona bene per tutte le immagini che non hanno trasparenza (tutti i valori alfa sono 1.0). Tuttavia, ora che sto cercando di caricare e utilizzare alcuni PNG che hanno trasparenza (variando i valori alfa), la mia trama è incasinata, come se avesse caricato i dati in modo errato o qualcosa del genere.

Sono abbastanza sicuro che ciò sia dovuto al mio codice di caricamento che utilizza alcune delle API Cocoa. Invierò qui il codice pertinente.

Qual è il modo migliore per caricare PNG o qualsiasi formato di immagine che supporti la trasparenza su OSX / iPhone? Questo metodo sembra rotonda. Renderlo in un CGContext e ottenere i dati sembra strano.

* LOADING *

CGImageRef CGImageRef_load(const char *filename) {
    NSString *path = [NSString stringWithFormat:@"%@/%s",
                      [[NSBundle mainBundle] resourcePath],
                      filename];
    UIImage *img = [UIImage imageWithContentsOfFile:path];
    if(img) return [img CGImage];
    return NULL;
}

unsigned char* CGImageRef_data(CGImageRef image) {
    NSInteger width = CGImageGetWidth(image);
    NSInteger height = CGImageGetHeight(image);
    unsigned char *data = (unsigned char*)malloc(width*height*4);

    CGContextRef context = CGBitmapContextCreate(data,
                                                 width, height,
                                                 8, width * 4,
                                                 CGImageGetColorSpace(image),
                                                 kCGImageAlphaPremultipliedLast);

    CGContextDrawImage(context,
                       CGRectMake(0.0, 0.0, (float)width, (float)height),
                       image);
    CGContextRelease(context);

    return data;
}

* UPLOADING *

(define (image-opengl-upload data width height)
  (let ((tex (alloc-opengl-image)))
    (glBindTexture GL_TEXTURE_2D tex)
    (glTexEnvi GL_TEXTURE_ENV GL_TEXTURE_ENV_MODE GL_DECAL)
    (glTexImage2D GL_TEXTURE_2D
                  0
                  GL_RGBA
                  width
                  height
                  0
                  GL_RGBA
                  GL_UNSIGNED_BYTE
                  (->void-array data))
    (glTexParameteri GL_TEXTURE_2D
                     GL_TEXTURE_MIN_FILTER
                     GL_LINEAR)
    (glTexParameteri GL_TEXTURE_2D
                     GL_TEXTURE_MAG_FILTER
                     GL_LINEAR)
    (glTexParameteri GL_TEXTURE_2D
                     GL_TEXTURE_WRAP_S
                     GL_CLAMP_TO_EDGE)
    (glTexParameteri GL_TEXTURE_2D
                     GL_TEXTURE_WRAP_T
                     GL_CLAMP_TO_EDGE)    
    (glBindTexture GL_TEXTURE_2D 0)
    tex))
È stato utile?

Soluzione

La tua superficie grafica principale dovrebbe essere azzerata prima di eseguire il rendering, quindi ti consiglio di usare calloc invece di malloc o di aggiungere un memset dopo il malloc.

Inoltre, non sono sicuro che desideri che TexEnv sia impostato su GL_DECAL . Potresti voler lasciare l'impostazione predefinita ( GL_MODULATE ).

Se desideri evitare Core Graphics per la decodifica delle immagini PNG, ti consiglio di caricare un file PVR. PVR è un formato di file estremamente semplice. Un'app denominata PVRTexTool è inclusa nell'SDK Imagination che semplifica la conversione da PNG a PVR. L'SDK include anche alcuni codici di esempio che mostrano come analizzare il loro formato di file.

Altri suggerimenti

Per essere espliciti ...

Il problema più comune con il caricamento di texture usando Core Image è che insiste nel convertire i dati in formato alfa premoltiplicato. Nel caso di PNG inclusi nel bundle, ciò viene effettivamente eseguito in una fase di preelaborazione del processo di generazione. Non tenerne conto si traduce in bande scure attorno agli oggetti miscelati.

Il modo per tenerne conto è usare glBlendMode (GL_ONE, GL_ONE_MINUS_SRC_ALPHA) anziché glBlendMode (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) . Se desideri utilizzare i canali alfa per qualcosa di diverso dalla fusione normale, l'unica opzione è passare a un formato e caricatore diversi (come suggerito l'orgoglio, ma per motivi diversi).

ETA: il problema di premoltiplicazione esiste anche in Mac & nbsp; OS & nbsp; X, ma la preelaborazione è specifica per iPhone.

Non so nulla di OpenGL, ma Cocoa estrae questa funzionalità con NSImage / UIImage.

Puoi usare i PVR ma ci saranno alcuni artefatti di compressione, quindi raccomanderei solo quelli per trame di oggetti 3D o trame che non richiedono un certo livello di dettaglio che il PVR non può offrire, specialmente con i gradienti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top