Shader & GLSL · Vertex / fragment
Coordinate spaces
Konum hangi uzayda?
Vertex / fragment serisinin son konusu: gl_Position yazılmadan önce konumun hangi
uzaylardan geçtiği. Veri akışı
taşıyıcıları ve adımları kurdu;
Interpolation
varying’lerin raster’da nasıl karıştığını anlattı — burada odak konum ve normalin matris
zinciri.
Three.js çoğu projede modelViewMatrix ve projectionMatrix
uniform’larını
otomatik besler; özel materyalde hangi uzayda hesap yaptığınızı bilmek zorunludur. Matris
çarpımı
kuralları
Operators
ve mat4 türü
Vec
types
konusundadır; bu sayfa uzay isimleri ve shader’daki tipik zinciri sabitler.
Genel koordinat sezgisi ByteOmi · koordinat sistemleri ve Matrix nedir? köprülerinde; aşağıdaki §1–§8 vertex shader bakışıyla ilerler.
Neden Koordinat Uzayları?
Aynı sahne içinde «konum» birden fazla anlama gelir. mesh.position nesneyi
sahne
grafiğinde taşır; attribute vec3 position; geometry’nin yerel köşe
koordinatıdır.
Vertex shader bu ikisini matrislerle birleştirip gl_Position üretir — uzay
karışınca model yerinde durur, uçar veya iç içe geçer (
Veri akışı · akış
hataları).
Fragment shader çoğu ışık hesabını «dünya» veya «görüntü» uzayında yapar; bu yüzden normal
çoğu zaman vertex’te dönüştürülüp varying ile taşınır. UV ve renk
enterpolasyonu
Interpolation
konusunda kalır; burada yalnızca konum / normal uzayı.
Bu sayfa ne anlatır, ne anlatmaz?
Anlatır: model → view → clip zinciri; Three.js matris uniform’ları;
gl_Position satırı; normalMatrix; uzaya özel hatalar. Anlatmaz:
tam matris türevi ve perspektif projeksiyon formülü (ByteOmi / matematik köprüleri); varying
bildirimi derinliği; pipeline donanım tablosu (
Shader
pipeline).
Seri içindeki yer
Vertex / fragment serisi burada kapanır: Veri akışı → Shader pipeline → Interpolation → Coordinate spaces (bu sayfa). Önce «veri nereye akar?», sonra donanım, sonra karışım, en son «konum hangi uzayda çarpılıyor?».
Uzay Zinciri: Model → View → Clip
Vertex shader’da tek bir köşe noktası, birkaç uzaydan geçerek ekrana giden üçgenin parçası olur. Zinciri ezberlemek yerine her adımda «şimdi hangi soruya cevap veriyorum?» diye okuyun — Holodepth isimleri Three.js ile uyumludur; özel materyalde de aynı uniform adları görülür.
Dört Kapı: Local → World → View → Clip
- Local / model — «Köşe mesh’in kendi gövdesinde nerede?»
attribute vec3 position;geometry tamponundan gelir; ölçek ve şekil burada tanımlıdır ( §3). - World — «Sahnedeki mutlak yer neresi?» Three.js
mesh.position/rotation/scalebu dönüşümü günceller; shader’damodelMatrixuniform’u köşeyi dünya uzayına taşır. - View / eye — «Kamera nereden bakıyor?»
viewMatrixdünya noktasını kamera önüne alır. Pratikte çoğu örnekmodelViewMatrixkullanır — iki adımı tek uniform’da birleştirir:modelViewMatrix = viewMatrix * modelMatrix( §4). - Clip — «Ekran / derinlik testine uygun koordinat nedir?»
projectionMatrixperspektif veya ortografik projeksiyon uygular; vertex çıkışıgl_Positionbu uzaya yakındır. Sonrasında raster ve enterpolasyon ( Interpolation · raster) devreye girer — konum ve UV ayrı kanallardır.
Tipik Satır: gl_Position
En sık görülen kalıp:
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
Okuma yönü sağdan sola düşünülür: önce vec4(position, 1.0) homojen köşe (yerel
uzay), sonra modelViewMatrix ile kamera önüne, en son
projectionMatrix
ile clip’e. Matrisler solda, vektör sağda kalır — GLSL’de
mat4 * vec4 sırası
Operators
konusundadır.
gl_Position taşıyıcı değildir; varying değildir — vertex’in zorunlu konum
çıkışıdır (
Veri akışı · vertex
çıkışı). Tam çarpım sırası, w bileşeninin perspektif bölünmesi ve NDC
ayrıntısı ileride bu bölümde derinleştirilecek; şimdilik «her matris bir uzay kapısı»
yeterlidir.
Ayrı Matrisler Ne Zaman?
modelMatrix ve viewMatrix’i ayrı kullanmak, dünya uzayında ışık /
gölge veya nesne bazlı efekt yazarken gerekebilir — örneğin fragment’te dünya konumu için
modelMatrix * vec4(position, 1.0) ayrı hesaplanır. Yalnızca standart mesh
çizimi
için modelViewMatrix + projectionMatrix çoğu zaman yeterlidir.
Genel vertex rolü
GLSL giriş · vertex aşaması
bölümünde de özetlenir. Aşağıdaki §3 yerel position attribute’unu, §4 Three.js
uniform setini, §5 örnek kodu açar.
Yerel köşe: attribute position
§2
zincirinin ilk kapısı buradadır: vertex shader’a giren position, henüz sahne
veya
kamera görmeyen yerel köşe koordinatıdır. Matrisler bu değeri dünya / görüntü /
clip’e
taşır — attribute içinde «dünya konumu» saklanmaz.
Geometry tamponu ve isim sözleşmesi
Attribute vec3 position; shader bildirimidir; veri
BufferGeometry üzerindeki position attribute tamponundan gelir.
İsimler
eşleşmelidir — Three.js’te farklı kanal adı kullanırsanız shader’a ulaşmaz (
Uniforms · attribute,
Attributes & buffer’lar).
Her vertex invokasyonu tampondan bir köşe satırı okur; değer draw call boyunca attribute
olarak sabitlenir, uniform gibi paylaşılmaz
(
Veri akışı ·
taşıyıcılar). Köşeden köşeye farklı position normaldir — mesh’in şekli
burada kodlanır.
Nesne dönüşümü ≠ köşe koordinatı
Sık karışıklık: mesh.position (ve rotation, scale)
tüm
nesneyi sahne grafiğinde taşır; position attribute’u ise geometry’nin kendi
gövdesindeki noktadır. Sahne tarafında nesneyi hareket ettirirsiniz; shader’da bunun
karşılığı
modelMatrix uniform’udur — attribute’a mesh.position yazılmaz (
Veri akışı · akış
hataları,
§8).
Vertex’te doğru kalıp:
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
— position yerel kalır, dönüşüm matrislerle gelir. Nesneyi shader içinde
position + vec3(...) ile kaydırmak yerine ya sahne grafiğini ya da
modelMatrix uniform’unu güncelleyin
( §4).
Kaynak: DCC export ve procedural mesh
Blender, Maya vb. export edilen mesh’ler köşeleri genelde model / yerel uzayda getirir — bu
yüzden import sonrası mesh.position ile sahneye yerleştirirsiniz. Three.js
PlaneGeometry, BoxGeometry, SphereGeometry de aynı
mantıkla köşeleri yerel uzayda üretir; merkez ve boyut parametreleri geometry oluşturulurken
tampona yazılır.
Özel tampon (
Custom buffer geometry)
yazarken de «bu array hangi uzayda?» sorusunu baştan netleştirin — çoğu zaman yerel mesh
uzayıdır; dünya koordinatı attribute’a gömülmez, modelMatrix ile taşınır.
Sonraki adımlar
Vertex shader’ın işi: bu yerel noktayı
§2
zinciriyle dünya / görüntü / clip’e taşımak ve gl_Position yazmak. Normal ve UV
ayrı attribute kanallarıdır; konumla aynı uzayda olmak zorunda değildir — normal
normalMatrix ile ayrı dönüştürülür (§6). Aşağıdaki §4, matris uniform setini;
§5 standart vertex örneğini gösterir.
Matris uniform’ları (Three.js)
§3
yerel position attribute’unu tanımladı; bu bölüm onu uzaylar arası taşıyan
mat4 uniform’larını shader dosyasında nasıl okuyacağınızı sabitler. Başlıkta
«Three.js» geçmesi, Holodepth örneklerindeki isim sözleşmesi içindir — kamera
kurulumu, Camera API’si veya Matrix4 JavaScript ayrıntısı bu
sayfada yoktur; odak GLSL tarafındaki uzay zinciridir.
ShaderMaterial ve çoğu built-in materyal, vertex shader’a aşağıdaki matris
uniform’larını otomatik enjekte eder — GLSL dosyasında isimler bire bir aynıdır. Sizin
işiniz motorun matrisi nasıl hesapladığını ezberlemek değil; vertex satırında hangi
uniform’un
hangi uzay kapısını kapattığını bilmektir.
ModelMatrix — Nesne → Dünya
uniform mat4 modelMatrix; yerel position attribute’unu (
§3) dünya uzayına taşır. Sahne grafiğinde
nesneyi taşıdığınızda güncellenen dönüşüm burada okunur; köşe tamponuna eklenmez.
Vertex’te dünya konumu gerekiyorsa:
vec4 worldPos = modelMatrix * vec4(position, 1.0); — sonrasında varying veya
ayrı hesap ile fragment’e taşınabilir. Standart çizimde bu adım çoğu zaman
modelViewMatrix içinde gizlidir.
ViewMatrix — Dünya → Kamera
uniform mat4 viewMatrix; dünya uzayındaki noktayı kamera / görüntü uzayına
alır.
Tek başına konum satırında daha seyrek görülür; pratikte modelViewMatrix model
ve
view adımlarını birleştirir.
Ayrı kullanım, kamera ve nesne dönüşümlerini shader içinde farklı kombinlemek istediğiniz özel efektlerde anlamlıdır; günlük materyal yazımında ikinci plandadır.
ModelViewMatrix — Birleşik Model + View
uniform mat4 modelViewMatrix;, kabaca
viewMatrix * modelMatrix çarpımının hazır halidir — konum için en sık
kullanılan
uniform’dur. Tipik çarpım:
modelViewMatrix * vec4(position, 1.0) (
§2 · gl_Position).
«Önce model sonra view» mantığı bu tek matriste paketlenmiştir; vertex’te ayrı ayrı çarpmak yerine motorun gönderdiği birleşik değeri okumak hem kısadır hem hatası azaltır.
ProjectionMatrix — Görüntü → Clip
uniform mat4 projectionMatrix; kamera önündeki noktayı clip uzayına yakın
temsile projekte eder — perspektif veya ortografik kamera ayarına bağlıdır. Vertex’te
genelde son çarpandır; çıktı gl_Position’dır ve raster buna göre aday piksel
seçer.
Tam satır:
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
— projeksiyon «ekran perspektifi» katmanıdır; UV veya renk bu matristen geçmez.
NormalMatrix — Normal İçin Ayrı Yol
uniform mat3 normalMatrix; konum matrisinin kopyası değildir; attribute
vec3 normal; yön vektörlerini dönüştürmek için türetilmiştir. Türü
mat3’tür — normal §6’daki kalıpta (
§6) kullanılır.
Konum için normalMatrix, view için modelViewMatrix kullanmak
yaygın
bir karışıklıktır; her attribute kendi uzay dönüşümünü izler.
Draw Call Boyunca Sabit; Enterpolasyon Yok
Tüm matris uniform’ları draw call başına bir kez bağlanır — aynı mesh çizimindeki her köşe
ve
fragment invokasyonu aynı projectionMatrix, aynı modelViewMatrix
değerini görür. Raster köşeler arasında matris karıştırmaz (
Interpolation ·
uniform karışmaz).
Uniform bildirim kuralları
Uniforms · uniform
konusundadır. Kamera veya nesne hareket ettiyse matrisler bir sonraki
render öncesi güncellenmiş olmalıdır (
Veri akışı · draw call
öncesi).
Tekrar Çarpım Tuzağı
Özel uniform eklerken «bu matris hangi uzayı birleştiriyor?» sorusunu sorun. Sık hatalar:
projectionMatrix * projectionMatrix * …— projeksiyon iki kez uygulanır.modelViewMatrixvarken ayrıcamodelMatrixile tekrar çarpmak — dünya adımı iki kez işlenir.- Konum için
normalMatrixkullanmak — yanlış uzay; normal §6’daki kalıpta kalır.
Güvenli yol: Three.js’in verdiği isimleri ve §2’deki tek satırlık kalıbı kopyalayıp yalnızca ihtiyaç duyduğunuz ek uniform’ları (zaman, doku) eklemek.
Ayrı Model + View Ne Zaman?
Shader’da modelMatrix ve viewMatrix’i ayrı tutmak, dünya uzayında
hesap gerektiğinde anlamlıdır — örneğin vertex’te
vec4 worldPos = modelMatrix * vec4(position, 1.0); yazıp varying ile fragment’e
taşımak. Yalnızca «mesh’i ekrana çiz» hedefi için
modelViewMatrix + projectionMatrix yeterlidir (
§2 · ayrı matrisler).
RawShaderMaterial Notu
RawShaderMaterial kullanıyorsanız bu matris uniform’ları otomatik gelmez —
vertex
shader’da bildirmeniz ve JavaScript tarafında beslemeniz gerekir. Holodepth vertex /
fragment
örnekleri varsayılan Three.js isim setini gösterir; motor API’si
GLSL
giriş (Three.js)
konusundadır, burada yalnızca «shader’da hangi isim, hangi uzay?» sabitlenir.
Aşağıdaki §5, bu uniform’ların tamamını içeren standart vertex örneğini gösterir.
Örnek: Standart Vertex Konumu
Aşağıdaki kalıp, konum uzayını tek satırda toplar. UV taşıma Interpolation · UV örneği ile birleştirildiğinde tam materyal iskeleti oluşur.
attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat3 normalMatrix;
varying vec2 vUv;
varying vec3 vNormal;
void main() {
vUv = uv;
vNormal = normalize(normalMatrix * normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
Normal: normalMatrix
Konum position ve modelViewMatrix ile clip’e gider (
§2,
§5). Normal ayrı bir yoldur:
attribute vec3 normal; yerel yüzey yönüdür; ışık ve yansıma hesapları çoğu
zaman
dünya veya görüntü uzayında yapılır — bu yüzden normalMatrix uniform’u (
§4 · normalMatrix) devreye
girer.
Vertex Kalıbı: Dönüştür, Normalize Et, Taşı
Tipik satır:
vNormal = normalize(normalMatrix * normal);
— önce uzay dönüşümü, sonra birim uzunluk. normalize enterpolasyondan önce veya
sonra tartışılır; pratikte vertex’te normalize edip varying ile göndermek yaygındır.
Fragment’te
dot(vNormal, lightDir) gibi hesaplar bu enterpolasyonlu yönü kullanır (
Interpolation,
Built-in · vektör).
normal attribute’unu fragment’te doğrudan okuyamazsınız — akış
attribute → varying → raster → varying (
Veri akışı ·
taşıyıcılar). Konum kanalı ile karıştırmayın; UV ayrı kanaldır.
Yerel Normal, Dünya Işığı
Fragment’te dot(normal, uLightDir) yazmak, yerel normali dünya uzayındaki ışık
vektörüyle karşılaştırmaktır — sonuç yanlış veya kameraya bağlı «kayar» görünür. Işık yönü
hangi uzaydaysa normal de o uzayda olmalıdır; vertex’te normalMatrix bu
eşleştirmeyi
sağlar.
Ters ölçek (scale negatif eksen) gibi durumlarda normalMatrix
özellikle
önemlidir — konum matrisinin üst 3×3’ünü kopyalamak yeterli değildir. Ayrıntılı türev (ters
çevrim üst 3×3) ileride bu bölümde açılacak; şimdilik pratik kural: motorun gönderdiği
uniform mat3 normalMatrix; değerini kullanın; elle modelMatrix ile
aynı
sanmayın.
Fragment’te Tüketim
vNormal enterpolasyonlu geldikten sonra fragment’te çoğu zaman tekrar
normalize(vNormal) uygulanır — üçgen içi karışım uzunluğu bozulmuş olabilir.
Işık modeli bu sayfada derinleştirilmez; uzay eşleşmesi sağlandıysa materyal formülünüz
çalışır.
Clip Çıkışı ve Raster
§4 · projectionMatrix
vertex’te son çarpandır; çıktı gl_Position’dır. Bu bölüm, konum zincirinin
GPU’ya
bıraktığı zorunlu çıkış ile raster / enterpolasyon arasındaki sınırı netleştirir — UV ve
normal
bu kanaldan gitmez.
gl_Position: Konum Çıkışı, Taşıyıcı Değil
gl_Position vertex shader’ın zorunlu çıkışıdır; attribute,
uniform veya varying değildir (
Veri akışı · vertex
çıkışı). Rasterizer hangi piksellerin üçgene aday olduğunu buna göre belirler —
«ekran
nerede?» sorusunun cevabı burada kodlanır.
vUv, vNormal ayrı varyings’lerdir; gl_Position onları
taşımaz. Enterpolasyon yalnızca varying kanallarında çalışır (
Interpolation ·
girdi
ve çıktı).
W Bileşeni ve Perspektif
gl_Position bir vec4’tür; w bileşeni perspektif
bölünmede
rol oynar. Derinlik testi ve perspektif enterpolasyon (UV’nin uzak köşede sıkışması gibi) bu
değere bağlıdır — çoğu zaman hata değil, projeksiyonun doğal sonucudur (
Interpolation
·
perspektif).
Clip uzayı, NDC ve ekran pikseli dönüşümünün matematiği ileride bu bölümde derinleştirilecek. Shader yazarken §2’deki tek satırlık kalıbı doğru uygulamak çoğu uygulama için yeterlidir.
Raster Sonrası
gl_Position işlendikten sonra pipeline rasterize eder; fragment shader renk ve
derinlik üretir — tam adım listesi
Shader
pipeline
konusundadır. Uzay serisi burada kapanır; sonraki §8 yaygın karışıklıkları özetler.
Uzaya özel karışıklıklar
Aşağıdaki liste konum ve normal uzayı karışıklıklarını vurgular — doğru taşıyıcı
ama
yanlış uzay. «uv fragment’te yok» veya «varying unuttum» gibi akış hataları
Interpolation ·
hatalar
ve
Veri akışı · hatalar
bölümlerinde kalır.
mesh.positionilepositionattribute’unu aynı sanmak — biri sahne düğümü (→modelMatrix), biri geometry köşesi (→ attribute). Düzeltme: sahne grafiğinde taşı veya §2 kalıbını kullan ( §3).- Normali dönüştürmeden
dot(normal, lightDir)— yerelnormal, dünya ışığı ile karşılaştırılır. Düzeltme:
vNormal = normalize(normalMatrix * normal);( §6). - Yanlış matrisle
gl_Position— model kaybolur, devasa görünür veya ters döner. Düzeltme: §2’deki
projectionMatrix * modelViewMatrix * vec4(position, 1.0)sırasını ve isimleri kopyalayın ( §4 · tekrar çarpım). - Matris çarpım sırasını ters yazmak — zincir bozulur. Düzeltme: Three.js uniform isimlerini olduğu gibi kullanın; elle yeniden sıralamayın.
- Ölçekli veya aynalı ölçekte
normalMatrixatlamak — aydınlatma yamuk, içe dönük görünür. Düzeltme:uniform mat3 normalMatrix;( §4). gl_Positionile varying karıştırmak — konum çıkışı ayrı kanal; UV/normalvaryingile taşınır ( §7).
Hızlı Kontrol Listesi
Şüphede iki soru: (1) Bu vektör hangi uzayda tanımlı? (2) Hedef uzayda hangi matris / varying gerekli? Konum için §2 kalıbı; normal için §6 kalıbı; taşıyıcı zinciri için Veri akışı özeti. Vertex / fragment serisi bu sorularla kapanır — geniş GLSL bağlamı için GLSL giriş (Three.js).
Holodepth notu
Vertex / fragment serisi tamamlandı. Özel materyalde kağıda
local → modelView → projection → gl_Position oklarını çizin; UV/normal için
Interpolation
sayfasına dönün. Geniş bağlam için
GLSL
giriş (Three.js).