ÿþM icrosoft W ord - I a . D 1 _ K apak

Transkript

ÿþM icrosoft W ord - I a . D 1 _ K apak
KARADENİ
Z TEKNİ
K ÜNİ
VERSİ
TESİ
MÜHENDİ
SLİ
K FAKÜLTESİ
Bİ
LGİ
SAYAR MÜHENDİ
SLİ
ĞİBÖLÜMÜ
Cg PROGRAMLAMA Dİ
Lİ
VE
Cg İ
LE PÜRÜZLÜ YÜZEY DOKUSU ÜRETİ
Mİ
Bİ
Tİ
RME TEZİ
UMUT DOĞAN
Trabzon 2006
KARADENİ
Z TEKNİ
K ÜNİ
VERSİ
TESİ
MÜHENDİ
SLİ
K FAKÜLTESİ
Bİ
LGİ
SAYAR MÜHENDİ
SLİ
ĞİBÖLÜMÜ
Cg PROGRAMLAMA Dİ
Lİ
VE
Cg İ
LE PÜRÜZLÜ YÜZEY DOKUSU ÜRETİ
Mİ
UMUT DOĞAN
Tezin Bölüme Verildiği Tarih : 02.06.2006
Tezin Savunma Tarihi
: 23.06.2006
Tez Danı
ş
manı
: Öğr. Gör. Ömer ÇAKIR
Jüri Üyesi
: Yrd. Doç. Dr. Murat EKİ
NCİ
Jüri Üyesi
: Yrd. Doç. Dr. Hüseyin PEHLİ
VAN
Jüri Üyesi
: Yrd. Doç. Dr. Tuğrul ÇAVDAR
Bölüm Baş
kanı
: Prof. Dr. Rı
fat YAZICI
Trabzon, 2006
ÖNSÖZ
“Cg Programlama Dili ve Cg ile Pürüzlü Yüzey Dokusu Üretimi” konulu bu
çalı
ş
ma, Karadeniz Teknik Üniversitesi, Mühendislik Fakültesi, Bilgisayar Mühendisliğ
i
Bölümü’nde “Bitirme Tezi” olarak hazı
rlanmı
ş
tı
r.
Bitirme tez danı
ş
manlı
ğı
nıüstlenerek, gerek konu seçimi, gerekse çalı
ş
maları
n
yürütülmesi ve değerlendirilmesi sı
rası
nda ilgi ve yardı
mları
nıesirgemeyen saygı
değer
hocam Öğr. Grv. Ömer ÇAKIR’a ve çalı
ş
maları
m sı
rası
nda bana yardı
mcıolan diğer
hocaları
m ve arkadaş
ları
ma teş
ekkür ederim.
Umut DOĞAN
II
İ
Çİ
NDEKİ
LER
Sayfa No
ÖNSÖZ …………………………………………………………………………………… II
İ
Çİ
NDEKİ
LER …………………………………………………………………………... III
ÖZET …………………………………………………………………………………….. VI
ŞEKİ
LLER Dİ
Zİ
Nİ…………………………………………………………………...... VII
1. GENEL Bİ
LGİ
LER ……………………………………………………………….......... 1
1.1. Cg Nedir ……………………………………………………………………………… 1
1.1.1. Cg: Grafik Donanı
mıProgramlama Dili …………………………………………… 2
1.1.2. Cg’nin Veri Akı
şModeli …………………………………………………………… 2
1.1.3. Özel AmaçlıGPU – Genel AmaçlıCPU ………………………………………..….. 3
1.1.4. Cg’nin Performans Temeli ….……………………………………………………… 3
1.1.5. Cg’nin Geleneksel Dillerle Birlikte Kullanı
mı…………………………………….. 4
1.1.6. Diğer Açı
lardan Cg ………………………………………………………………… 6
1.1.7 Cg Programları
nı
n Sı
nı
rlıÇalı
ş
ma Ortamı……………………………………..…… 7
1.2. Vertexler, Fragmentlar ve Grafik Pipeline …………………………………………… 7
1.2.1. Bilgisayar Grafikleri Donanı
mı
nı
n Geliş
imi ……………………………………….. 7
1.2.2. Bilgisayar Grafikleri Donanı
mı
nı
n Dört Kuş
ağ
ı…………………………………… 9
1.2.2.1. GPU Öncesi Dönemde Grafik Hı
zlandı
rı
cı
lar …………………………………... 10
1.2.2.2. Birinci Kuş
ak GPU’lar ………………………………………………………….. 10
1.2.2.3. İ
kinci Kuş
ak GPU’lar …………………………………………………………… 10
1.2.2.4. Üçüncü Kuş
ak GPU’lar …………………………………………………………. 11
1.2.2.5. Dördüncü Kuş
ak GPU’lar ………………………………………………………. 11
1.2.3. Grafik Donanı
mıPipeline’ı……………………………………………………….. 12
1.2.3.1. Vertex Dönüş
ümü ……………………………………………………………….. 13
1.2.3.2. Primitif Montajıve Pikselleş
tirme ……………………………………………… 14
1.2.3.3. İ
nterpolasyon, Doku Kaplama, Renklendirme ………………………………….. 15
1.2.3.4. Tarama İ
ş
lemleri ………………………………………………………………… 15
1.2.3.5. Grafik Pipeline’ıGörselleş
tirme ………………………………………………... 15
1.2.4. Programlanabilir Grafik Pipeline’ı………………………………………………... 16
1.2.4.1. Programlanabilir Vertex İ
ş
lemcisi ………………………………………………. 17
III
1.2.4.2. Programlanabilir Fragment İ
ş
lemcisi …………………………………………… 19
1.2.5. Cg; Vertex ve Fragment Programlanabilirliği Sağlar ……………………………... 20
1.3. Cg’nin Tarihsel Geliş
imi ……………………………………………………………. 21
1.3.1. Cg ve HLSL’yi Geliş
tirmek İ
çin NVIDIA ve Microsoft İ
ş
birliği ………………… 22
1.3.2. Etkileş
imli Olmayan Shading Dilleri …………………………………………....... 23
1.3.2.1. Shade Ağaçları………………………………………………………………….. 23
1.3.2.2. Renderman Shading Dili ………………………………………………………... 24
1.3.2.3. Donanı
ma Uygun Shading Dilleri ………………………………………………. 25
1.3.3. Üç Boyutlu Grafikler İ
çin Programlama Arayüzleri ……………………………… 26
1.4. Cg Ortamı…………………………………………………………………………… 26
1.4.1. Standart 3B Programlama Arayüzleri: OpenGL ve Direct3D …………………….. 26
1.4.1.1. OpenGL …………………………………………………………………………. 27
1.4.1.2. Direct3D ………………………………………………………………………… 27
1.4.2. Cg Derleyicisi ve Runtime’ı………………………………………………………. 27
1.4.2.1. Dinamik Derleme Desteğ
i ………………………………………………………. 28
1.4.2.2. 3B API’lere Özgü Cg Kütüphaneleri: CgGL, CgD3D ………………………….. 28
1.4.2.3. Cg Runtime Uygulamamı
za Nası
l Uyum Sağlar ……………………………….. 29
1.4.3. CgFX Araç Takı
mıve Dosya Biçimi ……………………………………………... 29
1.4.3.1. CgFX Ne Sağlar ………………………………………………………………… 29
1.4.3.2. Çoklu Shader Örnekleme ……………………………………………………….. 30
1.4.3.3. CgFX ile Sayı
sal İ
çerik Oluş
turma ……………………………………………... 31
1.4.3.4. CgFX Uygulamamı
za Nası
l Yerleş
ir …………………………………………… 31
2. Cg Dİ
Lİ
Nİ
N KURALLARI …………………………………………………………... 33
2.1. Cg Dil Profilleri ……………………………………………………………………... 33
2.2. Cg’de Programları
n Tanı
mlanması…………………………………………………. 34
2.3. Program Girdi ve Çı
ktı
ları…………………………………………………………... 34
2.3.1. Vertex Programları
ndaki Değiş
ken Girdiler ……………………………………… 34
2.3.2. Vertex Programları
ndaki Değiş
ken Çı
ktı
lar ………………………………………. 35
2.3.3. Fragment Programları
ndaki Değiş
ken Çı
ktı
lar …………………………………… 37
2.4. Veri Tipleri ………………………………………………………………………….. 39
2.4.1. Temel Veri Tipleri ………………………………………………………………… 39
2.4.2. Tip Dönüş
ümleri …………………………………………………………………... 40
2.4.3. Yapı
lar ve Üye Fonksiyonlar ……………………………………………………... 41
IV
2.4.4. Diziler ……………………………………………………………………………... 42
2.4.4.1. Boyutsuz Diziler ………………………………………………………………… 42
2.4.4.2. Arayüzler ………………………………………………………………………... 42
2.5. İ
fadeler ve Operatörler ……………………………………………………………… 43
2.5.1. Kontrol Akı
ş
ı……………………………………………………………………… 43
2.5.2. Fonksiyon Tanı
mlamalarıve Aş
ı
rıYüklemeler …………………………………... 43
2.5.3. Aritmetik Operatörler ……………………………………………………………... 44
2.5.4. Çarpma Fonksiyonu ………………………………………………………………. 44
2.5.5. Vektör Yapı
cı
lar ……………………………………..……………………………. 44
2.5.6. Bool ve Karş
ı
laş
tı
rma Operatörleri ……………………………………………….. 44
2.5.7. Swizzle Operatörü ………………………………………………………………… 45
2.5.8. Write Mask Operatörü …………………………………………………………….. 45
2.5.9. Koş
ullu Operatörler ……………………..………………………………………… 45
2.6. Cg Standart Kütüphane Fonksiyonları……………………………………………… 46
2.6.1. Matematiksel Fonksiyonlar ……………………………………..………………… 46
2.6.2. Geometrik Fonksiyonlar ……………………………………..……………………. 47
2.6.3. Doku Kaplama Fonksiyonları…………………………………………………….. 47
3. Cg VE DIRECT3D İ
LE YAZILMIŞKOD ÖRNEKLERİ…………………………… 48
3.1. Cg ile Kod Yazabilmek için Ayarlar ………………………………………………... 48
3.2. Basit Bir Vertex Programı…………………………………………………………... 49
3.3. Dalgalanan Türk BayrağıUygulaması……………………………………………… 57
4. Cg İ
LE PÜRÜZLÜ YÜZEY DOKUSU ÜRETİ
Mİ…………………………………... 64
4.1. Pürüzlü Yüzey Dokusu Üretimi Programlama Ortamı……………………………... 64
4.2. Pürüzlü Yüzey Dokusu Üretimi Nedir ……………………………………………… 64
4.3. Programda Kullanı
lan Algoritmalar ………………………………………………… 65
4.4. Cg ile İ
lgili Kı
sa Bilgiler ……………………………………………………………. 72
4.5. Cg Runtime ………………………………………………………………………….. 73
4.6. Cg Shader’ları……………………………………………………………………….. 75
4.7. Ana Program ………………………………………………………………………… 78
5. SONUÇLAR ………………………………………………………………………….. 87
6. ÖNERİ
LER ……………………………………………….……………………………88
7. KAYNAKLAR ………………………………………………………………………... 89
V
ÖZET
Bu bitirme tezinde; Cg grafik donanı
mı programlama dili, ayrı
ntı
ları
yla
anlatı
lmı
ş
tı
r. Tez grafik donanı
mı
nı
n geçmiş
iyle ilgili bilgiler verdikten sonra GPU’nun
çalı
ş
ma birimlerini açı
klamaktadı
r. Daha sonra shading dillerinin oluş
um süreciyle ilgili
ayrı
ntı
lar anlatı
lmı
ş
tı
r. Cg dilinin temel özellikleri, kurallarıtezin önemli bir kı
smı
nı
oluş
turmaktadı
r.
Cg ve Direct3D ile yazı
lmı
şkod örnekleri açı
klanarak ilk kez Cg kodu yazacaklara
önemli bilgiler verilmeye çalı
ş
ı
lmı
ş
tı
r. Ana proje olaraksa Cg ve OpenGL kullanarak
pürüzlü yüzey üretilmiş
tir.
Anahtar kelimeler:
Cg, C for Graphics, GPU, Direct3D, OpenGL, NVIDIA, Microsoft, Pürüzlü Yüzey
Üretimi, Bump mapping, Bilgisayar Grafikleri, Visual C++, Shading, Vertex, Fragment,
3B, CgFX, Cg Runtime
VI
ŞEKİ
LLER Dİ
Zİ
Nİ
Sayfa No
Şekil 1.1.
Örnek Assembly ve Cg Programları………………………………………. 5
Şekil 1.2.
Grafik Donanı
mıGeliş
imini Sağlayan Etmenler ………………………….. 8
Şekil 1.3.
FarklıKuş
aklardan NVIDIA GPU’larıiçin Performans Tablosu ……….. 12
Şekil 1.4.
Grafik Donanı
mıPipeline’ı……………………………………………… 13
Şekil 1.5.
Geometrik Primitifler……………………………………………………... 13
Şekil 1.6.
Standart OpenGL ve Direct3D Tarama İ
ş
lemleri ………………………... 16
Şekil 1.7.
Grafik Pipeline’ı
n Görselleş
tirilmesi …………………………………….. 16
Şekil 1.8.
Programlanabilir Grafik Pipeline ………………………………………… 17
Şekil 1.9.
Programlanabilir Vertex İ
ş
lemci Akı
şDiyagramı……………………….. 18
Şekil 1.10.
Programlanabilir Fragment İ
ş
lemci Akı
şDiyagramı……………………. 20
Şekil 1.11.
Cg’nin Teknolojisini Miras Aldı
ğıKaynaklar …………………………… 21
Şekil 1.12.
Cg’nin Geliş
tirilme Sürecinde Esinlenilen Kaynaklar …………………... 22
Şekil 1.13.
Rob COOK’un Makalesini Temel Alan Bir Shade Ağacı……………….. 24
Şekil 1.14.
Standart Bir Cg Uygulaması
nda Cg’nin Yeri ……………………………. 29
Şekil 1.15.
Cg ve CgFX Kullanan Sayı
sal İ
çerik Oluş
turma Uygulamaları…………. 31
Şekil 1.16.
Standart Bir Uygulamada CgFX’in Yeri ………………………………… 32
Şekil 3.1.
Basit Bir Vertex Programı……………………………………………….. 56
Şekil 3.2.
Dalgalanan Türk Bayrağı………………………………………………… 63
Şekil 4.1.
Orijinal 2B Resim ve Pürüzlü Yüzey Uygulanmı
şHali …………………. 64
Şekil 4.2.
(a) Herhangi bir yüzey Dokusu
Şekil 4.3.
Normal Map ……………………………………………………………… 66
Şekil 4.4.
Yüzeyle İ
liş
kili Vektörler ………………………………………………... 68
Şekil 4.5.
Uzaylar ve Dönüş
üm Matrisleri ………………………………………….. 69
Şekil 4.6.
Teğet UzayıKoordinatları……………………………………………….. 70
Şekil 4.7.
Üçgen ve Vertexleri ……………………………………………………… 73
Şekil 4.8.
Cg ile Pürüzlü Yüzey Dokusu Üretimi Ekran Görüntüleri ………………. 86
VII
(b) Normal Map …………………... 66
1. GENEL Bİ
LGİ
LER
1.1. Cg Nedir
Cg programlama dili, programlanabilir grafik donanı
mıkullanı
larak çizilen
nesnelerin biçim, görünüm ve hareketlerini kontrol edebilmemizi sağlar. Bu özelliklerin
programa dayalıkontrolüyle günümüz grafik iş
lemcilerinin inanı
lmaz hı
z ve kapasitelerini
birleş
tirir. Bilgisayar grafikleri uygulamacı
ları
, çizim sanatçı
larıve programcı
lar Cg dili
oluş
turulmadan önce ürettikleri gerçek-zamanlıgörüntülerde bu kadar kontrol sahibi
olamı
yorlardı
.
Cg, yazı
lı
m geliş
tiricilere kolay kullanı
labilir bir programlama platformu sunar ve
özel efektlerin hı
zlıyaratı
lması
nı
, birçok platformda sinema kalitesinde görüntüler
oluş
turmayıoldukça basitleş
tirir.
Yeni bir soyutlama seviyesi sağ
layan Cg, geliş
tiricilerin grafik donanı
mı
nı
assembly dili kullanarak programlama zorunluluğunu ortadan kaldı
rı
r. OpenGL, DirectX
gibi üç boyutlu (3B) programlama API’leri; Windows, Linux, Macintosh OSX gibi iş
letim
sistemleri ve Xbox gibi oyun konsolları
nda kolayca programlanabilir. Cg; NVIDIA ve
Microsoft ş
irketlerinin ortak çalı
ş
malarısonucunda geliş
tirilmiş
tir. OpenGL API’si ve
Microsoft’un DirectX9 için ürettiği High Level Shading Language (HLSL) ile uyumlu
çalı
ş
ı
r.
oluş
turulmuşpopüler, genel amaçlıbir dildir. Popülerliği ve sorunsuz tasarı
mınedeniyle C
dili kendisinden sonra gelen birçok dil için temel oluş
turmuş
tur. Örneğ
in C++, Java ve C#
‘ı
n sözdizimi ve yapı
sıbüyük oranda C ‘ye benzer. Cg dili de kendisini C tabanlıbir dil
olarak tanı
mlar. C veya türevi bir programlama dilini iyi bilen birisi için Cg’yi öğrenmek
çok kolay olacaktı
r.
Öte taraftan; C veya diğer genel amaçlıprogramlama dillerini iyi bilmeyen ancak
bilgisayar grafiklerine ilgi duyan ve yeni bir ş
eyler öğrenmek isteyen kiş
iler için de Cg
Umut DOGAN - Bitirme Tezi - Haziran 2006
Cg, ‘C for graphics’ deyiminin kı
saltması
dı
r. C programlama dili 1970’lerde
2
dilini öğrenmek çok zor olmayacaktı
r. Çünkü Cg programlarıoldukça kı
sa ve anlaş
ı
labilir
yapı
dadı
r.
1.1.1. Cg: Grafik Donanı
mıProgramlama Dili
Cg dili; C, C++ ve Java’dan oldukça farklı
dı
r. Çünkü özel amaçlı
dı
r. Örneğin, Cg
kullanarak bir kelime iş
lemci programıyazamayı
z. Bunun yerine Cg, grafik donanı
mı
nı
kullanarak nesnelerin biçim, görünüm ve hareketini programsal açı
dan kontrol
edebilmemizi sağlar. Bilgisayar grafiklerinde bu tarz bir dile shading dili denir. Cg
kullanarak ‘shading’ uygulamaları
nı
n yanı
nda fiziksel simülasyonlar da oluş
turabiliriz.
Genel olarak bir Cg programı
, programlanabilir grafik donanı
mıkullanı
larak bir
nesnenin nası
l gerçeklenebileceğ
ini anlatan detaylıbir reçete olarak düş
ünülebilir. Bir
yüzeyi engebeli göstermek için veya sanal bir karakteri canlandı
rmak için Cg ile
programlar yazı
labilir.
1.1.2. Cg’nin Veri Akı
şModeli
Cg ve diğ
er shading dilleri, geleneksel programlama dillerinden sadece grafik
programlamaya özgü olmaları
yla ayrı
lmazlar. Bunun dı
ş
ı
nda da önemli farklı
lı
klara
sahiptirler. Çünkü shading dilleri veri akı
şhesaplama modeline göre çalı
ş
ı
rlar. Bu modelde
hesaplamalar iş
lem adı
mları
ndan akan veriye yanı
t olarak oluş
ur.
Cg programları
, bir görüntüyü gerçeklerken iş
lenen vertex ve fragmentlardan
uğ
radı
ğıve öbür taraftan dönüş
üme uğramı
şş
ekilde çı
ktı
ğ
ıbir kara kutu gibi düş
ünebiliriz.
Ancak, buradaki kara kutu tam bir kara kutu özelliği göstermez çünkü Cg programı
nıbiz
yazdı
ğı
mı
z için kara kutunun içinde neler olup bittiğine biz karar veririz.
3B bir sahne gerçeklenirken her bir vertex iş
lendiğinde veya (pikselleş
tirici bir
fragment ürettiğinde) ilgili vertex (veya fragment) Cg programıçalı
ş
ı
r.
Umut DOGAN - Bitirme Tezi - Haziran 2006
oluş
ur. Cg programı
nıbir tarafı
ndan vertex ve fragmentları
n girdiği, içerisinde dönüş
üme
3
Yeni nesil kiş
isel bilgisayarları
n ve oyun konsolları
nı
n tümü 3B modelleri
dönüş
türme ve pikselleş
tirme gibi grafik iş
lemlerini yapmakla görevli bir grafik iş
leme
birimi (GPU, Graphics Processing Unit) içerirler. Cg programıbu GPU içinde çalı
ş
ı
r.
1.1.3. Özel AmaçlıGPU – Genel AmaçlıCPU
Bir kiş
isel bilgisayar veya oyun konsolu GPU’ya sahip olsa da olmasa da iş
letim
sistemini veya uygulama programları
nıkoş
an bir CPU’ya mutlaka sahip olmalı
dı
r.
CPU’lar tasarı
msal olarak genel amaçlı
dı
r ve C++, Java gibi genel amaçlıdillerde yazı
lmı
ş
uygulamalarıçalı
ş
tı
rı
rlar.
GPU’lar ise, özel amaçlıtasarı
mlarınedeniyle 3B sahneleri gerçeklemek gibi
grafiksel görevlerde, genel amaçlıbir CPU’dan onlarca kat daha hı
zlı
dı
rlar. Son nesil
GPU’lar saniyede on milyonlarca vertex iş
leyebilir ve yüz milyonlarca (hatta milyarlarca)
fragment pikselleş
tirebilirler. Gelecekteki GPU’lar elbette daha da hı
zlıolacaklardı
r.
GPU’nun
da
genel
amaçlı programları CPU’nun
çalı
ş
tı
rabileceği kadar
hı
zlı
çalı
ş
tı
ramayacağıunutulmamalı
dı
r.
Cg’nin var oluşnedeni GPU’nun özel amaçlı
, yüksek performanslıyapı
sı
dı
r. Genel
amaçlıprogramlama dilleri vertex ve fragmentlarıiş
lemek gibi özel bir görev için
yetersizdirler. Cg diliyse kendini tümüyle bu göreve adamı
ş
tı
r. Cg, GPU’nun çalı
ş
ma
modelini soyutlayan bir yapı
ya sahiptir.
Etkileş
imli görüntü oluş
turabilmek için bir 3B uygulama saniyede 15 veya daha
fazla görüntüden oluş
an canlandı
rma oranı
na (animation rate) sahip olmalı
dı
r. Genelde
gerçek zamanlıuygulamalarda 60 veya daha fazla çerçeve (frame) kullanı
lı
r. Bilgisayar
ekranlarısürekli tekrar oluş
turulmasıgereken bir milyon veya daha fazla piksel içerir. 3B
sahneler için GPU, nesnelerin birbirlerini kapatı
p kapatmadı
ğ
ı
nıbelirlemek veya
piksellerin görünüş
ünü geliş
tirmek için ekrandaki her pikseli birçok kez iş
ler. Yani gerçek
zamanlı3B uygulamalar saniyede yüz milyonlarca pikselin güncellenmesini gerektirir. 3B
modeller; çokgenleri, çizgileri ve noktalarıoluş
turan piksellere dönüş
türülmeden önce
Umut DOGAN - Bitirme Tezi - Haziran 2006
1.1.4. Cg’nin Performans Temeli
4
uygun bir ş
ekilde dönüş
türmemiz gereken vertexlerden oluş
ur. Bu, saniyede on
milyonlarca vertex’in dönüş
ümü anlamı
na gelir.
Ayrı
ca, grafik iş
leme sürecinde CPU’nun da her bir görüntü için canlandı
rmayı
güncelleme gibi önemli bir görevi vardı
r. Gerçek ş
udur ki, hem CPU’ya hem de GPU’nun
uzmanlaş
mı
şgrafik-tabanlıyeteneklerine ihtiyacı
mı
z vardı
r. Hem CPU hem de GPU;
sahneleri, 3B uygulama ve oyunları
n istediği ş
ekilde etkileş
im oranları
yla kalite
standartları
nda gerçeklemek için gereklidir. Özetle, yazı
lı
m geliş
tirici, C++ kullanarak 3B
bir uygulama veya oyun yazabilir ve daha sonra GPU’nun grafiksel katkı
ları
ndan
yaralanmak için Cg’yi kullanabilir.
1.1.5. Cg’nin Geleneksel Dillerle Birlikte Kullanı
mı
Cg, hiçbir ş
ekilde var olan genel amaçlıbir programlama dilinin yerini
almamaktadı
r. Cg, GPU’lar için özel olarak tasarlanmı
şyardı
mcıbir dildir. C ve C++ gibi
geleneksel dillerde CPU için yazı
lmı
şprogramlar, Cg programları
nıyüklerken GPU’nun
çalı
ş
tı
rmasıiçin Cg runtime’ı
nıkullanabilirler. Cg runtime, Cg programları
nıGPU’da
koş
acak ş
ekilde yüklemek, derlemek, düzenlemek ve ayarlamak için kullanı
lan
altyordamlar standardı
dı
r.
Cg, paralel iş
lemenin özel bir biçimini sağlar. CPU, geleneksel bir uygulama
çalı
ş
tı
rı
rken uygulama aynızamanda Cg programları
nda yazı
lmı
şvertex ve fragmentlerin
GPU’da paralel iş
lenmesini yönetir.
icat edilmedi?” sorusu yöneltilebilir. Bu sorunun yanı
tıbilgisayar grafikleri donanı
mı
nı
n
geliş
imiyle ilgilidir. 2001 yı
lıöncesinde birçok bilgisayar grafiği donanı
mısadece vertex
ve fragment iş
leme yapabilecek ş
ekilde sabit bağlantı
lı
ydı
. Burada “sabit bağlantı
lı
”
derken algoritmaları
n donanı
ma bağlıve sabit olduklarıbelirtiliyor. Yani bir programlama
dili kullanarak, grafik uygulamaları
nıdeğiş
tirmek mümkün değildi. Grafik uygulamaları
bu algoritmalarda değiş
iklikler yapabiliyordu, fakat donanı
m tasarlayı
cı
sı
nı
n tahmin
edemediği bir durum için programcı
, donanı
mıtekrar programlama yeteneğine sahip
Umut DOGAN - Bitirme Tezi - Haziran 2006
Tam bu noktada “Gerçek zamanlıbir shading dili iyi bir fikirse, neden daha önce
5
değildi. Ama bu durum günümüzde değiş
ti. Belki de bunun en önemli mimarları
ndan birisi
Cg dilidir.
2001 sonrası
nda grafik donanı
m tasarı
mıgeliş
ti ve yeni GPU’lardaki vertex ve
fragment iş
leme birimleri gerçekten programlanabilir oldu. Programlanabilir grafik
donanı
mıüretilmeden önce bunun için bir programlama dili geliş
tirmenin bir anlamıyoktu.
Günümüzde böyle bir donanı
m olduğu için bu donanı
mıkolay bir ş
ekilde programlamaya
gereksinimimiz var. C’nin CPU programlamada getirdiği kolaylı
ğı Cg, GPU
programlamada sağlamı
ş
tı
r.
Cg’den önce GPU’nun programlama özelliklerini kullanabilmek için alçak-seviyeli
assembly
dili
kullanmak
gerekiyordu.
Karmaş
ı
k emir
sözdizimi
ve
donanı
m
kaydedicilerini elle değiş
tirme zorunluluğu nedeniyle (DirectX8’deki vertex ve pixel
shaderlar ve bazıOpenGL uzantı
ları
ndaki gibi) GPU programlamak birçok geliş
tirici için
zor ve zaman alı
cıbir iş
ti. GPU teknolojisinin geliş
mesiyle assembly kodlarıbüyümeye ve
karmaş
ı
klaş
maya baş
layı
nca yüksek seviyeli bir dile gereksinim ortaya çı
ktı
. Düş
ük
seviyede programlamayla sağlanan
optimum performans
yüksek
seviyeli GPU
programlama dillerinin ortaya çı
kması
yla optimize derleyiciler tarafı
ndan sağlandı
.
Optimize derleyici, kod çı
ktı
sı
nıoptimize etmekle ve sı
kı
cıemir tarifeleme iş
lemlerini
halletmekle görevlidir. Şekil 1.1’de karmaş
ı
k GPU assembly dili kullanan bir program
Şekil 1.1: Örnek Assembly ve Cg Programları
Umut DOGAN - Bitirme Tezi - Haziran 2006
parçacı
ğıve hemen yanı
nda da uygun Cg program parçacı
ğ
ıverilmiş
tir.
6
Görüldüğü gibi donanı
m kaydedicilerine yaptı
ğıçok özel referanslar nedeniyle
assembly kodunu anlamak oldukça güçtür. Tersine, kurallara uygun yazı
lmı
şbir Cg
programıdaha taş
ı
nabilir, daha okunaklı
, hatalardan kolay ayı
klanabilir ve kolaylı
kla
tekrar kullanı
labilir bir yapı
dadı
r. Daha da önemlisi Cg dili, C gibi yüksek seviyeli bir dilde
çalı
ş
manı
n avantajları
nıve assembly koduyla yazmanı
n performansı
nısağlar.
1.1.6. Diğer Açı
lardan Cg
Cg, “küçükte programlama” mantı
ğı
na uyan bir dildir. Böyle bir dille
programlamak, C++ gibi genel amaçlıbir dilde programlamaktan daha çok verimlilik
sağ
lar. Cg, vertex ve fragment dönüş
ümleri üzerinde uzmanlaş
tı
ğıiçin yazı
lı
m
mühendisliği programları
nda kullanı
lan birçok karmaş
ı
k özelliği içermez. C++ ve Java’dan
farklıolarak Cg, sı
nı
f yapı
sı
nıve nesne tabanlıprogramlamanı
n diğer özelliklerini
desteklemez. Şu anki Cg sürümlerinde iş
aretçiler (pointer) ve bellek tahsisi
desteklenmemektedir. Cg’nin dosya girdi/çı
ktıiş
lemleri için desteği yoktur. Bu
kı
sı
tlamaları
n nedeni Cg dili değildir. Günümüz GPU’ları
nı
n yapı
sıbu özelliklerin
desteklenmesine
izin
gerçeklenebilmesine
ve
vermemektedir.
dil
yapı
sı
na
Ancak
Cg,
katı
lması
na
bu
özelliklerin
ileride
olanak
sağ
layacak
ş
ekilde
yapı
landı
rı
lmı
ş
tı
r.
Cg, dizi (array) ve yapı
ları(structure) destekler. Modern bir dilin tüm akı
ş
-kontrol
yapı
ları
na sahiptir: döngüler, koş
ullar, fonksiyon çağrı
ları
.
Cg doğal olarak vektör ve matrisleri destekler. Çünkü bu veri tipleri matematik
donanı
mları
na temel oluş
tururlar. Cg, Standard Library adıverilen bir fonksiyon
kütüphanesine sahiptir. Bu kütüphanede grafiklerle ilgili programlar yazarken gerekli olan
birçok fonksiyon bulunmaktadı
r. Örneğin Cg Standard Library, yansı
tma vektörlerini
hesaplamak için reflect adı
nda bir fonksiyon içerir.
Cg programlarıgöreli yalı
tı
mla (relative isolation) çalı
ş
ı
r. Yani herhangi bir vertex
veya fragment’in iş
lenmesinin, aynıanda iş
lenmekte olan diğer vertex veya fragment’ler
üzerinde bir etkisi yoktur. Cg programı
nı
n çalı
ş
masısı
rası
nda yan etki oluş
maz. Vertex ve
Umut DOGAN - Bitirme Tezi - Haziran 2006
iş
lemleriyle iliş
kilidir; grafik programlama ve vektör veri tiplerini destekleyen grafik
7
fragmentler arası
nda bağı
mlı
lı
ğı
n olmamasıCg programları
nı
n donanı
msal çalı
ş
ma
açı
sı
ndan yüksek derecede pipeline’lıve paralel olması
nısağlar.
1.1.7. Cg Programları
nı
n Sı
nı
rlıÇalı
ş
ma Ortamı
CPU için genel amaçlıbir program yazdı
ğı
mı
zda, eğer kurallara uymuş
sak
sorunsuz bir ş
ekilde derlenmesini bekleriz. Çünkü CPU tasarı
msal olarak genel amaçlı
programlarıçalı
ş
tı
rabilmek için gerekli kaynaklarısağlar.
Ancak GPU’da durum farklı
dı
r. Çünkü GPU özel amaçlı
dı
r. Bu nedenle bir GPU
için yazdı
ğ
ı
mı
z programı
n baş
ka GPU’larda koş
up koş
amayacağı
nıgaranti edemeyiz. Bu
nedenle Cg, donanı
m profilleri adı
nda bir özellik sunar. Her profil belli GPU mimarisi ve
grafik API’sinin birleş
iminden oluş
muş
tur. Programı
n sadece doğru olmasıyetmez, aynı
zamanda uygun profilin de seçilmişolmasıgereklidir. Öneğin bir fragment profili her bir
fragment için dörtten fazla doku oluş
turulması
na izin vermiyor olabilir. Bu durumda uygun
profili seçmezsek problemle karş
ı
laş
ı
rı
z.
Profillerle oluş
turulan sı
nı
rlandı
rmalar GPU kaynaklı
dı
r. Sı
nı
rlandı
rmanı
n nedeni
Cg değildir. NVIDIA firmasıgelecekte daha iyi GPU’lar üretildikçe bu profillerin de
güncelleneceği garantisini vermektedir. Cg programları
yla ş
u anki profillerle yazı
lmı
ş
kodlar gelecekte aynış
ekilde çalı
ş
tı
rı
labilir olacaklardı
r.
1.2. Vertexler, Fragmentlar ve Grafik Pipeline
pipeline’ıaçı
klanacaktı
r.
1.2.1. Bilgisayar Grafikleri Donanı
mı
nı
n Geliş
imi
Günümüzde bilgisayar grafikleri donanı
mıinanı
lmaz hı
zlarla geliş
iyor. Şekil 1.2’de
gösterildiği gibi bu hı
zlıgeliş
meyi sağlayan üç önemli etmen vardı
r.
Umut DOGAN - Bitirme Tezi - Haziran 2006
Bu bölümde grafik donanı
mı
nı
n tarihsel geliş
im süreci ve modern grafik donanı
mı
8
Şekil 1.2 : Grafik Donanı
mıGeliş
imini Sağlayan Etmenler
Birinci etmen, Moore yasası
dı
r. Yarıiletken endüstrisi bir mikroçip üzerinde
bulunan transistor sayı
sı
nıher 18 ayda bir ikiye katlayacağı
nıbelirtmiş
tir. Moore Yasası
olarak bilinen, bilgisayar gücünün bu ş
ekilde sabit bir sürede ikiye katlanmasıdaha ucuz
ve hı
zlıbilgisayar donanı
mıanlamı
na gelir.
İ
kinci etmen, görüntü oluş
turmanı
n paralel yapı
sı
dı
r. Etrafı
mı
zdaki dünyayısimüle
edebilmek için çok sayı
da paralel hesaplamalar yapmalı
yı
z. 3B dünyadaki görüntüleri
inanı
lmaz hı
zda ve gerçeklik oranı
nda algı
ları
z. Bilgisayar grafiklerinde de bu kavrayı
ş
noktası
na gelebilmemiz günümüz teknolojisiyle olanaksı
z görünmektedir. Ancak gün
geçtikçe görüntü kalitesi çok iyi boyutlara gelmektedir. Şansı
mı
za, görüntü üretimi paralel
bir problemdir. Paralel problemi hı
zlıbir ş
ekilde çözebilmek için problemi küçük parçalara
Üçüncü etmen ise görsel olarak uyarı
lmasıve eğlendirilmesi gereken tutkumuzdur.
Bu etmen sayesinde donanı
m teknolojisinin geliş
imini kullanarak görsel güzellikte
görüntüler yaratı
yoruz. Günümüzde animasyon film endüstrisinin geldiği nokta inanı
lmaz
boyutlardadı
r. Neredeyse her ay sinemalarda bir animasyon film gösterime girmektedir.
Bundan 8–10 yı
l kadar önce 15–20 dakikalı
k bir animasyon film yaratabilmek uzun yı
llar,
büyük bütçe ve çok sayı
da insan gücü gerektiren zor bir iş
ti. Bugün ise gerek animasyon
filmler gerekse 3B oyunlar kaliteli animasyonlarla oluş
turulabilmektedir.
Umut DOGAN - Bitirme Tezi - Haziran 2006
bölmek gereklidir.
9
Bilgisayar grafikleri donanı
mı
, diğer elemanlara nazaran çok daha hı
zlıbir ş
ekilde
ilerlemektedir. Böylece daha kaliteli görüntü üretmek daha da hı
zlıbir hale gelmektedir.
İ
ş
te bu nedenler Cg dilinin ortaya çı
kı
ş
ı
nıhı
zlandı
rmı
ş
tı
r.
1.2.2. Bilgisayar Grafikleri Donanı
mı
nı
n Dört Kuş
ağı
1990’ları
n ortaları
nda dünyanı
n en hı
zlıgrafik donanı
mı
; görüntüleri oluş
turmak ve
ekranda göstermek için birlikte çalı
ş
an birçok çipin bir araya gelmesinden oluş
uyordu. En
karmaş
ı
k bilgisayar grafikleri sistemleri farklıboardlara yayı
lmı
şdüzinelerce çipten
oluş
uyordu. Zaman geçtikçe ve yarı
iletken teknolojisi geliş
tikçe donanı
m mühendisleri
karmaş
ı
k çok sayı
da çipten oluş
an sitemleri tek bir grafik çipinde topladı
lar. Bu geliş
meler
ölçekleme nedeniyle ekonomik yönden avantaj sağ
ladı
.
Günümüzde GPU’lar, bir mikroçipte içerdikleri transistor sayı
sıbakı
mı
ndan
CPU’larıgeçmiş
lerdir. Transistor sayı
sıbir mikroçipe ne kadar bilgisayar donanı
mı
ayrı
ldı
ğı
yla ilgili kaba bir ölçümdür. Örneğin Intel’in 2.4 GHz’lik Pentium 4’ünde 55
milyon transistor vardı
r; öte yandan NVIDIA’nı
n GeForce FX GPU’sunda 125 milyondan
fazla transistor vardı
r.
NVIDIA firması
, terminolojiye GPU kelimesini “VGA denetleyicisi” terimi
PC’deki grafik donanı
mı
nıtam olarak tanı
mlamadı
ğı1990’ları
n sonunda sokmuş
tur. IBM,
1987’de VGA (Video Graphics Array) teknolojisini ilk kez piyasaya sunmuş
tu. O
zamanlar VGA denetleyicisi, bizim ş
u anda akı
lsı
z çerçeve tamponu (dumb frame buffer)
dediğimiz ş
eydi. Bu, “CPU tüm pikselleri güncellemekten sorumluydu” anlamı
na
donanı
mıtasarı
mcı
sıGPU’nun içerisine piksel güncellemelerinden sorumlu akı
llıbirimler
yerleş
tirmiş
tir.
Endüstri tarihçileri genel olarak dört GPU kuş
ağıtanı
mlarlar. Her kuş
akta GPU
performansı ve programlanabilirlik özellikleri geliş
miş
tir. Ayrı
ca her kuş
ak 3B
programlama arayüzleri olan OpenGL ve DirectX’i etkilemiş
tir. OpenGL; Windows,
Linux, UNIX ve Macintosh bilgisayarları
nda 3B programlama için bir açı
k standarttı
r.
Umut DOGAN - Bitirme Tezi - Haziran 2006
gelmekteydi. Günümüzde CPU, pikselleri nadiren doğrudan iş
ler. Bunun yerine grafik
10
DirectX ise Microsoft tarafı
ndan geliş
tirilmekte olan çoklu ortam programlama
arayüzüdür. DirectX, 3B programlama için Direct3D’yi içerir.
1.2.2.1. GPU Öncesi Dönemde Grafik Hı
zlandı
rı
cı
lar
GPU’lar ortaya çı
kmadan önce Silicon Graphics (SGI) ve Evans & Sutherland gibi
firmalar özel ve pahalıgrafik donanı
mlarıtasarladı
lar. Bu firmalar tarafı
ndan tasarlanan
grafik sistemleri günümüzde de kullanı
lan vertex dönüş
ümleri, doku kaplama gibi birçok
kavramıortaya çı
karmı
ş
tı
r. Bu sistemler bilgisayar grafikleri açı
sı
ndan önemlidir. Ancak
çok pahalıolmalarınedeniyle PC’ler ve oyun konsollarıiçin geliş
tirilmiştek çipli
GPU’ları
n baş
arı
sı
na ulaş
amamı
ş
lardı
r. Günümüzdeki GPU’lar bu sistemlerden çok daha
hı
zlıve ucuzdurlar.
1.2.2.2. Birinci Kuş
ak GPU’lar
GPU’ları
n birinci kuş
ağı(1998’e kadar) NVIDIA’nı
n TNT2’si, ATI’nin Rage’i ve
3dfx’in Voodoo3’ünü içerirler. Bu GPU’ları
n önceden dönüş
türülmüş üçgenleri
pikselleş
tirme ve bir veya iki doku uygulama özellikleri vardı
. Aynızamanda DirectX6
özellik takı
mı
nıda gerçekleş
tirdiler. Birçok 2B ve 3B uygulamayıçalı
ş
tı
rı
rken, CPU’nun
her bir pikseli güncelleme özelliğinden yararlandı
lar. Ancak bu GPU’ları
n iki önemli
kı
sı
tlamasıvardı
: Birincisi, 3B nesnelerin vertexlerini dönüş
türme yetenekleri yoktu,
vertex dönüş
ümleri CPU’da yapı
lı
yordu. İ
kincisi, dokularıbirleş
tirdikten sonra ilgili
pikselin rengini belirlemek için çok az sayı
da matematik iş
lemi vardı
.
İ
kinci kuş
ak GPU’lar (1999 – 2000) NVIDIA’nı
n GeForce 256’sıve GeForce 2’si,
ATI’nin Radeon 7500’ü ve S3’ün Savage3D’si ş
eklinde sı
ralanabilir. Bu GPU’lar 3D
vertex dönüş
ümü ve ı
ş
ı
klandı
rması(T&L) yükünü CPU’dan aldı
lar. Bu kuş
ağa kadar hı
zlı
vertex dönüş
ümü işistasyonlarıile PC’leri ayı
ran önemli özelliklerden biriydi. Hem
OpenGL hem de DirectX7 donanı
msal vertex dönüş
ümlerini desteklemektedir. Bu kuş
akta
bazımatematiksel iş
lemler geliş
tirilmişolsa da olası
lı
klar hala sı
nı
rlı
dı
r. Öte yandan, bu
Umut DOGAN - Bitirme Tezi - Haziran 2006
1.2.2.3. İ
kinci Kuş
ak GPU’lar
11
kuş
ak daha çok ayarlanabilir (configurable) olan, ama hala gerçekten programlanabilir
olmayan bir kuş
aktı
r.
1.2.2.4. Üçüncü Kuş
ak GPU’lar
Üçüncü kuş
ak GPU’lar (2001) NVIDIA’nı
n GeForce3’ünü ve GeForce 4 Ti’sini,
Microsoft’un Xbox’ı
nıve ATI’nin Radeon 8500’ünü içerirler. Bu kuş
akta OpenGL ve
DirectX7’in belirlediği vertex T&L biçimlerini kullanmak yerine GPU uygulamanı
n
vertexleri iş
lemek için emir ardı
ş
ı
klı
ğı
nıbelirlemesine izin vermiş
tir. Piksel seviyesinde
daha fazla ayarlanabilirlik vardı
r, ancak bu özellikler hala programlanabilirlik
sağ
lamamaktadı
rlar. Bu GPU’lar vertex programlanabilirliği sağladı
ğıama gerçek piksel
programlanabilirliği sağlamadı
ğıiçin geçişkuş
ağı
dı
r. DirectX8 ve OpenGL uzantı
sı
ARB_vertex_program uygulamalarda vertex seviyesi programlanabilirlik sağlamı
ş
tı
r.
DirectX8 piksel shaderlerıve değiş
ik üreticilere özgü OpenGL uzantı
ları
, fragment
seviyesi ayarlanabilirliğ
i geniş
letmiş
tir.
1.2.2.5. Dördüncü Kuş
ak GPU’lar
Dördüncü ve ş
u anki kuş
ak olan GPU’lar (2002 ve sonrası
) CineFX mimarisine
sahip NVIDIA’nı
n GeForce FX ailesini, ATI’nin Radeon 9700’ünü içerirler. Bu GPU’lar
hem vertex seviyesi hem de piksel seviyesi programlanabilirlik sağlarlar. Bu kuş
akta
CPU’nun vertex ve piksel dönüş
ümlerindeki yükü büyük oranda GPU’ya kaydı
rı
lmı
ş
tı
r.
DirectX9 ve değ
iş
ik OpenGL uzantı
larıbu GPU’ları
n vertex seviyesinde ve piksel
seviyesinde programlanabilirliğ
ini sağ
lamı
ş
tı
r. Şekil 1.3de farklıkuş
aklara ait NVIDIA
Tabloda kı
yaslama yapı
lı
rken ş
u terimler kullanı
lmı
ş
tı
r:
Süreç – her bir mikroçipi üretmek için kullanı
lan yarı
iletkenin mikron olarak
minimum boyutudur.
Transistör – Çiplerin tasarı
m ve üretim karmaş
ı
klı
ğı
, milyon olarak verilmiş
yaklaş
ı
k değerdir.
Antialiasing doldurma oranı– GPU’nun pikselleri doldurma yeteneği, saniyede
milyon olarak 32 bit RGBA pikseli ş
eklinde verilmiş
tir.
Umut DOGAN - Bitirme Tezi - Haziran 2006
GPU’larıve özellikleri gösterilmiş
tir.
12
Poligon oranı– GPU’nun üçgen çizebilme yeteneği. Saniyede çizilen milyon
olarak verilmişüçgen sayı
sı
dı
r.
Kuş
ak
Yı
l
Ürün Adı
Süreç
Transistör
Antialiasing
Poligon
Dold. Oranı
Oranı
Birinci
1998
RIVA TNT
0.25 µ
7M
50 M
6M
Birinci
1999
RIVA TNT2
0.22 µ
9M
75 M
9M
İ
kinci
1999
GeForce 256
0.22 µ
23 M
120 M
15 M
İ
kinci
2000
GeForce2
0.18 µ
25 M
200 M
25 M
Üçüncü
2001
GeForce3
0.15 µ
57 M
800 M
30 M
Üçüncü
2002
GeForce4 Ti
0.15 µ
63 M
1200 M
60 M
Dördüncü
2003
GeForce FX
0.13 µ
125 M
2000 M
200 M
Şekil 1.3: FarklıKuş
aklardan NVIDIA GPU'larıİ
çin Performans Tablosu
Gelecekte
GPU’lar
ş
u
anki
GPU’ları
n programlanabilirlik
özelliklerini
geliş
tireceklerdir. Cg de bu geliş
melere sürekli uyumlu olacağı
nı
n garantisini vermiş
tir.
1.2.3 Grafik Donanı
mıPipeline’ı
Pipeline, sabit sı
rayla paralel bir ş
ekilde çalı
ş
an aş
amalar (stages) dizisidir. Her
aş
ama girdisini bir önceki aş
amadan alı
r ve çı
ktı
sı
nıbir sonraki aş
amaya gönderir. Pipeline
kavramı
; belli bir anda her otomobilin farklıbir aş
amada olduğ
u, düzinelerce otomobilin
aynıanda üretildiği otomobil üretim tesislerindeki çalı
ş
ma mantı
ğı
yla açı
klanabilir. Grafik
donanı
mıpipeline’ıçok sayı
da vertex, geometrik primitifler ve fragmentler üzerinde
pipeline’lıçalı
ş
ma biçimiyle çalı
ş
ı
r.
gösterilmiş
tir. 3B uygulama, geometrik primitifler olarak toplanmı
şvertex dizisini GPU’ya
gönderir: tipik çokgenler, çizgiler ve noktalar… Şekil 1.5’te görüldüğ
ü gibi geometrik
primitifleri gösterebilmenin birçok yolu vardı
r. Her vertex’in bir durum değeri vardı
r.
Ayrı
ca her vertex renk, ikincil (veya specular) renk, bir veya daha fazla doku koordinatı
takı
mı
, normal vektörü gibi diğer birçok özelliğe de sahiptir. Normal vektörü, yüzeyin
vertex ile hangi yönde yüzleş
tiğini belirtir ve genelde ı
ş
ı
klandı
rma hesaplamaları
nda
kullanı
lı
r.
Umut DOGAN - Bitirme Tezi - Haziran 2006
Şekil 1.4’te günümüzdeki GPU’lar tarafı
ndan kullanı
lan grafik donanı
mıpipeline’ı
13
Şekil 1.4: Grafik Donanı
mıPipeline’ı
1.2.3.1. Vertex Dönüş
ümü
Grafik donanı
m pipeline’ı
nda ilk iş
lem aş
amasıvertex dönüş
ümüdür. Vertex
dönüş
ümü her vertex üzerinde bir dizi matematiksel iş
lemler gerçekleş
tirir. Bu iş
lemlerden
bazı
larıpikselleş
tirici tarafı
ndan kullanı
labilecek ş
ekilde vertex koordinatları
nıekran
koordinatları
na dönüş
türmek, doku kaplama için doku koordinatları
nıüretmek ve vertex’in
Şekil 1.5: Geometrik Primitifler
Umut DOGAN - Bitirme Tezi - Haziran 2006
rengini belirlemek için onu ı
ş
ı
klandı
rmak ş
eklinde sı
ralanabilir.
14
1.2.3.2. Primitif Montajıve Pikselleş
tirme
Dönüş
müş vertexlerin sonraki aş
amaya doğru akmaları
na primitif montajı
(primitive assembly) ve pikselleş
tirme (rasterization) denir. İ
lk önce primitif montajı
adı
mı
nda vertex dizisiyle birlikte gelen geometrik primitifler birleş
tirme bilgisine göre
vertexlere dönüş
türülür. Bu iş
lem sonucunda üçgenler, noktalar, çizgiler dizisi oluş
ur.
Primitifler bakı
şpenceresine göre (view frustum, 3B uzayı
n görülebilir kı
smı
) kı
rpı
lmayı
(clipping) gerektirebilir. Pikselleş
tirici, poligonlarıgörünen alanı
n içinde veya dı
ş
ı
nda
kalması
na göre yok sayabilir. Bu iş
leme de culling denir.
Clipping ve culling aş
amaları
ndan sonra geri kalan poligonları
n pikselleş
tirilmesi
gereklidir. Pikselleş
tirme iş
lemi bir geometrik primitif tarafı
ndan çevrelenmişpikseller
topluluğunu belirleme iş
lemidir. Poligonlar, çizgiler ve noktalar her bir primitifin
kuralları
na göre pikselleş
tirilir. Pikselleş
tirme sonucunda fragment olarak bilinen piksel
gruplarıoluş
ur. Bir primitifin vertex sayı
sı
yla, pikselleş
tirildikten sonra üretilen
fragmentlerin sayı
sıarası
nda bir iliş
ki yoktur. Örneğin sadece üç tane vertexten oluş
an bir
üçgen tüm ekranıkaplayı
p milyonlarca fragment oluş
turabilir.
Fragment ve piksel farklıkavramlardı
r. Piksel kelimesi, görüntü elemanı(picture
element) kelimesinin kı
saltı
lmı
ş
ı
dı
r ve çerçeve tamponunun belli bir noktadaki renk,
derinlik ve o yerle ilgili diğer bilgilerini gösterir. Fragment ise belli bir pikseli güncellemek
için gerekli durumdur.
Fragment terimi kullanı
lmaktadı
r çünkü pikselleş
tirme üçgen gibi her bir geometrik
pikselin bulunduğu yer, derinlik değeri ve renk, ikincil renk, bir veya daha fazla doku
koordinat kümeleri gibi interpole edilmişbazıparametrelere sahiptir. Bu interpole edilmiş
çeş
itli parametreler, fragment üretmede kullanı
lan belli bir geometrik primitifi oluş
turan
dönüş
türülmüşvertexlerden türetilir.
Fragment, “potansiyel piksel” olarak düş
ünülebilir. Eğer fragment çeş
itli
pikselleş
tirme testlerini geçerse bu fragment, çerçeve tamponundaki ilgili pikseli günceller.
Umut DOGAN - Bitirme Tezi - Haziran 2006
primitifi, primitifin kapladı
ğıher pikseli, piksel-boyutlu fragmentlere böler. Bir fragment
15
1.2.3.3. İ
nterpolasyon, Doku Kaplama, Renklendirme
Bir primitif, sı
fı
r veya daha fazla fragment’a pikselleş
tirilirse interpolasyon, doku
kaplama, renklendirme aş
amasıfragment değerlerini uygun ş
ekilde interpole eder, gerekli
doku kaplama ve matematik iş
lemleri dizisini gerçekleş
tirir ve her fragment’in kesin
rengini belirler. Fragment’in kesin rengini belirledikten sonra bu aş
ama aynızamanda yeni
derinlik belirleyebilir ve hatta fragment’in, çerçeve tamponunun ilgili pikselini
güncellemesini engelleyebilir. Bu aş
ama bazıfragment’leri yok sayabileceği için aldı
ğıher
girdi fragment için bir veya sı
fı
r renkli çı
ktıfragmenti verir.
1.2.3.4. Tarama İ
ş
lemleri
Tarama (raster) iş
lemleri aş
aması
, çerçeve tamponu güncellenmeden önce hı
zlıbir
ş
ekilde her fragment için son iş
lemler dizisini gerçekleş
tirir. Bu iş
lemler OpenGL ve
DirectX’in standart kı
sı
mları
dı
r. Bu adı
mda gizli yüzeyler derinlik testi (depth testing)
denilen bir yöntemle elemine edilir. Blending, stencil-based shadowing gibi diğer efektler
de bu aş
amada gerçekleş
tirilir.
Tarama iş
lemleri aş
amasıscissor, alpha, stencil ve depth testleri için her fragmenti
kontrol eder. Bu testler fragment’in son renk derinliğ
ini, piksel konumunu, pikselin
derinlik ve stencil değerleri gibi her bir piksel için olan değerleri gerektirir. Eğer herhangi
bir test baş
arı
sı
zlı
kla sonuçlanı
rsa pikselin renk değeri güncellenmez ve fragment atı
lı
r.
Test baş
arı
yla geçilirse pikselin derinlik değ
eri yerine fragment’in derinlik değeri atanı
r.
Testlerden sonra blending iş
lemiyle fragmentin son rengi ilgili pikselin renk değeriyle
harmanlaş
mı
şrenk yazı
lı
r. Şekil 1.6’da bu iş
lemler ardı
ş
ı
klı
ğıgörülmektedir. Şekilden
görüldüğü gibi tarama iş
lemleri aş
amasıpipeline aş
amalarıserisidir.
1.2.3.5. Grafik Pipeline’ıGörselleş
tirme
Şekil 1.7’de grafik pipeline betimlenmiş
tir. Şekilde iki üçgen pikselleş
tirilmiş
tir.
İ
ş
lem vertexlerin dönüş
türülmesi ve renklendirilmesiyle baş
lar. Daha sonra primitif
assembly aş
aması
nda noktalıçizgilerde gösterildiği gibi vertexlerden üçgenler yaratı
lı
r.
Umut DOGAN - Bitirme Tezi - Haziran 2006
birleş
tirilir. Son olarak frame buffer’a yazma iş
lemiyle pikselin renk değeri olarak
16
Bundan sonra pikselleş
tirici (rasterizer), üçgenleri fragmentlerle doldurur. Son olarak
vertexlerin register değerleri interpole edilerek doku kaplama ve renklendirme için
kullanı
lı
r. Birkaç tane vertex’ten birçok fragment elde edildiği görülüyor.
Şekil 1.6: Standart OpenGL ve Direct3D Tarama İ
ş
lemleri
Şekil 1.7: Grafik Pipeline'ı
n Görselleş
tirilmesi
Günümüzde grafik
donanı
mı tasarı
mı
nda yönelim
GPU’nun
daha fazla
programlanabilir olması yönündedir. Şekil 1.8’de programlanabilir bir GPU’nun
pipeline’ı
nda gerçekleş
en vertex ve fragment iş
leme aş
amalarıgörülüyor.
Şekil 1.8, Şekil 1.4’ten daha ayrı
ntı
lı
dı
r. Daha da önemlisi vertex ve fragment
iş
leme
adı
mları
nı programlanabilir
birimlere
ayrı
lmı
ş ş
ekilde
göstermektedir.
Umut DOGAN - Bitirme Tezi - Haziran 2006
1.2.4. Programlanabilir Grafik Pipeline’ı
17
Programlanabilir vertex iş
lemcisi, Cg vertex programları
nı
n üzerinde koş
tuğu donanı
mdı
r.
Benzer ş
ekilde, programlanabilir fragment iş
lemcisi ise Cg fragment programları
nı
n
üzerinde koş
tuğu donanı
mdı
r.
Şekil 1.8: Programlanabilir Grafik Pipeline
Daha önce de belirtildiği gibi GPU tasarı
mızaman içerisinde geliş
ti ve vertex ve
fragment iş
lemciler sadece ayarlanabilir olmaktan çı
kı
p programlanabilir hale dönüş
tüler.
1.2.4.1. Programlanabilir Vertex İ
ş
lemcisi
Şekil 1.9 programlanabilir vertex iş
lemcisinin akı
şdiyagramı
nıgöstermektedir.
Vertex iş
lemenin veri-akı
şmodeli her bir vertex’in konum, renk, doku koordinatlarıgibi
bütün emirleri alı
r ve vertex program sonlanı
ncaya kadar çalı
ş
tı
rı
r. Emirler konum, normal
ve renk gibi vektör değerlerini içeren farklıkaydedici (register) bankları
na eriş
irler. Vertex
öznitelik kaydedicileri (attribute registers) salt okunur özelliktedirler ve vertex için
uygulama tarafı
ndan belirlenmişdeğerleri içerirler. Geçici kaydediciler (temporary
registers) hem okunup hem yazı
labilirler ve ara değerleri hesaplamak için kullanı
lı
rlar.
Çı
ktısonuç kaydedicileri (output result registers) salt yazı
lı
rdı
rlar. Program sonuçları
nıbu
kaydedicilere yazmakla sorumludurlar. Vertex programısonlandı
ğızaman çı
ktısonuç
Umut DOGAN - Bitirme Tezi - Haziran 2006
özelliklerinin vertex iş
lemciye yüklenmesiyle baş
lar. Daha sonra vertex iş
lemci, sı
rayla
18
kaydedicileri dönüş
türülmüşyeni vertex’i içerir. Üçgen kurma ve pikselleş
tirmeden sonra,
her kaydedicinin interpole edilmişdeğerleri fragment iş
lemciye geçirilir.
Şekil 1.9: Programlanabilir Vertex İ
ş
lemci Akı
şDiyagramı
Vertex iş
leme adı
mları
nı
n birçoğu, sı
nı
rlısayı
da iş
lem çeş
idi kullanı
r. İ
ki, üç, dört
bileş
enli kayan noktalıvektörler üzerinde iş
lem yapabilen vektör matematik iş
lemleri
maksimumdur. Vektör olumsuzlama ve component-wise swizzling (vektör bileş
enlerinin
rasgele yeniden sı
ralanması
) için donanı
m desteği bu vektör matematik emirlerini
olumsuzlama, çı
karma ve vektör çarpı
mı
nıiçerecek ş
ekilde geneller. Component-wise
write mask tüm emirlerin çı
ktı
ları
nıkontrol etmekle yükümlüdür. Tersi (reciprocal) ve
reciprocal karekök iş
lemlerini vektör çarpı
mıve iç çarpı
mlarla birleş
tirmek sı
rası
yla
vektör-skaler bölmeyi ve vektör normalizasyonunu etkinleş
tirir. Üstel, logaritmik ve
trigonometrik yaklaş
ı
mlar ı
ş
ı
klandı
rma, sis ve geometrik hesaplamalarıkolaylaş
tı
rı
r. Özel
Umut DOGAN - Bitirme Tezi - Haziran 2006
zorunludur. Bu iş
lemler toplama, çarpma, çarpma-toplama, iç çarpı
m, minimum ve
19
emirler sayesinde ı
ş
ı
klandı
rma ve zayı
flatma (attenuation) fonksiyonlarıdaha kolay
hesaplanabilir hale gelirler.
Bundan baş
ka, sabitlerin göreli adreslenmesi, dallanma ve döngüler için akı
ş
kontrol desteği gibi özellikler son zamanlardaki vertex iş
lemcilerde bulunmaktadı
r.
1.2.4.2. Programlanabilir Fragment İ
ş
lemcisi
Programlanabilir Fragment iş
lemcileri, programlanabilir vertex iş
lemcilerle hemen
hemen aynımatematik iş
lemlerine ihtiyaç duyarlar, ayrı
ca doku kaplama iş
lemlerini de
desteklerler. Doku kaplama iş
lemleri iş
lemcinin doku görüntüsüne doku koordinatları
nı
kullanarak eriş
mesini sağlar ve daha sonra doku görüntüsünün filtrelenmişbir örneğini
döndürür.
Yeni GPU’lar kayan-noktalıdeğerler için tam desteğe sahiptir, eski GPU’larda ise
sı
nı
rlıoranda sabit-noktalıveri türleri vardı
r. Kayan noktalıiş
lemlerin olması
na rağmen,
düş
ük duyarlı
klıveri türleri kullanı
larak daha etkin bir ş
ekilde yapı
labilir. Günümüzdeki
GPU’lar birçok fragmenti bir kerede iş
leyebilecek ş
ekilde rasgele dallanmaya sahip
değillerdir, ancak donanı
mı
n geliş
mesiyle ilerleyen yı
llarda bu özellik eklenebilir.
Cg, dallanma (branching) ve yineleme (iterate) yapı
ları
nısimüle etmek için koş
ullu
atama ve döngü açma (loop unrolling) iş
lemlerini kullanarak fragment programları
yazmamı
za olanak sağlar.
diyagramıverilmiş
tir. Programlanabilir vertex iş
lemcilerdeki gibi veri akı
ş
ı
, program
sonlanı
ncaya kadar sı
rayla belli emirlerin koş
ulması
nıgerektirir. Yine aynış
ekilde girdi
kaydedicileri vardı
r. Ancak vertex özelliklerinden farklıolarak fragment iş
lemcisinin salt
okunur girdi kaydedicileri, fragment’in primitiflerinin her bir vertex için parametrelerinden
türetilmiş
, interpole edilmişher bir fragment için parametreleri içerirler. Yaz/oku geçici
kaydedicileri ara değerleri tutarlar. Salt-yazı
lı
r çı
ktıkaydedicilerine yapı
lan yazma
iş
lemleri fragmentin rengi ve opsiyonel olarak yeni derinliği olurlar. Fragment programı
emirleri doku alı
mları
nı(fetch) içerirler.
Umut DOGAN - Bitirme Tezi - Haziran 2006
Şekil 1.10’da günümüzde kullanı
lan programlanabilir fragment iş
lemcilerin akı
ş
20
Şekil 1.10: Programlanabilir Fragment İ
ş
lemci Akı
şDiyagramı
1.2.5. Cg; Vertex ve Fragment Programlanabilirliği Sağlar
Uygulama programcı
sı
; GPU’daki bu iki programlanabilir iş
lemcinin her birine,
algoritması
nıGPU donanı
mı
nı
n çalı
ş
tı
rabileceği bir dile dönüş
türmek için gerekli dili ve
derleyiciyi sağlamaktı
r. Cg sayesinde programcıŞekil 1.9 ve 1.10’da belirtilen seviyelerde
program yazmak yerine C’ye benzeyen yüksek seviyeli bir dille program yazabilir.
Umut DOGAN - Bitirme Tezi - Haziran 2006
çalı
ş
tı
rı
labilmesi için bir program oluş
turmalı
dı
r. İ
ş
te Cg’nin buradaki görevi, shading
21
1.3. Cg’nin Tarihsel Geliş
imi
Cg dili teknolojisini genel olarak, Şekil 1.11’de gösterilen kaynaklardan miras
almı
ş
tı
r. Sözdizimi ve anlambilim özellikleri, genel amaçlıC programlama dilinden
mirastı
r. Ayrı
ca, Renderman ve üniversiteler tarafı
ndan üretilmişdiğer çevrimdı
ş
ıshading
dillerinden birçok kavram içermektedir. Son olarak, gerçek zamanlıüç boyutluluk
sağ
layabilmek için gerekli grafiksel fonksiyonelliği OpenGL, Direct3D gibi programlama
arayüzlerinden almı
ş
tı
r.
Şekil 1.12’de Cg’nin tasarı
mısı
rası
nda ilham alı
nan genel amaçlıprogramlama
dilleri, 3B API’leri ve shading dilleri gösterilmiş
tir.
Umut DOGAN - Bitirme Tezi - Haziran 2006
Şekil 1.11: Cg'nin Teknolojisini Miras Aldı
ğıKaynaklar
22
Şekil 1.12: Cg'nin Geliş
tirilme Sürecinde Esinlenilen Kaynaklar
1.3.1. Cg ve HLSL’yi Geliş
tirmek İ
çin NVIDIA ve Microsoft İ
ş
birliği
NVIDIA ve Microsoft, Cg dilini geliş
tirmek için birlikte çalı
ş
tı
lar. Microsoft benzer
özelliklerdeki kendi ürününe High-Level Shading Language (HLSL) ismini vermiş
tir.
HLSL ve Cg birçok özellikleri ortak olduğundan aynıdil olarak tanı
mlanabilirler. HLSL,
bileş
enidir. Cg ise bütün 3B programlama arayüzlerinden bağı
msı
zdı
r ve hem Direct3D
hem OpenGL ile tümüyle bütünleş
ik bir ş
ekilde çalı
ş
abilir. Kurallara uygun yazı
lmı
şbir
Cg uygulaması
, bir kere yazı
lı
p hem OpenGL hem de Direct3D ile çalı
ş
tı
rı
labilir.
NVIDIA’nı
n Cg’si tüm 3B programlama arayüzleri ve iş
letim sistemiyle uyumlu
bir ş
ekilde çalı
ş
maktadı
r. Cg; Windows, Linux veya Mac OS X iş
letim sistemlerinden
herhangi biriyle, Xbox gibi oyun konsolları
yla veya gömülmüş(embedded) 3B donanı
m
platformuyla rahatlı
kla çalı
ş
abilmektedir. Cg programlarıbirçok donanı
m üreticisinin
Umut DOGAN - Bitirme Tezi - Haziran 2006
Microsoft’un DirectX API’sinin bir parçası
dı
r. Direct3D, DirectX API’sinin 3B
23
donanı
mı
yla çalı
ş
maktadı
r çünkü Cg baş
arı
lıbir ş
ekilde Direct3D veya OpenGL üzerinde
katman oluş
turur. Cg programları3DLabs, ATI, Matrox, NVIDIA gibi birçok büyük grafik
donanı
mıfirması
nı
n programlanabilir GPU’sunda sorunsuz bir ş
ekilde çalı
ş
abilmektedir.
Cg dilinin çok sayı
da donanı
m üreticisi tarafı
ndan desteklenmesi, çok sayı
da
API’de kullanı
labilmesi, çok sayı
da platformda çalı
ş
masıbu dili programlanabilir GPU’lar
için program yazarken kullanı
labilecek en iyi dil konumuna sokmaktadı
r.
1.3.2. Etkileş
imli Olmayan Shading Dilleri
RenderMan arayüz standardı
, en çok bilinen etkileş
imli olmayan shading dili olarak
karş
ı
mı
za çı
kmaktadı
r. Pixar firmasıbu dili, 1980’lerin sonunda filmlerde yüksek kalitede
bilgisayar animasyonlarıkullanabilmek için üretti. Pixar, RenderMan’le birlikte PRMan
(PhotoRealistic RenderMan) adı
nda çevrimdı
ş
ıbir rendering sistem üretti. Renderman
Shading Dili bu sistemin sadece bir bileş
eniydi.
1.3.2.1. Shade Ağaçları
Render Man Shading Dili, ‘shade ağaçları
’ fikrinden esinlenmiş
tir. Rob Cook
tarafı
ndan 1984’te SIGGRAPH’ta shade ağaçlarıhakkı
nda bir makale yayı
nlanı
yor. Shade
ağaçları
nı
n temel mantı
ğı
, birçok shading iş
lemlerini ağaç yapı
sı
nda düğümler halinde
organize etmektedir. Şekil 1.13’de bakı
r renkli bir yüzeyi render etmek için gerekli shade
ağacıgösterilmiş
tir. Yaprak düğümler, shade ağacı
na girdi değerleridir. Yaprak olmayan
düğ
ümler ise basit shading iş
lemlerini temsil etmektedir. Rendering iş
lemi sı
rası
nda
Renderer, shade ağacı
nıdeğerlendirmek için en üst düğümdeki shading iş
lemini uygular.
Ancak, verilen bir düğümün değerlendirilebilmesi için önce çocuk düğ
ümlerin
değerlendirilmesi gerekmektedir. Bu iş
lemler rekürsif bir biçimde tüm shade ağacı
değerlendirilinceye
kadar
sürer.
Yüzeyde
verilen
bir
noktadaki
shade
ağacı
değerlendirilmesi o noktanı
n rengini verir.
Shade ağacı
, çok hı
zlıbir ş
ekilde büyüdüğü için ekrandaki tüm nesne ve sahnelerin
bir anda render edilmesine olanak sağlamaz.
Umut DOGAN - Bitirme Tezi - Haziran 2006
renderer, yüzeyin rengini belirlemek için, verilen yüzeyle shade ağ
acı
nıdeğerlendirir.
24
Şekil 1.13: Rob COOK'un Makalesini Temel Alan Bir Shade Ağacı
Shade ağacıdiyagramlarıshading iş
lemlerinin veri-akı
ş
ı
nıgörmek için çok
kullanı
ş
lı
dı
r. Ancak eğer shade ağaçlarıkarmaş
ı
ksa diyagramlar anlaş
ı
lmaz olacaktı
r.
Pixar’daki araş
tı
rmacı
lar her shade ağacı
nı
n bir çeş
it sı
nı
rlıprogram olduğunu keş
fetmiş
ler
ve bu keş
if yeni bir programlama dili türü olan shading dilinin doğması
na neden olmuş
tur.
1.3.2.2. Renderman Shading Dili
RenderMan Shading Dili, shade ağaçları
n büyümesi sonucu oluş
muş
tur.
RenderMan, gerçek zamanlıolmayan shading dilleri arası
nda en çok kullanı
lan ve en çok
bilinenidir. 1990’ları
n sonunda yeniden gözden geçirilmişve geliş
tirilmiş
tir.
Umut DOGAN - Bitirme Tezi - Haziran 2006
Renderman Shading dili çevrimdı
ş
ı(gerçek zamanlıolmayan) bir shading dilidir.
25
1.3.2.3. Donanı
ma Uygun Shading Dilleri
Bir algoritmanı
n donanı
msal olarak etkin bir ş
ekilde gerçeklenmesi, her aş
amanı
n
sadece bir önceki ve sonraki aş
amalarla bağlantı
lıolduğ
u pipelinelıbir yapı
yla
oluş
turulması
na bağ
lı
dı
r.
Önceki baş
lı
klarda açı
klanan vertex-tabanlı ve fragment-tabanlı pipelinelar
donanı
ma uygun yapı
lardı
r. Ancak PhotoRealistic Renderman’de kullanı
lan Reyes
algoritmasıetkin donanı
m gerçeklemesi için uygun değildir çünkü yüksek oranda
geometrik iş
lemler yapar. ÇağdaşGPU’ları
n tümü vertex ve fragment tabanlıgrafik
pipeline içerirler.
North Carolina Üniversitesi’ndeki araş
tı
rmacı
lar, 1990’ları
n ortası
nda PixelFlow
adı
nda bir programlanabilir grafik donanı
mımimarisi geliş
tirmeye baş
ladı
lar. Bu proje
bilgisayar grafikleri alanı
nda yeni bir konu olan donanı
ma uygun shading dilleri
geliş
tirilmesiyle ilgili projeleri tetikledi. Ancak, PixelFlow çok pahalı
ydıve ticari olarak
baş
arı
sı
zlı
ğa uğ
radı
.
Sonraki
yı
llarda
Silicon
Graphics’teki
araş
tı
rmacı
lar
shaderları OpenGL
rendering’in çoklu geçiş
lerine (multiple pass) çevirmeye yarayan bir sistem üzerinde
çalı
ş
tı
lar. O dönemki OpenGL donanı
mıgünümüz GPU’larıgibi programlanabilir
olmaması
na rağmen OpenGL Shader sistemi shader’dan istenen birçok rendering
geçiş
lerini yapabilmiş
tir.
Pat Hanrahan isimli araş
tı
rmacı
lar özel olarak ikinci ve üçüncü kuş
ak GPU’lar için bir
shading dili geliş
tirdiler. Bu dil Stanford Real-Time Shading Language (RTSL) olarak
bilinir ve RTSL’de yazı
lmı
şshaderlarıbir veya daha fazla OpenGL rendering geçiş
inde
derleyebilmektedir.
Stanford’daki bu araş
tı
rma, NVIDIA firması
nıticari özellikli ve donanı
ma uygun
bir shading dili üretmeye teş
vik etti. Bill Mark, bugün Cg dediğimiz shading dilini
oluş
turmak için 2001 yı
lı
nda NVIDIA ekibine katı
ldıve çalı
ş
malarıyönetti. Bu süre
Umut DOGAN - Bitirme Tezi - Haziran 2006
Stanford Üniversitesi’ndeki Kekoa Proudfoot, Bill Mark, Svetoslav Tzvetkov ve
26
içerisinde NVIDIA, ortak dil sözdizimi ve özellikler konusunda Microsoft ile birlikte
çalı
ş
tı
.
1.3.3. Üç Boyutlu Grafikler için Programlama Arayüzleri
Cg üzerindeki üçüncü etki 3B programlama arayüzleri DirectX ve OpenGL
kaynaklı
dı
r. Bu programlama arayüzlerinin Cg üzerinde etkisi bir sonraki bölümde
anlatı
lacaktı
r.
1.4. Cg Ortamı
Cg, üç boyutlu (3B) karmaş
ı
k sahneleri programlanabilir GPU’larla gerçek zamanlı
bir ş
ekilde rendering için gerekli tüm donanı
m ve yazı
lı
m altyapı
sı
nı
n elemanları
ndan
sadece birisidir. Bu bölümde Cg’nin gerçek 3B uygulamalar ve oyunlarla nası
l etkileş
tiği
açı
klanmı
ş
tı
r.
1.4.1. Standart 3B Programlama Arayüzleri: OpenGL ve Direct3D
GPU öncesi dönemde PC’deki 3B grafik üretiminde, 3B bir sahneyi üretmek için
gerekli tüm vertex dönüş
ümlerini ve piksel-itme (pixel-pushing) görevlerini CPU
üstleniyordu. Grafik donanı
mı
nda sadece ekranda gösterilecek piksel tamponları
bulunuyordu. Programcı
lar kendi 3B grafik rendering algoritmaları
nıyazı
lı
msal olarak
oluş
turmak zorundaydı
lar. Vertex ve fragment iş
leme eskiden programlanabilir yapı
daydı
denilebilir. Ama burada ince bir ayrı
ntıvardı
: 3B efektler oluş
turmak için CPU çok yavaş
Günümüzde, 3B uygulamalar, CPU’ya dayalıkendi 3B rendering algoritmaları
nı
oluş
turmak zorunda değiller. Bunun yerine standart 3B programlama arayüzleri olan
OpenGL veya Direct3D’yi kullanarak GPU’nun rendering komutları
na eriş
ebiliyorlar.
Umut DOGAN - Bitirme Tezi - Haziran 2006
kalı
yordu.
27
1.4.1.1. OpenGL
1990’ları
n baş
ı
nda, Silicon Graphics firması
, büyük bilgisayar grafik sistem
üreticilerinin oluş
turduğu OpenGL Architecture Review Board (ARB) koordinasyonunda
OpenGL dilini geliş
tirdi. İ
lk baş
larda OpenGL sadece güçlü UNIX grafik iş
istasyonları
nda
çalı
ş
ı
yordu. Daha sonra ARB’nin kurucu üyelerinden Microsoft, OpenGL’i Windows NT
iş
letim sisteminde çalı
ş
abilecek ş
ekilde geliş
tirdi. Microsoft, bu desteği daha sonra bütün
masaüstü iş
letim sistemleri için sağ
ladı
.
OpenGL tek bir iş
letim sistemine bağlıdeğildir: Unix, Windows ve Mac OSX
üzerinde çalı
ş
abilir. OpenGL geniş
leyebilir özelliktedir, yani OpenGL geliş
tiricileri
OpenGL’e ek özellikler ekleyebilirler. Günümüzde OpenGL uzantı
larısayesinde GPU’nun
birçok özelliğine eriş
ilebilmektedir.
1.4.1.2. Direct3D
Microsoft Direct3D ortamı
nı
, 1995 yı
lı
nda DirectX’in bir parçası olarak
geliş
tirmeye baş
ladı
. Direct3D API, Windows üzerinde çalı
ş
an bilgisayar oyunlarıiçin en
çok kullanı
lan grafik API’sidir. DirectX 9 sürümünden itibaren Cg’nin Microsoft sürümü
olan HLSL, DirectX API’sinin bir parçasıhaline geldi.
1.4.2. Cg Derleyicisi ve Runtime’ı
Hiçbir GPU, Cg programları
nıdoğrudan çalı
ş
tı
ramaz. Derleme adıverilen bir
Cg programı
nıuygulamada kullanı
lan 3B programlama arayüzü (OpenGL veya Direct3D)
tarafı
ndan kabul edilecek biçime dönüş
türür. Daha sonra uygulama, dönüş
türülmüşhalini
tekrar dönüş
ümden geçirir. Bu aş
amada uygun OpenGL ve Direct3D komutları
kullanı
larak GPU’nun anlayabileceğ
i bir ş
ekle dönüş
türülür. Son olarak, OpenGL veya
Direct3D sürücüsü, programı
mı
zıGPU’nun gerektirdiği biçime dönüş
türür.
Bu dönüş
ümün detaylarıGPU’nun ve 3B programlama arayüzünün yeteneklerine
bağlı
dı
r. Bazen GPU’lar Cg programları
mı
zıçalı
ş
tı
rmayabilir, bunun nedeni GPU’nun Cg
Umut DOGAN - Bitirme Tezi - Haziran 2006
iş
lemle Cg programlarıGPU’nun çalı
ş
tı
rabileceği biçime dönüş
türülür. Cg derleyicisi önce
28
programı
nı
n istediği donanı
m desteğini sağlamaması
dı
r. Örneğin eğer Cg fragment
programı
mı
z derlenmiyorsa bunun nedeni programı
mı
zda, kullandı
ğı
mı
z GPU’nun
desteklediği doku kaplama birimi sayı
sı
nıaş
mı
şolmamı
z olabilir.
1.4.2.1. Dinamik Derleme Desteği
C veya C++ gibi bir dille programı
mı
zıderlediğimiz zaman derleme iş
lemi
çevrimdı
ş
ı(offline) bir süreçtir. Derleyicimiz programı
mı
zıCPU’nun çalı
ş
tı
rabileceğ
i
biçime dönüş
türür. Programı
mı
z bir kere derlendiğinde, eğer program kodunu
değiş
tirmeyeceksek tekrar derlememize gerek yoktur. Bu iş
leme statik derleme denir.
Cg ise farklıbir biçimde çalı
ş
ı
r, çünkü statik derlemeyi desteklediği gibi dinamik
derlemeyi de destekler. Cg derleyicisi ayrı bir program değildir, Cg runtime
kütüphanesinin bir parçası
dı
r. Cg kullanan 3B uygulama ve oyunlar Cg runtime ile
linklenmelidir. Daha sonra Cg kullanan uygulamalar Cg programları
nıderleyip çalı
ş
tı
rmak
için tümü cg öneki ile baş
layan Cg runtime yordamları
nıçağı
rı
rlar. Dinamik derleme Cg
programları
nı
n kullanı
cı
nı
n makinesindeki GPU’ya özgü bir ş
ekilde optimize edilmesini
sağ
lar.
1.4.2.2. 3B API’lere Özgü Cg Kütüphaneleri: CgGL, CgD3D
Cg çekirdekteki Cg runtime’ı
na ek olarak iki yakı
n iliş
kili kütüphane daha sağlar.
Eğer uygulamamı
z OpenGL kullanı
yorsa, Cg programı
mı
zıOpenGL sürücülerine
dönüş
türmek için CgGL kütüphanesini kullanmamı
z gereklidir. Benzer ş
ekilde eğer
CgGL ya da CgD3D kullanı
rı
z, her ikisini birden kullanamayı
z. Çünkü birçok uygulama
ya Direct3D ya da OpenGL kullanı
r, ikisini birden kullanmaz.
CgGL ve CgD3D kütüphaneleri, Cg derleyicisini içeren çekirdek Cg runtime
kütüphanesinden oldukça küçüktürler. Görevleri Cg programları
nıçalı
ş
ma zamanıiçin
ayarlamada uygun OpenGL ve Direct3D çağrı
ları
nıyapmaktı
r. Bu çağrı
lar sayesinde Cg
programı
mı
z GPU’nun anlayabileceğ
i bir dile dönüş
türülmüşolur. CgGL ve CgD3D
Umut DOGAN - Bitirme Tezi - Haziran 2006
Direct3D kullanan bir uygulamamı
z varsa CgD3D kullanmamı
z gereklidir. Normalde ya
29
kütüphaneleri birçok benzer yordama sahiptir. CgGL kütüphanesindeki yordamlar cgGL
ile, CgD3D kütüphanesindeki yordamlarsa cgD3D ile baş
lar.
1.4.2.3. Cg Runtime Uygulamamı
za Nası
l Uyum Sağlar
Şekil 1.14’de Cg kütüphaneleri kullanan tipik bir 3B uygulama gösterilmiş
tir.
Şekil 1.14: Standart Bir Cg Uygulaması
nda Cg'nin Yeri
1.4.3. CgFX Araç Takı
mıve Dosya Biçimi
Cg programları
; 3B modeller, dokular ve diğer veriler üzerinde çalı
ş
ı
r. Herhangi bir
veriyle iliş
kilendirilmemişbir Cg programıiş
e yaramaz. Cg programlarıve verileri uygun
3B programlama arayüzü ayarları
nı
n yapı
lmı
şolması
nıgerektirir. Genelde 3B model için
1.4.3.1. CgFX Ne Sağlar
CgFX tüm efektleri ve görünümü göstermek için standartlaş
tı
rı
lmı
ş dosya
biçimidir. Microsoft ve NVIDIA, Cg için yaptı
klarıortaklı
ğıCgFX dosya formatıiçin de
gerçekleş
tirmiş
lerdir. CgFx dosyalarımetin-tabanlı
dı
r. Cg’nin üst kümesi olan bir
sözdizimine sahiptir ve çok sayı
da Cg programıiçerebilir. CgFX dosyaları.fx sonekini
kullanı
rlar. CgFX dosyasıbir efektin tüm render durumları
nıtanı
mlar. Çoklu geçiş
ler,
Umut DOGAN - Bitirme Tezi - Haziran 2006
gerekli tüm bilgileri ve iliş
kilendirilmişprogramıbir araya getirmek kullanı
ş
lı
dı
r.
30
doku durumları
, özel vertex veya fragment programlarıtüm bir görünüm ve efekt
oluş
turmak için kullanı
labilir. CgFX dosyaları
nıkullanmak ve ayrı
ş
tı
rmak için Cg ile
beraber bir araç takı
mısunulmuş
tur.
Cg programlarıvertex ve fragmentlerin tek bir rendering geçiş
inde olması
nı
tanı
mlarlar, ancak bazıkarmaş
ı
k shading algoritmalarıçoklu rendering geçiş
leri gerektirir.
CgFX karmaş
ı
k çoklu geçişefektlerini kodlamak için, hangi rendering geçiş
inde hangi Cg
programı
nı
n kullanı
lacağıdâhil olmak üzere yeterli desteği sunar.
CgFX, Cg diline ek olarak üç özellik daha sağlar:
1. CgFX, çoklu rendering geçiş
leri ve isteğe bağlıolarak bir efektin çoklu
gerçeklenmesini sağlayan mekanizmalara sahiptir.
2. Alpha-test modlarıve doku filtreleme gibi programlanamayan rendering
durumları
nıde belirtmemize olanak sağlar. Bu rendering durumlarıiçin ayarlar, efekt
baş
latı
ldı
ğızaman CPU’da değerlendirilecek basit ifadeler biçiminde olabilir.
3. CgFX, shaderlara ve shader parametrelerine eklenecek ek açı
klamalar izin verir.
Bu ek açı
klamalar, içerik oluş
turma uygulamalarıdâhil olmak üzere uygulamalarla ilgili ek
bilgiler sağlar. Örneğin bir ek açı
klama bir shader parametresi için verilecek değ
er aralı
ğı
nı
belirtebilir.
1.4.3.2. Çoklu Shader Örnekleme
CgFX
dosya
formatı
, verilen
bir
shader
için
Cg
programı
nı
n farklı
programıile daha az özellik destekleyen, 2 kuş
ak GPU’lar için yazı
lmı
şbasit bir Cg
programı
nıaynıanda içerebilir. CgFX dosyası
nıyükleyen uygulama ise makinedeki
GPU’ya uygun olarak bu programlardan birini seçer.
Ayrı
ca Direct3D, OpenGL veya OpenGL ext için yazı
lmı
şCg programlarıCgFX’in
çoklu örnekleme özelliğ
i sayesinde aynıCgFX dosyası
nda bulunabilirler.
Umut DOGAN - Bitirme Tezi - Haziran 2006
gerçekleş
tirmelerini içerebilir. Örneğin 3. veya 4. kuş
ak GPU’lar için yazı
lmı
şCg shader
31
1.4.3.3. CgFX ile Sayı
sal İ
çerik Oluş
turma
CgFX araç takı
mı
; tüm CgFX sözdizimini destekleyen CgFX derleyicisi, CgFX
dosyaları
nıyükleyip değiş
tirebilmek için gerekli CgFX runtime API’si ve Maya, 3ds max
gibi sayı
sal içerik oluş
turma (DCC) uygulamalarıiçin eklenti modülleri içerir. Şekil
1.15’te bu uygulamaları
n CgFX ile kullanı
mıgösterilmiş
tir.
Şekil 1.15: Cg ve CgFX Kullanan Sayı
sal İ
çerik Oluş
turma Uygulamaları
CgFX’ten önce DCC uygulamaları
nı
n 3B içeriklerini gerçek zamanlıçalı
ş
ma için
gerekli tüm shading özellikleriyle birlikte export edebilecekleri belli bir standart yoktu.
oyunlarda gerçek zamanlıolarak kullanma çok basit bir hale gelmiş
tir.
1.4.3.4. CgFX, Uygulamamı
za Nası
l Yerleş
ir
Şekil 1.16’da 3B API ve Cg runtime bileş
enleriyle birleş
en CgFX’in uygulamada
nası
l kullanı
ldı
ğıgösterilmiş
tir.
Umut DOGAN - Bitirme Tezi - Haziran 2006
Günümüzde CgFX sayesinde sayı
sal içerik oluş
turma ve bunları3B uygulamalar ve
32
Umut DOGAN - Bitirme Tezi - Haziran 2006
Şekil 1.16: Standart Bir Uygulamada CgFX'in Yeri
2. Cg Dİ
Lİ
Nİ
N KURALLARI
2.1. Cg Dil Profilleri
Tüm CPU’lar hemen hemen aynıyetenekte olduğundan C dili için bütün CPU’larda
aynıtemel yetenekler sunulur. Ancak GPU programlama henüz bu seviyede bir genelliğe
ulaş
amadı
. Örneğin günümüzdeki programlanabilir vertex iş
lemciler, programlanabilir
fragment iş
lemcilerden çok daha fazla özellik sunarlar. Cg bu genellik sorununu dil
profilleri kavramı
nıortaya atarak çözmüş
tür. Bir Cg profili belli bir donanı
m veya API için
desteklenen tüm alt özellikleri tanı
mlar. Cg’nin ş
u anki sürümünde (Sürüm: 1.4.1, Tarih:
Mart 2006) ş
u profiller tanı
mlı
dı
r:
 OpenGL ARB vertex programları
 OpenGL ARB fragment programları
 OpenGL NV40 vertex programları
 OpenGL NV40 fragment programları
 OpenGL NV30 vertex programları
 OpenGL NV30 fragment programları
 OpenGL NV2X vertex programları
 OpenGL NV2X fragment programları
 DirectX 9 vertex shaderları
 DirectX 9 pixel shaderları
 DirectX 8 vertex shaderları
Bu profillerle ilgili ayarlar NVIDIA’nı
n sitesinden ücretsiz indirilebilen Cg Toolkit
User’s Manual: A Developer’s Guide to Programmable Graphics kitapçı
ğı
nda bulunabilir.
Programı
mı
zıhangi profile göre yazacaksak bunu koş
ma-zamanıprofilini (runtime profile)
ve derleyici seçeneğini (compiler option) uygun olana göre ayarlayarak gerçekleş
tirebiliriz.
Umut DOGAN - Bitirme Tezi - Haziran 2006
 DirectX 8 pixel shaderları
34
2.2. Cg’de Programları
n Tanı
mlanması
C’de CPU kodu genellikle main() olarak adlandı
rı
lan bir programdan ibarettir. Cg
programları
ysa herhangi bir ismi alabilirler. Program ş
u sözdizimine göre tanı
mlanı
r:
<döndürülen değer türü> <program-adı> (<parametreler>) [: <anlamsal-ad>]
{ /* … */ }
2.3. Program Girdi ve Çı
ktı
ları
GPU’daki programlanabilir iş
lemciler veri akı
ş
ları(data stream) üzerinde çalı
ş
ı
rlar.
Vertex iş
lemcisi vertexlerin ve fragment iş
lemcisi fragmentlerin akı
ş
larıüzerinde çalı
ş
ı
rlar.
Programcı
, ana programı
n CPU’da tek bir kez koş
tuğunu düş
ünebilir. Ama GPU’da
iş
ler böyle değildir. GPU’da akı
ş
taki her bir eleman için program tekrar tekrar koş
ulur.
İ
ki çeş
it program girdisi vardı
r:
Değiş
ken girdiler (varying inputs), girdi verisinin her bir elemanıiçin kullanı
lan
verilerdir. Fragment programıiçin değ
iş
ken girdiler interpolantlardı
r, örneğin doku
koordinatları
…
Birörnek girdiler (uniform inputs), girdi verisinin ana akı
ş
ı
ndan bağı
msı
z olarak
tanı
mlanan değerlerdir ve her akı
şelemanı
nda değiş
mez. Örneğin bir vertex programı
birörnek girdi olarak dönüş
üm matrisine ihtiyaç duyabilir.
Bir vertex programıgenel olarak değiş
ik sayı
da, farklıgirdileri kabul eder. Örneğin
program, her bir vertex için alttaki değiş
ken girdileri gerektirebilir:
 Model uzayıkonumu
 Model uzayınormal vektörü
 Doku koordinatları
Umut DOGAN - Bitirme Tezi - Haziran 2006
2.3.1. Vertex Programları
ndaki Değiş
ken Girdiler
35
Örnek olarak alttaki vertex program parçacı
ğı
nıverebiliriz:
struct myinputs {
float3 myPosition
float3 myNormal
float3 myTangent
float refractive_index
};
:
:
:
:
POSITION;
NORMAL;
TANGENT;
TEXCOORD3;
outdata foo(myinputs indata) {
/* ... */
// Programın içinde, parametreler
// “indata.myPosition”, “indata.myNormal”
// vb. şekilde referanslanır.
/* ... */
}
Struct tanı
mlaması
nda iki nokta üst üsteden sonra gelen ön tanı
mlıdeğerlere
bağlayı
cısemantikler (binding semantics) denir. Altta verilen bağlayı
cısemantikler tüm
Cg vertex programları
nda kullanı
labilir:
POSITION
BLENDWEIGHT
BINORMAL BLENDINDICES
NORMAL
TANGENT
PSIZE
TEXCOORD0-TEXCOORD7
OpenGL Cg profillerinde değiş
ken girdi değ
erlerini dolaylıbir ş
ekilde özel
donanı
m kaydedicilere haritalar. Ancak DirectX-tabanlıCg profillerinde böyle bir
haritalama söz konusu değildir.
2.3.2. Vertex Programları
ndaki Değiş
ken Çı
ktı
lar
Vertex programları
nı
n çı
ktı
larıpikselleş
tiriciden geçer ve fragment programı
na
çalı
ş
abilmeleri için üzerlerinde çalı
ş
acaklarıveriler konusunda iki tarafı
n da anlaş
mı
ş
olmasıgereklidir.
Uygulama programı
yla vertex programıarası
nda olduğu gibi vertex programı
yla
fragment programıarası
nda da veri akı
ş
ıiçin bağlayı
cısemantikler kullanı
lı
r.
Umut DOGAN - Bitirme Tezi - Haziran 2006
değiş
ken girdiler olarak hazı
rlanı
r. Vertex ve fragment programları
nı
n birlikte
36
Alttaki örnekte vertex program çı
ktı
sıiçin bağ
layı
cısemantiklerin kullanı
mı
gösterilmiş
tir:
// Vertex program
struct myvf {
float4 pout
float4 diffusecolor
float4 uv0
float4 uv1
};
myvf foo(/* ... */) {
myvf outstuff;
/* ... */
return outstuff;
}
Bu
program
ise
:
:
:
:
POSITION; // Pikselleştirme için
COLOR0;
TEXCOORD0;
TEXCOORD1;
aynı verinin
fragment
programda
girdi
olarak
nası
l
kullanı
labileceğini göstermektedir.
// Fragment program
struct myvf {
float4 diffusecolor
: COLOR0;
float4 uv0
: TEXCOORD0;
float4 uv1
: TEXCOORD1;
};
fragout bar(myvf indata) {
float4 x = indata.uv0;
/* ... */
}
Alttaki bağlayı
cısemantikler tüm Cg vertex profilleri için vertex programları
ndan
çı
ktıolarak kullanı
labilirler:
PSIZE
FOG
COLOR0-COLOR1
TEXCOORD0-TEXCOORD7
Tüm vertex programlarıPOSITION bağlayı
cısemantiğini kullanan bir vektör
çı
ktı
sıtanı
mlamalıve içeriğini ayarlamalı
dı
r. Bu değer pikselleş
tirme için gereklidir.
Vertex ve fragment programları
n uyumlu çalı
ş
masıiçin her ikisinin de kendi girdi
ve çı
ktı
larıiçin aynıstruct yapı
sı
nıkullanmalarıgereklidir.
Umut DOGAN - Bitirme Tezi - Haziran 2006
POSITION
37
Bunun için alttaki örnek verilebilir:
struct
float4
float4
float4
};
myvert2frag {
pos
uv0
uv1
: POSITION;
: TEXCOORD0;
: TEXCOORD1;
// Vertex program
myvert2frag vertmain(...) {
myvert2frag outdata;
/* ... */
return outdata;
}
// Fragment program
void fragmain(myvert2frag indata ) {
float4 tcoord = indata.uv0;
/* ... */
}
2.3.3. Fragment Programları
ndaki Değiş
ken Çı
ktı
lar
Fragment porgram çı
ktı
ları
nda bağlayı
cısemantikler her zaman gereklidir.
Fragment programları
nı
n COLOR semantiğini tanı
mlamak ve içeriğ
ini ayarlamak gibi bir
zorunluluklarıvardı
r. Bu değer genellikle donanı
m tarafı
ndan fragmentin son renk değeri
olarak kullanı
lı
r. Bazıfragment profilleri DEPTH vb. çı
ktısemantiklerini de desteklerler.
Fragment programlar da, vertex programlarda olduğu gibi kendi yapı
ları
nı
n içinde
değer döndürebilirler. Ama genellikle çı
ktı
larıout ş
eklinde deklare etmek alı
ş
kanlı
k
void main(/* ... */,
out float4 color
: COLOR,
out float depth
: DEPTH) {
/* ...*/
color = diffuseColor * /* ...*/;
depth = /*...*/;
}
Bir sonraki sayfada verilen örnekte basit bir vertex programıverilmiş
tir. Bu
program (dağı
nı
k) diffuse ve aynasal (specular) aydı
nlatmayıhesaplamaktadı
r. Değiş
ken
veriler için appin ve vertout adı
nda iki struct tanı
mlanmı
ş
tı
r.
Umut DOGAN - Bitirme Tezi - Haziran 2006
olmuş
tur:
38
// Uygulamadan gelen girdileri tanımla.
struct appin
{
float4 Position
: POSITION;
float4 Normal
: NORMAL;
};
// Vertex shader çıktılarını tanımla.
struct vertout
{
float4 HPosition : POSITION;
float4 Color
: COLOR;
};
vertout main(appin IN,
uniform float4x4 ModelViewProj,
uniform float4x4 ModelViewIT,
uniform float4 LightVec)
{
vertout OUT;
// Vertex konumunu homojen kırpılmış uzaya dönüştür.
OUT.HPosition = mul(ModelViewProj, IN.Position);
// Normali, model-uzayından görüntü-uzayına dönüştür.
float3 normalVec = normalize(mul(ModelViewIT,
IN.Normal).xyz);
// Normalize ışık vektörünü tut.
float3 lightVec = normalize(LightVec.xyz);
// Yarım açı vektörünü hesapla.
float3 eyeVec = float3(0.0, 0.0, 1.0);
float3 halfVec = normalize(lightVec + eyeVec);
// Diffuse bileşeni hesapla.
float diffuse = dot(normalVec, lightVec);
// Specular bileşeni hesapla.
float specular = dot(normalVec, halfVec);
// lit fonksiyonunu kullan ve ışıklandırma değerini
// diffuse ve specular değerlere göre hesapla.
float4 lighting = lit(diffuse, specular, 32);
// Beyaz specular materyal
float3 specularMaterial = float3(1.0, 1.0, 1.0);
// Diffuse ve specular bileşenlerin katkılarını hesapla
// ve final vertex rengini çıktı olarak ver.
OUT.Color.rgb = lighting.y * diffuseMaterial +
lighting.z * specularMaterial;
OUT.Color.a = 1.0;
return OUT;
}
Umut DOGAN - Bitirme Tezi - Haziran 2006
// Mavi diffuse materyal
float3 diffuseMaterial = float3(0.0, 0.0, 1.0);
39
2.4 Veri Tipleri
C gibi, Cg de veri oluş
turmak ve iş
lemek için gerekli altyapı
yısağlar: Temel Veri
Tipleri, Yapı
lar, Diziler, Tip dönüş
ümleri…
2.4.1. Temel Veri Tipleri
Cg, 7 temel veri tipini destekler:
o float
32 bit IEEE kayan noktalısayı
dı
r (s23e8). 1 iş
aret biti, 23 bit mantis ve 8 bit
üsten oluş
ur. Bu veri tipi tüm profillerde desteklenir, ancak DirectX 8 pixel
profilleri daha düş
ük bir duyarlı
lı
k seviyesi kullanı
r ve iş
lemlerde bazı
kı
sı
tlamalar yapar.
o half
16 bit IEEE-benzeri kayan noktalısayı
dı
r.
o int
32 bit tamsayı
dı
r. Bazı profillerde kullanı
lmaz veya float olarak
değerlendirilir.
o fixed
12 bit sabit noktalısayı
dı
r. Tüm fragment profillerinde desteklenir.
o bool
Kı
yaslamalar sonucunda üretilir. if ve koş
ullu operatör (?:) yapı
ları
nda
kullanı
lı
r. Bu veri tip de tüm profillerde desteklenir.
Doku nesnesi için gerekli tutaç (handle) altıdeğiş
ik biçimde oluş
ur:
sampler,
sampler1D,
sampler2D,
sampler3D,
samplerCUBE
ve
samplerRECT. Tek bir istisna dı
ş
ı
nda veri tipi tüm pixel, fragment ve
NV40 vertex profillerinde desteklenir. Sadece samplerRECT tipi DirectX
profillerinde desteklenmez.
o string
Günümüzdeki profil yapı
sı
nda Cg program kodları
nda string veri tipinin
kullanı
mı
na izin verilmese de Cg runtime API sayesinde kullanı
lı
p değerleri
Umut DOGAN - Bitirme Tezi - Haziran 2006
o sampler*
40
sorgulanabilir. Genelde Cg dosyası
nı
n içeriğiyle ilgili bilgiler tutmada
kullanı
ş
lı
dı
r.
Cg, aynızamanda temel veri tipleriyle iliş
kili yerleş
ik vektör veri tiplerine de
sahiptir. Bu yerleş
ik vektör veri tiplerine örnek olarak ş
unlarıverebiliriz:
float4
float3
float2
float1
bool4
bool3
bool2
bool1
Ayrı
ca 4X4 boyutlu matrislere kadar olan matrislere izin verilir. Bazımatris
tanı
mlama örnekleri ş
öyledir:
float1x1 matris1;
// Tek elemanlımatris
float2x2 matris2;
// İ
kiye üçlük matris (altıelemanlı
)
float4x2 matris3;
// Dörde ikilik matris (sekiz elemanlı
)
float4x4 matris4;
// Dörde dörtlük matris (onaltıelemanlı
)
Çok boyutlu float M[4][4] dizisi ile float4X4 M matrisinin tip olarak birbirlerinden
farklıoldukları
na dikkat edilmelidir.
Cg’nin ş
u anki sürümünde union ve bit alanlarıyoktur.
2.4.2. Tip Dönüş
ümleri
operatörüyle olduğ
u gibi açı
k bir biçimde belirtilebilir.
Cg, farklıtiplerin bulunduğu ifadelerde otomatik olarak tip yükseltme yapar.
Örneğ
in floatvar * halfvar ifadesi floatvar * (float) halfvar ş
eklinde derlenecektir.
Cg, tek bir istisnai durumda C’den farklıtip-yükseltme kuralları
nıuygular: Açı
k tip
öneki olmayan bir sabit tip yükseltmeye maruz kalmaz. Örneğin halfvar * 2.0 ifadesi
halfvar * (half) 2.0 ş
eklinde derlenir.
Umut DOGAN - Bitirme Tezi - Haziran 2006
Cg’deki tip dönüş
ümleri C’de olduğu gibi çalı
ş
ı
r. Tip dönüş
ümleri C’deki cast
41
Bu ifade C’de ise ((double) halfvar) * 2.0 ş
eklinde derlenir. Cg bu yaklaş
ı
mı
hesaplamaları
n daha yavaşyapı
ldı
ğıyüksek-duyarlıaritmetiği kullanmayıengellemek için
uygular.
Cg’de sabitler için ş
u tip önekleri kullanı
labilir:
o float için f
o half için h
o fixed için x
2.4.3. Yapı
lar ve Üye Fonksiyonlar
Cg’nin yapı
lara (struct) yaklaş
ı
mıC ile aynı
dı
r. Cg’de C++’daki gibi bir struct
tanı
mlandı
ğı
nda kapalıolarak typedef dönüş
ümünün yapı
lması
nısağlar:
struct ornekstruct {
/* … */ };
ornekstruct s;
// Burada s ornekstruct olarak tanımlanıyor.
Yapı
larda üye değiş
kenler gibi üye fonksiyonlar da tanı
mlanabilir:
struct Foo {
float deg;
float yardimci(float a) {
return deg + a;
}
};
float4 main(uniform Foo myfoo, uniform float myval) : COLOR {
return myfoo.yardimci(myval);
}
Umut DOGAN - Bitirme Tezi - Haziran 2006
Üye fonksiyonlar alı
ş
ı
lmı
ş“.” gösterimi kullanı
larak çağrı
lı
r.
42
2.4.4. Diziler
Diziler Cg’de de C’de olduğu gibi tanı
mlanı
r ve kullanı
lı
r. Cg iş
aretçileri
desteklemediğinden diziler her zaman dizi sözdizimi kullanı
larak tanı
mlanmalı
dı
r. İ
ş
aretçi
sözdizimi kullanmak doğru değildir.
// 5 skinning matrisi kullanan bir dizi kullanan
// bir fonksiyon tanımlanması
returnType foo(float4x4 matris[5]) {/* ... */};
C’den en önemli fark ş
udur: Dizi atamalarıtüm dizinin kopyası
nıoluş
turur.
Parametrelerle geçilen diziler değerle geçilir (passed by value). Yani bir değiş
iklik
yapı
lmadan önce tüm dizinin kopyasıalı
nı
r.
2.4.4.1. Boyutsuz Diziler
Cg, bir veya iki boyutunun uzunluğu belirtilmemişdizileri destekler. Bu sayede
alttaki örnekte görüldüğü gibi farklıboyutlardaki diziler üzerinde iş
lem yapabilen
fonksiyonlar yazmak mümkündür.
2.4.4.2. Arayüzler
Java ve C# gibi dillerde bulunan arayüz (interface) dil yapı
sıda Cg tarafı
ndan
desteklenir. Arayüzler soyut olarak özel bir yapı
da hangi üye fonksiyonları
n nası
l deklare
edileceğ
ini tanı
mlar. Üye fonksiyonları
n içeriklerinin deklarasyonuyla ilgilenmezler.
interface Light {
float3 illuminate(float3 P, out float3 L);
float3 color(void); };
Umut DOGAN - Bitirme Tezi - Haziran 2006
float myfunc(float vals[]) {
...
}
float4 main(...) {
float vals1[2];
float vals2[76];
...
float myval1 = myfunc(vals1); // eşleşir
float myval2 = myfunc(vals2); // eşleşir
...
}
43
2.5. İ
fadeler ve Operatörler
Cg ş
u tip ifade ve operatörleri destekler:
o Kontrol akı
ş
ı
o Fonksiyon tanı
mlamalarıve aş
ı
rıyüklemeleri (overload)
o C’deki aritmetik operatörler
o Çarpma fonksiyonu
o Vektör yapı
cı
ları(constructor)
o Bool ve karş
ı
laş
tı
rma operatörleri
o Swizzle operatörleri
o Write Mask operatörü
o Koş
ullu operatörler
2.5.1. Kontrol Akı
ş
ı
Cg ş
u C kontrol yapı
ları
nıkullanı
r:
o Fonksiyon çağrı
larıve return ifadesi
o if / else
o while
o for
Bu kontrol yapı
ları
yla ilgili olarak ayrı
ntı
lar C ile aynı
dı
r. Cg’de fonksiyon
özyineleme kullanı
lmaz. switch, case ve default anahtar kelimeleri ayrı
lmı
ş(reserved)
2.5.2. Fonksiyon Tanı
mlamalarıve Aş
ı
rıYüklemeleri
Örnek fonksiyon tanı
mlamalarış
uş
ekildedir:
function
function
function
function
fonksiyon1(out float x); // x sadece çıktıdır
fonksiyon2(inout float x); // x hem çıktı hem girdidir
fonksiyon3(in float x); // x sadece girdidir
fonksiyon4(float x); // x sadece girdidir (C’deki kullanım)
Fonksiyon aş
ı
rıyüklemeyeyse ş
öyle bir örnek verilebilir:
bool ayniFonksiyon(float a, float b) { return (a == b);}
bool ayniFonksiyon(bool a, bool b) { return (a == b);}
2.5.3. Aritmetik Operatörler
Umut DOGAN - Bitirme Tezi - Haziran 2006
kelimelerdir ama hiçbir profilde ve Cg derleyicisinde desteklenmez.
44
C’deki tüm standart aritmetik operatörleri (+, -, *, /) içerir. Bunlarıhem vektörler
hem de skalerler için kullanabilir. Vektör iş
lemleri her zaman her bir eleman için
uygulanı
r. Örneğin float3(a, b, c) * float3(A, B, C) ile float3(a*A, b*B, c*C) aynış
eydir.
a * float3(A, B, C) ile de float3(a*A, a*B, a*C) aynı
dı
r.
Cg’nin son sürümündeki (Cg 1.4.1) aritmetik operatörler, matris iş
lemlerini
desteklememektedir.
2.5.4. Çarpma Fonksiyonu
Cg’nin mul() fonksiyonu matrislerle matrisleri ve matrislerle vektörleri çarpmak
için kullanı
lı
r.
// Matris sütun-vektörü çarpımı
matrix-column vector: mul(M, v);
// Satır-vektörüyle matris çarpımı
row vector-matrix: mul(v, M);
// Matrisle matris çarpımı
matrix-matrix: mul(M, N);
2.5.5. Vektör Yapı
cı
lar
Cg dört boyutluya kadar olan vektörlerin altta verilen gösterim ş
ekliyle
oluş
turulması
na izin verir.
2.5.6. Bool ve Karş
ı
laş
tı
rma Operatörleri
Cg’de standart C bool operatörlerinin üçü kullanı
labilirdir:
&& lojik AND
|| lojik OR
! lojik NOT
Umut DOGAN - Bitirme Tezi - Haziran 2006
y = x * float4(3.0, 2.0, 1.0, -1.0);
45
Karş
ı
laş
tı
rma operatörleri de ş
uş
ekildedir:
< küçük
<= küçük veya eşit
!= eşit değil
== eşit
>= büyük veya eşit
> büyük
2.5.7. Swizzle Operatörü
Cg’de swizzle operatörü ( . ) denilen bir operatör vardı
r. Kullanı
m amacı
; var olan
bir vektörün elemanları
nı
n yeniden düzenlenmesiyle yeni bir vektör elde etmektir. Bazı
örnekler ş
öyle verilebilir:
float3(a, b, c).zyx
sonuç olarak float3(c, b, a) verir.
float4(a, b, c, d).xxyy
float2(a, b).yyxx
sonuç olarak float4(a, a, b, b) verir.
sonuç olarak float4(b, b, a, a) verir.
float4(a, b, c, d).w
sonuç olarak d verir.
Aynızamanda bir skalerden bir vektör üretmek için de kullanı
labilir:
a.xxxx
sonuç olarak float4(a, a, a, a) verir.
2.5.8. Write Mask Operatörü
bileş
enlerinden seçileninin üzerine yazmada kullanı
lı
r.
float4 color = float4(1.0, 1.0, 0.0, 0.0);
color.a = 1.0; // RGB’yi aynen bırakıp alpha’yı 1.0’a setler
2.5.9. Koş
ullu Operatörler
Cg, if/else koş
ullu ifadesini ve ?: koş
ullu operatörünü içerir.
Umut DOGAN - Bitirme Tezi - Haziran 2006
Write Mask operatörü ( . ) atama ifadesinin sol kı
smı
na yerleş
tirilir. Bir vektörün
46
float3 clamp(float3 x, float minval, float maxval) {
x = (x < minval.xxx) ? minval.xxx : x;
x = (x > maxval.xxx) ? maxval.xxx : x;
return x;
}
2.6. Cg Standart Kütüphane Fonksiyonları
Cg, birçok yerleş
ik fonksiyon ve bağlama semantikleriyle birlikte önceden tanı
mlı
yapı
yıGPU programcı
sı
nı
n kullanı
mı
na sunar. Bu fonksiyonları
n birçoğu C standart
Kütüphane Fonksiyonlarıkadar basit yapı
dadı
r. Bazı
ları
ysa karmaş
ı
k matematiksel
iş
lemleri çok hı
zlıbir ş
ekilde yapmamı
za olanak sağlar.
Cg Standart Kütüphane Fonksiyonlarış
u baş
lı
klar altı
nda incelenebilir:
o Matematiksel Fonksiyonlar
o Geometrik Fonksiyonlar
o Doku Kaplama Fonksiyonları
o Türev Fonksiyonları
o Öntanı
mlıYardı
mcıstruct Tipleri
Cg kullanı
cıel kitabı
nda, bütün kütüphane fonksiyonları
yla ilgili ayrı
ntı
lı
açı
klamalar bulunmaktadı
r. Tezimde örnek teş
kil etmesi açı
sı
ndan her alt baş
lı
kta sadece
birkaç kütüphane fonksiyonunu açı
kladı
m.
abs(x)
: x’in mutlak değeri
clamp(x,a,b) : x’i, [a, b] aralı
ğı
na ş
uş
ekilde kenetler:
-
x, a’dan küçükse a değerini döndürür.
-
x, b’den büyükse b değerini döndürür.
-
Diğ
er durumlarda x değerini döndürür.
dot(a,b)
: a ve b vektörlerinin iç çarpı
mı
Umut DOGAN - Bitirme Tezi - Haziran 2006
2.6.1. Matematiksel Fonksiyonlar
47
2.6.2. Geometrik Fonksiyonlar
distance(pt1, pt2)
: pt1 ve pt2 noktalarıarası
ndaki Öklit uzaklı
ğ
ı
normalize(v)
: v vektörüyle aynıdoğ
rultuda, 1 uzunluklu vektör döndürür.
2.6.3. Doku Kaplama Fonksiyonları
tex1D(sampler1D tex, float s) : İ
zdüş
ümsel olmayan 1B doku kaplama
tex3Dproj(sampler3D tex, float4 szq) : İ
zdüş
ümsel 3B, derinlik kı
yaslamalı
Ayrı
ca türev, hata ayı
klama fonksiyonlarıve öntanı
mlıfragment program çı
ktı
yapı
larıda bulunmaktadı
r. Bu konularla ve üst baş
lı
klardaki diğer fonksiyonlarla ilgili
ayrı
ntı
lar “Cg User’s Manual”de bulunmaktadı
r.
Not: Cg Runtime ile ilgili ayrı
ntı
lar 3B API’ler ve programlama ortamlarıiçin
farklı
lı
klar göstermektedir. Bu yüzden Cg runtime’ı
n ayrı
ntı
ları
na “Cg Dilinin Kuralları
”
baş
lı
ğıaltı
nda yer vermedim. Direct3D ile yaptı
ğı
m küçük vertex programları
nda Direct3D
ile ilgili kurallarıve ana uygulama projem “Cg ile Pürüzlü Yüzey Dokusu Üretimi”
baş
lı
ğı
nda da OpenGL ile ilgili olanları
nıözet halinde açı
klamaya çalı
ş
tı
m. NVIDIA
Developer sitesinde bulunan Cg User’s Manual’de bütün Cg Runtime özellikleri
Umut DOGAN - Bitirme Tezi - Haziran 2006
ayrı
ntı
ları
yla açı
klanmı
ş
tı
r. Gerek duyulmasıhalinde bu kaynağa baş
vurulabilirsiniz.
3. Cg VE DIRECT3D İ
LE YAZILMIŞKOD ÖRNEKLERİ
Bu bölümde sürekli geliş
mekte ve yeni özellikler eklenmekte olan Direct3D
API’siyle eş
güdümlü bir ş
ekilde geliş
tirilmiş bazıuygulamalar verilmiş
tir. Shader
programları
nı
n birçoğunu “Kaynaklar” bölümünde belirtilen kaynaklardan alı
p üzerlerinde
bazıdeğiş
iklikler yaparak buraya ekledim.
3.1. Cg ile Kod Yazabilmek için Ayarlar
Bu alt baş
lı
kta Cg, Direct3D ve Visual C++ ayarlamaları
nı
n nası
l yapı
lması
gerektiğini anlatacağı
m. İ
lk kez Cg diliyle programlamaya baş
layacak birisi için en ince
ayrı
ntı
sı
na kadar her ş
eyi açı
klamaya çalı
ş
tı
m.
Bilgisayarda Visual Studio 2003 kurulu olduğunu varsayı
yorum. Eğer kurulu
değilse bir ş
ekilde Trial veya Express sürümlerinden birisini indirip bilgisayarı
nı
za
kurabilirsiniz.
UygulamalarıVisual C++ dili yardı
mı
yla yazacağı
m. Visual C++ dilinde en
azı
ndan bazıtemelleri bilmek programlarıanlamak açı
sı
ndan size yardı
mcıolacaktı
r.
3D API olarak en son DirectX SDK’sı
nı(February 2006) Microsoft’un sitesinden
indirip bilgisayarı
mı
za kuruyoruz. Böylece Cg ile ilgili ayarlar hariç tüm önkoş
ullarıyerine
Cg Toolkit’i de NVidia Developer sitesinden indirip kuruyoruz. Kurulum
programı
nıindirdiğiniz sayfada “Cg Users Manual”i indirerek bu dilin bütün özelliklerini
öğ
renmek için bir baş
langı
ç yapabilirsiniz. Program varsayı
lan olarak C:\Program
Files\NVIDIA Corporation\Cg\ dizinine kurulacaktı
r.
Şimdi iş
in önemli noktalarıgeliyor. Burada birçok kopyala-yapı
ş
tı
r iş
lemi olduğu
için eğ
er bu iş
lemleri adı
m adı
m yapmazsanı
z büyük olası
lı
kla programı
nı
z
derlenmeyecektir. İ
lk önce C:\Program Files\NVIDIA Corporation\Cg dizinindeki include
Umut DOGAN - Bitirme Tezi - Haziran 2006
getirmişoluyoruz.
49
ve lib altdizinlerini C:\Program Files\Microsoft Visual Studio .NET 2003\VC7\ dizinine
kopyalı
yoruz. Kopyalama iş
lemi sı
rası
nda bu dizinlerin üzerine yazmak isteyip
istemediğimizi soracaktı
r. “Evet” diyoruz. Bu mesajıvermesinin nedeni hedef dizinde de
include ve lib dizinlerinin olması
dı
r. Bizim amacı
mı
z da bu dizinlerin içeriğini
geniş
letmektir.
Direct3D kodları
nı
n programı
mı
zda çalı
ş
masıiçin C:\Program Files\Microsoft
DirectX SDK (February 2006)\Include\ dizininin içeriğini C:\Program Files\Microsoft
Visual Studio .NET 2003\VC7\Include\ dizinine kopyalı
yoruz. Benzer ş
ekilde C:\Program
Files\Microsoft DirectX SDK (February 2006)\Lib\x86\ dizininin içeriğ
ini de C:\Program
Files\Microsoft Visual Studio .NET 2003\VC7\lib\ dizinine kopyalı
yoruz. Alternatif olarak
program ayarları
nda include yoluna DirectX SDK’nı
n bulunduğu dizin eklenebilir ama bu
yöntem daha garantili bir yöntemdir.
Son olarak kullanı
ş
lıbir özellik olan Visual Studio’da Cg için sözdizimi vurgulama
(syntax highlighting) özelliğin etkinleş
tirilmesini göstereceğ
im. Bunun için ilk adı
mda
C:\Program Files\NVIDIA Corporation\Cg\msdev_syntax_highlighting dizinine gidip
burada bulunan usertype.dat dosyası
nıC:\Program Files\Microsoft Visual Studio .NET
2003\Common7\IDE
dizinine
kopyalı
yoruz.
Daha
sonra
aynı dizindeki
install_highlighting_vs7.reg dosyası
nıçalı
ş
tı
rarak gerekli kayı
t girdilerini ayarlı
yoruz. Bu
sayede kod yazarken anahtar kelimeler vs. sanki herhangi bir .NET diliyle çalı
ş
ı
yormuş
uz
gibi farklırenklerde olacaktı
r. Bu özelliğin kod yazarken epeyce kullanı
ş
lıolduğunu
belirtmeliyim.
altyapı
yıoluş
turmuşolduk. Şimdi program yazmaya baş
layabiliriz.
3.2. Basit Bir Vertex Programı
Eğer yeni bir proje yaratmak yerine var olan Template’ler üzerinde düzenlemeler
yapı
lmak isteniyorsa http://www.codesampler.com/index.htm adresindeki Cg shader
programlarıiyi bir baş
langı
ç noktasıolabilir. İ
lk olarak Visual Studio 2003 ortamı
nıaçı
p
File -> New -> Project seçiyoruz. Açı
lan pencerede Project Types kı
smı
ndan Other
Umut DOGAN - Bitirme Tezi - Haziran 2006
Böylece Cg, Direct3D, Visual C++ üçlüsüyle program yazmak için gerekli bütün
50
Languages’a geçiyor ve Visual C++’ıseçiyoruz. Aynıpencerenin sağı
ndaki Templates
kı
smı
ndan proje türünü seçip projemize bir ad veriyoruz. Proje sayfasıaçı
ldı
ktan sonra
Solution Explorer’da Source Files dizinine sağtı
klayı
p Add -> New Item seçiyoruz.
Açı
lan pencerede solda Categories altı
ndaki Code’u sağdan da C++ File (.cpp) seçiyor ve
dosyamı
za da bir ad veriyoruz. Tamam’a tı
kladı
ktan sonra boşbir sayfa açı
lı
yor. Bu sayfa
içerisine Direct3D ve Visual C++ ile ilgili kodlarıyazacağı
z.
Şimdi Cg Shader’ı
nıyazacağı
mı
z kod dosyası
nıhazı
rlayalı
m. Bu amaçla Solution
Explorer’da boşbir yere sağtı
klayı
p Add -> New Filter seçiyoruz. Ve dizinimize Cg Files
ismini veriyoruz. Oluş
turduğumuz bu dizine de sağtı
klayı
p Add -> New Item seçiyoruz.
Açı
lan pencerede solda Categories altı
ndaki Code’u sağdan da C++ File (.cpp) seçiyor ve
dosyamı
za cg uzantı
sı
yla biten bir ad (örn. vertex_programi.cg) veriyoruz.
Şimdi kod yazmaya baş
layabiliriz. Öncelikle ana programı
mı
zı
n içeriğini
oluş
turuyoruz. Kodlarla ilgili açı
klamalar satı
r araları
nda verilmiş
tir. Kodları
n büyük kı
smı
Visual C++ ile ilgili ayarlamalardan oluş
tuğ
u için bunlarıburada belirtmedim.
//----------------------------------------------------------------------// Bu örnekte Direct3D ile basit bir Cg Shader uygulamasının nasıl
// yazılacağı anlatılmıştır.
//----------------------------------------------------------------------<d3d9.h>
<d3dx9.h>
<Cg/Cg.h>
<Cg/CgD3D9.h>
//----------------------------------------------------------------------// Global değişkenler
//----------------------------------------------------------------------HWND
g_hWnd
= NULL;
LPDIRECT3D9
g_pD3D
= NULL;
LPDIRECT3DDEVICE9
g_pd3dDevice
= NULL;
LPDIRECT3DVERTEXBUFFER9 g_pVertexBuffer = NULL;
LPDIRECT3DVERTEXDECLARATION9 g_pVertexDeclaration = NULL;
CGcontext
CGprogram
CGparameter
CGparameter
g_CGcontext;
g_CGprogram;
g_CGparam_worldViewProj;
g_CGparam_constColor;
D3DXMATRIX g_matWorld;
D3DXMATRIX g_matView;
D3DXMATRIX g_matProj;
Umut DOGAN - Bitirme Tezi - Haziran 2006
#include
#include
#include
#include
51
float
float
g_fSpinX = 0.0f;
g_fSpinY = 0.0f;
struct Vertex
{
float x, y, z;
DWORD color;
};
enum FVF
{
FVF_Flags = D3DFVF_XYZ | D3DFVF_DIFFUSE
};
Vertex g_quadVertices[]
{
// x
y
z
{ -1.0f,-1.0f, 0.0f,
{ 1.0f,-1.0f, 0.0f,
{ 1.0f, 1.0f, 0.0f,
{ -1.0f, 1.0f, 0.0f,
};
=
renk
0xffffff00,
0xff00ff00,
0xffff0000,
0xff0000ff,
},
},
},
}
//
//
//
//
Sol-alt,
Sağ-alt,
Sağ-üst,
Sol-üst,
sarı
yeşil
kırmızı
mavi
//----------------------------------------------------------------------// Fonksiyon Prototipleri
//----------------------------------------------------------------------void init(void);
void render(void);
void shutDown(void);
void initShader(void);
void setShaderConstants(void);
//----------------------------------------------------------------------// WindowProc() : Pencerelerle ilgili handler
// Pencere handlerları hangi tuşa basıldığında vs. nasıl tepki
// verileceği belirleniyor. Örneğin bu programda ekrandaki renkli
// dikdörtgen fareyle tutulup çevrildiğinde dönmesi sağlanıyor.
// Bu fonksiyonun içeriği de burada gösterilmemiştir.
//----------------------------------------------------------------------//----------------------------------------------------------------------// init() : başlatma işlemleri
//----------------------------------------------------------------------void init( void )
{
g_pD3D = Direct3DCreate9( D3D_SDK_VERSION );
D3DDISPLAYMODE d3ddm;
g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm );
D3DPRESENT_PARAMETERS d3dpp;
Umut DOGAN - Bitirme Tezi - Haziran 2006
//----------------------------------------------------------------------// WinMain() : Uygulamanın giriş noktası
// Bu fonksiyonda pencereyle ilgili standart ayarlamalar yapılıyor.
// Hemen hemen bütün Visual C++ uygulamaları için standart olduğu ve
// farklı uygulamalar için birkaç değişiklik gerektirdiği için burada
// ayrıca gösterilmemiştir.
//-----------------------------------------------------------------------
52
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed
d3dpp.SwapEffect
d3dpp.BackBufferFormat
d3dpp.EnableAutoDepthStencil
d3dpp.AutoDepthStencilFormat
d3dpp.PresentationInterval
=
=
=
=
=
=
TRUE;
D3DSWAPEFFECT_DISCARD;
d3ddm.Format;
TRUE;
D3DFMT_D16;
D3DPRESENT_INTERVAL_IMMEDIATE;
g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice );
g_pd3dDevice->CreateVertexBuffer( 4*sizeof(Vertex),
D3DUSAGE_WRITEONLY,
Vertex::FVF_Flags,
D3DPOOL_DEFAULT,
&g_pVertexBuffer, NULL );
void *pVertices = NULL;
0 );
g_pVertexBuffer->Lock( 0, sizeof(g_quadVertices), (void**)&pVertices,
memcpy( pVertices, g_quadVertices, sizeof(g_quadVertices) );
g_pVertexBuffer->Unlock();
g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
}
D3DXMatrixPerspectiveFovLH( &g_matProj, D3DXToRadian( 45.0f ),
640.0f / 480.0f, 0.1f, 100.0f );
g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &g_matProj );
//----------------------------------------------------------------------// initShader(): Vertex shader yükleme ayarları
//----------------------------------------------------------------------void initShader( void )
{
// Context oluştur...
g_CGcontext = cgCreateContext();
cgD3D9SetDevice( g_pd3dDevice );
// Kullanılabilecek en uygun vertex profilini seç...
CGprofile vertexProfile = cgD3D9GetLatestVertexProfile();
const char* profileOpts[] =
{
"-profileopts", "dcls", NULL,
};
Umut DOGAN - Bitirme Tezi - Haziran 2006
//
// CG'nin gelişmiş arayüzünü kullandığımız için,
// Direct3D aygıtını CG2ye geçmeliyiz.
//
53
//
// Vertex shader'ı oluştur...
//
g_CGprogram = cgCreateProgramFromFile( g_CGcontext,
CG_SOURCE,
"dx9_cg_simple.cg",
vertexProfile,
"main",
profileOpts );
//
// İkinci parametre TRUE'ya setlendiğinde, gölgelendirme
// etkinleştirilir.
// Bu sayede g_CGparam_constColor gibi parametrelerimiz bir kere
// ayarlanır ve tekrar tekrar ayarlanmasına gerek kalmadan
kullanılabilir.
//
cgD3D9LoadProgram( g_CGprogram, TRUE, 0 );
//
// Eğer programınız burada olduğu gibi açık binding semantics
// kullanıyorsa, bu semantic'leri kullanarak
// vertex deklarasyonu oluşturulabilir.
//
const D3DVERTEXELEMENT9 declaration[] =
{
{ 0, 0*sizeof(float), D3DDECLTYPE_FLOAT3,
D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
{ 0, 3*sizeof(float), D3DDECLTYPE_D3DCOLOR,
D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,
0 },
D3DDECL_END()
};
//
// Sonuç deklarasyonunun shader ile uyumlu olduğundan emin ol...
//
);
assert( cgD3D9ValidateVertexDeclaration( g_CGprogram, declaration )
//
// Bazı parametrelerini isimlerine göre bağla
// böylece bunları daha sonra ayarlayabiliriz...
//
g_CGparam_worldViewProj = cgGetNamedParameter( g_CGprogram,
"worldViewProj" );
g_CGparam_constColor
= cgGetNamedParameter( g_CGprogram,
"constColor" );
Umut DOGAN - Bitirme Tezi - Haziran 2006
g_pd3dDevice->CreateVertexDeclaration( declaration,
&g_pVertexDeclaration );
54
//
// Parametrelerimizin beklenen boyutta olup olmadığı kontrol
ediliyor...
//
assert( cgD3D9TypeToSize(
cgGetParameterType(g_CGparam_worldViewProj) ) == 16 );
assert( cgD3D9TypeToSize( cgGetParameterType(g_CGparam_constColor)
) == 4 );
//
// Program boyunca değişmeyen uniform parametreler ayarlanıyor.
// Sadece parametre gölgeleme etkinleştiğinde cgD3D9LoadProgram
// çağrısı sırasında tek bir kez ayarlanması yeterlidir.
//
}
D3DXVECTOR4 vConstColor( 0.0f, 0.0f, 1.0f, 0.0f );
cgD3D9SetUniform( g_CGparam_constColor, &vConstColor );
//----------------------------------------------------------------------// shutDown(): Daha önceden başlatılmış tüm nesneleri serbest bırak
//----------------------------------------------------------------------void shutDown( void )
{
cgD3D9SetDevice(NULL);
cgDestroyProgram(g_CGprogram);
cgDestroyContext(g_CGcontext);
if( g_pVertexBuffer != NULL )
{
g_pVertexBuffer->Release();
g_pVertexBuffer = NULL;
}
if( g_pd3dDevice != NULL )
{
g_pd3dDevice->Release();
g_pd3dDevice = NULL;
}
//----------------------------------------------------------------------// setShaderConstants() : Shader sabitlerini ayarla
//----------------------------------------------------------------------void setShaderConstants( void )
{
D3DXMATRIX matTrans;
D3DXMATRIX matRot;
D3DXMatrixTranslation( &matTrans, 0.0f, 0.0f, 4.0f );
D3DXMatrixRotationYawPitchRoll( &matRot,
D3DXToRadian(g_fSpinX),
D3DXToRadian(g_fSpinY),
0.0f );
Umut DOGAN - Bitirme Tezi - Haziran 2006
}
if( g_pD3D != NULL )
{
g_pD3D->Release();
g_pD3D = NULL;
}
55
g_matWorld = matRot * matTrans;
D3DXMatrixIdentity( &g_matView );
D3DXMATRIX worldViewProj = g_matWorld * g_matView * g_matProj;
D3DXMatrixTranspose( &worldViewProj, &worldViewProj );
}
// world-view-projection matrisi kombinasyonunu yükle
cgD3D9SetUniformMatrix( g_CGparam_worldViewProj, &worldViewProj );
//----------------------------------------------------------------------// render() : Sahneyi çizer
//----------------------------------------------------------------------void render( void )
{
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_COLORVALUE(0.0f,0.0f,0.0f,1.0f), 1.0f,
0 );
g_pd3dDevice->BeginScene();
g_pd3dDevice->SetVertexDeclaration( g_pVertexDeclaration );
cgD3D9BindProgram( g_CGprogram );
setShaderConstants();
g_pd3dDevice->SetStreamSource( 0, g_pVertexBuffer, 0,
sizeof(Vertex) );
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
g_pd3dDevice->EndScene();
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}
Bu uygulamada sadece vertex programıkullandı
k. Hangi programıkullanacağı
mı
z,
kaç tane vertex veya fragment shader programıkullanacağı
mı
z tamamen bize kalmı
ş
tı
r.
struct vertex
{
float4 position : POSITION;
float4 color0
: COLOR0;
};
struct fragment
{
float4 position : POSITION;
float4 color0
: COLOR0;
};
//----------------------------------------------------------------------// IN
- her bir vertex için işlenecek gelen veri
// worldViewProj - world-view-projection matris kombinasyonu
Umut DOGAN - Bitirme Tezi - Haziran 2006
İ
lgili vertex programıda ş
uş
ekildedir.
56
// constColor
- sabit renk
//----------------------------------------------------------------------fragment main( vertex IN,
uniform float4x4 worldViewProj,
uniform float4
constColor )
{
fragment OUT;
// float3'ten float4 oluşturuluyor
float4 tempPosition = float4( IN.position.x,
IN.position.y,
IN.position.z,
1.0f );
OUT.position = mul( worldViewProj, tempPosition );
OUT.color0 = IN.color0; // Belirtilen orijinal rengi kullan
return OUT;
}
Uygulamadan iki ekran görüntüsü Şekil 3.1’de verilmiş
tir. Bu program, basit yapı
sı
sayesinde 32 MB paylaş
ı
mlıekran kartıkullanan dizüstü bilgisayarı
mda rahatlı
kla çalı
ş
tı
.
Oysa pürüzlü yüzey dokusu üretimi için geliş
miş128 MB’lı
k bir ekran kartıkullanmak
zorunda kaldı
m. Buradan Cg’nin esnek profil yapı
sı
nı
n ne kadar yararlıolduğu
Şekil 3.1: Basit Bir Vertex Programı
Umut DOGAN - Bitirme Tezi - Haziran 2006
görülebiliyor.
57
3.3. Dalgalanan Türk BayrağıUygulaması
İ
kinci ve son uygulama olarak ekranda dalgalanan Türk bayrağı
mı
zı
n olduğu bir
uygulama seçtim. Bu uygulamayıda parçalar halinde inceleyeceğim. Öniş
lemci komutları
ve global değiş
kenlerin birçoğu 3.2. bölümdeki programla aynıolduğ
u için bunları
belirtmedim.
float
double
double
float
float
g_fElpasedTime;
g_dCurTime;
g_dLastTime;
g_fSpinX = 0.0f;
g_fSpinY = 0.0f;
float g_fCurrentAngle
= 0.0f;
float g_fSpeedOfRotation = 10.0f;
bool g_bWireFrameMode
= false;
D3DXMATRIX g_matWorld;
D3DXMATRIX g_matView;
D3DXMATRIX g_matProj;
const int g_nNumVertsX = 16; // x ekseni boyunca bayrak vertexlerinin
sayısı
const int g_nNumVertsZ = 16; // z ekseni boyunca bayrak vertexlerinin
sayısı
// Bayrak için gerekli üçgen sayısı
const int g_nTriCount = (g_nNumVertsX-1)*(g_nNumVertsZ-1)*2;
const int g_nVertCount = g_nTriCount*3;
struct Vertex
{
D3DXVECTOR3 position;
D3DXVECTOR3 normal;
D3DXVECTOR2 texcoords;
enum FVF
{
FVF_Flags = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1
};
Bayrak dokusunu yüklemek için gerekli fonksiyon alta verilmiş
tir. Standart
Direct3D komutlarıkullanarak basit bir ş
ekilde doku belirlenebiliyor. Arka plandaki
iş
lemleri Direct3D API’si bizim için hallediyor.
void loadTexture( void )
{
D3DXCreateTextureFromFile( g_pd3dDevice, "tr_bayrak.bmp", &g_pTexture
);
Umut DOGAN - Bitirme Tezi - Haziran 2006
};
58
g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER,
D3DTEXF_LINEAR);
g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER,
D3DTEXF_LINEAR);
}
Baş
latma iş
lemleri init() fonksiyonunda gerçekleş
tiriliyor.
void init( void )
{
g_pD3D = Direct3DCreate9( D3D_SDK_VERSION );
D3DDISPLAYMODE d3ddm;
g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm );
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed
d3dpp.SwapEffect
d3dpp.BackBufferFormat
d3dpp.EnableAutoDepthStencil
d3dpp.AutoDepthStencilFormat
d3dpp.PresentationInterval
=
=
=
=
=
=
TRUE;
D3DSWAPEFFECT_DISCARD;
d3ddm.Format;
TRUE;
D3DFMT_D16;
D3DPRESENT_INTERVAL_IMMEDIATE;
g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice );
g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
D3DXMatrixPerspectiveFovLH( &g_matProj, D3DXToRadian( 45.0f ),
640.0f / 480.0f, 0.1f, 100.0f );
g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &g_matProj );
loadTexture();
}
createMesh();
createMesh() fonksiyonuylaysa bayrak için mesh oluş
turuluyor.
// kare biçimli bir mesh oluştur. (g_nNumVertsX * g_nNumVertsZ)
float dX = (1.0f/(g_nNumVertsX-1));
float dZ = -(1.0f/(g_nNumVertsZ-1));
float dTU = 1.0f/(g_nNumVertsX-1);
float dTV = 1.0f/(g_nNumVertsZ-1);
int i
int x
int z
float
float
= 0;
= 0;
= 0;
fSizeFactorX = 8.0f;
fSizeFactorZ = 5.0f;
Umut DOGAN - Bitirme Tezi - Haziran 2006
void createMesh( void )
{
59
Vertex *v = NULL;
g_pd3dDevice->CreateVertexBuffer( g_nTriCount*3*sizeof(Vertex),
D3DUSAGE_WRITEONLY,
Vertex::FVF_Flags,
D3DPOOL_MANAGED,
&g_pMeshVertexBuffer, NULL );
g_pMeshVertexBuffer->Lock( 0, 0, (void**)&v, 0 );
// Normal her vertex için aynıdır.
for( i = 0; i < g_nVertCount; ++i )
v[i].normal = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
for( z = 0, i = 0; z < (g_nNumVertsZ-1); ++z )
{
for( x = 0; x < (g_nNumVertsX-1); ++x )
{
// İlk üçgen...
v[i].position = D3DXVECTOR3(fSizeFactorX*x*dX, 0.0f,
fSizeFactorZ*z*dZ );
v[i].texcoords = D3DXVECTOR2(x * dTU, z * dTV);
++i;
v[i].position = D3DXVECTOR3(fSizeFactorX*x*dX, 0.0f,
fSizeFactorZ*(z+1)*dZ );
v[i].texcoords = D3DXVECTOR2(x * dTU, (z+1.0f) * dTV);
++i;
v[i].position = D3DXVECTOR3(fSizeFactorX*(x+1)*dX, 0.0f,
fSizeFactorZ*(z+1)*dZ );
v[i].texcoords = D3DXVECTOR2((x+1.0f) * dTU, (z+1.0f) *
dTV);
++i;
// İkinci Üçgen...
v[i].position = D3DXVECTOR3(fSizeFactorX*(x+1)*dX, 0.0f,
fSizeFactorZ*(z+1)*dZ );
v[i].texcoords = D3DXVECTOR2((x+1.0f) * dTU, (z+1.0f) *
dTV);
++i;
v[i].position = D3DXVECTOR3(fSizeFactorX*(x+1)*dX, 0.0f,
fSizeFactorZ*z*dZ );
v[i].texcoords = D3DXVECTOR2((x+1.0f) * dTU, z * dTV);
++i;
}
}
}
g_pMeshVertexBuffer->Unlock();
Umut DOGAN - Bitirme Tezi - Haziran 2006
v[i].position = D3DXVECTOR3(fSizeFactorX*x*dX, 0.0f,
fSizeFactorZ*z*dZ );
v[i].texcoords = D3DXVECTOR2(x * dTU, z * dTU);
++i;
60
Şimdi de initShader() fonksiyonuyla shader bağlantı
larıbelirleniyor.
void initShader(void)
{
// Context oluştur...
g_CGcontext = cgCreateContext();
// Direct3D aygıtını Cg'ye geç...
cgD3D9SetDevice( g_pd3dDevice );
// En uygun profili seç...
CGprofile vertexProfile = cgD3D9GetLatestVertexProfile();
const char* vertexOptions[] =
{
"-profileopts", "dcls", NULL,
};
// Vertex shader oluştur...
g_CGprogram = cgCreateProgramFromFile( g_CGcontext, CG_SOURCE,
"dx9_cg_vertex_turkiye.cg",
vertexProfile,"main",
vertexOptions );
// Binding Semantics Deklarasyonları
const D3DVERTEXELEMENT9 declaration[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_POSITION, 0 },
{ 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_NORMAL,
0 },
{ 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_TEXCOORD, 0 },
D3DDECL_END()
};
));
assert(cgD3D9ValidateVertexDeclaration( g_CGprogram, declaration
g_pd3dDevice->CreateVertexDeclaration( declaration,
&g_pVertexDeclaration );
// Bazı parametreleri ada göre bind yap
g_CGparam_worldViewProj = cgGetNamedParameter( g_CGprogram,
"worldViewProj" );
g_CGparam_currentAngle = cgGetNamedParameter( g_CGprogram,
"currentAngle" );
// Prametreler istenen boyutta mı?
assert(cgD3D9TypeToSize(cgGetParameterType(g_CGparam_worldViewProj)
) == 16 );
assert(cgD3D9TypeToSize(cgGetParameterType(g_CGparam_currentAngle))
== 4 );
}
Umut DOGAN - Bitirme Tezi - Haziran 2006
// Cg programını yükle
cgD3D9LoadProgram( g_CGprogram, TRUE, 0 );
61
Kullandı
ğ
ı
mı
z kaynaklarıgeri verirken shutDown() fonksiyonu kullanı
lı
yor.
void shutDown( void )
{
cgD3D9SetDevice(NULL);
cgDestroyProgram(g_CGprogram);
cgDestroyContext(g_CGcontext);
if( g_pTexture != NULL )
g_pTexture->Release();
if( g_pMeshVertexBuffer != NULL )
g_pMeshVertexBuffer->Release();
if( g_pd3dDevice != NULL )
g_pd3dDevice->Release();
if( g_pD3D != NULL )
g_pD3D->Release();
}
Shader sabitleri setShaderConstants() fonksiyonunda ayarlanı
yor.
void setShaderConstants( void )
{
g_fCurrentAngle -= g_fSpeedOfRotation * g_fElpasedTime;
while( g_fCurrentAngle > 360.0f ) g_fCurrentAngle -= 360.0f;
while( g_fCurrentAngle < 0.0f
) g_fCurrentAngle += 360.0f;
D3DXMATRIX matTrans;
D3DXMATRIX matRot;
D3DXMatrixTranslation( &matTrans, -4.0f, 2.5f, 10.0f );
D3DXMatrixRotationYawPitchRoll( &matRot,
D3DXToRadian(g_fSpinX),
D3DXToRadian(g_fSpinY - 90.0f),
0.0f );
g_matWorld = matRot * matTrans;
D3DXMatrixIdentity( &g_matView );
D3DXMATRIX worldViewProj = g_matWorld * g_matView * g_matProj;
D3DXMatrixTranspose( &worldViewProj, &worldViewProj );
}
cgD3D9SetUniformMatrix( g_CGparam_worldViewProj, &worldViewProj );
cgD3D9SetUniform( g_CGparam_currentAngle, &vfCurrentAngle );
Ve sahne oluş
turma fonksiyonu da ş
uş
ekildedir.
void render( void )
{
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_COLORVALUE(0.0f,0.0f,0.0f,1.0f), 1.0f,
0 );
Umut DOGAN - Bitirme Tezi - Haziran 2006
D3DXVECTOR3 vfCurrentAngle( g_fCurrentAngle, 0.0f, 0.0f );
62
g_pd3dDevice->BeginScene();
);
if( g_bWireFrameMode )
g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME
else
g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
g_pd3dDevice->SetTexture( 0, g_pTexture );
g_pd3dDevice->SetStreamSource(0, g_pMeshVertexBuffer, 0, sizeof(
Vertex ) );
setShaderConstants();
g_pd3dDevice->SetVertexDeclaration( g_pVertexDeclaration );
cgD3D9BindProgram( g_CGprogram );
g_pd3dDevice->SetStreamSource( 0, g_pMeshVertexBuffer, 0,
sizeof(Vertex) );
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, g_nTriCount );
g_pd3dDevice->EndScene();
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}
Ayarlamalarıyukarı
daki ş
ekilde yaptı
ktan sonra Cg programı
mı
zı
n içeriği de ş
öyle
olmalı
dı
r.
struct vertex
{
float3 position : POSITION;
float3 normal
: NORMAL;
float2 texcoord0 : TEXCOORD0;
};
//----------------------------------------------------------------------// IN
- Her bir vertex için işlenecek gelen veri
// worldViewProj - model-view-projection matrisi kombibnasyonu
// currentAngle - 0 ile 360 arasında tekrar eden bir deger
//----------------------------------------------------------------------fragment main( vertex IN,
uniform float4x4 worldViewProj,
uniform float4 currentAngle )
{
fragment OUT;
float4 v = float4( IN.position.x, IN.position.y, IN.position.z,
1.0f );
//
//
//
//
Öncelikle, vertexlerin Y'lerinin; X'leri ve 0 ile 360 arasında
değişen uniform parametre değeriyle toplamı şeklinde yer
değiştirmesi için sin() fonksiyonu kullanılıyor. Bu şekilde
ekrandaki geometrik şekil sinüs dalgası gibi dalgalanıyor.
Umut DOGAN - Bitirme Tezi - Haziran 2006
struct fragment
{
float4 position : POSITION;
float2 texcoord0 : TEXCOORD0;
};
63
//
//
//
//
//
//
//
//
//
//
//
//
//
Bayrağımızın tam bir sinüs dalgası gibi dalgalanmasını
istemediğimiz için sin()'i tekrar çağırarak bir değişim
uyguluyoruz ama bu kez Z değerini kullanıyoruz.
Ayrıca bayrak direğine yakın olan vertexlerin çok fazla hareket
etmemesini istiyoruz, çünkü fiziksel gerçek böyledir. Bunun için
de şöyle yapıyoruz: Bayrak direğine yakın olan değerlerde tekrar
X değerlerini kullanarak Y değerlerinin hareketini azaltıyoruz.
X değerleri bayrak direğinin yakınlarında 0.0f'den başladığı ve
uzaklaştıkça büyüdüğü için bu işlem fazla zorluk çıkarmıyor.
Son olarak, görsel güzellik için 0.08f değeri kullanılmıştır.
v.y = sin( IN.position.x + currentAngle.x );
v.y += sin( IN.position.z + currentAngle.x );
v.y *= IN.position.x * 0.08f;
OUT.position = mul( worldViewProj, v );
OUT.texcoord0 = IN.texcoord0;
return OUT;
}
Uygulamadan iki ekran görüntüsü Şekil 3.2’de görülmektedir.
Şekil 3.2: Dalgalanan Türk Bayrağı
Böylece Cg ile Direct3D’yi rahatlı
kla birlikte kullanabileceğimizi görmüşolduk.
Zamanla pratik kazanı
larak bunun üstesinden rahatlı
kla gelinebilinir. Ayrı
ca bu
uygulamalar için Visual C++, Direct3D, Cg’nin üçün de bilmek zorunda olmak bir
dezavantaj gibi görülebilir. Ama Cg birçok dil ve 3D API kullanarak kod yazmamı
za
olanak sağladı
ğıiçin C#, VB.NET veya baş
ka bir dille yazmanı
n da pek bir zorluğu
bulunmamaktadı
r. Dördüncü bölümde Cg dili kullanı
larak pürüzlü yüzey dokusu
üretilmeye çalı
ş
ı
lacaktı
r.
Umut DOGAN - Bitirme Tezi - Haziran 2006
Burada en kafa karı
ş
tı
rı
cınokta ne zaman ve nası
l shader bağlantı
ları
nı
n kurulacağı
dı
r.
4. Cg İ
LE PÜRÜZLÜ YÜZEY DOKUSU ÜRETİ
Mİ
4.1. Pürüzlü Yüzey Dokusu Üretimi Programlama Ortamı
Pürüzlü yüzey dokusuyla ilgili kodu OpenGL ve Cg kullanarak yazdı
m. Kodları
n
yazı
mısı
rası
nda Visual Studio 2003 ortamı
nıkullandı
m. Dil olarak da Visual C++
tercihimdi.
4.2. Pürüzlü Yüzey Dokusu Üretimi Nedir
Pürüzlü yüzey dokusu üretimi basitçe Şekil 4.1’de görüldüğü gibi iki boyutlu
dokuları
n üç boyutlu gibi görünmesini sağlamak olarak açı
klanabilir.
Şekil 4.1: Orijinal 2B Resim ve Pürüzlü Yüzey Uygulanmı
şHali
(bump mapping) hemen hemen aynıiş
lemi ifade ederler. Çünkü pürüzlü yüzey dokusu
oluş
tururken yaptı
ğı
mı
z işdoku üzerinde verilen piksel için o anki ı
ş
ı
k yoğunluğunu
değerlendirmektir.
Pürüzlü yüzey dokusu üretimi (bump mapping) ilk olarak, 1978 yı
lı
nda Blinn
tarafı
ndan yazı
lan bir makalede ortaya atı
lmı
ş
tı
r. Geçen yı
llar süresince ana algoritma
üzerinde bir çok optimizasyon iş
lemi gerçekleş
tirilmeye çalı
ş
ı
lmı
şve farklıpürüzlü yüzey
Umut DOGAN - Bitirme Tezi - Haziran 2006
Piksel baş
ı
na ı
ş
ı
klandı
rma (per pixel lighting) ve pürüzlü yüzey dokusu üretimi
65
dokusu üretimi teknikleri üretilmiş
tir. Bu konulardaki tartı
ş
malarıkonunun özünden
sapmamak amacı
yla buraya almı
yorum. Ancak “Kaynaklar” kı
smı
nda verdiğim kaynaklar
farklıpürüzlü yüzey dokusu üretimi teknikleriyle, GPU üzerinde gerçeklenmesiyle ilgili
gerekli alt yapı
yısağlamaktadı
r. Tezimdeki amacı
m da GPU üzerinde pürüzlü yüzey
dokusu üretimini gerçekleş
tirmek olduğ
undan bu tip kaynaklardan sı
k sı
k yararlandı
m.
Özellikle aydı
nlatma modelleriyle ilgili kaynaklar önemli bilgiler içermektedir.
Tezimde 1978 yı
lı
nda Blinn tarafı
ndan önerilen teorik algoritmaya yakı
n bir
algoritma kullandı
m. Algoritmanı
n ayrı
ntı
larıbir sonraki baş
lı
kta açı
klanmı
ş
tı
r.
4.3.Programda Kullanı
lan Algoritmalar
Sı
radan iki boyutlu bir doku ele alalı
m. Bu dokunun yüzeyi düzdür ve doku
yüzeyinin normalleri Şekil 4.2a’da görüldüğü gibi direkt yukarı
ya doğru olacaktı
r. İ
ş
te bu
yüzden eskiden üç boyutlu oyunlarıoynarken küp ş
eklindeki bir kutuya yaklaş
tı
ğı
mı
zda
kutunun derinliği yokmuşgibi görünürdü. Bu yüzden de iki boyutlu dokular kullanı
lan
oyunlardan çok çabuk bir ş
ekilde sı
kı
lı
rdı
k.
Bu problemin çözümü, sahneyi gerçekledikçe doku üzerinde ı
ş
ı
k yoğunlukları
nı
sürekli değiş
tirmektir. Örneğin Şekil 4.1’de sağ
daki resimde ı
ş
ı
ğı
n sol üst köş
eden
geldiğ
ini düş
ünelim. Bu durumda taş
ı
nı
ş
ı
ğa doğru bakan uçlarıı
ş
ı
ğa bakmayan uçları
ndan
daha parlak görünecektir. İ
ş
te bizim istediğimiz görüntü de böyle bir görüntüdür.
Yaptı
ğı
mı
z ise her piksel için renk yoğ
unluğunu hesaplamak ve böylece dokuya sahte bir
derinlik kazandı
rmaktı
r. Böylece oyuncu gerçekten üç boyutlu bir dünyada oynadı
ğı
nı
Verilen doku öğesine (texel, texture element) ait ı
ş
ı
k yoğunluğunu hesaplayabilmek
için her bir doku öğesine ait yüzey normallerini bilmeliyiz. İ
ş
te bu noktada normal map
devreye giriyor. Normal map, her bir doku öğesi için yüzey normallerinin yön bilgisini
tutar. (Şekil 4.2b). Şekil 4.2b’de altta çizilmişkavisli yüzey normallerin benzetmeye
çalı
ş
tı
ğıgerçek yüzeydir.
Umut DOGAN - Bitirme Tezi - Haziran 2006
düş
ünecek ve oyundan daha büyük keyif alacaktı
r.
66
Şekil 4.2: (a) Herhangi bir yüzey dokusu (b) normal map
Gerçek bir normal map ise Şekil 4.3’te gösterilmiş
tir. Bu ş
ekil ilk bakı
ş
ta biraz
garip gelebilir ama ş
ekille ilgili açı
klamalardan sonra neden böyle olduğ
u daha iyi
anlaş
ı
lacaktı
r. Dokunun sol alt köş
esinde belirtilen üç eksenden x ekseni sağa, y ekseni
yukarıve z ekseni de ekrandan dı
ş
a doğ
rudur. Şimdi kı
rmı
zı
yla x, yeş
ille y ve maviyle de z
eksenini gösterelim. Şekle yakı
ndan bakı
lı
rsa +x eksenine doğru bakan kenarları
n kı
rmı
zı
,
+y eksenine doğru bakanları
n yeş
il ve yüzeyden dı
ş
a doğru çı
kan kı
sı
mları
nda mavi renkte
olduklarıgörülür. Dokumuzun yapı
sıitibariyle birçok kı
sı
m ekrandan dı
ş
a doğru olduğu
Şekil 4.3: Normal Map
Bu projede gerçekleş
tirdiğim önemli noktalardan birisi, verilen doku öğesi için
seçilmişrengi o konumdaki normalin yönü olarak belirlemektir. Normalin yönü üç
koordinatla gösterilmektedir. Bu koordinatlar [x, y, z] ‘dir ve her biri [-1,1] aralı
ğı
nda
değerler almaktadı
r. Ama dokumuzdaki renkler RGB (red, green, blue) ş
eklinde temsil
edilmekte ve [0,1] aralı
ğı
nda değerler alabilmektedir. Kı
rmı
zıdeğerleri x, yeş
il değerleri y
Umut DOGAN - Bitirme Tezi - Haziran 2006
için normal map’in büyük kı
smımavi renktedir.
67
ve mavi değerleri z olarak yorumlamak istiyorum. Bu yüzden [-1,1] aralı
ğı
ndaki değerleri
[0,1] aralı
ğı
na dönüş
türmem gerekli. Bu iş
leme renk değerlerini açma (decompressing)
deniyor. Renk değerlerini gerçek koordinat değerlerine açmak için ş
u eş
itlik kullanı
lı
yor:
x = 2.0 * (renkDegeri - 0.5)
0 değerini renkDegeri – 1 olarak belirlemeliyiz.
Bu noktada her bir doku öğesi için normallerin yönünü normal map’ten okuyup
yorumlayabilecek hale gelmişolduk.
Aydı
nlatma eş
itliği dinamik aydı
nlatmayla uğraş
ı
rken önemlidir. Alttaki ş
ekilde
formüle edilebilir:
I = A + att*(D + S)
Burada;
I son renk yoğunluğudur.
A çevre aydı
nlı
ğı
dı
r (ambient light). Çevre aydı
nlı
ğı
nıeklememizin nedeni gerçek
dünyayıtaklit edebilecek ş
ekilde tümüyle karanlı
k alanları
n oluş
ması
nıengellemektir. Bu
yüzden tüm piksellere uygulanacak bir varsayı
lan ı
ş
ı
k tanı
mladı
k.
att ise ı
ş
ı
ğı
n zayı
flama miktarı
nı(attenuation) temsil etmektedir. Tüm ı
ş
ı
k
kaynakları
nda ı
ş
ı
ğı
n eriş
ebileceği bir maksimum uzaklı
k vardı
r. Bu mesafe, üzerinde
çalı
ş
ı
lan piksel için renk solgunluğunun ne kadar olacağı
n belli eder.
D, yayı
nı
k (diffuse) renktir. Yayı
nı
k renk, ı
ş
ı
k bir nesneye çarptı
ğı
nda gördüğümüz
renktir.
Formülde I = D değiş
ikliği yaparak aydı
nlatma eş
itliğini biraz daha basitleş
tirdim.
Yani programda tek ilgileneceğimiz bileş
en yayı
nı
k bileş
en olacaktı
r. Buna göre formül;
I = Dl * Dm * clamp(L•N, 0, 1) ş
eklini alacaktı
r.
Burada;
Dl: ı
ş
ı
ğı
n yayı
nı
k rengidir.
Dm: nesne üzerindeki materyalin yayı
nı
k rengidir.
L: Yüzey üzerindeki bir noktadan ı
ş
ı
k kaynağı
na doğru olan vektördür.
Umut DOGAN - Bitirme Tezi - Haziran 2006
S, aynasal (specular) renktir. Nesnenin yansı
ttı
ğıı
ş
ı
ktı
r.
68
N: Üzerinde çalı
ş
tı
ğ
ı
mı
z piksel için yüzeyin normalidir.
L•N ise L ve M’nin iç çarpı
mı
dı
r.
Basitleş
tirilmişaydı
nlatma eş
itliğimize göre verilen herhangi bir piksel için baş
arı
lı
bir ş
ekilde ı
ş
ı
k yoğunluğunu hesaplayabilmek için üç parametreye ihtiyacı
mı
z vardı
r. L ile
N arası
ndaki iç çarpı
mla baş
layalı
m.
Burada L basit bir ş
ekilde o anki vertexin konumunu ı
ş
ı
k pozisyonundan
çı
karı
larak bulunabilir. N de daha önce açı
kladı
ğı
m normal map’ten kolay bir ş
ekilde
okunabilir. Dm, yani üzerinde çalı
ş
ı
lan doku öğesi için materyalin rengi orijinal dokudaki
rengi kullanacağ
ı
z. Şekil 4.1’de verdiğimiz örnekte Dm renginin gri taşrenginde olduğu
görülüyor. Dl ise ı
ş
ı
ğ
ı
n rengidir ve genellikle beyazdı
r.
Şekil 4.4: Yüzeyle İ
liş
kili Vektörler
Bu kı
sma kadar pürüzlü yüzey dokusu üretimiyle ilgili teoriyi büyük oranda
bitirmişolduk. 3B API’lerde modelview ve projeksiyon matrisleri önemli kavramlardı
r.
Pürüzlü yüzey dokusu üretimi projemde de bu kavramlarıkullandı
ğı
m için açı
klama gereği
duydum. Modelview ve projeksiyon matrisleri bir vertexi nesne uzayı
ndan (object space),
Umut DOGAN - Bitirme Tezi - Haziran 2006
Şekil 4.4’te yüzeyle iliş
kili vektörleri görsel olarak açı
klamaya çalı
ş
tı
m.
69
ekran uzayı
na (clip space) taş
ı
mak için kullanı
lı
r. Nesne uzayıkod yazarken kullandı
ğı
mı
z
koordinat sistemidir. Örneğin OpenGL’de glTranslatef(10.0f, 0.0f, -20.0f)
komtunu kullanı
p bir nesneyi x,y,z koordinatları
nda ötelememiz gibi. Tüm nesne uzayı
vertexlerini monitörümüzde düzgün bir ş
ekilde görüntülenebilmesi için ekran uzayı
na
dönüş
türmeliyiz. Bu iş
lem birbirine bağlımodelview ve projeksiyon matrisleriyle nesne
uzayı
ndaki bir vertexin çarpı
lması
yla olur.(Eğer shader kullanmı
yor olsaydı
k bu iş
lem
OpenGL tarafı
ndan otomatik olarak yapı
lı
yor olacaktı
.)
Farklıuzaylar arası
ndaki iliş
kiler ve bu uzayları
n birbirlerine nası
l dönüş
türüleceğ
i
Şekil 4.5: Uzaylar ve Dönüş
üm Matrisleri
Bu noktada biraz da teğet uzayıüzerinde duralı
m. Teğet (veya doku) uzayıŞekil
4.6’da görüldüğü gibi yüzeyle ilgili bir uzaydı
r.
Umut DOGAN - Bitirme Tezi - Haziran 2006
Şekil 4.5’te gösterilmiş
tir.
70
Şekil 4.6: Teğet UzayıKoordinatları
S teğetini x ekseni, T teğetini y ekseni ve normali de z ekseni olarak düş
ünebiliriz.
Şekilden de görüldüğ
ü gibi yüzey üzerindeki her bir vertexin kendi teğet uzayıvardı
r. (Her
bir köş
ede bir tane olmak üzere toplamda dört vertex). Üç eksen belli bir vertex için temel
oluş
turur ve teğ
et uzayı(tanjant veya doku uzayıda denir) adıverilen bir koordinat uzayı
oluş
tururlar. Eğer eksenleri bir matrisle temsil edecek olursak TBN matrisini (Tangent,
Binormal, Normal) elde etmişoluruz. Burada T ile S teğeti, binormal ile de T teğeti ifade
edilmektedir.
(Tx, Bx, Nx)
(Ty, By, Ny)
Teğet uzayı
ndaki herhangi bir noktayıbu matrisle çarparsak noktayınesne uzayı
na
çevirmişoluruz.
Verilen bir vertex için teğet temelini hesaplamak için alttaki eş
itliği kullanacağı
z.
Bu eş
itliğin nası
l elde edildiğiyle ilgili ayrı
ntı
lar için Kaynaklar kı
smı
na bakabilirsiniz.
Umut DOGAN - Bitirme Tezi - Haziran 2006
(Tz, Bz, Nz)
71
Buradan T ve B matrislerini;
ş
eklinde elde ederiz.
Burada;
Δv2v1 vertex1’
den vertex2’
ye olan vektördür. (V2-V1)
Δv3v1 vertex1’den vertex3’ye olan vektördür. (V3-V1)
Δc2c1T v2.dokuKoord.x – v1.dokuKoord.x
Δc2c1B v2.dokuKoord.y – v1.dokuKoord.y
Δc3c1T v2.dokuKoord.x – v1.dokuKoord.x
Δc3c1B v2.dokuKoord.y – v1.dokuKoord.y
ve
ş
eklindedir.
Normal map ve aydı
nlatma eş
itliğ
i anlatı
lı
rken yüzeydeki herhangi bir vektör ve
ı
ş
ı
k vektörünün iç çarpı
mı
nıyapmak istediğimizi belirtmiş
tik. Yüzey normali teğet
uzayı
nda bulunmaktadı
r ve ı
ş
ı
k vektörü de nesne uzayı
nda bulunmaktadı
r. İ
ş
te bu noktada,
iç çarpı
mı
n bir anlam ifade edebilmesi için bu iki vektörün aynıuzayda olması
nıistiyoruz.
Bu nedenle önümüzde ş
u iki seçenek var:
1) Iş
ı
k vektörünü teğet uzayı
na dönüş
türmek
Birinci seçeneğin daha mantı
klıolduğu görülmektedir. Eğer ikinci seçeneği seçmiş
olsaydı
k normal map’teki tüm normalleri nesne uzayı
na dönüş
türmemiz gerekecekti. Bu da
önemli miktarda performans düş
üş
ü demektir. TBN matrisi teğet uzayı
ndan nesne uzayı
na
dönüş
türdüğ
ü için biz bunun tam tersi yönde iş
lem yapmalı
yı
z. Yani altta görüldüğü gibi
TBN matrisinin tersini almalı
yı
z.
Umut DOGAN - Bitirme Tezi - Haziran 2006
2) Normal map’teki tüm yüzey normallerini nesne uzayı
na dönüş
türmek
72
Bir de optimizasyon gerçekleş
tirdik. Sadece üçgenlerle uğraş
tı
ğı
mı
z için her bir
üçgene ait tek bir ters TBN matrisi hesaplamamı
z yeterlidir. Yani her bir vertex için
hesaplama yapma zorunluluğumuz ortadan kalkmı
ş
tı
r. Ama burada önemli olan nokta
üçgen her döndürüldüğünde ter TBN matrisi tekrar hesaplanmalı
dı
r. Üçgenin ötelenmesi
için yeniden hesaplama gerektirmez.
Yani tek yapmamı
z gereken ters TBN matrisini ı
ş
ı
k vektörüyle çarpmaktı
r. Böylece
ı
ş
ı
k vektörünü teğet uzayı
na taş
ı
mı
şve iç çarpı
m hesaplamasıiçin hazı
r hale getirmiş
olduk.
Pürüzlü yüzey dokusu üretirken yaptı
ğı
mı
z iş
lemleri ş
öyle bir özetleyelim:
1)
Tüm üçgenler için ters TBN matrisi hesapla. (Sadece baş
langı
çta ve
dönme olduğunda yapı
lmasıgerekiyor.)
2)
Iş
ı
k vektörünü hesapla bu vektörü nesne uzayı
ndan teğet uzayı
na taş
ı
.
3)
Normal vektörünü normal haritası
ndan oku ve aralı
ğı[-1,1]’den [0,1]
aralı
ğı
na aç.
4)
Iş
ı
k vektörüyle normalin iç çarpı
mı
nıyap. Daha sonra bu çarpı
mla ı
ş
ı
ğ
ı
n
rengini ve yüzey materyalinin rengi çarparak sonuç yayı
nı
k rengini bul.
5)
Bütün bu iş
lemleri verilen yüzeydeki her piksel için tekrarla.
Önceki baş
lı
klarda Cg’nin NVIDIA firmasıtarafı
ndan geliş
tirilmişbir shader dili
olduğunu belirtmiş
; tarihçesi ve sözdizimiyle ilgili ayrı
ntı
larıvermiş
tim. Shader, grafik
kartı
mı
zı
n GPU’suna indirdiğimiz küçük bir programdı
r. Shader, doğrudan grafik kartı
nı
n
üzerinde koş
tuğundan çok güçlüdür ve doku ve matris gibi ş
eylere doğ
rudan eriş
ebilir.
Umut DOGAN - Bitirme Tezi - Haziran 2006
4.4.Cg ile İ
lgili Kı
sa Bilgiler
73
4.5. Cg Runtime
İ
ki tür shader vardı
r: Birincisi vertex shader ve ikincisi de fragment (pixel) shader.
Vertex shader glVertex3f() gibi komutlarla ekrana çizdiğ
imiz her vertex için çağrı
lı
r. Şekil
4.7’deki gibi üç tane glVertex3f() çağrı
sıalan bir üçgen çizdiğimizi düş
ünelim. Bu, aktif
olan vertex shader’ı
n üç kez çağrı
lması
nıgerektirecektir. Daha sonra üç vertex arası
ndaki
maddeyi (burada maviyle doldurulmuşkı
sı
m) tümüyle çizilinceye kadar üçgen boyunca
interpole ediyoruz. Üçgen üzerinde interpole ettiğimiz her piksel için fragment shader
çağrı
lı
yor.
Şekil 4.7: Üçgen ve Vertexleri
Temelde vertex shader, vertexlerin istediğimiz uzaya dönüş
türülmesiyle uğraş
ı
r.
Örneğ
in vertex shader, ı
ş
ı
k vektörünün nesne uzayı
ndan teğ
et uzayı
na dönüş
türülmesi için
mükemmel bir yerdir.
Öte yandan fragment shader iş
in sihirli kı
smı
nı
n olduğu yerdir. Fragment shader
Cg’yi uygulamamı
zda düzgün bir ş
ekilde kullanmak için bazıayarlamalar
yapmamı
z gerekiyor.
Öncelikle Cg context oluş
turmalı
yı
z. Cg context çok sayı
da Cg programıiçin bir
konteynerdir. Cg programıvertex veya shader programıolabilir. Ben de uygulamamda
öncelikle Cg context yarattı
m. Daha sonra bir vertex ve bir fragment programıyaratı
p bu
programlarıCg context’e bağladı
m. Bütün Cg programlarıCg context’e sahip olmalı
dı
r.
Umut DOGAN - Bitirme Tezi - Haziran 2006
her piksel için çağrı
ldı
ğı
ndan pürüzlü yüzey hesaplamaları
mı
zda kullanabiliriz.
74
Ayrı
ca önemli noktalardan biri de Cg profile’dir. Farklıgrafik kartlarıolduğu ve
birçoğu Cg’nin tüm shader özelliklerini desteklemediği için Cg profile tanı
mlamaları
sayesinde belli bir donanı
m platformu için Cg özellik kümesi tanı
mlanmı
şolur. Vertex
shaderları
n fragment shaderlardan farklıözellikleri olduğu için her biri için ayrıbir
profile’a ihtiyacı
mı
z vardı
r.
Daha sonra Cg context oluş
tururken, her bir Cg programıiçin programı
mı
zı
n
çalı
ş
tı
ğıbilgisayarı
n özelliklerine göre en uygun profili döndüren Cg profil fonksiyonunu
çağı
rı
yoruz. Daha sonra bu profilleri vertex ve fragment programları
na iliş
tiriyoruz.
Burada en önemli avantaj kodlamamı
zıstatik olarak belli bir profil için yapı
yor
olmamamı
zdı
r. Bunun yerine uygun profil koş
ma zamanı
nda (runtime) Cg profil
fonksiyonu tarafı
ndan belirleniyor. Böylece uygulamamı
zı
n çalı
ş
tı
ğ
ımakineye en uygun
profili seçmişoluyoruz.
Cg’deki önemli özelliklerden birisi de CG shaderlarla uğraş
ı
rken OpenGL’de veya
Direct3D’de dokularıyapabildiğimiz gibi burada da istediğimiz an shaderlarıetkinleş
tirip
pasifleş
tirebiliyoruz. Bu ş
ekilde uygulamamı
zda istediğimiz kadar shader program
kullanabiliyor ve uygulamamı
zı
n ihtiyaçları
na göre bunlar arası
nda geçiş
ler yapabiliyoruz.
Ama aynıanda sadece bir vertex ve bir fragment programıetkin olabiliyor. Eğ
er bütün
rendering olayları
nıshader programlarıyerine 3B API’mizin halletmesini istiyorsak tek
yapmamı
z gereken bütün etkin shaderlarıpasifleş
tirip gerekli ayarlamalarıyapmaktan
ibarettir.
Cg’nin bir baş
ka özelliğiyse shaderlarıkoş
ma zamanı
nda veya koş
ma zamanı
ndan
Cg derleyicisinin güncellenmişbir sürümünün özelliklerini de kullanma ş
ansı
mı
z olur.
Böylece ana program derlendikten yı
llar sonra bile shader çok daha verimli bir ş
ekilde
koş
abilir.
Umut DOGAN - Bitirme Tezi - Haziran 2006
önce derleyebiliyor olmamı
zdı
r. Eğer koş
ma zamanıderlemesinden yararlanacak olursak
75
4.6. Cg Shaderları
Öncelikle Cg shader programları
nıaçı
klamakla baş
lı
yorum. İ
lk programı
mı
z vertex
shader programı
. Vertex programı
nı
n görevi ı
ş
ı
k vektörünü nesne uzayı
ndan teğet uzayı
na
dönüş
türmektir. Ayrı
ca kullandı
ğı
mı
z shader OpenGL’in vertex handling mekanizması
nı
n
yerini aldı
ğıiçin her bir vertex konumunu nesne uzayı
ndan ekran uzayı
na manuel olarak
dönüş
türmemiz gerekmektedir. Önceki sayfalardaki teorik kı
sı
mda belirttiğim gibi bunu
yapabilmek için birleş
tirilmişmodelview ve projeksiyon matrisleriyle vertex konumu
çarpı
lmalı
dı
r. İ
ş
te bütün bu iş
lemleri yapan vertex shader program kodu açı
klamaları
yla
birlikte altta verilmiş
tir. Görüldüğü gibi program çok kı
sa ve anlaş
ı
labilir bir biçimdedir.
void main(
in float4 position
: POSITION,
// Üzerinde çalışılan vertexin konumu,
// vertex shader için bu parametre zorunludur.
in float2 texCoords
: TEXCOORD0,
// Veriyi shader'a göndermek için,
// glMultiTexCoord2fARB(GL_TEXTURE0_ARB, ...) kullanıyoruz.
in float3 vTangent
: TEXCOORD1,
// Veriyi shader'a göndermek için,
// glMultiTexCoord3fARB(GL_TEXTURE1_ARB, ...) kullanıyoruz.
in float3 vBinormal
: TEXCOORD2,
// Veriyi shader'a göndermek için,
// glMultiTexCoord3fARB(GL_TEXTURE2_ARB, ...) kullanıyoruz.
in float3 vNormal
: TEXCOORD3,
// Veriyi shader'a göndermek için,
// glMultiTexCoord3fARB(GL_TEXTURE3_ARB, ...) kullanıyoruz.
out float4 positionOUT
: POSITION,
// Dönüştürülmüş vertex konumunu fragment shadera gönder
out float2 normalCoordsOUT
: TEXCOORD1,
// Normal map'in doku koordinatlarını fragment shadera gönder
out float3 vLightVector
: TEXCOORD2,
// Dönüştürülmüş ışık vektörünü fragment shadera gönder
const uniform float4x4 modelViewProjMatrix,
// Birbirine bitiştirilmiş modelview ve projeksiyon matrisleri
const uniform float3 vLightPosition)
// Işık küresinin nesne uzayındaki konumu
{
Umut DOGAN - Bitirme Tezi - Haziran 2006
out float2 texCoordsOUT
: TEXCOORD0
// Doku map'in doku koordinatlarını fragment shadera gönder
76
// Işık vektörünü hesapla
vLightVector = vLightPosition - position.xyz;
// Işık vektörünü nesne uzayından teğet uzayına dönüştür
float3x3 TBNMatrix = float3x3(vTangent, vBinormal, vNormal);
vLightVector.xyz = mul(TBNMatrix, vLightVector);
// Üzerinde çalışılan vertexi nesne uzayından ekran uzayına
dönüştür
positionOUT = mul(modelViewProjMatrix, position);
// Doku map ve normal map'in koordinatlarını fragment shadera
gönder
texCoordsOUT = texCoords;
normalCoordsOUT = texCoords;
}
Bazıparametrelerden sonra kullandı
ğı
mı
z iki nokta üst üste (:) karakteri Cg’ye bu
parametreyi belli bir OpenGL çağrı
sı
na bağlamak istediğimizi belirtmektedir. Benzer
ş
ekilde eğ
er Direct3D API’si kullanmı
şolsaydı
m bu sefer de çağrıDirect3D ile ilgili
olacaktı
. Örneğin “:
POSITION”
“baseCoords : TEXCOORD0”
ile glVertex3f() çağrı
sı
nı
n değerini alı
r ve
ile de glMultiTexCoord2fARB(GL_TEXTURE0_ARB, ...)
komutuyla ayarladı
ğı
mı
z değ
erler kümesini alı
r.
“:
POSITION”
değerine bağlama
semantiği (binding semantic) denir. Burada dikkat edilirse her ikisi de aynıdeğerleri
içermesine rağmen doku ve normal map koordinatları
nıfragment shader’a ayrıayrı
gönderiyoruz. Bunun nedeni eski grafik kartları
yla uyumluluğu sağlayabilmektir. Tekörnek
(uniform) parametreler program boyunca çok fazla değ
iş
meyen parametrelerdir. Örneğ
in
ne ı
ş
ı
k konumu ne de birleş
tirilmişmodelview ve projeksiyon matrisleri, dörtgenimizi
oluş
turan dört vertexi oluş
tururken hiç değiş
ikliğe uğramazlar. Böylece ekrana bir ş
ey
çizmeye baş
lamadan önce tek biçim değ
erlerini main.cpp dosyamı
zda ş
u ş
ekilde
// Vertex shaderdaki "modelViewProjMatrix" parametresini üzerinde
çalışılan modelview ve projeksiyon matrislerine ayarla
cgGLSetStateMatrixParameter(g_modelViewMatrix,
CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);
// Vertex shaderdaki ışık konumu parametresini ayarla
cgGLSetParameter3f(g_lightPosition, g_vLightPos.x,
g_vLightPos.y, g_vLightPos.z);
Ayrı
ca shader’da out parametrelerini de bağlama sözdizimlerine nası
l bağladı
ğ
ı
mı
z
önemlidir. Bu sayede bunlarıfragment shader’dan doğrudan okuyabiliriz. Birazdan
Umut DOGAN - Bitirme Tezi - Haziran 2006
ayarlı
yoruz:
77
açı
klayacağı
m gibi örneğin vLightVector değeri TEXCOORD2’ye bağ
lanmı
ş
tı
r ve fragment
shader’da da TEXCOORD2 semantiğine bağlıolarak okunur.
Yukarı
da açı
klamasıverilen vertex shader kodu, olayı
n teorik boyutu anlaş
ı
ldı
ğı
nda
çok kolay bir ş
ekilde yazı
labilir. Fragment shader ise ş
öyledir:
void main(
in float4 colorIN
: COLOR0,
in float2 texCoords
: TEXCOORD0,
// Doku map'in doku koordinatları
in float2 normalCoords : TEXCOORD1,
// Normal map'in doku koordinatları
in float3 vLightVector : TEXCOORD2,
// Dönüştürülmüş ışık vektörü (tanjant uzayında)
out float4 colorOUT
// O anki pikselin son rengi
: COLOR0,
uniform sampler2D baseTexture : TEXUNIT0,
// Duvar dokusu
uniform sampler2D normalTexture : TEXUNIT1,
// Duvar dokusunun normal mapi
uniform float3 fLightDiffuseColor)
// Işık kaynağının yayınık rengi
{
// Işık vektörünü normalize etmeliyiz çünkü yüzey üzerinde doğrusal
olarak interpole ediliyor,
// yani biz interpole ettikçe vektörün boyutları değişiyor.
vLightVector = normalize(vLightVector);
// Normal map'teki normaller (renkler) [0, 1] aralığında olduğundan
bunları
// gerçek normal (vektör) doğrultularına açmalıyız.
// ([0, 1] -> [-1, 1])
float3 vNormal = 2.0f * (tex2D(normalTexture, normalCoords).rgb 0.5f);
// Yayınık bileşeni hesapla ve sonuç rengi olarak 'colorOUT' içine
// Yayınık bileşen şu şekilde tanımlanmıştı: I = Dl * Dm *
clamp(L•N, 0, 1)
// saturate() aynen clamp() gibi çalışır ama [0;1] arasında
kenetlenmeyi gerektirir.
colorOUT.rgb = fLightDiffuseColor * tex2D(baseTexture,
texCoords).rgb * saturate(dot(vLightVector, vNormal));
}
Burada da dikkat edilirse her ş
ey çok sade bir ş
ekilde teorik temeller üzerine
kurulmuş
tur. Gereksiz hiçbirş
ey yoktur sadece ilgili bağlamalar yapı
lmı
şve fragment
shader’da yapı
lmasıgereken hesaplamalar belirtilmiş
tir.
Umut DOGAN - Bitirme Tezi - Haziran 2006
yaz.
78
Buraya kadar olan kı
sı
m shader’larla ilgiliydi. Aslı
nda genelde yararlandı
ğı
m bütün
kaynaklarda shader oluş
turulması
yla ilgili bütün ayrı
ntı
lar açı
klanmı
şancak bu shader’ları
OpenGL veya Direct3D’ye nası
l bağlayacağı
m açı
klanmamı
ş
tı
. Tezimde uygulama
programı
yla ilgili açı
klamalarıyaptı
ğı
m bu kı
sı
mda OpenGL’e nası
l bağlandı
ğı
nı
anlatmaya çalı
ş
tı
m. Direct3D’ye bağlanması
nıise küçük örneklerin bulunduğu bir baş
ka
baş
lı
kta elimden geldiğ
ince açı
klamaya çalı
ş
tı
m.
4.7. Ana Program
İ
lk olarak Cg programları yazabilmek için gerekli include dosyaları
nı
n
programı
mı
za eklenmesiyle baş
lı
yoruz. Derleyicimizin yani Visual Studio 2003’ün include
ve lib dizinlerine (C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7), Cg
programları yazabilmemiz için gerekli kütüphaneleri (C:\Program Files\NVIDIA
Corporation\Cg) kopyaladı
ğı
mı
zıvarsayı
yorum. Bu ayarlamalarla ilgili kı
sı
mlar tezin
diğer bölümlerinde ayrı
ca belirtilmiş
tir. Ayrı
ca bir OpenGL extension olan OglExt
kütüphanesinin include ve lib dizinleri de aynıyere kopyalanmalı
dı
r.
//CG'nin ihtiyaç duyduğu headerlar
#include <CG/cg.h>
#include <CG/cgGL.h>
// CG'nin ihtiyaç duyduğu library dosyaları
#pragma comment (lib, "cg.lib")
#pragma comment (lib, "cgGL.lib")
// OglExt.lib OpenGL Extensions library dosyası
#pragma comment (lib, "OglExt.lib")
Daha sonra InitCG() fonksiyonunda Cg ayarlamalarıyapı
lı
yor ve Cg shader
BOOL InitCG()
{
// Sorun oluşursa Cg tarafından çağrılacak fonksiyonu ayarla
// tanımlaması biraz altta
cgSetErrorCallback(CGErrorCallback);
// shader programlarımızı tutacak Cg context oluştur
g_context = cgCreateContext();
Umut DOGAN - Bitirme Tezi - Haziran 2006
programlarıoluş
turuluyor.
79
// Fragment shader için çalışılan makinadaki ekran kartına göre
// en uygun profili seç
g_fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
cgGLSetOptimalOptions(g_fragmentProfile);
if (g_fragmentProfile == CG_PROFILE_UNKNOWN)
{
g_pLog.PrintLn("Desteklenmeyen Ekran Kartı! Uygun Fragment
Shader Profili Bulunamıyor!");
return FALSE;
}
// Vertex shader için çalışılan makinadaki ekran kartına göre
// en uygun profili seç
g_vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
cgGLSetOptimalOptions(g_vertexProfile);
if (g_vertexProfile == CG_PROFILE_UNKNOWN)
{
g_pLog.PrintLn("Desteklenmeyen Ekran Kartı! Uygun Vertex
Shader Profili Bulunamıyor!");
return FALSE;
}
// Fragment program oluştur.
// cgCreateProgramFromFile() şu parametreleri alıyor:
// Bir CG context, CG dosyasının türü (GL_SOURCE henüz derlenmemiş
bir shader okuduğumuzu belirtiyor),
// Cg shader dosya adı, az önce oluşturduğumuz Cg profili,
shaderdaki başlangıç fonksiyonunun adı.
g_fragmentProgram = cgCreateProgramFromFile(g_context, CG_SOURCE,
"FragmentShader.cg", g_fragmentProfile, "main", 0);
if (!g_fragmentProgram)
return FALSE;
// Fragment programı yükle
cgGLLoadProgram(g_fragmentProgram);
// Vertex programı oluştur
g_vertexProgram = cgCreateProgramFromFile(g_context, CG_SOURCE,
"VertexShader.cg", g_vertexProfile, "main", 0);
if (!g_vertexProgram)
return FALSE;
// Sahnedeki iki üçgen için de TBN matrisini hesapla
CalculateTBNMatrix(g_vQuad[0], g_vTexCoords[0], g_TBNMatrix[0]);
CalculateTBNMatrix(g_vQuad[1], g_vTexCoords[1], g_TBNMatrix[1]);
// Vertex ve fragment shaderlara geçeceğimiz parametreleri al.
// Bunu “main(int gecPar)” gibi düşünebiliriz.
// Altta yaptığımız işlem parametreler için bir referans almak
(gecPar gibi)
// değerlerini Cg programının dışında ayarlayabiliriz. Bağlantıları
alt satırlarda..
g_modelViewMatrix = cgGetNamedParameter(g_vertexProgram,
"modelViewProjMatrix");
g_lightPosition = cgGetNamedParameter(g_vertexProgram,
"vLightPosition");
Umut DOGAN - Bitirme Tezi - Haziran 2006
// Vertex programı yükle
cgGLLoadProgram(g_vertexProgram);
80
g_lightDiffuseColor = cgGetNamedParameter(g_fragmentProgram,
"fLightDiffuseColor");
// Işık küresini oluştur.
g_lightSphere = gluNewQuadric();
return TRUE;
}
Alttaki kod parçacı
ğıise iş
in mantı
ğı
yla ilgili önemli bir bölümdür. Dörtgenimizi
iki üçgenden ve verilen doku koordinatları
ndan oluş
acak ş
ekilde ayarladı
k. Burada dikkat
edilmesi gereken bir nokta da iki tane TBN matrisi kullandı
ğı
mı
zdı
r. Daha önce belirttiğim
gibi bu programda üçgenlerle ilgileniyoruz ve her bir üçgen için bir tane TBN matrisi
kullanmamı
z yeterlidir.
// Dörtgenimizin koordinatları (herbiri 3 vertexten oluşan 2 üçgen)
CVector g_vQuad[2][3] = { { CVector(-10.0f, -10.0f, -40.0f),
CVector(10.0f, -10.0f, -40.0f), CVector(10.0f, 10.0f, -40.0f) },
{ CVector(-10.0f, 10.0f, 40.0f), CVector(-10.0f, -10.0f, -40.0f), CVector(10.0f, -10.0f, 40.0f) } };
// 2 üçgen için doku koordinatları
CVector2 g_vTexCoords[2][3] = { { CVector2(0.0f, 0.0f),
CVector2(1.0f, 0.0f), CVector2(1.0f, 1.0f) },
{ CVector2(0.0f,
1.0f), CVector2(0.0f, 0.0f), CVector2(1.0f, 0.0f) } };
// 2 tane TBN matrisi (her bir üçgen için bir tane).Her matris 3
vektörden oluşuyor.
CVector g_TBNMatrix[2][3];
Altta verdiğim fonksiyon ise hata geri çağı
rma fonksiyonudur. Cg shader’larla ilgili
bir problem oluş
tuğunda oluş
an hatalarla ilgilenmektedir. Programda verilen hata
mesajları
nı
n büyük çoğunluğu İ
ngilizce olacaktı
r. Bunun nedeni dil tanı
mlanı
rken böyle
void CGErrorCallback()
{
// Hata mesajını log dosyasına yaz:
// cgGetErrorString() ortaya çıkan hatayı döndürür.
// cgGetLastListing() hatanın daha açıklayıcı bir çıktısını verir.
g_pLog.PrintLn("%s - %s", cgGetErrorString(cgGetError()),
cgGetLastListing(g_context));
}
Program sonlandı
rı
ldı
ğı
nda gerekli temizlik iş
lemleriniyse DestroyCG() fonksiyonu
yapmaktadı
r.
Umut DOGAN - Bitirme Tezi - Haziran 2006
tanı
mlanmaları
dı
r.
81
void DestroyCG()
{
// Işık küresini yok et ve serbest bırak
if (g_lightSphere)
gluDeleteQuadric(g_lightSphere);
// Cg contex yok edilince bağlı tüm programlar da yok edilir
cgDestroyContext(g_context);
}
Ekranda herhangi bir ş
eyi gerçekleyebilmek için ilk önce her bir üçgen için TBN
matrisini hesaplamamı
z gerekmektedir. CalculateTBNMatrix() fonksiyonu bu amaçla
oluş
turulmuş
tur. Girdi olarak üç parametre almaktadı
r:
-
TBN matrisini hesaplamak istediğimiz üçgen
-
Verilen üçgenin doku koordinatları
-
Hesaplanmı
ş veriyle
dolduracağı
mı
z
ve
çağı
ran
fonksiyona
döndüreceğimiz TBN matrisi
Bu bilgiler ı
ş
ı
ğı
nda ShaderUtils.cpp dosyası
nda bulunan CalculateTBNMatrix()
fonksiyonunun içeriği ş
öyledir:
void CalculateTBNMatrix(const CVector *pvTriangle, const CVector2
*pvTexCoords, CVector *pvTBNMatrix)
{
// Üçgenin her bir vertexi için teğet tabanını hesapla
//
// TBN matrisini hesaplamak için üçgenin sadece ilk vertexini
kullandık, eğer istersek
// diğer ikisinden birini de kullanabilirdik. Sonuç değişmezdi.
int i = 0;
// Üzerinde çalışılan vertexten üçgenin diğer iki vertexine olan
vektörleri hesapla
CVector v2v1 = pvTriangle[nNextIndex] - pvTriangle[i];
CVector v3v1 = pvTriangle[nPrevIndex] - pvTriangle[i];
//
//
//
//
//
Bitirme Raporunda belirtilen eşitlikler:
c2c1_T = V2.texcoord.x – V1.texcoord.x
c2c1_B = V2.texcoord.y – V1.texcoord.y
c3c1_T = V3.texcoord.x – V1.texcoord.x
c3c1_B = V3.texcoord.y – V1.texcoord.y
// c2c1_T ve c2c1_B'i hesapla
float c2c1_T = pvTexCoords[nNextIndex].x - pvTexCoords[i].x;
float c2c1_B = pvTexCoords[nNextIndex].y - pvTexCoords[i].y;
Umut DOGAN - Bitirme Tezi - Haziran 2006
// Sağdaki indexi ve o anki indexin solunu hesapla
int nNextIndex = (i + 1) % 3;
int nPrevIndex = (i + 2) % 3;
82
// c3c1_T ve c3c1_B'i hesapla
float c3c1_T = pvTexCoords[nPrevIndex].x - pvTexCoords[i].x;
float c3c1_B = pvTexCoords[nPrevIndex].y - pvTexCoords[i].y;
float fDenominator = c2c1_T * c3c1_B - c3c1_T * c2c1_B;
if (ROUNDOFF(fDenominator) == 0.0f)
{
// Sıfıra bölme hatası riskiyle karşılaşmamak için
// teğet matrisini birim matrise setliyoruz
pvTBNMatrix[0] = CVector(1.0f, 0.0f, 0.0f);
pvTBNMatrix[1] = CVector(0.0f, 1.0f, 0.0f);
pvTBNMatrix[2] = CVector(0.0f, 0.0f, 1.0f);
}
else
{
// tersi değerini bir kere hesapla ve tümü için kullan
(performans artışı sağlar)
float fScale1 = 1.0f / fDenominator;
// T ve B hesaplanıyor
CVector T, B, N;
T = CVector((c3c1_B * v2v1.x - c2c1_B * v3v1.x) * fScale1,
(c3c1_B * v2v1.y - c2c1_B * v3v1.y) * fScale1,
(c3c1_B * v2v1.z - c2c1_B * v3v1.z) * fScale1);
B = CVector((-c3c1_T * v2v1.x + c2c1_T * v3v1.x) * fScale1,
(-c3c1_T * v2v1.y + c2c1_T * v3v1.y) * fScale1,
(-c3c1_T * v2v1.z + c2c1_T * v3v1.z) * fScale1);
// N normali, T ve B arasında vektör çarpımı yapılarak
hesaplanıyor
N = T.CrossProduct(B);
// tersi değerini bir kere hesapla ve tümü için kullan
// (performans artışı sağlar)
float fScale2 = 1.0f / ((T.x * B.y * N.z - T.z * B.y * N.x) +
(B.x * N.y * T.z - B.z * N.y * T.x) + (N.x * T.y * B.z - N.z * T.y *
B.x));
pvTBNMatrix[1].x = -B.CrossProduct(N).y * fScale2;
pvTBNMatrix[1].y = N.CrossProduct(T).y * fScale2;
pvTBNMatrix[1].z = -T.CrossProduct(B).y * fScale2;
pvTBNMatrix[1].Normalize();
}
}
pvTBNMatrix[2].x = B.CrossProduct(N).z * fScale2;
pvTBNMatrix[2].y = -N.CrossProduct(T).z * fScale2;
pvTBNMatrix[2].z = T.CrossProduct(B).z * fScale2;
pvTBNMatrix[2].Normalize();
Umut DOGAN - Bitirme Tezi - Haziran 2006
// Ters TBN matrisinin hesaplanması
// Temel vektörleri pvTBNMatrix içinde tutuyoruz.
pvTBNMatrix[0].x = B.CrossProduct(N).x * fScale2;
pvTBNMatrix[0].y = -N.CrossProduct(T).x * fScale2;
pvTBNMatrix[0].z = T.CrossProduct(B).x * fScale2;
pvTBNMatrix[0].Normalize();
83
Şimdi de ası
l sihrin gerçekleş
tiği ve her ş
eyin ekrana bası
ldı
ğıRender()
fonksiyonuna geldik. Burada ı
ş
ı
klar gerçekleniyor çoklu doku kaplama ayarlanı
yor, vertex
ve fragment shaderlar etkinleş
tiriliyor ve ekranı
mı
zı
n ortası
nda dörtgen oluş
turan
RenderQuad fonksiyonu çağrı
lı
yor.
void Render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glPushAttrib(GL_CURRENT_BIT);
// Beyaz ışık kaynağı
glColor3f(1.0f, 1.0f, 1.0f);
glPushMatrix();
// Işık kaynağının dairesel bir yörüngede dönmesini
istiyoruz. Burada biraz trigonometri uyguluyoruz.
// Bu hesaplamada zaman çarpanını kullanmıyoruz (bunun nedeni
// bazı bilgisayarlarda bilgisayar hızına göre hızlı veya
yavaş olmabilme olasılığıdır.)
g_fRotAngle += (float)PI * 0.02f * g_fLightSpeed;
g_vLightPos.x = cosf(g_fRotAngle) * 10.0f;
g_vLightPos.y = sinf(g_fRotAngle) * 10.0f;
// Işık küresini konumlandırıp gerçekliyoruz
glTranslatef(g_vLightPos.x, g_vLightPos.y, g_vLightPos.z);
gluSphere(g_lightSphere, 1.0f, 20, 20);
glPopMatrix();
glPopAttrib();
// Vertex ve fragment profillerini etkinleştir ve vertex ve
fragment programlarına bağla
cgGLEnableProfile(g_vertexProfile);
cgGLEnableProfile(g_fragmentProfile);
// Vertex shaderdaki "modelViewProjMatrix" parametresini üzerinde
çalışılan
// modelview ve projeksiyon matrislerine ayarla
cgGLSetStateMatrixParameter(g_modelViewMatrix,
CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);
// Vertex shaderdaki ışık konumu parametresini ayarla
cgGLSetParameter3f(g_lightPosition, g_vLightPos.x, g_vLightPos.y,
g_vLightPos.z);
// Fragment shaderdaki yayınık ışığı ayarla
cgGLSetParameter3f(g_lightDiffuseColor, 1.0f, 1.0f, 1.0f);
// Duvar dokusunu etkinleştir ve bağla
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, g_uiRockTexture);
Umut DOGAN - Bitirme Tezi - Haziran 2006
cgGLBindProgram(g_vertexProgram);
cgGLBindProgram(g_fragmentProgram);
84
// Normal mapi etkinleştir ve bağla
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, g_uiNormalTexture);
RenderQuad();
// Vertex ve fragment profillerini tekrar devre dışı bırak
cgGLDisableProfile(g_vertexProfile);
cgGLDisableProfile(g_fragmentProfile);
// Dokuları devre dışı bırak
glActiveTextureARB(GL_TEXTURE0_ARB);
glDisable(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE1_ARB);
glDisable(GL_TEXTURE_2D);
}
RenderQuad() fonksiyonu da altta gösterilmiş
tir. Burada üçgen oluş
tururken
GL_TRIANGLE yerine GL_TRIANGLE_FAN kullanmamı
n nedeni 6 vertex yerine 4
vertex kullanarak optimizasyon sağlamı
şolmamdı
r. Ayrı
ca ters TBN matrislerini
glMultiTexCoord3fARB() çağrı
ları
yla belirttiğimize dikkat ediniz.
void RenderQuad()
{
glBegin(GL_TRIANGLE_FAN);
// Duvar dokusu ve normal map için doku koordinatlarını ayarla
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, g_vTexCoords[0][0].x,
g_vTexCoords[0][0].y);
bir bir belirle ve
g_TBNMatrix[0][0].x,
g_TBNMatrix[0][1].x,
g_TBNMatrix[0][2].x,
// Sol alt vertexi çizdir
glVertex3f(g_vQuad[0][0].x, g_vQuad[0][0].y,
g_vQuad[0][0].z);
// ------------------------------------------------------------ //
// Duvar dokusu ve normal map için doku koordinatlarını ayarla
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, g_vTexCoords[0][1].x,
g_vTexCoords[0][1].y);
// Sağ alt vertexi çizdir
glVertex3f(g_vQuad[0][1].x, g_vQuad[0][1].y,
g_vQuad[0][1].z);
Umut DOGAN - Bitirme Tezi - Haziran 2006
// teğet matris vektörlerini ilk üçgen için
bunları vertex shader'a gönder
glMultiTexCoord3fARB(GL_TEXTURE1_ARB,
g_TBNMatrix[0][0].y, g_TBNMatrix[0][0].z);
glMultiTexCoord3fARB(GL_TEXTURE2_ARB,
g_TBNMatrix[0][1].y, g_TBNMatrix[0][1].z);
glMultiTexCoord3fARB(GL_TEXTURE3_ARB,
g_TBNMatrix[0][2].y, g_TBNMatrix[0][2].z);
85
// ------------------------------------------------------------ //
// Duvar dokusu ve normal map için doku koordinatlarını ayarla
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, g_vTexCoords[0][2].x,
g_vTexCoords[0][2].y);
// Sağ üst vertexi çizdir
glVertex3f(g_vQuad[0][2].x, g_vQuad[0][2].y,
g_vQuad[0][2].z);
// ------------------------------------------------------------ //
// Duvar dokusu ve normal map için doku koordinatlarını ayarla
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, g_vTexCoords[1][0].x,
g_vTexCoords[1][0].y);
// teğet matris vektörlerini ikinci üçgen için bir bir belirle ve
bunları vertex shader'a gönder
glMultiTexCoord3fARB(GL_TEXTURE1_ARB, g_TBNMatrix[1][0].x,
g_TBNMatrix[1][0].y, g_TBNMatrix[1][0].z);
glMultiTexCoord3fARB(GL_TEXTURE2_ARB, g_TBNMatrix[1][1].x,
g_TBNMatrix[1][1].y, g_TBNMatrix[1][1].z);
glMultiTexCoord3fARB(GL_TEXTURE3_ARB, g_TBNMatrix[1][2].x,
g_TBNMatrix[1][2].y, g_TBNMatrix[1][2].z);
// Sol üst vertexi çizdir
glVertex3f(g_vQuad[1][0].x, g_vQuad[1][0].y,
g_vQuad[1][0].z);
glEnd();
}
Böylece Cg shader dili kullanarak pürüzlü yüzey dokusu üretmişoldum. Bu
bölümün son sayfası
nda programdan bazıekran görüntüleri verdim. Programda ı
ş
ı
k küresi
Page Up / Page Down tuş
larıkullanı
larak ekrandan içeri / dı
ş
arıdoğru gönderilebiliyor.
Ayrı
ca sol / sağ/ yukarı/ aş
ağıtuş
larıile ı
ş
ı
k kaynağı
nı
n konumu değiş
tirilebiliyor. - / +
tuş
ları
ysa ı
ş
ı
k küresinin dönme hı
zı
nıyavaş
latı
p hı
zlandı
rmaya yarı
yor. Ayrı
ca Esc tuş
una
bası
ldı
ğı
nda uygulama penceresi kapatı
lı
yor. Bütün bu ayarlamalar ve fazlasıVisual C++
Umut DOGAN - Bitirme Tezi - Haziran 2006
kodları
yla gerçekleş
tirilmişbir ş
ekilde Init.cpp dosyası
nda bulunmaktadı
r.
(a)
(b)
(c)
(d)
(e)
Şekil 4.8: Cg ile Pürüzlü Yüzey Dokusu Üretimi Uygulaması
ndan Ekran Görüntüleri
(a) Iş
ı
k küresi sağdayken
(b) Iş
ı
k küresi soldayken
(c) Iş
ı
k küresi tepedeyken
(d) Iş
ı
k küresi duvarı
n arkası
ndayken
(e) Iş
ı
k kaynağıekrana yakı
nlaş
tı
rı
lmı
ş
ken
Umut DOGAN - Bitirme Tezi - Haziran 2006
86
5. SONUÇLAR
Bitirme projesi olarak “Cg Programlama Dili ve Cg ile Pürüzlü Yüzey Dokusu
Üretimi” konusunu seçerken bu konunun yararlı olup olamayacağ
ı konusunda
çekincelerim vardı
. Fakat Cg dilini araş
tı
rmaya baş
ladı
ktan sonraki süreçte grafik
programlamanı
n ne kadar genişve keyifli bir alan olduğ
unu fark ettim.
CPU için yazı
lan programlar bütün dünyada standartlaş
maya baş
ladı
. Yani bir
veritabanıuygulamasıyazabilmek için çok fazla yetenek ve bilgiye gereksinim kalmamı
ş
durumda. Oysa Bilgisayar Grafikleri alanı
nda gerçek dünyanı
n simülasyonundan,
animasyonlara kadar onlarca farklıçalı
ş
ma alanı
nda ürünler verebilmek olasıdurumda.
Bilgisayar Grafikleri, bilgisayar bilimleri disiplinlerinin bütün önemli dalları
ndan
parçalar içeriyor. Bu nedenle çok önemli bir alandı
r. Ayrı
ca günümüzde geliş
miş
bilgisayar oyunları
na ve animasyon filmlere olan talep de üst seviyelere çı
kmı
ş
tı
r.
Cg programlama dili sayesinde CPU’nun üzerindeki ağı
r yükü hafifletip bu yükü
GPU’nun üzerine paylaş
tı
rı
yoruz. Hem de bunu karmaş
ı
k assembly kodları
yla değil
yüksek seviyeli bir dilin özelliklerini kullanarak yapabiliyoruz. Cg, henüz 5 yaş
ı
nda genç
bir dil. Standartlar konusunda bazısorunlar devam ediyor ancak grafik donanı
mıhı
zlı
geliş
imini sürdürdükçe Cg’nin de standart ve kolay kullanı
mlıbir noktaya eriş
eceğini
düş
ünüyorum.
karş
ı
mı
za çı
kı
yor. Ayrı
ca pürüzlü yüzey dokusu üretimi de 3B bilgisayar oyunları
nda daha
gerçekçi sahneler yaratabilmek için önemli bir önkoş
ul konumundadı
r. Cg ve pürüzlü
yüzey dokusu bir araya gelince ise Blinn’in 1978’de önerdiğ
i ve 30 yı
la yakı
n bir süredir
üzerinde çalı
ş
malar yapı
lan pürüzlü yüzey dokusu üretiminde epeyce yol kat edilmiş
oluyor.
Umut DOGAN - Bitirme Tezi - Haziran 2006
Sonuç olarak Cg, üzerinde çalı
ş
ı
lmaya değecek kalitede ve esneklikte bir dil olarak
6. ÖNERİ
LER
Bitirme tezimin; GPU programlamaya geçmekte, karmaş
ı
klı
ğıve zorluğu nedeniyle
çekinmekte olanlar için temel bir Türkçe kaynak olması
nıdiliyorum. Özellikle Cg dili
üzerine yazı
lmı
şilk Türkçe kaynaklardan birisi olduğu için yararlıolacağ
ı
nıumuyorum.
Bilgisayar grafikleri ve GPU programlama alanı
nda araş
tı
rma yapmak ve çalı
ş
mak
isteyenlere özellikle matematik ve fizik bilgilerini güçlendirmelerini öneriyorum. Projeyi
hazı
rlarken bu alanlarda önceki bilgilerimin ne kadar yetersiz olduğunu fark ettim ve bu
bilgileri elimden geldiğince geliş
tirmeye çalı
ş
tı
m.
Bir diğer önemli nokta da bilgisayar bilimlerinin bütün alanları
nda olduğu gibi
bilgisayar grafikleri alanı
nda da yeterli Türkçe kaynak olmaması
dı
r. “Bilgi paylaş
ı
ldı
kça
çoğalı
r” ilkesinin bizim insanları
mı
z tarafı
ndan da anlaş
ı
lmasıve uygulanmasıen büyük
dileklerimden birisidir. Paylaş
ı
lacak bilginin olmamasınedeniyle Türkçe kaynak sı
kı
ntı
sı
çekilmesiyse daha vahim bir durumdur. Bu eksiklikleri elimizden geldiğince kapatmaya
çalı
ş
malı
yı
z.
Elbette Türkiye’nin bir biliş
im ülkesi olabilmesi, iyi planlanmı
şdevlet politikaları
ve eğitime verdiğ
i katkı
lar sayesinde olabilir. Dilerim önümüzdeki on yı
llarda teknolojiyi
Umut DOGAN - Bitirme Tezi - Haziran 2006
sadece tüketen değil aynızamanda üreten bir ülke olabilmenin gururunu yaş
arı
z.

Benzer belgeler