Saya melihat beberapa pendekatan luas di luar sana untuk melakukan cel shading:
- Duplikasi & pembesaran model dengan membalik normals (bukan pilihan bagi saya)
- Sobel filter / fragmen shader mendekati ke deteksi tepi
- Buffer stensil mendekati deteksi tepi
- Pendekatan shader geometri (atau simpul) yang menghitung normals muka dan tepi
Apakah saya benar dalam mengasumsikan pendekatan geometri-sentris memberikan jumlah kontrol terbesar atas pencahayaan dan ketebalan garis, juga misalnya. untuk medan di mana Anda mungkin melihat garis siluet bukit bergabung secara bertahap menjadi dataran?
Bagaimana jika saya tidak membutuhkan pencahayaan piksel pada permukaan medan saya? (Dan saya mungkin tidak akan seperti saya berencana untuk menggunakan pencahayaan / bayangan berbasis vertex atau texturemap berbasis). Apakah saya kemudian akan lebih baik bertahan dengan pendekatan tipe geometri, atau pergi untuk ruang layar / pendekatan fragmen sebagai gantinya untuk menjaga hal-hal sederhana? Jika demikian, bagaimana saya akan mendapatkan "tinta" dari bukit-bukit dalam siluet mesh, daripada hanya garis besar seluruh mesh (tanpa "tinta" detail di dalam garis besar itu? ( Kontur sugestif AKA , lipatan ).
Terakhir, apakah mungkin untuk meniru dengan murah pendekatan flipped-normals, menggunakan geometri shader? Kekhawatiran saya dengan ini adalah bahwa saya pasti bisa menduplikasi setiap titik tunggal dan skala ini sesuai, tetapi bagaimana saya akan mendekati membalik normal, dan pewarnaan yang berbeda dalam fragmen shader?
Yang saya inginkan - ketebalan garis yang bervariasi dengan garis-garis intrusif di dalam siluet ...
Apa yang tidak saya inginkan ...
EDIT: Penelitian lebih lanjut telah muncul berikut ...
Karena saya memiliki jumlah titik besar di medan, bahkan mempertimbangkan LoD berbasis jarak, tidak membalik-normals atau pendekatan berbasis geometri shader (bahkan dengan pemusnahan frustum) akan menjadi pilihan yang masuk akal karena kompleksitas komputasi belaka yang terlibat dalam duplikasi & penskalaan semua simpul yang diunggah.
Mempertimbangkan bahwa saya tidak memerlukan pencahayaan per-pixel dalam bentuk bayangan warna solid pada permukaan medan, itu juga menjadi kurang bijaksana untuk mempertimbangkan pendekatan berbasis wajah-normal - jika tidak persyaratan untuk pencahayaan permukaan yang benar - karena ini secara alami cukup mahal untuk dihitung. Namun benar bahwa mereka memberikan tingkat kontrol terbaik; misalnya, kemampuan untuk menaungi tepi menggunakan pukulan "artistik": Cantik, tetapi sekali lagi, tidak benar-benar layak untuk lingkungan permainan yang sangat kompleks.
Buffer stensil adalah sesuatu yang saya lebih suka hindari karena saya lebih suka melakukan semua pekerjaan di shader. (Contoh di atas dengan garis merah dilakukan dengan buffer stensil - sekolah tua.)
Ini meninggalkan fragmen shader pendekatan gambar-ruang. Kompleksitas komputasi dikurangi menjadi jumlah fragmen daripada jumlah simpul (dalam kasus saya, ini adalah operasi 10-100x lebih sedikit daripada yang harus saya lakukan dalam geometri shader). Ini membutuhkan lebih dari satu render pass untuk menghasilkan buffer-g (terdiri dari buffer normal dan juga opsional buffer kedalaman) di mana kita dapat menerapkan filter diskontinuitas (mis. Operator Sobel). Diskontinuitas dalam adalah yang memungkinkan kontur dan lipatan sugestif. Saya hanya berdalih dengan pendekatan ini adalah ketidakmampuan untuk memberikan kontrol yang lebih baik atas lebar tepi bertinta, meskipun dengan algoritma yang tepat dalam fragmen shader, saya yakin ini akan mungkin.
Jadi pertanyaannya sekarang menjadi lebih spesifik: Bagaimana tepatnya saya pergi tentang mendapatkan lebar tepi variabel, terutama pada siluet luar, dalam shader fragmen?
sumber
Jawaban:
Saya telah memutuskan untuk menggunakan pendekatan fragmen shader melalui pemfilteran diskontinuitas buffer kedalaman. Alasan untuk ini adalah:
Setelah mengujinya, saya akan mengatakan bahwa dalam proyek mendatang saya akan menggunakan pendekatan berbasis geometri, karena alasan kompleksitas. Alasannya adalah bahwa (seperti yang disarankan dalam komentar), pendekatan fragmen shader untuk deteksi tepi dapat menjadi sangat intensif secara komputasi, khususnya dengan implementasi DoF di mana lingkaran jari-jari kebingungan, dan dengan demikian jumlah sampel per fragmen, bisa sangat tinggi. Untungnya hal ini kurang menjadi perhatian bagi penggaris garis besar.
sumber
Sebenarnya ada solusi umum yang sangat mudah jika Anda dapat menggunakan efek setelah. Yang hebat adalah, tidak masalah seberapa tinggi poli-count Anda. Jadikan peta Kedalaman sebagai skala abu-abu, lalu buat sebuah titik dalam warna garis yang Anda inginkan, ketika kontras antara dua piksel yang berdekatan lebih tinggi dari nilai ambang. Anda dapat membuat titik lebih besar sesuai dengan kontras dan atau tingkat cahaya dari gambar yang Anda buat.
Saya menemukan algoritma toonShader kembali pada tahun 2000/2001, bahkan sebelum pria Prancis itu, yang menciptakan solusi ini. Tambang didasarkan pada geometri bahan aktual. Kemudian pada dasarnya ada dua cara untuk melakukannya: 1. lihat normals, jika normals dua pesawat yang terhubung ke garis menghadap ke arah dan ke arah kamera, render garis itu, Anda kemudian dapat menggunakan kedalaman, pencahayaan dll sebagai isyarat untuk linedepths. 2. Lihatlah geomerty yang diberikan (jadi setelah transformasi perspektif) Ambil setiap garisegegmen, jika simpul dari bidang yang menyambung berada di sisi yang sama dari garisegegmen ini, Anda membuat garis. Anda kemudian dapat melakukan hal yang sama untuk ketebalan garis seperti pada metode 1. 3. Anda bisa membuat kombinasi dari ketiga teknik ini, tetapi saya menyebutkan yang pertama, karena Anda menunjukkan jumlah-poli yang sangat besar.
sumber