Wie erstelle ich einen "Retro" -Pixel-Shader für transformierte 2D-Sprites, der die Pixeltreue beibehält?

10

Das Bild unten zeigt zwei Sprites, die mit Punktabtastung auf einem Hintergrund gerendert wurden:

Geben Sie hier die Bildbeschreibung ein

  • Auf den linken Schädel wird keine Drehung / Skalierung angewendet, sodass jedes Pixel perfekt zum Hintergrund passt.
  • Der rechte Schädel wird gedreht / skaliert, was zu größeren Pixeln führt , die nicht mehr achsenausgerichtet sind .

Wie könnte ich einen Pixel-Shader entwickeln, der das transformierte Sprite auf der rechten Seite mit achsenausgerichteten Pixeln der gleichen Größe wie der Rest der Szene rendert?

Dies könnte damit zusammenhängen, wie die Sprite-Skalierung in alten Spielen wie Monkey Island implementiert wurde, da dies der Effekt ist, den ich erreichen möchte, aber mit hinzugefügter Rotation.


Bearbeiten

Gemäß den Vorschlägen von kaoD habe ich versucht, das Problem als Nachbearbeitung anzugehen. Der einfachste Ansatz bestand darin, zuerst auf ein separates Renderziel zu rendern (heruntergerechnet, um der gewünschten Pixelgröße zu entsprechen) und es dann beim zweiten Rendern zu vergrößern. Es hat meine Anforderungen oben angesprochen.

Zuerst habe ich es versucht Linear -> Pointund das Ergebnis war folgendes:

Geben Sie hier die Bildbeschreibung ein

Es gibt keine Verzerrung, aber das Ergebnis sieht unscharf aus und es verliert die meisten Glanzlichterfarben. Meiner Meinung nach bricht es den Retro-Look, den ich brauchte.

Das zweite Mal habe ich es versucht Point -> Pointund das Ergebnis war folgendes:

Geben Sie hier die Bildbeschreibung ein

Trotz der Verzerrung denke ich, dass dies für meine Bedürfnisse gut genug sein könnte, obwohl es als Standbild besser aussieht als in Bewegung.

Zur Demonstration hier ein Video des Effekts, obwohl YouTube die Pixel herausgefiltert hat:

http://youtu.be/hqokk58KFmI

Ich werde die Frage jedoch noch einige Tage offen lassen, falls jemand eine bessere Sampling-Lösung findet, die das gestochen scharfe Aussehen beibehält und gleichzeitig die Verzerrung beim Bewegen verringert.

David Gouveia
quelle
Das soll ein Schädel sein ...?
DeadMG
@DeadMG Ein Ochsenschädel, denke ich?
David Gouveia
Schöner Effekt, sieht besser aus, als ich dachte (ich habe es mit EXTREM niedriger Auflösung und Palette, 40x30 EGA, versucht.) Das ist so ziemlich der Look, den Sie erhalten, wenn Sie Ihren eigenen Postfx-Shader erstellen. Übrigens bezweifle ich, dass es eine bessere Sampling-Lösung gibt, die den Effekt so hält, wie Sie es beabsichtigen. NN ist so ziemlich das, was diesen gestochen scharfen Look verleiht.
Jedes
@kaoD Aber denk daran, dass ich zwei Durchgänge beantrage. Der zweite Durchgang, der das Bild hochabtastet, ist immer noch der nächste Nachbar, um das Retro-Gefühl zu bewahren. Ich denke jedoch, dass es von Vorteil sein könnte, beim ersten Durchgang verschiedene Stichprobenverfahren auszuprobieren. Ich schaue gerade in Scale2x!
David Gouveia
@kaoD Nein, ich gebe auf. Das Ändern der Shader-Parameter zwischen den einzelnen Sprite-Aufrufen SpriteBatcherfordert die Verwendung des Sofortmodus, sodass sich die Mühe nicht lohnt. Ich werde damit gehen :)
David Gouveia

Antworten:

3

Sie sollten Ihren Shader anwenden, nachdem Ihr Sprite gedreht wurde.

Wenn die gesamte Szene noch nicht schattiert wurde und Ihre Sprites tatsächlich pixelig sind, benötigen Sie eine Art Post-FX-Filter für Ihre gesamte Szene. Die Mittelung von Pixelbereichen funktioniert einwandfrei. Es ist nicht genau das, was Sie beabsichtigen (es wird beim Bewegen / Drehen etwas schwanken), aber es könnte den Trick tun.

Die einzige Möglichkeit, diesen Retro-Look wahrheitsgetreu zu halten, besteht darin, Ihre Sprite-Rotationen selbst zu zeichnen. Es hat nichts damit zu tun, wie die Skalierung implementiert wurde: Die Auflösung war tatsächlich schlecht. Apropos, haben Sie es mit extrem niedrigen Auflösungen versucht? Es könnte auch den Trick machen und wird natürlicher aussehen, da es tatsächlich den Effekt verursacht hat, den Sie suchen. Und es ist billig! Sehr günstig! Tatsächlich ist es billiger als das, was Sie bereits haben (weniger Fragment-Shader-Ausführungen).

Der Effekt ist in Ihrem Beispielbild ruiniert, da Ihre Auflösung im Vergleich zu Ihren Sprites hoch ist, sodass Sie die realen Pixel in der Szene sehen können.

kaoD
quelle
Ja, ich benutze noch keine Shader. Es handelt sich nur um normale Sprites mit Texturen mit sehr niedriger Auflösung, die mit der Standardeinstellung von XNA bei aktivierter Punktabtastung gerendert werden SpriteBatch. Aber ein Post-FX könnte wirklich funktionieren. Für den Anfang werde ich versuchen, mit linearer Abtastung auf ein Renderziel zu rendern und dann das gesamte Renderziel mit Punktabtastung auf den Backbuffer zu rendern.
David Gouveia
@DavidGouveia verpassen Sie nicht die Gelegenheit, Ihre Auflösung zu unterschätzen. Wenn Sie wirklich den ursprünglichen Effekt erzielen möchten, ist dies Ihre beste Aufnahme. Wenn Sie eine hohe Auflösung benötigen (wenn ein Teil Ihrer GFX hochauflösend ist oder native Auflösungen aufweisen möchten), können Sie dennoch in einen Off-Screen-Puffer mit niedriger Auflösung rendern und ihn dann als vollständigen Bild in Ihren hochauflösenden Framebuffer malen -screen quad mit ausgeschalteter Filterung. Denken Sie daran, dass Sie die Seitenverhältnisse anpassen müssen, um rechteckige Pixel zu vermeiden.
kaoD
Überprüfen Sie meine Bearbeitung :) Ich denke, es hat den größten Teil des Problems gelöst, obwohl ich immer noch neugierig bin, ob es für dieses Problem eine bessere Stichprobenlösung als den nächsten Nachbarn gibt. Ich werde die Frage noch eine Weile laufen lassen.
David Gouveia