Three.js · İleri geometri
GPU displacement: geometrinin donanımsal evrimi
Düşük poligonlu kafesten, shader’da zengin silüete
Advanced Geometries serimizin bu zirve noktasında, işlemciyi (CPU) tamamen
özgür bırakıp, geometrik detaylandırmayı bizzat ekran kartının (GPU) kalbine,
yani vertex ve fragment shader katmanlarına devrediyoruz.
GPU displacement, statik bir düşük poligonlu (low-poly)
mesh’i, çalışma zamanında (runtime) milyonlarca poligonluk bir detaya
dönüştürmenin en verimli yoludur.
Canlı lab ölçüleri
demo sabitleri
tablosunda doc-gpu-disp-compare-demo.js ile eşlenir.
GPU displacement mekaniği
Aradaki fark, sadece hız değil, aynı zamanda verinin işlenme felsefesidir.
CPU tarafında
JavaScript ile her bir vertex’in pozisyonunu tek tek hesaplayıp buffer’ı güncellemeniz gerekir. Bu, her karede devasa bir verinin CPU’dan GPU’ya taşınması demektir (bant genişliği darboğazı).
GPU tarafında
CPU sadece düşük poligonlu bir kafes (cage) ve bir veri kaynağı (doku / gürültü) gönderir. GPU, her bir vertex’i paralel olarak işler ve saniyenin binde biri sürede koordinatlarını değiştirir. Pratikte bu yaklaşım, vertex deformation lab’ında GPU modunda gördüğünüz “birkaç uniform, binlerce vertex” fikrinin doğal uzantısıdır.
Canlı: CPU buffer vs GPU shader
Sol düzlem yalnızca sinüs tabanı ile çalışır; her karede JavaScript
BufferAttribute güncellenir. Sağda aynı taban dalga vertex shader’da
tutulur ve üzerine ek prosedürel detay (gürültü) eklenir — ek maliyet
CPU’da vertex başına JS ile kopyalanmaz. Çözünürlüğü (224’e kadar)
artırdıkça CPU maliyeti belirginleşir; CPU’yu gizleyerek FPS farkını
netleştirin.
Ölçüler demo sabitleri
tablosunda özetlenir.
Taban dalga CPU ile aynıdır; GPU tarafında vertex aşamasında ekstra noise katmanı vardır (performans kıyasında GPU hâlâ buffer yükü taşımaz).
Demo sabitleri tablosu (CPU vs GPU displacement)
initGpuDispCompareDemo · sol düzlemde per-frame BufferAttribute,
sağda aynı taban dalga + vertex shader’da ek gürültü.
| Sahne / rol | Parametre | Değer | Tür |
|---|---|---|---|
| Düzlem çifti | PLANE_SIZE / PLANE_GAP |
boyut 7×7 · aralık 0.55 ·
rotateX(-π/2) · sol/sağ konum ±(PLANE_SIZE+GAP)/2
|
🔒 Sabit |
| CPU taban dalga | heightWave |
amp×0.5×(sin+cos) · wt = t×speed · hız
FIXED_SPEED 1.05
|
🔒 + ↔ UI |
| GPU yükseklik | height() (vertex) |
taban dalga + uAmp×0.11×fine · vnoise UV
(x,z)×(uFreq×3.1)+… · fdNormal
e = 0.06
|
🔒 + ↔ UI |
| Segment | MAX_SEG / yuvarlama |
aralık 12…224 (UI adım 4) ·
floor(seg/4)×4 veya 12
|
🔒 + ↔ UI |
| CPU materyal | MeshStandardMaterial |
0x4a7cbd · roughness 0.7 · metalness
0.1
|
🔒 Sabit |
| GPU fragment | gpuFrag |
L normalize (0.38, 0.88, 0.52) · taban
vec3(0.12, 0.42, 0.34) · lit = base×(0.22+0.78×ndl)
|
🔒 Sabit |
| Sis | Fog |
0x070910 · 10 / 48 |
🔒 Sabit |
| Işık | 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, 5.8, 13.2)
|
🔒 Sabit |
| OrbitControls | hedef / mesafe / dönüş | (0, 0.15, 0) · 5…28 · damping 0.07 ·
maxPolarAngle = π/2 − 0.1 · autoRotateSpeed 0.35
|
🔒 + ↔ UI |
| Girdi clamp | readParams |
genlik 0.08…2.0 · frekans 0.15…2.4 · segment
12…224
|
🔒 + ↔ UI |
| HTML başlangıç | range / toggles | genlik 0.55 · frekans 0.85 · segment 48
· otomatik dönüş açık · wire / CPU gizle kapalı |
🔒 + ↔ UI |
Önemli kod kesiti
Sol taraftaki CPU yolu her karede heightWave ile Y ofsetini yazar; sağdaki GPU
vertex shader’da aynı sinüs–kosinüs tabanına prosedürel mikro detay eklenir
(FIXED_SPEED her iki tarafta ortak).
function heightWave(x, z, t, amp, freq, speed) {
const wt = t * speed;
return amp * 0.5 * (Math.sin(x * freq + wt) + Math.cos(z * freq + wt));
}
Teknik bileşenler: vertex texture fetch (VTF)
GPU displacement’ın ana yakıtı, önceki derslerimizde değindiğimiz displacement map’lerdir. Web katmanında uygulama, kullanılan WebGL sürümüne ve donanım desteğine göre değişiklik gösterir.
Vertex texture fetch (VTF): Modern WebGL (özellikle WebGL 2.0) ile artık vertex shader içinde doku örnekleme (texture sampling) yapılabilir. Bu teknikte vertex, dokudaki kendine karşılık gelen UV koordinatına bakarak yükseklik verisini doğrudan GPU üzerinde okur.
Uyumluluk ve performans: WebGL 2 ile bu süreç standartlaşmış olsa da, performans maliyeti ve eski cihazlardaki kararlılık sorunları nedeniyle birçok ileri seviye sistem bu veriyi hâlâ önceden hesaplanmış attribute’lar veya fragment shader tabanlı simülasyonlar üzerinden yönetmeyi tercih edebilir.
Doku kanalından gelen yükseklik mantığı için Height / Displacement map sayfasındaki ayrımı hatırlayın.
Kritik mühendislik: simüle edilmiş tessellation
Bir düzlemi (plane) GPU üzerinde yukarı kaldırmak kolaydır; ancak yeterli vertex yoksa sonuç bloklu ve kalitesiz görünür.
Subdivision stratejisi
Masaüstü GPU’lardaki gerçek donanımsal tessellation (hardware tessellation) WebGL standartlarında doğrudan mevcut değildir. Bu nedenle HoloDepth mimarisinde bu işlem genellikle önceden bölünmüş (subdivided) yüksek yoğunluklu geometriler veya shader tabanlı matematiksel tekniklerle simüle edilir.
Scale ve bias
Dokudan gelen veri genellikle 0 ile 1 aralığındadır. Bunu gerçek dünya ölçeğine taşımak için
uDisplacementScale (yükseklik miktarı) ve
uDisplacementBias (temel seviye ayarı) gibi uniform değerleri
ile manipüle ederiz.
Normal ve ışık senkronizasyonu
GPU üzerinde noktaları hareket ettirdiğinizde, yüzeyin ışığı karşılama açısı değişir; ancak standart gölgelendirme hesaplamaları bu yeni pozisyondan haberdar olmaz — özetle silüet ile aydınlatma vektörü uyumsuz kalabilir.
Displacement + normal map
En keskin ve gerçekçi sonuçlar için displacement map ile birlikte bir normal map kullanılır: displacement geometrik formu (silüeti) değiştirirken, normal map mikro detaylardaki ışık kırılmalarını yönetir.
Shader derivatives
Daha ileri seviyede, shader içinde dFdx ve dFdy fonksiyonlarını
kullanarak (türev alma yoluyla) anlık olarak yüzey normallerini hesaplayabilirsiniz. Bu
yapılmazsa, yükselen tepeler düz bir kağıt gibi parlayacak ve derinlik hissi kaybolacaktır.
HoloDepth uygulama stratejileri
Bu tekniği HoloDepth projelerinde şu üç ana senaryo için kullanıyoruz:
- Holografik dalgalanmalar: Bir küre veya düzlemin yüzeyini yüksek frekanslı gürültü ile displacement yaparak enerji kalkanı veya plazma efekti yaratmak.
- Dinamik mikro detaylar: Düşük poligonlu bir zemin üzerine yüksek çözünürlüklü bir veri dokusu giydirerek, her taşın ve çukurun fiziksel olarak orada olduğu hissini vermek.
- Veri görselleştirme: Topografik verileri veya ses frekanslarını doğrudan vertex’lere bağlayarak veriyi dokunulabilir bir 3D forma dönüştürmek.
Özet: geometride son nokta
GPU displacement, bir web geliştiricisinin elindeki en güçlü araçlardan biridir. Ancak WebGL dünyasında bu gücü kullanırken donanım limitlerini ve normal hesaplamalarını doğru yönetmek, projenin “profesyonel” ile “amatör” arasındaki farkını belirler.