The Book of Shaders by Patricio Gonzalez Vivo & Jen Lowe

Українська - Bahasa Indonesia - Tiếng Việt - 日本語 - 中文版 - 한국어 - Español - Portugues - Français - Italiano - Deutsch - Русский - Polski - Türkçe - English


Paul Klee - Color Chart (1931)

Renkler

GLSL vektör tipleri hakkında konuşma fırsatımız pek olmadı. Daha ileri gitmeden önce bu değişkenler hakkında daha fazla bilgi edinmek önemlidir ve renkler konusu onlar hakkında daha fazla şey öğrenmenin harika bir yoludur.

Nesne yönelimli programlama paradigmalarına aşinaysanız, muhtemelen vektörlerin içindeki verilere herhangi bir normal C-benzeri struct gibi eriştiğimizi fark etmişsinizdir.

vec3 red = vec3(1.0,0.0,0.0);
red.x = 1.0;
red.y = 0.0;
red.z = 0.0;

Rengi x, y ve z gösterimi kullanarak tanımlamak kafa karıştırıcı ve yanıltıcı olabilir, değil mi? Bu yüzden aynı bilgiye farklı adlarla erişmenin başka yolları da vardır. .x, .y ve .z değerleri aynı zamanda .r, .g ve .b olarak, ve .s, .t ve .p olarak da çağrılabilir. (.s, .t ve .p genellikle bir dokunun uzaysal koordinatları için kullanılır, bunu ilerideki bir bölümde göreceğiz.) Vektördeki verilere dizin konumunu kullanarak da erişebilirsiniz: [0], [1] ve [2].

Aşağıdaki satırlar aynı veriye erişmenin tüm yollarını gösterir:

vec4 vector;
vector[0] = vector.r = vector.x = vector.s;
vector[1] = vector.g = vector.y = vector.t;
vector[2] = vector.b = vector.z = vector.p;
vector[3] = vector.a = vector.w = vector.q;

Bir vektörün içindeki değişkenlere işaret etmenin bu farklı yolları, açık kod yazmanıza yardımcı olmak için tasarlanmış adlandırma kurallarıdır. Gölgelendirme diline gömülü bu esneklik, renk ve uzay koordinatları hakkında birbirinin yerine düşünmeye başlamanız için bir kapıdır.

GLSL'deki vektör tiplerinin bir diğer harika özelliği, özelliklerin istediğiniz sırada birleştirilebilmesidir; bu da değerleri dönüştürmeyi ve karıştırmayı kolaylaştırır. Bu yeteneğe swizzle denir.

vec3 yellow, magenta, green;

// Sarı yapma
yellow.rg = vec2(1.0);  // Kırmızı ve yeşil kanallara 1 atama
yellow[2] = 0.0;        // Mavi kanala 0 atama

// Magenta yapma
magenta = yellow.rbg;   // Yeşil ve mavi kanalları değiştirilmiş olarak ata

// Yeşil yapma
green.rgb = yellow.bgb; // Sarının mavi kanalını (0) kırmızı ve mavi kanallara ata

Renk karıştırma

Artık renklerin nasıl tanımlandığını bildiğinize göre, bunu önceki bilgilerimizle entegre etmenin zamanı geldi. GLSL'de çok kullanışlı bir fonksiyon olan mix() vardır, iki değeri yüzdelerle karıştırmanızı sağlar. Yüzde aralığının ne olduğunu tahmin edebilir misiniz? Evet, 0.0 ile 1.0 arasındaki değerler! Çitle karate hareketleri pratiği yaparak geçirdiğiniz uzun saatlerden sonra bunları kullanmanın zamanı geldi!

Aşağıdaki kodu 18. satırda kontrol edin ve colorA ile colorB'yi karıştırmak için zamana bağlı bir sinüs dalgasının mutlak değerlerini nasıl kullandığımızı görün.

Yeteneklerinizi sergileyerek:

Gradyanlarla oynama

mix() fonksiyonunun sunabileceği daha fazlası var. Tek bir float yerine, ilk iki argümanla eşleşen bir değişken tipi geçirebiliriz, bizim durumumuzda bir vec3. Bunu yaparak her bir renk kanalı olan r, g ve b'nin karışım yüzdeleri üzerinde kontrol kazanırız.

Aşağıdaki örneğe bir göz atın. Önceki bölümdeki örnekler gibi, geçişi normalize edilmiş x koordinatına bağlıyoruz ve bir çizgiyle görselleştiriyoruz. Şu anda tüm kanallar aynı çizgi boyunca gidiyor.

Şimdi 25 numaralı satırın yorumunu kaldırın ve ne olduğunu izleyin. Ardından 26 ve 27. satırların yorumunu kaldırmayı deneyin. Satırların, kanal başına karıştırılacak colorA ve colorB miktarını görselleştirdiğini unutmayın.

Muhtemelen 25-27. satırlarda kullandığımız üç şekillendirme fonksiyonunu tanıyorsunuzdur. Onlarla oynayın! Önceki bölümdeki becerilerinizi keşfetme ve sergilemenin ve ilginç gradyanlar yapmanın zamanı. Aşağıdaki alıştırmaları deneyin:

William Turner - The Fighting Temeraire (1838)

HSB

Renk uzayı hakkında konuşmadan renkler hakkında konuşamayız. Muhtemelen bildiğiniz gibi, renkleri kırmızı, yeşil ve mavi kanalların yanı sıra düzenlemenin farklı yolları vardır.

HSB, Ton (Hue), Doygunluk (Saturation) ve Parlaklık (Brightness veya Value) anlamına gelir ve renklerin daha sezgisel ve kullanışlı bir organizasyonudur. Aşağıdaki kodda rgb2hsv() ve hsv2rgb() fonksiyonlarını okumak için bir dakikanızı ayırın.

x eksenindeki konumu Ton'a ve y eksenindeki konumu Parlaklığa eşleyerek, görünür renklerin güzel bir spektrumunu elde ederiz. Bu uzaysal renk dağılımı çok kullanışlı olabilir; HSB ile renk seçmek RGB'den daha sezgiseldir.

Kutupsal koordinatlarda HSB

HSB başlangıçta kartezyen koordinatlar (x ve y'ye dayalı) yerine kutupsal koordinatlarda (açı ve yarıçapa dayalı) temsil edilmek üzere tasarlanmıştır. HSB fonksiyonumuzu kutupsal koordinatlara eşlemek için, tuvalin merkezinden piksel koordinatına olan açıyı ve mesafeyi elde etmemiz gerekir. Bunun için length() fonksiyonunu ve atan(y,x) fonksiyonunu (yaygın olarak kullanılan atan2(y,x)'in GLSL versiyonu olan) kullanacağız.

Vektör ve trigonometrik fonksiyonlar kullanırken, vec2, vec3 ve vec4 renkleri temsil etseler bile vektör olarak ele alınır. Renkleri ve vektörleri benzer şekilde ele almaya başlayacağız, aslında bu kavramsal esnekliğin çok güçlendirici olduğunu göreceksiniz.

Not: Merak ediyorsanız, length'in yanı sıra daha fazla geometrik fonksiyon vardır: distance(), dot(), cross, normalize(), faceforward(), reflect() ve refract(). Ayrıca GLSL'de özel vektör karşılaştırma fonksiyonları vardır: lessThan(), lessThanEqual(), greaterThan(), greaterThanEqual(), equal() ve notEqual().

Açıyı ve uzunluğu elde ettikten sonra, değerlerini 0.0 ile 1.0 arasındaki aralığa "normalize" etmemiz gerekir. 27. satırda, atan(y,x) radyan cinsinden -PI ile PI (-3.14 ile 3.14) arasında bir açı döndürecektir, bu yüzden -0.5 ile 0.5 arasında değerler elde etmek için bu sayıyı TWO_PI (kodun üstünde tanımlanmıştır) ile bölmemiz gerekir, basit bir toplama ile istenen 0.0 ile 1.0 aralığına değiştiririz. Yarıçap maksimum 0.5 döndürecektir (çünkü görüntü alanının merkezinden mesafeyi hesaplıyoruz) bu yüzden maksimum 1.0 elde etmek için bu aralığı ikiye katlamamız (ikiyle çarpmamız) gerekir.

Gördüğünüz gibi, buradaki oyunumuz tamamen aralıkları sevdiğimiz 0.0 ile 1.0 aralığına dönüştürmek ve eşlemektir.

Aşağıdaki alıştırmaları deneyin:

William Home Lizars - Red, blue and yellow spectra, with the solar spectrum (1834)

Fonksiyonlar ve argümanlar hakkında not

Bir sonraki bölüme geçmeden önce duralım ve geri saralım. Önceki örneklerdeki fonksiyonlara geri dönün ve bakın. Argüman tiplerinin önünde in göreceksiniz. Bu bir niteleyici ve bu durumda değişkenin salt okunur olduğunu belirtir. Gelecekteki örneklerde argümanları out veya inout olarak tanımlamanın da mümkün olduğunu göreceğiz. Bu sonuncusu, inout, kavramsal olarak bir argümanı referansla geçirmeye benzer ve bize geçirilen bir değişkeni değiştirme imkanı verir.

int newFunction(in vec4 aVec4,      // salt-okunur
                out vec3 aVec3,     // salt-yazılır
                inout int aInt);    // okunur-yazılır

İnanmayabilirsiniz ama artık harika çizimler yapmak için tüm elemanlara sahibiz. Bir sonraki bölümde, uzayı harmanlayarak geometrik formlar yapmak için tüm numaralarımızı nasıl birleştireceğimizi öğreneceğiz. Evet... uzayı harmanlayarak.

Araç kutunuz için