Bagaimana saya bisa membuat bar kesehatan secara prosedural berbentuk tidak teratur?

35

Masalah bar kesehatan tradisional berbentuk persegi panjang atau berbasis jantung adalah sesuatu yang dipahami dengan baik dan mudah dipecahkan. Tapi apa solusi yang diterima untuk bar kesehatan yang lebih "berbentuk kreatif", seperti maket yang saya buat di bawah ini?

Kesehatan kosong Kesehatan penuh, kesehatan sebagian

Cara yang jelas untuk melakukan ini adalah memiliki sprite "di antara", sehingga gambar ketiga adalah sprite sendiri, bersama dengan banyak transisi lain untuk berbagai tingkat kesehatan. Tapi itu tampaknya benar-benar tidak tepat dan jumlah perantara yang diperlukan untuk menciptakan transisi yang lancar antara kondisi kesehatan akan menjadi besar.

Satu-satunya ide lain yang dapat saya tanyakan adalah untuk melapisi sprite "kesehatan penuh" di atas sprite "kesehatan kosong" dan kumpulan koordinat piksel pra-panggang untuk mewakili setiap centang kesehatan dan kemudian membuatnya buram atau transparan sebagai kesehatan naik atau turun.

Saya bermaksud pertanyaan ini menjadi agnostik bahasa dan platform tetapi jangan ragu untuk memberikan sampel konkret dalam bahasa / perpustakaan / kerangka kerja apa pun jika itu membantu jawabannya.

msd7734
sumber
5
"N̶a̶n̶o̶m̶a̶c̶h̶i̶n̶e̶s̶ Shaders, Nak"
Mukesh Ingham
Saya merasa transisi itu dapat didefinisikan secara matematis, dari sana Anda dapat meminta komputer untuk menghitung koordinat piksel untuk ditampilkan / disembunyikan daripada membuat sebelumnya
Richard Tingle
Bagaimana bar kesehatan berbentuk hati "mudah dipecahkan"?
MooseBoys
1
@ MooseBoys saya berbicara tentang kesehatan berbasis jantung, bukan berbentuk hati. Pikirkan game Legend of Zelda. Maaf karena tidak jelas.
msd7734
@ RichardTingle, ide bagus :)
Jon

Jawaban:

48

Ada cara yang sangat sederhana untuk mencapai hal ini dengan shader, Anda memerlukan tiga * tekstur: bar kesehatan kosong, tekstur dan masker bar kesehatan dengan gradien distribusi kesehatan dengan satu ekstrem (misalnya nilai alfa paling gelap bukan hitam atau paling transparan) di satu ujung dan lainnya di ujung lainnya. Yang terbaik ditunjukkan pada gambar, saya saat ini tidak dapat melakukan menggambar gradien melengkung hanya satu linier - tapi saya yakin artis Anda tidak akan mengalami masalah: masukkan deskripsi gambar di sini Sekarang, dalam sampel shader baik tekstur dan ambang batas nilai topeng, membuang semua piksel yang tidak lebih terang dari ambang input (berdasarkan pada kesehatan% input shader).
Kamu bisagunakan rumus matematika untuk menutupi alih-alih tekstur, tetapi jika Anda melakukannya, Anda masih akan sangat terbatas pada bentuk yang Anda dapat (= yang sederhana) untuk membuat dengan rumus kata - dan menemukan satu itu tidak sepele.
* lihat komentar

keajaiban
sumber
9
Dalam banyak kasus (termasuk contoh OP) menggunakan tekstur terpisah untuk warna berlebihan. Dalam kebanyakan kasus, Anda bisa memetakan kembali gradien topeng abu-abu ke warna yang ditentukan sebagai seragam untuk shader, sementara masih membuang nilai topeng apa pun di bawah ambang tertentu.
bcrist
1
Anda sebenarnya tidak perlu yang paling gelap bukan hitam, Anda bisa menggunakan saluran alpha untuk menyaring piksel yang tidak Anda inginkan.
Jack Aidley
1
@JackAidley yakin itu mungkin, tapi saya ingin solusinya sefleksibel mungkin - di sebagian besar judul AAA Anda tidak memiliki hp "merah" tetapi bertekstur.
wonderra
1
@ Christian titik bagus, saya menganggap menyarankan itu sebagai optimasi. Tetapi saya tidak dapat menggambarnya dengan benar sehingga saya memutuskan untuk membuatnya sesederhana mungkin dan meninggalkan optimasi untuk implementasi.
wonderra
@wondra Untuk banyak kasus termasuk contoh tampilan di OP Anda dapat menggunakan gradien prosedural, atau pencarian warna satu dimensi (dengan level mask sebagai input), daripada tekstur.
Random832
34

Diimplementasikan secara matematis, sebagai pixel shader:

Pada CPU, hitung HealthDirection dan produk titiknya dengan V2 masukkan deskripsi gambar di sini

Pada GPU, hitung arah yang dinormalisasi jauh dari titik tengah untuk setiap piksel. Bandingkan setiap produk titik dengan HealthDirections 'untuk memilih apakah akan menaungi "latar belakang", atau berwarna. masukkan deskripsi gambar di sini

Jika Anda "membalikkan" algoritme ini dan bekerja dari arah lain, Anda bisa "membatalkan-slerp" masing-masing arah piksel kembali ke persentase dan membandingkannya masing-masing dengan HealthPercent, sebagai gantinya. Dengan dihitungnya persentase setiap piksel, mengubah fade dari merah ke hijau pada GPU menjadi sepele.

Gambarlah bilah terlebih dahulu menerapkan algoritma ke quad; warna keluaran antara rangeMin dan rangeMax (bisa dipanggang) dan clip () atau output transparan di mana saja. Selanjutnya, gambar sprite (dimodifikasi) di atasnya, menggunakan alpha. Saya menelusuri bilah Anda di CAD, mengisinya dengan banjir, lalu "magic wanded" bentuk warna solid di Paint untuk menghapusnya. Milik saya terlihat seperti sampah karena mencampur AutoCAD dan Paint, dengan tangan; dengan asumsi Anda mencampur tepi bagian dalam menjadi transparan, milik Anda akan terlihat sempurna .

Perbatasan putih adalah batas quad. Ini dan X merah hanya untuk referensi:

masukkan deskripsi gambar di sini

"Sprite with hole" tidak perlu dirender bersamaan dengan bilah kesehatan. Mereka harus dipasang dan ditarik sekaligus, setelah semua bar kesehatan selesai. Karena algoritme itu mandiri di dalam shader, Anda juga bisa menambahkan instance ke dalamnya dan kemudian, juga menggambar semua healthbars dengan satu kali draw call yang dipasang. Menggambar setiap bilah alat kesehatan di layar harus menerima 2 panggilan DrawInstanced (...) dan menjadi "gila cepat".

Jon
sumber
1
Jika Anda ingin menutupi dengan cara melingkar seperti ini, Anda dapat menerapkannya lebih efisien dengan hanya mengubah segitiga yang Anda plot untuk pudar melingkar.
Jack Aidley
@JackAidley, harap lebih spesifik, karena saya tidak mempertimbangkan masking ini; bilah kemajuan sepenuhnya diberikan, pada tempatnya, hanya pada dua segitiga, tanpa sampel, setelah lintasan pertama. Sprite kebetulan memiliki lubang di dalamnya dan "cantik" semuanya di akhir. (Ini semacam topeng, tetapi bukan sebagai bagian integral dari algoritme?) Terima kasih
Jon
Apa yang Anda lakukan setara dengan menggambar versi topeng yang berwarna bilah berwarna di atas sprite latar belakang yang sudah memiliki warna abu-abu. Karena metode Anda memerlukan shader khusus dan menulis ke setiap piksel Anda berakhir dengan metode yang lebih lambat daripada menggambar hanya bagian yang diinginkan dari bentuk.
Jack Aidley
@JackAidley, tapi tidak ada sprite latar belakang? Pelangi ditarik hanya menggunakan empat posisi dunia float3; tidak ada UV, tidak ada "sprite latar belakang". Juga, Anda khawatir bahwa pixel shader akan macet bekerja pada beberapa paha depan kecil? Juga, RangeMin dan RangeMax klip () sebagian besar fragmen itu, secara instan.
Jon
Anda akan memerlukan sprite latar belakang untuk mendapatkan batas seperti yang ditunjukkan pada gambar asli; jika Anda menghilangkan ini maka, ya, metodenya berbeda.
Jack Aidley