Kardeşim, birlikte Three.JS ile manyak şeyler yapacağız inşallah. Ama biraz sabretmen lazım. Eğer tüm bilgileri bir anda verirsem kafan karışır, vazgeçersin. Bu yüzden adım adım, sindire sindire gideceğiz. Ama biliyorum ki, bu kadar görsel ağırlıklı bir kütüphanede tutup da sana sınıfları anlatırsam, en fazla birkaç makale dayanabilirsin. Bu yüzden yazabileceğimizin en azıyla, Three.JS neler yapabiliyor, bir görelim bakalım.


Three.JS'i kullanabilmek için öncelikle ilgili kütüphaneyi sitesinden indirip sayfamıza eklemek gerekiyor. Kütüphanenin bulunduğu GitHub sayfasına bu adresten ulaşabilirsin. Burada Three.JS'in kaynak kodlarını göreceksin. Bizim işimize yarayacak derlenmiş halini ise "build" klasörü altında "three.min.js" adıyla bulabilirsin. Ben bu makaleyi yazarken en güncel versiyon R61'di.









Not : GitHub'a alışık olmayanlar için söylüyorum, bir dosyaya tıkladığınızda dosyanın içeriği direk açılmaz ancak açılan sayfadaki "Raw" butonuna tıklarsanız, önünüze indirmeye hazır dosya gelecektir. GitHub'u da öğrenin artık canım, hangi devirde yaşıyoruz.

İndirdiğimiz dosyayı, iyi bir alışkanlık olarak versiyonu da içerecek şekilde yeniden adlandırıyoruz ki takibi kolay olsun. Örneğin ben "three-r61.min.js" ismini kullanıyorum.

Dikkat : Bu makaleyi yazdığım sıralarda WebGL halen beta aşamasındaydı. Bu yüzden eski internet tarayıcılar ile aşağıdaki örnekleri çalıştıramazsın. En azından Internet Explorer 11+, Google Chrome 9+, Mozilla Firefox 4+, Safari 6+ veya Opera 12+ kurulu olması gerekiyor. Henüz beta aşamasında olduğu için bazen tarayıcıların uygulamayı durdurmasına ve sayfanın Refresh edilmesine ihtiyaç duyuyor. Ayrıca Android Chrome gibi bazı tarayıcılarda WebGL desteği varsayılan olan kapalı geliyor ve kullanıcı tarafından açılması gerekiyor. Örneğin Android'de bunu açmak için Chrome'da "chrome:\\flags" adresine girmek ve burada "Enable WebGL" seçeneğini aktif hale getirmek gerekiyor. Henüz Beta aşamasında olduğu için bunları anlayışla karşılamak lazım.

Bunun haricinde işimizi kolaylaştırması için JQuery kütüphanesini ve asıl program kodumuzu yazacağımız "program.js" dosyasını da HTML belgesine eklememiz gerekiyor. Bu durumda HTML belgesinin son hali aşağıdaki gibi oluyor (HTML sayfamız ile three-r61.min.js ve program.js dosyalarının yan yana durduğunu varsayıyorum).

<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1254" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="three-r61.min.js"></script>
<script src="program.js"></script>
</head>
<body>
</body>
</html>


Sanırım her şey hazır. Haydi o zaman, iş başına. "program.js" dosyamızı aşağıdaki kodlarla dolduruyoruz ("Temel JS" kategorisinde anlattığım (veya anlatacağım) gibi "use strict" ifadesini her kod bloğunun başında kullanma alışkanlığımıza devam ediyoruz).

"use strict";

var renderer, scene, camera;

$(document).ready(function () {

    addContainer();

    setStyle();

    prepareScene();

    addSphere();

    animation();

});

function addContainer() {

    $("body").append("
<br>"); } function setStyle() { $("html, body, #Container").css("width", "100%"); $("html, body, #Container").css("height", "100%"); $("html, body, #Container").css("padding", "0"); $("html, body, #Container").css("margin", "0"); $("html, body, #Container").css("overflow", "hidden"); $("html, body, #Container").css("backgroundColor", "#000000"); } function prepareScene() { var container = $("#Container"); renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(container.width(), container.height()); container.append(renderer.domElement); scene = new THREE.Scene(); var aspectRatio = container.width() / container.height(); camera = new THREE.PerspectiveCamera(45, aspectRatio, 0.1, 20000); camera.position.set(0, 150, 400); camera.lookAt(new THREE.Vector3(0, 0, 0)); var light = new THREE.PointLight(0xffffff); light.position.set(0, 250, 0); scene.add(light); var ambientLight = new THREE.AmbientLight(0x111111); scene.add(ambientLight); } function addSphere() { var geometry = new THREE.SphereGeometry(50, 32, 32); var material = new THREE.MeshLambertMaterial({ color: 0x11ff55 }); var sphere = new THREE.Mesh(geometry, material); scene.add(sphere); } function animation() { renderer.render(scene, camera); requestAnimationFrame(animation); }


Burada neler yazdığını anlatacağım ama önce biraz aksiyon görelim. Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor (Henüz fare ile etkileşim için bir kod yazmadığımızdan, ekranda sadece durağan bir görüntü ile karşılaşacaksın).



Internet tarayıcısı içerisinde 3D bir şekil. Işık, mışık. Üstelik bunun için herhangi bir player veya eklentiye de ihtiyaç duymuyor. Bildiğin HTML ve JavaScript. İlginç değil mi? Emin ol, daha hiçbir şey görmedin.

Yazdığımız kodu adım adım anlatmadan önce biraz ön bilgilendirme lazım.

Render, Animasyon, FPS. Siz de kimsiniz? Ne oluyor burada?

3D dünyasında yeniysen, bu terimler sana biraz yabancı gelebilir ve bundan sonrası için bunların özet anlamına ihtiyacın olabilir. Bakalım bunu ne kadar hızlı yapabileceğiz.

Render denilen kavram, geniş bir kitle tarafından değişik anlamlarda kullanılmasına karşın bizim için anlamı, sanal bir 3D dünyadaki görüntüyü, bir kameranın bakış açısından bakarak, 2D bir düzleme çizme olarak ifade edilebilir. Render işlemi sonrasında, kameranın bakış açısından, kameraya uygun perspektifte bir fotoğraf çekeriz ve belirlenen 2D yüzeye fotoğrafımızı yerleştiririz.

Yukarıda bahsedilen Render işlemi sonrasında elimizde durağan bir fotoğraf olur. Eğer ki biz, çok sayıda fotoğrafı ekrandan arka arkaya hızlı bir şekilde geçirirsek, çizgi filmlerde kullanılan teknik ile fotoğrafları hareketliymiş gibi gösterebiliriz. Bu yönteme de animasyon denir.

Buradaki "hızlı" kelimesinin karşılığı, animasyondaki pürüzsüz geçişi belirler. Örneğin saniyede 5 fotoğrafı geçirdiğimiz takdirde gözümüz geçişleri hissedecektir. Ancak örneğin saniyede 50 fotoğraf geçirebilirsek, bu durumda gözümüz bu geçişleri yakalayamaz ve pürüzsüz hareketli bir görüntü olarak görür. Burada saniyede geçen görüntü sayısına FPS (Frame Per Second) denilir. Oyuncuların düşük FPS değerlerinde, "oyun donuyor" demesinin sebebi de budur.

Anlatacak çok şey var ama kapsam dışına çıkmayalım. Wikipedia linkleri üzerinden okursun.

Artık kodumuza dönebiliriz. Senin de göreceğin gibi, kodumuzda üç adet metodumuz var. "addContainer" fonksiyonu ile HTML sayfamıza bir "Div" ekliyoruz. Three.JS kütüphanesi bu Div'i, kendi ekleyeceği Canvas'a container olarak kullanacak. Canvas, HTML 5 ile birlikte gelen üzerinde çizim yapılabilen özel bir HTML elemanıdır. Az önce yukarıda anlatılan Render işlemi sonrasında, kameramızdan çektiğimiz fotoğrafı bu Canvas üzerine yansıtacağız. "setStyle" fonksiyonu ile Div'in ve dolayısıyla Canvas'ın sayfanın tamamını kaplaması için gerekli olan CSS kodlarını ekliyoruz. Hatta arka fonu da siyaha boyuyoruz ki bizim etkileşim kurmadığımız alanlar karanlık olsun ve kafa karıştırmasın. Sanırım buraya kadar bir sorun yoktur. Geriye üç fonksiyon kaldı. "prepareScene", "addSphere" ve "animation". Haydi bunları sindire sindire inceleyelim.

İlk olarak "prepareScene" fonksiyonu çağırılıyor ki, adından da anlaşılacağı gibi, bu fonksiyon bizim için sahneyi hazırlıyor. Bakalım ne yapıyormuş.

var container = $("#Container");

renderer = new THREE.WebGLRenderer({ antialias: true });

renderer.setSize(container.width(), container.height());

container.append(renderer.domElement);


Bu kod bloğu ile, "Container" adındaki Div elemanımızı JQuery yardımı ile seçiyoruz. Ardından Three.JS'in WebGLRenderer grafik motorunu kullanmak için bir nesne tanımlıyoruz. Burada geçtiğimiz parametre "Anti-aliasing" işleminin yapılıp yapılmayacağını söylüyor. Bu seçenek ile, Render işlemi sonucunda şekillerin kenarlarının daha yumuşak hatlı olması sağlanıyor. Anlamak için en güzeli, "false" seçeneği ile deneme yapıp karşılaştırmak.


scene = new THREE.Scene();

Bu kod satırı ile, 3D dünyamızı içeren sahnemizi tanımlıyoruz. Bundan sonra uygulamamıza koyacağımız tüm şekiller, ışıklar ve kameralar bu sahnede yer alacak. Bunu sanal 3D dünyamız olarak kabul edebiliriz.


var aspectRatio = container.width() / container.height();

camera = new THREE.PerspectiveCamera(45, aspectRatio, 0.1, 20000);

camera.position.set(100, 70, 300);

camera.lookAt(new THREE.Vector3(0, 0, 0));



Bu kod bloğu ile, sahnemize bir kamera yerleştiriyoruz. Tahmin edeceğin gibi, bu kameranın gözünden bakarak Render işlemi uygulanacak. Three.JS'de değişik özelliklere sahip kameralar var. Bu yüzden şimdilik detaya çok girmiyorum ama özet olarak bu kamera tipi, gerçek dünyadaki bakış açımıza benzeyen ve en yaygın kullanan kamera tipidir. Kameralar ile ilgili makalemde, burada geçilen parametrelerin anlamları ile ilgili detaylı bilgi vereceğim inşallah. Şimdilik, bu kameranın (x,y,z) koordinat ekseninde (100,70,300) koordinatında durduğunu ve (0,0,0) koordinatına doğru baktığını bil yeter.


var light = new THREE.PointLight(0xffffff);

light.position.set(100, 100, 100);

scene.add(light);

var ambientLight = new THREE.AmbientLight(0x111111);

scene.add(ambientLight);


Bu kod bloğu ile, sahnemize iki adet ışık kaynağı yerleştiriyoruz. Yine Three.JS'de değişik özelliklere sahip ışıklar var ve her birinin kendine has parametreleri var. Bu yüzden şimdilik detaya çok girmiyorum ama özet olarak ilk eklediğimiz ışık tipi, ampul gibi noktasal bir ışık kaynağıdır ve bulunduğu koordinattan (Ki şu anda (100,100,100)'de duruyor) her yöne doğru eşit şekilde ışık yayar. İkinci ışık tipi ise, sahnenin geri kalan karanlık kısımlarında hafif bir ışıklandırılma yapılmasını sağlar. Dediğim gibi, sırf bu konu hakkında ayrı bir makale yazacağım, şimdilik çok takılma.

Böylece "prepareScene" fonksiyonunu tamamladık ve sahnemiz kullanıma hazır hale geldi. Sırada sahnemize bir küre eklememizi sağlayan bir "addSphere" fonksiyonu var, inceleyelim.

var geometry = new THREE.SphereGeometry(50, 32, 32);

var material = new THREE.MeshLambertMaterial({ color: 0x11ff55 });

var sphere = new THREE.Mesh(geometry, material);

scene.add(sphere);


Three.JS'de sahneye bir şekil eklemek için iki farklı özelliğini belirtmemiz gerekir. Bunlardan biri (küre, küp, silindir gibi) şeklin geometrik özelliği, diğeri ise şeklin yapıldığı materyal özelliğidir. Çoğu zaman yukarıdaki kadar uzun uzun yazmamıza gerek kalmaz ama bu seferlik tek tek anlatabilmek için yazdım. Bu iki özelliği tanımladıktan sonra, bunlar üzerinden "THREE.Mesh" fonksiyonu vasıtasıyla bir 3D şekil elde ederiz (Ki buna Mesh diyoruz). Son olarak da bu şekli sahnemize ekliyoruz.


function animation() {

    renderer.render(scene, camera);

    requestAnimationFrame(animation);

}

Kodumuzdaki son fonksiyon da yukarıdaki kısım. Bu blok aslında sonsuz bir döngüyü ifade ediyor ve bu döngü içerisinde belirtilen kameranın gözünden belirtilen sahnenin fotoğrafı çekilerek, Canvas elemanına yansıtılıyor. Buradaki "renderer.render(scene, camera);" komutu, saniyede en fazla 60 kez olacak şekilde çağırılıyor. Bu da saniyede 60 Render, yani 60 FPS demek. Ancak bu, bilgisayarın performansından bağımsız ulaşılabilecek en yüksek limit. Sahnemizdeki komplekslik arttıkça ve uygulamamızı çalıştıran bilgisayarın performansı azaldıkça bu değer de aşağıya doğru inecektir. 24 FPS "Progressive Format" olarak bilinir ve çoğu zaman bu ve daha yukarısı kabul edilebilir bir değerdir.

İlk örneğimizi daha fazla uzatmayarak burada noktalıyorum. Bu makalede neler öğrendiğimizi özetleyelim.
  • WebGL'i çalıştırabilmek için güncel bir tarayıcıya sahip olmamız gerekiyor.
  • Render, animasyon ve FPS kavramlarına artık aşinayız ve oyun oynarken donmaya başlarsa eskisi kadar kızmayacağız.
  • Three.JS ile sanal 3D sahnemize koyduğumuz şekilleri, yine sanal kameramız gözünden Render ettirerek Canvas'ın üzerine yansıtıyoruz.
  • Bu Render işlemini sonsuz bir döngü içerisinde gerçekleştirerek bir animasyonun ortaya çıkmasını sağlıyoruz.
  • Animasyonun teknik olarak ulaşabileceği en yüksek FPS değeri 60'dır. Ancak sahnenin kompleksliği ve uygulamayı çalıştıran bilgisayarın performansı bunu aşağıya çekebilir.
  • 24 FPS "Progressive Format" olarak bilinir ve çoğu zaman bu ve daha yukarısı kabul edilebilir bir değerdir.


Yorum Gönder

 
Top