Das Problem bei der Verwendung von Texturatlanten und benachbarten Texeln, die auslaufen, hängt mit der Funktionsweise der linearen Texturfilterung zusammen.
Für jeden Punkt in der Textur, der nicht genau in der Mitte eines Texels abgetastet wird, werden bei der linearen Abtastung 4 benachbarte Texel abgetastet und der Wert an der von Ihnen angeforderten Stelle als gewichteter Durchschnitt (basierend auf dem Abstand vom Abtastpunkt) aller 4 berechnet Proben.
Hier ist eine schöne Visualisierung des Problems:
Da Sie so etwas wie GL_CLAMP_TO_EDGE
in einem Texturatlas nicht verwenden können , müssen Sie um den Rand jeder Textur Randtexel erstellen. Diese Randtexel verhindern, dass benachbarte Samples aus völlig unterschiedlichen Texturen im Atlas das Bild durch die oben erläuterte gewichtete Interpolation verändern.
Beachten Sie, dass Sie bei Verwendung der anisotropen Filterung möglicherweise die Breite des Rahmens erhöhen müssen. Dies liegt daran, dass anisotrope Filterung die Größe der Probenumgebung bei extremen Winkeln erhöht.
Um zu veranschaulichen, was ich mit einem Rand um den Rand jeder Textur meine, betrachten Sie die verschiedenen in OpenGL verfügbaren Umbruchmodi. Achten Sie besonders darauf CLAMP TO EDGE
.
Obwohl es einen Modus namens "Clamp to Border" gibt, ist dies eigentlich nicht das, woran wir interessiert sind. In diesem Modus können Sie eine einzelne Farbe definieren, die als Rand um Ihre Textur für alle Texturkoordinaten verwendet werden soll, die außerhalb der normalisierten [0.0 -1,0] Bereich.
Was wir wollen, ist das Verhalten zu replizieren CLAMP_TO_EDGE
, bei dem jede Texturkoordinate außerhalb des richtigen Bereichs für die (Unter-) Textur den Wert des letzten Texelzentrums in der Richtung erhält, in der es außerhalb der Grenzen lag. Da Sie fast die vollständige Kontrolle darüber haben Die Texturkoordinaten in einem Atlas-System. Das einzige Szenario, in dem sich (effektive) Texturkoordinaten auf einen Ort außerhalb Ihrer Textur beziehen, ist der gewichtete Durchschnittsschritt der Texturfilterung.
Wir wissen, dass GL_LINEAR
die 4 nächsten Nachbarn wie im obigen Diagramm dargestellt abgetastet werden, daher benötigen wir nur einen 1-Texel-Rand. Wenn Sie eine anisotrope Filterung verwenden, benötigen Sie möglicherweise einen breiteren Texelrand, da dies unter bestimmten Bedingungen die Größe der Probenumgebung erhöht.
Hier ist ein Beispiel für eine Textur, die den Rand deutlicher darstellt. Für Ihre Zwecke können Sie den Rand jedoch 1 Texel oder 2 Texel breit machen.
(HINWEIS: Der Rand, auf den ich mich beziehe, ist nicht das Schwarz an allen vier Bildrändern, sondern der Bereich, in dem sich das Schachbrettmuster nicht mehr regelmäßig wiederholt.)
Falls Sie sich gefragt haben, hier ist, warum ich immer wieder anisotrope Filterung anspreche. Es ändert die Form der Probenumgebung basierend auf dem Winkel und kann dazu führen, dass mehr als 4 Texel zum Filtern verwendet werden:
http://www.arcsynthesis.org/gltut/Texturing/ParallelogramDiag.svg
Je größer der von Ihnen verwendete Anisotropiegrad ist, desto wahrscheinlicher ist es, dass Sie sich mit Beispielvierteln befassen müssen, die mehr als 4 Texel enthalten. Ein 2-Texel-Rand sollte für die meisten anisotropen Filtersituationen ausreichend sein.
Last but not least wird hier ein gepackter Texturatlas erstellt, der das GL_CLAMP_TO_EDGE
Verhalten bei Vorhandensein eines GL_LINEAR
Texturfilters repliziert :
( Subtrahiere 1 von X und Y in den schwarzen Koordinaten, ich habe das Bild vor dem Posten nicht Korrektur gelesen. )
Aufgrund der Randspeicherung erfordert das Speichern von 4 256x256-Texturen in diesem Atlas eine Textur mit den Abmessungen 516x516. Die Ränder sind farbcodiert, je nachdem, wie Sie sie während der Atlaserstellung mit Texeldaten füllen würden:
- Rot = Durch Texel direkt darunter ersetzen
- Gelb = Durch Texel direkt darüber ersetzen
- Grün = Ersetzen Sie durch Texel direkt links
- Blau = Durch Texel direkt rechts ersetzen
In diesem gepackten Beispiel verwendet jede Textur im Atlas effektiv einen Bereich von 258 x 258 des Atlas. Sie generieren jedoch Texturkoordinaten, die dem sichtbaren Bereich von 256 x 256 zugeordnet sind. Die angrenzenden Texel werden immer nur verwendet, wenn die Texturfilterung an den Rändern der Texturen im Atlas durchgeführt wird und die Art und Weise, wie sie entworfen wurden, das GL_CLAMP_TO_EDGE
Verhalten nachahmt .
Falls Sie sich gefragt haben, können Sie andere Arten von Umbruchmodi mit einem ähnlichen Ansatz implementieren. Dies GL_REPEAT
kann durch Austauschen der Texel für den linken / rechten und oberen / unteren Rand im Texturatlas und ein wenig cleverer Texturkoordinatenmathematik in a implementiert werden Shader. Das ist etwas komplizierter, also mach dir vorerst keine Sorgen. Da Sie nur mit Sprite-Sheets zu tun haben, beschränken Sie sich auf GL_CLAMP_TO_EDGE
:)
GL_NEAREST
oderGL_LINEAR
zum Rendern der Textur?