Işıklandırma Eşlemeleri (Lighting Maps)
Önceki bölümde her nesnenin ışığa farklı tepki veren kendine özgü bir materyale sahip olabildiğini inceledik. Bu, nesnelere birbirinden farklı görünüm kazandırmak için harika bir yöntemdir; ancak bir nesnenin görsel çıktısı konusunda hâlâ fazla esneklik sunmuyor.
Önceki bölümde bir materyali nesnenin tamamına tek tip olarak tanımladık. Gerçek dünyadaki nesneler ise genellikle tek bir materyalden değil, birçok materyalden oluşur. Bir arabayı düşünün: dış gövde parlak bir yüzeye sahiptir, camlar çevreyi kısmen yansıtır, lastikler parlaklıktan uzak olduğundan specular vurguları yoktur; jantlar ise son derece parlaktır (eğer arabanızı yıkadıysanız tabii). Arabanın diffuse ve ambient renkleri de nesnenin tamamı için aynı değildir; farklı bölümlerde farklı ambient/diffuse renkler görürsünüz. Kısacası böyle bir nesne, parçalarına göre farklı materyal özelliklerine sahiptir.
Dolayısıyla önceki bölümdeki materyal sistemi en basit modeller dışında yeterli değildir. Sistemi diffuse ve specular eşlemeler (map) sunarak genişletmemiz gerekiyor. Bu eşlemeler, bir nesnenin diffuse (ve dolaylı olarak ambient — ikisi zaten aynı olmalı) ile specular bileşenini çok daha hassas şekilde kontrol etmemizi sağlar.
Diffuse Map
Amacımız, bir nesnenin diffuse renklerini her fragment için ayrı ayrı belirlemenin bir yolunu bulmaktır. Nesne üzerindeki fragment konumuna göre renk değeri alabileceğimiz bir sistem mi?
Bu kulağa tanıdık geliyor ve bir süredir böyle bir sistemi kullanıyoruz. Bu, daha önceki bölümde ayrıntılı olarak ele aldığımız dokulardan başka bir şey değil: nesneye sarılmış ve her fragment için benzersiz renk değerleri sunan bir görüntü. Işıklı sahnelerde buna genellikle diffuse map denir (PBR öncesinde 3D sanatçıların genel adlandırması budur), çünkü doku görüntüsü nesnenin tüm diffuse renklerini temsil eder.
Diffuse map'i göstermek için çelik çerçeveli bir ahşap konteynerin şu görüntüsünü kullanacağız:

Shader'larda diffuse map kullanımı, doku bölümünde gösterdiğimizle aynıdır. Bu kez dokuyu Material struct'ının içinde sampler2D olarak saklıyoruz. Daha önce tanımladığımız vec3 diffuse renk vektörünü diffuse map ile değiştiriyoruz.
sampler2D'nin opaque type (opak tür) olduğunu unutmayın. Bu, bu türden değişkenlerin yalnızca uniform olarak tanımlanabileceği, örneklenemeyeceği anlamına gelir. Struct, uniform dışında (örneğin fonksiyon parametresi olarak) örneklenirse GLSL garip hatalar verebilir; bu durum, opaque type içeren tüm struct'lar için geçerlidir.
Ambient materyal vektörünü de kaldırıyoruz; artık ambient rengi diffuse rengiyle eşit olduğundan ve ambient'i ışıkla kontrol ettiğimizden ayrıca saklamaya gerek kalmıyor:
Eğer biraz inatçıysanız ve ambient renkleri diffuse değerinden farklı ayarlamak istiyorsanız, ambient vec3'ü tutabilirsiniz; ancak bu durumda ambient renkler yine de tüm nesne için aynı kalacaktır. Her fragment için farklı ambient değerleri elde etmek isterseniz yalnızca ambient değerler için ayrı bir doku kullanmanız gerekir.
Fragment shader'da yine doku koordinatlarına ihtiyaç duyacağımıza dikkat edin; bu nedenle ekstra bir giriş değişkeni tanımladık. Ardından diffuse renk değerini almak için dokudan örnekleme yapıyoruz:
Ambient materyal rengini de diffuse materyal rengiyle eşitlemeyi unutmayın:
Diffuse map kullanmak için gereken tek şey bu kadar. Gördüğünüz gibi yeni bir şey değil; ancak görsel kalitede çarpıcı bir artış sağlıyor. Çalışması için vertex verilerini doku koordinatlarıyla güncellemek, bunları vertex attribute olarak fragment shader'a aktarmak, dokuyu yüklemek ve uygun texture unit'e bağlamak gerekiyor.
Güncellenmiş vertex verilerini buradan bulabilirsiniz. Vertex verisi artık küpün her vertex'i için vertex konumları, normal vektörler ve doku koordinatlarını içeriyor. Doku koordinatlarını vertex attribute olarak kabul etmek ve fragment shader'a iletmek için vertex shader'ı güncelleyelim:
Her iki VAO'nun vertex attribute pointer'larını yeni vertex verisine uygun şekilde güncellediğinizden ve konteyner görüntüsünü doku olarak yüklediğinizden emin olun. Küpü render etmeden önce material.diffuse uniform sampler'ına doğru texture unit'i atayın ve konteyner dokusunu bu texture unit'e bağlayın:
Artık diffuse map kullanarak detayda muazzam bir artış elde ediyoruz ve bu kez konteyner gerçekten parlamaya başlıyor. Konteyneriniz muhtemelen şuna benziyor:

Uygulamanın tam kaynak kodunu buradan bulabilirsiniz.
Specular Map
Specular vurgunun biraz tuhaf göründüğünü fark etmiş olabilirsiniz; zira nesne büyük ölçüde ahşaptan oluşan bir konteyner ve ahşabın böyle specular vurgulara sahip olmaması gerekir. Bunu nesnenin specular materyalini vec3(0.0) yaparak düzeltebiliriz; ancak bu, konteynerin çelik çerçevelerinin de specular vurgularından yoksun kalmasına yol açar ve metalin gerçekten specular vurgu göstermesi gerekir. Nesnenin hangi bölümlerinin specular vurgu göstereceğini farklı yoğunluklarda kontrol etmek istiyoruz. Tanıdık bir problem gibi mi geliyor? Tesadüf mü? Bence değil.
Specular vurgular için de bir texture map kullanabiliriz. Bu, nesnenin her bölümünün specular yoğunluğunu tanımlayan siyah-beyaz (ya da renkli, tercih meselesi) bir doku oluşturmamız gerektiği anlamına gelir. Specular map için örnek görüntü:

Specular vurgunun yoğunluğu, görüntüdeki her pikselin parlaklığından gelir. Specular map'teki her piksel, siyahın vec3(0.0) ve grinin örneğin vec3(0.5) renk vektörüne karşılık geldiği bir renk vektörü olarak yorumlanabilir. Fragment shader'da karşılık gelen renk değerini örnekler ve bu değeri ışığın specular yoğunluğuyla çarparız. Piksel ne kadar 'beyaz' ise çarpma sonucu o kadar büyür ve dolayısıyla nesnenin specular bileşeni o kadar parlak olur.
Konteyner büyük ölçüde ahşaptan oluştuğundan ve ahşabın specular vurguya sahip olmaması gerektiğinden, diffuse dokunun tüm ahşap kısmı siyaha dönüştürülmüştür: siyah bölgeler hiç specular vurgu almaz. Konteynerin çelik çerçevesi ise farklı specular yoğunluklarına sahiptir — metal yüzey specular vurgulara oldukça duyarlıyken çatlaklar daha az duyarlıdır.
Teknik olarak ahşabın da specular vurguları vardır; ancak çok daha düşük bir shininess değeriyle (daha fazla ışık saçılması) ve daha az belirgin olarak. Öğrenme amacıyla ahşabın specular ışığa hiç tepki vermediğini varsayabiliriz.
Photoshop veya Gimp gibi araçlar kullanarak, diffuse dokudan bazı bölümleri kesip siyah-beyaza dönüştürerek ve parlaklık/kontrastı artırarak bu tür bir specular görüntü elde etmek görece kolaydır.
Specular Map Örnekleme
Specular map, diğer herhangi bir doku gibidir; dolayısıyla kod, diffuse map koduyla benzerdir. Görüntüyü doğru şekilde yükleyip bir doku nesnesi oluşturduğunuzdan emin olun. Aynı fragment shader'da başka bir texture sampler kullandığımızdan, specular map için farklı bir texture unit kullanmamız gerekiyor (Dokular bölümüne bakın). Render etmeden önce uygun texture unit'e bağlayalım:
Ardından fragment shader'ın materyal özelliklerini, specular bileşeni için vec3 yerine sampler2D kabul edecek şekilde güncelleyin:
Son olarak fragment'ın karşılık gelen specular yoğunluğunu almak için specular map'ten örnekleme yapıyoruz:
Specular map kullanarak nesnenin hangi bölümlerinin parlak özelliğe sahip olduğunu büyük bir hassasiyetle belirleyebilir, hatta karşılık gelen yoğunluğu da kontrol edebiliriz. Specular map, diffuse map'in üstüne ek bir ışıklandırma kontrol katmanı ekler.
Çok geniş kitleye hitap etmek yerine, specular map'te her fragment'ın specular yoğunluğunu belirlemenin yanı sıra specular vurgunun rengini de belirlemek için gerçek renkler kullanabilirsiniz. Ancak gerçekte specular vurgunun rengi büyük ölçüde ışık kaynağının kendisi tarafından belirlenir; bu nedenle gerçekçi görsel sonuçlar vermez. (Bu yüzden görüntüler genellikle siyah-beyazdır: yalnızca yoğunlukla ilgileniyoruz.)
Uygulamayı çalıştırırsanız, konteynerin materyalinin artık gerçek bir ahşap konteynere çok daha yakın göründüğünü açıkça göreceksiniz:

Uygulamanın tam kaynak kodunu buradan bulabilirsiniz.
Diffuse ve specular map'leri kullanarak görece basit nesnelere muazzam miktarda detay ekleyebiliriz. Normal/bump map ve/veya yansıma map (reflection map) gibi başka texture map'leriyle de daha fazla detay ekleyebiliriz; ancak bunları ilerleyen bölümlere saklıyoruz. Konteynerinizi arkadaşlarınıza ve ailenize gösterin; bir gün olduğundan da güzel hale gelebileceği gerçeğiyle içiniz rahat etsin!
Alıştırmalar
Işık kaynağının ambient, diffuse ve specular vektörleriyle oynayın; konteynerin görsel çıktısını nasıl etkilediğini gözlemleyin.
Fragment shader'da specular map renk değerlerini ters çevirmeyi deneyin; böylece ahşap specular vurgu alırken çelik çerçeveler almaz (çelik çerçevedeki çatlaklar nedeniyle çerçeve hâlâ biraz specular vurgu alacaktır, ancak daha az yoğunlukla): çözüm.
Siyah-beyaz yerine gerçek renkler kullanan diffuse dokusundan bir specular map oluşturmayı deneyin ve sonucun pek gerçekçi görünmediğini fark edin. Kendiniz oluşturamıyorsanız renkli specular map'i kullanabilirsiniz: sonuç.
Emission map ekleyin: bu, her fragment için emisyon değerlerini saklayan bir dokudur. Emisyon değerleri, sanki kendi içinde bir ışık kaynağı varmış gibi bir nesnenin yaydığı renklerdir; böylece nesne ışık koşullarından bağımsız olarak parlar. Emission map'ler genellikle oyunlardaki parlayan nesnelerde görülür (robot gözleri veya konteyner üzerindeki ışık şeritleri gibi). Şu dokuyu (creativesam tarafından) konteynere emission map olarak ekleyin; sanki harfler ışık yayıyormuş gibi görünsün: çözüm; sonuç.
Orijinal kaynak: LearnOpenGL – Lighting/Lighting-maps Türkçe çeviri: Nezihe Sözen
Last updated