2017-10-27 3 views
3

Ich lade 32 bit RGBA normalmap Texturen, mit einer Heightmap in den Alpha-Kanal, über SDL2 2.0.7 und SDL2_image 2.0.2 auf OS X Sierra.SDL2 pre-multipliziert Alpha-Kanal beim Laden der Oberfläche auf OS X?

Jedes Pixel in diesen Texturen hat einen von Null verschiedenen RGB-Wert, der einen gerichteten Normalenvektor codiert. Ein Richtungsvektor von (0, 0, 0) (d. H. schwarz) ist ungültig.

Und doch, wenn ich eine solche Textur über SDL2_image laden, werden die Bereiche der Textur mit einem Alpha-Wert von 0 auch Ausbeute RGB-Werte von 0 ich SDL denken, ist vielleicht der Alpha-Wert für diese Pixel-Pre Multiplikation ?

Beigefügt ist eine dieser normalmap Texturen. Sie können bestätigen, dass es gültig ist, indem Sie die Textur z. GIMP und den Farbwähler auf einem der transparenten Bereiche verwenden. Sie werden sehen, dass in der Tat die transparenten Bereiche immer noch eine RGB-Farbe haben, die blau-isch ist (ein codierter Normalvektor).

32 bit RGBA normalmap with alpha-encoded heightmap for parallax mapping

Und unten ist ein minimaler Testfall darstellt, um das Problem für das angeschlossene PNG-Datei:

#include <SDL_image.h> 
#include <assert.h> 

int main(int argc, char **argv) { 

    SDL_Surface *s = IMG_Load("green3_2_nm.png"); 
    assert(s); 

    for (int i = 0; i < s->w * s->h; i++) { 
     const Uint32 *in = (Uint32 *) (s->pixels + i * s->format->BytesPerPixel); 

     SDL_Color color; 
     SDL_GetRGBA(*in, s->format, &color.r, &color.g, &color.b, &color.a); 

     assert(color.r || color.g || color.b); 
    } 

    SDL_FreeSurface(s); 

    return 0; 
} 

Ich bin der Zusammenstellung dieser Testfall mit gcc $(pkg-config --cflags --libs sdl2_image) test.c

Die Behauptung auf Linie 15 scheitert mehrere Zeilen im Bild - also genau dort, wo der Alpha-Wert auf 0 fällt.

habe ich ausprobiert sowohl TGA- als auch PNG-Bildformate, aber SDL macht das gleiche für beide.

Ist das ein Fehler in SDL, oder fehlt mir etwas? Ich bin neugierig, ob die Leute das gleiche Problem auch auf anderen Plattformen sehen.

===

Antwort: Core Graphics, das Standardbild Laden Backend für SDL2_image auf Apple OS X, tut in der Tat vorgemehrfach alpha - immer. Die Lösung ist SDL2_image ohne Core Graphics Unterstützung neu kompilieren und stattdessen libpng ermöglichen, libjpeg und alle anderen Bild Codecs, die Sie benötigen:

./configure \ 
--disable-imageio \ 
--disable-png-shared \ 
--disable-tif-shared \ 
--disable-jpg-shared \ 
--disable-webp-shared 

Auf meinem System hatte ich Core Graphics (imageio) und auch deaktivieren Laden der anderen Codecs, wie Sie sehen können. Dies führte zu einem Fett SDL2_image.so, das statisch mit libpng, libjpg usw. verbunden war, aber wie erwartet funktionierte.

Antwort

3

SDL_image ist ein Wrapper für plattformspezifischen Bildladecode, anstatt denselben Bildlader auf allen Plattformen zu verwenden.

  • Linux: LibPNG, Libjpeg
  • macOS, iOS: Core Graphics
  • Fenster: WinCodec

Dies hat den Vorteil, dass die Größe von SDL_image zu reduzieren, da es nicht muss Sie können mit jedem Bilddekodierungscode geliefert werden und können stattdessen dynamisch mit etwas verknüpfen, das wahrscheinlich bereits auf Ihrem System installiert ist.Unter MacOS und iOS unterstützt Core Graphics jedoch kein nicht-multipliziertes Alpha, daher muss SDL_image es umkehren.

See: mac-opengl - Re: kCGImageAlphaFirst not implemented (Was: (no subject)) ab Mai 2007 (von der Wayback-Maschine):

Ehrlich gesagt, würde ich nicht erwarten CGBitmapContextCreate() bald nicht premultiplied alpha jederzeit zu unterstützen.

...

Ich bin nicht sicher, ob ImageIO + Core Graphics verwendet wurde jemals wirklich wird verwendet für OpenGL-Anwendungen für ein Bildladeschema abgezielt.

Dieses Verhalten wurde in LibSDL bug #838 - OSX SDL darkens colours proportional to increase in alpha und eine Abhilfe entdeckt wurde in SDL_image changeset 240 eingeführt.

Sie können sehen, dass die Problemumgehung das Alpha nur un-multipliziert, das ist ein schrecklich verlustreicher Prozess.

Um dies zu beheben, könnten Sie Ihre eigene Version von SDL_image auf macOS erstellen, die LibPNG verwendet. Dies sollte nur durch die Konfiguration möglich sein, Sie sollten den SDL_image-Code selbst nicht ändern müssen. Verwenden Sie dazu die Option --disable-imageio. SDL_image wird mit einer eigenen Kopie des LibPNG-Codes ausgeliefert. Daher sollten Sie LibPNG nicht installieren müssen, damit dies funktioniert.

+0

Vielen Dank für Ihre Antwort. Bevor ich es akzeptiere, können Sie mir erklären, warum dies auch bei TGA-Bildern der Fall ist? Ich glaube, SDL dekodiert und lädt sie selbst, ist das korrekt? Wenn ja, warum zeigen sie auch dieses Problem? – jdolan

+1

SDL verwendet Core Graphics auf macOS für alle von Core Graphics unterstützten Formate, einschließlich TGA, TIFF und einige andere. –

+0

SDL_image dekodiert die Bilder jedoch nicht wirklich. Es verwendet Bibliotheken dafür. SDL_image stellt nur einen Wrapper mit einer gemeinsamen Schnittstelle zu all diesen anderen Bibliotheken bereit. (Es könnte einige Ausnahmen geben.) –