Was ist der effizienteste Weg, um Beleuchtung für eine Kachel-basierte Engine in Java zu tun? Würde es einen schwarzen Hintergrund hinter die Kacheln stellen und das Alpha der Kacheln verändern? Oder einen schwarzen Vordergrund setzen und das Alpha davon ändern? Oder irgendetwas anderes?
Dies ist ein Beispiel für die Art der Beleuchtung, die ich möchte:
Es gibt viele Möglichkeiten, dies zu erreichen. Nehmen Sie sich Zeit, bevor Sie Ihre endgültige Entscheidung treffen. Ich werde kurz einige Techniken zusammenfassen, die Sie verwenden könnten, und am Ende Code bereitstellen.
Wenn Sie einen Lichteffekt mit harten Kanten erzeugen möchten (wie Ihr Beispielbild), Einige Ansätze kommen mir in den Sinn:
Ein Problem ist, dass Sie eine Kachel weder heller als zuvor machen (Lichter) noch die Farbe des Lichts ändern können. Beides sind Aspekte, die die Beleuchtung in Spielen normalerweise gut aussehen lassen.
Dieser Ansatz hat die gleiche Wirkung wie der erste, mit dem Vorteil, dass Sie die Überlagerungsfliese jetzt in einer anderen Farbe als schwarz färben können, was sowohl farbige Lichter als auch helle Lichter erlaubt.
Beispiel:
Auch wenn es einfach ist, ein Problem ist, dass dies in der Tat ein sehr ineffizienter Weg ist. (Zwei gerenderte Kacheln pro Kachel, konstantes Nachfärben, viele Renderoperationen usw.)
Wenn ich Ihr Beispiel betrachte, stelle ich mir vor, dass das Licht immer von einer bestimmten Quelle kommt (Zeichen, Fackel, etc.)
Weiches Licht ist jetzt keine große Sache, verwenden Sie einfach mehr Details in der Lichtmaske im Vergleich zu den Fliesen. Wenn Sie nur 15% Alpha in der normalerweise schwarzen Region verwenden, können Sie einen niedrigen Sichteffekt hinzufügen, wenn eine Kachel nicht leuchtet:
Sie können sogar komplexere Beleuchtungsformen (Kegel usw.) einfach durch Ändern des Maskenbildes erreichen.
Bei der Kombination mehrerer Lichtquellen führt dieser Ansatz zu einem Problem: Das Zeichnen von zwei Masken, die sich überschneiden, könnte sich aufheben:
Wir wollen, dass sie ihre Lichter hinzufügen, anstatt sie zu subtrahieren. Vermeiden Sie das Problem:
Dies würde etwas Ähnliches ergeben:
Wenn Sie alle Kacheln in BufferedImage
zuerst rendern,
Ich werde einen Führungscode zur Verfügung stellen, der der zuletzt gezeigten Methode ähnelt (nur Graustufenunterstützung).
Mehrere Lichtmasken für z.B. Eine Fackel und ein Spieler können so kombiniert werden:
%Vor%Die letzte Maske wird mit dieser Methode erstellt und angewendet:
%Vor%Wie bereits erwähnt, ist dies ein primitives Beispiel. Das Implementieren von Farbmischen könnte ein bisschen mehr Arbeit sein.
vielleicht gehst du nicht über die ganze Map, vielleicht ist es genug, wenn du deine Raytrace für eine 20x20-Ansicht einstellst? Hinweis: Sie müssen wirklich entlang der Grenzen des Ansichtsfensters gehen, es ist nicht erforderlich, jeden Punkt zu verfolgen.
Ich füge den Zeilenalgorithmus hinzu, um Ihre Arbeit zu vereinfachen:
%Vor%Ich habe dieses ganze Blitzzeug vor einiger Zeit gemacht, ein * pathfindin fühle mich frei, weitere Fragen zu stellen
Anhang: vielleicht füge ich einfach die kleinen algorithmen für raytracing ^^
hinzuum den Norden zu bekommen & amp; South Border Point benutze einfach dieses Snippet:
%Vor%und die Raytrace funktioniert so:
%Vor%Ich bin jetzt seit ungefähr drei Jahren in der Entwicklung von Indie-Spielen. Die Art und Weise, wie ich dies tun würde, ist zunächst einmal OpenGL, damit Sie alle Vorteile der grafischen Rechenleistung der GPU nutzen können (hoffentlich tun Sie das schon). Angenommen, wir beginnen mit allen Kacheln in einem vollständig beleuchteten VBO. Jetzt gibt es mehrere Möglichkeiten, um zu erreichen, was Sie wollen. Abhängig davon, wie komplex Ihr Beleuchtungssystem ist, können Sie einen anderen Ansatz wählen.
Wenn Ihr Licht rund um den Player ist, unabhängig davon, ob Hindernisse das Licht im wirklichen Leben blockieren würden, könnten Sie sich für einen Beleuchtungsalgorithmus entscheiden, der im Vertex-Shader implementiert ist. Im Vertex-Shader können Sie den Abstand des Eckpunkts zum Player berechnen und eine Funktion anwenden, die definiert, wie helle Objekte in Abhängigkeit von der berechneten Entfernung funktionieren sollen. Verwenden Sie kein Alpha, sondern multiplizieren Sie einfach die Farbe der Textur / Kachel mit dem Lichtwert.
Wenn Sie eine benutzerdefinierte Lightmap verwenden möchten (was wahrscheinlicher ist), würde ich vorschlagen, ein zusätzliches Vertex-Attribut hinzuzufügen, das die Helligkeit der Kachel angibt. Aktualisieren Sie die VBO bei Bedarf. Dieselbe Vorgehensweise gilt hier: Multiplizieren Sie das Pixel der Textur mit dem Lichtwert. Wenn Sie das Licht rekursiv mit der Spielerposition als Startpunkt füllen, aktualisieren Sie den VBO jedes Mal, wenn der Spieler sich bewegt.
Wenn Ihre Lichtkarte davon abhängt, wo das Sonnenlicht auf Ihr Niveau trifft, können Sie zwei Arten von Beleuchtungstechniken kombinieren. Erstellen Sie ein Vertex-Attribut für die Sonnenhelligkeit und ein weiteres Vertex-Attribut für das Licht, das von Lichtpunkten ausgesandt wird (wie eine Fackel, die vom Spieler gehalten wird). Jetzt können Sie diese beiden Werte im Vertex-Shader kombinieren. Angenommen, Ihre Sonne geht auf und geht unter, wie bei Tag und Nacht. Nehmen wir an, die Sonnenhelligkeit ist sun
, was ein Wert zwischen 0 und 1 ist. Dieser Wert kann als Uniform an den Vertex-Shader übergeben werden. Das Scheitelpunktattribut, das die Sonnenhelligkeit darstellt, ist s
, und das Scheitelpunktattribut, das die Sonnenhelligkeit darstellt, ist l
und das für Licht, das von Lichtpunkten emittiert wird, ist flicker
Dann könntest du das gesamte Licht für diese Kachel so berechnen:
Wo %code% (auch eine Vertex-Shader-Uniform) ist eine Art winkender Funktion, die die kleinen Varianten in der Helligkeit Ihrer Lichtpunkte repräsentiert.
Dieser Ansatz macht die Szene dynamisch, ohne ständig VBOs neu erstellen zu müssen. Ich habe diesen Ansatz in einem Proof-of-Concept-Projekt implementiert. Es funktioniert großartig. Sie können sehen, wie es hier aussieht: Ссылка . Beachte wie das Fackellicht im Video um 0:40 flackert. Das geschieht durch das, was ich hier erklärt habe.