Skip to content

Tarayıcıda açık dünya oluşturmak, bölüm 7: Marching cubes ve ilk gerçek mağaralar

Yazan: Oleg Sidorkin, Cinevva CTO'su ve Kurucu Ortağı

Burada yeni misiniz? Seri rehberine göz atın. Bu rehber, spike'ın ne olduğunu açıklar ve tüm bölümlere bağlantı verir.

Yükseklik haritaları, çıkıntılara ihtiyaç duyana kadar harikadır.

Oyulmuş tüneller, havada uzanan kaya çıkıntıları veya mağara tavanları istediğiniz anda, yalnızca yükseklik alanına dayanan bir işlem hattı sizi kısıtlamaya başlar. Bir yükseklik haritası, her XZ koordinatı için tek bir Y değeri saklar. Kendi üzerine kıvrılan herhangi bir yüzeyi temsil etmesi fiziksel olarak mümkün değildir. Hacimsel bir temsile ihtiyacımız vardı.

Spike 12, WebGPU compute shader'larını kullanarak GPU üzerinde marching cubes uyguladı. Algoritma, 3B bir ızgara üzerinde işaretli uzaklık alanını (SDF) değerlendirir ve sıfır geçişi yüzeyinde bir üçgen ağı çıkarır. Her hücrenin 8 köşesi vardır ve her köşe yüzeyin ya içinde ya da dışındadır; bu da 28=256 olası işaret örüntüsü verir. Bir arama tablosu, her örüntüyü bir üçgen kümesiyle eşler. Köşe noktaları, alanın sıfırı kestiği noktada hücre kenarları üzerinde yer alır. Alan değerleri fa ve fb olan a ve b köşeleri arasındaki bir kenar için doğrusal enterpolasyon, köşe noktasını şu konuma yerleştirir:

v=pa+t(pbpa),t=fafbfa

Burada t, alanın sıfıra ulaştığı kenar üzerindeki oranı ifade eder. Kesişen bir kenarda fa ve fb zıt işaretlere sahip olduğundan, t her zaman [0,1] aralığında kalır. Bunu aynı anda dört etkin 64 küplük chunk üzerinde çalıştırdık ve kare başına yeniden mesh oluşturma ile animasyonlu SDF düzenlemelerini test ettik.

Spike 12'yi yeni bir sekmede açın ↗ · Kaynak kodunu görüntüleyin

İlk kazanım, compute işlem hattının kendisine duyduğumuz güvendi. Tek bir dispatch çağrısı; CPU'ya hiçbir veri geri okumadan SDF'yi değerlendirebiliyor, hücreleri sınıflandırabiliyor ve köşe noktalarını bir GPU tamponuna yazabiliyordu. İkinci kazanım ise “çalışıyor” aşamasından görsel bozulma avına ne kadar hızlı geçildiğini keşfetmekti. Eksik üçgenler nadiren marching cubes kuramıyla ilgili bir sorundan kaynaklanıyordu. Genellikle tablo indeksi uyuşmazlıkları, etkin köşe noktası sayısının ötesini okuyan hatalı çizim aralıkları veya komşu SDF örneklerinin bulunmadığı chunk sınırlarına yakın uç durum etkileşimleriydi.

Bu spike, bizi bölgeler hâlinde düşünmeye zorladı. Kameranın yakınında, oyuncuların araziyi oyabilmesi, kazabilmesi ve mağaraları görebilmesi için hacimsel özgürlük istersiniz. Kameradan uzakta ise düz bir yükseklik haritasının daha ucuz ve tamamen yeterli olduğu clipmap verimliliğini istersiniz. Bu ikilik, Spike 13'ten itibaren geliştirmeyi sürdürdüğümüz mimarinin omurgası hâline geldi.

En sevdiğim hata ayıklama anlarından biri, düzenlemeler çalışırken tel kafes görünümünü açıp kapatmaktı. Topolojinin gerçek zamanlı olarak oluşup çözülmesini izlemek, kalite ödünlerini anında görünür kılıyordu. Köşe noktası yoğunluğunun nerede yeterli olduğunu, nerede fazla seyrekleştiğini ve LOD geçişlerinde çatlakları önlemek için tam olarak nerede Transvoxel desteğine ihtiyaç duyulacağını görebiliyordunuz.

  1. bölümde entegrasyon zorluğunu ele alıyoruz. Ham, compute güdümlü mesh'leri ve Three.js sahne grafiği mantığını tek ve kararlı bir render işlem hattında bir arada tutmak, bağımsız demonun düşündürdüğünden daha zordu.

Bu bölümde değinilen teknolojiler

Marching cubes. 3B bir skaler alandan üçgen ağı çıkarmaya yarayan bir algoritmadır (Lorensen ve Cline, 1987). Düzenli bir 3B ızgaradaki her hücre, alanın 8 köşesinde örneklenmesiyle sınıflandırılır. İşaret örüntüsü bir durum indeksi (0-255) üretir ve bir arama tablosu her durumu bir üçgen kümesiyle eşler. Köşe noktaları, iki köşe arasında enterpolasyon yapılarak ızgara kenarlarına yerleştirilir. Her hücre bağımsız olarak işlendiğinden algoritma son derece paraleldir ve bu da onu GPU hesaplamaları için ideal kılar. SDF'ler ve marching cubes hakkındaki arazi rehberimize göz atın.

İşaretli Uzaklık Alanları (SDF'ler). 3B uzaydaki her noktada en yakın yüzeye olan işaretli uzaklığı saklayan hacimsel bir temsildir. Pozitif değerler dışarıyı, negatif değerler içeriyi belirtir; sıfır geçişi ise yüzeyi oluşturur. SDF'ler, yükseklik haritalarının ifade edemediği mağaralar, kemerler, çıkıntılar ve havada duran geometriler gibi herhangi bir 3B şekli temsil edebilir. Düzenleme, alan üzerinde doğal küme cebiriyle yapılır. Malzeme ekleme (iki şeklin birleşimi) d=min(d1,d2), çıkarma (kazma) işlemi oyma şeklinin işareti ters çevrilerek d=max(d1,d2) biçimindedir; yumuşak bir harmanlama ise aşağıdaki gibi bir yumuşak minimum kullanır:

smin(d1,d2,k)=min(d1,d2)h24k,h=max(k|d1d2|,0)

Burada k, harmanlama yarıçapını kontrol eder. k0 olduğunda bu ifade yeniden katı bir min işlemine dönüşür. SDF arazi temsiline göz atın.

WebGPU compute shader'ları. Rasterleştirme işlem hattına bağlı olmadan genel amaçlı hesaplama yapan GPU programlarıdır. Bir compute shader, paralel olarak çalışan iş parçacığı çalışma gruplarını yürütür. Marching cubes için her iş parçacığı tek bir ızgara hücresini işler: SDF'yi örnekler, hücreyi sınıflandırır, üçgenleştirmeyi arama tablosundan bulur, kenar köşe noktalarını enterpole eder ve atomik sayaçlar kullanarak bunları bir mesh tamponuna ekler. Çıktı tamponu render için doğrudan köşe noktası verisi olarak kullanıldığından CPU'ya veri geri okumak gerekmez. Will Usher'ın webgpu-marching-cubes projesi, tarayıcıda gerçek zamanlı 256^3 ızgara işlemeyi gösterir. WebGPU güdümlü LOD hakkındaki arazi rehberimize göz atın.

Hibrit yükseklik haritası + SDF mimarisi. Tarayıcı tabanlı araziler için pratik yaklaşım şudur: yükseklik haritaları tüm dünyayı kaplarken (ucuz ve kompakt), SDF hacimleri yalnızca mağaralara, çıkıntılara veya içerik üreticilerinin oyduğu özelliklere ihtiyaç duyan chunk'larda (chunk'ların %5-10'u) bulunur. Kameranın yakınında hacimsel özgürlük, oyma işlemlerine ve mağaralara olanak tanır. Uzakta ise yükseklik haritaları, düz araziyi verimli biçimde sağlar. Hibrit arazi temsiline göz atın.


12 bölümün 7.'si.
Önceki: Bölüm 6 - Clipmap'ler gidişatı değiştirdi
Sonraki: Bölüm 8 - Temel çizgimizi kaybetmeden entegrasyon
Seri rehberi: /blog/2026-02-25-open-world-browser-series-guide