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

Panduan Permulaan untuk Pengekodan Graphics Shaders: Bahagian 2

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
A Beginner's Guide to Coding Graphics Shaders: Part 3

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

ShaderToy, yang kami gunakan dalam tutorial sebelumnya dalam siri ini, sangat baik untuk ujian dan eksperimen yang cepat, tetapi agak terhad. Anda tidak boleh mengawal data yang dihantar kepada shader sebagai contoh, antara lain. Mempunyai persekitaran sendiri di mana anda boleh menjalankan shader bermakna anda boleh melakukan segala macam kesan mewah, dan anda boleh menggunakannya untuk projek anda sendiri!

Kami akan menggunakan Three.js sebagai rangka kerja kami untuk menjalankan shader di pelayar. WebGL adalah API Javascript yang akan membolehkan kami menjadikan shaders; Three.js hanya membuat kerja ini lebih mudah.

Jika anda tidak berminat dalam JavaScript atau platform web, jangan risau: kami tidak akan memfokuskan kepada spesifikasi rendering web (walaupun jika anda ingin mengetahui lebih lanjut mengenai rangka kerja, lihat tutorial ini). Menyediakan shader dalam penyemak imbas adalah cara paling cepat untuk bermula, tetapi menjadi selesa dengan proses ini akan membolehkan anda dengan mudah menetapkan dan menggunakan shaders pada platform apa saja yang anda suka.

Persediaan

Bahagian ini akan membimbing anda melalui menubuhkan shaders di dalam negara. Anda boleh mengikuti tanpa perlu memuat turun apa-apa dengan CodePen yang telah dibina ini:

Anda boleh menanggalkan dan mengeditnya di CodePen.

Hello Three.js!

Three.js adalah rangka kerja JavaScript yang mengurus banyak kod boilingplate untuk WebGL yang kita perlukan untuk menjadikan shader kami. Cara paling mudah untuk bermula ialah menggunakan versi yang dihoskan pada CDN.

Berikut adalah fail HTML yang boleh anda muat turun yang hanya mempunyai adegan Threejs asas.

Cuba simpan fail itu ke cakera, kemudian bukanya dalam penyemak imbas web anda. Anda harus melihat skrin hitam. Itu tidak begitu menarik, jadi mari kita cuba menambah kiub, hanya untuk memastikan semuanya berfungsi.

Untuk membuat kiub, kita perlu menentukan geometri dan bahannya, dan kemudian tambahkannya ke tempat kejadian. Tambah coretan kod ini di bawah tempat ia berkata Tambah kod anda di sini:

Kami tidak akan terperinci dalam semua kod ini, kerana kami lebih berminat dengan bahagian shader. Tetapi jika semua berjalan dengan betul, anda akan melihat kiub hijau di tengah-tengah skrin:

Walaupun kita berada di sana, mari kita membuatnya berputar. Fungsi render berjalan setiap bingkai. Kita boleh mengakses putaran kiub melalui cube.rotation.x (atau .y atau .z). Cuba pertambahan itu, supaya fungsi render anda kelihatan seperti ini:

Cabaran: Bolehkah anda membuatnya berputar sepanjang paksi yang berbeza? Bagaimana pula dengan dua paksi pada masa yang sama?

Kini anda mempunyai segala-galanya yang ditetapkan, mari tambahkan beberapa shaders!

Menambah Shaders

Pada ketika ini, kita boleh mula memikirkan proses melaksanakan shaders. Anda mungkin mendapati diri anda berada dalam situasi yang sama tanpa mengira platform yang anda merancang untuk menggunakan shaders pada: anda mempunyai semua yang ditetapkan, dan anda mempunyai sesuatu yang ditarik pada skrin, kini bagaimana anda mengakses GPU?

Langkah 1: Memuatkan dalam Kod GLSL

Kami menggunakan JavaScript untuk membina adegan ini. Dalam situasi lain, anda mungkin menggunakan C++, atau Lua atau bahasa lain. Shaders, tanpa mengira, ditulis dalam Bahasa Shading yang istimewa. Bahasa teduhan OpenGL adalah GLSL (OpenGL Shading Language). Oleh kerana kami menggunakan WebGL, yang berdasarkan OpenGL, maka GLSL adalah apa yang kami gunakan.

Jadi bagaimana dan di manakah kita menulis kod GLSL kita? Peraturan umum ialah anda ingin memuatkan kod GLSL anda sebagai string rentetan. Anda boleh menghantarnya untuk dihuraikan dan dilaksanakan oleh GPU.

Dalam JavaScript, anda boleh melakukan ini dengan hanya membuang semua kod anda dalam baris dalam pembolehubah seperti:

Ini berfungsi, tetapi sejak JavaScript tidak mempunyai cara untuk membuat strings multiline dengan mudah, ini tidak mudah bagi kami. Kebanyakan orang cenderung menulis kod shader dalam fail teks dan memberikannya lanjutan .glsl atau .frag (pendek untuk shader fragmen), kemudian muatkan fail tersebut.

Ini sah, tetapi kami akan menulis kod shader kami di dalam tag <skrip>  yang baru dan memuatkannya ke dalam JavaScript dari sana, supaya kita dapat menyimpan segala sesuatu dalam satu fail untuk tujuan tutorial ini.

Buat tag <skrip>  baru di dalam HTML yang kelihatan seperti ini:

Kami memberikan ID fragShader supaya kami dapat mengaksesnya kemudian. Kod-shader jenis sebenarnya adalah jenis skrip palsu yang tidak wujud. (Anda boleh memasukkan apa-apa nama di sana dan ia akan berfungsi). Sebabnya kita melakukan ini supaya kod tersebut tidak dapat dilaksanakan, dan tidak dapat dipaparkan dalam HTML.

Sekarang mari kita buang dalam shader yang sangat asas yang hanya kembali putih.

(Komponen vec4 dalam kes ini sesuai dengan nilai rgba, seperti dijelaskan dalam tutorial sebelumnya.)

Akhirnya, kita perlu memuatkan dalam kod ini. Kita boleh melakukan ini dengan garis JavaScript yang mudah yang menemui elemen HTML dan menarik teks dalaman:

Ini harus pergi di bawah kod kiub anda.

Ingat: hanya apa yang dimuatkan sebagai rentetan akan diasingkan sebagai kod GLSL yang sah (iaitu, tidak sah utama () {...}. Selebihnya hanyalah HTML boilerplate.)

Anda boleh menanggalkan dan mengeditnya di CodePen.

Langkah 2: Menerapkan Shader

Kaedah untuk memohon shader mungkin berbeza bergantung kepada platform yang anda gunakan dan bagaimana ia menghubungkan dengan GPU. Ia tidak pernah menjadi langkah rumit, tetapi, pencarian Google sepintas lalu menunjukkan kepada kita cara membuat objek dan menggunakan shader dengan Three.js.

Kita perlu membuat bahan khas, dan memberikannya kod shader kita. Kami akan membuat pesawat sebagai objek shader kami (tetapi kita juga boleh menggunakan kiub). Ini semua yang perlu kita lakukan:

Sekarang, anda perlu melihat skrin putih:

Anda boleh menanggalkan dan mengeditnya di CodePen.


Sekiranya anda mengubah kod dalam shader ke warna lain dan muat semula, anda harus melihat warna baru!

Cabaran: Bolehkah anda menetapkan bahagian skrin untuk merah, dan bahagian lain menjadi biru? (Sekiranya anda terperangkap, langkah seterusnya perlu memberi petunjuk!)

Langkah 3: Menghantar Data

Pada ketika ini, kita boleh melakukan apa sahaja yang kita mahu dengan shader kita, tetapi tidak banyak yang boleh kita lakukan. Kami hanya mempunyai kedudukan pixel terbina dalam gl_FragCoord untuk berfungsi, dan jika anda ingat, itu tidak normal. Kita perlu mempunyai sekurang-kurangnya dimensi skrin.

Untuk menghantar data kepada shader kami, kami perlu menghantarnya sebagai apa yang dipanggil pembolehubah seragam. Untuk melakukan ini, kami membuat objek yang dipanggil seragam dan menambah pemboleh ubah kami kepadanya. Inilah sintaks untuk menghantar resolusi itu:

Setiap pemboleh ubah seragam mesti mempunyai jenis dan nilai. Dalam kes ini, ia adalah vektor 2 dimensi dengan lebar dan ketinggian tetingkap sebagai koordinatnya. Jadual di bawah (diambil dari dokumentasi Three.js) menunjukkan kepada anda semua jenis data yang anda boleh hantar dan pengenal mereka:
Rentetan jenis seragam Jenis GLSL Jenis JavaScript
'i', '1i'
int
Nombor
'f', '1f' terapung
Nombor
'v2'
vec2
THREE.Vector2
'v3'
vec3
THREE.Vector3
'c' vec3
TIGA.Color
'v4' vec4
THREE.Vector4
'm3' mat3
TIGA.Matrix3
'm4' mat4
THREE.Matrix4
't' sampler2D
THREE.Texture
't' samplerCube
THREE.CubeTexture
Untuk benar-benar menghantarnya ke shader, ubah suai instantiator ShaderMaterial untuk menyertakannya, seperti ini:

Kami belum selesai! Sekarang shader kami menerima pembolehubah ini, kita perlu melakukan sesuatu dengannya. Mari buat kecerunan dengan cara yang sama seperti yang kita lakukan dalam tutorial sebelumnya: dengan menormalkan koordinat kami dan menggunakannya untuk mencipta nilai warna kami.

Ubah kod shader anda supaya kelihatan seperti ini:

Dan anda harus melihat kecerunan yang bagus!

Anda boleh menanggalkan dan mengeditnya di CodePen.

Jika anda sedikit kabur tentang bagaimana kami berjaya mencipta kecerunan yang bagus dengan hanya dua baris kod shader, periksa bahagian pertama siri tutorial ini untuk menjalankan logik di sebalik ini.

Cabaran: Bolehkah anda memisahkan skrin ke 4 bahagian yang sama dengan warna yang berbeza? Sesuatu seperti ini:

Langkah 4: Mengemas Kini Data

Adalah baik untuk dapat menghantar data kepada shader kami, tetapi bagaimana jika kami perlu mengemas kini? Sebagai contoh, jika anda membuka contoh sebelumnya dalam tab baru, kemudian mengubah saiz tetingkap, kecerunan tidak dikemas kini, kerana ia masih menggunakan dimensi skrin awal.

Untuk mengemas kini pembolehubah anda, biasanya anda hanya menghantar semula pembolehubah seragam dan ia akan dikemas kini. Dengan Three.js, bagaimanapun, kita hanya perlu mengemaskini objek seragam dalam fungsi render kami-tidak perlu menghantar semula kepada shader.

Jadi inilah ciri-ciri yang kelihatan seperti selepas membuat perubahan itu:

Jika anda membuka CodePen baru dan saiz semula tetingkap, anda akan melihat perubahan warna (walaupun saiz paparan awalnya tetap sama). Ia mudah untuk melihatnya dengan melihat warna di setiap sudut untuk mengesahkan bahawa mereka tidak berubah.

Nota: Menghantar data ke GPU seperti ini biasanya mahal. Menghantar segelintir pemboleh ubah setiap bingkai baik-baik saja, tetapi framerate anda benar-benar boleh melambatkan jika anda menghantar beratus-ratus per bingkai. Ia mungkin tidak terdengar seperti senario yang realistis, tetapi jika anda mempunyai beberapa ratus objek pada skrin, dan semua perlu mempunyai pencahayaan yang diterapkan kepada mereka, contohnya, semua dengan ciri-ciri yang berbeza, maka perkara-perkara dapat dengan cepat dapat dikendalikan. Kami akan mempelajari lebih lanjut mengenai mengoptimumkan shader kami dalam artikel masa depan!

Cabaran: Bolehkah anda membuat warna berubah dari semasa ke semasa? (Jika anda terperangkap, lihat bagaimana kami melakukannya di bahagian pertama siri tutorial ini.)

Langkah 5: Menangani Tekstur

Terlepas dari bagaimana anda memuatkan dalam tekstur anda atau dalam format apa, anda akan menghantarnya ke shader anda dengan cara yang sama di seluruh platform, sebagai pemboleh ubah seragam.

Nota ringkas mengenai memuatkan fail dalam JavaScript: anda boleh memuatkan imej dari URL luaran tanpa banyak masalah (yang kami lakukan di sini) tetapi jika anda mahu memuatkan imej secara tempatan, anda akan menghadapi isu kebenaran, kerana JavaScript tidak boleh, dan tidak boleh, biasanya mengakses fail pada sistem anda. Cara paling mudah untuk mendapatkan sekitar ini adalah untuk memulakan pelayan Python tempatan, yang lebih mudah daripada mungkin bunyi.

Three.js menyediakan kami dengan sedikit fungsi berguna untuk memuatkan imej sebagai tekstur:

Baris pertama hanya perlu ditetapkan sekali. Anda boleh memasukkan mana-mana URL ke imej di sana.

Seterusnya, kami mahu menambahkan tekstur kami kepada objek seragam.

Akhirnya, kami mahu mengisytiharkan pemboleh ubah seragam kami dalam kod shader kami, dan lukiskannya dengan cara yang sama seperti yang kami lakukan dalam tutorial terdahulu, dengan fungsi texture2D:

Dan anda akan melihat beberapa kacang jeli yang lazat, merentang di skrin kami:

Anda boleh menanggalkan dan mengeditnya di CodePen.

(Gambar ini adalah imej ujian standard dalam bidang grafik komputer, diambil dari Institut Pemprosesan Isyarat dan Imej Pemprosesan Imej Universiti California Selatan (dengan itu IPI inisial). Nampaknya sesuai untuk menggunakannya sebagai imej ujian kami semasa belajar tentang shader grafik!)

Cabaran: Bolehkah anda membuat tekstur dari warna penuh ke grayscale dari semasa ke semasa? (Sekali lagi, jika anda terperangkap, kami melakukan ini di bahagian pertama siri ini.)

Langkah Bonus: Menerapkan Shaders ke Objek Lain

Tidak ada yang istimewa mengenai pesawat yang kami buat. Kami boleh menggunakan semua ini ke kiub kami. Malah, kita hanya boleh menukar baris geometri pesawat:

Untuk

Voila, kacang jelly di atas kiub:

Anda boleh menanggalkan dan mengeditnya di CodePen.

Sekarang anda mungkin berfikir, "Terus, itu tidak kelihatan seperti unjuran yang betul tekstur ke kubus!'. Dan anda betul; jika kita melihat kembali kepada shader kita, kita akan melihat bahawa semua yang kita benar-benar lakukan adalah mengatakan 'peta semua piksel imej ini ke skrin". Hakikat bahawa ia berada di kiub hanya bermakna piksel di luar sedang dibuang.

Jika anda mahu menggunakannya supaya kelihatan seperti ia ditarik secara fizikal ke dalam kiub, yang melibatkan banyak mencipta semula enjin 3D (yang terdengar agak bodoh memandangkan kita sudah menggunakan enjin 3D dan kita hanya boleh memintanya lukiskan tekstur ke setiap sisi secara berasingan). Siri tutorial ini adalah lebih lanjut mengenai penggunaan shaders untuk melakukan perkara-perkara yang tidak dapat kami capai, jadi kami tidak akan membincangkan perkara seperti itu. (Udacity mempunyai kursus hebat pada asas-asas grafik 3D, jika anda ingin mengetahui lebih lanjut!)

Langkah seterusnya

Pada ketika ini, anda harus dapat melakukan semua yang kami lakukan di ShaderToy, kecuali sekarang anda mempunyai kebebasan untuk menggunakan apa sahaja tekstur yang anda inginkan pada bentuk apa pun yang anda suka, dan harap pada platform apa saja yang anda pilih.

Dengan kebebasan ini, kita kini boleh melakukan sesuatu seperti memasang sistem pencahayaan, dengan bayang-bayang yang kelihatan dan kelihatan hebat. Inilah bahagian seterusnya yang akan difokuskan, serta petua dan teknik untuk mengoptimumkan shader!

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.