Wie kann ich einen Scanline-Effekt implementieren?

8

Ich arbeite an einem Old-School-Plattformer in libgdx und möchte, dass er einen "Scanline" -Effekt hat, wie folgt:

Maledita Castilla Scanline-Effekt

Mein erster Versuch war, eine kleine Textur zu erstellen und sie auf einem Quad im Vollbildmodus zu zeichnen. Ich habe zwei verschiedene orthografische Kameramodi verwendet (einen für die Haupt-Tilemap des Spiels und einen zweiten zum Rendern der Scanline-Textur). Manchmal klebt die Textur auf der Tilemap und manchmal ist sie zu groß und bedeckt den gesamten Bildschirm in Schwarz.

Ist mein Ansatz mit zwei Kameras und einer Textur sinnvoll? Was ist eine gute Lösung, um diesen Effekt zu erzielen?

Alexandre GUIDET
quelle

Antworten:

4

Das Problem beim naiven Rendern einer kleinen Scanline-Textur auf einem großen Vollbild-Quad besteht darin, dass die Textur vergrößert wird und das ergibt, was war eine Reihe von Ein-Pixel - Abtastlinien in der Textur viel dicker, unschärfer (je nach Interpolationsmethode) und im Allgemeinen hässlicher.

Sie sollten stattdessen kachelndie Textur über das Quad so, dass ein Pixel-zu-Texel-Verhältnis von 1: 1 erhalten bleibt. Dazu müssen Sie die Texturkoordinaten des Quad so anpassen, dass sie im weitesten Maße größer als 1 sind, und den Umbruchparameter für Texturen so einstellen, dass er wiederholt wird, anstatt zu klemmen. Wenn Ihre Textur 64 x 64 Pixel und Ihr Bildschirm 1024 x 768 Pixel beträgt, können Sie sich vorstellen, dass Sie die Textur auf der X-Achse 16 Mal kacheln müssen (1024/64). Ebenso müssen Sie es auf der Y-Achse 12 Mal kacheln (768/64). Sie können diese Mathematik an die tatsächlichen Grenzen Ihrer Textur und Ihres Bildschirms anpassen. Verwenden Sie diese Zahlen (16 und 12) als maximale Ausdehnung der Texturkoordinaten Ihres Quad, und Sie erhalten ein viel besseres Ergebnis. Abhängig davon, wie Ihre orthografische Projektion derzeit für die Kacheln eingerichtet ist, müssen Sie sie möglicherweise nicht einmal ändern, um dies zu rendern.

Alternativ können Sie einen Shader-Ansatz wählen: Rendern Sie Ihre reguläre Szene in eine Textur und rendern Sie diese Textur dann als Vollbild-Quad, lassen Sie jedoch jede ungerade Pixelzeile weg. Wenn Sie die Grenzen des Bildschirms im Shader kennen, können Sie dies ziemlich einfach tun (dies ist Pseudocode , vage HLSL-artig, sollte aber leicht zu übersetzen sein):

float2    screenSize;
sampler2D textureSampler;
float2    textureCoordinate;

float4 main () { 
   // Interpolation of texture coordinates means that we don't get nice
   // integer boundaries we could take the modulus of.
   float half_y = textureCoordinate.y * screenSize.y * 0.5;
   float delta = round(half_y) - half_y;
   float delta_squared = delta * delta;
   if (delta_squared < 0.1) {
      return texture2D(textureSampler, textureCoordinate);
   } 

   return float4(0,0,0,0);
}

quelle
0

Das Problem bei der Verwendung einer Kamera besteht darin, dass das Bild skaliert wird. Was Sie im Wesentlichen wollen, ist, immer das gleiche Bild in der gleichen Größe (100%) zu zeichnen. Ich gehe davon aus, dass es groß genug ist, um immer den gesamten Bildschirm abzudecken.

Wenn dies der Fall ist, besteht eine Lösung darin, die inverse Transformation der Kamera auf das Bild anzuwenden, so dass es mit einer "pixelgenauen" Größe zeichnet.

Die einfachere Möglichkeit wäre, es selbst zu skalieren. Z.B. Wenn Ihre Kamera auf 75% gezoomt wird, wird Ihr Bild auf 133% skaliert ( 1/0.75).

Asche999
quelle
Sie sagen, dass das Bild groß genug sein muss, um den gesamten Bildschirm abzudecken. Ist es nicht möglich, ein bisschen direkt mit einer kleinen Textur zu füllen?
Alexandre GUIDET
@AlexandreGUIDET Ich bin nicht sicher. Ich verwende eine Textur zum Ein- und Ausblenden und es ist ein 1x1 Pixel, das skaliert ist. Für Scanlines soll es wiederholt werden. Sie sollten prüfen, ob libGDX eine Option dafür hat.
Asche999
@AlexandreGUIDET hast du das versucht?
Asche999
Ich wähle einen anderen Ansatz mit einer anderen Kamera und zeichne den Scanline-Effekt über der Szene. Ich bin noch nicht zufrieden mit dem Ergebnis, da die Szene hinter die Scanlinien zu rutschen scheint. Was denkst du über die Verwendung eines Shaders?
Alexandre GUIDET