Que diriez-vous quelque chose comme ça?
Ne dessinez pas votre éclairage en teintant vos sprites de tuiles. Dessinez vos tuiles non éclairées sur une cible de rendu, puis dessinez les lumières des tuiles sur une deuxième cible de rendu, représentant chacune sous la forme d'un rectangle en niveaux de gris couvrant la zone de la tuile. Pour rendre la scène finale, utilisez un shader pour combiner les deux cibles de rendu, assombrissant chaque pixel du premier en fonction de la valeur de la seconde.
Cela produira exactement ce que vous avez maintenant. Cela ne vous aide pas, alors changeons-le un peu.
Modifiez les dimensions de votre cible de rendu lightmap de sorte que chaque mosaïque soit représentée par un seul pixel , plutôt que par une zone rectangulaire. Lors de la composition de la scène finale, utilisez un état d'échantillonneur avec filtrage linéaire. Sinon, laissez tout le reste inchangé.
En supposant que vous avez correctement écrit votre shader, le lightmap devrait être effectivement "agrandi" pendant la composition. Cela vous donnera un bel effet de dégradé gratuitement via l'échantillonneur de texture du périphérique graphique.
Vous pouvez également couper le shader et le faire plus simplement avec un BlendState `` assombrissant '', mais je devrais l'expérimenter avant de pouvoir vous donner les détails.
MISE À JOUR
J'ai eu un peu de temps aujourd'hui pour me moquer de ça. La réponse ci-dessus reflète mon habitude d'utiliser des shaders comme première réponse à tout, mais dans ce cas, ils ne sont pas réellement nécessaires et leur utilisation complique inutilement les choses.
Comme je l'ai suggéré, vous pouvez obtenir exactement le même effet en utilisant un BlendState personnalisé. Plus précisément, ce BlendState personnalisé:
BlendState Multiply = new BlendState()
{
AlphaSourceBlend = Blend.DestinationAlpha,
AlphaDestinationBlend = Blend.Zero,
AlphaBlendFunction = BlendFunction.Add,
ColorSourceBlend = Blend.DestinationColor,
ColorDestinationBlend = Blend.Zero,
ColorBlendFunction = BlendFunction.Add
};
L'équation de mélange est
result = (source * sourceBlendFactor) blendFunction (dest * destBlendFactor)
Donc, avec notre BlendState personnalisé, cela devient
result = (lightmapColor * destinationColor) + (0)
Ce qui signifie qu'une couleur source de blanc pur (1, 1, 1, 1) conservera la couleur de destination, une couleur source de noir pur (0, 0, 0, 1) assombrira la couleur de destination en noir pur, et tout une nuance de gris entre les deux assombrira la couleur de destination d'une quantité moyenne.
Pour mettre cela en pratique, faites d'abord tout ce que vous devez faire pour créer votre lightmap:
var lightmap = GetLightmapRenderTarget();
Ensuite, dessinez simplement votre scène non éclairée directement dans le backbuffer comme vous le feriez normalement:
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);
/* draw the world here */
spriteBatch.End();
Puis dessinez la lightmap en utilisant le BlendState personnalisé:
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();
Cela multipliera la couleur de destination (tuiles non éclairées) par la couleur source (lightmap), assombrissant les tuiles non éclairées de manière appropriée et créant un effet de dégradé à la suite de la mise à l'échelle de la texture lightmap jusqu'à la taille nécessaire.