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.
Oke di sini adalah salah satu metode yang sangat sederhana untuk membuat beberapa petir 2D sederhana dan halus, render dalam tiga lintasan:
Dalam lulus 1 Anda menggambar semua sprite dan medan.
Dalam lulus 2 Anda menggambar kelompok sprite kedua yang merupakan sumber cahaya. Mereka harus terlihat mirip dengan ini:
Inisialisasi target render dengan warna hitam dan gambar sprite ke atasnya dengan pencampuran Maksimum atau Aditif.
Dalam pass 3 Anda menggabungkan dua pass sebelumnya. Ada beberapa cara berbeda bagaimana mereka dapat digabungkan. Tetapi metode paling sederhana dan paling berseni adalah untuk menggabungkan mereka melalui Multiply Ini akan terlihat seperti ini:
sumber
Tautan kedua yang Anda poskan tampak seperti kabut perang , ada beberapa pertanyaan lain tentang ini
Bagi saya itu terlihat seperti tekstur , di mana Anda "menghapus" bit overlay hitam (dengan mengatur alpha dari piksel tersebut ke 0) saat pemain bergerak maju.
Saya akan mengatakan orang itu harus menggunakan jenis sikat "hapus" di mana pemain telah dieksplorasi.
sumber
Vertikal ringan (sudut antara ubin) bukan ubin. Padukan pencahayaan di setiap ubin berdasarkan empat simpulnya.
Lakukan tes garis pandang ke setiap titik untuk menentukan seberapa terang itu (Anda bisa memiliki blok menghentikan semua cahaya atau mengurangi cahaya, misalnya menghitung berapa banyak persimpangan ke setiap titik dikombinasikan dengan jarak untuk menghitung nilai cahaya daripada menggunakan uji biner murni terlihat / tidak terlihat).
Saat merender ubin, kirim nilai lampu untuk setiap simpul ke GPU. Anda dapat dengan mudah menggunakan shader fragmen untuk mengambil nilai cahaya interpolasi pada setiap fragmen dalam sprite ubin untuk menerangi setiap piksel dengan lancar. Sudah cukup lama sejak saya menyentuh GLSL sehingga saya tidak akan merasa nyaman memberikan sampel kode yang nyata, tetapi dalam kode pseudo akan sesederhana:
Vertex shader hanya perlu meneruskan nilai input ke shader fragmen, tidak ada yang rumit bahkan jauh.
Anda bahkan akan mendapatkan pencahayaan yang lebih halus dengan lebih banyak simpul (katakanlah, jika setiap ubin diberikan sebagai empat sub-ubin), tetapi itu mungkin tidak sepadan dengan usaha tergantung pada kualitas yang Anda inginkan. Cobalah dulu dengan cara yang lebih sederhana.
sumber
line-of sight tests to each vertex
? Itu akan mahal.