Three.js · Geometri
Attributes ve Buffer’lar (veri katmanları)
Geometri = GPU’ya giden sayılar
Three.js’te bir geometri, GPU belleğine aktarılan bir dizi sayıdan ibarettir. Bu sayılar rastgele değil; BufferAttribute adı verilen yapılarda, belirli bir düzende (interleaved veya sequential) saklanır. GPU, bu buffer’lar üzerinden okuma yaparak her vertex’i ekrandaki piksellere dönüştürür; “şekil” dediğiniz şey, aslında bu sayıların okunma biçimidir.
Bu sayfa attribute ve buffer katmanına odaklanır: vertex başına hangi kanallar
vardır, Float32Array ile nasıl paketlenir, sequential / interleaved farkı nedir.
BufferGeometry’nin genel rolü ve vertex → yüzey çerçevesi
Geometri
giriş
sayfasındadır; primitive üretimi ve segment seçimi
Primitive
geometriler
konusuna bırakılır; burada tekrar etmiyoruz.
Manuel geometri yazımı ve özel buffer kurulumu Custom buffer geometri ile devam eder; ileri seviye interleaved ayrıntısı Interleaved buffers konusundadır. Aşağıda özel attribute örneği, bellek sayacı ve mobil bütçe notu bulunur.
Attribute nedir?
Attribute = her vertex için tekrar eden veri bloğu. “Modelin verisi”
dediğiniz
şey, aslında vertex sayısı boyunca uzanan sütunlardır:
position, normal, uv, color … Aynı satır
indeksi (ör. 42. vertex) tüm sütunlarda o köşeyi tanımlar; tablo gibi düşünün: satır =
vertex,
sütun = attribute kanalı.
Standart kanallar ne taşır?
Çoğu BufferGeometry en az position taşır; gerçekçi ışık ve doku
için
normal ve uv eklenir. color isteğe bağlıdır; vertex
başına renk veya varyasyon gerektiğinde devreye girer. Hepsi aynı vertex indeksinde
hizalanır; Typed Arrays bölümündeki
itemSize değerleri kanala göre değişir (3, 3, 2, 3 …).
- position: Şeklin iskeleti — köşenin model (yerel) veya dünya uzayındaki
(x, y, z)adresi. Olmadan mesh çizilemez; vertex shader buradan başlar,modelViewMatrixveprojectionMatrixile ekrana taşınır. Yerel / dünya ayrımı Object3D transform katmanındadır — geometri yalnızca “köşe adreslerini” verir. - normal: Yüzeyin o noktadaki “baktığı yön” vektörü; ışık, gölge ve PBR
hesapları buna göre yapılır. Düz renkli materyalde bile eksik normal, yüzeyin “düz veya
ters” görünmesine yol açar. Elle yazılmış geometride
geometry.computeVertexNormals()çoğu zaman yeterlidir; karmaşık ağlarda DCC’den gelen normal’ler tercih edilir — normal map materyal kanalından ayrıdır ( normal map yüzey pürüzünü taklit eder). - uv: 2B doku koordinatı (
u, v, genelde 0–1 aralığı) — hangi pikselin bu köşeye yapışacağını söyler; materyaldekimap,normalMap,roughnessMapvb. bu koordinatla örneklenir. UV olmadan düz renk çalışır; desen, logo veya PBR dokuları için şarttır. Sarma ve tekrar mantığı UV mapping konusundadır — burada yalnızca geometridekiuvattribute’una odaklanıyoruz. - color: (İsteğe bağlı) Vertex başına renk veya varyasyon; basit
gölgelendirme,
MeshBasicMaterialile vertex color, partikül veya özel shader girdisi için kullanılır — her mesh’te şart değildir. MateryaldevertexColors: trueaçılmadan buffer okunmaz; kanal yoksa materyal rengi / doku yeterlidir.
Özet: position zorunlu iskelet; normal + uv çoğu
gerçekçi sahne için pratik zorunluluk; color özel efekt. Kanal rollerinin kısa
tablosu
Geometri
giriş · veri türleri
sayfasında; burada paketleme ve bellek tarafına devam ediyoruz. Vertex → yüzey çerçevesi
Geometri giriş
sayfasındadır.
GPU her vertex için ne sorar?
Üstteki liste her kanalın ne taşıdığını anlatır; bu alt başlık ise draw
anında GPU’nun vertex shader’a ne okuduğunu hatırlatır. Her
draw çağrısında, indekslenmiş veya sıralı her köşe için attribute buffer’dan
bir
satır çekilir ve shader girdisi olur; binlerce vertex varsa bu döngü binlerce kez
tekrarlanır.
Vertex shader kabaca şu soruları yanıtlar; cevaplar attribute’lardan gelir:
- Position: Neredesin? — Okunan
positionönce model, sonra görüntü uzayına taşınır; çıktıgl_Positionile ekrandaki konuma dönüşür. Kanal tanımı yukarıda. - Normal: Nereye bakıyorsun? (yüzey yönü) — Işık yönü ve gölgelendirme
bu vektöre göre hesaplanır; normal eksik veya tersse yüzey “içe dönük” veya düz görünür.
Dönüşüm matrisleri normali de döndürür (
normalMatrix). - UV: Üzerine hangi doku (texture) parçasını giyeceksin? — Vertex shader
UV’yi çoğu zaman fragment’a iletir (
varying); asıl doku örnekleme fragment aşamasında, materyalinmapkanallarıyla yapılır. - Color: (Varsa) Senin rengin ne? —
colorattribute yoksa bu soru sorulmaz; varsa vertex rengi materyal rengi veya doku ile karıştırılabilir (vertexColors: true).
Özet: attribute’lar vertex shader’ın ham girdisi; matris çarpımları onları ekrana taşır. Üçgenler oluştuktan sonra fragment shader piksel başına renk, derinlik ve doku hesaplar; geometri buffer’ları o aşamada yeniden okunmaz, vertex aşamasında okunan değerler interpolate edilir. Tam hat Renderer · pipeline sayfasında; burada yalnızca “köşe başına okunan dört soru” vurgulanır.
Vertex sayısı ve Three.js isimlendirmesi
GPU her vertex için attribute’ları tekrar tekrar işler. 1000 vertex varsa
position, normal, uv gibi her aktif kanal da
1000 kayıt üzerinden okunur; vertex sayısı, her sütunun “yüksekliğini”
belirler.
Üçgen sayısı arttıkça çizim maliyeti artar; attribute dizilerinin uzunluğu ise benzersiz
köşe
sayısına bağlıdır.
Three.js tarafında kanallar geometride isimle tutulur:
geometry.attributes.position, geometry.attributes.normal,
geometry.attributes.uv, geometry.attributes.color vb. Eksik
attribute
eklemek veya özel kanal tanımlamak
sonraki bölümde
setAttribute ile yapılır. Position / normal / UV / index rollerinin kısa
tablosu
Geometri
giriş · veri türleri
sayfasındadır; burada tekrar etmiyoruz.
Paylaşılan köşeler için geometry.index aynı vertex satırını birden fazla
üçgende
kullanır; böylece attribute verisi tekrar yazılmaz. Attribute boyutu çoğu zaman
position.count ile okunur; bellek tahmini için
bellek sayacına bakın.
Typed Arrays ve BufferAttribute
JavaScript’in standart dizileri (Array) esnektir ama grafik tarafında veri
transferi için pahalıdır: elemanlar farklı tiplerde olabilir, bellek düzeni GPU’nun
beklediği
gibi ardışık değildir. Bu yüzden TypedArray kullanılır; özellikle
Float32Array: bellekte kesintisiz bir blok kaplar; GPU veriyi tek hamlede
“yutabilir”. Önceki bölümdeki attribute sütunları, pratikte bu typed array’lerin geometriye
bağlanmış halidir.
Float32Array: CPU’dan GPU’ya köprü
Koordinat ve çoğu shader girdisi 32-bit kayan nokta ile yeterlidir; bu yüzden
Float32Array en sık görülen seçimdir. Her sayı bellekte 4 byte
yer kaplar; örneğin 10.000 vertex’lik yalnızca position kanalı kabaca
120 KB ham veridir (meta veri ve diğer kanallar hariç). Tahmin için
bellek sayacı kullanılabilir.
İndeks listesi için çoğu zaman Uint16Array veya büyük mesh’lerde
Uint32Array tercih edilir; paylaşımlı köşe mantığı
Attribute nedir? bölümünde
kısaca geçilmişti.
BufferAttribute ve itemSize
Ham dizi tek başına yetmez; Three.js’e “bu sayıları nasıl okuyacağını” söyleyen sarmalayıcı
BufferAttribute’dur:
new THREE.BufferAttribute(typedArray, itemSize)
Item size, bir attribute’un kaç bileşenden oluştuğunu belirtir; GPU’ya
“her vertex kaydı şu kadar ardışık sayıdan oluşur” demenin yoludur. Dizi uzunluğu itemSize’a
bölünürse vertex sayısı çıkar:
attr.count === typedArray.length / itemSize.
Kanal adı ile itemSize eşleşmesi ( standart kanallar) şöyledir; yanlış itemSize, GPU’nun sayıları yanlış gruplamasına yol açar (kaymış veya patlamış mesh):
- position: itemSize 3 —
x, y, z - uv: itemSize 2 —
u, v - normal: itemSize 3 — yüzey yönü
- Özel kanal: Örneğin
aSizeiçin itemSize 1 — tek skaler per vertex; uygulama bölümünde gösterilir
setAttribute: geometriye bağlama
Typed array hazır olduktan sonra kanal ismiyle geometriye eklenir. İsim,
shader ve Three.js tarafında attribute’u tanımlar; aynı geometriye
normal, uv gibi başka kanallar da aynı kalıpla bağlanır.
Aşağıdaki örnek yalnızca position ile tek üçgenin üç köşesini tanımlar:
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array([
-1, -1, 1,
1, -1, 1,
1, 1, 1,
]);
geometry.setAttribute(
'position',
new THREE.BufferAttribute(vertices, 3)
);
Adım adım okuma:
- BufferGeometry: Boş bir geometri kabı; attribute’lar sonradan
setAttributeile takılır. - Float32Array: Dokuz sayı = 3 vertex × itemSize 3. Dizi düz akar;
gruplama
BufferAttribute’un ikinci argümanı (3) ile yapılır —vertices.length / 3 === 3vertex. - setAttribute('position', …): Bu kanalı “konum” olarak kaydeder;
erişim
geometry.attributes.positionüzerinden olur.
Bu örnek tek üçgen çizer (varsayılan drawRange ile). Daha karmaşık mesh’lerde
aynı position dizisine ek olarak geometry.setIndex(...) ile köşe
paylaşımı tanımlanır; indeks ayrı bir buffer’dır, itemSize genelde 1 (
Attribute nedir? bölümünde geçmişti).
Işık için çoğu zaman
geometry.computeVertexNormals() veya elle normal attribute’u
eklenir; tam manuel akış
Geometri giriş · manuel veri
örneğinde; burada yalnızca bağlama kalıbı gösterilir.
BoxGeometry gibi primitive’ler aynı yapıyı sizin yerinize üretir; Primitive
geometriler
konusunda parametre verirsiniz, içeride yine setAttribute benzeri bir yol
izlenir.
Statik mesh’te veri bir kez yüklenir; her karede dizi değişiyorsa
attribute.needsUpdate = true ve çoğu zaman
DynamicDraw; buffer kullanım tablosu.
Özel geometri ve çok kanallı kurulum
Custom
buffer geometri
ile devam eder.
Teknik tablo: buffer tipleri ve kullanım amaçları
| Buffer türü | İçerik | GPU rolü |
|---|---|---|
StaticDraw |
Çoğu geometri için varsayılan senaryo (küp, küre, statik mesh). | Default düşün: Veri genelde bir kez yüklenir, çok hızlı okunur. |
DynamicDraw |
Vertex sürekli değişiyorsa (animasyon, dalga, deformasyon). | Önemli: Sık güncelleme için; CPU→GPU akışı vardır. |
StreamDraw |
Çok nadir güncellenen veriler. | Nadir: Bazı akış senaryoları için; çoğu projede gerekmez. |
GPU’ya veri gönderme: interleaved vs sequential
Profesyonel projelerde veriyi nasıl dizdiğiniz, GPU’nun önbellek (cache)
davranışını etkiler. İki yöntem de aynı sayıları taşır; aynı
position, normal, uv kanalları (
standart kanallar); fark,
vertex shader bir köşeyi işlerken bellekte ne kadar sıçradığınızdır.
Sequential “her kanal ayrı rafta” okumak; interleaved “bir köşenin tüm evrakı arka arkaya”
okumak gibidir.
Kurulum ayrıntısı (InterleavedBuffer,
InterleavedBufferAttribute, stride, offset)
Interleaved buffers
konusunda kalır; burada kavram, artı/eksi ve karar.
Sequential (ardışık) — Three.js varsayılanı
Önce tüm konumlar, sonra tüm normaller yazılır; uv ve diğer kanallar ayrı
dizilerde devam eder. Her kanal kendi BufferAttribute ve çoğu zaman ayrı GPU
buffer’ıdır; setAttribute('position', …),
setAttribute('normal', …) kalıbı (
önceki bölüm) doğrudan buna
uyar.
CPU’da üretmek, debug etmek ve yalnızca position animasyonu yapmak kolaydır; Three.js’in doğal yolu budur.
- Artı: Okunaklı kod; tek kanalı güncellerken diğer dizilere dokunmazsınız; Holodepth öğrenme ve çoğu web sahnesi için yeterlidir.
- Eksi: Çok büyük mesh’lerde GPU, bir vertex için
position,normalveuvokurken bellekte uzak bölgelere atlayabilir — cache isabetsizliği teorik olarak artar (her GPU’da ölçülmeli).
Interleaved (iç içe)
Bir vertex’in konumu, normali, rengi bellekte yan yana yazılır:
[pos, norm, col, pos, norm, col, …]. Tek büyük typed array veya paylaşılan
buffer
üzerinde her attribute farklı offset ile okunur. GPU bir vertex işlerken o
köşeye ait alanların çoğu aynı bellek bandında kalır; büyük, statik, tek sefer yüklenen veri
setlerinde cache performansı daha iyi olabilir; her cihazda ve her sahne
tipinde garanti değildir.
- Artı: Vertex başına yerellik; devasa statik mesh’lerde profiler ile görülen kazançlar.
- Eksi: Paketleme, export ve tek kanal güncelleme zahmetli; stride/offset hatası mesh’i sessizce bozar — önce sequential ile doğrulayıp sonra dönüştürmek daha güvenlidir.
Kısa karar rehberi
“Önce doğru çalışsın” diyorsanız sequential ile kalın. Veri setiniz devasa, erişim paterni net ve hedef cihazda profil ile kazanç ölçülmüşse interleaved bazı GPU’larda daha iyi çıkabilir; varsayım yerine kare süresi ve bellek ölçün.
- Sequential tercih: Prototip, öğrenme, sık attribute güncellemesi (
needsUpdate, dalga, morph), küçük–orta mesh, birden fazla kaynaktan birleşen geometri. - Interleaved tercih: Tek büyük statik mesh (terrain, scan), attribute seti sabit, mobil veya düşük bant genişliğinde ölçülen darboğaz.
- Ölçüm: Layout değişikliği her platformda aynı sonucu vermez; ham attribute boyutu için bellek sayacı, performans için hedef cihazda FPS / frame time.
Aynı verinin iki dizilimini satır satır karşılaştırmak için hemen altındaki
görsel şema bölümüne geçin; tablo
orada, burada yorum. Kanal anlamı
Attribute nedir?; typed array ve setAttribute
Typed Arrays
bölümünde; burada yalnızca bellek düzeni farkı anlatılır.
Görsel şema: aynı veri, iki farklı dizilim
Aşağıdaki şema, GPU’nun bellekte “nasıl yürüdüğünü” hissettirir. Solda ardışık kanallar, sağda vertex başına paketlenmiş kayıtlar:
Sequential → yönetimi kolay (Three.js default) · Interleaved → cache dostu olabilir (büyük veri).
| Sequential (kanal kanal) | Interleaved (vertex vertex) |
|---|---|
|
|
Uygulama: özel bir attribute eklemek
Sadece konumu değil, her vertex’e rastgele bir “boyut” veya “hız” bilgisi ekleyip shader’da
kullanmak için, yeni bir TypedArray oluşturup geometriye isimle bağlarsınız. GPU bu veriyi
shader içinde attribute float aSize olarak tanır.
Bağlantı şu: bu değer, vertex shader’da bir hesapta “çarpan” olur. Örneğin point cloud
çiziyorsanız:
gl_PointSize = aSize * 10.0;
const geometry = new THREE.BufferGeometry();
const count = 5000;
// Her vertex için 1 değer (itemSize: 1)
const sizes = new Float32Array(count);
for (let i = 0; i < count; i++) {
sizes[i] = Math.random(); // 0 … 1 arası rastgele ölçek
}
// 'aSize' adında özel bir attribute oluşturuyoruz
geometry.setAttribute('aSize', new THREE.BufferAttribute(sizes, 1));
// GPU bu veriyi shader içerisinde 'attribute float aSize' olarak tanıyacak.
attribute float aSize;
void main() {
// ... position transform ...
gl_PointSize = aSize * 10.0;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
Mini araç: attribute belleğini anında hesapla
“Bu geometri kaç KB/MB yer tutar?” sorusu pratikte en çok iş yapan refleks. Aşağıdaki araç,
seçtiğiniz vertex sayısı ve attribute seti için yaklaşık ham veri boyutunu
hesaplar; Three.js’te sık kullanılan Float32Array / Float32
varsayımıyla (her bileşen 4 byte).
Bu bir GPU sürücü raporu değildir: index buffer, geometri
meta verisi, InterleavedBuffer hizalama dolgusu ve doku belleği dahil
değildir; ama “sadece bu dört attribute ile kaç MB büyür?” tahmini için hızlı bir cetvel
işlevi görür.
Attribute bellek sayacı
Float32 · canlı tahmin
Satır satır (Float32)
- position —
- normal —
- uv —
- color —
index buffer ve geometri ötesi bellek bu toplama dahil değildir.
Holodepth notu: bellek bütçesi
Attribute’lar çok hızlı büyür: önce ihtiyacı ölç
Her bir Float32Array elemanı bellekte 4 byte yer kaplar.
1 milyon vertex’li bir modelde sadece position verisi bile yaklaşık
12 MB (\(1{,}000{,}000 \times 3 \times 4\) byte) yer tutar.
Normaller, UV’ler ve diğer attribute’lar eklendikçe bu miktar hızla artar. Mobil cihazlarda çökme yaşamamak için her zaman ihtiyacınız olmayan attribute’ları temizleyin ve gerekiyorsa LOD / basitleştirme stratejileri kullanın.