Skip to content

3D Fırça Teknikleri ve Oyun İçinde Dünya Şekillendirme

Oyuncuların dünyayı şekillendirmesini istiyoruz. Bir ızgaraya hazır nesneler yerleştirmelerini değil. Blokları açıp kapatmalarını değil. Arazinin biçimini gerçekten değiştirmelerini: nehirler oymalarını, dağlar yükseltmelerini, uçurum yamaçlarını yumuşatmalarını, mağaralar kazmalarını. ZBrush ve Blender'ın şekillendirme modunun sanatçılar için yaptığını, çok oyunculu bir tarayıcı oyununun içinde 60 fps hızında çalışacak şekilde yapmak istiyoruz.

Bu; veri temsilini, mesh çıkarımını, GPU hesaplamalarını, fırça matematiğini ve ağ senkronizasyonunu kapsayan zorlu bir mühendislik problemidir. Bu rehber, bulduğumuz her şeyi belgeliyor.

Arazi Temsilinin İki Dünyası

Her şekillendirme sistemi, arazi verilerinin nasıl saklanacağına dair bir seçimle başlar. Bu seçim, hangi tür düzenlemelerin mümkün olduğunu, ne kadar hızlı çalıştıklarını ve ne kadar bellek gerektirdiklerini belirler.

Yükseklik Haritaları

Bir yükseklik haritası, her ızgara noktası için tek bir yükseklik değeri saklar. Bunu, parlaklığın rakıma karşılık geldiği gri tonlamalı bir görüntü olarak düşünebilirsiniz. Mevcut world/client arazimiz tam olarak bu şekilde çalışır: noise.ts, FBM değer gürültüsü aracılığıyla yükseklik üretir ve her Chunk, bir PlaneGeometry üzerine yansıtılan Float32Array türünde bir yükseklik haritası saklar.

Yükseklik haritaları hızlıdır. Örnekleme, çift doğrusal enterpolasyonla yapılan tek bir dizi erişiminden ibarettir. Izgara çözünürlüğünü azaltmanız yeterli olduğundan LOD son derece basittir. Splat tabanlı doku harmanlama doğrudan UV ızgarasına eşlenir. Fizik çarpışmaları ise bir yükseklik sorgusuna indirgenir.

Sınırlaması topolojidir. Bir yükseklik haritası, her (x, z) koordinatı için yalnızca tek bir yüksekliği temsil edebilir. Mağaralar yoktur. Çıkıntılar yoktur. Kemerler yoktur. Tüneller yoktur. Bir oyuncu kendi üzerine kıvrılan bir uçurum şekillendirirse yükseklik haritası bunu saklayamaz. Çoğunlukla inişli çıkışlı tepelerden ve dağlardan oluşan araziler için bu sorun değildir. Oyuncuların toprağı kazabildiği serbest biçimli şekillendirmede ise çıkmaz sokaktır.

Hacimsel (3D Skaler Alanlar)

Alternatif yaklaşım, 3D uzaydaki her noktada bir değer saklamaktır. Değer katı malzemenin içinde negatif, dışında pozitifse (veya tam tersi) bir İşaretli Uzaklık Alanınız (SDF) vardır. Değer yalnızca bir yoğunluksa (belirli bir eşiğin üzeri katı, altı boşsa) bir yoğunluk alanınız vardır.

Hacimsel temsiller her türlü topolojiyi işleyebilir. Mağaralar, çıkıntılar, yüzen adalar ve dağların içinden geçen tüneller mümkündür. Bunun bedeli bellek kullanımı ve karmaşıklıktır. 32 bit kayan noktalı değerlere sahip 256^3 boyutunda bir ızgara 64 MB tutar. 512^3 boyutunda bir ızgara ise 512 MB tutar. Üstelik bu yalnızca tek bir chunk içindir. Bunu uygulanabilir kılmak için seyrek veri yapılarına (octree'ler, brick map'ler) ihtiyacınız vardır.

Mesh çıkarma adımı da basit değildir. Yalnızca köşelerin Y konumlarını ayarlayıp işi bitiremezsiniz. Skaler alanı okuyan ve alanın sıfırı kestiği yüzeyi yaklaşık olarak temsil eden bir üçgen mesh üreten bir algoritmaya ihtiyacınız vardır.

Mesh Çıkarımı: Marching Cubes, Surface Nets ve Dual Contouring

Marching Cubes

Marching Cubes, en eski ve en yaygın uygulanmış izoyüzey çıkarma algoritmasıdır. Lorensen ve Cline tarafından 1987'de yayımlanan algoritma, her köşesinde bir skaler değer bulunan voxel ızgarasındaki her küpü inceleyerek çalışır. Bazı köşeler yüzeyin içinde (negatif), bazıları ise dışında (pozitif) olduğunda bu küpün içine bir üçgen mesh parçası yerleştirilir.

Her küpün 8 köşesi vardır ve her biri içeride veya dışarıda olabilir; böylece 256 olası yapılandırma (2^8) ortaya çıkar. Bunlar simetri yoluyla 15 benzersiz duruma indirgenir. Bir arama tablosu, her durumu bir üçgen kümesiyle eşleştirir. Kenar kesişim noktaları, işaretin değiştiği kenarlar boyunca doğrusal enterpolasyonla bulunur.

Yakın tarihli GPU uygulamaları, Marching Cubes'u gerçek zamanlı şekillendirme için yeterince hızlı hâle getirmiştir. UE5 üzerinde geliştirilen 2025 tarihli bir uygulama, her GPU iş parçacığını bir küpe atayarak binlerce küpü eş zamanlı işler. Temel nokta, her küpün üçgenleştirilmesinin komşularından bağımsız olmasıdır; bu da algoritmayı son derece kolay paralelleştirilebilir kılar.

MCHex (arxiv 2511.02064, 2025), Marching Cubes'u pozitif Jacobian değerleri garanti edilen uyarlanabilir altı yüzlü mesh üretimine genişleterek simülasyon mesh'lerinde sınır yaklaşımını iyileştirir.

rupMC, CPU/GPU heterojen mimarileri kullanarak seri uygulamalardan onlarca kat, paralel DMC varyantlarından ise 4 kat daha yüksek performansa ulaşır.

Başlıca sınırlaması şudur: Marching Cubes keskin ayrıntılarda zorlanır. 90 derecelik bir kenar, yuvarlanarak pürüzsüz bir eğriye dönüşür. Arazi şekillendirmede bu genellikle kabul edilebilir (doğal arazi çoğunlukla pürüzsüzdür), ancak mimari unsurlar için sorun oluşturur.

Surface Nets

Surface Nets, ayrık skaler alanlardan daha pürüzsüz mesh'ler üreten daha yeni bir algoritma ailesidir. Surface Nets, köşeleri küp kenarlarına yerleştirmek yerine (Marching Cubes gibi), yüzeyi içeren her küp başına bir köşe yerleştirir ve ardından bitişik köşeleri bağlayarak dörtgenler oluşturur.

Sonuç doğal olarak daha pürüzsüzdür. 2024 tarihli bir makale (arxiv 2401.14906), sıralı algoritmalardan bir ila iki büyüklük mertebesi daha hızlı çalışan, yüksek performanslı bir paralel Surface Nets uygulaması göstermiştir. fast-surface-nets Rust crate'i, küçük arama tabloları ve SIMD hızlandırma kullanarak 2,5 GHz hızındaki tek bir çekirdekte saniyede yaklaşık 20 milyon üçgen üretir.

bevy-sculpter (v0.18.0, Ocak 2026), birincil mesh oluşturma stratejisi olarak Surface Nets'i kullanır. Bu crate, dört fırça türüyle SDF tabanlı hacimsel şekillendirme sunar: sert CSG (anında ekleme/çıkarma), pürüzsüz sürekli (basılı tutulan giriş için), bulanıklaştırma (yüzey yumuşatma) ve düzleştirme (hedef yüksekliğe ayarlama). Ayrıca düzenlemelerden sonra doğru işaretli uzaklık alanı özelliklerini geri kazandırmak için Fast Sweeping Method aracılığıyla SDF mesafelerini yeniden hesaplama işlevini içerir.

Surface Nets; Marching Cubes (basit ve hızlıdır, ancak ikili verilerde aliasing'li mesh'ler üretir) ile Dual Contouring (özellikleri korur ama karmaşıktır) arasında iyi bir orta yoldur.

Dual Contouring

Dual Contouring, Marching Cubes ve Surface Nets'in koruyamadığı keskin ayrıntıları korur. Bunu yalnızca her köşedeki alanın işaretini değil, kenar kesişimlerindeki gradyanı (normali) da kullanarak yapar. QEF (Quadratic Error Function) minimizasyonu, her hücrenin içindeki köşeyi tüm kenar kesişim kısıtlamalarını en iyi karşılayan konuma yerleştirir.

Sonuç olarak çıkarılan mesh'te keskin kenarlar ve köşeler korunur. Birbirine dik yüzlere sahip bir küp, küp olarak kalır.

Bunun bedeli karmaşıklıktır. QEF çözümü, GPU üzerinde paralelleştirmeyi zorlaştıran hücreler arası bağımlılıklara sahiptir. Manifold olmayan mesh'ler (ikiden fazla çokgen tarafından paylaşılan kenarlar) üretebilir. Ayrıca Johannes Jendersie, çalışan bir Dual Contouring uygulamasının yaklaşık 200 satır, sağlam bir Marching Cubes uygulamasının ise 500'den fazla satır kod olduğunu belirtse de uygulaması Marching Cubes'tan daha karmaşıktır.

Cubical Marching Squares (CMS) bir orta yol olarak önerilmiştir: hücreler arası bağımsızdır (GPU dostudur) ve yine de belirli ölçüde ayrıntı koruması sunar.

Hangisini Kullanmalı?

Tarayıcıda oyunculara sunulan arazi şekillendirme için:

Surface Nets en güçlü adaydır. İkili veriler üzerinde Marching Cubes'ta görülen aliasing artefaktları olmadan pürüzsüz mesh'ler (doğal görünümlü arazi) üretir. Gerçek zamanlı yeniden mesh oluşturma için yeterince hızlıdır. Üstelik uygulanması Dual Contouring'den daha basittir.

Marching Cubes, GPU paralelliğinin öncelikli olduğu (her küp bağımsızdır) veya en geniş kütüphane desteğine ihtiyaç duyduğunuz durumlarda sağlam bir seçenek olmaya devam eder. Reinder Nijhoff'un WebGPU SDF Editor'ü (Ocak 2026), tamamen GPU üzerinde çalışan çıkarım işlem hattında hem Marching Cubes'u hem de Surface Nets'i uygular.

Dual Contouring, en uygun şekilde mimari hassasiyetin performanstan daha önemli olduğu durumlara ayrılmalıdır. Tarayıcı bağlamında gerçek zamanlı arazi şekillendirme için ideal değildir.

Transvoxel Algoritması: LOD Birleştirme Sorununu Çözmek

Voxel arazi farklı çözünürlüklerde mesh'e dönüştürüldüğünde (oyuncunun yakınında LOD0, uzakta LOD2), sınırlar boyunca çatlaklar oluşur. Yükseklik haritalarında bu basit bir problemdir: daha düşük çözünürlüklü komşuyla eşleşmesi için kenar köşelerine enterpolasyon uygulanır. Mevcut chunk.ts dosyamız stitchEdge() içinde tam olarak bunu yapar.

Hacimsel arazide ise problem çok daha zordur. LOD0'daki bir mağara ağzı sınırda 30 üçgen üretebilir. Aynı bölge LOD1'de tamamen farklı bir topolojiyle 8 üçgen üretebilir. Bunlar arasında doğrusal enterpolasyon yapmanın basit bir yolu yoktur.

Eric Lengyel'in Transvoxel Algorithm'i (2009), bu sorunu "geçiş hücreleriyle" çözer. İki LOD seviyesi arasındaki sınırda algoritma, 8 küp köşesi yerine 9 yüksek çözünürlüklü örneği değerlendirir ve 73 eşdeğerlik sınıfına ayrılan 512 olası yapılandırma üretir. Her sınıf, iki çözünürlük arasındaki boşluğu kusursuz biçimde dolduran önceden tanımlı bir üçgen deseniyle eşleştirilir.

Algoritma yerel voxel verileri üzerinde çalıştığından değiştirilmiş bir bölgenin yeniden üçgenleştirilmesi hızlıdır. Bu, gerçek zamanlı şekillendirme açısından kritik öneme sahiptir: bir oyuncu LOD sınırına yakın araziyi düzenlediğinde yalnızca geçiş hücrelerinin yeniden oluşturulması gerekir.

transvoxel crate'i olarak bir Rust uygulaması mevcuttur. Orijinal arama tablolarına transvoxel.org adresinden ulaşılabilir.

Fırça Matematiği

Şekillendirme fırçası, hedef noktanın çevresindeki bir yarıçap içinde skaler alan değerlerini değiştiren bir fonksiyondur. Blender'dan Unreal Engine'e ve çalışma zamanı oyun sistemlerine kadar tüm uygulamalardaki matematik şaşırtıcı derecede benzerdir.

Azalma Fonksiyonları

Fırça azalması, düzenleme gücünün merkezden kenara doğru nasıl azaldığını belirler. Blender 5.1 şu standart profilleri tanımlar:

Pürüzsüz: f(d) = 3d^2 - 2d^3 (Hermite enterpolasyonu, noise.ts dosyamızdaki smoothstep ile aynı)

Küre: Merkezde güçlüdür ve sınıra yakın bölgede hızla azalır. f(d) = sqrt(1 - d^2) olarak yaklaştırılır.

Keskin: n > 2 olmak üzere f(d) = (1 - d)^n. İnce bir uç oluşturur.

Doğrusal: d, merkezden normalleştirilmiş uzaklık olmak üzere (merkezde 0, kenarda 1) f(d) = 1 - d.

Sabit: d < 1 için f(d) = 1; fırça sınırında keskin biçimde sonlanır.

Ters Kare: Doğal, "kil benzeri" bir his için pürüzsüz ve küre arasında hibrit bir profildir.

Tüm durumlarda d = distance_to_center / brush_radius olur ve [0, 1] aralığına sabitlenir. Azalma değeri, her noktadaki gerçek alan değişikliğini üretmek için fırça gücüyle çarpılır.

Azalma Uzayı

Blender, küresel azalma (uzaklık 3D dünya uzayında hesaplanır) ile izdüşümsel azalma (uzaklık 2D ekran uzayında hesaplanır) arasında ayrım yapar. İzdüşümsel azalma, dünya uzayında çok farklı derinliklerde olsalar bile ekranda birbirine yakın görünen iki noktanın birbirini eşit ölçüde etkilemesi anlamına gelir. Arazi şekillendirme için 3D dünya uzayındaki azalma genellikle daha sezgiseldir.

Temel Fırça İşlemleri

Yükseltme/Alçaltma (Yer Değiştirme): Azalmaya göre ağırlıklandırarak fırça yarıçapı içindeki skaler alana değer ekler veya alandan değer çıkarır. Yükseklik haritaları için: height[i] += strength * falloff(d). SDF'ler için: sdf[i] -= strength * falloff(d) (değer çıkarmak malzemeyi daha katı hâle getirerek yüzeyi yükseltir).

Yumuşatma (Laplasyen): Her değeri, azalmaya göre ağırlıklandırılmış komşularının ortalamasıyla değiştirir. Bu işlem ayrıntıları siler ve gürültüyü azaltır. Laplasyen filtresi küçük bir çekirdeği (yükseklik haritaları için 3x3, hacimler için 3x3x3) örnekler ve değeri ortalamaya doğru harmanlar. HC (Humphrey's Classes) yumuşatma, ham Laplasyen yöntemine kıyasla hacmi daha iyi koruyan bir varyanttır.

Düzleştirme: Alan değerini hedef yüksekliğe (veya SDF uzayındaki uzaklığa) ayarlar ve azalmaya göre harmanlar. Hedef genellikle fırça darbesi başladığında fırça merkezinden örneklenir ve ardından sabit tutulur. Bu, düz platolar oluşturur.

Sıkıştırma/Şişirme: Köşeleri yüzey normaline doğru veya normalden uzağa taşır. SDF uzayında bu, gradyan yönü boyunca yer değiştirmeye eşdeğerdir.

Tutma: Alanın bir bölgesini kil çekiyormuşsunuz gibi taşır. Yer değiştirme vektörü, dünya uzayına yansıtılan fare delta değeridir ve yarıçap içindeki alan değerlerine uygulanır.

Gürültü: Fırça yarıçapı içindeki alana prosedürel gürültü ekler. Pürüzsüz yüzeyleri kabalaştırmak için kullanışlıdır.

Damga: 2D gri tonlamalı bir görüntüyü yer değiştirme olarak uygular ve imlecin altındaki yüzeye yansıtır. Unreal Engine'in Landscape aracı bunu arazi fırçaları için destekler.

Uyarlanabilir Tessellation

sculpt-3D (React + Three.js ile tarayıcıda şekillendirme), uyarlanabilir tessellation uygular: fırça mesh üzerinde hareket ederken, deformasyon için daha fazla köşe sağlamak üzere fırça merkezinin yakınındaki üçgenler alt bölümlere ayrılır. Bu, kaba bir mesh'in şekillendirme nedeniyle bozulduğu "düşük poligonlu esneme" sorununu önler. Alt bölümleme, eşit üçgen kalitesi için simetrik bölme kullanır.

Hacimsel sistemlerde mesh alandan yeniden üretildiği için uyarlanabilir tessellation'a aynı şekilde ihtiyaç duyulmaz. Bunun yerine aynı etkiyi elde etmek amacıyla düzenlemelerin yakınındaki voxel çözünürlüğünü yerel olarak artırabilirsiniz (uyarlanabilir octree'ler).

SDF Şekillendirme: Dreams Yaklaşımı

Media Molecule'ün Dreams'i (PS4, 2020), şimdiye kadar piyasaya sürülmüş en iddialı oyun içi şekillendirme sistemidir. Alex Evans, teknik yaklaşımı SIGGRAPH 2015'te sunmuştur.

Temsil

Dreams, geometriyi 83^3 fp16 hacim dokusu bloklarında bileşik bir SDF fonksiyonu olarak saklar. Her şekillendirme, 1 ila 100.000 "düzenlemeden" oluşan bir listedir; her düzenleme, ilkel bir şekil (küre, küp, silindir, koni, elipsoit, torus vb.) ve bir harmanlama moduyla birlikte bir CSG işlemidir (ekleme, çıkarma, renklendirme). Karıştırma modları soft-max ve soft-min fonksiyonlarını kullanır. "Yumuşak" karıştırma, primitifler arasında yuvarlatılmış geçişler oluşturur (birbirine bastırılmış kil gibi). "Sert" karıştırma ise keskin boolean kesitleri üretir. Karıştırma yarıçapı kullanıcı tarafından ayarlanabilir.

Render Alma

Dreams, üçgen mesh çıkarmaz. Bunun yerine özel bir nokta bulutu oluşturucusu ("flecks") kullanarak doğrudan SDF'den render alır. Her fleck, yüzey normaline göre yönlendirilmiş küçük bir disktir. Yüzeyleri bulmak için SDF örneklenir ve fleck'ler bu yüzeylere dağıtılır. Bu, mesh çıkarma darboğazını tamamen ortadan kaldırır ancak özel bir renderer gerektirir.

Bu yaklaşım, Three.js/WebGL tabanlı bir dünya için doğrudan uygulanabilir değildir. Mesh çıkarmamız gerekir. Ancak CSG düzenleme listesi kavramı, geri alma/yineleme ve ağ senkronizasyonu açısından son derece önemlidir.

Mike Turitzin'in Dinamik SDF Motoru (2026)

Mike Turitzin tarafından geliştirilmekte olan bir oyun motoru, temel temsil olarak dinamik SDF'leri kullanıyor. Motor şunları destekliyor:

Oynanış sırasında ayrıntılı değişiklikler: Maddeyi yumuşak biçimde veya keskin kenarlarla ekleme ve kaldırma. Delikleri taşıma veya oyuncunun arkasında kaybolan geçici tüneller oluşturma gibi tahribatsız değişiklikler.

Seyrek önbellekleme için brick map'ler ve brick atlas'lar. SDF alanının tamamını yoğun bir 3B ızgarada depolamak yerine alan, "brick"lere (küçük 3B döşemelere) bölünür. Yalnızca yüzey sınırını içeren brick'ler ayrılır. Bu, çoğunlukla boş veya katı hacimden oluşan sahnelerde bellek kullanımını önemli ölçüde azaltır.

LOD için geometri clipmap'leri (Losasso & Hoppe, SIGGRAPH 2004). Giderek artan çözünürlükteki iç içe geçmiş düzenli ızgaralar kamera konumunu çevreler. En içteki ızgara en yüksek çözünürlüğe sahiptir; dıştaki ızgaralar giderek daha düşük çözünürlüklüdür. Bu, geniş alanları desteklerken bellek kullanımını büyük ölçüde azaltır. Clipmap'ler kamera hareket ettikçe artımlı olarak güncellenir ve bu sayede açık dünyaların akışla yüklenmesinde verimli olur.

Fizik ve çarpışma, doğrudan SDF üzerinde çalışır. Sphere-tracing (adım boyutu olarak SDF mesafesini kullanan ray marching) verimli ışın yayılımı sağlar. Çarpışma algılama, yüzey normali olarak SDF gradyanını ve iç içe geçme derinliği olarak mesafe değerini kullanır.

Teardown: Büyük Ölçekli Voksel Yıkımı

Teardown (Voxagon), yelpazenin diğer ucunu temsil eder: dünyadaki her nesne, parça parça yok edilebilen bir voksel hacmidir.

Mimari

Nesneler, düzenli aralıklara sahip voksel ızgaraları olarak depolanır. Motor, render almak için Marching Cubes veya SDF kullanmaz. Bunun yerine, OpenGL 3.3 üzerinde fragment shader'lardaki değiştirilmiş bir DDA (Digital Differential Analyzer) algoritmasıyla vokselleri doğrudan ışın izler. Mipmap'ler, ışın kesişimi sırasında boş alan geçişini hızlandırmak için yoğun bir octree yapısı oluşturur.

Motor, her nesne için yönlendirilmiş sınırlayıcı kutusunu (OBB) rasterleştirir ve voksel kesişimlerini bulmak üzere içinden bir ışın geçirir. OBB'nin yalnızca arka yüzleri render edilir; böylece kamera sınırlayıcı hacmin içine girebilir.

Yıkım Senkronizasyonu (Çok Oyunculu)

Teardown'ın Mart 2026 tarihli çok oyunculu güncellemesi, yarı deterministik bir yaklaşım kullanır. Yapısal yıkım (delik açma, sahipliği değiştirme, eklemleri yeniden bağlama), güvenilir bir ağ akışı üzerinden sabit noktalı tamsayı matematiğiyle işlenir. Tüm istemciler aynı deterministik komutları çalıştırır ve aynı dünya durumuna ulaşır. Yapısal olmayan değişiklikler (enkaz, parçacıklar) güvenilir olmayan durum senkronizasyonunu kullanır.

Bu, çok oyunculu dünyamız açısından önemli bir çıkarımdır: arazi düzenlemeleri deterministik olmalıdır. Oyuncu A bir dağa şekil verirse tüm istemciler aynı alan verisinden aynı mesh'i üretmelidir. Ortaya çıkan mesh değil, düzenleme komutları (fırça konumu, yarıçapı, gücü ve işlem türü) yetkili veri olmalıdır.

ALICE-SDF: Sıkıştırma ve CSG Ağaçları

ALICE-SDF (Adaptive Lightweight Implicit Compression Engine, v1.3.0 Mart 2026), SDF tabanlı uzamsal veriler için poligon mesh'lere kıyasla 10-1000 kat sıkıştırma sağlayan bir Rust uygulamasıdır. Şunları destekler:

126 yapı taşı: 72 primitif, 24 işlem, 7 dönüşüm ve 23 değiştirici. Yumuşak karıştırma işlemleri (birleşim, çıkarma, kesişim), sert kenarlı pahlar için chamfer karıştırmaları ve basamaklı CSG geçişleri için merdiven karıştırmaları.

Geri alma/yineleme ve ağ senkronizasyonu için CSG ağacı diff/patch. Bu, çok oyunculu şekillendirmenin temel özelliğidir: alan durumunun tamamını göndermek yerine iki CSG ağacı arasındaki yapısal farkı gönderirsiniz. İstemci, yeni durumu yeniden oluşturmak için yamayı uygular. Bu, ham voksel verilerine delta sıkıştırması uygulamaktan çok daha az bant genişliği kullanır.

Kimlik dönüşümlerinin kaldırılması, iç içe geçmiş dönüşümlerin birleştirilmesi ve değiştiricilerin alt seviyeye indirilmesi dâhil CSG ağacı optimizasyonu. Böylece düzenlemeler biriktikçe ağaç kompakt kalır.

Hem Marching Cubes hem de Dual Contouring ile mesh üretimi. Fiziksel çarpışma algılama doğrudan SDF üzerinde çalışır.

WebAssembly desteği, tarayıcı entegrasyonunu mümkün kılar. Motor, WASM bağlayıcılarıyla Rust dilinde yazılmıştır ve bu nedenle Three.js uygulamaları için gerçekçi bir seçenektir.

Arazi İçin WebGPU Compute

WebGPU, 2025'in sonlarından itibaren tüm büyük tarayıcılarda kullanılabilir durumdadır. Chrome 113+, Edge 113+, Firefox 141+ ve Safari 26+ sürümlerinin tamamında etkin olarak sunulur. Bu, daha önce yalnızca GPU'da kullanılabilen compute shader işlem hatlarının önünü açar.

Performans

WebGPU compute shader'ları, yoğun paralelleştirme sayesinde araziyi CPU yöntemlerinden yaklaşık 100 kat daha hızlı üretir. GPU, binlerce hesaplamayı eş zamanlı olarak yürütür ve arazi üretiminin neredeyse tamamı paraleldir (her tepe noktası/voksel bağımsızdır).

İşler üç katmanda düzenlenir: Dispatch Düzeyi (iş yükünün GPU geneline dağıtılması), Workgroup Düzeyi (bir işlem birimi içindeki paylaşımlı bellek) ve Thread Düzeyi (tekil hesaplamalar). Shader dili olarak WGSL (WebGPU Shading Language) kullanılır.

Gerçek Zamanlı Arazi Şekillendirme İşlem Hattı

Bir WebGPU şekillendirme işlem hattı şu şekilde çalışır:

  1. Fırça uygulaması (compute shader): Fırça yarıçapı içindeki skaler alan değerlerini günceller. Her thread bir vokseli işler. Fırça parametrelerini (konum, yarıçap, güç, düşüş türü ve işlem) bir uniform buffer'dan okur ve değişikliği uygular.

  2. Mesh çıkarma (compute shader): Değiştirilen bölgede Surface Nets veya Marching Cubes çalıştırır. Nijhoff'un WebGPU SDF Editor'ü bunu çok aşamalı bir işlem hattı olarak uygular: 16.384 hücre genelinde alan bölümleme, octree tabanlı hücre bölme ve ardından yüzey çıkarma.

  3. Tepe noktası buffer'ını güncelleme (GPU tarafında): Çıkarılan tepe noktalarını CPU belleği üzerinden gidip gelmeden doğrudan bir render buffer'ına yazar.

  4. Normal hesaplama (compute shader): Tepe noktası normallerini mesh'ten veya SDF gradyanından hesaplar.

  5. Render alma (standart işlem hattı): Mesh'i standart PBR materyalleriyle çizer.

1-4 arasındaki adımların tümü, JavaScript'e herhangi bir veri döndürülmeden GPU'da çalışabilir. CPU'nun her karede yalnızca fırça parametrelerini göndermesi gerekir.

WebGPU SDF Editor

Reinder Nijhoff'un WebGPU SDF Editor'ü (Ocak 2026), bu yaklaşımın Chrome'da çalıştığını gösterir. Altı primitifi (koni, silindir, kapsül, torus, kutu, küre), ayarlanabilir yumuşak karıştırmaya sahip üç karıştırma işlemini (birleşim, çıkarma, kesişim) ve hiyerarşik sahne grafiklerini destekler. Her primitif, tek bir GPU buffer'ında 112 bayt yer kaplar.

Render işlem hattı, çevresel perdeleme ve zamansal kenar yumuşatma için 1.024 gölge haritası kullanır. Bu, üst seviye GPU'larda etkileşimli kare hızlarında çalışır.

Heightmap Şekillendirme: Daha Basit Yol

Mağara ve çıkıntı desteği gerekmiyorsa heightmap şekillendirme, hacimsel işlem hattının tamamına duyulan ihtiyacı ortadan kaldırır. Yayınlanmış oyunların çoğu, arazi düzenlemeyi bu şekilde gerçekleştirir.

Çalışma Zamanı Uygulama Modeli

Unity Runtime Terrain (JohannHotzel, Ocak 2026), standart modeli gösterir:

  1. Arazi üzerindeki isabet noktasını bulmak için kameradan fare konumuna doğru raycast uygula.
  2. İsabet noktasını eşleştirerek heightmap koordinatlarına dönüştür.
  3. Düşüşe göre ağırlıklandırarak yakındaki heightmap değerlerine fırçayı uygula.
  4. Değiştirilmiş heightmap'e göre tepe noktalarının Y konumlarını ayarlayarak mesh'i güncelle.
  5. Yeni mesh'le eşleşmesi için fizik collider'ını yeniden oluştur.

Three.js arazimizde 1-4 arasındaki adımlar, mevcut mimariye doğrudan uyarlanabilir. Chunk sınıfı zaten heightmap'leri depoluyor ve bunlardan mesh oluşturuyor. Şekillendirme eklemek için şunlar gerekir:

  • Chunk mesh'lerine karşı çalışan bir raycast sistemi (Three.js Raycaster)
  • chunk.heightmap değerlerini değiştiren fırça uygulama fonksiyonları
  • Mesh tepe noktası güncellemeleri (Y konumlarını ayarlama, normalleri yeniden hesaplama)
  • Etkilenen bölge için splat map'in yeniden hesaplanması (böylece doku karışımı yeni eğimi/yüksekliği yansıtır)
  • Düzenlemenin mevcut WebSocket protokolü üzerinden diğer istemcilere ağ yayınıyla gönderilmesi (fırça konumu, yarıçapı, gücü ve işlemi)

Clipmap Yaklaşımı

Landow.dev, heightmap araziler için "gezinen clipmap" tanımlar: oyuncuyu takip eden ve değişken alt bölüm yoğunluğuna sahip tek bir mesh. Heightmap'i farklı LOD düzeylerine sahip ayrı mesh'lere bölmek yerine (şu anda yaptığımız gibi), clipmap kameraya yakın yerlerde yoğun, kenarlarda ise seyrek olan kesintisiz bir mesh'tir.

Bu yaklaşım, LOD birleştirmeyi tamamen ortadan kaldırır. Mesh, ihtiyaç duyduğunuz yerlerde daha fazla, ihtiyaç duymadığınız yerlerde ise daha az üçgene sahip olur. Bunun karşılığında şekillendirme, ayrı chunk'lar yerine tek ve büyük bir mesh'in güncellenmesini gerektirir; bu da büyük düzenlemelerde maliyetli olabilir.

Tahribatsız SDF Heightmap'leri

Landow.dev ayrıca heightmap'in kendisinin bir SDF bileşiminden üretildiği bir teknik tanımlar. Şekil örnekleri (küreler, kutular, gürültü fonksiyonları), CSG işlemleri kullanılarak bir compute shader'da birleştirilir ve çıktı bir heightmap olarak örneklenir. Bu, heightmap tabanlı render almanın basitliğini korurken tahribatsız düzenleme sağlar (herhangi bir şekil örneğini istediğiniz zaman taşıyabilir veya silebilirsiniz).

Bu ilgi çekici bir hibrittir: veri temsili hacimseldir (SDF CSG ağacı), ancak render yolu standart bir heightmap mesh'idir. SDF tarafının geri alma/yineleme ve ağ dostu düzenleme işlemleriyle heightmap tarafının basit render ve fizik özelliklerini birlikte elde edersiniz. Sınırlama ise değişmez: mağara veya çıkıntı yoktur.

Büyük Dünyalar İçin Seyrek Voksel Octree'leri

Yoğun 3B ızgaralar ölçeklenebilir değildir. Her bir kenarı 1 km olan ve 0,5 m çözünürlüğe sahip bir dünya, 8 milyar voksel gerektirir. Seyrek Voksel Octree'leri (SVO), alanı yinelemeli olarak alt bölümlere ayırıp yalnızca yüzey sınırını içeren octant'lar için depolama alanı ayırarak bu sorunu çözer.

Bir SVO, doğal olarak hiyerarşik LOD sağlar: herhangi bir noktadaki ağaç derinliği, etkin çözünürlüğü belirler. Oyuncunun yakınında ağaç tamamen genişletilir (maksimum ayrıntı). Uzakta ise daha düşük çözünürlüklü bir düzeyde kesilir.

Render almak için SVO'lar doğrudan ışın izlenebilir (mesh çıkarılması gerekmez). Bir GPU ray marcher, ışınları her ağaç düzeyindeki eksen hizalı kutularla kesiştirir ve boş alt ağaçları tamamen atlar. Bu, chunk tabanlı render almanın overdraw sorunlarını ortadan kaldırır ve greedy meshing yapaylıklarını önler.

AdamYuan'ın Vulkan tabanlı SVO oluşturucusu kayda değer bir performans sergiler: GTX 1660 Ti üzerinde 2^10 çözünürlükte Crytek Sponza için 19 ms oluşturma süresi.

Şekillendirmede SVO değişikliği verimlidir: yalnızca fırça yarıçapındaki yaprak düğümlerin güncellenmesi gerekir ve ağaç yapısı değişken çözünürlüğü doğal olarak yönetir. Oyuncunun şekillendirdiği yerde ayrıntı eklemek (düğümleri daha yüksek çözünürlüğe bölmek) ve düzelttiği yerde ayrıntıyı azaltmak (düğümleri daha düşük çözünürlükte birleştirmek), veri yapısının doğal bir sonucudur.

Tarayıcı dağıtımındaki zorluk, WebGL'nin compute shader'ları desteklememesi ve WebGPU desteklese bile SVO oluşturma ve dolaşma algoritmalarının WGSL ile uygulanmasının karmaşık olmasıdır.

Çok Oyunculu Şekillendirmede Ağ Senkronizasyonu

Dünyamız, Cloudflare Durable Objects (world-chunk-do.ts) aracılığıyla zaten çok oyunculu desteğe sahip. Şekillendirme eklemek, arazi değişikliklerini bağlı tüm istemciler arasında senkronize etmek anlamına gelir.

Delta Sıkıştırması

Ham voksel verisi göndermek maliyetlidir. Oulu Üniversitesi'nin 2024 tarihli bir çalışması, delta kodlamasını DEFLATE sıkıştırmasıyla birleştirerek ve voksel güncellemelerini voksel başına bir bayttan az yer kaplayacak şekilde paketleyerek veri yükünde 2-8 kat iyileşme sağladı. SDEC codec'i, genel amaçlı serileştirmedeki 1114 bayta karşılık ortalama 259 baytlık paketler üreten bit paketli delta kodlamasını gösterir.

İşlem Tabanlı Senkronizasyon (Önerilen)

Alan durumunu senkronize etmek yerine işlemleri senkronize edin. Her şekillendirme eylemi bir mesaja dönüşür:

typescript
interface TerrainEditMsg {
  t: MsgType.TerrainEdit
  brush: {
    position: [number, number, number]
    radius: number
    strength: number
    falloff: 'smooth' | 'linear' | 'sharp' | 'constant'
    operation: 'raise' | 'lower' | 'smooth' | 'flatten' | 'noise'
    targetHeight?: number
  }
}

Sunucu bunu tüm istemcilere yayınlar ve her istemci aynı deterministik fırça işlemini kendi yerel arazi verisine uygular. Bu, Teardown'ın yapısal yıkım için kullandığı yaklaşımla aynıdır: güvenilir bir akış üzerinden deterministik komutlar.

ALICE-SDF'nin CSG ağacı diff/patch sistemi bunu bir adım ileri taşır: fark, tek tek fırça darbeleri yerine CSG ağacının tamamındaki yapısal değişikliği temsil eder. Bu, ağ genelinde verimli geri alma/yineleme sağlar (ters yamayı göndererek) ve sonradan katılan istemciler işlem günlüğünü yeniden oynatarak dünya durumunun tamamını yeniden oluşturabilir.

Öncelik ve Hız Sınırlama

Bağlı oyuncuların yakınındaki arazi düzenlemeleri yüksek öncelikli olmalıdır (hemen yayınlanmalıdır). Herhangi bir oyuncudan uzaktaki düzenlemeler toplu hâle getirilebilir ve daha düşük sıklıkta gönderilebilir. Enshrouded'ın voksel ağ sistemi bu modeli kullanır: oyuncuya yakın arazi için 60 Hz, arka plan bölgeleri için 10 Hz güncelleme.

Aktarım sırasında ZSTD sıkıştırması kullanmak, arazi güncelleme mesajlarının paket boyutlarını %60'a kadar azaltır.

İş Birliğine Dayalı Şekillendirme: Eş Zamanlı Düzenlemeler

Birden fazla oyuncu aynı bölgeyi eş zamanlı olarak şekillendirdiğinde çakışma çözümüne ihtiyaç duyulur. cSculpt (CNR Visual Computing Lab, 2016), bunu çok çözünürlüklü bir birleştirme algoritmasıyla çözdü. Her düzenleme birden fazla ölçekte temsil edilir ve eş zamanlı, örtüşen düzenlemeler çok çözünürlüklü temsilleri harmanlanarak birleştirilir. Amaçlarımız doğrultusunda daha basit bir yaklaşım yeterlidir: sunucu sıralamasıyla son yazan kazanır. Durable Object her düzenlemeye zaman damgası ekler ve bunları sırayla yayınlar. Tüm istemciler düzenlemeleri aynı sırayla uygular. Fırça darbeleri küçük, yerel ve eklemeli/çıkarmalı olduğundan, eşzamanlı düzenlemelerin sırasındaki küçük değişikliklerin görsel sonucu genellikle “doğru” sıradan ayırt edilemez.

INST-Sculpt: Nöral SDF Düzenleme (Araştırmanın Uç Noktası)

INST-Sculpt (arxiv 2502.02891, Şubat 2025), nöral SDF'lerin fırça darbeleriyle düzenlenmesini sağlar. Kullanıcılar yüzey üzerine darbeler çizer ve sistem, darbe yolunun çevresindeki tübüler komşuluklar boyunca alttaki nöral alanı deforme eder. Özel fırça profilleri (yapılandırılabilir kesitler), deformasyonun şeklini kontrol eder.

Bu, yapay zekâyla üretilen arazi açısından ilgi çekicidir: temel dünya bir nöral SDF (3B koordinatları işaretli uzaklığa eşleyen küçük bir sinir ağı) olarak temsil ediliyorsa şekillendirme, açık voksel verileri yerine ağ ağırlıklarını değiştirir. Bu temsil son derece kompakttır (bütün bir dünya için birkaç MB), ancak değerlendirilmesi bir arama tablosuna kıyasla daha maliyetlidir.

Bu teknoloji hâlâ araştırma aşamasındadır. Nöral SDF'lerin tüketici donanımlarındaki çıkarım maliyeti, günümüzde gerçek zamanlı oyunlarda kullanılmaları için fazla yüksektir. Ancak özellikle WebGPU gölgelendirici yetenekleri geliştikçe ve model çıkarımı hızlandıkça takip edilmeye değerdir.

World Creator 2026.3: Ticari Arazi Araçlarında Son Teknoloji

World Creator (BiteTheBytes, Mart 2026), arazi oluşturma araçlarında ticari son teknolojiyi temsil eder. 2026.3 sürümü; otomatik arazi uyarlamalı GPU tabanlı arazi üretimi (arazi, yerleştirilen nesnelere uyum sağlar), LOD optimizasyonu için kamera odaklı nesne dağıtımı ve gerçek dünya yükseklik verilerini içe aktarma (GeoTIFF, HGT, DTED) özelliklerini ekledi.

World Creator 2026.4 (28 Nisan 2026) daha sonra sayısal alanlara matematiksel ifadeler, öne çıkan nesneleri yüzeye oturtmak için arazi normali harmanlama, eksiksiz dekal desteği ve maksimum nesne sayısını kullanılabilir GPU belleğine göre ayarlayan VRAM ölçeklendirmesi ekledi. BiteTheBytes ayrıca tüm özellikleri içeren ancak dışa aktarımı devre dışı bırakılmış ücretsiz bir Community Edition yayımlayarak fiilen sınırsız bir deneme sürümü sundu.

Yaklaşımları tüm arazi işlemlerinde GPU hesaplamasını kullanır: erozyon simülasyonu, nehir oyma ve doku boyama. Fırça araçları, gerçek zamanlı görünüm alanı geri bildirimiyle GPU hızlandırmalıdır. Bu, yukarıda açıklanan ve masaüstü GPU'larda çalışan WebGPU hesaplama işlem hattıyla örtüşür.

Şimdiye Kadar Oluşturduklarımız: 24 Spike ve Üretimdeki Bir Dünya

world/spikes/ dizini, kendi başına çalışabilen 24 prototip içerir. Bunlar basit oyuncak demolar değildir. Her spike'ın belirli bir sorunu çözdüğü, hedefe göre karşılaştırmalı performans ölçümü yaptığı ve bir sonrakine yön verdiği aşamalı bir Ar-Ge işlem hattıdır. Şekillendirme sistemi yalnızca sonraki hacimsel spike'ları değil, bunların tümünü temel alır.

Üretimdeki Yükseklik Haritası Arazisi (world/client/)

Canlı dünya, Three.js WebGL üzerinde parçalara bölünmüş bir yükseklik haritası sistemi kullanır:

  • noise.ts, deterministik bir terrainHeight(wx, wz) fonksiyonuyla FBM değer gürültüsü üzerinden arazi yüksekliği üretir (tepeler için 5 oktav, sırtlar için 4, mikro ayrıntılar için 3)
  • chunk.ts, 3 LOD seviyesine sahip Float32Array yükseklik haritalarından PlaneGeometry örgüleri oluşturur (64 birimlik parça başına 32/8/4 segment) ve tohumlanmış rastgele yerleşim ile nesne başına çarpıştırıcılar kullanarak örneklenmiş ağaçlar/billboard'lar yerleştirir
  • chunk-manager.ts, oyuncunun çevresindeki halkalarda parçaları akışla yükler (LOD0'da yarıçap 1, LOD1'de yarıçap 3, LOD2'de yarıçap 6), stitchEdge() içinde doğrusal enterpolasyonla kenar birleştirme yapar ve fizik katmanı için getHeight(), getNormal() ve resolveCollisions() sağlar
  • terrain-material.ts, eğim ve yüksekliğe dayalı ağırlıklarla MeshStandardMaterial.onBeforeCompile üzerinden 4 katmanlı sıçrama haritası tabanlı doku harmanlama (çim/kaya/kum/toprak) ve katman başına normal harita harmanlama gerçekleştirir
  • character-controller.ts, yerçekimi, yere basma ve eğim reddi (maksimum eğim kosinüsü 50 derece) için her karede arazi yüksekliğini örnekler. Şekillendirme, değiştirilmiş yükseklikleri bu sisteme anında aktarmalıdır; aksi takdirde oyuncu düzenlenen arazinin içinden düşer
  • placement.ts, nesne yerleştirme aracı için parça örgülerine isabet eden bir Raycaster içerir. Fırça aracı, ışın izlemeyi sıfırdan oluşturmak yerine tam olarak bu kalıbı izlemelidir
  • protocol.ts, şu anda PlayerState, PlaceObject, RemoveObject ve Snapshot mesajlarını işleyen world-chunk-do.ts Durable Object üzerinden çok oyunculu senkronizasyon için MessagePack kodlamalı mesajları tanımlar. Arazi düzenlemeleri için yeni bir mesaj türü gerekecektir
  • world-chunk-do.ts (Cloudflare Worker), yerleştirilmiş nesneleri Durable Object depolama alanında kalıcı hâle getirir ve 50 ms aralıklarla bağlı oyunculara yayınlar. Henüz arazi değişikliklerine ilişkin bir kavram içermez

Spike 01-11: Temel Katman

Bu spike'lar, şekillendirmenin bağlı olacağı temel sistemleri doğruladı. Bunları atlamak, şekillendirme sisteminin uyması gereken kısıtları gözden kaçırmak anlamına gelir.

Spike 01 (Arazi + Örnekleme): Three.js'teki ilk arazi prototipi. chunk.ts tarafından hâlâ kullanılan PlaneGeometry + yükseklik haritası kalıbını ve örneklenmiş nesne yerleşimini oluşturdu.

Spike 02 (Rapier Fizik Worker'ı): Bir Web Worker içinde ColliderDesc.heightfield() çarpıştırıcısıyla çalışan Rapier 3D. Otomatik basamak çıkma, eğim sınırları ve zemine yapışma özelliklerine sahip kinematik bir karakter denetleyicisi oluşturdu. Bu spike, fiziğin bir yükseklik alanına karşı ana iş parçacığı dışında çalışabileceğini kanıtladı. Araziyi şekillendirirsek fizik yükseklik alanı yeniden oluşturulmalı veya MC parçaları için bir üçgen örgü çarpıştırıcısıyla değiştirilmelidir.

Spike 05 (LLM Davranışları): Araziyle doğrudan ilişkili değildir ancak oyun nesneleri için JSON davranış şemasını oluşturdu. Şekillendirilmiş arazi özellikleri davranışları tetikleyebileceği için önemlidir (ör. oyulmuş bir nehrin su efektleri oluşturması).

Spike 06 (Parça Akışı): Oyuncu hareket ettikçe dinamik yükleme yapan ilk parça yükleme/değiştirme sistemi. chunk-manager.ts tarafından kullanılan kalıbı oluşturdu: yüklenen ve kaldırılan renkli bölgeler. Şekillendirme, parçalar kaldırılıp yeniden yüklendiğinde düzenleme durumunu korumalıdır.

Spike 07 (Yoğunluk Haritalarından GPU Bitki Örtüsü): Arazi yüksekliğini ve eğimini örnekleyen yoğunluk haritalarıyla yerleştirilmiş örneklenmiş çimler ve ağaçlar. Şekillendirme, bitki örtüsü yerleşimini geçersiz kılar: arazi yüksekliği değişirse ağaçlar havada kalabilir veya gömülebilir. Düzenlenen parçalar için yoğunluk haritası yeniden oluşturulmalıdır.

Spike 08 (Arazi Malzemesi Gölgelendirici Maliyeti): Üç düzlemli projeksiyon, normal haritalar ve 4 katmanlı harmanlama için karşılaştırmalı performans ölçümleri yaptı. Her özelliğin kesin milisaniye maliyetini ölçtü. Üç düzlemli projeksiyon + normaller + 4 katmanın 45+ FPS'de bütçe içinde kaldığını belirledi. Bu bütçe şekillendirilmiş arazi açısından önemlidir: “düzenlenmiş toprak” için 5. bir katman ekler veya oyulmuş yüzeylerde harmanlamayı değiştirirsek ne kadar payımız olduğunu tam olarak biliriz.

Spike 09 (CSM Gölge Bütçesi): 1024^2 çözünürlükte 3 kademeli basamaklı gölge haritaları. Gölge maliyetini yaklaşık 1,5 ms olarak ölçtü. Şekillendirilmiş arazi gölge haritalarını değiştirir, ancak maliyet arazi şeklinden bağımsız olarak sabittir.

Spike 10 (Geometri Clipmap'leri + Geomorphing): Belirme efektini ortadan kaldırmak için LOD seviyeleri arasında geomorphing kullanan iç içe clipmap halkaları. Sabit üçgen sayısı, öngörülebilir GPU maliyeti sağlar. Geomorphing, şekillendirme açısından önemlidir: oyuncu bir LOD sınırının yakınında şekillendirme yaptığında LOD seviyeleri arasındaki geçiş düzenlemeyi yansıtmalıdır. Düzenleme yalnızca yüksek çözünürlüklü halkada bulunuyorsa geomorph hedefi yanlıştır.

Spike 11 (Yükseklik Haritası Parça Akışı): LOD seviyesi başına yüklenmiş/yükleniyor/kaldırılmış durumlarını gösteren görsel bir ızgaraya sahip daha gelişmiş parça akışı. Akış bütçesini belirledi: kare başına yüklenecek maksimum parça sayısı ve LOD yükseltmesi gereken parçaların önceliklendirilmesi. Şekillendirme yeni bir öncelik sinyali ekler: oyuncunun etkin olarak düzenlediği parçalar asla kaldırılmamalıdır.

Spike 12-14: WebGPU + Three.js Entegrasyonu

Spike 12 (WebGPU Marching Cubes): İlk hacimsel spike. Tamamen GPU üzerinde çalışan, animasyonlu küresel mağaralara sahip dört adet 64^3 SDF parçası. Ham WebGPU kullanır: SDF değerlendirmesi için hesaplama işlem hatları, Twinklebear durum tablosuyla MC çıkarımı (her biri 16 girişli 256 yapılandırma), atomik tepe noktası sayacı ve dolaylı çizim. Performans hedefi parça başına <4 ms, 4 parçanın tamamı için <12 ms idi. Bu, GPU MC'nin tarayıcıda gerçek zamanlı yeniden örgüleme için yeterince hızlı olduğunu doğruladı. Sonraki tüm hacimsel spike'lar burada tanımlanan MC durum tablosunu ve WGSL gölgelendiricilerini yeniden kullanır.

Spike 13 (Spike 12'den Temel Sıfırlama): Spike 12'nin ham WebGPU çizim yolunu, arka ucun device öğesine doğrudan erişerek Three.js'in WebGPURenderer bileşeni içinde çalışacak şekilde taşıdı. İşleme hattı hâlâ ham WebGPU kullanır (drawIndirect ve struct Vertex vec4+vec4). Bu, özel hesaplama ile Three.js sahne işlemenin aynı GPU aygıtında birlikte çalışabileceğini kanıtladı.

Spike 14 (Three.js WebGPU Artımlı Sağlamlaştırma): Ham işleme hattını konumlar ve normaller için Three.js StorageBufferAttribute ile değiştirdi. MC hesaplaması doğrudan GPU'da yerleşik bu tamponlara yazar. drawIndirect tamponu, Three.js'in kaç tepe noktası çizeceğini kontrol eder. Sonraki tüm spike'ların kullandığı kalıp budur: hesaplama ham WebGPU olarak kalırken işleme Three.js sahne grafiği üzerinden yapılır. Bu spike'lardaki Three.js sürümü, WebGPU arka ucu kararlı hâle geldikçe 0.170.0'dan 0.172.0'a ilerledi.

Spike 15-17: Transvoxel LOD Birleştirme

Spike 15 (Transvoxel Dikiş İskelesi): Üç bölgeli mimariyi ekledi: MC parçası (hacimsel merkez), geçiş şeridi (MC sınırı ile yükseklik haritası arasındaki dikiş) ve arazi halkası (çevredeki yükseklik haritası). Üçü de aynı malzeme geçişini paylaşır. Bu aşamada geçiş şeridi, gerçek Transvoxel hücreleri değil, yer tutucu bir örgüdür.

Spike 16 (Paylaşılan Yükseklik Haritasıyla Transvoxel +X Yüzü): Tek bir spike'ta iki kritik atılım. İlk olarak SDF'deki düz arazi düzlemini paylaşılan bir Perlin yükseklik haritasıyla değiştirdi: depolama tamponu olarak GPU'ya yüklenen ve SDF hesaplama gölgelendiricisinde çift doğrusal enterpolasyonla örneklenen 257x257 Float32Array. MC yüzeyi ile yükseklik haritası örgüsü artık aynı temel gerçekte uzlaşır. İkinci olarak Eric Lengyel'in referans veri tablolarını GitHub'dan (transitionCellClass, transitionVertexData, transitionCellData) ve npm transvoxel-data paketini alarak +X yüzü için gerçek Transvoxel geçiş hücrelerini uyguladı. CPU, 9 örnekli geçiş hücrelerini (512 yapılandırma, 73 eşdeğerlik sınıfı) değerlendirir, ızgara noktalarındaki SDF değerlerini enterpole ederek tepe noktaları yerleştirir ve aynalanmış durumlarda sarım yönünün tersine çevrilmesini işler.

Spike 17 (İkili MC 1x/2x LOD): Farklı çözünürlüklerde yan yana iki MC parçası. Yüksek çözünürlük: cell_scale=1.0 ile 62 hücre. Düşük çözünürlük: cell_scale=2.0 ile 31 hücre. MC gölgelendiricisine cell_scale ve grid_points uniform'ları eklendi. transition_shrink kullanıma sunuldu: düşük çözünürlüklü parçanın yüz-0 sınır tepe noktaları cell_scale değerinin %15'i kadar içeri çekilerek Transvoxel geçiş hücrelerinin z-fighting olmadan doldurabileceği ince bir boşluk oluşturulur. Üretim sisteminin ihtiyaç duyduğu LOD modeli budur: yakındaki parçalar tam çözünürlükte, uzaktaki parçalar yarı çözünürlükte ve her sınırda Transvoxel.

Spike 18-21: Transvoxel Uç Durumları ve GPU Hızlandırması

Bu dört spike'ın her biri Transvoxel uygulamasındaki belirli bir hata durumunu çözdü. Bunları gruplandırmak, farklı sorunların görünürlüğünü azaltır.

Spike 18 (Yükseklik Haritası 2:1 Dikişi): Transvoxel'i, bir tarafın diğerinin iki katı çözünürlüğe sahip olduğu saf bir yükseklik haritası sınırına uyguladı. MC kullanılmadı. 62 hücreli ve 31 hücreli yükseklik haritası parçaları arasındaki dikiş, %15 düşük yüz küçültmeyle Transvoxel geçiş tablolarından oluşturulur. Bu, Transvoxel'in yalnızca MC'de değil, sadece yükseklik haritası kullanılan durumda da çalıştığını doğruladı.

Spike 19 (64/32/32/16 Köşe Izgarası): En zor birleştirme durumu: farklı çözünürlüklerdeki dört parçanın bir köşe noktasında buluşması (64, 32, 32 ve 16 hücre). Dikiş sistemi dört kenar boyunca (A-B, A-C, B-D, C-D) her yön için doğru sarımla geçiş hücreleri oluşturmalıdır. Bu spike, Transvoxel tablolarının özel durum mantığı gerektirmeden çok çözünürlüklü köşeyi işleyebildiğini kanıtladı.

Spike 20 (GPU Transvoxel Köşesi): 64/32/32/16 köşe düzeninde Transvoxel geçiş hücresi üretimini GPU'ya taşıdı. Animasyonlu arazi için geçiş hücreleri her karede yeniden oluşturulduğunda CPU darboğaz oluşturuyordu. GPU hesaplaması, dikiş tepe noktalarını MC çıkarımıyla aynı geçişte üretir.

Spike 21 (GPU MC + Transvoxel Köşesi): Tam GPU MC çıkarımını ve GPU Transvoxel dikiş üretimini tek bir hesaplama dispatch dizisinde birleştirdi. Hem MC parçaları hem de dört dikişin tamamı GPU üzerinde oluşturulur; tepe noktası sayıları atomik sayaçlarla yönetilir ve drawIndirect ile çizilir. Bu, kesintisiz LOD geçişlerine sahip çok çözünürlüklü hacimsel arazi için eksiksiz GPU işlem hattıdır.

Spike 22-24: Hibrit Mimari

Spike 22 (Hibrit MC/Yükseklik Haritası İlkesi): Temel mimari spike'ı. Parçalar varsayılan olarak yükseklik haritasıdır. Animasyonlu deformasyon küresi bir parçanın AABB'siyle kesiştiğinde o parça MC moduna geçer. Geri kalanlar statik yükseklik haritası örgüleri olarak kalır. Düzen: farklı çözünürlüklerde 64, 32/32 ve 16 hücreli parçalar. Transvoxel dikişleri, MC'den yükseklik haritasına geçişler dâhil tüm sınırları işler. Spike, kare başına MC parça sayısını HM parça sayısına göre ve tepe noktası taşmasını izler.

Spike 23 (İlke Odaklı Parça Modları): Spike 22'nin üzerine bir yama olarak yüklendi. Kamera mesafesi histerezisi (kamera bir eşiğin yakınındayken parçalar modlar arasında titremez) ve bir düzenleme maskesi (deforme edilmiş parçalar, deformasyon kaynağı uzaklaşsa bile MC modunda kalır) ekledi. Şekillendirmenin ihtiyaç duyduğu “kalıcı düzenleme” davranışı budur: oyuncu bir mağara oyduğunda ilgili parça sonsuza kadar hacimsel kalır.

Spike 24 (İlke + Clipmap Halkaları): En gelişmiş spike. Spike 23'teki yakın alan ilke sistemini, Spike 10'daki uzak alan geometri clipmap halkalarıyla birleştirir. Three.js 0.183.1'e yükseltildi. Yakın alan, 64/32/16 çözünürlükte Transvoxel dikişlerine sahip HM/MC hibritini kullanır. Uzak alan, kamerayı takip eden statik merkezli clipmap halkaları kullanır. Eksiksiz arazi işleme mimarisi budur: ihtiyaç duyulan yerlerde parçalara bölünmüş hacimsel şekillendirme, diğer her yerde düşük maliyetli clipmap arazisi.

Neden Surface Nets Değil de Marching Cubes?

Bu kılavuzun harici araştırma bölümü, tarayıcıda arazi şekillendirme için en güçlü aday olarak Surface Nets'i öneriyor. Ancak işlem hattındaki tüm spike'lar Marching Cubes kullanıyor. Bu tesadüf değil.

MC'nin belirleyici avantajı, son derece kolay paralelleştirilebilmesidir: her küp tamamen bağımsızdır. Spike 12-24'teki WGSL compute shader'ları, hücreler arası hiçbir iletişim olmadan küp başına bir thread çalıştırır. Vertex tahsisini atomik sayaçlar yönetir. Bu yaklaşım GPU workgroup'larına mükemmel biçimde uyar.

Surface Nets, yüzey içeren her hücreye bir vertex yerleştirir ve ardından komşuları birbirine bağlar. Bu komşuluk bağlantısı, hücreler arası bir bağımlılık oluşturur. fast-surface-nets crate'i bunu CPU'da dikkatli bir iterasyon sırasıyla yönetir. GPU'da ise ya iki geçişli bir yaklaşım (önce vertex'leri bul, sonra bağla) ya da workgroup'lar içinde paylaşımlı bellek gerekir. Her ikisi de WebGPU'da mümkündür, ancak karmaşıklığı artırır.

Pratik öneri: şekillendirme işlem hattında Marching Cubes kullanmaya devam edin. Kod tabanımızda kendini kanıtladı, WGSL shader'ları mevcut ve benchmark'ları yapıldı; ayrıca Transvoxel dikiş sistemi MC'nin kenar tabanlı vertex yerleşimi etrafında oluşturuldu. MC'nin ikili verilerdeki aliasing sorunu görünür hâle gelirse Surface Nets'i yeniden değerlendirmeye değer; ancak değerlerin yumuşak gradyanlar olduğu SDF arazilerinde MC temiz sonuçlar üretir.

Arazi Şekillendirme İçin Pratik Mimari

Spike dizisi render işlem hattını çözdü. Geriye fırça sistemi, oyun sistemlerine yayılan yan etkiler ve çok oyunculu senkronizasyon kalıyor. İşte tüm spike'ların üzerine inşa edilen plan.

Aşama 1: Heightmap Şekillendirme (Minimum Değişiklik, Maksimum Kapsam)

Üretim ortamındaki world/client/ koduna chunk heightmap'lerini değiştiren fırça araçları ekleyin. Bu, mevcut WebGL renderer ile çalışır ve WebGPU gerektirmez.

Fırça girdisi: placement.ts içindeki PlacementTool kalıbını izleyin. Bu araçta hâlihazırda chunkManager.getChunkMeshes() ile kesişim arayan ve isabet noktasında bir hayalet mesh izleyen bir Raycaster bulunuyor. Bir TerrainBrushTool da aynı raycast işlemini gerçekleştirir, ancak nesne yerleştirmek yerine chunk heightmap'ini değiştirir. World.onMouseDown işleyicisi zaten araç durumuna göre yönlendirme yapıyor.

Chunk değişikliği (Chunk.applyBrush): Fırçanın dünya konumunu heightmap ızgara koordinatlarına eşleyin. Fırça yarıçapı içindeki her ızgara noktası için falloff ağırlıklı yer değiştirmeyi hesaplayıp heightmap değerine ekleyin veya değerden çıkarın. Ardından mesh'i güncelleyin: vertex Y konumlarını değiştirilmiş heightmap'ten ayarlayın, merkezi fark yöntemiyle normalleri yeniden hesaplayın (chunk.ts dosyasının 155-158. satırlarında kullanılan aynı terrainHeight(wx +/- eps, wz) kalıbı) ve eğime dayalı doku harmanlamasının güncellenmesi için etkilenen bölgede terrain-material.ts içindeki createSplatMap() aracılığıyla splat map'i yeniden oluşturun.

Karakter kontrolcüsü: CharacterController.update(), karakteri zeminde tutmak için her karede getHeight() çağırır. ChunkManager.getHeight(), chunk'ın heightmap Float32Array'inden okuyan Chunk.sampleHeight() metoduna yönlendirir. Bu diziyi doğrudan değiştirdiğimiz için karakter kontrolcüsü değişikliği sonraki karede hiçbir ek bağlantı gerektirmeden algılar.

Nesne geçersizleştirme: chunk.ts içindeki ağaç instance'ları, oluşturulma sırasında terrainHeight() örneklenerek yerleştirilir. Şekillendirmeden sonra etkilenen alandaki ağaçlar yanlış yükseklikte kalabilir. Aşama 1 bunu erteleyebilir (küçük düzenlemelerde ağaçlar hafifçe havada kalır). Aşama 2'de yükseklikleri yeniden örnekleyen ve instance matrislerini yeniden oluşturan bir chunk.invalidateObjects() gerekir. Aynı durum resolveCollisions() içinde kullanılan collider'lar için de geçerlidir.

Rapier fiziği (entegre edilmişse): Spike 02, heightfield collider'ların çalıştığını kanıtladı. Rapier etkinse değiştirilen chunk için heightfield collider'ın yeniden oluşturulması veya yamalanması gerekir. Rapier'ın ColliderDesc.heightfield() metodu düz bir Float32Array aldığı için bu, doğrudan bir değiştirme işlemidir.

Ağ senkronizasyonu: protocol.ts dosyasına MsgType.TerrainEdit = 10 ekleyin:

typescript
interface TerrainEditMsg {
  t: MsgType.TerrainEdit
  cx: number
  cz: number
  brush: {
    wx: number
    wz: number
    radius: number
    strength: number
    falloff: number
    operation: number
  }
}

WorldChunkDO bunu tüm istemcilere yayınlar ve Durable Object depolamasında tutulan chunk başına düzenleme günlüğüne ekler. Sonradan katılan istemciler düzenleme günlüğünü Snapshot mesajında alır ve arazi durumunu yeniden oluşturmak için tekrar oynatır. Tüm istemciler aynı deterministik fırça işlevini uyguladığından aynı heightmap üzerinde birleşir.

Chunk'ı kaldırma/yeniden yükleme: Spike 06 ve Spike 11, streaming kalıbını oluşturdu. Bir chunk kaldırılıp daha sonra yeniden yüklendiğinde, o chunk'a ait düzenleme günlüğünün temel prosedürel heightmap üzerine yeniden uygulanması gerekir. Düzenleme günlüğü sunucu tarafında (Durable Object) saklanır ve Snapshot mesajına dâhil edilir.

Aşama 2: Spike 22-24 Mimarisiyle Hacimsel Şekillendirme

Spike 24 işlem hattını üretim dünyasına taşıyın. Oyuncu yüzeyin altını şekillendirdiğinde (mağara oymak veya tünel kazmak gibi), etkilenen chunk heightmap modundan MC moduna geçer.

WebGPU renderer geçişi: Spike 13-14, Three.js'in WebGPURenderer bileşeninin sahne grafiğiyle birlikte özel compute işlemlerini barındırabildiğini kanıtladı. Üretim dünyası, MC chunk'ları için StorageBufferAttribute kullanarak WebGLRenderer'dan WebGPURenderer'a geçer. WebGPU kullanılamadığında Aşama 1'deki yalnızca heightmap kullanan yola geri dönülür.

Chunk başına SDF tahsisi: Spike 22'nin hibrit kalıbını izleyin. Her chunk bir heightmap olarak başlar. İlk hacimsel fırça darbesinde bir 64^3 Float32Array tahsis edin, heightmap'i örnekleyerek başlatın (her noktadaki SDF değeri world.y - heightmap_value olur) ve MC render işlemine geçin. Spike 23'teki politika sistemi, chunk'ın kalıcı olarak MC modunda kalmasını sağlar (düzenleme maskesindeki "kalıcı düzenleme" davranışı).

SDF shader'ında paylaşılan heightmap: Spike 16'daki height_at() işlevi. Chunk'ın heightmap'ini bir GPU storage buffer'a yükleyin. SDF compute shader'ı max(height_sdf, edit_sdf) ifadesini değerlendirir; burada height_sdf = world.y - height_at(world.xz) ve edit_sdf fırça değişikliklerini içerir. MC ve heightmap chunk'ları, sınırlarında aynı temel gerçeklik üzerinde uzlaşır.

Transvoxel dikişleri: Spike 15-21'deki tam yığın. MC-heightmap sınırları, daraltma boşluğuna sahip geçiş hücrelerini kullanır. Farklı çözünürlüklerdeki MC-MC sınırları, Spike 17'nin çift LOD kalıbını kullanır. Spike 19'daki köşe durumu, dört yönlü kesişimleri yönetir. Spike 21'in GPU compute işlemi, tüm dikiş geometrisini aynı dispatch içinde üretir.

Clipmap uzak alanı: Şekillendirme menzilinin dışındaki arazi için Spike 24'ün clipmap halkaları kullanılır. Şekillendirme bu halkalara hiçbir zaman dokunmaz; halkalar temel prosedürel heightmap'i örnekler.

Geomorphing: Spike 10'daki geomorphing, LOD geçişlerindeki ani belirmeyi ortadan kaldırır. Düzenlenmiş chunk'larda geomorph hedefi düzenlemeyi de içermelidir. Bir chunk LOD0'da MC ise ve LOD1 komşusu bir heightmap ise geomorph, iki temsil arasında harmanlama yapar. Bunun için düzenleme günlüğünün daha düşük LOD'larda bile örneklenmesi gerekir.

Materyal bütçesi: Spike 08, normallerle birlikte 4 katmanlı triplanar materyali 45+ FPS'de benchmark etti. MC chunk'ları da aynı materyale ihtiyaç duyar. Splat map, heightmap eğimi yerine SDF gradyanından üretilebilir (dik = kaya, düz = çim). Bu, 4 katmanlı bütçe içinde kalır.

Bitki örtüsü geçersizleştirme: Spike 07'nin yoğunluk haritasına dayalı bitki örtüsü, arazi yüksekliğine ve eğimine bağlıdır. Bir chunk MC moduna geçtiğinde, ağaç instance'ları SDF yüzeyi örneklenerek yeniden oluşturulmalıdır. Çıkıntıların üzerindeki veya mağaraların içindeki ağaçlar ayıklanmalıdır. chunk.ts içindeki instanced mesh matrisleri yeni yüzeyden yeniden oluşturulur.

Aşama 3: Geri Alma/Yineleme ve Ağ Senkronizasyonu İçin CSG Düzenleme Ağaçları

Ham SDF mutasyonunu bir CSG işlem ağacıyla değiştirin. Her fırça darbesi, bir işlemle (ekleme, çıkarma, yumuşak harmanlama) birlikte bir ilkel şekli (küre, kapsül, kutu) ağaca ekler. SDF, ağaçtan yeniden hesaplanır.

Avantajları:

  • Tahribatsızdır: herhangi bir düzenleme geri alınmak üzere ağaçtan kaldırılabilir
  • Ağ açısından verimlidir: ham alan değerlerini değil, CSG işlemini yayınlar
  • Deterministiktir: tüm istemciler aynı işlem dizisinden aynı SDF'yi oluşturur
  • ALICE-SDF'nin CSG ağaç diff/patch özelliği, ağ genelinde bant genişliği açısından verimli senkronizasyon ve geri alma/yineleme sağlar

Durable Object depolaması: Chunk başına düzenleme ağacı, Aşama 1'deki düz düzenleme günlüğünün yerini alır. WorldChunkDO, ham heightmap deltaları yerine CSG ağaç yapısını saklar. Snapshot mesajları ağacı içerir ve sonradan katılan istemciler yerel SDF'yi üretmek için ağacı değerlendirir.

Aşama 4: İş Birliğine Dayalı Şekillendirme

Sunucu tarafından sıralanan işlem tekrarıyla eşzamanlı düzenleme desteği ekleyin. Durable Object her düzenlemeye zaman damgası ekler ve bunları sırayla yayınlar. Sonradan katılan istemciler işlem günlüğünü alarak dünya durumunu yeniden oluşturur. Mevcut Snapshot mesaj türü, chunk başına arazi düzenleme geçmişini içerecek şekilde genişletilir.

Fırça darbeleri küçük, yerelleştirilmiş ve eklemeli/çıkarmalı olduğundan, eşzamanlı düzenlemelerin biraz farklı sırayla uygulanmasının görsel sonucu genellikle "doğru" sıradan ayırt edilemez. Sunucu sıralamasıyla son yazanın kazanması yeterlidir. Durable Object'in tick() işlevi (şu anda oyuncu durumu için 50 ms aralıklarla çalışıyor), arazi düzenleme yayınlarını aynı döngüye ekler.

Temel Kaynaklar

Algoritmalar:

  • Lorensen & Cline, "Marching Cubes" (1987)
  • Eric Lengyel, "Transvoxel Algorithm" (2009), transvoxel.org
  • Losasso & Hoppe, "Geometry Clipmaps" (SIGGRAPH 2004)
  • "A High-Performance SurfaceNets Discrete Isocontouring Algorithm" (arxiv 2401.14906, 2024)
  • MCHex (arxiv 2511.02064, 2025)

Uygulamalar:

  • bevy-sculpter v0.18.0 (Rust, Surface Nets + SDF fırçaları)
  • fast-surface-nets (Rust, 20M üçgen/sn)
  • ALICE-SDF v1.3.0 (Rust + WASM, CSG ağaç diff/patch)
  • WebGPU SDF Editor (Nijhoff, Ocak 2026)
  • SculptingPro (Unity çalışma zamanı şekillendirme API'si)
  • TerraBrush (Godot arazi şekillendirme GDExtension'ı)

Oyunlar:

  • Dreams (Media Molecule, SDF + nokta bulutu render işlemi, SIGGRAPH 2015)
  • Teardown (Voxagon, voxel DDA ışın izleme, deterministik çok oyunculu yıkım)
  • Mike Turitzin'in SDF motoru (brick map'ler + geometry clipmap'ler, Ocak 2026)

Ağ:

  • "Optimizing payload size for voxel state synchronization" (Oulu, 2024)
  • Teardown çok oyunculu modu (yarı deterministik yıkım senkronizasyonu, Mart 2026)
  • cSculpt (çok çözünürlüklü birleştirmeyle iş birliğine dayalı mesh şekillendirme)
Hemen deneyinDaha az şekillendir, daha erken oyna

Fırçaya dokunmadan arazi odaklı bir oyun oluştur.

Ücretsiz oluştur →Ücretsiz, tarayıcınızda çalışır, kurulum yok.