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.