Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Game Development
  2. Shaders
Gamedevelopment

Panduan Pemula untuk Coding Graphics Shaders

by
Difficulty:IntermediateLength:LongLanguages:
This post is part of a series called A Beginner's Guide to Coding Graphics Shaders.
A Beginner's Guide to Coding Graphics Shaders: Part 2

Malay (Melayu) translation by Seurion (you can also view the original English article)

Belajar untuk menulis grafik shader adalah belajar untuk memanfaatkan kuasa GPU, dengan beribu-ribu inti yang semuanya berjalan secara selari. Ia adalah sejenis pengaturcaraan yang memerlukan minda yang berbeza, tetapi membuka peluangnya adalah masalah awal.

Hampir setiap simulasi grafik moden yang anda lihat dihidupkan dalam beberapa cara dengan kod yang ditulis untuk GPU, dari kesan pencahayaan yang realistik dalam permainan AAA canggih ke 2D selepas pemprosesan kesan dan simulasi cecair.

Satu adegan di Minecraft, sebelum dan selepas memohon beberapa shaders.

Matlamat Panduan ini

Pengaturcaraan Shader kadangkala bermula sebagai sihir hitam yang misterius dan sering disalahpahami. Terdapat banyak contoh kod di luar sana yang menunjukkan kepada anda bagaimana untuk membuat kesan yang luar biasa, tetapi menawarkan penjelasan sedikit atau tidak. Panduan ini bertujuan untuk merapatkan jurang itu. Saya akan memberi tumpuan lebih kepada asas-asas penulisan dan pemahaman kod shader, jadi anda boleh tweak, menggabungkan, atau menulis sendiri dari awal!

Ini adalah panduan umum, jadi apa yang anda pelajari di sini akan digunakan untuk apa-apa yang boleh menjalankan shader.

Jadi Apa itu Shader?

Shader hanyalah program yang berjalan dalam saluran paip grafik dan memberitahu komputer bagaimana untuk menjadikan setiap piksel. Program ini dipanggil shaders kerana mereka sering digunakan untuk mengawal pencahayaan dan kesan teduhan, tetapi tidak ada sebab mereka tidak dapat mengendalikan kesan istimewa lain.

Shaders ditulis dalam bahasa teduhan khas. Jangan risau, anda tidak perlu keluar dan belajar bahasa yang sama sekali baru; kami akan menggunakan GLSL (OpenGL Shading Language) yang merupakan bahasa seperti-C. (Terdapat banyak bahasa teduhan di luar sana untuk platform yang berbeza, tetapi kerana mereka semua disesuaikan untuk berjalan di GPU, mereka semua sangat serupa)

Mari Jump!

Kami akan menggunakan ShaderToy untuk tutorial ini. Ini membolehkan anda memulakan pemrograman shaders tepat di dalam penyemak imbas anda, tanpa kerumitan untuk menetapkan sesuatu! (Ia menggunakan WebGL untuk membuat rendering, jadi anda memerlukan pelayar yang boleh menyokongnya.) Membuat akaun adalah pilihan, tetapi berguna untuk menyimpan kod anda.

Nota: ShaderToy berada dalam versi beta pada masa menulis artikel ini. Sesetengah butiran UI/sintaks kecil mungkin sedikit berbeza.

Apabila mengklik New Shader, anda sepatutnya melihat sesuatu seperti ini:

Antara muka anda mungkin kelihatan sedikit berbeza jika anda tidak log masuk.

Anak panah hitam kecil di bahagian bawah adalah apa yang anda klik untuk menyusun kod anda.

Apa yang sedang berlaku?

Saya akan menjelaskan bagaimana shaders bekerja dalam satu ayat. Adakah anda bersedia? Di sini!

Satu tujuan shader adalah untuk mengembalikan empat nombor: r, g, b, dan a.

Itulah yang pernah dilakukan atau boleh dilakukan. Fungsi yang anda lihat di hadapan anda berjalan untuk setiap piksel pada skrin. Ia mengembalikan nilai empat warna tersebut, dan itu menjadi warna piksel thie. Inilah yang dipanggil Pixel Shader (kadang-kadang dirujuk sebagai Fragment Shader).

Dengan itu, mari kita cuba menjadikan skrin merah padat. Rgba (merah, hijau, biru, dan 'alpha', yang mentakrifkan ketelusan) pergi dari 0 ke 1, jadi semua yang perlu kita lakukan ialah pulangan r, g, b, a = 1,0,0,1. ShaderToy menjangka warna pixel akhir disimpan di fragColor.

Selamat Ini adalah shader kerja anda yang pertama!

Cabaran: Bolehkah anda menukarnya ke warna kelabu yang padat?

vec4 hanya jenis data, jadi kami boleh mengisytiharkan warna kami sebagai pemboleh ubah, seperti:

Ini tidak begitu menarik, walaupun. Kami mempunyai kuasa untuk menjalankan kod pada beratus-ratus ribu piksel selari dan kami menetapkan mereka semua dengan warna yang sama.

Mari cuba buat kecerunan merentasi skrin. Nah, kita tidak boleh berbuat banyak tanpa mengetahui beberapa perkara mengenai piksel yang kita hadapi, seperti lokasinya di skrin ...

Input Shader

Shader piksel melewati beberapa pembolehubah untuk digunakan. Yang paling berguna kepada kami ialah fragCoord, yang memegang koordinat x dan y pixel (dan z, jika anda bekerja dalam 3D). Mari cuba putar semua piksel pada separuh kiri skrin hitam, dan semua yang di sebelah kanan separuh merah:

Nota: Untuk sebarang vec4, anda boleh mengakses komponennya melalui obj.x, obj.y, obj.z dan obj.w atau melalui obj.r, obj.g, obj.b, obj.a. Mereka bersamaan; ia hanya cara mudah menamakan mereka untuk membuat kod anda lebih mudah dibaca, supaya apabila orang lain melihat obj.r, mereka memahami bahawa obj mewakili warna.

Adakah anda melihat masalah dengan kod di atas? Cuba klik pada butang skrin penuh di bahagian bawah kanan tetingkap pratonton anda.

Perkadaran skrin yang berwarna merah akan berbeza bergantung pada saiz skrin. Untuk memastikan bahawa separuh daripada skrin adalah merah, kita perlu tahu berapa besar skrin kita. Saiz skrin bukan pembolehubah yang dibina seperti lokasi piksel, kerana ia biasanya terpulang kepada anda, pengaturcara yang membina aplikasinya, untuk menetapkannya. Dalam kes ini, pemaju ShaderToy yang menetapkan saiz skrin.

Jika sesuatu tidak dibina dalam pembolehubah, anda boleh menghantar maklumat tersebut dari CPU (program utama anda) ke GPU (shader anda). ShaderToy mengendalikannya untuk kami. Anda boleh melihat semua pembolehubah yang diluluskan kepada shader dalam tab Input Shader. Pemboleh ubah yang diluluskan dengan cara ini dari CPU ke GPU dipanggil seragam dalam GLSL.

Mari tweak kod kami di atas untuk mendapatkan pusat skrin dengan betul. Kita perlu menggunakan input shader iResolution:

Sekiranya anda cuba membesarkan tetingkap pratonton kali ini, warna-warna masih sepatutnya memisahkan skrin dengan separuh.

Dari Split ke Kecerunan

Mengubah ini menjadi kecerunan haruslah mudah. Nilai warna kami pergi dari 0 ke 1, dan koordinat kami sekarang pergi dari 0 ke 1 juga.

Dan voila!

Cabaran: Bolehkah anda mengubah ini menjadi kecerunan menegak? Bagaimana pula dengan pepenjuru? Bagaimana pula dengan kecerunan dengan lebih daripada satu warna?

Jika anda bermain dengan cukup ini, anda boleh memberitahu bahawa sudut kiri atas mempunyai koordinat (0,1), bukan (0,0). Ini penting untuk diingat.

Lukisan Imej

Bermain-main dengan warna-warna yang menyeronokkan, tetapi jika kita mahu melakukan sesuatu yang mengagumkan, shader kita harus dapat mengambil input dari imej dan mengubahnya. Dengan cara ini, kita boleh membuat shader yang mempengaruhi skrin keseluruhan permainan kami (seperti kesan cairan bawah air atau pembetulan warna) atau hanya mempengaruhi objek tertentu dengan cara tertentu berdasarkan input (seperti sistem pencahayaan yang realistik).

Sekiranya kami memprogramkan pada platform biasa, kami perlu menghantar gambar kami (atau tekstur) kepada GPU sebagai pakaian seragam, dengan cara yang sama anda akan menghantar resolusi skrin. ShaderToy mengurusnya untuk kami. Terdapat empat saluran masukan di bahagian bawah:

Empat saluran input ShaderToy.

Klik pada iChannel0 dan pilih sebarang tekstur (imej) yang anda suka.

Sebaik sahaja itu selesai, anda kini mempunyai imej yang dihantar kepada shader anda. Terdapat satu masalah, bagaimanapun: tidak ada fungsi DrawImage(). Ingat, satu-satunya perkara yang boleh dilakukan oleh piksel shader ialah menukar warna setiap piksel.

Jadi jika kita hanya boleh memulangkan warna, bagaimana kita menarik tekstur kita pada skrin? Kita perlu entah bagaimana memetakan piksel semasa shader kita dihidupkan, ke pixel yang sama pada tekstur:

Ingat, piksel kiri atas di skrin kami ialah (0,1) manakala piksel kiri atas tekstur adalah (0,0), jadi kita perlu flip paksi-y.

Kita boleh melakukan ini dengan menggunakan texture2D (tekstur, koordinat) fungsi, yang mengambil tekstur dan pasangan koordinat (x, y) sebagai input, dan mengembalikan warna tekstur pada koordinat tersebut sebagai vec4.

Anda boleh memadankan koordinat ke skrin dengan cara yang anda suka. Anda boleh melukis keseluruhan tekstur pada seperempat skrin (dengan melangkau piksel, memancarkannya secara berkesan) atau hanya menarik sebahagian daripada teksturnya.

Untuk tujuan kami, kami hanya mahu melihat imej, jadi kami akan sepadan dengan piksel 1: 1:

Dengan itu, kami mendapat imej pertama kami!

Sekarang bahawa anda betul menarik data dari tekstur, anda boleh memanipulasinya tetapi anda suka! Anda boleh meregangkan dan membuatnya, atau bermain-main dengan warna.

Mari cuba ubah suai ini dengan kecerunan, sama seperti yang kita lakukan di atas:

Tahniah, anda baru sahaja membuat kesan pemprosesan pertama anda!

Cabaran: Bolehkah anda menulis shader yang akan menjadikan imej hitam dan putih?

Ambil perhatian bahawa walaupun ia adalah imej statik, apa yang anda lihat di hadapan anda sedang berlaku dalam masa nyata. Anda dapat melihat ini untuk diri sendiri dengan menggantikan imej statik dengan video: klik pada input iChannel0 sekali lagi dan pilih salah satu video.

Menambah Pergerakan Beberapa

Sejauh ini semua kesan kami telah statik. Kita boleh melakukan perkara yang lebih menarik dengan menggunakan input yang ShaderToy memberi kita. iGlobalTime adalah pemboleh ubah yang sentiasa meningkat; kita boleh menggunakannya sebagai benih untuk membuat kesan berkala. Mari kita cuba bermain dengan warna sedikit:

Terdapat fungsi sinus dan kosinus yang dibina ke dalam GLSL, serta banyak fungsi berguna lain, seperti mendapatkan panjang vektor atau jarak antara dua vektor. Warna tidak sepatutnya negatif, jadi kami pastikan kami mendapat nilai mutlak dengan menggunakan fungsi abs.

Cabaran: Bolehkah anda membuat shader yang mengubah imej berulang-alik dari hitam dan putih ke warna penuh?

Nota mengenai Shaders Debugging

Walaupun anda mungkin digunakan untuk melangkah kod anda dan mencetak nilai-nilai segala-galanya untuk melihat apa yang sedang berlaku, itu tidak mungkin berlaku ketika menulis shaders. Anda mungkin mendapati beberapa alat debug yang khusus untuk platform anda, tetapi secara umumnya, pertaruhan terbaik anda adalah untuk menetapkan nilai yang anda uji kepada sesuatu grafik yang anda dapat lihat.

Kesimpulan

Ini hanya asas untuk bekerja dengan shaders, tetapi dengan selesa dengan asas-asas ini akan membolehkan anda melakukan lebih banyak lagi. Semak imbas kesan pada ShaderToy dan lihat jika anda dapat memahami atau meniru sesetengahnya!

Satu perkara yang saya tidak sebut dalam tutorial ini ialah Vertex Shaders. Mereka masih ditulis dalam bahasa yang sama, kecuali mereka berjalan di setiap puncaknya bukannya setiap piksel, dan mereka mengembalikan kedudukan serta warna. Vertex Shaders biasanya bertanggungjawab untuk memperlihatkan adegan 3D ke skrin (sesuatu yang terbina dalam paip grafik yang paling). Shaders Pixel bertanggungjawab untuk banyak kesan canggih yang kita lihat, oleh itu itulah sebabnya fokus kami.

Cabaran akhir: Bolehkah anda menulis shader yang menghilangkan skrin hijau dalam video pada ShaderToy dan menambah video lain sebagai latar belakang yang pertama?

Itu sahaja untuk panduan ini! Saya sangat menghargai maklum balas dan pertanyaan anda. Sekiranya ada sesuatu yang anda ingin ketahui lebih lanjut, sila tinggalkan komen. Panduan masa depan boleh termasuk topik seperti asas-asas sistem pencahayaan, atau cara membuat simulasi cecair, atau menubuhkan shader untuk platform tertentu.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.