Three.js · İleri geometri · Advanced Geometries (final)
Procedural Geometry: Kodla form inşa etmek
Statik dosya değil, çalışma zamanında üretilen yaşayan geometri
Advanced Geometries serisinin bu son aşamasında, hazır modelleme araçlarından (Blender, Maya vb.) tamamen kopmuyor; fakat geometrinin bizzat kendisini çalışma zamanında (runtime) matematiksel formüllerle inşa etme fikrine odaklanıyoruz. Procedural geometry (yordamsal geometri), önceden kaydedilmiş statik veriler yerine algoritmaların hüküm sürdüğü bir düzendir: aynı kod, farklı parametrelerle sonsuz varyasyon üretebilir.
Ön okuma:
Indexed vs
non-indexed,
Custom
attributes,
Geometry
optimization,
Attributes
lifecycle & buffer,
Geometri giriş.
Her canlı örneğin altında kendi demo sabitleri tablosu vardır:
parametrik,
noise,
regenerate,
L-system
— hepsi doc-procedural-geometry-demo.js ile satır satır eşlenir.
Matematiksel tasarım: fonksiyondan forma
Procedural (yordamsal) geometride, birçok senaryoda her bir vertex bir fonksiyonun
çıktısıdır. Bir küreyi doğrudan SphereGeometry ile çağırmak
yerine,
trigonometrik denklemlerle (sin, cos) noktaların uzaydaki
konumlarını siz hesaplayabilirsiniz; böylece şekil, veri dosyasından değil
koddan
türetilir.
Parametrik yüzeyler: Bir yüzeyin formunu tanımlamak için u ve
v gibi parametreler kullanılır. Bu parametreler değiştikçe yüzey, bir kumaş
gibi
dalgalanabilir veya bir kabuk gibi kıvrılabilir; ızgara üzerinde örnekleme yaparak
BufferGeometry doldurmak doğal bir sonraki adımdır.
Sonsuz varyasyon: Elinizde sabit bir .obj dosyası olmak
zorunda değildir. Bunun yerine bir tohum (seed)
değerine veya kullanıcı kaydırıcılarına göre her seferinde farklılaşan dağlar, ağaçlar,
bulutlar veya soyut formlar üretebilirsiniz.
Form = matematik —
her vertex u ve v ile tanımlanan dalga fonksiyonundan gelir;
kaydırıcılar yalnızca yerel hesabı değiştirir.
Düzlem ızgara üzerindeki her köşe, aynı analitik yüzeyin örneklenmiş hâlidir; segment sayısı arttıkça eğri yumuşar, azalınca “dijital kırılım” belirginleşir. Dış veri veya ağ isteği yoktur.
Demo sabitleri tablosu (parametrik yüzey)
initParametricDemo; dört kökün bağlanması için
L-system kod kesitindeki
bootProceduralDemos bölümüne bakın (bu tabloda özet).
| Sahne / rol | Parametre | Değer | Tür |
|---|---|---|---|
| Ortak | makeRenderer |
ACESFilmicToneMapping · exposure 1.2 ·
SRGBColorSpace · setPixelRatio(min(dpr,2)) · arka plan
0x04060e
|
🔒 Sabit |
| Geometri | PlaneGeometry |
5.5×5.5 · segment uSeg×vSeg ·
rotateX(-π/2) · girdi clamp 4…64
|
🔒 + ↔ UI |
| Dalga | vertex Y |
amp×sin(freq×2π×u)×cos(freq×2π×v) ·
u=x/5.5+0.5 · v=z/5.5+0.5
|
🔒 + ↔ UI |
| Materyal | MeshStandardMaterial |
0x4ad4c8 · metalness 0.15 · roughness
0.42 · DoubleSide
|
🔒 Sabit |
| Işık | Ambient / Directional | beyaz 0.35 · yönlü 1.05 konum
(2.2, 4.5, 3.2)
|
🔒 Sabit |
| Kamera | PerspectiveCamera |
FOV 42 · yakın/uzak 0.06 / 200 · konum
(4.2, 3.4, 5.2)
|
🔒 Sabit |
| OrbitControls | target |
(0, 0.2, 0) |
🔒 Sabit |
| Modül | bootProceduralDemos |
data-proc-demo="parametric" → initParametricDemo
(diğer kökler aynı fonksiyonda) |
🔒 Sabit |
Önemli kod kesiti
Her input değişiminde build() düzlemi yeniden kurar ve dalga ile
position yüksekliğini yazar.
const geo = new THREE.PlaneGeometry(5.5, 5.5, uSeg, vSeg);
geo.rotateX(-Math.PI / 2);
const pos = geo.attributes.position;
for (let i = 0; i < pos.count; i++) {
const x = pos.getX(i);
const z = pos.getZ(i);
const u = x / 5.5 + 0.5;
const v = z / 5.5 + 0.5;
const y =
amp * Math.sin(freq * Math.PI * 2 * u) * Math.cos(freq * Math.PI * 2 * v);
pos.setY(i, y);
}
pos.needsUpdate = true;
geo.computeVertexNormals();
Gürültü fonksiyonları (noise)
Doğadaki düzensizliği taklit etmek için bilgisayar biliminin en güçlü araçlarından biri noise fonksiyonlarıdır. Standart rastgele değerlerden farklı olarak, Perlin ve Simplex gibi gürültü aileleri genellikle sürekli ve yumuşak geçişler sunar; komşu noktalar birbirinden kopuk zıplamaz.
Kullanım alanı: Bir düzlemi (PlaneGeometry veya özel bir
ızgara)
alıp yükseklik veya yer değiştirmeyi noise ile modüle ettiğinizde, kısa sürede arazi, deniz
yüzeyi veya organik deformasyon hissi elde edebilirsiniz. Gürültünün
frekansını ve genliğini (amplitude)
değiştirerek yumuşak tepelerden daha keskin varyasyonlara kadar kontrol sizde kalır.
Seed değişince yeni dünya — aynı frekans ve genlikte bile topoğrafya tamamen farklı; bu, “sonsuz varyasyon” fikrinin somut hâlidir.
Üçlü gürültü (yerel hash + yumuşak interpolasyon) ile yükseklik üretilir; Perlin kütüphanesi yoktur, böylece demo hafif ve tamamen tarayıcı içi kalır. Frekans ölçeği küçüldükçe geniş tepeler, arttıkça daha sık detay görürsünüz.
Demo sabitleri tablosu (noise arazi)
initNoiseTerrainDemo · terrainHeight yerel
smoothNoise2D katmanlarını kullanır.
| Sahne / rol | Parametre | Değer | Tür |
|---|---|---|---|
| Ortak | makeRenderer |
ACESFilmicToneMapping · exposure 1.2 ·
SRGBColorSpace · setPixelRatio(min(dpr,2)) · arka plan
0x04060e
|
🔒 Sabit |
| Geometri | PlaneGeometry |
7×7 · segment 56×56 · rotateX(-π/2) |
🔒 Sabit |
| Yükseklik | terrainHeight |
smoothNoise2D oktavları · katsayılar 1 ·
0.45 · 0.22 · 0.11 · çıktı
(n−0.48)×amp
|
🔒 + ↔ UI |
| Materyal | MeshStandardMaterial |
0x6eb87a · metalness 0.08 · roughness
0.62 · DoubleSide
|
🔒 Sabit |
| Işık | Ambient / Directional | beyaz 0.38 · yönlü 0xfff0e0 yoğunluk
1.05 konum (-3, 6, 2)
|
🔒 Sabit |
| Kamera | PerspectiveCamera |
FOV 40 · yakın/uzak 0.08 / 200 · konum
(5.5, 4.2, 6.2)
|
🔒 Sabit |
| OrbitControls | target |
(0, 0.35, 0) |
🔒 Sabit |
Önemli kod kesiti
Kaydırıcılar applyHeights() ile tüm köşelerin Y değerini
günceller.
function applyHeights() {
const freq = Number(inFreq.value);
const amp = Number(inAmp.value);
const seed = Math.round(Number(inSeed.value));
const pos = geo.attributes.position;
for (let i = 0; i < pos.count; i++) {
const x = pos.getX(i);
const z = pos.getZ(i);
pos.setY(i, terrainHeight(x, z, seed, freq, amp));
}
pos.needsUpdate = true;
geo.computeVertexNormals();
}
Dinamik topoloji ve buffer manipülasyonu
Procedural geometri yalnızca ilk şekli üretmekle kalmaz; aynı zamanda bu şekli
canlı tutabilir. Kullanıcı etkileşime girdiğinde (örneğin fare ile bir
bölgeye dokunma), BufferAttribute içindeki sayıları anında yeniden hesaplayıp
GPU’ya haber vermeniz gerekir: Three.js’te bu sinyal needsUpdate bayrağıdır;
kısmi yükleme için güncel sürümlerde addUpdateRange /
clearUpdateRanges
kullanımını
buffer
lifecycle sayfasında özetledik. Aşağıdaki iki figürün her birinin altında o demoya
özel demo sabitleri ve
L-system sabitleri
tabloları bulunur.
Geometry = hesaplanan veri — procedural modda her karede pozisyon buffer’ı yeniden yazılır; statik modda ise son anlık görüntü dondurulur.
Statik mesh: anlık yüzeyi dondurur (örneğin bir kareyi yakalamak
için). Procedural regenerate: zamanla sürekli yeni dalga formülü
yazar; GPU’ya needsUpdate ile haber verilir. Düğme, statik moddayken
farklı bir “fotoğraf” almanız için fazı kaydırır.
Demo sabitleri tablosu (vertex regenerate)
initRegenerateDemo · statik / procedural modları aynı düzlem buffer’ında
needsUpdate ile ayırır.
| Sahne / rol | Parametre | Değer | Tür |
|---|---|---|---|
| Ortak | makeRenderer |
ACESFilmicToneMapping · exposure 1.2 ·
SRGBColorSpace · setPixelRatio(min(dpr,2)) · arka plan
0x04060e
|
🔒 Sabit |
| Geometri | PlaneGeometry |
4.5×4.5 · segment 42×42 · rotateX(-π/2) ·
baseY Float32Array
|
🔒 Sabit |
| Statik dalga | staticWaveY |
çift sinüs terimi + sin((x+z)×3.2 + t×2.2) ·
bakeStaticInitial başlangıç t≈0.85
|
🔒 Koşul |
| Procedural dalga | proceduralWaveY |
morfoloji frekansı · drift · ridge ·
smoothNoise2D örneklemesi
|
🔒 Koşul |
| Zaman | procTime |
procedural modda procTime += dt × 0.18 · düğme
pulsePhase += 1.7
|
🔒 + ↔ UI |
| Materyal | MeshStandardMaterial |
0x7aa8ff · metalness 0.12 · roughness
0.45 · DoubleSide
|
🔒 Sabit |
| Işık | Ambient / Directional | beyaz 0.4 · yönlü 1 konum (2, 5, 3) |
🔒 Sabit |
| Kamera | PerspectiveCamera |
FOV 42 · yakın/uzak 0.08 / 200 · konum
(3.6, 2.8, 4.4)
|
🔒 Sabit |
| OrbitControls | target |
(0, 0, 0) |
🔒 Sabit |
| JS başlangıç | mode |
'static' · HTML: Statik mesh seçili |
🔒 + ↔ UI |
Önemli kod kesiti
Procedural modda her karede proceduralWaveY ile Y yeniden yazılır;
sonra needsUpdate ve normal yeniden hesaplanır.
if (mode === 'proc') {
procTime += dt * 0.18;
for (let i = 0; i < pos.count; i++) {
const x = pos.getX(i);
const z = pos.getZ(i);
pos.setY(i, proceduralWaveY(x, z, procTime, pulsePhase));
}
pos.needsUpdate = true;
geo.computeVertexNormals();
}
L-systems (Lindenmayer sistemleri): Bitki büyüme örüntülerini veya fraktal dallanmaları modellemek için kullanılan kural kümeleridir. Tek bir çizgi veya basit bir başlangıçla, özyinelemeli kurallarla genişleyen yapılar kurup bunları üçgene veya çizgiye dökmek procedural düşüncenin klasik örneklerindendir.
Procedural yalnızca yüzey değildir — aynı mantık, çizgi ve kural genişlemesiyle fraktal büyüme gösterir.
Klasik Koch dizesi (F → F+F−F−F+F, 90° dönüş) ile üretilen çizgi;
iterasyon arttıkça dize uzunluğu hızla büyür, bu yüzden üst sınır 4 ile sınırlıdır.
Gerçek bitki L-system’leri daha zengin alfabe ve yığın sembolleri kullanır; burada
fikir gösterimi amaçlanmıştır.
Demo sabitleri tablosu (Koch / L-system)
initLsystemDemo · Koch dizesi üretimi ve bbox ile sahneye sığdırma.
| Sahne / rol | Parametre | Değer | Tür |
|---|---|---|---|
| Ortak | makeRenderer |
ACESFilmicToneMapping · exposure 1.2 ·
SRGBColorSpace · setPixelRatio(min(dpr,2)) · arka plan
0x04060e
|
🔒 Sabit |
| Kural | expandKoch |
F → F+F-F-F+F · başlangıç dizesi 'F' |
🔒 Sabit |
| Kaplumbağa | ANGLE / TURTLE_STEP |
π/2 · 1 |
🔒 Sabit |
| Güvenlik | dize uzunluğu | genişleme döngüsünde maxLen 120000 aşılırsa dur |
🔒 Sabit |
| İterasyon | inIter |
clamp 0…4 (girdi) |
🔒 + ↔ UI |
| Yerleşim | bbox ölçek | hedef genişlik 5.2 · y = 0.04 |
🔒 Sabit |
| Çizgi | LineBasicMaterial |
0xffd24a |
🔒 Sabit |
| Işık | Ambient / Directional | beyaz 0.55 · yönlü 0.9 konum (0, 8, 4)
|
🔒 Sabit |
| Kamera | PerspectiveCamera |
FOV 38 · başlangıç (0, 5.5, 10) ·
boundingSphere ile yakın/uzak ve konum ayarı
|
🔒 Koşul |
| Modül | bootProceduralDemos |
data-proc-demo="lsystem" → initLsystemDemo |
🔒 Sabit |
Önemli kod kesiti
Koch kuralı: her iterasyonda F beş karakterlik dizgeyle genişler. Aynı dosyada
dört canlı örneği bağlayan giriş bootProceduralDemosdır (üstteki dört tabloda
da kısaca geçer).
function expandKoch(s) {
let out = '';
for (let i = 0; i < s.length; i++) {
const ch = s[i];
if (ch === 'F') out += 'F+F-F-F+F';
else out += ch;
}
return out;
}
function bootProceduralDemos() {
document.querySelectorAll('[data-proc-demo]').forEach((root) => {
const kind = root.getAttribute('data-proc-demo');
if (kind === 'parametric') initParametricDemo(root);
else if (kind === 'noise') initNoiseTerrainDemo(root);
else if (kind === 'regenerate') initRegenerateDemo(root);
else if (kind === 'lsystem') initLsystemDemo(root);
});
}
Neden procedural? (HoloDepth vizyonu)
HoloDepth perspektifi
Modern ve fütüristik bir 3D web platformunda procedural yaklaşımların öne çıkmasının birkaç güçlü gerekçesi vardır:
- Düşük dosya boyutu: Gigabaytlarca önceden modellenmiş veri indirmek yerine, çoğu zaman kısa bir matematik tanımı ve birkaç parametre taşınır; dünya, kullanıcının tarayıcısında o an üretilir.
- Sonsuz detay: Kullanıcı bir bölgeye yaklaştıkça, algoritma o bölge için daha ince bir ızgara veya daha zengin kurallarla detay üretebilir (fraktal yakınlaştırma mantığıyla ilişkilendirilebilir).
- Benzersiz deneyim: Parametreler veya tohum değiştiğinde, her oturumda dünyada eşi benzeri olmayan bir geometri ile karşılaşmak mümkündür.
Teknik uygulama stratejisi
Bir procedural geometri hattı kurarken sık görülen yapı taşları şunlardır:
| Teknik | Kısa tanım | Tipik kullanım |
|---|---|---|
| Voxel tabanlı yapılar | Veriyi 3B ızgarada (küp hücrelerde) saklama. | Minecraft benzeri blok dünyalar, hacimsel düzenleme. |
| Marching cubes | Yoğunluk alanından üçgen ağı çıkarma. | Tıbbi hacim verisi, akışkan yüzeyi, “iso-surface” önizlemesi. |
| Parametrik ızgara + noise | u, v üzerinde örnekleme ve gürültü ile yükseklik.
|
Arazi, dalga, basit organik yüzeyler. |
Bu tablo “her şeyi marching cubes yapın” demez; ama hangi matematiksel temsilin (voxel alan mı, parametrik yüzey mi) sizin probleminize uyduğunu seçmenize yardım eder.
Özet: geometrinin geleceği
Advanced Geometries üst konusunu burada tamamlarken şunu netleştirebiliriz: geometri artık yalnızca statik bir dosya değil, yaşayan ve gelişen bir veri kümesi olarak düşünülebilir. Indexed yapı ile verimlilik, custom attribute’lar ile ifade gücü, optimizasyon ile hız disiplini ve son olarak procedural yöntemlerle sonsuzluk ve varyasyon aynı haritada bir araya gelir.