- Ringkasan pengalaman mengimplementasikan sendiri engine game kecil yang mencakup dua game demo sambil mempelajari Vulkan selama 3 bulan
- Berdasarkan pengalaman OpenGL yang sudah ada, kompleksitas Vulkan diatasi secara bertahap, sambil mengimplementasikan fitur inti seperti pemuatan glTF, skinning, dan shadow mapping
- Engine tersebut adalah EDBR (Elias Daler’s Bikeshed Engine), terdiri dari sekitar 19 ribu baris kode dan memanfaatkan teknik grafis modern seperti bindless descriptor, PVP, dan BDA
- Tulisan ini membagikan detail implementasi praktis seperti library penting vk-bootstrap, VMA, volk serta pola pipeline, otomatisasi build shader, dan manajemen sinkronisasi
- Dengan beralih ke Vulkan, penulis memperoleh penghapusan global state, kontrol eksplisit, lingkungan debugging yang lebih baik, dan konsistensi antar-GPU, serta berencana menambahkan render graph, font SDF, dan efek volumetrik
Gambaran umum pembelajaran Vulkan dan pengembangan engine
- Penulis mulai mempelajari pemrograman grafis secara otodidak dan pernah membuat engine 3D dengan OpenGL sekitar satu setengah tahun lalu
- Engine berbasis Vulkan ini cocok untuk game kecil berbasis level, dengan fokus utama pada pembelajaran dan eksperimen, bukan efisiensi
- Pada tahap awal, penulis membuat game 3D sederhana terlebih dahulu lalu memisahkan bagian-bagian yang bisa digunakan ulang menjadi engine
- Salah satu alasan proyek ini bisa selesai dalam 3 bulan adalah karena cakupannya dibatasi sebagai engine untuk tujuan tertentu, bukan engine serbaguna
Jalur belajar pemrograman grafis
- Untuk pemula, disarankan memulai dari OpenGL dengan mempelajari hal-hal seperti menampilkan model bertekstur, pencahayaan Blinn-Phong, dan shadow mapping
- Materi yang direkomendasikan antara lain learnopengl.com, Anton’s OpenGL 4 Tutorials, dan kuliah Thorsten Thormählen
- Penulis juga menekankan pentingnya memahami aljabar linear (vektor, matriks, kuaternion) bersama materi praktik OpenGL 4.6 terbaru
Saran untuk menghindari bike-shedding
- Hindari desain dan abstraksi yang berlebihan yang tidak perlu, dan pertahankan prinsip “implementasikan hanya yang dibutuhkan sekarang”
- Pendekatan “yang penting berfungsi dulu, perbaiki nanti” direkomendasikan
- Menyelesaikan game kecil lebih efisien daripada langsung mencoba membuat engine serbaguna
- Jangan meniru begitu saja kode atau struktur rumit milik orang lain; mulailah dari struktur yang sederhana
Alasan memilih Vulkan
- Untuk game AAA biasanya digunakan DirectX, untuk macOS/iOS digunakan Metal, dan untuk web umumnya WebGPU/WebGL
- Penulis memilih Vulkan karena menyukai open source dan teknologi standar, serta karena sesuai untuk tujuan membuat game 3D desktop berskala kecil
- OpenGL tidak lagi berkembang dan telah dihentikan di macOS
- WebGPU memang lebih ringkas, tetapi masih memiliki keterbatasan seperti stabilitas yang kurang, batasan fitur, serta tidak mendukung bindless dan push constant
Proses belajar Vulkan
- Pada awalnya terasa sesulit “menulis driver grafis sendiri”,
tetapi kemunculan dynamic rendering, vk-bootstrap, dan vkguide membuatnya lebih mudah diakses
- Materi belajar utama:
- vkguide.dev (berfokus pada praktik dari dasar)
- TU Wien Vulkan Lecture Series
- 3D Graphics Rendering Cookbook, Mastering Graphics Programming with Vulkan
- Dalam bulan pertama, penulis sudah menyelesaikan implementasi pemuatan glTF, compute skinning, frustum culling, dan shadow mapping
Struktur engine EDBR dan pemrosesan frame
- Kode engine sekitar 19.000 baris, game 3D sekitar 4.600 baris, dan game platformer 2D sekitar 1.200 baris
- Tahap rendering utama:
- Compute skinning → Cascaded Shadow Mapping (4096×4096) → geometry shading berbasis PBR
- Depth Resolve → Post FX (kabut berbasis kedalaman) → rendering UI
- Semua sistem grafis ditulis ulang khusus untuk Vulkan, tanpa mencampur dengan kode OpenGL lama
Tips praktis pengembangan Vulkan
Library yang direkomendasikan
- vk-bootstrap: menyederhanakan inisialisasi dan konfigurasi swapchain
- Vulkan Memory Allocator (VMA): mengotomatiskan manajemen memori
- volk: menyederhanakan pemuatan fungsi ekstensi
Abstraksi GfxDevice
- Mengelola
VkDevice, VkQueue, VmaAllocator, dan lain-lain dalam satu objek
- Bertanggung jawab atas awal/akhir frame, pembuatan image dan buffer, serta manajemen bindless descriptor
Manajemen shader
- Menggunakan GLSL, dikompilasi lebih dulu ke SPIR-V dengan
glslc pada saat build
- Menggunakan
DEPFILE di CMake agar shader dibangun ulang otomatis saat berubah
Pola pipeline
- Tiap tahap rendering dipisahkan menjadi pipeline per kelas (
init, cleanup, draw)
- Dengan
VK_KHR_dynamic_rendering, render pass dan subpass bisa dihilangkan sehingga struktur tetap sederhana
Programmable Vertex Pulling + Buffer Device Address
- Semua mesh diproses dengan satu struktur Vertex
- Shader mengakses data langsung melalui buffer_reference, sehingga VAO tidak diperlukan
Bindless Descriptor
- Menggunakan array tekstur global (
textures[], samplers[]) untuk sampling berdasarkan ID tekstur
- ID tekstur disimpan di struktur material dan dikirim lewat push constant
Upload data dinamis
- Data dikirim dengan mengganti buffer GPU per frame atau memakai buffer staging CPU
- Struktur frame in-flight dikelola dengan kelas
NBuffer
Pembersihan resource dan sinkronisasi
- Menggunakan fungsi cleanup eksplisit, dikelola manual alih-alih mengandalkan pembersihan otomatis oleh destructor
- Sinkronisasi memori antar-pass dilakukan dengan
vkCmdPipelineBarrier2
- Render Graph direncanakan untuk diimplementasikan di masa depan
Contoh detail implementasi
Rendering sprite
- Dengan bindless texture dan instancing, ribuan sprite dirender sekaligus
- Struktur
SpriteDrawCommand diunggah ke buffer GPU, lalu dipanggil vkCmdDraw(6, N)
- 10 ribu sprite dirender dalam 315μs
Compute skinning
- Compute shader melakukan deformasi vertex berdasarkan matriks tulang dan bobot
- Buffer output dibuat terpisah untuk tiap instance, lalu diproses sama pada tahap rendering berikutnya
Pemisahan game/rendering
- Logika game menggunakan entt ECS, sementara renderer hanya memproses vektor DrawCommand
- Perintah render dibuat lewat pemanggilan
drawMesh dan drawSkinnedMesh
Pemuatan scene dan prefab
- Level disusun di Blender lalu diekspor ke glTF, dan prefab di-spawn otomatis berdasarkan aturan nama node
- Prefab didefinisikan dalam JSON dan mereferensikan glTF eksternal
MSAA, UI, ImGui
- Menerapkan MSAA x8 berbasis forward rendering
- Mengimplementasikan sistem layout otomatis yang terinspirasi dari Roblox UI API
- Menulis backend Vulkan sendiri untuk mengatasi masalah sRGB pada Dear ImGui
Komponen lainnya
- Menggunakan Jolt Physics untuk fisika, entt untuk ECS, OpenAL-soft untuk audio, dan Tracy sebagai profiler
Manfaat beralih ke Vulkan
- Penghapusan global state menghasilkan struktur kode yang lebih eksplisit dan modular
- Validation layer dan debugging dengan RenderDoc memudahkan pelacakan masalah
- Konsistensi yang lebih baik antar-GPU dan OS, dengan perilaku yang lebih dapat diprediksi dibanding OpenGL
- Memberi ruang ekspansi ke bahasa shading baru (slang, shady) dan lainnya
- Abstraksi yang lebih sedikit dan kontrol pipeline yang lebih jelas meningkatkan kemudahan pemeliharaan
Rencana ke depan
- Direncanakan penambahan font SDF, pemuatan gambar paralel dan pembuatan mipmap, Bloom, kabut volumetrik, animation blending, render graph, dan AO
- Mempelajari Vulkan memang sulit, tetapi sangat membantu dalam memahami API grafis modern dan meningkatkan kemampuan merancang engine
Belum ada komentar.