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ç
uniformile 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.
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.
Demo sabitleri tablosu (Deformation lab)
initVertexDeformLab · statik / CPU / GPU ve deform tipi aynı sahne üzerinde
karşılaştırılır.
| 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/veyageometry.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.