Alat dan teknik pilihan untuk pengembangan game prosedural
(cprimozic.net)- Seiring membesarnya proyek scene dan level 3D yang berjalan di browser, terkumpul alat-alat reusable yang menerapkan teknik prosedural dan generatif pada elemen tertentu dalam level, alih-alih membangkitkan seluruh dunia
- Fokus pekerjaan tekstur adalah Triplanar Mapping dan Hex Tiling, yang digunakan untuk menerapkan tekstur tanpa UV atau menyembunyikan pola berulang
- Kedua teknik menerapkan
pow()pada bobot interpolasi untuk memperbesar porsi sumbu dominan atau hasil lookup, serta mengurangi beban performa dengan melewati sebagian lookup tekstur - Fragment shader yang mahal dapat diringankan dengan Depth Pre-Pass, dan pada scene dengan banyak overdraw performa bisa meningkat lebih dari 30%
- Di sisi mesh dan geometri, ada arah untuk memperluas ekspresi dekorasi, latar, dan kerusakan melalui LoD terrain, pipeline pemrosesan mesh runtime, serta ke depannya Constructive Solid Geometry
Alat-alat prosedural yang terkumpul dari scene 3D di browser
- Selama beberapa tahun membuat 3D scenes and levels yang berjalan di browser, demo independen yang berpusat pada shader kustom berkembang menjadi bentuk seperti game yang saling terhubung
- Pendekatan umumnya adalah menerapkan teknik prosedural dan generatif pada bagian tertentu dari level, bukan membuat dunia prosedural sepenuhnya
- Alat dan efek prosedural maupun semi-prosedural yang berulang kali digunakan di berbagai level pun terkumpul secara alami
Shader dan tekstur
- Sebagian besar tekstur adalah seamless texture yang dapat di-tile tanpa putus pada dua sumbu, dan jika dibentangkan di area luas pola berulangnya bisa terlihat jelas
- Berbagai fitur ditambahkan ke shader kustom yang memperluas
MeshPhysicalMaterialmilik Three.JS untuk meningkatkan dukungan seamless texturing -
Triplanar Mapping
- Triplanar Mapping adalah alat teksturing inti yang digunakan di hampir semua level
- Teknik ini memungkinkan mesh diberi tekstur dengan seamless texture tanpa UV map yang sudah ditentukan sebelumnya, sehingga berguna pada kasus seperti terrain prosedural ketika modeler tidak punya kesempatan mendefinisikan UV mapping
- Bekerja dengan baik untuk mesh yang dihasilkan maupun mesh yang dimodelkan secara manual
- Implementasinya ringan dan sederhana, dan implementasi referensi tersedia di triplanarMapping.ts
-
Peningkatan Triplanar Mapping
- Triplanar Mapping biasa melakukan linear blending terhadap lookup tekstur dari tiga sumbu berdasarkan normal fragmen
- Pada area tempat normal tidak mendekati satu sumbu tunggal, tekstur bisa terlihat seperti berlapis-lapis
- Jika
pow()dengan eksponen tinggi diterapkan pada bobot lalu dinormalisasi ulang, porsi sumbu dominan menjadi lebih besar dan area transisi mengecil - Transformasi ini membuat bobot satu sumbu mendekati 1 pada sebagian besar mesh, sementara bobot dua sumbu lainnya mendekati 0
- Dengan melewati lookup tekstur untuk bobot yang lebih kecil dari ambang batas, beban performa Triplanar Mapping dapat ditekan hingga hanya sedikit lebih besar daripada teksturing berbasis UV biasa
- Pemrosesan normal map perlu dipertimbangkan secara terpisah dalam kode shader, dan menggunakan metode GPU Gems
- Detail implementasi dapat dilihat di Normal Mapping for a Triplanar Shader
-
Hex Tiling
- Hex Tiling adalah algoritme untuk menyembunyikan tiling dan pengulangan yang mencolok pada seamless texture
- Hanya dengan menambahkan satu opsi pengaturan pada material, sebuah scene bisa berubah dari terlihat seperti mockup berkualitas rendah menjadi mendekati semi-realistis
- Implementasi awal berbasis Shadertoy karya Fabrice Neyret, lalu dikonversi agar sesuai dengan material system Three.JS dan diintegrasikan ke shader material utama proyek
- Setelah mendapat izin, implementasi ini kemudian di-port menjadi library independen three-hex-tiling yang dapat menambahkan Hex Tiling ke built-in material proyek Three.JS
- Tidak seperti Triplanar Mapping, teknik ini membutuhkan UV mapping yang sudah ditentukan sebelumnya
- Jika kedua teknik digunakan bersama, jumlah texture fetch maksimum per fragmen untuk setiap map bisa meningkat hingga 27, sehingga tidak praktis
- Hex Tiling juga melakukan interpolasi linear terhadap tiga hasil lookup pada tiap fragmen, sehingga teknik bobot
pow()yang digunakan pada Triplanar Mapping dapat meningkatkan performa sekaligus kualitas hasil
-
Depth Pre-Pass
- Teknik teksturing canggih dapat menghasilkan fragment shader yang mahal pada scene besar
- Depth Pre-Pass adalah cara merender seluruh scene terlebih dahulu dengan material yang sangat sederhana dan murah untuk mencatat depth tiap piksel
- Meski ada overhead karena scene dirender dua kali, pada scene dengan banyak overdraw manfaatnya umumnya lebih besar daripada biayanya
- Jika overdraw tinggi, penambahan Depth Pre-Pass dapat meningkatkan performa lebih dari 30%
- Dengan mengubah pengaturan pre-pass, hanya occluded fragment yang dapat dirender untuk memvisualisasikan fragmen yang akan dilewati saat memakai pre-pass
- Detail implementasi dan pengaturan Three.JS dapat dilihat di dedicated article
-
Sintesis tekstur PBR berbasis AI
- AI-generated texture digunakan di hampir semua scene
- Jika digunakan secara hemat, hasilnya bisa terlihat cukup bagus, dan semua tekstur pada scene contoh adalah AI-generated
- Proses pembuatan tekstur, pembuatan PBR map, serta penggabungannya menjadi seamless 4K texture tanpa upscaling dibahas dalam artikel terpisah
- Situs web yang disebutkan dalam artikel tersebut untuk membuat PBR map sudah tidak dapat digunakan lagi
- Saat ini DeepBump digunakan untuk membuat normal map, dan jika diperlukan, tool non-AI seperti Materialize digunakan untuk map lain
-
Volumetric Fog/Clouds
- Volumetric rendering adalah bidang yang menarik perhatian karena dapat memberi efek unik pada scene
- Dibuat shader yang relatif serbaguna untuk menambahkan cloud atau fog ke scene Three.JS mana pun
- Terinspirasi dari Shadertoy karya Inigo Quilez, dibuat shader volumetric clouds dasar yang menggunakan lookup LoD noise serupa, lalu kemudian diperluas menjadi bentuk yang lebih umum dan dapat dikonfigurasi
- Shader ini berguna untuk mengisi ruang kosong pada level yang jarang, serta menambahkan kesan dinamis pada level statis melalui cloud atau fog yang bergerak
- Sebagian kode dan pendekatan yang dikembangkan n8programs di proyek
three-good-godraysjuga digunakan three-good-godraysjuga sering digunakan, dan menambahkan suasana yang sangat khas pada level
Mesh dan geometri
- Pembuatan mesh saat runtime adalah area yang semakin banyak dikerjakan
- Ada ketertarikan pada ide dunia yang tumbuh dari seed perangkat lunak, tetapi juga upaya menghindari fenomena “tak terbatas tetapi kosong” pada sebagian game yang mengusung procedural generation
- Karena itu, fokus utamanya bukan membangkitkan seluruh pengalaman inti secara prosedural, melainkan menambahkan dekorasi, latar, dan procedural flourish ke level
-
LoD Terrain
- Terrain generation adalah bidang representatif dalam pengembangan game prosedural, dan implementasinya sendiri tidak istimewa
- Seperti kebanyakan pendekatan, terrain heightmap dibuat dengan noise function, lalu di-tessellate menjadi triangle untuk dirender
- Untuk teksturing digunakan Triplanar Mapping atau Hex Tiling
- Intinya adalah sistem LoD, yang membuat terrain dalam satuan tile dan menghasilkan tiap tile dalam beberapa resolusi
- Resolusi yang berbeda diganti secara dinamis sesuai jarak antara tile dan camera
- Terrain generation system ini sering digunakan kembali, dan berkat sistem yang fleksibel serta efisien, dapat diterapkan ke berbagai level dengan sedikit usaha
-
Pipeline pemrosesan dan manipulasi mesh prosedural
- Bagian yang paling banyak dikerjakan belakangan ini adalah pipeline procedural mesh processing
- Tujuan awalnya adalah melakukan subdivide dan deform mesh low-poly secara prosedural, termasuk mesh yang dihasilkan secara dinamis
- Tujuannya agar mesh sederhana seperti platform, boulder, dan struktur besar terlihat lebih realistis atau menarik saat ditempatkan di level
- Pekerjaan ini berujung pada pipeline perangkat lunak di runtime browser yang menerima raw geometry data, memodifikasinya secara arbitrer, lalu mengekspornya kembali ke format yang dapat dirender
- Proses ini membutuhkan pertimbangan detail, terutama dalam pemrosesan normal
- Detail implementasi ada di artikel subdividing meshes for displacement
Kandidat eksperimen berikutnya: Constructive Solid Geometry
- Sebagian besar alat yang tercantum di sini awalnya dimulai sebagai implementasi sekali pakai untuk kasus penggunaan tertentu, tetapi kemudian berulang kali digunakan kembali di level dan konteks lain
- Ide utama yang ingin dicoba berikutnya adalah Constructive Solid Geometry
- Constructive Solid Geometry adalah sistem yang menerapkan boolean operator pada ruang 3D
- Dua mesh arbitrer dapat digabungkan
- Chunk dapat dipotong dari sebuah mesh
- Manipulasi serupa lainnya dapat dilakukan
- csg.js mengimplementasikan CSG toolkit yang mencakup mesh primitive, boolean operator, dan API yang rapi dalam satu file JavaScript berkomentar sepanjang sekitar 500 LoC
- Suatu saat library ini rencananya akan di-port ke Rust sambil memahami cara kerjanya dengan lebih baik
- Menggunakan CSG bersama pipeline mesh processing yang sudah ada berpotensi menghasilkan hal-hal menarik
- Secara khusus, ada keinginan untuk mencoba fitur merusak mesh secara prosedural
- Memotong chunk dari building atau bridge untuk mensimulasikan decay atau weathering
- Membuat crack pada wall atau road
1 komentar
Komentar Hacker News
Dulu saya sempat mencoba-coba procedural generation, terutama untuk membuat pohon yang terlihat bagus, tetapi bagian yang hilang bagi saya adalah cara menghubungkan geometri dengan mudah.
Membuat dua silinder itu mudah, tetapi menyambungkan keduanya secara alami sangat sulit.
Secara teori, CSG bisa mengisi celah ini, tetapi cara memikirkan masalah seperti itu tidak mudah. Sebab, ini tidak bisa dilihat sekadar sebagai loop yang menambahkan vertex; semuanya harus dimodelkan sebagai bentuk 3D.
Saya juga pernah membuat routine yang menerima dua loop vertex lalu menambahkan face secara heuristik untuk menghubungkannya, tetapi memilih vertex mana yang harus dihubungkan ternyata jauh lebih sulit dari perkiraan, dan sambungan yang tampak jelek mudah sekali muncul.
Suatu hari saya ingin membuat game di mana berbagai sistem procedural generation modular yang berbeda bisa bekerja sama sambil tetap mempertahankan improvisasi. Misalnya, sistem-sistem itu “menempati” sebagian dunia, lalu mendelegasikan bagian tersebut ke sistem lain, atau menyambungkannya secara alami dengan elemen di sekitarnya.
Baru-baru ini ada video [0] tentang membuat pohon generatif, dan solusinya ternyata hanya membiarkan silinder-silinder saling beririsan. Cara hacky seperti ini juga bisa bekerja dengan baik dan hasilnya bisa cukup bagus.
Seperti yang disebutkan, CSG juga memungkinkan, tetapi bisa terlalu rumit. Cara lain adalah membuat skeleton pohon lalu melakukan lofting, dan jika perlu menggabungkannya dengan CSG untuk membuat batang dan kulit kayu.
Library yang bagus membuka banyak kemungkinan. Jika menemukan library geometri 3D yang menyediakan operasi boolean seperti penggabungan silinder atau pengurangan geometri, Anda bisa mencoba banyak ide baru. Saya sudah mencoba beberapa, tetapi satu-satunya yang lumayan saya sukai adalah JSCAD [1].
[0] https://youtu.be/8zMbJmuwEUc?si=KQclrVPeSrIRmsbA
[1] https://github.com/jscad/OpenJSCAD.org
Pendekatannya mirip dengan mendeskripsikan dan mentransformasikan bentuk 3D secara fungsional.
Untuk melihat apa yang pernah dibuat orang-orang di demoscene dengan teknik ini, saya sangat merekomendasikan mencari Mercury Delight di YouTube. Di Shadertoy juga ada banyak contoh, dan banyak yang benar-benar menakjubkan.
https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Condition...
Contoh di bawah ini juga layak dilihat.
https://github.com/MaxBondABE/batteries/blob/master/src/geom...
Terrain generation yang bagus sama sekali tidak sepele, baik pada skala dunia maupun skala setinggi mata.
Pendekatan sederhana, seperti yang terlihat di artikel, menghasilkan heightmap yang bergelombang, hampir tidak mirip dengan medan nyata, dan juga tidak terlalu menarik untuk dieksplorasi.
Misalnya, Dwarf Fortress memang dimulai dari midpoint displacement dasar, tetapi setelah itu melewati banyak post-processing khusus.
Dari hal-hal yang dibahas di artikel ini, tidak ada yang bahkan secara samar bisa dibilang sepele. Penulisnya, setidaknya dalam rendering shader GPU, jelas mendekati developer 100x dibandingkan hampir semua orang di Bumi.
“Pendekatan sederhana”, benarkah sederhana?
Dari 8 miliar orang, berapa persen yang bahkan bisa mengimplementasikan tahap “Hello World” yang diperlukan untuk memulai artikel ini? Berapa banyak pula yang tahu apa itu shader? Pekerjaan OpenGL juga tidak sebanyak itu. Situasi seperti “OpenGL itu apa, kami cuma pakai Unity” juga umum.
Bagaimana dengan gamer online? Pada 28 Juli 2024 pukul 13.22 EST, dari 1.021.282 orang [1] yang sedang terhubung ke Counter Strike 2, berapa persen yang bisa mengimplementasikan bahkan tahap pertama shader yang dibutuhkan oleh game yang mereka mainkan?
Berapa persen yang bisa mengompilasi program C++ command-line sederhana, atau menulis skrip JavaScript yang lebih sederhana di browser? Sebenarnya ini sedikit pertanyaan jebakan, karena kebanyakan orang bahkan kesulitan menangani email.
[1] https://steamdb.info/app/730/charts/
Sama seperti AI, procedural content generation terbaik pun pada hasil akhirnya akan melibatkan post-processing khusus.
Ini artikel yang sangat membantu karena merangkum dengan baik berbagai teknik prosedural yang dipakai di web.
Jika tertarik dengan editor level RPG prosedural yang sedang saya kerjakan, silakan lihat https://github.com/gamedevgrunt/3D-Action-RPG-JavaScript.
Pengalaman saya memakai depth pre-pass campur aduk.
Dalam beberapa percobaan, saya tidak melihat peningkatan performa yang mencolok pada GPU desktop kelas menengah hingga atas.
Saya tidak tahu alasan pastinya, tetapi mungkin karena early Z rejection sudah mengurangi pemanggilan pixel shader. Biasanya mesh opak dirender dari depan ke belakang.
Namun, eksperimen saya berada dalam konteks aplikasi CAD/CAM, bukan game. Adegan-adegannya juga cukup berbeda dari lingkungan game umum: teksturnya sedikit dan geometrinya memiliki jumlah poligon yang sangat besar.
Depth pre-pass sering kali juga menjadi tahap pertama occlusion culling, tetapi ini pun sama-sama bergantung pada situasi. Kemungkinan jauh lebih berguna pada lanskap kota yang kompleks daripada pada model CAD.
Ini paling berguna ketika depth complexity tinggi dan fragment shader mahal. Agar adil, sebagian besar game memang masuk kategori ini.
Pada deferred renderer biasanya tidak wajib, tetapi pada forward+ umumnya cukup menguntungkan.