Three.js · Etkileşim · Raycaster
Raycaster performansı: maliyet ve verimlilik
Raycasting, doğası gereği pahalı bir işlemdir. Her karede (frame) binlerce poligonun üzerinden geçmek, özellikle mobil cihazlarda ve tarayıcı tabanlı uygulamalarda FPS düşüşlerine, ısınmaya ve takılmalara yol açabilir.
Bu sayfa üç soruya odaklanır: ne kadar geometri taranıyor, ne sıklıkla, hangi doğrulukta? Ön okuma: Continuous vs. single, Bounding volume, Layer filtreleme.
İşlem maliyetini belirleyen faktörler
Raycast performansını tipik olarak üç ana değişken belirler. Bunlar birbirinden bağımsız değildir: sık tetiklenen ama ucuz bir kutu testi, seyrek ama ağır bir üçgen turundan daha az yorucu olabilir — bu yüzden tek tek düşünmek yerine çarpım olarak görmek faydalıdır.
Sahne karmaşıklığı — geometri ve arama alanı
Sahnedeki toplam obje ve poligon (triangle) sayısı arttıkça, tipik uygulamalarda raycaster belirli bir aday kümesi üzerinde dolaşır; aday ne kadar geniş ve üçgen başına test ne kadar pahalıysa maliyet o kadar artar. Çoğu sahne için ilk daraltma geometriden değil aday sayısından gelir: yüzlerce bağımsız mesh, tek tek işaretçi ile tek tek test edildiğinde maliyet doğrusal büyür.
Çalıştırma frekansı — single veya continuous
Işının saniyede kaç kez fırlatıldığı (single vs. continuous), aynı geometride bile toplam iş yükünü doğrudan çarpar: tıklama başına bir örnek ile her karede bir örnek aynı şey değildir. Sürekli tarama davranışını sayıların diliyle bağlamak için bkz. Continuous vs. single raycast.
Test hassasiyeti — kutu mu, üçgen mi?
Bounding box gibi kaba bir test mi, yoksa intersection ile poligon bazlı detaylı bir test mi yapıldığı, başına düşen matematik maliyetini değiştirir. Genelde üretimde önce kabaca ele, gerektiğinde daralt sırası kullanılır: uzaktaki seçim için kutu yeterliyken, yüzeye yapışık hassas seçimde üçgen testi kaçınılmazdır.
Özet: üç faktörün çarpımı pratikte “anı başına iş”e yaklaşır — birini düşürmek diğer ikisini olduğu gibi bıraksanız bile ölçülebilir rahatlama verir; tam çözüm ise B bölümündeki stratejiler ile bu üçlünün her birini bilinçlice budamaktır.
Stratejik optimizasyon yöntemleri
Profesyonel bir mimaride “her şeyi her zaman taramak” yerine, sadece gerekeni gerektiği kadar taramak ilkesi benimsenir.
1. Gereksiz taramadan kaçınma — tetikleyiciyi bilinçle
En büyük performans artışı, raycast işlemini yalnızca kullanıcı bir aksiyon aldığında çalıştırmaktır.
- Olay bazlı çalıştırma: Fare hareket etmiyorsa veya kullanıcı tıklamıyorsa raycast’i tamamen uyutmak.
- Throttle & debounce: Hareketi takip ediyorsanız (hover), işlemi her milisaniyede değil — örneğin her 50 ms’de bir çalışacak şekilde sınırlamak. Detaylı ritim karşılaştırması için Continuous vs. single raycast.
Kısa fark: throttle sabit aralıkta en fazla bir örnek üretir; debounce ise duraksama sonrası tek sefer çalıştırmaya yaklaşır — ikisi de “aynı saniyede gereksiz yüzlerce tarama”yı keser; hangisinin uygun olduğu etkileşim tasarımına bağlıdır (ör. sürekli izlenen imleç mi, durunca güncellenen panel mi).
2. Obje sayısını ve kapsamını sınırla — adayı küçült
Işının dünyadaki her şeyi kontrol etmesine izin vermeyin:
- Frustum culling: Kameranın görüş alanı dışında kalan objeleri raycast aday listesinden çıkarmak (mantık olarak sahne düzenine bağlıdır).
- Mesafe sınırı (far plane / maxDistance): Işının sonsuza gitmesini engellemek; örneğin 100 birimden uzaktaki objeleri taramayı bırakmak.
Bu iki başlık genelde birlikte düşünülür: görüş dışı veya çok uzak nesneler hem çizmeye hem de seçime dahil edilmeyecekse, aday kümesi doğrudan küçülür. Semantik olarak benzer bir daraltma için katman bazlı filtre de kullanılabilir — Layer filtreleme ile “ışın şunu hiç görmesin” kuralı kurmak, özellikle UI vs. dünya ayrımında sıktır.
3. Uzamsal bölümleme — hücre ve ağaç ile tarayı daralt
Bu yapı, yoğun sahnelerde raycaster maliyetini düşürmenin sık kullanılan yoludur: sahneyi görünmez hücrelere bölerek ışının yalnızca yakınındaki objelerle test edilmesini sağlamak.
- BVH (Bounding Volume Hierarchy): Objeleri ağaç gibi gruplar; dal çarpışması yoksa o dala bağlı çok sayıda yaprağı tek seferde elemek mümkündür.
- Octree / ızgara (grid): Uzayı küplere böler; ışın hangi bölgelerden geçiyorsa yalnızca o bölgelerdeki objelerle test.
Three.js çekirdek Raycaster sahne grafiğini doğrusal tarar; çok büyük modellerde harici hızlandırıcılar (three-mesh-bvh vb.) sahneye ayrı entegre edilir — konsept olarak yine “önce kabaca ele, sonra dar test” mantığıdır.
Özetle uzamsal yapılar, A bölümündeki “sahne karmaşıklığı” faktörünü tek başına azaltmaz; adayların çoğunu erken ve ucuz testlerle devreden çıkararak etkin üçgen sayısını düşürür. Son hassasiyet (kutu vs. üçgen) yine C bölümündeki seçimle dengelenir.
Don’t overkill: doğru hassasiyeti seçmek
Her etkileşim milimetrik hassasiyet gerektirmez. Performans için hassasiyetten bilinçli ödün verilebilir:
Kaba seçim — önce hacim, sonra yüzey
Uzaktaki bir nesneyi seçmek için detaylı yaprağa inmeyin; silindir veya kutu (bounding box) çoğu zaman yeterlidir — teorik çerçeve için Bounding volume.
Bu yaklaşım, özellikle “hangi nesne?” sorusunun “hangi üçgene?” sorusundan ayrıldığı yerlerde işe yarar: vitrin, seçim önceliği, kaba odak. Oyuncu veya imleç nesneye yaklaştıkça ikinci bir aşamada intersection test ile üçgene inmek, maliyeti yalnızca gerektiği anda ödetir.
Proxy mesh — gösteriş görünür, seçim hafif
Görsel olarak ağır bir modelin yanına, yalnızca raycast için kullanılan düşük poligonlu görünmez çarpışma gövdesi yerleştirmek yaygın bir üretim desenidir. Oyunda olduğu gibi grafiksel “yüksek çözünürlük” ile mantıksal “basit gövde”yi ayırırsınız; kullanıcı ayrımı sahne içinden görmez.
Proxy, B bölümündeki uzamsal optimizasyonların yerine geçmez: ikisi birlikte düşünülür — biri geometriyi süsler, diğeri etkin test yüzeyini küçültür. Özet tabloya geçmeden önce şunu hatırlamak yeterli: doğru hassasiyet, en düşük maliyetle yanlış cevaba razı olunabilecek yerde düşük, doğru kullanıcı hissiyatının gerektirdiği yerde yüksek olmalıdır.
Canlı demo: Ray Budget Lab
Aynı sahne üzerinde karmaşıklık (kaç mesh), sıklık (single / continuous / throttled) ve hassasiyet (bounding küre vs. üçgen) üçlüsünü oynatın. Renkli ışın, tahmini yükü; CPU çubuğu görsel geri bildirimi temsil eder (ölçüm yaklaşımsaldır).
Not: Three.js’te intersectObjects(..., recursive)
parametresi sahne grafiğinde çocukları gezmeyi kontrol eder; üçgen testini otomatik
“kapatmaz”. Bu yüzden “ucuz” mod burada dünya küresi ile ön testi simüle eder; “pahalı” mod
ise gerçek mesh kesişimidir.
Metrics
Ray/sn —
Aday kümesi —
Test obje —
Üçgen (yakl.) —
FPS —
Ray cost heat —
Maliyet dağılımı
Aşağıdaki yüzdeler, üstteki heat ile aynı ağırlıkların normalize edilmiş paylarıdır (model yaklaşıksaldır).
- Rays —
- Triangles —
- Objects —
Complexity
Frequency
Precision
Özet: performans kontrol listesi
Takım içi “ışın bütçesi” için tek bakışta sorun → çözüm → beklenen etki haritası:
| Sorun | Çözüm | Etki |
|---|---|---|
| Düşük FPS | Kare atlama (frame skipping) veya throttle | Yüksek |
| Çok fazla obje | BVH veya octree | Kritik |
| Karmaşık geometri | Bounding volume veya proxy mesh | Orta–yüksek |
| Gereksiz hesaplama | Layer filtreleme ve frustum culling | Orta |
Holodepth teknik notu
Raycaster performansı bir denge sanatıdır. Görsel kaliteden ödün vermeden, işlemciyi en az yoracak matematiksel yolu seçmek, Holodepth projelerinin akıcılığını (smoothness) belirleyen ana unsurdur. Senaryo bazlı düşünmek için kullanım senaryoları sayfasıyla birlikte okuyun.