Holodepth • ByteOmi Köprü • 3D Matematik
Matrisler
Matrisler, 3D uzaydaki dönüşümleri (taşıma, döndürme, ölçekleme) tek bir “paket” altında toplar. Bir modeli binlerce noktaya tek tek işlem uygulamak yerine, dönüşümü bir kez matris olarak birleştirip her noktaya aynı kuralı uygularsın. Bu sayfada dönüşüm paketini, matris çarpımının “birleşik güç” mantığını ve MVP zincirini sezgisel şekilde kuruyoruz.
Kaynak metin: byteomi.com • İlgili köprü: Koordinat Sistemleri
Canlı demo: “The Space Bender”
Aynı TRS değerlerini iki farklı sırayla birleştiriyoruz. Order matters etkisini, solda M = T · R · S (S→R→T) ve sağda M = S · R · T (T→R→S) olarak gör. Alttaki tablolar, her objenin 4×4 dönüşüm paketini canlı gösterir.
Hero demo
Sol: S→R→T • Sağ: T→R→S • Aynı sayılar, farklı çarpım sırası → farklı dünya.
Shader sezgisi: gl_Position = P · V · M · vec4(position, 1.0)
Matrix: bir “dönüşüm paketi”
Vektörler tek bir nokta veya yönü temsil eder; ama gerçek 3D sahnelerde bir model, binlerce noktadan oluşur. Bir arabayı hem taşımak, hem 45° döndürmek, hem de iki kat büyütmek istediğinde her noktaya tek tek işlem yapmak istemezsin. Matris, translation + rotation + scale bilgisini tek bir yapı içinde birleştirir.
Three.js notu: bir objenin position, rotation ve
scale değerleri değiştiğinde,
kütüphane bunları arka planda tek bir 4×4 dönüşüm matrisi içinde
birleştirir. “4×4” detayı,
taşıma işlemini de aynı çarpım zincirine sokmak için kullanılan homogeneous
coordinates yüzündendir.
Pratik karşılık: geometriyi yeniden yazmazsın; dönüşüm paketini değiştirirsin. Bu, hem
performans hem de sahne düzeni için
büyük bir avantajdır. Bazı senaryolarda (özellikle matrixAutoUpdate kapalıysa)
matrisi manuel güncellemen gerekir;
“taşıdım ama etkisi yok” hissi çoğu zaman buradan çıkar.
Neden matris? Birleşik güç
Matrislerin en büyük gücü, çarpılabilir olmalarıdır: döndürme matrisi ile taşıma matrisini çarptığında, elinde hem döndüren hem taşıyan tek bir paket kalır. Kritik detay: çarpım değişmeli değildir; yani çoğu zaman \(A \cdot B \neq B \cdot A\).
Sezgi: çoğu 3D kurguda önce objeyi kendi merkezinde ölçekler, sonra döndürür, en son dünyada bir yere taşırsın. Bu sıralama (S→R→T), “objenin yerini değiştirmeden döndürme” gibi beklentileri karşılar.
CPU–GPU iş bölümünde de aynı mantık var: CPU tarafı dönüşüm paketlerini (matrisleri) hazırlar; GPU tarafı aynı paketi devasa sayıda vertex üzerinde paralel uygular. Local→World geçişi (parent/child) de matris zinciriyle taşınır: parent world matrisi, child local dönüşümünü “dünyaya” taşır.
MVP: Model • View • Projection
Bir 3D noktanın ekrana düşene kadar geçtiği yol çoğu zaman üç matrisle kontrol edilir: Model (objeyi dünyaya koyar), View (dünyayı kameraya göre hizalar), Projection (3D’yi 2D ekrana sığdıran mercek). Bu zincir local → world → view → clip → NDC akışını kurar.
Clip uzayından NDC’ye geçişte kritik adım perspective divide’dır:
koordinatlar w bileşenine bölünür.
Bu adım, perspektif hissinin matematiksel çekirdeğidir. Pratikte çoğu zaman zincir tek
matrise birleştirilir:
MVP = P · V · M ve shader’da
gl_Position = MVP · vec4(position, 1.0) olarak yürür.
Hafif bir bakış: matris okuma
4×4 matris ilk bakışta korkutucu görünebilir; ama çoğu zaman bakacağın yerler bellidir:
üstteki 3×3 alan genellikle
dönme/ölçekleme bileşenlerini; konum ise son sütunda (dizilime göre) taşınır. Three.js’te
matrixWorld,
objenin world uzayındaki dönüşümünü temsil eder.
Üstteki 3×3 blok aynı zamanda objenin yerel eksenlerini (basis) taşır: sağ/yukarı/ileri yönlerinin world uzayında nereye döndüğünü buradan okursun. Ölçek varsa bu eksen vektörlerinin boyları 1 olmaz; “model yamuldu” gibi durumlarda hızlı sinyal verir.
Düzen notu: “konum son sütunda mı, son satırda mı?” detayı column-major/row-major farkına bağlıdır. Three.js bunu kendi içinde tutarlı yönetir; debug ederken aynı düzeni takip etmek yeterlidir.