Skip to content

PlayCanvas'ı çatallamak yerine neden kendi WebGPU motorumuzu geliştirdik

Cinevva CTO'su ve Kurucu Ortağı Oleg Sidorkin tarafından

Cinevva'nın WebGPU motoruyla işlenen stilize, düşük poligonlu bir dünya: inişli çıkışlı tepeler, bir uçuruma oyulmuş mağara, kıvrılarak akan nehir ve altın saatte bir patikada adım atarken görülen avatar

Cinevva World'e bakan teknik bilgili herkes beş dakika içinde aynı soruyu soruyor. Küçük bir ekipsiniz. Olgun web 3D motorları zaten var. Neden PlayCanvas veya Babylon'ı temel alıp daha hızlı yayınlamak yerine kendi işleyicinizi, karakter fiziğinizi ve animasyon sisteminizi yazdınız?

Bu makul bir soru ve buna verilecek yanlış cevap “burada icat edilmedi” sendromudur. Biz gerekli araştırmayı yaptık. Karar vermeden önce mevcut motorları çalıştırdık, kaynak kodlarını okuduk ve ikisinin üzerinde deneme sürümleri geliştirdik. Bu yazı, söz konusu kararın dürüst anlatımıdır: hazır seçeneklerin gerçekten iyi olduğu alanlar, ihtiyaçlarımızın kendi çözümümüzü geliştirmeyi haklı çıkaracak kadar ayrıştığı dört nokta ve bizi örnek almak yerine bu seçeneklerden birini tercih etmeniz gereken durumlar. Geliştirme sürecinin kendisini uzun soluklu tarayıcıda açık dünya mühendisliği serisinde belgeledik; dolayısıyla aşağıdaki bir iddiayı destekleyen çalışma günlüğü varsa ona bağlantı vereceğim.

Gerçekten değerlendirdiğimiz seçenekler

Dört farklı şeye “web oyun motoru” deniyor ve bunların hepsi aynı türde değil.

Three.js bir oyun motoru değil, işleme kütüphanesidir. Size bir sahne grafiği, materyaller, yükleyiciler ve işleyici sunar, ardından yolunuzdan çekilir. Editörü, fizik sistemi veya varlık sistemi yoktur ve oyununuzun nasıl yapılandırılması gerektiği konusunda herhangi bir yaklaşım dayatmaz. Hem cazibesi hem de bedeli budur. İşleyicinin üzerindeki her şeyi kendiniz geliştirirsiniz ama hiçbir şey de size karşı koymaz. MIT lisanslıdır, bu alandaki en büyük ekosisteme sahiptir ve gece saat 02.00'de sıra dışı bir gölgelendirici hatasıyla karşılaştığınızda forumda sizi bekleyen bir cevap vardır.

Babylon.js, sahne grafiği, fizik entegrasyonu (Havok), varlık işlem hattı ve web editörü içeren tam kapsamlı bir motordur. MIT lisanslıdır, Microsoft bünyesindeki bir ekip tarafından desteklenir ve WebGPU çalışmaları hızla ilerlemektedir. Her şeyin hazır gelmesini istiyorsanız ve motorun yapısı içinde çalışmaktan memnunsanız güçlü bir varsayılan tercihtir.

PlayCanvas, “web için Unity” tanımına en çok yaklaşan çözümdür. Bu yazının yazıldığı sırada motor, 5 Haziran 2026'da yayınlanan v2.19.6 sürümündedir ve motorun kendisi MIT kapsamında açık kaynaklıdır. Ancak çoğu kişinin gerçekten kullandığı şey barındırılan görsel editördür ve bu editör açık kaynaklı değil, ticari bir üründür. PlayCanvas bir varlık-bileşen sistemi kullanır; TypeScript veya JavaScript ile betik yazarsınız, varlıklar sunucu tarafındaki bir GLB işlem hattından geçer ve bununla gerçek ticari oyunlar yayınlanmıştır (örneğin Snap, üretim çalışmalarında PlayCanvas kullanıyor). İşleyicisi WebGL2 üzerinde çalışır; WebGPU yolu ise varsayılan olmak yerine hâlâ olgunlaşma aşamasındadır. Bu son ayrıntı göründüğünden daha önemli ve ona birazdan geri döneceğim.

Unity WebGL aslında bir web motoru değildir. Bir dışa aktarma hedefidir. Oyunu Unity masaüstü editöründe geliştirip bir WebGL paketi olarak derlersiniz. Zaten bir Unity oyununuz varsa ve onu tarayıcıya taşımak istiyorsanız doğru araçtır. Ancak “orta sınıf bir telefonda, bir sekmede anında yüklenmesi” kesin bir gereksinimse yanlış araçtır; çünkü çalışma zamanı ve indirme boyutu da beraberinde gelir.

Bunların herhangi biri normal bir web oyunu için makul bir temel olabilir. Bizimki normal bir web oyunu değildi.

Birinci karar: WebGPU bizim için bitiş çizgisi değil, alt sınır

Bizi tüm hazır çözümlerden uzaklaştıran ayrım şu: Bizim için WebGPU, zamanla geçeceğimiz bir özellik değil, bir gereksinim.

Arazi sistemimiz statik bir yükseklik haritasından ibaret değil. Akışla yüklenen bir yükseklik haritası alanı ile işaretli uzaklık alanıyla desteklenen marching cubes parçalarının hibritinden oluşuyor; böylece dünyada gerçek mağaralar ve çıkıntılar bulunabiliyor, içerik üreticileri de araziyi canlı olarak şekillendirebiliyor. Şekillendirme fırçaları, bitki örtüsü dağıtımı ve arazi ağ oluşturma işlemlerinin tümü hesaplama gölgelendiricileri olarak çalışıyor. Hesaplamayı kaldırdığınızda dünya daha düşük kalitede çalışmıyor; hiç çalışmıyor.

Bu, genel amaçlı motorların bugün bulunduğu noktanın tam tersi. Bu motorların WebGPU desteği, WebGL2 öncelikli bir işleyici üzerine aşamalı iyileştirme olarak tasarlanıyor ve bunu desteklemeyen tarayıcılar için bir geri dönüş yolu bulunuyor. Özellikle PlayCanvas, WebGL2 önceliklidir ve WebGPU hâlâ beta aşamasındadır. Bu onlar için doğru karardır; çünkü görevleri mümkün olan en geniş oyun yelpazesini, mümkün olan en geniş cihaz yelpazesinde çalıştırmaktır. Bizim görevimiz daha dar ve daha derin olduğu için tersini yaptık: 13. denemede yalnızca WebGPU'ya geçtik ve bir daha arkamıza bakmadık. WebGPU'suz tarayıcılarda kalite düşürülmüyor; bu tarayıcılar desteklenmiyor. Bunu, WebGL2 geri dönüşü tek bir yapılandırma seçeneği uzağındaymış gibi davranmak yerine erişim oranı olarak takip ediyoruz. Çünkü öyle değil. Böyle bir geri dönüş, arazi ve bitki örtüsü aşamalarımızın kısmen yeniden yazılmasını gerektirirdi.

WebGL2 öncelikli bir motorun üzerine inşa etmek, ya her hesaplama özelliğinde motorun geri dönüş varsayımlarıyla mücadele etmek ya da sonsuza kadar iki işleme yolu sürdürmek anlamına gelecekti. İşleyicinin bize ait olması, hesaplamayı temel kabul etmemizi sağladı.

İkinci karar: fizik motoru değil, karakter çözücüsü

Ders kitaplarındaki standart yaklaşım, bir fizik motorunu projeye eklemektir. Bunu denedik. İlk denemelerden biri Rapier'ın bir worker içinde çalışmasını doğruladı ve gayet iyi hissettirdi.

Yine de kendi çözümümüzü yazdık ve yayınlanan sürümün hiçbir yerinde Rapier, Cannon veya Ammo yok. Bunun nedeni kapsam. Katı cisimlere, eklemlere, ragdoll sistemlerine veya kısıt çözücüsüne ihtiyacımız yok. Bir kapsülün arazi üzerinde doğru hareket etmesine ihtiyacımız var; ayrıca yürüme, kayma, süzülme, tırmanma ve yüzme sistemlerinin “yere basıyor muyum, hangi yüzeydeyim ve hangi açıdayım?” sorusuna verilen tek bir ortak cevapta uzlaşması gerekiyor. Genel amaçlı bir fizik motoru bunu kolaylaştırmak yerine zorlaştırıyor; çünkü bu hareket modları sonunda motorun dahili yayları ve sönümleyicileriyle mücadele ediyor.

Bu nedenle karakter denetleyicimiz takılıp çıkarılabilir, çok kanallı bir durum makinesi. Her mod, o karede denetimi isteyip istemediğini belirten ve kazanırsa hızı ve bakış yönünü yazan küçük bir birimdir. Üç kanalda önceliğe göre hakemlik yaparlar: önce kaynak, ardından duruş, sonra hareket. Hepsi aynı arazi sorgusunu okur. Çarpışma, parçaya bağlı olarak yükseklik haritasına veya işaretli uzaklık alanına karşı yapılan bir kapsül yoklamasıdır.

En çok gurur duyduğum ayrıntı pek gösterişli değil. Zemin algılama sistemi, SDF gradyanına güvenmek yerine ayaklarınızın altındaki dikey sütunda bulunan her yüzeyi tarıyor ve kapsül hizasında veya altında bulunan en yüksek yüzeyi seçiyor. Bir çıkıntının kenarında, yan yöndeki en yakın yüzey uçurum duvarıdır. Bu nedenle gradyan tabanlı normal, “zemin” ile “duvar” arasında gidip gelir ve hayalet kaymalar yaşanır. Sütun sorgusu, bir çıkıntının üzerinde durmayı sıkıcı hâle getiriyor ki istediğiniz şey de tam olarak budur. Hazır bir yükseklik alanı çarpıştırıcısı bunu bize kendiliğinden sunamazdı, çünkü öncelikle arazimizi göremez. Arazi, bizim formatımızda GPU üzerinde yaşar. Her düzenlemede alanın tamamını harici motorun çarpıştırıcı formatına kopyalamadan hiçbir harici motor bununla çarpışma hesabı yapamaz.

Üçüncü karar: iskeletler arasında taşınabilen animasyon

Avatarlar Synty POLYGON iskeletini kullanıyor ve hareket kliplerimiz geniş bir açık animasyon kütüphanesinden geliyor. İskelet ve klipler aynı kemik adlarını paylaştığı için yaygın durumda çalışma zamanında yeniden hedefleme gerekmiyor; izler doğrudan ada göre bağlanıyor. Karakter işlem hattının tamamını evrensel karakterler yazısında anlattık.

Asıl ilginç çalışma, bunların eşleşmediği durumda başlıyor. Bir iskeleti diğerine eşleyen bir yeniden hedefleme geçişi geliştirdik ve bunu doğru yapmak üç özel sorunu çözmemizi gerektirdi. Önce bağlama pozlarını hizalarsınız; çünkü A pozu ile T pozu arasındaki fark, her ekleme fark ettirmeden yaklaşık otuz derece ekler. Kök hareketini ve adım uzunluğunu iki ayrı oranla ölçeklersiniz: dikey eksen için kalçadan zemine olan mesafe, yatay eksen içinse genel vücut oranı. Ayrıca yeniden hedeflenmiş klipleri sabit bir örnekleme hızında kaynaklarıyla karşılaştırarak test edersiniz; böylece gerilemeler oyuncudan önce ortaya çıkar. Bu işlem hattı, her klibi elle düzeltmeden yeni animasyon kaynakları ve nihayetinde içerik üreticilerinin sağladığı karakterler ekleyebilmemizi sağlıyor.

Bunun üzerinde, her karede hareket durumuna göre doğru klip ailesini seçen bir animasyon durum makinesi bulunuyor: hıza göre sıçrama çeşidi, darbenin şiddetine göre iniş, hızın arazi gradyanıyla skaler çarpımından eğim yönü, dururken ay yürüyüşü yapmamanız için ayak fazına uygun duruşlar ve bir duvara çarpmanın yürüme ile düşme arasında gidip gelmenize yol açmaması için yüz milisaniyelik gecikme filtresi. Bunların hiçbiri sıra dışı değil, ancak ancak bu katmana sahip olduğunuzda elde edebileceğiniz türden ayrıntılar.

Dördüncü karar: hiçbir motorun sunmadığı bölüm

Diğer üç karar dünyanın nasıl çalıştığıyla ilgili. Bu karar ise ürünün ne olduğuyla ilgili ve PlayCanvas karşılaştırmasının nihayetinde neden bir kategori hatası olduğunu açıklıyor.

PlayCanvas, Babylon, Unity ve elle geliştirilmiş bir Three.js uygulamasının tümü aynı modeli varsayar: Oyununuzu bir masa başında, 2D editörde, dünyaya dışarıdan bakarak geliştirirsiniz; ardından oynat düğmesine basıp ayrı bir çalışma zamanı yayınlarsınız. Motor içi düzenleme özelliklerinde bile bir iş istasyonunun başında oturur ve baktığınız sahneyi değiştirirsiniz.

Cinevva World bunu tersine çeviriyor. Dünyanın içinden, oyuncularınızın duracağı alanın aynısında duran bir avatar olarak; istediğiniz şeyi tarif edip ortaya çıkışını izleyerek üretim yaparsınız. Üretim ve oyun, bir çalışma zamanına bağlanan geliştirme adımı değil, kesintisiz tek bir oturumdur. Buna en yakın örnekler web 3D motorları değil; Roblox, Rec Room ve Horizon Worlds'tür. Üstelik onlar bile üretimin büyük bölümünü masa başında tutar. Fareyle kullanılan bir editör olmadan bunu uygulanabilir kılan şey, “buraya fenerlerle aydınlatılmış bir iskele yerleştir” ifadesini geometriye ve yerleşime dönüştüren yapay zekâ destekli oluşturucudur.

Bunu genel amaçlı bir motora sonradan ekleyemezsiniz; çünkü bu bir işleme özelliği değildir. Arazinin çalışma zamanında nasıl düzenlenebildiğinden ağ sisteminin her nesneyi yakında duran bir kişinin az önce yaptığı bir şey olarak ele almasına kadar tüm teknoloji yığınının temel varsayımıdır.

Bizim yaptığımızı ne zaman yapmamalısınız?

“Kendi motorumuzu geliştirdik” türündeki yazıların genellikle atladığı bölüm şudur: Bu çeyrekte bir tarayıcı oyunu yayınlamak istiyorsanız bizi örnek almayın. Unity tarzı bir editör ve yönetilen bir işlem hattı istiyorsanız PlayCanvas kullanın. Fizik sistemi dâhil tam kapsamlı bir motor istiyorsanız ve onun yapısı içinde çalışmaktan memnunsanız Babylon kullanın. En yüksek denetimi, en az dayatmayla istiyorsanız ve bunun üzerindeki katmanları geliştirecek ekibiniz varsa Three.js kullanın. Zaten bir Unity oyununuz varsa onu taşıyın.

Kendi işleyicinizi, fizik sisteminizi ve animasyon sisteminizi yazmak yalnızca ürününüzün temel fikri hazır çözümlerle bağdaşmıyorsa; geliştirdiğiniz şey bir motor üzerinde çalışan oyun değil, bir motordan oluşan bir mekânsa doğru karardır. Bizim durumumuzda bu doğruydu. Muhtemelen sizin durumunuzda doğru değil ve bunda bir sorun yok. Dürüst bir değerlendirme yapmanın amacı, ilk kod satırını yazmadan önce hangi durumda olduğunuzu bilmektir.