Bagaimana cara membuat lingkaran pemilihan unit bergabung?

16

Saya ingin tahu cara membuat efek ini dari pemilihan lingkaran gabungan. Berikut adalah gambar untuk diilustrasikan:

masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

Pada dasarnya saya mencari efek ini:

masukkan deskripsi gambar di sini

Bagaimana efek gabungan lingkaran dapat dicapai? Saya tidak menemukan penjelasan mengenai efek ini. Saya tahu bahwa untuk memproyeksikan tekstur tersebut saya dapat mengembangkan sistem decal tetapi saya tidak tahu cara membuat efek penggabungan.

Jika memungkinkan, saya mencari solusi murni shader.

Tikar
sumber
Bisakah Anda menjelaskan apa yang Anda maksud dengan "efek gabungan"?
wondra
Tentu saja, jika Anda melihat karakter layar kanan atas, decals tidak saling bersilangan tetapi keduanya di sebelah kiri melewati lingkaran biru mereka dan digabung. Saya menambahkan tangkapan layar baru untuk menunjukkan efeknya.
MaT
Apakah Anda bersikeras solusi shader? Jika tidak, Anda baru saja menyelesaikannya di gambar terakhir Anda.
wondra
Tangkapan layar terakhir hanya menunjukkan efek yang saya targetkan. Hasil akhir akan terlihat seperti tangkapan layar sebelumnya.
MaT
1
Yap, saya setuju, saya pikir mereka membangun secara dinamis lingkaran jala dengan tekstur dan kemudian memotong jala untuk menggabungkannya. Ini juga merupakan solusi yang baik tetapi saya pikir ini lebih terbatas dalam hal efek yang dapat Anda lakukan.
MaT

Jawaban:

8

Ada beberapa trik yang bisa Anda lakukan:

Z-buffer

Setelah Anda memberikan semua objek lain, untuk setiap unit render lingkaran transparan dengan ukuran lebih kecil dengan nilai Z maksimum. Kemudian render lingkaran seleksi decals di tanah. Karena mereka di bawah dalam Z-order, mereka akan dibuang ketika di bawah unit.

Menjadi sepenuhnya transparan berarti bahwa lingkaran hanya dituliskan ke Z-buffer (nilai maks Z). Sekarang ketika Anda membuat decals, mereka diuji terhadap nilai buffer Z, dan jika mereka lulus tes mereka diberikan (yang terjadi hanya di luar lingkaran)

Setensilan

Sama seperti dengan pendekatan sebelumnya, tetapi kali ini menggunakan buffer stensil. Buat lingkaran yang lebih kecil untuk unit dengan beberapa nilai stensil, lalu render decals pilihan. Atur stensil untuk membuang elemen apa pun dengan nilai stensil Anda.

Kromster berkata mendukung Monica
sumber
Teknik Z-Buffer menarik tetapi saya tidak mengerti bagaimana lingkaran transparan pertama dapat memotong decals dasar.
MaT
0

Sebagai contoh, Anda dapat memeriksa di shader render pixel decal jika ada persimpangan dengan decals lain dan membunuh pixel jika demikian. Ini cukup efisien untuk melakukan decals melingkar seperti ini.

JarkkoL
sumber
1
Saya berasumsi Anda telah melewatkan bagian dari jawaban Anda - untuk meneruskan semua lokasi lingkaran dan radius ke shader.
Kromster mengatakan mendukung Monica
@ Krom Jika OP menyatakan minat pada solusi, saya senang untuk memberikan rincian lebih lanjut.
JarkkoL
0

Apakah maksud Anda lingkaran biru di tanah?

Mungkin ada cara yang lebih cerdas untuk melakukan ini, tetapi pertimbangkan solusi saya sebagai contoh bagaimana ini bisa dilakukan. Jadikan lingkaran Anda menjadi tekstur kosong yang terpisah dari ukuran layar. Pada titik ini Anda dapat menggabungkan keduanya, apa pun yang Anda inginkan. Tergantung pada kebutuhan Anda, Anda dapat menulis warna penuh atau hanya informasi bahwa sebuah lingkaran hadir pada piksel yang diberikan. Namun, Anda pasti membutuhkan informasi mendalam untuk setiap piksel yang Anda tulis jika Anda menginginkan efek uji-Z.

Saat Anda merender medan setelah langkah sebelumnya, Anda dapat mencicipi tekstur yang dibuat sebelumnya, menggunakan koordinat layar dalam pixel shader, sebagai UV. Sekarang Anda tahu, bahwa lingkaran seharusnya atau tidak seharusnya diproyeksikan pada piksel medan yang diberikan. Namun, cara ini akan berfungsi seolah-olah uji-Z dinonaktifkan, sehingga medan tidak dapat menyembunyikan lingkaran apa pun. Jika Anda ingin medan menyembunyikan lingkaran di belakangnya, lakukan pengujian mendalam sebelum memadukan lingkaran dengan tekstur medan. Anda dapat menggunakan bias kecil untuk mengaktifkan rendering lingkaran yang hanya sedikit di bawah medan tetapi Anda tetap ingin mereka merendernya.


Sunting: Sekarang untuk mendapatkan efek lingkaran gabungan apa yang perlu Anda lakukan adalah: Ketika merender ke tekstur yang terpisah, Anda perlu memeriksa apakah sudah ada lingkaran yang diberikan di mana Anda mencoba membuat yang baru. (Periksa apakah tekstur memiliki nilai di sana) jika demikian, hapus piksel ini. Ini akan memberikan efek "garis besar" ketika dua atau lebih lingkaran tumpang tindih. Agar ini berfungsi dengan benar, namun Anda harus melakukan tes ini hanya untuk bagian dalam lingkaran, bukan perbatasan. Jadi ketika merender lingkaran, tulis beberapa nilai spesifik ke tekstur output, yang menunjukkan bahwa itu adalah lingkaran di dalamnya. Maka Anda hanya perlu tidak membuat apa pun di lingkaran di dalam dan Anda harus baik.

Sunting2: Untuk contoh merah / hijau sederhana Anda: Sebelum Anda membuat piksel apa pun, periksa apakah piksel ini belum berwarna hijau. Jika ya, jangan render. Ini akan melakukan triknya. Bahkan, saat menulis ke tekstur Anda bahkan dapat menggunakan merah / hijau untuk luar / di dalam lingkaran, dan kemudian saat rendering medan membaca nilai-nilai itu dan mengubahnya menjadi warna yang diinginkan.

Jika jawaban saya terlalu abstrak secara kebetulan, beri tahu saya.

Elvithari
sumber
Saya mendapatkan ide umum tetapi seperti yang Anda katakan, ini sedikit abstrak bagi saya tentang lingkaran gabungan :)
MaT
0

Ada beberapa opsi. Sebagai metode umum, buffer stensil sering kali menjadi sangat berguna di mana gambar tertentu perlu ditutup, seperti garis besar di mana lingkaran tumpang tindih dalam contoh Anda.

Dalam hal ini, saya pikir ini dapat dilakukan dengan mudah tanpa buffer stensil. Anda dapat menggunakan buffer kedalaman untuk menghilangkan garis besar di mana lingkaran tumpang tindih. Idenya adalah bahwa Anda menggambar interior lingkaran menjadi hanya penyangga kedalaman (karena kita tidak ingin melihat interior), dan kemudian menggambar garis besarnya. Dengan cara ini, bagian garis besar yang tumpang tindih dengan lingkaran lain akan dihilangkan dengan uji kedalaman.

Satu-satunya peringatan adalah bahwa Anda harus berhati-hati tentang pertempuran mendalam. Anda dapat menggunakan offset kecil untuk memastikan bahwa garis sebenarnya berada di belakang interior, dan dihilangkan dengan uji kedalaman. Alternatifnya adalah menggunakan glPolygonOffset().

Katakanlah Anda memiliki dua lingkaran yang sejajar dengan bidang xy, dengan pusat di (x1, y1, z) dan (x2, y2, z). Dan Anda memiliki fungsi menggambar ini:

// Draw interior part of circle, shown in green in the schematic in the question.
drawInterior(x, y, z);

// Draw outline of circle, shown in red in the schematic in the question.
drawOutline(x, y, z);

Urutan gambar kemudian terlihat seperti ini, dengan deltamenjadi offset kecil:

glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
drawInterior(x1, y1, z + delta);
drawInterior(x2, y2, z + delta);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
drawOutline(x1, y1, z);
drawOutline(x2, y2, z);

sumber
0

Dari atas kepala saya, jika decals ini digambar sebagai cakram, saya akan menguji setiap lingkaran untuk persimpangan satu sama lain, dan menempatkan titik-titik persimpangan ke dalam array. Kemudian gambarlah busur yang tidak di dalam persimpangan. Ini bukan solusi shader.

melfar
sumber
Ya saya juga memikirkan hal itu :) tetapi seperti yang Anda katakan itu bukan solusi shader dan itu bukan solusi yang sangat umum. Tapi terima kasih
MaT
Deskripsi yang cukup samar
Kromster mengatakan mendukung Monica
0

Anda ingin stensil di sini. Pass pertama Anda membuat lingkaran ke buffer stensil. Lewat kedua menampilkan garis yang terlihat , di mana saja penyangga stensil tidak berubah. Lintasan kedua harus menggunakan geometri yang lebih besar dari lintasan pertama, dalam hal ini, skalar linier sederhana sudah cukup.

Sementara solusi yang saya miliki untuk menggambar garis besar di sini lebih dari yang Anda butuhkan (karena shader mengubah setiap tepi jala menjadi quad penuh), ia mengikuti pendekatan ini: menggambar model asli ke buffer stensil, kemudian merender versi yang lebih besar di mana buffer stensil masih 0.

Draco tidak lagi percaya pada SE
sumber
Terima kasih! Jadi, alih-alih terlebih dahulu menggambar bagian yang terlihat, saya harus mulai dengan merender lingkaran transparan ke stensil. Tapi bagaimana cara membuat lingkaran transparan? Saya tidak bisa membatasi bagian gambar yang akan dimasukkan ke stensil. Ketika saya membuat stensil, semuanya ada di sana, apakah saya benar?
Doodlemeat
Ya, itulah mengapa pass kedua (bagian yang terlihat) diskalakan lebih besar: sehingga batasnya lebih besar dari buffer stensil. Anda hanya perlu menerapkan skalar vertex di pass kedua (lihat-lihat untuk garis besar shader, kebanyakan dari mereka menggunakan skalar sederhana yang saya maksud). Anda juga tidak dapat mengubah buffer stensil jika warnanya transparan. Anda mungkin perlu topeng tekstur kedua dalam kasus ini atau Anda bisa melakukan matematika jarak jauh untuk menentukan lingkaran. Saya perlu beberapa jam dan akses ke Unity untuk memberikan kode apa pun.
Draco18s tidak lagi mempercayai SE
Hmm, bagaimana dengan memiliki gambar hitam / putih hanya untuk menulis ke buffer stensil di pass pertama sehingga hitam menjadi 0 dan putih menjadi 1 di stensil. Apakah itu mungkin?
Doodlemeat
Itulah yang saya maksud dengan topeng tekstur kedua. Saya cukup yakin itu akan berhasil, saya hanya tidak dapat benar-benar memverifikasi tanpa memiliki Unity di depan saya, yang tidak akan saya miliki selama lebih dari 24 jam.
Draco18s tidak lagi mempercayai SE