Wie wäre es mit so etwas?
Zeichnen Sie nicht Ihre Beleuchtung, indem Sie Ihre Fliesensprites tönen. Zeichnen Sie Ihre nicht beleuchteten Kacheln auf ein Render-Ziel und zeichnen Sie dann die Kachel-Lichter auf ein zweites Render-Ziel, wobei jedes als Graustufen-Rechteck den Bereich der Kachel abdeckt. Verwenden Sie zum Rendern der endgültigen Szene einen Shader, um die beiden Renderziele zu kombinieren, und verdunkeln Sie jedes Pixel des ersten entsprechend dem Wert des zweiten.
Dies wird genau das produzieren, was Sie jetzt haben. Das hilft dir nicht, also lass es uns ein bisschen ändern.
Ändern Sie die Abmessungen Ihres Lightmap-Render-Ziels entsprechend Kachel durch ein einzelnes Pixel und nicht durch einen rechteckigen Bereich dargestellt wird. Verwenden Sie beim Zusammenstellen der endgültigen Szene einen Sampler-Status mit linearer Filterung. Ansonsten alles gleich lassen.
Vorausgesetzt, Sie haben Ihren Shader korrekt geschrieben, sollte die Lightmap beim Compositing effektiv "vergrößert" werden. Dadurch erhalten Sie über den Textur-Sampler des Grafikgeräts kostenlos einen schönen Verlaufseffekt.
Möglicherweise können Sie den Shader auch ausschneiden und dies einfacher mit einem "verdunkelnden" BlendState tun, aber ich muss damit experimentieren, bevor ich Ihnen die Details geben kann.
AKTUALISIEREN
Ich hatte heute einige Zeit, um dies tatsächlich zu verspotten. Die obige Antwort spiegelt meine Gewohnheit wider, Shader als erste Antwort auf alles zu verwenden, aber in diesem Fall sind sie eigentlich nicht notwendig und ihre Verwendung erschwert die Dinge unnötig.
Wie ich bereits angedeutet habe, können Sie mit einem benutzerdefinierten BlendState genau denselben Effekt erzielen. Speziell dieser benutzerdefinierte BlendState:
BlendState Multiply = new BlendState()
{
AlphaSourceBlend = Blend.DestinationAlpha,
AlphaDestinationBlend = Blend.Zero,
AlphaBlendFunction = BlendFunction.Add,
ColorSourceBlend = Blend.DestinationColor,
ColorDestinationBlend = Blend.Zero,
ColorBlendFunction = BlendFunction.Add
};
Die Mischungsgleichung lautet
result = (source * sourceBlendFactor) blendFunction (dest * destBlendFactor)
So wird das mit unserem benutzerdefinierten BlendState
result = (lightmapColor * destinationColor) + (0)
Dies bedeutet, dass eine Quellfarbe in reinem Weiß (1, 1, 1, 1) die Zielfarbe beibehält, eine Quellfarbe in reinem Schwarz (0, 0, 0, 1) die Zielfarbe zu reinem Schwarz verdunkelt und alle dazwischen liegender Grauton verdunkelt die Zielfarbe um einen mittleren Betrag.
Um dies in die Praxis umzusetzen, müssen Sie zunächst alle erforderlichen Schritte ausführen, um Ihre Lightmap zu erstellen:
var lightmap = GetLightmapRenderTarget();
Dann ziehen Sie Ihre unbeleuchtete Szene einfach wie gewohnt direkt in den Backbuffer:
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);
/* draw the world here */
spriteBatch.End();
Dann zeichne die Lightmap mit dem benutzerdefinierten BlendState:
var offsetX = 0; // you'll need to set these values to whatever offset is necessary
var offsetY = 0; // to align the lightmap with the map tiles currently being drawn
var width = lightmapWidthInTiles * tileWidth;
var height = lightmapHeightInTiles * tileHeight;
spriteBatch.Begin(SpriteSortMode.Immediate, Multiply);
spriteBatch.Draw(lightmap, new Rectangle(offsetX, offsetY, width, height), Color.White);
spriteBatch.End();
Dadurch wird die Zielfarbe (nicht beleuchtete Kacheln) mit der Quellfarbe (Lightmap) multipliziert, und nicht beleuchtete Kacheln werden entsprechend abgedunkelt. Dadurch wird ein Verlaufseffekt erzeugt, da die Lightmap-Textur auf die erforderliche Größe skaliert wird.
Okay, hier ist eine sehr einfache Methode, um einen einfachen und gleichmäßigen 2D-Blitz zu erstellen, der in drei Durchgängen gerendert wird:
In Pass 1 zeichnest du alle Sprites und das Terrain.
In Durchgang 2 zeichnen Sie eine zweite Gruppe von Sprites, die die Lichtquellen sind. Sie sollten ungefähr so aussehen:
Initialisieren Sie das Render-Ziel mit Schwarz und zeichnen Sie diese Sprites mit Maximum oder Additiv-Überblendung darauf.
In Durchgang 3 kombinieren Sie die beiden vorherigen Durchgänge. Es gibt verschiedene Möglichkeiten, wie sie kombiniert werden können. Die einfachste und am wenigsten künstlerische Methode besteht darin, sie über Multiplizieren zu mischen. Das würde so aussehen:
quelle
Der zweite Link, den Sie gepostet haben, sieht aus wie eine Art Nebel des Krieges. Dazu gibt es noch ein paar andere Fragen
Das sieht für mich wie eine Textur aus , bei der Sie Bits der schwarzen Überlagerung "löschen" (indem Sie das Alpha dieser Pixel auf 0 setzen), wenn der Player vorwärts geht.
Ich würde sagen, die Person muss einen Pinsel vom Typ "Löschen" verwendet haben, den der Spieler erkundet hat.
quelle
Leichte Eckpunkte (Ecken zwischen Kacheln) anstelle von Kacheln. Mischen Sie die Beleuchtung über jede Kachel anhand ihrer vier Eckpunkte.
Führen Sie jeweils Sichtprüfungen durch Scheitelpunkt durch, um festzustellen, wie beleuchtet er ist (Sie können entweder festlegen, dass ein Block das gesamte Licht anhält oder das Licht verringert, z reiner binärer sichtbarer / nicht sichtbarer Test).
Senden Sie beim Rendern einer Kachel den Lichtwert für jeden Scheitelpunkt an die GPU. Mit einem Fragment-Shader können Sie problemlos den interpolierten Lichtwert für jedes Fragment im Sprite der Kachel verwenden, um jedes Pixel gleichmäßig zu beleuchten. Es ist schon lange genug her, dass ich GLSL angerührt habe, um ein echtes Codebeispiel zu geben, aber in Pseudocode wäre es so einfach wie:
Der Vertex-Shader muss lediglich die Eingabewerte an den Fragment-Shader weitergeben, was auch nur annähernd kompliziert ist.
Sie erhalten eine noch gleichmäßigere Beleuchtung mit mehr Scheitelpunkten (z. B. wenn jede Kachel als vier Unterkacheln gerendert wird), aber das lohnt sich möglicherweise nicht, abhängig von der Qualität, die Sie anstreben. Versuchen Sie es zuerst auf einfachere Weise.
quelle
line-of sight tests to each vertex
? Das wird teuer.