holodepth

Three.js · Sahne & geometri

Geometrinin anatomisi ve veri yönetimi

3D web geliştirmede geometri, bir nesnenin uzaydaki fiziksel varlığını tanımlayan saf matematiksel veridir. Three.js'te bir objeyi "görmek", aslında GPU'ya binlerce noktanın koordinatlarını ve bu noktaların nasıl birleşeceğini söylemektir. Modern bir projede asıl iş, bu veriyi doğru yapılandırmak ve verimli taşımaktır.

Pratikte ekranda gördüğünüz cisim bir Mesh'tir: geometri (shape; şekil) ile materyal (appearance; görünüş) bir araya gelir; şekil verisi tek başına renk, parlaklık veya doku üretmez. Materyal Giriş sayfası bu ikinci yarıyı tamamlar.

3D veri katmanları: vertex'ten yüzeye

Dijital bir objenin iskeleti (shape verisi) üç katmandan okunur; materyal ve ışık bunların üstüne biner; sahne grafiği ( Object3D ) nesnenin nerede durduğunu, geometri ne şekilde olduğunu tanımlar:

  • Vertices (noktalar): Uzaydaki (x, y, z) (ve gerektiğinde normal, UV gibi) attribute verisinin atomik satırıdır — her şey buradan başlar. BufferGeometry'da çoğu zaman position dizisi olarak GPU'ya gider; binlerce köşe tek bir typed array içinde paketlenir. Noktayı kaydırmak, tüm bağlı kenar ve yüzeyleri dolaylı olarak etkiler.
  • Edges (kenarlar): İki vertex arasındaki bağ — çoğu zaman “iki index yan yana” olarak düşünülür. Tam yüzeyli render’da kenarlar ayrı çizilmez; tel kafes (wireframe) veya EdgesGeometry / çizgi materyali ile hata ayıklama ve teknik çizim hissi için görünür kılınır. Kenar, yüzeyden önce kavramsal bir ara basamaktır.
  • Faces (yüzeyler): En az üç vertex ile kapanan üçgen — GPU rasterization yalnızca üçgenleri ekrana çizer. Dörtgen yüz bile iki üçgene bölünür; karmaşık modeller “üçgen çorbası”dır — aşağıdaki triangulation paragrafı bunu geneller. Hangi üçgenin “ön” yüz sayılacağı vertex sırasına (winding) bağlıdır; hemen alt başlıkta.

Tüm modern GPU'lar, nihai olarak her yüzeyi üçgenlere indirger (triangulation); dörtgen veya daha karmaşık çokgenler bile rasterization aşamasında bu atomik üçgenlere ayrılır.

Winding order (vertex sırası): Bir üçgenin köşelerinin bağlanma yönü, yüzeyin "ön" mü yoksa "arka" mı olduğunu belirler. Ters bir sıralama, yüzeyin kameraya arkasını dönmesine ve materyal ayarlarınıza bağlı olarak görünmez olmasına (back-face culling) yol açar.

Hazır geometriler ve parametrik yaklaşım

Three.js, kodla anında üretilen primitive (ilkel) geometriler sunar; BoxGeometry, SphereGeometry, PlaneGeometry, CylinderGeometry gibi. Bunlar parametrik formüllerle vertex ve üçgen üretir; Blender’dan gelen glTF ağının yerini öğrenme ve prototipte alır, üretimde çoğu zaman özel mesh veya düşük segment bilinçli seçim tercih edilir. Ayrıntılı primitive listesi Primitive geometriler konusundadır; burada segment fikrini netleştiriyoruz.

  • Segment sayısı: Küre, silindir veya düzlemde yüzeyi kaç parçaya böldüğünüzdür (widthSegments, heightSegments, radialSegments …). Segment arttıkça üçgen sayısı ve bellek artar; kenarlar daha yuvarlak, silüet daha pürüzsüz görünür. Öğrenirken “yüksek = güzel” alışkanlığı kolaydır; üretimde “yeterince düşük, yeterince iyi” hedeflenir — kameradan uzak zemin düşük segment, yakın hero nesne biraz daha yüksek olabilir.
  • Performans bütçesi: Gereksiz yüksek segment, vertex attribute ve draw maliyetini şişirir; mobil ve VR’da triangle bütçesi hızla dolar. Düşük poligonlu ( low-poly) geometri + iyi normal / PBR materyal çoğu zaman yüksek poligon + basit materyalden daha ikna edici ve hızlıdır — materyal tarafı şekli “tamamlar”. Primitive’ler de sonuçta BufferGeometry olarak GPU’ya gider; segment seçimi, o tamponun boyutunu doğrudan belirler.

BufferGeometry: GPU ile doğrudan iletişim

Modern Three.js'te performans kalbi BufferGeometry'dedir: vertex verisi Float32Array ve benzeri typed array'lerde paketlenir, WebGL buffer nesnelerine yüklenir. Eski Geometry sınıfı kaldırıldı; BoxGeometry gibi primitive'ler de arka planda bu yapıyı üretir (segment seçimi doğrudan tampon boyutunu etkiler). Amaç, her karede binlerce Vector3 nesnesi oluşturmak yerine tek seferlik, GPU'ya uygun bellek düzenidir.

  • Hız: Veri bir kez (veya seyrek) CPU’dan GPU’ya gider; çizim sırasında yalnızca buffer referansları kullanılır — RAM ↔ GPU köprüsü minimize edilir. Sahne grafiğinde Mesh konumu her tick değişebilir; geometri buffer’ı çoğu statik mesh’te sabit kalır. Kullanılmayan geometriyi geometry.dispose() ile serbest bırakmayı unutmayın (sayfa sonu dispose notu). Dinamik deformasyon (parçacık, cloth) istisnadır; orada attribute dizileri bilinçli güncellenir.
  • Öznitelikler (attributes): Her vertex için paralel kanallar: position (şekil), normal (ışık / gölge yönü), uv (doku sarma) — malzeme ve ışık bunları okur, geometri tek başına renk üretmez. setAttribute('position', …) ile eklenir; paylaşılan köşeler için setIndex bellek kazanır. Eksik normalde computeVertexNormals() yardımcı olur; ayrıntılı tür tablosu hemen altında.

Mesh = geometri + materyal; renderer.render(scene, camera) bu buffer’ları pipeline’dan geçirip piksele çevirir. Nesnenin nerede durduğu Object3D transformudur; yerel / dünya ayrı katmandır. Rasterization ve WebGL hattının özeti Renderer · pipeline sayfasındadır; burada geometri verisinin GPU’ya nasıl paketlendiğine odaklandık.

Teknik tablo: veri türleri ve fonksiyonları

Özellik Teknik karşılık Neden önemli?
Position Float32Array Nesnenin asıl fiziksel şeklini ve hacmini belirler.
Normal Vector3 (attribute olarak paketlenir) Yüzeyin baktığı yönü belirleyerek gölge ve ışık hesaplarını mümkün kılar.
UV mapping Vector2 (attribute olarak paketlenir) 2D bir resmin (doku), 3D yüzeye hatasız giydirilmesini sağlar.
Index Uint16Array / Uint32Array Aynı noktayı kullanan üçgenlerde veriyi tekrar yazmaz; bellek tasarrufu sağlar.

Uygulama: manuel veri yönetimi

Bir BufferGeometry oluştururken sadece noktaları girmek yetmez; sistemi tam verimle çalıştırmak için sınırlayıcı hacimleri (bounding volumes) hesaplamalı ve ışık için gerekliyse normalleri üretmelisiniz:

// 1. Veri hazırlığı
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array([-1, -1, 1, 1, -1, 1, 1, 1, 1]);

// 2. Veriyi GPU'ya bağlama
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));

// 3. Otomatik hesaplamalar (hayati adımlar)
geometry.computeVertexNormals(); // Işık hesapları için gerekli
geometry.computeBoundingBox(); // Görünürlük (culling) testleri için gerekli
geometry.computeBoundingSphere(); // Mesafe bazlı optimizasyonlar için gerekli

Holodepth notu: Bellek temizliği (dispose)

Yazılım dünyasında çöp toplayıcılar (garbage collector) JavaScript nesnelerini temizler, ancak GPU belleği için bu geçerli değildir. Sahneden sildiğiniz bir nesne GPU belleğinde yaşamaya devam edebilir. Uzun süreli oturumlarda projenizin çökmemesi için, artık kullanılmayan geometrileri mutlaka geometry.dispose() komutuyla bellekten tamamen atmalısınız.