Tarayıcıda açık dünya inşa etmek, bölüm 21: Daha hızlı olmayan bir renderer
Cinevva CTO'su ve Kurucu Ortağı Oleg Sidorkin tarafından
Burada yeni misiniz? Seri rehberine göz atın. Rehber, spike'ın ne olduğunu açıklıyor ve tüm bölümlere bağlantı veriyor.
20. Bölüm, düz bir quad üzerinde yüzey derinliği yanılsaması oluşturdu. Bu bölüm bir render mimarisi kararıyla ilgili ve ders kitaplarındaki yanıtın donanımımız için yanlış çıktığı spike'ı ele alıyor. Soru şu: üçüncü şahıs kamerası altında sinematik yoğunlukta, alfa testli çimler için 200 oyunculu yoğunluğa geçmeden önce bir görünürlük tamponuna ihtiyacımız var mı? Genel kanı kesinlikle evet diyor. Biz bunu geliştirdik, ölçtük ve yanıtın hayır olduğunu gördük.
Herkesin önerdiği teknik
Spike 40'ı yeni sekmede aç ↗ · Kaynak kodunu görüntüle
Görünürlük tamponu, render işlemini iki geçişe ayırır. 1. geçiş geometriyi rasterleştirir ve hiçbir gölgelendirme yapmadan yalnızca üçgen ve örnek kimliklerini kompakt bir tamsayı hedefine, derinlikle birlikte yazar. 2. geçiş, kaplanan her pikseldeki kimlikleri okuyan, ilgili üçgenin köşelerini yeniden getiren, enterpole edilmiş öznitelikleri yeniden oluşturan ve görünür her pikseli tam olarak bir kez gölgelendiren tam ekran bir geçiştir. Vaat, aşırı çizimin kusursuz biçimde elenmesidir: derinlik testi, üzerinde hiçbir gölgelendirme işlemi yapılmamış fragmanlara uygulanır; böylece pahalı materyal yalnızca gerçekten gördüğünüz alanlarda çalışır.
Spike, tek canvas ve tek cihaz üzerinde iki yol çalıştırır; böylece tek değişken gölgelendirmenin nerede gerçekleştiğidir. İleri yönlü yol, three.js üzerinden normal bir MeshStandardNodeMaterial kullanır. Görünürlük tamponu yolu ise three.js dışında çalışan, iki geçişli ham bir WebGPU işlem hattıdır. Bu yol, three.js'in çim dokusunu doğrudan backend'den okur, 1. geçişte bir RG32Uint hedefine (instanceId, triId) yazar ve 2. geçişte aydınlatmayı çözümler. Her iki yol da aynı referans aydınlatma kurulumunu paylaşır.
Saklamaya değer iki uygulama notu var. WebGPU, fragman shader'larında hâlâ taşınabilir bir primitive_index yerleşik değerine sahip değil. Bu nedenle çözüm, indekslenmemiş geometriye köşe başına bir üçgen kimliği işleyip bunu flat enterpolasyonla okumaktır. Bu, köşe sayısını 3 katına çıkarır ancak 12 köşeli bir çim kartında maliyeti ihmal edilebilir düzeydedir. Ayrıca context'i hiçbir zaman yeniden yapılandırmadığınız veya canvas boyutlarına dokunmadığınız sürece canvas'ı three.js renderer'ıyla paylaşmak büyük ölçüde sorunsuzdur; çünkü bunların ikisi de three.js'in kontrolündedir. Zor olan kısım ileri yönlü yolu zamanlamaktı; çünkü three.js, render geçişinin içine GPU zaman damgası sorguları eklemek için herhangi bir hook sunmuyor. Geçici çözüm, ileri yönlü yolun çalışmasını önce ve sonra gönderilen, işlem yapmayan iki zaman damgası geçişiyle çevrelemekti. GPU bunları gönderim sırasına göre çalıştırır.
Rakamlar ters yönde ilerliyor
M serisi bir Mac'te, yaklaşık 1080p çözünürlükte ve 80 metrelik bir alana yayılmış çapraz kartlı çim yapraklarıyla:
50.000 örnekte görünürlük tamponu yolu %25 farkla kazandı: ileri yönlü yolun 5,51 ms'sine karşı 4,13 ms. 100.000 örnekte sonuçlar başa baştı. 200.000 örnekte ise ileri yönlü yol %44 farkla kazandı: görünürlük tamponunun 7,80 ms'sine karşı 5,44 ms. Yoğunluk arttıkça görünürlük tamponu yolu göreli olarak daha kötü hâle geliyor. Bu, tam da aşırı çizim yoğunlaştığında üstün gelmesi gerektiğini söyleyen yaygın kanının tam tersi.
İleri yönlü render neden dayanıklı kalıyor?
Apple Silicon GPU'lar karo tabanlı ertelenmiş renderer'lardır ve bu, tüm hesabı değiştirir. Bir TBDR üzerindeki ileri yönlü gölgelendirme, fragman shader'ından önce çalışan gizli yüzey kaldırma aşamasına sahiptir: rasterleştirici, bir karoya eşlenen her fragmanı toplar, derinliğe göre sıralar ve yalnızca hayatta kalanlar (alfa testinden sonra) fragman shader'ına ulaşır. Dolayısıyla ileri yönlü yol, görünürlük tamponunun “piksel başına bir kez gölgelendirme” vaadinin büyük kısmını zaten donanım içinde ücretsiz olarak karşılıyor. Yapraklar ekranı doldurdukça daha fazla fragman, herhangi bir gölgelendirme başlamadan önce HSR tarafından eleniyor ve ileri yönlü yolun piksel başına efektif maliyeti aşırı çizimle birlikte büyümek yerine kabaca sabit kalıyor.
Görünürlük tamponu yolunun 1. geçişi de aynı TBDR avantajından yararlanıyor. Sorunun tamamı 2. geçişte. 2. geçiş, her pikselin örnek matrisini bir tampondan okuyor. Bu tampon 200.000 örnekte 12,8 MB boyutunda ve herhangi bir GPU önbelleğinden çok daha büyük. Ekranda yan yana duran pikseller genellikle farklı çim örneklerine aittir; dağılım sapmalı bir ızgara olduğundan komşu yaprakların örnek kimlikleri gelişigüzeldir. Bu nedenle o tampona erişen her wave, uyumsuz erişimler nedeniyle önbelleği ıskalar. Bu tutarsız rastgele erişim, tek başına kare başına yaklaşık 4 ms harcar. İleri yönlü yol bundan tamamen kaçınır; çünkü örnek matrisi köşeyle birlikte örnek başına öznitelik yolu üzerinden gelir. Dolayısıyla fragman shader'ı çalıştığında dönüştürülmüş köşe verileri zaten karo içi yerel register'lardadır ve megabayt ölçeğinde rastgele okuma gerekmez.
Nanite'ın materyal sınıflandırma geçişi tam olarak bu maliyeti dağıtmak için vardır: pikselleri örneğe göre gruplandırır ve sıralanmış compute wave'leri gönderir; böylece her wave'in okumaları tutarlı olur. Bizde bu yok. Kabaca yapılan bir hesap, pikselleri örneğe göre sıralamanın bu 4 ms'yi yaklaşık 1,5 ila 2 ms'ye düşürebileceğini ve kesişme noktasını 400.000 ila 500.000 örneğe taşıyabileceğini gösteriyor. Ancak bu, en başta burada üstün gelmeyen bir mimarinin üzerine optimizasyonlar yığmak anlamına geliyor.
Dürüst sonuç ve bu sonucu güvenilir kılan denetim
Apple Silicon WebGPU'da alfa testli çapraz kart bitki örtüsü için three.js'in TSL işlem hattını kullanan ileri yönlü yolun maliyeti zaten görünürlük tamponuyla aynı seviyede veya daha düşük. Görünürlük tamponu altyapısı, 200.000 örneğin çok ötesine geçene kadar görünür hiçbir kazanç sağlamıyor; o noktada bile ayrıca bir sıralama veya gruplama geçişi eklemeniz gerekiyor. Üretim motoru için pratik karar, önceki spike'lardaki ileri yönlü render, LOD ve imposter yığınını korumak ve iki koşuldan biri gerçekleşene kadar görünürlük tamponu altyapısına yatırım yapmamak: baskın dağıtım hedefimiz, aşırı çizim maliyetinin daha doğrusal olduğu ayrık NVIDIA veya AMD GPU'lar hâline gelirse ya da görünürlük tamponunun zaten doğal çıktı olduğu bir meshlet mimarisine geçersek.
Bu sonuç sezgilere aykırı olduğu için karşılaştırma adil değilse çıkarımın hiçbir değeri yoktur. Bu nedenle spike kapsamlı bir denetimden geçti. Birkaç gerçek hata ortaya çıkarıldı ve düzeltildi: iki yolu sessizce birbirinden koparan bir yaprak ölçeği kaydırıcısı, anti-paralel normaller nedeniyle ileri yönlü yoldaki yaprakların yarısının zifiri karanlık render edilmesi (standart yukarı yönlü normal kullanan bitki örtüsü tekniğiyle düzeltildi) ve görünürlük tamponunun enerjiyi koruyan 1/π yerine elle seçilmiş bir Lambert katsayısı, sabit kodlanmış bir ortam terimi ve eksik ton eşleme nedeniyle yaklaşık 2 kat fazla parlak okuması. Düzeltme, three.js'in ACES filmik eğrisini eksiksiz olarak WGSL'ye kopyaladı ve her karede ışık renkleriyle yoğunluklarını gerçek sahne ışıklarından okuyor. Bilinen son eksiklik olan 2. geçişte doğrudan speküler yansımanın bulunmaması, karşılaştırmayı görünürlük tamponu lehine çarpıtıyor. Yani ileri yönlü yol piksel başına kesinlikle daha fazla iş yapıyor ve yine de yüksek yoğunlukta kazanıyor. Bu da ana sonucu iyimser değil, ihtiyatlı kılıyor. Geçerliliğini koruyan tek uyarı şu: bunların tamamı M serisine özgü ve ayrık bir ekran kartında kesişme noktası pekâlâ tersine dönebilir. Bu nedenle Apple dışı hedefler için teknoloji yığınını kesinleştirmeden önce testi yeniden çalıştırmaya değer.
Bu bölümde değinilen teknolojiler
Görünürlük tamponuyla render. 1. geçiş geometriyi rasterleştirir ve hiçbir gölgelendirme yapmadan yalnızca üçgen ve örnek kimlikleriyle derinliği yazar. 2. geçiş, kaplanan her piksel için kimlikleri okuyan, kaynak üçgeni yeniden getiren, perspektif düzeltmeli barycentrik öznitelikleri yeniden oluşturan ve her görünür pikseli bir kez gölgelendiren tam ekran bir çözümleme geçişidir. WebGPU taşınabilir bir fragman primitive_index değeri sunmadığından üçgen kimliği, indekslenmemiş geometri üzerinde flat enterpolasyonlu, köşe başına bir öznitelik olarak işlenir.
TBDR gizli yüzey kaldırma ile ertelenmiş çözümlemenin karşılaştırılması. Karo tabanlı ertelenmiş bir GPU'da (Apple Silicon), ileri yönlü gölgelendirme fragman shader'ı çalışmadan önce örtülen fragmanları zaten eler. Böylece görünürlük tamponunun tek seferlik gölgelendirme avantajının büyük kısmını ücretsiz olarak elde eder ve aşırı çizim arttıkça piksel başına maliyeti kabaca sabit kalır. Görünürlük tamponunun çözümleme geçişi ise örnek başına büyük bir tampona yapılan tutarsız rastgele erişimin maliyetini öder (200 bin örnekte 12,8 MB). Nanite'ın materyal sınıflandırmasında olduğu gibi pikseller önce örneğe göre sıralanmadığı veya gruplandırılmadığı sürece bu maliyet yüksek yoğunlukta baskın hâle gelir.
Bir canvas'ı three.js'in WebGPURenderer'ıyla paylaşmak. context.configure() işlevini yeniden çağırmadığınız veya canvas.width/height değerlerini değiştirmediğiniz sürece ham WebGPU komut tamponları, paylaşılan kuyrukta three.js gönderimleriyle doğru biçimde iç içe çalışır; çünkü bunların ikisi de renderer'ın kontrolündedir. three.js'in hook sunmadığı ileri yönlü yol GPU zamanlaması, render çağrısının çevresine gönderilen ve işlem yapmayan iki zaman damgalı render geçişiyle ölçülebilir; çünkü GPU komut tamponlarını gönderim sırasıyla çalıştırır.
Sezgilere aykırı bir benchmark'ı doğrulamak. Şaşırtıcı bir performans sonucu, ancak karşılaştırmanın adilliği kadar güvenilirdir. Her iki yolu da aynı sahne içeriği ve gölgelendirmeyle denetlemek (eşleşen ACES ton eşleme, enerjiyi koruyan Lambert, aynı nesnelerden okunan ışıklar ve aynı yaprak ölçeği), “görünürlük tamponu daha yavaş” sonucunu olası bir ölçüm hatası olmaktan çıkarıp savunulabilir bir sonuca dönüştürdü. Geriye kalan tek asimetri de sonucu ihtiyatlı yönde çarpıtıyor.
29 bölümün 21. bölümü. Önceki: 20. Bölüm - Düz bir düzlemde derinlik yanılsaması oluşturmak Sonraki: 22. Bölüm - İçinden uçabileceğiniz bulutlar ve karşılığını veren ayıklama Seri rehberi: /tr/blog/2026-02-25-open-world-browser-series-guide