Bagaimana dengan sesuatu yang seperti ini?
Jangan menggambar pencahayaan Anda dengan mewarnai sprite ubin Anda. Gambar ubin yang belum menyala ke target render, lalu gambar lampu ubin ke target render kedua, yang mewakili masing-masing sebagai persegi panjang abu-abu yang menutupi area ubin. Untuk membuat adegan terakhir, gunakan shader untuk menggabungkan dua target render, menggelapkan setiap piksel yang pertama sesuai dengan nilai yang kedua.
Ini akan menghasilkan apa yang Anda miliki sekarang. Itu tidak membantu Anda, jadi mari kita ubah sedikit.
Ubah dimensi target render lightmap Anda sehingga setiap ubin diwakili oleh satu piksel , bukan area persegi panjang. Saat menyusun adegan akhir, gunakan status sampler dengan penyaringan linier. Kalau tidak biarkan semuanya tetap sama.
Dengan asumsi Anda telah menulis shader Anda dengan benar, lightmap harus secara efektif "ditingkatkan" selama pengomposisian. Ini akan memberi Anda efek gradien yang bagus secara gratis melalui sampler tekstur perangkat grafis.
Anda mungkin juga dapat memotong shader dan melakukan ini lebih sederhana dengan BlendState 'gelap', tetapi saya harus bereksperimen dengan itu sebelum saya bisa memberi Anda spesifik.
MEMPERBARUI
Saya punya waktu hari ini untuk benar-benar mengejek ini. Jawaban di atas mencerminkan kebiasaan saya menggunakan shader sebagai jawaban pertama saya untuk semuanya, tetapi dalam kasus ini mereka sebenarnya tidak perlu dan penggunaannya akan mempersulit hal-hal.
Seperti yang saya sarankan, Anda dapat mencapai efek yang persis sama menggunakan custom BlendState. Secara khusus, BlendState khusus ini:
BlendState Multiply = new BlendState()
{
AlphaSourceBlend = Blend.DestinationAlpha,
AlphaDestinationBlend = Blend.Zero,
AlphaBlendFunction = BlendFunction.Add,
ColorSourceBlend = Blend.DestinationColor,
ColorDestinationBlend = Blend.Zero,
ColorBlendFunction = BlendFunction.Add
};
Persamaan pencampuran adalah
result = (source * sourceBlendFactor) blendFunction (dest * destBlendFactor)
Jadi dengan BlendState kebiasaan kami, itu menjadi
result = (lightmapColor * destinationColor) + (0)
Yang berarti bahwa sumber warna putih murni (1, 1, 1, 1) akan mempertahankan warna tujuan, sumber warna hitam murni (0, 0, 0, 1) akan menggelapkan warna tujuan menjadi hitam murni, dan naungan abu-abu di antaranya akan menggelapkan warna tujuan dengan jumlah lumayan.
Untuk mempraktikkannya, pertama-tama lakukan apa yang perlu Anda lakukan untuk membuat peta cahaya Anda:
var lightmap = GetLightmapRenderTarget();
Kemudian gambarkan adegan yang tidak terang langsung ke backbuffer seperti biasa:
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);
/* draw the world here */
spriteBatch.End();
Kemudian gambar lightmap menggunakan custom 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();
Ini akan melipatgandakan warna tujuan (ubin yang tidak dinyalakan) dengan warna sumber (lightmap), secara tepat menggelapkan ubin yang tidak diterangi, dan menciptakan efek gradien sebagai akibat dari tekstur lightmap yang ditingkatkan ke ukuran yang diperlukan.