Skip to content

Membangun dunia terbuka di browser, bagian 10: Kekacauan sambungan dan pertarungan bos di sudut

Oleh Oleg Sidorkin, CTO dan Salah Satu Pendiri Cinevva

Baru mengikuti seri ini? Gunakan panduan seri. Panduan tersebut menjelaskan apa itu spike dan memuat tautan ke semua bagian.

Jika bagian-bagian sebelumnya terasa sistematis, bab ini terasa seperti pertempuran.

Spike 17 hingga 22 adalah era kasus ekstrem kami. Marching cubes LOD ganda, sambungan batas antara heightmap dan MC, chunk sudut beresolusi campuran tempat tiga atau empat tingkat LOD bertemu, pembuatan sambungan di GPU, serta perilaku mode fallback. Setiap spike menangani skenario kegagalan tertentu yang telah kami temui atau perkirakan.

Spike 17 menguji marching cubes ganda dengan dua tingkat LOD yang aktif secara bersamaan. Tantangannya adalah tetangga sebuah chunk dapat memiliki resolusi berbeda pada sisi-sisi yang berbeda. Logika sel transisi dari Spike 16 berfungsi untuk satu sisi dalam satu waktu, tetapi ketika sebuah chunk memerlukan sel transisi pada beberapa sisi, pengelolaan buffer vertex menjadi rumit. Sel transisi setiap sisi harus dibuat dan ditambahkan tanpa menimpa sel dari sisi lainnya.

Buka Spike 19 di tab baru ↗ · Lihat kode sumber

Musuh pertama yang terus muncul adalah urutan winding. Beberapa kali kami mengira ada masalah topologi, tetapi ternyata masalahnya ada pada orientasi. Backface culling menghilangkan segitiga sambungan yang valid karena winding-nya terbalik terhadap mesh utama. Akar masalahnya sama, tetapi gejala visualnya berbeda-beda tergantung sudut kamera. Perbaikannya adalah menerapkan konvensi winding yang konsisten dalam kode emisi sel transisi dan memverifikasinya dengan pengalih material dua sisi.

Musuh kedua adalah rasa percaya diri palsu akibat hasil yang hanya benar sebagian. Sebuah sambungan bisa terlihat sempurna dari satu sudut kamera, lalu rusak ketika peran LOD bertukar antara chunk beresolusi lebih tinggi dan lebih rendah. Sel transisi bersifat asimetris. Sel tersebut mengambil sampel dari sisi beresolusi tinggi dan sisi beresolusi rendah dengan cara yang berbeda. Jika logika “sisi mana yang beresolusi tinggi” terbalik untuk satu konfigurasi, bug hanya akan terlihat ketika kamera bergerak ke posisi tertentu.

Lalu terjadilah salah satu pemulihan favorit kami. Kami sedang memburu artefak sambungan yang terpotong pada tile heightmap dan menyalahkan logika transisi. Dua hari habis untuk itu. Penyebab sebenarnya adalah overdraw usang. Geometri beresolusi lebih tinggi dari frame sebelumnya masih tertinggal di bagian akhir buffer setelah chunk diturunkan ke LOD yang lebih rendah. Rentang gambar masih menggunakan jumlah vertex lama yang lebih besar. Begitu kami membatasi rentang gambar ke jumlah vertex aktif yang dilaporkan oleh penghitung atomik milik compute shader, “masalah sambungan misterius” itu menghilang.

Itu menjadi pengingat yang sangat baik bahwa bug rendering sering menyamar sebagai bug pembuatan mesh. Geometrinya sebenarnya sudah benar sejak awal. Draw call hanya membaca melewati akhir data yang valid.

Pada Spike 22, kami menguji fallback hibrida yang memungkinkan chunk beralih dari marching cubes ke mode heightmap dalam kondisi tertentu, misalnya ketika chunk tidak memiliki edit volumetrik dan berada cukup jauh dari kamera. Ini memberi kami pendekatan yang lebih praktis daripada kebijakan serba-atau-tidak-sama-sekali. Chunk dekat kamera yang telah diedit menggunakan MC demi kebebasan volumetrik. Chunk jauh yang belum diedit menggunakan heightmap demi efisiensi.

Buka Spike 22 di tab baru ↗ · Lihat kode sumber

Bab ini adalah turunan curam dalam wahana roller coaster. Menjengkelkan sekaligus produktif. Banyak perbaikannya berukuran kecil, terkadang hanya satu baris yang mengubah operator perbandingan atau offset. Namun, pemahaman yang dihasilkannya tentang interaksi antara transisi LOD, pengelolaan buffer, dan rentang gambar sama sekali tidak kecil.

Di bagian 11, kami membahas lapisan stabilisasi yang muncul setelah kekacauan ini: mode chunk berbasis kebijakan dan peralihan dari perbaikan bug secara reaktif menuju aturan sistem yang eksplisit.

Teknologi yang dibahas dalam bab ini

Marching cubes LOD ganda. Menjalankan marching cubes pada dua tingkat resolusi secara bersamaan, dengan sel transisi yang menyatukan batasnya. Tantangannya adalah tetangga sebuah chunk dapat memiliki resolusi berbeda pada sisi-sisi yang berbeda, sehingga setiap sisi memerlukan pembuatan sel transisi secara independen. Sel transisi dari setiap sisi ditambahkan ke buffer vertex tanpa menimpa sel dari sisi lainnya. Penghitung atomik melacak jumlah total vertex aktif di seluruh sisi.

Urutan winding. Urutan vertex dalam setiap segitiga menentukan sisi mana yang menjadi permukaan “depan”. Winding yang konsisten—biasanya berlawanan arah jarum jam jika dilihat dari luar—diperlukan untuk backface culling. Ketika sel transisi menghasilkan segitiga, winding-nya harus mengikuti konvensi mesh utama. Jika terbalik, backface culling akan menghilangkan segitiga sambungan yang valid, sehingga dari sudut kamera tertentu terlihat seperti ada permukaan yang hilang. Teknik debugging yang umum adalah mengaktifkan side: THREE.DoubleSide pada material untuk memastikan apakah artefak tersebut disebabkan oleh masalah winding atau celah topologi yang sebenarnya.

Fallback dari heightmap ke MC. Mode chunk hibrida tempat chunk yang jauh atau belum diedit menggunakan medan heightmap—murah dan berupa permukaan datar—sedangkan chunk yang dekat atau telah diedit menggunakan marching cubes—bersifat volumetrik dan mendukung gua. Keputusan fallback bergantung pada jarak dari kamera dan apakah chunk memuat edit SDF. Sambungan antara chunk heightmap dan chunk MC memerlukan geometri transisinya sendiri, mirip dengan Transvoxel, tetapi menjembatani dua representasi berbeda alih-alih dua tingkat LOD. Lihat heightmap hibrida + overlay volumetrik.

Rentang gambar dan penghitung atomik. Dalam pembuatan mesh berbasis GPU, compute shader menulis vertex ke dalam buffer dan menaikkan penghitung atomik untuk melacak jumlah vertex yang dihasilkan. Draw call harus menggunakan penghitung ini sebagai jumlah vertex, bukan kapasitas buffer. Jika rentang gambar tidak dibatasi ke jumlah aktif, vertex usang dari frame sebelumnya—yang masih tertinggal di bagian akhir buffer—akan menghasilkan geometri hantu: serpihan tipis dan segitiga berkedip yang tampak seperti kesalahan topologi, tetapi sebenarnya merupakan artefak rendering akibat pembacaan yang melewati data valid.


Bagian 10 dari 12.
Sebelumnya: Bagian 9 - Transvoxel dimulai dengan sebuah kerangka
Berikutnya: Bagian 11 - Mode berbasis kebijakan, bukan mode yang di-hardcode
Panduan seri: /blog/2026-02-25-open-world-browser-series-guide