holodepth

Babylon.js · Motor & sahne

Render loop: kare bütçesi ve zaman disiplini

Holodepth'te Three.js ve WebGL taraflarında render döngüsünü çoğu zaman requestAnimationFrame, saat (Clock) ve hedef kare hızı üzerinden anlattık: yani döngüyü siz kurarsınız, çağrı sırasını ve biriken zamanı siz yönetirsiniz. Babylon.js'te aynı fiziksel gerçeklik — ekran yine düzenli yenilenir, GPU yine kare başına iş yapar — fakat çerçeve genelde Engine üzerinden gelir: motor bir geri çağrı çalıştırır, sahne o turda güncellenir ve çizilir.

Bu sayfanın amacı, "döngü nasıl yazılır" tekrarı yapmak değil; motorun altında kareyi nasıl bütçelersiniz, delta zamanı nasıl doğru okursunuz ve hangi işin döngü içinde kalıp hangisinin dışarı taşınması gerektiğini netleştirmek. Böylece Three.js sayfalarıyla çakışmadan, Babylon.js'i motor deneyimi olarak konumlandırırız.

Özet: döngüyü yöneten kavramlar

Kavram Kullanıcıya ne anlatır? Babylon.js pratiğinde tipik karşılık
Kare bütçesi Bir yenilemede CPU ve GPU için ayrılan süre üst sınırı. runRenderLoop gövdesinin hafif tutulması; ağır işin kare dışına veya amortismana taşınması.
Delta zaman İki kare arasındaki süre; hareketin kare hızına bağlı kalmamasını sağlar. engine.getDeltaTime() (milisaniye); saniye bazlı fizik için dönüşüm.
Güncelleme / çizim Mantık adımı ile ekrana basma adımının ayrılması. Sahne kancaları veya döngü içi aşamalar; tek çağrıda scene.render().
Döngü ömrü Sekme arka planda veya görünüm kapalıyken gereksiz işlememek. Döngüyü durdurma / yeniden başlatma; resize ile uyum ( motor yaşam döngüsü).

Render döngüsü nedir ve motora ne borçlusunuz?

Soyut düzeyde render döngüsü, uygulamanızın "şimdi bir kare üret" davetine verdiği yanıttır. Tarayıcı dünyasında bu davet tipik olarak görünür pencere başına düzenli bir ritimle gelir; ancak ritmin tam olarak kaç milisaniyede bir geleceği cihaza, güç planına ve arka plandaki diğer sekmelere bağlıdır. Bu yüzden döngü kodu "her zaman 60 kez çalışır" varsayımına güvenmemelidir — güvenilir olan, her çağrıda son kareden beri geçen süreyi ölçebilmektir.

Babylon.js'te bu çağrı çoğu projede engine.runRenderLoop ile kayıt altına alınır. Motor, geri çağrınızı uygun zamanda tetikler; siz de içinde sahneyi ilerletirsiniz. Bu sözleşmenin özü şudur: geri çağrı kısa ve öngörülebilir kalmalıdır. Uzun süren senkron işler (büyük veri ayrıştırma, ağ isteğinin bekletilmesi, devasa dizilerin tek karede işlenmesi) buraya girerse kare süresi uzar; kullanıcı bunu gecikme veya takılma olarak hisseder — motor bu kötü davranışı "otomatik düzeltmez", yalnızca sizin kodunuzu zamanında çalıştırır.

scene.render() bir turun özeti

Tipik kullanımda döngü gövdesinin sonunda sahne çizilir. Bu tek satır, içeride oldukça çok aşamayı tetikleyebilir: aktif kamera seçimi, görünür nesnelerin toplanması, materyal ve ışık durumunun GPU ile buluşması gibi. Bu yüzden "döngü hafif" demek, yalnızca JavaScript tarafında az satır yazmak değildir; sahneye eklediğiniz her yeni özellik (gölge, post süreci, yoğun parçacık, ağır seçim testleri) kare bütçesinin GPU tarafını da şişirir.

Yönetimsel bakış açısı: döngü içinde yaptığınız her şeyin bir maliyet sınıfı vardır — düşük (O(1) güncelleme), orta (sınırlı nesne turu), yüksek (her kare tam sahne taraması). İlk optimizasyon çoğu zaman "daha akıllı shader" değil, yanlış yerde yapılan işi döngü dışına taşımak olur.

Kare zamanı: delta ve kareden bağımsız hareket

İki kare arasındaki süre — delta — oyun benzeri uygulamalarda hareketin "takılmadan" akmasını sağlar. Aynı hızla ilerleyen bir nesne, kare süresi uzadığında daha büyük bir adım atmalıdır; aksi halde yavaş karede yavaş hareket illüzyonu oluşur. Babylon.js motoru, bu süreyi sizin için ölçümlemeye uygun bir araç sunar: engine.getDeltaTime() milisaniye cinsinden önceki kareye göre farkı verir. Saniye bazlı fizik için bu değeri 1000'e bölerek kullanırsınız.

Pratikte çoğu hata, delta yerine "sabit adım" varsayımlarından gelir: örneğin her karede position.x += 0.05 yazmak, 30 FPS ile 120 FPS'te farklı gerçek hızlar üretir. Delta ile çarpılan hız, ekran yenileme ritminden kopar; bu disiplin, Holodepth'in Three.js sayfalarında vurguladığı clock mantığı ile aynı ailedendir — fakat Babylon.js'te ölçüm çoğu zaman motor üzerinden tek satırla erişilir.

// Örnek: saniye bazlı sabit hız (delta motor tarafından ölçülür)
// speed birim/saniye; engine.getDeltaTime() ms döner.

engine.runRenderLoop(() => {
  const dtSec = engine.getDeltaTime() / 1000;
  // mesh.position.x += speed * dtSec;
  scene.render();
});

«Her zaman 60 FPS» hayalinin bedeli

Geliştirme makinenizde sabit yüksek kare görmeniz, kullanıcının da aynı deneyimi yaşayacağı anlamına gelmez. Mobil cihazlar ısınınca kare düşer; tarayıcı güç tasarrufu yapar; arka planda sekme kısılır. Bu yüzden delta ile hareket yalnızca "doğru fizik" için değil, ürün kalitesi tutarlılığı içindir. İkinci olarak, animasyon eğrilerinde veya kamera yumuşatmasında aşırı büyük delta değerleri (örneğin uzun bir duraklamadan sonra ilk kare) için üst sınır (clamp) düşünmek gerekir; aksi halde tek karede sıçrama yaşanır.

İş bölümü: güncelleme mantığı ve çizim yükü

Okunabilir bir mimari için döngü gövdesini zihinsel olarak iki yarıya ayırmak faydalıdır: durumu ilerlet (konum, animasyon seçici, basit yapay zeka) ve sonucu çiz (scene.render()). Bu ayrım safdır — fiziksel olarak her şey aynı geri çağrıda çalışır — ama kodu yazarken "burası durum, burası görüntü" diye ayırmak, hangi satırın kare süresini şişirdiğini görmenizi kolaylaştırır.

Sahne yönetimi sayfasında değindiğimiz gözlemlenebilir kancalar, güncelleme mantığını dosyalar arasında düzenli biçimde dağıtmanıza yardım eder; döngü gövdesi ise genelde bu parçaların "nihai toplanma" noktasıdır. Önemli olan, her sistem kendi içinde sınırlı kalsın; aksi halde tek bir runRenderLoop bloğu kısa sürede bakımı zor bir "tek tanrı fonksiyonu"na dönüşür.

  • Döngü içinde kalması iyi olanlar: kısa transform güncellemeleri, giriş okumasının özetlenmesi, sınırlı sayıda nesne üzerinde seçim.
  • Şüpheli olanlar: her kare tam liste dolaşımı, tekrarlanan bellek tahsisi, gereksiz yeni nesne üretimi (GC baskısı).
  • Genelde döngü dışına taşınması gerekenler: büyük model ayrıştırma, ağ yanıtının bekletilmesi, sunucudan gelen dev metinlerin işlenmesi — bunlar için kare başına küçük payla amortisman veya arka plan iş kuyruğu düşünün.

Performans: döngüyü durdurmak ve gereksiz kare üretmemek

Üç boyutlu görünüm görünür değilken veya kullanıcı başka sekmedeyken kare üretmeye devam etmek, pil ve ısı için gereksiz maliyettir. Üretim uygulamalarında sık görülen desen: görünürlük veya odak olaylarında döngüyü durdurmak, geri gelince yeniden başlatmak. Motorun yaşam döngüsü ile birlikte düşünüldüğünde bu, yalnızca "optimizasyon" değil, ürün nezaketidir — özellikle dizüstü ve mobil web'de fark edilir.

İkinci bir açı: döngü çalışsa bile içinde "hiçbir şey değişmedi" durumlarında gereksiz işten kaçınmak için içerik bazlı bayraklar kullanılabilir; örneğin sahne tamamen statikse bazı projeler düşük frekansta yeniden çizmeyi tercih eder. Bu tür stratejiler uygulamaya özgüdür; motor size hazır bir "değişmedi atlama" düğmesi sunmak zorunda değildir — karar sizin ürün gereksiniminize aittir.

Teşhis: kare süresini ve darboğazı okumak

Performans sorununda ilk soru genelde "neden düşük FPS?" değildir; doğru soru hangi aşama milisaniyeyi yiyor? sorusudur. Babylon.js ekosisteminde sahne ve motor için ayrıntılı ölçüm araçları bulunur; üretim kodunda bunları kalıcı açık bırakmak yerine, geliştirme ve profil çıkarma sırasında kısa süreli etkinleştirmek tipik bir pratikir. Motor tarafında basit bir gösterge olarak kare hızı okumak mümkündür; ancak gerçek iyileştirme için CPU tarafı ile GPU tarafının ayrıştırılması gerekir — tek sayı yetmez.

Bu sayfa ölçüm arayüzlerinin kullanım kılavuzu değildir; mesele, döngüyü yazarken zihninizde ölçülebilir bir plan bulundurmaktır: önce en pahalı şüpheliyi kanıtlayın, sonra gölgeleri kapatmak gibi rastgele ayar kapama/açma denemelerinden kaçının. İyi bir profil, sahneyi küçük deneylerle değil, veriye dayalı kararlarla inceltir.

Three.js ile yan yana değil, üst üste okumak

Çakışmayı önleyen bakış açısı

Three.js öğrenirken döngüyü kurmak ve kronometreyi yönetmek bilinçli bir öğrenme hedefidir; bu yüzden Holodepth'te o sayfalar geniş tutulur. Babylon.js tarafında ise aynı konu, çoğu zaman motor çağrısının etrafında kısalır: siz yine delta ve bütçe disiplinine bağlısınız, fakat "kim beni her karede çağırıyor?" sorusunun cevabı daha tek merkezlidir. İki anlatım çelişmez — biri nasıl yapılır laboratuvarı, diğeri motor nasıl çerçeveler deneyimidir.

Bu klasörde sıradaki başlıklar

Render döngüsü netleştikten sonra gözlemlenebilir kancalar ve sahne örgütlenmesi için Sahne yönetimi sayfasına geçebilirsiniz. Önceki adım: Motor yaşam döngüsü.