In meinem Spiel gibt es ein Minecraft-ähnliches Terrain, das aus Würfeln besteht. Ich generiere einen Vertex-Puffer aus den Voxeldaten und verwende einen Texturatlas für das Aussehen verschiedener Blöcke:
Das Problem ist, dass die Textur entfernter Würfel mit benachbarten Kacheln im Texturatlas interpoliert. Dies führt zu falschen Farben zwischen den Würfeln (möglicherweise müssen Sie den Screenshot unten in voller Größe anzeigen, um die Grafikfehler zu erkennen):
Im GL_NEAREST
Moment verwende ich diese Interpolationseinstellungen, aber ich habe jede Kombination ausprobiert und auch ohne Mipmapping liefert es keine besseren Ergebnisse.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
Ich habe auch versucht, einen Versatz in den Texturkoordinaten hinzuzufügen, um einen etwas kleineren Bereich der Kachel auszuwählen, aber da der unerwünschte Effekt vom Abstand zur Kamera abhängt, kann dies das Problem nicht vollständig lösen. In weiten Entfernungen treten die Streifen trotzdem auf.
Wie kann ich diese Texturblutung lösen? Da die Verwendung eines Texturatlas eine beliebte Technik ist, gibt es möglicherweise einen gemeinsamen Ansatz. Leider kann ich aus Gründen, die in den Kommentaren erläutert wurden, nicht auf andere Texturen oder Texturarrays wechseln.
GL_LINEAR
, was ein ähnliches Ergebnis ergibt, oder es wird das nächste Pixel ausgewählt,GL_NEAREST
das ohnehin auch Streifen zwischen Blöcken ergibt. Die zuletzt genannte Option verringert den Pixelfehler, beseitigt ihn jedoch nicht.Antworten:
Okay, ich denke, Sie haben hier zwei Probleme.
Das erste Problem ist mit Mipmapping. Im Allgemeinen möchten Sie das Atlasing nicht naiv mit dem Mipmapping mischen, da es zu Texturbluten kommt, wenn Ihre Subtexturen nicht genau 1x1 Pixel groß sind. Durch Hinzufügen von Polstern wird das Problem einfach auf eine niedrigere MIP-Ebene verschoben.
Als Faustregel gilt, dass Sie bei 2D, wo Sie normalerweise atlasieren, keine Mipmap verwenden. während für 3D, wo Sie mipmap, Sie nicht atlas (tatsächlich haut Sie so, dass Blutungen kein Problem sein)
Ich denke jedoch, dass Ihr Programm momentan nicht die richtigen Texturkoordinaten verwendet und Ihre Texturen daher bluten.
Nehmen wir eine 8x8-Textur an. Sie erhalten wahrscheinlich das obere linke Viertel, indem Sie UV-Koordinaten von (0,0) bis (0,5, 0,5) verwenden:
Und das Problem ist, dass der Sampler bei einer u-Koordinate von 0,5 das Zielfragment mit der Hälfte des linken Texels und der Hälfte des rechten Texels interpoliert. Dasselbe passiert bei der u-Koordinate 0 und bei den v-Koordinaten. Dies liegt daran, dass Sie die Grenzen zwischen Texeln und nicht die Zentren ansprechen.
Was Sie stattdessen tun sollten, ist die Mitte jedes Texels zu adressieren. In diesem Beispiel sind dies die Koordinaten, die Sie verwenden möchten:
In diesem Fall wird immer die Mitte jedes Texels abgetastet, und Sie sollten keine Ausblutung feststellen. Wenn Sie kein Mipmapping verwenden, wird die Ausblutung immer auf der Mip-Ebene beginnen, auf der die skalierte Subtextur nicht ordentlich ist passen in das Pixelraster .
Um zu verallgemeinern, wenn Sie auf ein bestimmtes Texel zugreifen möchten, werden die Koordinaten wie folgt berechnet:
Dies wird als "Halbpixelkorrektur" bezeichnet. Wenn Sie interessiert sind, finden Sie hier eine ausführlichere Erklärung .
quelle
Eine Option, die viel einfacher ist als das Fummeln mit Mipmaps und das Hinzufügen von Texturkoordinaten-Fuzz-Faktoren, ist die Verwendung eines Texturarrays. Textur-Arrays ähneln 3D-Texturen, haben jedoch kein Mipmapping in der 3. Dimension und sind daher ideal für Textur-Atlanten, bei denen die "Subtexturen" alle gleich groß sind.
http://www.opengl.org/wiki/Array_Texture
quelle
Nachdem ich mich viel mit diesem Problem auseinandergesetzt hatte, fand ich endlich eine Lösung.
Um sowohl einen Texturatlas als auch ein Mipmapping zu verwenden, muss ich das Downsampling selbst durchführen, da OpenGL andernfalls über die Grenzen der Kacheln im Atlas interpolieren würde. Außerdem musste ich die richtigen Texturparameter einstellen, da das Interpolieren zwischen Mipmaps auch zu Texturbluten führen würde.
Mit diesen Parametern tritt keine Blutung auf.
Es gibt eine Sache, die Sie beachten müssen, wenn Sie benutzerdefinierte Mipmaps bereitstellen. Da es keinen Sinn macht, den Atlas zu verkleinern, selbst wenn bereits eine Kachel vorhanden ist
1x1
, muss der maximale Mipmap-Level entsprechend Ihrer Angaben festgelegt werden.Vielen Dank für alle anderen Antworten und sehr hilfreichen Kommentare! Übrigens weiß ich immer noch nicht, wie man lineare Skalierung einsetzt, aber ich denke, es gibt keinen Weg.
quelle
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_FILTER, GL_NEAREST_MIPMAP_LINEAR);
GL_TEXTURE_MAX_FILTER
auf werdenGL_NEAREST_MIPMAP_LINEAR
Blutungen nicht aufgrund von Mipmapping, sondern aufgrund von Interpolation verursacht. In diesem Fall ist dies äquivalent zu,GL_LINEAR
da ohnehin die niedrigste Mipmap-Ebene verwendet wird.glTexImage2D()
. Die GPU wählt automatisch die richtige Stufe basierend auf der Größe der Objekte auf dem Bildschirm.Es sieht so aus, als könnte das Problem durch MSAA verursacht werden. Siehe diese Antwort und den verlinkten Artikel :
Die Lösung ist die Verwendung der Schwerpunktabtastung. Wenn Sie den Umbruch der Texturkoordinaten in einem Vertex-Shader berechnen, kann das Problem auch durch Verschieben dieser Logik in den Fragment-Shader behoben werden.
quelle
Dies ist ein altes Thema, und ich hatte ein ähnliches Problem wie das Thema.
Ich hatte meine Texturkoordinaten in Ordnung, aber indem ich die Kameraposition (die die Position meines Elements veränderte) wie folgt veränderte:
Das ganze Problem war, dass Util.lerp () ein float oder double zurückgibt. Dies war schlecht, da die Kamera außerhalb des Rasters übersetzte und einige seltsame Probleme mit Texturausschnitten verursachte, bei denen> 0 in X und> 0 in Y waren.
TLDR: Tween oder ähnliches nicht mit Floats
quelle