Saya sedang mengerjakan game mirip Megaman di mana saya perlu mengubah warna piksel tertentu saat runtime. Untuk referensi : di Megaman ketika Anda mengubah senjata yang Anda pilih maka palet karakter utama berubah untuk mencerminkan senjata yang dipilih. Tidak semua warna sprite berubah, hanya yang tertentu yang berubah .
Efek semacam ini biasa dan cukup mudah dilakukan pada SEN karena programmer memiliki akses ke palet dan pemetaan logis antara piksel dan indeks palet. Pada perangkat keras modern, ini sedikit lebih menantang karena konsep paletnya tidak sama.
Semua tekstur saya 32-bit dan tidak menggunakan palet.
Ada dua cara yang saya tahu untuk mencapai efek yang saya inginkan, tetapi saya ingin tahu apakah ada cara yang lebih baik untuk mencapai efek ini dengan mudah. Dua opsi yang saya tahu adalah:
- Gunakan shader dan tulis beberapa GLSL untuk melakukan perilaku "swapping palet".
- Jika shader tidak tersedia (katakanlah, karena kartu grafis tidak mendukungnya) maka dimungkinkan untuk mengkloning tekstur "asli" dan menghasilkan versi yang berbeda dengan perubahan warna yang sudah diterapkan sebelumnya.
Idealnya saya ingin menggunakan shader karena tampaknya mudah dan memerlukan sedikit kerja tambahan yang bertentangan dengan metode duplikat-tekstur. Saya khawatir duplikat tekstur hanya untuk mengubah warna di dalamnya membuang-buang VRAM - haruskah saya tidak khawatir tentang itu?
Sunting : Saya akhirnya menggunakan teknik jawaban yang diterima dan inilah shader saya untuk referensi.
uniform sampler2D texture;
uniform sampler2D colorTable;
uniform float paletteIndex;
void main()
{
vec2 pos = gl_TexCoord[0].xy;
vec4 color = texture2D(texture, pos);
vec2 index = vec2(color.r + paletteIndex, 0);
vec4 indexedColor = texture2D(colorTable, index);
gl_FragColor = indexedColor;
}
Kedua tekstur 32-bit, satu tekstur digunakan sebagai tabel pencarian yang mengandung beberapa palet yang semuanya berukuran sama (dalam kasus saya 6 warna). Saya menggunakan saluran merah pixel sumber sebagai indeks ke tabel warna. Ini bekerja seperti pesona untuk mencapai swapping palet seperti Megaman!
Ada 2 cara yang bisa saya pikirkan untuk melakukan ini.
Cara # 1: GL_MODULATE
Anda dapat membuat sprite dalam nuansa abu-abu, dan
GL_MODULATE
tekstur saat digambar dengan satu warna solid.Sebagai contoh,
Ini tidak memungkinkan Anda banyak fleksibilitas namun, pada dasarnya Anda hanya bisa lebih terang dan lebih gelap dari warna yang sama.
Cara # 2:
if
pernyataan (buruk untuk kinerja)Hal lain yang bisa Anda lakukan adalah mewarnai tekstur Anda dengan beberapa nilai kunci yang melibatkan R, G dan B. SO misalnya, warna pertama adalah (1,0,0), warna ke-2 adalah (0,1,0), ke-3 warna adalah (0,0,1).
Anda mendeklarasikan beberapa seragam suka
Kemudian dalam shader, warna pixel terakhir adalah sesuatu seperti
color1
,color2
,color3
, Yang seragam sehingga mereka dapat diatur sebelum berjalan shader (tergantung pada apa yang "baju" Megaman dalam), maka shader hanya melakukan sisanya.Anda juga bisa menggunakan
if
pernyataan jika Anda membutuhkan lebih banyak warna, tetapi Anda harus memastikan pemeriksaan kesetaraan berfungsi dengan benar (tekstur biasanyaR8G8B8
antara 0 dan 255 masing-masing dalam file tekstur, tetapi dalam shader, Anda memiliki rgba float)Cara # 3: Hanya menyimpan gambar berwarna secara berbeda di peta sprite
Ini mungkin cara termudah, jika Anda tidak mencoba menghemat memori
sumber
Saya akan menggunakan shader. Jika Anda tidak ingin menggunakannya (atau tidak bisa) saya akan menggunakan satu tekstur (atau bagian dari tekstur) per warna dan hanya menggunakan putih bersih. Ini akan memungkinkan Anda untuk mewarnai tekstur (misalnya melalui
glColor()
) tanpa Anda harus khawatir tentang membuat tekstur tambahan untuk warna. Anda bahkan dapat menukar warna dalam pelarian tanpa pekerjaan tekstur tambahan.sumber
"Tidak semua warna sprite berubah, hanya yang tertentu yang berubah."
Game lama melakukan trik palet karena hanya itu yang mereka miliki. Saat ini, Anda dapat menggunakan banyak tekstur dan menggabungkannya dengan berbagai cara.
Anda dapat membuat tekstur topeng abu-abu terpisah yang Anda gunakan untuk memutuskan piksel mana yang akan berubah warna. Area putih pada tekstur menerima modifikasi warna penuh, dan area hitam tetap tidak berubah.
Dalam languague shader:
Atau Anda dapat menggunakan fungsi multi-tekstur tetap dengan berbagai mode penggabung tekstur.
Jelas ada banyak cara berbeda yang bisa Anda lakukan tentang ini; Anda dapat menempatkan masker untuk warna berbeda di masing-masing saluran RGB, atau memodulasi warna dengan menggeser warna dalam ruang warna HSV.
Pilihan lain, mungkin lebih sederhana, adalah menggambar sprite menggunakan tekstur terpisah untuk setiap komponen. Satu tekstur untuk rambut, satu untuk baju zirah, satu untuk sepatu bot, dll. Masing-masing warna tintable secara terpisah.
sumber
Pertama-tama ini umumnya disebut sebagai bersepeda (bersepeda palet), sehingga dapat membantu Google-fu Anda.
Ini akan tergantung pada efek apa yang ingin Anda hasilkan dan jika Anda berurusan dengan konten 2D statis atau barang 3D dinamis (yaitu apakah Anda hanya ingin berurusan dengan spites / tekstur, atau membuat adegan 3D secara keseluruhan kemudian menukar pallet itu). Juga jika Anda membatasi diri Anda pada sejumlah warna atau menggunakan warna penuh.
Pendekatan yang lebih lengkap, menggunakan shader, akan benar-benar menghasilkan gambar yang diindeks warna dengan tekstur palet. Buat tekstur tetapi alih-alih memiliki warna, miliki warna yang mewakili indeks untuk dicari kemudian memiliki tekstur warna lain yaitu piring. Misalnya merah bisa menjadi koordinat t tekstur, dan hijau bisa menjadi koordinat s. Gunakan shader untuk melakukan pencarian. Dan menghidupkan / memodifikasi warna tekstur palet itu. Ini akan cukup dekat dengan efek retro tetapi hanya akan berfungsi untuk konten 2D statis seperti sprite atau tekstur. Jika Anda melakukan grafik retro asli maka Anda mungkin dapat menghasilkan sprite warna yang diindeks dan menulis sesuatu untuk mengimpornya dan palet.
Anda juga akan ingin berolahraga jika Anda akan menggunakan palet 'global'. Seperti berapa lama perangkat keras akan bekerja, lebih sedikit memori untuk palet karena Anda hanya perlu satu tetapi lebih sulit untuk menghasilkan karya seni Anda karena Anda harus menyinkronkan palet di semua gambar) atau memberikan setiap gambar itu palet sendiri. Itu akan memberi Anda lebih banyak fleksibilitas tetapi menggunakan lebih banyak memori. Tentu saja Anda bisa melakukan keduanya, juga Anda hanya bisa menggunakan palet untuk hal-hal yang Anda sukai. Juga tentukan sejauh mana Anda tidak ingin membatasi warna Anda, game-game lama akan menggunakan 256 warna misalnya. Jika Anda menggunakan tekstur maka Anda akan mendapatkan jumlah piksel sehingga 256 * 256 akan memberi Anda
Jika Anda hanya ingin efek palsu yang murah, seperti air yang mengalir, Anda bisa membuat tekstur ke-2 yang mengandung topeng abu-abu di area yang ingin Anda modifikasi, kemudian gunakan tekstur yang sudah ditata untuk mengubah rona / saturasi / kecerahan dengan jumlah dalam tekstur topeng abu-abu. Anda bisa menjadi lebih malas dan hanya mengubah rona / kecerahan / saturasi apa pun dalam rentang warna.
Jika Anda memang membutuhkannya dalam 3D penuh, Anda dapat mencoba menghasilkan gambar yang diindeks dengan cepat tetapi akan lambat karena Anda harus mencari palet, Anda juga kemungkinan akan terbatas dalam kisaran warna.
Kalau tidak, Anda bisa memalsukannya di shader, jika warna == bertukar warna, tukar. Itu akan lambat dan hanya akan bekerja dengan sejumlah warna swapping yang terbatas tetapi seharusnya tidak menekankan perangkat keras saat ini, terutama jika Anda hanya berurusan dengan grafis 2D dan Anda selalu dapat menandai sprite yang memiliki swapping warna dan menggunakan shader yang berbeda.
Jika tidak benar-benar memalsukan mereka, buatlah sekelompok tekstur animasi untuk setiap negara bagian.
Berikut ini adalah demo hebat bersepeda palet yang dilakukan dalam HTML5 .
sumber
Saya percaya jika cukup cepat untuk ruang warna [0 ... 1] untuk dibagi menjadi dua:
Dengan cara ini nilai warna antara 0 dan 0,5 dicadangkan untuk nilai warna normal; dan 0,5 - 1,0 dicadangkan untuk nilai "termodulasi", di mana 0,5..1.0 memetakan ke rentang apa pun yang dipilih oleh pengguna.
Hanya resolusi warna yang terpotong dari 256 nilai per piksel hingga 128 nilai.
Mungkin seseorang dapat menggunakan fungsi builtin seperti max (color-0.5f, 0.0f) untuk menghapus ifs sepenuhnya (menukarkannya ke multiplikasi dengan nol atau satu ...).
sumber