holodepth

Three.js · İleri geometri

Custom Attributes: Geometriye Kişisel Bir Kimlik Kazandırmak

Standart kanalların ötesinde, vertex başına özel veri taşımak

Advanced Geometri yolculuğunun bu durağında, Three.js’in sunduğu standart sınırların dışına çıkıyoruz. position, normal ve uv gibi varsayılan değerler bir objenin şeklini ve dokusunu belirler; ancak custom attribute’lar, o geometriye özel davranış veya görsel “karakter” yükleyen ek veri kanallarıdır.

Temel attribute modeli için Attributes & buffer’lar; özel geometri inşası için Custom BufferGeometry; çoklu örnek için Instancing.

Custom attribute nedir?

Kısaca: bir attribute, GPU’ya her bir vertex (veya ilgili shader girişi) için gönderdiğiniz veri kanalıdır. Standart attribute’lar (ör. position) motor ve materyal tarafından doğrudan kullanılır; custom attribute ise adını ve anlamını siz tanımlarsınız — tipik olarak yazdığınız ShaderMaterial / RawShaderMaterial içindeki GLSL kodu ile anlamlandırılır.

Örneğin bir deniz yüzeyi simülasyonunda, her dalga tepesinin fazını, yüksekliğini veya bir parçacığın kalan ömrünü vertex başına taşıyarak CPU’da tek tek döngü yazmadan GPU’da yoğunlaştırabilirsiniz.

Neden “uniform” değil de “attribute”?

Yeni başlayanların sık karıştırdığı nokta: uniform tüm çizim çağrısı boyunca tek değerdir (zaman, genel renk, global parametre); tüm vertex’ler aynı uniform’u okur. Attribute ise vertex başına (veya ilgili düzenlemeye göre instance başına) farklı değer taşır — 10.000 noktanız varsa, teoride 10.000 ayrı “hız”, “ölçek” veya “parlaklık” katsayısı taşınabilir.

Bu ayrım, hem görsel çeşitlilik hem de performans stratejisi için kritiktir: örneğin instancing ile tek draw call altında her örneğe farklı karakter vermek, sıklıkla attribute (veya instance attribute) kombinasyonlarıyla kurulur.

Tür Kapsam Tipik kullanım
uniform Tüm vertex’ler / fragment’ler için ortak Zaman uTime, genel renk, global eşik değerleri
attribute / custom Vertex (veya instance) başına Faz, ömür, rastgele ofset, köşe başına renk ağırlığı

Bu ayrımı en net gösteren örneklerden biri nokta bulutu (Points) tabanlı sahnelerdir: her vertex kendi hızı, fazı, yönü ve ekran boyutuyla hareket edebilir. Aşağıdaki canlı modelde yaklaşık 12.000 parçacık; vertex başına dört özel kanal (aRandomSpeed, aRandomPhase, aRandomSize, aRandomDir) taşınır. Teknik ölçüler demo sabitleri tablosunda doc-custom-attributes-demo.js ile satır satır eşlenir.

Canlı demo · Points
Vertex

Uniform mod: tüm noktalar aynı yön ve hızla salınır; ölçek de ortaktır. Custom attribute mod: her vertex kendi shader verisini okur — bulut “dağılır” ve ritimleri farklılaşır.

Aynı geometri ve aynı zaman (uTime) ile iki mod arasında geçiş yapın: fark sadece verinin tek mi yoksa vertex başına mı taşındığında ortaya çıkar.

Demo sabitleri tablosu (Points · uniform ↔ attribute)

initCustomAttrParticleDemo ve buildParticleGeometry: aynı ShaderMaterial içinde uAttrMix ile ortak uniform yolu ile vertex başına kanallar arasında geçiş.

initCustomAttrParticleDemo · nokta bulutu
Sahne / rol Parametre Değer Tür
Örneklem PARTICLE_COUNT 12000 🔒 Sabit
Konum küre içi + yarıçap randomUnitSphere · r = 0.55 + rand × 0.95 🔒 Sabit
Custom float aRandomSpeed 0.55 + rand × 1.85 🔒 Sabit
Custom float aRandomPhase rand × 2π 🔒 Sabit
Custom float aRandomSize 4.2 + rand × 10.5 🔒 Sabit
Custom vec3 aRandomDir birim küre yönü (randomUnitSphere) 🔒 Sabit
Uniform (paylaşık yön) uUniformDir (0.22, 1, 0.12) normalize 🔒 Sabit
Uniform uUniformSpeed / uUniformPointSize 1.15 · 6.8 🔒 Sabit
Vertex shader yer değiştirme dir * sin(uTime × speed + phase) × 0.48 (speed / dir uniform ↔ attribute mix) 🔒 Sabit
Vertex shader gl_PointSize sizeBase × (320 / max(0.001, -mvPosition.z)) · clamp(2, 36) 🔒 Sabit
Fragment shader daire + renk discard if length(gl_PointCoord-0.5) > 0.5 · cyan–mor mix · α edge × 0.88 🔒 Sabit
Materyal ShaderMaterial transparent: true · depthWrite: false · NormalBlending 🔒 Sabit
Kamera PerspectiveCamera FOV 48 · yakın/uzak 0.06 / 80 · konum (0, 0.15, 4.35) 🔒 Sabit
Pivot dönüş / zaman y += dt × 0.11 · x += dt × 0.04 · uTime += dt 🔒 Sabit
Renderer makeRenderer ACESFilmicToneMapping · exposure 1.35 · SRGBColorSpace · setPixelRatio(min(dpr,2)) · setSize(…, true) 🔒 Sabit
Mod geçişi uAttrMix uniform mod 0 · custom attribute mod 1 ↔ UI
JS başlangıç mode 'attributes' (HTML ile uyumlu: Custom attribute mod seçili) 🔒 Sabit

Önemli kod kesiti

Geometriye position ile birlikte dört özel BufferAttribute eklenir; shader’da uAttrMix ile uniform tabanlı hareket ile per-vertex veri arasında mix yapılır.

const PARTICLE_COUNT = 12000;

const geo = new THREE.BufferGeometry();
geo.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geo.setAttribute('aRandomSpeed', new THREE.BufferAttribute(aRandomSpeed, 1));
geo.setAttribute('aRandomPhase', new THREE.BufferAttribute(aRandomPhase, 1));
geo.setAttribute('aRandomSize', new THREE.BufferAttribute(aRandomSize, 1));
geo.setAttribute('aRandomDir', new THREE.BufferAttribute(aRandomDir, 3));

const material = new THREE.ShaderMaterial({
  uniforms: {
    uTime: { value: 0 },
    uAttrMix: { value: 1 },
    uUniformDir: { value: uUniformDir },
    uUniformSpeed: { value: 1.15 },
    uUniformPointSize: { value: 6.8 },
  },
  vertexShader: VERT,
  fragmentShader: FRAG,
  transparent: true,
  depthWrite: false,
  blending: THREE.NormalBlending,
});

function applyMode() {
  const isAttr = mode === 'attributes';
  material.uniforms.uAttrMix.value = isAttr ? 1 : 0;
}

Neden bu model? Attribute tam olarak vertex başına veridir; farkı en çok hissettiren şey, her noktanın bağımsız davranmasıdır. Üretimde sık görülen alternatifler (dalgalanan düzlem, küre deformasyonu, instanced küpler) bu sayfada da iş görür; ancak düzlem bazen displacement / mapping konusuyla karışır, kürede fark daha az belirgindir, instancing ise başlı başına ayrı bir konu başlığıdır.

Teknik yapılandırma ve veri akışı

Custom attribute eklerken verinin CPU’dan GPU’ya yolculuğu kabaca şu adımlarla özetlenir:

  1. Veri hazırlama: JavaScript tarafında vertex sayınızla orantılı bir Float32Array (veya ihtiyaca uygun başka typed array) oluşturursunuz.
  2. BufferAttribute: Bu diziyi Three.js’in anlayacağı bir BufferAttribute (veya interleaved senaryosunda ilgili attribute sınıfı) ile sararsınız.
  3. Geometriye bağlama: geometry.setAttribute('attributeName', attribute) ile kanalı geometriye eklersiniz.
  4. Shader’da okuma: Vertex shader’da uyumlu tipte bir giriş tanımlarsınız; örneğin attribute float aRandomSpeed; — ardından bu değeri pozisyon, normal veya başka çıktılara bağlayarak görsel manipülasyon yaparsınız.

Materyal tarafında attribute adlarının shader’daki isimlerle eşleşmesi gerekir; aksi halde veri sessizce yok sayılır veya bağlama hatasına yol açar.

HoloDepth projelerinde kullanım senaryoları

HoloDepth’in daha “premium” ve futuristik görsellerinde custom attribute’lar sık devreye girer — hazır kalıpların ötesine geçip atomik vertex verisiyle oynamanızı sağlarlar.

A. Vertex tabanlı animasyon

Her vertex’e örneğin aRandomSpeed gibi bir attribute vererek, bir kürenin parçalarının farklı hızlarda dağılması veya yüzeyin dalga dalga hareket etmesi gibi efektleri GPU üzerinde, CPU’da ağır döngüler yazmadan kurgulayabilirsiniz.

B. Köşe başına renklendirme

Doku yerine (veya dokuya ek olarak) color benzeri özel bir attribute ile köşe başına renk taşıyarak ışık oyunları veya karmaşık geçişler kurabilirsiniz; yüksek poligonlu “glassmorphism” tarzı yüzeylerde esneklik sağlar.

C. Gürültü ile displacement

Bir ofset veya genlik attribute’u ile düz bir PlaneGeometry’yi gerçek zamanlı engebeli arazi veya dalgalanan yüzey gibi göstermek; uniform zaman + vertex attribute fazı kombinasyonu tipik bir kalıptır.

Performans ve optimizasyon uyarısı

Custom attribute’lar güçlüdür; fakat her yeni kanal GPU’ya taşınan vertex verisinin boyutunu artırır — bant genişliği ve bellek baskısı doğrudan etkilenir.

  • Veri tipi: Değer aralığınız küçükse Float32 yerine daha dar tipler veya normalized integer formatları (ör. renk için) düşünün.
  • Gereksiz kanal yok: Shader’da gerçekten kullanmayacağınız attribute’u göndermeyin; kullanılmayan her kanal, bant genişliğinden “çalınan” lükstür.
  • Önbellek / interleaved: Yoğun güncelleme senaryolarında veri düzenini interleaved buffer ile düşünmek, attribute sayısı arttıkça daha anlamlı hale gelir.

Özet: özgünlüğün sınırı

Custom attribute’lar, HoloDepth kullanıcılarına hazır modellerin ötesine geçip geometrinin atomik yapısına müdahale etme şansı verir. Standart geometriler birer kalıpsa, bu özel kanallar o kalıpları canlandıran sinir sistemi gibidir: doğru yerde, doğru miktarda veriyle kullanıldığında en yüksek etkiyi verir.