Membangun dunia terbuka di browser, bagian 5: Mengatur anggaran untuk elemen visual
Oleh Oleg Sidorkin, CTO dan Co-Founder Cinevva
Baru mengikuti seri ini? Gunakan panduan seri. Panduan tersebut menjelaskan apa itu spike dan menyediakan tautan ke semua bagian.
Di bab inilah ambisi visual bertemu dengan perhitungan.
Kami membagi biaya rendering ke dalam beberapa spike terpisah karena hasil yang digabungkan sulit didiagnosis. Jika Anda mengaktifkan semuanya sekaligus, Anda hanya akan mengetahui bahwa frame berjalan lambat. Anda tidak akan mengetahui fitur mana yang menghabiskan anggaran.
Spike 7 menargetkan kepadatan vegetasi dan biaya animasi. Pendekatannya menggunakan penyebaran saat runtime dari density map 32x32 untuk setiap chunk medan, yang mengisi kumpulan InstancedMesh berukuran besar. Setiap helai rumput dan kelompok semak mendapatkan efek angin di vertex shader yang digerakkan oleh tekstur noise bergulir. Angka utama yang kami pantau bukan jumlah segitiga, melainkan overhead draw call dan throughput vertex pada GPU kelas menengah. Kami menemukan bahwa mengelompokkan instance ke dalam lebih sedikit mesh lebih penting daripada mengurangi jumlah poligon per helai.
Buka Spike 7 di tab baru ↗ · Lihat kode sumber
Spike 8 mendorong kompleksitas material medan. Perpaduan multilapis yang dibobot berdasarkan sudut kemiringan dan ketinggian, proyeksi triplanar opsional untuk permukaan tebing, serta normal map per lapisan. Shader melakukan splatting berbasis kemiringan dengan empat lapisan tekstur, masing-masing membutuhkan satu sampel diffuse dan normal. Itu berarti
Buka Spike 8 di tab baru ↗ · Lihat kode sumber
Spike 9 berfokus pada biaya cascaded shadow map dengan beban medan dan objek yang realistis. CSM dengan tiga cascade menjadi patokan dasar. Kami secara khusus mengujinya dengan posisi matahari bersudut rendah karena pada kondisi itulah tekanan terhadap cascade menjadi paling berat. Cascade terjauh mencakup potongan frustum yang sangat besar, sementara detail bayangan ditentukan oleh kepadatan texel,
Buka Spike 9 di tab baru ↗ · Lihat kode sumber
Bagian tersulit dalam fase ini adalah disiplin produk. Beberapa efek terlihat sangat memukau, tetapi tetap harus dibatasi karena menghabiskan terlalu banyak anggaran frame dibandingkan dengan dampak visualnya.
Aturan kami menjadi sederhana. Sebuah fitur hanya dilanjutkan jika biayanya dapat dijelaskan menggunakan data waktu frame yang terukur.
Kedengarannya jelas. Namun, praktik ini tidak umum dalam siklus pembuatan prototipe cepat ketika semua orang antusias terhadap peningkatan visual berikutnya. Menerapkan aturan ini sejak awal membuat keputusan arsitektur seputar clipmap dan zona volumetrik menjadi jauh lebih jelas di kemudian hari karena kami sudah mengetahui biaya per fitur dari semua hal yang bersaing memperebutkan 16 md yang sama.
Di bagian 6, kami melakukan perubahan arah besar pertama pada arsitektur medan dengan geometry clipmap.
Teknologi yang dirujuk dalam bab ini
InstancedMesh dan vegetasi GPU. InstancedMesh milik Three.js merender N salinan geometri yang sama dengan satu draw call. Untuk vegetasi, density map (32x32 per chunk) mengendalikan penyebaran helai rumput dan kelompok semak saat runtime ke dalam buffer instance. Animasi angin berjalan di vertex shader menggunakan tekstur noise bergulir. Dalam skala besar, ComputeInstanceCulling milik WebGPU menghilangkan instance di luar layar dan di kejauhan sebelum rasterisasi, sedangkan IndirectBatchedMesh mengemas beberapa jenis vegetasi ke dalam satu buffer yang dirender dengan multi-draw indirect. Lihat panduan lanskap kami tentang culling vegetasi GPU.
Pemetaan triplanar. Tekstur standar dengan pemetaan UV akan meregang pada lereng curam karena koordinat UV terkompresi. Pemetaan triplanar memproyeksikan tekstur di sepanjang ketiga sumbu (X, Y, Z) dan memadukannya berdasarkan normal permukaan. Permukaan tebing mendapatkan proyeksi X atau Z (tanpa peregangan), sedangkan tanah datar mendapatkan proyeksi Y. Perpaduannya halus dan otomatis tanpa memerlukan UV unwrapping. Untuk medan PBR, bobot perpaduan yang sama diterapkan pada channel albedo, normal, roughness, dan ambient occlusion. Lihat detail pemetaan triplanar.
Splatting material berbasis kemiringan dan ketinggian. Alih-alih menggunakan splat map yang dilukis manual, material ditetapkan secara prosedural di fragment shader berdasarkan karakteristik medan. Tanah datar pada ketinggian rendah mendapatkan rumput, lereng curam mendapatkan batu, area berketinggian tinggi mendapatkan salju (hanya pada permukaan yang cukup datar agar salju dapat menumpuk), dan area dekat permukaan laut mendapatkan pasir. Transisinya menggunakan smoothstep agar perpaduan tetap halus. Dalam implementasi kami, setiap chunk medan mengevaluasi empat lapisan tekstur dengan sampel diffuse dan normal per lapisan, sehingga menghasilkan delapan pengambilan tekstur per fragmen sebelum pencahayaan. Lihat penetapan material berdasarkan kemiringan dan ketinggian.
Cascaded Shadow Maps (CSM). CSM membagi frustum pandangan kamera menjadi 3–4 rentang jarak (cascade). Setiap cascade merender shadow map dari perspektif matahari dengan resolusi yang disesuaikan dengan jaraknya. Cascade dekat mendapatkan bayangan beresolusi tinggi (contact shadow yang mendetail di bawah pohon dan bangunan), sedangkan cascade jauh mendapatkan resolusi lebih rendah (bayangan pegunungan yang luas). Shader medan mengambil sampel dari semua cascade dan memilih cascade yang sesuai untuk setiap fragmen. Biaya performa: 3–4 cascade pada resolusi 1024x1024 menambahkan sekitar 0,5–1 md untuk rendering shadow map, ditambah sekitar 0,2–0,3 md untuk pengambilan sampel. Lihat bayangan untuk medan.
Bagian 5 dari 12.
Sebelumnya: Bagian 4 - Streaming sebelum medan yang canggih
Berikutnya: Bagian 6 - Clipmap mengubah jalan cerita
Panduan seri: /blog/2026-02-25-open-world-browser-series-guide