holodepth

Three.js · İleri geometri

Vertex deformation: geometrinin dinamik manipülasyonu

CPU, GPU, normal ve morph — statikten akışkana

Advanced Geometries yolculuğunda arazi oluşturma ile büyük ölçekli yapıları kurmayı işledik. Şimdi odağı daha mikro ve akışkan bir seviyeye taşıyoruz: vertex deformation (tepe noktası deformasyonu): statik bir mesh’in her bir köşesini (vertex) matematiksel fonksiyonlar veya dinamik verilerle hareket ettirerek nesneye “yaşam” verme sanatı. Canlı lab ölçüleri demo sabitleri tablosunda doc-vertex-deform-demo.js ile eşlenir.

CPU ve GPU deformasyonu: stratejik seçim

Vertex deformasyonu iki farklı katmanda gerçekleşebilir. Holodepth tarzı projelerde performans ve kontrol dengesini kurmak için yükü nereye vereceğinizi netleştirmeniz gerekir.

CPU deformasyonu

Veriler JavaScript tarafında, BufferAttribute içindeki diziler güncellenerek değiştirilir; her karede position.needsUpdate = true ile GPU’ya yeniden yükleme tetiklenir.

  • Avantaj: Karmaşık oyun mantığı, fizik veya içerik araçları ile etkileşim doğrudandır (ör. bir çarpışma noktasının mesh’e etkisi).
  • Dezavantaj: Çok sayıda vertex’i her karede CPU’da hesaplayıp GPU’ya geri göndermek (upload) bant genişliği ve CPU süresi açısından hızla darboğaz olur.

GPU deformasyonu (vertex shader)

Mantık doğrudan GLSL (veya Three.js’te ShaderMaterial / özel chunk’lar) ile vertex aşamasında çalışır; aynı mantık binlerce köşeye paralel uygulanır.

  • Avantaj: Yüksek vertex sayısında gecikme hissi düşük kalır; animasyon parametreleri çoğu zaman birkaç uniform ile taşınır.
  • Dezavantaj: Shader içindeki veriye JS’ten “anlık” ve rastgele indeksle erişmek zordur; “şu an 55. vertex nerede?” gibi sorular CPU tarafında çözülmelidir.

Trigonometrik ve gürültü tabanlı hareket

Nesneyi deforme etmenin estetik yollarından biri, doğadaki periyodik veya yarı-periyodik hareketleri taklit etmektir.

Sinüs ve kosinüs dalgaları

En temel deformasyon araçlarıdır. Bayrak dalgalanması, su yüzeyi salınımı veya “nefes alan” bir ölçek animasyonu, vertex pozisyonlarına eklenen sin(time + position) benzeri terimlerle kurulur; fazı konuma bağlamak dalganın uzayda yayılmasını sağlar.

Gerçek zamanlı gürültü

Daha organik, öngörülemez hareket için (ateş, bulut, organik yüzey) vertex aşamasında noise (ör. Simplex / klasik gradient noise) kullanılır. Her noktaya farklı bir “itme” vektörü vererek statik geometrileri yaşayan formlara dönüştürür.

Normal correction (normalleri onarma)

Vertex deformation’daki en büyük tuzaklardan biri yalnızca pozisyonu değiştirmektir. Bir köşenin yerini oynattığınızda yüzeyin ışığı karşılama açısı da değişir.

Sorun: Pozisyonu güncelleyip normali eski geometriye göre bırakırsanız, hareket olsa da gölgeler ve parlaklık “plastik” ve statik kalır — yüzey hâlâ eski kırılımda aydınlanıyormuş gibi görünür.

Çözüm: Shader içinde deforme ederken yeni yüzeye uygun normali de üretin. Bu genelde komşu örneklerden türev alarak (dFdx / dFdy ile yaklaşım) veya analitik fonksiyonun gradient’i ile yapılır. CPU tarafında güncelliyorsanız computeVertexNormals() bir çıkış yoludur; yoğun mesh’lerde maliyeti göz önünde bulundurun.

Canlı: deformation lab

Aynı düzlem üzerinde statik, CPU (buffer güncelleme) ve GPU (vertex shader) modlarını anında karşılaştırın. Doğru normaller kapalıyken pozisyon oynar fakat aydınlatma “eski yüzeyde” kalır; açınca farkın kaynağını görürsünüz. Dış veri yoktur. Ölçüler demo sabitleri tablosunda özetlenir.

Deformation lab
Mod: — FPS: —
Çalışma modu
Deformasyon tipi

CPU modunda ızgara daha sık (daha çok vertex güncellemesi); GPU/statikte daha seyrek — FPS farkı genelde buradan gelir. GPU’da kırmızı küre yaklaşık hacim ipucudur. “Doğru normaller” kapalıyken yönlü ışık sertleşir; yanlış normaller daha çarpıcı görünür.

Önce CPU ile oynayıp doğru normalleri kapatın: hareket var, ışık “yanlış” kalır. Sonra aynı deneyi GPU modunda tekrarlayın. Statik mod referans düzlemdir.

Demo sabitleri tablosu (Deformation lab)

initVertexDeformLab · statik / CPU / GPU ve deform tipi aynı sahne üzerinde karşılaştırılır.

initVertexDeformLab · deformation lab
Sahne / rol Parametre Değer Tür
Düzlem PLANE_SIZE / segment boyut 9×9 · GPU 32×32 · CPU 56×56 · rotateX(-π/2) 🔒 Sabit
CPU yükseklik heightCpu sin: 0.5×(sin+cos)×amp · pulse: breathe×wave · noise: (vnoiseCpu−0.5)×2.2×amp 🔒 + ↔ UI
GPU uniform uAmp / uFreq / uSpeed başlangıç 0.55 · 0.55 · 0.9 · uType deform eşlemesi · uCorrectNormal 🔒 + ↔ UI
GPU normal fdNormal merkezi fark e = 0.07 · uCorrectNormal kapalıysa sabit normal 🔒 Sabit
CPU materyal MeshStandardMaterial 0x3a8f72 · roughness 0.72 · metalness 0.08 (sert modda değişir) 🔒 + Koşul
Işık (sert mod) syncLighting yanlış normal + CPU/GPU iken hemi 0.24 · dir 2.55 · konum (5.2, 7.8, 2.8) 🔒 Koşul
Bbox ipucu IcosahedronGeometry (1, 2) · kırmızı wireframe · opaklık 0.55 · GPU’da ölçek 2.2 + amp×0.55 ↔ UI
Sis Fog 0x070910 · 8 / 42 🔒 Sabit
Işık (yumuşak) HemisphereLight / DirectionalLight 0xb8e0ff / 0x1a1e28 · 0.82 · yönlü 1.02 (3.2, 9.5, 5.5) 🔒 Sabit
Renderer WebGLRenderer antialias: false · arka plan 0x070910 · setPixelRatio(min(dpr, 1.35)) · SRGBColorSpace 🔒 Sabit
Kamera PerspectiveCamera FOV 48 · yakın/uzak 0.1 / 100 · konum (0, 6.2, 11.5) 🔒 Sabit
OrbitControls hedef / mesafe / dönüş (0, 0.2, 0) · 4…28 · damping 0.07 · maxPolarAngle = π/2 − 0.12 · autoRotateSpeed 0.38 🔒 + ↔ UI
Girdi clamp readParams genlik 0.05…2.2 · frekans 0.15…2.4 · hız 0.05…3.5 🔒 + ↔ UI
HTML başlangıç mod / deform / toggles CPU · sinüs · doğru normaller + otomatik dönüş açık · bbox/wire kapalı 🔒 + ↔ UI

Önemli kod kesiti

CPU yolu her vertex için heightCpu ile Y ofsetini yazar; GPU’da aynı fikir vertex shader içindeki height() ile tekrarlanır.

function heightCpu(x, z, t, deformType, amp, freq, speed) {
  const wt = t * speed;
  const wave = 0.5 * (Math.sin(x * freq + wt) + Math.cos(z * freq + wt));
  if (deformType === "sin") return amp * wave;
  if (deformType === "pulse") {
    const breathe = 0.35 + 0.65 * Math.sin(wt);
    return amp * breathe * wave;
  }
  return (
    amp *
    (vnoiseCpu(x * freq + t * speed * 0.12, z * freq - t * speed * 0.08) -
      0.5) *
    2.2
  );
}

Morph targets (shape keys)

Bazen saf matematiksel fonksiyonlar karmaşık bir deformasyonu (gülümseme, ezilme, ürün varyantı) tarif etmekte yetersiz kalır. Burada morph targets devreye girer: taban (base) ve hedef (target) haller önceden tanımlanır; GPU iki hal arasında vertex başına doğrusal (veya seçilen eğriyle) interpolasyon yapar.

Holodepth içeriklerinde pürüzsüz “şekil geçişleri” çoğu zaman bu yöntemle, 0 ile 1 arasında kayan bir influence değeriyle yönetilir. Detay için Morph Targets sayfasına bakın.

Holodepth uygulama notları: performans

  • Attribute precision: Deformasyon verisi taşırken hassasiyet gerekmiyorsa daha hafif tipler veya daha az sıklıkta güncelleme ile bant genişliğini koruyun; gereksiz yüksek çözünürlük hem bellek hem upload maliyetidir.
  • Pre-computed buffers: Hareket döngüsel ve öngörülebilirse, bir döngü boyunca örnekleri önceden yazıp GPU’da indeks veya zaman ile seçmek CPU maliyetini düşürebilir.
  • Bounding volume güncelleme: Shader içinde büyük deformasyon uyguladığınızda Three.js’in frustum culling’i eski sınırları kullanıp mesh’i yanlışlıkla dışarıda sayabilir. Gerekirse geometry.computeBoundingSphere() ve/veya geometry.computeBoundingBox() ile hacmi güncelleyin; aşırı geniş kutu “her zaman görünür” davranışına yol açabilir — dengeyi sahne ölçeğine göre kurun.

Özel veri köprüsü

Shader’a vertex başına ek veri taşımak için custom attribute ve buffer yaşam döngüsü sık kullanılır; deformasyon + renk + blend weight aynı pakette ilerleyebilir.

Özet: statikten dinamiğe geçiş

Vertex deformation, geometrinin katı bir listeden akışkan bir veri akışına dönüştüğü katmandır. Şekil vermenin ötesinde, nesneye zaman boyutu ve etkileşim kabiliyeti kazandırırsınız: doğru normal ve doğru CPU/GPU sınırı ile bu akış hem güzel hem sürdürülebilir kalır.