holodepth

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:

  1. 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.
  2. 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.
  3. 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.
  4. Dequantization: Izgara üzerine oturtulmuş tam sayılar, ölçek ve ofset ile orijinal float aralığına geri çarpılarak döndürülür.
  5. 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.