Ausgabe
Immer wenn ich eine Textur zeichne, die Alpha an den Rändern hat (sie wird von Photoshop geglättet), werden diese Ränder dunkel. Ich habe endlos mit Texturfiltern und Mischmodi herumgespielt, hatte aber keinen Erfolg.
Hier ist, was ich meine:
minFilter: Linear magFilter: Linear
minFilter: MipMapLinearNearest magFilter: Linear
minFilter: MipMapLinearLinear magFilter: Linear
Wie Sie sehen können, macht das Ändern des Filters im libGDX Texture Packer einen großen Unterschied im Aussehen, aber Alphas sind immer noch dunkel .
Ich habe versucht, den Texturfilter in libgdx manuell einzustellen mit:
texture.setFilter(minFilter, magFilter);
Aber das geht nicht.
Ich habe gelesen, dass das Herunterskalieren mit einem linearen Filter dazu führt, dass die Alpha-Pixel standardmäßig schwarz sind? Wenn dies der Fall ist, wie kann ich es vermeiden?
Ich habe auch versucht, den Mischmodus zu ändern: glBlend(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_APHA)
macht keinen Unterschied. glBlend(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
entfernt Alpha vollständig, so dass das nicht funktioniert.
Ich möchte mein nicht auf setzen minFilter
, Nearest
weil es die Dinge schrecklich pixelig aussehen lässt. Ich habe jede andere Kombination von Texturfiltern ausprobiert, aber alles führt zu demselben Effekt mit schwarzen/dunklen Kanten/Konturen.
Lösung
Ich habe gelesen, dass das Herunterskalieren mit einem linearen Filter dazu führt, dass die Alpha-Pixel standardmäßig schwarz sind?
Dies ist nicht unbedingt wahr; es hängt davon ab, welche Farbe Photoshop in die vollständig transparenten Pixel eingefügt hat. Anscheinend ist dies in Ihrem Fall schwarz.
Das Problem tritt auf, weil die GPU zwischen zwei benachbarten Pixeln interpoliert, von denen eines vollständig transparent ist (wobei alle Farbkanäle ebenfalls auf Null gesetzt sind). Nehmen wir an, das andere Pixel ist hellrot:
(255, 0, 0, 255) // Bright red, fully opaque
( 0, 0, 0, 0) // Black, fully transparent
Interpolation mit einem Verhältnis von 50/50 ergibt:
(128, 0, 0, 128)
This is a half-opaque dark red pixel, which explains the dark fringes you’re seeing.
There are two possible solutions.
1. Add bleeds to transparent regions
Make sure that the fully transparent pixels have the right colour assigned to them; essentially “bleed” the colour from the nearest non-transparent pixel into adjacent fully transparent pixels. I’m not sure Photoshop can do this, but the libGDX TexturePacker can; see the bleed
and bleedIterations
settings. You need to be careful to set bleedIterations
high enough, and add enough padding for the bleed to expand into, for your particular level of downscaling.
Now the example comes out like this:
(255, 0, 0, 255)
(255, 0, 0, 0) // Red bled into the transparent region
Interpolation now gives a bright red transparent pixel, as desired:
(255, 0, 0, 128)
2. Use premultiplied alpha
This is less finicky to get right, but it helps to know exactly what you’re doing. Again TexturePacker has you covered, with the premultipliedAlpha
setting. This is OpenGL blend mode glBlend(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
.
The numbers in the example don’t change; this is still the pixel that comes out:
(128, 0, 0, 128)
However, this is no longer interpreted as “half-transparent dark red”, but rather as “add some red, and remove some background”. More generally, with premultiplied alpha, the colour channels are not “which colour to blend in” but “how much colour to add”.
Beachten Sie, dass ein Pixel wie (255, 0, 0, 0)
in der Quelltextur nicht mehr existieren kann: Da das Alpha vormultipliziert ist, bedeutet ein Alpha von Null automatisch, dass alle Farbkanäle ebenfalls Null sein müssen. (Wenn Sie wirklich schick werden möchten, können Sie solche Pixel sogar verwenden, um additives Mischen im selben Renderdurchlauf und dieselbe Textur wie beim normalen Mischen anzuwenden!)
Weiterführende Literatur zum vormultiplizierten Alpha:
Beantwortet von – Thomas
Antwort geprüft von – Marilyn (FixError Volunteer)