Shader & GLSL · Vertex / fragment
Veri akışı
Köşeden piksele veri yolculuğu
GLSL sözdizimi serisi (Variables …
Uniforms & varyings)
shader dosyasında ne bildirildiğini sabitledi: uniform,
attribute, varying ve türleri. Vertex / fragment serisi ise
ne zaman ve hangi yönde aktığını sorar — JavaScript sahnesinden GPU
invokasyonlarına kadar tek bir harita.
Pratikte iki dünya üst üste çalışır: Three.js tarafında geometry,
material.uniforms ve renderer.render; shader tarafında vertex ve
fragment programları. Veri akışı sayfası bu iki dünyayı «köprü» kelimesiyle değil,
zaman çizelgesi ile anlatır — draw call anında hangi paketin vertex’e, hangisinin
raster sonrası fragment’e ulaştığını gösterir.
Pipeline adımlarının tam listesi
Shader pipeline,
enterpolasyonun nasıl karıştırdığı
Interpolation,
model / görüntü / clip uzayları
Coordinate
spaces
konusundadır. Burada yalnızca taşıyıcılar (attribute → varying →
uniform okuma noktaları) ve akış yönü öne çıkar; aşağıdaki §2 bu haritayı tek
kareye
indirger.
Neden veri akışı?
Shader yazarken iki soru üst üste biner. Birincisi: «Bu değişken hangi anahtar sözcükle
bildirilir?» — uniform, attribute veya varying?
İkincisi: «Bu değer vertex’te mi, fragment’te mi, arada mı kullanılır?» Birinci soru
Uniforms & varyings
konusundaydı; üç karar sorusu (
Uniforms · üç soru) orada özetlenir. İkinci soru bu sayfanın
konusudur — kod derlenir ama yanlış aşamada okunursa sessiz veya link hatası üretir.
İki soru farklı hata türlerine yol açar. Yanlış anahtar sözcük çoğu zaman derlemede veya
link aşamasında yakalanır (attribute fragment dosyasında geçemez). Yanlış aşama
ise bazen derlemeyi geçer: örneğin fragment’te texture2D(uMap, uv) yazmak —
uv vertex’teki attribute adıdır, fragment’te okunacak isim enterpolasyonlu
vUv olmalıdır (
§6). Uniform ismi yanlışken program
yine derlenebilir; akış
doğru görünür ama değer bağlanmaz (
Uniforms · sessiz hatalar).
Bu bölüm, üstteki giriş paragraflarında söylenen «ne zaman / hangi yönde» ayrımını sayfa sınırları ve okuma sırasıyla somutlaştırır; §2’den itibaren zincir ve örnek kod devreye girer.
Bu sayfa ne anlatır, ne anlatmaz?
Holodepth’te vertex / fragment serisi, sözdizimi serisinin ardından gelir. Sözdizimi dosyada ne yazılır; bu seri değer hangi pipeline adımında okunur diye sorar. Aşağıdaki ayrım, kardeş sayfalara tekrar etmeden bu sayfanın payını çizer.
Anlatır:
- CPU → draw call → vertex → raster → fragment zincirinde taşıyıcı seçimi (§2 özet, §3 giriş, §4– §5 örnekler).
gl_Positionile konumun raster’a gidişi;varyingile köşe verisinin fragment girdisine bağlanması — formül değil, yön.- Yanlış aşamada veri arama ( §6).
Anlatmaz (bilinçli sınır; her konu kendi sayfasında derinleşir):
- GLSL türleri, vektörler, operatörler — Variables … Operators serisi.
- Uniform / attribute bildirimi,
{ value: … }, isim sözleşmesi — Uniforms · Three.js köprüsü. - Enterpolasyon matematiği ve perspektif notları — Interpolation.
- Model / view / projection matris türevleri ve uzay adları — Coordinate spaces.
- Derinlik testi, blending, tam donanım pipeline tablosu — Shader pipeline.
Seyrek vertex, yoğun fragment
Vertex shader seyrek çalışır: invokasyon sayısı köşe sayısına yakındır. Fragment shader
yoğun
çalışır: üçgen başına çok sayıda aday piksel üretilir. Bu yüzden attribute yalnızca vertex’e
bağlanır; köşe verisini fragment’e taşımak için varying ve rasterizasyon
gerekir.
Genel rol ayrımı
GLSL giriş · shader türleri
bölümünde anlatılır; burada yalnızca «veri neden köprü ister?» sorusuna cevap verilir.
Köprü ihtiyacı, «seyrek → yoğun» farkından gelir. Vertex’te bir kez yazılan
vUv = uv;, raster sonrası binlerce fragment invokasyonuna enterpolasyonla
yayılır; JavaScript’te bu adımın karşılığı yoktur (
Interpolation).
Buna karşılık uTime gibi çağrı boyunca sabit veri her invokasyonda aynıdır;
varying ile taşımak yerine uniform yeterlidir (
Uniforms · üç soru, birinci madde).
Özet: attribute ve uniform vertex girişidir; yalnızca köşeye özel ve fragment’te de
gereken bilgi varying ile «arada» taşınır.
§3 attribute ve uniform girişini,
§4–§5 vertex çıkışı ve fragment girişini kodla gösterir.
Seri içindeki yer
Vertex / fragment alt serisini şu sırayla okumanız önerilir: Veri akışı (bu sayfa) → Shader pipeline → Interpolation → Coordinate spaces. Önce «veri nereye akıyor?», sonra «pipeline’da hangi donanım adımı var?», sonra «köprü nasıl karışıyor?», en son «konum hangi uzayda?».
Her kardeş sayfa tek bir soruya odaklanır; bu sayfada yalnızca bağlantıları hatırlatıyoruz:
Shader
pipeline
raster öncesi/sonrası donanım adımlarını (derinlik, blending) listeler —
§2’deki 6. madde oraya gider. Interpolation
varying’lerin «arada» nasıl karıştığını açar;
burada yalnızca köprünün varlığı yeter. Coordinate
spaces
gl_Position öncesi matris zincirini işler; veri akışı yalnızca «konum vertex
çıkışıdır» der.
Uniforms & varyings sayfasını bitirdiyseniz, bu sayfayı doğrudan §2 özet listesiyle de okuyabilirsiniz; sözdizimi tekrarı yapılmaz. İlk kez shader yazıyorsanız §1 → §2 → §3 sırası zihinde haritayı kurar, §4–§5 örnekleri doldurur.
Aşağıdaki §2, tek bir render karesinde bu akışın özet zincirini listeler;
sonraki
bölümler her taşıyıcıyı örnek kodla açar.
Tek karede özet yol
renderer.render(scene, camera) tek bir kare çizer. O karede sahne
tarafında önce veri hazırlanır, sonra GPU her mesh için ayrı bir draw
call gönderir. Aşağıdaki liste tek bir çizim için kronolojik özetdir — «şu anda
veri nerede, hangi taşıyıcıyla okunuyor?» sorusuna cevap verir. Genel vertex / fragment rol
ayrımı
GLSL giriş · shader türleri
bölümünde de özetlenir; burada yalnızca taşıyıcılar işaretlenir.
Liste iki bölüme ayrılır: 1–2 adımlar JavaScript / CPU tarafında (shader henüz çalışmaz); 3–5 adımlar GPU’da (vertex → raster → fragment). 6. adım shader sonrası donanım işleridir.
- CPU / Three.js —
geometryattribute tamponları (konum, UV, normal) vematerial.uniformsgüncellenir. Veri GPU’ya yüklenmiş veya güncellenmiş olmalıdır; henüz vertex shader invokasyonu yoktur. - Draw call — Seçilen programa bağlanır: vertex + fragment shader, attribute tampon bağlamaları, uniform seti. Bu paket çağrı boyunca sabitlenir ( §3).
- Vertex shader — Her köşe için bir invokasyon:
attributeokunur,uniformuygulanır;gl_Position(konum çıkışı) vevarying(fragment’e taşınacak köşe verisi) yazılır ( §4). - Rasterizasyon — Üçgenler ekranda aday piksellere bölünür; köşe
varyingdeğerleri iç noktalara enterpolasyonla yayılır. Bu adım shader dosyası yazılmaz; GPU pipeline’ının «arada» adımıdır ( Interpolation). - Fragment shader — Her aday piksel için invokasyon:
enterpolasyonlu
varying+ aynı draw call’ınuniform’ları okunur; renk (gl_FragColorveyaout) üretilir ( §5).attributebu aşamada yoktur. - Sonrası — Derinlik testi, stencil, blending, framebuffer’a yazma vb. Shader pipeline konusundadır; veri taşıyıcısı değil, çıktının ekrana nasıl birleştiği sorulur.
Taşıyıcılar hangi adımda?
Aynı isimler farklı adımlarda farklı rol oynar. Listeyi ezberlemek yerine her taşıyıcı için «ilk nerede hazırlanır, nerede okunur, nerede biter?» üçlüsünü düşünün — anahtar sözcük seçimi Uniforms · kim, nerede okur? konusunda kalır.
attribute— 1. adımdageometrytamponunda güncellenir, 2. adımda draw call ile GPU’ya bağlanır; okuma yalnızca 3. adımda, köşe başına bir kez (position,uv). 5. adımda attribute yoktur — fragment’te aynı ismi kullanmak akış hatasıdır; köşe verisi önce varying ile taşınmalıdır.uniform— 1. adımdamaterial.uniformsile beslenir, 2. adımda pakete sabitlenir; 3. ve 5. adımda aynı değer okunur (matris,uTime, doku tutamacı). Köşeden köşeye değişmez; bu yüzden 4. adımda enterpolasyon görmez — paylaşılan çağrı parametresidir.varying— 3. adımda vertex’te yazılır (vUv = uv;), henüz fragment girdisi değildir. 4. adımda raster üçgen içinde karıştırır; formül Interpolation konusundadır. 5. adımda fragment aynı isimle okur — değer artık köşe değil, o pikseldeki enterpolasyonlu sonuçtur.
Kısa kontrol: köşeye özel → attribute + (gerekirse) varying; çağrıya ortak → uniform; vertex’te üretilip fragment’te lazım → varying zinciri (3 → 4 → 5).
gl_Position taşıyıcı değildir; vertex’in zorunlu konum çıkışıdır ve 4. adıma
girdi sağlar. Konumun hangi matrislerle çarpıldığı
Coordinate
spaces
konusundadır.
Haritayı pratikte kullanmak
Shader’da bir isim «tanımsız» veya yanlış görünüyorsa listede ilk geçtiği adımı işaretleyin.
Fragment’te uv arıyorsanız 5. adımda attribute olmadığını, 3–4–5
zincirinde vUv varying’inin gerekli olduğunu hatırlayın. Uniform değeri bir
kare
gerideyse sorun çoğu zaman 1. adımda — render öncesi güncelleme (
§6).
Bu sayfa 3–5. adımlardaki taşıyıcıları örnek kodla açar ( §3 giriş, §4 vertex çıkışı, §5 fragment girişi). 1–2’nin Three.js ayrıntısı §3’te; 6. adımın donanım tablosu Shader pipeline sayfasında kalır.
Giriş: attribute ve uniform
§2’deki zincirin 1–3. adımları bu bölümün
konusudur: draw call öncesi CPU tarafında veri
hazırlanır; çağrı anında GPU’ya iki tür giriş bağlanır — köşe başına attribute,
çağrı boyunca sabit uniform. varying henüz giriş değildir; vertex
çıkışı olarak §4’te ele alınır.
Draw call başladığında bu iki kanal akar. Attribute kanalları geometry tamponundan okunur; her vertex invokasyonu farklı köşe satırını görür. Uniform değerleri aynı çağrıda tüm invokasyonlarca paylaşılır — matrisler, zaman, doku tutamacı. Bildirim sözdizimi ve Three.js köprüsü Uniforms · uniform ve attribute bölümlerindedir; burada yalnızca «hangi adımda, hangi yönde?» sorulur.
Draw call öncesi: tampon ve uniform paketi
renderer.render çağrılmadan önce sahne tarafında iki hazırlık yapılır.
BufferGeometry attribute tamponları (konum, UV, normal) GPU’ya veya paylaşımlı
belleğe yüklenmiş olmalıdır; isimler shader’daki attribute bildirimleriyle
eşleşir. material.uniforms veya ShaderMaterial üzerindeki alanlar
aynı draw için shader’daki uniform isimlerine bağlanır. Tampon yapısı ve
güncelleme sıklığı
Attributes & buffer’lar
konusundadır; burada önemli olan, attribute’un «render anından önce hazır tampon» olduğudur.
Uniform güncellemesi çoğu projede kare başında yapılır (uTime,
uResolution). Değer draw call sırasında sabitlenir; vertex ve fragment aynı
paketi okur. Güncellemeyi render sonrasına bırakmak bir kare gecikme üretir (
§6).
Draw call anında: program + tampon + uniform
Tek bir mesh çizimi, GPU’ya «şu program, şu attribute bağlamaları, şu uniform seti» paketi
gönderir. Paket draw call boyunca değişmez: aynı üçgenin üç köşesi farklı
position / uv attribute değerleri görür; hepsi aynı
modelViewMatrix ve uTime uniform’unu görür. Bu ayrım,
§1’deki «seyrek vertex, yoğun
fragment»
notunun pratik karşılığıdır — köşe verisi taşınır, çağrı
parametreleri paylaşılır.
Three.js içinde WebGLRenderer bu paketi materyal ve geometry’den derler; siz
akışı shader dosyasında okursunuz: vertex’te attribute + uniform,
fragment’te yalnızca uniform (ve §5’teki enterpolasyonlu varyings). Fragment
shader geometry tamponuna doğrudan erişemez; bu kısıt akış hatası değil, pipeline kuralıdır.
Akış dilinde kısa özet
Rol tablosunun tam listesi Uniforms · kim, nerede okur? bölümündedir. Veri akışı perspektifinden yalnızca zaman çizelgesi hatırlanır:
attribute— Yalnızca vertex girişi; değer draw call öncesi yüklenen tampondan, invokasyon başına bir köşe satırı olarak okunur.uniform— Vertex ve fragment girişi; değer draw call paketinde sabit; aynı çağrıdaki tüm köşe ve piksel invokasyonları paylaşır.varying— Bu bölümde giriş değil; vertex’te yazılır, raster sonrası fragment’te okunur ( §4, Interpolation).
«Bu değer köşeye mi özel, çağrıya mı ortak?» sorusu Uniforms · üç soru ile seçim yapar; «vertex’te mi okunur?» sorusu bu sayfada cevaplanır.
Vertex’te birlikte okuma
Tipik vertex girişi şöyle okunur: position, uv,
normal attribute’tan gelir; modelViewMatrix,
projectionMatrix uniform’dan. Vertex bu iki kaynağı birleştirip
gl_Position yazar ve fragment’e taşınacak varyings atar — örnek akış aşağıdaki
editörde. Konumun hangi uzayda çarpıldığı
Coordinate
spaces
konusunda; burada yalnızca «girişler vertex’te bir araya gelir» notu yeterlidir.
Attribute yalnızca vertex girişidir. Uniform aynı draw call paketinin parçası olarak fragment’te de okunur — çoğu zaman doku, zaman veya ışık; vertex çıkışları ve fragment girişi §4–§5’te devam eder.
Vertex çıkışı: konum ve varying
Vertex shader’ın iki tür çıkışı vardır. gl_Position donanımın sabit çıktısıdır
—
clip uzayına yakın konum; rasterizer hangi piksellerin aday olacağını buna göre belirler.
Model → görüntü → projeksiyon zinciri ve uzay isimleri
Coordinate
spaces
konusundadır.
İkinci çıkış varying atamalarıdır: vUv = uv;,
vNormal = normalMatrix * normal;. Vertex’te hesaplanır, fragment’te tüketilir;
aradaki enterpolasyon GPU pipeline’ında olur — JavaScript’te karşılığı yoktur (
Uniforms · varying).
// Giriş: attribute + uniform
attribute vec3 position;
attribute vec2 uv;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
varying vec2 vUv;
void main() {
vUv = uv; // fragment'e taşınacak
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
Fragment girişi: enterpolasyonlu paket
Fragment shader çalıştığında attribute artık yoktur; enterpolasyonlu
varying değerleri ve aynı draw call’ın uniform’ları okunur. Tipik
akış: varyings ile UV/normal al → uniform ile doku/zaman/ışık al → yerel hesap → renk
çıkışı.
texture2D(uMap, vUv) bu akışın kısa özeti: uMap uniform (çağrı
başına
sabit tutamak), vUv varying (köşeden gelen koordinat). texture2D
Built-in · doku
konusundadır.
// Giriş: varying + uniform (attribute yok)
varying vec2 vUv;
uniform sampler2D uMap;
uniform float uTime;
void main() {
vec4 albedo = texture2D(uMap, vUv);
float pulse = 0.5 + 0.5 * sin(uTime);
gl_FragColor = vec4(albedo.rgb * pulse, albedo.a);
}
Akışa özel karışıklıklar
Aşağıdaki liste yanlış aşamada veri aramayı vurgular — doğru isim yanlış adımda
kullanıldığında da hata oluşur. Derleme veya link hatası yerine siyah ekran, donmuş
animasyon
veya «her pikselde aynı UV» gibi belirtiler çoğu zaman akış kopuğuna işaret eder. İsim, tür
ve
Three.js sözleşmesi
(
{ value: … }, yanlış uniform adı, attribute kanalı eksikliği)
Uniforms · sık hatalar
bölümünde kalır.
Her madde §2 zincirindeki adım numarasıyla okunabilir — «bu değer hangi adımda hazırlanır, nerede tüketilir?» sorusu akış hatalarını ayırmada yeterlidir.
- Fragment’te (5. adım)
texture2D(uMap, uv)—uvyalnızca vertex’te (3. adım) okunan attribute’tur; fragment’te geçerli değildir. Doğrusu: vertex’tevUv = uv;, 4. adımda enterpolasyon, 5. adımdatexture2D(uMap, vUv)( §5). - Zaman (
uTime) veya global ışık rengini varying ile taşımak — değer çağrı boyunca sabittir; 2. adımda paketeuniformolarak bağlanmalı, 3. ve 5. adımda doğrudan okunmalıdır. Varying köşe verisi içindir; sabit parametreyi «taşımak» gereksiz ve bazen yanlış enterpolasyon üretir ( Uniforms · üç soru, birinci madde). - Vertex’te hesaplanan değeri (dünya normali, özelleştirilmiş UV) varying ile fragment’e
göndermeyi unutmak — 3. adımda üretilen veri 4. adımdan geçmeden 5. adımda yoktur.
Belirti: fragment’te sabit veya sıfır değer; düzeltme vertex’te atama + fragment’te aynı
varyingbildirimi ( §4). - Uniform güncellemesini
rendersonrasına koymak — veri 1. adımda hazırlanmalı, 2. adımda pakete girmelidir; bir sonraki karede görünür (bir kare gecikme). Animasyon ve etkileşimli uniform’larda ilk kontrol noktası JavaScript zamanlamasıdır, shader sözdizimi değil ( §3 · draw call öncesi). mesh.position(nesne dönüşümü, sahne grafiği) ile köşepositionattribute’unu karıştırmak — ilki sahne düğümü, 2. adımdamodelMatrixuniform’u ile shader’a gider; ikincisi geometry tamponunda, 3. adımda attribute olarak okunur. İkisini aynı kavram sanmak konum kaymasına yol açar; uzay ayrımı Coordinate spaces konusundadır.
Şüphede: §2 zincirini işaretleyin
Değişken için iki nokta çizin: ilk görünüm (hangi adımda veri kaynağa bağlanır?) ve
tüketim (hangi adımda shader okur?). Örnek: doku rengi — uMap 1–2’de
uniform, vUv 3’te yazılır, 5’te texture2D ile okunur. Arada 4.
adım atlanmışsa veya 5’te hâlâ 3. adımın attribute adı kullanılıyorsa akış kırılmıştır.
Anahtar sözcük doğru ama sonuç yanlışsa önce adımı, adım doğruysa sözleşmeyi kontrol edin. Taşıyıcı–adım eşlemesi için §2 · taşıyıcılar hangi adımda? özetine dönün; bildirim ve isim listesi Uniforms · sık hatalar’da kalır.
Holodepth notu
Vertex / fragment serisini şu sırayla okuyun: Veri akışı (bu sayfa) → Shader pipeline →
Interpolation → Coordinate spaces. Yeni materyalde kağıda
attribute → varying → uniform oklarını çizin; sonra shader ve
material.uniforms tarafını doldurun.