giriiş
Three.js çok şey yapar ve diğer 3B alanlarıyla nasıl ilişkilendirildiği biraz kafa karıştırıcı olabilir. Kapsamı da sürekli gelişen bir şey olduğundan, özetlemesi pek kolay değildir ve bu gözlemler özneldir.
JavaScript 3D kütüphanesi
Bu projenin amacı, hafif ve kullanımı kolay bir 3B kütüphane oluşturmaktır. Bu kütüphane, görselleştirmeler sağlar. , , CSS3D ve WebGL.
Bu, GitHub deposundaki resmi açıklama. Aslında durumu oldukça iyi özetliyor, ancak bu cümledeki her konu başlı başına geniş bir konu ve three.js'nin tek yaptığı bu değil.
Kütüphanenin kendisi JavaScript ile yazılmıştır ve JavaScript ortamında kullanılmak üzere tasarlanmıştır. Çoğu durumda bu, istemci tarafında, yani bir cihazdaki web tarayıcısında çalıştığı anlamına gelir. Ancak node.js ve başsız tarayıcılarla sunucu tarafında da kullanılabilir. Akla gelen ilk düşünce render işlemidir; belki sunucuda bazı önizleme görüntüleri, ancak three.js zengin bir matematik kütüphanesine sahip olduğundan, bu yalnızca 3B hesaplamalar da olabilir. Bu inanılmaz derecede geniş bir terim. 3B çok şey ifade edebilir. Çoğu durumda aklımıza "grafikler" gelir.
Gördüğümüz çoğu three.js projesi, kullanıcı etkileşiminin anında görsel geri bildirim sağladığı gerçek zamanlı 3B grafikler içerir. Diğer 3B grafik türleri arasında filmlerdeki çeşitli efektler veya yapay karakterler ya da basılı materyallerde veya bir web kataloğunda görebileceğiniz çeşitli "işlemeler" bulunur (örneğin, IKEA'nın web sitesi, tüm ürün fotoğrafları bilgisayar ortamında oluşturulduğu için 3B grafiklerle doludur).
Tüm bunların bir alt kümesi 3B matematiktir. 3B grafikler matematik olmadan yapılamaz ve bilgisayar dilleri varsayılan olarak 3B kavramlarını anlamaz. İşte tam bu noktada bir kütüphane devreye girer; bu matematik işlemlerini soyutlar, belki de optimize eder ve Matrix4 veya .dot() gibi üst düzey bir arayüz sunar.
Three.js, 3D matematiğe özgü sınıflar içeren kendi matematik kütüphanesiyle birlikte gelir. Yalnızca bu matematikle ilgilenen bağımsız kütüphaneler mevcut olsa da, Three'de bu, çok daha büyük bir sistemin yalnızca bir alt kümesidir.
Rendering, kütüphanenin bir diğer büyük sorumluluğudur, ancak burada da işler biraz karmaşıklaşır. WebGL oldukça spesifiktir ve diğerlerinden sıyrılır.
Canvas, SVG ve CSS ile renderleme sorumluluğu tamamen 3B'ye aittir. Bu API'ler, 3B olmayan nesneler çizmek için birçok kütüphaneye sahiptir veya varsayılan olarak bunu yaparlar (CSS 2B dikdörtgenler çizer, Canvas ise çeşitli 2B şekiller çizer), ancak 3B renderlemeyi gerçekten yapmak için sihirli bir dokunuş ve 3B matematik gerektirirler.
Sihirli dokunuş çoğunlukla arayüz soyutlamasıyla gelir. Örneğin, bir öğenin 3B durumunu yönetmek gibi. <div> CSS ile 3B'ye dönüştürmek çok zordur. Canvas API'sinin 3B gibi görünen bir şey çizmesini sağlamak için çok fazla mantık gerekir. WebGL ise çok daha karmaşıktır.
Three, tüm bu API'leri render() gibi basit bir şeye soyutlar, ancak bunu yapmak için "3B dünya"nın ne olduğuna dair genel bir temsile ihtiyaç duyar.
Sahne diyagramı
three.js'de "3B dünya"nın genel soyutlaması olarak işlev gören bir alan tanımlanabilir. Sahne grafiği, bir 3B sahnedeki (dünyadaki) nesnelerin birbirleriyle nasıl ilişkili olduğunu tanımlamak için kullanılan bir veri yapısıdır. Aslında 3B olması gerekmez, çünkü bu herhangi bir vektör grafik hiyerarşisini tanımlamanın kullanışlı bir yoludur. Daha spesifik olarak, "kök düğümü" olan "düğümlerden" dallanan bir "ağaç"tır. three.js'de bu veri yapısının temel sınıfı Object3D'dir.
Bu, DOM ağacıyla neredeyse tamamen aynıdır. THREE.Scene benzerdir <body> olacak ve diğer her şey bir daldır. DOM'da nesneleri yerleştirebiliriz, ancak bunlar nispeten sınırlıdır. Dönme genellikle bir eksen etrafında gerçekleşir ve nesneleri sola/sağa veya yukarı/aşağı hareket ettiririz. 3B bir sahne grafiğinde daha fazla serbestlik derecesine sahibiz.
Üçüncü sahne daha çok sanal bir DOM'a benziyor. İşlemlerimizi gerçekleştirip durumu o ağaçta ayarlıyoruz ve bu durumun görsel bir anlık görüntüsünü almak istediğimizde (örneğin sürekli bir döngüde veya bir kullanıcı etkileşimi/durum değişikliğinde), render (sahne) diyoruz. Bir şey değiştiğinde, tüm DOM ağacını güncellemek istemezsiniz; ancak öğeyle birlikte , tüm görünümü temizlememiz ve ardından sadece bir elemanın konumunu değiştirse bile her şeyi yeniden çizmemiz gerekiyor.
Bir <div> Birinde <div> THREE.Mesh('sun')->THREE.Mesh('earth') ebeveyn-çocuk ilişkisine benzer. Bir CSS kuralı, color:'red' gibi bir açıklamanın sihir yaratıp bir şeyi kırmızıya çevirdiği bir THREE.Material kuralına benzeyebilir. Son olarak, threeRenderer.render(scene) çağrısı, tarayıcının bazı CSS kuralları içeren bir HTML sayfasını yüklemesine benzeyebilir.
Mesh, Scene, Camera ve Light, bu genel sınıfın alt sınıflarıdır. Bu, "sahneye" bir "kutu" veya "kameraya" bir "ışık" eklemenize olanak tanır.
Basit bir yapı oldukça düz olabilir. Kök düğüm "dünya" olarak görülebilir ve alt düğümleri olarak "zemin", "ev", "güneş" ve "kamera" olabilir.
THREE.Scene('world')
|-THREE.Mesh('ground')
|-THREE.Mesh('house')
|-THREE.Light('sun')
|-THREE.Camera('main')Bu, görsel bir sonuç elde etmek için bir görüntü oluşturucuya girilebilecek yeterli bilgidir. Bazı sahnelerde, farklı şeyleri temsil eden iki ızgara bulunur: zemin ve tepedeki ev. Nasıl aydınlatıldıklarını tanımlayan bir ışık (sabah, öğlen, flaş ışığı) ve bakış açımızı, dünyaya bakış açımızı tanımlayan bir nesne (kamera).
Sonuçlar değişebilir, örneğin CSS çok hafif bir render ile sınırlıdır, WebGL ise gölgeler ve genel olarak yüksek doğruluk sağlayabilir.
Bu yapı sayesinde 3B dünya yönetilir. Gün ışığının farklı mevsimlerde bir evi nasıl etkilediğini simüle etmek istiyorsak, ışığın dünyadaki konumunu ve yönünü programatik olarak değiştiririz. Sahne grafiğinin görevi bu "konum" kancasını ortaya çıkarmaktır, ancak onu gerçekten canlandırmak için kendi mantığınızı uygulamanız gerekir. Bir 3B sahneyi canlandırmanın basit bir yolu, "tweening" kütüphanesi olan three.js'dir.
Tüm bunlar muhtemelen sadece teoride doğrudur ve sahne renderlarını istediğiniz gibi değiştiremeyebilirsiniz. Ancak bu çoğunlukla "malzemelerin" sahne grafiğiyle örtüşmesinden ve renderlarla olan bağlantısından kaynaklanır. Örneğin, bir sahneyi gölgelendirmenin bir yolu yoktur. <div> Ya da metal olarak görünmüyor, ki bu bir WebGL malzemesinin tanımlayabileceği bir şey, ama kırmızı yapılabilir, ki bu tüm malzemelerin yapabileceği bir şey.
Tüm bunların temelinde Object3D hala geneldir ve düğümlerin birbirlerine göre mekansal ve hiyerarşik ilişkileri bir "sahne grafiği" aracılığıyla tanımlanır.
Basitçe söylemek gerekirse, bu scene.add(my_foo) fonksiyonunu birden fazla kez çağırdıktan sonra elde ettiğiniz sahne değişkenidir.
WebGL
Webgl son derece spesifiktir ve muhtemelen mevcut three.js uygulamalarının 'unda kullanılmaktadır. Bu kapsamlı bir konu, bu yüzden önce alternatiflere hızlıca bir göz atmakta fayda olabilir.
tuval, css, svg
Bunların hepsi API'lerdir. Bu, bir programcı olarak tarayıcıya belirli şeyleri çizmesini söylemek için kullanabileceğiniz bir arayüzdür. CSS, web'deki en yaygın arayüzdür çünkü onsuz her şey düz metin gibi görünür. Tarihsel olarak 3B ile hiçbir ilgisi yoktu.
Canvas aslında çizim için aynı WebGL öğesini kullanır, ancak farklı bir bağlamı vardır. Bağlam aslında "2 boyutlu" olarak adlandırılır, ancak 3 boyutlu zaten sahte olduğundan ve ister gerçek ister sanal olsun, her zaman bir tür 2 boyutlu yüzey çizdiğimizden, bu bağlamı 3 boyutlu grafikler çizmek için de kullanabiliriz.
SVG, genellikle logolar veya simgeler gibi öğeleri tanımlamak için kullanılan 3B olmayan bir API'dir. Ancak, çizgiler gibi temel öğeleri tanımlayabildiği için 3B bir bağlamda da temsil edilebilir (örneğin bir haritadaki bir katman veya uzamsal olarak duyarlı kullanıcı arayüzü veya HUD öğeleri).
Buradaki ortak nokta, bunların hiçbirinin 3B kullanım için tasarlanmamış olmasıdır. Bir diğer önemli özellik ise hepsinin üst düzey olmasıdır; daha önce başka bir amaç için tasarlanmışlardı. Örneğin, üçü de "daire" çizmeyi biliyor. Canvas ile bu açık bir şekildir; CSS ile kenarlık yarıçapları kullanmanız gerekebilir, ancak sonuç olarak daireye doğrudan erişim elde edersiniz.
WebGL oldukça düşük seviyelidir ve 3B grafik kavramı hakkında pek bir şey bilmez. 3B grafikler belirli matematiksel hesaplamalar gerektirir ve çok sayıda hesaplama gerektirir. Yüksek çözünürlüklü bir ekranı ve sahip olduğu piksel sayısını bir saniye düşünün. Belirli bir ışık miktarının yüzeyi nasıl etkilediğini belirlemek için her piksel için hesaplamalar yapmanız gerekiyorsa ve bunu saniyede 60 kez yapmanız gerekiyorsa, bu sayı toplanır.
Grafik işlemcisi
Dizüstü bilgisayarlar, masaüstü bilgisayarlar, cep telefonları ve hatta saatler gibi çoğu bilgisayar, bu 3B işlemleri verimli bir şekilde hesaplayabilen ve etkileşimli grafiklerin görüntülenmesini sağlayan bir tür donanım aygıtına sahiptir. Buna grafik işleme birimi denir.
Ana işlemciden farklıdır çünkü farklı amaçlar için oluşturulmuştur; paralel olarak yürütülen belirli matematiksel işlemler.
Tarayıcı programlamada JavaScript kullandığımız gibi, grafik kartı programlamada da WebGL kullanıyoruz.
Kavramsal olarak bu doğru, ancak pratikte ikisi çok farklı. WebGL, hem JavaScript kodundan (talimatlar) hem de hesaplamaları yapan tamamen farklı bir dilden (GLSL) oluşur. HTML ve JavaScript arasında ve bir sayfada nasıl birlikte çalıştıkları konusunda bazı benzerlikler kurabilirsiniz.
İki boyutlu ve üç boyutlu
Bu donanım hızlandırmasından sadece 3D değil. Video işleme de iyi bir aday. Grafik kartını renkleri değiştirecek veya canlı video akışındaki görüntüyü değiştirecek şekilde programlayabilirsiniz.
Çok düşük seviyeli olan WebGL geneldir. 2D veya 3D hakkında bilgi sahibi değildir, ancak bellek, tamponlar, komut kuyrukları, gölgelendiriciler vb. hakkında bilgi sahibidir.
Paralel programlama, JavaScript'te programlamaktan farklıdır. Yaygın bir sorun, farklı iş parçacıklarının paylaşılan bir değişkene nasıl eriştiğidir.
Bu farklı paradigma, GLSL adında bambaşka bir dilin var olduğu anlamına geliyor. Bu, her düşük seviyeli grafik API'sinde bulunan bir gölgelendirme dili. Büyük sayılar için gerçek mantığı burada yazıyorsunuz ve tek avantajı, makine kodu yazmak zorunda olmamanız.
WebGL API'sinin diğer kısmı, GPU'ya bir şeyler yapmasını söylediğiniz JavaScript bağlamalarıdır. Bir gölgelendirici "A hesaplamalarını yapar" ve bir bağlama "bir milyon kez çalışır".
A'nın ne olduğunu hesaplamak programcıya kalmış. 3D ile ilgili bir şey olabilir veya videoyu bulanıklaştıran bir çekirdek olabilir.
Bu hesaplamaları ve komutları soyutlamaya başladığınızda elinizde three.js olur.
Birlikte çalışan render'lar
Mantıklı bir kullanım örneği, "3B" olarak iyi görünen şeyler çizmek için birden fazla görüntü oluşturucunun bir arada kullanılmasıdır. WebGL birçok sayıyı işleyip gerçekten gerçekçi görüntüler oluşturabilir, ancak metin ve hatta bazı çizgileri işlemede zayıftır. Ek bir görüntü oluşturulmuş metin katmanı CSS ve Canvas görüntü oluşturucuları ile işlenebilirken, yollar ve çeşitli çizgiler SVG ile işlenebilir.
ÜÇ.WebGLRenderer
Tüm bu düşük seviyeli bilgiler, three.js WebGLRenderer sınıfı aracılığıyla soyutlanır. Bu, küpü GPU belleğinde bir dizi sayıya dönüştürür.
İronik olarak, 3B grafikler oluşturması gerekmeyen tek three.js görüntüleyicisi olsa da, bu iş için en iyi seçenektir. Geri kalanı 2B API'leri kullanarak 3B'yi taklit ederken, WebGL kasıtlı olarak genel bir paralel hesaplama API'si kullanarak 3B oluşturur. Ancak bu, onu yalnızca canlı video akışını işlemek için kullanabileceğiniz bir senaryoyu ortadan kaldırmaz. WebGL'den yeterince soyutlama yaparak bu iş için kullanışlı olabilir, ancak muhtemelen kütüphanenin üçte birini kullanıyorsunuzdur. WebGL ile son derece duyarlı bir kullanıcı arayüzü katmanı veya three.js'nin hala harika bir araç olacağı bir Super Mario tarzı platform oyunu oluşturabilirsiniz.
Kütüphanenin yalnızca üçte birini kullanıyor olmanız, bu kullanım için farklı bir aracın daha uygun olabileceği veya three.js'nin bir alt kümesini oluşturabileceğiniz anlamına gelir. Hem Super Mario hem de video işleme örnekleri yalnızca PlaneGeometry ve belki de bir malzeme türüne ihtiyaç duyabilir.
üç matematik
3B'de belirli matematiksel işlemleri gerçekleştiren JavaScript kodu. JS'de varsayılan olarak Math.pow() bulunur, ancak Quaternion.inverse() bulunmaz. Bu sınıflarla, render gerektirmeyen algoritmalar yazabiliriz; örneğin, kimin ateş ettiğini, kimin çok sayıda ışın çektiğini ancak hiçbir şey çizmediğini doğrulayan bir oyun sunucusu.
üç sahne grafiği
Bir "3B dünya"yı ve içindeki nesnelerin ilişkilerini tanımlayan bir ağaç veri yapısı oluşturan bir Object3D alt sınıfları ailesi. Kavramsal olarak soyuttur, ancak koda derinlemesine indiğinizde belirli bir işlemeyle bir dereceye kadar işlenebilir.
üç render
Bu genel grafiği ekranda veya bir tamponda görsel bir temsile dönüştüren katmandır (örneğin, bunu sunucu tarafında oluşturursunuz). Bu amaca ulaşmak için çeşitli teknolojiler kullanır.
ÜÇ-WebGLRenderer
Donanım hızlandırmaya olanak tanıyan ve birçok 3B kavramını bilen, ancak aynı zamanda 2B (ve hatta genel bilgi işlem) için de kullanılabilen özel bir görüntüleyici. Bence bunlar three.js'nin temel yapı taşları. Ben genellikle "3B" yerine "Grafikler" kullanmayı tercih ediyorum, ancak bu yalnızca WebGLRenderer için geçerli.
Three.js bir oyun motoru değildir.
Web'de 3B (veya grafik) ihtiyacı olan herkes oyun yapmıyor. Oyun motorları genellikle 3B dünyaları tanımlamanın ve görüntülemenin ötesinde birçok optimizasyon yapar. Farklı oyunların farklı ihtiyaçları vardır ve gerçek zamanlı strateji ve birinci şahıs nişancı oyunlarının fizik ve render sistemlerinin de çok farklı ihtiyaçları olması muhtemeldir. Tüm bunlar daha fazla kod anlamına gelir ve bir ürün kataloğunun parçası olarak sadece bir 3B model oluşturmak isteyen biri için bu sadece gereksiz değil, aynı zamanda istenmeyen bir durumdur. Elbette, bir oyun motoru oluşturabilir ve render ve motor blokları oluşturmak için üçünü kullanabilirsiniz.
Three.js pek yüklenmiyor
Elbette, çekirdekte bazı varlıklar için birden fazla yükleyici bulunur, ancak gltf veya fbx gibi tüm yaygın formatlar birbirinden bağımsızdır. Threejs, varlıklarınızı nasıl edindiğinizle ilgilenmez; yeter ki onları doğru şekilde ayrıştırıp 3B bir nesne oluşturun. Threejs açısından, bir gltf dosyasından alınan bir ağ ile prosedürel bir küre arasında hiçbir fark yoktur. Birçok yaratıcı örnek, küpler ve küreler kullanır ve Three.js'nin kendisi dışında hiçbir şey yüklemez. Çekirdek yükleyiciler oldukça geneldir; görselleri ve dosyaları yükler ve Malzeme veya Doku gibi bir Threejs nesnesinin doğrudan bir temsilini sunar. Formata özgü yükleyiciler bu yapı taşlarıyla oluşturulur.









