Shader & GLSL · Sözdizimi & türler
Uniforms & varyings
CPU ile GPU arasındaki veri sözleşmesi
Shader içindeki yerel değişkenler yalnızca o invokasyon içinde yaşar ( Variables). Gerçek sahne verisi — zaman, matrisler, köşe tamponları, vertex’ten fragment’e taşınan UV — ise uniform, attribute ve varying (veya in / out) ile bildirilir. Bu sayfa, GLSL sözdizimi serisinin «dış dünya köprüsü» katmanıdır.
Tür seçimi (vec3, sampler2D …)
Vec types
ve yerleşik çağrılar (texture2D, dot …)
Built-in
functions
konusundadır; burada kimin ne zaman okuduğu ve Three.js tarafında nasıl beslendiği öne çıkar.
Genel panorama ve draw call çerçevesi GLSL giriş · depolama bölümündedir — burada shader dosyasındaki bildirim sözdizimi ve sık hatalar sabitlenir.
Neden uniform ve varying?
Three.js sahnesinde konum, renk veya zamanı JavaScript ile değiştirirsiniz:
mesh.position.set(...), material.uniforms.uTime.value = t gibi
satırlar
CPU tarafında kalır. Shader dosyası ise GPU’da çalışır; aynı bilgiyi orada
uniform, attribute veya varying (veya
GLSL ES 3.00’da in / out) anahtar
sözcükleriyle
okursunuz. İki dünya arasındaki bağ, isim ve türün bire bir eşleşmesine dayanır — buna
Holodepth’te
kısaca sözleşme denir.
Sözleşme kırıldığında davranış her zaman aynı değildir. Tür veya operatör uyumsuzluğu çoğu zaman shader derlemesinde hata verir ( Operators · hatalar). Yanlış uniform adı ise programı derletebilir ama değeri bağlamaz: ekranda sessizce yanlış renk, donmuş animasyon veya siyah kare görürsünüz. Bu yüzden özel materyal yazarken önce «hangi isim, hangi tür, hangi taraftan besleniyor?» sorusunu netleştirmek, doğrudan GLSL satırı yazmaktan önce gelir.
Shader içinde hesapladığınız ara sonuçlar ( Variables · yerel) her vertex veya fragment invokasyonunda yeniden üretilir; sahne verisi dışarıdan gelir. Uniform, attribute ve varying bu dış veriyi dosyada görünür kılar — rol ayrımı ve «kim nerede okur?» tablosu bir sonraki bölümde; burada yalnızca «neden ayrı bir katman var?» sorusuna odaklanıyoruz.
Üç karar sorusu
Yeni bir değer shader’a eklenecekse, bildirim yazmadan önce şu üç soruyu sırayla sorun. Çoğu tasarım hatası bu sırayı atlayınca ortaya çıkar; cevaplar doğrudan anahtar sözcüğe map edilir.
- Bu değer tek bir çizim çağrısı (draw call) boyunca her köşede ve
her
pikselde aynı mı? Örnek: geçen süre, ekran çözünürlüğü, ışık rengi,
projectionMatrix. Evet ise →uniform. - Değer köşeden köşeye değişiyor mu? Örnek: model uzayındaki konum, UV, vertex rengi. Evet
ise →
attribute(yalnızca vertex shader girişi). - Vertex aşamasında bilinen bir şey, fragment aşamasında da gerekli mi? Örnek:
enterpolasyonlu
UV, dünya uzayı normali. Evet ise →
varyingveyain·outçifti; vertex’te yazılır, fragment’te okunur.
Üç sorunun cevabı da «hayır» ise değer büyük olasılıkla yerel değişkendir:
float edge = smoothstep(0.45, 0.55, vUv.x); gibi bir satır dışarıdan veri
almaz, yalnızca
o invokasyonda hesaplanır. Attribute’u fragment’te okumaya çalışmak veya zamanı varying ile
taşımak
gibi karışıklıklar bu ayrımı netleştirince kaybolur.
Çizim çağrısıyla ilişki
renderer.render(scene, camera) her karede birden fazla mesh çizer; her mesh +
materyal
kombinasyonu GPU’ya ayrı bir çağrı gönderir. Uniform değerleri o çağrı süresince sabitlenir
— aynı
üçgende köşe A ile köşe B aynı uTime değerini görür. Sonraki mesh’e
geçildiğinde
modelMatrix yeniden bağlanabilir. Draw call ve depolama sınıflarının genel
tablosu
GLSL giriş · depolama
bölümündedir; bu sayfada çağrı kavramı yalnızca «uniform neden çağrı başına sabit?» sorusunu
cevaplamak için anımsatılır.
Sessiz hatalar ve isim listesi
Varying eksikliği çoğu zaman program link aşamasında patlar; uniform ismi yanlışsa hata görünmeyebilir. Materyal başına kısa bir liste tutmak — uniform adları, attribute kanalları, varying çiftleri — diff okunurluğunu artırır. Sık görülen kalıplar §7’de toplanır; seri sonunda Holodepth notu üç sütunlu planı özetler.
Üç rol: yerel değişkenden farkı
Önceki bölüm «hangi anahtar sözcüğü seçmeliyim?» sorusuna cevap verir; burada seçimin arkasındaki rol sabitlenir: veri shader’ın içinde mi üretiliyor, CPU’dan mı geliyor, yoksa vertex’ten fragment’e mi taşınıyor? Variables · arayüz bölümünde yerel/global ile arayüz ayrımı tanıtılmıştı — burada aynı ayrımı üç isimle somutlaştırıyoruz; bildirim örnekleri ve Three.js köprüsü sonraki bölümlerde kalır.
Kısa kural: float t = 0.5; gibi yerel veya global shader değişkenleri programın
kendi hesabıdır; uniform, attribute ve varying ise
dış dünyayla veya pipeline aşamaları arasıyla konuşan katmandır. JavaScript’teki
BufferAttribute ile shader’daki attribute vec3 position; aynı
isimle
eşleşir ama farklı katmanlardadır — tampon yapısı
Attributes & buffer’lar
konusunda, shader tarafındaki bildirim bu sayfada.
Kim, nerede okur?
Aşağıdaki özet, materyal yazarken «bu değişken hangi dosyada geçer?» sorusuna hızlı cevap verir. Derin enterpolasyon ve doku örneği §5 ile §3–§4’te açılır; genel draw call tablosu GLSL giriş · depolama bölümündedir.
uniform— Vertex ve fragment shader’da okunabilir; tek bir çizim çağrısı boyunca değişmez. Zaman (uniform float uTime;), dönüşüm (uniform mat4 projectionMatrix;), doku tutamacı (uniform sampler2D uMap;) bu gruptadır. Aynı üçgenin tüm köşeleri ve tüm pikselleri aynıuTimedeğerini görür.attribute— Yalnızca vertex shader girişi; her invokasyon bir köşeyi temsil eder. Konum (attribute vec3 position;), UV
(attribute vec2 uv;), normal gibi kanallar GPU tamponundan gelir. Fragment shader bu isimlere erişemez; ihtiyaç varsa değer önce varying ile taşınır.varying— Vertex’te yazılır, fragment’te aynı isim ve türle okunur; aradaki değerler rasterizer tarafından enterpolasyonla karıştırılır. Tipik kalıp:varying vec2 vUv;— vertex’tevUv = uv;, fragment’tetexture2D(uMap, vUv). Enterpolasyonun sezgisi ve perspektif notu §5’te kalır.
Yerel değişkenle karıştırmayın
Üç rol, yerel değişkenin yapamadığı işleri üstlenir. Örneğin fragment’te
vec3 lit = baseColor * ndotl; yalnızca o pikselde hesaplanır; komşu piksel bu
lit değerini görmez. Buna karşılık uniform vec3 uLightColor; tüm
fragment’lerde ortaktır ama fragment içinde uLightColor = … ile yeniden
atanamaz —
uniform salt okunur giriştir.
«Köşedeki UV’yi fragment’te kullanmak» isteği de yerel değişkenle çözülmez: attribute
doğrudan
fragment’te yoktur; vertex’te vUv = uv; yazıp varying ile aktarmak gerekir.
Zamanı
veya ışık rengini varying ile taşımak yerine uniform kullanmak genelde doğrudur — değer
zaten
çağrı boyunca sabittir (
§1 · üç soru).
Global shader değişkeni de her invokasyonda paylaşılan «program hafızası» değildir; paralel GPU çalışması nedeniyle güvenilir paylaşım için uniform veya doku kullanılır. Her kare değişen sabitler için global yerine uniform tercih edin ( Variables · global).
GLSL ES 3.00: in
ve
out
WebGL2 ve GLSL ES 3.00 shader’larında varying yerine
vertex’te out vec2 vUv;, fragment’te in vec2 vUv; yazılır; anlam
değişmez, yalnızca sözdizimi ayrışır. Attribute tarafında in vec3 position;
gibi
girişler de aynı nesneyi ifade eder — Three.js hâlâ buffer attribute isimlerini eşleştirir.
Holodepth örnekleri çoğu zaman klasik attribute / varying çiftini
gösterir; WebGL2 projelerinde karşılığı bire bir çevrilebilir. flat niteliği,
perspektif enterpolasyon ve varyings’in sınırları
GLSL giriş · varying
ile
§5’te işlenir — burada yalnızca «aynı
köprü, farklı anahtar sözcük» notu yeterlidir.
Uniform
§2’de uniform’ın vertex ve fragment’te okunabildiği ve çizim çağrısı boyunca sabit kaldığı özetlendi. Bu bölümde odak, shader dosyasında nasıl bildirildiği ve Three.js tarafında nasıl beslendiğidir — attribute ve varying §4–§5’e bırakılır.
Pratikte uniform, «bu mesh bu materyalle çizilirken herkesin gördüğü ortak parametre»
demektir:
geçen süre (uTime), tuval boyutu (uResolution), ışık rengi, kamera
ve
model matrisleri (projectionMatrix, modelMatrix), doku tutamacı (
sampler2D uMap). Köşe başına değişen konum veya UV burada değildir; onlar
attribute
ve ardından varying ile gelir. Draw call çerçevesi
§1’de; Three.js’te
material.uniforms kalıbı
§6’da tamamlanır.
Bildirim ve tür
Bildirim kalıbı sabittir: uniform + tür + isim + ;. Örnekler:
uniform float uTime;, uniform vec2 uResolution;,
uniform mat4 modelMatrix;, uniform sampler2D uDiffuse;. Tür seçimi
Vec types kurallarıyla
aynıdır —
shader tarafında kaç bileşen beklediğiniz, JavaScript’te gönderdiğiniz değerin şekliyle
eşleşmelidir.
Skaler ve vektörlerde Three.js çoğu zaman karşılık gelen sınıfları kabul eder:
uniform float ↔ sayı, uniform vec2 ↔ Vector2 veya iki
elemanlı
dizi, uniform vec3 ↔ Vector3. Bileşen sayısı uyuşmazsa derleme
veya bağlama
aşamasında hata alırsınız (
boyut uyumu,
Operators · hatalar).
Renk için
uniform vec3 ile uniform vec4 karıştırmak sık görülen bir tuzaktır
— alpha
kanalı gerekiyorsa dörtlü tür seçin.
uniform mat4 vertex shader’da konum taşımada kullanılır; ifade
projectionMatrix * modelViewMatrix * vec4(position, 1.0) hem matris
uniform’larına hem de
mat4 × vec4 kuralına
dayanır (
Operators ·
matris). Matris
uniform’larının ayrıntılı listesi aşağıda; önce fragment tarafında zaman ve doku ile çalışan
kısa
örneğe bakın.
uniform float uTime;
uniform vec2 uResolution;
uniform sampler2D uDiffuse;
void main() {
vec2 uv = gl_FragCoord.xy / uResolution;
float pulse = 0.5 + 0.5 * sin(uTime);
vec4 tex = texture2D(uDiffuse, uv);
gl_FragColor = vec4(tex.rgb * pulse, tex.a);
}
Matris uniform’ları
Three.js standart materyalleri modelViewMatrix, projectionMatrix,
normalMatrix gibi isimleri otomatik bağlar; özel shader yazarken aynı isimleri
kullanmak en az sürtünmeyi verir. Vertex shader’da
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); satırı
bu
uniform’lara dayanır — isimleri shader’da değiştirirseniz materyal veya
onBeforeCompile tarafında da güncellemeniz gerekir. Normal dönüşümü için
normalMatrix ayrı bir uniform olarak gelir; vektör matematiği
Built-in ·
vektör
ile birlikte kullanılır.
sampler2D ve doku
sampler2D bir uniform türüdür: GPU’ya hangi dokunun bağlanacağını söyler,
piksel
verisinin kendisi değildir. Fragment’te örnekleme
texture2D(uDiffuse, vUv) şeklinde yapılır — texture2D sözdizimi
Built-in ·
doku
konusundadır. Burada kritik nokta isim eşleşmesidir:
uniforms.uDiffuse = { value: myTexture } ↔ shader’daki
uniform sampler2D uDiffuse;. UV çoğu zaman varying ile gelir (
§5); tam ekran efektlerinde bazen
gl_FragCoord / uResolution ile de hesaplanır.
Güncelleme sırası
Uniform değeri çizimden önce yazılmalıdır:
material.uniforms.uTime.value = clock.getElapsedTime(); satırı
renderer.render(...) çağrısından önce çalışır. Sonradan yapılan atama çoğu
zaman
bir sonraki karede görünür. «Hareket yok» şikâyetinde önce doğru materyal örneğine ve isim
yazımına bakın (
§7). Aynı Vector3 veya
doku
referansını birden fazla materyal paylaşıyorsa beklenmedik yan etki olabilir — gerekirse her
materyale
ayrı { value: … } nesnesi verin.
İsimlendirme: u öneki
Holodepth ve Three.js örneklerinde u öneki uniform’ları ayırt eder (
Variables ·
isimlendirme).
Zorunlu değil; tutarlılık diff okunurluğunu artırır.
Attribute
§3 çizim çağrısı boyunca sabit veriyi
anlattı; attribute ise köşe başına değişen tampon verisidir. Yalnızca vertex
shader’da
okunur — her GPU invokasyonu bir köşeyi temsil eder. Fragment shader’da
attribute
bildiremezsiniz; piksel başına farklı değer ihtiyacı
§5 ile çözülür.
Three.js tarafında kanal adı ile shader ismi bire bir eşleşmelidir:
geometry.setAttribute('uv', uvAttribute) ↔ shader’da
attribute vec2 uv;. JavaScript’teki BufferAttribute GPU tamponunu
doldurur; shader’daki attribute satırı o tamponun vertex girişidir. Tampon
oluşturma,
güncelleme ve itemSize
Attributes & buffer’lar
konusundadır — burada yalnızca «isim ve tür sözleşmesi» sabitlenir.
Standart kanallar
BufferGeometry ve glTF export’ları çoğu mesh’te aynı kanal isimlerini kullanır.
Özel geometri yazarken de bu isimlere uymak, Three.js ve örnek shader’larla uyumu
kolaylaştırır.
position— Model (veya lokal) uzayda köşe konumu; shader’da geneldeattribute vec3 position;.gl_Positionhesabına girer; uniform matrislerle birlikte kullanılır ( §3 · matris).uv— Doku koordinatı;attribute vec2 uv;. Fragment’te doğrudan yoktur — vertex’tevUv = uv;yazılıp varying ile taşınır; doku örnekleme §5 ve Built-in · doku ile birleşir.normal— Yüzey normali;attribute vec3 normal;. Işık için çoğu zamanvNormal = normalMatrix * normal;ile görüş uzayına çevrilip varying olarak gönderilir ( Built-in · vektör).
Renk, teğet (tangent) veya özel veri kanalları da aynı mantıkla eklenir:
geometry’de
isim, shader’da uygun attribute vecN türü. Kanal başına bileşen sayısı
itemSize ile shader türü uyumlu olmalıdır — üç sayı gönderip
attribute vec2 okumak beklenmedik sonuç üretir (
Attributes · itemSize,
Vec types).
Fragment’te okunamaz
texture2D(uMap, uv) fragment shader’da geçersizdir; doğru zincir
attribute vec2 uv → vertex’te vUv = uv → fragment’te
texture2D(uMap, vUv). Attribute’u «her pikselde farklı UV» sanmak sık başlangıç
hatasıdır — köşeler farklıdır, piksel değerleri rasterizer enterpolasyonu ile
varying üzerinden gelir (
§2 · üç rol).
Aşağıdaki vertex.glsl örneği üç standart kanalı uniform matrislerle
birleştirir;
vUv ve vNormal fragment dosyanızda aynı isimle bildirilmelidir.
attribute vec3 position;
attribute vec2 uv;
attribute vec3 normal;
varying vec2 vUv;
varying vec3 vNormal;
void main() {
vUv = uv;
vNormal = normalMatrix * normal;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
Varying ve enterpolasyon
§4 attribute’ların yalnızca
vertex’te
okunduğunu gördük; fragment’in ihtiyaç duyduğu köşe verisi varying (veya
GLSL ES 3.00’da out / in) ile taşınır.
Vertex
shader’da atadığınız değer, fragment shader’da aynı isim ve türle okunur; aradaki adımı
GPU’nun
rasterizer’ı doldurur.
Üçgen çizildikten sonra köşe değerleri iç noktalara enterpolasyonla karıştırılır: bir köşede
kırmızı, karşıda mavi renk taşıyorsanız yüzey ortasında mor ton görürsünüz. UV, normal veya
özel
veri için de aynı mantık geçerlidir — «köşede keskin, yüzeyde yumuşak» geçişlerin çoğu
varying +
enterpolasyon kombinasyonundan gelir. Zaman veya ışık rengi gibi çağrı boyunca sabit veriler
buraya
değil, uniform ile gelir (
§1 · üç soru).
Çift taraflı bildirim
Vertex ve fragment dosyalarında aynı bildirim satırı gerekir — örneğin her iki tarafta da
varying vec2 vUv;. Vertex’te vUv = uv; yazılır; fragment’te
yalnızca
okunur. İsim veya tür uyuşmazlığı (vec2 vs vec3) program link
aşamasında
hata verir; bu, uniform ismindeki sessiz hatadan farklı olarak genelde konsolda görünür (
§1 · sessiz hatalar).
in / out sözdizimi
§2’de özetlendi; WebGL2’de
vertex’te
out vec2 vUv;, fragment’te in vec2 vUv; çifti aynı köprüdür.
Three.js özel
materyallerinde klasik varying yazımı yaygındır.
Perspektif enterpolasyon
WebGL, clip uzayından sonra UV ve renk gibi varyings için perspektif düzeltmeli
enterpolasyon
uygular. Eğik 3B yüzeylerde doku hafif «akıyor» gibi görünebilir; bu çoğu zaman hata değil,
beklenen davranışa yakındır. Tam ekran 2B quad veya ortografik sahnelerde fark nadiren
hissedilir.
Üçgen başına tek değer taşımak isteyen kanallar için flat niteliği ve sınırlar
GLSL giriş · varying
bölümündedir — burada yalnızca «köşe → piksel karışımı» sezgisi yeterlidir.
Normal, UV ve doku zinciri
varying vec3 vNormal fragment’te genelde normalize(vNormal) ile
ışık
hesabına girer; vertex tarafında çoğu zaman
vNormal = normalMatrix * normal; yazılır (
§4 · vertex örneği,
Built-in ·
vektör).
varying vec2 vUv ise doku örneklemesi için kullanılır: fragment’te
texture2D(uMap, vUv) — uMap uniform’ı §3’te,
texture2D
Built-in ·
doku
konusundadır. Varying üzerinde swizzle ve tür kuralları
Vec types /
Operators ile aynıdır;
yeni tür
eklemeden önce kanalın gerçekten vertex’te üretilip fragment’e taşınması gerektiğini
doğrulayın.
Aşağıdaki fragment örneği yalnızca vUv ve doku uniform’ını gösterir; tam vertex
+
fragment çifti
GLSL giriş · ilk örnek
ile §4 vertex kodunu birleştirin.
varying vec2 vUv;
uniform sampler2D uMap;
void main() {
vec4 albedo = texture2D(uMap, vUv);
gl_FragColor = albedo;
}
Three.js köprüsü
§3–§5 shader dosyasında uniform, attribute ve varying
bildirimlerini işledi; bu bölüm aynı sözleşmenin Three.js tarafındaki karşılığını toplar.
Standart materyaller (MeshStandardMaterial vb.) çoğu matris ve ışık uniform’ını
sizin
adınıza günceller — kaynak kodu görmezsiniz ama aynı köprü mantığı geçerlidir. Tam kontrol
için
ShaderMaterial veya mevcut materyale küçük eklemeler için
onBeforeCompile
kullanırsınız; her iki yolda da shader’daki isimler JavaScript tarafıyla bire bir
eşleşmelidir.
Genel ShaderMaterial panoraması ve ilk bağlama adımları GLSL giriş (Three.js) bölümündedir — burada yalnızca uniform / attribute / varying’in nereden yazıldığı özetlenir; GLSL sözdizimi serisinin pratik kapanışı sayılır.
Uniform nesnesi
ShaderMaterial oluştururken uniforms anahtarı bir sözlük bekler;
her giriş
{ value: … } sarmalayıcısı ister — doğrudan uTime: 0 yazmak
çalışmaz. Kare
döngüsünde çoğu zaman uniforms.uTime.value = t; ile güncellersiniz; atama
renderer.render öncesinde olmalıdır (
§3 · güncelleme sırası).
Skaler,
Vector2 / Vector3, Matrix4 ve Texture
örnekleri
shader türüyle eşleşmelidir (
§3 · bildirim ve tür).
Aynı uniforms nesnesini materyale verip döngüde .value alanlarını
değiştirmek yaygın bir kalıptır — aşağıdaki örnek bunu gösterir. Paylaşılan referanslar (tek
Vector3 örneği) beklenmedik yan etki verebilir; gerekirse materyal başına ayrı
{ value: new THREE.Vector3() } kullanın.
import * as THREE from 'three';
const uniforms = {
uTime: { value: 0 },
uResolution: { value: new THREE.Vector2() },
uMap: { value: null },
};
const material = new THREE.ShaderMaterial({
uniforms,
vertexShader: document.getElementById('vs').textContent,
fragmentShader: document.getElementById('fs').textContent,
});
function animate() {
uniforms.uTime.value = performance.now() * 0.001;
renderer.render(scene, camera);
}
Geometry attribute’ları
BufferGeometry üzerinde tanımladığınız kanal adları, vertex shader’daki
attribute isimleriyle eşleşir: geometry.setAttribute('uv', …) ↔
attribute vec2 uv;. BoxGeometry gibi hazır geometriler çoğu zaman
position, uv ve normal kanallarını zaten içerir —
özel
shader yazarken bu isimlere uymak en az sürtünmeyi verir. Tampon doldurma, güncelleme ve
itemSize
Attributes & buffer’lar
konusundadır; shader tarafındaki eşleşme kuralı
§4’te sabitlendi.
mesh.position veya mesh.rotation JavaScript nesne dönüşümüdür;
shader’daki
attribute vec3 position köşe tamponudur — ikisi farklı katmandadır. Model
hareketini
genelde uniform matrisler (modelMatrix, modelViewMatrix) taşır;
köşe
konumları geometri tamponunda kalır.
Varying sizin sorumluluğunuzda
Three.js, ShaderMaterial için otomatik vUv veya
vNormal
üretmez. Vertex ve fragment shader kaynaklarınızda aynı varying (veya WebGL2’de
out / in) satırlarını siz yazarsınız; vertex’te atama, fragment’te
okuma
(
§5,
§4 · vertex örneği). Enterpolasyon
tamamen GPU
pipeline’ında olur — JavaScript’te «varying güncelle» diye bir API yoktur.
onBeforeCompile
Mevcut MeshPhysicalMaterial gibi bir materyalin shader kaynağı derlenmeden
hemen önce
değiştirilmek istendiğinde material.onBeforeCompile = (shader) => { … }
kullanılır.
Küçük bir renk karışımı veya ek uniform eklemek için uygundur; callback içinde
shader.uniforms.uMyEffect = { value: 1.0 }; yazılır ve GLSL parçası kaynağa
enjekte edilir — shader’da yine uniform float uMyEffect; bildirimi gerekir.
Varying veya
attribute eklemediğiniz sürece Three.js mevcut köprüyü korur; yeni köprü kanalları yine
sizin
shader metninizde tanımlanmalıdır.
Tam ekran efekt, çok dosyalı GLSL veya sıfırdan pipeline için ayrı
ShaderMaterial çoğu
zaman daha okunaklıdır. İki yolu aynı projede karıştırırken uniform isimlerinin
çakışmadığından emin
olun.
Son hatırlatma: döngüdeki yerel let t = … veya const color = …
değişkenleri
GPU’ya otomatik gitmez — shader’a veri yalnızca material.uniforms,
geometry.attributes ve kendi yazdığınız vertex/fragment çifti üzerinden akar.
Karışıklık
çoğu zaman «JS’te değişkeni güncelledim ama shader görmüyor» şikâyetinde ortaya çıkar (
§7).
Sık hatalar
Bu sayfa boyunca uniform, attribute ve varying ayrı ayrı tanıtıldı; sahada hata çoğu zaman «yanlış katmana veri koymak» veya «isim/tür sözleşmesini kırmak» şeklinde görünür. Bazıları derleme veya link aşamasında patlar; uniform ismi gibi bazıları ise programı çalıştırıp sessizce yanlış sonuç üretir ( §1 · sessiz hatalar). Aşağıdaki başlıklar teşhis sırasına yakın bir kontrol listesi sunar — her madde ilgili bölüme link verir, aynı metni tekrar etmez.
İsim uyumsuzluğu
Belirti: animasyon donuk, renk hep siyah veya varsayılan, doku görünmüyor — konsol bazen
temiz.
Tipik örnek: shader’da uniform float uTime;, JavaScript’te
material.uniforms.time veya uTIME. WebGL eşleşmeyen ismi bağlamaz;
değer
sıfırda kalabilir. Büyük/küçük harf duyarlıdır; vertex ve fragment dosyaları da aynı yazımı
ister.
Çözüm: materyal başına tek liste (uniform adları, attribute kanalları, varying çiftleri);
shader ve
uniforms sözlüğünde bire bir aynı string. onBeforeCompile içinde
eklenen
uniform’lar için hem shader.uniforms.uX hem GLSL bildirimi gerekir (
§6).
Varying tek tarafta veya tür uyumsuz
Belirti: program link hatası — «varying … not declared» benzeri mesajlar. Vertex’te
varying vec2 vUv; varken fragment’te eksik satır veya vec3 yazmak
en sık
nedenlerdir. WebGL2’de out / in çiftinde de isim ve tür bire bir
aynı olmalıdır
(
§5 · çift bildirim).
Çözüm: iki shader dosyasını yan yana açın; varying listesini satır satır eşleştirin. Yeni kanal eklerken önce §1’deki üç soruyu sorun — gerçekten varying mi, yoksa uniform mu?
Attribute’u fragment’te kullanmak
Belirti: derleme hatası veya «uv undeclared» — fragment’te texture2D(uMap, uv)
yazmak.
uv yalnızca vertex shader girişidir (
§4). Doğru zincir:
attribute vec2 uv → vertex’te vUv = uv → fragment’te
texture2D(uMap, vUv).
İlgili karışıklık: zaman veya ışık rengini varying ile taşımaya çalışmak — çağrı boyunca
sabit
veriler uniform olmalıdır (
§1 · üç soru).
Tür ve boyut
Belirti: shader derlemesi reddedilir veya mesh garip deforme olur. Örnekler:
uniform vec2’ye üç bileşen göndermek; shader’da vec3 + vec2
yazmak;
tamponda itemSize: 2 iken attribute vec3 position; okumak. İlk
ikisi
Operators · hatalar ve
Vec types · boyut
konusundadır; üçüncüsü
Attributes · itemSize
ile §4’te özetlendi.
Çözüm: her kanal için «tampon kaç bileşen? shader hangi vecN? JS hangi sınıf?»
üçlüsünü
yazın; doku için sampler2D + Texture eşleşmesini §3 ile kontrol
edin.
Güncelleme zamanı ve paylaşılan referans
Belirti: uniform «bir kare gecikmeli» veya iki materyal beklenmedik şekilde aynı rengi
paylaşıyor.
renderer.render çağrısından sonra yazılan
uniforms.uTime.value çoğu
zaman bir sonraki karede görünür (
§3 · güncelleme). İki
ShaderMaterial aynı Vector3 veya Texture referansını
paylaşıyorsa biri güncellendiğinde diğeri de değişir.
Çözüm: güncellemeyi render öncesine alın; paylaşım istemiyorsanız materyal başına
{ value: new THREE.Vector3() } veya dokunun kopyası. Yerel let
değişkeni
shader’a otomatik gitmez — veri yalnızca material.uniforms ve geometry
attribute’ları
üzerinden akar (
§6).
Hızlı teşhis sırası
Sorun çıktığında sırayla: (1) Konsolda derleme / link hatası var mı? (2) İsim listesi üç
dosyada
(JS, vertex, fragment) uyumlu mu? (3) Veri doğru katmanda mı — uniform / attribute /
varying? (4) Tür
ve itemSize eşleşiyor mu? (5) Uniform güncellemesi render öncesinde mi? Çoğu
vaka bu
beş adımda kapanır; kalan edge case’ler için
GLSL giriş · depolama
geniş tabloya bakın.
Holodepth notu
GLSL sözdizimi serisini bitirirken şu sırayı koruyun: tür ve paket (Vec types) → işlem
(Operators) → yerleşik (Built-in) → veri köprüsü (bu sayfa). Yeni materyal yazarken önce
kağıt
üzerinde üç sütun çizin: uniform listesi, attribute listesi, varying listesi — sonra shader
ve
material.uniforms tarafını doldurun. §7’deki teşhis listesini projeye
yapıştırıp ilk
hatada işaretlemek, uzun debug oturumlarını kısaltır.