Bagaimana cara membuat shader piksel "retro" untuk sprite 2D yang diubah yang mempertahankan kesetiaan piksel?

10

Gambar di bawah ini menunjukkan dua sprite yang diberikan dengan pengambilan sampel titik di atas latar belakang:

masukkan deskripsi gambar di sini

  • Tengkorak kiri tidak memiliki rotasi / penskalaan yang diterapkan padanya, sehingga setiap piksel cocok dengan latar belakang.
  • Tengkorak kanan diputar / diskalakan, dan ini menghasilkan piksel yang lebih besar yang tidak lagi sejajar sumbu .

Bagaimana saya bisa mengembangkan pixel shader yang akan membuat sprite yang diubah di sebelah kanan dengan sumbu sejajar pixel dengan ukuran yang sama dengan sisa adegan?

Ini mungkin terkait dengan bagaimana scaling scaling diimplementasikan dalam game lama seperti Monkey Island, karena itulah efek yang saya coba capai, tetapi dengan rotasi ditambahkan.


Edit

Sesuai saran kaoD, saya mencoba mengatasi masalah ini sebagai proses pasca. Pendekatan termudah adalah melakukan render ke target render yang terpisah terlebih dahulu (downsampled agar sesuai dengan ukuran piksel yang diinginkan) dan kemudian meningkatkannya saat rendering kedua kalinya. Itu memang memenuhi persyaratan saya di atas.

Pertama saya mencoba melakukannya Linear -> Pointdan hasilnya adalah ini:

masukkan deskripsi gambar di sini

Tidak ada distorsi tetapi hasilnya terlihat buram dan kehilangan sebagian besar warna highlight. Menurut pendapat saya itu merusak tampilan retro yang saya butuhkan.

Kedua kalinya saya mencoba Point -> Pointdan hasilnya adalah ini:

masukkan deskripsi gambar di sini

Meskipun distorsi, saya pikir itu mungkin cukup baik untuk kebutuhan saya, meskipun itu terlihat lebih baik sebagai gambar diam daripada bergerak.

Untuk mendemonstrasikan, inilah video efeknya, meskipun YouTube menyaring piksel darinya:

http://youtu.be/hqokk58KFmI

Namun, saya akan membiarkan pertanyaan terbuka selama beberapa hari lagi jika seseorang datang dengan solusi pengambilan sampel yang lebih baik yang mempertahankan tampilan yang tajam sambil mengurangi jumlah distorsi saat bergerak.

David Gouveia
sumber
Itu seharusnya tengkorak ...?
DeadMG
@DeadMG Tengkorak sapi, kurasa?
David Gouveia
Efek yang bagus, terlihat lebih baik daripada yang saya kira kelihatannya (saya mencobanya pada res rendah dan palet, EGA 40x30.) Itu cukup banyak tampilan Anda akan membuat shader postfx Anda sendiri. BTW, saya ragu ada solusi pengambilan sampel yang lebih baik yang menjaga efek sesuai keinginan Anda. NN cukup banyak yang memberikan tampilan yang tajam, pengambilan sampel lain akan mengaburkan gambar akhir (hanya menebak-nebak.)
kaoD
@ KoD Tapi ingat bahwa saya menerapkan dua pass. Lintasan kedua yang menampilkan contoh gambar akan tetap menjadi tetangga terdekat untuk mempertahankan kesan retro. Tapi saya pikir mungkin ada beberapa manfaat dalam mencoba teknik pengambilan sampel yang berbeda untuk lintasan pertama. Saat ini saya sedang mencari Scale2x!
David Gouveia
@ kaoD Nah, saya menyerah. Mengubah parameter shader antara setiap panggilan sprite dengan SpriteBatchmengharuskan saya menggunakan mode Segera, jadi tidak sepadan dengan masalahnya. Saya akan pergi dengan ini :)
David Gouveia

Jawaban:

3

Anda harus menerapkan shader SETELAH sprite Anda telah diputar.

Jika seluruh adegan belum diarsir dan sprite Anda benar-benar pixelated, yang Anda butuhkan adalah semacam filter pasca-FX untuk seluruh adegan Anda. Rata-rata wilayah piksel akan berfungsi baik. Ini bukan apa yang Anda maksudkan (itu akan terlihat agak ragu-ragu saat bergerak / berputar) tetapi mungkin melakukan trik.

Satu-satunya cara untuk menjaga agar retro terlihat jujur ​​dengan apa yang Anda inginkan adalah menggambar rotasi sprite Anda sendiri. Ini tidak ada hubungannya dengan bagaimana penskalaan diterapkan: resolusinya sebenarnya buruk, ngomong-ngomong, apakah Anda mencoba dengan resolusi yang sangat rendah? Mungkin juga melakukan trik dan akan terlihat lebih alami karena, yah, sebenarnya itulah yang menyebabkan efek yang Anda cari. Dan itu murah! Sangat murah! Bahkan itu akan lebih murah daripada yang sudah Anda miliki (eksekusi shader kurang fragmen.)

Efeknya hancur pada gambar sampel Anda karena resolusi Anda tinggi dibandingkan dengan sprite Anda, sehingga memungkinkan Anda melihat piksel nyata di tempat kejadian.

kaoD
sumber
Ya, saya belum menggunakan shader. Ini hanya sprite biasa dengan tekstur resolusi sangat rendah, diberikan dengan standar XNA SpriteBatchdengan pengambilan sampel titik dihidupkan. Tetapi post-fx mungkin benar-benar berhasil. Sebagai permulaan, saya akan mencoba render dengan sampling linier ke target render, dan kemudian render seluruh target render ke backbuffer dengan point sampling.
David Gouveia
@ DavidVouveia jangan lewatkan kesempatan untuk meningkatkan versi resolusi Anda. Jika Anda benar-benar ingin mencapai efek orisinal itu adalah kesempatan terbaik Anda. Jika Anda membutuhkan resolusi tinggi (jika sebagian GFX Anda beresolusi tinggi atau Anda ingin mencocokkan resolusi asli), Anda masih dapat merender ke buffer resolusi rendah di layar dan kemudian mengecatnya dalam framebuffer resolusi tinggi Anda sebagai penuh layar quad dengan penyaringan dimatikan. Ingatlah bahwa Anda harus mencocokkan rasio aspek untuk menghindari piksel persegi panjang, tentu saja.
kaoD
Periksa hasil edit saya :) Saya pikir itu memecahkan sebagian besar masalah, meskipun saya masih penasaran apakah ada solusi pengambilan sampel yang lebih baik yang tetangga terdekat untuk masalah ini. Saya akan membiarkan pertanyaan berjalan lebih lama.
David Gouveia