Three.js · Varlık · Draco
Vertex quantization: hassasiyetten hıza giden yol
3B modeli saklarken en büyük engellerden biri, çoğu zaman gereksiz süreklilik hassasiyetidir: bir köşenin uzaydaki yerini anlamsız derecede ince bilmek, ekranda fark edilmeyen bir avantaj sağlamadan veriyi şişirir. Vertex quantization (köşe nicelemesi), bu fazlalığı kontrollü biçimde budama işlemidir.
Bu sayfa yalnızca konum kanalına odaklanır; özniteliklerin tamamı ve GPU köprüsü için
Öznitelik
sıkıştırma · position ve
Mesh compression · niceleme ile birlikte okuyun.
Önce okuyun: Ağ → decode → GPU zinciri.
«Nasıl küçültüyoruz?» — adım adım niceleme
Nicelemeyi, sürekli bir sinyali dijital bir ızgara (grid) üzerine oturtmaya veya görüntü çözünürlüğünü bilinçli düşürmeye benzetebilirsiniz: amaç bilgi kaybetmek değil, görsel toleransın altındaki ayrımları taşımayı bırakmaktır.
- Bounding box (sınırlayıcı kutu): Modelin kapladığı hacmi içine alan eksenlere hizalı bir kutu seçilir; niceleme bu kutunun içinde yapılır. Kutu gereğinden genişse, aynı bit bütçesi daha kaba bir dünyaya yayılır.
- Izgara oluşturma: Kutunun her ekseni, seçilen bit
derinliği
biçin yaklaşık 2b eş aralıklı parçaya bölünür. Örneğin eksen başına11bit, o eksende 2048 ayrık konum demektir (211). - Snap (mıknatıslama): Ham verideki 32-bit float bileşenler (ör. uzun ondalık kuyruklu bir değer), her eksende ızgaradaki en yakın tam sayı indeksine yuvarlanır.
- Açma (dequantization): İstemci aynı kutu ve bit bilgisini kullanarak indeksleri tekrar dünya uzayına ölçekler; bu çarpma / kaydırma ucuzdur, maliyet çoğu zaman sıkıştırılmış tel + entropy tarafındadır.
Motor seviyesi formüller (eksen başına)
Pratikte x, y, z birbirinden bağımsız niceleme görür: her eksen için
kendi min, max ve b değeri (veya ortak kutu ile
paylaşılan sınırlar) kullanılır; aşağıdaki ifadeler tek bir bileşen içindir.
range = max − min, b bit ve q saklanan nice
değer olsun. Sürekli değerden tamsayıya geçişte motorlar çoğu zaman en yakın ızgaraya
yuvarlar (round). Açma (dequantization) aynı range ve b ile
tersine çevirir; böylece encode → tel → decode
→ GPU hattı kapanır:
q = round((value - min) / (max - min) * (2^b - 1)) value = min + (q / (2^b - 1)) * range
Hata mertebesi. İki komşu ızgara noktası arası adım kabaca
range / (2b − 1)’dir; yuvarlama sonrası mutlak hata en fazla
yaklaşık yarım adım ile sınırlıdır. Büyük b için bu,
kabaca range / 2b mertebesinde düşünülebilir — yani bit
arttıkça aynı kutuda hata üstel olarak küçülür.
Hassasiyet: sayıların dili
Üretimde her köşe konumu çoğu zaman üç adet 32-bit float (x, y, z) olarak gelir: bu, ince gradyanlar için esneklik sunar; fakat web teslimatında aynı bilgi yoğunluğu her zaman gerekmeyebilir.
Nicelemede ise tipik tablo şöyle düşünülür: eksen başına b bit ile o eksende
2b ayrık seviye vardır; üç eksen birlikte düşünüldüğünde
konum «hücre» sayısı bu seviyelerin çarpımıyla büyür. Ham float’ın
anlamdaki «sonsuz» sürekliliği yerine, sınırlı bir kod kitabı taşınır.
Sonuç: köşe başına düşen bit genellikle belirgin biçimde düşer; tam yüzde modelin
ölçeğine, kutuya ve b seçimine bağlıdır.
Bu dönüşüm kayıplı (lossy) olabilir; kazanç, dosya boyutu ve decode sonrası ara temsilin hafiflemesi — takas masası yine geçerlidir.
GPU tarafı: ölçek + kaydırma
Nice değer VRAM’de tamsayı olarak dursa bile, köşe işlerken
genellikle tekrar dünya veya model uzayına çevrilir; bu, shader
veya CPU tarafında aynı matematiğin çarpan + toplam
(scale + offset) biçiminde yazılması demektir.
Örneğin bir bileşen için scale = range / (2b − 1) ve
offset = min seçilirse value = q × scale + offset — yani
yukarıdaki açma formülünün
doğrudan ALU dostu yazımı.
Tamsayı depolama avantajı
Uint16 / Uint32 gibi sıkı tamsayı temsiller, aynı köşe sayısında daha az bayt ve çoğu mimaride daha öngörülebilir hizalama (alignment) sunar; bu da bellek kopyalama ve önbellek satırı kullanımında küçük ama ölçekte hissedilir kazançlar doğurabilir. Float tamponla karışık düzenlerde (interleaved) yine de düzen seçimi ölçümle doğrulanmalıdır — Attributes & buffers sayfasındaki düzenle birlikte düşünün.
Görsel kalite: ne kadar kaybediyoruz?
Niceleme kaybı kontrollü olmalıdır; kontrolsüz düşük bit, geometriyi ızgaraya «fırlatır».
Wobbling ve z-fighting riski
Bit çok düşükse (ör. eksen başına 8 gibi agresif değerler), köşeler büyük
adımlarla kayar; animasyon veya kamera hareketinde yüzeyde dalgalanma
(wobbling) hissi doğabilir. Birbirine çok yakın yüzeylerde derinlik
ayrımı zayıflayınca z-fighting (titreyen çakışan yüzey) de
tetiklenebilir.
Bit için pratik denge
11–12 bit (eksen başına): birçok vitrin ve ürün görüntüleyicide, tipik izleme mesafesinde başlangıç tatlı noktası olarak sık seçilir. 14–16 bit: geniş dünya ölçeği, şehir ölçeği tarama veya mühendislik doğruluğu gerektiren içeriklerde daha güvenli taraftır.
Yüksek bit ile düşük bit farkını görmek için aynı kamerada yan yana A/B vitrin kurmak en hızlı kalite kontrolüdür; tek kare ekran görüntüsü, özellikle düşük bitte köşe kaymasını netleştirir.
İnteraktiv laboratuvar: bbox + ızgara + snap
Aşağıdaki sahne harici model yüklemez; yüksek segmentli prosedürel
düzlemde yüksek frekanslı yükseklik (detay) vardır — düşük bitle bu detay
bloklaşır ve köşeler yukarıdaki
q = round((value - min) / (max - min) * (2^b - 1)) mantığıyla aynı
sınırlayıcı kutu içinde ızgaraya
kilitlenir. Tek sahne modunda bit sürgüsü (8–16) geometriyi anında
yeniden üretir; Split modunda sol 16
bit, sağ 8 bit sabit karşılaştırma (ortadaki tutamacı
sürükleyebilirsiniz). Izgara ve hata görselleştirme
onay kutuları aşağıdadır. Öznitelik laboratuvarı kanal renklerini gösterirken, burada
odak şekil (konum tamponu) üzerindedir.
Amaç: aynı yüksek frekanslı yüzeyde b küçüldükçe
snap’in artması; 8 bitte «voksel» hissi, 14–16 bitte daha pürüzsüz silüet.
Izgara (8 bit XZ kafesi) düşük bitten otomatik görünür; yüksek bitte
kaybolur — «çözünürlük artıyor» hissi. Hata görselleştir tepe başına
orijinal konuma göre sapmayı renklendirir; lejant yalnızca tek sahne + bu mod açıkken
görünür. Bit sürgüsü değişince kısa bir ease (≈0,18 sn) yeni ızgaraya
oturmayı hissettirir. Orijinal alt katman tek sahne modunda, nicelemesiz
yüzeyi hafif gri ve biraz altta gösterir; fark özellikle düşük bitte
okunur. Split modunda bit sürgüsü
devre dışıdır; sol ve sağ yarı farklı b ile aynı matematiği gösterir ve sağ
yarıda 8 bit ızgarası görünür. Wobbling bu demoda
canlandırılmaz; sayfadaki wobbling
notu hareketli sahneler içindir.
Ölçek faktörü
Aynı b, farklı dünya ölçeklerinde farklı fiziksel adım
demektir.
Küçük bir obje dar kutuda 11 bit ile genelde temiz kalırken; kilometrelerce uzanan bir
stadyum veya şehir modelinde aynı bütçe, detaylarda bloklaşma / voksel
hissi üretebilir. Bu yüzden bit seçimi yalnız «kalite kaydırıcısı» değil, kutu
boyutu + sahne ölçeği ile birlikte düşünülmelidir.
Floating origin ve büyük dünya
Dünya koordinatları milyonlarca birime çıktığında, saf float32 zaten inceleme (precision) sorunları yaşar; üzerine kaba niceleme bindiğinde artefakt daha erken görünür. Bu yüzden büyük sahnelerde kamera veya oyuncuya göre periyodik orijin kaydırma (floating origin / dünya yeniden merkezleme) sık kullanılır: geometri lokal uzayda küçük kalır, dev öteleme üst node’da tutulur — Holodepth notu ile aynı ailedir.
Scene graph ve hiyerarşi için Scene graph sayfasına bakın.
HoloDepth teknik notu
Merkeze yakın tutmak
Görsel kaliteyi korumada sık işe yarayan pratik: geometriyi mümkün olduğunca orijine yakın (0, 0, 0 çevresinde) çalışmak ve büyük ötelemeleri üst düğüme (node dönüşümü) taşımaktır. Böylece niceleme hatası, dünya uzayında daha homojen dağılır; aşırı büyük mutlak koordinatlarda float zaten incelir, üstüne kaba bir ızgara bindiğinde artefakt daha çok belli olur.
Bu not, Scene graph düşüncesiyle birleşince özellikle anlamlıdır: geometriyi «yerelde» tutup sahneyi dışarıda ölçeklemek.