WebGL · Lineer cebir · Uzay sözleşmesi
WebGL: Dönüşüm zinciri ve uzay mantığı
WebGL’de bir nesneyi kaydırmak veya kamerayı döndürmek, soyut bir sahne komutundan önce vertekslerin uzaylar arasında aktarılmasıdır. Bu sayfa, bu aktarımın omurgasını oluşturan matris zincirini ve her uzayın “hangi soruya cevap verdiğini” sabitler.
Hedefimiz kütüphane kullanımını yeniden anlatmak değil; GPU’nun beklediği net kalıbı görmek:
ham model verisi → model/view/projeksiyon → clip → NDC → viewport. Ayrıntılı koordinat
yolculuğu ve
gl_Position bağlamı için Vertex Shader sayfasıyla birlikte okumak verimi artırır.
Transform nedir? (kavramsal giriş)
Dönüşüm (transformation), bir noktanın uzaydaki durumunu matematiksel olarak değiştiren işlemler kümesidir. WebGL tarafında konuştuğumuz şey “sahnede bir animasyon oynatıyorum” cümlesinden önce gelir: GPU’ya giden ham geometri, çoğu zaman bu kurallarla yeniden konumlandırılır. Üst katmanda süre ve anahtar kareler vardır; alt katmanda ise her verteks için aynı matematiksel kuralın uygulanması vardır.
WebGL pratiğinde bu işlemler çoğu zaman 4×4 matrisler ve homojen koordinatlar (\(x,y,z,w\)) üzerinden birleştirilir — böylece öteleme, dönüş ve ölçeği tek çarpım ailesinde toplayabilirsiniz. Burada hedef lineer cebir dersi vermek değil; şu sezgiyi sabitlemek: “tek bir matris” gördüğünüzde, arkasında çoğu zaman birden fazla temel hareketin bileşimi yatar ve çarpım sırası yanlışsa sonuç beklenmedik şekilde kayar (detaylı sıra ve bileşik MVP için 6. bölüm).
Kavramsal olarak üç ana hareket tipi öne çıkar:
- Öteleme (translation): Noktayı doğrusal olarak kaydırmak — “origin’a göre nereye?” sorusunun toplamsal kaymasıdır.
- Döndürme (rotation): Bir eksen veya referansa göre yönü değiştirmek — mesafe (uzunluk) çoğu klasik uygulamada korunur, yön değişir.
- Ölçekleme (scaling): Eksenlere göre mesafeleri büyütüp küçülterek nesneyi gerip sıkmak — “aynı şekil, farklı ölçü” veya eksen bazlı deformasyon.
Önemli sezgi: bu işlemler “ekranda gördüğüm animasyon”dan önce, vertex başına uygulanan sayısal kurallardır. Bir mesh’i döndürdüğünüzde, GPU çoğu zaman binlerce verteksi aynı matrisle günceller; siz üstte bir komut verirsiniz, altta ise çok sayıda paralel tekrar çalışır. Bu yüzden performans düşüncesi bile bazen “hangi animasyon?”dan önce “bu karede hangi matris her verteks için koşuyor?” sorusuna döner.
Son küçük ayrım (bu sayfanın odağını netleştirmek için): burada temel olarak konum (pozisyon) dönüşümünden bahsediyoruz. Yön vektörleri ve normaller, özellikle ölçek içeren dönüşümlerde aynı matrisle birebir taşınamayabilir; aydınlatma doğruluğu için normal tarafı model matrix tartışmasında ayrı bir not olarak işaretlenmiştir — böylece konum mantığı ile normal mantığı birbirine karışmaz.
Coordinate spaces (uzay yolculuğu)
Bir verteks ekrana düşmeden önce aynı geometri için aynı köşenin farklı sayı temsillerini görürsünüz. Koniğin şekli değişmez; değişen, koordinatları kimin merkezine göre okuduğunuzdur. Her uzay, “bu nokta kime göre nerede?” sorusunun ayrı bir cevap anahtarıdır — bu yüzden uzay değiştirmek, “yeniden ölçülüyorum” demektir, “yeni model yaptım” demek değildir.
- Model space (local): Mesh’in kendi kaynak eksenine göre koordinatlar — çoğu zaman model dosyasından çıkan ham buffer ile uyumludur. Bu uzayda “sahnede nerede?” sorusu henüz yoktur; soru “mesh içinde hangi köşe?”dur.
- World space: Nesnenin sahneye yerleştirilmiş tek ortak evrendeki konumu, yönü ve ölçeği. Birbirinden bağımsız modeller burada aynı cetvelle karşılaşır.
- View space (camera space): Her şeyin kameranın bakış eksenlerine göre yeniden yazıldığı uzay. “Dünya hâlâ var ama ölçüm cetveli kamera oldu.” düşüncesi burayı sabitleştirir (view matrix).
- Clip space: Projeksiyon sonrası homojen koordinatlarda, görüş hacmine göre kırpmaya uygun ara temsil. Burası henüz “ekran pikseli” değildir; \(w\) bileşeniyle birlikte gelir ve bir sonraki sabit aşamalarda NDC + viewport’a giden kapıyı açar (8. bölüm).
Tipik akış soyuttur ama sırayı bilmek teşhisleri kolaylaştırır: model → world → view sırasını model ve view matrisleri üzerinden düşünürsünüz; clip ise projection ile gelir (MVP bunların bileşimidir). Bu tabloyu ezberlemekten çok, shader’a hangi uzayı “nihai doğru” diye verdiğinizi bilmek gerekir: örneğin dünya uzayındaki ışık yönüyle model uzayındaki normal’ı doğrudan çarparsanız, sonuç matematiksel olarak “bir şey üretir” ama fiziksel olarak anlamsız olabilir — aydınlatma tarafında bu tuzak için Holodepth’teki ışık · uzay birliği uyarısıyla birlikte düşünün.
Bu sıra “ezber”den çok veri sözleşmesidir: bir sonraki adımın beklediği vektör hangi uzaydaysa, önceki adımın çıktısı o uzaya uygun olmalıdır. Uygunsuzlukta gördüğünüz şey çoğu zaman “mesh bozuk” değil, “yanlış merkeze göre ölçülmüş”tür: nesne sahneyi boydan boya süzülür, iç yüzeyler dışarı çıkar, iki nesne iç içe geçmiş görünür veya perspektif “sırf yanlış uzaklıkta” duruyormuş gibi hissedilir. Kök neden geometriden önce yanlış uzayda çarpım yapmaktır; ilk sorulması gereken “shader doğru mu?”dan önce “bu vektör hangi uzaya göre yazılmıştı?” sorusudur.
Space stage
Matrix stack
Active vertex data
Altın cümle
Bir vertex, farklı uzaylardan geçerek ekrana giden yolu tamamlar.
Model matrix: “nesne nerede?”
Model matrix, buffer’da duran verteks konumlarını model (yerel) uzaydan dünya uzayına taşır. Nesnenin dünyaya göre öteleme, dönüş ve ölçek bilgisi bu matriste paketlenir; böylece aynı küre (veya aynı indeksli) geometriyi tek kez GPU’ya verip, çizim başına farklı bir model matrisi seçerek sahneye birçok kez yerleştirebilirsiniz. Ham koordinatlar çoğu zaman model dosyasının orijinine kilitlidir; model matrisi ise “bu mesh şimdi ortak cetvelde nerede, hangi yöne dönük, ne ölçüde?” sorusunun cevabını dünya uzayında yazar.
Bu sayfa ve bu bölüm özellikle pozisyon akışına odaklanır. Normal vektörleri gibi yön verileri, aydınlatmada ışık yönüyle aynı uzayı paylaşmak zorunda olduğundan ayrı bir dönüşüm sözleşmesi ister; çoğu klasik pipeline’da normal için inverse transpose (veya eşdeğer bir normal matris) fikri burada devreye girer ve konumu taşıyan matrisle birebir özdeş düşünülmemelidir. Uzay birliği, hata teşhisi ve normal tartışması için ışıklandırma — normal vektör bölümüyle birlikte okumak uyumludur — burada kritik olan, “nerede?” sorusunun model → world köprüsündeki konum tarafıdır.
Kısa not: ebeveyn–çocuk zinciri gibi hiyerarşik sahnelerde uygulama, çoğu zaman bu halkaları tek bir dünya (world) matrisine çökertir ve shader’a o birleşik sonucu “model” olarak verir. Motorların sahne grafiğini nasıl sıraya dizdiği ayrı bir anlatı katmanıdır; WebGL tarafında elinizde kalan soyut gerçek, GPU’nun çarptığı sembolün dünyaya göre yerleşimi kodlamasıdır.
View matrix: “kamera nereden bakıyor?”
Görüntüyü çizen kameradır; ama GPU’ya giden matematikte sık kullanılan zihinsel numara şudur: kamerayı dünya içinde gerçekten “yürütüyor” gibi düşünmek yerine, tüm dünyayı kameranın bakışına göre ters yönde yeniden yazarız. View matrix, bu yüzden world → view dönüşümünü üstlenir. Model matrix nesneyi ortak sahne cetveline yerleştirdikten sonra, view matrix o cetveli bu kez kameranın konum ve eksenlerine göre yeniden ölçer.
Buradaki amaç görsel bir “hile” üretmekten çok, hesabı tek bir referans çerçevesinde toplamaktır. Kamera orijinde duruyor, ileri bakış yönü sabitmiş gibi davranmak; bir noktanın kameranın solunda mı sağında mı, önünde mi arkasında mı, ne kadar uzakta mı olduğunu daha düzenli okumayı sağlar. Yani view uzayı, “dünyayı kaydırdım” hissinden çok, “artık tüm konumları kameraya göre okuyorum” sözleşmesidir.
Bu çerçeve, clip uzayına giden matematiksel yolu sadeleştirir: önce nesneyi dünyaya yerleştir, sonra dünyayı kameranın önünde hizala, ardından projection matrix ile görüş hacmine projekte et. Özellikle perspektif hesabı “kamera nerede?” sorusunu tekrar çözmek istemez; bu bilgi önce view matrisinde sindirilir, projeksiyon ise ondan sonra “nasıl görünecek?” sorusuna geçer.
Projection matrix: “nasıl görünüyor?”
Projection matrix, görüş hacmini ve ekran düzlemine projeksiyon kuralını matematiksel olarak kodlar. View uzayında “kameraya göre nerede?” diye okunabilen bir nokta, projection ile artık “ekrana nasıl düşecek?” sorusunun alanına girer. Yani bu matris, konumu tek başına taşımaktan çok; hangi hacmin görünür sayılacağını, derinliğin görüntüde nasıl hissedileceğini ve clip uzayına giden sayısal sözleşmeyi belirler. İki yaygın aile:
- Perspective: Derinlik mesafesi ile boyut algısı; uzaktaki nesneler daha küçük görünür.
- Orthographic: Paralel projeksiyon; mesafe tek başına “küçültme” yapmaz — teknik, izometrik veya UI benzeri görünümlerde sık görülür.
Aradaki temel fark, “uzaklık görüntü ölçeğine karışıyor mu?” sorusudur. Perspective projeksiyon, insan gözüne ve fiziksel kameraya daha yakın bir derinlik hissi üretir; aynı boyuttaki iki nesneden uzakta olan daha küçük görünür. Orthographic projeksiyon ise paralel ilişkileri korumaya daha yakındır; bu yüzden ölçü okuma, teknik çizim mantığı veya sahnede göreli boyutu sabit tutmak istediğiniz anlatımlarda daha öngörülebilir davranır.
Burada kritik nokta, projection’ın nesneyi “dünyada nereye koyduğunu” çözmemesidir; o iş model ve view tarafında tamamlanır. Projection, bu hazır konumu alıp görüş hacmiyle karşılaştırır, homojen koordinat düzenine taşır ve sonraki aşamalarda yapılacak clip / NDC mantığı için zemini kurar. Özellikle perspective ailesinde bu iş, tabloda özetlenen \(w\) bileşeni ve perspektif bölen davranışıyla görünür hale gelir.
Özet karşılaştırma
| Özellik | Perspective | Orthographic |
|---|---|---|
| Derinlik hissi | Yüksek (konik görüş, yakın/büyük — uzak/küçük) | Düşük (ölçek mesafeden bağımsız kalır) |
| Yaygın kullanım | Oyun, ürün görselleştirme, sahne | CAD hissi, 2.5D, bazı UI/ölçüm görünümleri |
| Projeksiyon matrisi | Görüş kırması ve perspektif bölen (\(w\)) üretir | Paralel köşeler korunmaya yakın görünüm |
MVP matrix: dönüşümün zirvesi
Üç matris tek tek her verteks için çarpılabilir; pratikte ise GPU tarafında çoğu zaman önce tek bir bileşik matris hesaplanır ve verteksler bu bileşik ile işlenir. Tipik yazılış şöyledir: \(\mathrm{MVP} = P \cdot V \cdot M\).
Kolon vektör konvansiyonunda (GLSL’de sık görülen), bir pozisyon için özet işlem şöyle düşünülür: \(\mathbf{p}_{\mathrm{clip}} = \mathrm{MVP}\,\mathbf{p}_{\mathrm{model}}\). Burada \(P\) projection, \(V\) view, \(M\) model’dir; sıra, kullandığınız matematik kütüphanesinin vektörün sağdan çarpımına göre doğrulanmalıdır — yanlış sıra, doğru parçaları bile saçma bir görüntüye gömer.
Performans notu: MVP çoğu karede bir kez güncellenir; verteks başına tekrarlanan işlem tek bir matris–vektör çarpımına indirgenir.
Vertex shader bağlantısı
Bu zincirin sahne tarafında “yaşadığı” yer çoğu pipeline’da vertex
shaderdır.
Attribute olarak gelen model uzayı pozisyonu, seçtiğiniz tek bir bileşik matris veya ayrık
\(M,V,P\)
çarpımlarıyla clip uzayına taşınır ve gl_Position (veya WebGL2 eşdeğeri çıktı)
ile bir
sonraki sabit işlevsel aşamaya verilir.
Yani “matrix kodu” dediğimiz şey CPU’da JS veya motor katmanında hazırlanabilir; ama her verteks için uygulanan çarpım GPU vertex programında gerçekleşir. Bu yüzden MVP’yi anlamak, vertex shader okumayı da okumaktır.
Clip space, NDC ve perspective divide
Vertex shader çıktısı clip space içinde homojen bir vektördür: henüz “ekran pikseli” değildir; görüş hacmine göre kırpma ve rasterization öncesi ara temsilidir. Clip koordinatları genelde \(x,y,z\) bileşenleri ile birlikte dördüncü bileşen \(w\) taşır.
Perspective divide: Donanım, \(\mathbf{p}_{\mathrm{ndc}}\approx(x/w,\;y/w,\;z/w)\) işlemini uygular ve NDC (Normalized Device Coordinates) düzlemine geçilir. Mesafe algısının “uzak küçülür” kısmı çoğu perspective kurulumda bu \(w\) ile bölme üzerinden tamamlanır.
Sonrasında viewport dönüşümü ekran piksellerine ölçekler — bu adım vertex shader’dan sonra sabit işlevdedir; ama clip → NDC geçişini görmezseniz “projeksiyon doğru ama sahne garip” teşhisi zorlaşır.
Three.js bağlantısı
Üst seviye bir motorda bu zinciri elle kurmak zorunda kalmazsınız; Three.js kamera
ve nesne
dönüşümlerinden model/view/projeksiyon üretir, bileştirir ve materyalın bağlı
olduğu shader’a
uniform olarak gönderir. Bir nesnenin
position/rotation/scale
özetinin altında yatan şey, çizim anında güncellenen model (ve türev) matris matematiğidir.
Burada duruyoruz: sahne grafiği, materyal seçimi ve matris güncelleme ayrıntıları Three.js içeriğinde kalır. WebGL tarafında kazanımınız şudur: ekranda gördüğünüz her hareketin bir uzay + matris sırası karşılığı vardır; bug ayıklarken önce “hangi uzayda çarpıyorum?” sorusunu sormak, çoğu zaman yanlış sırayı çözer.