holodepth

Shader & GLSL · Sözdizimi & türler

Built-in functions (GLSL yerleşik fonksiyonlar)

Operatörlerden sonra GPU’nun standart kütüphanesi

GLSL, shader içinde kullanabileceğiniz zengin bir yerleşik fonksiyon seti sunar: trigonometri, vektör geometrisi, renk karışımı, eşik fonksiyonları ve doku örnekleme. Bunlar dilin parçasıdır — harici kütüphane import etmezsiniz; derleyici ve GPU bu isimleri tanır.

Operatörler (+, *, == …) Operators konusunda; vektör paketleri ve dot / mix gibi beşlinin kavramsal özeti Vec types · vektör matematiği bölümünde — burada fonksiyon çağrısı sözdizimi, kategoriler ve fragment shader pratiği öne çıkar.

Genel dil panoraması ve sampler2D çerçevesi GLSL giriş · tipler sayfasındadır; uniform ile doku bağlama Uniforms & varyings konusuna bırakılır.

Neden yerleşik fonksiyon?

Operatörler ifadeleri birleştirir; yerleşik fonksiyonlar hazır işlemler sunar — normalize etmek, iki renk arasında geçiş, dokudan örnek almak gibi. GPU bu çağrıları donanıma yakın yollarla uygular; kendi sqrt veya sin implementasyonunuzu yazmanız gerekmez.

JavaScript’te Math.sin düşünün; GLSL’de sin doğrudan shader gövdesinde çağrılır. Fark: türler katıdır — sin(vec3) bileşen bazında sonuç üretir (vektör girdi → vektör çıktı), dot(vec3, vec3) ise skaler döndürür.

Dört pratik kategori

Resmi GLSL spesifikasyonu onlarca yerleşik isim listeler; Holodepth’te shader yazarken dört grup çoğu efekti kapsar. Aşağıdaki özet sayfanın geri kalanına yol haritasıdır — her madde ilgili bölümde açılır; burada yalnızca «hangi problem hangi aileye düşer?» sorusuna cevap verilir.

  • Zaman ve dalga (sin, cos, fract, mod): uniform float uTime ile nefes alan parlaklık, dalgalı desen veya tekrarlayan şeritler. sin / cos periyodik; fract ve mod «döngü içinde neredeyim?» sorusuna yanıt verir. Operatörlerle birleşince (0.5 + 0.5 * sin(uTime)) skaler maske üretilir. Ayrıntı §2 · Zaman ve dalga.
  • Vektör geometrisi (dot, cross, normalize, length): vec3 paketleriyle 3B sahne — ışık yönü, yüzey normali, bakış vektörü. dot skaler döndürür (parlaklık); normalize vektör döndürür (birim yön). Bu grup matris × vektör ile birlikte düşünülür; kavramsal özet Vec types · vektör matematiği bölümünde — burada çağrı kalıpları §3’te kalır.
  • Renk ve maske (mix, step, smoothstep, clamp): Fragment shader’ın «prosedürel boya» seti. Operatörler koşul üretir ( karşılaştırma); bu fonksiyonlar koşulu renge çevirir — if yerine mix(colorA, colorB, mask) tercihinin nedeni budur. Gradyan bant, yumuşak kenar ve değer sıkıştırma bu gruptadır. Ayrıntı §4, Operators · mix.
  • Doku (texture2D veya profilde texture): sampler2D tutacısı + vec2 UV ile bitmap’ten renk okuma. Aritmetik veya mix ile aynı değil — sampler üzerinde doğrudan + yapılmaz; önce texture2D(uMap, vUv) ile vec4 örneklenir, sonra maske veya karışım uygulanır. Uniform atama ve Three.js malzeme köprüsü Uniforms & varyings konusundadır; shader içi kalıp §5 · Doku.

Efekt tasarlarken önce kategoriyi seçin: «zamanla değişen skaler mi, 3B yön mü, ekran maskesi mi, dosyadan renk mi?» — sonra ilgili bölüme geçin. §6’daki tuzaklar tüm gruplarda geçerli olan hassasiyet ve tür uyumu konularını toplar.

Zaman, dalga ve yardımcılar

uniform float uTime;

void main() {
  float wave = 0.5 + 0.5 * sin(uTime + vUv.x * 6.28);
  float bands = fract(vUv.y * 8.0);
  gl_FragColor = vec4(vec3(wave * bands), 1.0);
}

sin / cos radyan alır; uTime uniform’ı ile nefes alan parlaklık, dalga veya titreşim üretilir. fract kesirli kısmı verir — tekrarlayan şeritler; mod benzer ama başlangıç ofseti farklıdır.

pow, sqrt, abs, floor, ceil skaler ve vektörde overload edilir: girdi türü çıktı türünü belirler. min / max iki değerin küçük/büyük olanını seçer — maske birleştirmede sık görülür.

Vektör geometrisi

§1’deki «vektör geometrisi» ailesi, vec3 paketleriyle 3B sahne mantığını shader satırına taşır — normal, ışık yönü, bakış vektörü. Kavramsal tanımlar ve «neden skaler / vektör döner?» özeti Vec types · vektör matematiği bölümünde; burada çağrı kalıpları, tipik uniform/attribute bağlamı ve üretim tuzakları öne çıkar.

dot(a, b) — iç çarpım

İki eş boyutlu vektör alır; sonuç float (skaler). Klasik aydınlatmada float ndotl = max(dot(normal, lightDir), 0.0); — yüzey normali ile ışık yönü ne kadar hizalıysa parlaklık o kadar yüksek. Fresnel ve rim ışığı yaklaşımları da dot ile başlar; ayrıntılı materyal modelleri ileri konularda.

a ve b aynı türde olmalıdır (vec3 ile vec3); vec3 ile vec2 derleme hatasıdır ( Operators · boyut).

cross(a, b) — çapraz çarpım

Yalnızca vec3 ile tanımlıdır; sonuç yine vec3’tür ve her iki girdiye dik bir vektör üretir. İki kenar vektöründen yüzey normali türetmek veya teğet uzayında (TBN) üçüncü eksen bulmak için kullanılır — normal haritalama shader’larında sık görülür.

Sıra önemlidir: cross(a, b) ile cross(b, a) zıt yönlüdür. Kavramsal not Vec types · cross bölümünde; burada yalnızca «üçüncü eksen üret» kullanımı sabitlenir.

length ve distance

length(v) tek noktanın kökenden uzaklığını verir; distance(a, b) iki nokta arası mesafedir — matematiksel olarak length(a - b) ile aynı düşünce. Girdi vec2vec4 olabilir; sonuç her zaman skalerdir.

normalize öncesi «vektör çok kısa mı?» kontrolü veya efekt mesafesine göre sönümleme için kullanılır. Sıfıra yakın uzunluk, sonraki bölmede NaN üretebilir — bu yüzden normalize ile birlikte düşünülür.

normalize(v) — birim yön

Vektörü aynı yönde tutup uzunluğu 1 yapar. Işık yönü, bakış vektörü ve dünya uzayına taşınmış normal için standart çağrıdır. Vertex tarafında normal çoğu zaman normalMatrix * normal ile dönüştürülür, ardından normalize edilir ( Vec types · normal taşıma, dot öncesi zorunlu adım).

Sıfır vektörde bölme tanımsızdır; üretimde v / max(length(v), 1e-6) veya benzeri epsilon koruması görülür ( Vec types · normalize).

reflect ve refract

reflect(I, N) gelen yön I ve yüzey normali N ile yansıma yönü üretir; ayna ve su yüzeyi yaklaşımlarında. refract kırılma yönü — cam ve şeffaf materyaller; indis parametresi (eta) gerekir. Holodepth’te temel seride yalnızca isimleri sabitlenir; PBR ve ileri materyal konularında açılır.

vec3 n = normalize(normalMatrix * normal);
vec3 l = normalize(lightDir);
float ndotl = max(dot(n, l), 0.0);
vec3 diffuse = baseColor * ndotl;

Bu dörtlü çoğu Lambert tabanlı fragment shader’ın çekirdeğidir — renk karışımı ve maske §4’te eklenir.

Renk, maske ve eşik

§1’deki «renk ve maske» ailesi, fragment shader’da ekrana giden rengi doğrudan şekillendirir — gradyan, şerit, yumuşak kenar, iki malzeme arası geçiş. §3’teki vektör geometrisi ışık hesabına odaklanır; burada sonuç çoğu zaman «kaç parlak / hangi renk» sorusuna cevap verir.

Operatörden renge: neden if değil mix?

Operators · karşılaştırma ve mantık (&&, ||) koşul üretir — «bu piksel şu bölgede mi?». Yerleşik fonksiyonlar bu koşulu renge ve desene çevirir: 0–1 arası maske, iki rengin karışımı, yumuşak geçiş.

Fragment shader’da if (vUv.x > 0.5) yazmak mümkündür; fakat GPU’da dal başına farklı yürütme yolları pahalı olabilir.
mix(colorA, colorB, mask) tek ifadede her iki rengi de hesaplar — çoğu prosedürel efekt için kabul edilebilir ve okunur kalır ( Operators · mix).

mix — doğrusal karışım

mix(a, b, t): t == 0.0 tamamen a, t == 1.0 tamamen b. a ve b aynı türde olmalıdır — vec3 renk karışımı, vec2 ofset interpolasyonu. t skaler veya vektör olabilir; mix(colorA, colorB, vUv.x) yatay gradyan üretir.

Kavramsal özet ve t vektör varyantları Vec types · mix bölümünde; burada fragment’te «iki sabit renk + maske» kalıbı öne çıkar.

step ve smoothstep — eşik ve yumuşak geçiş

step(edge, x) sert basamak: x < edge → 0, aksi → 1. Keskin şerit veya pikselleşmiş maske için. smoothstep(e0, e1, x) iki eşik arasında 0’dan 1’e yumuşak S-eğrisi — gradyan bantları, kenar yumuşatma, vignette kenarları.

Çoğu zaman smoothstep çıktısı doğrudan mix’in üçüncü argümanı olur; step ise «açık / kapalı» iki durumlu maske için yeterlidir. §2’deki sin dalgası ile birleştirilerek nefes alan bantlar da üretilebilir.

clamp ve yardımcılar

clamp(x, lo, hi) değeri aralıkta tutar — renk kanallarını [0, 1]’e sıkıştırmak, aşırı parlaklığı kesmek için. min / max iki değerin küçük/büyük olanını seçer; birden fazla maskeyi birleştirirken sık görülür (min(maskA, maskB)).

float mask = smoothstep(0.3, 0.7, vUv.y);
vec3 col = mix(vec3(0.05), vec3(0.95), mask);
col = clamp(col, 0.0, 1.0);
// if (vUv.y > 0.5) col = vec3(0.95);  // çoğu efektte mix tercih edilir

GLSL giriş · altın kurallar listesindeki mix / smoothstep maddesi bu pratiğin kısa hatırlatmasıdır — tam imza listesi resmi spesifikasyondadır; Holodepth’te desen yazımı için yukarıdaki zincir yeterlidir.

Doku örnekleme

sampler2D opak bir tutacıdır — üzerinde aritmetik yapılmaz; yalnızca texture fonksiyonlarına verilir ( GLSL giriş · sampler2D). Koordinat çoğu zaman varying vec2 vUv ( Vec types · vec2).

uniform sampler2D uMap;
varying vec2 vUv;

void main() {
  vec4 tex = texture2D(uMap, vUv);
  gl_FragColor = tex;
}

GLSL ES 1.00’da texture2D; daha yeni profillerde texture — proje ve Three.js sürümüne göre isim değişir. Doku uniform’ını JavaScript’ten atama Uniforms & varyings konusundadır; burada yalnızca shader içi çağrı kalıbı sabitlenir.

Sık tuzaklar

Bu bölüm, §2–§5’teki yerleşik çağrıların sahada nasıl «yanlış piksel» veya «kırmızı derleyici satırı» ürettiğini toplar. Çoğu tuzak, fonksiyonun kendisinden çok profil, tür ve performans kaynaklıdır — hata ayıklarken önce hangi kategoride olduğunuzu hatırlayın ( §1 · dört kategori).

  • Hassasiyet: Fragment shader kökünde precision mediump float; (veya proje standardınız) yaygındır. mediump mobilde performans kazandırır; düşük kontrastlı gradyanlarda banding (renk basamakları) görülebilir. Her yere gereksiz highp yazmak register baskısı yaratır — yalnızca gerçekten gereken yerde (derinlik, hassas UV) kullanın.
  • Tür uyumu: mix(a, b, t) ve dot(a, b) gibi çağrılarda a ile b aynı vektör boyutunda olmalıdır; mix(vec3, vec2, t) derleme hatasıdır. Bu, operatör kurallarıyla aynı disiplindir ( Operators · hatalar, tip zorunluluğu). Yerleşik isimler küçük harfle yazılır: mix, Mix değil.
  • Normalize ve sıfır vektör: normalize(v) sıfır uzunlukta tanımsız bölme üretebilir — ekranda siyah veya NaN pikselleri. Üretimde
    v / max(length(v), 1e-6) koruması ( §3 · normalize, Vec types) şarttır.
  • Doku döngüsü: for içinde onlarca texture2D çağrısı fragment başına maliyeti artırır. Mümkünse tek örnek alıp kanalları swizzle ile ayırın (tex.rg, tex.a); çoklu malzeme için atlas veya ayrı pass düşünün ( §5 · doku).
  • Türevler (dFdx / dFdy): Komşu pikseller arası farktan türetilir; mip seçimi ve kenar yumuşatma için kullanılır. Bilinçli kullanılmazsa (özellikle if ile dal içinde) beklenmedik titreme veya platforma özel sonuç görülebilir — Holodepth temel serisinde yalnızca «ileri konu, dikkatli kullan» notu; ayrıntılı anlatım ileride.

Hata ayıklarken uzun zinciri ara değişkenlere bölün ( Operators · ara değişken) — hangi satırın kırdığını hemen görürsünüz. Holodepth notundaki «önce kategori, sonra sonuç türü» alışkanlığı bu listeyle birlikte düşünülmelidir.

Holodepth notu

Yeni efekt yazarken önce «hangi kategori?» diye sorun: dalga mı (sin), maske mi (smoothstep), doku mu (texture2D)? Her çağrıdan sonra sonuç türünü not edin — dot skaler, normalize vektör. Uzun zinciri ara değişkenlere bölün; Built-in isimleri küçük harfle yazılır (mix, Mix değil).