Three.js · Varlık · Draco
Decode süreci: tarayıcıdaki dijital simya
Decode süreci, paketlenmiş (encoded) verinin çalışma zamanında (runtime) tekrar GPU’nun anlayabileceği ham vertex buffer yapılarına dönüştürülmesidir. Bu işlem, kullanıcı modelin yüklenmesini beklerken arka planda saniyeler — hatta uygun koşullarda milisaniyeler — içinde gerçekleşir.
Encode tarafı için Encode süreci, sıkıştırmanın matematiği için Mesh compression ve Vertex quantization sayfalarına bakın. glTF hattında bir sonraki durak: Scene graph.
Çalışma zamanında ne olur? Adım adım yolculuk
Kullanıcı örneğin holodepth.com adresine girdiğinde ve bir 3D model yüklenmeye başladığında kabaca şu trafik gerçekleşir:
- Veri transferi: Sıkıştırılmış .glb dosyası (Draco içerikli) ağ üzerinden iner. Dosya küçük olduğu için bu aşama çoğu zaman hızlıdır.
- Worker iş parçacığına geçiş: Ana iş parçacığını (UI) kilitlememek için decompress (çözme) işlemi genellikle bir Web Worker’a aktarılır.
- WASM çekirdeği: Draco’nun C++ ile yazılmış çözücü kodu WebAssembly üzerinde çalışır; sıkıştırılmış bitstream burada işlenir.
- Dequantization: Izgara üzerine oturtulmuş tam sayılar, ölçek ve ofset ile orijinal float aralığına geri çarpılarak döndürülür.
- Reconstruction: Noktalar arası bağlantı (connectivity) yeniden kurulur; üçgen ağ (mesh) çizime hazır öznitelik akışlarına dönüşür.
Bu adımlar bittiğinde geometri ana bellekte ham tamponlar olarak durur; çizim için bir sonraki aşama bu verinin GPU belleğine yazılmasıdır (buffer upload). Yani «decode bitti» ile «karede hazır» arasında hâlâ bir köprü vardır; ayrıntılar için aşağıdaki performans notlarına bakın.
DRACOLoader: Three.js ve ötesi
Web geliştiricileri için bu sürecin yönetim merkezi DRACOLoader’dır: tarayıcı ile Draco kütüphanesi arasındaki köprüyü kurar ve GLTFLoader ile birlikte çalışır.
Neden ayrı bir loader? Standart GLTFLoader, Draco ile sıkıştırılmış tamponu tek başına «okuyamaz»; uzantı altındaki sıkıştırılmış veriyi açmak için Draco çözücüsüne ihtiyaç duyar.
Konfigürasyon: DRACOLoader’a çözücünün WASM / JS dosyalarının sunucuda nerede durduğunu
söylemeniz gerekir. Geliştirmede bunlar çoğu zaman
node_modules/three/examples/jsm/libs/draco/ altındadır; canlı ortamda aynı
dosyaları statik olarak (CDN veya kendi asset
klasörünüz) servis etmek yaygındır.
GLTFLoader örneğiniz bu köprüyü şu satırla tanır; aksi hâlde yükleyici Draco uzantılı tamponu çözemez:
loader.setDRACOLoader(dracoLoader);
Tarayıcı tarafı: WebAssembly neden kritik?
Draco’nun decompress yolu matematiksel olarak yoğundur. Aynı iş saf JavaScript ile yazılsaydı çoğu senaryoda belirgin şekilde daha yavaş kalırdı; büyük modellerde sekme «yanıt vermiyor» hissi oluşabilirdi.
WebAssembly ile C++ seviyesine yakın bir çekirdek tarayıcıda çalışır; pratikte yoğun çözümleme yüklerinde saf JS’e kıyasla çoğu zaman büyük çarpanlarla (örneğin onlarca kata kadar çıkan ölçümler raporlanabilir) hızlanma görmek mümkündür — tam sayı model boyutuna, tarayıcıya ve donanıma göre değişir. Kullanıcı için sonuç: indirme bittiği anda geometrinin hızlıca sahneye oturmasıdır.
Dikkat edilmesi gereken performans tuzakları
Decode süreci ağ tasarrufu sağlasa da «bedava» değildir:
- Bellekte ani yükseliş (memory spike): Geçiş anlarında sıkıştırılmış baytlar ile açılmış ham tamponlar kısa süreliğine de olsa aynı anda ana bellekte bulunabilir. Özellikle büyük tek mesh’lerde «dosya küçük» olsa da RAM baskısı ani sıçrayabilir.
- GPU yüklemesi: Çözümleme CPU / worker tarafında biter; ardından WebGL / WebGPU yolunda tamponların cihaz belleğine aktarılması ayrı maliyettir. Yoğun geometride bu upload dalgası kare zamanlamasını etkileyebilir.
- Akış (streaming) sınırı: Draco mesh çözümlemesinde dosya parça parça gelse bile, tipik kullanımda ilerlemeli (progressive) decode beklentisine uygun bir «yarım ağ çiz» modeli yoktur; pratikte ilgili tamponun tamamlanması beklenir.
- CPU maliyeti: Dosya küçüldükçe bant genişliği rahatlar; fakat açma işi işlemciyi yükler. Çok düşük donanımda agresif sıkıştırma, kısa süreli takılmalara yol açabilir.
- Worker sayısı ve çekirdekler: Three.js tarafında DRACOLoader’ın setWorkerLimit() ile verdiğiniz üst sınır, fiziksel çekirdek ve eşzamanlı model sayısıyla birlikte düşünülmelidir: çok düşük sınır çekirdekleri boş bırakır; çok agresif sınır ise aynı anda çok fazla ağır decode isteğinde CPU’yu doyurup başka işlere nefes bırakmayabilir.
- Kare düşüşü (frame drop) riski: Decode’u worker’a almak ana iş parçacığını CPU açısından rahatlatır; buna karşılık sahne kurulumu, materyal atamaları ve büyük buffer yüklemeleri yine ana iş parçacığında işlendiği için, özellikle tek karede toplanan GPU upload dalgaları kısa süreli takılmaya yol açabilir.
- Önbellek (cache): Tarayıcı ağ önbelleği sıkıştırılmış .glb’yi tekrar indirmeyi azaltabilir; fakat tipik akışta her sayfa yükünde JavaScript tarafında Draco decode’unun yeniden çalışması yaygındır. Aynı geometriyi tekrar tekrar açmak istemiyorsanız, uygulama düzeyinde (bellek / IndexedDB / kendi önbelleğiniz) tutma stratejisi ayrıca tasarlanmalıdır.
Bölüm özeti ve HoloDepth notu
Döngü tamamlandı:
- Encode: Boyutu küçült; bant genişliğini koru.
- Transfer: Veriyi kullanıcıya ulaştır.
- Decode (WASM): İşlemciyi kullanarak veriyi CPU / GPU yoluna hazır hale getir.
HoloDepth son not
Bir web 3D projesinde başarı, yükleme süresi ile çözümleme süresi arasındaki dengeyi kurmaktır. Draco bu dengeyi yönetmek için güçlü bir anahtar sunar: ağı küçültürsünüz, sonra maliyeti bilinçli biçimde decode tarafında ödersiniz.