Wie vermeidet man den „Treppeneffekt“ in der Pixelkunstbewegung?

21

Ich rendere Sprites mit genauen Pixelkoordinaten, um den durch Antialiasing verursachten Unschärfeeffekt zu vermeiden (die Sprites sind Pixelkunst und sehen bei Filterung schrecklich aus). Da die Bewegung der Objekte jedoch mit variabler Geschwindigkeit, Schwerkraft und physikalischen Wechselwirkungen einhergeht, wird die Flugbahn mit Subpixel-Genauigkeit berechnet.

Bei ausreichend großen Bildschirmgeschwindigkeiten (vΔt größer als 2 oder 3 Pixel) funktioniert dies sehr gut. Bei geringer Geschwindigkeit kann jedoch ein merklicher Treppeneffekt auftreten, insbesondere entlang diagonaler Linien. Bei sehr langsamen Bildschirmgeschwindigkeiten (v << 1 Pixel pro Sekunde) ist dies kein Problem mehr, daher suche ich nur nach einer Lösung für Zwischengeschwindigkeiten.

Links ist die geplottete Trajektorie für eine große Geschwindigkeit dargestellt, die durch einfaches Runden der Objektkoordinaten erhalten wird. In der Mitte sehen Sie, was passiert, wenn die Geschwindigkeit abnimmt, und den Treppeneffekt, von dem ich spreche. Rechts den Ort der Flugbahn, den ich mir wünschen würde.

Pixelkoordinaten für die Objektbahn

Ich interessiere mich für Algorithmusideen zum Filtern der Trajektorie, um das Aliasing zu minimieren und gleichzeitig das ursprüngliche Verhalten bei großen und kleinen Geschwindigkeiten beizubehalten. Ich habe Zugriff auf Δt, momentane Position und Geschwindigkeit sowie eine beliebige Anzahl vorheriger Werte, aber da es sich um eine Echtzeitsimulation handelt, weiß ich nichts über zukünftige Werte (obwohl eine Schätzung unter bestimmten Voraussetzungen bei Bedarf extrapoliert werden könnte). . Beachten Sie, dass aufgrund der Physiksimulation auch plötzliche Richtungsänderungen auftreten können.

sam hocevar
quelle

Antworten:

18

Hier ist ein kurzer Überblick über einen Algorithmus, der einigermaßen gut funktionieren sollte.

  1. Berechnen Sie zunächst die Richtung, in die sich das Objekt bewegt, und prüfen Sie, ob es näher an der Horizontalen oder Vertikalen liegt.
  2. Wenn die Richtung eher vertikal (horizontal) ist, stellen Sie die Position des Objekts entlang des Richtungsvektors auf die Mitte der nächsten Pixelzeile (-spalte) ein.
  3. Runden Sie die Position auf die Mitte des nächsten Pixels ab.

Im Pseudocode:

if ( abs(velocity.x) > abs(velocity.y) ) {
    x = round(position.x);
    y = round(position.y + (x - position.x) * velocity.y / velocity.x);
} else {
    y = round(position.y);
    x = round(position.x + (y - position.y) * velocity.x / velocity.y);
}

Edit: Ja, getestet, funktioniert ganz gut.

Ilmari Karonen
quelle
+1, das funktioniert überraschend gut! Ich bemerke seltsame Rückwärtssprünge mit kreisenden Bewegungen bei langsamen Geschwindigkeiten, da die Einstellung in der Richtung entgegengesetzt zum Geschwindigkeitsvektor erfolgen kann (was normalerweise in Ordnung ist, aber nicht bei kleinen Flugbahnkrümmungen). Dies kann durch Multiplikation velocity.y / velocity.xmit einem zur Geschwindigkeit proportionalen Korrekturfaktor gelöst werden.
Sam Hocevar
@Sam: Du meinst kleinen Wenderadius (= hohe Krümmung), oder? Dies könnte in der Tat Probleme mit der linearen Extrapolation bei niedrigen Geschwindigkeiten verursachen. (Grundsätzlich funktioniert dies, solange das Quadrat der Geschwindigkeit pro Beschleunigung viel größer als 1 Pixel ist.) Eine mögliche (kluge) Lösung besteht darin, sich die zuletzt gerundete Position zu merken und sie erneut zu verwenden, wenn sie näher an der tatsächlichen Position liegt als die neu berechnete. (Man könnte auch eine Extrapolation höherer Ordnung versuchen, aber die Formeln werden ziemlich hässlich.)
Ilmari Karonen
In der Tat meinte ich kleinen Radius. Mein Fehler. Und danke für die zusätzlichen Hinweise; Da die Leistung dort nicht kritisch ist, kann ich es mir leisten, die Qualität zu verbessern.
Sam Hocevar
3

In einer allgemeinen physikbasierten Welt kann man nicht viel dagegen tun. Wenn sich alle Ihre Objekte entlang von Linien oder bestimmten Kreisen bewegen, können Sie etwas tun. Aber Sie arbeiten unter der tatsächlichen Physik. Das Objekt ist dort, wo die Physik es ausdrückt. Sie zeichnen einfach eine pixelbasierte Annäherung an diesen Ort.

Es ist im Allgemeinen etwas, das Sie akzeptieren müssen, wenn Sie sich an Pixelkoordinaten halten möchten. Es sollte nicht zu auffällig sein, es sei denn, Sie zeigen mit einer unglaublich geringen Auflösung an (weniger als 640 x 480, obwohl dies von der nativen Auflösung und Größe des Displays abhängt).

Nicol Bolas
quelle
Selbst bei hohen Auflösungen wird das Rendering hochskaliert (nächster Nachbar), um das Erscheinungsbild der alten Schule zu verbessern. Dies ist eine künstlerische Richtungsentscheidung.
Sam Hocevar
@SamHocevar: Wenn du einen "oldschool Auftritt" willst, warum willst du nicht einen vollständigen "oldschool Auftritt"? Warum ist das Treppensteigen, das jedes "Oldschool" -Spiel gehabt hätte, nicht Teil des Gesamteffekts, den Sie erzielen möchten?
Nicol Bolas
Ich glaube nicht, dass ein anständiges Oldschool-Spiel eine diagonale Bewegung implementiert hätte, die diesen Treppeneffekt hat, weil es wie Mist ausgesehen hätte. Nicht wie Mist
auszusehen,
@SamHocevar: Die meisten Old-School-Spiele sind Actionspiele und bewegen sich daher nicht langsam genug, um es zu bemerken. Sie neigen auch dazu, sich nicht entlang von Kurven zu bewegen. Das Spiel, an das ich gerade gedacht habe, war Solar Jetman, was sich sehr positiv auf langsame Bewegungen auswirkt. Zugegeben, die Kamera ist immer auf Sie zentriert, sodass Sie es in der Weltbewegung bemerken, aber es ist sehr viel da.
Nicol Bolas
3

Wenn die anstehende Bewegung senkrecht zur letzten Bewegung (im Bildschirmbereich) ist, ignorieren Sie sie und verwenden Sie die letzten Bildschirmkoordinaten. Wenn dies zu einem Stottern führt, das genauso schlimm ist wie das Treppenhaus, können Sie versuchen, die Summe aus dem anstehenden und dem letzten Satz zu verschieben.

Ich denke, das Problem liegt in v <sqrt (2). v> sqrt (2) sollte sich immer mindestens um eine volle Diagonale bewegen, um den Treppeneffekt zu vermeiden. Möglicherweise nützlich für das Beschneiden, das die vorherigen Bewegungsvergleiche benötigt.

mghicks
quelle
+1 für das Hervorheben einer Obergrenze für v. Ilmaris Vorschlag ist detaillierter, aber Sie geben nützliche Informationen.
Sam Hocevar